diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 14aad1a183..17d3dea94e 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -286,7 +286,16 @@ void view_destroy(struct sway_view *view); void view_begin_destroy(struct sway_view *view); /** - * Map a view, ie. make it visible in the tree. + * Map a view, ie. make it visible in the tree. view_premap must be called + * before calling view_map. + */ +void view_map(struct sway_view *view, struct wlr_surface *wlr_surface); + +/** + * Prepare the view for its upcoming mapping, sending the intended dimensions + * so that the first frame has a chance of being correct. If CSD preferences or + * floating tendency changes, this may turn out to be inaccurate but no worse + * than skipping the step. * * `fullscreen` should be set to true (and optionally `fullscreen_output` * should be populated) if the view should be made fullscreen immediately. @@ -294,7 +303,7 @@ void view_begin_destroy(struct sway_view *view); * `decoration` should be set to true if the client prefers CSD. The client's * preference may be ignored. */ -void view_map(struct sway_view *view, struct wlr_surface *wlr_surface, +void view_premap(struct sway_view *view, struct wlr_surface *wlr_surface, bool fullscreen, struct wlr_output *fullscreen_output, bool decoration); void view_unmap(struct sway_view *view); diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index 3aed4ec7eb..7ebf206d41 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c @@ -287,10 +287,25 @@ static void handle_commit(struct wl_listener *listener, void *data) { if (view->xdg_decoration != NULL) { set_xdg_decoration_mode(view->xdg_decoration); } - // XXX: https://github.com/swaywm/sway/issues/2176 + + bool csd = false; + if (view->xdg_decoration) { + enum wlr_xdg_toplevel_decoration_v1_mode mode = + view->xdg_decoration->wlr_xdg_decoration->requested_mode; + csd = mode == WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE; + } else { + struct sway_server_decoration *deco = + decoration_from_surface(xdg_surface->surface); + csd = !deco || deco->wlr_server_decoration->mode == + WLR_SERVER_DECORATION_MANAGER_MODE_CLIENT; + } + wlr_xdg_surface_schedule_configure(xdg_surface); wlr_xdg_toplevel_set_wm_capabilities(view->wlr_xdg_toplevel, XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN); + view_premap(&xdg_shell_view->view, xdg_surface->surface, false, NULL, csd); + transaction_commit_dirty(); + // TODO: wlr_xdg_toplevel_set_bounds() return; } @@ -465,23 +480,7 @@ static void handle_map(struct wl_listener *listener, void *data) { view->natural_width = toplevel->base->geometry.width; view->natural_height = toplevel->base->geometry.height; - bool csd = false; - - if (view->xdg_decoration) { - enum wlr_xdg_toplevel_decoration_v1_mode mode = - view->xdg_decoration->wlr_xdg_decoration->requested_mode; - csd = mode == WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE; - } else { - struct sway_server_decoration *deco = - decoration_from_surface(toplevel->base->surface); - csd = !deco || deco->wlr_server_decoration->mode == - WLR_SERVER_DECORATION_MANAGER_MODE_CLIENT; - } - - view_map(view, toplevel->base->surface, - toplevel->requested.fullscreen, - toplevel->requested.fullscreen_output, - csd); + view_map(view, toplevel->base->surface); transaction_commit_dirty(); @@ -518,7 +517,7 @@ static void handle_destroy(struct wl_listener *listener, void *data) { struct sway_xdg_shell_view *xdg_shell_view = wl_container_of(listener, xdg_shell_view, destroy); struct sway_view *view = &xdg_shell_view->view; - if (!sway_assert(view->surface == NULL, "Tried to destroy a mapped view")) { + if (!sway_assert(view->surface == NULL || !view->surface->mapped, "Tried to destroy a mapped view")) { return; } wl_list_remove(&xdg_shell_view->destroy.link); diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index b83537a0a8..f622db2b96 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -526,7 +526,8 @@ static void handle_map(struct wl_listener *listener, void *data) { xwayland_view->commit.notify = handle_commit; // Put it back into the tree - view_map(view, xsurface->surface, xsurface->fullscreen, NULL, false); + view_premap(view, xsurface->surface, xsurface->fullscreen, NULL, false); + view_map(view, xsurface->surface); xwayland_view->surface_tree = wlr_scene_subsurface_tree_create( xwayland_view->view.content_tree, xsurface->surface); diff --git a/sway/tree/view.c b/sway/tree/view.c index d25a09c2a2..708b9b6c43 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -714,10 +714,10 @@ static void handle_foreign_destroy( wl_list_remove(&view->foreign_destroy.link); } -void view_map(struct sway_view *view, struct wlr_surface *wlr_surface, +void view_premap(struct sway_view *view, struct wlr_surface *wlr_surface, bool fullscreen, struct wlr_output *fullscreen_output, bool decoration) { - if (!sway_assert(view->surface == NULL, "cannot map mapped view")) { + if (!sway_assert(view->surface == NULL, "cannot premap mapped view")) { return; } view->surface = wlr_surface; @@ -846,6 +846,16 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface, view_execute_criteria(view); + const char *app_id; + const char *class; + if ((app_id = view_get_app_id(view)) != NULL) { + wlr_foreign_toplevel_handle_v1_set_app_id(view->foreign_toplevel, app_id); + } else if ((class = view_get_class(view)) != NULL) { + wlr_foreign_toplevel_handle_v1_set_app_id(view->foreign_toplevel, class); + } +} + +void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { bool set_focus = should_focus(view); #if WLR_HAS_XWAYLAND @@ -863,14 +873,6 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface, if (view->ext_foreign_toplevel) { update_ext_foreign_toplevel(view); } - - const char *app_id; - const char *class; - if ((app_id = view_get_app_id(view)) != NULL) { - wlr_foreign_toplevel_handle_v1_set_app_id(view->foreign_toplevel, app_id); - } else if ((class = view_get_class(view)) != NULL) { - wlr_foreign_toplevel_handle_v1_set_app_id(view->foreign_toplevel, class); - } } void view_unmap(struct sway_view *view) {