aboutsummaryrefslogtreecommitdiff
path: root/sway
diff options
context:
space:
mode:
Diffstat (limited to 'sway')
-rw-r--r--sway/commands/bar.c115
-rw-r--r--sway/commands/bar/hidden_state.c34
-rw-r--r--sway/commands/bar/id.c2
-rw-r--r--sway/commands/bar/mode.c34
-rw-r--r--sway/commands/bar/status_command.c2
-rw-r--r--sway/commands/border.c2
-rw-r--r--sway/commands/gaps.c50
-rw-r--r--sway/commands/move.c8
-rw-r--r--sway/commands/sticky.c5
-rw-r--r--sway/commands/swap.c19
-rw-r--r--sway/commands/workspace.c22
-rw-r--r--sway/config.c1
-rw-r--r--sway/config/bar.c16
-rw-r--r--sway/desktop/output.c12
-rw-r--r--sway/desktop/render.c165
-rw-r--r--sway/input/cursor.c6
-rw-r--r--sway/input/keyboard.c28
-rw-r--r--sway/input/seat.c51
-rw-r--r--sway/ipc-server.c18
-rw-r--r--sway/main.c1
-rw-r--r--sway/sway-bar.5.scd16
-rw-r--r--sway/sway-input.5.scd2
-rw-r--r--sway/sway-output.5.scd66
-rw-r--r--sway/sway.1.scd2
-rw-r--r--sway/sway.5.scd86
-rw-r--r--sway/tree/arrange.c4
-rw-r--r--sway/tree/container.c4
-rw-r--r--sway/tree/view.c11
-rw-r--r--sway/tree/workspace.c7
29 files changed, 446 insertions, 343 deletions
diff --git a/sway/commands/bar.c b/sway/commands/bar.c
index 03f4c557..c808aef2 100644
--- a/sway/commands/bar.c
+++ b/sway/commands/bar.c
@@ -17,7 +17,6 @@ static struct cmd_handler bar_handlers[] = {
{ "height", bar_cmd_height },
{ "hidden_state", bar_cmd_hidden_state },
{ "icon_theme", bar_cmd_icon_theme },
- { "id", bar_cmd_id },
{ "mode", bar_cmd_mode },
{ "modifier", bar_cmd_modifier },
{ "output", bar_cmd_output },
@@ -27,7 +26,6 @@ static struct cmd_handler bar_handlers[] = {
{ "separator_symbol", bar_cmd_separator_symbol },
{ "status_command", bar_cmd_status_command },
{ "strip_workspace_numbers", bar_cmd_strip_workspace_numbers },
- { "swaybar_command", bar_cmd_swaybar_command },
{ "tray_output", bar_cmd_tray_output },
{ "tray_padding", bar_cmd_tray_padding },
{ "workspace_buttons", bar_cmd_workspace_buttons },
@@ -36,54 +34,49 @@ static struct cmd_handler bar_handlers[] = {
// Must be in alphabetical order for bsearch
static struct cmd_handler bar_config_handlers[] = {
- { "hidden_state", bar_cmd_hidden_state },
- { "mode", bar_cmd_mode }
+ { "id", bar_cmd_id },
+ { "swaybar_command", bar_cmd_swaybar_command },
};
+// Determines whether the subcommand is valid in any bar handler struct
+static bool is_subcommand(char *name) {
+ return find_handler(name, bar_handlers, sizeof(bar_handlers)) ||
+ find_handler(name, bar_config_handlers, sizeof(bar_config_handlers));
+}
+
struct cmd_results *cmd_bar(int argc, char **argv) {
struct cmd_results *error = NULL;
- if ((error = checkarg(argc, "bar", EXPECTED_AT_LEAST, 1))) {
+ if ((error = checkarg(argc, "bar", EXPECTED_AT_LEAST, 2))) {
return error;
}
- if (find_handler(argv[0], bar_config_handlers,
- sizeof(bar_config_handlers))) {
- if (config->reading) {
- return config_subcommand(argv, argc, bar_config_handlers,
- sizeof(bar_config_handlers));
- }
- return cmd_results_new(CMD_FAILURE, "bar",
- "Can only be used in config file.");
- }
-
- if (argc > 1) {
- struct bar_config *bar = NULL;
- if (!find_handler(argv[0], bar_handlers, sizeof(bar_handlers))
- && find_handler(argv[1], bar_handlers, sizeof(bar_handlers))) {
- for (int i = 0; i < config->bars->length; ++i) {
- struct bar_config *item = config->bars->items[i];
- if (strcmp(item->id, argv[0]) == 0) {
- wlr_log(WLR_DEBUG, "Selecting bar: %s", argv[0]);
- bar = item;
- break;
- }
+ bool spawn = false;
+ struct bar_config *bar = NULL;
+ if (strcmp(argv[0], "id") != 0 && is_subcommand(argv[1])) {
+ for (int i = 0; i < config->bars->length; ++i) {
+ struct bar_config *item = config->bars->items[i];
+ if (strcmp(item->id, argv[0]) == 0) {
+ wlr_log(WLR_DEBUG, "Selecting bar: %s", argv[0]);
+ bar = item;
+ break;
}
+ }
+ if (!bar) {
+ spawn = !config->reading;
+ wlr_log(WLR_DEBUG, "Creating bar: %s", argv[0]);
+ bar = default_bar_config();
if (!bar) {
- wlr_log(WLR_DEBUG, "Creating bar: %s", argv[0]);
- bar = default_bar_config();
- if (!bar) {
- return cmd_results_new(CMD_FAILURE, "bar",
- "Unable to allocate bar state");
- }
-
- bar->id = strdup(argv[0]);
+ return cmd_results_new(CMD_FAILURE, "bar",
+ "Unable to allocate bar state");
}
- config->current_bar = bar;
- ++argv; --argc;
+
+ bar->id = strdup(argv[0]);
}
+ config->current_bar = bar;
+ ++argv; --argc;
}
- if (!config->current_bar) {
+ if (!config->current_bar && config->reading) {
// Create new bar with default values
struct bar_config *bar = default_bar_config();
if (!bar) {
@@ -92,18 +85,13 @@ struct cmd_results *cmd_bar(int argc, char **argv) {
}
// set bar id
- for (int i = 0; i < config->bars->length; ++i) {
- if (bar == config->bars->items[i]) {
- const int len = 5 + numlen(i); // "bar-" + i + \0
- bar->id = malloc(len * sizeof(char));
- if (bar->id) {
- snprintf(bar->id, len, "bar-%d", i);
- } else {
- return cmd_results_new(CMD_FAILURE,
- "bar", "Unable to allocate bar ID");
- }
- break;
- }
+ const int len = 5 + numlen(config->bars->length - 1); // "bar-"+i+\0
+ bar->id = malloc(len * sizeof(char));
+ if (bar->id) {
+ snprintf(bar->id, len, "bar-%d", config->bars->length - 1);
+ } else {
+ return cmd_results_new(CMD_FAILURE,
+ "bar", "Unable to allocate bar ID");
}
// Set current bar
@@ -111,5 +99,32 @@ struct cmd_results *cmd_bar(int argc, char **argv) {
wlr_log(WLR_DEBUG, "Creating bar %s", bar->id);
}
- return config_subcommand(argv, argc, bar_handlers, sizeof(bar_handlers));
+ if (find_handler(argv[0], bar_config_handlers,
+ sizeof(bar_config_handlers))) {
+ if (config->reading) {
+ return config_subcommand(argv, argc, bar_config_handlers,
+ sizeof(bar_config_handlers));
+ } else if (spawn) {
+ for (int i = config->bars->length - 1; i >= 0; i--) {
+ struct bar_config *bar = config->bars->items[i];
+ if (bar == config->current_bar) {
+ list_del(config->bars, i);
+ free_bar_config(bar);
+ break;
+ }
+ }
+ }
+ return cmd_results_new(CMD_INVALID, "bar",
+ "Can only be used in the config file.");
+ }
+
+ struct cmd_results *res =
+ config_subcommand(argv, argc, bar_handlers, sizeof(bar_handlers));
+ if (!config->reading) {
+ if (spawn) {
+ load_swaybar(config->current_bar);
+ }
+ config->current_bar = NULL;
+ }
+ return res;
}
diff --git a/sway/commands/bar/hidden_state.c b/sway/commands/bar/hidden_state.c
index 502ce2c4..28adf6c7 100644
--- a/sway/commands/bar/hidden_state.c
+++ b/sway/commands/bar/hidden_state.c
@@ -32,7 +32,7 @@ static struct cmd_results *bar_set_hidden_state(struct bar_config *bar,
}
// free old mode
free(old_state);
- return cmd_results_new(CMD_SUCCESS, NULL, NULL);
+ return NULL;
}
struct cmd_results *bar_cmd_hidden_state(int argc, char **argv) {
@@ -50,24 +50,20 @@ struct cmd_results *bar_cmd_hidden_state(int argc, char **argv) {
const char *state = argv[0];
if (config->reading) {
- return bar_set_hidden_state(config->current_bar, state);
- }
-
- const char *id = NULL;
- if (argc == 2) {
- id = argv[1];
- }
- struct bar_config *bar;
- for (int i = 0; i < config->bars->length; ++i) {
- bar = config->bars->items[i];
- if (id && strcmp(id, bar->id) == 0) {
- return bar_set_hidden_state(bar, state);
- }
-
- error = bar_set_hidden_state(bar, state);
- if (error) {
- return error;
+ error = bar_set_hidden_state(config->current_bar, state);
+ } else {
+ const char *id = argc == 2 ? argv[1] : NULL;
+ for (int i = 0; i < config->bars->length; ++i) {
+ struct bar_config *bar = config->bars->items[i];
+ if (id) {
+ if (strcmp(id, bar->id) == 0) {
+ error = bar_set_hidden_state(bar, state);
+ break;
+ }
+ } else if ((error = bar_set_hidden_state(bar, state))) {
+ break;
+ }
}
}
- return cmd_results_new(CMD_SUCCESS, NULL, NULL);
+ return error ? error : cmd_results_new(CMD_SUCCESS, NULL, NULL);
}
diff --git a/sway/commands/bar/id.c b/sway/commands/bar/id.c
index 65fa69fd..7690a852 100644
--- a/sway/commands/bar/id.c
+++ b/sway/commands/bar/id.c
@@ -13,6 +13,8 @@ struct cmd_results *bar_cmd_id(int argc, char **argv) {
const char *oldname = config->current_bar->id;
if (strcmp(name, oldname) == 0) {
return cmd_results_new(CMD_SUCCESS, NULL, NULL); // NOP
+ } else if (strcmp(name, "id") == 0) {
+ return cmd_results_new(CMD_INVALID, "id", "id cannot be 'id'");
}
// check if id is used by a previously defined bar
for (int i = 0; i < config->bars->length; ++i) {
diff --git a/sway/commands/bar/mode.c b/sway/commands/bar/mode.c
index 28e2d77b..dbdd3897 100644
--- a/sway/commands/bar/mode.c
+++ b/sway/commands/bar/mode.c
@@ -33,7 +33,7 @@ static struct cmd_results *bar_set_mode(struct bar_config *bar, const char *mode
// free old mode
free(old_mode);
- return cmd_results_new(CMD_SUCCESS, NULL, NULL);
+ return NULL;
}
struct cmd_results *bar_cmd_mode(int argc, char **argv) {
@@ -51,24 +51,20 @@ struct cmd_results *bar_cmd_mode(int argc, char **argv) {
const char *mode = argv[0];
if (config->reading) {
- return bar_set_mode(config->current_bar, mode);
- }
-
- const char *id = NULL;
- if (argc == 2) {
- id = argv[1];
- }
-
- struct bar_config *bar;
- for (int i = 0; i < config->bars->length; ++i) {
- bar = config->bars->items[i];
- if (id && strcmp(id, bar->id) == 0) {
- return bar_set_mode(bar, mode);
- }
- error = bar_set_mode(bar, mode);
- if (error) {
- return error;
+ error = bar_set_mode(config->current_bar, mode);
+ } else {
+ const char *id = argc == 2 ? argv[1] : NULL;
+ for (int i = 0; i < config->bars->length; ++i) {
+ struct bar_config *bar = config->bars->items[i];
+ if (id) {
+ if (strcmp(id, bar->id) == 0) {
+ error = bar_set_mode(bar, mode);
+ break;
+ }
+ } else if ((error = bar_set_mode(bar, mode))) {
+ break;
+ }
}
}
- return cmd_results_new(CMD_SUCCESS, NULL, NULL);
+ return error ? error : cmd_results_new(CMD_SUCCESS, NULL, NULL);
}
diff --git a/sway/commands/bar/status_command.c b/sway/commands/bar/status_command.c
index 5b4fdc87..490393f1 100644
--- a/sway/commands/bar/status_command.c
+++ b/sway/commands/bar/status_command.c
@@ -25,7 +25,7 @@ struct cmd_results *bar_cmd_status_command(int argc, char **argv) {
}
if (config->active && !config->validating) {
- load_swaybars();
+ load_swaybar(config->current_bar);
}
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
diff --git a/sway/commands/border.c b/sway/commands/border.c
index bfd3b9ed..cc0d635a 100644
--- a/sway/commands/border.c
+++ b/sway/commands/border.c
@@ -81,7 +81,7 @@ struct cmd_results *cmd_border(int argc, char **argv) {
border_toggle(view);
} else {
return cmd_results_new(CMD_INVALID, "border",
- "Expected 'border <none|normal|pixel|toggle>' "
+ "Expected 'border <none|normal|pixel|csd|toggle>' "
"or 'border pixel <px>'");
}
if (argc == 2) {
diff --git a/sway/commands/gaps.c b/sway/commands/gaps.c
index 2e0876a9..042b415f 100644
--- a/sway/commands/gaps.c
+++ b/sway/commands/gaps.c
@@ -20,31 +20,6 @@ struct gaps_data {
int amount;
};
-// gaps edge_gaps on|off|toggle
-static struct cmd_results *gaps_edge_gaps(int argc, char **argv) {
- struct cmd_results *error;
- if ((error = checkarg(argc, "gaps", EXPECTED_AT_LEAST, 2))) {
- return error;
- }
-
- if (strcmp(argv[1], "on") == 0) {
- config->edge_gaps = true;
- } else if (strcmp(argv[1], "off") == 0) {
- config->edge_gaps = false;
- } else if (strcmp(argv[1], "toggle") == 0) {
- if (!config->active) {
- return cmd_results_new(CMD_INVALID, "gaps",
- "Cannot toggle gaps while not running.");
- }
- config->edge_gaps = !config->edge_gaps;
- } else {
- return cmd_results_new(CMD_INVALID, "gaps",
- "gaps edge_gaps on|off|toggle");
- }
- arrange_root();
- return cmd_results_new(CMD_SUCCESS, NULL, NULL);
-}
-
// gaps inner|outer <px>
static struct cmd_results *gaps_set_defaults(int argc, char **argv) {
struct cmd_results *error = checkarg(argc, "gaps", EXPECTED_EQUAL_TO, 2);
@@ -68,15 +43,17 @@ static struct cmd_results *gaps_set_defaults(int argc, char **argv) {
return cmd_results_new(CMD_INVALID, "gaps",
"Expected 'gaps inner|outer <px>'");
}
- if (amount < 0) {
- amount = 0;
- }
-
if (inner) {
- config->gaps_inner = amount;
+ config->gaps_inner = (amount >= 0) ? amount : 0;
} else {
config->gaps_outer = amount;
}
+
+ // Prevent negative outer gaps from moving windows out of the workspace.
+ if (config->gaps_outer < -config->gaps_inner) {
+ config->gaps_outer = -config->gaps_inner;
+ }
+
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
}
@@ -95,8 +72,12 @@ static void configure_gaps(struct sway_workspace *ws, void *_data) {
*prop -= data->amount;
break;
}
- if (*prop < 0) {
- *prop = 0;
+ // Prevent invalid gaps configurations.
+ if (ws->gaps_inner < 0) {
+ ws->gaps_inner = 0;
+ }
+ if (ws->gaps_outer < -ws->gaps_inner) {
+ ws->gaps_outer = -ws->gaps_inner;
}
arrange_workspace(ws);
}
@@ -156,7 +137,6 @@ static struct cmd_results *gaps_set_runtime(int argc, char **argv) {
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
}
-// gaps edge_gaps on|off|toggle
// gaps inner|outer <px> - sets defaults for workspaces
// gaps inner|outer current|all set|plus|minus <px> - runtime only
struct cmd_results *cmd_gaps(int argc, char **argv) {
@@ -165,10 +145,6 @@ struct cmd_results *cmd_gaps(int argc, char **argv) {
return error;
}
- if (strcmp(argv[0], "edge_gaps") == 0) {
- return gaps_edge_gaps(argc, argv);
- }
-
if (argc == 2) {
return gaps_set_defaults(argc, argv);
}
diff --git a/sway/commands/move.c b/sway/commands/move.c
index fc2f1cc1..24036f36 100644
--- a/sway/commands/move.c
+++ b/sway/commands/move.c
@@ -543,7 +543,7 @@ static struct cmd_results *cmd_move_container(int argc, char **argv) {
if (new_output_last_ws && new_output_last_ws != new_workspace) {
struct sway_node *new_output_last_focus =
seat_get_focus_inactive(seat, &new_output_last_ws->node);
- seat_set_focus_warp(seat, new_output_last_focus, false, false);
+ seat_set_raw_focus(seat, new_output_last_focus);
}
// restore focus
@@ -556,7 +556,7 @@ static struct cmd_results *cmd_move_container(int argc, char **argv) {
focus = seat_get_focus_inactive(seat, &old_ws->node);
}
}
- seat_set_focus_warp(seat, focus, true, false);
+ seat_set_focus(seat, focus);
// clean-up, destroying parents if the container was the last child
if (old_parent) {
@@ -593,7 +593,7 @@ static void workspace_move_to_output(struct sway_workspace *workspace,
char *ws_name = workspace_next_name(old_output->wlr_output->name);
struct sway_workspace *ws = workspace_create(old_output, ws_name);
free(ws_name);
- seat_set_focus_workspace(seat, ws);
+ seat_set_raw_focus(seat, &ws->node);
}
workspace_consider_destroy(new_output_old_ws);
@@ -704,7 +704,7 @@ static struct cmd_results *cmd_move_in_direction(
}
// Hack to re-focus container
- seat_set_focus_workspace(config->handler_context.seat, new_ws);
+ seat_set_raw_focus(config->handler_context.seat, &new_ws->node);
seat_set_focus_container(config->handler_context.seat, container);
if (old_ws != new_ws) {
diff --git a/sway/commands/sticky.c b/sway/commands/sticky.c
index 7995cdd6..f18322b7 100644
--- a/sway/commands/sticky.c
+++ b/sway/commands/sticky.c
@@ -16,6 +16,11 @@ struct cmd_results *cmd_sticky(int argc, char **argv) {
return error;
}
struct sway_container *container = config->handler_context.container;
+
+ if (container == NULL) {
+ return cmd_results_new(CMD_FAILURE, "sticky", "No current container");
+ };
+
if (!container_is_floating(container)) {
return cmd_results_new(CMD_FAILURE, "sticky",
"Can't set sticky on a tiled container");
diff --git a/sway/commands/swap.c b/sway/commands/swap.c
index e7f9cbea..9cc0d5c2 100644
--- a/sway/commands/swap.c
+++ b/sway/commands/swap.c
@@ -22,6 +22,7 @@ static void swap_places(struct sway_container *con1,
temp->width = con1->width;
temp->height = con1->height;
temp->parent = con1->parent;
+ temp->workspace = con1->workspace;
con1->x = con2->x;
con1->y = con2->y;
@@ -34,8 +35,18 @@ static void swap_places(struct sway_container *con1,
con2->height = temp->height;
int temp_index = container_sibling_index(con1);
- container_insert_child(con2->parent, con1, container_sibling_index(con2));
- container_insert_child(temp->parent, con2, temp_index);
+ if (con2->parent) {
+ container_insert_child(con2->parent, con1,
+ container_sibling_index(con2));
+ } else {
+ workspace_insert_tiling(con2->workspace, con1,
+ container_sibling_index(con2));
+ }
+ if (temp->parent) {
+ container_insert_child(temp->parent, con2, temp_index);
+ } else {
+ workspace_insert_tiling(temp->workspace, con2, temp_index);
+ }
free(temp);
}
@@ -50,13 +61,13 @@ static void swap_focus(struct sway_container *con1,
enum sway_container_layout layout2 = container_parent_layout(con2);
if (focus == con1 && (layout2 == L_TABBED || layout2 == L_STACKED)) {
if (workspace_is_visible(ws2)) {
- seat_set_focus_warp(seat, &con2->node, false, true);
+ seat_set_focus_warp(seat, &con2->node, false);
}
seat_set_focus_container(seat, ws1 != ws2 ? con2 : con1);
} else if (focus == con2 && (layout1 == L_TABBED
|| layout1 == L_STACKED)) {
if (workspace_is_visible(ws1)) {
- seat_set_focus_warp(seat, &con1->node, false, true);
+ seat_set_focus_warp(seat, &con1->node, false);
}
seat_set_focus_container(seat, ws1 != ws2 ? con1 : con2);
} else if (ws1 != ws2) {
diff --git a/sway/commands/workspace.c b/sway/commands/workspace.c
index 63f29641..58c2201d 100644
--- a/sway/commands/workspace.c
+++ b/sway/commands/workspace.c
@@ -1,5 +1,6 @@
#define _XOPEN_SOURCE 500
#include <ctype.h>
+#include <limits.h>
#include <string.h>
#include <strings.h>
#include "sway/commands.h"
@@ -20,8 +21,8 @@ static struct workspace_config *workspace_config_find_or_create(char *ws_name) {
return NULL;
}
wsc->workspace = strdup(ws_name);
- wsc->gaps_inner = -1;
- wsc->gaps_outer = -1;
+ wsc->gaps_inner = INT_MIN;
+ wsc->gaps_outer = INT_MIN;
list_add(config->workspace_configs, wsc);
return wsc;
}
@@ -94,7 +95,16 @@ struct cmd_results *cmd_workspace(int argc, char **argv) {
return cmd_results_new(CMD_FAILURE, "workspace gaps",
"Expected 'workspace <ws> gaps inner|outer <px>'");
}
- *prop = val >= 0 ? val : 0;
+ *prop = val;
+
+ // Prevent invalid gaps configurations.
+ if (wsc->gaps_inner < 0) {
+ wsc->gaps_inner = 0;
+ }
+ if (wsc->gaps_outer < -wsc->gaps_inner) {
+ wsc->gaps_outer = -wsc->gaps_inner;
+ }
+
} else {
if (config->reading || !config->active) {
return cmd_results_new(CMD_DEFER, "workspace", NULL);
@@ -132,7 +142,11 @@ struct cmd_results *cmd_workspace(int argc, char **argv) {
strcasecmp(argv[0], "current") == 0) {
ws = workspace_by_name(argv[0]);
} else if (strcasecmp(argv[0], "back_and_forth") == 0) {
- if (!(ws = workspace_by_name(argv[0])) && prev_workspace_name) {
+ if (!prev_workspace_name) {
+ return cmd_results_new(CMD_INVALID, "workspace",
+ "There is no previous workspace");
+ }
+ if (!(ws = workspace_by_name(argv[0]))) {
ws = workspace_create(NULL, prev_workspace_name);
}
} else {
diff --git a/sway/config.c b/sway/config.c
index f239ba1d..89b89464 100644
--- a/sway/config.c
+++ b/sway/config.c
@@ -234,7 +234,6 @@ static void config_defaults(struct sway_config *config) {
config->show_marks = true;
config->tiling_drag = true;
- config->edge_gaps = true;
config->smart_gaps = false;
config->gaps_inner = 0;
config->gaps_outer = 0;
diff --git a/sway/config/bar.c b/sway/config/bar.c
index c6899f57..8b88642e 100644
--- a/sway/config/bar.c
+++ b/sway/config/bar.c
@@ -16,6 +16,7 @@
#include "stringop.h"
#include "list.h"
#include "log.h"
+#include "util.h"
static void terminate_swaybar(pid_t pid) {
wlr_log(WLR_DEBUG, "Terminating swaybar %d", pid);
@@ -101,6 +102,7 @@ struct bar_config *default_bar_config(void) {
bar->binding_mode_indicator = true;
bar->verbose = false;
bar->pid = 0;
+ bar->modifier = get_modifier_mask_by_name("Mod4");
if (!(bar->mode = strdup("dock"))) {
goto cleanup;
}
@@ -226,13 +228,17 @@ static void invoke_swaybar(struct bar_config *bar) {
close(filedes[1]);
}
+void load_swaybar(struct bar_config *bar) {
+ if (bar->pid != 0) {
+ terminate_swaybar(bar->pid);
+ }
+ wlr_log(WLR_DEBUG, "Invoking swaybar for bar id '%s'", bar->id);
+ invoke_swaybar(bar);
+}
+
void load_swaybars(void) {
for (int i = 0; i < config->bars->length; ++i) {
struct bar_config *bar = config->bars->items[i];
- if (bar->pid != 0) {
- terminate_swaybar(bar->pid);
- }
- wlr_log(WLR_DEBUG, "Invoking swaybar for bar id '%s'", bar->id);
- invoke_swaybar(bar);
+ load_swaybar(bar);
}
}
diff --git a/sway/desktop/output.c b/sway/desktop/output.c
index adc1ee10..fc52dd28 100644
--- a/sway/desktop/output.c
+++ b/sway/desktop/output.c
@@ -223,11 +223,15 @@ void output_drag_icons_for_each_surface(struct sway_output *output,
}
}
+static int scale_length(int length, int offset, float scale) {
+ return round((offset + length) * scale) - round(offset * scale);
+}
+
static void scale_box(struct wlr_box *box, float scale) {
- box->x *= scale;
- box->y *= scale;
- box->width *= scale;
- box->height *= scale;
+ box->width = scale_length(box->width, box->x, scale);
+ box->height = scale_length(box->height, box->y, scale);
+ box->x = round(box->x * scale);
+ box->y = round(box->y * scale);
}
struct sway_workspace *output_get_active_workspace(struct sway_output *output) {
diff --git a/sway/desktop/render.c b/sway/desktop/render.c
index 3617da87..9b26c560 100644
--- a/sway/desktop/render.c
+++ b/sway/desktop/render.c
@@ -33,11 +33,27 @@ struct render_data {
float alpha;
};
+/**
+ * Apply scale to a width or height.
+ *
+ * One does not simply multiply the width by the scale. We allow fractional
+ * scaling, which means the resulting scaled width might be a decimal.
+ * So we round it.
+ *
+ * But even this can produce undesirable results depending on the X or Y offset
+ * of the box. For example, with a scale of 1.5, a box with width=1 should not
+ * scale to 2px if its X coordinate is 1, because the X coordinate would have
+ * scaled to 2px.
+ */
+static int scale_length(int length, int offset, float scale) {
+ return round((offset + length) * scale) - round(offset * scale);
+}
+
static void scale_box(struct wlr_box *box, float scale) {
- box->x *= scale;
- box->y *= scale;
- box->width *= scale;
- box->height *= scale;
+ box->width = scale_length(box->width, box->x, scale);
+ box->height = scale_length(box->height, box->y, scale);
+ box->x = round(box->x * scale);
+ box->y = round(box->y * scale);
}
static void scissor_output(struct wlr_output *wlr_output,
@@ -392,14 +408,23 @@ static void render_titlebar(struct sway_output *output,
render_rect(output->wlr_output, output_damage, &box, color);
// Single pixel right edge
- box.x = (x + width - TITLEBAR_BORDER_THICKNESS) * output_scale;
+ box.x = x + width - TITLEBAR_BORDER_THICKNESS;
+ box.y = y + TITLEBAR_BORDER_THICKNESS;
+ box.width = TITLEBAR_BORDER_THICKNESS;
+ box.height =
+ container_titlebar_height() - TITLEBAR_BORDER_THICKNESS * 2;
+ scale_box(&box, output_scale);
render_rect(output->wlr_output, output_damage, &box, color);
}
size_t inner_width = width - TITLEBAR_H_PADDING * 2;
+ int bg_y = y + TITLEBAR_BORDER_THICKNESS;
+ int ob_bg_height = scale_length(
+ (TITLEBAR_V_PADDING - TITLEBAR_BORDER_THICKNESS) * 2 +
+ config->font_height, bg_y, output_scale);
// Marks
- size_t marks_ob_width = 0; // output-buffer-local
+ int marks_ob_width = 0; // output-buffer-local
if (config->show_marks && marks_texture) {
struct wlr_box texture_box;
wlr_texture_get_size(marks_texture,
@@ -408,15 +433,14 @@ static void render_titlebar(struct sway_output *output,
// The marks texture might be shorter than the config->font_height, in
// which case we need to pad it as evenly as possible above and below.
- int ob_padding_total = config->font_height * output_scale -
- texture_box.height;
- int ob_padding_above = floor(ob_padding_total / 2);
- int ob_padding_below = ceil(ob_padding_total / 2);
+ int ob_padding_total = ob_bg_height - texture_box.height;
+ int ob_padding_above = floor(ob_padding_total / 2.0);
+ int ob_padding_below = ceil(ob_padding_total / 2.0);
// Render texture
- texture_box.x = (x - output_x + width - TITLEBAR_H_PADDING)
- * output_scale - texture_box.width;
- texture_box.y = (y - output_y + TITLEBAR_V_PADDING) * output_scale +
+ texture_box.x = round((x - output_x + width - TITLEBAR_H_PADDING)
+ * output_scale) - texture_box.width;
+ texture_box.y = round((bg_y - output_y) * output_scale) +
ob_padding_above;
float matrix[9];
@@ -431,29 +455,18 @@ static void render_titlebar(struct sway_output *output,
&texture_box, matrix, con->alpha);
// Padding above
- if (ob_padding_above > 0) {
- memcpy(&color, colors->background, sizeof(float) * 4);
- premultiply_alpha(color, con->alpha);
- box.x = (x + width - TITLEBAR_H_PADDING) * output_scale -
- texture_box.width;
- box.y = (y + TITLEBAR_V_PADDING) * output_scale;
- box.width = texture_box.width;
- box.height = ob_padding_above;
- render_rect(output->wlr_output, output_damage, &box, color);
- }
+ memcpy(&color, colors->background, sizeof(float) * 4);
+ premultiply_alpha(color, con->alpha);
+ box.x = texture_box.x + round(output_x * output_scale);
+ box.y = round((y + TITLEBAR_BORDER_THICKNESS) * output_scale);
+ box.width = texture_box.width;
+ box.height = ob_padding_above;
+ render_rect(output->wlr_output, output_damage, &box, color);
// Padding below
- if (ob_padding_below > 0) {
- memcpy(&color, colors->background, sizeof(float) * 4);
- premultiply_alpha(color, con->alpha);
- box.x = (x + width - TITLEBAR_H_PADDING) * output_scale -
- texture_box.width;
- box.y = (y + TITLEBAR_V_PADDING) * output_scale +
- ob_padding_above + texture_box.height;
- box.width = texture_box.width;
- box.height = ob_padding_below;
- render_rect(output->wlr_output, output_damage, &box, color);
- }
+ box.y += ob_padding_above + texture_box.height;
+ box.height = ob_padding_below;
+ render_rect(output->wlr_output, output_damage, &box, color);
}
// Title text
@@ -466,89 +479,73 @@ static void render_titlebar(struct sway_output *output,
// The title texture might be shorter than the config->font_height,
// in which case we need to pad it above and below.
- int ob_padding_above = (config->font_baseline - con->title_baseline)
- * output_scale;
- int ob_padding_below = (config->font_height - con->title_height)
- * output_scale - ob_padding_above;
+ int ob_padding_above = round((config->font_baseline -
+ con->title_baseline + TITLEBAR_V_PADDING -
+ TITLEBAR_BORDER_THICKNESS) * output_scale);
+ int ob_padding_below = ob_bg_height - ob_padding_above -
+ texture_box.height;
// Render texture
- texture_box.x = (x - output_x + TITLEBAR_H_PADDING) * output_scale;
- texture_box.y = (y - output_y + TITLEBAR_V_PADDING) * output_scale +
- ob_padding_above;
+ texture_box.x =
+ round((x - output_x + TITLEBAR_H_PADDING) * output_scale);
+ texture_box.y =
+ round((bg_y - output_y) * output_scale) + ob_padding_above;
float matrix[9];
wlr_matrix_project_box(matrix, &texture_box,
WL_OUTPUT_TRANSFORM_NORMAL,
0.0, output->wlr_output->transform_matrix);
- if (inner_width * output_scale - marks_ob_width < texture_box.width) {
- texture_box.width = inner_width * output_scale - marks_ob_width;
+ int inner_x = x - output_x + TITLEBAR_H_PADDING;
+ int ob_inner_width = scale_length(inner_width, inner_x, output_scale);
+ if (ob_inner_width - marks_ob_width < texture_box.width) {
+ texture_box.width = ob_inner_width - marks_ob_width;
}
render_texture(output->wlr_output, output_damage, title_texture,
&texture_box, matrix, con->alpha);
// Padding above
- if (ob_padding_above > 0) {
- memcpy(&color, colors->background, sizeof(float) * 4);
- premultiply_alpha(color, con->alpha);
- box.x = (x + TITLEBAR_H_PADDING) * output_scale;
- box.y = (y + TITLEBAR_V_PADDING) * output_scale;
- box.width = texture_box.width;
- box.height = ob_padding_above;
- render_rect(output->wlr_output, output_damage, &box, color);
- }
+ memcpy(&color, colors->background, sizeof(float) * 4);
+ premultiply_alpha(color, con->alpha);
+ box.x = texture_box.x + round(output_x * output_scale);
+ box.y = round((y + TITLEBAR_BORDER_THICKNESS) * output_scale);
+ box.width = texture_box.width;
+ box.height = ob_padding_above;
+ render_rect(output->wlr_output, output_damage, &box, color);
// Padding below
- if (ob_padding_below > 0) {
- memcpy(&color, colors->background, sizeof(float) * 4);
- premultiply_alpha(color, con->alpha);
- box.x = (x + TITLEBAR_H_PADDING) * output_scale;
- box.y = (y + TITLEBAR_V_PADDING) * output_scale +
- ob_padding_above + texture_box.height;
- box.width = texture_box.width;
- box.height = ob_padding_below;
- render_rect(output->wlr_output, output_damage, &box, color);
- }
+ box.y += ob_padding_above + texture_box.height;
+ box.height = ob_padding_below;
+ render_rect(output->wlr_output, output_damage, &box, color);
}
- // Padding above title
- memcpy(&color, colors->background, sizeof(float) * 4);
- premultiply_alpha(color, con->alpha);
- box.x = x + (layout == L_TABBED) * TITLEBAR_BORDER_THICKNESS;
- box.y = y + TITLEBAR_BORDER_THICKNESS;
- box.width = width - (layout == L_TABBED) * TITLEBAR_BORDER_THICKNESS * 2;
- box.height = TITLEBAR_V_PADDING - TITLEBAR_BORDER_THICKNESS;
- scale_box(&box, output_scale);
- render_rect(output->wlr_output, output_damage, &box, color);
-
- // Padding below title
- box.y = (y + TITLEBAR_V_PADDING + config->font_height) * output_scale;
- render_rect(output->wlr_output, output_damage, &box, color);
-
// Filler between title and marks
- box.width = inner_width * output_scale - title_ob_width - marks_ob_width;
+ box.width =
+ round(inner_width * output_scale) - title_ob_width - marks_ob_width;
if (box.width > 0) {
- box.x = (x + TITLEBAR_H_PADDING) * output_scale + title_ob_width;
- box.y = (y + TITLEBAR_V_PADDING) * output_scale;
- box.height = config->font_height * output_scale;
+ box.x = round((x + TITLEBAR_H_PADDING) * output_scale) + title_ob_width;
+ box.y = round(bg_y * output_scale);
+ box.height = ob_bg_height;
render_rect(output->wlr_output, output_damage, &box, color);
}
// Padding left of title
left_offset = (layout == L_TABBED) * TITLEBAR_BORDER_THICKNESS;
box.x = x + left_offset;
- box.y = y + TITLEBAR_V_PADDING;
+ box.y = y + TITLEBAR_BORDER_THICKNESS;
box.width = TITLEBAR_H_PADDING - left_offset;
- box.height = config->font_height;
+ box.height = (TITLEBAR_V_PADDING - TITLEBAR_BORDER_THICKNESS) * 2 +
+ config->font_height;
scale_box(&box, output_scale);
render_rect(output->wlr_output, output_damage, &box, color);
// Padding right of marks
right_offset = (layout == L_TABBED) * TITLEBAR_BORDER_THICKNESS;
box.x = x + width - TITLEBAR_H_PADDING;
- box.y = y + TITLEBAR_V_PADDING;
+ box.y = y + TITLEBAR_BORDER_THICKNESS;
box.width = TITLEBAR_H_PADDING - right_offset;
- box.height = config->font_height;
+ box.height = (TITLEBAR_V_PADDING - TITLEBAR_BORDER_THICKNESS) * 2 +
+ config->font_height;
scale_box(&box, output_scale);
render_rect(output->wlr_output, output_damage, &box, color);
diff --git a/sway/input/cursor.c b/sway/input/cursor.c
index 21e104ec..925190d6 100644
--- a/sway/input/cursor.c
+++ b/sway/input/cursor.c
@@ -597,7 +597,7 @@ void cursor_send_pointer_motion(struct sway_cursor *cursor, uint32_t time_msec,
struct sway_output *focused_output = node_get_output(focus);
struct sway_output *output = node_get_output(node);
if (output != focused_output) {
- seat_set_focus_warp(seat, node, false, true);
+ seat_set_focus_warp(seat, node, false);
}
} else if (node->type == N_CONTAINER && node->sway_container->view) {
// Focus node if the following are true:
@@ -607,14 +607,14 @@ void cursor_send_pointer_motion(struct sway_cursor *cursor, uint32_t time_msec,
if (!wlr_seat_keyboard_has_grab(cursor->seat->wlr_seat) &&
node != prev_node &&
view_is_visible(node->sway_container->view)) {
- seat_set_focus_warp(seat, node, false, true);
+ seat_set_focus_warp(seat, node, false);
} else {
struct sway_node *next_focus =
seat_get_focus_inactive(seat, &root->node);
if (next_focus && next_focus->type == N_CONTAINER &&
next_focus->sway_container->view &&
view_is_visible(next_focus->sway_container->view)) {
- seat_set_focus_warp(seat, next_focus, false, true);
+ seat_set_focus_warp(seat, next_focus, false);
}
}
}
diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c
index fb1fe7b5..2c8b41cd 100644
--- a/sway/input/keyboard.c
+++ b/sway/input/keyboard.c
@@ -9,6 +9,7 @@
#include "sway/input/input-manager.h"
#include "sway/input/keyboard.h"
#include "sway/input/seat.h"
+#include "sway/ipc-server.h"
#include "log.h"
/**
@@ -66,10 +67,10 @@ static void update_shortcut_state(struct sway_shortcut_state *state,
bool last_key_was_a_modifier = raw_modifiers != state->last_raw_modifiers;
state->last_raw_modifiers = raw_modifiers;
- if (last_key_was_a_modifier && state->last_keycode) {
- // Last pressed key before this one was a modifier
- state_erase_key(state, state->last_keycode);
- }
+ if (last_key_was_a_modifier && state->last_keycode) {
+ // Last pressed key before this one was a modifier
+ state_erase_key(state, state->last_keycode);
+ }
if (event->state == WLR_KEY_PRESSED) {
// Add current key to set; there may be duplicates
@@ -235,7 +236,6 @@ static void handle_keyboard_key(struct wl_listener *listener, void *data) {
code_modifiers);
}
-
bool handled = false;
// Identify active release binding
@@ -337,6 +337,19 @@ static int handle_keyboard_repeat(void *data) {
return 0;
}
+static void determine_bar_visibility(uint32_t modifiers) {
+ for (int i = 0; i < config->bars->length; ++i) {
+ struct bar_config *bar = config->bars->items[i];
+ if (strcmp(bar->mode, bar->hidden_state) == 0) { // both are "hide"
+ bool should_be_visible = (~modifiers & bar->modifier) == 0;
+ if (bar->visible_by_modifier != should_be_visible) {
+ bar->visible_by_modifier = should_be_visible;
+ ipc_event_bar_state_update(bar);
+ }
+ }
+ }
+}
+
static void handle_keyboard_modifiers(struct wl_listener *listener,
void *data) {
struct sway_keyboard *keyboard =
@@ -346,6 +359,9 @@ static void handle_keyboard_modifiers(struct wl_listener *listener,
keyboard->seat_device->input_device->wlr_device;
wlr_seat_set_keyboard(wlr_seat, wlr_device);
wlr_seat_keyboard_notify_modifiers(wlr_seat, &wlr_device->keyboard->modifiers);
+
+ uint32_t modifiers = wlr_keyboard_get_modifiers(wlr_device->keyboard);
+ determine_bar_visibility(modifiers);
}
struct sway_keyboard *sway_keyboard_create(struct sway_seat *seat,
@@ -464,7 +480,7 @@ void sway_keyboard_configure(struct sway_keyboard *keyboard) {
keyboard->keyboard_key.notify = handle_keyboard_key;
wl_list_remove(&keyboard->keyboard_modifiers.link);
- wl_signal_add( &wlr_device->keyboard->events.modifiers,
+ wl_signal_add(&wlr_device->keyboard->events.modifiers,
&keyboard->keyboard_modifiers);
keyboard->keyboard_modifiers.notify = handle_keyboard_modifiers;
}
diff --git a/sway/input/seat.c b/sway/input/seat.c
index 23f582ca..d8d2f3a4 100644
--- a/sway/input/seat.c
+++ b/sway/input/seat.c
@@ -184,8 +184,8 @@ static void handle_seat_node_destroy(struct wl_listener *listener, void *data) {
seat_set_focus(seat, next_focus);
} else {
// Setting focus_inactive
- seat_set_focus_warp(seat, next_focus, false, false);
- seat_set_focus_warp(seat, focus, false, false);
+ seat_set_raw_focus(seat, next_focus);
+ seat_set_raw_focus(seat, focus);
}
}
@@ -623,8 +623,25 @@ static void container_raise_floating(struct sway_container *con) {
}
}
+static void set_workspace(struct sway_seat *seat,
+ struct sway_workspace *new_ws) {
+ if (seat->workspace == new_ws) {
+ return;
+ }
+ ipc_event_workspace(seat->workspace, new_ws, "focus");
+ seat->workspace = new_ws;
+}
+
+void seat_set_raw_focus(struct sway_seat *seat, struct sway_node *node) {
+ struct sway_seat_node *seat_node = seat_node_from_node(seat, node);
+ wl_list_remove(&seat_node->link);
+ wl_list_insert(&seat->focus_stack, &seat_node->link);
+ node_set_dirty(node);
+ node_set_dirty(node_get_parent(node));
+}
+
void seat_set_focus_warp(struct sway_seat *seat, struct sway_node *node,
- bool warp, bool notify) {
+ bool warp) {
if (seat->focused_layer) {
return;
}
@@ -688,34 +705,20 @@ void seat_set_focus_warp(struct sway_seat *seat, struct sway_node *node,
if (container) {
struct sway_container *parent = container->parent;
while (parent) {
- struct sway_seat_node *seat_node =
- seat_node_from_node(seat, &parent->node);
- wl_list_remove(&seat_node->link);
- wl_list_insert(&seat->focus_stack, &seat_node->link);
- node_set_dirty(&parent->node);
+ seat_set_raw_focus(seat, &parent->node);
parent = parent->parent;
}
}
if (new_workspace) {
- struct sway_seat_node *seat_node =
- seat_node_from_node(seat, &new_workspace->node);
- wl_list_remove(&seat_node->link);
- wl_list_insert(&seat->focus_stack, &seat_node->link);
- node_set_dirty(&new_workspace->node);
+ seat_set_raw_focus(seat, &new_workspace->node);
}
if (container) {
- struct sway_seat_node *seat_node =
- seat_node_from_node(seat, &container->node);
- wl_list_remove(&seat_node->link);
- wl_list_insert(&seat->focus_stack, &seat_node->link);
- node_set_dirty(&container->node);
+ seat_set_raw_focus(seat, &container->node);
seat_send_focus(&container->node, seat);
}
// emit ipc events
- if (notify && new_workspace && last_workspace != new_workspace) {
- ipc_event_workspace(last_workspace, new_workspace, "focus");
- }
+ set_workspace(seat, new_workspace);
if (container && container->view) {
ipc_event_window(container, "focus");
}
@@ -798,17 +801,17 @@ void seat_set_focus_warp(struct sway_seat *seat, struct sway_node *node,
}
void seat_set_focus(struct sway_seat *seat, struct sway_node *node) {
- seat_set_focus_warp(seat, node, true, true);
+ seat_set_focus_warp(seat, node, true);
}
void seat_set_focus_container(struct sway_seat *seat,
struct sway_container *con) {
- seat_set_focus_warp(seat, con ? &con->node : NULL, true, true);
+ seat_set_focus_warp(seat, con ? &con->node : NULL, true);
}
void seat_set_focus_workspace(struct sway_seat *seat,
struct sway_workspace *ws) {
- seat_set_focus_warp(seat, ws ? &ws->node : NULL, true, true);
+ seat_set_focus_warp(seat, ws ? &ws->node : NULL, true);
}
void seat_set_focus_surface(struct sway_seat *seat,
diff --git a/sway/ipc-server.c b/sway/ipc-server.c
index 2d915502..63c95503 100644
--- a/sway/ipc-server.c
+++ b/sway/ipc-server.c
@@ -349,6 +349,22 @@ void ipc_event_barconfig_update(struct bar_config *bar) {
json_object_put(json);
}
+void ipc_event_bar_state_update(struct bar_config *bar) {
+ if (!ipc_has_event_listeners(IPC_EVENT_BAR_STATE_UPDATE)) {
+ return;
+ }
+ wlr_log(WLR_DEBUG, "Sending bar_state_update event");
+
+ json_object *json = json_object_new_object();
+ json_object_object_add(json, "id", json_object_new_string(bar->id));
+ json_object_object_add(json, "visible_by_modifier",
+ json_object_new_boolean(bar->visible_by_modifier));
+
+ const char *json_string = json_object_to_json_string(json);
+ ipc_send_event(json_string, IPC_EVENT_BAR_STATE_UPDATE);
+ json_object_put(json);
+}
+
void ipc_event_mode(const char *mode, bool pango) {
if (!ipc_has_event_listeners(IPC_EVENT_MODE)) {
return;
@@ -651,6 +667,8 @@ void ipc_client_handle_command(struct ipc_client *client) {
client->subscribed_events |= event_mask(IPC_EVENT_WORKSPACE);
} else if (strcmp(event_type, "barconfig_update") == 0) {
client->subscribed_events |= event_mask(IPC_EVENT_BARCONFIG_UPDATE);
+ } else if (strcmp(event_type, "bar_state_update") == 0) {
+ client->subscribed_events |= event_mask(IPC_EVENT_BAR_STATE_UPDATE);
} else if (strcmp(event_type, "mode") == 0) {
client->subscribed_events |= event_mask(IPC_EVENT_MODE);
} else if (strcmp(event_type, "shutdown") == 0) {
diff --git a/sway/main.c b/sway/main.c
index dea4a31c..8d39d5f1 100644
--- a/sway/main.c
+++ b/sway/main.c
@@ -287,7 +287,6 @@ int main(int argc, char **argv) {
}
}
- // TODO: switch logging over to wlroots?
if (debug) {
wlr_log_init(WLR_DEBUG, NULL);
} else if (verbose || validate) {
diff --git a/sway/sway-bar.5.scd b/sway/sway-bar.5.scd
index 6729c9ac..873741c0 100644
--- a/sway/sway-bar.5.scd
+++ b/sway/sway-bar.5.scd
@@ -65,6 +65,22 @@ Sway allows configuring swaybar in the sway configuration file.
is given, when mouse button _n_ has been released). To disable the default
behavior for a button, use the command _nop_.
+*mode* dock|hide|invisible
+ Specifies the visibility of the bar. In _dock_ mode, it is permanently
+ visible at one edge of the screen. In _hide_ mode, it is hidden unless the
+ modifier key is pressed, though this behaviour depends on the hidden state.
+ In _invisible_ mode, it is permanently hidden. Default is _dock_.
+
+*hidden\_state* hide|show
+ Specifies the behaviour of the bar when it is in _hide_ mode. When the
+ hidden state is _hide_, then it is normally hidden, and only unhidden by
+ pressing the modifier key or in case of urgency hints. When the hidden
+ state is _show_, then it is permanently visible, drawn on top of the
+ currently visible workspace. Default is _hide_.
+
+*modifier* <Modifier>|none
+ Specifies the modifier key that shows a hidden bar. Default is _Mod4_.
+
## TRAY
Swaybar provides a system tray where third-party applications may place icons.
diff --git a/sway/sway-input.5.scd b/sway/sway-input.5.scd
index e5673452..82273ef3 100644
--- a/sway/sway-input.5.scd
+++ b/sway/sway-input.5.scd
@@ -143,4 +143,4 @@ in their own "seat").
# SEE ALSO
-*sway*(5)
+*sway*(5) *sway-output*(5)
diff --git a/sway/sway-output.5.scd b/sway/sway-output.5.scd
new file mode 100644
index 00000000..fe5b33bc
--- /dev/null
+++ b/sway/sway-output.5.scd
@@ -0,0 +1,66 @@
+sway-output(5)
+
+# NAME
+
+sway-output - output configuration commands for sway
+
+# DESCRIPTION
+
+You may combine output commands into one, like so:
+
+ output HDMI-A-1 mode 1920x1080 pos 1920,0 bg ~/wallpaper.png stretch
+
+You can get a list of output names with *swaymsg -t get\_outputs*. You may also
+match any output by using the output name "\*".
+
+# COMMANDS
+
+*output* <name> mode|resolution|res <WIDTHxHEIGHT>[@<RATE>[Hz]]
+ Configures the specified output to use the given mode. Modes are a
+ combination of width and height (in pixels) and a refresh rate that your
+ display can be configured to use. For a list of available modes for each
+ output, use *swaymsg -t get\_outputs*.
+
+ Examples:
+
+ output HDMI-A-1 mode 1920x1080
+
+ output HDMI-A-1 mode 1920x1080@60Hz
+
+*output* <name> position|pos <X> <Y>
+ Places the specified output at the specific position in the global
+ coordinate space.
+
+*output* <name> scale <factor>
+ Scales the specified output by the specified scale _factor_. An integer is
+ recommended, but fractional values are also supported. If a fractional
+ value are specified, be warned that it is not possible to faithfully
+ represent the contents of your windows - they will be rendered at the next
+ highest integral scale factor and downscaled. You may be better served by
+ setting an integral scale factor and adjusting the font size of your
+ applications to taste.
+
+*output* <name> background|bg <file> <mode> [<fallback\_color>]
+ Sets the wallpaper for the given output to the specified file, using the
+ given scaling mode (one of "stretch", "fill", "fit", "center", "tile"). If
+ the specified file cannot be accessed or if the image does fill the entire
+ output, a fallback color may be provided to cover the rest of the output.
+ __fallback\_color__ should be specified as _#RRGGBB_. Alpha is not
+ supported.
+
+*output* <name> background|bg <color> solid\_color
+ Sets the background of the given output to the specified color. _color_
+ should be specified as _#RRGGBB_. Alpha is not supported.
+
+*output* <name> transform <transform>
+ Sets the background transform to the given value. Can be one of "90", "180",
+ "270" for rotation; or "flipped", "flipped-90", "flipped-180", "flipped-270"
+ to apply a rotation and flip, or "normal" to apply no transform.
+
+*output* <name> disable|enable
+ Enables or disables the specified output (all outputs are enabled by
+ default).
+
+# SEE ALSO
+
+*sway*(5) *sway-input*(5)
diff --git a/sway/sway.1.scd b/sway/sway.1.scd
index 0c2ee974..f66c4cdb 100644
--- a/sway/sway.1.scd
+++ b/sway/sway.1.scd
@@ -92,4 +92,4 @@ source contributors. For more information about sway development, see
# SEE ALSO
-*sway*(5) *swaymsg*(1) *sway-input*(5) *sway-bar*(5)
+*sway*(5) *swaymsg*(1) *sway-input*(5) *sway-output*(5) *sway-bar*(5)
diff --git a/sway/sway.5.scd b/sway/sway.5.scd
index 240e0731..f6f0e859 100644
--- a/sway/sway.5.scd
+++ b/sway/sway.5.scd
@@ -87,14 +87,15 @@ The following commands may only be used in the configuration file.
The following commands cannot be used directly in the configuration file.
They are expected to be used with *bindsym* or at runtime through *swaymsg*(1).
-*border* normal|pixel [<n>]
+*border* none|normal|csd|pixel [<n>]
Set border style for focused window. _normal_ includes a border of
thickness _n_ and a title bar. _pixel_ is a border without title bar _n_
- pixels thick. Default is _normal_ with border thickness 2.
+ pixels thick. Default is _normal_ with border thickness 2. _csd_ is short
+ for client-side-decorations, which allows the client to draw its own
+ decorations.
-*border* none|toggle
- Set border style for focused window to _none_ or _toggle_ between the
- available border styles: _normal_, _pixel_, _none_.
+*border* toggle
+ Cycles through the available border styles.
*exit*
Exit sway and end your Wayland session.
@@ -420,15 +421,11 @@ The default colors are:
_focus\_wrapping force_. This is only available for convenience. Please
use _focus\_wrapping_ instead when possible.
-*gaps* edge\_gaps on|off|toggle
- When _on_, gaps will be added between windows and workspace edges if the
- inner gap is nonzero. When _off_, gaps will only be added between views.
- _toggle_ cannot be used in the configuration file.
-
*gaps* inner|outer <amount>
Sets default _amount_ pixels of _inner_ or _outer_ gap, where the inner
affects spacing around each view and outer affects the spacing around each
- workspace. Outer gaps are in addition to inner gaps.
+ workspace. Outer gaps are in addition to inner gaps. To reduce or remove
+ outer gaps, outer gaps can be set to a negative value.
This affects new workspaces only, and is used when the workspace doesn't
have its own gaps settings (see: workspace <ws> gaps inner|outer <amount>).
@@ -501,61 +498,6 @@ The default colors are:
Prevents windows matching <criteria> from being focused automatically when
they're created. This has no effect on the first window in a workspace.
-*output* <name> mode|resolution|res <WIDTHxHEIGHT>[@<RATE>[Hz]]
- Configures the specified output to use the given mode. Modes are a
- combination of width and height (in pixels) and a refresh rate that your
- display can be configured to use. For a list of available modes for each
- output, use *swaymsg -t get\_outputs*.
-
- Examples:
-
- output HDMI-A-1 mode 1920x1080
-
- output HDMI-A-1 mode 1920x1080@60Hz
-
-*output* <name> position|pos <X> <Y>
- Places the specified output at the specific position in the global
- coordinate space.
-
-*output* <name> scale <factor>
- Scales the specified output by the specified scale _factor_. An integer is
- recommended, but fractional values are also supported. If a fractional
- value are specified, be warned that it is not possible to faithfully
- represent the contents of your windows - they will be rendered at the next
- highest integral scale factor and downscaled. You may be better served by
- setting an integral scale factor and adjusting the font size of your
- applications to taste.
-
-*output* <name> background|bg <file> <mode> [<fallback\_color>]
- Sets the wallpaper for the given output to the specified file, using the
- given scaling mode (one of "stretch", "fill", "fit", "center", "tile"). If
- the specified file cannot be accessed or if the image does fill the entire
- output, a fallback color may be provided to cover the rest of the output.
- __fallback\_color__ should be specified as _#RRGGBB_. Alpha is not
- supported.
-
-**output** <name> background|bg <color> solid\_color
- Sets the background of the given output to the specified color. _color_
- should be specified as _#RRGGBB_. Alpha is not supported.
-
-**output** <name> transform <transform>
- Sets the background transform to the given value. Can be one of "90", "180",
- "270" for rotation; or "flipped", "flipped-90", "flipped-180", "flipped-270"
- to apply a rotation and flip, or "normal" to apply no transform.
-
-*output* <name> disable|enable
- Enables or disables the specified output (all outputs are enabled by
- default).
-
-*NOTES FOR THE OUTPUT COMMANDS*
-
-You may combine output commands into one, like so:
-
- output HDMI-A-1 mode 1920x1080 pos 1920,0 bg ~/wallpaper.png stretch
-
-You can get a list of output names with *swaymsg -t get\_outputs*. You may also
-match any output by using the output name "\*".
-
*popup\_during\_fullscreen* smart|ignore|leave\_fullscreen
Determines what to do when a fullscreen view opens a dialog.
If _smart_ (the default), the dialog will be displayed. If _ignore_, the
@@ -618,6 +560,18 @@ match any output by using the output name "\*".
*workspace\_layout* default|stacking|tabbed
Specifies the initial layout for new workspaces.
+# BAR CONTROL
+
+*bar hidden\_state* hide|show|toggle [<bar\_id>]
+ Sets the hidden state of the bar (see *sway-bar*(5)), either individually,
+ by specifying a bar id, or if none is given, for all bar instances.
+ _toggle_ switches between _hide_ and _show_.
+
+*bar mode* dock|hide|invisible|toggle [<bar\_id>]
+ Sets the mode of the bar (see *sway-bar*(5)), either individually,
+ by specifying a bar id, or if none is given, for all bar instances.
+ _toggle_ switches between _dock_ and _hide_.
+
# CRITERIA
A criteria is a string in the form of, for example:
diff --git a/sway/tree/arrange.c b/sway/tree/arrange.c
index 373460a2..852d53bf 100644
--- a/sway/tree/arrange.c
+++ b/sway/tree/arrange.c
@@ -180,6 +180,10 @@ void arrange_workspace(struct sway_workspace *workspace) {
if (config->reloading) {
return;
}
+ if (!workspace->output) {
+ // Happens when there are no outputs connected
+ return;
+ }
struct sway_output *output = workspace->output;
struct wlr_box *area = &output->usable_area;
wlr_log(WLR_DEBUG, "Usable area for ws: %dx%d@%d,%d",
diff --git a/sway/tree/container.c b/sway/tree/container.c
index f36fe4b0..edab7a17 100644
--- a/sway/tree/container.c
+++ b/sway/tree/container.c
@@ -1202,8 +1202,8 @@ struct sway_container *container_split(struct sway_container *child,
container_add_child(cont, child);
if (set_focus) {
- seat_set_focus_container(seat, cont);
- seat_set_focus_container(seat, child);
+ seat_set_raw_focus(seat, &cont->node);
+ seat_set_raw_focus(seat, &child->node);
}
return cont;
diff --git a/sway/tree/view.c b/sway/tree/view.c
index 4b9bbfd0..85998547 100644
--- a/sway/tree/view.c
+++ b/sway/tree/view.c
@@ -504,7 +504,16 @@ static struct sway_workspace *select_workspace(struct sway_view *view) {
}
// Use the focused workspace
- return seat_get_focused_workspace(seat);
+ struct sway_node *node = seat_get_focus_inactive(seat, &root->node);
+ if (node && node->type == N_WORKSPACE) {
+ return node->sway_workspace;
+ } else if (node && node->type == N_CONTAINER) {
+ return node->sway_container->workspace;
+ }
+
+ // If there's no focus_inactive workspace then we must be running without
+ // any outputs connected
+ return root->saved_workspaces->items[0];
}
static bool should_focus(struct sway_view *view) {
diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c
index d7650560..a1282c1e 100644
--- a/sway/tree/workspace.c
+++ b/sway/tree/workspace.c
@@ -73,10 +73,10 @@ struct sway_workspace *workspace_create(struct sway_output *output,
if (name) {
struct workspace_config *wsc = workspace_find_config(name);
if (wsc) {
- if (wsc->gaps_outer != -1) {
+ if (wsc->gaps_outer != INT_MIN) {
ws->gaps_outer = wsc->gaps_outer;
}
- if (wsc->gaps_inner != -1) {
+ if (wsc->gaps_inner != INT_MIN) {
ws->gaps_inner = wsc->gaps_inner;
}
}
@@ -618,9 +618,6 @@ void workspace_add_gaps(struct sway_workspace *ws) {
if (ws->current_gaps > 0) {
return;
}
- if (!config->edge_gaps) {
- return;
- }
if (config->smart_gaps) {
struct sway_seat *seat = input_manager_get_default_seat(input_manager);
struct sway_container *focus =