00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include <glib.h>
00033 #include <string.h>
00034 #include <sys/time.h>
00035 #include <hal/libhal.h>
00036 #include <gdk/gdkx.h>
00037 #include <gtk/gtk.h>
00038 #include <X11/Xlib.h>
00039 #include <X11/Xatom.h>
00040 #include <X11/extensions/scrnsaver.h>
00041
00042
00043
00044
00045 #include "log.h"
00046 #include "xwindow.h"
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 static Atom atom_client_list;
00064 static Atom atom_active_window;
00065 static Atom atom_wm_user_time;
00066 static Display *g_display = NULL;
00067
00068
00069
00070
00071
00072
00073 static GList *get_window_list (void);
00074 static int on_x_error (Display *display, XErrorEvent *event);
00075
00076
00077
00078
00079
00080
00081 void window_set_services()
00082 {
00083
00084 XInitThreads();
00085
00086 LOGPRINTF("XinitThreads returned");
00087
00088
00089 XSetErrorHandler(on_x_error);
00090
00091
00092 g_display = gdk_x11_get_default_xdisplay();
00093
00094
00095 atom_client_list = XInternAtom(g_display, "_NET_CLIENT_LIST", False);
00096 atom_active_window = XInternAtom(g_display, "_NET_ACTIVE_WINDOW", False);
00097 atom_wm_user_time = XInternAtom(g_display, "_NET_WM_USER_TIME", False);
00098 }
00099
00100
00101 Window get_application_window(const char *app_name)
00102 {
00103 LOGPRINTF("entry: %s", app_name);
00104
00105 Atom type;
00106 int format;
00107 unsigned char *data = NULL;
00108 unsigned long n_items, bytes_after;
00109 int result;
00110 int i;
00111
00112 g_return_val_if_fail(app_name != NULL, 0);
00113
00114
00115
00116 result = XGetWindowProperty(g_display, RootWindow(g_display, DefaultScreen(g_display)),
00117 atom_client_list,
00118 0, 10000L,
00119 False, XA_WINDOW,
00120 &type, &format, &n_items,
00121 &bytes_after, (unsigned char **)&data);
00122
00123 if (result != Success || data == NULL || n_items == 0)
00124 {
00125 if (data) XFree(data);
00126 WARNPRINTF("failed to get client list, %d (items=%ld)", result, n_items);
00127 return None;
00128 }
00129
00130
00131 for (i = n_items-1; i >= 0; i--)
00132 {
00133 XClassHint hint;
00134 Window wnd = ((Window*)data)[i];
00135
00136
00137
00138 if (XGetClassHint(g_display, wnd, &hint))
00139 {
00140 LOGPRINTF("Window [%d] %d, %s", i, (guint) wnd, hint.res_name);
00141
00142 if (strcmp(hint.res_name, app_name) == 0)
00143 {
00144
00145 if (data) XFree(data);
00146 return wnd;
00147 }
00148 }
00149 }
00150
00151 if (data) XFree(data);
00152 return None;
00153 }
00154
00155
00156 gboolean window_register_destroy(Window new_window, void *callback_destroy, void *user_data)
00157 {
00158 LOGPRINTF("entry");
00159
00160 GList *l;
00161 l = get_window_list();
00162
00163 while (l)
00164 {
00165 Window window = (Window) l->data;
00166
00167 if (window == new_window)
00168 {
00169 LOGPRINTF("window found, register destroy handler");
00170
00171 g_signal_connect(G_OBJECT(window),
00172 "destroy",
00173 G_CALLBACK(callback_destroy),
00174 user_data);
00175 return TRUE;
00176 }
00177 l = l->next;
00178 }
00179
00180 WARNPRINTF("window not found: %d", (guint) new_window);
00181 g_list_free(l);
00182 return FALSE;
00183 }
00184
00185
00186 void window_activate(Window win)
00187 {
00188 LOGPRINTF("entry");
00189
00190 guint32 timestamp = gtk_get_current_event_time();
00191
00192
00193 XChangeProperty(g_display, win, atom_wm_user_time, XA_CARDINAL, 32, PropModeReplace, (guchar *) ×tamp, 1);
00194
00195 XEvent ev;
00196 memset(&ev, 0, sizeof ev);
00197 ev.xclient.type = ClientMessage;
00198 ev.xclient.window = win;
00199 ev.xclient.message_type = atom_active_window;
00200 ev.xclient.format = 32;
00201 ev.xclient.data.l[0] = 1;
00202 ev.xclient.data.l[1] = 0;
00203 ev.xclient.data.l[2] = 0;
00204 ev.xclient.data.l[3] = 0;
00205 ev.xclient.data.l[4] = 0;
00206
00207
00208
00209 XSendEvent(g_display,
00210 RootWindow(g_display, DefaultScreen(g_display)),
00211 False,
00212 SubstructureRedirectMask,
00213 &ev);
00214 }
00215
00216
00217
00218 char *get_application_of_window(Window wnd)
00219 {
00220 gchar *app_name = NULL;
00221 XClassHint hint;
00222
00223 LOGPRINTF("entry: %d", (int) wnd);
00224
00225 if (XGetClassHint(g_display, wnd, &hint))
00226 {
00227 LOGPRINTF("Window %s, %s", hint.res_name, hint.res_class);
00228 app_name = g_strdup(hint.res_name);
00229 if (hint.res_name) XFree(hint.res_name);
00230 if (hint.res_class) XFree(hint.res_class);
00231 return app_name;
00232 }
00233
00234 return NULL;
00235 }
00236
00237
00238 gint window_get_idle_time()
00239 {
00240 gint idle_time = -1;
00241 static XScreenSaverInfo *info;
00242
00243 LOGPRINTF("entry");
00244
00245 info = XScreenSaverAllocInfo();
00246 if (info != NULL)
00247 {
00248 XScreenSaverQueryInfo(g_display, RootWindow(g_display, DefaultScreen(g_display)), info);
00249 idle_time = (info->idle) / 1000;
00250 XFree(info);
00251 }
00252 return idle_time;
00253 }
00254
00255
00256
00257
00258
00259
00260 #if (TESTING_ON)
00261 void print_window_list()
00262 {
00263 Atom type;
00264 int format;
00265 unsigned char *data = NULL;
00266 unsigned long n_items, bytes_after;
00267 int result;
00268
00269
00270
00271 result = XGetWindowProperty(g_display, RootWindow(g_display, DefaultScreen(g_display)),
00272 atom_client_list,
00273 0, 10000L,
00274 False, XA_WINDOW,
00275 &type, &format, &n_items,
00276 &bytes_after, (unsigned char **)&data);
00277
00278 if (result != Success || data == NULL || n_items == 0)
00279 {
00280 if (data) XFree(data);
00281 WARNPRINTF("failed to get client list, %d (items=%ld)", result, n_items);
00282 return;
00283 }
00284
00285 printf("%s() WINDOWS (%lu)\n", __func__, n_items);
00286
00287 unsigned int i;
00288 for (i = 0; i < n_items; i++)
00289 {
00290 XClassHint hint;
00291 Window wnd = ((Window*)data)[i];
00292
00293
00294
00295 if (XGetClassHint(g_display, wnd, &hint))
00296 {
00297 printf(" Window [%d] %d, %s\n", i, (guint) wnd, hint.res_name);
00298 }
00299 }
00300 if (data) XFree(data);
00301 }
00302 #endif
00303
00304
00305 static GList *get_window_list()
00306 {
00307 LOGPRINTF("entry");
00308
00309 Atom type;
00310 int format;
00311 unsigned char *data = NULL;
00312 unsigned long n_items, bytes_after;
00313 int result;
00314 GList *l = NULL;
00315
00316
00317
00318 result = XGetWindowProperty(g_display, RootWindow(g_display, DefaultScreen(g_display)),
00319 atom_client_list,
00320 0, 10000L,
00321 False, XA_WINDOW,
00322 &type, &format, &n_items,
00323 &bytes_after, (unsigned char **)&data);
00324
00325 unsigned int i;
00326 for (i = 0; i <n_items; i++)
00327 {
00328
00329 l = g_list_prepend(l, (gpointer) ((Window*)data)[i]);
00330 }
00331
00332 if (data) XFree(data);
00333 return l;
00334 }
00335
00336
00337 static int on_x_error(Display *display, XErrorEvent *event)
00338 {
00339 char buf[100];
00340
00341 XGetErrorText(display, event->error_code, buf, sizeof(buf));
00342 ERRORPRINTF("X error: %s", buf);
00343
00344 return 0;
00345 }