spkp

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

commit 916113a022defbeb238b7f6e4ae2d34e71c8197e
parent b9c568acf464738c717fc23a11b21c9aad0d21ad
Author: Willy Goiffon <dev@z3bra.org>
Date:   Mon,  9 Nov 2020 11:14:17 +0100

Add cursor support (passthrough)

Diffstat:
Mcompositor.c | 213+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------
1 file changed, 166 insertions(+), 47 deletions(-)

diff --git a/compositor.c b/compositor.c @@ -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; @@ -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; @@ -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); @@ -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 @@ -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); } @@ -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); } /* @@ -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); } /* @@ -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) { @@ -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); @@ -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); @@ -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);