[PATCH] Reapply settings when external keyboard connects

Martin Kelly martin at martingkelly.com
Fri May 9 20:05:10 CEST 2014


Signed-off-by: Martin Kelly <martin at martingkelly.com>
---
 xfsettingsd/keyboards.c | 115 +++++++++++++++++++++++++++++++++++++++++++++---
 xfsettingsd/keyboards.h |  12 +++++
 2 files changed, 122 insertions(+), 5 deletions(-)

diff --git a/xfsettingsd/keyboards.c b/xfsettingsd/keyboards.c
index 976e2ba..e5c59de 100644
--- a/xfsettingsd/keyboards.c
+++ b/xfsettingsd/keyboards.c
@@ -54,6 +54,13 @@ static void xfce_keyboards_helper_channel_property_changed  (XfconfChannel
                                                              XfceKeyboardsHelper      *helper);
 static void xfce_keyboards_helper_restore_numlock_state     (XfconfChannel            *channel);
 static void xfce_keyboards_helper_save_numlock_state        (XfconfChannel            *channel);
+static gboolean xfce_keyboards_helper_device_is_keyboard    (XID xid);
+static void xfce_keyboards_helper_set_all_settings          (XfceKeyboardsHelper      *helper);
+#ifdef DEVICE_HOTPLUGGING
+static GdkFilterReturn  xfce_keyboards_helper_event_filter  (GdkXEvent                *xevent,
+                                                             GdkEvent                 *gdk_event,
+                                                             gpointer                 user_data);
+#endif
 
 
 
@@ -69,6 +76,12 @@ struct _XfceKeyboardsHelper
 
     /* xfconf channel */
     XfconfChannel *channel;
+
+#ifdef DEVICE_HOTPLUGGING
+    /* device presence event type */
+    gint device_presence_event_type;
+#endif
+
 };
 
 
@@ -93,11 +106,18 @@ xfce_keyboards_helper_init (XfceKeyboardsHelper *helper)
 {
     gint dummy;
     gint marjor_ver, minor_ver;
+    Display *xdisplay;
+#ifdef DEVICE_HOTPLUGGING
+    XEventClass event_class;
+#endif
 
     /* init */
     helper->channel = NULL;
 
-    if (XkbQueryExtension (GDK_DISPLAY (), &dummy, &dummy, &dummy, &marjor_ver, &minor_ver))
+    /* get the default display */
+    xdisplay = gdk_x11_display_get_xdisplay (gdk_display_get_default ());
+
+    if (XkbQueryExtension (xdisplay, &dummy, &dummy, &dummy, &marjor_ver, &minor_ver))
     {
         xfsettings_dbg (XFSD_DEBUG_KEYBOARDS, "initialized xkb %d.%d", marjor_ver, minor_ver);
 
@@ -108,10 +128,24 @@ xfce_keyboards_helper_init (XfceKeyboardsHelper *helper)
         g_signal_connect (G_OBJECT (helper->channel), "property-changed",
             G_CALLBACK (xfce_keyboards_helper_channel_property_changed), helper);
 
-        /* load settings */
-        xfce_keyboards_helper_set_auto_repeat_mode (helper);
-        xfce_keyboards_helper_set_repeat_rate (helper);
-        xfce_keyboards_helper_restore_numlock_state (helper->channel);
+#ifdef DEVICE_HOTPLUGGING
+        if (G_LIKELY (xdisplay != NULL))
+        {
+            /* monitor device changes */
+            gdk_error_trap_push ();
+            DevicePresence (xdisplay, helper->device_presence_event_type, event_class);
+            XSelectExtensionEvent (xdisplay, RootWindow (xdisplay, DefaultScreen (xdisplay)), &event_class, 1);
+
+            /* add an event filter */
+            if (gdk_error_trap_pop () == 0)
+                gdk_window_add_filter (NULL, xfce_keyboards_helper_event_filter, helper);
+            else
+                g_warning ("Failed to create device filter");
+        }
+#endif
+
+        /* load keyboard settings */
+        xfce_keyboards_helper_set_all_settings (helper);
     }
     else
     {
@@ -271,3 +305,74 @@ xfce_keyboards_helper_save_numlock_state (XfconfChannel *channel)
 
     xfconf_channel_set_bool (channel, "/Default/Numlock", numlock_state);
 }
+
+
+
+static void
+xfce_keyboards_helper_set_all_settings (XfceKeyboardsHelper *helper)
+{
+        xfce_keyboards_helper_set_auto_repeat_mode (helper);
+        xfce_keyboards_helper_set_repeat_rate (helper);
+        xfce_keyboards_helper_restore_numlock_state (helper->channel);
+}
+
+
+
+#ifdef DEVICE_HOTPLUGGING
+static gboolean
+xfce_keyboards_helper_device_is_keyboard (XID xid)
+{
+    XDeviceInfo *device;
+    gboolean device_found;
+    XDeviceInfo *device_list;
+    Atom         keyboard_type;
+    gint         n, ndevices;
+    Display     *xdisplay = GDK_DISPLAY ();
+
+    keyboard_type = XInternAtom (xdisplay, XI_KEYBOARD, True);
+    device_list = XListInputDevices(xdisplay, &ndevices);
+    device_found = FALSE;
+    for (n = 0; n < ndevices; n++)
+    {
+        device = &device_list[n];
+        /* look for a keyboard that matches this XID */
+        if (device->type == keyboard_type &&
+            device->id == xid)
+        {
+            device_found = TRUE;
+            break;
+        }
+    }
+    XFreeDeviceList(device_list);
+
+    return device_found;
+}
+#endif
+
+
+
+#ifdef DEVICE_HOTPLUGGING
+static GdkFilterReturn
+xfce_keyboards_helper_event_filter (GdkXEvent *xevent,
+                                    GdkEvent  *gdk_event,
+                                    gpointer   user_data)
+{
+    XEvent                     *event = xevent;
+    XDevicePresenceNotifyEvent *dpn_event = xevent;
+    XfceKeyboardsHelper        *helper = XFCE_KEYBOARDS_HELPER (user_data);
+
+    if (G_UNLIKELY (event->type != helper->device_presence_event_type))
+        return GDK_FILTER_CONTINUE;
+
+    if (G_LIKELY (dpn_event->devchange != DeviceAdded))
+        return GDK_FILTER_CONTINUE;
+
+    if (!xfce_keyboards_helper_device_is_keyboard(dpn_event->deviceid))
+        return GDK_FILTER_CONTINUE;
+
+    /* New keyboard added. Need to reapply settings. */
+    xfce_keyboards_helper_set_all_settings (helper);
+
+    return GDK_FILTER_CONTINUE;
+}
+#endif
diff --git a/xfsettingsd/keyboards.h b/xfsettingsd/keyboards.h
index ff2c174..a276be3 100644
--- a/xfsettingsd/keyboards.h
+++ b/xfsettingsd/keyboards.h
@@ -19,6 +19,8 @@
  *  by Olivier Fourdan.
  */
 
+#include <X11/extensions/XInput.h>
+
 #ifndef __KEYBOARDS_H__
 #define __KEYBOARDS_H__
 
@@ -32,6 +34,16 @@ typedef struct _XfceKeyboardsHelper      XfceKeyboardsHelper;
 #define XFCE_IS_KEYBOARDS_HELPER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XFCE_TYPE_KEYBOARDS_HELPER))
 #define XFCE_KEYBOARDS_HELPER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), XFCE_TYPE_KEYBOARDS_HELPER, XfceKeyboardsHelperClass))
 
+/* test if the required version of inputproto (1.4.2) is available */
+#undef DEVICE_HOTPLUGGING
+#ifdef XI_Add_DevicePresenceNotify_Major
+#  if XI_Add_DevicePresenceNotify_Major >= 1 && defined (DeviceRemoved)
+#    define DEVICE_HOTPLUGGING
+#  else
+#    undef DEVICE_HOTPLUGGING
+#  endif
+#endif
+
 GType xfce_keyboards_helper_get_type (void) G_GNUC_CONST;
 
 #endif /* !__KEYBOARDS_H__ */
-- 
2.0.0.rc2



More information about the Xfce4-dev mailing list