[mutter/wip/xinput2r: 6/68] core: Add helper code to handle input events



commit facfa526234237955d2e5c481165af1e7113c10c
Author: Carlos Garnacho <carlosg gnome org>
Date:   Wed Jun 8 10:18:35 2011 +0200

    core: Add helper code to handle input events
    
    These will be used with every input event out there so they're
    dealt with uniformly.

 src/Makefile.am         |    2 +
 src/core/input-events.c |  497 +++++++++++++++++++++++++++++++++++++++++++++++
 src/core/input-events.h |   64 ++++++
 3 files changed, 563 insertions(+), 0 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index d5b398c..3a73afd 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -97,6 +97,8 @@ libmutter_la_SOURCES =				\
 	meta/group.h				\
 	core/iconcache.c			\
 	core/iconcache.h			\
+	core/input-events.c			\
+	core/input-events.h			\
 	core/keybindings.c			\
 	core/keybindings-private.h		\
 	core/main.c				\
diff --git a/src/core/input-events.c b/src/core/input-events.c
new file mode 100644
index 0000000..fbd9d2a
--- /dev/null
+++ b/src/core/input-events.c
@@ -0,0 +1,497 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+
+/* XEvent utility methods */
+
+/*
+ * Copyright (C) 2011 Carlos Garnacho
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <config.h>
+#include "input-events.h"
+#include <X11/Xlib.h>
+
+#ifdef HAVE_XINPUT2
+#include <X11/extensions/XInput2.h>
+#endif
+
+/* Quite a hack: normalizes XI2 events to their
+ * core event equivalent, so most code is shared
+ * for both implementations, code handling input
+ * events should use the helper functions so
+ * the actual event is treated correctly.
+ */
+gboolean
+meta_input_event_get_type (MetaDisplay *display,
+                           XEvent      *ev,
+                           guint       *ev_type)
+{
+  guint type = 0; /* Silence gcc */
+  gboolean retval = TRUE;
+
+#ifdef HAVE_XINPUT2
+  if (display->have_xinput2 &&
+      ev->type == GenericEvent &&
+      ev->xcookie.extension == display->xinput2_opcode)
+    {
+      XIEvent *xev;
+
+      /* NB: GDK event filters already have generic events
+       * allocated, so no need to do XGetEventData() on our own
+       */
+      xev = (XIEvent *) ev->xcookie.data;
+
+      switch (xev->evtype)
+        {
+        case XI_Motion:
+          type = MotionNotify;
+          break;
+        case XI_ButtonPress:
+          type = ButtonPress;
+          break;
+        case XI_ButtonRelease:
+          type = ButtonRelease;
+          break;
+        case XI_KeyPress:
+          type = KeyPress;
+          break;
+        case XI_KeyRelease:
+          type = KeyRelease;
+          break;
+        case XI_FocusIn:
+          type = FocusIn;
+          break;
+        case XI_FocusOut:
+          type = FocusOut;
+          break;
+        case XI_Enter:
+          type = EnterNotify;
+          break;
+        case XI_Leave:
+          type = LeaveNotify;
+          break;
+        default:
+          retval = FALSE;
+          break;
+        }
+    }
+  else
+#endif /* HAVE_XINPUT2 */
+    {
+      switch (ev->type)
+        {
+        case MotionNotify:
+        case ButtonPress:
+        case ButtonRelease:
+        case KeyPress:
+        case KeyRelease:
+        case FocusIn:
+        case FocusOut:
+        case EnterNotify:
+        case LeaveNotify:
+          type = ev->type;
+          break;
+        default:
+          retval = FALSE;
+          break;
+        }
+    }
+
+  if (retval)
+    {
+      if (ev_type)
+        *ev_type = type;
+
+      return TRUE;
+    }
+  else
+    return FALSE;
+}
+
+
+Window
+meta_input_event_get_window (MetaDisplay *display,
+                             XEvent      *ev)
+{
+#ifdef HAVE_XINPUT2
+  if (ev->type == GenericEvent &&
+      ev->xcookie.extension == display->xinput2_opcode)
+    {
+      XIEvent *xev;
+
+      g_assert (display->have_xinput2 == TRUE);
+
+      /* GDK event filters already have generic events allocated */
+      xev = (XIEvent *) ev->xcookie.data;
+
+      switch (xev->evtype)
+        {
+        case XI_Motion:
+        case XI_ButtonPress:
+        case XI_ButtonRelease:
+        case XI_KeyPress:
+        case XI_KeyRelease:
+          return ((XIDeviceEvent *) xev)->event;
+        case XI_FocusIn:
+        case XI_FocusOut:
+        case XI_Enter:
+        case XI_Leave:
+          return ((XIEnterEvent *) xev)->event;
+        default:
+          return None;
+        }
+    }
+  else
+#endif /* HAVE_XINPUT2 */
+    return ev->xany.window;
+}
+
+Window
+meta_input_event_get_root_window (MetaDisplay *display,
+                                  XEvent      *ev)
+{
+#ifdef HAVE_XINPUT2
+  if (ev->type == GenericEvent &&
+      ev->xcookie.extension == display->xinput2_opcode)
+    {
+      XIEvent *xev;
+
+      g_assert (display->have_xinput2 == TRUE);
+
+      xev = (XIEvent *) ev->xcookie.data;
+
+      switch (xev->evtype)
+        {
+        case XI_Motion:
+        case XI_ButtonPress:
+        case XI_ButtonRelease:
+        case XI_KeyPress:
+        case XI_KeyRelease:
+          return ((XIDeviceEvent *) xev)->root;
+        case XI_FocusIn:
+        case XI_FocusOut:
+        case XI_Enter:
+        case XI_Leave:
+          return ((XIEnterEvent *) xev)->root;
+        default:
+          break;
+        }
+    }
+  else
+#endif /* HAVE_XINPUT2 */
+    {
+      switch (ev->type)
+        {
+        case KeyPress:
+        case KeyRelease:
+          return ev->xkey.root;
+        case ButtonPress:
+        case ButtonRelease:
+          return ev->xbutton.root;
+        case EnterNotify:
+        case LeaveNotify:
+          return ev->xcrossing.root;
+        case MotionNotify:
+          return ev->xbutton.root;
+        default:
+          break;
+        }
+    }
+
+  return None;
+}
+
+Time
+meta_input_event_get_time (MetaDisplay *display,
+                           XEvent      *ev)
+{
+#ifdef HAVE_XINPUT2
+  if (ev->type == GenericEvent &&
+      ev->xcookie.extension == display->xinput2_opcode)
+    {
+      XIEvent *xev;
+
+      g_assert (display->have_xinput2 == TRUE);
+
+      xev = (XIEvent *) ev->xcookie.data;
+
+      switch (xev->evtype)
+        {
+        case XI_Motion:
+        case XI_ButtonPress:
+        case XI_ButtonRelease:
+        case XI_KeyPress:
+        case XI_KeyRelease:
+          return ((XIDeviceEvent *) xev)->time;
+        case XI_FocusIn:
+        case XI_FocusOut:
+        case XI_Enter:
+        case XI_Leave:
+          return ((XIEnterEvent *) xev)->time;
+        default:
+          break;
+        }
+    }
+  else
+#endif /* HAVE_XINPUT2 */
+    {
+      switch (ev->type)
+        {
+        case KeyPress:
+        case KeyRelease:
+          return ev->xkey.time;
+        case ButtonPress:
+        case ButtonRelease:
+          return ev->xbutton.time;
+        case EnterNotify:
+        case LeaveNotify:
+          return ev->xcrossing.time;
+        case MotionNotify:
+          return ev->xmotion.time;
+        default:
+          break;
+        }
+    }
+
+  return CurrentTime;
+}
+
+gboolean
+meta_input_event_get_coordinates (MetaDisplay *display,
+                                  XEvent      *ev,
+                                  gdouble     *x_ret,
+                                  gdouble     *y_ret,
+                                  gdouble     *x_root_ret,
+                                  gdouble     *y_root_ret)
+{
+  gdouble x, y, x_root, y_root;
+  gboolean retval = TRUE;
+
+#ifdef HAVE_XINPUT2
+  if (ev->type == GenericEvent &&
+      ev->xcookie.extension == display->xinput2_opcode)
+    {
+      XIEvent *xev;
+
+      g_assert (display->have_xinput2 == TRUE);
+
+      xev = (XIEvent *) ev->xcookie.data;
+
+      switch (xev->evtype)
+        {
+        case XI_Motion:
+        case XI_ButtonPress:
+        case XI_ButtonRelease:
+        case XI_KeyPress:
+        case XI_KeyRelease:
+          {
+            XIDeviceEvent *event = (XIDeviceEvent *) xev;
+
+            x = event->event_x;
+            y = event->event_y;
+            x_root = event->root_x;
+            y_root = event->root_y;
+          }
+
+          break;
+        case XI_FocusIn:
+        case XI_FocusOut:
+        case XI_Enter:
+        case XI_Leave:
+          {
+            XIEnterEvent *event = (XIEnterEvent *) xev;
+
+            x = event->event_x;
+            y = event->event_y;
+            x_root = event->root_x;
+            y_root = event->root_y;
+          }
+
+          break;
+        default:
+          retval = FALSE;
+          break;
+        }
+    }
+  else
+#endif /* HAVE_XINPUT2 */
+    {
+      switch (ev->type)
+        {
+        case KeyPress:
+        case KeyRelease:
+          x = ev->xkey.x;
+          y = ev->xkey.y;
+          x_root = ev->xkey.x_root;
+          y_root = ev->xkey.y_root;
+          break;
+        case ButtonPress:
+        case ButtonRelease:
+          x = ev->xbutton.x;
+          y = ev->xbutton.y;
+          x_root = ev->xbutton.x_root;
+          y_root = ev->xbutton.y_root;
+          break;
+        case EnterNotify:
+        case LeaveNotify:
+          x = ev->xcrossing.x;
+          y = ev->xcrossing.y;
+          x_root = ev->xcrossing.x_root;
+          y_root = ev->xcrossing.y_root;
+          break;
+        case MotionNotify:
+          x = ev->xmotion.x;
+          y = ev->xmotion.y;
+          x_root = ev->xmotion.x_root;
+          y_root = ev->xmotion.y_root;
+          break;
+        default:
+          retval = FALSE;
+          break;
+        }
+    }
+
+  if (retval)
+    {
+      if (x_ret)
+        *x_ret = x;
+
+      if (y_ret)
+        *y_ret = y;
+
+      if (x_root_ret)
+        *x_root_ret = x_root;
+
+      if (y_root_ret)
+        *y_root_ret = y_root;
+    }
+
+  return retval;
+}
+
+gboolean
+meta_input_event_get_state (MetaDisplay *display,
+                            XEvent      *ev,
+                            guint       *state)
+{
+  gboolean retval = TRUE;
+  guint s;
+
+#ifdef HAVE_XINPUT2
+  if (ev->type == GenericEvent &&
+      ev->xcookie.extension == display->xinput2_opcode)
+    {
+      XIEvent *xev;
+
+      g_assert (display->have_xinput2 == TRUE);
+
+      xev = (XIEvent *) ev->xcookie.data;
+
+      switch (xev->evtype)
+        {
+        case XI_Motion:
+        case XI_ButtonPress:
+        case XI_ButtonRelease:
+        case XI_KeyPress:
+        case XI_KeyRelease:
+          s = ((XIDeviceEvent *) xev)->mods.effective;
+          break;
+        case XI_FocusIn:
+        case XI_FocusOut:
+        case XI_Enter:
+        case XI_Leave:
+          s = ((XIDeviceEvent *) xev)->mods.effective;
+          break;
+        default:
+          retval = FALSE;
+          break;
+        }
+    }
+  else
+#endif /* HAVE_XINPUT2 */
+    {
+      switch (ev->type)
+        {
+        case KeyPress:
+        case KeyRelease:
+          s = ev->xkey.state;
+          break;
+        case ButtonPress:
+        case ButtonRelease:
+          s = ev->xbutton.state;
+          break;
+        case EnterNotify:
+        case LeaveNotify:
+          s = ev->xcrossing.state;
+          break;
+        case MotionNotify:
+          s = ev->xmotion.state;
+          break;
+        default:
+          retval = FALSE;
+          break;
+        }
+    }
+
+  if (retval && state)
+    *state = s;
+
+  return retval;
+}
+
+gboolean
+meta_input_event_get_keycode (MetaDisplay *display,
+                              XEvent      *ev,
+                              guint       *keycode)
+{
+#ifdef HAVE_XINPUT2
+  if (ev->type == GenericEvent &&
+      ev->xcookie.extension == display->xinput2_opcode)
+    {
+      XIEvent *xev;
+
+      g_assert (display->have_xinput2 == TRUE);
+
+      xev = (XIEvent *) ev->xcookie.data;
+
+      if (xev->evtype == XI_KeyPress ||
+          xev->evtype == XI_KeyRelease)
+        {
+          if (keycode)
+            {
+              /* The detail field contains keycode for key events */
+              *keycode = ((XIDeviceEvent *) xev)->detail;
+            }
+
+          return TRUE;
+        }
+    }
+  else
+#endif /* HAVE_XINPUT2 */
+    {
+      if (ev->type == KeyPress ||
+          ev->type == KeyRelease)
+        {
+          if (keycode)
+            *keycode = ev->xkey.keycode;
+
+          return TRUE;
+        }
+    }
+
+  return FALSE;
+}
diff --git a/src/core/input-events.h b/src/core/input-events.h
new file mode 100644
index 0000000..ea2c12e
--- /dev/null
+++ b/src/core/input-events.h
@@ -0,0 +1,64 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+
+/**
+ * \file event.h  Utility functions for handling events
+ *
+ * Handling events.
+ * This file contains helper methods to handle events, specially
+ * input events, which can be either core or XInput2.
+ */
+
+/*
+ * Copyright (C) 2011 Carlos Garnacho
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef META_EVENT_H
+#define META_EVENT_H
+
+#include <config.h>
+#include <X11/Xlib.h>
+#include "display-private.h"
+
+
+gboolean meta_input_event_get_type          (MetaDisplay *display,
+                                             XEvent      *ev,
+                                             guint       *ev_type);
+
+Window   meta_input_event_get_window        (MetaDisplay *display,
+                                             XEvent      *ev);
+Window   meta_input_event_get_root_window   (MetaDisplay *display,
+                                             XEvent      *ev);
+
+Time     meta_input_event_get_time          (MetaDisplay *display,
+                                             XEvent      *ev);
+
+gboolean meta_input_event_get_coordinates   (MetaDisplay *display,
+                                             XEvent      *ev,
+                                             gdouble     *x_ret,
+                                             gdouble     *y_ret,
+                                             gdouble     *x_root_ret,
+                                             gdouble     *y_root_ret);
+
+gboolean meta_input_event_get_state         (MetaDisplay *display,
+                                             XEvent      *ev,
+                                             guint       *state);
+gboolean meta_input_event_get_keycode       (MetaDisplay *display,
+                                             XEvent      *ev,
+                                             guint       *keycode);
+
+#endif /* META_EVENT_H */



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