surface: Make send_enter store entered outputs
wlr_surface_send_enter now stores outputs that have been entered. Combined with a new 'bind' event on wlr_output, this allows us to delay enter events as necessary until the respective wl_output global has been bound. Closes: https://github.com/swaywm/wlroots/issues/2466
This commit is contained in:
parent
754179dacd
commit
ebecc5404b
|
@ -166,6 +166,8 @@ struct wlr_output {
|
|||
struct wl_signal commit; // wlr_output_event_commit
|
||||
// Emitted right after the buffer has been presented to the user
|
||||
struct wl_signal present; // wlr_output_event_present
|
||||
// Emitted after a client bound the wl_output global
|
||||
struct wl_signal bind; // wlr_output_event_bind
|
||||
struct wl_signal enable;
|
||||
struct wl_signal mode;
|
||||
struct wl_signal scale;
|
||||
|
@ -233,6 +235,11 @@ struct wlr_output_event_present {
|
|||
uint32_t flags; // enum wlr_output_present_flag
|
||||
};
|
||||
|
||||
struct wlr_output_event_bind {
|
||||
struct wlr_output *output;
|
||||
struct wl_resource *resource;
|
||||
};
|
||||
|
||||
struct wlr_surface;
|
||||
|
||||
/**
|
||||
|
|
|
@ -67,6 +67,15 @@ struct wlr_surface_role {
|
|||
void (*precommit)(struct wlr_surface *surface);
|
||||
};
|
||||
|
||||
struct wlr_surface_output {
|
||||
struct wlr_surface *surface;
|
||||
struct wlr_output *output;
|
||||
|
||||
struct wl_list link; // wlr_surface::current_outputs
|
||||
struct wl_listener bind;
|
||||
struct wl_listener destroy;
|
||||
};
|
||||
|
||||
struct wlr_surface {
|
||||
struct wl_resource *resource;
|
||||
struct wlr_renderer *renderer;
|
||||
|
@ -126,6 +135,8 @@ struct wlr_surface {
|
|||
// wlr_subsurface::parent_pending_link
|
||||
struct wl_list subsurface_pending_list;
|
||||
|
||||
struct wl_list current_outputs; // wlr_surface_output::link
|
||||
|
||||
struct wl_listener renderer_destroy;
|
||||
|
||||
void *data;
|
||||
|
|
|
@ -93,6 +93,13 @@ static void output_bind(struct wl_client *wl_client, void *data,
|
|||
send_current_mode(resource);
|
||||
send_scale(resource);
|
||||
send_done(resource);
|
||||
|
||||
struct wlr_output_event_bind evt = {
|
||||
.output = output,
|
||||
.resource = resource,
|
||||
};
|
||||
|
||||
wlr_signal_emit_safe(&output->events.bind, &evt);
|
||||
}
|
||||
|
||||
void wlr_output_create_global(struct wlr_output *output) {
|
||||
|
@ -333,6 +340,7 @@ void wlr_output_init(struct wlr_output *output, struct wlr_backend *backend,
|
|||
wl_signal_init(&output->events.precommit);
|
||||
wl_signal_init(&output->events.commit);
|
||||
wl_signal_init(&output->events.present);
|
||||
wl_signal_init(&output->events.bind);
|
||||
wl_signal_init(&output->events.enable);
|
||||
wl_signal_init(&output->events.mode);
|
||||
wl_signal_init(&output->events.scale);
|
||||
|
|
|
@ -616,9 +616,16 @@ static void subsurface_destroy(struct wlr_subsurface *subsurface) {
|
|||
free(subsurface);
|
||||
}
|
||||
|
||||
static void surface_output_destroy(struct wlr_surface_output *surface_output);
|
||||
|
||||
static void surface_handle_resource_destroy(struct wl_resource *resource) {
|
||||
struct wlr_surface_output *surface_output, *tmp;
|
||||
struct wlr_surface *surface = wlr_surface_from_resource(resource);
|
||||
|
||||
wl_list_for_each_safe(surface_output, tmp, &surface->current_outputs, link) {
|
||||
surface_output_destroy(surface_output);
|
||||
}
|
||||
|
||||
wlr_signal_emit_safe(&surface->events.destroy, surface);
|
||||
|
||||
wl_list_remove(wl_resource_get_link(surface->resource));
|
||||
|
@ -676,6 +683,7 @@ struct wlr_surface *wlr_surface_create(struct wl_client *client,
|
|||
wl_signal_init(&surface->events.new_subsurface);
|
||||
wl_list_init(&surface->subsurfaces);
|
||||
wl_list_init(&surface->subsurface_pending_list);
|
||||
wl_list_init(&surface->current_outputs);
|
||||
pixman_region32_init(&surface->buffer_damage);
|
||||
pixman_region32_init(&surface->opaque_region);
|
||||
pixman_region32_init(&surface->input_region);
|
||||
|
@ -1091,10 +1099,59 @@ struct wlr_surface *wlr_surface_surface_at(struct wlr_surface *surface,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void surface_output_destroy(struct wlr_surface_output *surface_output) {
|
||||
wl_list_remove(&surface_output->bind.link);
|
||||
wl_list_remove(&surface_output->destroy.link);
|
||||
wl_list_remove(&surface_output->link);
|
||||
|
||||
free(surface_output);
|
||||
}
|
||||
|
||||
static void surface_handle_output_bind(struct wl_listener *listener,
|
||||
void *data) {
|
||||
struct wlr_output_event_bind *evt = data;
|
||||
struct wlr_surface_output *surface_output =
|
||||
wl_container_of(listener, surface_output, bind);
|
||||
struct wl_client *client = wl_resource_get_client(
|
||||
surface_output->surface->resource);
|
||||
if (client == wl_resource_get_client(evt->resource)) {
|
||||
wl_surface_send_enter(surface_output->surface->resource, evt->resource);
|
||||
}
|
||||
}
|
||||
|
||||
static void surface_handle_output_destroy(struct wl_listener *listener,
|
||||
void *data) {
|
||||
struct wlr_surface_output *surface_output =
|
||||
wl_container_of(listener, surface_output, destroy);
|
||||
surface_output_destroy(surface_output);
|
||||
}
|
||||
|
||||
void wlr_surface_send_enter(struct wlr_surface *surface,
|
||||
struct wlr_output *output) {
|
||||
struct wl_client *client = wl_resource_get_client(surface->resource);
|
||||
struct wlr_surface_output *surface_output;
|
||||
struct wl_resource *resource;
|
||||
|
||||
wl_list_for_each(surface_output, &surface->current_outputs, link) {
|
||||
if (surface_output->output == output) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
surface_output = calloc(1, sizeof(struct wlr_surface_output));
|
||||
if (surface_output == NULL) {
|
||||
return;
|
||||
}
|
||||
surface_output->bind.notify = surface_handle_output_bind;
|
||||
surface_output->destroy.notify = surface_handle_output_destroy;
|
||||
|
||||
wl_signal_add(&output->events.bind, &surface_output->bind);
|
||||
wl_signal_add(&output->events.destroy, &surface_output->destroy);
|
||||
|
||||
surface_output->surface = surface;
|
||||
surface_output->output = output;
|
||||
wl_list_insert(&surface->current_outputs, &surface_output->link);
|
||||
|
||||
wl_resource_for_each(resource, &output->resources) {
|
||||
if (client == wl_resource_get_client(resource)) {
|
||||
wl_surface_send_enter(surface->resource, resource);
|
||||
|
@ -1105,10 +1162,19 @@ void wlr_surface_send_enter(struct wlr_surface *surface,
|
|||
void wlr_surface_send_leave(struct wlr_surface *surface,
|
||||
struct wlr_output *output) {
|
||||
struct wl_client *client = wl_resource_get_client(surface->resource);
|
||||
struct wlr_surface_output *surface_output, *tmp;
|
||||
struct wl_resource *resource;
|
||||
wl_resource_for_each(resource, &output->resources) {
|
||||
if (client == wl_resource_get_client(resource)) {
|
||||
wl_surface_send_leave(surface->resource, resource);
|
||||
|
||||
wl_list_for_each_safe(surface_output, tmp,
|
||||
&surface->current_outputs, link) {
|
||||
if (surface_output->output == output) {
|
||||
surface_output_destroy(surface_output);
|
||||
wl_resource_for_each(resource, &output->resources) {
|
||||
if (client == wl_resource_get_client(resource)) {
|
||||
wl_surface_send_leave(surface->resource, resource);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue