Skip to content

Commit

Permalink
tree/view: Send configure before mapping
Browse files Browse the repository at this point in the history
Sending 0,0 as configure dimensions indicate that the client is free to
pick its own dimensions. When tiling, the client needs to strictly
adhere to the tile dimensions. Sway's handling of this has been to send
a the appropriate dimensions in a new configure when the surface is
mapped, leading to the first buffer most likely being incorrectly sized.

Move the majority of the mapping logic to view_premap, issued on the
initial role commit rather than when mapping the view. This allow the
first configure to be driven by a tree transaction with the appropriate
geometr, and allows container siblings to start preparing earlier as
well, reducing the new window latency.

Fixes: #2176
  • Loading branch information
kennylevinsen committed Aug 25, 2024
1 parent 77b9dda commit 4f0392d
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 32 deletions.
13 changes: 11 additions & 2 deletions include/sway/tree/view.h
Original file line number Diff line number Diff line change
Expand Up @@ -286,15 +286,24 @@ 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.
*
* `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);
Expand Down
37 changes: 18 additions & 19 deletions sway/desktop/xdg_shell.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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();

Expand Down Expand Up @@ -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);
Expand Down
3 changes: 2 additions & 1 deletion sway/desktop/xwayland.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
22 changes: 12 additions & 10 deletions sway/tree/view.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand All @@ -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) {
Expand Down

0 comments on commit 4f0392d

Please sign in to comment.