Fixed bug where the keyboard layout was changed when generating a key event #113
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
When an event is generated by xcape, the group/layout of the keyboard was always set to 0 (the default group, state 0x0??? in xev -event keyboard).
Example showing the bug
$ ./xcape -d -e "Control_L=#65"
Starting with the keyboard layout 0x2000 (group 1) I press the "j" key, then tap the Control_L key to trigger xcape and then press the "j" key again.
before, group = 1
Intercepted key event 2, key code 44
after, group = 1
jbefore, group = 1 // pressing "j"
Intercepted key event 3, key code 44
after, group = 1
before, group = 1
Intercepted key event 2, key code 66
Key pressed!
after, group = 1
before, group = 1 // before the generated event the group is still correct
Intercepted key event 3, key code 66
Key released!
Generating space!
after, group = 0 // wrong group, corresponds to keyboard state 0x0000 (DVORAK)
before, group = 0
Ignoring generated event.
before, group = 0
Ignoring generated event.
before, group = 0 // generated space at the beginning of this line
Intercepted key event 2, key code 44
after, group = 0
hbefore, group = 0 // pressing "j" will now give an "h" (DVORAK)
Intercepted key event 3, key code 44
after, group = 0
"before" corresponds to the group at the beginning of intercept() and "after" corresponds to the group at the end of intercept() just before the "exit" mark.
Example showing a change of the keyboard layout
$ ./xcape -d -e "Control_L=#65"
My keyboard configuration file: /etc/X11/xorg.conf.d/00-keyboard.conf
Press Alt_L and Shift_L to change from keyboard layout us (QWERTY) to de (QWERTZ).
before, group = 1
Intercepted key event 2, key code 47
after, group = 1
;before, group = 1 // pressing semicolon key
Intercepted key event 3, key code 47
after, group = 1
before, group = 1
Intercepted key event 2, key code 64 // alt key
after, group = 1
before, group = 2 // group already changed to 2 (0x4000, de QWERTZ)
Intercepted key event 2, key code 50 // shift key
after, group = 2
before, group = 2
Intercepted key event 3, key code 50
after, group = 2
before, group = 2
Intercepted key event 3, key code 64
after, group = 2
before, group = 2
Intercepted key event 2, key code 47
after, group = 2
öbefore, group = 2 // press semicolon key, now an "ö" (de QWERTZ)
Intercepted key event 3, key code 47
after, group = 2
Solution
In the first case the group change appears at the end of intercept(), whereas in the second case the group change occurs before intercept(). Saving the group from the previous key event therefore allows to separate the two cases and handle them correctly. If user_data->previous_group matches current_group at the beginning of intercept(), the group will be set to user_data->intended_group. If user_data->previous_group does not match current_group, both user_data->intended_group and user_data->previous_group will be set to current_group to confirm the layout change.