summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Hutterer <peter.hutterer@who-t.net>2021-11-17 16:24:00 +1000
committerJosé Expósito <jose.exposito89@gmail.com>2021-12-14 08:09:20 +0000
commit57a592e2df06e159901e0dd1162a6e99d350294f (patch)
tree946d2219471786d5da0ebebd8ec83b5ee2f7dee3
parent167cebf7de1258be2047a4a9a8630288e5bbf466 (diff)
downloadlibinput-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.c37
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;
}