Skip to content

Commit

Permalink
Introduce stacking|tabbed_titlebar commands
Browse files Browse the repository at this point in the history
Stacking and tabbed layouts effectively override the titlebar control of
the border command, always showing the titlebar to allow navigation.

Allow users to also hide the titlebar of stacking/tabbed layouts,
through new commands that specify whether titlebars for these layouts
should always be visible (the default) or if they should follow the
active container's border configuration.
  • Loading branch information
kennylevinsen committed Aug 18, 2024
1 parent c30c451 commit 5b855f7
Show file tree
Hide file tree
Showing 11 changed files with 178 additions and 1 deletion.
4 changes: 4 additions & 0 deletions include/sway/commands.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ sway_cmd cmd_commands;
sway_cmd cmd_create_output;
sway_cmd cmd_default_border;
sway_cmd cmd_default_floating_border;
sway_cmd cmd_default_stacking_titlebar;
sway_cmd cmd_default_tabbed_titlebar;
sway_cmd cmd_default_orientation;
sway_cmd cmd_exec;
sway_cmd cmd_exec_always;
Expand Down Expand Up @@ -181,10 +183,12 @@ sway_cmd cmd_split;
sway_cmd cmd_splith;
sway_cmd cmd_splitt;
sway_cmd cmd_splitv;
sway_cmd cmd_stacking_titlebar;
sway_cmd cmd_sticky;
sway_cmd cmd_swaybg_command;
sway_cmd cmd_swaynag_command;
sway_cmd cmd_swap;
sway_cmd cmd_tabbed_titlebar;
sway_cmd cmd_tiling_drag;
sway_cmd cmd_tiling_drag_threshold;
sway_cmd cmd_title_align;
Expand Down
3 changes: 3 additions & 0 deletions include/sway/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,9 @@ struct sway_config {

bool has_focused_tab_title;

bool stacking_titlebar_follows_border;
bool tabbed_titlebar_follows_border;

// floating view
int32_t floating_maximum_width;
int32_t floating_maximum_height;
Expand Down
10 changes: 10 additions & 0 deletions include/sway/tree/container.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ struct sway_container_state {
bool border_left;
bool border_right;

bool stacking_titlebar_follows_border;
bool tabbed_titlebar_follows_border;

// These are in layout coordinates.
double content_x, content_y;
double content_width, content_height;
Expand Down Expand Up @@ -217,6 +220,13 @@ void container_set_geometry_from_content(struct sway_container *con);
*/
bool container_is_floating(struct sway_container *container);

/**
* Determine if the given container should have a titlebar.
*
* Uses pending container state.
*/
bool container_has_titlebar(struct sway_container *container);

/**
* Get a container's box in layout coordinates.
*/
Expand Down
4 changes: 4 additions & 0 deletions sway/commands.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ static const struct cmd_handler handlers[] = {
{ "client.urgent", cmd_client_urgent },
{ "default_border", cmd_default_border },
{ "default_floating_border", cmd_default_floating_border },
{ "default_stacking_titlebar", cmd_default_stacking_titlebar },
{ "default_tabbed_titlebar", cmd_default_tabbed_titlebar },
{ "exec", cmd_exec },
{ "exec_always", cmd_exec_always },
{ "floating_maximum_size", cmd_floating_maximum_size },
Expand Down Expand Up @@ -135,8 +137,10 @@ static const struct cmd_handler command_handlers[] = {
{ "splith", cmd_splith },
{ "splitt", cmd_splitt },
{ "splitv", cmd_splitv },
{ "stacking_titlebar", cmd_stacking_titlebar },
{ "sticky", cmd_sticky },
{ "swap", cmd_swap },
{ "tabbed_titlebar", cmd_tabbed_titlebar },
{ "title_format", cmd_title_format },
{ "unmark", cmd_unmark },
{ "urgent", cmd_urgent },
Expand Down
40 changes: 40 additions & 0 deletions sway/commands/default_stacking_titlebar.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#include "log.h"
#include "sway/commands.h"
#include "sway/config.h"
#include "sway/tree/container.h"

struct cmd_results *cmd_default_stacking_titlebar(int argc, char **argv) {
struct cmd_results *error = NULL;
if ((error = checkarg(argc, "default_stacking_titlebar", EXPECTED_EQUAL_TO, 1))) {
return error;
}

if (strcmp(argv[0], "always_visible") == 0) {
config->stacking_titlebar_follows_border = false;
} else if (strcmp(argv[0], "follows_border") == 0) {
config->stacking_titlebar_follows_border = true;
} else {
return cmd_results_new(CMD_INVALID,
"Expected 'default_stacking_titlebar <always_visible|follows_border>");
}

return cmd_results_new(CMD_SUCCESS, NULL);
}

struct cmd_results *cmd_default_tabbed_titlebar(int argc, char **argv) {
struct cmd_results *error = NULL;
if ((error = checkarg(argc, "default_tabbed_titlebar", EXPECTED_EQUAL_TO, 1))) {
return error;
}

if (strcmp(argv[0], "always_visible") == 0) {
config->tabbed_titlebar_follows_border = false;
} else if (strcmp(argv[0], "follows_border") == 0) {
config->tabbed_titlebar_follows_border = true;
} else {
return cmd_results_new(CMD_INVALID,
"Expected 'default_tabbed_titlebar <always_visible|follows_border>");
}

return cmd_results_new(CMD_SUCCESS, NULL);
}
64 changes: 64 additions & 0 deletions sway/commands/stacking_titlebar.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#include "log.h"
#include "sway/commands.h"
#include "sway/config.h"
#include "sway/tree/arrange.h"
#include "sway/tree/container.h"
#include "sway/tree/view.h"

struct cmd_results *cmd_stacking_titlebar(int argc, char **argv) {
struct cmd_results *error = NULL;
if ((error = checkarg(argc, "border", EXPECTED_EQUAL_TO, 1))) {
return error;
}

struct sway_container *container = config->handler_context.container;
if (!container) {
return cmd_results_new(CMD_INVALID, "No container to set");
}

if (strcmp(argv[0], "always_visible") == 0) {
container->pending.stacking_titlebar_follows_border = false;
} else if (strcmp(argv[0], "follows_border") == 0) {
container->pending.stacking_titlebar_follows_border = true;
} else {
return cmd_results_new(CMD_INVALID,
"Expected 'stacking_titlebar <always_visible|follows_border>");
}

if (container_is_floating(container)) {
container_set_geometry_from_content(container);
}

arrange_container(container);

return cmd_results_new(CMD_SUCCESS, NULL);
}

struct cmd_results *cmd_tabbed_titlebar(int argc, char **argv) {
struct cmd_results *error = NULL;
if ((error = checkarg(argc, "border", EXPECTED_EQUAL_TO, 1))) {
return error;
}

struct sway_container *container = config->handler_context.container;
if (!container) {
return cmd_results_new(CMD_INVALID, "No container to set");
}

if (strcmp(argv[0], "always_visible") == 0) {
container->pending.tabbed_titlebar_follows_border = false;
} else if (strcmp(argv[0], "follows_border") == 0) {
container->pending.tabbed_titlebar_follows_border = true;
} else {
return cmd_results_new(CMD_INVALID,
"Expected 'tabbed_titlebar <always_visible|follows_border>");
}

if (container_is_floating(container)) {
container_set_geometry_from_content(container);
}

arrange_container(container);

return cmd_results_new(CMD_SUCCESS, NULL);
}
10 changes: 10 additions & 0 deletions sway/desktop/transaction.c
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,11 @@ static void arrange_children(enum sway_container_layout layout, list_t *children
title_bar_height = 0;
}

if (active && active->current.tabbed_titlebar_follows_border &&
active->current.border != B_NORMAL) {
title_bar_height = 0;
}

double w = (double) width / children->length;
int title_offset = 0;
for (int i = 0; i < children->length; i++) {
Expand Down Expand Up @@ -329,6 +334,11 @@ static void arrange_children(enum sway_container_layout layout, list_t *children
title_bar_height = 0;
}

if (active && active->current.stacking_titlebar_follows_border &&
active->current.border != B_NORMAL) {
title_bar_height = 0;
}

int title_height = title_bar_height * children->length;

int y = 0;
Expand Down
2 changes: 2 additions & 0 deletions sway/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ sway_sources = files(
'commands/create_output.c',
'commands/default_border.c',
'commands/default_floating_border.c',
'commands/default_stacking_titlebar.c',
'commands/default_orientation.c',
'commands/exit.c',
'commands/exec.c',
Expand All @@ -69,6 +70,7 @@ sway_sources = files(
'commands/fullscreen.c',
'commands/gaps.c',
'commands/gesture.c',
'commands/stacking_titlebar.c',
'commands/hide_edge_borders.c',
'commands/inhibit_idle.c',
'commands/kill.c',
Expand Down
18 changes: 18 additions & 0 deletions sway/sway.5.scd
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,16 @@ They are expected to be used with *bindsym* or at runtime through *swaymsg*(1).
*border* toggle
Cycles through the available border styles.

*stacking_titlebar* always_visible|follows_border
Set whether the titlebar for contains with stacking layouts should always
be visible (the default) or if it should respect the border setting like
other layouts.

*tabbed_titlebar* always_visible|follows_border
Set whether the titlebar for contains with tabbed layouts should always
be visible (the default) or if it should respect the border setting like
other layouts.

*exit*
Exit sway and end your Wayland session.

Expand Down Expand Up @@ -677,6 +687,14 @@ The default colors are:
windows that are spawned in floating mode, not windows that become floating
afterwards.

*default_stacking_titlebar* always_visible|follows_border
Set the default stacking titlebar setting for new windows. Config reload
won't affect existing windows, only newly created ones after the reload.

*default_tabbed_titlebar* always_visible|follows_border
Set the default tabbed titlebar setting for new windows. Config reload
won't affect existing windows, only newly created ones after the reload.

*exec* <shell command>
Executes _shell command_ with sh.

Expand Down
18 changes: 18 additions & 0 deletions sway/tree/container.c
Original file line number Diff line number Diff line change
Expand Up @@ -1002,6 +1002,24 @@ bool container_is_floating(struct sway_container *container) {
return false;
}

bool container_has_titlebar(struct sway_container *container) {
switch (container->pending.layout) {
case L_NONE:
return false;
case L_HORIZ:
case L_VERT:
return container->pending.border == B_NORMAL;
case L_STACKED:
return container->pending.border == B_NORMAL ||
!container->pending.stacking_titlebar_follows_border;
case L_TABBED:
return container->pending.border == B_NORMAL ||
!container->pending.tabbed_titlebar_follows_border;
default:
abort();
}
}

void container_get_box(struct sway_container *container, struct wlr_box *box) {
box->x = container->pending.x;
box->y = container->pending.y;
Expand Down
6 changes: 5 additions & 1 deletion sway/tree/view.c
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ void view_autoconfigure(struct sway_view *view) {
}
}

if (!container_is_floating(con)) {
if (!container_is_floating(con) && container_has_titlebar(con)) {
// In a tabbed or stacked container, the container's y is the top of the
// title area. We have to offset the surface y by the height of the title,
// bar, and disable any top border because we'll always have the title bar.
Expand Down Expand Up @@ -819,6 +819,10 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface,
view->container->pending.border_thickness = config->border_thickness;
view_set_tiled(view, true);
}
view->container->pending.stacking_titlebar_follows_border =
config->stacking_titlebar_follows_border;
view->container->pending.tabbed_titlebar_follows_border =
config->tabbed_titlebar_follows_border;

if (config->popup_during_fullscreen == POPUP_LEAVE &&
container->pending.workspace &&
Expand Down

0 comments on commit 5b855f7

Please sign in to comment.