Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions include/waybox/server.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ struct wb_server {
struct wlr_xdg_output_manager_v1 *output_manager;
struct wlr_renderer *renderer;
struct wlr_scene *scene;
/* Container for all xdg toplevels, kept at a fixed z between the lower
* (background, bottom) and upper (top, overlay) layer-shell trees so panels
* like Waybar correctly render above ordinary windows. */
struct wlr_scene_tree *toplevel_tree;
struct wlr_scene_output_layout *scene_layout;
struct wlr_session *session;
struct wlr_subcompositor *subcompositor;
Expand Down
18 changes: 13 additions & 5 deletions waybox/decoration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,22 @@
* negotiation honours DecorMode::Full and client SSD requests. */
static constexpr bool kSsdAvailable = true;

/* Whether this toplevel should currently wear a server-side frame: the
* negotiated decoration is server-side and it is not fullscreen. */
/* Whether this toplevel should currently wear a server-side frame.
*
* SSD requires the client to participate in the xdg-decoration protocol: a
* client that never created a decoration object (notably GTK, which is
* CSD-only and always draws its own titlebar + shadow) cannot be told to drop
* its decorations, so imposing an SSD frame on it produces conflicting double
* decorations. We therefore only wear a frame when the client bound the
* decoration protocol for this toplevel; for such clients we then honour
* DecorMode and the client's requested mode. */
static bool toplevel_wants_ssd(struct wb_toplevel *toplevel) {
if (toplevel->xdg_toplevel->current.fullscreen)
return false;
bool client_wants_ssd = toplevel->decoration != nullptr &&
toplevel->decoration->requested_mode ==
WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE;
if (toplevel->decoration == nullptr)
return false; /* CSD-only client (e.g. GTK): leave its decorations be */
bool client_wants_ssd = toplevel->decoration->requested_mode ==
WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE;
return wb::negotiate_decoration(toplevel->decorations, client_wants_ssd,
kSsdAvailable) == wb::NegotiatedDecoration::ServerSide;
}
Expand Down
14 changes: 14 additions & 0 deletions waybox/output.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,20 @@ void new_output_notify(struct wb_server *server, void *data) {
&wlr_scene_tree_create(&server->scene->tree)->node;
}

/* Stack this output's layer trees around the shared toplevel container so
* panels render correctly: background/bottom below ordinary windows; the
* fullscreen, top and overlay layers (where panels like Waybar live) above
* them. New toplevels are children of toplevel_tree, so they never lift
* above the top/overlay layers. */
struct wlr_scene_node *tl = &server->toplevel_tree->node;
wlr_scene_node_place_below(&output->layers.shell_background->node, tl);
wlr_scene_node_place_below(&output->layers.shell_bottom->node, tl);
wlr_scene_node_place_above(&output->layers.shell_top->node, tl);
wlr_scene_node_place_above(&output->layers.shell_fullscreen->node,
&output->layers.shell_top->node);
wlr_scene_node_place_above(&output->layers.shell_overlay->node,
&output->layers.shell_fullscreen->node);

wl_list_insert(&server->outputs, &output->link);

/* Initialise the usable area to the full output; arrange_layers() will
Expand Down
5 changes: 5 additions & 0 deletions waybox/server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,11 @@ bool wb_start_server(struct wb_server* server) {
server->scene = wlr_scene_create();
server->scene_layout =
wlr_scene_attach_output_layout(server->scene, server->output_layout);
/* The toplevel container. Created up-front so per-output layer trees (made
* as outputs come up) can be stacked relative to it; toplevels are added as
* its children, so adding/raising a window never lifts it above the panel
* layers. */
server->toplevel_tree = wlr_scene_tree_create(&server->scene->tree);

const char *socket = wl_display_add_socket_auto(server->wl_display);
if (!socket) {
Expand Down
14 changes: 12 additions & 2 deletions waybox/xdg_shell.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -724,11 +724,21 @@ void set_toplevel_fullscreen(struct wb_toplevel *toplevel, bool fullscreen) {
struct wlr_output *wlr_output = get_active_output(toplevel);
struct wb_output *output = static_cast<struct wb_output *>(
wlr_output ? wlr_output->data : NULL);
if (output != NULL)
if (output != NULL) {
toplevel->geometry = output->geometry; /* layout box: pos + size */
/* Lift the window into the fullscreen layer so it covers panels
* (the top layer), which ordinary toplevels sit below. */
if (toplevel->scene_tree != NULL)
wlr_scene_node_reparent(&toplevel->scene_tree->node,
output->layers.shell_fullscreen);
}
raise_toplevel(toplevel);
} else {
toplevel->geometry = toplevel->restore_fullscreen;
/* Return to the ordinary toplevel container (below the panel layers). */
if (toplevel->scene_tree != NULL)
wlr_scene_node_reparent(&toplevel->scene_tree->node,
toplevel->server->toplevel_tree);
}

wlr_xdg_toplevel_set_fullscreen(toplevel->xdg_toplevel, fullscreen);
Expand Down Expand Up @@ -951,7 +961,7 @@ static void handle_new_xdg_toplevel(struct wb_server *server, void *data) {
* decoration nodes). For now the surface sits at the container origin: with
* no decorations the insets are zero, so this is identical to attaching the
* surface directly. */
toplevel->scene_tree = wlr_scene_tree_create(&toplevel->server->scene->tree);
toplevel->scene_tree = wlr_scene_tree_create(toplevel->server->toplevel_tree);
toplevel->surface_tree = wlr_scene_xdg_surface_create(
toplevel->scene_tree, xdg_toplevel->base);
/* Tag both the container and the surface tree so a click on a decoration
Expand Down