tRefactor pointer motion event handling - spkp - Stacking wayland compositor
 (HTM) git clone git://git.z3bra.org/spkp.git
 (DIR) Log
 (DIR) Files
 (DIR) Refs
       ---
 (DIR) commit 1cc098d782f101b0661c607714d621b5cd494fdf
 (DIR) parent 5367b98d9a0350d5a77dcedae2bc48f8e24bb6a5
 (HTM) Author: Willy Goiffon <dev@z3bra.org>
       Date:   Mon,  9 Nov 2020 16:40:56 +0100
       
       Refactor pointer motion event handling
       
       Diffstat:
         M compositor.c                        |     105 +++++++++++++++++++++++---------
       
       1 file changed, 77 insertions(+), 28 deletions(-)
       ---
 (DIR) diff --git a/compositor.c b/compositor.c
       t@@ -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;
       t@@ -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 *);
       t@@ -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)
       t@@ -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)
       t@@ -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[])
        {
       t@@ -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;
        
       t@@ -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);