summaryrefslogtreecommitdiff
path: root/src/utilities/bindingManager.vala
diff options
context:
space:
mode:
Diffstat (limited to 'src/utilities/bindingManager.vala')
-rw-r--r--src/utilities/bindingManager.vala191
1 files changed, 150 insertions, 41 deletions
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;
+ });
+ }
}
}