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.
This commit is contained in:
Scott Anderson 2018-11-11 18:09:04 +13:00
parent 47545cf550
commit bbce92a923
3 changed files with 136 additions and 114 deletions

View File

@ -15,27 +15,26 @@
#include "util/signal.h" #include "util/signal.h"
#include "xdg-shell-unstable-v6-client-protocol.h" #include "xdg-shell-unstable-v6-client-protocol.h"
struct wlr_wl_backend *get_wl_backend_from_backend( struct wlr_wl_backend *get_wl_backend_from_backend(struct wlr_backend *backend) {
struct wlr_backend *wlr_backend) { assert(wlr_backend_is_wl(backend));
assert(wlr_backend_is_wl(wlr_backend)); return (struct wlr_wl_backend *)backend;
return (struct wlr_wl_backend *)wlr_backend;
} }
static int dispatch_events(int fd, uint32_t mask, void *data) { 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; int count = 0;
if ((mask & WL_EVENT_HANGUP) || (mask & WL_EVENT_ERROR)) { if ((mask & WL_EVENT_HANGUP) || (mask & WL_EVENT_ERROR)) {
wl_display_terminate(backend->local_display); wl_display_terminate(wl->local_display);
return 0; return 0;
} }
if (mask & WL_EVENT_READABLE) { if (mask & WL_EVENT_READABLE) {
count = wl_display_dispatch(backend->remote_display); count = wl_display_dispatch(wl->remote_display);
} }
if (mask == 0) { if (mask == 0) {
count = wl_display_dispatch_pending(backend->remote_display); count = wl_display_dispatch_pending(wl->remote_display);
wl_display_flush(backend->remote_display); wl_display_flush(wl->remote_display);
} }
return count; 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 * compositor and creates surfaces for each output, then registers globals on
* the specified display. * the specified display.
*/ */
static bool backend_start(struct wlr_backend *wlr_backend) { static bool backend_start(struct wlr_backend *backend) {
struct wlr_wl_backend *backend = get_wl_backend_from_backend(wlr_backend); struct wlr_wl_backend *wl = get_wl_backend_from_backend(backend);
wlr_log(WLR_INFO, "Initializating wayland backend"); wlr_log(WLR_INFO, "Initializating wayland backend");
wl_registry_add_listener(backend->registry, &registry_listener, backend); wl->started = true;
wl_display_dispatch(backend->remote_display);
wl_display_roundtrip(backend->remote_display);
if (!backend->compositor || !backend->shell) { if (wl->keyboard) {
wlr_log_errno(WLR_ERROR, "Could not obtain retrieve required globals"); create_wl_keyboard(wl->keyboard, wl);
return false;
} }
backend->started = true; for (size_t i = 0; i < wl->requested_outputs; ++i) {
wlr_wl_output_create(&wl->backend);
for (size_t i = 0; i < backend->requested_outputs; ++i) {
wlr_wl_output_create(&backend->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; return true;
} }
static void backend_destroy(struct wlr_backend *wlr_backend) { static void backend_destroy(struct wlr_backend *backend) {
struct wlr_wl_backend *backend = get_wl_backend_from_backend(wlr_backend); if (!backend) {
if (backend == NULL) {
return; return;
} }
struct wlr_wl_backend *wl = get_wl_backend_from_backend(backend);
struct wlr_wl_output *output, *tmp_output; 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); wlr_output_destroy(&output->wlr_output);
} }
struct wlr_input_device *input_device, *tmp_input_device; 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_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(wl->remote_display_src);
wl_event_source_remove(backend->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); if (wl->seat) {
wlr_egl_finish(&backend->egl); wl_seat_destroy(wl->seat);
if (backend->pointer) {
wl_pointer_destroy(backend->pointer);
} }
if (backend->seat) { if (wl->shm) {
wl_seat_destroy(backend->seat); wl_shm_destroy(wl->shm);
} }
if (backend->shm) { zxdg_shell_v6_destroy(wl->shell);
wl_shm_destroy(backend->shm); wl_compositor_destroy(wl->compositor);
} wl_registry_destroy(wl->registry);
if (backend->shell) { wl_display_disconnect(wl->remote_display);
zxdg_shell_v6_destroy(backend->shell); free(wl);
}
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);
} }
static struct wlr_renderer *backend_get_renderer( static struct wlr_renderer *backend_get_renderer(struct wlr_backend *backend) {
struct wlr_backend *wlr_backend) { struct wlr_wl_backend *wl = get_wl_backend_from_backend(backend);
struct wlr_wl_backend *backend = get_wl_backend_from_backend(wlr_backend); return wl->renderer;
return backend->renderer;
} }
static struct wlr_backend_impl backend_impl = { 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) { static void handle_display_destroy(struct wl_listener *listener, void *data) {
struct wlr_wl_backend *backend = struct wlr_wl_backend *wl =
wl_container_of(listener, backend, local_display_destroy); wl_container_of(listener, wl, local_display_destroy);
backend_destroy(&backend->backend); backend_destroy(&wl->backend);
} }
struct wlr_backend *wlr_wl_backend_create(struct wl_display *display, struct wlr_backend *wlr_wl_backend_create(struct wl_display *display,
const char *remote, wlr_renderer_create_func_t create_renderer_func) { const char *remote, wlr_renderer_create_func_t create_renderer_func) {
wlr_log(WLR_INFO, "Creating wayland backend"); wlr_log(WLR_INFO, "Creating wayland backend");
struct wlr_wl_backend *backend = calloc(1, sizeof(struct wlr_wl_backend)); struct wlr_wl_backend *wl = calloc(1, sizeof(*wl));
if (!backend) { if (!wl) {
wlr_log(WLR_ERROR, "Allocation failed: %s", strerror(errno)); wlr_log_errno(WLR_ERROR, "Allocation failed");
return NULL; return NULL;
} }
wlr_backend_init(&backend->backend, &backend_impl);
wl_list_init(&backend->devices); wlr_backend_init(&wl->backend, &backend_impl);
wl_list_init(&backend->outputs);
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); wl->remote_display = wl_display_connect(remote);
if (!backend->remote_display) { if (!wl->remote_display) {
wlr_log_errno(WLR_ERROR, "Could not connect to 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); wl->registry = wl_display_get_registry(wl->remote_display);
if (backend->registry == NULL) { if (!wl->registry) {
wlr_log_errno(WLR_ERROR, "Could not obtain reference to remote registry"); wlr_log_errno(WLR_ERROR, "Could not obtain reference to remote registry");
goto error_display;
}
wl_registry_add_listener(wl->registry, &registry_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; 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[] = { static EGLint config_attribs[] = {
EGL_SURFACE_TYPE, EGL_WINDOW_BIT, 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; create_renderer_func = wlr_renderer_autocreate;
} }
backend->renderer = create_renderer_func(&backend->egl, EGL_PLATFORM_WAYLAND_EXT, wl->renderer = create_renderer_func(&wl->egl, EGL_PLATFORM_WAYLAND_EXT,
backend->remote_display, config_attribs, WL_SHM_FORMAT_ARGB8888); wl->remote_display, config_attribs, WL_SHM_FORMAT_ARGB8888);
if (backend->renderer == NULL) { if (!wl->renderer) {
wlr_log(WLR_ERROR, "Could not create renderer"); wlr_log(WLR_ERROR, "Could not create renderer");
goto error_renderer; goto error_event;
} }
backend->local_display_destroy.notify = handle_display_destroy; wl->local_display_destroy.notify = handle_display_destroy;
wl_display_add_destroy_listener(display, &backend->local_display_destroy); wl_display_add_destroy_listener(display, &wl->local_display_destroy);
return &backend->backend; return &wl->backend;
error_renderer: error_event:
wl_registry_destroy(backend->registry); wl_event_source_remove(wl->remote_display_src);
error_registry: error_registry:
wl_display_disconnect(backend->remote_display); if (wl->compositor) {
error_connect: wl_compositor_destroy(wl->compositor);
free(backend); }
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; return NULL;
} }

View File

@ -321,8 +321,7 @@ static void pointer_handle_output_destroy(struct wl_listener *listener,
wlr_input_device_destroy(&pointer->input_device->wlr_input_device); wlr_input_device_destroy(&pointer->input_device->wlr_input_device);
} }
void create_wl_pointer(struct wl_pointer *wl_pointer, void create_wl_pointer(struct wl_pointer *wl_pointer, struct wlr_wl_output *output) {
struct wlr_wl_output *output) {
struct wlr_wl_backend *backend = output->backend; struct wlr_wl_backend *backend = output->backend;
struct wlr_input_device *wlr_dev; 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); 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, static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat,
enum wl_seat_capability caps) { enum wl_seat_capability caps) {
struct wlr_wl_backend *backend = data; 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)) { if ((caps & WL_SEAT_CAPABILITY_KEYBOARD)) {
wlr_log(WLR_DEBUG, "seat %p offered keyboard", (void*) wl_seat); 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); struct wl_keyboard *wl_keyboard = wl_seat_get_keyboard(wl_seat);
wl_keyboard_add_listener(wl_keyboard, &keyboard_listener, wlr_dev); backend->keyboard = wl_keyboard;
dev->resource = wl_keyboard;
wlr_signal_emit_safe(&backend->backend.events.new_input, wlr_dev); if (backend->started) {
create_wl_keyboard(wl_keyboard, backend);
}
} }
} }

View File

@ -32,6 +32,7 @@ struct wlr_wl_backend {
struct wl_shm *shm; struct wl_shm *shm;
struct wl_seat *seat; struct wl_seat *seat;
struct wl_pointer *pointer; struct wl_pointer *pointer;
struct wl_keyboard *keyboard;
struct wlr_wl_pointer *current_pointer; struct wlr_wl_pointer *current_pointer;
char *seat_name; char *seat_name;
}; };
@ -78,12 +79,11 @@ struct wlr_wl_pointer {
struct wl_listener output_destroy; struct wl_listener output_destroy;
}; };
struct wlr_wl_backend *get_wl_backend_from_backend( struct wlr_wl_backend *get_wl_backend_from_backend(struct wlr_backend *backend);
struct wlr_backend *wlr_backend);
void update_wl_output_cursor(struct wlr_wl_output *output); void update_wl_output_cursor(struct wlr_wl_output *output);
struct wlr_wl_pointer *pointer_get_wl(struct wlr_pointer *wlr_pointer); struct wlr_wl_pointer *pointer_get_wl(struct wlr_pointer *wlr_pointer);
void create_wl_pointer(struct wl_pointer *wl_pointer, void create_wl_pointer(struct wl_pointer *wl_pointer, struct wlr_wl_output *output);
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; extern const struct wl_seat_listener seat_listener;