mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-02-04 22:10:25 +01:00
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>
This commit is contained in:
parent
167cebf7de
commit
57a592e2df
1 changed files with 26 additions and 11 deletions
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue