alols / xcape

Linux utility to configure modifier keys to act as other keys when pressed and released on their own.
GNU General Public License v3.0
2.1k stars 117 forks source link

Add state conditions #104

Open c-max opened 6 years ago

c-max commented 6 years ago

Hello Albin,

searching for a way to make Space act as Shift, if pressed with another key, I found xcape. Very nice! Big thanx from me and my relaxed small fingers for providing the code.

Using a custom multi level keyboard layout (xkb) with key {[Hyper_R,Hyper_R,space,0,space]}; // Hyper_R >> Shift-Mod I had to prevent xcape from generating space at levels 3..5 (set by combinations of Mod1&2). Therefore I added condidions to xcape (see below) and simply call:

xcape -e 'Hyper_R=#255?,0x30

It works very well in my normal use, but nearly simultaneous keystrokes might fool the modifier state detection (see below).

Problem: XRecordInterceptData does not seem to reference any modifier state data. Nearly simultaneous keystrokes might cause XRecord to record a second key before the XkbGetState() call is done.

If you like to adopt this mod feel free to do so. Suggestions for improvements are very welcome.

Regards,

max


Description:

ModKey=GenKey[Condidions][|OtherGenKey[Condidions]...]

The Condidions syntax is ´?[[Filter],[Mask]]...´ (see examples).

Conditions can be used to control the key generation based on the keyboard/pointer state before ModKey was pressed. This is especially usefull if the ModKey has variable keysyms or actions using a multi level/group keyboard layouts with xkb. (The Key should be referenced by its key code in this case.)

State bits:

0 .. 7: Shift, Lock, Control, Mod1..Mod5 8 .. 10: Pointer buttons 11 .. 12: n/a (always 0 in xcape) 13 .. 15: index of layout group (0..3)

The debug mode (-d) can be used to show current states.

A GenKey with one or more condidions will be generated if at least one condidion matches the state. That is all masked bits of Filter are equal to those of the state.

Filter and Mask may be specified decimal (no prefix), octal (0) or hexadecimal (0x) within the valid range 0x0..0x7fff. Both are optional. Filter defaults to 0x0, Mask to Filter. So Mask (Filter) can be omitted if a condition checks set (unset) state bits only.

Examples:

Press both Shift keys to toogle Caps Lock:

xcape -e 'Shift_L=Caps_Lock?1;Shift_R=Caps_Lock?1'

Press both Shift keys to set Caps Lock - one to unset:

xcape -e 'Shift_L=Caps_Lock?1?2;Shift_R=Caps_Lock?1?2'

Press both Shift keys to set Caps Lock - one to unset if Control is unset:

xcape -e 'Shift_L=Caps_Lock?1?2,6;Shift_R=Caps_Lock?1?2,6'

Known problem:

Nearly simultaneous keystrokes might fool the modifier state detection since xcape gets key events and the current modifier state from two different sources.

In the examples above simultaneous Shift + Control might lead to unintended Caps Lock.