xwindow.c

Go to the documentation of this file.
00001 /*
00002  * File Name: xwindow.c
00003  */
00004 
00005 /*
00006  * This file is part of sysd.
00007  *
00008  * sysd is free software: you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation, either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * sysd is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program. If not, see <http://www.gnu.org/licenses/>.
00020  */
00021 
00022 /**
00023  * Copyright (C) 2008 iRex Technologies B.V.
00024  * All rights reserved.
00025  */
00026 
00027 //----------------------------------------------------------------------------
00028 // Include Files
00029 //----------------------------------------------------------------------------
00030 
00031 // system include files, between < >
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 // ereader include files, between < >
00043 
00044 // local include files, between " "
00045 #include "log.h"
00046 #include "xwindow.h"
00047 
00048 
00049 //----------------------------------------------------------------------------
00050 // Type Declarations
00051 //----------------------------------------------------------------------------
00052 
00053 
00054 //----------------------------------------------------------------------------
00055 // Constants
00056 //----------------------------------------------------------------------------
00057 
00058 
00059 //----------------------------------------------------------------------------
00060 // Static Variables
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 // Local Function Definitions
00071 //============================================================================
00072 
00073 static GList *get_window_list       (void);
00074 static int   on_x_error             (Display *display, XErrorEvent *event);
00075 
00076 
00077 //============================================================================
00078 // Functions Implementation
00079 //============================================================================
00080 
00081 void window_set_services()
00082 {
00083     // make Xlib thread safe
00084     XInitThreads();
00085     
00086     LOGPRINTF("XinitThreads returned");
00087     
00088     // install custom error handler to avoid X's default fatal errors
00089     XSetErrorHandler(on_x_error);
00090     
00091     // set display globally
00092     g_display = gdk_x11_get_default_xdisplay();
00093 
00094     // set atoms globally
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     // get list of available windows
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     // check backwards as new application is likely last in line
00131     for (i = n_items-1; i >= 0; i--)
00132     {
00133         XClassHint hint;
00134         Window wnd = ((Window*)data)[i];
00135         
00136         // get name of application of the window
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                 // found our application
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     // update user time for window
00193     XChangeProperty(g_display, win, atom_wm_user_time, XA_CARDINAL, 32, PropModeReplace, (guchar *) &timestamp, 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     // activate/raise window
00208     //
00209     XSendEvent(g_display,
00210                RootWindow(g_display, DefaultScreen(g_display)), 
00211                False,
00212                SubstructureRedirectMask, 
00213                &ev);
00214 }
00215 
00216 
00217 /* result should be freed when no longer used */
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 // Local Functions Implementation
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     // get list of available windows
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         // get name of application of the window
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     // get list of available windows
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 //        LOGPRINTF("-- window %s");
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 }
Generated by  doxygen 1.6.2-20100208