diff --git a/backend/wayland/backend.c b/backend/wayland/backend.c index 913642343..6740b7216 100644 --- a/backend/wayland/backend.c +++ b/backend/wayland/backend.c @@ -236,6 +236,34 @@ static const struct zwp_linux_dmabuf_feedback_v1_listener .tranche_flags = linux_dmabuf_feedback_v1_handle_tranche_flags, }; +static void wlr_output_handle_scale(void *data, + struct wl_output *wl_output, int32_t factor) { + struct wlr_wl_remote_output *output = data; + output->scale = factor; +} + +static void wlr_output_handle_geometry(void *data, struct wl_output *wl_output, + int32_t x, int32_t y, int32_t phys_width, int32_t phys_height, + int32_t subpixel, const char *make, const char *model, int32_t transform) { + // This is intentionally left blank +} + +static void wlr_output_handle_mode(void *data, struct wl_output *wl_output, + uint32_t flags, int32_t width, int32_t height, int32_t refresh) { + // This is intentionally left blank +} + +static void wlr_output_handle_done(void *data, struct wl_output *wl_output) { + // This is intentionally left blank +} + +static const struct wl_output_listener output_listener = { + .scale = wlr_output_handle_scale, + .geometry = wlr_output_handle_geometry, + .mode = wlr_output_handle_mode, + .done = wlr_output_handle_done +}; + static bool device_has_name(const drmDevice *device, const char *name) { for (size_t i = 0; i < DRM_NODE_MAX; i++) { if (!(device->available_nodes & (1 << i))) { @@ -393,6 +421,24 @@ static void registry_global(void *data, struct wl_registry *registry, } else if (strcmp(iface, xdg_activation_v1_interface.name) == 0) { wl->activation_v1 = wl_registry_bind(registry, name, &xdg_activation_v1_interface, 1); + } else if (strcmp(iface, wl_output_interface.name) == 0) { + struct wlr_wl_remote_output *output = calloc(1, sizeof(*output)); + if (!output) { + return; + } + + struct wl_output *wl_output = wl_registry_bind(registry, name, &wl_output_interface, 2); + if (!wl_output) { + free(output); + return; + } + + output->output = wl_output; + output->scale = 1; + output->name = name; + + wl_list_insert(&wl->remote_outputs, &output->link); + wl_output_add_listener(wl_output, &output_listener, output); } } @@ -407,6 +453,15 @@ static void registry_global_remove(void *data, struct wl_registry *registry, break; } } + + struct wlr_wl_remote_output *output; + wl_list_for_each(output, &wl->remote_outputs, link) { + if (output->name == name) { + wl_list_remove(&output->link); + free(output); + break; + } + } } static const struct wl_registry_listener registry_listener = { @@ -466,6 +521,13 @@ static void backend_destroy(struct wlr_backend *backend) { destroy_wl_buffer(buffer); } + struct wlr_wl_remote_output *remote_output, *tmp_remote_output; + wl_list_for_each_safe(remote_output, tmp_remote_output, + &wl->remote_outputs, link) { + wl_output_release(remote_output->output); + free(remote_output); + } + wlr_backend_finish(backend); wl_list_remove(&wl->local_display_destroy.link); @@ -560,6 +622,7 @@ struct wlr_backend *wlr_wl_backend_create(struct wl_display *display, wl_list_init(&wl->outputs); wl_list_init(&wl->seats); wl_list_init(&wl->buffers); + wl_list_init(&wl->remote_outputs); wl->presentation_clock = CLOCK_MONOTONIC; wl->remote_display = wl_display_connect(remote); diff --git a/include/backend/wayland.h b/include/backend/wayland.h index 5af8ed53d..bdfa4f214 100644 --- a/include/backend/wayland.h +++ b/include/backend/wayland.h @@ -47,9 +47,21 @@ struct wlr_wl_backend { struct wlr_drm_format_set linux_dmabuf_v1_formats; struct wl_drm *legacy_drm; struct xdg_activation_v1 *activation_v1; + struct wl_list remote_outputs; // wlr_wl_remote_output.link char *drm_render_name; }; +struct wlr_wl_remote_output { + struct wl_output *output; + uint32_t scale; + + // we use this to identify the output in the + // global registry so that we can remove it later + uint32_t name; + + struct wl_list link; // wlr_wl_backend.remote_outputs +}; + struct wlr_wl_buffer { struct wlr_buffer *buffer; struct wl_buffer *wl_buffer;