mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2025-12-20 17:20:04 +01:00
tablet: handle a direct tool switch correctly
Fixes #259 Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
parent
bc461b0292
commit
d20bbfa5cb
2 changed files with 72 additions and 18 deletions
|
|
@ -1731,7 +1731,7 @@ tablet_proximity_out_quirk_set_timer(struct tablet_dispatch *tablet,
|
||||||
time + FORCED_PROXOUT_TIMEOUT);
|
time + FORCED_PROXOUT_TIMEOUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static bool
|
||||||
tablet_update_tool_state(struct tablet_dispatch *tablet,
|
tablet_update_tool_state(struct tablet_dispatch *tablet,
|
||||||
struct evdev_device *device,
|
struct evdev_device *device,
|
||||||
uint64_t time)
|
uint64_t time)
|
||||||
|
|
@ -1739,6 +1739,7 @@ tablet_update_tool_state(struct tablet_dispatch *tablet,
|
||||||
enum libinput_tablet_tool_type type;
|
enum libinput_tablet_tool_type type;
|
||||||
uint32_t changed;
|
uint32_t changed;
|
||||||
int state;
|
int state;
|
||||||
|
uint32_t doubled_up_new_tool_bit = 0;
|
||||||
|
|
||||||
/* We need to emulate a BTN_TOOL_PEN if we get an axis event (i.e.
|
/* We need to emulate a BTN_TOOL_PEN if we get an axis event (i.e.
|
||||||
* stylus is def. in proximity) and:
|
* stylus is def. in proximity) and:
|
||||||
|
|
@ -1766,16 +1767,23 @@ tablet_update_tool_state(struct tablet_dispatch *tablet,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tablet->tool_state == tablet->prev_tool_state)
|
if (tablet->tool_state == tablet->prev_tool_state)
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
/* Kernel tools are supposed to be mutually exclusive, if we have
|
/* Kernel tools are supposed to be mutually exclusive, if we have
|
||||||
* two set discard the most recent one. */
|
* two, we force a proximity out for the older tool and handle the
|
||||||
|
* new tool as separate proximity in event.
|
||||||
|
*/
|
||||||
if (tablet->tool_state & (tablet->tool_state - 1)) {
|
if (tablet->tool_state & (tablet->tool_state - 1)) {
|
||||||
evdev_log_bug_kernel(device,
|
/* tool_state has 2 bits set. We set the current tool state
|
||||||
"Multiple tools active simultaneously (%#x)\n",
|
* to zero, thus setting everything up for a prox out on the
|
||||||
tablet->tool_state);
|
* tool. Once that is set up, we change the tool state to be
|
||||||
tablet->tool_state = tablet->prev_tool_state;
|
* the new one we just got so when we re-process this
|
||||||
goto out;
|
* 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;
|
||||||
|
tablet->tool_state = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
changed = tablet->tool_state ^ tablet->prev_tool_state;
|
changed = tablet->tool_state ^ tablet->prev_tool_state;
|
||||||
|
|
@ -1803,9 +1811,13 @@ tablet_update_tool_state(struct tablet_dispatch *tablet,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
|
||||||
tablet->prev_tool_state = tablet->tool_state;
|
tablet->prev_tool_state = tablet->tool_state;
|
||||||
|
|
||||||
|
if (doubled_up_new_tool_bit) {
|
||||||
|
tablet->tool_state = doubled_up_new_tool_bit;
|
||||||
|
return true; /* need to re-process */
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct libinput_tablet_tool *
|
static struct libinput_tablet_tool *
|
||||||
|
|
@ -1826,8 +1838,10 @@ tablet_flush(struct tablet_dispatch *tablet,
|
||||||
uint64_t time)
|
uint64_t time)
|
||||||
{
|
{
|
||||||
struct libinput_tablet_tool *tool;
|
struct libinput_tablet_tool *tool;
|
||||||
|
bool process_tool_twice;
|
||||||
|
|
||||||
tablet_update_tool_state(tablet, device, time);
|
reprocess:
|
||||||
|
process_tool_twice = tablet_update_tool_state(tablet, device, time);
|
||||||
|
|
||||||
tool = tablet_get_current_tool(tablet);
|
tool = tablet_get_current_tool(tablet);
|
||||||
if (!tool)
|
if (!tool)
|
||||||
|
|
@ -1860,6 +1874,9 @@ tablet_flush(struct tablet_dispatch *tablet,
|
||||||
}
|
}
|
||||||
|
|
||||||
tablet_send_events(tablet, tool, device, time);
|
tablet_send_events(tablet, tool, device, time);
|
||||||
|
|
||||||
|
if (process_tool_twice)
|
||||||
|
goto reprocess;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
|
|
|
||||||
|
|
@ -2902,12 +2902,28 @@ START_TEST(tool_direct_switch_skip_tool_update)
|
||||||
libinput_tablet_tool_ref(tool);
|
libinput_tablet_tool_ref(tool);
|
||||||
libinput_event_destroy(event);
|
libinput_event_destroy(event);
|
||||||
|
|
||||||
/* Direct tool switch after proximity in is ignored */
|
|
||||||
litest_disable_log_handler(li);
|
|
||||||
litest_event(dev, EV_KEY, BTN_TOOL_RUBBER, 1);
|
litest_event(dev, EV_KEY, BTN_TOOL_RUBBER, 1);
|
||||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||||
litest_assert_empty_queue(li);
|
libinput_dispatch(li);
|
||||||
litest_restore_log_handler(li);
|
|
||||||
|
event = libinput_get_event(li);
|
||||||
|
tev = litest_is_tablet_event(event,
|
||||||
|
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
|
||||||
|
ck_assert_int_eq(libinput_event_tablet_tool_get_proximity_state(tev),
|
||||||
|
LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
|
||||||
|
ck_assert_ptr_eq(libinput_event_tablet_tool_get_tool(tev), tool);
|
||||||
|
libinput_event_destroy(event);
|
||||||
|
|
||||||
|
event = libinput_get_event(li);
|
||||||
|
tev = litest_is_tablet_event(event,
|
||||||
|
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
|
||||||
|
ck_assert_int_eq(libinput_event_tablet_tool_get_proximity_state(tev),
|
||||||
|
LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN);
|
||||||
|
ck_assert_ptr_ne(libinput_event_tablet_tool_get_tool(tev), tool);
|
||||||
|
libinput_tablet_tool_unref(tool);
|
||||||
|
tool = libinput_event_tablet_tool_get_tool(tev);
|
||||||
|
libinput_tablet_tool_ref(tool);
|
||||||
|
libinput_event_destroy(event);
|
||||||
|
|
||||||
litest_tablet_motion(dev, 20, 30, axes);
|
litest_tablet_motion(dev, 20, 30, axes);
|
||||||
libinput_dispatch(li);
|
libinput_dispatch(li);
|
||||||
|
|
@ -2919,18 +2935,36 @@ START_TEST(tool_direct_switch_skip_tool_update)
|
||||||
tool);
|
tool);
|
||||||
libinput_event_destroy(event);
|
libinput_event_destroy(event);
|
||||||
|
|
||||||
/* Direct tool switch during sequence in is ignored */
|
|
||||||
litest_disable_log_handler(li);
|
|
||||||
litest_event(dev, EV_KEY, BTN_TOOL_RUBBER, 0);
|
litest_event(dev, EV_KEY, BTN_TOOL_RUBBER, 0);
|
||||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||||
litest_assert_empty_queue(li);
|
libinput_dispatch(li);
|
||||||
|
|
||||||
|
event = libinput_get_event(li);
|
||||||
|
tev = litest_is_tablet_event(event,
|
||||||
|
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
|
||||||
|
ck_assert_int_eq(libinput_event_tablet_tool_get_proximity_state(tev),
|
||||||
|
LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
|
||||||
|
ck_assert_ptr_eq(libinput_event_tablet_tool_get_tool(tev),
|
||||||
|
tool);
|
||||||
|
libinput_event_destroy(event);
|
||||||
|
|
||||||
litest_push_event_frame(dev);
|
litest_push_event_frame(dev);
|
||||||
litest_event(dev, EV_KEY, BTN_TOOL_RUBBER, 1);
|
litest_event(dev, EV_KEY, BTN_TOOL_RUBBER, 1);
|
||||||
litest_tablet_motion(dev, 30, 40, axes);
|
litest_tablet_motion(dev, 30, 40, axes);
|
||||||
litest_pop_event_frame(dev);
|
litest_pop_event_frame(dev);
|
||||||
libinput_dispatch(li);
|
libinput_dispatch(li);
|
||||||
litest_restore_log_handler(li);
|
|
||||||
|
event = libinput_get_event(li);
|
||||||
|
tev = litest_is_tablet_event(event,
|
||||||
|
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
|
||||||
|
ck_assert_int_eq(libinput_event_tablet_tool_get_proximity_state(tev),
|
||||||
|
LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN);
|
||||||
|
ck_assert_ptr_eq(libinput_event_tablet_tool_get_tool(tev),
|
||||||
|
tool);
|
||||||
|
libinput_event_destroy(event);
|
||||||
|
|
||||||
|
litest_tablet_motion(dev, 40, 30, axes);
|
||||||
|
libinput_dispatch(li);
|
||||||
|
|
||||||
event = libinput_get_event(li);
|
event = libinput_get_event(li);
|
||||||
tev = litest_is_tablet_event(event,
|
tev = litest_is_tablet_event(event,
|
||||||
|
|
@ -2939,7 +2973,10 @@ START_TEST(tool_direct_switch_skip_tool_update)
|
||||||
tool);
|
tool);
|
||||||
libinput_event_destroy(event);
|
libinput_event_destroy(event);
|
||||||
|
|
||||||
|
litest_push_event_frame(dev);
|
||||||
|
litest_event(dev, EV_KEY, BTN_TOOL_RUBBER, 0);
|
||||||
litest_tablet_proximity_out(dev);
|
litest_tablet_proximity_out(dev);
|
||||||
|
litest_pop_event_frame(dev);
|
||||||
libinput_dispatch(li);
|
libinput_dispatch(li);
|
||||||
litest_timeout_tablet_proxout();
|
litest_timeout_tablet_proxout();
|
||||||
libinput_dispatch(li);
|
libinput_dispatch(li);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue