From dec2565f2b6b0a723d08f025967ac8ff1b7ee756 Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Mon, 11 Apr 2022 21:33:15 +0300 Subject: [PATCH] xdg-toplevel: don't schedule configures on state requests --- include/wlr/types/wlr_xdg_shell.h | 8 ++++++++ tinywl/tinywl.c | 30 ++++++++++++++++++++++++++++++ types/xdg_shell/wlr_xdg_toplevel.c | 4 ---- 3 files changed, 38 insertions(+), 4 deletions(-) diff --git a/include/wlr/types/wlr_xdg_shell.h b/include/wlr/types/wlr_xdg_shell.h index 48bfbb97..95c6ee6c 100644 --- a/include/wlr/types/wlr_xdg_shell.h +++ b/include/wlr/types/wlr_xdg_shell.h @@ -147,8 +147,16 @@ struct wlr_xdg_toplevel { char *app_id; struct { + // Note: as per xdg-shell protocol, the compositor has to + // handle state requests by sending a configure event, + // even if it didn't actually change the state. Therefore, + // every compositor implementing xdg-shell support *must* + // listen to these signals and schedule a configure event + // immediately or at some time in the future; not doing so + // is a protocol violation. struct wl_signal request_maximize; struct wl_signal request_fullscreen; + struct wl_signal request_minimize; struct wl_signal request_move; struct wl_signal request_resize; diff --git a/tinywl/tinywl.c b/tinywl/tinywl.c index 290dd094..2ab0bcc0 100644 --- a/tinywl/tinywl.c +++ b/tinywl/tinywl.c @@ -85,6 +85,8 @@ struct tinywl_view { struct wl_listener destroy; struct wl_listener request_move; struct wl_listener request_resize; + struct wl_listener request_maximize; + struct wl_listener request_fullscreen; int x, y; }; @@ -619,6 +621,8 @@ static void xdg_toplevel_destroy(struct wl_listener *listener, void *data) { wl_list_remove(&view->destroy.link); wl_list_remove(&view->request_move.link); wl_list_remove(&view->request_resize.link); + wl_list_remove(&view->request_maximize.link); + wl_list_remove(&view->request_fullscreen.link); free(view); } @@ -684,6 +688,26 @@ static void xdg_toplevel_request_resize( begin_interactive(view, TINYWL_CURSOR_RESIZE, event->edges); } +static void xdg_toplevel_request_maximize( + struct wl_listener *listener, void *data) { + /* This event is raised when a client would like to maximize itself, + * typically because the user clicked on the maximize button on + * client-side decorations. tinywl doesn't support maximization, but + * to conform to xdg-shell protocol we still must send a configure. + * wlr_xdg_surface_schedule_configure() is used to send an empty reply. */ + struct tinywl_view *view = + wl_container_of(listener, view, request_maximize); + wlr_xdg_surface_schedule_configure(view->xdg_toplevel->base); +} + +static void xdg_toplevel_request_fullscreen( + struct wl_listener *listener, void *data) { + /* Just as with request_maximize, we must send a configure here. */ + struct tinywl_view *view = + wl_container_of(listener, view, request_fullscreen); + wlr_xdg_surface_schedule_configure(view->xdg_toplevel->base); +} + static void server_new_xdg_surface(struct wl_listener *listener, void *data) { /* This event is raised when wlr_xdg_shell receives a new xdg surface from a * client, either a toplevel (application window) or popup. */ @@ -730,6 +754,12 @@ static void server_new_xdg_surface(struct wl_listener *listener, void *data) { wl_signal_add(&toplevel->events.request_move, &view->request_move); view->request_resize.notify = xdg_toplevel_request_resize; wl_signal_add(&toplevel->events.request_resize, &view->request_resize); + view->request_maximize.notify = xdg_toplevel_request_maximize; + wl_signal_add(&toplevel->events.request_maximize, + &view->request_maximize); + view->request_fullscreen.notify = xdg_toplevel_request_fullscreen; + wl_signal_add(&toplevel->events.request_fullscreen, + &view->request_fullscreen); } int main(int argc, char *argv[]) { diff --git a/types/xdg_shell/wlr_xdg_toplevel.c b/types/xdg_shell/wlr_xdg_toplevel.c index a78a4e89..786cfdad 100644 --- a/types/xdg_shell/wlr_xdg_toplevel.c +++ b/types/xdg_shell/wlr_xdg_toplevel.c @@ -320,7 +320,6 @@ static void xdg_toplevel_handle_set_maximized(struct wl_client *client, wlr_xdg_toplevel_from_resource(resource); toplevel->requested.maximized = true; wlr_signal_emit_safe(&toplevel->events.request_maximize, NULL); - wlr_xdg_surface_schedule_configure(toplevel->base); } static void xdg_toplevel_handle_unset_maximized(struct wl_client *client, @@ -329,7 +328,6 @@ static void xdg_toplevel_handle_unset_maximized(struct wl_client *client, wlr_xdg_toplevel_from_resource(resource); toplevel->requested.maximized = false; wlr_signal_emit_safe(&toplevel->events.request_maximize, NULL); - wlr_xdg_surface_schedule_configure(toplevel->base); } static void handle_fullscreen_output_destroy(struct wl_listener *listener, @@ -369,7 +367,6 @@ static void xdg_toplevel_handle_set_fullscreen(struct wl_client *client, store_fullscreen_requested(toplevel, true, output); wlr_signal_emit_safe(&toplevel->events.request_fullscreen, NULL); - wlr_xdg_surface_schedule_configure(toplevel->base); } static void xdg_toplevel_handle_unset_fullscreen(struct wl_client *client, @@ -380,7 +377,6 @@ static void xdg_toplevel_handle_unset_fullscreen(struct wl_client *client, store_fullscreen_requested(toplevel, false, NULL); wlr_signal_emit_safe(&toplevel->events.request_fullscreen, NULL); - wlr_xdg_surface_schedule_configure(toplevel->base); } static void xdg_toplevel_handle_set_minimized(struct wl_client *client,