spkp

Stacking wayland compositor
git clone git://git.z3bra.org/sp:kp.git
Log | Files | Refs

commit 1cc098d782f101b0661c607714d621b5cd494fdf
parent 5367b98d9a0350d5a77dcedae2bc48f8e24bb6a5
Author: Willy Goiffon <dev@z3bra.org>
Date:   Mon,  9 Nov 2020 16:40:56 +0100

Refactor pointer motion event handling

Diffstat:
Mcompositor.c | 105++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------
1 file changed, 77 insertions(+), 28 deletions(-)

diff --git a/compositor.c b/compositor.c @@ -45,7 +45,7 @@ struct state { /* cursor related events */ struct wl_listener req_cursor; - struct wl_listener motion; + struct wl_listener motion_relative; struct wl_listener motion_absolute; struct wl_listener click; struct wl_listener scroll; @@ -118,7 +118,8 @@ static void cb_destroy_window(struct wl_listener *, void *); static void cb_kb_mod(struct wl_listener *, void *); static void cb_kb_key(struct wl_listener *, void *); -static void cb_motion(struct wl_listener *, void *); +static void cb_motion(struct state *, uint32_t); +static void cb_motion_relative(struct wl_listener *, void *); static void cb_motion_absolute(struct wl_listener *, void *); static void cb_click(struct wl_listener *, void *); static void cb_scroll(struct wl_listener *, void *); @@ -130,6 +131,7 @@ static void render(struct wlr_surface *, int, int, void *); static void focus(struct window *, struct wlr_surface *); static int keybinding(struct state *, uint32_t, uint32_t); static struct window *underneath(struct state *, double, double); +static struct wlr_surface *topsurface(struct window *, double, double, double *, double *); void usage(char *pgm) @@ -426,70 +428,106 @@ void cb_req_cursor(struct wl_listener *listener, void *data) wlr_cursor_set_surface(server->cursor, ev->surface, ev->hotspot_x, ev->hotspot_y); } + +void cb_motion(struct state *server, uint32_t time) +{ + double x, y, sx, sy; + struct window *w; + struct wlr_seat *seat; + struct wlr_surface *surface; + + seat = server->seat; + + /* + * reset focus and cursor image when no window is under the + * pointer + */ + w = underneath(server, server->cursor->x, server->cursor->y); + if (!w) { + wlr_seat_pointer_clear_focus(seat); + wlr_xcursor_manager_set_cursor_image(server->cursor_mgr, + "left_ptr", server->cursor); + return; + } + + x = server->cursor->x - w->x; + y = server->cursor->y - w->y; + surface = topsurface(w, x, y, &sx, &sy); + + if (surface) { + if (seat->pointer_state.focused_surface == surface) + wlr_seat_pointer_notify_motion(seat, time, sx, sy); + else + wlr_seat_pointer_notify_enter(seat, surface, sx, sy); + } + + focus(w, w->surface->surface); +} + /* * Cursor moved, reporting relative coordinates. */ -void cb_motion(struct wl_listener *listener, void *data) +void cb_motion_relative(struct wl_listener *listener, void *data) { struct state *server; struct wlr_event_pointer_motion *ev; - struct window *w; - server = wl_container_of(listener, server, motion); + server = wl_container_of(listener, server, motion_relative); ev = data; wlr_cursor_move(server->cursor, ev->device, ev->delta_x, ev->delta_y); - wlr_xcursor_manager_set_cursor_image(server->cursor_mgr, "left_ptr", server->cursor); - - /* activate underneath window, if any */ - if ((w = underneath(server, server->cursor->x, server->cursor->y))) { - focus(w, w->surface->surface); - } else { - wlr_seat_pointer_clear_focus(server->seat); - } + cb_motion(server, ev->time_msec); } void cb_motion_absolute(struct wl_listener *listener, void *data) { struct state *server; struct wlr_event_pointer_motion_absolute *ev; - struct window *w; server = wl_container_of(listener, server, motion_absolute); ev = data; wlr_cursor_warp_absolute(server->cursor, ev->device, ev->x, ev->y); - wlr_xcursor_manager_set_cursor_image(server->cursor_mgr, "left_ptr", server->cursor); - if ((w = underneath(server, server->cursor->x, server->cursor->y))) { - focus(w, w->surface->surface); - } else { - wlr_seat_pointer_clear_focus(server->seat); - } + cb_motion(server, ev->time_msec); } void cb_click(struct wl_listener *listener, void *data) { + double x, y, sx, sy; struct state *server; struct wlr_event_pointer_button *ev; struct window *w; + struct wlr_surface *surface; server = wl_container_of(listener, server, click); ev = data; wlr_seat_pointer_notify_button(server->seat, ev->time_msec, ev->button, ev->state); - if ((w = underneath(server, server->cursor->x, server->cursor->y))) { - /* reinsert window on top of the stack */ - wl_list_remove(&w->link); - wl_list_insert(&server->windows, &w->link); + if (ev->state == WLR_BUTTON_RELEASED) + return; - focus(w, w->surface->surface); - } else { + w = underneath(server, server->cursor->x, server->cursor->y); + if (!w) { wlr_seat_pointer_clear_focus(server->seat); + return; } + /* reinsert window on top of the stack */ + wl_list_remove(&w->link); + wl_list_insert(&server->windows, &w->link); + + x = server->cursor->x - w->x; + y = server->cursor->y - w->y; + surface = topsurface(w, x, y, &sx, &sy); + + if (surface) + wlr_seat_pointer_notify_enter(server->seat, surface, sx, sy); + + focus(w, surface); + } void cb_scroll(struct wl_listener *listener, void *data) @@ -663,6 +701,17 @@ underneath(struct state *server, double x, double y) return NULL; } +struct wlr_surface * +topsurface(struct window *window, double x, double y, double *rx, double *ry) +{ + struct wlr_surface *surface; + + surface = wlr_xdg_surface_surface_at(window->surface, + x - window->x, y - window->y, rx, ry); + + return surface; +} + int main(int argc, char *argv[]) { @@ -716,9 +765,9 @@ main(int argc, char *argv[]) server.new_output.notify = cb_new_output; server.click.notify = cb_click; - server.motion.notify = cb_motion; server.scroll.notify = cb_scroll; server.paint_cursor.notify = cb_paint_cursor; + server.motion_relative.notify = cb_motion_relative; server.motion_absolute.notify = cb_motion_absolute; server.req_cursor.notify = cb_req_cursor; @@ -727,9 +776,9 @@ main(int argc, char *argv[]) wl_signal_add(&server.backend->events.new_input, &server.new_input); wl_signal_add(&server.cursor->events.button, &server.click); - wl_signal_add(&server.cursor->events.motion, &server.motion); wl_signal_add(&server.cursor->events.axis, &server.scroll); wl_signal_add(&server.cursor->events.frame, &server.paint_cursor); + wl_signal_add(&server.cursor->events.motion, &server.motion_relative); wl_signal_add(&server.cursor->events.motion_absolute, &server.motion_absolute); wl_signal_add(&server.seat->events.request_set_cursor, &server.req_cursor);