-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Enable mapping button events on keyboard #6099
Conversation
Meson update is missing. Looks good in general… @hramrach can you explain a bit more why this is needed (the first patch)? |
The kernel is capable of mapping a BTN_* event on a scancode but the hwdb syntax cannot represent that limiting the possible mappings. With this patch you can replace hid_mac (mac mouse emulatiion) legacy driver with hwdb mappings. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems okay, but did you actually test that this is sufficient? I'm not convinced that src/udev/udev-builtin-keyboard.c will accept and actually set BTN_* constants in maps without further changes:
key = udev_list_entry_get_name(entry);
if (startswith(key, "KEYBOARD_KEY_")) {
and there is no corresponding check for BTN_*
.
Please fix the commit message:
- Drop the period at the end of the short description and start with lower case
- "Keyboards support only keys, not buttons." is not a description of the change, but the current state, which is confusing - that commit does not make keyboards support only keys. Just drop that sentence.
Makefile.am
Outdated
|
||
src/udev/keyboard-keys-from-name.gperf: src/udev/keyboard-keys-list.txt | ||
$(AM_V_GEN)$(AWK) 'BEGIN{ print "struct key_name { const char* name; unsigned short id; };"; print "%null-strings"; print "%%";} { print tolower(substr($$1 ,5)) ", " $$1 }' < $< > $@ | ||
$(AM_V_GEN)$(AWK) 'BEGIN{ print "struct key_name { const char* name; unsigned short id; };"; print "%null-strings"; print "%%";} /^KEY_/{ print tolower(substr($$1 ,5)) ", " $$1 } !/^KEY_/{ print tolower($$1) ", " $$1 }' < $< > $@ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So KEY_*
gets that prefix dropped, but anything else keeps the BTN_
prefix. Not exactly consistent, but necessary for backwards compatibility, and dropping all prefixes is too prone to collisions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could change this to also accept key_ prefix. Since there is some fancy processing of the data this should probably not result in significant processing time or binary size increase.
It is sufficient to map the buttons but for libinput to pick up the events input classes must be assigned based on the remapped events. The extra two commits should make that happen. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please clarify the intent in the commit message of "fix detection of pads" to describe the change, not the status quo ("are not assigned any input class").
src/udev/udev-builtin-input_id.c
Outdated
if (has_mouse_button) | ||
if (has_rel_coordinates) | ||
is_mouse = true; | ||
if (!has_abs_coordinates) /* exclude vmmouse and joysticks */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you mean to drop the !
here? I'd certainly define a "pad" to be a device with mouse buttons and absolute coordinates, not the absence of the latter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And what is a device with buttons and no axis? Nothing? Mouse? Pad?
My pad has no axis, only buttons. Based on that I classify such devices as pads.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, like a game controller, not a touchpad. Indeed we call the latter ID_INPUT_TOUCHPAD
. Can you please clarify that in a comment, or maybe rename is_pad
to is_game_controller
or perhaps more precisely is_buttonsonly
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am actually missing a { here
src/udev/udev-builtin-input_id.c
Outdated
|
||
if (is_pointing_stick) | ||
udev_builtin_add_property(dev, test, "ID_INPUT_POINTINGSTICK", "1"); | ||
if (is_mouse) | ||
udev_builtin_add_property(dev, test, "ID_INPUT_MOUSE", "1"); | ||
if (is_pad) | ||
udev_builtin_add_property(dev, test, "ID_INPUT_MOUSE", "1"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TBH I don't understand this. The net effect of this patch should be exactly the same as we have now, except for the case where there is a device without relative nor absolute axes: your patch would currently label it a a mouse (which sounds completely wrong), and with dropping the !
above it would behave it as right now (which then makes little sense). And the is_<device>
really ought to coincide with the ID_INPUT_<DEVICE>
variables, please don't mix up pads and mouses.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately, if you classify something as tablet-pad libinput implies wacom-tablet-pad and if the device is not compatible with libwacom it will not work. Hence the mouse capability. I say that in the commit message.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm, the two if checks above have the same body, hence they should be combined as if (is_mouse || is_pad) …
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With the above rationale and classification of "only buttons", setting INPUT_MOUSE
here makes even less sense IMHO. These are most probably for games, so we'd rather want the more widely accessible ID_INPUT_JOYSTICK
permissions and thus either classify them as joysticks or introduce a new ID_INPUT_GAMEPAD
or so. What kind of device do you actually have?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nope. It has mouse buttons so it is a mouse. If we make it a joystick libinput will ignore it generating no windowing system events.
ok, updated the patch for detecting devices with buttons to exclude any mention of pads in the code since that seems to be misleading. The pad I am referring to here is the subdevice of a Wacom tablet that has the mouse buttons and possibly (but not always) some scroll wheel axis. When you map some mouse buttons on a device that does not have mouse features otherwise it looks much like this. But unlike actual Wacom tablet subdevice it is not compatible with libwacom so it should be assigned the mouse class. |
duh, this works for me when backported to systemd 228 but not 232. The other difference is usb vs ps/2 keyboard. Needs some more debugging. ... and the discrepancy seems to be due to udevadm test showing capabilities of the actual device state and not of the device state that would result from applying the tested rules. So WorksForMe now. hm, was missing button aliases and had quite a few superfluous event names. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please update the PR title — those certainly are not "small" fixups.
src/udev/udev-builtin-input_id.c
Outdated
if (has_rel_coordinates) | ||
is_mouse = true; | ||
else if (!has_abs_coordinates) /* mouse buttons and no axis */ | ||
is_mouse = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be written as:
if (has_mouse_button &&
(has_rel_coordinates || !has_abs_coordinates /* mouse_buttons and no axis */))
is_mouse = true;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also a note on the commit message: the first sentence says "Assign input class...", but I think it'd be clearer to be explicit and say "Label devices which have mouse buttons and no axis as ID_INPUT_MOUSE=1.".
src/udev/udev-builtin-input_id.c
Outdated
@@ -158,10 +158,12 @@ static bool test_pointers(struct udev_device *dev, | |||
const unsigned long* bitmask_rel, | |||
const unsigned long* bitmask_props, | |||
bool test) { | |||
int btn; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No abbrevations like this please.
src/udev/udev-builtin-input_id.c
Outdated
@@ -193,7 +195,7 @@ static bool test_pointers(struct udev_device *dev, | |||
is_pointing_stick = test_bit(INPUT_PROP_POINTING_STICK, bitmask_props); | |||
stylus_or_pen = test_bit(BTN_STYLUS, bitmask_key) || test_bit(BTN_TOOL_PEN, bitmask_key); | |||
finger_but_no_pen = test_bit(BTN_TOOL_FINGER, bitmask_key) && !test_bit(BTN_TOOL_PEN, bitmask_key); | |||
has_mouse_button = test_bit(BTN_LEFT, bitmask_key); | |||
for (btn = BTN_LEFT; btn < BTN_JOYSTICK && !(has_mouse_button = test_bit(btn, bitmask_key)); btn++); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a comment above the loop saying what it does. It's not entirely obvious at first glance. And an empty line before the comment and after the loop.
The for-loop style is a bit unusual, but is seems to work here better then alternatives, so OK.
src/udev/udev-builtin-input_id.c
Outdated
test_bit(ABS_GAS, bitmask_abs) || | ||
test_bit(ABS_BRAKE, bitmask_abs); | ||
for (btn = BTN_JOYSTICK; btn < BTN_DIGI && !(has_joystick_buttons = test_bit(btn, bitmask_key)); btn++); | ||
for (btn = ABS_RX; btn < ABS_PRESSURE && !(has_joystick_axes = test_bit(btn, bitmask_abs)); btn++); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here.
Makefile.am
Outdated
@@ -3922,7 +3922,7 @@ noinst_LTLIBRARIES += \ | |||
|
|||
src/udev/keyboard-keys-list.txt: | |||
$(AM_V_at)$(MKDIR_P) $(dir $@) | |||
$(AM_V_GEN)$(CPP) $(CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) -dM -include linux/input.h - < /dev/null | $(AWK) '/^#define[ \t]+(KEY|BTN)_[^ ]+[ \t]+[0-9BK]/ { if ($$2 != "KEY_MAX") { print $$2 } }' > $@ | |||
$(AM_V_GEN)$(CPP) $(CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) -dM -include linux/input.h - < /dev/null | grep -vEe '\<(KEY_(MAX|MIN_INTERESTING))|(BTN_(MISC|MOUSE|JOYSTICK|GAMEPAD|DIGI|WHEEL|TRIGGER_HAPPY))\>'| $(AWK) '/^#define[ \t]+(KEY|BTN)_[^ ]+[ \t]+[0-9BK]/ { print $$2 }' > $@ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to call grep
, if awk
is already being called. Use next
or something (`awk is not my thing) [https://www.gnu.org/software/gawk/manual/html_node/Next-Statement.html].
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
awk docs say it uses grep extended regexps so just moving the regexp inside the awk call should work. Might not be so easy when the supported regexp variant happens to differ
It seems this s390x test fails randomly. I did not touch networking so I do not see how networkd would be affected. |
src/udev/udev-builtin-input_id.c
Outdated
has_mouse_button = test_bit(BTN_LEFT, bitmask_key); | ||
|
||
/* Set has_mouse_button if any button in [BTN_MOUSE, BTN_JOYSTICK) is found */ | ||
for (button = BTN_MOUSE; button < BTN_JOYSTICK && !(has_mouse_button = test_bit(button, bitmask_key)); button++); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you please follow coding style and use ;
on a separate line if you do for loops with no body?
Also, I really don't appreciate this overly condensed style I must say, this doesn't help readability. Instead of cramming the entire logic with variable assignment and everything into the second part of the for description, why not just place it in the body of the for loop and make it actually readable?
This is not a contest in writing the shortest most unreadable code, but quite the opposite: the focus is on readability.
src/udev/udev-builtin-input_id.c
Outdated
* Set has_joystick_buttons if any button in [BTN_JOYSTICK, BTN_DIGI) is found | ||
* and has_joystick_axes if any axis in [ABS_RX, ABS_PRESSURE) is found */ | ||
for (button = BTN_JOYSTICK; button < BTN_DIGI && !(has_joystick_buttons = test_bit(button, bitmask_key)); button++); | ||
for (axis = ABS_RX; axis < ABS_PRESSURE && !(has_joystick_axes = test_bit(axis, bitmask_abs)); axis++); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the same here.
The old code I could understand, the new code looks like Perl.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few nitpicks, the only real blocker here are the missing meson bits and I really think the PR needs to be renamed to something more expressive. Main goal here is to "Support button events from remapped keyboards" so that would be better than just "fixups".
Rest are nitpicks, the code itself looks good.
@@ -8,7 +8,7 @@ IMPORT{builtin}="hwdb --subsystem=input --lookup-prefix=evdev:", \ | |||
RUN{builtin}+="keyboard", GOTO="evdev_end" | |||
|
|||
# AT keyboard matching by the machine's DMI data | |||
ENV{ID_INPUT_KEY}=="?*", DRIVERS=="atkbd", \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The second sentence of the commit message is typoed, should read "because it is not yet assigned at this point"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think "not yet assigned" and "now not assigned (at this point)" are the same thing. "now not" is not as easy to parse, but it's good enough.
rules/60-input-id.rules
Outdated
|
||
SUBSYSTEM=="input", ENV{ID_INPUT}=="", IMPORT{builtin}="input_id" | ||
|
||
LABEL="default_end" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please rename the label "input_id_end" so it doesn't look like a copy/paste error
@@ -3924,10 +3924,10 @@ noinst_LTLIBRARIES += \ | |||
|
|||
src/udev/keyboard-keys-list.txt: | |||
$(AM_V_at)$(MKDIR_P) $(dir $@) | |||
$(AM_V_GEN)$(CPP) $(CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) -dM -include linux/input.h - < /dev/null | $(AWK) '/^#define[ \t]+KEY_[^ ]+[ \t]+[0-9K]/ { if ($$2 != "KEY_MAX") { print $$2 } }' > $@ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is missing the matching change to src/udev/generate-keyboard-keys-list.sh and the one below to src/udev/generate-keyboard-gperf.py for meson. I'd say the best option here would be to have a separate patch to Makefile.am to use the scripts as well so we only have one place to fix this up.
hm, pushed an update and gihub is not picking it up. Updated the Makefile and meson to use same script and while it is verified no-op for Makefile I have no idea about meson. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
move this commit to the first one in the set please, otherwise we'll have known broken ones - that's usually frowned upon.
For meson testing, all you need is "meson builddir; ninja -C builddir" and that builds it. Heaps of documentation out there, start with mesonbuild.org
Support BTN_* codes with btn_ prefix and keys with KEY_ prefix optionally removed.
udevadm trigger /dev/input/event* does not work use udevadm trigger --verbose --sysname-match="event*"
This places the input_id call after the evdev hwdb calls. With this the hwdb fixups in evdev can affect the device capabilities assigned in input_id. Remove the ID_INPUT_KEY dependency in atkbd rule because it is now not assigned at this point.
Assign ID_INPUT_MOUSE property to devices with mouse buttons and no axis. Libinput tries to use libwacom on devices with tablet-pad capability which are detected by ID_INPUT_TABLET_PAD=1 property so assign pointer class by setting ID_INPUT_MOUSE=1 to devices with mouse buttons and let libwacom override the class for Wacom pads.
Due to remapping some devices might not have the first button. Check whole button range.
The defines KEY_MAX KEY_CNT KEY_MIN_INTERESTING BTN_MISC BTN_MOUSE BTN_JOYSTICK BTN_GAMEPAD BTN_DIGI BTN_WHEEL BTN_TRIGGER_HAPPY mark start/end of key blocks and do not designate events. Exclude them from the list of recognized key events.
They would not be broken. The results for meson and makefile would diverge, though. They diverge slightly anyway because the cpp invocation differs between makefile and meson resulting in different order of the key event defines in the gperf file and probably other oddities. |
FTR, after sorting, I get the following difference: @@ -1,3 +1,114 @@
+BTN_0
+BTN_1
+BTN_2
+BTN_3
+BTN_4
+BTN_5
+BTN_6
+BTN_7
+BTN_8
+BTN_9
+BTN_A
+BTN_B
+BTN_BACK
+BTN_BASE
+BTN_BASE2
+BTN_BASE3
+BTN_BASE4
+BTN_BASE5
+BTN_BASE6
+BTN_C
+BTN_DEAD
+BTN_DPAD_DOWN
+BTN_DPAD_LEFT
+BTN_DPAD_RIGHT
+BTN_DPAD_UP
+BTN_EAST
+BTN_EXTRA
+BTN_FORWARD
+BTN_GEAR_DOWN
+BTN_GEAR_UP
+BTN_LEFT
+BTN_MIDDLE
+BTN_MODE
+BTN_NORTH
+BTN_PINKIE
+BTN_RIGHT
+BTN_SELECT
+BTN_SIDE
+BTN_SOUTH
+BTN_START
+BTN_STYLUS
+BTN_STYLUS2
+BTN_TASK
+BTN_THUMB
+BTN_THUMB2
+BTN_THUMBL
+BTN_THUMBR
+BTN_TL
+BTN_TL2
+BTN_TOOL_AIRBRUSH
+BTN_TOOL_BRUSH
+BTN_TOOL_DOUBLETAP
+BTN_TOOL_FINGER
+BTN_TOOL_LENS
+BTN_TOOL_MOUSE
+BTN_TOOL_PEN
+BTN_TOOL_PENCIL
+BTN_TOOL_QUADTAP
+BTN_TOOL_QUINTTAP
+BTN_TOOL_RUBBER
+BTN_TOOL_TRIPLETAP
+BTN_TOP
+BTN_TOP2
+BTN_TOUCH
+BTN_TR
+BTN_TR2
+BTN_TRIGGER
+BTN_TRIGGER_HAPPY1
+BTN_TRIGGER_HAPPY10
+BTN_TRIGGER_HAPPY11
+BTN_TRIGGER_HAPPY12
+BTN_TRIGGER_HAPPY13
+BTN_TRIGGER_HAPPY14
+BTN_TRIGGER_HAPPY15
+BTN_TRIGGER_HAPPY16
+BTN_TRIGGER_HAPPY17
+BTN_TRIGGER_HAPPY18
+BTN_TRIGGER_HAPPY19
+BTN_TRIGGER_HAPPY2
+BTN_TRIGGER_HAPPY20
+BTN_TRIGGER_HAPPY21
+BTN_TRIGGER_HAPPY22
+BTN_TRIGGER_HAPPY23
+BTN_TRIGGER_HAPPY24
+BTN_TRIGGER_HAPPY25
+BTN_TRIGGER_HAPPY26
+BTN_TRIGGER_HAPPY27
+BTN_TRIGGER_HAPPY28
+BTN_TRIGGER_HAPPY29
+BTN_TRIGGER_HAPPY3
+BTN_TRIGGER_HAPPY30
+BTN_TRIGGER_HAPPY31
+BTN_TRIGGER_HAPPY32
+BTN_TRIGGER_HAPPY33
+BTN_TRIGGER_HAPPY34
+BTN_TRIGGER_HAPPY35
+BTN_TRIGGER_HAPPY36
+BTN_TRIGGER_HAPPY37
+BTN_TRIGGER_HAPPY38
+BTN_TRIGGER_HAPPY39
+BTN_TRIGGER_HAPPY4
+BTN_TRIGGER_HAPPY40
+BTN_TRIGGER_HAPPY5
+BTN_TRIGGER_HAPPY6
+BTN_TRIGGER_HAPPY7
+BTN_TRIGGER_HAPPY8
+BTN_TRIGGER_HAPPY9
+BTN_WEST
+BTN_X
+BTN_Y
+BTN_Z
KEY_0
KEY_1
KEY_102ND
@@ -264,7 +375,6 @@
KEY_MESSENGER
KEY_MHP
KEY_MICMUTE
-KEY_MIN_INTERESTING
KEY_MINUS
KEY_MODE
KEY_MOVE Looks good. I think @whot's comments have been addressed. |
This PR causes #6219. |
@nrlewis117 please also look this over. |
hm, BTN_DPAD_* are outside of any BTN block so they should be added to the joystick test I guess. |
-> hid_mac can be replaced with evdev hwdb rule