[gpointing-device-settings] Watch DevicePresenceNotify event.



commit ff25a24d387887bc3bbacfb5bcaf2756695df096
Author: Hiroyuki Ikezoe <hiikezoe gnome org>
Date:   Sat Jun 26 19:55:40 2010 +0900

    Watch DevicePresenceNotify event.
    
    Some devices are not reported by xserver at the time of startiung up
    of gnome-settings-daemon, so we need to watch DevicePresenceNotify
    event at that time.
    
    Fix for bug #609050.

 .../gsd-pointing-device-plugin.c                   |  120 ++++++++++++++------
 src/gpds-xinput-utils.c                            |   27 +++++
 src/gpds-xinput-utils.h                            |    2 +
 test/test-xinput-utils.c                           |   16 +++-
 4 files changed, 131 insertions(+), 34 deletions(-)
---
diff --git a/modules/gnome-settings-daemon-plugins/gsd-pointing-device-plugin.c b/modules/gnome-settings-daemon-plugins/gsd-pointing-device-plugin.c
index 31dd336..8a2d98f 100644
--- a/modules/gnome-settings-daemon-plugins/gsd-pointing-device-plugin.c
+++ b/modules/gnome-settings-daemon-plugins/gsd-pointing-device-plugin.c
@@ -24,10 +24,13 @@
 #include <gnome-settings-daemon/gnome-settings-plugin.h>
 #include <glib/gi18n.h>
 #include <gconf/gconf-client.h>
+#include <gdk/gdkx.h>
+#include <X11/extensions/XInput.h>
 
 #include "gsd-pointing-device-manager.h"
 #include "gpds-gconf.h"
 #include "gpds-xinput-pointer-info.h"
+#include "gpds-xinput-utils.h"
 
 #define GSD_TYPE_POINTING_DEVICE_PLUGIN            (gsd_pointing_device_plugin_get_type ())
 #define GSD_POINTING_DEVICE_PLUGIN(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSD_TYPE_POINTING_DEVICE_PLUGIN, GsdPointingDevicePlugin))
@@ -61,44 +64,90 @@ gsd_pointing_device_plugin_init (GsdPointingDevicePlugin *plugin)
     plugin->managers = NULL;
 }
 
-static GList *
-collect_pointer_device_infos_from_gconf (void)
+static gboolean
+has_manager (GsdPointingDevicePlugin *plugin, const gchar *device_name)
 {
-    GConfClient *gconf;
-    GSList *dirs, *node;
-    GList *infos = NULL;
-
-    gconf = gconf_client_get_default();
-    dirs = gconf_client_all_dirs(gconf, GPDS_GCONF_DIR, NULL);
-
-    for (node = dirs; node; node = g_slist_next(node)) {
-        const gchar *dir = node->data;
-        gchar *device_type;
-        gchar *device_type_key;
-
-        device_type_key = gconf_concat_dir_and_key(dir, GPDS_GCONF_DEVICE_TYPE_KEY);
-        device_type = gconf_client_get_string(gconf, device_type_key, NULL);
-        if (device_type) {
-            GpdsXInputPointerInfo *info;
-            gchar *device_name, *unescaped_device_name;
-
-            device_name = g_path_get_basename(dir);
-            unescaped_device_name = gconf_unescape_key(device_name, -1);
-            info = gpds_xinput_pointer_info_new(unescaped_device_name, device_type);
-            infos = g_list_prepend(infos, info);
-            g_free(unescaped_device_name);
-            g_free(device_name);
+    GList *node;
+
+    for (node = plugin->managers; node; node = g_list_next(node)) {
+        GsdPointingDeviceManager *manager = node->data;
+
+        if (g_str_equal(gsd_pointing_device_manager_get_device_name(manager), device_name))
+            return TRUE;
+    }
+
+    return FALSE;
+}
+
+static GdkFilterReturn
+device_presence_filter (GdkXEvent *xevent,
+                        GdkEvent  *event,
+                        gpointer   data)
+{
+    XEvent *xev = (XEvent *)xevent;
+    XEventClass class_presence;
+    int xi_presence;
+    GsdPointingDevicePlugin *plugin = GSD_POINTING_DEVICE_PLUGIN(data);
+
+    DevicePresence(gdk_x11_get_default_xdisplay(), xi_presence, class_presence);
+
+    if (xev->type == xi_presence) {
+        XDeviceInfo *device_info = NULL;
+        XDevicePresenceNotifyEvent *notify_event = (XDevicePresenceNotifyEvent *)xev;
+
+        device_info = gpds_xinput_utils_get_device_info_from_id(notify_event->deviceid, NULL);
+        if (notify_event->devchange == DeviceEnabled) {
+            GsdPointingDeviceManager *manager;
+
+            if (has_manager(plugin, device_info->name))
+                return GDK_FILTER_CONTINUE;
+
+            manager = gsd_pointing_device_manager_new(gdk_x11_get_xatom_name(device_info->type),
+                                                      device_info->name);
+            if (manager) {
+                gsd_pointing_device_manager_start(manager, NULL);
+                plugin->managers = g_list_prepend(plugin->managers, manager);
+            }
+        } else if (notify_event->devchange == DeviceRemoved) {
         }
+    }
 
-        g_free(device_type_key);
-        g_free(device_type);
+    return GDK_FILTER_CONTINUE;
+}
+
+static void
+add_device_presence_filter (GsdPointingDevicePlugin *plugin)
+{
+    Display *display;
+    XEventClass class_presence;
+    gint xi_presence;
+
+    gint op_code, event, error;
+
+    if (!XQueryExtension(GDK_DISPLAY(),
+                         "XInputExtension",
+                         &op_code,
+                         &event,
+                         &error)) {
+        return;
     }
 
-    g_slist_foreach(dirs, (GFunc)g_free, NULL);
-    g_slist_free(dirs);
-    g_object_unref(gconf);
+    display = gdk_x11_get_default_xdisplay();
 
-    return infos;
+    gdk_error_trap_push();
+    DevicePresence(display, xi_presence, class_presence);
+    XSelectExtensionEvent(display,
+                          RootWindow(display, DefaultScreen(display)),
+                          &class_presence, 1);
+    gdk_flush();
+    if (!gdk_error_trap_pop())
+        gdk_window_add_filter(NULL, device_presence_filter, plugin);
+}
+
+static void
+remove_device_presence_filter (GsdPointingDevicePlugin *plugin)
+{
+    gdk_window_remove_filter(NULL, device_presence_filter, plugin);
 }
 
 static void
@@ -109,7 +158,10 @@ activate (GnomeSettingsPlugin *plugin)
 
     pointing_device_plugin = GSD_POINTING_DEVICE_PLUGIN(plugin); 
 
-    pointer_device_infos = collect_pointer_device_infos_from_gconf();
+    add_device_presence_filter(pointing_device_plugin);
+
+    pointer_device_infos = gpds_xinput_utils_collect_pointer_infos();
+
     for (node = pointer_device_infos; node; node = g_list_next(node)) {
         GsdPointingDeviceManager *manager;
         GpdsXInputPointerInfo *info = node->data;
@@ -133,6 +185,8 @@ stop_all_managers (GsdPointingDevicePlugin *plugin)
 {
     GList *node;
 
+    remove_device_presence_filter(plugin);
+
     for (node = plugin->managers; node; node = g_list_next(node)) {
         GsdPointingDeviceManager *manager = node->data;
 
diff --git a/src/gpds-xinput-utils.c b/src/gpds-xinput-utils.c
index 48dc2a5..0f7ceea 100644
--- a/src/gpds-xinput-utils.c
+++ b/src/gpds-xinput-utils.c
@@ -62,6 +62,33 @@ gpds_xinput_utils_get_device_info (const gchar *device_name, GError **error)
     return NULL;
 }
 
+XDeviceInfo *
+gpds_xinput_utils_get_device_info_from_id  (XID id, GError **error)
+{
+    XDeviceInfo *device_infos;
+    gint i, n_device_infos;
+
+    device_infos = XListInputDevices(GDK_DISPLAY(), &n_device_infos);
+
+    for (i = 0; i < n_device_infos; i++) {
+        if (device_infos[i].use != IsXExtensionPointer)
+            continue;
+        if (device_infos[i].id == id) {
+            XFreeDeviceList(device_infos);
+            return &device_infos[i];
+        }
+    }
+
+    XFreeDeviceList(device_infos);
+
+    g_set_error(error,
+                GPDS_XINPUT_UTILS_ERROR,
+                GPDS_XINPUT_UTILS_ERROR_NO_DEVICE,
+                _("No device found for %d."), (int)id);
+
+    return NULL;
+}
+
 gshort
 gpds_xinput_utils_get_device_num_buttons (const gchar *device_name, GError **error)
 {
diff --git a/src/gpds-xinput-utils.h b/src/gpds-xinput-utils.h
index 9cc4564..74e491a 100644
--- a/src/gpds-xinput-utils.h
+++ b/src/gpds-xinput-utils.h
@@ -38,6 +38,8 @@ typedef enum
 GQuark       gpds_xinput_utils_error_quark              (void);
 XDeviceInfo *gpds_xinput_utils_get_device_info          (const gchar *device_name,
                                                          GError **error);
+XDeviceInfo *gpds_xinput_utils_get_device_info_from_id  (XID id,
+                                                         GError **error);
 XDevice     *gpds_xinput_utils_open_device              (const gchar *device_name, GError **error);
 Atom         gpds_xinput_utils_get_float_atom           (GError **error);
 gshort       gpds_xinput_utils_get_device_num_buttons   (const gchar *device_name, GError **error);
diff --git a/test/test-xinput-utils.c b/test/test-xinput-utils.c
index 29b3f4e..a06dcbc 100644
--- a/test/test-xinput-utils.c
+++ b/test/test-xinput-utils.c
@@ -6,6 +6,7 @@
 void test_exist_device (void);
 void test_get_float_atom (void);
 void test_get_device_info (void);
+void test_get_device_info_from_id (void);
 void test_open_device (void);
 void test_open_no_device (void);
 void test_get_device_num_buttons (void);
@@ -49,7 +50,7 @@ test_get_float_atom (void)
 void
 test_get_device_info (void)
 {
-    XDeviceInfo *device_info = NULL; 
+    XDeviceInfo *device_info = NULL;
     device_info = gpds_xinput_utils_get_device_info(DEVICE_NAME, &error);
     cut_assert(device_info);
 
@@ -57,6 +58,19 @@ test_get_device_info (void)
 }
 
 void
+test_get_device_info_from_id (void)
+{
+    XDeviceInfo *device_info = NULL;
+    device_info = gpds_xinput_utils_get_device_info(DEVICE_NAME, &error);
+    cut_assert(device_info);
+
+    gcut_assert_error(error);
+
+    device_info = gpds_xinput_utils_get_device_info_from_id(device_info->id, &error);
+    cut_assert_equal_string(DEVICE_NAME, device_info->name);
+}
+
+void
 test_open_device (void)
 {
     device = gpds_xinput_utils_open_device(DEVICE_NAME, &error);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]