diff options
Diffstat (limited to 'backend')
-rw-r--r-- | backend/CMakeLists.txt | 1 | ||||
-rw-r--r-- | backend/backend.c | 26 | ||||
-rw-r--r-- | backend/multi/backend.c | 107 |
3 files changed, 128 insertions, 6 deletions
diff --git a/backend/CMakeLists.txt b/backend/CMakeLists.txt index 5505e417..23914240 100644 --- a/backend/CMakeLists.txt +++ b/backend/CMakeLists.txt @@ -18,6 +18,7 @@ add_library(wlr-backend libinput/events.c libinput/keyboard.c + multi/backend.c backend.c egl.c udev.c diff --git a/backend/backend.c b/backend/backend.c index 03c662c3..02fd7479 100644 --- a/backend/backend.c +++ b/backend/backend.c @@ -8,6 +8,7 @@ #include <wlr/backend/interface.h> #include <wlr/backend/drm.h> #include <wlr/backend/libinput.h> +#include <wlr/backend/multi.h> #include "backend/libinput.h" #include "backend/udev.h" #include "common/log.h" @@ -46,19 +47,32 @@ struct wlr_backend *wlr_backend_autocreate(struct wl_display *display, wlr_log(L_ERROR, "Failed to start udev"); goto error; } - struct wlr_backend *wlr; - wlr = wlr_libinput_backend_create(display, session, udev); - return wlr; int gpu = wlr_udev_find_gpu(udev, session); if (gpu == -1) { wlr_log(L_ERROR, "Failed to open DRM device"); goto error_udev; } - wlr = wlr_drm_backend_create(display, session, udev, gpu); - if (!wlr) { + struct wlr_backend *multi = wlr_multi_backend_create(); + if (!multi) { goto error_gpu; } - return wlr; + struct wlr_backend *libinput = + wlr_libinput_backend_create(display, session, udev); + if (!libinput) { + goto error_multi; + } + struct wlr_backend *drm = + wlr_drm_backend_create(display, session, udev, gpu); + if (!drm) { + goto error_libinput; + } + wlr_multi_backend_add(multi, libinput); + wlr_multi_backend_add(multi, drm); + return multi; +error_libinput: + wlr_backend_destroy(libinput); +error_multi: + wlr_backend_destroy(multi); error_gpu: close(gpu); error_udev: diff --git a/backend/multi/backend.c b/backend/multi/backend.c new file mode 100644 index 00000000..e3d87ccc --- /dev/null +++ b/backend/multi/backend.c @@ -0,0 +1,107 @@ +#include <stdbool.h> +#include <stdlib.h> +#include <wlr/backend/interface.h> +#include <wlr/common/log.h> +#include "backend/multi.h" +#include "common/log.h" + +struct subbackend_state { + struct wlr_backend *backend; + struct wlr_backend *container; + struct wl_listener input_add; + struct wl_listener input_remove; + struct wl_listener output_add; + struct wl_listener output_remove; +}; + +static bool multi_backend_init(struct wlr_backend_state *state) { + for (size_t i = 0; i < state->backends->length; ++i) { + struct subbackend_state *sub = state->backends->items[i]; + if (!wlr_backend_init(sub->backend)) { + wlr_log(L_ERROR, "Failed to initialize backend %zd", i); + return false; + } + } + return true; +} + +static void multi_backend_destroy(struct wlr_backend_state *state) { + for (size_t i = 0; i < state->backends->length; ++i) { + struct subbackend_state *sub = state->backends->items[i]; + wlr_backend_destroy(sub->backend); + free(sub); + } + list_free(state->backends); + free(state); +} + +struct wlr_backend_impl backend_impl = { + .init = multi_backend_init, + .destroy = multi_backend_destroy +}; + +struct wlr_backend *wlr_multi_backend_create() { + struct wlr_backend_state *state = + calloc(1, sizeof(struct wlr_backend_state)); + if (!state) { + wlr_log(L_ERROR, "Backend allocation failed"); + return NULL; + } + state->backends = list_create(); + if (!state->backends) { + free(state); + wlr_log(L_ERROR, "Backend allocation failed"); + return NULL; + } + struct wlr_backend *backend = wlr_backend_create(&backend_impl, state); + state->backend = backend; + return backend; +} + +static void input_add_reemit(struct wl_listener *listener, void *data) { + struct subbackend_state *state = wl_container_of(listener, + state, input_add); + wl_signal_emit(&state->container->events.input_add, data); +} + +static void input_remove_reemit(struct wl_listener *listener, void *data) { + struct subbackend_state *state = wl_container_of(listener, + state, input_remove); + wl_signal_emit(&state->container->events.input_remove, data); +} + +static void output_add_reemit(struct wl_listener *listener, void *data) { + struct subbackend_state *state = wl_container_of(listener, + state, output_add); + wl_signal_emit(&state->container->events.output_add, data); +} + +static void output_remove_reemit(struct wl_listener *listener, void *data) { + struct subbackend_state *state = wl_container_of(listener, + state, output_remove); + wl_signal_emit(&state->container->events.output_remove, data); +} + +void wlr_multi_backend_add(struct wlr_backend *multi, + struct wlr_backend *backend) { + struct subbackend_state *sub = calloc(1, sizeof(struct subbackend_state)); + sub->backend = backend; + sub->container = multi; + + sub->input_add.notify = input_add_reemit; + sub->input_remove.notify = input_remove_reemit; + sub->output_add.notify = output_add_reemit; + sub->output_remove.notify = output_remove_reemit; + + wl_list_init(&sub->input_add.link); + wl_list_init(&sub->input_remove.link); + wl_list_init(&sub->output_add.link); + wl_list_init(&sub->output_remove.link); + + wl_signal_add(&backend->events.input_add, &sub->input_add); + wl_signal_add(&backend->events.input_remove, &sub->input_remove); + wl_signal_add(&backend->events.output_add, &sub->output_add); + wl_signal_add(&backend->events.output_remove, &sub->output_remove); + + list_add(multi->state->backends, sub); +} |