diff --git a/src/run/display/hotkey.cr b/src/run/display/hotkey.cr index f658c4c..47a5a67 100644 --- a/src/run/display/hotkey.cr +++ b/src/run/display/hotkey.cr @@ -33,7 +33,7 @@ module Run end def init(escape_char) - key_combos = Util::AhkString.parse_key_combinations(@key_str.gsub("*","").gsub("~",""), escape_char, implicit_braces: true) + key_combos = Util::AhkString.parse_key_combinations(@key_str.downcase.gsub("*","").gsub("~",""), escape_char, implicit_braces: true) raise Run::RuntimeException.new "Multiple keys aren't allowed for Hotkey definitions" if key_combos.size != 1 # TODO: probably impossible? @key_name = key_combos[0].key_name @keysym = key_combos[0].keysym diff --git a/src/run/display/hotkeys.cr b/src/run/display/hotkeys.cr index d9fbec0..7335c35 100644 --- a/src/run/display/hotkeys.cr +++ b/src/run/display/hotkeys.cr @@ -75,9 +75,10 @@ module Run end if hotkey if ! hotkey.up && ! hotkey.no_grab - # Fixing https://github.com/jordansissel/xdotool/issues/210: (also see Send/SendRaw) + # Fixing https://github.com/jordansissel/xdotool/issues/210: # Doing a `hotkey.keycode` UP event works great but breaks key remaps. - # Instead, the following magic seems to work reliably. + # Instead, the following magic seems to work reliably, as long as the hotkey key + # isn't sent itself (see Send for that other fix). # Note that both grab and ungrab may fail / not work as expected but that's fine. # This would better be placed at the *first* `Send`/`SendRaw` command on a per-hotkey # basis, but since the performance penalty is negligible and it has no negative @@ -113,6 +114,7 @@ module Run end end end + # todo doesnt belong here def block_input @runner.display.adapter.grab_keyboard end diff --git a/src/run/display/x11.cr b/src/run/display/x11.cr index a72686a..2445d1f 100644 --- a/src/run/display/x11.cr +++ b/src/run/display/x11.cr @@ -7,6 +7,7 @@ at_exit { GC.collect } module X11::C # Infer a long list of key names from lib/x11/src/x11/c/keysymdef.cr, stripped from XK_ and underscores. # Seems to be necessary because XStringToKeysym is always case sensitive (?) + # In our X11 key handling, we only deal with lowercase chars. def self.ahk_key_name_to_keysym_generic {{ @type.constants # TODO: possible to declare this outside of the module? @@ -317,7 +318,15 @@ module Run lookup = key_event.lookup_string char = lookup[:string][0]? keysym = lookup[:keysym] - @key_handler.not_nil!.call(key_event, keysym, char) + # We may have e.g. grabbed *a (so including Shift + lowercase a) but the reported + # event here will return Shift + uppercase A. We'll deal with lowercase only. + if char && char.downcase != char + char = char.downcase + keysym = Run::X11.ahk_key_name_to_keysym(char.to_s) + # TODO: like ahk-string.cr + raise Run::RuntimeException.new "Unexpected keysym #{keysym} is uppercase but can't be mapped to lowercase" if ! keysym || ! keysym.is_a?(Int32) + end + @key_handler.not_nil!.call(key_event, keysym.to_u64, char) end # It's easier to just grab on the root window once, but by repeatedly reattaching to the respectively currently diff --git a/src/util/ahk-string.cr b/src/util/ahk-string.cr index 6b68624..8006e3a 100644 --- a/src/util/ahk-string.cr +++ b/src/util/ahk-string.cr @@ -124,12 +124,8 @@ class Util::AhkString end escape = false if key_name - if key_name.size == 1 && key_name.upcase != key_name.downcase - if modifiers & ::X11::ShiftMask == ::X11::ShiftMask - key_name = key_name.upcase - elsif key_name.upcase == key_name - modifiers |= ::X11::ShiftMask - end + if key_name.size == 1 && key_name.upcase != key_name.downcase && key_name.upcase == key_name + modifiers |= ::X11::ShiftMask end keysym = Run::X11.ahk_key_name_to_keysym(key_name) # TODO: why the typecheck / why not in x11.cr? diff --git a/tests.ahk b/tests.ahk index c6fc47c..fb3eab6 100755 --- a/tests.ahk +++ b/tests.ahk @@ -3,7 +3,7 @@ ; Right now, only commands that can be easily tested in 1-2 lines are tested. ;;;;;;;;;;;;;;;;;;;;;; -N_TESTS = 53 +N_TESTS = 55 GoSub, run_tests if tests_run != %N_TESTS% @@ -656,6 +656,10 @@ key = +S xdotool_run = key shift+s gosub test_hotkey_success +key = *s +xdotool_run = key shift+s +gosub test_hotkey_success + ; esc and xbutton2 share the same keycode: key = esc xdotool_run = key Escape