diff options
Diffstat (limited to 'src/platform/wayland/pointer.c')
| -rw-r--r-- | src/platform/wayland/pointer.c | 85 |
1 files changed, 63 insertions, 22 deletions
diff --git a/src/platform/wayland/pointer.c b/src/platform/wayland/pointer.c index 0cd8c5b..9f8ca49 100644 --- a/src/platform/wayland/pointer.c +++ b/src/platform/wayland/pointer.c @@ -35,21 +35,33 @@ struct tablet_pad { struct zwp_tablet_pad_v2 *proxy; }; -static struct yasl_private_vector2i device_from_fixed(const struct wayland_surface *w, - wl_fixed_t x, wl_fixed_t y) +static struct yasl_private_vector2d device_precise(const struct wayland_surface *w, + wl_fixed_t x, wl_fixed_t y) { - return (struct yasl_private_vector2i){ - .x = (int)lrint(wl_fixed_to_double(x) * w->scale_factor), - .y = (int)lrint(wl_fixed_to_double(y) * w->scale_factor), + return (struct yasl_private_vector2d){ + .x = wl_fixed_to_double(x) * w->scale_factor, + .y = wl_fixed_to_double(y) * w->scale_factor, }; } +static struct yasl_private_vector2i device_round(struct yasl_private_vector2d p) +{ + return (struct yasl_private_vector2i){ .x = (int)lrint(p.x), .y = (int)lrint(p.y) }; +} + void seat_note_input(struct seat *s, uint32_t serial) { s->input_serial = serial; s->conn->active_seat = s; } +uint32_t seat_held_press_serial(const struct seat *s) +{ + if (!s) return 0; + bool held = s->pointer_buttons != 0 || (s->tool && s->tool->in_contact); + return held ? s->press_serial : 0; +} + static void push_pointer(struct seat *s, struct wayland_surface *w, enum yasl_private_event_type type, struct yasl_private_pointer_event ev) { @@ -220,6 +232,9 @@ static void press_queue_flush(struct seat *s, struct press_queue *q, *buttons = (*buttons & ~mask) | ((uint64_t)(!p.release) << p.button); struct yasl_private_pointer_event ev = like; ev.pos = p.pos; + ev.precise_x = p.precise.x; + ev.precise_y = p.precise.y; + ev.precise_position = true; ev.button = (enum yasl_private_pointer_button)p.button; enum yasl_private_event_type type = p.release ? YASL_PRIVATE_EVENT_POINTER_UP : YASL_PRIVATE_EVENT_POINTER_DOWN; push_pointer(s, p.surface, type, ev); @@ -229,14 +244,15 @@ static void press_queue_flush(struct seat *s, struct press_queue *q, } static void press_queue_push(struct press_queue *q, struct wayland_surface *w, - struct yasl_private_vector2i pos, int button, bool release) + struct yasl_private_vector2i pos, struct yasl_private_vector2d precise, + int button, bool release) { if (q->n == 8) { q->head = (q->head + 1) & 7; q->n--; } q->ev[(q->head + q->n) & 7] = (struct pending_press){ - .surface = w, .pos = pos, .button = button, .release = release, + .surface = w, .pos = pos, .precise = precise, .button = button, .release = release, }; q->n++; } @@ -282,6 +298,9 @@ static void flush_pending_motion(struct seat *s, struct wayland_surface *w) s->motion_pending = false; push_pointer(s, w, YASL_PRIVATE_EVENT_POINTER_MOTION, (struct yasl_private_pointer_event){ .pos = s->pointer_pos, + .precise_x = s->pointer_precise.x, + .precise_y = s->pointer_precise.y, + .precise_position = true, }); } @@ -295,7 +314,8 @@ static void pointer_enter(void *data, struct wl_pointer *pointer, (struct wayland_surface *)wl_surface_get_user_data(surface) : NULL; s->pointer_focus = w; if (!w) return; - s->pointer_pos = device_from_fixed(w, surface_x, surface_y); + s->pointer_precise = device_precise(w, surface_x, surface_y); + s->pointer_pos = device_round(s->pointer_precise); s->pointer_serial = serial; s->cursor_shape = -1; seat_set_cursor(s, w); @@ -315,6 +335,7 @@ static void pointer_leave(void *data, struct wl_pointer *pointer, pointer_frame(s, s->pointer); s->ptr_left = w; s->ptr_left_pos = s->pointer_pos; + s->ptr_left_precise = s->pointer_precise; s->ptr_left_motion = s->motion_pending; s->motion_pending = false; pointer_event_done(s); @@ -327,7 +348,8 @@ static void pointer_motion(void *data, struct wl_pointer *pointer, struct seat *s = data; struct wayland_surface *w = s->pointer_focus; if (!w) return; - s->pointer_pos = device_from_fixed(w, surface_x, surface_y); + s->pointer_precise = device_precise(w, surface_x, surface_y); + s->pointer_pos = device_round(s->pointer_precise); s->motion_pending = true; pointer_event_done(s); } @@ -360,7 +382,7 @@ static void pointer_button(void *data, struct wl_pointer *pointer, s->press_serial = serial; s->press_surface = w; } - press_queue_push(&s->ptr_presses, w, s->pointer_pos, b, release); + press_queue_push(&s->ptr_presses, w, s->pointer_pos, s->pointer_precise, b, release); pointer_event_done(s); } @@ -464,17 +486,22 @@ static void pointer_frame(void *data, struct wl_pointer *pointer) if (s->ptr_left_motion) push_pointer(s, left, YASL_PRIVATE_EVENT_POINTER_MOTION, (struct yasl_private_pointer_event){ .pos = s->ptr_left_pos, + .precise_x = s->ptr_left_precise.x, + .precise_y = s->ptr_left_precise.y, + .precise_position = true, }); press_queue_flush(s, &s->ptr_presses, left, &s->pointer_buttons, (struct yasl_private_pointer_event){0}); push_pointer(s, left, YASL_PRIVATE_EVENT_POINTER_LEAVE, (struct yasl_private_pointer_event){ .pos = s->ptr_left_pos, }); struct yasl_private_vector2i pos = s->pointer_pos; + struct yasl_private_vector2d precise = s->pointer_precise; bool motion = s->motion_pending; uint32_t serial = s->pointer_focus ? s->pointer_serial : 0; int shape = s->pointer_focus ? s->cursor_shape : -1; seat_pointer_reset(s); s->pointer_pos = pos; + s->pointer_precise = precise; s->motion_pending = motion; s->pointer_serial = serial; s->cursor_shape = shape; @@ -508,6 +535,9 @@ static void relative_motion(void *data, struct zwp_relative_pointer_v1 *pointer, flush_pending_motion(s, w); push_pointer(s, w, YASL_PRIVATE_EVENT_POINTER_MOTION, (struct yasl_private_pointer_event){ .pos = s->pointer_pos, + .precise_x = s->pointer_precise.x, + .precise_y = s->pointer_precise.y, + .precise_position = true, .delta = {wl_fixed_to_double(dx) * w->scale_factor, wl_fixed_to_double(dy) * w->scale_factor}, }); @@ -571,6 +601,17 @@ static void seat_lock_surfaces(struct seat *s) surface_lock_pointer(w, s); } +void surface_lock_preferred(struct wayland_surface *w) +{ + struct wayland_display *c = w->conn; + /* Prefer the seat that last delivered input; others lock once it goes away. */ + struct seat *seat = c->active_seat && c->active_seat->pointer ? c->active_seat : NULL; + for (struct seat *s = c->seats; s && !seat; s = s->next) + if (s->pointer) seat = s; + if (seat) + surface_lock_pointer(w, seat); +} + bool wayland_surface_set_pointer_mode(struct wayland_surface *w, enum yasl_private_pointer_mode mode) { if (!w || !w->conn || w->destroyed) @@ -581,12 +622,7 @@ bool wayland_surface_set_pointer_mode(struct wayland_surface *w, enum yasl_priva return false; w->relative = relative; if (relative) { - /* Prefer the seat that last delivered input; others lock once it goes away. */ - struct seat *seat = c->active_seat && c->active_seat->pointer ? c->active_seat : NULL; - for (struct seat *s = c->seats; s && !seat; s = s->next) - if (s->pointer) seat = s; - if (seat) - surface_lock_pointer(w, seat); + surface_lock_preferred(w); } else { surface_unlock_pointer(w); } @@ -859,6 +895,7 @@ static void tablet_tool_proximity_in(void *data, if (!w) return; t->x = s->tool_pos.x; t->y = s->tool_pos.y; + s->tool_precise = (struct yasl_private_vector2d){ s->tool_pos.x, s->tool_pos.y }; if (s->conn->cursor_shape_mgr && !t->shape_dev) t->shape_dev = wp_cursor_shape_manager_v1_get_tablet_tool_v2( s->conn->cursor_shape_mgr, t->proxy); @@ -903,7 +940,7 @@ static void tablet_tool_down(void *data, struct zwp_tablet_tool_v2 *tool, uint32 seat_note_input(s, serial); s->press_serial = serial; s->press_surface = w; - press_queue_push(&s->tool_presses, w, s->tool_pos, 0, false); + press_queue_push(&s->tool_presses, w, s->tool_pos, s->tool_precise, 0, false); t->in_contact = true; pen_action_push(t, YASL_PRIVATE_PEN_DOWN, 0); } @@ -916,7 +953,7 @@ static void tablet_tool_up(void *data, struct zwp_tablet_tool_v2 *tool) struct wayland_surface *w = s->tablet_focus; if (!w) return; s->pen.pressure = 0; - press_queue_push(&s->tool_presses, w, s->tool_pos, 0, true); + press_queue_push(&s->tool_presses, w, s->tool_pos, s->tool_precise, 0, true); t->pressure = 0; t->in_contact = false; pen_action_push(t, YASL_PRIVATE_PEN_UP, 0); @@ -929,10 +966,11 @@ static void tablet_tool_motion(void *data, struct zwp_tablet_tool_v2 *tool, wl_f struct seat *s = ((struct tablet_tool *)data)->seat; struct wayland_surface *w = s->tablet_focus; if (!w) return; - s->tool_pos = device_from_fixed(w, x, y); + s->tool_precise = device_precise(w, x, y); + s->tool_pos = device_round(s->tool_precise); struct tablet_tool *owned = data; - owned->x = wl_fixed_to_double(x) * w->scale_factor; - owned->y = wl_fixed_to_double(y) * w->scale_factor; + owned->x = s->tool_precise.x; + owned->y = s->tool_precise.y; s->tool_motion = true; } @@ -953,7 +991,7 @@ static void tablet_tool_button(void *data, struct zwp_tablet_tool_v2 *tool, default: return; } bool release = state == ZWP_TABLET_TOOL_V2_BUTTON_STATE_RELEASED; - press_queue_push(&s->tool_presses, w, s->tool_pos, b, release); + press_queue_push(&s->tool_presses, w, s->tool_pos, s->tool_precise, b, release); pen_action_push(t, YASL_PRIVATE_PEN_BUTTON, (unsigned)b); } @@ -1032,6 +1070,9 @@ static void tool_frame(void *d, struct zwp_tablet_tool_v2 *t, uint32_t time) if (s->tool_motion) { struct yasl_private_pointer_event ev = like; ev.pos = s->tool_pos; + ev.precise_x = s->tool_precise.x; + ev.precise_y = s->tool_precise.y; + ev.precise_position = true; push_pointer(s, w, YASL_PRIVATE_EVENT_POINTER_MOTION, ev); s->tool_motion = false; } |
