mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2026-04-20 06:47:19 -04:00
backend/wayland: maintain a list of active outputs for each virtual WL display
This commit is contained in:
parent
f8733c40d0
commit
8824fe2121
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,
|
.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,
|
static void wlr_output_handle_scale(void *data,
|
||||||
struct wl_output *wl_output, int32_t factor) {
|
struct wl_output *wl_output, int32_t factor) {
|
||||||
struct wlr_wl_remote_output *output = data;
|
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) {
|
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 = {
|
static const struct wl_output_listener output_listener = {
|
||||||
|
|
@ -436,6 +444,7 @@ static void registry_global(void *data, struct wl_registry *registry,
|
||||||
output->output = wl_output;
|
output->output = wl_output;
|
||||||
output->scale = 1;
|
output->scale = 1;
|
||||||
output->name = name;
|
output->name = name;
|
||||||
|
output->backend = wl;
|
||||||
|
|
||||||
wl_list_insert(&wl->remote_outputs, &output->link);
|
wl_list_insert(&wl->remote_outputs, &output->link);
|
||||||
wl_output_add_listener(wl_output, &output_listener, output);
|
wl_output_add_listener(wl_output, &output_listener, output);
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,12 @@ static void presentation_feedback_destroy(
|
||||||
free(feedback);
|
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,
|
static void presentation_feedback_handle_sync_output(void *data,
|
||||||
struct wp_presentation_feedback *feedback, struct wl_output *output) {
|
struct wp_presentation_feedback *feedback, struct wl_output *output) {
|
||||||
// This space is intentionally left blank
|
// This space is intentionally left blank
|
||||||
|
|
@ -288,6 +294,12 @@ static bool output_commit(struct wlr_output *wlr_output,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state->committed & WLR_OUTPUT_STATE_BUFFER) {
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
struct wp_presentation_feedback *wp_feedback = NULL;
|
struct wp_presentation_feedback *wp_feedback = NULL;
|
||||||
if (output->backend->presentation != NULL) {
|
if (output->backend->presentation != NULL) {
|
||||||
wp_feedback = wp_presentation_feedback(output->backend->presentation,
|
wp_feedback = wp_presentation_feedback(output->backend->presentation,
|
||||||
|
|
@ -414,6 +426,12 @@ static void output_destroy(struct wlr_output *wlr_output) {
|
||||||
presentation_feedback_destroy(feedback);
|
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) {
|
if (output->zxdg_toplevel_decoration_v1) {
|
||||||
zxdg_toplevel_decoration_v1_destroy(output->zxdg_toplevel_decoration_v1);
|
zxdg_toplevel_decoration_v1_destroy(output->zxdg_toplevel_decoration_v1);
|
||||||
}
|
}
|
||||||
|
|
@ -482,14 +500,41 @@ bool wlr_output_is_wl(struct wlr_output *wlr_output) {
|
||||||
return wlr_output->impl == &output_impl;
|
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,
|
static void xdg_surface_handle_configure(void *data,
|
||||||
struct xdg_surface *xdg_surface, uint32_t serial) {
|
struct xdg_surface *xdg_surface, uint32_t serial) {
|
||||||
struct wlr_wl_output *output = data;
|
struct wlr_wl_output *output = data;
|
||||||
assert(output && output->xdg_surface == xdg_surface);
|
assert(output && output->xdg_surface == xdg_surface);
|
||||||
|
|
||||||
|
if (wl_list_empty(&output->active_remote_outputs)) {
|
||||||
xdg_surface_ack_configure(xdg_surface, serial);
|
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 = {
|
static const struct xdg_surface_listener xdg_surface_listener = {
|
||||||
|
|
@ -506,12 +551,8 @@ static void xdg_toplevel_handle_configure(void *data,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_output_state state = {
|
output->requested.width = width;
|
||||||
.committed = WLR_OUTPUT_STATE_MODE,
|
output->requested.height = height;
|
||||||
.mode_type = WLR_OUTPUT_STATE_MODE_CUSTOM,
|
|
||||||
.custom_mode = { .width = width, .height = height },
|
|
||||||
};
|
|
||||||
wlr_output_send_request_state(&output->wlr_output, &state);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void xdg_toplevel_handle_close(void *data,
|
static void xdg_toplevel_handle_close(void *data,
|
||||||
|
|
@ -527,6 +568,50 @@ static const struct xdg_toplevel_listener xdg_toplevel_listener = {
|
||||||
.close = xdg_toplevel_handle_close,
|
.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_output *wlr_wl_output_create(struct wlr_backend *wlr_backend) {
|
||||||
struct wlr_wl_backend *backend = get_wl_backend_from_backend(wlr_backend);
|
struct wlr_wl_backend *backend = get_wl_backend_from_backend(wlr_backend);
|
||||||
if (!backend->started) {
|
if (!backend->started) {
|
||||||
|
|
@ -559,6 +644,7 @@ struct wlr_output *wlr_wl_output_create(struct wlr_backend *wlr_backend) {
|
||||||
|
|
||||||
output->backend = backend;
|
output->backend = backend;
|
||||||
wl_list_init(&output->presentation_feedbacks);
|
wl_list_init(&output->presentation_feedbacks);
|
||||||
|
wl_list_init(&output->active_remote_outputs);
|
||||||
|
|
||||||
output->surface = wl_compositor_create_surface(backend->compositor);
|
output->surface = wl_compositor_create_surface(backend->compositor);
|
||||||
if (!output->surface) {
|
if (!output->surface) {
|
||||||
|
|
@ -598,6 +684,7 @@ struct wlr_output *wlr_wl_output_create(struct wlr_backend *wlr_backend) {
|
||||||
&xdg_surface_listener, output);
|
&xdg_surface_listener, output);
|
||||||
xdg_toplevel_add_listener(output->xdg_toplevel,
|
xdg_toplevel_add_listener(output->xdg_toplevel,
|
||||||
&xdg_toplevel_listener, output);
|
&xdg_toplevel_listener, output);
|
||||||
|
wl_surface_add_listener(output->surface, &surface_listener, output);
|
||||||
wl_surface_commit(output->surface);
|
wl_surface_commit(output->surface);
|
||||||
|
|
||||||
wl_display_roundtrip(output->backend->remote_display);
|
wl_display_roundtrip(output->backend->remote_display);
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,7 @@ struct wlr_wl_backend {
|
||||||
|
|
||||||
struct wlr_wl_remote_output {
|
struct wlr_wl_remote_output {
|
||||||
struct wl_output *output;
|
struct wl_output *output;
|
||||||
|
struct wlr_wl_backend *backend;
|
||||||
uint32_t scale;
|
uint32_t scale;
|
||||||
|
|
||||||
// we use this to identify the output in the
|
// we use this to identify the output in the
|
||||||
|
|
@ -62,6 +63,11 @@ struct wlr_wl_remote_output {
|
||||||
struct wl_list link; // wlr_wl_backend.remote_outputs
|
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_wl_buffer {
|
||||||
struct wlr_buffer *buffer;
|
struct wlr_buffer *buffer;
|
||||||
struct wl_buffer *wl_buffer;
|
struct wl_buffer *wl_buffer;
|
||||||
|
|
@ -89,9 +95,20 @@ struct wlr_wl_output {
|
||||||
struct xdg_toplevel *xdg_toplevel;
|
struct xdg_toplevel *xdg_toplevel;
|
||||||
struct zxdg_toplevel_decoration_v1 *zxdg_toplevel_decoration_v1;
|
struct zxdg_toplevel_decoration_v1 *zxdg_toplevel_decoration_v1;
|
||||||
struct wl_list presentation_feedbacks;
|
struct wl_list presentation_feedbacks;
|
||||||
|
struct wl_list active_remote_outputs; // wlr_wl_active_remote_output.link
|
||||||
|
|
||||||
uint32_t enter_serial;
|
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 {
|
||||||
struct wlr_wl_pointer *pointer;
|
struct wlr_wl_pointer *pointer;
|
||||||
struct wl_surface *surface;
|
struct wl_surface *surface;
|
||||||
|
|
@ -167,6 +184,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_seat(struct wlr_wl_seat *seat);
|
||||||
void destroy_wl_buffer(struct wlr_wl_buffer *buffer);
|
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_pointer_impl wl_pointer_impl;
|
||||||
extern const struct wlr_tablet_pad_impl wl_tablet_pad_impl;
|
extern const struct wlr_tablet_pad_impl wl_tablet_pad_impl;
|
||||||
extern const struct wlr_tablet_impl wl_tablet_impl;
|
extern const struct wlr_tablet_impl wl_tablet_impl;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue