summaryrefslogtreecommitdiffstats
path: root/sway
diff options
context:
space:
mode:
Diffstat (limited to 'sway')
-rw-r--r--sway/commands/bar.c2
-rw-r--r--sway/commands/bar/status_edge_padding.c21
-rw-r--r--sway/commands/bar/status_padding.c21
-rw-r--r--sway/commands/bind.c126
-rw-r--r--sway/commands/input/events.c76
-rw-r--r--sway/config.c21
-rw-r--r--sway/config/bar.c4
-rw-r--r--sway/input/cursor.c73
-rw-r--r--sway/ipc-json.c25
-rw-r--r--sway/ipc-server.c8
-rw-r--r--sway/meson.build2
-rw-r--r--sway/sway-bar.5.scd12
-rw-r--r--sway/sway-input.5.scd9
-rw-r--r--sway/sway.5.scd2
-rw-r--r--sway/tree/output.c2
15 files changed, 335 insertions, 69 deletions
diff --git a/sway/commands/bar.c b/sway/commands/bar.c
index 507ee10a..3e7c1b0f 100644
--- a/sway/commands/bar.c
+++ b/sway/commands/bar.c
@@ -23,6 +23,8 @@ static struct cmd_handler bar_handlers[] = {
23 { "position", bar_cmd_position }, 23 { "position", bar_cmd_position },
24 { "separator_symbol", bar_cmd_separator_symbol }, 24 { "separator_symbol", bar_cmd_separator_symbol },
25 { "status_command", bar_cmd_status_command }, 25 { "status_command", bar_cmd_status_command },
26 { "status_edge_padding", bar_cmd_status_edge_padding },
27 { "status_padding", bar_cmd_status_padding },
26 { "strip_workspace_name", bar_cmd_strip_workspace_name }, 28 { "strip_workspace_name", bar_cmd_strip_workspace_name },
27 { "strip_workspace_numbers", bar_cmd_strip_workspace_numbers }, 29 { "strip_workspace_numbers", bar_cmd_strip_workspace_numbers },
28 { "tray_bindsym", bar_cmd_tray_bindsym }, 30 { "tray_bindsym", bar_cmd_tray_bindsym },
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 @@
1#include <stdlib.h>
2#include <string.h>
3#include "sway/commands.h"
4#include "log.h"
5
6struct cmd_results *bar_cmd_status_edge_padding(int argc, char **argv) {
7 struct cmd_results *error = NULL;
8 if ((error = checkarg(argc, "status_edge_padding", EXPECTED_EQUAL_TO, 1))) {
9 return error;
10 }
11 char *end;
12 int padding = strtol(argv[0], &end, 10);
13 if (strlen(end) || padding < 0) {
14 return cmd_results_new(CMD_INVALID, "status_edge_padding",
15 "Padding must be a positive integer");
16 }
17 config->current_bar->status_edge_padding = padding;
18 wlr_log(WLR_DEBUG, "Status edge padding on bar %s: %d",
19 config->current_bar->id, config->current_bar->status_edge_padding);
20 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
21}
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 @@
1#include <stdlib.h>
2#include <string.h>
3#include "sway/commands.h"
4#include "log.h"
5
6struct cmd_results *bar_cmd_status_padding(int argc, char **argv) {
7 struct cmd_results *error = NULL;
8 if ((error = checkarg(argc, "status_padding", EXPECTED_EQUAL_TO, 1))) {
9 return error;
10 }
11 char *end;
12 int padding = strtol(argv[0], &end, 10);
13 if (strlen(end) || padding < 0) {
14 return cmd_results_new(CMD_INVALID, "status_padding",
15 "Padding must be a positive integer");
16 }
17 config->current_bar->status_padding = padding;
18 wlr_log(WLR_DEBUG, "Status padding on bar %s: %d",
19 config->current_bar->id, config->current_bar->status_padding);
20 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
21}
diff --git a/sway/commands/bind.c b/sway/commands/bind.c
index 4fceaf8c..be47d412 100644
--- a/sway/commands/bind.c
+++ b/sway/commands/bind.c
@@ -85,69 +85,91 @@ static int key_qsort_cmp(const void *keyp_a, const void *keyp_b) {
85 */ 85 */
86static struct cmd_results *identify_key(const char* name, bool first_key, 86static struct cmd_results *identify_key(const char* name, bool first_key,
87 uint32_t* key_val, enum binding_input_type* type) { 87 uint32_t* key_val, enum binding_input_type* type) {
88 if (*type == BINDING_KEYCODE) { 88 if (*type == BINDING_MOUSECODE) {
89 // check for keycode 89 // check for mouse bindcodes
90 xkb_keycode_t keycode = strtol(name, NULL, 10); 90 char *message = NULL;
91 if (!xkb_keycode_is_legal_ext(keycode)) { 91 uint32_t button = get_mouse_bindcode(name, &message);
92 return cmd_results_new(CMD_INVALID, "bindcode", 92 if (!button) {
93 "Invalid keycode '%s'", name); 93 if (message) {
94 struct cmd_results *error =
95 cmd_results_new(CMD_INVALID, "bindcode", message);
96 free(message);
97 return error;
98 } else {
99 return cmd_results_new(CMD_INVALID, "bindcode",
100 "Unknown button code %s", name);
101 }
94 } 102 }
95 *key_val = keycode; 103 *key_val = button;
96 } else { 104 } else if (*type == BINDING_MOUSESYM) {
97 // check for keysym 105 // check for mouse bindsyms (x11 buttons or event names)
98 xkb_keysym_t keysym = xkb_keysym_from_name(name, 106 char *message = NULL;
99 XKB_KEYSYM_CASE_INSENSITIVE); 107 uint32_t button = get_mouse_bindsym(name, &message);
100 108 if (!button) {
101 // Check for mouse binding 109 if (message) {
102 uint32_t button = 0; 110 struct cmd_results *error =
103 if (strncasecmp(name, "button", strlen("button")) == 0) { 111 cmd_results_new(CMD_INVALID, "bindsym", message);
104 // Map to x11 mouse buttons 112 free(message);
105 button = name[strlen("button")] - '0'; 113 return error;
106 if (button < 1 || button > 9 || strlen(name) > strlen("button0")) { 114 } else if (!button) {
107 return cmd_results_new(CMD_INVALID, "bindsym", 115 return cmd_results_new(CMD_INVALID, "bindsym",
108 "Only buttons 1-9 are supported. For other mouse " 116 "Unknown button %s", name);
109 "buttons, use the name of the event code.");
110 } 117 }
111 uint32_t buttons[] = {BTN_LEFT, BTN_MIDDLE, BTN_RIGHT, 118 }
112 SWAY_SCROLL_UP, SWAY_SCROLL_DOWN, SWAY_SCROLL_LEFT, 119 *key_val = button;
113 SWAY_SCROLL_RIGHT, BTN_SIDE, BTN_EXTRA}; 120 } else if (*type == BINDING_KEYCODE) {
114 button = buttons[button - 1]; 121 // check for keycode. If it is the first key, allow mouse bindcodes
115 } else if (strncmp(name, "BTN_", strlen("BTN_")) == 0) { 122 if (first_key) {
116 // Get event code 123 char *message = NULL;
117 int code = libevdev_event_code_from_name(EV_KEY, name); 124 uint32_t button = get_mouse_bindcode(name, &message);
118 if (code == -1) { 125 free(message);
119 return cmd_results_new(CMD_INVALID, "bindsym", 126 if (button) {
120 "Invalid event code name %s", name); 127 *type = BINDING_MOUSECODE;
128 *key_val = button;
129 return NULL;
121 } 130 }
122 button = code;
123 } 131 }
124 132
125 if (*type == BINDING_KEYSYM) { 133 xkb_keycode_t keycode = strtol(name, NULL, 10);
126 if (button) { 134 if (!xkb_keycode_is_legal_ext(keycode)) {
127 if (first_key) { 135 if (first_key) {
128 *type = BINDING_MOUSE; 136 return cmd_results_new(CMD_INVALID, "bindcode",
129 *key_val = button; 137 "Invalid keycode or button code '%s'", name);
130 } else {
131 return cmd_results_new(CMD_INVALID, "bindsym",
132 "Mixed button '%s' into key sequence", name);
133 }
134 } else if (keysym) {
135 *key_val = keysym;
136 } else { 138 } else {
137 return cmd_results_new(CMD_INVALID, "bindsym", 139 return cmd_results_new(CMD_INVALID, "bindcode",
138 "Unknown key '%s'", name); 140 "Invalid keycode '%s'", name);
139 } 141 }
140 } else { 142 }
141 if (button) { 143 *key_val = keycode;
144 } else {
145 // check for keysym. If it is the first key, allow mouse bindsyms
146 if (first_key) {
147 char *message = NULL;
148 uint32_t button = get_mouse_bindsym(name, &message);
149 if (message) {
150 struct cmd_results *error =
151 cmd_results_new(CMD_INVALID, "bindsym", message);
152 free(message);
153 return error;
154 } else if (button) {
155 *type = BINDING_MOUSESYM;
142 *key_val = button; 156 *key_val = button;
143 } else if (keysym) { 157 return NULL;
158 }
159 }
160
161 xkb_keysym_t keysym = xkb_keysym_from_name(name,
162 XKB_KEYSYM_CASE_INSENSITIVE);
163 if (!keysym) {
164 if (first_key) {
144 return cmd_results_new(CMD_INVALID, "bindsym", 165 return cmd_results_new(CMD_INVALID, "bindsym",
145 "Mixed keysym '%s' into button sequence", name); 166 "Unknown key or button '%s'", name);
146 } else { 167 } else {
147 return cmd_results_new(CMD_INVALID, "bindsym", 168 return cmd_results_new(CMD_INVALID, "bindsym",
148 "Unknown button '%s'", name); 169 "Unknown key '%s'", name);
149 } 170 }
150 } 171 }
172 *key_val = keysym;
151 } 173 }
152 return NULL; 174 return NULL;
153} 175}
@@ -201,7 +223,8 @@ static struct cmd_results *cmd_bindsym_or_bindcode(int argc, char **argv,
201 } 223 }
202 if (binding->flags & (BINDING_BORDER | BINDING_CONTENTS | BINDING_TITLEBAR) 224 if (binding->flags & (BINDING_BORDER | BINDING_CONTENTS | BINDING_TITLEBAR)
203 || exclude_titlebar) { 225 || exclude_titlebar) {
204 binding->type = BINDING_MOUSE; 226 binding->type = binding->type == BINDING_KEYCODE ?
227 BINDING_MOUSECODE : BINDING_MOUSESYM;
205 } 228 }
206 229
207 if (argc < 2) { 230 if (argc < 2) {
@@ -249,7 +272,8 @@ static struct cmd_results *cmd_bindsym_or_bindcode(int argc, char **argv,
249 // that this is one 272 // that this is one
250 if (exclude_titlebar) { 273 if (exclude_titlebar) {
251 binding->flags &= ~BINDING_TITLEBAR; 274 binding->flags &= ~BINDING_TITLEBAR;
252 } else if (binding->type == BINDING_MOUSE) { 275 } else if (binding->type == BINDING_MOUSECODE
276 || binding->type == BINDING_MOUSESYM) {
253 binding->flags |= BINDING_TITLEBAR; 277 binding->flags |= BINDING_TITLEBAR;
254 } 278 }
255 279
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 @@
1#include <limits.h>
1#include <string.h> 2#include <string.h>
2#include <strings.h> 3#include <strings.h>
4#include <wlr/backend/libinput.h>
3#include "sway/config.h" 5#include "sway/config.h"
4#include "sway/commands.h" 6#include "sway/commands.h"
5#include "sway/input/input-manager.h" 7#include "sway/input/input-manager.h"
6#include "log.h" 8#include "log.h"
7 9
10static void toggle_send_events_for_device(struct input_config *ic,
11 struct sway_input_device *input_device) {
12 struct wlr_input_device *wlr_device = input_device->wlr_device;
13 if (!wlr_input_device_is_libinput(wlr_device)) {
14 return;
15 }
16 struct libinput_device *libinput_dev
17 = wlr_libinput_get_device_handle(wlr_device);
18
19 enum libinput_config_send_events_mode mode =
20 libinput_device_config_send_events_get_mode(libinput_dev);
21 uint32_t possible =
22 libinput_device_config_send_events_get_modes(libinput_dev);
23
24 switch (mode) {
25 case LIBINPUT_CONFIG_SEND_EVENTS_ENABLED:
26 mode = LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE;
27 if (possible & mode) {
28 break;
29 }
30 // fall through
31 case LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE:
32 mode = LIBINPUT_CONFIG_SEND_EVENTS_DISABLED;
33 if (possible & mode) {
34 break;
35 }
36 // fall through
37 case LIBINPUT_CONFIG_SEND_EVENTS_DISABLED:
38 default:
39 mode = LIBINPUT_CONFIG_SEND_EVENTS_ENABLED;
40 break;
41 }
42
43 ic->send_events = mode;
44}
45
46static void toggle_send_events(struct input_config *ic) {
47 struct sway_input_device *input_device = NULL;
48 wl_list_for_each(input_device, &server.input->devices, link) {
49 if (strcmp(input_device->identifier, ic->identifier) == 0) {
50 toggle_send_events_for_device(ic, input_device);
51 }
52 }
53}
54
55static void toggle_wildcard_send_events() {
56 struct sway_input_device *input_device = NULL;
57 wl_list_for_each(input_device, &server.input->devices, link) {
58 struct input_config *ic = new_input_config(input_device->identifier);
59 if (!ic) {
60 break;
61 }
62 toggle_send_events_for_device(ic, input_device);
63 store_input_config(ic);
64 }
65}
66
8struct cmd_results *input_cmd_events(int argc, char **argv) { 67struct cmd_results *input_cmd_events(int argc, char **argv) {
9 struct cmd_results *error = NULL; 68 struct cmd_results *error = NULL;
10 if ((error = checkarg(argc, "events", EXPECTED_AT_LEAST, 1))) { 69 if ((error = checkarg(argc, "events", EXPECTED_AT_LEAST, 1))) {
@@ -23,9 +82,24 @@ struct cmd_results *input_cmd_events(int argc, char **argv) {
23 } else if (strcasecmp(argv[0], "disabled_on_external_mouse") == 0) { 82 } else if (strcasecmp(argv[0], "disabled_on_external_mouse") == 0) {
24 ic->send_events = 83 ic->send_events =
25 LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE; 84 LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE;
26 } else { 85 } else if (config->reading) {
27 return cmd_results_new(CMD_INVALID, "events", 86 return cmd_results_new(CMD_INVALID, "events",
28 "Expected 'events <enabled|disabled|disabled_on_external_mouse>'"); 87 "Expected 'events <enabled|disabled|disabled_on_external_mouse>'");
88 } else if (strcasecmp(argv[0], "toggle") == 0) {
89 if (strcmp(ic->identifier, "*") == 0) {
90 // Update the device input configs and then reset the wildcard
91 // config send events mode so that is does not override the device
92 // ones. The device ones will be applied when attempting to apply
93 // the wildcard config
94 toggle_wildcard_send_events();
95 ic->send_events = INT_MIN;
96 } else {
97 toggle_send_events(ic);
98 }
99 } else {
100 return cmd_results_new(CMD_INVALID, "events",
101 "Expected 'events <enabled|disabled|disabled_on_external_mouse|"
102 "toggle>'");
29 } 103 }
30 104
31 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 105 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
diff --git a/sway/config.c b/sway/config.c
index cd0857f4..5ca4806c 100644
--- a/sway/config.c
+++ b/sway/config.c
@@ -573,15 +573,18 @@ bool load_include_configs(const char *path, struct sway_config *config,
573} 573}
574 574
575// get line, with backslash continuation 575// get line, with backslash continuation
576static ssize_t getline_with_cont(char **lineptr, size_t *line_size, FILE *file) { 576static ssize_t getline_with_cont(char **lineptr, size_t *line_size, FILE *file,
577 int *nlines) {
577 char *next_line = NULL; 578 char *next_line = NULL;
578 size_t next_line_size = 0; 579 size_t next_line_size = 0;
579 ssize_t nread = getline(lineptr, line_size, file); 580 ssize_t nread = getline(lineptr, line_size, file);
581 *nlines = nread == -1 ? 0 : 1;
580 while (nread >= 2 && strcmp(&(*lineptr)[nread - 2], "\\\n") == 0) { 582 while (nread >= 2 && strcmp(&(*lineptr)[nread - 2], "\\\n") == 0) {
581 ssize_t next_nread = getline(&next_line, &next_line_size, file); 583 ssize_t next_nread = getline(&next_line, &next_line_size, file);
582 if (next_nread == -1) { 584 if (next_nread == -1) {
583 break; 585 break;
584 } 586 }
587 (*nlines)++;
585 588
586 nread += next_nread - 2; 589 nread += next_nread - 2;
587 if ((ssize_t) *line_size < nread + 1) { 590 if ((ssize_t) *line_size < nread + 1) {
@@ -599,6 +602,7 @@ static ssize_t getline_with_cont(char **lineptr, size_t *line_size, FILE *file)
599} 602}
600 603
601static int detect_brace(FILE *file) { 604static int detect_brace(FILE *file) {
605 int ret = 0;
602 int lines = 0; 606 int lines = 0;
603 long pos = ftell(file); 607 long pos = ftell(file);
604 char *line = NULL; 608 char *line = NULL;
@@ -607,15 +611,17 @@ static int detect_brace(FILE *file) {
607 lines++; 611 lines++;
608 strip_whitespace(line); 612 strip_whitespace(line);
609 if (*line) { 613 if (*line) {
610 if (strcmp(line, "{") != 0) { 614 if (strcmp(line, "{") == 0) {
611 fseek(file, pos, SEEK_SET); 615 ret = lines;
612 lines = 0;
613 } 616 }
614 break; 617 break;
615 } 618 }
616 } 619 }
617 free(line); 620 free(line);
618 return lines; 621 if (ret == 0) {
622 fseek(file, pos, SEEK_SET);
623 }
624 return ret;
619} 625}
620 626
621static char *expand_line(const char *block, const char *line, bool add_brace) { 627static char *expand_line(const char *block, const char *line, bool add_brace) {
@@ -662,7 +668,8 @@ bool read_config(FILE *file, struct sway_config *config,
662 ssize_t nread; 668 ssize_t nread;
663 list_t *stack = create_list(); 669 list_t *stack = create_list();
664 size_t read = 0; 670 size_t read = 0;
665 while ((nread = getline_with_cont(&line, &line_size, file)) != -1) { 671 int nlines = 0;
672 while ((nread = getline_with_cont(&line, &line_size, file, &nlines)) != -1) {
666 if (reading_main_config) { 673 if (reading_main_config) {
667 if (read + nread > config_size) { 674 if (read + nread > config_size) {
668 wlr_log(WLR_ERROR, "Config file changed during reading"); 675 wlr_log(WLR_ERROR, "Config file changed during reading");
@@ -678,7 +685,7 @@ bool read_config(FILE *file, struct sway_config *config,
678 line[nread - 1] = '\0'; 685 line[nread - 1] = '\0';
679 } 686 }
680 687
681 line_number++; 688 line_number += nlines;
682 wlr_log(WLR_DEBUG, "Read line %d: %s", line_number, line); 689 wlr_log(WLR_DEBUG, "Read line %d: %s", line_number, line);
683 690
684 strip_whitespace(line); 691 strip_whitespace(line);
diff --git a/sway/config/bar.c b/sway/config/bar.c
index 670219f1..701bf051 100644
--- a/sway/config/bar.c
+++ b/sway/config/bar.c
@@ -96,7 +96,7 @@ struct bar_config *default_bar_config(void) {
96 bar->pango_markup = false; 96 bar->pango_markup = false;
97 bar->swaybar_command = NULL; 97 bar->swaybar_command = NULL;
98 bar->font = NULL; 98 bar->font = NULL;
99 bar->height = -1; 99 bar->height = 0;
100 bar->workspace_buttons = true; 100 bar->workspace_buttons = true;
101 bar->wrap_scroll = false; 101 bar->wrap_scroll = false;
102 bar->separator_symbol = NULL; 102 bar->separator_symbol = NULL;
@@ -106,6 +106,8 @@ struct bar_config *default_bar_config(void) {
106 bar->verbose = false; 106 bar->verbose = false;
107 bar->pid = 0; 107 bar->pid = 0;
108 bar->modifier = get_modifier_mask_by_name("Mod4"); 108 bar->modifier = get_modifier_mask_by_name("Mod4");
109 bar->status_padding = 1;
110 bar->status_edge_padding = 3;
109 if (!(bar->mode = strdup("dock"))) { 111 if (!(bar->mode = strdup("dock"))) {
110 goto cleanup; 112 goto cleanup;
111 } 113 }
diff --git a/sway/input/cursor.c b/sway/input/cursor.c
index 96feb47d..9af7ef57 100644
--- a/sway/input/cursor.c
+++ b/sway/input/cursor.c
@@ -2,8 +2,10 @@
2#include <math.h> 2#include <math.h>
3#include <libevdev/libevdev.h> 3#include <libevdev/libevdev.h>
4#include <linux/input-event-codes.h> 4#include <linux/input-event-codes.h>
5#include <errno.h>
5#include <float.h> 6#include <float.h>
6#include <limits.h> 7#include <limits.h>
8#include <strings.h>
7#include <wlr/types/wlr_cursor.h> 9#include <wlr/types/wlr_cursor.h>
8#include <wlr/types/wlr_xcursor_manager.h> 10#include <wlr/types/wlr_xcursor_manager.h>
9#include <wlr/types/wlr_idle.h> 11#include <wlr/types/wlr_idle.h>
@@ -85,6 +87,10 @@ static struct sway_node *node_at_coords(
85 return NULL; 87 return NULL;
86 } 88 }
87 struct sway_output *output = wlr_output->data; 89 struct sway_output *output = wlr_output->data;
90 if (!output) {
91 // output is being destroyed
92 return NULL;
93 }
88 double ox = lx, oy = ly; 94 double ox = lx, oy = ly;
89 wlr_output_layout_output_coords(root->output_layout, wlr_output, &ox, &oy); 95 wlr_output_layout_output_coords(root->output_layout, wlr_output, &ox, &oy);
90 96
@@ -1092,6 +1098,8 @@ static void dispatch_cursor_axis(struct sway_cursor *cursor,
1092 enum wlr_edges edge = cont ? find_edge(cont, cursor) : WLR_EDGE_NONE; 1098 enum wlr_edges edge = cont ? find_edge(cont, cursor) : WLR_EDGE_NONE;
1093 bool on_border = edge != WLR_EDGE_NONE; 1099 bool on_border = edge != WLR_EDGE_NONE;
1094 bool on_titlebar = cont && !on_border && !surface; 1100 bool on_titlebar = cont && !on_border && !surface;
1101 bool on_titlebar_border = cont && on_border &&
1102 cursor->cursor->y < cont->content_y;
1095 bool on_contents = cont && !on_border && surface; 1103 bool on_contents = cont && !on_border && surface;
1096 float scroll_factor = 1104 float scroll_factor =
1097 (ic == NULL || ic->scroll_factor == FLT_MIN) ? 1.0f : ic->scroll_factor; 1105 (ic == NULL || ic->scroll_factor == FLT_MIN) ? 1.0f : ic->scroll_factor;
@@ -1117,7 +1125,7 @@ static void dispatch_cursor_axis(struct sway_cursor *cursor,
1117 } 1125 }
1118 1126
1119 // Scrolling on a tabbed or stacked title bar (handled as press event) 1127 // Scrolling on a tabbed or stacked title bar (handled as press event)
1120 if (!handled && on_titlebar) { 1128 if (!handled && (on_titlebar || on_titlebar_border)) {
1121 enum sway_container_layout layout = container_parent_layout(cont); 1129 enum sway_container_layout layout = container_parent_layout(cont);
1122 if (layout == L_TABBED || layout == L_STACKED) { 1130 if (layout == L_TABBED || layout == L_STACKED) {
1123 struct sway_node *tabcontainer = node_get_parent(node); 1131 struct sway_node *tabcontainer = node_get_parent(node);
@@ -1527,3 +1535,66 @@ void cursor_warp_to_workspace(struct sway_cursor *cursor,
1527 1535
1528 wlr_cursor_warp(cursor->cursor, NULL, x, y); 1536 wlr_cursor_warp(cursor->cursor, NULL, x, y);
1529} 1537}
1538
1539uint32_t get_mouse_bindsym(const char *name, char **error) {
1540 if (strncasecmp(name, "button", strlen("button")) == 0) {
1541 // Map to x11 mouse buttons
1542 int number = name[strlen("button")] - '0';
1543 if (number < 1 || number > 9 || strlen(name) > strlen("button0")) {
1544 *error = strdup("Only buttons 1-9 are supported. For other mouse "
1545 "buttons, use the name of the event code.");
1546 return 0;
1547 }
1548 static const uint32_t buttons[] = {BTN_LEFT, BTN_MIDDLE, BTN_RIGHT,
1549 SWAY_SCROLL_UP, SWAY_SCROLL_DOWN, SWAY_SCROLL_LEFT,
1550 SWAY_SCROLL_RIGHT, BTN_SIDE, BTN_EXTRA};
1551 return buttons[number - 1];
1552 } else if (strncmp(name, "BTN_", strlen("BTN_")) == 0) {
1553 // Get event code from name
1554 int code = libevdev_event_code_from_name(EV_KEY, name);
1555 if (code == -1) {
1556 size_t len = snprintf(NULL, 0, "Unknown event %s", name) + 1;
1557 *error = malloc(len);
1558 if (*error) {
1559 snprintf(*error, len, "Unknown event %s", name);
1560 }
1561 return 0;
1562 }
1563 return code;
1564 }
1565 return 0;
1566}
1567
1568uint32_t get_mouse_bindcode(const char *name, char **error) {
1569 // Validate event code
1570 errno = 0;
1571 char *endptr;
1572 int code = strtol(name, &endptr, 10);
1573 if (endptr == name && code <= 0) {
1574 *error = strdup("Button event code must be a positive integer.");
1575 return 0;
1576 } else if (errno == ERANGE) {
1577 *error = strdup("Button event code out of range.");
1578 return 0;
1579 }
1580 const char *event = libevdev_event_code_get_name(EV_KEY, code);
1581 if (!event || strncmp(event, "BTN_", strlen("BTN_")) != 0) {
1582 size_t len = snprintf(NULL, 0, "Event code %d (%s) is not a button",
1583 code, event) + 1;
1584 *error = malloc(len);
1585 if (*error) {
1586 snprintf(*error, len, "Event code %d (%s) is not a button",
1587 code, event);
1588 }
1589 return 0;
1590 }
1591 return code;
1592}
1593
1594uint32_t get_mouse_button(const char *name, char **error) {
1595 uint32_t button = get_mouse_bindsym(name, error);
1596 if (!button && !error) {
1597 button = get_mouse_bindcode(name, error);
1598 }
1599 return button;
1600}
diff --git a/sway/ipc-json.c b/sway/ipc-json.c
index 53e0e335..15f89f65 100644
--- a/sway/ipc-json.c
+++ b/sway/ipc-json.c
@@ -11,6 +11,7 @@
11#include "sway/output.h" 11#include "sway/output.h"
12#include "sway/input/input-manager.h" 12#include "sway/input/input-manager.h"
13#include "sway/input/seat.h" 13#include "sway/input/seat.h"
14#include <wlr/backend/libinput.h>
14#include <wlr/types/wlr_box.h> 15#include <wlr/types/wlr_box.h>
15#include <wlr/types/wlr_output.h> 16#include <wlr/types/wlr_output.h>
16#include <xkbcommon/xkbcommon.h> 17#include <xkbcommon/xkbcommon.h>
@@ -598,6 +599,26 @@ json_object *ipc_json_describe_input(struct sway_input_device *device) {
598 } 599 }
599 } 600 }
600 601
602 if (wlr_input_device_is_libinput(device->wlr_device)) {
603 struct libinput_device *libinput_dev;
604 libinput_dev = wlr_libinput_get_device_handle(device->wlr_device);
605
606 const char *events = "unknown";
607 switch (libinput_device_config_send_events_get_mode(libinput_dev)) {
608 case LIBINPUT_CONFIG_SEND_EVENTS_ENABLED:
609 events = "enabled";
610 break;
611 case LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE:
612 events = "disabled_on_external_mouse";
613 break;
614 case LIBINPUT_CONFIG_SEND_EVENTS_DISABLED:
615 events = "disabled";
616 break;
617 }
618 json_object_object_add(object, "libinput_send_events",
619 json_object_new_string(events));
620 }
621
601 return object; 622 return object;
602} 623}
603 624
@@ -660,6 +681,10 @@ json_object *ipc_json_describe_bar_config(struct bar_config *bar) {
660 } 681 }
661 json_object_object_add(json, "bar_height", 682 json_object_object_add(json, "bar_height",
662 json_object_new_int(bar->height)); 683 json_object_new_int(bar->height));
684 json_object_object_add(json, "status_padding",
685 json_object_new_int(bar->status_padding));
686 json_object_object_add(json, "status_edge_padding",
687 json_object_new_int(bar->status_edge_padding));
663 json_object_object_add(json, "wrap_scroll", 688 json_object_object_add(json, "wrap_scroll",
664 json_object_new_boolean(bar->wrap_scroll)); 689 json_object_new_boolean(bar->wrap_scroll));
665 json_object_object_add(json, "workspace_buttons", 690 json_object_object_add(json, "workspace_buttons",
diff --git a/sway/ipc-server.c b/sway/ipc-server.c
index 456db866..ff1bc89f 100644
--- a/sway/ipc-server.c
+++ b/sway/ipc-server.c
@@ -445,8 +445,12 @@ void ipc_event_binding(struct sway_binding *binding) {
445 json_object_object_add(json_binding, "input_code", json_object_new_int(input_code)); 445 json_object_object_add(json_binding, "input_code", json_object_new_int(input_code));
446 json_object_object_add(json_binding, "symbols", symbols); 446 json_object_object_add(json_binding, "symbols", symbols);
447 json_object_object_add(json_binding, "symbol", symbol); 447 json_object_object_add(json_binding, "symbol", symbol);
448 json_object_object_add(json_binding, "input_type", binding->type == BINDING_MOUSE ? 448
449 json_object_new_string("mouse") : json_object_new_string("keyboard")); 449 bool mouse = binding->type == BINDING_MOUSECODE ||
450 binding->type == BINDING_MOUSESYM;
451 json_object_object_add(json_binding, "input_type", mouse
452 ? json_object_new_string("mouse")
453 : json_object_new_string("keyboard"));
450 454
451 json_object *json = json_object_new_object(); 455 json_object *json = json_object_new_object();
452 json_object_object_add(json, "change", json_object_new_string("run")); 456 json_object_object_add(json, "change", json_object_new_string("run"));
diff --git a/sway/meson.build b/sway/meson.build
index 98676ce0..ab5862c5 100644
--- a/sway/meson.build
+++ b/sway/meson.build
@@ -116,6 +116,8 @@ sway_sources = files(
116 'commands/bar/position.c', 116 'commands/bar/position.c',
117 'commands/bar/separator_symbol.c', 117 'commands/bar/separator_symbol.c',
118 'commands/bar/status_command.c', 118 'commands/bar/status_command.c',
119 'commands/bar/status_edge_padding.c',
120 'commands/bar/status_padding.c',
119 'commands/bar/strip_workspace_numbers.c', 121 'commands/bar/strip_workspace_numbers.c',
120 'commands/bar/strip_workspace_name.c', 122 'commands/bar/strip_workspace_name.c',
121 'commands/bar/swaybar_command.c', 123 'commands/bar/swaybar_command.c',
diff --git a/sway/sway-bar.5.scd b/sway/sway-bar.5.scd
index 2357591d..e1a4a937 100644
--- a/sway/sway-bar.5.scd
+++ b/sway/sway-bar.5.scd
@@ -69,7 +69,7 @@ Sway allows configuring swaybar in the sway configuration file.
69 use. 69 use.
70 70
71*height* <height> 71*height* <height>
72 Sets the height of the bar. Default height will match the font size. 72 Sets the height of the bar. Default height (0) will match the font size.
73 73
74*bindsym* [--release] button<n> <command> 74*bindsym* [--release] button<n> <command>
75 Executes _command_ when mouse button _n_ has been pressed (or if _released_ 75 Executes _command_ when mouse button _n_ has been pressed (or if _released_
@@ -92,6 +92,16 @@ Sway allows configuring swaybar in the sway configuration file.
92*modifier* <Modifier>|none 92*modifier* <Modifier>|none
93 Specifies the modifier key that shows a hidden bar. Default is _Mod4_. 93 Specifies the modifier key that shows a hidden bar. Default is _Mod4_.
94 94
95*status\_padding* <padding>
96 Sets the vertical padding that is used for the status line. The default is
97 _1_. If _padding_ is _0_, blocks will be able to take up the full height of
98 the bar. This value will be multiplied by the output scale.
99
100*status\_edge\_padding* <padding>
101 Sets the padding that is used when the status line is at the right edge of
102 the bar. This value will be multiplied by the output scale. The default is
103 _3_.
104
95## TRAY 105## TRAY
96 106
97Swaybar provides a system tray where third-party applications may place icons. 107Swaybar 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 820194a9..c54babaa 100644
--- a/sway/sway-input.5.scd
+++ b/sway/sway-input.5.scd
@@ -82,9 +82,12 @@ The following commands may only be used in the configuration file.
82*input* <identifier> dwt enabled|disabled 82*input* <identifier> dwt enabled|disabled
83 Enables or disables disable-while-typing for the specified input device. 83 Enables or disables disable-while-typing for the specified input device.
84 84
85*input* <identifier> events enabled|disabled|disabled\_on\_external\_mouse 85*input* <identifier> events enabled|disabled|disabled\_on\_external\_mouse|toggle
86 Enables or disables send\_events for specified input device. (Disabling 86 Enables or disables send\_events for specified input device. Disabling
87 send\_events disables the input device) 87 send\_events disables the input device. The _toggle_ option cannot be used
88 in the config. The order is enabled, disabled\_on\_external\_mouse,
89 disabled, (loop back to enabled). Any mode which is not supported by the
90 device will be skipped during the toggle.
88 91
89*input* <identifier> left\_handed enabled|disabled 92*input* <identifier> left\_handed enabled|disabled
90 Enables or disables left handed mode for specified input device. 93 Enables or disables left handed mode for specified input device.
diff --git a/sway/sway.5.scd b/sway/sway.5.scd
index 3757a097..3398ad58 100644
--- a/sway/sway.5.scd
+++ b/sway/sway.5.scd
@@ -302,7 +302,7 @@ runtime.
302``` 302```
303 303
304 *bindcode* [--release|--locked] [--input-device=<device>] [--no-warn] <code> <command> 304 *bindcode* [--release|--locked] [--input-device=<device>] [--no-warn] <code> <command>
305 is also available for binding with key codes instead of key names. 305 is also available for binding with key/button codes instead of key/button names.
306 306
307*client.<class>* <border> <background> <text> <indicator> <child\_border> 307*client.<class>* <border> <background> <text> <indicator> <child\_border>
308 Configures the color of window borders and title bars. All 5 colors are 308 Configures the color of window borders and title bars. All 5 colors are
diff --git a/sway/tree/output.c b/sway/tree/output.c
index 95ab9378..f24be010 100644
--- a/sway/tree/output.c
+++ b/sway/tree/output.c
@@ -58,6 +58,7 @@ struct sway_output *output_create(struct wlr_output *wlr_output) {
58 wlr_output->data = output; 58 wlr_output->data = output;
59 59
60 wl_signal_add(&wlr_output->events.destroy, &output->destroy); 60 wl_signal_add(&wlr_output->events.destroy, &output->destroy);
61 wl_signal_init(&output->events.destroy);
61 62
62 wl_list_insert(&root->all_outputs, &output->link); 63 wl_list_insert(&root->all_outputs, &output->link);
63 64
@@ -76,7 +77,6 @@ void output_enable(struct sway_output *output, struct output_config *oc) {
76 for (size_t i = 0; i < len; ++i) { 77 for (size_t i = 0; i < len; ++i) {
77 wl_list_init(&output->layers[i]); 78 wl_list_init(&output->layers[i]);
78 } 79 }
79 wl_signal_init(&output->events.destroy);
80 80
81 output->enabled = true; 81 output->enabled = true;
82 list_add(root->outputs, output); 82 list_add(root->outputs, output);