summaryrefslogtreecommitdiff
path: root/src/platform/wayland/pointer.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/platform/wayland/pointer.c')
-rw-r--r--src/platform/wayland/pointer.c85
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;
}