From 192bc1429a3072f57cb3b32f4b91078dac28ce0c Mon Sep 17 00:00:00 2001 From: nia Date: Thu, 20 Feb 2020 22:36:54 +0000 Subject: [PATCH 1/2] seat: Move common code to new seat.c, old seat.c becomes seat-linux.c --- libswc/local.mk | 3 +- libswc/seat-linux.c | 387 +++++++++++++++++++++++++++++++++++++++++++ libswc/seat-ws.c | 72 +------- libswc/seat.c | 391 ++------------------------------------------ libswc/seat.h | 8 + 5 files changed, 418 insertions(+), 443 deletions(-) create mode 100644 libswc/seat-linux.c diff --git a/libswc/local.mk b/libswc/local.mk index 1493172..29324fb 100644 --- a/libswc/local.mk +++ b/libswc/local.mk @@ -41,6 +41,7 @@ SWC_SOURCES = \ libswc/pointer.c \ libswc/primary_plane.c \ libswc/region.c \ + libswc/seat.c \ libswc/screen.c \ libswc/shell.c \ libswc/shell_surface.c \ @@ -65,7 +66,7 @@ SWC_SOURCES = \ ifeq ($(shell uname),NetBSD) SWC_SOURCES += libswc/seat-ws.c else - SWC_SOURCES += libswc/seat.c + SWC_SOURCES += libswc/seat-linux.c $(dir)_PACKAGES += libinput ifeq ($(ENABLE_LIBUDEV),1) $(dir)_CFLAGS += -DENABLE_LIBUDEV diff --git a/libswc/seat-linux.c b/libswc/seat-linux.c new file mode 100644 index 0000000..647e6bc --- /dev/null +++ b/libswc/seat-linux.c @@ -0,0 +1,387 @@ +/* swc: libswc/seat-linux.c + * + * Copyright (c) 2013-2020 Michael Forney + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "seat.h" +#include "compositor.h" +#include "data_device.h" +#include "event.h" +#include "internal.h" +#include "keyboard.h" +#include "launch.h" +#include "pointer.h" +#include "screen.h" +#include "surface.h" +#include "util.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#ifdef ENABLE_LIBUDEV +# include +#endif + +struct seat { + struct swc_seat base; + + char *name; + uint32_t capabilities; + + struct libinput *libinput; + struct wl_event_source *libinput_source; + +#ifdef ENABLE_LIBUDEV + struct udev *udev; +#endif + + struct wl_listener swc_listener; + + struct pointer pointer; + + struct wl_global *global; + struct wl_list resources; +}; + +static void +handle_swc_event(struct wl_listener *listener, void *data) +{ + struct seat *seat = wl_container_of(listener, seat, swc_listener); + struct event *ev = data; + + switch (ev->type) { + case SWC_EVENT_DEACTIVATED: + libinput_suspend(seat->libinput); + keyboard_reset(seat->base.keyboard); + break; + case SWC_EVENT_ACTIVATED: + if (libinput_resume(seat->libinput) != 0) + WARNING("Failed to resume libinput context\n"); + break; + } +} + +static void +bind_seat(struct wl_client *client, void *data, uint32_t version, uint32_t id) +{ + struct seat *seat = data; + struct wl_resource *resource; + + resource = wl_resource_create(client, &wl_seat_interface, version, id); + if (!resource) { + wl_client_post_no_memory(client); + return; + } + wl_resource_set_implementation(resource, &seat_impl, seat, &remove_resource); + wl_list_insert(&seat->resources, wl_resource_get_link(resource)); + + if (version >= 2) + wl_seat_send_name(resource, seat->name); + + wl_seat_send_capabilities(resource, seat->capabilities); +} + +static void +update_capabilities(struct seat *seat, uint32_t capabilities) +{ + struct wl_resource *resource; + + if (!(~seat->capabilities & capabilities)) + return; + + seat->capabilities |= capabilities; + wl_list_for_each(resource, &seat->resources, link) + wl_seat_send_capabilities(resource, seat->capabilities); +} + +static int +open_restricted(const char *path, int flags, void *user_data) +{ + return launch_open_device(path, flags); +} + +static void +close_restricted(int fd, void *user_data) +{ + close(fd); +} + +const struct libinput_interface libinput_interface = { + .open_restricted = open_restricted, + .close_restricted = close_restricted, +}; + +static uint32_t +device_capabilities(struct libinput_device *device) +{ + uint32_t capabilities = 0; + + if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_KEYBOARD)) + capabilities |= WL_SEAT_CAPABILITY_KEYBOARD; + if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_POINTER)) + capabilities |= WL_SEAT_CAPABILITY_POINTER; + /* TODO: Add touch device support + * if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_TOUCH)) + * capabilities |= WL_SEAT_CAPABILITY_TOUCH; + */ + + return capabilities; +} + +static void +handle_libinput_axis_event(struct seat *seat, struct libinput_event_pointer *event, enum libinput_pointer_axis axis) +{ + wl_fixed_t amount; + + if (!libinput_event_pointer_has_axis(event, axis)) + return; + + amount = wl_fixed_from_double(libinput_event_pointer_get_axis_value(event, axis)); + pointer_handle_axis(&seat->pointer, libinput_event_pointer_get_time(event), axis, amount); +} + +static int +handle_libinput_data(int fd, uint32_t mask, void *data) +{ + struct seat *seat = data; + struct screen *screen; + struct swc_rectangle *rect; + struct libinput_event *generic_event; + struct libinput_device *device; + union { + struct libinput_event_keyboard *k; + struct libinput_event_pointer *p; + } event; + wl_fixed_t x, y; + uint32_t time, key, state; + + if (libinput_dispatch(seat->libinput) != 0) { + WARNING("libinput_dispatch failed: %s\n", strerror(errno)); + return 0; + } + + while ((generic_event = libinput_get_event(seat->libinput))) { + switch (libinput_event_get_type(generic_event)) { + case LIBINPUT_EVENT_DEVICE_ADDED: + device = libinput_event_get_device(generic_event); + update_capabilities(seat, device_capabilities(device)); + if (swc.manager->new_device) + swc.manager->new_device(device); + break; + case LIBINPUT_EVENT_KEYBOARD_KEY: + event.k = libinput_event_get_keyboard_event(generic_event); + time = libinput_event_keyboard_get_time(event.k); + key = libinput_event_keyboard_get_key(event.k); + state = libinput_event_keyboard_get_key_state(event.k); + keyboard_handle_key(seat->base.keyboard, time, key, state); + break; + case LIBINPUT_EVENT_POINTER_MOTION: + event.p = libinput_event_get_pointer_event(generic_event); + time = libinput_event_pointer_get_time(event.p); + x = wl_fixed_from_double(libinput_event_pointer_get_dx(event.p)); + y = wl_fixed_from_double(libinput_event_pointer_get_dy(event.p)); + pointer_handle_relative_motion(&seat->pointer, time, x, y); + break; + case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE: + screen = wl_container_of(swc.screens.next, screen, link); + rect = &screen->base.geometry; + event.p = libinput_event_get_pointer_event(generic_event); + time = libinput_event_pointer_get_time(event.p); + x = wl_fixed_from_double(libinput_event_pointer_get_absolute_x_transformed(event.p, rect->width)); + y = wl_fixed_from_double(libinput_event_pointer_get_absolute_y_transformed(event.p, rect->height)); + pointer_handle_absolute_motion(&seat->pointer, time, x, y); + break; + case LIBINPUT_EVENT_POINTER_BUTTON: + event.p = libinput_event_get_pointer_event(generic_event); + time = libinput_event_pointer_get_time(event.p); + key = libinput_event_pointer_get_button(event.p); + state = libinput_event_pointer_get_button_state(event.p); + pointer_handle_button(&seat->pointer, time, key, state); + if (state == LIBINPUT_BUTTON_STATE_PRESSED) { + /* qemu generates GEAR_UP/GEAR_DOWN events on scroll, so pass + * those through as axis events. */ + switch (key) { + case BTN_GEAR_DOWN: + pointer_handle_axis(&seat->pointer, time, WL_POINTER_AXIS_VERTICAL_SCROLL, wl_fixed_from_int(10)); + break; + case BTN_GEAR_UP: + pointer_handle_axis(&seat->pointer, time, WL_POINTER_AXIS_VERTICAL_SCROLL, wl_fixed_from_int(-10)); + break; + } + } + break; + case LIBINPUT_EVENT_POINTER_AXIS: + event.p = libinput_event_get_pointer_event(generic_event); + handle_libinput_axis_event(seat, event.p, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL); + handle_libinput_axis_event(seat, event.p, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL); + break; + default: + break; + } + + libinput_event_destroy(generic_event); + } + + return 0; +} + +bool +initialize_libinput(struct seat *seat) +{ +#ifdef ENABLE_LIBUDEV + if (!(seat->udev = udev_new())) { + ERROR("Could not create udev context\n"); + goto error0; + } + + seat->libinput = libinput_udev_create_context(&libinput_interface, NULL, seat->udev); +#else + seat->libinput = libinput_netlink_create_context(&libinput_interface, NULL); +#endif + + if (!seat->libinput) { + ERROR("Could not create libinput context\n"); + goto error1; + } + +#ifdef ENABLE_LIBUDEV + if (libinput_udev_assign_seat(seat->libinput, seat->name) != 0) { + ERROR("Failed to assign seat to libinput context\n"); + goto error2; + } +#else + if (libinput_netlink_assign_seat(seat->libinput, seat->name) != 0) { + ERROR("Failed to assign seat to libinput context\n"); + goto error2; + } +#endif + + seat->libinput_source = wl_event_loop_add_fd(swc.event_loop, libinput_get_fd(seat->libinput), WL_EVENT_READABLE, &handle_libinput_data, seat); + if (!seat->libinput_source) { + ERROR("Could not create event source for libinput\n"); + goto error2; + } + + if (!swc.active) + libinput_suspend(seat->libinput); + + return true; + +error2: + libinput_unref(seat->libinput); +error1: +#ifdef ENABLE_LIBUDEV + udev_unref(seat->udev); +error0: +#endif + return false; +} + +struct swc_seat * +seat_create(struct wl_display *display, const char *seat_name) +{ + struct seat *seat; + + seat = malloc(sizeof(*seat)); + if (!seat) + goto error0; + seat->name = strdup(seat_name); + if (!seat->name) { + ERROR("Could not allocate seat name string\n"); + goto error1; + } + seat->global = wl_global_create(display, &wl_seat_interface, 4, seat, &bind_seat); + if (!seat->global) + goto error2; + seat->capabilities = 0; + wl_list_init(&seat->resources); + + seat->swc_listener.notify = &handle_swc_event; + wl_signal_add(&swc.event_signal, &seat->swc_listener); + + seat->base.data_device = data_device_create(); + if (!seat->base.data_device) { + ERROR("Could not initialize data device\n"); + goto error3; + } + seat->base.data_device_listener.notify = &seat_handle_data_device_event; + wl_signal_add(&seat->base.data_device->event_signal, &seat->base.data_device_listener); + + seat->base.keyboard = keyboard_create(NULL); + if (!seat->base.keyboard) { + ERROR("Could not initialize keyboard\n"); + goto error4; + } + seat->base.keyboard_focus_listener.notify = &seat_handle_keyboard_focus_event; + wl_signal_add(&seat->base.keyboard->focus.event_signal, &seat->base.keyboard_focus_listener); + + if (!pointer_initialize(&seat->pointer)) { + ERROR("Could not initialize pointer\n"); + goto error5; + } + seat->base.pointer = &seat->pointer; + + if (!initialize_libinput(seat)) + goto error6; + + return &seat->base; + +error6: + pointer_finalize(&seat->pointer); +error5: + keyboard_destroy(seat->base.keyboard); +error4: + data_device_destroy(seat->base.data_device); +error3: + wl_global_destroy(seat->global); +error2: + free(seat->name); +error1: + free(seat); +error0: + return NULL; +} + +void +seat_destroy(struct swc_seat *seat_base) +{ + struct seat *seat = wl_container_of(seat_base, seat, base); + + wl_event_source_remove(seat->libinput_source); + libinput_unref(seat->libinput); +#ifdef ENABLE_LIBUDEV + udev_unref(seat->udev); +#endif + + pointer_finalize(&seat->pointer); + keyboard_destroy(seat->base.keyboard); + data_device_destroy(seat->base.data_device); + + wl_global_destroy(seat->global); + free(seat->name); + free(seat); +} diff --git a/libswc/seat-ws.c b/libswc/seat-ws.c index 75d0bb5..85120cf 100644 --- a/libswc/seat-ws.c +++ b/libswc/seat-ws.c @@ -1,7 +1,7 @@ /* swc: libswc/seat-ws.c * * Copyright (c) 2013, 2014 Michael Forney - * Copyright (c) 2019 Nia Alarie + * Copyright (c) 2019, 2020 Nia Alarie * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -95,45 +95,12 @@ struct seat { struct wl_listener swc_listener; - struct wl_listener keyboard_focus_listener; struct pointer pointer; - struct wl_listener data_device_listener; struct wl_global *global; struct wl_list resources; }; -static void -handle_keyboard_focus_event(struct wl_listener *listener, void *data) -{ - struct seat *seat = wl_container_of(listener, seat, keyboard_focus_listener); - struct event *ev = data; - struct input_focus_event_data *event_data = ev->data; - - if (ev->type != INPUT_FOCUS_EVENT_CHANGED) - return; - - if (event_data->new) { - struct wl_client *client = wl_resource_get_client(event_data->new->surface->resource); - - /* Offer the selection to the new focus. */ - data_device_offer_selection(seat->base.data_device, client); - } -} - -static void -handle_data_device_event(struct wl_listener *listener, void *data) -{ - struct seat *seat = wl_container_of(listener, seat, data_device_listener); - struct event *ev = data; - - if (ev->type != DATA_DEVICE_EVENT_SELECTION_CHANGED) - return; - - if (seat->base.keyboard->focus.client) - data_device_offer_selection(seat->base.data_device, seat->base.keyboard->focus.client); -} - static void handle_swc_event(struct wl_listener *listener, void *data) { @@ -151,35 +118,6 @@ handle_swc_event(struct wl_listener *listener, void *data) } } -/* Wayland Seat Interface */ -static void -get_pointer(struct wl_client *client, struct wl_resource *resource, uint32_t id) -{ - struct seat *seat = wl_resource_get_user_data(resource); - - pointer_bind(&seat->pointer, client, wl_resource_get_version(resource), id); -} - -static void -get_keyboard(struct wl_client *client, struct wl_resource *resource, uint32_t id) -{ - struct seat *seat = wl_resource_get_user_data(resource); - - keyboard_bind(seat->base.keyboard, client, wl_resource_get_version(resource), id); -} - -static void -get_touch(struct wl_client *client, struct wl_resource *resource, uint32_t id) -{ - /* XXX: Implement */ -} - -static struct wl_seat_interface seat_impl = { - .get_pointer = get_pointer, - .get_keyboard = get_keyboard, - .get_touch = get_touch, -}; - static void bind_seat(struct wl_client *client, void *data, uint32_t version, uint32_t id) { @@ -389,16 +327,16 @@ seat_create(struct wl_display *display, const char *seat_name) ERROR("Could not initialize data device\n"); goto error3; } - seat->data_device_listener.notify = &handle_data_device_event; - wl_signal_add(&seat->base.data_device->event_signal, &seat->data_device_listener); + seat->base.data_device_listener.notify = &seat_handle_data_device_event; + wl_signal_add(&seat->base.data_device->event_signal, &seat->base.data_device_listener); seat->base.keyboard = keyboard_create(&seat->names); if (!seat->base.keyboard) { ERROR("Could not initialize keyboard\n"); goto error4; } - seat->keyboard_focus_listener.notify = handle_keyboard_focus_event; - wl_signal_add(&seat->base.keyboard->focus.event_signal, &seat->keyboard_focus_listener); + seat->base.keyboard_focus_listener.notify = &seat_handle_keyboard_focus_event; + wl_signal_add(&seat->base.keyboard->focus.event_signal, &seat->base.keyboard_focus_listener); if (!pointer_initialize(&seat->pointer)) { ERROR("Could not initialize pointer\n"); diff --git a/libswc/seat.c b/libswc/seat.c index 54c46c3..240cfa4 100644 --- a/libswc/seat.c +++ b/libswc/seat.c @@ -20,59 +20,19 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ - #include "seat.h" #include "compositor.h" #include "data_device.h" #include "event.h" -#include "internal.h" #include "keyboard.h" -#include "launch.h" #include "pointer.h" -#include "screen.h" #include "surface.h" -#include "util.h" - -#include -#include -#include -#include -#include -#include - -#include -#include -#ifdef ENABLE_LIBUDEV -# include -#endif - -struct seat { - struct swc_seat base; - - char *name; - uint32_t capabilities; - - struct libinput *libinput; - struct wl_event_source *libinput_source; - -#ifdef ENABLE_LIBUDEV - struct udev *udev; -#endif +#include - struct wl_listener swc_listener; - - struct wl_listener keyboard_focus_listener; - struct pointer pointer; - struct wl_listener data_device_listener; - - struct wl_global *global; - struct wl_list resources; -}; - -static void -handle_keyboard_focus_event(struct wl_listener *listener, void *data) +void +seat_handle_keyboard_focus_event(struct wl_listener *listener, void *data) { - struct seat *seat = wl_container_of(listener, seat, keyboard_focus_listener); + struct swc_seat *seat = wl_container_of(listener, seat, keyboard_focus_listener); struct event *ev = data; struct input_focus_event_data *event_data = ev->data; @@ -83,58 +43,39 @@ handle_keyboard_focus_event(struct wl_listener *listener, void *data) struct wl_client *client = wl_resource_get_client(event_data->new->surface->resource); /* Offer the selection to the new focus. */ - data_device_offer_selection(seat->base.data_device, client); + data_device_offer_selection(seat->data_device, client); } } -static void -handle_data_device_event(struct wl_listener *listener, void *data) +void +seat_handle_data_device_event(struct wl_listener *listener, void *data) { - struct seat *seat = wl_container_of(listener, seat, data_device_listener); + struct swc_seat *seat = wl_container_of(listener, seat, data_device_listener); struct event *ev = data; if (ev->type != DATA_DEVICE_EVENT_SELECTION_CHANGED) return; - if (seat->base.keyboard->focus.client) - data_device_offer_selection(seat->base.data_device, seat->base.keyboard->focus.client); -} - -static void -handle_swc_event(struct wl_listener *listener, void *data) -{ - struct seat *seat = wl_container_of(listener, seat, swc_listener); - struct event *ev = data; - - switch (ev->type) { - case SWC_EVENT_DEACTIVATED: - libinput_suspend(seat->libinput); - keyboard_reset(seat->base.keyboard); - break; - case SWC_EVENT_ACTIVATED: - if (libinput_resume(seat->libinput) != 0) - WARNING("Failed to resume libinput context\n"); - break; - } + if (seat->keyboard->focus.client) + data_device_offer_selection(seat->data_device, seat->keyboard->focus.client); } /* Wayland Seat Interface */ + static void get_pointer(struct wl_client *client, struct wl_resource *resource, uint32_t id) { - struct seat *seat = wl_resource_get_user_data(resource); + struct swc_seat *seat = wl_resource_get_user_data(resource); - if (!pointer_bind(&seat->pointer, client, wl_resource_get_version(resource), id)) - wl_resource_post_no_memory(resource); + pointer_bind(seat->pointer, client, wl_resource_get_version(resource), id); } static void get_keyboard(struct wl_client *client, struct wl_resource *resource, uint32_t id) { - struct seat *seat = wl_resource_get_user_data(resource); + struct swc_seat *seat = wl_resource_get_user_data(resource); - if (!keyboard_bind(seat->base.keyboard, client, wl_resource_get_version(resource), id)) - wl_resource_post_no_memory(resource); + keyboard_bind(seat->keyboard, client, wl_resource_get_version(resource), id); } static void @@ -143,309 +84,9 @@ get_touch(struct wl_client *client, struct wl_resource *resource, uint32_t id) /* XXX: Implement */ } -static const struct wl_seat_interface seat_impl = { +struct wl_seat_interface seat_impl = { .get_pointer = get_pointer, .get_keyboard = get_keyboard, .get_touch = get_touch, }; -static void -bind_seat(struct wl_client *client, void *data, uint32_t version, uint32_t id) -{ - struct seat *seat = data; - struct wl_resource *resource; - - resource = wl_resource_create(client, &wl_seat_interface, version, id); - if (!resource) { - wl_client_post_no_memory(client); - return; - } - wl_resource_set_implementation(resource, &seat_impl, seat, &remove_resource); - wl_list_insert(&seat->resources, wl_resource_get_link(resource)); - - if (version >= 2) - wl_seat_send_name(resource, seat->name); - - wl_seat_send_capabilities(resource, seat->capabilities); -} - -static void -update_capabilities(struct seat *seat, uint32_t capabilities) -{ - struct wl_resource *resource; - - if (!(~seat->capabilities & capabilities)) - return; - - seat->capabilities |= capabilities; - wl_list_for_each(resource, &seat->resources, link) - wl_seat_send_capabilities(resource, seat->capabilities); -} - -static int -open_restricted(const char *path, int flags, void *user_data) -{ - return launch_open_device(path, flags); -} - -static void -close_restricted(int fd, void *user_data) -{ - close(fd); -} - -const struct libinput_interface libinput_interface = { - .open_restricted = open_restricted, - .close_restricted = close_restricted, -}; - -static uint32_t -device_capabilities(struct libinput_device *device) -{ - uint32_t capabilities = 0; - - if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_KEYBOARD)) - capabilities |= WL_SEAT_CAPABILITY_KEYBOARD; - if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_POINTER)) - capabilities |= WL_SEAT_CAPABILITY_POINTER; - /* TODO: Add touch device support - * if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_TOUCH)) - * capabilities |= WL_SEAT_CAPABILITY_TOUCH; - */ - - return capabilities; -} - -static void -handle_libinput_axis_event(struct seat *seat, struct libinput_event_pointer *event, enum libinput_pointer_axis axis) -{ - wl_fixed_t amount; - - if (!libinput_event_pointer_has_axis(event, axis)) - return; - - amount = wl_fixed_from_double(libinput_event_pointer_get_axis_value(event, axis)); - pointer_handle_axis(&seat->pointer, libinput_event_pointer_get_time(event), axis, amount); -} - -static int -handle_libinput_data(int fd, uint32_t mask, void *data) -{ - struct seat *seat = data; - struct screen *screen; - struct swc_rectangle *rect; - struct libinput_event *generic_event; - struct libinput_device *device; - union { - struct libinput_event_keyboard *k; - struct libinput_event_pointer *p; - } event; - wl_fixed_t x, y; - uint32_t time, key, state; - - if (libinput_dispatch(seat->libinput) != 0) { - WARNING("libinput_dispatch failed: %s\n", strerror(errno)); - return 0; - } - - while ((generic_event = libinput_get_event(seat->libinput))) { - switch (libinput_event_get_type(generic_event)) { - case LIBINPUT_EVENT_DEVICE_ADDED: - device = libinput_event_get_device(generic_event); - update_capabilities(seat, device_capabilities(device)); - if (swc.manager->new_device) - swc.manager->new_device(device); - break; - case LIBINPUT_EVENT_KEYBOARD_KEY: - event.k = libinput_event_get_keyboard_event(generic_event); - time = libinput_event_keyboard_get_time(event.k); - key = libinput_event_keyboard_get_key(event.k); - state = libinput_event_keyboard_get_key_state(event.k); - keyboard_handle_key(seat->base.keyboard, time, key, state); - break; - case LIBINPUT_EVENT_POINTER_MOTION: - event.p = libinput_event_get_pointer_event(generic_event); - time = libinput_event_pointer_get_time(event.p); - x = wl_fixed_from_double(libinput_event_pointer_get_dx(event.p)); - y = wl_fixed_from_double(libinput_event_pointer_get_dy(event.p)); - pointer_handle_relative_motion(&seat->pointer, time, x, y); - break; - case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE: - screen = wl_container_of(swc.screens.next, screen, link); - rect = &screen->base.geometry; - event.p = libinput_event_get_pointer_event(generic_event); - time = libinput_event_pointer_get_time(event.p); - x = wl_fixed_from_double(libinput_event_pointer_get_absolute_x_transformed(event.p, rect->width)); - y = wl_fixed_from_double(libinput_event_pointer_get_absolute_y_transformed(event.p, rect->height)); - pointer_handle_absolute_motion(&seat->pointer, time, x, y); - break; - case LIBINPUT_EVENT_POINTER_BUTTON: - event.p = libinput_event_get_pointer_event(generic_event); - time = libinput_event_pointer_get_time(event.p); - key = libinput_event_pointer_get_button(event.p); - state = libinput_event_pointer_get_button_state(event.p); - pointer_handle_button(&seat->pointer, time, key, state); - if (state == LIBINPUT_BUTTON_STATE_PRESSED) { - /* qemu generates GEAR_UP/GEAR_DOWN events on scroll, so pass - * those through as axis events. */ - switch (key) { - case BTN_GEAR_DOWN: - pointer_handle_axis(&seat->pointer, time, WL_POINTER_AXIS_VERTICAL_SCROLL, wl_fixed_from_int(10)); - break; - case BTN_GEAR_UP: - pointer_handle_axis(&seat->pointer, time, WL_POINTER_AXIS_VERTICAL_SCROLL, wl_fixed_from_int(-10)); - break; - } - } - break; - case LIBINPUT_EVENT_POINTER_AXIS: - event.p = libinput_event_get_pointer_event(generic_event); - handle_libinput_axis_event(seat, event.p, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL); - handle_libinput_axis_event(seat, event.p, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL); - break; - default: - break; - } - - libinput_event_destroy(generic_event); - } - - return 0; -} - -bool -initialize_libinput(struct seat *seat) -{ -#ifdef ENABLE_LIBUDEV - if (!(seat->udev = udev_new())) { - ERROR("Could not create udev context\n"); - goto error0; - } - - seat->libinput = libinput_udev_create_context(&libinput_interface, NULL, seat->udev); -#else - seat->libinput = libinput_netlink_create_context(&libinput_interface, NULL); -#endif - - if (!seat->libinput) { - ERROR("Could not create libinput context\n"); - goto error1; - } - -#ifdef ENABLE_LIBUDEV - if (libinput_udev_assign_seat(seat->libinput, seat->name) != 0) { - ERROR("Failed to assign seat to libinput context\n"); - goto error2; - } -#else - if (libinput_netlink_assign_seat(seat->libinput, seat->name) != 0) { - ERROR("Failed to assign seat to libinput context\n"); - goto error2; - } -#endif - - seat->libinput_source = wl_event_loop_add_fd(swc.event_loop, libinput_get_fd(seat->libinput), WL_EVENT_READABLE, &handle_libinput_data, seat); - if (!seat->libinput_source) { - ERROR("Could not create event source for libinput\n"); - goto error2; - } - - if (!swc.active) - libinput_suspend(seat->libinput); - - return true; - -error2: - libinput_unref(seat->libinput); -error1: -#ifdef ENABLE_LIBUDEV - udev_unref(seat->udev); -error0: -#endif - return false; -} - -struct swc_seat * -seat_create(struct wl_display *display, const char *seat_name) -{ - struct seat *seat; - - seat = malloc(sizeof(*seat)); - if (!seat) - goto error0; - seat->name = strdup(seat_name); - if (!seat->name) { - ERROR("Could not allocate seat name string\n"); - goto error1; - } - seat->global = wl_global_create(display, &wl_seat_interface, 4, seat, &bind_seat); - if (!seat->global) - goto error2; - seat->capabilities = 0; - wl_list_init(&seat->resources); - - seat->swc_listener.notify = &handle_swc_event; - wl_signal_add(&swc.event_signal, &seat->swc_listener); - - seat->base.data_device = data_device_create(); - if (!seat->base.data_device) { - ERROR("Could not initialize data device\n"); - goto error3; - } - seat->data_device_listener.notify = &handle_data_device_event; - wl_signal_add(&seat->base.data_device->event_signal, &seat->data_device_listener); - - seat->base.keyboard = keyboard_create(NULL); - if (!seat->base.keyboard) { - ERROR("Could not initialize keyboard\n"); - goto error4; - } - seat->keyboard_focus_listener.notify = handle_keyboard_focus_event; - wl_signal_add(&seat->base.keyboard->focus.event_signal, &seat->keyboard_focus_listener); - - if (!pointer_initialize(&seat->pointer)) { - ERROR("Could not initialize pointer\n"); - goto error5; - } - seat->base.pointer = &seat->pointer; - - if (!initialize_libinput(seat)) - goto error6; - - return &seat->base; - -error6: - pointer_finalize(&seat->pointer); -error5: - keyboard_destroy(seat->base.keyboard); -error4: - data_device_destroy(seat->base.data_device); -error3: - wl_global_destroy(seat->global); -error2: - free(seat->name); -error1: - free(seat); -error0: - return NULL; -} - -void -seat_destroy(struct swc_seat *seat_base) -{ - struct seat *seat = wl_container_of(seat_base, seat, base); - - wl_event_source_remove(seat->libinput_source); - libinput_unref(seat->libinput); -#ifdef ENABLE_LIBUDEV - udev_unref(seat->udev); -#endif - - pointer_finalize(&seat->pointer); - keyboard_destroy(seat->base.keyboard); - data_device_destroy(seat->base.data_device); - - wl_global_destroy(seat->global); - free(seat->name); - free(seat); -} diff --git a/libswc/seat.h b/libswc/seat.h index 54d889f..b037ef5 100644 --- a/libswc/seat.h +++ b/libswc/seat.h @@ -24,15 +24,23 @@ #ifndef SWC_SEAT_H #define SWC_SEAT_H +#include + struct wl_display; struct swc_seat { struct pointer *pointer; struct keyboard *keyboard; struct data_device *data_device; + struct wl_listener keyboard_focus_listener; + struct wl_listener data_device_listener; }; struct swc_seat *seat_create(struct wl_display *display, const char *name); void seat_destroy(struct swc_seat *seat); +void seat_handle_keyboard_focus_event(struct wl_listener *listener, void *data); +void seat_handle_data_device_event(struct wl_listener *listener, void *data); + +struct wl_seat_interface seat_impl; #endif From df5253429086e8272b8531fc60ac642c74c480f3 Mon Sep 17 00:00:00 2001 From: nia Date: Sun, 23 Feb 2020 11:06:01 +0000 Subject: [PATCH 2/2] seat: Restore lost error check --- libswc/seat.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libswc/seat.c b/libswc/seat.c index 240cfa4..317fda2 100644 --- a/libswc/seat.c +++ b/libswc/seat.c @@ -67,7 +67,8 @@ get_pointer(struct wl_client *client, struct wl_resource *resource, uint32_t id) { struct swc_seat *seat = wl_resource_get_user_data(resource); - pointer_bind(seat->pointer, client, wl_resource_get_version(resource), id); + if (!pointer_bind(seat->pointer, client, wl_resource_get_version(resource), id)) + wl_resource_post_no_memory(resource); } static void @@ -75,7 +76,8 @@ get_keyboard(struct wl_client *client, struct wl_resource *resource, uint32_t id { struct swc_seat *seat = wl_resource_get_user_data(resource); - keyboard_bind(seat->keyboard, client, wl_resource_get_version(resource), id); + if (!keyboard_bind(seat->keyboard, client, wl_resource_get_version(resource), id)) + wl_resource_post_no_memory(resource); } static void