diff --git a/input/pointer.c b/input/pointer.c new file mode 100644 index 0000000..de0aa6b --- /dev/null +++ b/input/pointer.c @@ -0,0 +1,43 @@ +/* + * Cage: A Wayland kiosk. + * + * Copyright (C) 2018-2020 Jente Hidskes + * Copyright (C) 2019 The Sway authors + * + * See the LICENSE file accompanying this file. + */ + +#include +#include +#include + +#include "pointer.h" + +static void +handle_pointer_destroy(struct wl_listener *listener, void *data) +{ + struct cg_pointer *pointer = wl_container_of(listener, pointer, destroy); + cage_pointer_fini(pointer); +} + +void +cage_pointer_init(struct cg_pointer *pointer, struct wlr_input_device *device) +{ + assert(pointer != NULL); + assert(device != NULL); + + pointer->device = device; + pointer->destroy.notify = handle_pointer_destroy; + wl_signal_add(&device->events.destroy, &pointer->destroy); +} + +void +cage_pointer_fini(struct cg_pointer *pointer) +{ + assert(pointer != NULL); + + wl_list_remove(&pointer->link); + wl_list_remove(&pointer->destroy.link); + + free(pointer); +} diff --git a/input/pointer.h b/input/pointer.h new file mode 100644 index 0000000..7c49e16 --- /dev/null +++ b/input/pointer.h @@ -0,0 +1,17 @@ +#ifndef CG_POINTER_H +#define CG_POINTER_H + +#include +#include + +struct cg_pointer { + struct wl_list link; // seat::pointers + struct wlr_input_device *device; + + struct wl_listener destroy; +}; + +void cage_pointer_init(struct cg_pointer *pointer, struct wlr_input_device *device); +void cage_pointer_fini(struct cg_pointer *pointer); + +#endif diff --git a/input/seat.c b/input/seat.c index 3c4bad4..b68efd1 100644 --- a/input/seat.c +++ b/input/seat.c @@ -9,11 +9,46 @@ #include #include #include +#include #include +#include #include "cursor.h" +#include "pointer.h" #include "seat.h" +void +cage_seat_add_new_pointer(struct cg_seat *seat, struct wlr_input_device *device) +{ + struct cg_pointer *pointer = calloc(1, sizeof(struct cg_pointer)); + if (!pointer) { + wlr_log(WLR_ERROR, "Cannot allocate pointer"); + return; + } + + cage_pointer_init(pointer, device); + wlr_cursor_attach_input_device(seat->cursor->wlr_cursor, device); + wl_list_insert(&seat->pointers, &pointer->link); +} + +void +cage_seat_update_capabilities(struct cg_seat *seat) +{ + uint32_t caps = 0; + + if (!wl_list_empty(&seat->pointers)) { + caps |= WL_SEAT_CAPABILITY_POINTER; + } + wlr_seat_set_capabilities(seat->wlr_seat, caps); + + /* Hide cursor if the seat doesn't have pointer capability. */ + if ((caps & WL_SEAT_CAPABILITY_POINTER) == 0) { + cage_cursor_set_image(seat->cursor, NULL); + } else { + cage_cursor_set_image(seat->cursor, DEFAULT_XCURSOR); + } +} + static void handle_seat_destroy(struct wl_listener *listener, void *user_data) { @@ -33,6 +68,8 @@ cage_seat_init(struct cg_seat *seat, struct wlr_seat *wlr_seat, struct cg_cursor seat->seat_destroy.notify = handle_seat_destroy; wl_signal_add(&seat->wlr_seat->events.destroy, &seat->seat_destroy); + + wl_list_init(&seat->pointers); } void @@ -47,5 +84,10 @@ cage_seat_fini(struct cg_seat *seat) cage_cursor_fini(seat->cursor); + struct cg_pointer *pointer, *pointer_tmp; + wl_list_for_each_safe (pointer, pointer_tmp, &seat->pointers, link) { + cage_pointer_fini(pointer); + } + free(seat); } diff --git a/input/seat.h b/input/seat.h index e08f1bf..2112ffc 100644 --- a/input/seat.h +++ b/input/seat.h @@ -2,6 +2,7 @@ #define CG_SEAT_H #include +#include #include #include "cursor.h" @@ -15,6 +16,8 @@ struct cg_seat { struct wl_list pointers; // cg_pointer::link }; +void cage_seat_add_new_pointer(struct cg_seat *seat, struct wlr_input_device *device); +void cage_seat_update_capabilities(struct cg_seat *seat); void cage_seat_init(struct cg_seat *seat, struct wlr_seat *wlr_seat, struct cg_cursor *cursor); void cage_seat_fini(struct cg_seat *seat); diff --git a/meson.build b/meson.build index 14ebdb9..af3dcc3 100644 --- a/meson.build +++ b/meson.build @@ -130,6 +130,7 @@ cageng_sources = [ 'desktop/view.c', 'desktop/xdg_shell.c', 'input/cursor.c', + 'input/pointer.c', 'input/seat.c', 'cageng.c', ] @@ -144,6 +145,7 @@ cageng_headers = [ 'desktop/view.h', 'desktop/xdg_shell.h', 'input/cursor.h', + 'input/pointer.h', 'input/seat.h', 'serverng.h', ]