mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2026-04-18 06:47:31 -04:00
backend/wayland: maintain a list of active outputs for each virtual WL display
This commit is contained in:
parent
152c58c340
commit
ecc3892808
3 changed files with 124 additions and 9 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue