summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Brian Ashworth <bosrsf04@gmail.com>2018-10-18 13:13:40 -0400
committerLibravatar Brian Ashworth <bosrsf04@gmail.com>2018-10-18 13:42:01 -0400
commit2e637b7368de565a85f77fbd03408f33b763dd7b (patch)
tree00f3a082111e02dc2d7e7e54af60db4e58ebfc26
parentMerge pull request #2874 from ianyfan/swaybar (diff)
downloadsway-2e637b7368de565a85f77fbd03408f33b763dd7b.tar.gz
sway-2e637b7368de565a85f77fbd03408f33b763dd7b.tar.zst
sway-2e637b7368de565a85f77fbd03408f33b763dd7b.zip
cmd_bind{sym,code}: Implement per-device bindings
bindsym --input-device=<identifier> ... bindcode --input-device=<identifier> ...
-rw-r--r--include/sway/config.h1
-rw-r--r--include/sway/input/cursor.h5
-rw-r--r--include/sway/input/input-manager.h1
-rw-r--r--sway/commands/bind.c14
-rw-r--r--sway/commands/seat/cursor.c2
-rw-r--r--sway/input/cursor.c40
-rw-r--r--sway/input/input-manager.c6
-rw-r--r--sway/input/keyboard.c34
-rw-r--r--sway/sway.5.scd10
9 files changed, 77 insertions, 36 deletions
diff --git a/include/sway/config.h b/include/sway/config.h
index be5a00b5..fef3a60a 100644
--- a/include/sway/config.h
+++ b/include/sway/config.h
@@ -43,6 +43,7 @@ enum binding_flags {
43struct sway_binding { 43struct sway_binding {
44 enum binding_input_type type; 44 enum binding_input_type type;
45 int order; 45 int order;
46 char *input;
46 uint32_t flags; 47 uint32_t flags;
47 list_t *keys; // sorted in ascending order 48 list_t *keys; // sorted in ascending order
48 uint32_t modifiers; 49 uint32_t modifiers;
diff --git a/include/sway/input/cursor.h b/include/sway/input/cursor.h
index 5556ea11..299721f0 100644
--- a/include/sway/input/cursor.h
+++ b/include/sway/input/cursor.h
@@ -42,8 +42,9 @@ void sway_cursor_destroy(struct sway_cursor *cursor);
42struct sway_cursor *sway_cursor_create(struct sway_seat *seat); 42struct sway_cursor *sway_cursor_create(struct sway_seat *seat);
43void cursor_send_pointer_motion(struct sway_cursor *cursor, uint32_t time_msec, 43void cursor_send_pointer_motion(struct sway_cursor *cursor, uint32_t time_msec,
44 bool allow_refocusing); 44 bool allow_refocusing);
45void dispatch_cursor_button(struct sway_cursor *cursor, uint32_t time_msec, 45void dispatch_cursor_button(struct sway_cursor *cursor,
46 uint32_t button, enum wlr_button_state state); 46 struct wlr_input_device *device, uint32_t time_msec, uint32_t button,
47 enum wlr_button_state state);
47 48
48void cursor_set_image(struct sway_cursor *cursor, const char *image, 49void cursor_set_image(struct sway_cursor *cursor, const char *image,
49 struct wl_client *client); 50 struct wl_client *client);
diff --git a/include/sway/input/input-manager.h b/include/sway/input/input-manager.h
index bde3cf46..b7073006 100644
--- a/include/sway/input/input-manager.h
+++ b/include/sway/input/input-manager.h
@@ -63,5 +63,6 @@ struct sway_seat *input_manager_current_seat(struct sway_input_manager *input);
63 63
64struct input_config *input_device_get_config(struct sway_input_device *device); 64struct input_config *input_device_get_config(struct sway_input_device *device);
65 65
66char *input_device_get_identifier(struct wlr_input_device *device);
66 67
67#endif 68#endif
diff --git a/sway/commands/bind.c b/sway/commands/bind.c
index 701d9746..5832d01e 100644
--- a/sway/commands/bind.c
+++ b/sway/commands/bind.c
@@ -26,6 +26,7 @@ void free_sway_binding(struct sway_binding *binding) {
26 if (binding->keys) { 26 if (binding->keys) {
27 free_flat_list(binding->keys); 27 free_flat_list(binding->keys);
28 } 28 }
29 free(binding->input);
29 free(binding->command); 30 free(binding->command);
30 free(binding); 31 free(binding);
31} 32}
@@ -37,6 +38,10 @@ void free_sway_binding(struct sway_binding *binding) {
37 */ 38 */
38static bool binding_key_compare(struct sway_binding *binding_a, 39static bool binding_key_compare(struct sway_binding *binding_a,
39 struct sway_binding *binding_b) { 40 struct sway_binding *binding_b) {
41 if (strcmp(binding_a->input, binding_b->input) != 0) {
42 return false;
43 }
44
40 if (binding_a->type != binding_b->type) { 45 if (binding_a->type != binding_b->type) {
41 return false; 46 return false;
42 } 47 }
@@ -149,6 +154,7 @@ static struct cmd_results *cmd_bindsym_or_bindcode(int argc, char **argv,
149 return cmd_results_new(CMD_FAILURE, bindtype, 154 return cmd_results_new(CMD_FAILURE, bindtype,
150 "Unable to allocate binding"); 155 "Unable to allocate binding");
151 } 156 }
157 binding->input = strdup("*");
152 binding->keys = create_list(); 158 binding->keys = create_list();
153 binding->modifiers = 0; 159 binding->modifiers = 0;
154 binding->flags = 0; 160 binding->flags = 0;
@@ -168,6 +174,10 @@ static struct cmd_results *cmd_bindsym_or_bindcode(int argc, char **argv,
168 binding->flags |= BINDING_BORDER; 174 binding->flags |= BINDING_BORDER;
169 } else if (strcmp("--exclude-titlebar", argv[0]) == 0) { 175 } else if (strcmp("--exclude-titlebar", argv[0]) == 0) {
170 exclude_titlebar = true; 176 exclude_titlebar = true;
177 } else if (strncmp("--input-device=", argv[0],
178 strlen("--input-device=")) == 0) {
179 free(binding->input);
180 binding->input = strdup(argv[0] + strlen("--input-device="));
171 } else { 181 } else {
172 break; 182 break;
173 } 183 }
@@ -257,8 +267,8 @@ static struct cmd_results *cmd_bindsym_or_bindcode(int argc, char **argv,
257 list_add(mode_bindings, binding); 267 list_add(mode_bindings, binding);
258 } 268 }
259 269
260 wlr_log(WLR_DEBUG, "%s - Bound %s to command %s", 270 wlr_log(WLR_DEBUG, "%s - Bound %s to command `%s` for device '%s'",
261 bindtype, argv[0], binding->command); 271 bindtype, argv[0], binding->command, binding->input);
262 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 272 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
263 273
264} 274}
diff --git a/sway/commands/seat/cursor.c b/sway/commands/seat/cursor.c
index cd6630e0..595e9bc6 100644
--- a/sway/commands/seat/cursor.c
+++ b/sway/commands/seat/cursor.c
@@ -80,6 +80,6 @@ static struct cmd_results *press_or_release(struct sway_cursor *cursor,
80 return cmd_results_new(CMD_INVALID, "cursor", expected_syntax); 80 return cmd_results_new(CMD_INVALID, "cursor", expected_syntax);
81 } 81 }
82 } 82 }
83 dispatch_cursor_button(cursor, 0, button, state); 83 dispatch_cursor_button(cursor, NULL, 0, button, state);
84 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 84 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
85} 85}
diff --git a/sway/input/cursor.c b/sway/input/cursor.c
index 688fc230..7ac5013d 100644
--- a/sway/input/cursor.c
+++ b/sway/input/cursor.c
@@ -727,19 +727,23 @@ static void state_add_button(struct sway_cursor *cursor, uint32_t button) {
727 * Return the mouse binding which matches modifier, click location, release, 727 * Return the mouse binding which matches modifier, click location, release,
728 * and pressed button state, otherwise return null. 728 * and pressed button state, otherwise return null.
729 */ 729 */
730static struct sway_binding* get_active_mouse_binding(const struct sway_cursor *cursor, 730static struct sway_binding* get_active_mouse_binding(
731 list_t *bindings, uint32_t modifiers, bool release, bool on_titlebar, 731 const struct sway_cursor *cursor, list_t *bindings, uint32_t modifiers,
732 bool on_border, bool on_content) { 732 bool release, bool on_titlebar, bool on_border, bool on_content,
733 const char *identifier) {
733 uint32_t click_region = (on_titlebar ? BINDING_TITLEBAR : 0) | 734 uint32_t click_region = (on_titlebar ? BINDING_TITLEBAR : 0) |
734 (on_border ? BINDING_BORDER : 0) | 735 (on_border ? BINDING_BORDER : 0) |
735 (on_content ? BINDING_CONTENTS : 0); 736 (on_content ? BINDING_CONTENTS : 0);
736 737
738 struct sway_binding *current = NULL;
737 for (int i = 0; i < bindings->length; ++i) { 739 for (int i = 0; i < bindings->length; ++i) {
738 struct sway_binding *binding = bindings->items[i]; 740 struct sway_binding *binding = bindings->items[i];
739 if (modifiers ^ binding->modifiers || 741 if (modifiers ^ binding->modifiers ||
740 cursor->pressed_button_count != (size_t)binding->keys->length || 742 cursor->pressed_button_count != (size_t)binding->keys->length ||
741 release != (binding->flags & BINDING_RELEASE) || 743 release != (binding->flags & BINDING_RELEASE) ||
742 !(click_region & binding->flags)) { 744 !(click_region & binding->flags) ||
745 (strcmp(binding->input, identifier) != 0 &&
746 strcmp(binding->input, "*") != 0)) {
743 continue; 747 continue;
744 } 748 }
745 749
@@ -755,13 +759,20 @@ static struct sway_binding* get_active_mouse_binding(const struct sway_cursor *c
755 continue; 759 continue;
756 } 760 }
757 761
758 return binding; 762 if (!current || strcmp(current->input, "*") == 0) {
763 current = binding;
764 if (strcmp(current->input, identifier) == 0) {
765 // If a binding is found for the exact input, quit searching
766 break;
767 }
768 }
759 } 769 }
760 return NULL; 770 return current;
761} 771}
762 772
763void dispatch_cursor_button(struct sway_cursor *cursor, 773void dispatch_cursor_button(struct sway_cursor *cursor,
764 uint32_t time_msec, uint32_t button, enum wlr_button_state state) { 774 struct wlr_input_device *device, uint32_t time_msec, uint32_t button,
775 enum wlr_button_state state) {
765 if (time_msec == 0) { 776 if (time_msec == 0) {
766 time_msec = get_current_time_msec(); 777 time_msec = get_current_time_msec();
767 } 778 }
@@ -797,18 +808,21 @@ void dispatch_cursor_button(struct sway_cursor *cursor,
797 struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat->wlr_seat); 808 struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat->wlr_seat);
798 uint32_t modifiers = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0; 809 uint32_t modifiers = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0;
799 810
811 char *device_identifier = device ? input_device_get_identifier(device)
812 : strdup("*");
800 struct sway_binding *binding = NULL; 813 struct sway_binding *binding = NULL;
801 if (state == WLR_BUTTON_PRESSED) { 814 if (state == WLR_BUTTON_PRESSED) {
802 state_add_button(cursor, button); 815 state_add_button(cursor, button);
803 binding = get_active_mouse_binding(cursor, 816 binding = get_active_mouse_binding(cursor,
804 config->current_mode->mouse_bindings, modifiers, false, 817 config->current_mode->mouse_bindings, modifiers, false,
805 on_titlebar, on_border, on_contents); 818 on_titlebar, on_border, on_contents, device_identifier);
806 } else { 819 } else {
807 binding = get_active_mouse_binding(cursor, 820 binding = get_active_mouse_binding(cursor,
808 config->current_mode->mouse_bindings, modifiers, true, 821 config->current_mode->mouse_bindings, modifiers, true,
809 on_titlebar, on_border, on_contents); 822 on_titlebar, on_border, on_contents, device_identifier);
810 state_erase_button(cursor, button); 823 state_erase_button(cursor, button);
811 } 824 }
825 free(device_identifier);
812 if (binding) { 826 if (binding) {
813 seat_execute_command(seat, binding); 827 seat_execute_command(seat, binding);
814 return; 828 return;
@@ -942,7 +956,7 @@ static void handle_cursor_button(struct wl_listener *listener, void *data) {
942 struct sway_cursor *cursor = wl_container_of(listener, cursor, button); 956 struct sway_cursor *cursor = wl_container_of(listener, cursor, button);
943 wlr_idle_notify_activity(cursor->seat->input->server->idle, cursor->seat->wlr_seat); 957 wlr_idle_notify_activity(cursor->seat->input->server->idle, cursor->seat->wlr_seat);
944 struct wlr_event_pointer_button *event = data; 958 struct wlr_event_pointer_button *event = data;
945 dispatch_cursor_button(cursor, 959 dispatch_cursor_button(cursor, event->device,
946 event->time_msec, event->button, event->state); 960 event->time_msec, event->button, event->state);
947 transaction_commit_dirty(); 961 transaction_commit_dirty();
948} 962}
@@ -1128,7 +1142,7 @@ static void handle_tool_tip(struct wl_listener *listener, void *data) {
1128 struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_tip); 1142 struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_tip);
1129 wlr_idle_notify_activity(cursor->seat->input->server->idle, cursor->seat->wlr_seat); 1143 wlr_idle_notify_activity(cursor->seat->input->server->idle, cursor->seat->wlr_seat);
1130 struct wlr_event_tablet_tool_tip *event = data; 1144 struct wlr_event_tablet_tool_tip *event = data;
1131 dispatch_cursor_button(cursor, event->time_msec, 1145 dispatch_cursor_button(cursor, event->device, event->time_msec,
1132 BTN_LEFT, event->state == WLR_TABLET_TOOL_TIP_DOWN ? 1146 BTN_LEFT, event->state == WLR_TABLET_TOOL_TIP_DOWN ?
1133 WLR_BUTTON_PRESSED : WLR_BUTTON_RELEASED); 1147 WLR_BUTTON_PRESSED : WLR_BUTTON_RELEASED);
1134 transaction_commit_dirty(); 1148 transaction_commit_dirty();
@@ -1143,14 +1157,14 @@ static void handle_tool_button(struct wl_listener *listener, void *data) {
1143 switch (event->state) { 1157 switch (event->state) {
1144 case WLR_BUTTON_PRESSED: 1158 case WLR_BUTTON_PRESSED:
1145 if (cursor->tool_buttons == 0) { 1159 if (cursor->tool_buttons == 0) {
1146 dispatch_cursor_button(cursor, 1160 dispatch_cursor_button(cursor, event->device,
1147 event->time_msec, BTN_RIGHT, event->state); 1161 event->time_msec, BTN_RIGHT, event->state);
1148 } 1162 }
1149 cursor->tool_buttons++; 1163 cursor->tool_buttons++;
1150 break; 1164 break;
1151 case WLR_BUTTON_RELEASED: 1165 case WLR_BUTTON_RELEASED:
1152 if (cursor->tool_buttons == 1) { 1166 if (cursor->tool_buttons == 1) {
1153 dispatch_cursor_button(cursor, 1167 dispatch_cursor_button(cursor, event->device,
1154 event->time_msec, BTN_RIGHT, event->state); 1168 event->time_msec, BTN_RIGHT, event->state);
1155 } 1169 }
1156 cursor->tool_buttons--; 1170 cursor->tool_buttons--;
diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c
index 70c2abf7..671f9a47 100644
--- a/sway/input/input-manager.c
+++ b/sway/input/input-manager.c
@@ -45,7 +45,7 @@ struct sway_seat *input_manager_get_seat(
45 return seat_create(input, seat_name); 45 return seat_create(input, seat_name);
46} 46}
47 47
48static char *get_device_identifier(struct wlr_input_device *device) { 48char *input_device_get_identifier(struct wlr_input_device *device) {
49 int vendor = device->vendor; 49 int vendor = device->vendor;
50 int product = device->product; 50 int product = device->product;
51 char *name = strdup(device->name); 51 char *name = strdup(device->name);
@@ -278,7 +278,7 @@ static void handle_new_input(struct wl_listener *listener, void *data) {
278 device->data = input_device; 278 device->data = input_device;
279 279
280 input_device->wlr_device = device; 280 input_device->wlr_device = device;
281 input_device->identifier = get_device_identifier(device); 281 input_device->identifier = input_device_get_identifier(device);
282 wl_list_insert(&input->devices, &input_device->link); 282 wl_list_insert(&input->devices, &input_device->link);
283 283
284 wlr_log(WLR_DEBUG, "adding device: '%s'", 284 wlr_log(WLR_DEBUG, "adding device: '%s'",
@@ -375,7 +375,7 @@ void handle_virtual_keyboard(struct wl_listener *listener, void *data) {
375 device->data = input_device; 375 device->data = input_device;
376 376
377 input_device->wlr_device = device; 377 input_device->wlr_device = device;
378 input_device->identifier = get_device_identifier(device); 378 input_device->identifier = input_device_get_identifier(device);
379 wl_list_insert(&input_manager->devices, &input_device->link); 379 wl_list_insert(&input_manager->devices, &input_device->link);
380 380
381 wlr_log(WLR_DEBUG, "adding virtual keyboard: '%s'", 381 wlr_log(WLR_DEBUG, "adding virtual keyboard: '%s'",
diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c
index 2c8b41cd..4427dabe 100644
--- a/sway/input/keyboard.c
+++ b/sway/input/keyboard.c
@@ -87,7 +87,7 @@ static void update_shortcut_state(struct sway_shortcut_state *state,
87 */ 87 */
88static void get_active_binding(const struct sway_shortcut_state *state, 88static void get_active_binding(const struct sway_shortcut_state *state,
89 list_t *bindings, struct sway_binding **current_binding, 89 list_t *bindings, struct sway_binding **current_binding,
90 uint32_t modifiers, bool release, bool locked) { 90 uint32_t modifiers, bool release, bool locked, const char *input) {
91 for (int i = 0; i < bindings->length; ++i) { 91 for (int i = 0; i < bindings->length; ++i) {
92 struct sway_binding *binding = bindings->items[i]; 92 struct sway_binding *binding = bindings->items[i];
93 bool binding_locked = binding->flags & BINDING_LOCKED; 93 bool binding_locked = binding->flags & BINDING_LOCKED;
@@ -96,7 +96,9 @@ static void get_active_binding(const struct sway_shortcut_state *state,
96 if (modifiers ^ binding->modifiers || 96 if (modifiers ^ binding->modifiers ||
97 state->npressed != (size_t)binding->keys->length || 97 state->npressed != (size_t)binding->keys->length ||
98 release != binding_release || 98 release != binding_release ||
99 locked > binding_locked) { 99 locked > binding_locked ||
100 (strcmp(binding->input, input) != 0 &&
101 strcmp(binding->input, "*") != 0)) {
100 continue; 102 continue;
101 } 103 }
102 104
@@ -112,13 +114,19 @@ static void get_active_binding(const struct sway_shortcut_state *state,
112 continue; 114 continue;
113 } 115 }
114 116
115 if (*current_binding && *current_binding != binding) { 117 if (*current_binding && *current_binding != binding &&
118 strcmp((*current_binding)->input, binding->input) == 0) {
116 wlr_log(WLR_DEBUG, "encountered duplicate bindings %d and %d", 119 wlr_log(WLR_DEBUG, "encountered duplicate bindings %d and %d",
117 (*current_binding)->order, binding->order); 120 (*current_binding)->order, binding->order);
118 } else { 121 } else if (!*current_binding ||
122 strcmp((*current_binding)->input, "*") == 0) {
119 *current_binding = binding; 123 *current_binding = binding;
124
125 if (strcmp((*current_binding)->input, input) == 0) {
126 // If a binding is found for the exact input, quit searching
127 return;
128 }
120 } 129 }
121 return;
122 } 130 }
123} 131}
124 132
@@ -202,6 +210,7 @@ static void handle_keyboard_key(struct wl_listener *listener, void *data) {
202 struct wlr_seat *wlr_seat = seat->wlr_seat; 210 struct wlr_seat *wlr_seat = seat->wlr_seat;
203 struct wlr_input_device *wlr_device = 211 struct wlr_input_device *wlr_device =
204 keyboard->seat_device->input_device->wlr_device; 212 keyboard->seat_device->input_device->wlr_device;
213 char *device_identifier = input_device_get_identifier(wlr_device);
205 wlr_idle_notify_activity(seat->input->server->idle, wlr_seat); 214 wlr_idle_notify_activity(seat->input->server->idle, wlr_seat);
206 struct wlr_event_keyboard_key *event = data; 215 struct wlr_event_keyboard_key *event = data;
207 bool input_inhibited = seat->exclusive_client != NULL; 216 bool input_inhibited = seat->exclusive_client != NULL;
@@ -242,13 +251,13 @@ static void handle_keyboard_key(struct wl_listener *listener, void *data) {
242 struct sway_binding *binding_released = NULL; 251 struct sway_binding *binding_released = NULL;
243 get_active_binding(&keyboard->state_keycodes, 252 get_active_binding(&keyboard->state_keycodes,
244 config->current_mode->keycode_bindings, &binding_released, 253 config->current_mode->keycode_bindings, &binding_released,
245 code_modifiers, true, input_inhibited); 254 code_modifiers, true, input_inhibited, device_identifier);
246 get_active_binding(&keyboard->state_keysyms_translated, 255 get_active_binding(&keyboard->state_keysyms_translated,
247 config->current_mode->keysym_bindings, &binding_released, 256 config->current_mode->keysym_bindings, &binding_released,
248 translated_modifiers, true, input_inhibited); 257 translated_modifiers, true, input_inhibited, device_identifier);
249 get_active_binding(&keyboard->state_keysyms_raw, 258 get_active_binding(&keyboard->state_keysyms_raw,
250 config->current_mode->keysym_bindings, &binding_released, 259 config->current_mode->keysym_bindings, &binding_released,
251 raw_modifiers, true, input_inhibited); 260 raw_modifiers, true, input_inhibited, device_identifier);
252 261
253 // Execute stored release binding once no longer active 262 // Execute stored release binding once no longer active
254 if (keyboard->held_binding && binding_released != keyboard->held_binding && 263 if (keyboard->held_binding && binding_released != keyboard->held_binding &&
@@ -268,13 +277,14 @@ static void handle_keyboard_key(struct wl_listener *listener, void *data) {
268 if (event->state == WLR_KEY_PRESSED) { 277 if (event->state == WLR_KEY_PRESSED) {
269 get_active_binding(&keyboard->state_keycodes, 278 get_active_binding(&keyboard->state_keycodes,
270 config->current_mode->keycode_bindings, &binding, 279 config->current_mode->keycode_bindings, &binding,
271 code_modifiers, false, input_inhibited); 280 code_modifiers, false, input_inhibited, device_identifier);
272 get_active_binding(&keyboard->state_keysyms_translated, 281 get_active_binding(&keyboard->state_keysyms_translated,
273 config->current_mode->keysym_bindings, &binding, 282 config->current_mode->keysym_bindings, &binding,
274 translated_modifiers, false, input_inhibited); 283 translated_modifiers, false, input_inhibited,
284 device_identifier);
275 get_active_binding(&keyboard->state_keysyms_raw, 285 get_active_binding(&keyboard->state_keysyms_raw,
276 config->current_mode->keysym_bindings, &binding, 286 config->current_mode->keysym_bindings, &binding,
277 raw_modifiers, false, input_inhibited); 287 raw_modifiers, false, input_inhibited, device_identifier);
278 288
279 if (binding) { 289 if (binding) {
280 seat_execute_command(seat, binding); 290 seat_execute_command(seat, binding);
@@ -315,6 +325,8 @@ static void handle_keyboard_key(struct wl_listener *listener, void *data) {
315 } 325 }
316 326
317 transaction_commit_dirty(); 327 transaction_commit_dirty();
328
329 free(device_identifier);
318} 330}
319 331
320static int handle_keyboard_repeat(void *data) { 332static int handle_keyboard_repeat(void *data) {
diff --git a/sway/sway.5.scd b/sway/sway.5.scd
index f6f0e859..e5e7918f 100644
--- a/sway/sway.5.scd
+++ b/sway/sway.5.scd
@@ -257,20 +257,22 @@ runtime.
257 257
258 for\_window <criteria> move container to output <output> 258 for\_window <criteria> move container to output <output>
259 259
260*bindsym* [--release|--locked] <key combo> <command> 260*bindsym* [--release|--locked] [--input-device=<device>] <key combo> <command>
261 Binds _key combo_ to execute the sway command _command_ when pressed. You 261 Binds _key combo_ to execute the sway command _command_ when pressed. You
262 may use XKB key names here (*xev*(1) is a good tool for discovering these). 262 may use XKB key names here (*xev*(1) is a good tool for discovering these).
263 With the flag _--release_, the command is executed when the key combo is 263 With the flag _--release_, the command is executed when the key combo is
264 released. Unless the flag _--locked_ is set, the command will not be run 264 released. Unless the flag _--locked_ is set, the command will not be run
265 when a screen locking program is active. 265 when a screen locking program is active. If _input-device_ is given, the
266 binding will only be executed for that input device and will be executed
267 instead of any binding that is generic to all devices.
266 268
267 Example: 269 Example:
268 270
269 # Execute firefox when alt, shift, and f are pressed together 271 # Execute firefox when alt, shift, and f are pressed together
270 bindsym Mod1+Shift+f exec firefox 272 bindsym Mod1+Shift+f exec firefox
271 273
272 *bindcode* [--release|--locked] <code> <command> is also available for 274 *bindcode* [--release|--locked] [--input-device=<device>] <code> <command>
273 binding with key codes instead of key names. 275 is also available for binding with key codes instead of key names.
274 276
275*client.<class>* <border> <background> <text> <indicator> <child\_border> 277*client.<class>* <border> <background> <text> <indicator> <child\_border>
276 Configures the color of window borders and title bars. All 5 colors are 278 Configures the color of window borders and title bars. All 5 colors are