tRefactor mouse click events handling - spkp - Stacking wayland compositor
 (HTM) git clone git://git.z3bra.org/spkp.git
 (DIR) Log
 (DIR) Files
 (DIR) Refs
       ---
 (DIR) commit a8b09a56046536686e6a00db338d02e08d5fb05d
 (DIR) parent 08dafffce80305abfea7da9365ac9850f4b7f8c1
 (HTM) Author: Willy Goiffon <dev@z3bra.org>
       Date:   Sun, 15 Nov 2020 16:02:04 +0100
       
       Refactor mouse click events handling
       
       Diffstat:
         M config.def.h                        |       2 ++
         M sp:kp.c                             |     150 +++++++++++++++++++-------------
       
       2 files changed, 92 insertions(+), 60 deletions(-)
       ---
 (DIR) diff --git a/config.def.h b/config.def.h
       t@@ -18,3 +18,5 @@ struct key keys[] = {
                { LOGO     , XKB_KEY_Return, kb_exec     , {.v = "alacritty"} },
                { LOGO     , XKB_KEY_d     , kb_desktop  , {0     } },
        };
       +
       +xkb_mod_mask_t mousemod = LOGO;
 (DIR) diff --git a/sp:kp.c b/sp:kp.c
       t@@ -188,6 +188,8 @@ 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_click_press(struct state *, struct wlr_event_pointer_button *);
       +static void cb_click_release(struct state *, struct wlr_event_pointer_button *);
        static void cb_scroll(struct wl_listener *, void *);
        static void cb_paint_cursor(struct wl_listener *, void *);
        
       t@@ -700,56 +702,82 @@ cb_click(struct wl_listener *listener, void *data)
        {
                struct state *server;
                struct wlr_event_pointer_button *ev;
       -        struct window *w;
       -        struct wlr_keyboard *kb;
       -        struct wlr_box geom;
        
                server = wl_container_of(listener, server, click);
       -        kb = wlr_seat_get_keyboard(server->seat);
                ev = data;
        
       -        if (ev->state == WLR_BUTTON_RELEASED) {
       -                switch(server->grabmode) {
       -                case MOVE:
       -                case TELEPORT:
       -                        server->grabbed->x = server->grabbox.x;
       -                        server->grabbed->y = server->grabbox.y;
       -                        if (server->grabmode == MOVE)
       -                                break;
       -                        /* FALLTHROUGH */
       -                case RESIZE:
       -                        geom.width = server->grabbox.width;
       -                        geom.height = server->grabbox.height;
       -                        wlr_xdg_toplevel_set_size(server->grabbed->toplevel, geom.width, geom.height);
       -                        break;
       -                case NORMAL:
       -                        /* pass down event when not grabbing a window */
       -                        wlr_seat_pointer_notify_button(server->seat,
       -                                        ev->time_msec, ev->button, ev->state);
       +        switch (ev->state) {
       +        case WLR_BUTTON_RELEASED:
       +                cb_click_release(server, ev);
       +                break;
       +        case WLR_BUTTON_PRESSED:
       +                cb_click_press(server, ev);
       +                break;
       +        }
       +}
       +
       +/*
       + * Mouse button was released. There are only 2 different use cases:
       + * either we where grabbing a window to move/resize it, or not.
       + * In the first case, it means the operation is over, so me must
       + * move/resize the window.
       + * When it's not, the event is simply passed down to the focused window.
       + */
       +void
       +cb_click_release(struct state *server, struct wlr_event_pointer_button *ev)
       +{
       +        struct wlr_box geom;
       +
       +        switch(server->grabmode) {
       +        case TELEPORT:
       +        case RESIZE:
       +                geom.width = server->grabbox.width;
       +                geom.height = server->grabbox.height;
       +                wlr_xdg_toplevel_set_size(server->grabbed->toplevel, geom.width, geom.height);
       +                /* FALLTHROUGH */
       +        case MOVE:
       +                server->grabbed->x = server->grabbox.x;
       +                server->grabbed->y = server->grabbox.y;
       +                break;
       +
       +        default:
       +                /* pass down event when not grabbing a window */
       +                wlr_seat_pointer_notify_button(server->seat,
       +                                ev->time_msec, ev->button, ev->state);
        
       -                }
       -                server->grabmode = NORMAL;
       -                return;
                }
        
       +        server->grabmode = NORMAL;
       +}
        
       -        if (kb->modifiers.depressed & WLR_MODIFIER_LOGO && ev->button == BTN_MIDDLE) {
       -                server->grabmode = TELEPORT;
       -                server->grabbox.x = server->cursor->x;
       -                server->grabbox.y = server->cursor->y;
       -                server->grabbox.width = 1;
       -                server->grabbox.height = 1;
       +/*
       + * Mouse button was pressed. If the modifier key is held down, we enter
       + * the "grab mode", which will move and/or resize the clicked or focused
       + * window, and will terminate when the button is released.
       + */
       +void
       +cb_click_press(struct state *server, struct wlr_event_pointer_button *ev)
       +{
       +        struct window *w;
       +        struct wlr_keyboard *kb;
       +        struct wlr_box geom;
       +
       +        /* Ignore all press events when a window is grabbed */
       +        if (server->grabmode != NORMAL)
                        return;
       -        }
        
       -        /* stop processing if no window is under the cursor */
       -        if (!(w = underneath(server, server->cursor->x, server->cursor->y)))
       +        kb = wlr_seat_get_keyboard(server->seat);
       +
       +        if (kb->modifiers.depressed != mousemod) {
       +                wlr_seat_pointer_notify_button(server->seat,
       +                        ev->time_msec, ev->button, ev->state);
                        return;
       +        }
        
       -        if ((w->area == BORDER || (kb->modifiers.depressed & WLR_MODIFIER_LOGO))
       -         && ev->state == WLR_BUTTON_PRESSED
       -         && server->grabmode == NORMAL) {
       +        w = underneath(server, server->cursor->x, server->cursor->y);
        
       +        /* pass down event when not grabbing a window */
       +        if (w) {
                        /*
                         * Save which window was clicked, and the coordinates
                         * of the event on that surface.
       t@@ -760,31 +788,33 @@ cb_click(struct wl_listener *listener, void *data)
                        server->grabbox.x = w->x;
                        server->grabbox.y = w->y;
        
       -                switch (ev->button) {
       -                case BTN_LEFT:
       -                        wlr_xdg_surface_get_geometry(w->toplevel, &geom);
       -                        server->grabbox.width = geom.width;
       -                        server->grabbox.height = geom.height;
       -                        server->grabmode = MOVE;
       -                        break;
       -                case BTN_RIGHT:
       -                        server->grabmode = RESIZE;
       -                        server->grabbox.width = w->sx + 2 * bordersize;
       -                        server->grabbox.height = w->sy + 2 * bordersize;
       -                        break;
       -                }
       -        }
       -
       -        /* pass down event when not grabbing a window */
       -        if (server->grabmode == NORMAL)
       -                wlr_seat_pointer_notify_button(server->seat,
       -                        ev->time_msec, ev->button, ev->state);
       +                /* bring window to the front */
       +                wl_list_remove(&w->link);
       +                wl_list_insert(&server->windows, &w->link);
        
       -        /* bring window to the front */
       -        wl_list_remove(&w->link);
       -        wl_list_insert(&server->windows, &w->link);
       +                focus(w);
       +        }
        
       -        focus(w);
       +        switch (ev->button) {
       +        case BTN_MIDDLE:
       +                server->grabmode = TELEPORT;
       +                server->grabbox.x = server->cursor->x;
       +                server->grabbox.y = server->cursor->y;
       +                server->grabbox.width = 1;
       +                server->grabbox.height = 1;
       +                break;
       +        case BTN_LEFT:
       +                wlr_xdg_surface_get_geometry(w->toplevel, &geom);
       +                server->grabmode = MOVE;
       +                server->grabbox.width = geom.width;
       +                server->grabbox.height = geom.height;
       +                break;
       +        case BTN_RIGHT:
       +                server->grabmode = RESIZE;
       +                server->grabbox.width = w->sx + 2 * bordersize;
       +                server->grabbox.height = w->sy + 2 * bordersize;
       +                break;
       +        }
        }
        
        /*