diff options
Diffstat (limited to 'sway/commands')
56 files changed, 923 insertions, 300 deletions
diff --git a/sway/commands/assign.c b/sway/commands/assign.c index 04582e88..716d70cf 100644 --- a/sway/commands/assign.c +++ b/sway/commands/assign.c @@ -1,4 +1,4 @@ -#define _XOPEN_SOURCE 700 +#define _POSIX_C_SOURCE 200809L #include <stdio.h> #include <string.h> #include "sway/commands.h" diff --git a/sway/commands/bar.c b/sway/commands/bar.c index c808aef2..2a82d508 100644 --- a/sway/commands/bar.c +++ b/sway/commands/bar.c @@ -8,12 +8,12 @@ // Must be in alphabetical order for bsearch static struct cmd_handler bar_handlers[] = { - { "activate_button", bar_cmd_activate_button }, + { "bindcode", bar_cmd_bindcode }, { "binding_mode_indicator", bar_cmd_binding_mode_indicator }, { "bindsym", bar_cmd_bindsym }, { "colors", bar_cmd_colors }, - { "context_button", bar_cmd_context_button }, { "font", bar_cmd_font }, + { "gaps", bar_cmd_gaps }, { "height", bar_cmd_height }, { "hidden_state", bar_cmd_hidden_state }, { "icon_theme", bar_cmd_icon_theme }, @@ -22,10 +22,13 @@ static struct cmd_handler bar_handlers[] = { { "output", bar_cmd_output }, { "pango_markup", bar_cmd_pango_markup }, { "position", bar_cmd_position }, - { "secondary_button", bar_cmd_secondary_button }, { "separator_symbol", bar_cmd_separator_symbol }, { "status_command", bar_cmd_status_command }, + { "status_edge_padding", bar_cmd_status_edge_padding }, + { "status_padding", bar_cmd_status_padding }, + { "strip_workspace_name", bar_cmd_strip_workspace_name }, { "strip_workspace_numbers", bar_cmd_strip_workspace_numbers }, + { "tray_bindsym", bar_cmd_tray_bindsym }, { "tray_output", bar_cmd_tray_output }, { "tray_padding", bar_cmd_tray_padding }, { "workspace_buttons", bar_cmd_workspace_buttons }, diff --git a/sway/commands/bar/activate_button.c b/sway/commands/bar/activate_button.c deleted file mode 100644 index 7310e7ec..00000000 --- a/sway/commands/bar/activate_button.c +++ /dev/null @@ -1,8 +0,0 @@ -#include <stdlib.h> -#include "sway/commands.h" -#include "log.h" - -struct cmd_results *bar_cmd_activate_button(int argc, char **argv) { - // TODO TRAY - return cmd_results_new(CMD_INVALID, "activate_button", "TODO TRAY"); -} diff --git a/sway/commands/bar/bind.c b/sway/commands/bar/bind.c new file mode 100644 index 00000000..a4c65ec4 --- /dev/null +++ b/sway/commands/bar/bind.c @@ -0,0 +1,106 @@ +#include <libevdev/libevdev.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include "sway/commands.h" +#include "sway/config.h" +#include "sway/input/cursor.h" +#include "list.h" +#include "log.h" +#include "stringop.h" + +static struct cmd_results *bar_cmd_bind(int argc, char **argv, bool code) { + const char *command = code ? "bar bindcode" : "bar bindsym"; + struct cmd_results *error = NULL; + if ((error = checkarg(argc, command, EXPECTED_AT_LEAST, 2))) { + return error; + } + if (!config->current_bar) { + return cmd_results_new(CMD_FAILURE, command, "No bar defined."); + } + + struct bar_binding *binding = calloc(1, sizeof(struct bar_binding)); + if (!binding) { + return cmd_results_new(CMD_FAILURE, command, + "Unable to allocate bar binding"); + } + + binding->release = false; + if (strcmp("--release", argv[0]) == 0) { + binding->release = true; + argv++; + argc--; + } + + char *message = NULL; + if (code) { + binding->button = get_mouse_bindcode(argv[0], &message); + } else { + binding->button = get_mouse_bindsym(argv[0], &message); + } + if (message) { + free_bar_binding(binding); + error = cmd_results_new(CMD_INVALID, command, message); + free(message); + return error; + } else if (!binding->button) { + free_bar_binding(binding); + return cmd_results_new(CMD_INVALID, command, + "Unknown button %s", argv[0]); + } + + const char *name = libevdev_event_code_get_name(EV_KEY, binding->button); + if (!name) { + switch (binding->button) { + case SWAY_SCROLL_UP: + name = "SWAY_SCROLL_UP"; + break; + case SWAY_SCROLL_DOWN: + name = "SWAY_SCROLL_DOWN"; + break; + case SWAY_SCROLL_LEFT: + name = "SWAY_SCROLL_LEFT"; + break; + case SWAY_SCROLL_RIGHT: + name = "SWAY_SCROLL_RIGHT"; + break; + default: + // Unreachable + break; + } + } + + binding->command = join_args(argv + 1, argc - 1); + + list_t *bindings = config->current_bar->bindings; + bool overwritten = false; + for (int i = 0; i < bindings->length; i++) { + struct bar_binding *other = bindings->items[i]; + if (other->button == binding->button && + other->release == binding->release) { + overwritten = true; + bindings->items[i] = binding; + free_bar_binding(other); + wlr_log(WLR_DEBUG, "[bar %s] Updated binding for %u (%s)%s", + config->current_bar->id, binding->button, name, + binding->release ? " - release" : ""); + break; + } + } + if (!overwritten) { + list_add(bindings, binding); + wlr_log(WLR_DEBUG, "[bar %s] Added binding for %u (%s)%s", + config->current_bar->id, binding->button, name, + binding->release ? " - release" : ""); + } + + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} + +struct cmd_results *bar_cmd_bindcode(int argc, char **argv) { + return bar_cmd_bind(argc, argv, true); +} + +struct cmd_results *bar_cmd_bindsym(int argc, char **argv) { + return bar_cmd_bind(argc, argv, false); +} diff --git a/sway/commands/bar/bindsym.c b/sway/commands/bar/bindsym.c deleted file mode 100644 index 965c8903..00000000 --- a/sway/commands/bar/bindsym.c +++ /dev/null @@ -1,69 +0,0 @@ -#define _XOPEN_SOURCE 500 -#include <stdlib.h> -#include <string.h> -#include <strings.h> -#include "sway/commands.h" -#include "sway/config.h" -#include "list.h" -#include "log.h" -#include "stringop.h" - -struct cmd_results *bar_cmd_bindsym(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "bar bindsym", EXPECTED_AT_LEAST, 2))) { - return error; - } - if (!config->current_bar) { - return cmd_results_new(CMD_FAILURE, "bar bindsym", "No bar defined."); - } - - struct bar_binding *binding = calloc(1, sizeof(struct bar_binding)); - if (!binding) { - return cmd_results_new(CMD_FAILURE, "bar bindsym", - "Unable to allocate bar binding"); - } - - binding->release = false; - if (strcmp("--release", argv[0]) == 0) { - binding->release = true; - argv++; - argc--; - } - - binding->button = 0; - if (strncasecmp(argv[0], "button", strlen("button")) == 0 && - strlen(argv[0]) == strlen("button0")) { - binding->button = argv[0][strlen("button")] - '0'; - } - if (binding->button < 1 || binding->button > 9) { - free_bar_binding(binding); - return cmd_results_new(CMD_FAILURE, "bar bindsym", - "Only button<1-9> is supported"); - } - - binding->command = join_args(argv + 1, argc - 1); - - list_t *bindings = config->current_bar->bindings; - bool overwritten = false; - for (int i = 0; i < bindings->length; i++) { - struct bar_binding *other = bindings->items[i]; - if (other->button == binding->button && - other->release == binding->release) { - overwritten = true; - bindings->items[i] = binding; - free_bar_binding(other); - wlr_log(WLR_DEBUG, "[bar %s] Updated binding for button%u%s", - config->current_bar->id, binding->button, - binding->release ? " (release)" : ""); - break; - } - } - if (!overwritten) { - list_add(bindings, binding); - wlr_log(WLR_DEBUG, "[bar %s] Added binding for button%u%s", - config->current_bar->id, binding->button, - binding->release ? " (release)" : ""); - } - - return cmd_results_new(CMD_SUCCESS, NULL, NULL); -} diff --git a/sway/commands/bar/colors.c b/sway/commands/bar/colors.c index 8c862ca9..ebf1e3e1 100644 --- a/sway/commands/bar/colors.c +++ b/sway/commands/bar/colors.c @@ -118,8 +118,8 @@ struct cmd_results *bar_colors_cmd_statusline(int argc, char **argv) { } struct cmd_results *bar_colors_cmd_focused_statusline(int argc, char **argv) { - return parse_single_color(&(config->current_bar->colors.focused_separator), - "focused_separator", argc, argv); + return parse_single_color(&(config->current_bar->colors.focused_statusline), + "focused_statusline", argc, argv); } struct cmd_results *bar_colors_cmd_urgent_workspace(int argc, char **argv) { diff --git a/sway/commands/bar/context_button.c b/sway/commands/bar/context_button.c deleted file mode 100644 index 3b76885a..00000000 --- a/sway/commands/bar/context_button.c +++ /dev/null @@ -1,8 +0,0 @@ -#include <stdlib.h> -#include "sway/commands.h" -#include "log.h" - -struct cmd_results *bar_cmd_context_button(int argc, char **argv) { - // TODO TRAY - return cmd_results_new(CMD_INVALID, "context_button", "TODO TRAY"); -} diff --git a/sway/commands/bar/gaps.c b/sway/commands/bar/gaps.c new file mode 100644 index 00000000..f78f3742 --- /dev/null +++ b/sway/commands/bar/gaps.c @@ -0,0 +1,60 @@ +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include "sway/commands.h" +#include "sway/ipc-server.h" +#include "log.h" + +struct cmd_results *bar_cmd_gaps(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "gaps", EXPECTED_AT_LEAST, 1))) { + return error; + } + if ((error = checkarg(argc, "gaps", EXPECTED_AT_MOST, 4))) { + return error; + } + if (!config->current_bar) { + return cmd_results_new(CMD_FAILURE, "bar gaps", "No bar defined."); + } + + int top = 0, right = 0, bottom = 0, left = 0; + + for (int i = 0; i < argc; i++) { + char *end; + int amount = strtol(argv[i], &end, 10); + if (strlen(end) && strcasecmp(end, "px") != 0) { + return cmd_results_new(CMD_INVALID, "bar gaps", + "Expected 'bar [<bar-id>] gaps <all> | <horizonal> " + "<vertical> | <top> <right> <bottom> <left>'"); + } + + if (i == 0) { + top = amount; + } + if (i == 0 || i == 1) { + right = amount; + } + if (i == 0 || i == 2) { + bottom = amount; + } + if (i == 0 || i == 1 || i == 3) { + left = amount; + } + } + + config->current_bar->gaps.top = top; + config->current_bar->gaps.right = right; + config->current_bar->gaps.bottom = bottom; + config->current_bar->gaps.left = left; + + wlr_log(WLR_DEBUG, "Setting bar gaps to %d %d %d %d on bar: %s", + config->current_bar->gaps.top, config->current_bar->gaps.right, + config->current_bar->gaps.bottom, config->current_bar->gaps.left, + config->current_bar->id); + + if (!config->reading) { + ipc_event_barconfig_update(config->current_bar); + } + + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/commands/bar/hidden_state.c b/sway/commands/bar/hidden_state.c index 5be6c2dc..79eaf01c 100644 --- a/sway/commands/bar/hidden_state.c +++ b/sway/commands/bar/hidden_state.c @@ -1,4 +1,4 @@ -#define _XOPEN_SOURCE 500 +#define _POSIX_C_SOURCE 200809L #include <string.h> #include <strings.h> #include "sway/commands.h" diff --git a/sway/commands/bar/icon_theme.c b/sway/commands/bar/icon_theme.c index 44cd3076..9d3b6040 100644 --- a/sway/commands/bar/icon_theme.c +++ b/sway/commands/bar/icon_theme.c @@ -1,8 +1,28 @@ -#define _XOPEN_SOURCE 500 +#define _POSIX_C_SOURCE 200809L #include <string.h> +#include "config.h" #include "sway/commands.h" +#include "sway/config.h" +#include "log.h" struct cmd_results *bar_cmd_icon_theme(int argc, char **argv) { - // TODO TRAY - return cmd_results_new(CMD_INVALID, "icon_theme", "TODO TRAY"); +#if HAVE_TRAY + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "icon_theme", EXPECTED_EQUAL_TO, 1))) { + return error; + } + + if (!config->current_bar) { + return cmd_results_new(CMD_FAILURE, "tray_padding", "No bar defined."); + } + + wlr_log(WLR_DEBUG, "[Bar %s] Setting icon theme to %s", + config->current_bar->id, argv[0]); + free(config->current_bar->icon_theme); + config->current_bar->icon_theme = strdup(argv[0]); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +#else + return cmd_results_new(CMD_INVALID, "icon_theme", + "Sway has been compiled without tray support"); +#endif } diff --git a/sway/commands/bar/id.c b/sway/commands/bar/id.c index 7690a852..35509459 100644 --- a/sway/commands/bar/id.c +++ b/sway/commands/bar/id.c @@ -1,4 +1,4 @@ -#define _XOPEN_SOURCE 500 +#define _POSIX_C_SOURCE 200809L #include <string.h> #include "sway/commands.h" #include "log.h" diff --git a/sway/commands/bar/mode.c b/sway/commands/bar/mode.c index 2cba785e..dcaf6da9 100644 --- a/sway/commands/bar/mode.c +++ b/sway/commands/bar/mode.c @@ -1,4 +1,4 @@ -#define _XOPEN_SOURCE 500 +#define _POSIX_C_SOURCE 200809L #include <string.h> #include <strings.h> #include "sway/commands.h" diff --git a/sway/commands/bar/modifier.c b/sway/commands/bar/modifier.c index 09025fff..b5a16f45 100644 --- a/sway/commands/bar/modifier.c +++ b/sway/commands/bar/modifier.c @@ -20,15 +20,14 @@ struct cmd_results *bar_cmd_modifier(int argc, char **argv) { uint32_t tmp_mod; if ((tmp_mod = get_modifier_mask_by_name(split->items[i])) > 0) { mod |= tmp_mod; - continue; } else { error = cmd_results_new(CMD_INVALID, "modifier", "Unknown modifier '%s'", split->items[i]); - free_flat_list(split); + list_free_items_and_destroy(split); return error; } } - free_flat_list(split); + list_free_items_and_destroy(split); config->current_bar->modifier = mod; wlr_log(WLR_DEBUG, "Show/Hide the bar when pressing '%s' in hide mode.", argv[0]); diff --git a/sway/commands/bar/output.c b/sway/commands/bar/output.c index 72754e05..930d779d 100644 --- a/sway/commands/bar/output.c +++ b/sway/commands/bar/output.c @@ -1,4 +1,4 @@ -#define _XOPEN_SOURCE 500 +#define _POSIX_C_SOURCE 200809L #include <stdbool.h> #include <string.h> #include "sway/commands.h" diff --git a/sway/commands/bar/secondary_button.c b/sway/commands/bar/secondary_button.c deleted file mode 100644 index 449124cb..00000000 --- a/sway/commands/bar/secondary_button.c +++ /dev/null @@ -1,8 +0,0 @@ -#include <stdlib.h> -#include "sway/commands.h" -#include "log.h" - -struct cmd_results *bar_cmd_secondary_button(int argc, char **argv) { - // TODO TRAY - return cmd_results_new(CMD_INVALID, "secondary_button", "TODO TRAY"); -} diff --git a/sway/commands/bar/separator_symbol.c b/sway/commands/bar/separator_symbol.c index 392ab730..060b8f52 100644 --- a/sway/commands/bar/separator_symbol.c +++ b/sway/commands/bar/separator_symbol.c @@ -1,4 +1,4 @@ -#define _XOPEN_SOURCE 500 +#define _POSIX_C_SOURCE 200809L #include <string.h> #include "sway/commands.h" #include "log.h" diff --git a/sway/commands/bar/status_edge_padding.c b/sway/commands/bar/status_edge_padding.c new file mode 100644 index 00000000..f3b10631 --- /dev/null +++ b/sway/commands/bar/status_edge_padding.c @@ -0,0 +1,21 @@ +#include <stdlib.h> +#include <string.h> +#include "sway/commands.h" +#include "log.h" + +struct cmd_results *bar_cmd_status_edge_padding(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "status_edge_padding", EXPECTED_EQUAL_TO, 1))) { + return error; + } + char *end; + int padding = strtol(argv[0], &end, 10); + if (strlen(end) || padding < 0) { + return cmd_results_new(CMD_INVALID, "status_edge_padding", + "Padding must be a positive integer"); + } + config->current_bar->status_edge_padding = padding; + wlr_log(WLR_DEBUG, "Status edge padding on bar %s: %d", + config->current_bar->id, config->current_bar->status_edge_padding); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/commands/bar/status_padding.c b/sway/commands/bar/status_padding.c new file mode 100644 index 00000000..13b8eb6b --- /dev/null +++ b/sway/commands/bar/status_padding.c @@ -0,0 +1,21 @@ +#include <stdlib.h> +#include <string.h> +#include "sway/commands.h" +#include "log.h" + +struct cmd_results *bar_cmd_status_padding(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "status_padding", EXPECTED_EQUAL_TO, 1))) { + return error; + } + char *end; + int padding = strtol(argv[0], &end, 10); + if (strlen(end) || padding < 0) { + return cmd_results_new(CMD_INVALID, "status_padding", + "Padding must be a positive integer"); + } + config->current_bar->status_padding = padding; + wlr_log(WLR_DEBUG, "Status padding on bar %s: %d", + config->current_bar->id, config->current_bar->status_padding); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/commands/bar/strip_workspace_name.c b/sway/commands/bar/strip_workspace_name.c new file mode 100644 index 00000000..79692f6e --- /dev/null +++ b/sway/commands/bar/strip_workspace_name.c @@ -0,0 +1,32 @@ +#include <string.h> +#include <strings.h> +#include "sway/commands.h" +#include "log.h" +#include "util.h" + +struct cmd_results *bar_cmd_strip_workspace_name(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, + "strip_workspace_name", EXPECTED_EQUAL_TO, 1))) { + return error; + } + if (!config->current_bar) { + return cmd_results_new(CMD_FAILURE, + "strip_workspace_name", "No bar defined."); + } + + config->current_bar->strip_workspace_name = + parse_boolean(argv[0], config->current_bar->strip_workspace_name); + + if (config->current_bar->strip_workspace_name) { + config->current_bar->strip_workspace_numbers = false; + + wlr_log(WLR_DEBUG, "Stripping workspace name on bar: %s", + config->current_bar->id); + } else { + wlr_log(WLR_DEBUG, "Enabling workspace name on bar: %s", + config->current_bar->id); + } + + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/commands/bar/strip_workspace_numbers.c b/sway/commands/bar/strip_workspace_numbers.c index 4e47d047..b33d01e5 100644 --- a/sway/commands/bar/strip_workspace_numbers.c +++ b/sway/commands/bar/strip_workspace_numbers.c @@ -2,6 +2,7 @@ #include <strings.h> #include "sway/commands.h" #include "log.h" +#include "util.h" struct cmd_results *bar_cmd_strip_workspace_numbers(int argc, char **argv) { struct cmd_results *error = NULL; @@ -13,17 +14,19 @@ struct cmd_results *bar_cmd_strip_workspace_numbers(int argc, char **argv) { return cmd_results_new(CMD_FAILURE, "strip_workspace_numbers", "No bar defined."); } - if (strcasecmp("yes", argv[0]) == 0) { - config->current_bar->strip_workspace_numbers = true; + + config->current_bar->strip_workspace_numbers = + parse_boolean(argv[0], config->current_bar->strip_workspace_numbers); + + if (config->current_bar->strip_workspace_numbers) { + config->current_bar->strip_workspace_name = false; + wlr_log(WLR_DEBUG, "Stripping workspace numbers on bar: %s", config->current_bar->id); - } else if (strcasecmp("no", argv[0]) == 0) { - config->current_bar->strip_workspace_numbers = false; + } else { wlr_log(WLR_DEBUG, "Enabling workspace numbers on bar: %s", config->current_bar->id); - } else { - return cmd_results_new(CMD_INVALID, - "strip_workspace_numbers", "Invalid value %s", argv[0]); } + return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/bar/tray_bindsym.c b/sway/commands/bar/tray_bindsym.c new file mode 100644 index 00000000..ad413446 --- /dev/null +++ b/sway/commands/bar/tray_bindsym.c @@ -0,0 +1,55 @@ +#include <strings.h> +#include "config.h" +#include "sway/commands.h" +#include "sway/config.h" +#include "log.h" + +struct cmd_results *bar_cmd_tray_bindsym(int argc, char **argv) { +#if HAVE_TRAY + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "tray_bindsym", EXPECTED_EQUAL_TO, 2))) { + return error; + } + + if (!config->current_bar) { + return cmd_results_new(CMD_FAILURE, "tray_bindsym", "No bar defined."); + } + + int button = 0; + if (strncasecmp(argv[0], "button", strlen("button")) == 0 && + strlen(argv[0]) == strlen("button0")) { + button = argv[0][strlen("button")] - '0'; + } + if (button < 1 || button > 9) { + return cmd_results_new(CMD_FAILURE, "tray_bindsym", + "[Bar %s] Only buttons 1 to 9 are supported", + config->current_bar->id); + } + + static const char *commands[] = { + "ContextMenu", + "Activate", + "SecondaryActivate", + "ScrollDown", + "ScrollLeft", + "ScrollRight", + "ScrollUp", + "nop" + }; + + for (size_t i = 0; i < sizeof(commands) / sizeof(commands[0]); ++i) { + if (strcasecmp(argv[1], commands[i]) == 0) { + wlr_log(WLR_DEBUG, "[Bar %s] Binding button %d to %s", + config->current_bar->id, button, commands[i]); + config->current_bar->tray_bindings[button] = commands[i]; + return cmd_results_new(CMD_SUCCESS, NULL, NULL); + } + } + + return cmd_results_new(CMD_INVALID, "tray_bindsym", + "[Bar %s] Invalid command %s", config->current_bar->id, argv[1]); +#else + return cmd_results_new(CMD_INVALID, "tray_bindsym", + "Sway has been compiled without tray support"); +#endif +} diff --git a/sway/commands/bar/tray_output.c b/sway/commands/bar/tray_output.c index 6ab16731..a1169c20 100644 --- a/sway/commands/bar/tray_output.c +++ b/sway/commands/bar/tray_output.c @@ -1,8 +1,42 @@ -#define _XOPEN_SOURCE 500 +#define _POSIX_C_SOURCE 200809L #include <string.h> +#include "config.h" #include "sway/commands.h" +#include "sway/config.h" +#include "list.h" +#include "log.h" struct cmd_results *bar_cmd_tray_output(int argc, char **argv) { - // TODO TRAY - return cmd_results_new(CMD_INVALID, "tray_output", "TODO TRAY"); +#if HAVE_TRAY + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "tray_output", EXPECTED_EQUAL_TO, 1))) { + return error; + } + + if (!config->current_bar) { + return cmd_results_new(CMD_FAILURE, "tray_output", "No bar defined."); + } + + list_t *outputs = config->current_bar->tray_outputs; + if (!outputs) { + config->current_bar->tray_outputs = outputs = create_list(); + } + + if (strcmp(argv[0], "none") == 0) { + wlr_log(WLR_DEBUG, "Hiding tray on bar: %s", config->current_bar->id); + for (int i = 0; i < outputs->length; ++i) { + free(outputs->items[i]); + } + outputs->length = 0; + } else { + wlr_log(WLR_DEBUG, "Showing tray on output '%s' for bar: %s", argv[0], + config->current_bar->id); + } + list_add(outputs, strdup(argv[0])); + + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +#else + return cmd_results_new(CMD_INVALID, "tray_output", + "Sway has been compiled without tray support"); +#endif } diff --git a/sway/commands/bar/tray_padding.c b/sway/commands/bar/tray_padding.c index 91c56f19..eb795b00 100644 --- a/sway/commands/bar/tray_padding.c +++ b/sway/commands/bar/tray_padding.c @@ -1,9 +1,42 @@ #include <stdlib.h> #include <strings.h> +#include "config.h" #include "sway/commands.h" +#include "sway/config.h" #include "log.h" struct cmd_results *bar_cmd_tray_padding(int argc, char **argv) { - // TODO TRAY - return cmd_results_new(CMD_INVALID, "tray_padding", "TODO TRAY"); +#if HAVE_TRAY + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "tray_padding", EXPECTED_AT_LEAST, 1))) { + return error; + } + if ((error = checkarg(argc, "tray_padding", EXPECTED_AT_MOST, 2))) { + return error; + } + + if (!config->current_bar) { + return cmd_results_new(CMD_FAILURE, "tray_padding", "No bar defined."); + } + struct bar_config *bar = config->current_bar; + + char *end; + int padding = strtol(argv[0], &end, 10); + if (padding < 0 || (*end != '\0' && strcasecmp(end, "px") != 0)) { + return cmd_results_new(CMD_INVALID, "tray_padding", + "[Bar %s] Invalid tray padding value: %s", bar->id, argv[0]); + } + + if (argc == 2 && strcasecmp(argv[1], "px") != 0) { + return cmd_results_new(CMD_INVALID, "tray_padding", + "Expected 'tray_padding <px> [px]'"); + } + + wlr_log(WLR_DEBUG, "[Bar %s] Setting tray padding to %d", bar->id, padding); + config->current_bar->tray_padding = padding; + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +#else + return cmd_results_new(CMD_INVALID, "tray_padding", + "Sway has been compiled without tray support"); +#endif } diff --git a/sway/commands/bind.c b/sway/commands/bind.c index a9de227f..be47d412 100644 --- a/sway/commands/bind.c +++ b/sway/commands/bind.c @@ -1,15 +1,13 @@ -#define _XOPEN_SOURCE 500 -#ifdef __linux__ +#define _POSIX_C_SOURCE 200809L +#include <libevdev/libevdev.h> #include <linux/input-event-codes.h> -#elif __FreeBSD__ -#include <dev/evdev/input-event-codes.h> -#endif #include <xkbcommon/xkbcommon.h> #include <xkbcommon/xkbcommon-names.h> #include <string.h> #include <strings.h> #include "sway/commands.h" #include "sway/config.h" +#include "sway/input/cursor.h" #include "sway/ipc-server.h" #include "list.h" #include "log.h" @@ -23,9 +21,7 @@ void free_sway_binding(struct sway_binding *binding) { return; } - if (binding->keys) { - free_flat_list(binding->keys); - } + list_free_items_and_destroy(binding->keys); free(binding->input); free(binding->command); free(binding); @@ -80,7 +76,6 @@ static int key_qsort_cmp(const void *keyp_a, const void *keyp_b) { return (key_a < key_b) ? -1 : ((key_a > key_b) ? 1 : 0); } - /** * From a keycode, bindcode, or bindsym name and the most likely binding type, * identify the appropriate numeric value corresponding to the key. Return NULL @@ -90,52 +85,91 @@ static int key_qsort_cmp(const void *keyp_a, const void *keyp_b) { */ static struct cmd_results *identify_key(const char* name, bool first_key, uint32_t* key_val, enum binding_input_type* type) { - if (*type == BINDING_KEYCODE) { - // check for keycode + if (*type == BINDING_MOUSECODE) { + // check for mouse bindcodes + char *message = NULL; + uint32_t button = get_mouse_bindcode(name, &message); + if (!button) { + if (message) { + struct cmd_results *error = + cmd_results_new(CMD_INVALID, "bindcode", message); + free(message); + return error; + } else { + return cmd_results_new(CMD_INVALID, "bindcode", + "Unknown button code %s", name); + } + } + *key_val = button; + } else if (*type == BINDING_MOUSESYM) { + // check for mouse bindsyms (x11 buttons or event names) + char *message = NULL; + uint32_t button = get_mouse_bindsym(name, &message); + if (!button) { + if (message) { + struct cmd_results *error = + cmd_results_new(CMD_INVALID, "bindsym", message); + free(message); + return error; + } else if (!button) { + return cmd_results_new(CMD_INVALID, "bindsym", + "Unknown button %s", name); + } + } + *key_val = button; + } else if (*type == BINDING_KEYCODE) { + // check for keycode. If it is the first key, allow mouse bindcodes + if (first_key) { + char *message = NULL; + uint32_t button = get_mouse_bindcode(name, &message); + free(message); + if (button) { + *type = BINDING_MOUSECODE; + *key_val = button; + return NULL; + } + } + xkb_keycode_t keycode = strtol(name, NULL, 10); if (!xkb_keycode_is_legal_ext(keycode)) { - return cmd_results_new(CMD_INVALID, "bindcode", - "Invalid keycode '%s'", name); + if (first_key) { + return cmd_results_new(CMD_INVALID, "bindcode", + "Invalid keycode or button code '%s'", name); + } else { + return cmd_results_new(CMD_INVALID, "bindcode", + "Invalid keycode '%s'", name); + } } *key_val = keycode; } else { - // check for keysym - xkb_keysym_t keysym = xkb_keysym_from_name(name, - XKB_KEYSYM_CASE_INSENSITIVE); - - // Check for mouse binding - uint32_t button = 0; - if (strncasecmp(name, "button", strlen("button")) == 0 && - strlen(name) == strlen("button0")) { - button = name[strlen("button")] - '1' + BTN_LEFT; + // check for keysym. If it is the first key, allow mouse bindsyms + if (first_key) { + char *message = NULL; + uint32_t button = get_mouse_bindsym(name, &message); + if (message) { + struct cmd_results *error = + cmd_results_new(CMD_INVALID, "bindsym", message); + free(message); + return error; + } else if (button) { + *type = BINDING_MOUSESYM; + *key_val = button; + return NULL; + } } - if (*type == BINDING_KEYSYM) { - if (button) { - if (first_key) { - *type = BINDING_MOUSE; - *key_val = button; - } else { - return cmd_results_new(CMD_INVALID, "bindsym", - "Mixed button '%s' into key sequence", name); - } - } else if (keysym) { - *key_val = keysym; - } else { - return cmd_results_new(CMD_INVALID, "bindsym", - "Unknown key '%s'", name); - } - } else { - if (button) { - *key_val = button; - } else if (keysym) { + xkb_keysym_t keysym = xkb_keysym_from_name(name, + XKB_KEYSYM_CASE_INSENSITIVE); + if (!keysym) { + if (first_key) { return cmd_results_new(CMD_INVALID, "bindsym", - "Mixed keysym '%s' into button sequence", name); + "Unknown key or button '%s'", name); } else { return cmd_results_new(CMD_INVALID, "bindsym", - "Unknown button '%s'", name); + "Unknown key '%s'", name); } } + *key_val = keysym; } return NULL; } @@ -161,6 +195,7 @@ static struct cmd_results *cmd_bindsym_or_bindcode(int argc, char **argv, binding->type = bindcode ? BINDING_KEYCODE : BINDING_KEYSYM; bool exclude_titlebar = false; + bool warn = true; // Handle --release and --locked while (argc > 0) { @@ -178,6 +213,8 @@ static struct cmd_results *cmd_bindsym_or_bindcode(int argc, char **argv, strlen("--input-device=")) == 0) { free(binding->input); binding->input = strdup(argv[0] + strlen("--input-device=")); + } else if (strcmp("--no-warn", argv[0]) == 0) { + warn = false; } else { break; } @@ -186,7 +223,8 @@ static struct cmd_results *cmd_bindsym_or_bindcode(int argc, char **argv, } if (binding->flags & (BINDING_BORDER | BINDING_CONTENTS | BINDING_TITLEBAR) || exclude_titlebar) { - binding->type = BINDING_MOUSE; + binding->type = binding->type == BINDING_KEYCODE ? + BINDING_MOUSECODE : BINDING_MOUSESYM; } if (argc < 2) { @@ -220,21 +258,22 @@ static struct cmd_results *cmd_bindsym_or_bindcode(int argc, char **argv, uint32_t *key = calloc(1, sizeof(uint32_t)); if (!key) { free_sway_binding(binding); - free_flat_list(split); + list_free_items_and_destroy(split); return cmd_results_new(CMD_FAILURE, bindtype, "Unable to allocate binding key"); } *key = key_val; list_add(binding->keys, key); } - free_flat_list(split); + list_free_items_and_destroy(split); binding->order = binding_order++; // refine region of interest for mouse binding once we are certain // that this is one if (exclude_titlebar) { binding->flags &= ~BINDING_TITLEBAR; - } else if (binding->type == BINDING_MOUSE) { + } else if (binding->type == BINDING_MOUSECODE + || binding->type == BINDING_MOUSESYM) { binding->flags |= BINDING_TITLEBAR; } @@ -255,8 +294,15 @@ static struct cmd_results *cmd_bindsym_or_bindcode(int argc, char **argv, for (int i = 0; i < mode_bindings->length; ++i) { struct sway_binding *config_binding = mode_bindings->items[i]; if (binding_key_compare(binding, config_binding)) { - wlr_log(WLR_DEBUG, "overwriting old binding with command '%s'", - config_binding->command); + wlr_log(WLR_INFO, "Overwriting binding '%s' for device '%s' " + "from `%s` to `%s`", argv[0], binding->input, + binding->command, config_binding->command); + if (warn) { + config_add_swaynag_warning("Overwriting binding" + "'%s' for device '%s' to `%s` from `%s`", + argv[0], binding->input, binding->command, + config_binding->command); + } free_sway_binding(config_binding); mode_bindings->items[i] = binding; overwritten = true; @@ -270,7 +316,6 @@ static struct cmd_results *cmd_bindsym_or_bindcode(int argc, char **argv, wlr_log(WLR_DEBUG, "%s - Bound %s to command `%s` for device '%s'", bindtype, argv[0], binding->command, binding->input); return cmd_results_new(CMD_SUCCESS, NULL, NULL); - } struct cmd_results *cmd_bindsym(int argc, char **argv) { @@ -281,21 +326,25 @@ struct cmd_results *cmd_bindcode(int argc, char **argv) { return cmd_bindsym_or_bindcode(argc, argv, true); } - /** * Execute the command associated to a binding */ void seat_execute_command(struct sway_seat *seat, struct sway_binding *binding) { wlr_log(WLR_DEBUG, "running command for binding: %s", binding->command); - config->handler_context.seat = seat; - struct cmd_results *results = execute_command(binding->command, NULL, NULL); - if (results->status == CMD_SUCCESS) { + list_t *res_list = execute_command(binding->command, seat, NULL); + bool success = true; + for (int i = 0; i < res_list->length; ++i) { + struct cmd_results *results = res_list->items[i]; + if (results->status != CMD_SUCCESS) { + wlr_log(WLR_DEBUG, "could not run command for binding: %s (%s)", + binding->command, results->error); + success = false; + } + free_cmd_results(results); + } + list_free(res_list); + if (success) { ipc_event_binding(binding); - } else { - wlr_log(WLR_DEBUG, "could not run command for binding: %s (%s)", - binding->command, results->error); } - - free_cmd_results(results); } diff --git a/sway/commands/exec_always.c b/sway/commands/exec_always.c index 7a15709b..9ec28d81 100644 --- a/sway/commands/exec_always.c +++ b/sway/commands/exec_always.c @@ -1,4 +1,4 @@ -#define _XOPEN_SOURCE 500 +#define _POSIX_C_SOURCE 200809L #include <stdlib.h> #include <stdint.h> #include <string.h> diff --git a/sway/commands/focus.c b/sway/commands/focus.c index f6338c55..97ffe91c 100644 --- a/sway/commands/focus.c +++ b/sway/commands/focus.c @@ -193,7 +193,7 @@ static struct cmd_results *focus_output(struct sway_seat *seat, "Expected 'focus output <direction|name>'"); } char *identifier = join_args(argv, argc); - struct sway_output *output = output_by_name(identifier); + struct sway_output *output = output_by_name_or_id(identifier); if (!output) { enum wlr_direction direction; @@ -269,6 +269,9 @@ struct cmd_results *cmd_focus(int argc, char **argv) { } if (argc == 0 && container) { + if (container->scratchpad && !container->workspace) { + root_scratchpad_show(container); + } seat_set_focus_container(seat, container); seat_consider_warp_to_focus(seat); return cmd_results_new(CMD_SUCCESS, NULL, NULL); diff --git a/sway/commands/for_window.c b/sway/commands/for_window.c index ac4d6563..7c0f7d7f 100644 --- a/sway/commands/for_window.c +++ b/sway/commands/for_window.c @@ -1,4 +1,3 @@ -#define _XOPEN_SOURCE 500 #include <string.h> #include "sway/commands.h" #include "sway/criteria.h" diff --git a/sway/commands/fullscreen.c b/sway/commands/fullscreen.c index ff7cbba7..b78187d9 100644 --- a/sway/commands/fullscreen.c +++ b/sway/commands/fullscreen.c @@ -13,14 +13,14 @@ struct cmd_results *cmd_fullscreen(int argc, char **argv) { return error; } if (!root->outputs->length) { - return cmd_results_new(CMD_INVALID, "fullscreen", + return cmd_results_new(CMD_FAILURE, "fullscreen", "Can't run this command while there's no outputs connected."); } struct sway_node *node = config->handler_context.node; struct sway_container *container = config->handler_context.container; struct sway_workspace *workspace = config->handler_context.workspace; if (node->type == N_WORKSPACE && workspace->tiling->length == 0) { - return cmd_results_new(CMD_INVALID, "fullscreen", + return cmd_results_new(CMD_FAILURE, "fullscreen", "Can't fullscreen an empty workspace"); } if (node->type == N_WORKSPACE) { diff --git a/sway/commands/input/events.c b/sway/commands/input/events.c index e7ed69c6..69f46269 100644 --- a/sway/commands/input/events.c +++ b/sway/commands/input/events.c @@ -1,10 +1,69 @@ +#include <limits.h> #include <string.h> #include <strings.h> +#include <wlr/backend/libinput.h> #include "sway/config.h" #include "sway/commands.h" #include "sway/input/input-manager.h" #include "log.h" +static void toggle_send_events_for_device(struct input_config *ic, + struct sway_input_device *input_device) { + struct wlr_input_device *wlr_device = input_device->wlr_device; + if (!wlr_input_device_is_libinput(wlr_device)) { + return; + } + struct libinput_device *libinput_dev + = wlr_libinput_get_device_handle(wlr_device); + + enum libinput_config_send_events_mode mode = + libinput_device_config_send_events_get_mode(libinput_dev); + uint32_t possible = + libinput_device_config_send_events_get_modes(libinput_dev); + + switch (mode) { + case LIBINPUT_CONFIG_SEND_EVENTS_ENABLED: + mode = LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE; + if (possible & mode) { + break; + } + // fall through + case LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE: + mode = LIBINPUT_CONFIG_SEND_EVENTS_DISABLED; + if (possible & mode) { + break; + } + // fall through + case LIBINPUT_CONFIG_SEND_EVENTS_DISABLED: + default: + mode = LIBINPUT_CONFIG_SEND_EVENTS_ENABLED; + break; + } + + ic->send_events = mode; +} + +static void toggle_send_events(struct input_config *ic) { + struct sway_input_device *input_device = NULL; + wl_list_for_each(input_device, &server.input->devices, link) { + if (strcmp(input_device->identifier, ic->identifier) == 0) { + toggle_send_events_for_device(ic, input_device); + } + } +} + +static void toggle_wildcard_send_events() { + struct sway_input_device *input_device = NULL; + wl_list_for_each(input_device, &server.input->devices, link) { + struct input_config *ic = new_input_config(input_device->identifier); + if (!ic) { + break; + } + toggle_send_events_for_device(ic, input_device); + store_input_config(ic); + } +} + struct cmd_results *input_cmd_events(int argc, char **argv) { struct cmd_results *error = NULL; if ((error = checkarg(argc, "events", EXPECTED_AT_LEAST, 1))) { @@ -23,9 +82,24 @@ struct cmd_results *input_cmd_events(int argc, char **argv) { } else if (strcasecmp(argv[0], "disabled_on_external_mouse") == 0) { ic->send_events = LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE; - } else { + } else if (config->reading) { return cmd_results_new(CMD_INVALID, "events", "Expected 'events <enabled|disabled|disabled_on_external_mouse>'"); + } else if (strcasecmp(argv[0], "toggle") == 0) { + if (strcmp(ic->identifier, "*") == 0) { + // Update the device input configs and then reset the wildcard + // config send events mode so that is does not override the device + // ones. The device ones will be applied when attempting to apply + // the wildcard config + toggle_wildcard_send_events(); + ic->send_events = INT_MIN; + } else { + toggle_send_events(ic); + } + } else { + return cmd_results_new(CMD_INVALID, "events", + "Expected 'events <enabled|disabled|disabled_on_external_mouse|" + "toggle>'"); } return cmd_results_new(CMD_SUCCESS, NULL, NULL); diff --git a/sway/commands/input/scroll_button.c b/sway/commands/input/scroll_button.c index 1958f23c..d82a1fe1 100644 --- a/sway/commands/input/scroll_button.c +++ b/sway/commands/input/scroll_button.c @@ -1,9 +1,7 @@ -#include <string.h> -#include <strings.h> -#include <errno.h> +#include <libevdev/libevdev.h> #include "sway/config.h" #include "sway/commands.h" -#include "sway/input/input-manager.h" +#include "sway/input/cursor.h" struct cmd_results *input_cmd_scroll_button(int argc, char **argv) { struct cmd_results *error = NULL; @@ -16,22 +14,26 @@ struct cmd_results *input_cmd_scroll_button(int argc, char **argv) { "No input device defined."); } - errno = 0; - char *endptr; - int scroll_button = strtol(*argv, &endptr, 10); - if (endptr == *argv && scroll_button == 0) { - return cmd_results_new(CMD_INVALID, "scroll_button", - "Scroll button identifier must be an integer."); + if (strcmp(*argv, "disable") == 0) { + ic->scroll_button = 0; + return cmd_results_new(CMD_SUCCESS, NULL, NULL); } - if (errno == ERANGE) { + + char *message = NULL; + uint32_t button = get_mouse_button(*argv, &message); + if (message) { + error = cmd_results_new(CMD_INVALID, "scroll_button", message); + free(message); + return error; + } else if (button == SWAY_SCROLL_UP || button == SWAY_SCROLL_DOWN + || button == SWAY_SCROLL_LEFT || button == SWAY_SCROLL_RIGHT) { return cmd_results_new(CMD_INVALID, "scroll_button", - "Scroll button identifier out of range."); - } - if (scroll_button < 0) { + "X11 axis buttons are not supported for scroll_button"); + } else if (!button) { return cmd_results_new(CMD_INVALID, "scroll_button", - "Scroll button identifier cannot be negative."); + "Unknown button %s", *argv); } - ic->scroll_button = scroll_button; + ic->scroll_button = button; return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/input/xkb_layout.c b/sway/commands/input/xkb_layout.c index 5fccd4a3..43166401 100644 --- a/sway/commands/input/xkb_layout.c +++ b/sway/commands/input/xkb_layout.c @@ -1,4 +1,4 @@ -#define _XOPEN_SOURCE 700 +#define _POSIX_C_SOURCE 200809L #include "sway/config.h" #include "sway/commands.h" #include "sway/input/input-manager.h" diff --git a/sway/commands/input/xkb_model.c b/sway/commands/input/xkb_model.c index c4d04638..066f632b 100644 --- a/sway/commands/input/xkb_model.c +++ b/sway/commands/input/xkb_model.c @@ -1,4 +1,4 @@ -#define _XOPEN_SOURCE 700 +#define _POSIX_C_SOURCE 200809L #include "sway/config.h" #include "sway/commands.h" #include "sway/input/input-manager.h" diff --git a/sway/commands/input/xkb_options.c b/sway/commands/input/xkb_options.c index 794ab6e9..09dc4a5c 100644 --- a/sway/commands/input/xkb_options.c +++ b/sway/commands/input/xkb_options.c @@ -1,4 +1,4 @@ -#define _XOPEN_SOURCE 700 +#define _POSIX_C_SOURCE 200809L #include "sway/config.h" #include "sway/commands.h" #include "sway/input/input-manager.h" diff --git a/sway/commands/input/xkb_rules.c b/sway/commands/input/xkb_rules.c index 257c3288..d3e576e6 100644 --- a/sway/commands/input/xkb_rules.c +++ b/sway/commands/input/xkb_rules.c @@ -1,4 +1,4 @@ -#define _XOPEN_SOURCE 700 +#define _POSIX_C_SOURCE 200809L #include "sway/config.h" #include "sway/commands.h" #include "sway/input/input-manager.h" diff --git a/sway/commands/input/xkb_variant.c b/sway/commands/input/xkb_variant.c index 3832dc8e..2d7581d1 100644 --- a/sway/commands/input/xkb_variant.c +++ b/sway/commands/input/xkb_variant.c @@ -1,4 +1,4 @@ -#define _XOPEN_SOURCE 700 +#define _POSIX_C_SOURCE 200809L #include "sway/config.h" #include "sway/commands.h" #include "sway/input/input-manager.h" diff --git a/sway/commands/mode.c b/sway/commands/mode.c index 637ca45e..189e3c1a 100644 --- a/sway/commands/mode.c +++ b/sway/commands/mode.c @@ -1,4 +1,4 @@ -#define _XOPEN_SOURCE 500 +#define _POSIX_C_SOURCE 200809L #include <stdbool.h> #include <string.h> #include <strings.h> diff --git a/sway/commands/move.c b/sway/commands/move.c index 7d8c1f1a..72e177e8 100644 --- a/sway/commands/move.c +++ b/sway/commands/move.c @@ -1,4 +1,4 @@ -#define _XOPEN_SOURCE 500 +#define _POSIX_C_SOURCE 200809L #include <ctype.h> #include <stdbool.h> #include <string.h> @@ -64,7 +64,7 @@ static struct sway_output *output_in_direction(const char *direction_string, } } - return output_by_name(direction_string); + return output_by_name_or_id(direction_string); } static bool is_parallel(enum sway_container_layout layout, @@ -154,6 +154,8 @@ static void container_move_to_container_from_direction( static void container_move_to_workspace_from_direction( struct sway_container *container, struct sway_workspace *workspace, enum wlr_direction move_dir) { + container->width = container->height = 0; + if (is_parallel(workspace->layout, move_dir)) { wlr_log(WLR_DEBUG, "Reparenting container (parallel)"); int index = @@ -216,6 +218,7 @@ static void container_move_to_container(struct sway_container *container, return; } if (container_is_floating(container)) { + container_move_to_workspace(container, destination->workspace); return; } struct sway_workspace *old_workspace = container->workspace; diff --git a/sway/commands/no_focus.c b/sway/commands/no_focus.c index 61a8de7e..cb81a445 100644 --- a/sway/commands/no_focus.c +++ b/sway/commands/no_focus.c @@ -1,4 +1,3 @@ -#define _XOPEN_SOURCE 500 #include <string.h> #include "sway/commands.h" #include "sway/criteria.h" diff --git a/sway/commands/output/background.c b/sway/commands/output/background.c index 30fb47c4..2cd1b76a 100644 --- a/sway/commands/output/background.c +++ b/sway/commands/output/background.c @@ -116,11 +116,8 @@ struct cmd_results *output_cmd_background(int argc, char **argv) { if (!can_access) { wlr_log(WLR_ERROR, "Unable to access background file '%s': %s", src, strerror(errno)); - if (config->reading && !config->validating) { - swaynag_log(config->swaynag_command, - &config->swaynag_config_errors, - "Unable to access background file '%s'", src); - } + config_add_swaynag_warning("Unable to access background file '%s'", + src); free(src); } else { // Escape double quotes in the final path for swaybg diff --git a/sway/commands/output/transform.c b/sway/commands/output/transform.c index c1555323..ca6f73a4 100644 --- a/sway/commands/output/transform.c +++ b/sway/commands/output/transform.c @@ -45,7 +45,7 @@ struct cmd_results *output_cmd_transform(int argc, char **argv) { return cmd_results_new(CMD_INVALID, "output", "Cannot apply relative transform to all outputs."); } - struct sway_output *s_output = output_by_name(output->name); + struct sway_output *s_output = output_by_name_or_id(output->name); if (s_output == NULL) { return cmd_results_new(CMD_INVALID, "output", "Cannot apply relative transform to unknown output %s", output->name); diff --git a/sway/commands/reload.c b/sway/commands/reload.c index 62105cdc..3ccbbf34 100644 --- a/sway/commands/reload.c +++ b/sway/commands/reload.c @@ -1,4 +1,4 @@ -#define _XOPEN_SOURCE 500 +#define _POSIX_C_SOURCE 200809L #include <string.h> #include "sway/commands.h" #include "sway/config.h" @@ -24,8 +24,7 @@ static void do_reload(void *data) { if (!load_main_config(config->current_config_path, true, false)) { wlr_log(WLR_ERROR, "Error(s) reloading config"); - list_foreach(bar_ids, free); - list_free(bar_ids); + list_free_items_and_destroy(bar_ids); return; } @@ -42,9 +41,7 @@ static void do_reload(void *data) { } } } - - list_foreach(bar_ids, free); - list_free(bar_ids); + list_free_items_and_destroy(bar_ids); config_update_font_height(true); root_for_each_container(rebuild_textures_iterator, NULL); diff --git a/sway/commands/rename.c b/sway/commands/rename.c index 0cee9293..491dbab0 100644 --- a/sway/commands/rename.c +++ b/sway/commands/rename.c @@ -1,4 +1,3 @@ -#define _XOPEN_SOURCE 500 #include <ctype.h> #include <string.h> #include <strings.h> @@ -82,8 +81,12 @@ struct cmd_results *cmd_rename(int argc, char **argv) { struct sway_workspace *tmp_workspace = workspace_by_name(new_name); if (tmp_workspace) { free(new_name); - return cmd_results_new(CMD_INVALID, "rename", - "Workspace already exists"); + if (tmp_workspace == workspace) { + return cmd_results_new(CMD_SUCCESS, NULL, NULL); + } else { + return cmd_results_new(CMD_INVALID, "rename", + "Workspace already exists"); + } } wlr_log(WLR_DEBUG, "renaming workspace '%s' to '%s'", workspace->name, new_name); diff --git a/sway/commands/resize.c b/sway/commands/resize.c index a90d578e..cf5dea02 100644 --- a/sway/commands/resize.c +++ b/sway/commands/resize.c @@ -512,34 +512,42 @@ static struct cmd_results *resize_set_floating(struct sway_container *con, calculate_constraints(&min_width, &max_width, &min_height, &max_height); if (width->amount) { - if (width->unit == RESIZE_UNIT_PPT || - width->unit == RESIZE_UNIT_DEFAULT) { + switch (width->unit) { + case RESIZE_UNIT_PPT: // Convert to px width->amount = con->workspace->width * width->amount / 100; width->unit = RESIZE_UNIT_PX; - } - if (width->unit == RESIZE_UNIT_PX) { + // Falls through + case RESIZE_UNIT_PX: + case RESIZE_UNIT_DEFAULT: width->amount = fmax(min_width, fmin(width->amount, max_width)); grow_width = width->amount - con->width; - con->x -= grow_width / 2; con->width = width->amount; + break; + case RESIZE_UNIT_INVALID: + sway_assert(false, "invalid width unit"); + break; } } if (height->amount) { - if (height->unit == RESIZE_UNIT_PPT || - height->unit == RESIZE_UNIT_DEFAULT) { + switch (height->unit) { + case RESIZE_UNIT_PPT: // Convert to px height->amount = con->workspace->height * height->amount / 100; height->unit = RESIZE_UNIT_PX; - } - if (height->unit == RESIZE_UNIT_PX) { + // Falls through + case RESIZE_UNIT_PX: + case RESIZE_UNIT_DEFAULT: height->amount = fmax(min_height, fmin(height->amount, max_height)); grow_height = height->amount - con->height; - con->y -= grow_height / 2; con->height = height->amount; + break; + case RESIZE_UNIT_INVALID: + sway_assert(false, "invalid height unit"); + break; } } diff --git a/sway/commands/seat.c b/sway/commands/seat.c index 5abb19b0..b8db862b 100644 --- a/sway/commands/seat.c +++ b/sway/commands/seat.c @@ -10,6 +10,7 @@ static struct cmd_handler seat_handlers[] = { { "attach", seat_cmd_attach }, { "cursor", seat_cmd_cursor }, { "fallback", seat_cmd_fallback }, + { "hide_cursor", seat_cmd_hide_cursor }, }; struct cmd_results *cmd_seat(int argc, char **argv) { @@ -26,9 +27,18 @@ struct cmd_results *cmd_seat(int argc, char **argv) { struct cmd_results *res = config_subcommand(argv + 1, argc - 1, seat_handlers, sizeof(seat_handlers)); + if (res && res->status != CMD_SUCCESS) { + free_seat_config(config->handler_context.seat_config); + config->handler_context.seat_config = NULL; + return res; + } - free_seat_config(config->handler_context.seat_config); - config->handler_context.seat_config = NULL; + struct seat_config *sc = + store_seat_config(config->handler_context.seat_config); + if (!config->reading) { + input_manager_apply_seat_config(sc); + } - return res; + config->handler_context.seat_config = NULL; + return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/seat/attach.c b/sway/commands/seat/attach.c index 6b4bcf1f..0fb17f1d 100644 --- a/sway/commands/seat/attach.c +++ b/sway/commands/seat/attach.c @@ -1,10 +1,7 @@ -#define _XOPEN_SOURCE 700 +#define _POSIX_C_SOURCE 200809L #include <string.h> -#include <strings.h> -#include "sway/input/input-manager.h" #include "sway/commands.h" #include "sway/config.h" -#include "log.h" #include "stringop.h" struct cmd_results *seat_cmd_attach(int argc, char **argv) { @@ -12,19 +9,17 @@ struct cmd_results *seat_cmd_attach(int argc, char **argv) { if ((error = checkarg(argc, "attach", EXPECTED_AT_LEAST, 1))) { return error; } - struct seat_config *current_seat_config = - config->handler_context.seat_config; - if (!current_seat_config) { + if (!config->handler_context.seat_config) { return cmd_results_new(CMD_FAILURE, "attach", "No seat defined"); } - struct seat_config *new_config = new_seat_config(current_seat_config->name); - struct seat_attachment_config *new_attachment = seat_attachment_config_new(); - new_attachment->identifier = strdup(argv[0]); - list_add(new_config->attachments, new_attachment); - - if (!config->validating) { - apply_seat_config(new_config); + struct seat_attachment_config *attachment = seat_attachment_config_new(); + if (!attachment) { + return cmd_results_new(CMD_FAILURE, "attach", + "Failed to allocate seat attachment config"); } + attachment->identifier = strdup(argv[0]); + list_add(config->handler_context.seat_config->attachments, attachment); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/seat/cursor.c b/sway/commands/seat/cursor.c index 1d41a94e..8d9e426a 100644 --- a/sway/commands/seat/cursor.c +++ b/sway/commands/seat/cursor.c @@ -1,12 +1,9 @@ -#define _XOPEN_SOURCE 700 -#ifdef __linux__ +#define _POSIX_C_SOURCE 200809L #include <linux/input-event-codes.h> -#elif __FreeBSD__ -#include <dev/evdev/input-event-codes.h> -#endif #include <strings.h> #include <wlr/types/wlr_cursor.h> +#include <wlr/types/wlr_pointer.h> #include "sway/commands.h" #include "sway/input/cursor.h" @@ -15,20 +12,10 @@ static struct cmd_results *press_or_release(struct sway_cursor *cursor, static const char *expected_syntax = "Expected 'cursor <move> <x> <y>' or " "'cursor <set> <x> <y>' or " - "'curor <press|release> <left|right|1|2|3...>'"; - -struct cmd_results *seat_cmd_cursor(int argc, char **argv) { - struct cmd_results *error = NULL; - if ((error = checkarg(argc, "cursor", EXPECTED_AT_LEAST, 2))) { - return error; - } - struct sway_seat *seat = config->handler_context.seat; - if (!seat) { - return cmd_results_new(CMD_FAILURE, "cursor", "No seat defined"); - } - - struct sway_cursor *cursor = seat->cursor; + "'curor <press|release> <button[1-9]|event-name-or-code>'"; +static struct cmd_results *handle_command(struct sway_cursor *cursor, + int argc, char **argv) { if (strcasecmp(argv[0], "move") == 0) { if (argc < 3) { return cmd_results_new(CMD_INVALID, "cursor", expected_syntax); @@ -50,6 +37,7 @@ struct cmd_results *seat_cmd_cursor(int argc, char **argv) { if (argc < 2) { return cmd_results_new(CMD_INVALID, "cursor", expected_syntax); } + struct cmd_results *error = NULL; if ((error = press_or_release(cursor, argv[0], argv[1]))) { return error; } @@ -58,6 +46,40 @@ struct cmd_results *seat_cmd_cursor(int argc, char **argv) { return cmd_results_new(CMD_SUCCESS, NULL, NULL); } +struct cmd_results *seat_cmd_cursor(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "cursor", EXPECTED_AT_LEAST, 2))) { + return error; + } + struct seat_config *sc = config->handler_context.seat_config; + if (!sc) { + return cmd_results_new(CMD_FAILURE, "cursor", "No seat defined"); + } + + if (config->reading || !config->active) { + return cmd_results_new(CMD_DEFER, NULL, NULL); + } + + if (strcmp(sc->name, "*") != 0) { + struct sway_seat *seat = input_manager_get_seat(sc->name); + if (!seat) { + return cmd_results_new(CMD_FAILURE, "cursor", + "Failed to get seat"); + } + error = handle_command(seat->cursor, argc, argv); + } else { + struct sway_seat *seat = NULL; + wl_list_for_each(seat, &server.input->seats, link) { + error = handle_command(seat->cursor, argc, argv); + if ((error && error->status != CMD_SUCCESS)) { + break; + } + } + } + + return error ? error : cmd_results_new(CMD_SUCCESS, NULL, NULL); +} + static struct cmd_results *press_or_release(struct sway_cursor *cursor, char *action, char *button_str) { enum wlr_button_state state; @@ -70,15 +92,35 @@ static struct cmd_results *press_or_release(struct sway_cursor *cursor, return cmd_results_new(CMD_INVALID, "cursor", expected_syntax); } - if (strcasecmp(button_str, "left") == 0) { - button = BTN_LEFT; - } else if (strcasecmp(button_str, "right") == 0) { - button = BTN_RIGHT; - } else { - button = strtol(button_str, NULL, 10); - if (button == 0) { - return cmd_results_new(CMD_INVALID, "cursor", expected_syntax); - } + char *message = NULL; + button = get_mouse_button(button_str, &message); + if (message) { + struct cmd_results *error = + cmd_results_new(CMD_INVALID, "cursor", message); + free(message); + return error; + } else if (button == SWAY_SCROLL_UP || button == SWAY_SCROLL_DOWN + || button == SWAY_SCROLL_LEFT || button == SWAY_SCROLL_RIGHT) { + // Dispatch axis event + enum wlr_axis_orientation orientation = + (button == SWAY_SCROLL_UP || button == SWAY_SCROLL_DOWN) + ? WLR_AXIS_ORIENTATION_VERTICAL + : WLR_AXIS_ORIENTATION_HORIZONTAL; + double delta = (button == SWAY_SCROLL_UP || button == SWAY_SCROLL_LEFT) + ? -1 : 1; + struct wlr_event_pointer_axis event = { + .device = NULL, + .time_msec = 0, + .source = WLR_AXIS_SOURCE_WHEEL, + .orientation = orientation, + .delta = delta * 15, + .delta_discrete = delta + }; + dispatch_cursor_axis(cursor, &event); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); + } else if (!button) { + return cmd_results_new(CMD_INVALID, "curor", + "Unknown button %s", button_str); } dispatch_cursor_button(cursor, NULL, 0, button, state); return cmd_results_new(CMD_SUCCESS, NULL, NULL); diff --git a/sway/commands/seat/fallback.c b/sway/commands/seat/fallback.c index a0ddf3ef..8f1ab12c 100644 --- a/sway/commands/seat/fallback.c +++ b/sway/commands/seat/fallback.c @@ -1,27 +1,18 @@ -#include <string.h> -#include <strings.h> #include "sway/config.h" #include "sway/commands.h" -#include "sway/input/input-manager.h" #include "util.h" struct cmd_results *seat_cmd_fallback(int argc, char **argv) { struct cmd_results *error = NULL; - if ((error = checkarg(argc, "fallback", EXPECTED_AT_LEAST, 1))) { + if ((error = checkarg(argc, "fallback", EXPECTED_EQUAL_TO, 1))) { return error; } - struct seat_config *current_seat_config = - config->handler_context.seat_config; - if (!current_seat_config) { + if (!config->handler_context.seat_config) { return cmd_results_new(CMD_FAILURE, "fallback", "No seat defined"); } - struct seat_config *new_config = - new_seat_config(current_seat_config->name); - - new_config->fallback = parse_boolean(argv[0], false); - if (!config->validating) { - apply_seat_config(new_config); - } + config->handler_context.seat_config->fallback = + parse_boolean(argv[0], false); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/seat/hide_cursor.c b/sway/commands/seat/hide_cursor.c new file mode 100644 index 00000000..343573b5 --- /dev/null +++ b/sway/commands/seat/hide_cursor.c @@ -0,0 +1,29 @@ +#define _POSIX_C_SOURCE 200809L +#include <string.h> +#include "sway/commands.h" +#include "sway/config.h" +#include "sway/input/seat.h" +#include "stringop.h" + +struct cmd_results *seat_cmd_hide_cursor(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "hide_cursor", EXPECTED_EQUAL_TO, 1))) { + return error; + } + if (!config->handler_context.seat_config) { + return cmd_results_new(CMD_FAILURE, "hide_cursor", "No seat defined"); + } + + char *end; + int timeout = strtol(argv[0], &end, 10); + if (*end) { + return cmd_results_new(CMD_INVALID, "hide_cursor", + "Expected an integer timeout"); + } + if (timeout < 100 && timeout != 0) { + timeout = 100; + } + config->handler_context.seat_config->hide_cursor_timeout = timeout; + + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/commands/set.c b/sway/commands/set.c index be51230b..d912e4fd 100644 --- a/sway/commands/set.c +++ b/sway/commands/set.c @@ -1,4 +1,4 @@ -#define _XOPEN_SOURCE 700 +#define _POSIX_C_SOURCE 200809L #include <stdio.h> #include <string.h> #include <strings.h> diff --git a/sway/commands/split.c b/sway/commands/split.c index ed106a86..84385fa9 100644 --- a/sway/commands/split.c +++ b/sway/commands/split.c @@ -18,6 +18,10 @@ static struct cmd_results *do_split(int layout) { workspace_split(ws, layout); } + if (con && con->parent && con->parent->parent) { + container_flatten(con->parent->parent); + } + arrange_workspace(ws); return cmd_results_new(CMD_SUCCESS, NULL, NULL); diff --git a/sway/commands/swap.c b/sway/commands/swap.c index 08860264..670d6bca 100644 --- a/sway/commands/swap.c +++ b/sway/commands/swap.c @@ -108,7 +108,7 @@ static void container_swap(struct sway_container *con1, container_set_fullscreen(con2, false); } - struct sway_seat *seat = input_manager_get_default_seat(); + struct sway_seat *seat = config->handler_context.seat; struct sway_container *focus = seat_get_focused_container(seat); struct sway_workspace *vis1 = output_get_active_workspace(con1->workspace->output); diff --git a/sway/commands/tiling_drag_threshold.c b/sway/commands/tiling_drag_threshold.c new file mode 100644 index 00000000..6b0531c3 --- /dev/null +++ b/sway/commands/tiling_drag_threshold.c @@ -0,0 +1,22 @@ +#include <string.h> +#include "sway/commands.h" +#include "sway/config.h" +#include "log.h" + +struct cmd_results *cmd_tiling_drag_threshold(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "tiling_drag_threshold", EXPECTED_EQUAL_TO, 1))) { + return error; + } + + char *inv; + int value = strtol(argv[0], &inv, 10); + if (*inv != '\0' || value < 0) { + return cmd_results_new(CMD_INVALID, "tiling_drag_threshold", + "Invalid threshold specified"); + } + + config->tiling_drag_threshold = value; + + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/commands/title_align.c b/sway/commands/title_align.c new file mode 100644 index 00000000..82578186 --- /dev/null +++ b/sway/commands/title_align.c @@ -0,0 +1,30 @@ +#include "sway/commands.h" +#include "sway/config.h" +#include "sway/output.h" +#include "sway/tree/container.h" +#include "sway/tree/root.h" + +struct cmd_results *cmd_title_align(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "title_align", EXPECTED_AT_LEAST, 1))) { + return error; + } + + if (strcmp(argv[0], "left") == 0) { + config->title_align = ALIGN_LEFT; + } else if (strcmp(argv[0], "center") == 0) { + config->title_align = ALIGN_CENTER; + } else if (strcmp(argv[0], "right") == 0) { + config->title_align = ALIGN_RIGHT; + } else { + return cmd_results_new(CMD_INVALID, "title_align", + "Expected 'title_align left|center|right'"); + } + + for (int i = 0; i < root->outputs->length; ++i) { + struct sway_output *output = root->outputs->items[i]; + output_damage_whole(output); + } + + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/commands/titlebar_border_thickness.c b/sway/commands/titlebar_border_thickness.c new file mode 100644 index 00000000..c1e9bb52 --- /dev/null +++ b/sway/commands/titlebar_border_thickness.c @@ -0,0 +1,30 @@ +#include <string.h> +#include "sway/commands.h" +#include "sway/config.h" +#include "sway/output.h" +#include "sway/tree/arrange.h" +#include "log.h" + +struct cmd_results *cmd_titlebar_border_thickness(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "titlebar_border_thickness", EXPECTED_EQUAL_TO, 1))) { + return error; + } + + char *inv; + int value = strtol(argv[0], &inv, 10); + if (*inv != '\0' || value < 0 || value > config->titlebar_v_padding) { + return cmd_results_new(CMD_FAILURE, "titlebar_border_thickness", + "Invalid size specified"); + } + + config->titlebar_border_thickness = value; + + for (int i = 0; i < root->outputs->length; ++i) { + struct sway_output *output = root->outputs->items[i]; + arrange_workspace(output_get_active_workspace(output)); + output_damage_whole(output); + } + + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/commands/titlebar_padding.c b/sway/commands/titlebar_padding.c new file mode 100644 index 00000000..a642e945 --- /dev/null +++ b/sway/commands/titlebar_padding.c @@ -0,0 +1,42 @@ +#include <string.h> +#include "sway/commands.h" +#include "sway/config.h" +#include "sway/output.h" +#include "sway/tree/arrange.h" +#include "log.h" + +struct cmd_results *cmd_titlebar_padding(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "titlebar_padding", EXPECTED_AT_LEAST, 1))) { + return error; + } + + char *inv; + int h_value = strtol(argv[0], &inv, 10); + if (*inv != '\0' || h_value < 0 || h_value < config->titlebar_border_thickness) { + return cmd_results_new(CMD_FAILURE, "titlebar_padding", + "Invalid size specified"); + } + + int v_value; + if (argc == 1) { + v_value = h_value; + } else { + v_value = strtol(argv[1], &inv, 10); + if (*inv != '\0' || v_value < 0 || v_value < config->titlebar_border_thickness) { + return cmd_results_new(CMD_FAILURE, "titlebar_padding", + "Invalid size specified"); + } + } + + config->titlebar_v_padding = v_value; + config->titlebar_h_padding = h_value; + + for (int i = 0; i < root->outputs->length; ++i) { + struct sway_output *output = root->outputs->items[i]; + arrange_workspace(output_get_active_workspace(output)); + output_damage_whole(output); + } + + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/commands/workspace.c b/sway/commands/workspace.c index 92118ecf..211b344d 100644 --- a/sway/commands/workspace.c +++ b/sway/commands/workspace.c @@ -1,4 +1,4 @@ -#define _XOPEN_SOURCE 500 +#define _POSIX_C_SOURCE 200809L #include <ctype.h> #include <limits.h> #include <string.h> @@ -33,12 +33,12 @@ static struct workspace_config *workspace_config_find_or_create(char *ws_name) { void free_workspace_config(struct workspace_config *wsc) { free(wsc->workspace); - free_flat_list(wsc->outputs); + list_free_items_and_destroy(wsc->outputs); free(wsc); } static void prevent_invalid_outer_gaps(struct workspace_config *wsc) { - if (wsc->gaps_outer.top != INT_MIN && + if (wsc->gaps_outer.top != INT_MIN && wsc->gaps_outer.top < -wsc->gaps_inner) { wsc->gaps_outer.top = -wsc->gaps_inner; } |