From c15cd16d0eec6356b7250779ce9f82833ba6477e Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Tue, 22 Nov 2022 19:00:05 -0500 Subject: [PATCH 1/5] backend/wayland: maintain a list of displays --- backend/wayland/backend.c | 63 +++++++++++++++++++++++++++++++++++++++ include/backend/wayland.h | 12 ++++++++ 2 files changed, 75 insertions(+) diff --git a/backend/wayland/backend.c b/backend/wayland/backend.c index b4bacf127..3f56deb41 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))) { @@ -396,6 +424,24 @@ static void registry_global(void *data, struct wl_registry *registry, } else if (strcmp(iface, wl_subcompositor_interface.name) == 0) { wl->subcompositor = wl_registry_bind(registry, name, &wl_subcompositor_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); } } @@ -410,6 +456,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 = { @@ -469,6 +524,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); @@ -575,6 +637,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 13c652355..83aadc1ca 100644 --- a/include/backend/wayland.h +++ b/include/backend/wayland.h @@ -48,9 +48,21 @@ struct wlr_wl_backend { struct wl_drm *legacy_drm; struct xdg_activation_v1 *activation_v1; struct wl_subcompositor *subcompositor; + 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; From 152c58c340f848801876930b9aeb4453673b0b32 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Thu, 2 Feb 2023 12:48:07 -0500 Subject: [PATCH 2/5] backend/wayland: remember cursor state so that we can call update_wl_output_cursor arbitrarily --- backend/wayland/output.c | 66 ++++++++++++++++++++++----------------- include/backend/wayland.h | 1 + 2 files changed, 39 insertions(+), 28 deletions(-) diff --git a/backend/wayland/output.c b/backend/wayland/output.c index 38daade25..24ca43540 100644 --- a/backend/wayland/output.c +++ b/backend/wayland/output.c @@ -527,34 +527,18 @@ static bool output_commit(struct wlr_output *wlr_output, static bool output_set_cursor(struct wlr_output *wlr_output, struct wlr_buffer *wlr_buffer, int hotspot_x, int hotspot_y) { struct wlr_wl_output *output = get_wl_output_from_output(wlr_output); - struct wlr_wl_backend *backend = output->backend; output->cursor.hotspot_x = hotspot_x; output->cursor.hotspot_y = hotspot_y; - if (output->cursor.surface == NULL) { - output->cursor.surface = - wl_compositor_create_surface(backend->compositor); - } - struct wl_surface *surface = output->cursor.surface; + wlr_buffer_unlock(output->cursor.buffer); + output->cursor.buffer = NULL; - if (wlr_buffer != NULL) { - struct wlr_wl_buffer *buffer = - get_or_create_wl_buffer(output->backend, wlr_buffer); - if (buffer == NULL) { - return false; - } - - wl_surface_attach(surface, buffer->wl_buffer, 0, 0); - wl_surface_damage_buffer(surface, 0, 0, INT32_MAX, INT32_MAX); - wl_surface_commit(surface); - } else { - wl_surface_attach(surface, NULL, 0, 0); - wl_surface_commit(surface); + if (wlr_buffer) { + output->cursor.buffer = wlr_buffer_lock(wlr_buffer); } update_wl_output_cursor(output); - wl_display_flush(backend->remote_display); return true; } @@ -603,15 +587,41 @@ static void output_destroy(struct wlr_output *wlr_output) { void update_wl_output_cursor(struct wlr_wl_output *output) { struct wlr_wl_pointer *pointer = output->cursor.pointer; - if (pointer) { - assert(pointer->output == output); - assert(output->enter_serial); - - struct wlr_wl_seat *seat = pointer->seat; - wl_pointer_set_cursor(seat->wl_pointer, output->enter_serial, - output->cursor.surface, output->cursor.hotspot_x, - output->cursor.hotspot_y); + if (!pointer || !output->cursor.buffer) { + return; } + + assert(pointer->output == output); + assert(output->enter_serial); + + struct wlr_wl_backend *backend = output->backend; + + if (output->cursor.surface == NULL) { + output->cursor.surface = + wl_compositor_create_surface(backend->compositor); + } + + struct wl_surface *surface = output->cursor.surface; + if (!surface) { + return; + } + + struct wlr_wl_buffer *buffer = + get_or_create_wl_buffer(output->backend, output->cursor.buffer); + if (!buffer) { + return; + } + + wl_surface_attach(surface, buffer->wl_buffer, 0, 0); + wl_surface_damage_buffer(surface, 0, 0, INT32_MAX, INT32_MAX); + wl_surface_commit(surface); + + wl_display_flush(backend->remote_display); + + struct wlr_wl_seat *seat = pointer->seat; + wl_pointer_set_cursor(seat->wl_pointer, output->enter_serial, + output->cursor.surface, output->cursor.hotspot_x, + output->cursor.hotspot_y); } static bool output_move_cursor(struct wlr_output *_output, int x, int y) { diff --git a/include/backend/wayland.h b/include/backend/wayland.h index 83aadc1ca..7d70cd598 100644 --- a/include/backend/wayland.h +++ b/include/backend/wayland.h @@ -104,6 +104,7 @@ struct wlr_wl_output { struct { struct wlr_wl_pointer *pointer; struct wl_surface *surface; + struct wlr_buffer *buffer; int32_t hotspot_x, hotspot_y; } cursor; }; From ecc389280847143879cc77d702d3e3233be46b12 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Tue, 22 Nov 2022 19:35:05 -0500 Subject: [PATCH 3/5] backend/wayland: maintain a list of active outputs for each virtual WL display --- backend/wayland/backend.c | 11 +++- backend/wayland/output.c | 103 +++++++++++++++++++++++++++++++++++--- include/backend/wayland.h | 19 +++++++ 3 files changed, 124 insertions(+), 9 deletions(-) diff --git a/backend/wayland/backend.c b/backend/wayland/backend.c index 3f56deb41..6b9408c9e 100644 --- a/backend/wayland/backend.c +++ b/backend/wayland/backend.c @@ -236,6 +236,13 @@ static const struct zwp_linux_dmabuf_feedback_v1_listener .tranche_flags = linux_dmabuf_feedback_v1_handle_tranche_flags, }; +static void update_outputs(struct wlr_wl_backend *backend) { + struct wlr_wl_output *output; + wl_list_for_each(output, &backend->outputs, link) { + surface_update(output); + } +} + static void wlr_output_handle_scale(void *data, struct wl_output *wl_output, int32_t factor) { struct wlr_wl_remote_output *output = data; @@ -254,7 +261,8 @@ static void wlr_output_handle_mode(void *data, struct wl_output *wl_output, } static void wlr_output_handle_done(void *data, struct wl_output *wl_output) { - // This is intentionally left blank + struct wlr_wl_remote_output *output = data; + update_outputs(output->backend); } static const struct wl_output_listener output_listener = { @@ -439,6 +447,7 @@ static void registry_global(void *data, struct wl_registry *registry, output->output = wl_output; output->scale = 1; output->name = name; + output->backend = wl; wl_list_insert(&wl->remote_outputs, &output->link); wl_output_add_listener(wl_output, &output_listener, output); diff --git a/backend/wayland/output.c b/backend/wayland/output.c index 24ca43540..f2f4c68df 100644 --- a/backend/wayland/output.c +++ b/backend/wayland/output.c @@ -66,6 +66,12 @@ static void presentation_feedback_destroy( free(feedback); } +static void active_remote_output_destroy( + struct wlr_wl_active_remote_output *output) { + wl_list_remove(&output->link); + free(output); +} + static void presentation_feedback_handle_sync_output(void *data, struct wp_presentation_feedback *feedback, struct wl_output *output) { // This space is intentionally left blank @@ -442,6 +448,12 @@ static bool output_commit(struct wlr_output *wlr_output, } if (state->committed & WLR_OUTPUT_STATE_BUFFER) { + if (output->requested.needs_ack) { + output->requested.needs_ack = false; + xdg_surface_ack_configure(output->xdg_surface, + output->requested.serial); + } + const pixman_region32_t *damage = NULL; if (state->committed & WLR_OUTPUT_STATE_DAMAGE) { damage = &state->damage; @@ -575,6 +587,12 @@ static void output_destroy(struct wlr_output *wlr_output) { presentation_feedback_destroy(feedback); } + struct wlr_wl_active_remote_output *active, *active_tmp; + wl_list_for_each_safe(active, active_tmp, + &output->active_remote_outputs, link) { + active_remote_output_destroy(active); + } + if (output->zxdg_toplevel_decoration_v1) { zxdg_toplevel_decoration_v1_destroy(output->zxdg_toplevel_decoration_v1); } @@ -643,14 +661,41 @@ bool wlr_output_is_wl(struct wlr_output *wlr_output) { return wlr_output->impl == &output_impl; } +void surface_update(struct wlr_wl_output *output) { + if (wl_list_empty(&output->active_remote_outputs)) { + return; + } + + struct wlr_output_state state = { + .committed = WLR_OUTPUT_STATE_MODE, + .mode_type = WLR_OUTPUT_STATE_MODE_CUSTOM, + .custom_mode = { + .width = output->requested.width, + .height = output->requested.height + }, + }; + + wlr_output_send_request_state(&output->wlr_output, &state); +} + static void xdg_surface_handle_configure(void *data, struct xdg_surface *xdg_surface, uint32_t serial) { struct wlr_wl_output *output = data; assert(output && output->xdg_surface == xdg_surface); - xdg_surface_ack_configure(xdg_surface, serial); + if (wl_list_empty(&output->active_remote_outputs)) { + xdg_surface_ack_configure(xdg_surface, serial); + wl_surface_commit(output->surface); + return; + } - // nothing else? + output->requested.needs_ack = true; + output->requested.serial = serial; + surface_update(output); + + // if the compositor did not commit a new buffer during the surface_update + // above, assume that the compositor did not acknowledge the configure. + output->requested.needs_ack = false; } static const struct xdg_surface_listener xdg_surface_listener = { @@ -667,12 +712,8 @@ static void xdg_toplevel_handle_configure(void *data, return; } - struct wlr_output_state state = { - .committed = WLR_OUTPUT_STATE_MODE, - .mode_type = WLR_OUTPUT_STATE_MODE_CUSTOM, - .custom_mode = { .width = width, .height = height }, - }; - wlr_output_send_request_state(&output->wlr_output, &state); + output->requested.width = width; + output->requested.height = height; } static void xdg_toplevel_handle_close(void *data, @@ -688,6 +729,50 @@ static const struct xdg_toplevel_listener xdg_toplevel_listener = { .close = xdg_toplevel_handle_close, }; +static void surface_enter(void *data, struct wl_surface *wl_surface, + struct wl_output *wl_output) { + struct wlr_wl_output *output = data; + + struct wlr_wl_remote_output *remote_output; + wl_list_for_each(remote_output, &output->backend->remote_outputs, link) { + if (remote_output->output != wl_output) { + continue; + } + + struct wlr_wl_active_remote_output *active = calloc(1, sizeof(*active)); + if (!active) { + return; + } + + active->remote_output = remote_output; + + wl_list_insert(&output->active_remote_outputs, &active->link); + surface_update(output); + break; + } +} + +static void surface_leave(void *data, struct wl_surface *wl_surface, + struct wl_output *wl_output) { + struct wlr_wl_output *output = data; + + struct wlr_wl_active_remote_output *active; + wl_list_for_each(active, &output->active_remote_outputs, link) { + if (active->remote_output->output != wl_output) { + continue; + } + + active_remote_output_destroy(active); + surface_update(output); + break; + } +} + +static const struct wl_surface_listener surface_listener = { + .enter = &surface_enter, + .leave = &surface_leave, +}; + struct wlr_output *wlr_wl_output_create(struct wlr_backend *wlr_backend) { struct wlr_wl_backend *backend = get_wl_backend_from_backend(wlr_backend); if (!backend->started) { @@ -720,6 +805,7 @@ struct wlr_output *wlr_wl_output_create(struct wlr_backend *wlr_backend) { output->backend = backend; wl_list_init(&output->presentation_feedbacks); + wl_list_init(&output->active_remote_outputs); output->surface = wl_compositor_create_surface(backend->compositor); if (!output->surface) { @@ -759,6 +845,7 @@ struct wlr_output *wlr_wl_output_create(struct wlr_backend *wlr_backend) { &xdg_surface_listener, output); xdg_toplevel_add_listener(output->xdg_toplevel, &xdg_toplevel_listener, output); + wl_surface_add_listener(output->surface, &surface_listener, output); wl_surface_commit(output->surface); wl_display_roundtrip(output->backend->remote_display); diff --git a/include/backend/wayland.h b/include/backend/wayland.h index 7d70cd598..6a58e2b98 100644 --- a/include/backend/wayland.h +++ b/include/backend/wayland.h @@ -54,6 +54,7 @@ struct wlr_wl_backend { struct wlr_wl_remote_output { struct wl_output *output; + struct wlr_wl_backend *backend; uint32_t scale; // we use this to identify the output in the @@ -63,6 +64,11 @@ struct wlr_wl_remote_output { struct wl_list link; // wlr_wl_backend.remote_outputs }; +struct wlr_wl_active_remote_output { + struct wlr_wl_remote_output *remote_output; + struct wl_list link; // wlr_wl_output.active_remote_outputs +}; + struct wlr_wl_buffer { struct wlr_buffer *buffer; struct wl_buffer *wl_buffer; @@ -98,9 +104,20 @@ struct wlr_wl_output { struct xdg_toplevel *xdg_toplevel; struct zxdg_toplevel_decoration_v1 *zxdg_toplevel_decoration_v1; struct wl_list presentation_feedbacks; + struct wl_list active_remote_outputs; // wlr_wl_active_remote_output.link uint32_t enter_serial; + // last requested output size. This is not the actual size that the + // compositor has accepted. + struct { + bool needs_ack; + uint32_t serial; + + int32_t width; + int32_t height; + } requested; + struct { struct wlr_wl_pointer *pointer; struct wl_surface *surface; @@ -182,6 +199,8 @@ bool create_wl_seat(struct wl_seat *wl_seat, struct wlr_wl_backend *wl, void destroy_wl_seat(struct wlr_wl_seat *seat); void destroy_wl_buffer(struct wlr_wl_buffer *buffer); +void surface_update(struct wlr_wl_output *output); + extern const struct wlr_pointer_impl wl_pointer_impl; extern const struct wlr_tablet_pad_impl wl_tablet_pad_impl; extern const struct wlr_tablet_impl wl_tablet_impl; From e7ee2a24425759d5719f0ccde1641bcf08af0696 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Thu, 30 Mar 2023 11:24:05 +0200 Subject: [PATCH 4/5] backend/wayland: handle scale --- backend/wayland/output.c | 36 ++++++++++++++++++++++++++++++------ backend/wayland/pointer.c | 5 +++-- backend/wayland/seat.c | 5 +++-- 3 files changed, 36 insertions(+), 10 deletions(-) diff --git a/backend/wayland/output.c b/backend/wayland/output.c index f2f4c68df..15f4335fc 100644 --- a/backend/wayland/output.c +++ b/backend/wayland/output.c @@ -447,6 +447,12 @@ static bool output_commit(struct wlr_output *wlr_output, return false; } + bool needs_commit = false; + if (state->committed & WLR_OUTPUT_STATE_SCALE) { + wl_surface_set_buffer_scale(output->surface, ceil(state->scale)); + needs_commit = true; + } + if (state->committed & WLR_OUTPUT_STATE_BUFFER) { if (output->requested.needs_ack) { output->requested.needs_ack = false; @@ -501,7 +507,7 @@ static bool output_commit(struct wlr_output *wlr_output, output->surface); } - wl_surface_commit(output->surface); + needs_commit = true; if (wp_feedback != NULL) { struct wlr_wl_presentation_feedback *feedback = @@ -526,6 +532,10 @@ static bool output_commit(struct wlr_output *wlr_output, } } + if (needs_commit) { + wl_surface_commit(output->surface); + } + wl_display_flush(output->backend->remote_display); if (state->committed & WLR_OUTPUT_STATE_MODE) { @@ -630,16 +640,18 @@ void update_wl_output_cursor(struct wlr_wl_output *output) { return; } + int scale = ceil(output->wlr_output.scale); wl_surface_attach(surface, buffer->wl_buffer, 0, 0); wl_surface_damage_buffer(surface, 0, 0, INT32_MAX, INT32_MAX); + wl_surface_set_buffer_scale(surface, scale); wl_surface_commit(surface); wl_display_flush(backend->remote_display); struct wlr_wl_seat *seat = pointer->seat; wl_pointer_set_cursor(seat->wl_pointer, output->enter_serial, - output->cursor.surface, output->cursor.hotspot_x, - output->cursor.hotspot_y); + output->cursor.surface, output->cursor.hotspot_x / scale, + output->cursor.hotspot_y / scale); } static bool output_move_cursor(struct wlr_output *_output, int x, int y) { @@ -666,16 +678,28 @@ void surface_update(struct wlr_wl_output *output) { return; } + uint32_t scale = 1; + + struct wlr_wl_active_remote_output *active; + wl_list_for_each(active, &output->active_remote_outputs, link) { + struct wlr_wl_remote_output *output = active->remote_output; + if (scale < output->scale) { + scale = output->scale; + } + } + struct wlr_output_state state = { - .committed = WLR_OUTPUT_STATE_MODE, + .committed = WLR_OUTPUT_STATE_MODE | WLR_OUTPUT_STATE_SCALE, .mode_type = WLR_OUTPUT_STATE_MODE_CUSTOM, + .scale = scale, .custom_mode = { - .width = output->requested.width, - .height = output->requested.height + .width = output->requested.width * scale, + .height = output->requested.height * scale }, }; wlr_output_send_request_state(&output->wlr_output, &state); + update_wl_output_cursor(output); } static void xdg_surface_handle_configure(void *data, diff --git a/backend/wayland/pointer.c b/backend/wayland/pointer.c index 4ce233e52..f50f6600f 100644 --- a/backend/wayland/pointer.c +++ b/backend/wayland/pointer.c @@ -87,11 +87,12 @@ static void pointer_handle_motion(void *data, struct wl_pointer *wl_pointer, } struct wlr_output *wlr_output = &pointer->output->wlr_output; + int scale = ceil(wlr_output->scale); struct wlr_pointer_motion_absolute_event event = { .pointer = &pointer->wlr_pointer, .time_msec = time, - .x = wl_fixed_to_double(sx) / wlr_output->width, - .y = wl_fixed_to_double(sy) / wlr_output->height, + .x = wl_fixed_to_double(sx) * scale / wlr_output->width, + .y = wl_fixed_to_double(sy) * scale / wlr_output->height, }; wl_signal_emit_mutable(&pointer->wlr_pointer.events.motion_absolute, &event); } diff --git a/backend/wayland/seat.c b/backend/wayland/seat.c index 46c6958b4..756551e4e 100644 --- a/backend/wayland/seat.c +++ b/backend/wayland/seat.c @@ -127,8 +127,9 @@ static void touch_coordinates_to_absolute(struct wlr_wl_seat *seat, */ struct wlr_wl_output *output, *tmp; wl_list_for_each_safe(output, tmp, &seat->backend->outputs, link) { - *sx = wl_fixed_to_double(x) / output->wlr_output.width; - *sy = wl_fixed_to_double(y) / output->wlr_output.height; + int scale = ceil(output->wlr_output.scale); + *sx = wl_fixed_to_double(x) * scale / output->wlr_output.width; + *sy = wl_fixed_to_double(y) * scale / output->wlr_output.height; return; // Choose the first output in the list } From f0b387db1ee053997063d8a0ce3d1014f6e072e5 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Thu, 6 Jan 2022 19:24:30 -0500 Subject: [PATCH 5/5] backend/wayland: handle subpixel --- backend/wayland/backend.c | 4 +++- backend/wayland/output.c | 9 ++++++++- include/backend/wayland.h | 1 + 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/backend/wayland/backend.c b/backend/wayland/backend.c index 6b9408c9e..025b90e83 100644 --- a/backend/wayland/backend.c +++ b/backend/wayland/backend.c @@ -252,7 +252,8 @@ static void wlr_output_handle_scale(void *data, 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 + struct wlr_wl_remote_output *output = data; + output->subpixel = subpixel; } static void wlr_output_handle_mode(void *data, struct wl_output *wl_output, @@ -448,6 +449,7 @@ static void registry_global(void *data, struct wl_registry *registry, output->scale = 1; output->name = name; output->backend = wl; + output->subpixel = WL_OUTPUT_SUBPIXEL_UNKNOWN; wl_list_insert(&wl->remote_outputs, &output->link); wl_output_add_listener(wl_output, &output_listener, output); diff --git a/backend/wayland/output.c b/backend/wayland/output.c index 15f4335fc..b581785b5 100644 --- a/backend/wayland/output.c +++ b/backend/wayland/output.c @@ -679,6 +679,7 @@ void surface_update(struct wlr_wl_output *output) { } uint32_t scale = 1; + enum wl_output_subpixel subpixel = WL_OUTPUT_SUBPIXEL_UNKNOWN; struct wlr_wl_active_remote_output *active; wl_list_for_each(active, &output->active_remote_outputs, link) { @@ -686,12 +687,18 @@ void surface_update(struct wlr_wl_output *output) { if (scale < output->scale) { scale = output->scale; } + + if (output->subpixel != WL_OUTPUT_SUBPIXEL_UNKNOWN) { + subpixel = output->subpixel; + } } struct wlr_output_state state = { - .committed = WLR_OUTPUT_STATE_MODE | WLR_OUTPUT_STATE_SCALE, + .committed = WLR_OUTPUT_STATE_MODE | WLR_OUTPUT_STATE_SCALE | + WLR_OUTPUT_STATE_SUBPIXEL, .mode_type = WLR_OUTPUT_STATE_MODE_CUSTOM, .scale = scale, + .subpixel = subpixel, .custom_mode = { .width = output->requested.width * scale, .height = output->requested.height * scale diff --git a/include/backend/wayland.h b/include/backend/wayland.h index 6a58e2b98..d5bc43e7d 100644 --- a/include/backend/wayland.h +++ b/include/backend/wayland.h @@ -56,6 +56,7 @@ struct wlr_wl_remote_output { struct wl_output *output; struct wlr_wl_backend *backend; uint32_t scale; + enum wl_output_subpixel subpixel; // we use this to identify the output in the // global registry so that we can remove it later