diff options
author | Peter Hutterer <peter.hutterer@who-t.net> | 2021-11-17 16:24:00 +1000 |
---|---|---|
committer | José Expósito <jose.exposito89@gmail.com> | 2021-12-14 08:09:20 +0000 |
commit | 57a592e2df06e159901e0dd1162a6e99d350294f (patch) | |
tree | 946d2219471786d5da0ebebd8ec83b5ee2f7dee3 | |
parent | 167cebf7de1258be2047a4a9a8630288e5bbf466 (diff) | |
download | libinput-57a592e2df06e159901e0dd1162a6e99d350294f.tar.gz |
tablet: handle a BTN_TOOL_PEN on top of BTN_TOOL_RUBBER
The Wacom 524C device triggers a kernel bug in the InRange and Invert
handling. Every time BTN_TOUCH is set/unset the device also sets/unsets
BTN_TOOL_PEN even when we nominally have the eraser in proximity.
The event sequence effectively looks like this:
# on prox in
BTN_TOOL_RUBBER 1
-- SYN_REPORT ---
# on tip down
BTN_TOOL_PEN 1
BTN_TOUCH 1
-- SYN_REPORT ---
# on tip up
BTN_TOUCH 0
BTN_TOOL_PEN 0
-- SYN_REPORT ---
# on prox out
BTN_TOOL_RUBBER 1
-- SYN_REPORT ---
To work around this, bias our duplicate tool detection code towards the
eraser - if we have an eraser in-prox already and the pen goes
in-prox, ignore it and continue with the eraser. But if we have a pen
in-prox and the eraser goes in-prox as well, force a prox-out for the
pen and put the eraser in-prox.
Recording originally from
https://github.com/linuxwacom/xf86-input-wacom/issues/186
Fixes #702
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
-rw-r--r-- | src/evdev-tablet.c | 37 |
1 files changed, 26 insertions, 11 deletions
diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c index 3b77b47c..25bb57d6 100644 --- a/src/evdev-tablet.c +++ b/src/evdev-tablet.c @@ -1810,20 +1810,35 @@ tablet_update_tool_state(struct tablet_dispatch *tablet, if (tablet->tool_state == tablet->prev_tool_state) return false; - /* Kernel tools are supposed to be mutually exclusive, if we have - * two, we force a proximity out for the older tool and handle the - * new tool as separate proximity in event. + /* Kernel tools are supposed to be mutually exclusive, but we may have + * two bits set due to firmware/kernel bugs. + * Two cases that have been seen in the wild: + * - BTN_TOOL_PEN on proximity in, followed by + * BTN_TOOL_RUBBER later, see #259 + * -> We force a prox-out of the pen, trigger prox-in for eraser + * - BTN_TOOL_RUBBER on proximity in, but BTN_TOOL_PEN when + * the tip is down, see #702. + * -> We ignore BTN_TOOL_PEN + * In both cases the eraser is what we want, so we bias + * towards that. */ if (tablet->tool_state & (tablet->tool_state - 1)) { - /* tool_state has 2 bits set. We set the current tool state - * to zero, thus setting everything up for a prox out on the - * tool. Once that is set up, we change the tool state to be - * the new one we just got so when we re-process this - * function we now get the new tool as prox in. - * Importantly, we basically rely on nothing else happening - * in the meantime. - */ doubled_up_new_tool_bit = tablet->tool_state ^ tablet->prev_tool_state; + + /* The new tool is the pen. Ignore it */ + if (doubled_up_new_tool_bit == bit(LIBINPUT_TABLET_TOOL_TYPE_PEN)) { + tablet->tool_state &= ~bit(LIBINPUT_TABLET_TOOL_TYPE_PEN); + return false; + } + + /* The new tool is some tool other than pen (usually eraser). + * We set the current tool state to zero, thus setting + * everything up for a prox out on the tool. Once that is set + * up, we change the tool state to be the new one we just got. + * When we re-process this function we now get the new tool + * as prox in. Importantly, we basically rely on nothing else + * happening in the meantime. + */ tablet->tool_state = 0; } |