diff options
-rw-r--r-- | include/sway/config.h | 16 | ||||
-rw-r--r-- | include/swaybar/config.h | 8 | ||||
-rw-r--r-- | include/swaybar/ipc.h | 1 | ||||
-rw-r--r-- | sway/commands/bar/bindsym.c | 60 | ||||
-rw-r--r-- | sway/commands/mouse_warping.c | 8 | ||||
-rw-r--r-- | sway/config.c | 2 | ||||
-rw-r--r-- | sway/config/bar.c | 13 | ||||
-rw-r--r-- | sway/input/cursor.c | 1 | ||||
-rw-r--r-- | sway/input/seat.c | 21 | ||||
-rw-r--r-- | sway/ipc-json.c | 16 | ||||
-rw-r--r-- | sway/sway-bar.5.scd | 5 | ||||
-rw-r--r-- | sway/sway.5.scd | 7 | ||||
-rw-r--r-- | sway/tree/container.c | 12 | ||||
-rw-r--r-- | sway/tree/view.c | 4 | ||||
-rw-r--r-- | swaybar/bar.c | 31 | ||||
-rw-r--r-- | swaybar/config.c | 16 | ||||
-rw-r--r-- | swaybar/ipc.c | 26 | ||||
-rw-r--r-- | swaybar/main.c | 2 | ||||
-rw-r--r-- | swaymsg/main.c | 2 |
19 files changed, 226 insertions, 25 deletions
diff --git a/include/sway/config.h b/include/sway/config.h index 00b5f25b..bc02c0fd 100644 --- a/include/sway/config.h +++ b/include/sway/config.h | |||
@@ -239,6 +239,12 @@ struct bar_config { | |||
239 | } colors; | 239 | } colors; |
240 | }; | 240 | }; |
241 | 241 | ||
242 | struct bar_binding { | ||
243 | uint32_t button; | ||
244 | bool release; | ||
245 | char *command; | ||
246 | }; | ||
247 | |||
242 | struct border_colors { | 248 | struct border_colors { |
243 | float border[4]; | 249 | float border[4]; |
244 | float background[4]; | 250 | float background[4]; |
@@ -325,6 +331,12 @@ enum focus_wrapping_mode { | |||
325 | WRAP_FORCE | 331 | WRAP_FORCE |
326 | }; | 332 | }; |
327 | 333 | ||
334 | enum mouse_warping_mode { | ||
335 | WARP_NO, | ||
336 | WARP_OUTPUT, | ||
337 | WARP_CONTAINER | ||
338 | }; | ||
339 | |||
328 | /** | 340 | /** |
329 | * The configuration struct. The result of loading a config file. | 341 | * The configuration struct. The result of loading a config file. |
330 | */ | 342 | */ |
@@ -366,7 +378,7 @@ struct sway_config { | |||
366 | // Flags | 378 | // Flags |
367 | bool focus_follows_mouse; | 379 | bool focus_follows_mouse; |
368 | bool raise_floating; | 380 | bool raise_floating; |
369 | bool mouse_warping; | 381 | enum mouse_warping_mode mouse_warping; |
370 | enum focus_wrapping_mode focus_wrapping; | 382 | enum focus_wrapping_mode focus_wrapping; |
371 | bool active; | 383 | bool active; |
372 | bool failed; | 384 | bool failed; |
@@ -527,6 +539,8 @@ struct bar_config *default_bar_config(void); | |||
527 | 539 | ||
528 | void free_bar_config(struct bar_config *bar); | 540 | void free_bar_config(struct bar_config *bar); |
529 | 541 | ||
542 | void free_bar_binding(struct bar_binding *binding); | ||
543 | |||
530 | void free_workspace_config(struct workspace_config *wsc); | 544 | void free_workspace_config(struct workspace_config *wsc); |
531 | 545 | ||
532 | /** | 546 | /** |
diff --git a/include/swaybar/config.h b/include/swaybar/config.h index 5f5688cf..d0336c27 100644 --- a/include/swaybar/config.h +++ b/include/swaybar/config.h | |||
@@ -3,6 +3,7 @@ | |||
3 | #include <stdbool.h> | 3 | #include <stdbool.h> |
4 | #include <stdint.h> | 4 | #include <stdint.h> |
5 | #include <wayland-client.h> | 5 | #include <wayland-client.h> |
6 | #include "list.h" | ||
6 | #include "util.h" | 7 | #include "util.h" |
7 | 8 | ||
8 | struct box_colors { | 9 | struct box_colors { |
@@ -17,6 +18,12 @@ struct config_output { | |||
17 | size_t index; | 18 | size_t index; |
18 | }; | 19 | }; |
19 | 20 | ||
21 | struct swaybar_binding { | ||
22 | uint32_t button; | ||
23 | char *command; | ||
24 | bool release; | ||
25 | }; | ||
26 | |||
20 | struct swaybar_config { | 27 | struct swaybar_config { |
21 | char *status_command; | 28 | char *status_command; |
22 | bool pango_markup; | 29 | bool pango_markup; |
@@ -29,6 +36,7 @@ struct swaybar_config { | |||
29 | bool binding_mode_indicator; | 36 | bool binding_mode_indicator; |
30 | bool wrap_scroll; | 37 | bool wrap_scroll; |
31 | bool workspace_buttons; | 38 | bool workspace_buttons; |
39 | list_t *bindings; | ||
32 | struct wl_list outputs; // config_output::link | 40 | struct wl_list outputs; // config_output::link |
33 | bool all_outputs; | 41 | bool all_outputs; |
34 | int height; | 42 | int height; |
diff --git a/include/swaybar/ipc.h b/include/swaybar/ipc.h index 81e48a6b..8731dac2 100644 --- a/include/swaybar/ipc.h +++ b/include/swaybar/ipc.h | |||
@@ -7,5 +7,6 @@ bool ipc_initialize(struct swaybar *bar, const char *bar_id); | |||
7 | bool handle_ipc_readable(struct swaybar *bar); | 7 | bool handle_ipc_readable(struct swaybar *bar); |
8 | void ipc_get_workspaces(struct swaybar *bar); | 8 | void ipc_get_workspaces(struct swaybar *bar); |
9 | void ipc_send_workspace_command(struct swaybar *bar, const char *ws); | 9 | void ipc_send_workspace_command(struct swaybar *bar, const char *ws); |
10 | void ipc_execute_binding(struct swaybar *bar, struct swaybar_binding *bind); | ||
10 | 11 | ||
11 | #endif | 12 | #endif |
diff --git a/sway/commands/bar/bindsym.c b/sway/commands/bar/bindsym.c index ac09a03f..4eea3e6a 100644 --- a/sway/commands/bar/bindsym.c +++ b/sway/commands/bar/bindsym.c | |||
@@ -1,5 +1,7 @@ | |||
1 | #define _XOPEN_SOURCE 500 | ||
1 | #include <stdlib.h> | 2 | #include <stdlib.h> |
2 | #include <string.h> | 3 | #include <string.h> |
4 | #include <strings.h> | ||
3 | #include "sway/commands.h" | 5 | #include "sway/commands.h" |
4 | #include "sway/config.h" | 6 | #include "sway/config.h" |
5 | #include "list.h" | 7 | #include "list.h" |
@@ -7,5 +9,61 @@ | |||
7 | #include "stringop.h" | 9 | #include "stringop.h" |
8 | 10 | ||
9 | struct cmd_results *bar_cmd_bindsym(int argc, char **argv) { | 11 | struct cmd_results *bar_cmd_bindsym(int argc, char **argv) { |
10 | return cmd_results_new(CMD_FAILURE, "bindsym", "TODO"); // TODO | 12 | struct cmd_results *error = NULL; |
13 | if ((error = checkarg(argc, "bar bindsym", EXPECTED_MORE_THAN, 1))) { | ||
14 | return error; | ||
15 | } | ||
16 | if (!config->current_bar) { | ||
17 | return cmd_results_new(CMD_FAILURE, "bar bindsym", "No bar defined."); | ||
18 | } | ||
19 | |||
20 | struct bar_binding *binding = calloc(1, sizeof(struct bar_binding)); | ||
21 | if (!binding) { | ||
22 | return cmd_results_new(CMD_FAILURE, "bar bindsym", | ||
23 | "Unable to allocate bar binding"); | ||
24 | } | ||
25 | |||
26 | binding->release = false; | ||
27 | if (strcmp("--release", argv[0]) == 0) { | ||
28 | binding->release = true; | ||
29 | argv++; | ||
30 | argc--; | ||
31 | } | ||
32 | |||
33 | binding->button = 0; | ||
34 | if (strncasecmp(argv[0], "button", strlen("button")) == 0 && | ||
35 | strlen(argv[0]) == strlen("button0")) { | ||
36 | binding->button = argv[0][strlen("button")] - '0'; | ||
37 | } | ||
38 | if (binding->button < 1 || binding->button > 9) { | ||
39 | free_bar_binding(binding); | ||
40 | return cmd_results_new(CMD_FAILURE, "bar bindsym", | ||
41 | "Only button<1-9> is supported"); | ||
42 | } | ||
43 | |||
44 | binding->command = join_args(argv + 1, argc - 1); | ||
45 | |||
46 | list_t *bindings = config->current_bar->bindings; | ||
47 | bool overwritten = false; | ||
48 | for (int i = 0; i < bindings->length; i++) { | ||
49 | struct bar_binding *other = bindings->items[i]; | ||
50 | if (other->button == binding->button && | ||
51 | other->release == binding->release) { | ||
52 | overwritten = true; | ||
53 | bindings->items[i] = binding; | ||
54 | free_bar_binding(other); | ||
55 | wlr_log(WLR_DEBUG, "[bar %s] Updated binding for button%u%s", | ||
56 | config->current_bar->id, binding->button, | ||
57 | binding->release ? " (release)" : ""); | ||
58 | break; | ||
59 | } | ||
60 | } | ||
61 | if (!overwritten) { | ||
62 | list_add(bindings, binding); | ||
63 | wlr_log(WLR_DEBUG, "[bar %s] Added binding for button%u%s", | ||
64 | config->current_bar->id, binding->button, | ||
65 | binding->release ? " (release)" : ""); | ||
66 | } | ||
67 | |||
68 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
11 | } | 69 | } |
diff --git a/sway/commands/mouse_warping.c b/sway/commands/mouse_warping.c index eef32ce7..d067bc65 100644 --- a/sway/commands/mouse_warping.c +++ b/sway/commands/mouse_warping.c | |||
@@ -6,13 +6,15 @@ struct cmd_results *cmd_mouse_warping(int argc, char **argv) { | |||
6 | struct cmd_results *error = NULL; | 6 | struct cmd_results *error = NULL; |
7 | if ((error = checkarg(argc, "mouse_warping", EXPECTED_EQUAL_TO, 1))) { | 7 | if ((error = checkarg(argc, "mouse_warping", EXPECTED_EQUAL_TO, 1))) { |
8 | return error; | 8 | return error; |
9 | } else if (strcasecmp(argv[0], "container") == 0) { | ||
10 | config->mouse_warping = WARP_CONTAINER; | ||
9 | } else if (strcasecmp(argv[0], "output") == 0) { | 11 | } else if (strcasecmp(argv[0], "output") == 0) { |
10 | config->mouse_warping = true; | 12 | config->mouse_warping = WARP_OUTPUT; |
11 | } else if (strcasecmp(argv[0], "none") == 0) { | 13 | } else if (strcasecmp(argv[0], "none") == 0) { |
12 | config->mouse_warping = false; | 14 | config->mouse_warping = WARP_NO; |
13 | } else { | 15 | } else { |
14 | return cmd_results_new(CMD_FAILURE, "mouse_warping", | 16 | return cmd_results_new(CMD_FAILURE, "mouse_warping", |
15 | "Expected 'mouse_warping output|none'"); | 17 | "Expected 'mouse_warping output|container|none'"); |
16 | } | 18 | } |
17 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 19 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
18 | } | 20 | } |
diff --git a/sway/config.c b/sway/config.c index 1926bc08..f239ba1d 100644 --- a/sway/config.c +++ b/sway/config.c | |||
@@ -223,7 +223,7 @@ static void config_defaults(struct sway_config *config) { | |||
223 | // Flags | 223 | // Flags |
224 | config->focus_follows_mouse = true; | 224 | config->focus_follows_mouse = true; |
225 | config->raise_floating = true; | 225 | config->raise_floating = true; |
226 | config->mouse_warping = true; | 226 | config->mouse_warping = WARP_OUTPUT; |
227 | config->focus_wrapping = WRAP_YES; | 227 | config->focus_wrapping = WRAP_YES; |
228 | config->validating = false; | 228 | config->validating = false; |
229 | config->reloading = false; | 229 | config->reloading = false; |
diff --git a/sway/config/bar.c b/sway/config/bar.c index b8695798..c6899f57 100644 --- a/sway/config/bar.c +++ b/sway/config/bar.c | |||
@@ -28,6 +28,14 @@ static void terminate_swaybar(pid_t pid) { | |||
28 | } | 28 | } |
29 | } | 29 | } |
30 | 30 | ||
31 | void free_bar_binding(struct bar_binding *binding) { | ||
32 | if (!binding) { | ||
33 | return; | ||
34 | } | ||
35 | free(binding->command); | ||
36 | free(binding); | ||
37 | } | ||
38 | |||
31 | void free_bar_config(struct bar_config *bar) { | 39 | void free_bar_config(struct bar_config *bar) { |
32 | if (!bar) { | 40 | if (!bar) { |
33 | return; | 41 | return; |
@@ -39,7 +47,10 @@ void free_bar_config(struct bar_config *bar) { | |||
39 | free(bar->status_command); | 47 | free(bar->status_command); |
40 | free(bar->font); | 48 | free(bar->font); |
41 | free(bar->separator_symbol); | 49 | free(bar->separator_symbol); |
42 | // TODO: Free mouse bindings | 50 | for (int i = 0; i < bar->bindings->length; i++) { |
51 | struct bar_binding *binding = bar->bindings->items[i]; | ||
52 | free_bar_binding(binding); | ||
53 | } | ||
43 | list_free(bar->bindings); | 54 | list_free(bar->bindings); |
44 | if (bar->outputs) { | 55 | if (bar->outputs) { |
45 | free_flat_list(bar->outputs); | 56 | free_flat_list(bar->outputs); |
diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 6d57c45f..5c446299 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c | |||
@@ -877,6 +877,7 @@ void dispatch_cursor_button(struct sway_cursor *cursor, | |||
877 | while (cont->parent) { | 877 | while (cont->parent) { |
878 | cont = cont->parent; | 878 | cont = cont->parent; |
879 | } | 879 | } |
880 | seat_set_focus_container(seat, cont); | ||
880 | seat_begin_move_floating(seat, cont, button); | 881 | seat_begin_move_floating(seat, cont, button); |
881 | return; | 882 | return; |
882 | } | 883 | } |
diff --git a/sway/input/seat.c b/sway/input/seat.c index f418785d..03ed638e 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c | |||
@@ -772,7 +772,9 @@ void seat_set_focus_warp(struct sway_seat *seat, struct sway_node *node, | |||
772 | } | 772 | } |
773 | 773 | ||
774 | if (last_focus) { | 774 | if (last_focus) { |
775 | if (config->mouse_warping && warp && new_output != last_output) { | 775 | if (config->mouse_warping && warp && |
776 | (new_output != last_output || | ||
777 | config->mouse_warping == WARP_CONTAINER)) { | ||
776 | double x = 0; | 778 | double x = 0; |
777 | double y = 0; | 779 | double y = 0; |
778 | if (container) { | 780 | if (container) { |
@@ -782,9 +784,11 @@ void seat_set_focus_warp(struct sway_seat *seat, struct sway_node *node, | |||
782 | x = new_workspace->x + new_workspace->width / 2.0; | 784 | x = new_workspace->x + new_workspace->width / 2.0; |
783 | y = new_workspace->y + new_workspace->height / 2.0; | 785 | y = new_workspace->y + new_workspace->height / 2.0; |
784 | } | 786 | } |
787 | |||
785 | if (!wlr_output_layout_contains_point(root->output_layout, | 788 | if (!wlr_output_layout_contains_point(root->output_layout, |
786 | new_output->wlr_output, seat->cursor->cursor->x, | 789 | new_output->wlr_output, seat->cursor->cursor->x, |
787 | seat->cursor->cursor->y)) { | 790 | seat->cursor->cursor->y) |
791 | || config->mouse_warping == WARP_CONTAINER) { | ||
788 | wlr_cursor_warp(seat->cursor->cursor, NULL, x, y); | 792 | wlr_cursor_warp(seat->cursor->cursor, NULL, x, y); |
789 | cursor_send_pointer_motion(seat->cursor, 0, true); | 793 | cursor_send_pointer_motion(seat->cursor, 0, true); |
790 | } | 794 | } |
@@ -1038,7 +1042,7 @@ void seat_begin_down(struct sway_seat *seat, struct sway_container *con, | |||
1038 | seat->op_moved = false; | 1042 | seat->op_moved = false; |
1039 | 1043 | ||
1040 | // In case the container was not raised by gaining focus, raise on click | 1044 | // In case the container was not raised by gaining focus, raise on click |
1041 | if (con && !config->raise_floating) { | 1045 | if (!config->raise_floating) { |
1042 | container_raise_floating(con); | 1046 | container_raise_floating(con); |
1043 | } | 1047 | } |
1044 | } | 1048 | } |
@@ -1052,6 +1056,12 @@ void seat_begin_move_floating(struct sway_seat *seat, | |||
1052 | seat->operation = OP_MOVE_FLOATING; | 1056 | seat->operation = OP_MOVE_FLOATING; |
1053 | seat->op_container = con; | 1057 | seat->op_container = con; |
1054 | seat->op_button = button; | 1058 | seat->op_button = button; |
1059 | |||
1060 | // In case the container was not raised by gaining focus, raise on click | ||
1061 | if (!config->raise_floating) { | ||
1062 | container_raise_floating(con); | ||
1063 | } | ||
1064 | |||
1055 | cursor_set_image(seat->cursor, "grab", NULL); | 1065 | cursor_set_image(seat->cursor, "grab", NULL); |
1056 | } | 1066 | } |
1057 | 1067 | ||
@@ -1085,6 +1095,11 @@ void seat_begin_resize_floating(struct sway_seat *seat, | |||
1085 | seat->op_ref_con_ly = con->y; | 1095 | seat->op_ref_con_ly = con->y; |
1086 | seat->op_ref_width = con->width; | 1096 | seat->op_ref_width = con->width; |
1087 | seat->op_ref_height = con->height; | 1097 | seat->op_ref_height = con->height; |
1098 | // | ||
1099 | // In case the container was not raised by gaining focus, raise on click | ||
1100 | if (!config->raise_floating) { | ||
1101 | container_raise_floating(con); | ||
1102 | } | ||
1088 | 1103 | ||
1089 | const char *image = edge == WLR_EDGE_NONE ? | 1104 | const char *image = edge == WLR_EDGE_NONE ? |
1090 | "se-resize" : wlr_xcursor_get_resize_name(edge); | 1105 | "se-resize" : wlr_xcursor_get_resize_name(edge); |
diff --git a/sway/ipc-json.c b/sway/ipc-json.c index f02f370b..54d611f2 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c | |||
@@ -623,6 +623,22 @@ json_object *ipc_json_describe_bar_config(struct bar_config *bar) { | |||
623 | 623 | ||
624 | json_object_object_add(json, "colors", colors); | 624 | json_object_object_add(json, "colors", colors); |
625 | 625 | ||
626 | if (bar->bindings->length > 0) { | ||
627 | json_object *bindings = json_object_new_array(); | ||
628 | for (int i = 0; i < bar->bindings->length; ++i) { | ||
629 | struct bar_binding *binding = bar->bindings->items[i]; | ||
630 | json_object *bind = json_object_new_object(); | ||
631 | json_object_object_add(bind, "input_code", | ||
632 | json_object_new_int(binding->button)); | ||
633 | json_object_object_add(bind, "command", | ||
634 | json_object_new_string(binding->command)); | ||
635 | json_object_object_add(bind, "release", | ||
636 | json_object_new_boolean(binding->release)); | ||
637 | json_object_array_add(bindings, bind); | ||
638 | } | ||
639 | json_object_object_add(json, "bindings", bindings); | ||
640 | } | ||
641 | |||
626 | // Add outputs if defined | 642 | // Add outputs if defined |
627 | if (bar->outputs && bar->outputs->length > 0) { | 643 | if (bar->outputs && bar->outputs->length > 0) { |
628 | json_object *outputs = json_object_new_array(); | 644 | json_object *outputs = json_object_new_array(); |
diff --git a/sway/sway-bar.5.scd b/sway/sway-bar.5.scd index 8c7be8e7..6729c9ac 100644 --- a/sway/sway-bar.5.scd +++ b/sway/sway-bar.5.scd | |||
@@ -60,6 +60,11 @@ Sway allows configuring swaybar in the sway configuration file. | |||
60 | *height* <height> | 60 | *height* <height> |
61 | Sets the height of the bar. Default height will match the font size. | 61 | Sets the height of the bar. Default height will match the font size. |
62 | 62 | ||
63 | *bindsym* [--release] button<n> <command> | ||
64 | Executes _command_ when mouse button _n_ has been pressed (or if _released_ | ||
65 | is given, when mouse button _n_ has been released). To disable the default | ||
66 | behavior for a button, use the command _nop_. | ||
67 | |||
63 | ## TRAY | 68 | ## TRAY |
64 | 69 | ||
65 | Swaybar provides a system tray where third-party applications may place icons. | 70 | Swaybar provides a system tray where third-party applications may place icons. |
diff --git a/sway/sway.5.scd b/sway/sway.5.scd index 28ab15df..240e0731 100644 --- a/sway/sway.5.scd +++ b/sway/sway.5.scd | |||
@@ -492,9 +492,10 @@ The default colors are: | |||
492 | If _--pango\_markup_ is given, then _mode_ will be interpreted as pango | 492 | If _--pango\_markup_ is given, then _mode_ will be interpreted as pango |
493 | markup. | 493 | markup. |
494 | 494 | ||
495 | *mouse\_warping* output|none | 495 | *mouse\_warping* output|container|none |
496 | If _output_ is specified, the mouse will be moved to new outputs as you | 496 | If _output_ is specified, the mouse will be moved to new outputs as you |
497 | move focus between them. Default is _output_. | 497 | move focus between them. If _container_ is specified, the mouse will be |
498 | moved to the middle of the container on switch. Default is _output_. | ||
498 | 499 | ||
499 | *no\_focus* <criteria> | 500 | *no\_focus* <criteria> |
500 | Prevents windows matching <criteria> from being focused automatically when | 501 | Prevents windows matching <criteria> from being focused automatically when |
@@ -598,7 +599,7 @@ match any output by using the output name "\*". | |||
598 | *workspace* prev\_on\_output|next\_on\_output | 599 | *workspace* prev\_on\_output|next\_on\_output |
599 | Switches to the next workspace on the current output. | 600 | Switches to the next workspace on the current output. |
600 | 601 | ||
601 | *workspace* back_and_forth | 602 | *workspace* back\_and\_forth |
602 | Switches to the previously focused workspace. | 603 | Switches to the previously focused workspace. |
603 | 604 | ||
604 | *workspace* <name> gaps inner|outer <amount> | 605 | *workspace* <name> gaps inner|outer <amount> |
diff --git a/sway/tree/container.c b/sway/tree/container.c index 1664514a..f36fe4b0 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c | |||
@@ -358,7 +358,6 @@ struct sway_container *container_at(struct sway_workspace *workspace, | |||
358 | struct wlr_surface **surface, double *sx, double *sy) { | 358 | struct wlr_surface **surface, double *sx, double *sy) { |
359 | struct sway_container *c; | 359 | struct sway_container *c; |
360 | 360 | ||
361 | // Focused view's popups | ||
362 | struct sway_seat *seat = input_manager_current_seat(input_manager); | 361 | struct sway_seat *seat = input_manager_current_seat(input_manager); |
363 | struct sway_container *focus = seat_get_focused_container(seat); | 362 | struct sway_container *focus = seat_get_focused_container(seat); |
364 | bool is_floating = focus && container_is_floating_or_child(focus); | 363 | bool is_floating = focus && container_is_floating_or_child(focus); |
@@ -370,14 +369,11 @@ struct sway_container *container_at(struct sway_workspace *workspace, | |||
370 | } | 369 | } |
371 | *surface = NULL; | 370 | *surface = NULL; |
372 | } | 371 | } |
373 | // Cast a ray to handle floating windows | 372 | // Floating |
374 | for (int i = workspace->floating->length - 1; i >= 0; --i) { | 373 | if ((c = floating_container_at(lx, ly, surface ,sx ,sy))) { |
375 | struct sway_container *cn = workspace->floating->items[i]; | 374 | return c; |
376 | if (cn->view && (c = surface_at_view(cn, lx, ly, surface, sx, sy))) { | ||
377 | return c; | ||
378 | } | ||
379 | } | 375 | } |
380 | // If focused is tiling, focused view's non-popups | 376 | // Tiling (focused) |
381 | if (focus && focus->view && !is_floating) { | 377 | if (focus && focus->view && !is_floating) { |
382 | if ((c = surface_at_view(focus, lx, ly, surface, sx, sy))) { | 378 | if ((c = surface_at_view(focus, lx, ly, surface, sx, sy))) { |
383 | return c; | 379 | return c; |
diff --git a/sway/tree/view.c b/sway/tree/view.c index 1f00452d..e613ac0b 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c | |||
@@ -243,10 +243,10 @@ void view_autoconfigure(struct sway_view *view) { | |||
243 | // title area. We have to offset the surface y by the height of the title, | 243 | // title area. We have to offset the surface y by the height of the title, |
244 | // bar, and disable any top border because we'll always have the title bar. | 244 | // bar, and disable any top border because we'll always have the title bar. |
245 | enum sway_container_layout layout = container_parent_layout(con); | 245 | enum sway_container_layout layout = container_parent_layout(con); |
246 | if (layout == L_TABBED) { | 246 | if (layout == L_TABBED && !container_is_floating(con)) { |
247 | y_offset = container_titlebar_height(); | 247 | y_offset = container_titlebar_height(); |
248 | view->border_top = false; | 248 | view->border_top = false; |
249 | } else if (layout == L_STACKED) { | 249 | } else if (layout == L_STACKED && !container_is_floating(con)) { |
250 | list_t *siblings = container_get_siblings(con); | 250 | list_t *siblings = container_get_siblings(con); |
251 | y_offset = container_titlebar_height() * siblings->length; | 251 | y_offset = container_titlebar_height() * siblings->length; |
252 | view->border_top = false; | 252 | view->border_top = false; |
diff --git a/swaybar/bar.c b/swaybar/bar.c index 3990f1ca..5b7fea71 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c | |||
@@ -144,6 +144,19 @@ static void wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, | |||
144 | bar->pointer.y = wl_fixed_to_int(surface_y); | 144 | bar->pointer.y = wl_fixed_to_int(surface_y); |
145 | } | 145 | } |
146 | 146 | ||
147 | static bool check_bindings(struct swaybar *bar, uint32_t x11_button, | ||
148 | uint32_t state) { | ||
149 | bool released = state == WL_POINTER_BUTTON_STATE_RELEASED; | ||
150 | for (int i = 0; i < bar->config->bindings->length; i++) { | ||
151 | struct swaybar_binding *binding = bar->config->bindings->items[i]; | ||
152 | if (binding->button == x11_button && binding->release == released) { | ||
153 | ipc_execute_binding(bar, binding); | ||
154 | return true; | ||
155 | } | ||
156 | } | ||
157 | return false; | ||
158 | } | ||
159 | |||
147 | static void wl_pointer_button(void *data, struct wl_pointer *wl_pointer, | 160 | static void wl_pointer_button(void *data, struct wl_pointer *wl_pointer, |
148 | uint32_t serial, uint32_t time, uint32_t button, uint32_t state) { | 161 | uint32_t serial, uint32_t time, uint32_t button, uint32_t state) { |
149 | struct swaybar *bar = data; | 162 | struct swaybar *bar = data; |
@@ -152,6 +165,11 @@ static void wl_pointer_button(void *data, struct wl_pointer *wl_pointer, | |||
152 | if (!sway_assert(output, "button with no active output")) { | 165 | if (!sway_assert(output, "button with no active output")) { |
153 | return; | 166 | return; |
154 | } | 167 | } |
168 | |||
169 | if (check_bindings(bar, wl_button_to_x11_button(button), state)) { | ||
170 | return; | ||
171 | } | ||
172 | |||
155 | if (state != WL_POINTER_BUTTON_STATE_PRESSED) { | 173 | if (state != WL_POINTER_BUTTON_STATE_PRESSED) { |
156 | return; | 174 | return; |
157 | } | 175 | } |
@@ -180,6 +198,15 @@ static void wl_pointer_axis(void *data, struct wl_pointer *wl_pointer, | |||
180 | return; | 198 | return; |
181 | } | 199 | } |
182 | 200 | ||
201 | // If there is a button press binding, execute it, skip default behavior, | ||
202 | // and check button release bindings | ||
203 | if (check_bindings(bar, wl_axis_to_x11_button(axis, value), | ||
204 | WL_POINTER_BUTTON_STATE_PRESSED)) { | ||
205 | check_bindings(bar, wl_axis_to_x11_button(axis, value), | ||
206 | WL_POINTER_BUTTON_STATE_RELEASED); | ||
207 | return; | ||
208 | } | ||
209 | |||
183 | struct swaybar_hotspot *hotspot; | 210 | struct swaybar_hotspot *hotspot; |
184 | wl_list_for_each(hotspot, &output->hotspots, link) { | 211 | wl_list_for_each(hotspot, &output->hotspots, link) { |
185 | double x = pointer->x * output->scale; | 212 | double x = pointer->x * output->scale; |
@@ -247,6 +274,10 @@ static void wl_pointer_axis(void *data, struct wl_pointer *wl_pointer, | |||
247 | } | 274 | } |
248 | 275 | ||
249 | ipc_send_workspace_command(bar, new->name); | 276 | ipc_send_workspace_command(bar, new->name); |
277 | |||
278 | // Check button release bindings | ||
279 | check_bindings(bar, wl_axis_to_x11_button(axis, value), | ||
280 | WL_POINTER_BUTTON_STATE_RELEASED); | ||
250 | } | 281 | } |
251 | 282 | ||
252 | static void wl_pointer_frame(void *data, struct wl_pointer *wl_pointer) { | 283 | static void wl_pointer_frame(void *data, struct wl_pointer *wl_pointer) { |
diff --git a/swaybar/config.c b/swaybar/config.c index 4e851cca..09d40c24 100644 --- a/swaybar/config.c +++ b/swaybar/config.c | |||
@@ -3,6 +3,8 @@ | |||
3 | #include <string.h> | 3 | #include <string.h> |
4 | #include "swaybar/config.h" | 4 | #include "swaybar/config.h" |
5 | #include "wlr-layer-shell-unstable-v1-client-protocol.h" | 5 | #include "wlr-layer-shell-unstable-v1-client-protocol.h" |
6 | #include "stringop.h" | ||
7 | #include "list.h" | ||
6 | 8 | ||
7 | uint32_t parse_position(const char *position) { | 9 | uint32_t parse_position(const char *position) { |
8 | uint32_t horiz = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | | 10 | uint32_t horiz = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | |
@@ -34,6 +36,7 @@ struct swaybar_config *init_config(void) { | |||
34 | config->binding_mode_indicator = true; | 36 | config->binding_mode_indicator = true; |
35 | config->wrap_scroll = false; | 37 | config->wrap_scroll = false; |
36 | config->workspace_buttons = true; | 38 | config->workspace_buttons = true; |
39 | config->bindings = create_list(); | ||
37 | wl_list_init(&config->outputs); | 40 | wl_list_init(&config->outputs); |
38 | 41 | ||
39 | /* height */ | 42 | /* height */ |
@@ -69,11 +72,24 @@ struct swaybar_config *init_config(void) { | |||
69 | return config; | 72 | return config; |
70 | } | 73 | } |
71 | 74 | ||
75 | static void free_binding(struct swaybar_binding *binding) { | ||
76 | if (!binding) { | ||
77 | return; | ||
78 | } | ||
79 | free(binding->command); | ||
80 | free(binding); | ||
81 | } | ||
82 | |||
72 | void free_config(struct swaybar_config *config) { | 83 | void free_config(struct swaybar_config *config) { |
73 | free(config->status_command); | 84 | free(config->status_command); |
74 | free(config->font); | 85 | free(config->font); |
75 | free(config->mode); | 86 | free(config->mode); |
76 | free(config->sep_symbol); | 87 | free(config->sep_symbol); |
88 | for (int i = 0; i < config->bindings->length; i++) { | ||
89 | struct swaybar_binding *binding = config->bindings->items[i]; | ||
90 | free_binding(binding); | ||
91 | } | ||
92 | list_free(config->bindings); | ||
77 | struct config_output *coutput, *tmp; | 93 | struct config_output *coutput, *tmp; |
78 | wl_list_for_each_safe(coutput, tmp, &config->outputs, link) { | 94 | wl_list_for_each_safe(coutput, tmp, &config->outputs, link) { |
79 | wl_list_remove(&coutput->link); | 95 | wl_list_remove(&coutput->link); |
diff --git a/swaybar/ipc.c b/swaybar/ipc.c index 7c53a44f..a67814c1 100644 --- a/swaybar/ipc.c +++ b/swaybar/ipc.c | |||
@@ -7,6 +7,7 @@ | |||
7 | #include "swaybar/config.h" | 7 | #include "swaybar/config.h" |
8 | #include "swaybar/ipc.h" | 8 | #include "swaybar/ipc.h" |
9 | #include "ipc-client.h" | 9 | #include "ipc-client.h" |
10 | #include "list.h" | ||
10 | 11 | ||
11 | void ipc_send_workspace_command(struct swaybar *bar, const char *ws) { | 12 | void ipc_send_workspace_command(struct swaybar *bar, const char *ws) { |
12 | const char *fmt = "workspace \"%s\""; | 13 | const char *fmt = "workspace \"%s\""; |
@@ -154,6 +155,7 @@ static bool ipc_parse_config( | |||
154 | json_object *markup, *mode, *hidden_bar, *position, *status_command; | 155 | json_object *markup, *mode, *hidden_bar, *position, *status_command; |
155 | json_object *font, *bar_height, *wrap_scroll, *workspace_buttons, *strip_workspace_numbers; | 156 | json_object *font, *bar_height, *wrap_scroll, *workspace_buttons, *strip_workspace_numbers; |
156 | json_object *binding_mode_indicator, *verbose, *colors, *sep_symbol, *outputs; | 157 | json_object *binding_mode_indicator, *verbose, *colors, *sep_symbol, *outputs; |
158 | json_object *bindings; | ||
157 | json_object_object_get_ex(bar_config, "mode", &mode); | 159 | json_object_object_get_ex(bar_config, "mode", &mode); |
158 | json_object_object_get_ex(bar_config, "hidden_bar", &hidden_bar); | 160 | json_object_object_get_ex(bar_config, "hidden_bar", &hidden_bar); |
159 | json_object_object_get_ex(bar_config, "position", &position); | 161 | json_object_object_get_ex(bar_config, "position", &position); |
@@ -169,6 +171,7 @@ static bool ipc_parse_config( | |||
169 | json_object_object_get_ex(bar_config, "colors", &colors); | 171 | json_object_object_get_ex(bar_config, "colors", &colors); |
170 | json_object_object_get_ex(bar_config, "outputs", &outputs); | 172 | json_object_object_get_ex(bar_config, "outputs", &outputs); |
171 | json_object_object_get_ex(bar_config, "pango_markup", &markup); | 173 | json_object_object_get_ex(bar_config, "pango_markup", &markup); |
174 | json_object_object_get_ex(bar_config, "bindings", &bindings); | ||
172 | if (status_command) { | 175 | if (status_command) { |
173 | free(config->status_command); | 176 | free(config->status_command); |
174 | config->status_command = strdup(json_object_get_string(status_command)); | 177 | config->status_command = strdup(json_object_get_string(status_command)); |
@@ -202,6 +205,21 @@ static bool ipc_parse_config( | |||
202 | if (markup) { | 205 | if (markup) { |
203 | config->pango_markup = json_object_get_boolean(markup); | 206 | config->pango_markup = json_object_get_boolean(markup); |
204 | } | 207 | } |
208 | if (bindings) { | ||
209 | int length = json_object_array_length(bindings); | ||
210 | for (int i = 0; i < length; ++i) { | ||
211 | json_object *bindobj = json_object_array_get_idx(bindings, i); | ||
212 | struct swaybar_binding *binding = | ||
213 | calloc(1, sizeof(struct swaybar_binding)); | ||
214 | binding->button = json_object_get_int( | ||
215 | json_object_object_get(bindobj, "input_code")); | ||
216 | binding->command = strdup(json_object_get_string( | ||
217 | json_object_object_get(bindobj, "command"))); | ||
218 | binding->release = json_object_get_boolean( | ||
219 | json_object_object_get(bindobj, "release")); | ||
220 | list_add(config->bindings, binding); | ||
221 | } | ||
222 | } | ||
205 | 223 | ||
206 | struct config_output *output, *tmp; | 224 | struct config_output *output, *tmp; |
207 | wl_list_for_each_safe(output, tmp, &config->outputs, link) { | 225 | wl_list_for_each_safe(output, tmp, &config->outputs, link) { |
@@ -319,6 +337,14 @@ static void ipc_get_outputs(struct swaybar *bar) { | |||
319 | free(res); | 337 | free(res); |
320 | } | 338 | } |
321 | 339 | ||
340 | void ipc_execute_binding(struct swaybar *bar, struct swaybar_binding *bind) { | ||
341 | wlr_log(WLR_DEBUG, "Executing binding for button %u (release=%d): `%s`", | ||
342 | bind->button, bind->release, bind->command); | ||
343 | uint32_t len = strlen(bind->command); | ||
344 | free(ipc_single_command(bar->ipc_socketfd, | ||
345 | IPC_COMMAND, bind->command, &len)); | ||
346 | } | ||
347 | |||
322 | bool ipc_initialize(struct swaybar *bar, const char *bar_id) { | 348 | bool ipc_initialize(struct swaybar *bar, const char *bar_id) { |
323 | uint32_t len = strlen(bar_id); | 349 | uint32_t len = strlen(bar_id); |
324 | char *res = ipc_single_command(bar->ipc_socketfd, | 350 | char *res = ipc_single_command(bar->ipc_socketfd, |
diff --git a/swaybar/main.c b/swaybar/main.c index d2c579db..db204f4a 100644 --- a/swaybar/main.c +++ b/swaybar/main.c | |||
@@ -62,7 +62,7 @@ int main(int argc, char **argv) { | |||
62 | bar_id = strdup(optarg); | 62 | bar_id = strdup(optarg); |
63 | break; | 63 | break; |
64 | case 'v': | 64 | case 'v': |
65 | fprintf(stdout, "sway version " SWAY_VERSION "\n"); | 65 | fprintf(stdout, "swaybar version " SWAY_VERSION "\n"); |
66 | exit(EXIT_SUCCESS); | 66 | exit(EXIT_SUCCESS); |
67 | break; | 67 | break; |
68 | case 'd': // Debug | 68 | case 'd': // Debug |
diff --git a/swaymsg/main.c b/swaymsg/main.c index 3767daf3..4688737c 100644 --- a/swaymsg/main.c +++ b/swaymsg/main.c | |||
@@ -345,7 +345,7 @@ int main(int argc, char **argv) { | |||
345 | cmdtype = strdup(optarg); | 345 | cmdtype = strdup(optarg); |
346 | break; | 346 | break; |
347 | case 'v': | 347 | case 'v': |
348 | fprintf(stdout, "sway version " SWAY_VERSION "\n"); | 348 | fprintf(stdout, "swaymsg version " SWAY_VERSION "\n"); |
349 | exit(EXIT_SUCCESS); | 349 | exit(EXIT_SUCCESS); |
350 | break; | 350 | break; |
351 | default: | 351 | default: |