aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/wlr/types/wlr_xdg_shell.h6
-rw-r--r--types/xdg_shell/wlr_xdg_surface.c5
-rw-r--r--types/xdg_shell/wlr_xdg_toplevel.c28
3 files changed, 37 insertions, 2 deletions
diff --git a/include/wlr/types/wlr_xdg_shell.h b/include/wlr/types/wlr_xdg_shell.h
index d813ad65..804b0083 100644
--- a/include/wlr/types/wlr_xdg_shell.h
+++ b/include/wlr/types/wlr_xdg_shell.h
@@ -105,6 +105,12 @@ struct wlr_xdg_toplevel_state {
uint32_t width, height;
uint32_t max_width, max_height;
uint32_t min_width, min_height;
+
+ // Since the fullscreen request may be made before the toplevel's surface
+ // is mapped, this is used to store the requested fullscreen output (if
+ // any) for wlr_xdg_toplevel::client_pending.
+ struct wlr_output *fullscreen_output;
+ struct wl_listener fullscreen_output_destroy;
};
struct wlr_xdg_toplevel {
diff --git a/types/xdg_shell/wlr_xdg_surface.c b/types/xdg_shell/wlr_xdg_surface.c
index ada5b419..e3f13e0e 100644
--- a/types/xdg_shell/wlr_xdg_surface.c
+++ b/types/xdg_shell/wlr_xdg_surface.c
@@ -459,6 +459,11 @@ void reset_xdg_surface(struct wlr_xdg_surface *xdg_surface) {
wl_resource_set_user_data(xdg_surface->toplevel->resource, NULL);
xdg_surface->toplevel->resource = NULL;
+ if (xdg_surface->toplevel->client_pending.fullscreen_output) {
+ struct wlr_xdg_toplevel_state *client_pending =
+ &xdg_surface->toplevel->client_pending;
+ wl_list_remove(&client_pending->fullscreen_output_destroy.link);
+ }
free(xdg_surface->toplevel);
xdg_surface->toplevel = NULL;
break;
diff --git a/types/xdg_shell/wlr_xdg_toplevel.c b/types/xdg_shell/wlr_xdg_toplevel.c
index d3ee0cb7..96bb0537 100644
--- a/types/xdg_shell/wlr_xdg_toplevel.c
+++ b/types/xdg_shell/wlr_xdg_toplevel.c
@@ -375,6 +375,30 @@ static void xdg_toplevel_handle_unset_maximized(struct wl_client *client,
wlr_signal_emit_safe(&surface->toplevel->events.request_maximize, surface);
}
+static void handle_fullscreen_output_destroy(struct wl_listener *listener,
+ void *data) {
+ struct wlr_xdg_toplevel_state *state =
+ wl_container_of(listener, state, fullscreen_output_destroy);
+ state->fullscreen_output = NULL;
+ wl_list_remove(&state->fullscreen_output_destroy.link);
+}
+
+static void store_fullscreen_pending(struct wlr_xdg_surface *surface,
+ bool fullscreen, struct wlr_output *output) {
+ struct wlr_xdg_toplevel_state *state = &surface->toplevel->client_pending;
+ state->fullscreen = fullscreen;
+ if (state->fullscreen_output) {
+ wl_list_remove(&state->fullscreen_output_destroy.link);
+ }
+ state->fullscreen_output = output;
+ if (state->fullscreen_output) {
+ state->fullscreen_output_destroy.notify =
+ handle_fullscreen_output_destroy;
+ wl_signal_add(&state->fullscreen_output->events.destroy,
+ &state->fullscreen_output_destroy);
+ }
+}
+
static void xdg_toplevel_handle_set_fullscreen(struct wl_client *client,
struct wl_resource *resource, struct wl_resource *output_resource) {
struct wlr_xdg_surface *surface =
@@ -385,7 +409,7 @@ static void xdg_toplevel_handle_set_fullscreen(struct wl_client *client,
output = wlr_output_from_resource(output_resource);
}
- surface->toplevel->client_pending.fullscreen = true;
+ store_fullscreen_pending(surface, true, output);
struct wlr_xdg_toplevel_set_fullscreen_event event = {
.surface = surface,
@@ -401,7 +425,7 @@ static void xdg_toplevel_handle_unset_fullscreen(struct wl_client *client,
struct wlr_xdg_surface *surface =
wlr_xdg_surface_from_toplevel_resource(resource);
- surface->toplevel->client_pending.fullscreen = false;
+ store_fullscreen_pending(surface, false, NULL);
struct wlr_xdg_toplevel_set_fullscreen_event event = {
.surface = surface,