| 24 #include "gtkidle.h" |
24 #include "gtkidle.h" |
| 25 |
25 |
| 26 #ifdef HAVE_IOKIT |
26 #ifdef HAVE_IOKIT |
| 27 # include <CoreFoundation/CoreFoundation.h> |
27 # include <CoreFoundation/CoreFoundation.h> |
| 28 # include <IOKit/IOKitLib.h> |
28 # include <IOKit/IOKitLib.h> |
| 29 #else |
29 #elif defined _WIN32 |
| 30 # ifdef USE_SCREENSAVER |
30 # include "gtkwin32dep.h" |
| 31 # ifdef _WIN32 |
31 #endif |
| 32 # include "gtkwin32dep.h" |
|
| 33 # else |
|
| 34 /* We're on X11 and not MacOS X with IOKit. */ |
|
| 35 # include <X11/Xlib.h> |
|
| 36 # include <X11/Xutil.h> |
|
| 37 # include <X11/extensions/scrnsaver.h> |
|
| 38 # include <gdk/gdkx.h> |
|
| 39 # endif /* !_WIN32 */ |
|
| 40 # endif /* USE_SCREENSAVER */ |
|
| 41 #endif /* !HAVE_IOKIT */ |
|
| 42 |
32 |
| 43 #include "idle.h" |
33 #include "idle.h" |
| |
34 |
| |
35 #if !defined(HAVE_IOKIT) && !defined(_WIN32) |
| |
36 typedef struct { |
| |
37 gchar *bus_name; |
| |
38 gchar *object_path; |
| |
39 gchar *iface_name; |
| |
40 } PidginDBusScreenSaverInfo; |
| |
41 |
| |
42 static const PidginDBusScreenSaverInfo screensavers[] = { |
| |
43 { |
| |
44 "org.freedesktop.ScreenSaver", |
| |
45 "/org/freedesktop/ScreenSaver", |
| |
46 "org.freedesktop.ScreenSaver" |
| |
47 }, { |
| |
48 "org.gnome.ScreenSaver", |
| |
49 "/org/gnome/ScreenSaver", |
| |
50 "org.gnome.ScreenSaver" |
| |
51 }, { |
| |
52 "org.kde.ScreenSaver", |
| |
53 "/org/kde/ScreenSaver", |
| |
54 "org.kde.ScreenSaver" |
| |
55 }, |
| |
56 { NULL, NULL, NULL} |
| |
57 }; |
| |
58 #endif /* !HAVE_IOKIT && !_WIN32 */ |
| 44 |
59 |
| 45 /* |
60 /* |
| 46 * pidgin_get_time_idle: |
61 * pidgin_get_time_idle: |
| 47 * |
62 * |
| 48 * Get the number of seconds the user has been idle. In Unix-world |
63 * Get the number of seconds the user has been idle. In Unix-world |
| 49 * this is based on the X Windows usage. In MS Windows this is |
64 * this is based on the DBus ScreenSaver interfaces. In MS Windows this |
| 50 * based on keyboard/mouse usage information obtained from the OS. |
65 * is based on keyboard/mouse usage information obtained from the OS. |
| 51 * In MacOS X, this is based on keyboard/mouse usage information |
66 * In MacOS X, this is based on keyboard/mouse usage information |
| 52 * obtained from the OS, if configure detected IOKit. Otherwise, |
67 * obtained from the OS, if configure detected IOKit. Otherwise, |
| 53 * MacOS X is handled as a case of X Windows. |
68 * MacOS X is handled as a case of Unix. |
| 54 * |
|
| 55 * In Debian bug #271639, jwz says: |
|
| 56 * |
|
| 57 * Purple should simply ask xscreensaver how long the user has been idle: |
|
| 58 * % xscreensaver-command -time |
|
| 59 * XScreenSaver 4.18: screen blanked since Tue Sep 14 14:10:45 2004 |
|
| 60 * |
|
| 61 * Or you can monitor the _SCREENSAVER_STATUS property on root window #0. |
|
| 62 * Element 0 is the status (0, BLANK, LOCK), element 1 is the time_t since |
|
| 63 * the last state change, and subsequent elements are which hack is running |
|
| 64 * on the various screens: |
|
| 65 * % xprop -f _SCREENSAVER_STATUS 32ac -root _SCREENSAVER_STATUS |
|
| 66 * _SCREENSAVER_STATUS(INTEGER) = BLANK, 1095196626, 10, 237 |
|
| 67 * |
|
| 68 * See watch() in xscreensaver/driver/xscreensaver-command.c. |
|
| 69 * |
69 * |
| 70 * Returns: The number of seconds the user has been idle. |
70 * Returns: The number of seconds the user has been idle. |
| 71 */ |
71 */ |
| 72 #if defined(USE_SCREENSAVER) || defined(HAVE_IOKIT) |
|
| 73 static time_t |
72 static time_t |
| 74 pidgin_get_time_idle(void) |
73 pidgin_get_time_idle(void) |
| 75 { |
74 { |
| 76 # ifdef HAVE_IOKIT |
75 # ifdef HAVE_IOKIT |
| 77 /* Query the IOKit API */ |
76 /* Query the IOKit API */ |
| 99 # else |
98 # else |
| 100 # ifdef _WIN32 |
99 # ifdef _WIN32 |
| 101 /* Query Windows */ |
100 /* Query Windows */ |
| 102 return (GetTickCount() - winpidgin_get_lastactive()) / 1000; |
101 return (GetTickCount() - winpidgin_get_lastactive()) / 1000; |
| 103 # else |
102 # else |
| 104 /* We're on X11 and not MacOS X with IOKit. */ |
103 static const PidginDBusScreenSaverInfo *info = screensavers; |
| |
104 GApplication *app; |
| |
105 GDBusConnection *conn; |
| |
106 GVariant *reply = NULL; |
| |
107 guint32 active_time = 0; |
| |
108 GError *error = NULL; |
| 105 |
109 |
| 106 /* Query xscreensaver */ |
110 app = g_application_get_default(); |
| 107 static XScreenSaverInfo *mit_info = NULL; |
|
| 108 static int has_extension = -1; |
|
| 109 int event_base, error_base; |
|
| 110 |
111 |
| 111 if (has_extension == -1) |
112 if (app == NULL) { |
| 112 has_extension = XScreenSaverQueryExtension(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), |
113 purple_debug_error("gtkidle", |
| 113 &event_base, &error_base); |
114 "Unable to retrieve GApplication"); |
| |
115 return 0; |
| |
116 } |
| 114 |
117 |
| 115 if (has_extension) |
118 conn = g_application_get_dbus_connection(app); |
| 116 { |
|
| 117 if (mit_info == NULL) |
|
| 118 mit_info = XScreenSaverAllocInfo(); |
|
| 119 |
119 |
| 120 XScreenSaverQueryInfo(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), |
120 if (conn == NULL) { |
| 121 GDK_ROOT_WINDOW(), mit_info); |
121 purple_debug_misc("gtkidle", |
| 122 return (mit_info->idle) / 1000; |
122 "GApplication lacking DBus connection. " |
| |
123 "Skip checking ScreenSaver interface"); |
| |
124 return 0; |
| 123 } |
125 } |
| 124 else |
126 |
| |
127 while (reply == NULL && info->bus_name != NULL) { |
| |
128 reply = g_dbus_connection_call_sync(conn, |
| |
129 info->bus_name, info->object_path, |
| |
130 info->iface_name, "GetActiveTime", |
| |
131 NULL, G_VARIANT_TYPE("(u)"), |
| |
132 G_DBUS_CALL_FLAGS_NO_AUTO_START, 1000, |
| |
133 NULL, &error); |
| |
134 |
| |
135 if (reply != NULL) { |
| |
136 break; |
| |
137 } |
| |
138 |
| |
139 if (g_error_matches(error, G_DBUS_ERROR, |
| |
140 G_DBUS_ERROR_NOT_SUPPORTED)) { |
| |
141 purple_debug_info("gtkidle", |
| |
142 "Querying idle time on '%s' " |
| |
143 "unsupported. Trying the next one", |
| |
144 info->bus_name); |
| |
145 } else if (g_error_matches(error, G_DBUS_ERROR, |
| |
146 G_DBUS_ERROR_NAME_HAS_NO_OWNER)) { |
| |
147 purple_debug_info("gtkidle", |
| |
148 "Querying idle time on '%s' " |
| |
149 "not found. Trying the next one", |
| |
150 info->bus_name); |
| |
151 } else { |
| |
152 purple_debug_error("gtkidle", |
| |
153 "Querying idle time on '%s' " |
| |
154 "error: %s", info->bus_name, |
| |
155 error->message); |
| |
156 } |
| |
157 |
| |
158 g_clear_error(&error); |
| |
159 ++info; |
| |
160 } |
| |
161 |
| |
162 if (reply == NULL) { |
| |
163 purple_debug_warning("gtkidle", |
| |
164 "Failed to query ScreenSaver active time: " |
| |
165 "No working ScreenSaver interfaces"); |
| 125 return 0; |
166 return 0; |
| |
167 } |
| |
168 |
| |
169 g_variant_get(reply, "(u)", &active_time); |
| |
170 g_variant_unref(reply); |
| |
171 |
| |
172 return active_time; |
| 126 # endif /* !_WIN32 */ |
173 # endif /* !_WIN32 */ |
| 127 # endif /* !HAVE_IOKIT */ |
174 # endif /* !HAVE_IOKIT */ |
| 128 } |
175 } |
| 129 #endif /* USE_SCREENSAVER || HAVE_IOKIT */ |
|
| 130 |
176 |
| 131 static PurpleIdleUiOps ui_ops = |
177 static PurpleIdleUiOps ui_ops = |
| 132 { |
178 { |
| 133 #if defined(USE_SCREENSAVER) || defined(HAVE_IOKIT) |
|
| 134 pidgin_get_time_idle, |
179 pidgin_get_time_idle, |
| 135 #else |
|
| 136 NULL, |
|
| 137 #endif /* USE_SCREENSAVER || HAVE_IOKIT */ |
|
| 138 NULL, |
180 NULL, |
| 139 NULL, |
181 NULL, |
| 140 NULL, |
182 NULL, |
| 141 NULL |
183 NULL |
| 142 }; |
184 }; |