tAdd cursor support (passthrough) - spkp - Stacking wayland compositor
 (HTM) git clone git://git.z3bra.org/spkp.git
 (DIR) Log
 (DIR) Files
 (DIR) Refs
       ---
 (DIR) commit 916113a022defbeb238b7f6e4ae2d34e71c8197e
 (DIR) parent b9c568acf464738c717fc23a11b21c9aad0d21ad
 (HTM) Author: Willy Goiffon <dev@z3bra.org>
       Date:   Mon,  9 Nov 2020 11:14:17 +0100
       
       Add cursor support (passthrough)
       
       Diffstat:
         M compositor.c                        |     213 ++++++++++++++++++++++++-------
       
       1 file changed, 166 insertions(+), 47 deletions(-)
       ---
 (DIR) diff --git a/compositor.c b/compositor.c
       t@@ -33,7 +33,9 @@ struct state {
                struct wlr_renderer *renderer;
                struct wlr_xdg_shell *shell;
                struct wlr_output_layout *layout;
       +
                struct wlr_seat *seat;
       +
                struct wlr_cursor *cursor;
                struct wlr_xcursor_manager *cursor_mgr;
        
       t@@ -41,6 +43,14 @@ struct state {
                struct wl_listener new_output;
                struct wl_listener new_window;
        
       +        /* cursor related events */
       +        struct wl_listener req_cursor;
       +        struct wl_listener motion;
       +        struct wl_listener motion_absolute;
       +        struct wl_listener click;
       +        struct wl_listener scroll;
       +        struct wl_listener paint_cursor;
       +
                struct wl_list outputs;
                struct wl_list windows;
                struct wl_list keyboards;
       t@@ -108,7 +118,14 @@ 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_absolute(struct wl_listener *, void *);
       +static void cb_click(struct wl_listener *, void *);
       +static void cb_scroll(struct wl_listener *, void *);
       +static void cb_paint_cursor(struct wl_listener *, void *);
       +
        static void add_keyboard(struct state *, struct wlr_input_device *);
       +static void add_pointer(struct state *, struct wlr_input_device *);
        static void render(struct wlr_surface *, int, int, void *);
        static int  keybinding(struct state *, uint32_t, uint32_t);
        
       t@@ -119,41 +136,6 @@ usage(char *pgm)
        }
        
        /*
       - * Configure a newly added keyboard
       - */
       -void
       -add_keyboard(struct state *server, struct wlr_input_device *device)
       -{
       -        struct keyboard *kb;
       -        struct xkb_context *context;
       -        struct xkb_keymap *keymap;
       -        struct xkb_rule_names rules = { 0 };
       -
       -        kb = calloc(1, sizeof(*kb));
       -
       -        kb->server = server;
       -        kb->device = device;
       -
       -        context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
       -        keymap = xkb_map_new_from_names(context, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
       -
       -        wlr_keyboard_set_keymap(device->keyboard, keymap);
       -        xkb_keymap_unref(keymap);
       -        xkb_context_unref(context);
       -        wlr_keyboard_set_repeat_info(device->keyboard, 25, 600);
       -
       -        kb->key.notify = cb_kb_key;
       -        kb->modifiers.notify = cb_kb_mod;
       -
       -        wl_signal_add(&device->keyboard->events.key, &kb->key);
       -        wl_signal_add(&device->keyboard->events.modifiers, &kb->modifiers);
       -
       -        wlr_seat_set_keyboard(server->seat, device);
       -
       -        wl_list_insert(&server->keyboards, &kb->link);
       -}
       -
       -/*
         * A new input device is available
         */
        void
       t@@ -168,16 +150,17 @@ cb_new_input(struct wl_listener *listener, void *data)
        
                switch(device->type) {
                case WLR_INPUT_DEVICE_KEYBOARD:
       +                cap |= WL_SEAT_CAPABILITY_KEYBOARD;
                        add_keyboard(server, device);
                        break;
       +        case WLR_INPUT_DEVICE_POINTER:
       +                cap |= WL_SEAT_CAPABILITY_POINTER;
       +                add_pointer(server, device);
       +                break;
                default:
                        break;
                }
        
       -        /* used to notify clients what our seat is capable of */
       -        if (!wl_list_empty(&server->keyboards))
       -                cap |= WL_SEAT_CAPABILITY_KEYBOARD;
       -
                wlr_seat_set_capabilities(server->seat, cap);
        }
        
       t@@ -226,6 +209,8 @@ cb_new_output(struct wl_listener *listener, void *data)
        
                /* create global and arrange outputs from left to right */
                wlr_output_layout_add_auto(server->layout, wlr_output);
       +        wlr_xcursor_manager_load(server->cursor_mgr, 1);
       +        wlr_xcursor_manager_set_cursor_image(server->cursor_mgr, "left_ptr", server->cursor);
        }
        
        /*
       t@@ -348,8 +333,12 @@ cb_map_window(struct wl_listener *listener, void *data)
                /* give window keyboard focus */
                kb = wlr_seat_get_keyboard(server->seat);
                wlr_xdg_toplevel_set_activated(w->surface, true);
       +
                wlr_seat_keyboard_notify_enter(server->seat, w->surface->surface,
                        kb->keycodes, kb->num_keycodes, &kb->modifiers);
       +
       +        wlr_seat_pointer_notify_enter(server->seat, w->surface->surface,
       +                server->cursor->x, server->cursor->y);
        }
        
        /*
       t@@ -427,6 +416,126 @@ cb_kb_key(struct wl_listener *listener, void *data)
                }
        }
        
       +void cb_req_cursor(struct wl_listener *listener, void *data)
       +{
       +        struct state *server;
       +        struct wlr_seat_pointer_request_set_cursor_event *ev;
       +        struct wlr_seat_client *focus;
       +
       +        server = wl_container_of(listener, server, req_cursor);
       +        ev = data;
       +
       +        focus = server->seat->pointer_state.focused_client;
       +        if (focus == ev->seat_client)
       +                wlr_cursor_set_surface(server->cursor, ev->surface, ev->hotspot_x, ev->hotspot_y);
       +}
       +
       +/*
       + * Cursor moved, reporting relative coordinates.
       + */
       +void cb_motion(struct wl_listener *listener, void *data)
       +{
       +        struct state *server;
       +        struct wlr_event_pointer_motion *ev;
       +
       +        server = wl_container_of(listener, server, motion);
       +        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);
       +}
       +
       +void cb_motion_absolute(struct wl_listener *listener, void *data)
       +{
       +        struct state *server;
       +        struct wlr_event_pointer_motion_absolute *ev;
       +
       +        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);
       +}
       +
       +void cb_click(struct wl_listener *listener, void *data)
       +{
       +        struct state *server;
       +        struct wlr_event_pointer_button *ev;
       +
       +        server = wl_container_of(listener, server, click);
       +        ev = data;
       +
       +        wlr_seat_pointer_notify_button(server->seat, ev->time_msec, ev->button, ev->state);
       +}
       +
       +void cb_scroll(struct wl_listener *listener, void *data)
       +{
       +        struct state *server;
       +        struct wlr_event_pointer_axis *ev;
       +
       +        server = wl_container_of(listener, server, scroll);
       +        ev = data;
       +
       +        wlr_seat_pointer_notify_axis(server->seat, ev->time_msec, ev->orientation,
       +                ev->delta, ev->delta_discrete, ev->source);
       +}
       +
       +void cb_paint_cursor(struct wl_listener *listener, void *data)
       +{
       +        struct state *server;
       +
       +        (void)data;
       +
       +        server = wl_container_of(listener, server, paint_cursor);
       +
       +        wlr_seat_pointer_notify_frame(server->seat);
       +}
       +
       +/*
       + * Configure a newly added keyboard
       + */
       +void
       +add_keyboard(struct state *server, struct wlr_input_device *device)
       +{
       +        struct keyboard *kb;
       +        struct xkb_context *context;
       +        struct xkb_keymap *keymap;
       +        struct xkb_rule_names rules = { 0 };
       +
       +        kb = calloc(1, sizeof(*kb));
       +
       +        kb->server = server;
       +        kb->device = device;
       +
       +        context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
       +        keymap = xkb_map_new_from_names(context, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
       +
       +        wlr_keyboard_set_keymap(device->keyboard, keymap);
       +        xkb_keymap_unref(keymap);
       +        xkb_context_unref(context);
       +        wlr_keyboard_set_repeat_info(device->keyboard, 25, 600);
       +
       +        kb->key.notify = cb_kb_key;
       +        kb->modifiers.notify = cb_kb_mod;
       +
       +        wl_signal_add(&device->keyboard->events.key, &kb->key);
       +        wl_signal_add(&device->keyboard->events.modifiers, &kb->modifiers);
       +
       +        wlr_seat_set_keyboard(server->seat, device);
       +
       +        wl_list_insert(&server->keyboards, &kb->link);
       +}
       +
       +/*
       + * Configure a newly added pointer device
       + */
       +void
       +add_pointer(struct state *server, struct wlr_input_device *device)
       +{
       +        /* no special configuration required (eg, accel, …) */
       +        wlr_cursor_attach_input_device(server->cursor, device);
       +}
       +
        void
        render(struct wlr_surface *surface, int x, int y, void *data)
        {
       t@@ -495,6 +604,9 @@ main(int argc, char *argv[])
                server.backend = wlr_backend_autocreate(server.dpy, NULL);
                server.renderer = wlr_backend_get_renderer(server.backend);
        
       +        server.cursor = wlr_cursor_create();
       +        server.cursor_mgr = wlr_xcursor_manager_create(NULL, 24);
       +
                wl_list_init(&server.outputs);
                wl_list_init(&server.windows);
                wl_list_init(&server.keyboards);
       t@@ -502,6 +614,8 @@ main(int argc, char *argv[])
                wl_display_init_shm(server.dpy);
                wlr_renderer_init_wl_display(server.renderer, server.dpy);
        
       +        wlr_cursor_attach_output_layout(server.cursor, server.layout);
       +
                wlr_compositor_create(server.dpy, server.renderer);
                wlr_data_device_manager_create(server.dpy);
        
       t@@ -517,18 +631,23 @@ main(int argc, char *argv[])
                server.new_input.notify = cb_new_input;
                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_absolute.notify = cb_motion_absolute;
       +        server.req_cursor.notify = cb_req_cursor;
       +
                wl_signal_add(&server.backend->events.new_output, &server.new_output);
                wl_signal_add(&server.shell->events.new_surface, &server.new_window);
                wl_signal_add(&server.backend->events.new_input, &server.new_input);
        
       -
       -        /*
       -        server.cursor = wlr_cursor_create();
       -        server.cursor_mgr = wlr_xcursor_manager_create(NULL, 24);
       -
       -        wlr_cursor_attach_output_layout(server.cursor, server.layout);
       -        wlr_xcursor_manager_load(server.cursor_mgr, 1);
       -        */
       +        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_absolute, &server.motion_absolute);
       +        wl_signal_add(&server.seat->events.request_set_cursor, &server.req_cursor);
        
                socket = wl_display_add_socket_auto(server.dpy);
                setenv("WAYLAND_DISPLAY", socket, 1);