From 0ec6166efe8f74bf8e2c3a447cfd05700c23423d Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Thu, 6 Sep 2012 11:06:35 +0900 Subject: [PATCH] gtk3: Call XIGrabKeycode directly from Vala 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 | 1 + bindings/vala/xi.vapi | 53 +++++++++++++++++++++ ui/gtk3/Makefile.am | 2 +- ui/gtk3/grabkeycode.c | 105 ----------------------------------------- ui/gtk3/keybindingmanager.vala | 83 ++++++++++++++++++++++++++++---- 5 files changed, 130 insertions(+), 114 deletions(-) create mode 100644 bindings/vala/xi.vapi delete mode 100644 ui/gtk3/grabkeycode.c diff --git a/bindings/vala/Makefile.am b/bindings/vala/Makefile.am index faa92a6..abcc543 100644 --- a/bindings/vala/Makefile.am +++ b/bindings/vala/Makefile.am @@ -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 index 0000000..29c4251 --- /dev/null +++ b/bindings/vala/xi.vapi @@ -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); +} diff --git a/ui/gtk3/Makefile.am b/ui/gtk3/Makefile.am index 8d362bc..5473027 100644 --- a/ui/gtk3/Makefile.am +++ b/ui/gtk3/Makefile.am @@ -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 index 6a2d02f..0000000 --- a/ui/gtk3/grabkeycode.c +++ /dev/null @@ -1,105 +0,0 @@ -/* vim:set et sts=4 sw=4: - * - * ibus - The Input Bus - * - * Copyright(c) 2011 Peng Huang - * - * 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 -#include -#include - -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; -} diff --git a/ui/gtk3/keybindingmanager.vala b/ui/gtk3/keybindingmanager.vala index 9b53b09..5ff0c65 100644 --- a/ui/gtk3/keybindingmanager.vala +++ b/ui/gtk3/keybindingmanager.vala @@ -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 */ -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; + } } /* -- 2.7.4