From bbce92a9238951bfecb6d337f34c9a0153aa9c0f Mon Sep 17 00:00:00 2001 From: Scott Anderson Date: Sun, 11 Nov 2018 18:09:04 +1300 Subject: [PATCH] backend/wayland: Move initilisation code earlier The renderer redesign is going to need the render fd before the backend is fully started, so we have to move the wl registry code to when the backend is created instead of when it is started. We also need to stash the wl_keyboard and emit it to library users later, once they've added their listeners and started the backend. --- backend/wayland/backend.c | 195 ++++++++++++++++++++------------------ backend/wayland/wl_seat.c | 47 +++++---- include/backend/wayland.h | 8 +- 3 files changed, 136 insertions(+), 114 deletions(-) diff --git a/backend/wayland/backend.c b/backend/wayland/backend.c index 8375ea57..7ccd632d 100644 --- a/backend/wayland/backend.c +++ b/backend/wayland/backend.c @@ -15,27 +15,26 @@ #include "util/signal.h" #include "xdg-shell-unstable-v6-client-protocol.h" -struct wlr_wl_backend *get_wl_backend_from_backend( - struct wlr_backend *wlr_backend) { - assert(wlr_backend_is_wl(wlr_backend)); - return (struct wlr_wl_backend *)wlr_backend; +struct wlr_wl_backend *get_wl_backend_from_backend(struct wlr_backend *backend) { + assert(wlr_backend_is_wl(backend)); + return (struct wlr_wl_backend *)backend; } static int dispatch_events(int fd, uint32_t mask, void *data) { - struct wlr_wl_backend *backend = data; + struct wlr_wl_backend *wl = data; int count = 0; if ((mask & WL_EVENT_HANGUP) || (mask & WL_EVENT_ERROR)) { - wl_display_terminate(backend->local_display); + wl_display_terminate(wl->local_display); return 0; } if (mask & WL_EVENT_READABLE) { - count = wl_display_dispatch(backend->remote_display); + count = wl_display_dispatch(wl->remote_display); } if (mask == 0) { - count = wl_display_dispatch_pending(backend->remote_display); - wl_display_flush(backend->remote_display); + count = wl_display_dispatch_pending(wl->remote_display); + wl_display_flush(wl->remote_display); } return count; } @@ -90,90 +89,70 @@ static const struct wl_registry_listener registry_listener = { * compositor and creates surfaces for each output, then registers globals on * the specified display. */ -static bool backend_start(struct wlr_backend *wlr_backend) { - struct wlr_wl_backend *backend = get_wl_backend_from_backend(wlr_backend); +static bool backend_start(struct wlr_backend *backend) { + struct wlr_wl_backend *wl = get_wl_backend_from_backend(backend); wlr_log(WLR_INFO, "Initializating wayland backend"); - wl_registry_add_listener(backend->registry, ®istry_listener, backend); - wl_display_dispatch(backend->remote_display); - wl_display_roundtrip(backend->remote_display); + wl->started = true; - if (!backend->compositor || !backend->shell) { - wlr_log_errno(WLR_ERROR, "Could not obtain retrieve required globals"); - return false; + if (wl->keyboard) { + create_wl_keyboard(wl->keyboard, wl); } - backend->started = true; - - for (size_t i = 0; i < backend->requested_outputs; ++i) { - wlr_wl_output_create(&backend->backend); + for (size_t i = 0; i < wl->requested_outputs; ++i) { + wlr_wl_output_create(&wl->backend); } - struct wl_event_loop *loop = wl_display_get_event_loop(backend->local_display); - int fd = wl_display_get_fd(backend->remote_display); - int events = WL_EVENT_READABLE | WL_EVENT_ERROR | WL_EVENT_HANGUP; - backend->remote_display_src = wl_event_loop_add_fd(loop, fd, events, - dispatch_events, backend); - wl_event_source_check(backend->remote_display_src); - return true; } -static void backend_destroy(struct wlr_backend *wlr_backend) { - struct wlr_wl_backend *backend = get_wl_backend_from_backend(wlr_backend); - if (backend == NULL) { +static void backend_destroy(struct wlr_backend *backend) { + if (!backend) { return; } + struct wlr_wl_backend *wl = get_wl_backend_from_backend(backend); + struct wlr_wl_output *output, *tmp_output; - wl_list_for_each_safe(output, tmp_output, &backend->outputs, link) { + wl_list_for_each_safe(output, tmp_output, &wl->outputs, link) { wlr_output_destroy(&output->wlr_output); } struct wlr_input_device *input_device, *tmp_input_device; - wl_list_for_each_safe(input_device, tmp_input_device, &backend->devices, link) { + wl_list_for_each_safe(input_device, tmp_input_device, &wl->devices, link) { wlr_input_device_destroy(input_device); } - wlr_signal_emit_safe(&wlr_backend->events.destroy, wlr_backend); + wlr_signal_emit_safe(&wl->backend.events.destroy, &wl->backend); - wl_list_remove(&backend->local_display_destroy.link); + wl_list_remove(&wl->local_display_destroy.link); - free(backend->seat_name); + free(wl->seat_name); - if (backend->remote_display_src) { - wl_event_source_remove(backend->remote_display_src); + wl_event_source_remove(wl->remote_display_src); + + wlr_renderer_destroy(wl->renderer); + wlr_egl_finish(&wl->egl); + + if (wl->pointer) { + wl_pointer_destroy(wl->pointer); } - wlr_renderer_destroy(backend->renderer); - wlr_egl_finish(&backend->egl); - if (backend->pointer) { - wl_pointer_destroy(backend->pointer); + if (wl->seat) { + wl_seat_destroy(wl->seat); } - if (backend->seat) { - wl_seat_destroy(backend->seat); + if (wl->shm) { + wl_shm_destroy(wl->shm); } - if (backend->shm) { - wl_shm_destroy(backend->shm); - } - if (backend->shell) { - zxdg_shell_v6_destroy(backend->shell); - } - if (backend->compositor) { - wl_compositor_destroy(backend->compositor); - } - if (backend->registry) { - wl_registry_destroy(backend->registry); - } - if (backend->remote_display) { - wl_display_disconnect(backend->remote_display); - } - free(backend); + zxdg_shell_v6_destroy(wl->shell); + wl_compositor_destroy(wl->compositor); + wl_registry_destroy(wl->registry); + wl_display_disconnect(wl->remote_display); + free(wl); } -static struct wlr_renderer *backend_get_renderer( - struct wlr_backend *wlr_backend) { - struct wlr_wl_backend *backend = get_wl_backend_from_backend(wlr_backend); - return backend->renderer; +static struct wlr_renderer *backend_get_renderer(struct wlr_backend *backend) { + struct wlr_wl_backend *wl = get_wl_backend_from_backend(backend); + return wl->renderer; } static struct wlr_backend_impl backend_impl = { @@ -187,38 +166,64 @@ bool wlr_backend_is_wl(struct wlr_backend *b) { } static void handle_display_destroy(struct wl_listener *listener, void *data) { - struct wlr_wl_backend *backend = - wl_container_of(listener, backend, local_display_destroy); - backend_destroy(&backend->backend); + struct wlr_wl_backend *wl = + wl_container_of(listener, wl, local_display_destroy); + backend_destroy(&wl->backend); } struct wlr_backend *wlr_wl_backend_create(struct wl_display *display, const char *remote, wlr_renderer_create_func_t create_renderer_func) { wlr_log(WLR_INFO, "Creating wayland backend"); - struct wlr_wl_backend *backend = calloc(1, sizeof(struct wlr_wl_backend)); - if (!backend) { - wlr_log(WLR_ERROR, "Allocation failed: %s", strerror(errno)); + struct wlr_wl_backend *wl = calloc(1, sizeof(*wl)); + if (!wl) { + wlr_log_errno(WLR_ERROR, "Allocation failed"); return NULL; } - wlr_backend_init(&backend->backend, &backend_impl); - wl_list_init(&backend->devices); - wl_list_init(&backend->outputs); + wlr_backend_init(&wl->backend, &backend_impl); - backend->local_display = display; + wl->local_display = display; + wl_list_init(&wl->devices); + wl_list_init(&wl->outputs); - backend->remote_display = wl_display_connect(remote); - if (!backend->remote_display) { + wl->remote_display = wl_display_connect(remote); + if (!wl->remote_display) { wlr_log_errno(WLR_ERROR, "Could not connect to remote display"); - goto error_connect; + goto error_wl; } - backend->registry = wl_display_get_registry(backend->remote_display); - if (backend->registry == NULL) { + wl->registry = wl_display_get_registry(wl->remote_display); + if (!wl->registry) { wlr_log_errno(WLR_ERROR, "Could not obtain reference to remote registry"); + goto error_display; + } + + wl_registry_add_listener(wl->registry, ®istry_listener, wl); + wl_display_dispatch(wl->remote_display); + wl_display_roundtrip(wl->remote_display); + + if (!wl->compositor) { + wlr_log(WLR_ERROR, + "Remote Wayland compositor does not support wl_compositor"); goto error_registry; } + if (!wl->shell) { + wlr_log(WLR_ERROR, + "Remote Wayland compositor does not support zxdg_shell_v6"); + goto error_registry; + } + + struct wl_event_loop *loop = wl_display_get_event_loop(wl->local_display); + int fd = wl_display_get_fd(wl->remote_display); + int events = WL_EVENT_READABLE | WL_EVENT_ERROR | WL_EVENT_HANGUP; + wl->remote_display_src = wl_event_loop_add_fd(loop, fd, events, + dispatch_events, wl); + if (!wl->remote_display_src) { + wlr_log(WLR_ERROR, "Failed to create event source"); + goto error_registry; + } + wl_event_source_check(wl->remote_display_src); static EGLint config_attribs[] = { EGL_SURFACE_TYPE, EGL_WINDOW_BIT, @@ -233,24 +238,32 @@ struct wlr_backend *wlr_wl_backend_create(struct wl_display *display, create_renderer_func = wlr_renderer_autocreate; } - backend->renderer = create_renderer_func(&backend->egl, EGL_PLATFORM_WAYLAND_EXT, - backend->remote_display, config_attribs, WL_SHM_FORMAT_ARGB8888); + wl->renderer = create_renderer_func(&wl->egl, EGL_PLATFORM_WAYLAND_EXT, + wl->remote_display, config_attribs, WL_SHM_FORMAT_ARGB8888); - if (backend->renderer == NULL) { + if (!wl->renderer) { wlr_log(WLR_ERROR, "Could not create renderer"); - goto error_renderer; + goto error_event; } - backend->local_display_destroy.notify = handle_display_destroy; - wl_display_add_destroy_listener(display, &backend->local_display_destroy); + wl->local_display_destroy.notify = handle_display_destroy; + wl_display_add_destroy_listener(display, &wl->local_display_destroy); - return &backend->backend; + return &wl->backend; -error_renderer: - wl_registry_destroy(backend->registry); +error_event: + wl_event_source_remove(wl->remote_display_src); error_registry: - wl_display_disconnect(backend->remote_display); -error_connect: - free(backend); + if (wl->compositor) { + wl_compositor_destroy(wl->compositor); + } + if (wl->shell) { + zxdg_shell_v6_destroy(wl->shell); + } + wl_registry_destroy(wl->registry); +error_display: + wl_display_disconnect(wl->remote_display); +error_wl: + free(wl); return NULL; } diff --git a/backend/wayland/wl_seat.c b/backend/wayland/wl_seat.c index 562d9431..711abeca 100644 --- a/backend/wayland/wl_seat.c +++ b/backend/wayland/wl_seat.c @@ -321,8 +321,7 @@ static void pointer_handle_output_destroy(struct wl_listener *listener, wlr_input_device_destroy(&pointer->input_device->wlr_input_device); } -void create_wl_pointer(struct wl_pointer *wl_pointer, - struct wlr_wl_output *output) { +void create_wl_pointer(struct wl_pointer *wl_pointer, struct wlr_wl_output *output) { struct wlr_wl_backend *backend = output->backend; struct wlr_input_device *wlr_dev; @@ -364,6 +363,28 @@ void create_wl_pointer(struct wl_pointer *wl_pointer, wlr_signal_emit_safe(&backend->backend.events.new_input, wlr_dev); } +void create_wl_keyboard(struct wl_keyboard *wl_keyboard, struct wlr_wl_backend *wl) { + struct wlr_wl_input_device *dev = + create_wl_input_device(wl, WLR_INPUT_DEVICE_KEYBOARD); + if (!dev) { + return; + } + + struct wlr_input_device *wlr_dev = &dev->wlr_input_device; + + wlr_dev->keyboard = calloc(1, sizeof(*wlr_dev->keyboard)); + if (!wlr_dev->keyboard) { + wlr_log_errno(WLR_ERROR, "Allocation failed"); + free(dev); + return; + } + wlr_keyboard_init(wlr_dev->keyboard, NULL); + + wl_keyboard_add_listener(wl_keyboard, &keyboard_listener, wlr_dev); + dev->resource = wl_keyboard; + wlr_signal_emit_safe(&wl->backend.events.new_input, wlr_dev); +} + static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat, enum wl_seat_capability caps) { struct wlr_wl_backend *backend = data; @@ -384,25 +405,13 @@ static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat, } if ((caps & WL_SEAT_CAPABILITY_KEYBOARD)) { wlr_log(WLR_DEBUG, "seat %p offered keyboard", (void*) wl_seat); - struct wlr_wl_input_device *dev = create_wl_input_device(backend, - WLR_INPUT_DEVICE_KEYBOARD); - if (dev == NULL) { - wlr_log(WLR_ERROR, "Allocation failed"); - return; - } - struct wlr_input_device *wlr_dev = &dev->wlr_input_device; - wlr_dev->keyboard = calloc(1, sizeof(struct wlr_keyboard)); - if (!wlr_dev->keyboard) { - free(dev); - wlr_log(WLR_ERROR, "Allocation failed"); - return; - } - wlr_keyboard_init(wlr_dev->keyboard, NULL); struct wl_keyboard *wl_keyboard = wl_seat_get_keyboard(wl_seat); - wl_keyboard_add_listener(wl_keyboard, &keyboard_listener, wlr_dev); - dev->resource = wl_keyboard; - wlr_signal_emit_safe(&backend->backend.events.new_input, wlr_dev); + backend->keyboard = wl_keyboard; + + if (backend->started) { + create_wl_keyboard(wl_keyboard, backend); + } } } diff --git a/include/backend/wayland.h b/include/backend/wayland.h index 54b791b1..7c92cf84 100644 --- a/include/backend/wayland.h +++ b/include/backend/wayland.h @@ -32,6 +32,7 @@ struct wlr_wl_backend { struct wl_shm *shm; struct wl_seat *seat; struct wl_pointer *pointer; + struct wl_keyboard *keyboard; struct wlr_wl_pointer *current_pointer; char *seat_name; }; @@ -78,12 +79,11 @@ struct wlr_wl_pointer { struct wl_listener output_destroy; }; -struct wlr_wl_backend *get_wl_backend_from_backend( - struct wlr_backend *wlr_backend); +struct wlr_wl_backend *get_wl_backend_from_backend(struct wlr_backend *backend); void update_wl_output_cursor(struct wlr_wl_output *output); struct wlr_wl_pointer *pointer_get_wl(struct wlr_pointer *wlr_pointer); -void create_wl_pointer(struct wl_pointer *wl_pointer, - struct wlr_wl_output *output); +void create_wl_pointer(struct wl_pointer *wl_pointer, struct wlr_wl_output *output); +void create_wl_keyboard(struct wl_keyboard *wl_keyboard, struct wlr_wl_backend *wl); extern const struct wl_seat_listener seat_listener;