pwr-Solaar / Solaar

Linux device manager for Logitech devices
https://pwr-solaar.github.io/Solaar
GNU General Public License v2.0
5.54k stars 409 forks source link

KeyPress: [less] produces a "z" rather than a "<" #1596

Closed Hubro closed 2 years ago

Hubro commented 2 years ago

Information

Describe the bug

I am trying to type out a < character using a rule. The rule looks like this:

---
- Key: [G5, pressed]
- KeyPress: [less]

Instead of typing a <, this types out a z, which is the key right next to <.

To Reproduce Steps to reproduce the behavior:

Screenshots

-

Additional context

Nordic keyboard, if that matters.

pfps commented 2 years ago

Solaar simulates character input by simulating the press and release of keyboard keys which are roughly identified by their location. Solaar tries to determine which keyboard key corresponds to which character but this does not always work, particularly under Wayland. Conditions under which the determination can (but doesn't always) go wrong include using non-QWERTY keyboards or switching between keyboard groups.

As you are using a Nordic keyboard, this is likely the problem. Solaar determines that on your keyboard the key that produces < is near the lower-left but the mechanism it uses to simulate keyboard input uses a US QWERTY mapping.

If you are willing to do some testing, it should be possible to make Solaar work better here. The first thing to do is to run Solaar as solaar -ddd, make the rule run, and post the output.

Hubro commented 2 years ago

@pfps The output from running solaar -ddd and pressing the G5 key is:

10:25:06,099    DEBUG [ReceiverListener:hidraw17] logitech_receiver.base: (19) => r[11 01 1100 10000000000000000000000000000000]
10:25:06,099    DEBUG [ReceiverListener:hidraw17] logitech_receiver.notifications: <Device(1,407C,G915 WIRELESS RGB MECHANICAL GAMING KEYBOARD,460DF756)>: notification for feature GKEY, report 1, data 10000000000000000000000000000000
10:25:06,099     INFO [MainThread] logitech_receiver.diversion: KeyPress action: ['less'], modifiers 16 ['0x3c']
10:25:06,100     INFO [MainThread] logitech_receiver.diversion: XKB display set up
10:25:06,100    DEBUG [MainThread] logitech_receiver.diversion: uinput simulated input 1 44 1
10:25:06,100    DEBUG [MainThread] logitech_receiver.diversion: uinput simulated input 1 44 0
10:25:06,227    DEBUG [ReceiverListener:hidraw17] logitech_receiver.base: (19) => r[11 01 1100 00000000000000000000000000000000]
10:25:06,227    DEBUG [ReceiverListener:hidraw17] logitech_receiver.notifications: <Device(1,407C,G915 WIRELESS RGB MECHANICAL GAMING KEYBOARD,460DF756)>: notification for feature GKEY, report 1, data 00000000000000000000000000000000

This is what xev produces when I press the < key:

KeyPress event, serial 34, synthetic NO, window 0x6200001,
    root 0x3cc, subw 0x0, time 812692392, (96,85), root:(2567,702),
    state 0x10, keycode 94 (keysym 0x3c, less), same_screen YES,
    XLookupString gives 1 bytes: (3c) "<"
    XmbLookupString gives 1 bytes: (3c) "<"
    XFilterEvent returns: False

I am indeed running Wayland (Sway). I assumed this didn't matter, since I thought the key press was being simulated by the driver anyway.

pfps commented 2 years ago

Input processing is complex and is done in several places. What can be simulated is not inputting characters but instead pushing and releasing keyboard keys (as keycodes). There are two ways to do this - XTest in X11 and uinput. Solaar uses both, depending on what is available. On Wayland Solaar only uses uinput. These keycode presses and releases are then sent into the windowing system and programs can see them directly, see a slight interpretation of them, or just see a stream of characters. Also, the keys are not things like the A key, but instead are something like "the key that is the left-most character key on the middle row of the keyboard keys". X11 and Wayland both use the X Keyboard Extension for this purpose but don't work exactly the same.

What would be nice would be if there was a way to set up a separate keyboard whose interpretation doesn't change but this doesn't seem to be possible so Solaar has to try to figure out what keycode corresponds to what symbol in a way that works in both X11 and Wayland.

What Solaar appears to see is several keycodes that can be used for < and picks one that doesn't work. To make this work better, I'll create an instrumented version of Solaar that shows the information that Solaar uses in your setup.

pfps commented 2 years ago

PR #1599 prints information about the keycode mapping. Please download this PR and run bin/solaar -ddd and post the output for the rule.

To clone and use Solar from its GitHub repository

git clone https://github.com/pwr-Solaar/Solaar.git
cd Solaar

Run Solaar as bin/solaar from this directory.

To run PR #1599, first clone Solaar if you have not already done so and cd to the clone directory. The first time you download the pull request, fetch it into a new branch and checkout that branch, as in:

git fetch origin pull/1599/head:pull_1599
git checkout pull_1599

To download a new version of the pull request, fetch it and then set your pull branch to the new fetch, as in:

git checkout pull_1599
git fetch origin pull/1599/head
git reset --hard FETCH_HEAD
pfps commented 2 years ago

What appears to be happening is that your Z key has four symbols that it can be used for - z, Z, guillemotleft, and less. Solaar is picking that key to use for less, but doesn't realize that less requires a shift and a level-3-shift. So z results.

The current version of PR #1599 should do better, and also prints some debugging information. Run it as bin/solaar -ddd, run the rule, and post the output from the rule. Also try changing the key press to some other values (try a, A, greater, and comma, at least) and post that output). In each case say what character was output.

Hubro commented 2 years ago

@pfps Awesome, I can confirm it works as expected on your branch :smile:

Here is the debug output of the button press, if that's interesting:

15:44:47,348    DEBUG [ReceiverListener:hidraw15] logitech_receiver.base: (19) => r[11 01 1100 10000000000000000000000000000000]
15:44:47,348    DEBUG [ReceiverListener:hidraw15] logitech_receiver.notifications: <Device(1,407C,G915 WIRELESS RGB MECHANICAL GAMING KEYBOARD,460DF756)>: notification for feature GKEY, report 1, data 10000000000000000000000000000000
15:44:47,348     INFO [MainThread] logitech_receiver.diversion: KeyPress action: ['Alt_L', 'less'], modifiers 16 ['0xffe9', '0x3c']
KK 65513 16 0 64 0 [(64, 0, 0), (204, 0, 1)]
15:44:47,349    DEBUG [MainThread] logitech_receiver.diversion: uinput simulated input 1 56 1
KK 60 16 0 94 0 [(52, 0, 3), (94, 0, 0)]
15:44:47,349    DEBUG [MainThread] logitech_receiver.diversion: uinput simulated input 1 86 1
KK 60 16 0 94 0 [(52, 0, 3), (94, 0, 0)]
15:44:47,349    DEBUG [MainThread] logitech_receiver.diversion: uinput simulated input 1 86 0
KK 65513 16 0 64 0 [(64, 0, 0), (204, 0, 1)]
15:44:47,349    DEBUG [MainThread] logitech_receiver.diversion: uinput simulated input 1 56 0
15:44:47,486    DEBUG [ReceiverListener:hidraw15] logitech_receiver.base: (19) => r[11 01 1100 00000000000000000000000000000000]
15:44:47,486    DEBUG [ReceiverListener:hidraw15] logitech_receiver.notifications: <Device(1,407C,G915 WIRELESS RGB MECHANICAL GAMING KEYBOARD,460DF756)>: notification for feature GKEY, report 1, data 00000000000000000000000000000000

(Note that I changed my rule to this before capturing the debug output:)

---
- Key: [G5, pressed]
- KeyPress: [Alt_L, less]
pfps commented 2 years ago

Good. The current version of the PR has the print statement removed. It will be merged in shortly.