From d6b2677825cbb423e2099563c16321c3e23d7899 Mon Sep 17 00:00:00 2001 From: Alessandro Ghedini Date: Sun, 20 Nov 2011 15:50:38 +0100 Subject: Imported Upstream version 0.3.1 --- src/utilities/bindingManager.vala | 191 ++++++++++++++++++++++++++++++-------- 1 file changed, 150 insertions(+), 41 deletions(-) (limited to 'src/utilities/bindingManager.vala') diff --git a/src/utilities/bindingManager.vala b/src/utilities/bindingManager.vala index 8795124..437f4c1 100644 --- a/src/utilities/bindingManager.vala +++ b/src/utilities/bindingManager.vala @@ -53,6 +53,10 @@ public class BindingManager : GLib.Object { Gdk.ModifierType.LOCK_MASK|Gdk.ModifierType.MOD5_MASK, Gdk.ModifierType.MOD2_MASK|Gdk.ModifierType.LOCK_MASK|Gdk.ModifierType.MOD5_MASK }; + + private uint32 delayed_count = 0; + private X.Event? delayed_event = null; + private Keybinding? delayed_binding = null; ///////////////////////////////////////////////////////////////////// /// Helper class to store keybinding @@ -60,16 +64,12 @@ public class BindingManager : GLib.Object { private class Keybinding { - public Keybinding(string accelerator, int keycode, Gdk.ModifierType modifiers, string id) { - this.accelerator = accelerator; - this.keycode = keycode; - this.modifiers = modifiers; + public Keybinding(Trigger trigger, string id) { + this.trigger = trigger; this.id = id; } - public string accelerator { get; set; } - public int keycode { get; set; } - public Gdk.ModifierType modifiers { get; set; } + public Trigger trigger { get; set; } public string id { get; set; } } @@ -89,32 +89,30 @@ public class BindingManager : GLib.Object { /// Binds the ID to the given accelerator. ///////////////////////////////////////////////////////////////////// - public void bind(string accelerator, string id) { - uint keysym; - Gdk.ModifierType modifiers; - Gtk.accelerator_parse(accelerator, out keysym, out modifiers); + public void bind(Trigger trigger, string id) { + if(trigger.key_code != 0) { + Gdk.Window rootwin = Gdk.get_default_root_window(); + X.Display display = Gdk.x11_drawable_get_xdisplay(rootwin); + X.ID xid = Gdk.x11_drawable_get_xid(rootwin); - if (keysym == 0) { - warning("Invalid keystroke: " + accelerator); - return; - } - - Gdk.Window rootwin = Gdk.get_default_root_window(); - X.Display display = Gdk.x11_drawable_get_xdisplay(rootwin); - X.ID xid = Gdk.x11_drawable_get_xid(rootwin); - int keycode = display.keysym_to_keycode(keysym); - - if(keycode != 0) { Gdk.error_trap_push(); foreach(uint lock_modifier in lock_modifiers) { - display.grab_key(keycode, modifiers|lock_modifier, xid, false, X.GrabMode.Async, X.GrabMode.Async); + if (trigger.with_mouse) { + display.grab_button(trigger.key_code, trigger.modifiers|lock_modifier, xid, false, + X.EventMask.ButtonPressMask | X.EventMask.ButtonReleaseMask, + X.GrabMode.Async, X.GrabMode.Async, xid, 0); + } else { + display.grab_key(trigger.key_code, trigger.modifiers|lock_modifier, + xid, false, X.GrabMode.Async, X.GrabMode.Async); + } } Gdk.flush(); - Keybinding binding = new Keybinding(accelerator, keycode, modifiers, id); + Keybinding binding = new Keybinding(trigger, id); bindings.add(binding); + display.flush(); } } @@ -130,13 +128,18 @@ public class BindingManager : GLib.Object { foreach(var binding in bindings) { if(id == binding.id) { foreach(uint lock_modifier in lock_modifiers) { - display.ungrab_key(binding.keycode, binding.modifiers, xid); + if (binding.trigger.with_mouse) { + display.ungrab_button(binding.trigger.key_code, binding.trigger.modifiers|lock_modifier, xid); + } else { + display.ungrab_key(binding.trigger.key_code, binding.trigger.modifiers|lock_modifier, xid); + } } remove_bindings.add(binding); } } bindings.remove_all(remove_bindings); + display.flush(); } ///////////////////////////////////////////////////////////////////// @@ -144,15 +147,13 @@ public class BindingManager : GLib.Object { ///////////////////////////////////////////////////////////////////// public string get_accelerator_label_of(string id) { - string accelerator = this.get_accelerator_of(id); - - if (accelerator == "") - return _("Not bound"); + foreach (var binding in bindings) { + if (binding.id == id) { + return binding.trigger.label_with_specials; + } + } - uint key = 0; - Gdk.ModifierType mods; - Gtk.accelerator_parse(accelerator, out key, out mods); - return Gtk.accelerator_get_label(key, mods); + return _("Not bound"); } ///////////////////////////////////////////////////////////////////// @@ -162,7 +163,38 @@ public class BindingManager : GLib.Object { public string get_accelerator_of(string id) { foreach (var binding in bindings) { if (binding.id == id) { - return binding.accelerator; + return binding.trigger.name; + } + } + + return ""; + } + + ///////////////////////////////////////////////////////////////////// + /// Returns whether the pie with the given ID is in turbo mode. + ///////////////////////////////////////////////////////////////////// + + public bool get_is_turbo(string id) { + foreach (var binding in bindings) { + if (binding.id == id) { + return binding.trigger.turbo; + } + } + + return false; + } + + ///////////////////////////////////////////////////////////////////// + /// Returns the name ID of the Pie bound to the given Trigger. + /// Returns "" if there is nothing bound to this trigger. + ///////////////////////////////////////////////////////////////////// + + public string get_assigned_id(Trigger trigger) { + foreach (var binding in bindings) { + var first = binding.trigger.name.replace("[turbo]", "").replace("[delayed]", ""); + var second = trigger.name.replace("[turbo]", "").replace("[delayed]", ""); + if (first == second) { + return binding.id; } } @@ -170,12 +202,10 @@ public class BindingManager : GLib.Object { } ///////////////////////////////////////////////////////////////////// - /// Event filter method needed to fetch X.Events + /// Event filter method needed to fetch X.Events. ///////////////////////////////////////////////////////////////////// - private Gdk.FilterReturn event_filter(Gdk.XEvent gdk_xevent, Gdk.Event gdk_event) { - Gdk.FilterReturn filter_return = Gdk.FilterReturn.CONTINUE; - + private Gdk.FilterReturn event_filter(Gdk.XEvent gdk_xevent, Gdk.Event gdk_event) { void* pointer = &gdk_xevent; X.Event* xevent = (X.Event*) pointer; @@ -183,13 +213,92 @@ public class BindingManager : GLib.Object { foreach(var binding in bindings) { // remove NumLock, CapsLock and ScrollLock from key state uint event_mods = xevent.xkey.state & ~ (lock_modifiers[7]); - if(xevent->xkey.keycode == binding.keycode && event_mods == binding.modifiers) { - on_press(binding.id); + if(xevent->xkey.keycode == binding.trigger.key_code && event_mods == binding.trigger.modifiers) { + if (binding.trigger.delayed) { + this.activate_delayed(binding, *xevent); + } else { + on_press(binding.id); + } } } } + else if(xevent->type == X.EventType.ButtonPress) { + foreach(var binding in bindings) { + // remove NumLock, CapsLock and ScrollLock from key state + uint event_mods = xevent.xbutton.state & ~ (lock_modifiers[7]); + if(xevent->xbutton.button == binding.trigger.key_code && event_mods == binding.trigger.modifiers) { + if (binding.trigger.delayed) { + this.activate_delayed(binding, *xevent); + } else { + on_press(binding.id); + } + } + } + } + else if(xevent->type == X.EventType.ButtonRelease || xevent->type == X.EventType.KeyRelease) { + this.activate_delayed(null, *xevent); + } - return filter_return; + return Gdk.FilterReturn.CONTINUE; + } + + ///////////////////////////////////////////////////////////////////// + /// This method is always called when a trigger is activated which is + /// delayed. Therefore on_press() is only emitted, when this method + /// is not called again within 300 milliseconds. Else a fake event is + /// sent in order to simulate the actual key which has been pressed. + ///////////////////////////////////////////////////////////////////// + + private void activate_delayed(Keybinding? binding , X.Event event) { + // increase event count, so any waiting event will realize that + // something happened in the meantime + var current_count = ++this.delayed_count; + + if (binding == null && this.delayed_event != null) { + // if the trigger is released and an event is currently waiting + // simulate that the trigger has been pressed without any inter- + // ference of Gnome-Pie + Gdk.Window rootwin = Gdk.get_default_root_window(); + X.Display display = Gdk.x11_drawable_get_xdisplay(rootwin); + + // unbind the trigger, else we'll capture that event again ;) + unbind(delayed_binding.id); + + if (this.delayed_binding.trigger.with_mouse) { + // simulate mouse click + X.Test.fake_button_event(display, this.delayed_event.xbutton.button, true, 0); + display.flush(); + + X.Test.fake_button_event(display, this.delayed_event.xbutton.button, false, 0); + display.flush(); + + } else { + // simulate key press + X.Test.fake_key_event(display, this.delayed_event.xkey.keycode, true, 0); + display.flush(); + + X.Test.fake_key_event(display, this.delayed_event.xkey.keycode, false, 0); + display.flush(); + } + + // bind it again + bind(delayed_binding.trigger, delayed_binding.id); + } else if (binding != null) { + // if the trigger has been pressed, store it and wait for any interuption + // within the next 300 milliseconds + this.delayed_event = event; + this.delayed_binding = binding; + + Timeout.add(300, () => { + // if nothing has been pressed in the meantime + if (current_count == this.delayed_count) { + this.delayed_binding = null; + this.delayed_event = null; + on_press(binding.id); + } + return false; + }); + } } } -- cgit v1.2.3