[gtk+/xi2: 318/1239] Add initial XI2 GdkDeviceManager implementation.



commit 1ca43e353c8c31bf2b2033b0d3b83f9a5084f9a3
Author: Carlos Garnacho <carlosg gnome org>
Date:   Sun Jun 14 19:14:14 2009 +0200

    Add initial XI2 GdkDeviceManager implementation.

 configure.in                   |    6 +-
 gdk/x11/Makefile.am            |    7 +-
 gdk/x11/gdkdevicemanager-x11.c |   38 ++++++
 gdk/x11/gdkdevicemanager-xi2.c |  273 ++++++++++++++++++++++++++++++++++++++++
 gdk/x11/gdkdevicemanager-xi2.h |   59 +++++++++
 5 files changed, 381 insertions(+), 2 deletions(-)
---
diff --git a/configure.in b/configure.in
index faf9496..55defa5 100644
--- a/configure.in
+++ b/configure.in
@@ -1560,9 +1560,12 @@ if test "x$gdktarget" = "xx11"; then
   if test "x$with_xinput" = "xxfree" || test "x$with_xinput" = "xyes"; then
     AC_DEFINE(XINPUT_XFREE, 1,
               [Define to 1 if XFree XInput should be used])
-    
+
     if $PKG_CONFIG --exists xi ; then
       X_PACKAGES="$X_PACKAGES xi"
+
+      AC_CHECK_HEADER(X11/extensions/XInput2.h,
+                      have_xinput2=yes; AC_DEFINE(XINPUT_2, 1, [Define to 1 if XInput 2.0 is available]))
     else
       GTK_ADD_LIB(x_extra_libs, Xi)
     fi
@@ -1572,6 +1575,7 @@ if test "x$gdktarget" = "xx11"; then
   fi
 
   AM_CONDITIONAL(XINPUT_XFREE, test x$with_xinput = xxfree || test x$with_xinput = xyes)
+  AM_CONDITIONAL(XINPUT_2, test "x$have_xinput2" = "xyes")
 
   # Check for the RANDR extension
   if $PKG_CONFIG --exists "xrandr >= 1.2.99" ; then
diff --git a/gdk/x11/Makefile.am b/gdk/x11/Makefile.am
index 93b18cf..4cd9e2c 100644
--- a/gdk/x11/Makefile.am
+++ b/gdk/x11/Makefile.am
@@ -23,6 +23,7 @@ libgdk_x11_la_SOURCES =    	\
 	gdkasync.h		\
 	gdkcolor-x11.c	   	\
 	gdkcursor-x11.c	   	\
+	gdkdevicemanager-core.c \
 	gdkdevicemanager-x11.c	\
 	gdkdisplay-x11.c	\
 	gdkdisplay-x11.h	\
@@ -64,10 +65,14 @@ libgdk_x11_la_SOURCES =    	\
 	xsettings-common.h	\
 	xsettings-common.c
 
+if XINPUT_2
+libgdk_x11_la_SOURCES += gdkinput-x11.c gdkinput-xfree.c gdkdevicemanager-xi2.c
+else
 if XINPUT_XFREE
 libgdk_x11_la_SOURCES += gdkinput-x11.c gdkinput-xfree.c
 else
-libgdk_x11_la_SOURCES += gdkinput-none.c gdkdevicemanager-core.c
+libgdk_x11_la_SOURCES += gdkinput-none.c
+endif
 endif
 
 
diff --git a/gdk/x11/gdkdevicemanager-x11.c b/gdk/x11/gdkdevicemanager-x11.c
index 5ad9512..47dc4a7 100644
--- a/gdk/x11/gdkdevicemanager-x11.c
+++ b/gdk/x11/gdkdevicemanager-x11.c
@@ -18,11 +18,49 @@
  */
 
 #include "config.h"
+#include "gdkx.h"
 #include "gdkdevicemanager-core.h"
 
+#ifdef XINPUT_2
+#include "gdkdevicemanager-xi2.h"
+#endif /* XINPUT_2 */
+
 GdkDeviceManager *
 _gdk_device_manager_new (GdkDisplay *display)
 {
+  GdkDeviceManager *device_manager;
+  int opcode, firstevent, firsterror;
+  int major, minor;
+  Display *xdisplay;
+
+#if defined (XINPUT_2) || defined (XINPUT_XFREE)
+  xdisplay = GDK_DISPLAY_XDISPLAY (display);
+
+  if (XQueryExtension (xdisplay, "XInputExtension",
+                       &opcode, &firstevent, &firsterror))
+    {
+#if defined (XINPUT_2)
+      major = 2;
+      minor = 0;
+
+      if (XIQueryVersion (xdisplay, &major, &minor) != BadRequest)
+        {
+          GdkDeviceManagerXI2 *device_manager_xi2;
+
+          device_manager = g_object_new (GDK_TYPE_DEVICE_MANAGER_XI2,
+                                         "display", display,
+                                         NULL);
+
+          device_manager_xi2 = GDK_DEVICE_MANAGER_XI2 (device_manager);
+          device_manager_xi2->opcode = opcode;
+
+          return device_manager;
+        }
+#endif
+    }
+
+#endif /* XINPUT_2 || XINPUT_XFREE */
+
   return g_object_new (GDK_TYPE_DEVICE_MANAGER_CORE,
                        "display", display,
                        NULL);
diff --git a/gdk/x11/gdkdevicemanager-xi2.c b/gdk/x11/gdkdevicemanager-xi2.c
new file mode 100644
index 0000000..704a859
--- /dev/null
+++ b/gdk/x11/gdkdevicemanager-xi2.c
@@ -0,0 +1,273 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 2009 Carlos Garnacho <carlosg gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "gdkdevicemanager-xi2.h"
+#include "gdkeventtranslator.h"
+#include "gdkinputprivate.h"
+#include "gdkx.h"
+
+static void    gdk_device_manager_xi2_constructed (GObject *object);
+
+static GList * gdk_device_manager_xi2_get_devices (GdkDeviceManager *device_manager,
+                                                   GdkDeviceType     type);
+static void    gdk_device_manager_xi2_set_window_events (GdkDeviceManager *device_manager,
+                                                         GdkWindow        *window,
+                                                         GdkEventMask      event_mask);
+
+static void     gdk_device_manager_xi2_event_translator_init (GdkEventTranslatorIface *iface);
+
+static gboolean gdk_device_manager_xi2_translate_event (GdkEventTranslator *translator,
+                                                        GdkDisplay         *display,
+                                                        GdkEvent           *event,
+                                                        XEvent             *xevent);
+
+
+G_DEFINE_TYPE_WITH_CODE (GdkDeviceManagerXI2, gdk_device_manager_xi2, GDK_TYPE_DEVICE_MANAGER,
+                         G_IMPLEMENT_INTERFACE (GDK_TYPE_EVENT_TRANSLATOR,
+                                                gdk_device_manager_xi2_event_translator_init))
+
+
+static void
+gdk_device_manager_xi2_class_init (GdkDeviceManagerXI2Class *klass)
+{
+  GdkDeviceManagerClass *device_manager_class = GDK_DEVICE_MANAGER_CLASS (klass);
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->constructed = gdk_device_manager_xi2_constructed;
+
+  device_manager_class->get_devices = gdk_device_manager_xi2_get_devices;
+  device_manager_class->set_window_events = gdk_device_manager_xi2_set_window_events;
+}
+
+static void
+gdk_device_manager_xi2_init (GdkDeviceManagerXI2 *device_manager)
+{
+}
+
+static void
+translate_event_mask (GdkEventMask   event_mask,
+                      unsigned char *mask)
+{
+  if (event_mask & GDK_POINTER_MOTION_MASK ||
+      event_mask & GDK_POINTER_MOTION_HINT_MASK)
+    XISetMask (mask, XI_Motion);
+
+  if (event_mask & GDK_BUTTON_MOTION_MASK ||
+      event_mask & GDK_BUTTON1_MOTION_MASK ||
+      event_mask & GDK_BUTTON2_MOTION_MASK ||
+      event_mask & GDK_BUTTON3_MOTION_MASK)
+    {
+      XISetMask (mask, XI_ButtonPress);
+      XISetMask (mask, XI_ButtonRelease);
+      XISetMask (mask, XI_Motion);
+    }
+
+  if (event_mask & GDK_SCROLL_MASK)
+    {
+      XISetMask (mask, XI_ButtonPress);
+      XISetMask (mask, XI_ButtonRelease);
+    }
+
+  if (event_mask & GDK_BUTTON_PRESS_MASK)
+    XISetMask (mask, XI_ButtonPress);
+
+  if (event_mask & GDK_BUTTON_RELEASE_MASK)
+    XISetMask (mask, XI_ButtonRelease);
+
+      if (event_mask & GDK_KEY_PRESS_MASK)
+    XISetMask (mask, XI_KeyPress);
+
+  if (event_mask & GDK_KEY_RELEASE_MASK)
+    XISetMask (mask, XI_KeyRelease);
+
+  if (event_mask & GDK_ENTER_NOTIFY_MASK)
+    XISetMask (mask, XI_Enter);
+
+  if (event_mask & GDK_LEAVE_NOTIFY_MASK)
+    XISetMask (mask, XI_Leave);
+
+  if (event_mask & GDK_FOCUS_CHANGE_MASK)
+    {
+      XISetMask (mask, XI_FocusIn);
+      XISetMask (mask, XI_FocusOut);
+    }
+
+  /* FIXME: Proximity in/out mask */
+}
+
+static void
+_gdk_device_manager_xi2_select_events (GdkDeviceManager *device_manager,
+                                       GdkWindow        *window,
+                                       int               device_id,
+                                       unsigned char    *mask)
+{
+  GdkDisplay *display;
+  Display *xdisplay;
+  Window xwindow;
+  XIEventMask event_mask;
+
+  display = gdk_device_manager_get_display (device_manager);
+  xdisplay = GDK_DISPLAY_XDISPLAY (display);
+  xwindow = GDK_WINDOW_XWINDOW (window);
+
+  event_mask.deviceid = device_id;
+  event_mask.mask_len = sizeof (mask);
+  event_mask.mask = mask;
+
+  XISelectEvents (xdisplay, xwindow, &event_mask, 1);
+}
+
+static void
+gdk_device_manager_xi2_constructed (GObject *object)
+{
+  GdkDeviceManagerXI2 *device_manager_xi2;
+  GdkDisplay *display;
+  GdkScreen *screen;
+  Display *xdisplay;
+  XIDeviceInfo *info, *dev;
+  int ndevices, i;
+  unsigned char mask[2] = { 0 };
+
+  device_manager_xi2 = GDK_DEVICE_MANAGER_XI2 (object);
+  display = gdk_device_manager_get_display (GDK_DEVICE_MANAGER (object));
+  xdisplay = GDK_DISPLAY_XDISPLAY (display);
+
+  info = XIQueryDevice(xdisplay, XIAllDevices, &ndevices);
+
+  /* Initialize devices list */
+  for (i = 0; i < ndevices; i++)
+    {
+      GdkDevice *device;
+      GdkDevicePrivate *private;
+
+      dev = &info[i];
+
+      device = g_object_new (GDK_TYPE_DEVICE, NULL);
+      private = (GdkDevicePrivate *) device;
+
+      device->name = g_strdup (dev->name);
+      device->source = GDK_SOURCE_MOUSE;
+      device->mode = GDK_MODE_SCREEN;
+      device->has_cursor = TRUE;
+      device->num_axes = 0;
+      device->axes = NULL;
+      device->num_keys = 0;
+      device->keys = NULL;
+
+      private->display = display;
+
+      if (dev->use == XIMasterPointer)
+        device_manager_xi2->master_devices = g_list_prepend (device_manager_xi2->master_devices, device);
+      else if (dev->use == XISlavePointer)
+        device_manager_xi2->slave_devices = g_list_prepend (device_manager_xi2->slave_devices, device);
+      else if (dev->use == XIFloatingSlave)
+        device_manager_xi2->floating_devices = g_list_prepend (device_manager_xi2->floating_devices, device);
+      else
+        {
+          g_warning ("Unhandled device: %s\n", device->name);
+          g_object_unref (device);
+        }
+    }
+
+  XIFreeDeviceInfo(info);
+
+  /* Connect to hierarchy change events */
+  screen = gdk_display_get_default_screen (display);
+  XISetMask (mask, XI_HierarchyChanged);
+
+  _gdk_device_manager_xi2_select_events (GDK_DEVICE_MANAGER (object),
+                                         gdk_screen_get_root_window (screen),
+                                         XIAllDevices,
+                                         mask);
+}
+
+static GList *
+gdk_device_manager_xi2_get_devices (GdkDeviceManager *device_manager,
+                                    GdkDeviceType     type)
+{
+  GdkDeviceManagerXI2 *device_manager_xi2;
+  GList *list = NULL;
+
+  device_manager_xi2 = GDK_DEVICE_MANAGER_XI2 (device_manager);
+
+  switch (type)
+    {
+    case GDK_DEVICE_TYPE_MASTER:
+      list = device_manager_xi2->master_devices;
+      break;
+    case GDK_DEVICE_TYPE_SLAVE:
+      list = device_manager_xi2->slave_devices;
+      break;
+    case GDK_DEVICE_TYPE_FLOATING:
+      list = device_manager_xi2->floating_devices;
+      break;
+    default:
+      g_assert_not_reached ();
+    }
+
+  return g_list_copy (list);;
+}
+
+static void
+gdk_device_manager_xi2_set_window_events (GdkDeviceManager *device_manager,
+                                          GdkWindow        *window,
+                                          GdkEventMask      event_mask)
+{
+  unsigned char mask[2] = { 0 };
+
+  translate_event_mask (event_mask, mask);
+
+  _gdk_device_manager_xi2_select_events (device_manager, window,
+                                         XIAllMasterDevices,
+                                         mask);
+}
+
+static void
+gdk_device_manager_xi2_event_translator_init (GdkEventTranslatorIface *iface)
+{
+  iface->translate_event = gdk_device_manager_xi2_translate_event;
+}
+
+static gboolean
+gdk_device_manager_xi2_translate_event (GdkEventTranslator *translator,
+                                        GdkDisplay         *display,
+                                        GdkEvent           *event,
+                                        XEvent             *xevent)
+{
+  GdkDeviceManagerXI2 *device_manager;
+  XIEvent *ev;
+  gboolean return_val = TRUE;
+
+  ev = (XIEvent *) xevent;
+  device_manager = (GdkDeviceManagerXI2 *) translator;
+
+  if (ev->type != GenericEvent || ev->extension != device_manager->opcode)
+    return FALSE;
+
+  switch (ev->evtype)
+    {
+    default:
+      return_val = FALSE;
+      break;
+    }
+
+  XIFreeEventData (ev);
+
+  return return_val;
+}
diff --git a/gdk/x11/gdkdevicemanager-xi2.h b/gdk/x11/gdkdevicemanager-xi2.h
new file mode 100644
index 0000000..b033c65
--- /dev/null
+++ b/gdk/x11/gdkdevicemanager-xi2.h
@@ -0,0 +1,59 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 2009 Carlos Garnacho <carlosg gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GDK_DEVICE_MANAGER_XI2_H__
+#define __GDK_DEVICE_MANAGER_XI2_H__
+
+#include <gdk/gdkdevicemanager.h>
+#include <X11/extensions/XInput2.h>
+
+G_BEGIN_DECLS
+
+#define GDK_TYPE_DEVICE_MANAGER_XI2         (gdk_device_manager_xi2_get_type ())
+#define GDK_DEVICE_MANAGER_XI2(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), GDK_TYPE_DEVICE_MANAGER_XI2, GdkDeviceManagerXI2))
+#define GDK_DEVICE_MANAGER_XI2_CLASS(c)     (G_TYPE_CHECK_CLASS_CAST ((c), GDK_TYPE_DEVICE_MANAGER_XI2, GdkDeviceManagerXI2Class))
+#define GDK_IS_DEVICE_MANAGER_XI2(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDK_TYPE_DEVICE_MANAGER_XI2))
+#define GDK_IS_DEVICE_MANAGER_XI2_CLASS(c)  (G_TYPE_CHECK_CLASS_TYPE ((c), GDK_TYPE_DEVICE_MANAGER_XI2))
+#define GDK_DEVICE_MANAGER_XI2_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDK_TYPE_DEVICE_MANAGER_XI2, GdkDeviceManagerXI2Class))
+
+typedef struct _GdkDeviceManagerXI2 GdkDeviceManagerXI2;
+typedef struct _GdkDeviceManagerXI2Class GdkDeviceManagerXI2Class;
+
+struct _GdkDeviceManagerXI2
+{
+  GdkDeviceManager parent_object;
+
+  GList *master_devices;
+  GList *slave_devices;
+  GList *floating_devices;
+
+  int opcode;
+};
+
+struct _GdkDeviceManagerXI2Class
+{
+  GdkDeviceManagerClass parent_class;
+};
+
+GType gdk_device_manager_xi2_get_type (void) G_GNUC_CONST;
+
+
+G_END_DECLS
+
+#endif /* __GDK_DEVICE_MANAGER_CORE_H__ */



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