* @author Oliver Sauder <os@esite.ch>
*/
-using Gdk;
-using GLib;
-using Gtk;
-using X;
-
-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
public static const uint MODIFIER_FILTER =
Gdk.ModifierType.MODIFIER_MASK & ~(
- Gdk.ModifierType.MOD2_MASK |
- Gdk.ModifierType.LOCK_MASK |
- Gdk.ModifierType.MOD4_MASK |
- Gdk.ModifierType.MOD5_MASK |
+ Gdk.ModifierType.LOCK_MASK | // Caps Lock
+ // Gdk.ModifierType.MOD1_MASK | // Alt
+ Gdk.ModifierType.MOD2_MASK | // Num Lock
+ // Gdk.ModifierType.MOD3_MASK |
+ // Gdk.ModifierType.MOD4_MASK | // Super, Hyper
+ // Gdk.ModifierType.MOD5_MASK | //
Gdk.ModifierType.BUTTON1_MASK |
Gdk.ModifierType.BUTTON2_MASK |
Gdk.ModifierType.BUTTON3_MASK |
Gdk.ModifierType.BUTTON4_MASK |
- Gdk.ModifierType.BUTTON5_MASK);
+ Gdk.ModifierType.BUTTON5_MASK |
+ Gdk.ModifierType.SUPER_MASK |
+ Gdk.ModifierType.HYPER_MASK |
+ Gdk.ModifierType.META_MASK);
/**
* Helper class to store keybinding
*/
private class Keybinding {
- public Keybinding(string accelerator,
- uint keysym,
+ public Keybinding(uint keysym,
Gdk.ModifierType modifiers,
KeybindingHandlerFunc handler) {
- this.accelerator = accelerator;
this.keysym = keysym;
this.modifiers = modifiers;
this.handler = handler;
}
- public string accelerator { get; set; }
public uint keysym { get; set; }
public Gdk.ModifierType modifiers { get; set; }
public unowned KeybindingHandlerFunc handler { get; set; }
/**
* Bind accelerator to given handler
*
- * @param accelerator accelerator parsable by Gtk.accelerator_parse
+ * @param keysym
+ * @param modifiers
* @param handler handler called when given accelerator is pressed
*/
- public bool bind(string accelerator,
+ public bool bind(uint keysym,
+ Gdk.ModifierType modifiers,
KeybindingHandlerFunc handler) {
- debug("Binding key " + accelerator);
-
- // convert accelerator
- uint keysym;
- Gdk.ModifierType modifiers;
- Gtk.accelerator_parse(accelerator, out keysym, out modifiers);
-
unowned X.Display display = Gdk.x11_get_default_xdisplay();
int keycode = display.keysym_to_keycode(keysym);
grab_keycode (Gdk.Display.get_default(), keysym, modifiers);
// store binding
- Keybinding binding = new Keybinding(accelerator,
- keysym, modifiers,
- handler);
+ Keybinding binding = new Keybinding(keysym, modifiers, handler);
m_bindings.append(binding);
- debug("Successfully binded key " + accelerator);
return true;
}
/**
* Unbind given accelerator.
*
- * @param accelerator accelerator parsable by Gtk.accelerator_parse
+ * @param keysym
+ * @param modifiers
*/
- public void unbind (string accelerator) {
- debug("Unbinding key " + accelerator);
-
+ public void unbind(uint keysym,
+ Gdk.ModifierType modifiers) {
// unbind all keys with given accelerator
GLib.List<Keybinding> remove_bindings = new GLib.List<Keybinding>();
foreach(Keybinding binding in m_bindings) {
- if(str_equal(accelerator, binding.accelerator)) {
+ if (binding.keysym == keysym && binding.modifiers == modifiers) {
ungrab_keycode (Gdk.Display.get_default(),
binding.keysym,
binding.modifiers);
return m_instance;
}
- public static uint get_primary_modifier (uint binding_mask) {
- const uint[] masks = {
+ public static Gdk.ModifierType get_primary_modifier (uint binding_mask) {
+ const Gdk.ModifierType[] masks = {
Gdk.ModifierType.MOD5_MASK,
Gdk.ModifierType.MOD4_MASK,
Gdk.ModifierType.MOD3_MASK,
Gdk.ModifierType.SHIFT_MASK,
Gdk.ModifierType.LOCK_MASK
};
- foreach (uint mask in masks) {
+ for (int i = 0; i < masks.length; i++) {
+ Gdk.ModifierType mask = masks[i];
if ((binding_mask & mask) == mask)
return mask;
}
private void event_handler(Gdk.Event event) {
do {
- if (event.any.window != Gdk.get_default_root_window())
+ if (event.any.window != Gdk.get_default_root_window()) {
break;
+ }
if (event.type == Gdk.EventType.KEY_PRESS) {
uint modifiers = event.key.state & MODIFIER_FILTER;
} 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 = {};
+ for (int i = 0; i < ignored_modifiers.length; i++) {
+ int modifier = ignored_modifiers[i];
+ 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;
+ }
}
/*