This commit is contained in:
Kenny Levinsen 2024-11-05 14:03:20 +07:00 committed by GitHub
commit c172987159
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 72 additions and 36 deletions

View File

@ -284,7 +284,21 @@ void view_destroy(struct sway_view *view);
void view_begin_destroy(struct sway_view *view); void view_begin_destroy(struct sway_view *view);
/** /**
* Map a view, ie. make it visible in the tree. * Perform post-map setup like updating focus. view_setup 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.
*
* This may bail early for some views if the surface is not mapped, in which
* case it should be called again before view_map once the surface is mapped.
* It is safe to call view_setup adancegain even if the first call before
* surface map succeeded.
* *
* `fullscreen` should be set to true (and optionally `fullscreen_output` * `fullscreen` should be set to true (and optionally `fullscreen_output`
* should be populated) if the view should be made fullscreen immediately. * should be populated) if the view should be made fullscreen immediately.
@ -292,7 +306,7 @@ void view_begin_destroy(struct sway_view *view);
* `decoration` should be set to true if the client prefers CSD. The client's * `decoration` should be set to true if the client prefers CSD. The client's
* preference may be ignored. * preference may be ignored.
*/ */
void view_map(struct sway_view *view, struct wlr_surface *wlr_surface, void view_setup(struct sway_view *view, struct wlr_surface *wlr_surface,
bool fullscreen, struct wlr_output *fullscreen_output, bool decoration); bool fullscreen, struct wlr_output *fullscreen_output, bool decoration);
void view_unmap(struct sway_view *view); void view_unmap(struct sway_view *view);

View File

@ -277,6 +277,20 @@ static const struct sway_view_impl view_impl = {
.destroy = destroy, .destroy = destroy,
}; };
static bool view_wants_csd(struct sway_view *view) {
struct wlr_xdg_toplevel *toplevel = view->wlr_xdg_toplevel;
struct wlr_xdg_surface *xdg_surface = toplevel->base;
if (view->xdg_decoration) {
enum wlr_xdg_toplevel_decoration_v1_mode mode =
view->xdg_decoration->wlr_xdg_decoration->requested_mode;
return mode == WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE;
}
struct sway_server_decoration *deco =
decoration_from_surface(xdg_surface->surface);
return !deco || deco->wlr_server_decoration->mode ==
WLR_SERVER_DECORATION_MANAGER_MODE_CLIENT;
}
static void handle_commit(struct wl_listener *listener, void *data) { static void handle_commit(struct wl_listener *listener, void *data) {
struct sway_xdg_shell_view *xdg_shell_view = struct sway_xdg_shell_view *xdg_shell_view =
wl_container_of(listener, xdg_shell_view, commit); wl_container_of(listener, xdg_shell_view, commit);
@ -287,10 +301,14 @@ static void handle_commit(struct wl_listener *listener, void *data) {
if (view->xdg_decoration != NULL) { if (view->xdg_decoration != NULL) {
set_xdg_decoration_mode(view->xdg_decoration); set_xdg_decoration_mode(view->xdg_decoration);
} }
// XXX: https://github.com/swaywm/sway/issues/2176
wlr_xdg_surface_schedule_configure(xdg_surface); wlr_xdg_surface_schedule_configure(xdg_surface);
wlr_xdg_toplevel_set_wm_capabilities(view->wlr_xdg_toplevel, wlr_xdg_toplevel_set_wm_capabilities(view->wlr_xdg_toplevel,
XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN); XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN);
view_setup(&xdg_shell_view->view, xdg_surface->surface, false, NULL,
view_wants_csd(&xdg_shell_view->view));
transaction_commit_dirty();
// TODO: wlr_xdg_toplevel_set_bounds() // TODO: wlr_xdg_toplevel_set_bounds()
return; return;
} }
@ -465,23 +483,8 @@ static void handle_map(struct wl_listener *listener, void *data) {
view->natural_width = toplevel->base->geometry.width; view->natural_width = toplevel->base->geometry.width;
view->natural_height = toplevel->base->geometry.height; view->natural_height = toplevel->base->geometry.height;
bool csd = false; view_setup(view, toplevel->base->surface, false, NULL, view_wants_csd(view));
view_map(view, toplevel->base->surface);
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);
transaction_commit_dirty(); transaction_commit_dirty();
@ -518,7 +521,8 @@ static void handle_destroy(struct wl_listener *listener, void *data) {
struct sway_xdg_shell_view *xdg_shell_view = struct sway_xdg_shell_view *xdg_shell_view =
wl_container_of(listener, xdg_shell_view, destroy); wl_container_of(listener, xdg_shell_view, destroy);
struct sway_view *view = &xdg_shell_view->view; 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; return;
} }
wl_list_remove(&xdg_shell_view->destroy.link); wl_list_remove(&xdg_shell_view->destroy.link);

View File

@ -526,7 +526,8 @@ static void handle_map(struct wl_listener *listener, void *data) {
xwayland_view->commit.notify = handle_commit; xwayland_view->commit.notify = handle_commit;
// Put it back into the tree // Put it back into the tree
view_map(view, xsurface->surface, xsurface->fullscreen, NULL, false); view_setup(view, xsurface->surface, xsurface->fullscreen, NULL, false);
view_map(view, xsurface->surface);
xwayland_view->surface_tree = wlr_scene_subsurface_tree_create( xwayland_view->surface_tree = wlr_scene_subsurface_tree_create(
xwayland_view->view.content_tree, xsurface->surface); xwayland_view->view.content_tree, xsurface->surface);

View File

@ -711,12 +711,23 @@ static void handle_foreign_destroy(
wl_list_remove(&view->foreign_destroy.link); wl_list_remove(&view->foreign_destroy.link);
} }
void view_map(struct sway_view *view, struct wlr_surface *wlr_surface, void view_setup(struct sway_view *view, struct wlr_surface *wlr_surface,
bool fullscreen, struct wlr_output *fullscreen_output, bool fullscreen, struct wlr_output *fullscreen_output,
bool decoration) { bool decoration) {
if (!sway_assert(view->surface == NULL, "cannot map mapped view")) { if (view->surface) {
// Setup has already already completed
return; return;
} }
if (!wlr_surface->mapped && view->impl->wants_floating &&
view->impl->wants_floating(view)) {
// Configuring floating containers before the surface is mapped lead to
// us accidentally sending the configured minimum dimensions, which we
// only want to send if the client comes up with unreasonably small
// dimensions. As a hack, just skip this scenario for now and have the
// caller call view_setup again after the surface has been mapped.
return;
}
view->surface = wlr_surface; view->surface = wlr_surface;
view_populate_pid(view); view_populate_pid(view);
view->container = container_create(view); view->container = container_create(view);
@ -843,6 +854,24 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface,
view_execute_criteria(view); 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);
}
if (view->ext_foreign_toplevel) {
update_ext_foreign_toplevel(view);
}
}
void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) {
if (!sway_assert(view->surface != NULL, "cannot map view that has not been setup")) {
return;
}
bool set_focus = should_focus(view); bool set_focus = should_focus(view);
#if WLR_HAS_XWAYLAND #if WLR_HAS_XWAYLAND
@ -856,18 +885,6 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface,
if (set_focus) { if (set_focus) {
input_manager_set_focus(&view->container->node); input_manager_set_focus(&view->container->node);
} }
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) { void view_unmap(struct sway_view *view) {