aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sway/commands.h1
-rw-r--r--include/sway/config.h10
-rw-r--r--include/sway/input/cursor.h2
-rw-r--r--include/swaybar/config.h10
-rw-r--r--include/swaybar/input.h15
-rw-r--r--sway/commands/bar.c1
-rw-r--r--sway/commands/bar/bind.c22
-rw-r--r--sway/commands/bar/tray_bind.c97
-rw-r--r--sway/commands/bar/tray_bindsym.c55
-rw-r--r--sway/config/bar.c7
-rw-r--r--sway/input/cursor.c16
-rw-r--r--sway/ipc-json.c19
-rw-r--r--sway/meson.build2
-rw-r--r--sway/sway-bar.5.scd20
-rw-r--r--swaybar/config.c20
-rw-r--r--swaybar/i3bar.c25
-rw-r--r--swaybar/input.c25
-rw-r--r--swaybar/ipc.c12
-rw-r--r--swaybar/tray/item.c15
19 files changed, 230 insertions, 144 deletions
diff --git a/include/sway/commands.h b/include/sway/commands.h
index 68487879..7672a3fd 100644
--- a/include/sway/commands.h
+++ b/include/sway/commands.h
@@ -207,6 +207,7 @@ sway_cmd bar_cmd_pango_markup;
207sway_cmd bar_cmd_strip_workspace_numbers; 207sway_cmd bar_cmd_strip_workspace_numbers;
208sway_cmd bar_cmd_strip_workspace_name; 208sway_cmd bar_cmd_strip_workspace_name;
209sway_cmd bar_cmd_swaybar_command; 209sway_cmd bar_cmd_swaybar_command;
210sway_cmd bar_cmd_tray_bindcode;
210sway_cmd bar_cmd_tray_bindsym; 211sway_cmd bar_cmd_tray_bindsym;
211sway_cmd bar_cmd_tray_output; 212sway_cmd bar_cmd_tray_output;
212sway_cmd bar_cmd_tray_padding; 213sway_cmd bar_cmd_tray_padding;
diff --git a/include/sway/config.h b/include/sway/config.h
index 96fe899b..978606a6 100644
--- a/include/sway/config.h
+++ b/include/sway/config.h
@@ -260,7 +260,7 @@ struct bar_config {
260 260
261#if HAVE_TRAY 261#if HAVE_TRAY
262 char *icon_theme; 262 char *icon_theme;
263 const char *tray_bindings[10]; // mouse buttons 0-9 263 struct wl_list tray_bindings; // struct tray_binding::link
264 list_t *tray_outputs; // char * 264 list_t *tray_outputs; // char *
265 int tray_padding; 265 int tray_padding;
266#endif 266#endif
@@ -272,6 +272,14 @@ struct bar_binding {
272 char *command; 272 char *command;
273}; 273};
274 274
275#if HAVE_TRAY
276struct tray_binding {
277 uint32_t button;
278 const char *command;
279 struct wl_list link; // struct tray_binding::link
280};
281#endif
282
275struct border_colors { 283struct border_colors {
276 float border[4]; 284 float border[4];
277 float background[4]; 285 float background[4];
diff --git a/include/sway/input/cursor.h b/include/sway/input/cursor.h
index 77aa0ea1..abd72783 100644
--- a/include/sway/input/cursor.h
+++ b/include/sway/input/cursor.h
@@ -103,4 +103,6 @@ uint32_t get_mouse_bindcode(const char *name, char **error);
103// Considers both bindsym and bindcode 103// Considers both bindsym and bindcode
104uint32_t get_mouse_button(const char *name, char **error); 104uint32_t get_mouse_button(const char *name, char **error);
105 105
106const char *get_mouse_button_name(uint32_t button);
107
106#endif 108#endif
diff --git a/include/swaybar/config.h b/include/swaybar/config.h
index add0a1cf..ec042e51 100644
--- a/include/swaybar/config.h
+++ b/include/swaybar/config.h
@@ -70,13 +70,21 @@ struct swaybar_config {
70 70
71#if HAVE_TRAY 71#if HAVE_TRAY
72 char *icon_theme; 72 char *icon_theme;
73 char *tray_bindings[10]; // mouse buttons 0-9 73 struct wl_list tray_bindings; // struct tray_binding::link
74 bool tray_hidden; 74 bool tray_hidden;
75 list_t *tray_outputs; // char * 75 list_t *tray_outputs; // char *
76 int tray_padding; 76 int tray_padding;
77#endif 77#endif
78}; 78};
79 79
80#if HAVE_TRAY
81struct tray_binding {
82 uint32_t button;
83 char *command;
84 struct wl_list link; // struct tray_binding::link
85};
86#endif
87
80struct swaybar_config *init_config(void); 88struct swaybar_config *init_config(void);
81void free_config(struct swaybar_config *config); 89void free_config(struct swaybar_config *config);
82uint32_t parse_position(const char *position); 90uint32_t parse_position(const char *position);
diff --git a/include/swaybar/input.h b/include/swaybar/input.h
index 4b46b0de..d76cd551 100644
--- a/include/swaybar/input.h
+++ b/include/swaybar/input.h
@@ -22,19 +22,6 @@ struct swaybar_pointer {
22 uint32_t serial; 22 uint32_t serial;
23}; 23};
24 24
25enum x11_button {
26 NONE,
27 LEFT,
28 MIDDLE,
29 RIGHT,
30 SCROLL_UP,
31 SCROLL_DOWN,
32 SCROLL_LEFT,
33 SCROLL_RIGHT,
34 BACK,
35 FORWARD,
36};
37
38enum hotspot_event_handling { 25enum hotspot_event_handling {
39 HOTSPOT_IGNORE, 26 HOTSPOT_IGNORE,
40 HOTSPOT_PROCESS, 27 HOTSPOT_PROCESS,
@@ -54,6 +41,8 @@ extern const struct wl_seat_listener seat_listener;
54 41
55void update_cursor(struct swaybar *bar); 42void update_cursor(struct swaybar *bar);
56 43
44uint32_t event_to_x11_button(uint32_t event);
45
57void free_hotspots(struct wl_list *list); 46void free_hotspots(struct wl_list *list);
58 47
59#endif 48#endif
diff --git a/sway/commands/bar.c b/sway/commands/bar.c
index b19d9574..2cfc538f 100644
--- a/sway/commands/bar.c
+++ b/sway/commands/bar.c
@@ -28,6 +28,7 @@ static struct cmd_handler bar_handlers[] = {
28 { "status_padding", bar_cmd_status_padding }, 28 { "status_padding", bar_cmd_status_padding },
29 { "strip_workspace_name", bar_cmd_strip_workspace_name }, 29 { "strip_workspace_name", bar_cmd_strip_workspace_name },
30 { "strip_workspace_numbers", bar_cmd_strip_workspace_numbers }, 30 { "strip_workspace_numbers", bar_cmd_strip_workspace_numbers },
31 { "tray_bindcode", bar_cmd_tray_bindcode },
31 { "tray_bindsym", bar_cmd_tray_bindsym }, 32 { "tray_bindsym", bar_cmd_tray_bindsym },
32 { "tray_output", bar_cmd_tray_output }, 33 { "tray_output", bar_cmd_tray_output },
33 { "tray_padding", bar_cmd_tray_padding }, 34 { "tray_padding", bar_cmd_tray_padding },
diff --git a/sway/commands/bar/bind.c b/sway/commands/bar/bind.c
index 71adced8..4b0be804 100644
--- a/sway/commands/bar/bind.c
+++ b/sway/commands/bar/bind.c
@@ -46,27 +46,7 @@ static struct cmd_results *bar_cmd_bind(int argc, char **argv, bool code) {
46 free_bar_binding(binding); 46 free_bar_binding(binding);
47 return cmd_results_new(CMD_INVALID, "Unknown button %s", argv[0]); 47 return cmd_results_new(CMD_INVALID, "Unknown button %s", argv[0]);
48 } 48 }
49 49 const char *name = get_mouse_button_name(binding->button);
50 const char *name = libevdev_event_code_get_name(EV_KEY, binding->button);
51 if (!name) {
52 switch (binding->button) {
53 case SWAY_SCROLL_UP:
54 name = "SWAY_SCROLL_UP";
55 break;
56 case SWAY_SCROLL_DOWN:
57 name = "SWAY_SCROLL_DOWN";
58 break;
59 case SWAY_SCROLL_LEFT:
60 name = "SWAY_SCROLL_LEFT";
61 break;
62 case SWAY_SCROLL_RIGHT:
63 name = "SWAY_SCROLL_RIGHT";
64 break;
65 default:
66 // Unreachable
67 break;
68 }
69 }
70 50
71 binding->command = join_args(argv + 1, argc - 1); 51 binding->command = join_args(argv + 1, argc - 1);
72 52
diff --git a/sway/commands/bar/tray_bind.c b/sway/commands/bar/tray_bind.c
new file mode 100644
index 00000000..48a15462
--- /dev/null
+++ b/sway/commands/bar/tray_bind.c
@@ -0,0 +1,97 @@
1#include <strings.h>
2#include "config.h"
3#include "sway/commands.h"
4#include "sway/config.h"
5#include "sway/input/cursor.h"
6#include "log.h"
7
8static struct cmd_results *tray_bind(int argc, char **argv, bool code) {
9#if HAVE_TRAY
10 const char *command = code ? "bar tray_bindcode" : "bar tray_bindsym";
11 struct cmd_results *error = NULL;
12 if ((error = checkarg(argc, command, EXPECTED_EQUAL_TO, 2))) {
13 return error;
14 }
15 if (!config->current_bar) {
16 return cmd_results_new(CMD_FAILURE, "No bar defined.");
17 }
18
19 struct tray_binding *binding = calloc(1, sizeof(struct tray_binding));
20 if (!binding) {
21 return cmd_results_new(CMD_FAILURE, "Unable to allocate tray binding");
22 }
23
24 char *message = NULL;
25 if (code) {
26 binding->button = get_mouse_bindcode(argv[0], &message);
27 } else {
28 binding->button = get_mouse_bindsym(argv[0], &message);
29 }
30 if (message) {
31 free(binding);
32 error = cmd_results_new(CMD_INVALID, message);
33 free(message);
34 return error;
35 } else if (!binding->button) {
36 free(binding);
37 return cmd_results_new(CMD_INVALID, "Unknown button %s", argv[0]);
38 }
39 const char *name = get_mouse_button_name(binding->button);
40
41 static const char *commands[] = {
42 "ContextMenu",
43 "Activate",
44 "SecondaryActivate",
45 "ScrollDown",
46 "ScrollLeft",
47 "ScrollRight",
48 "ScrollUp",
49 "nop"
50 };
51
52 for (size_t i = 0; i < sizeof(commands) / sizeof(commands[0]); ++i) {
53 if (strcasecmp(argv[1], commands[i]) == 0) {
54 binding->command = commands[i];
55 }
56 }
57 if (!binding->command) {
58 return cmd_results_new(CMD_INVALID, "[Bar %s] Invalid tray command %s",
59 config->current_bar->id, argv[1]);
60 }
61
62 bool overwritten = false;
63 struct tray_binding *other = NULL;
64 wl_list_for_each(other, &config->current_bar->tray_bindings, link) {
65 if (other->button == binding->button) {
66 overwritten = true;
67 other->command = binding->command;
68 free(binding);
69 binding = other;
70 wlr_log(WLR_DEBUG,
71 "[bar %s] Updated tray binding for %u (%s) to %s",
72 config->current_bar->id, binding->button, name,
73 binding->command);
74 break;
75 }
76 }
77 if (!overwritten) {
78 wl_list_insert(&config->current_bar->tray_bindings, &binding->link);
79 wlr_log(WLR_DEBUG, "[bar %s] Added tray binding for %u (%s) to %s",
80 config->current_bar->id, binding->button, name,
81 binding->command);
82 }
83
84 return cmd_results_new(CMD_SUCCESS, NULL);
85#else
86 return cmd_results_new(CMD_INVALID,
87 "Sway has been compiled without tray support");
88#endif
89}
90
91struct cmd_results *bar_cmd_tray_bindcode(int argc, char **argv) {
92 return tray_bind(argc, argv, true);
93}
94
95struct cmd_results *bar_cmd_tray_bindsym(int argc, char **argv) {
96 return tray_bind(argc, argv, false);
97}
diff --git a/sway/commands/bar/tray_bindsym.c b/sway/commands/bar/tray_bindsym.c
deleted file mode 100644
index 4e57e35e..00000000
--- a/sway/commands/bar/tray_bindsym.c
+++ /dev/null
@@ -1,55 +0,0 @@
1#include <strings.h>
2#include "config.h"
3#include "sway/commands.h"
4#include "sway/config.h"
5#include "log.h"
6
7struct cmd_results *bar_cmd_tray_bindsym(int argc, char **argv) {
8#if HAVE_TRAY
9 struct cmd_results *error = NULL;
10 if ((error = checkarg(argc, "tray_bindsym", EXPECTED_EQUAL_TO, 2))) {
11 return error;
12 }
13
14 if (!config->current_bar) {
15 return cmd_results_new(CMD_FAILURE, "No bar defined.");
16 }
17
18 int button = 0;
19 if (strncasecmp(argv[0], "button", strlen("button")) == 0 &&
20 strlen(argv[0]) == strlen("button0")) {
21 button = argv[0][strlen("button")] - '0';
22 }
23 if (button < 1 || button > 9) {
24 return cmd_results_new(CMD_FAILURE,
25 "[Bar %s] Only buttons 1 to 9 are supported",
26 config->current_bar->id);
27 }
28
29 static const char *commands[] = {
30 "ContextMenu",
31 "Activate",
32 "SecondaryActivate",
33 "ScrollDown",
34 "ScrollLeft",
35 "ScrollRight",
36 "ScrollUp",
37 "nop"
38 };
39
40 for (size_t i = 0; i < sizeof(commands) / sizeof(commands[0]); ++i) {
41 if (strcasecmp(argv[1], commands[i]) == 0) {
42 wlr_log(WLR_DEBUG, "[Bar %s] Binding button %d to %s",
43 config->current_bar->id, button, commands[i]);
44 config->current_bar->tray_bindings[button] = commands[i];
45 return cmd_results_new(CMD_SUCCESS, NULL);
46 }
47 }
48
49 return cmd_results_new(CMD_INVALID,
50 "[Bar %s] Invalid command %s", config->current_bar->id, argv[1]);
51#else
52 return cmd_results_new(CMD_INVALID,
53 "Sway has been compiled without tray support");
54#endif
55}
diff --git a/sway/config/bar.c b/sway/config/bar.c
index 701bf051..b1aa2313 100644
--- a/sway/config/bar.c
+++ b/sway/config/bar.c
@@ -81,6 +81,12 @@ void free_bar_config(struct bar_config *bar) {
81#if HAVE_TRAY 81#if HAVE_TRAY
82 list_free_items_and_destroy(bar->tray_outputs); 82 list_free_items_and_destroy(bar->tray_outputs);
83 free(bar->icon_theme); 83 free(bar->icon_theme);
84
85 struct tray_binding *tray_bind = NULL, *tmp_tray_bind = NULL;
86 wl_list_for_each_safe(tray_bind, tmp_tray_bind, &bar->tray_bindings, link) {
87 wl_list_remove(&tray_bind->link);
88 free(tray_bind);
89 }
84#endif 90#endif
85 free(bar); 91 free(bar);
86} 92}
@@ -174,6 +180,7 @@ struct bar_config *default_bar_config(void) {
174 180
175#if HAVE_TRAY 181#if HAVE_TRAY
176 bar->tray_padding = 2; 182 bar->tray_padding = 2;
183 wl_list_init(&bar->tray_bindings);
177#endif 184#endif
178 185
179 list_add(config->bars, bar); 186 list_add(config->bars, bar);
diff --git a/sway/input/cursor.c b/sway/input/cursor.c
index 731e82ad..5eb44412 100644
--- a/sway/input/cursor.c
+++ b/sway/input/cursor.c
@@ -1237,3 +1237,19 @@ uint32_t get_mouse_button(const char *name, char **error) {
1237 } 1237 }
1238 return button; 1238 return button;
1239} 1239}
1240
1241const char *get_mouse_button_name(uint32_t button) {
1242 const char *name = libevdev_event_code_get_name(EV_KEY, button);
1243 if (!name) {
1244 if (button == SWAY_SCROLL_UP) {
1245 name = "SWAY_SCROLL_UP";
1246 } else if (button == SWAY_SCROLL_DOWN) {
1247 name = "SWAY_SCROLL_DOWN";
1248 } else if (button == SWAY_SCROLL_LEFT) {
1249 name = "SWAY_SCROLL_LEFT";
1250 } else if (button == SWAY_SCROLL_RIGHT) {
1251 name = "SWAY_SCROLL_RIGHT";
1252 }
1253 }
1254 return name;
1255}
diff --git a/sway/ipc-json.c b/sway/ipc-json.c
index 6e5ba4fd..d72fc5db 100644
--- a/sway/ipc-json.c
+++ b/sway/ipc-json.c
@@ -852,15 +852,16 @@ json_object *ipc_json_describe_bar_config(struct bar_config *bar) {
852 } 852 }
853 853
854 json_object *tray_bindings = json_object_new_array(); 854 json_object *tray_bindings = json_object_new_array();
855 for (int i = 0; i < 10; ++i) { 855 struct tray_binding *tray_bind = NULL;
856 if (bar->tray_bindings[i]) { 856 wl_list_for_each(tray_bind, &bar->tray_bindings, link) {
857 json_object *bind = json_object_new_object(); 857 json_object *bind = json_object_new_object();
858 json_object_object_add(bind, "input_code", 858 json_object_object_add(bind, "input_code",
859 json_object_new_int(i)); 859 json_object_new_int(event_to_x11_button(tray_bind->button)));
860 json_object_object_add(bind, "command", 860 json_object_object_add(bind, "event_code",
861 json_object_new_string(bar->tray_bindings[i])); 861 json_object_new_int(tray_bind->button));
862 json_object_array_add(tray_bindings, bind); 862 json_object_object_add(bind, "command",
863 } 863 json_object_new_string(tray_bind->command));
864 json_object_array_add(tray_bindings, bind);
864 } 865 }
865 if (json_object_array_length(tray_bindings) > 0) { 866 if (json_object_array_length(tray_bindings) > 0) {
866 json_object_object_add(json, "tray_bindings", tray_bindings); 867 json_object_object_add(json, "tray_bindings", tray_bindings);
diff --git a/sway/meson.build b/sway/meson.build
index c2ed6298..0a08ee74 100644
--- a/sway/meson.build
+++ b/sway/meson.build
@@ -127,7 +127,7 @@ sway_sources = files(
127 'commands/bar/strip_workspace_numbers.c', 127 'commands/bar/strip_workspace_numbers.c',
128 'commands/bar/strip_workspace_name.c', 128 'commands/bar/strip_workspace_name.c',
129 'commands/bar/swaybar_command.c', 129 'commands/bar/swaybar_command.c',
130 'commands/bar/tray_bindsym.c', 130 'commands/bar/tray_bind.c',
131 'commands/bar/tray_output.c', 131 'commands/bar/tray_output.c',
132 'commands/bar/tray_padding.c', 132 'commands/bar/tray_padding.c',
133 'commands/bar/workspace_buttons.c', 133 'commands/bar/workspace_buttons.c',
diff --git a/sway/sway-bar.5.scd b/sway/sway-bar.5.scd
index 3f6b4298..9a6397e3 100644
--- a/sway/sway-bar.5.scd
+++ b/sway/sway-bar.5.scd
@@ -115,13 +115,19 @@ Sway allows configuring swaybar in the sway configuration file.
115Swaybar provides a system tray where third-party applications may place icons. 115Swaybar provides a system tray where third-party applications may place icons.
116The following commands configure the tray. 116The following commands configure the tray.
117 117
118The _button_ argument in all cases is a platform-specific button code. On Linux 118*tray\_bindcode* <event-code>
119you can find a list of these at linux/input-event-codes.h. 119ContextMenu|Activate|SecondaryActivate|ScrollDown|ScrollLeft|ScrollRight|ScrollUp|nop
120 120 Executes the action when the mouse button has been pressed. The buttons can
121*tray\_bindsym* button<n> ContextMenu|Activate|SecondaryActivate|ScrollDown|ScrollLeft|ScrollRight|ScrollUp|nop 121 be given as an event code, which can be obtained from `libinput debug-events`.
122 Binds mouse button _n_ (1 to 9) to the specified action. Use the command 122 To disable the default behavior for a button, use the command _nop_.
123 _nop_ to disable the default action (Activate for button 1, ContextMenu for 123
124 button 2 and SecondaryActivate for button 3). 124*tray\_bindsym* button[1-9]|<event-name>
125ContextMenu|Activate|SecondaryActivate|ScrollDown|ScrollLeft|ScrollRight|ScrollUp|nop
126 Executes the action when the mouse button has been pressed. The buttons can
127 be given as a x11 button number or an event name, which can be obtained
128 from `libinput debug-events`. Use the command _nop_ to disable the default
129 action (Activate for button1, ContextMenu for button2 and SecondaryActivate
130 for button3).
125 131
126*tray\_padding* <px> [px] 132*tray\_padding* <px> [px]
127 Sets the pixel padding of the system tray. This padding will surround the 133 Sets the pixel padding of the system tray. This padding will surround the
diff --git a/swaybar/config.c b/swaybar/config.c
index d4cc9b1a..0071c7f9 100644
--- a/swaybar/config.c
+++ b/swaybar/config.c
@@ -78,6 +78,7 @@ struct swaybar_config *init_config(void) {
78 78
79#if HAVE_TRAY 79#if HAVE_TRAY
80 config->tray_padding = 2; 80 config->tray_padding = 2;
81 wl_list_init(&config->tray_bindings);
81#endif 82#endif
82 83
83 return config; 84 return config;
@@ -91,6 +92,16 @@ static void free_binding(struct swaybar_binding *binding) {
91 free(binding); 92 free(binding);
92} 93}
93 94
95#if HAVE_TRAY
96static void free_tray_binding(struct tray_binding *binding) {
97 if (!binding) {
98 return;
99 }
100 free(binding->command);
101 free(binding);
102}
103#endif
104
94void free_config(struct swaybar_config *config) { 105void free_config(struct swaybar_config *config) {
95 free(config->status_command); 106 free(config->status_command);
96 free(config->font); 107 free(config->font);
@@ -111,9 +122,14 @@ void free_config(struct swaybar_config *config) {
111 } 122 }
112#if HAVE_TRAY 123#if HAVE_TRAY
113 list_free_items_and_destroy(config->tray_outputs); 124 list_free_items_and_destroy(config->tray_outputs);
114 for (int i = 0; i < 10; ++i) { 125
115 free(config->tray_bindings[i]); 126 struct tray_binding *tray_bind = NULL, *tmp_tray_bind = NULL;
127 wl_list_for_each_safe(tray_bind, tmp_tray_bind, &config->tray_bindings,
128 link) {
129 wl_list_remove(&tray_bind->link);
130 free_tray_binding(tray_bind);
116 } 131 }
132
117 free(config->icon_theme); 133 free(config->icon_theme);
118#endif 134#endif
119 free(config); 135 free(config);
diff --git a/swaybar/i3bar.c b/swaybar/i3bar.c
index 116c8f6e..8bca1bf9 100644
--- a/swaybar/i3bar.c
+++ b/swaybar/i3bar.c
@@ -259,31 +259,6 @@ bool i3bar_handle_readable(struct status_line *status) {
259 } 259 }
260} 260}
261 261
262static uint32_t event_to_x11_button(uint32_t event) {
263 switch (event) {
264 case BTN_LEFT:
265 return 1;
266 case BTN_MIDDLE:
267 return 2;
268 case BTN_RIGHT:
269 return 3;
270 case SWAY_SCROLL_UP:
271 return 4;
272 case SWAY_SCROLL_DOWN:
273 return 5;
274 case SWAY_SCROLL_LEFT:
275 return 6;
276 case SWAY_SCROLL_RIGHT:
277 return 7;
278 case BTN_SIDE:
279 return 8;
280 case BTN_EXTRA:
281 return 9;
282 default:
283 return 0;
284 }
285}
286
287enum hotspot_event_handling i3bar_block_send_click(struct status_line *status, 262enum hotspot_event_handling i3bar_block_send_click(struct status_line *status,
288 struct i3bar_block *block, int x, int y, int rx, int ry, int w, int h, 263 struct i3bar_block *block, int x, int y, int rx, int ry, int w, int h,
289 uint32_t button) { 264 uint32_t button) {
diff --git a/swaybar/input.c b/swaybar/input.c
index bdd55e58..998b186f 100644
--- a/swaybar/input.c
+++ b/swaybar/input.c
@@ -22,6 +22,31 @@ void free_hotspots(struct wl_list *list) {
22 } 22 }
23} 23}
24 24
25uint32_t event_to_x11_button(uint32_t event) {
26 switch (event) {
27 case BTN_LEFT:
28 return 1;
29 case BTN_MIDDLE:
30 return 2;
31 case BTN_RIGHT:
32 return 3;
33 case SWAY_SCROLL_UP:
34 return 4;
35 case SWAY_SCROLL_DOWN:
36 return 5;
37 case SWAY_SCROLL_LEFT:
38 return 6;
39 case SWAY_SCROLL_RIGHT:
40 return 7;
41 case BTN_SIDE:
42 return 8;
43 case BTN_EXTRA:
44 return 9;
45 default:
46 return 0;
47 }
48}
49
25static uint32_t wl_axis_to_button(uint32_t axis, wl_fixed_t value) { 50static uint32_t wl_axis_to_button(uint32_t axis, wl_fixed_t value) {
26 bool negative = wl_fixed_to_double(value) < 0; 51 bool negative = wl_fixed_to_double(value) < 0;
27 switch (axis) { 52 switch (axis) {
diff --git a/swaybar/ipc.c b/swaybar/ipc.c
index 097f9161..0dc39439 100644
--- a/swaybar/ipc.c
+++ b/swaybar/ipc.c
@@ -313,11 +313,13 @@ static bool ipc_parse_config(
313 int length = json_object_array_length(tray_bindings); 313 int length = json_object_array_length(tray_bindings);
314 for (int i = 0; i < length; ++i) { 314 for (int i = 0; i < length; ++i) {
315 json_object *bind = json_object_array_get_idx(tray_bindings, i); 315 json_object *bind = json_object_array_get_idx(tray_bindings, i);
316 json_object *button, *command; 316 struct tray_binding *binding =
317 json_object_object_get_ex(bind, "input_code", &button); 317 calloc(1, sizeof(struct tray_binding));
318 json_object_object_get_ex(bind, "command", &command); 318 binding->button = json_object_get_int(
319 config->tray_bindings[json_object_get_int(button)] = 319 json_object_object_get(bind, "event_code"));
320 strdup(json_object_get_string(command)); 320 binding->command = strdup(json_object_get_string(
321 json_object_object_get(bind, "command")));
322 wl_list_insert(&config->tray_bindings, &binding->link);
321 } 323 }
322 } 324 }
323 325
diff --git a/swaybar/tray/item.c b/swaybar/tray/item.c
index 0833dcb9..9056331e 100644
--- a/swaybar/tray/item.c
+++ b/swaybar/tray/item.c
@@ -301,8 +301,15 @@ void destroy_sni(struct swaybar_sni *sni) {
301} 301}
302 302
303static void handle_click(struct swaybar_sni *sni, int x, int y, 303static void handle_click(struct swaybar_sni *sni, int x, int y,
304 enum x11_button button, int delta) { 304 uint32_t button, int delta) {
305 const char *method = sni->tray->bar->config->tray_bindings[button]; 305 const char *method = NULL;
306 struct tray_binding *binding = NULL;
307 wl_list_for_each(binding, &sni->tray->bar->config->tray_bindings, link) {
308 if (binding->button == button) {
309 method = binding->command;
310 break;
311 }
312 }
306 if (!method) { 313 if (!method) {
307 static const char *default_bindings[10] = { 314 static const char *default_bindings[10] = {
308 "nop", 315 "nop",
@@ -316,7 +323,7 @@ static void handle_click(struct swaybar_sni *sni, int x, int y,
316 "nop", 323 "nop",
317 "nop" 324 "nop"
318 }; 325 };
319 method = default_bindings[button]; 326 method = default_bindings[event_to_x11_button(button)];
320 } 327 }
321 if (strcmp(method, "nop") == 0) { 328 if (strcmp(method, "nop") == 0) {
322 return; 329 return;
@@ -345,7 +352,7 @@ static int cmp_sni_id(const void *item, const void *cmp_to) {
345 352
346static enum hotspot_event_handling icon_hotspot_callback( 353static enum hotspot_event_handling icon_hotspot_callback(
347 struct swaybar_output *output, struct swaybar_hotspot *hotspot, 354 struct swaybar_output *output, struct swaybar_hotspot *hotspot,
348 int x, int y, enum x11_button button, void *data) { 355 int x, int y, uint32_t button, void *data) {
349 wlr_log(WLR_DEBUG, "Clicked on %s", (char *)data); 356 wlr_log(WLR_DEBUG, "Clicked on %s", (char *)data);
350 357
351 struct swaybar_tray *tray = output->bar->tray; 358 struct swaybar_tray *tray = output->bar->tray;