device specific settings
kbilsted opened this issue · 21 comments
It seems unlikely given the docs say nothing about it. Give something like this a shot? https://www.eightforums.com/threads/tutorial-how-to-change-device-names-in-device-manager.15321/
Aside: do long press timing based remaps work for on your systems on v4.0? I had to revert back to a commit a bit later than v3.5.3 that introduced ContextActive
. In v4.0.0 all keymaps using the form X{200ms}
stopped working.
@ristomatti Many thanks. Did not work but this may.. https://www.thewindowsclub.com/how-to-rename-hardware-in-device-manager-of-windows It renames devices but i have yet to see it survives a reboot etc.
I have taken a detour from combo configurations ...
But I did notice, and reported here as an issue, that the timings were behaving really unexpected and change from many combos, and then taking a 2 sec pause and then invoking combo's again...
i have also tried changing the description field that held the name along with some other data. So i have given up on it for now.. really a shame because i had cool idea to try out using multiple identical keyboards. Its weird though, because my Razer does publis its name correctly...
Multiple identical sounds like a lot of headache especially on Windows (possibly also on Mac). On Linux there's no such limits. 😉
Well not sure about identical devices as Keymapper identifies the devices by the reported name. But I'd be surprised if that couldn't be worked around using udev
rules. For instance, I've created a rule to map Keymapper's virtual input device to a specific device, so that I can attach evtest
to listen on the events without tracing to which input device number it's currently linked to.
$ cat /etc/udev/rules.d/99-keyboard.rules
#
# Create symlink for Keymapper's virtual input device
#
SUBSYSTEM=="input", ATTRS{name}=="Keymapper", SYMLINK+="keymapper"
$ ls -l /dev/keymapper
lrwxrwxrwx root root 13 B Tue Apr 9 22:02:10 2024 /dev/keymapper ⇒ input/event20
I can then do this:
$ sudo evtest /dev/keymapper | grep -Ev '(REL_X|REL_Y|SYN_REPORT)'
Input driver version is 1.0.1
Input device ID: bus 0x3 vendor 0xd1ce product 0x1 version 0x1
Input device name: "Keymapper"
Supported events:
Event type 0 (EV_SYN)
Event type 1 (EV_KEY)
Event code 1 (KEY_ESC)
Event code 2 (KEY_1)
Event code 3 (KEY_2)
...
Value 0
Min 0
Max 1023
Key repeat handling:
Repeat type 20 (EV_REP)
Repeat code 0 (REP_DELAY)
Value 250
Repeat code 1 (REP_PERIOD)
Value 33
Properties:
Testing ... (interrupt to exit)
Event: time 1712698213.100691, type 1 (EV_KEY), code 28 (KEY_ENTER), value 0
Event: time 1712698213.409776, type 1 (EV_KEY), code 35 (KEY_H), value 1
hEvent: time 1712698213.448761, type 1 (EV_KEY), code 35 (KEY_H), value 0
Event: time 1712698213.609793, type 1 (EV_KEY), code 18 (KEY_E), value 1
eEvent: time 1712698213.695726, type 1 (EV_KEY), code 18 (KEY_E), value 0
Event: time 1712698213.762754, type 1 (EV_KEY), code 38 (KEY_L), value 1
lEvent: time 1712698213.821754, type 1 (EV_KEY), code 38 (KEY_L), value 0
Event: time 1712698213.908614, type 1 (EV_KEY), code 38 (KEY_L), value 1
lEvent: time 1712698213.977647, type 1 (EV_KEY), code 38 (KEY_L), value 0
Event: time 1712698214.074795, type 1 (EV_KEY), code 24 (KEY_O), value 1
oEvent: time 1712698214.139815, type 1 (EV_KEY), code 24 (KEY_O), value 0
Event: time 1712698218.885735, type 1 (EV_KEY), code 57 (KEY_SPACE), value 1
Event: time 1712698218.962762, type 1 (EV_KEY), code 57 (KEY_SPACE), value 0
Event: time 1712698218.991758, type 1 (EV_KEY), code 17 (KEY_W), value 1
wEvent: time 1712698219.071970, type 1 (EV_KEY), code 17 (KEY_W), value 0
Event: time 1712698219.106959, type 1 (EV_KEY), code 24 (KEY_O), value 1
oEvent: time 1712698219.194910, type 1 (EV_KEY), code 24 (KEY_O), value 0
Event: time 1712698219.264923, type 1 (EV_KEY), code 19 (KEY_R), value 1
rEvent: time 1712698219.341965, type 1 (EV_KEY), code 19 (KEY_R), value 0
Event: time 1712698219.430947, type 1 (EV_KEY), code 38 (KEY_L), value 1
lEvent: time 1712698219.510912, type 1 (EV_KEY), code 38 (KEY_L), value 0
Event: time 1712698219.525952, type 1 (EV_KEY), code 32 (KEY_D), value 1
dEvent: time 1712698219.619953, type 1 (EV_KEY), code 32 (KEY_D), value 0
This reminded me of an obscure Keymapper related issue I solved during the weekend. I found a Logitech trackball mouse from one of my gadget archive boxes. I don't remember ever using it, I got it from my father >10y ago. I figured to try if I can do something neat with it with Keymapper. With some testing I realized it's the perfect secondary/left hand mouse for scrolling long pages/files very precisely.
I just needed to find a way to make it effortless, e.g. scroll while pressing one of it's buttons. As happens time after time, I end up in Arch Wiki which has instructions on how to make it do just that (among other things) https://wiki.archlinux.org/title/Logitech_Marble_Mouse#Scroll_modifier. However, nothing I tried seemed to work. After hours of head scratching, it occurred to me to check if Keymapper could somehow be the culprit. Sure enough, if I stopped Keymapper the scroll modifier started working with this config:
$ cat /etc/X11/xorg.conf.d/10-logitech-marble-mouse.conf
Section "InputClass"
Identifier "Marble Mouse"
MatchIsPointer "on"
MatchProduct "Logitech USB Trackball"
Driver "libinput"
Option "ScrollMethod" "button"
Option "ScrollButton" "8"
Option "AccelProfile" "flat"
Option "HorizontalScrolling" "false"
Option "ButtonMapping" "1 2 3 4 5 6 7 8 8"
EndSection
It turned out, as a low level remapping tool, Keymapper was grabbing the events and sending them out through it's virtual mouse. The trick was to set the libinput
settings on the virtual device! I then created an over engineered systemd
configuration that involved wrapping keymapper
in a systemd user service and adding another systemd service bound to it which was responsible of redoing the mappings using xinput
when ever keymapper
got started/restarted.
Today I realized I can reach the same end result using the new ContextActive
mechanism:
# On startup
setScrollButton = $(sleep 1 && xinput set-prop "pointer:Keymapper" "libinput Button Scrolling Button" 2)
enableScrollButton = $(sleep 1 && xinput set-prop "pointer:Keymapper" "libinput Scroll Method Enabled" 0, 0, 1)
[default]
ContextActive >> on_startup
on_startup >> setScrollButton enableScrollButton
To further make it a more effortless scrolling device, I came up with this config:
MouseScrollLock = Virtual7
MouseTrackball = "Logitech USB Trackball"
DoubleTap = $0 !250ms $0{!250ms}
# Mouse scroll lock (NB: this affects all pointer devices)
[modifier=MouseScrollLock]
ContextActive >> context["modifier = MouseScrollLock"]
MouseButton >> MouseScrollLock
[default]
MouseScrollLock >> ButtonMiddle
# Mouse Buttons // Logitech Trackball
[device=MouseTrackball]
ContextActive >> context["device = MouseTrackball"]
DoubleTap[ButtonLeft] >> ButtonBack
DoubleTap[ButtonRight] >> ButtonForward
(ButtonLeft ButtonRight) >> MouseScrollLock
ButtonLeft >> ButtonRight
ButtonRight >> ButtonLeft
ButtonForward >> ButtonMiddle
Pretty nifty? 😎
FYI @houmain, you might be curious about the libinput
adventure.
Forgot to mention, I found out the mouse is still produced and commands a whopping 200€ price tag! https://www.amazon.com/Logitech-910-000808-Marble-Mouse/dp/B001DQY9AW... And I just had it buried under some cables longer than I can remember! 😆
(It looks awfully ugly next to my Keychron K15 Pro and Logitech G502X Lightspeed mouse though...)
Ill pay you €5 for it.. including shipping
Where does keymapper get the name from (on Linux if it matters)?
@Zireael07 It uses the names listed with xinput
.
$ xinput list
⎡ Virtual core pointer id=2 [master pointer (3)]
⎜ ↳ Virtual core XTEST pointer id=4 [slave pointer (2)]
⎜ ↳ SynPS/2 Synaptics TouchPad id=24 [slave pointer (2)]
⎜ ↳ TPPS/2 Elan TrackPoint id=25 [slave pointer (2)]
⎜ ↳ SINO WEALTH Gaming KB Consumer Control id=34 [slave pointer (2)]
⎜ ↳ SINO WEALTH Gaming KB Mouse id=38 [slave pointer (2)]
⎜ ↳ Keymapper id=31 [slave pointer (2)]
⎜ ↳ Logitech USB Trackball id=11 [slave pointer (2)]
⎜ ↳ Keychron Keychron K15 Pro Mouse id=15 [slave pointer (2)]
⎜ ↳ Keychron Keychron K15 Pro Consumer Control id=16 [slave pointer (2)]
⎜ ↳ Logitech MX Anywhere 2S id=18 [slave pointer (2)]
⎜ ↳ Logitech USB Receiver Keyboard id=21 [slave pointer (2)]
⎜ ↳ Logitech USB Receiver id=27 [slave pointer (2)]
⎜ ↳ Generic Blue Microphones Consumer Control id=29 [slave pointer (2)]
⎣ Virtual core keyboard id=3 [master keyboard (2)]
↳ Virtual core XTEST keyboard id=5 [slave keyboard (3)]
↳ Power Button id=6 [slave keyboard (3)]
↳ Video Bus id=7 [slave keyboard (3)]
↳ Sleep Button id=8 [slave keyboard (3)]
↳ Integrated Camera: Integrated C id=9 [slave keyboard (3)]
↳ Integrated Camera: Integrated I id=10 [slave keyboard (3)]
↳ AT Translated Set 2 keyboard id=23 [slave keyboard (3)]
↳ ThinkPad Extra Buttons id=26 [slave keyboard (3)]
↳ SINO WEALTH Gaming KB System Control id=33 [slave keyboard (3)]
↳ SINO WEALTH Gaming KB Consumer Control id=35 [slave keyboard (3)]
↳ SINO WEALTH Gaming KB Keyboard id=36 [slave keyboard (3)]
↳ SINO WEALTH Gaming KB id=37 [slave keyboard (3)]
↳ Keymapper id=32 [slave keyboard (3)]
↳ Keychron Keychron K15 Pro Keyboard id=12 [slave keyboard (3)]
↳ Keychron Keychron K15 Pro System Control id=13 [slave keyboard (3)]
↳ Keychron Keychron K15 Pro id=14 [slave keyboard (3)]
↳ Keychron Keychron K15 Pro Consumer Control id=17 [slave keyboard (3)]
↳ Logitech MX Anywhere 2S id=19 [slave keyboard (3)]
↳ Lenovo ThinkPad Thunderbolt 3 Dock USB Audio id=20 [slave keyboard (3)]
↳ Logitech USB Receiver Keyboard id=22 [slave keyboard (3)]
↳ Generic Blue Microphones id=28 [slave keyboard (3)]
↳ Generic Blue Microphones Consumer Control id=30 [slave keyboard (3)]
↳ Ugreen-70304E (AVRCP) id=39 [slave keyboard (3)]
@ristomatti Thanks a lot, this should be mentioned in the README tbh
You can see it also with dmesg -w
if you attach the device while monitoring the output:
$ dmesg -w
[2688710.195134] usb 5-2.1.4: USB disconnect, device number 13
[2688712.775513] usb 5-2.1.4: new full-speed USB device number 24 using xhci_hcd
[2688712.925149] usb 5-2.1.4: New USB device found, idVendor=3434, idProduct=02f6, bcdDevice= 1.02
[2688712.925153] usb 5-2.1.4: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[2688712.925155] usb 5-2.1.4: Product: Keychron K15 Pro
[2688712.925156] usb 5-2.1.4: Manufacturer: Keychron
[2688712.943498] input: Keychron Keychron K15 Pro as /devices/pci0000:00/0000:00:1c.0/0000:04:00.0/0000:05:01.0/0000:07:00.0/0000:08:02.0/0000:09:00.0/usb5/5-2/5-2.1/5-2.1.4/5-2.1.4:1.0/0003:3434:02F6.0179/input/input812
[2688713.003846] hid-generic 0003:3434:02F6.0179: input,hidraw4: USB HID v1.11 Keyboard [Keychron Keychron K15 Pro] on usb-0000:09:00.0-2.1.4/input0
[2688713.004505] hid-generic 0003:3434:02F6.017A: hiddev1,hidraw5: USB HID v1.11 Device [Keychron Keychron K15 Pro] on usb-0000:09:00.0-2.1.4/input1
[2688713.005387] input: Keychron Keychron K15 Pro Mouse as /devices/pci0000:00/0000:00:1c.0/0000:04:00.0/0000:05:01.0/0000:07:00.0/0000:08:02.0/0000:09:00.0/usb5/5-2/5-2.1/5-2.1.4/5-2.1.4:1.2/0003:3434:02F6.017B/input/input813
[2688713.005521] input: Keychron Keychron K15 Pro System Control as /devices/pci0000:00/0000:00:1c.0/0000:04:00.0/0000:05:01.0/0000:07:00.0/0000:08:02.0/0000:09:00.0/usb5/5-2/5-2.1/5-2.1.4/5-2.1.4:1.2/0003:3434:02F6.017B/input/input814
[2688713.063871] input: Keychron Keychron K15 Pro Consumer Control as /devices/pci0000:00/0000:00:1c.0/0000:04:00.0/0000:05:01.0/0000:07:00.0/0000:08:02.0/0000:09:00.0/usb5/5-2/5-2.1/5-2.1.4/5-2.1.4:1.2/0003:3434:02F6.017B/input/input815
[2688713.064063] input: Keychron Keychron K15 Pro Keyboard as /devices/pci0000:00/0000:00:1c.0/0000:04:00.0/0000:05:01.0/0000:07:00.0/0000:08:02.0/0000:09:00.0/usb5/5-2/5-2.1/5-2.1.4/5-2.1.4:1.2/0003:3434:02F6.017B/input/input816
[2688713.064461] hid-generic 0003:3434:02F6.017B: input,hidraw6: USB HID v1.11 Mouse [Keychron Keychron K15 Pro] on usb-0000:09:00.0-2.1.4/input2
...or tail -f /var/log/kernel.log
Since the 4.1.1 release the tray icon menu contains an entry "Devices" which creates a notification containing the names of the grabbed devices. This should help with making device filters without additional tools.
The tray is neat <3 <3 but doesn't solve the underlying problem. I now have two numpads, and not only are they named as super generic "USB szh keyboard" but both of them report the same name.
udev cannot rename devices (As I just discovered) and keymapper seems to entirely ignore the symlinks I just spent half a day creating
I ended up using https://github.com/Blugatroff/diversion for the time being which lets me grab only the two numpads and do the rebinding magic in a Lua file. Might be worth looking at in terms of how they grab the input devices
@Zireael07 Nice find! Perhaps Keymapper could be extended to support device files as an alternative way to define device identifiers. Any thoughts @houmain?
So the /dev/input/by-id
path would be the best way to distinguish identical devices on Linux?
@houmain Rather any file under /dev/input
file. They're all just symlinks to /dev/input/eventXXX
anyhow. I don't have two identical devices to test to be able to tell how they appear.
Or maybe just any file under /dev
. I've for instance created an udev
rule like this:
#
# Create symlink for Keymapper's virtual input device
#
SUBSYSTEM=="input", ATTRS{name}=="Keymapper", SYMLINK+="keymapper"
This creates a symlink to Keymapper's current device file under /dev/keymapper
:
$ ll /dev/keymapper
lrwxrwxrwx root root 13 B Wed May 1 22:26:13 2024 /dev/keymapper ⇒ input/event12
The dev/input/by-id is how I differentiated the two numpads, yes.
What is needed is not just the ability to follow symlinks but also the ability to specify devices using filenames as opposed to device names because the latter are hardcoded at driver/kernel level apparently
(Except for special characters, proudly typed on the two numpads under discussion which both have a device name of "usb szh keyboard")
There is a new device_id
filter in the 4.2.0 release. The id is available for devices which have a /dev/input/by-id
link.