gtk3: Call XIGrabKeycode directly from Vala
authorDaiki Ueno <ueno@unixuser.org>
Thu, 6 Sep 2012 02:06:35 +0000 (11:06 +0900)
committerDaiki Ueno <ueno@unixuser.org>
Thu, 6 Sep 2012 02:06:35 +0000 (11:06 +0900)
Port the logic of grabkeycode.c into Vala.  This will make it easier to
implement XI2 GenericEvent handling in KeybindingManager.

BUG=none

Review URL: https://codereview.appspot.com/6501080

bindings/vala/Makefile.am
bindings/vala/xi.vapi [new file with mode: 0644]
ui/gtk3/Makefile.am
ui/gtk3/grabkeycode.c [deleted file]
ui/gtk3/keybindingmanager.vala

index faa92a6..abcc543 100644 (file)
@@ -45,6 +45,7 @@ EXTRA_DIST = \
        IBus-1.0.metadata \
        IBus-1.0-custom.vala \
        config.vapi \
+       xi.vapi \
        $(NULL)
 
 MAINTAINERCLEANFILES = ibus-@IBUS_API_VERSION@.vapi
diff --git a/bindings/vala/xi.vapi b/bindings/vala/xi.vapi
new file mode 100644 (file)
index 0000000..29c4251
--- /dev/null
@@ -0,0 +1,53 @@
+[CCode (cprefix = "", lower_case_cprefix = "", cheader_filename = "X11/extensions/XInput2.h")]
+namespace XI {
+    public enum EventType {
+        [CCode (cname = "XI_KeyPress")]
+        KeyPress,
+        [CCode (cname = "XI_KeyRelease")]
+        KeyRelease,
+    }
+
+    [CCode (cname = "XIAllMasterDevices")]
+    public const int AllMasterDevices;
+
+    [CCode (cname = "XI_LASTEVENT")]
+    public const int LASTEVENT;
+
+    [Compact]
+    [CCode (cname = "XIEventMask", destroy_function = "")]
+    public struct EventMask {
+        public int deviceid;
+        [CCode (array_length_cname = "mask_len")]
+        public uchar[] mask;
+    }
+
+    [CCode (cname = "XISetMask")]
+    public void set_mask(void *mask, EventType type);
+
+    [Compact]
+    [CCode (cname = "XIGrabModifiers", destroy_function = "")]
+    public struct GrabModifiers {
+        public int modifiers;
+        public int status;
+    }
+
+    [CCode (cname = "XIGrabKeycode")]
+    public int grab_keycode (X.Display display,
+                             int deviceid,
+                             int keycode,
+                             X.Window grab_window,
+                             int grab_mode,
+                             int paired_device_mode,
+                             bool owner_events,
+                             XI.EventMask mask,
+                             [CCode (array_length_pos = 8.9)]
+                             XI.GrabModifiers[] modifiers);
+
+    [CCode (cname = "XIUngrabKeycode")]
+    public int ungrab_keycode (X.Display display,
+                               int deviceid,
+                               int keycode,
+                               X.Window grab_window,
+                               [CCode (array_length_pos = 4.9)]
+                               XI.GrabModifiers[] modifiers);
+}
index 8d362bc..5473027 100644 (file)
@@ -82,6 +82,7 @@ AM_VALAFLAGS = \
        --pkg=gdk-x11-3.0 \
        --pkg=ibus-1.0 \
        --pkg=config \
+       --pkg=xi \
        $(NULL)
 
 libexec_PROGRAMS = ibus-ui-gtk3
@@ -98,7 +99,6 @@ ibus_ui_gtk3_SOURCES = \
        property.vala \
        separator.vala \
        switcher.vala \
-       grabkeycode.c \
        $(NULL)
 
 ibus_ui_gtk3_LDADD = \
diff --git a/ui/gtk3/grabkeycode.c b/ui/gtk3/grabkeycode.c
deleted file mode 100644 (file)
index 6a2d02f..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-/* vim:set et sts=4 sw=4:
- *
- * ibus - The Input Bus
- *
- * Copyright(c) 2011 Peng Huang <shawn.p.huang@gmail.com>
- *
- * 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 program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA  02111-1307  USA
- */
-
-#include <glib.h>
-#include <gdk/gdkx.h>
-#include <X11/extensions/XInput2.h>
-
-gboolean grab_keycode (GdkDisplay *display,
-                       guint keyval,
-                       guint modifiers) {
-    Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
-    int keycode = XKeysymToKeycode (xdisplay, keyval);
-    if (keycode == 0) {
-        g_warning ("Can not convert keyval=%u to keycode!", keyval);
-        return FALSE;
-    }
-
-    XIEventMask mask;
-    mask.deviceid = XIAllMasterDevices;
-    mask.mask_len = XIMaskLen(XI_RawMotion);
-    mask.mask = g_new0 (unsigned char, mask.mask_len);
-    XISetMask (mask.mask, XI_KeyPress);
-    XISetMask (mask.mask, XI_KeyRelease);
-
-    XIGrabModifiers ximodifiers[] = {
-        { modifiers, 0 },
-        { LockMask | modifiers, 0 },
-        { Mod2Mask | modifiers, 0 },
-        { Mod5Mask | modifiers, 0 },
-        { LockMask | Mod2Mask | modifiers, 0 },
-        { Mod2Mask | Mod5Mask | modifiers, 0 },
-        { LockMask | Mod5Mask | modifiers, 0 },
-        { LockMask | Mod2Mask | Mod5Mask | modifiers, 0 },
-    };
-
-    int retval = XIGrabKeycode (xdisplay,
-                                XIAllMasterDevices,
-                                keycode,
-                                DefaultRootWindow (xdisplay),
-                                GrabModeAsync,
-                                GrabModeAsync,
-                                True,
-                                &mask,
-                                G_N_ELEMENTS (ximodifiers),
-                                ximodifiers);
-
-    g_free (mask.mask);
-
-    if (retval == -1)
-        return FALSE;
-    return TRUE;
-}
-
-gboolean ungrab_keycode (GdkDisplay *display,
-                         guint keyval,
-                         guint modifiers) {
-    Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
-    int keycode = XKeysymToKeycode (xdisplay, keyval);
-    if (keycode == 0) {
-        g_warning ("Can not convert keyval=%u to keycode!", keyval);
-        return FALSE;
-    }
-
-    XIGrabModifiers ximodifiers[] = {
-        {modifiers, 0},
-        {Mod2Mask | modifiers, 0},
-        {LockMask | modifiers, 0},
-        {Mod5Mask | modifiers, 0},
-        {Mod2Mask | LockMask | modifiers, 0},
-        {Mod2Mask | Mod5Mask | modifiers, 0},
-        {LockMask | Mod5Mask | modifiers, 0},
-        {Mod2Mask | LockMask | Mod5Mask | modifiers, 0},
-    };
-
-    int retval = XIUngrabKeycode (xdisplay,
-                                  XIAllMasterDevices,
-                                  keycode,
-                                  DefaultRootWindow (xdisplay),
-                                  G_N_ELEMENTS (ximodifiers),
-                                  ximodifiers);
-
-    if (retval == -1)
-        return FALSE;
-
-    return TRUE;
-}
index 9b53b09..5ff0c65 100644 (file)
@@ -10,14 +10,6 @@ valac --pkg gtk+-2.0 --pkg x11 --pkg gdk-x11-2.0 --pkg gee-1.0 keybinding-manage
  * @author Oliver Sauder <os@esite.ch>
  */
 
-extern bool grab_keycode (Gdk.Display display,
-                          uint keyval,
-                          uint modifiers);
-
-extern bool ungrab_keycode (Gdk.Display display,
-                            uint keyval,
-                            uint modifiers);
-
 public class KeybindingManager : GLib.Object {
     /**
      * list of binded keybindings
@@ -213,6 +205,81 @@ public class KeybindingManager : GLib.Object {
         } while (false);
         Gtk.main_do_event(event);
     }
+
+    // Get union of given modifiers and all the combination of the
+    // modifiers in ignored_modifiers.
+    XI.GrabModifiers[] get_grab_modifiers(uint modifiers) {
+        const int[] ignored_modifiers = {
+            X.KeyMask.LockMask,
+            X.KeyMask.Mod2Mask,
+            X.KeyMask.Mod5Mask
+        };
+        int[] masks = {};
+        foreach (var modifier in ignored_modifiers) {
+            masks += modifier;
+
+            int length = masks.length;
+            for (int j = 0; j < length - 1; j++) {
+                masks += masks[j] | modifier;
+            }
+        }
+        masks += 0;
+
+        XI.GrabModifiers[] ximodifiers = {};
+        foreach (var mask in masks) {
+            ximodifiers += XI.GrabModifiers() {
+                modifiers = mask | modifiers,
+                status = 0
+            };
+        }
+
+        return ximodifiers;
+    }
+
+    bool grab_keycode(Gdk.Display display, uint keyval, uint modifiers) {
+        unowned X.Display xdisplay = Gdk.X11Display.get_xdisplay(display);
+        int keycode = xdisplay.keysym_to_keycode(keyval);
+        if (keycode == 0) {
+            warning("Can not convert keyval=%u to keycode!", keyval);
+            return false;
+        }
+
+        XI.EventMask evmask = XI.EventMask() {
+            deviceid = XI.AllMasterDevices,
+            mask = new uchar[(XI.LASTEVENT + 7) / 8]
+        };
+        XI.set_mask(evmask.mask, XI.EventType.KeyPress);
+        XI.set_mask(evmask.mask, XI.EventType.KeyRelease);
+
+        int retval = XI.grab_keycode (xdisplay,
+                                      XI.AllMasterDevices,
+                                      keycode,
+                                      xdisplay.default_root_window(),
+                                      X.GrabMode.Async,
+                                      X.GrabMode.Async,
+                                      true,
+                                      evmask,
+                                      get_grab_modifiers(modifiers));
+            
+        return retval == 0;
+    }
+
+    bool ungrab_keycode(Gdk.Display display, uint keyval, uint modifiers) {
+        unowned X.Display xdisplay = Gdk.X11Display.get_xdisplay(display);
+        int keycode = xdisplay.keysym_to_keycode(keyval);
+        if (keycode == 0) {
+            warning("Can not convert keyval=%u to keycode!", keyval);
+            return false;
+        }
+
+        int retval = XI.ungrab_keycode (xdisplay,
+                                        XI.AllMasterDevices,
+                                        keycode,
+                                        xdisplay.default_root_window(),
+                                        get_grab_modifiers(modifiers));
+
+        return retval == 0;
+    }
 }
 
 /*