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 <vlad.zahorodnii@kde.org>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2032>
This commit is contained in:
Vlad Zahorodnii 2025-06-20 15:59:55 +03:00 committed by Marge Bot
parent c1a3e99ce0
commit 60f0bfe852
2 changed files with 16 additions and 15 deletions

View file

@ -2190,22 +2190,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
@ -2328,7 +2323,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 */
@ -2393,7 +2388,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);
@ -2409,9 +2404,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) {
@ -2431,7 +2431,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) {

View file

@ -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;