diff options
Diffstat (limited to 'sway')
-rw-r--r-- | sway/commands/bar.c | 115 | ||||
-rw-r--r-- | sway/commands/bar/hidden_state.c | 34 | ||||
-rw-r--r-- | sway/commands/bar/id.c | 2 | ||||
-rw-r--r-- | sway/commands/bar/mode.c | 34 | ||||
-rw-r--r-- | sway/commands/bar/status_command.c | 2 | ||||
-rw-r--r-- | sway/commands/border.c | 2 | ||||
-rw-r--r-- | sway/commands/gaps.c | 50 | ||||
-rw-r--r-- | sway/commands/move.c | 8 | ||||
-rw-r--r-- | sway/commands/sticky.c | 5 | ||||
-rw-r--r-- | sway/commands/swap.c | 19 | ||||
-rw-r--r-- | sway/commands/workspace.c | 22 | ||||
-rw-r--r-- | sway/config.c | 1 | ||||
-rw-r--r-- | sway/config/bar.c | 16 | ||||
-rw-r--r-- | sway/desktop/output.c | 12 | ||||
-rw-r--r-- | sway/desktop/render.c | 165 | ||||
-rw-r--r-- | sway/input/cursor.c | 6 | ||||
-rw-r--r-- | sway/input/keyboard.c | 28 | ||||
-rw-r--r-- | sway/input/seat.c | 51 | ||||
-rw-r--r-- | sway/ipc-server.c | 18 | ||||
-rw-r--r-- | sway/main.c | 1 | ||||
-rw-r--r-- | sway/sway-bar.5.scd | 16 | ||||
-rw-r--r-- | sway/sway-input.5.scd | 2 | ||||
-rw-r--r-- | sway/sway-output.5.scd | 66 | ||||
-rw-r--r-- | sway/sway.1.scd | 2 | ||||
-rw-r--r-- | sway/sway.5.scd | 86 | ||||
-rw-r--r-- | sway/tree/arrange.c | 4 | ||||
-rw-r--r-- | sway/tree/container.c | 4 | ||||
-rw-r--r-- | sway/tree/view.c | 11 | ||||
-rw-r--r-- | sway/tree/workspace.c | 7 |
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 = |