susam / uncap

Map Caps Lock to Escape or any key to any key
MIT License
1.07k stars 43 forks source link

Can't map extended keys (0xB4) #3

Closed serverwentdown closed 5 years ago

serverwentdown commented 6 years ago

I ran uncap like this and it doesn't map the mail (0xB4) key to escape, nor the media select key (0xB5):

uncap -d 0xB4:0x1B 0xB5:0x1B 0x14:0x1B
KEYUP      -   -   -   UP   28  13 (RETURN)
KEYDOWN    -   -   -   -    58  20 (0x14)
KEYDOWN    -   INJ -   -     0  27 (0x1B)
KEYUP      -   -   -   UP   58  20 (0x14)
KEYUP      -   INJ -   UP    0  27 (0x1B)
KEYDOWN    -   -   -   -    58  20 (0x14)
KEYDOWN    -   INJ -   -     0  27 (0x1B)
KEYUP      -   -   -   UP   58  20 (0x14)
KEYUP      -   INJ -   UP    0  27 (0x1B)
KEYDOWN    -   -   -   -    58  20 (0x14)
KEYDOWN    -   INJ -   -     0  27 (0x1B)
KEYUP      -   -   -   UP   58  20 (0x14)
KEYUP      -   INJ -   UP    0  27 (0x1B)
KEYDOWN    -   -   -   -    58  20 (0x14)
KEYDOWN    -   INJ -   -     0  27 (0x1B)
KEYUP      -   -   -   UP   58  20 (0x14)
KEYUP      -   INJ -   UP    0  27 (0x1B)
KEYDOWN    -   -   -   -    58  20 (0x14)
KEYDOWN    -   INJ -   -     0  27 (0x1B)
KEYUP      -   -   -   UP   58  20 (0x14)
KEYUP      -   INJ -   UP    0  27 (0x1B)
KEYDOWN    -   -   -   -    58  20 (0x14)
KEYDOWN    -   INJ -   -     0  27 (0x1B)
KEYUP      -   -   -   UP   58  20 (0x14)
KEYUP      -   INJ -   UP    0  27 (0x1B)
KEYDOWN    -   -   -   -    58  20 (0x14)
KEYDOWN    -   INJ -   -     0  27 (0x1B)
KEYUP      -   -   -   UP   58  20 (0x14)
KEYUP      -   INJ -   UP    0  27 (0x1B)
KEYDOWN    EXT INJ -   -     0 180 (0xB4)
KEYUP      EXT INJ -   UP    0 180 (0xB4)
KEYDOWN    EXT INJ -   -     0 181 (0xB5)
KEYUP      EXT INJ -   UP    0 181 (0xB5)
KEYDOWN    EXT INJ -   -     0 181 (0xB5)
KEYUP      EXT INJ -   UP    0 181 (0xB5)
KEYDOWN    EXT INJ -   -     0 181 (0xB5)
KEYUP      EXT INJ -   UP    0 181 (0xB5)
KEYDOWN    EXT INJ -   -     0 180 (0xB4)
KEYUP      EXT INJ -   UP    0 180 (0xB4)
KEYDOWN    EXT INJ -   -     0 180 (0xB4)
KEYUP      EXT INJ -   UP    0 180 (0xB4)
susam commented 6 years ago

Thank you for the including the debug output from Uncap. The debug output explains why the issue occurs.

When the Start Mail or Select Media key is pressed, the LLKHF_INJECTED flag is set in the low-level keyboard input event. This LLKHF_INJECTED flag is denoted as INJ in the debug output.

The lines of the debug output I am referring to are:

KEYDOWN    EXT INJ -   -     0 180 (0xB4)
KEYUP      EXT INJ -   UP    0 180 (0xB4)
KEYDOWN    EXT INJ -   -     0 181 (0xB5)
KEYUP      EXT INJ -   UP    0 181 (0xB5)

The INJ in the output seems to indicate that the Start Mail or Select Media key-presses lead to injected keyboard events. Uncap ignores injected keyboard input events in order to prevent remap-loops. For example, if Uncap does not ignore injected keyboard input events and A is swapped with B using Uncap, then pressing A would lead Uncap to inject an event for B which would trigger Uncap to inject another event for A and so on leading to a remap-loop. Therefore Uncap ignores keyboard input events with the LLKHF_INJECTED flag set in order to prevent such remap-loops.

In order to resolve the reported issue, Uncap must not ignore events with the LLKHF_INJECTED flag set and yet be able to prevent remap-loops with another mechanism. I do not have plans to work on this issue now but I may work on this at a later time.

In the meantime, if anyone else is willing to work on this issue and send me a pull request, here are a few options to consider, although I am not sure if these would lead to any fruitful result:

References:

susam commented 5 years ago

I have pushed commit 78f52d7b2e03fc51885c8072d53ff5d41fbe3ffc with a fix for this issue just now.

Like I mentioned in my earlier comment, Uncap previously ignored any injected events to avoid remap loops. It tested the LLKHF_INJECTED flag of every keyboard event to recognize whether it is an injected event or not and ignored the ones which had this flag set. This meant that extended keys like the Start Mail and Select Media keys which generated events with this flag set were being ignored. Therefore Uncap refused to map these keys.

Although I do not have a keyboard with Start Mail and Select Media keys, I could reproduce pretty much the same issue with the On-Screen Keyboard that comes with Windows 10 Pro. I observed that Uncap refused to map keys pressed with the On-Screen Keyboard because any keyboard events generated with this tool had their LLKHF_INJECTED flag set.

The solution of course turns out to be to not ignore injected events. But we still need to avoid remap loops, so Uncap now sets a magic value in the dwExtraInfo member of any keyboard events it generates as a result of mapping and it ignores any keyboard events received that have the same magic value. In this way, Uncap now ignores only those keyboard events that it itself injected thereby avoiding remap loops while still honouring remapping of other injected keyboard events. Please see commit 78f52d7b2e03fc51885c8072d53ff5d41fbe3ffc for more details on the fix.

Thank you, Ambrose (@serverwentdown), once again for reporting this issue along with debug output which was very useful in understanding the issue and coming up with a fix for it.

This fix is not released yet. I will close this issue after the fix becomes available in a new release.

susam commented 5 years ago

The fix for this issue is now available in Uncap 0.3.0.

Closing this issue now.