From cbd1fc7ee6dced7ad6beecd5b9ad56a7f977f0c4 Mon Sep 17 00:00:00 2001 From: Berke Güzel Date: Tue, 13 Oct 2026 16:57:59 +0300 Subject: Report held pointer buttons on every pointer event Pointer events set button only on press and release, so wsap_term tracked held buttons itself to tell a drag from a hover. yasl_pointer_event.buttons now holds a YASL_BUTTON_BIT() mask of the buttons held after each event. The common input queue tracks it from the DOWN and UP events it queues, and clears it on INPUT_RESET and on allocation failure. Wayland also clears it on leave, since the compositor sends leave during a press only when it takes the pointer and no release follows. X11 and Cocoa keep it, because they deliver motion and the release to the pressed window after leave. Co-Authored-By: Claude Opus 5.5 --- src/common/input.c | 17 ++++++++++++++++- src/common/input.h | 7 ++++++- 2 files changed, 22 insertions(+), 2 deletions(-) (limited to 'src/common') diff --git a/src/common/input.c b/src/common/input.c index 0b55f1f..ce3219c 100644 --- a/src/common/input.c +++ b/src/common/input.c @@ -33,6 +33,7 @@ bool input_queue_push(struct input_queue *q, const struct yasl_event *ev) owned[len] = '\0'; copy.text.data = owned; } + uint32_t buttons = q->buttons; switch (ev->type) { case YASL_EVENT_POINTER_MOTION: if (!q->relative) { @@ -41,19 +42,31 @@ bool input_queue_push(struct input_queue *q, const struct yasl_event *ev) ev->pointer.pos.y - q->last_pos.y} : (struct yasl_vector2d){0, 0}; } - [[fallthrough]]; + q->last_pos = ev->pointer.pos; + q->has_last_pos = true; + break; case YASL_EVENT_POINTER_DOWN: case YASL_EVENT_POINTER_UP: + if ((unsigned)ev->pointer.button < 32) { + uint32_t bit = YASL_BUTTON_BIT(ev->pointer.button); + buttons = ev->type == YASL_EVENT_POINTER_DOWN ? buttons | bit : buttons & ~bit; + } q->last_pos = ev->pointer.pos; q->has_last_pos = true; break; case YASL_EVENT_POINTER_LEAVE: + if (q->leave_ends_press) buttons = 0; + q->has_last_pos = false; + break; case YASL_EVENT_INPUT_RESET: + buttons = 0; q->has_last_pos = false; break; default: break; } + if (ev->type >= YASL_EVENT_POINTER_DOWN && ev->type <= YASL_EVENT_POINTER_LEAVE) + copy.pointer.buttons = buttons; if (q->count == q->capacity) { size_t capacity = q->capacity ? q->capacity * 2 : 32; if (capacity < q->capacity || capacity > SIZE_MAX / sizeof(*q->events)) @@ -74,6 +87,7 @@ bool input_queue_push(struct input_queue *q, const struct yasl_event *ev) } q->events[(q->head + q->count) & (q->capacity - 1)] = copy; q->count++; + q->buttons = buttons; return true; failed: @@ -84,6 +98,7 @@ failed: q->reset_surface = ev->surface; q->reset_pending = true; q->has_last_pos = false; + q->buttons = 0; return false; } diff --git a/src/common/input.h b/src/common/input.h index ffd1663..aad5c9a 100644 --- a/src/common/input.h +++ b/src/common/input.h @@ -15,11 +15,16 @@ struct input_queue { bool relative; struct yasl_surface *reset_surface; bool reset_pending; + /* YASL_BUTTON_BIT() mask from pushed DOWN/UP events. */ + uint32_t buttons; + /* Set by backends whose pointer leave ends any press: no release follows. */ + bool leave_ends_press; }; /* Copies text payloads and stamps time_ns when zero. Unless q->relative is set, * POINTER_MOTION delta is computed from the previous position; otherwise the - * backend-supplied delta is kept. Leave and reset clear the position history. */ + * backend-supplied delta is kept. Leave and reset clear the position history. + * Pointer events get the held-button mask; reset clears it. */ bool input_queue_push(struct input_queue *q, const struct yasl_event *ev); bool input_queue_pop(struct input_queue *q, struct yasl_event *ev); void input_queue_clear(struct input_queue *q); -- cgit v1.2.3