From 69e440a282ceb8d9d093fd69cf1fc5389c46a784 Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Fri, 20 Jun 2025 15:59:55 +0300 Subject: [PATCH] xwayland: Dispatch tablet tool tip events after frame events Xwayland dispatches tablet tool tip events immediately when they arrive. With compositors such as mutter and sway, it is not an issue because their libinput backends synthetize axis events before tip events. In other words, axis data and the tip status belong to different frames. On the other hand, kwin sends axis and tip events in a single frame (its libinput backend generates a single tip event with axis data attached to it). Since the tip events are dispatched immediately, they can have wrong information associated with them, for example tool position or pressure. It results in undesired "streaks" when the user presses the tablet tool against the tablet. See also https://bugs.kde.org/show_bug.cgi?id=479856. Signed-off-by: Vlad Zahorodnii (cherry picked from commit 60f0bfe852b988b3c4351483720e3c72c75f7405) Part-of: --- hw/xwayland/xwayland-input.c | 26 +++++++++++++------------- hw/xwayland/xwayland-input.h | 5 +++-- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c index 53cc5144b..d5bce3783 100644 --- a/hw/xwayland/xwayland-input.c +++ b/hw/xwayland/xwayland-input.c @@ -2183,22 +2183,17 @@ tablet_tool_down(void *data, struct zwp_tablet_tool_v2 *tool, uint32_t serial) { struct xwl_tablet_tool *xwl_tablet_tool = data; struct xwl_seat *xwl_seat = xwl_tablet_tool->seat; - ValuatorMask mask; + xwl_tablet_tool->tip = TRUE; xwl_seat->xwl_screen->serial = serial; - - valuator_mask_zero(&mask); - QueuePointerEvents(xwl_tablet_tool->xdevice, ButtonPress, 1, 0, &mask); } static void tablet_tool_up(void *data, struct zwp_tablet_tool_v2 *tool) { struct xwl_tablet_tool *xwl_tablet_tool = data; - ValuatorMask mask; - valuator_mask_zero(&mask); - QueuePointerEvents(xwl_tablet_tool->xdevice, ButtonRelease, 1, 0, &mask); + xwl_tablet_tool->tip = FALSE; } static void @@ -2321,7 +2316,7 @@ tablet_tool_button_state(void *data, struct zwp_tablet_tool_v2 *tool, { struct xwl_tablet_tool *xwl_tablet_tool = data; struct xwl_seat *xwl_seat = xwl_tablet_tool->seat; - uint32_t *mask = &xwl_tablet_tool->buttons_now; + uint32_t *mask = &xwl_tablet_tool->buttons; int xbtn = 0; /* BTN_0 .. BTN_9 */ @@ -2386,7 +2381,7 @@ tablet_tool_frame(void *data, struct zwp_tablet_tool_v2 *tool, uint32_t time) { struct xwl_tablet_tool *xwl_tablet_tool = data; ValuatorMask mask; - uint32_t released, pressed, diff; + uint32_t effective_buttons, released, pressed, diff; int button; valuator_mask_zero(&mask); @@ -2402,9 +2397,14 @@ tablet_tool_frame(void *data, struct zwp_tablet_tool_v2 *tool, uint32_t time) valuator_mask_zero(&mask); - diff = xwl_tablet_tool->buttons_prev ^ xwl_tablet_tool->buttons_now; - released = diff & ~xwl_tablet_tool->buttons_now; - pressed = diff & xwl_tablet_tool->buttons_now; + effective_buttons = xwl_tablet_tool->buttons; + if (xwl_tablet_tool->tip) { + SetBit(&effective_buttons, 0); + } + + diff = effective_buttons ^ xwl_tablet_tool->effective_buttons; + released = diff & ~effective_buttons; + pressed = diff & effective_buttons; button = 1; while (released) { @@ -2424,7 +2424,7 @@ tablet_tool_frame(void *data, struct zwp_tablet_tool_v2 *tool, uint32_t time) pressed >>= 1; } - xwl_tablet_tool->buttons_prev = xwl_tablet_tool->buttons_now; + xwl_tablet_tool->effective_buttons = effective_buttons; while (xwl_tablet_tool->wheel_clicks) { if (xwl_tablet_tool->wheel_clicks < 0) { diff --git a/hw/xwayland/xwayland-input.h b/hw/xwayland/xwayland-input.h index d40bca08a..0a742f017 100644 --- a/hw/xwayland/xwayland-input.h +++ b/hw/xwayland/xwayland-input.h @@ -148,8 +148,9 @@ struct xwl_tablet_tool { double rotation; double slider; - uint32_t buttons_now, - buttons_prev; + uint32_t buttons; + Bool tip; + uint32_t effective_buttons; int32_t wheel_clicks;