mirror of
https://github.com/swaywm/sway.git
synced 2024-11-27 18:31:28 +00:00
Introduce stacking|tabbed_titlebar commands
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.
This commit is contained in:
parent
c30c451907
commit
5b855f7168
|
@ -124,6 +124,8 @@ sway_cmd cmd_commands;
|
||||||
sway_cmd cmd_create_output;
|
sway_cmd cmd_create_output;
|
||||||
sway_cmd cmd_default_border;
|
sway_cmd cmd_default_border;
|
||||||
sway_cmd cmd_default_floating_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_default_orientation;
|
||||||
sway_cmd cmd_exec;
|
sway_cmd cmd_exec;
|
||||||
sway_cmd cmd_exec_always;
|
sway_cmd cmd_exec_always;
|
||||||
|
@ -181,10 +183,12 @@ sway_cmd cmd_split;
|
||||||
sway_cmd cmd_splith;
|
sway_cmd cmd_splith;
|
||||||
sway_cmd cmd_splitt;
|
sway_cmd cmd_splitt;
|
||||||
sway_cmd cmd_splitv;
|
sway_cmd cmd_splitv;
|
||||||
|
sway_cmd cmd_stacking_titlebar;
|
||||||
sway_cmd cmd_sticky;
|
sway_cmd cmd_sticky;
|
||||||
sway_cmd cmd_swaybg_command;
|
sway_cmd cmd_swaybg_command;
|
||||||
sway_cmd cmd_swaynag_command;
|
sway_cmd cmd_swaynag_command;
|
||||||
sway_cmd cmd_swap;
|
sway_cmd cmd_swap;
|
||||||
|
sway_cmd cmd_tabbed_titlebar;
|
||||||
sway_cmd cmd_tiling_drag;
|
sway_cmd cmd_tiling_drag;
|
||||||
sway_cmd cmd_tiling_drag_threshold;
|
sway_cmd cmd_tiling_drag_threshold;
|
||||||
sway_cmd cmd_title_align;
|
sway_cmd cmd_title_align;
|
||||||
|
|
|
@ -583,6 +583,9 @@ struct sway_config {
|
||||||
|
|
||||||
bool has_focused_tab_title;
|
bool has_focused_tab_title;
|
||||||
|
|
||||||
|
bool stacking_titlebar_follows_border;
|
||||||
|
bool tabbed_titlebar_follows_border;
|
||||||
|
|
||||||
// floating view
|
// floating view
|
||||||
int32_t floating_maximum_width;
|
int32_t floating_maximum_width;
|
||||||
int32_t floating_maximum_height;
|
int32_t floating_maximum_height;
|
||||||
|
|
|
@ -60,6 +60,9 @@ struct sway_container_state {
|
||||||
bool border_left;
|
bool border_left;
|
||||||
bool border_right;
|
bool border_right;
|
||||||
|
|
||||||
|
bool stacking_titlebar_follows_border;
|
||||||
|
bool tabbed_titlebar_follows_border;
|
||||||
|
|
||||||
// These are in layout coordinates.
|
// These are in layout coordinates.
|
||||||
double content_x, content_y;
|
double content_x, content_y;
|
||||||
double content_width, content_height;
|
double content_width, content_height;
|
||||||
|
@ -217,6 +220,13 @@ void container_set_geometry_from_content(struct sway_container *con);
|
||||||
*/
|
*/
|
||||||
bool container_is_floating(struct sway_container *container);
|
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.
|
* Get a container's box in layout coordinates.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -57,6 +57,8 @@ static const struct cmd_handler handlers[] = {
|
||||||
{ "client.urgent", cmd_client_urgent },
|
{ "client.urgent", cmd_client_urgent },
|
||||||
{ "default_border", cmd_default_border },
|
{ "default_border", cmd_default_border },
|
||||||
{ "default_floating_border", cmd_default_floating_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", cmd_exec },
|
||||||
{ "exec_always", cmd_exec_always },
|
{ "exec_always", cmd_exec_always },
|
||||||
{ "floating_maximum_size", cmd_floating_maximum_size },
|
{ "floating_maximum_size", cmd_floating_maximum_size },
|
||||||
|
@ -135,8 +137,10 @@ static const struct cmd_handler command_handlers[] = {
|
||||||
{ "splith", cmd_splith },
|
{ "splith", cmd_splith },
|
||||||
{ "splitt", cmd_splitt },
|
{ "splitt", cmd_splitt },
|
||||||
{ "splitv", cmd_splitv },
|
{ "splitv", cmd_splitv },
|
||||||
|
{ "stacking_titlebar", cmd_stacking_titlebar },
|
||||||
{ "sticky", cmd_sticky },
|
{ "sticky", cmd_sticky },
|
||||||
{ "swap", cmd_swap },
|
{ "swap", cmd_swap },
|
||||||
|
{ "tabbed_titlebar", cmd_tabbed_titlebar },
|
||||||
{ "title_format", cmd_title_format },
|
{ "title_format", cmd_title_format },
|
||||||
{ "unmark", cmd_unmark },
|
{ "unmark", cmd_unmark },
|
||||||
{ "urgent", cmd_urgent },
|
{ "urgent", cmd_urgent },
|
||||||
|
|
40
sway/commands/default_stacking_titlebar.c
Normal file
40
sway/commands/default_stacking_titlebar.c
Normal file
|
@ -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
sway/commands/stacking_titlebar.c
Normal file
64
sway/commands/stacking_titlebar.c
Normal file
|
@ -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);
|
||||||
|
}
|
|
@ -299,6 +299,11 @@ static void arrange_children(enum sway_container_layout layout, list_t *children
|
||||||
title_bar_height = 0;
|
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;
|
double w = (double) width / children->length;
|
||||||
int title_offset = 0;
|
int title_offset = 0;
|
||||||
for (int i = 0; i < children->length; i++) {
|
for (int i = 0; i < children->length; i++) {
|
||||||
|
@ -329,6 +334,11 @@ static void arrange_children(enum sway_container_layout layout, list_t *children
|
||||||
title_bar_height = 0;
|
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 title_height = title_bar_height * children->length;
|
||||||
|
|
||||||
int y = 0;
|
int y = 0;
|
||||||
|
|
|
@ -51,6 +51,7 @@ sway_sources = files(
|
||||||
'commands/create_output.c',
|
'commands/create_output.c',
|
||||||
'commands/default_border.c',
|
'commands/default_border.c',
|
||||||
'commands/default_floating_border.c',
|
'commands/default_floating_border.c',
|
||||||
|
'commands/default_stacking_titlebar.c',
|
||||||
'commands/default_orientation.c',
|
'commands/default_orientation.c',
|
||||||
'commands/exit.c',
|
'commands/exit.c',
|
||||||
'commands/exec.c',
|
'commands/exec.c',
|
||||||
|
@ -69,6 +70,7 @@ sway_sources = files(
|
||||||
'commands/fullscreen.c',
|
'commands/fullscreen.c',
|
||||||
'commands/gaps.c',
|
'commands/gaps.c',
|
||||||
'commands/gesture.c',
|
'commands/gesture.c',
|
||||||
|
'commands/stacking_titlebar.c',
|
||||||
'commands/hide_edge_borders.c',
|
'commands/hide_edge_borders.c',
|
||||||
'commands/inhibit_idle.c',
|
'commands/inhibit_idle.c',
|
||||||
'commands/kill.c',
|
'commands/kill.c',
|
||||||
|
|
|
@ -111,6 +111,16 @@ They are expected to be used with *bindsym* or at runtime through *swaymsg*(1).
|
||||||
*border* toggle
|
*border* toggle
|
||||||
Cycles through the available border styles.
|
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*
|
||||||
Exit sway and end your Wayland session.
|
Exit sway and end your Wayland session.
|
||||||
|
|
||||||
|
@ -677,6 +687,14 @@ The default colors are:
|
||||||
windows that are spawned in floating mode, not windows that become floating
|
windows that are spawned in floating mode, not windows that become floating
|
||||||
afterwards.
|
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>
|
*exec* <shell command>
|
||||||
Executes _shell command_ with sh.
|
Executes _shell command_ with sh.
|
||||||
|
|
||||||
|
|
|
@ -1002,6 +1002,24 @@ bool container_is_floating(struct sway_container *container) {
|
||||||
return false;
|
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) {
|
void container_get_box(struct sway_container *container, struct wlr_box *box) {
|
||||||
box->x = container->pending.x;
|
box->x = container->pending.x;
|
||||||
box->y = container->pending.y;
|
box->y = container->pending.y;
|
||||||
|
|
|
@ -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
|
// 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,
|
// 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.
|
// bar, and disable any top border because we'll always have the title bar.
|
||||||
|
@ -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->container->pending.border_thickness = config->border_thickness;
|
||||||
view_set_tiled(view, true);
|
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 &&
|
if (config->popup_during_fullscreen == POPUP_LEAVE &&
|
||||||
container->pending.workspace &&
|
container->pending.workspace &&
|
||||||
|
|
Loading…
Reference in a new issue