aboutsummaryrefslogtreecommitdiff
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;
sway_cmd bar_cmd_strip_workspace_numbers;
sway_cmd bar_cmd_strip_workspace_name;
sway_cmd bar_cmd_swaybar_command;
+sway_cmd bar_cmd_tray_bindcode;
sway_cmd bar_cmd_tray_bindsym;
sway_cmd bar_cmd_tray_output;
sway_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 {
#if HAVE_TRAY
char *icon_theme;
- const char *tray_bindings[10]; // mouse buttons 0-9
+ struct wl_list tray_bindings; // struct tray_binding::link
list_t *tray_outputs; // char *
int tray_padding;
#endif
@@ -272,6 +272,14 @@ struct bar_binding {
char *command;
};
+#if HAVE_TRAY
+struct tray_binding {
+ uint32_t button;
+ const char *command;
+ struct wl_list link; // struct tray_binding::link
+};
+#endif
+
struct border_colors {
float border[4];
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);
// Considers both bindsym and bindcode
uint32_t get_mouse_button(const char *name, char **error);
+const char *get_mouse_button_name(uint32_t button);
+
#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 {
#if HAVE_TRAY
char *icon_theme;
- char *tray_bindings[10]; // mouse buttons 0-9
+ struct wl_list tray_bindings; // struct tray_binding::link
bool tray_hidden;
list_t *tray_outputs; // char *
int tray_padding;
#endif
};
+#if HAVE_TRAY
+struct tray_binding {
+ uint32_t button;
+ char *command;
+ struct wl_list link; // struct tray_binding::link
+};
+#endif
+
struct swaybar_config *init_config(void);
void free_config(struct swaybar_config *config);
uint32_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 {
uint32_t serial;
};
-enum x11_button {
- NONE,
- LEFT,
- MIDDLE,
- RIGHT,
- SCROLL_UP,
- SCROLL_DOWN,
- SCROLL_LEFT,
- SCROLL_RIGHT,
- BACK,
- FORWARD,
-};
-
enum hotspot_event_handling {
HOTSPOT_IGNORE,
HOTSPOT_PROCESS,
@@ -54,6 +41,8 @@ extern const struct wl_seat_listener seat_listener;
void update_cursor(struct swaybar *bar);
+uint32_t event_to_x11_button(uint32_t event);
+
void free_hotspots(struct wl_list *list);
#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[] = {
{ "status_padding", bar_cmd_status_padding },
{ "strip_workspace_name", bar_cmd_strip_workspace_name },
{ "strip_workspace_numbers", bar_cmd_strip_workspace_numbers },
+ { "tray_bindcode", bar_cmd_tray_bindcode },
{ "tray_bindsym", bar_cmd_tray_bindsym },
{ "tray_output", bar_cmd_tray_output },
{ "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) {
free_bar_binding(binding);
return cmd_results_new(CMD_INVALID, "Unknown button %s", argv[0]);
}
-
- const char *name = libevdev_event_code_get_name(EV_KEY, binding->button);
- if (!name) {
- switch (binding->button) {
- case SWAY_SCROLL_UP:
- name = "SWAY_SCROLL_UP";
- break;
- case SWAY_SCROLL_DOWN:
- name = "SWAY_SCROLL_DOWN";
- break;
- case SWAY_SCROLL_LEFT:
- name = "SWAY_SCROLL_LEFT";
- break;
- case SWAY_SCROLL_RIGHT:
- name = "SWAY_SCROLL_RIGHT";
- break;
- default:
- // Unreachable
- break;
- }
- }
+ const char *name = get_mouse_button_name(binding->button);
binding->command = join_args(argv + 1, argc - 1);
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 @@
+#include <strings.h>
+#include "config.h"
+#include "sway/commands.h"
+#include "sway/config.h"
+#include "sway/input/cursor.h"
+#include "log.h"
+
+static struct cmd_results *tray_bind(int argc, char **argv, bool code) {
+#if HAVE_TRAY
+ const char *command = code ? "bar tray_bindcode" : "bar tray_bindsym";
+ struct cmd_results *error = NULL;
+ if ((error = checkarg(argc, command, EXPECTED_EQUAL_TO, 2))) {
+ return error;
+ }
+ if (!config->current_bar) {
+ return cmd_results_new(CMD_FAILURE, "No bar defined.");
+ }
+
+ struct tray_binding *binding = calloc(1, sizeof(struct tray_binding));
+ if (!binding) {
+ return cmd_results_new(CMD_FAILURE, "Unable to allocate tray binding");
+ }
+
+ char *message = NULL;
+ if (code) {
+ binding->button = get_mouse_bindcode(argv[0], &message);
+ } else {
+ binding->button = get_mouse_bindsym(argv[0], &message);
+ }
+ if (message) {
+ free(binding);
+ error = cmd_results_new(CMD_INVALID, message);
+ free(message);
+ return error;
+ } else if (!binding->button) {
+ free(binding);
+ return cmd_results_new(CMD_INVALID, "Unknown button %s", argv[0]);
+ }
+ const char *name = get_mouse_button_name(binding->button);
+
+ static const char *commands[] = {
+ "ContextMenu",
+ "Activate",
+ "SecondaryActivate",
+ "ScrollDown",
+ "ScrollLeft",
+ "ScrollRight",
+ "ScrollUp",
+ "nop"
+ };
+
+ for (size_t i = 0; i < sizeof(commands) / sizeof(commands[0]); ++i) {
+ if (strcasecmp(argv[1], commands[i]) == 0) {
+ binding->command = commands[i];
+ }
+ }
+ if (!binding->command) {
+ return cmd_results_new(CMD_INVALID, "[Bar %s] Invalid tray command %s",
+ config->current_bar->id, argv[1]);
+ }
+
+ bool overwritten = false;
+ struct tray_binding *other = NULL;
+ wl_list_for_each(other, &config->current_bar->tray_bindings, link) {
+ if (other->button == binding->button) {
+ overwritten = true;
+ other->command = binding->command;
+ free(binding);
+ binding = other;
+ wlr_log(WLR_DEBUG,
+ "[bar %s] Updated tray binding for %u (%s) to %s",
+ config->current_bar->id, binding->button, name,
+ binding->command);
+ break;
+ }
+ }
+ if (!overwritten) {
+ wl_list_insert(&config->current_bar->tray_bindings, &binding->link);
+ wlr_log(WLR_DEBUG, "[bar %s] Added tray binding for %u (%s) to %s",
+ config->current_bar->id, binding->button, name,
+ binding->command);
+ }
+
+ return cmd_results_new(CMD_SUCCESS, NULL);
+#else
+ return cmd_results_new(CMD_INVALID,
+ "Sway has been compiled without tray support");
+#endif
+}
+
+struct cmd_results *bar_cmd_tray_bindcode(int argc, char **argv) {
+ return tray_bind(argc, argv, true);
+}
+
+struct cmd_results *bar_cmd_tray_bindsym(int argc, char **argv) {
+ return tray_bind(argc, argv, false);
+}
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 @@
-#include <strings.h>
-#include "config.h"
-#include "sway/commands.h"
-#include "sway/config.h"
-#include "log.h"
-
-struct cmd_results *bar_cmd_tray_bindsym(int argc, char **argv) {
-#if HAVE_TRAY
- struct cmd_results *error = NULL;
- if ((error = checkarg(argc, "tray_bindsym", EXPECTED_EQUAL_TO, 2))) {
- return error;
- }
-
- if (!config->current_bar) {
- return cmd_results_new(CMD_FAILURE, "No bar defined.");
- }
-
- int button = 0;
- if (strncasecmp(argv[0], "button", strlen("button")) == 0 &&
- strlen(argv[0]) == strlen("button0")) {
- button = argv[0][strlen("button")] - '0';
- }
- if (button < 1 || button > 9) {
- return cmd_results_new(CMD_FAILURE,
- "[Bar %s] Only buttons 1 to 9 are supported",
- config->current_bar->id);
- }
-
- static const char *commands[] = {
- "ContextMenu",
- "Activate",
- "SecondaryActivate",
- "ScrollDown",
- "ScrollLeft",
- "ScrollRight",
- "ScrollUp",
- "nop"
- };
-
- for (size_t i = 0; i < sizeof(commands) / sizeof(commands[0]); ++i) {
- if (strcasecmp(argv[1], commands[i]) == 0) {
- wlr_log(WLR_DEBUG, "[Bar %s] Binding button %d to %s",
- config->current_bar->id, button, commands[i]);
- config->current_bar->tray_bindings[button] = commands[i];
- return cmd_results_new(CMD_SUCCESS, NULL);
- }
- }
-
- return cmd_results_new(CMD_INVALID,
- "[Bar %s] Invalid command %s", config->current_bar->id, argv[1]);
-#else
- return cmd_results_new(CMD_INVALID,
- "Sway has been compiled without tray support");
-#endif
-}
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) {
#if HAVE_TRAY
list_free_items_and_destroy(bar->tray_outputs);
free(bar->icon_theme);
+
+ struct tray_binding *tray_bind = NULL, *tmp_tray_bind = NULL;
+ wl_list_for_each_safe(tray_bind, tmp_tray_bind, &bar->tray_bindings, link) {
+ wl_list_remove(&tray_bind->link);
+ free(tray_bind);
+ }
#endif
free(bar);
}
@@ -174,6 +180,7 @@ struct bar_config *default_bar_config(void) {
#if HAVE_TRAY
bar->tray_padding = 2;
+ wl_list_init(&bar->tray_bindings);
#endif
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) {
}
return button;
}
+
+const char *get_mouse_button_name(uint32_t button) {
+ const char *name = libevdev_event_code_get_name(EV_KEY, button);
+ if (!name) {
+ if (button == SWAY_SCROLL_UP) {
+ name = "SWAY_SCROLL_UP";
+ } else if (button == SWAY_SCROLL_DOWN) {
+ name = "SWAY_SCROLL_DOWN";
+ } else if (button == SWAY_SCROLL_LEFT) {
+ name = "SWAY_SCROLL_LEFT";
+ } else if (button == SWAY_SCROLL_RIGHT) {
+ name = "SWAY_SCROLL_RIGHT";
+ }
+ }
+ return name;
+}
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) {
}
json_object *tray_bindings = json_object_new_array();
- for (int i = 0; i < 10; ++i) {
- if (bar->tray_bindings[i]) {
- json_object *bind = json_object_new_object();
- json_object_object_add(bind, "input_code",
- json_object_new_int(i));
- json_object_object_add(bind, "command",
- json_object_new_string(bar->tray_bindings[i]));
- json_object_array_add(tray_bindings, bind);
- }
+ struct tray_binding *tray_bind = NULL;
+ wl_list_for_each(tray_bind, &bar->tray_bindings, link) {
+ json_object *bind = json_object_new_object();
+ json_object_object_add(bind, "input_code",
+ json_object_new_int(event_to_x11_button(tray_bind->button)));
+ json_object_object_add(bind, "event_code",
+ json_object_new_int(tray_bind->button));
+ json_object_object_add(bind, "command",
+ json_object_new_string(tray_bind->command));
+ json_object_array_add(tray_bindings, bind);
}
if (json_object_array_length(tray_bindings) > 0) {
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(
'commands/bar/strip_workspace_numbers.c',
'commands/bar/strip_workspace_name.c',
'commands/bar/swaybar_command.c',
- 'commands/bar/tray_bindsym.c',
+ 'commands/bar/tray_bind.c',
'commands/bar/tray_output.c',
'commands/bar/tray_padding.c',
'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.
Swaybar provides a system tray where third-party applications may place icons.
The following commands configure the tray.
-The _button_ argument in all cases is a platform-specific button code. On Linux
-you can find a list of these at linux/input-event-codes.h.
-
-*tray\_bindsym* button<n> ContextMenu|Activate|SecondaryActivate|ScrollDown|ScrollLeft|ScrollRight|ScrollUp|nop
- Binds mouse button _n_ (1 to 9) to the specified action. Use the command
- _nop_ to disable the default action (Activate for button 1, ContextMenu for
- button 2 and SecondaryActivate for button 3).
+*tray\_bindcode* <event-code>
+ContextMenu|Activate|SecondaryActivate|ScrollDown|ScrollLeft|ScrollRight|ScrollUp|nop
+ Executes the action when the mouse button has been pressed. The buttons can
+ be given as an event code, which can be obtained from `libinput debug-events`.
+ To disable the default behavior for a button, use the command _nop_.
+
+*tray\_bindsym* button[1-9]|<event-name>
+ContextMenu|Activate|SecondaryActivate|ScrollDown|ScrollLeft|ScrollRight|ScrollUp|nop
+ Executes the action when the mouse button has been pressed. The buttons can
+ be given as a x11 button number or an event name, which can be obtained
+ from `libinput debug-events`. Use the command _nop_ to disable the default
+ action (Activate for button1, ContextMenu for button2 and SecondaryActivate
+ for button3).
*tray\_padding* <px> [px]
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) {
#if HAVE_TRAY
config->tray_padding = 2;
+ wl_list_init(&config->tray_bindings);
#endif
return config;
@@ -91,6 +92,16 @@ static void free_binding(struct swaybar_binding *binding) {
free(binding);
}
+#if HAVE_TRAY
+static void free_tray_binding(struct tray_binding *binding) {
+ if (!binding) {
+ return;
+ }
+ free(binding->command);
+ free(binding);
+}
+#endif
+
void free_config(struct swaybar_config *config) {
free(config->status_command);
free(config->font);
@@ -111,9 +122,14 @@ void free_config(struct swaybar_config *config) {
}
#if HAVE_TRAY
list_free_items_and_destroy(config->tray_outputs);
- for (int i = 0; i < 10; ++i) {
- free(config->tray_bindings[i]);
+
+ struct tray_binding *tray_bind = NULL, *tmp_tray_bind = NULL;
+ wl_list_for_each_safe(tray_bind, tmp_tray_bind, &config->tray_bindings,
+ link) {
+ wl_list_remove(&tray_bind->link);
+ free_tray_binding(tray_bind);
}
+
free(config->icon_theme);
#endif
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) {
}
}
-static uint32_t event_to_x11_button(uint32_t event) {
- switch (event) {
- case BTN_LEFT:
- return 1;
- case BTN_MIDDLE:
- return 2;
- case BTN_RIGHT:
- return 3;
- case SWAY_SCROLL_UP:
- return 4;
- case SWAY_SCROLL_DOWN:
- return 5;
- case SWAY_SCROLL_LEFT:
- return 6;
- case SWAY_SCROLL_RIGHT:
- return 7;
- case BTN_SIDE:
- return 8;
- case BTN_EXTRA:
- return 9;
- default:
- return 0;
- }
-}
-
enum hotspot_event_handling i3bar_block_send_click(struct status_line *status,
struct i3bar_block *block, int x, int y, int rx, int ry, int w, int h,
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) {
}
}
+uint32_t event_to_x11_button(uint32_t event) {
+ switch (event) {
+ case BTN_LEFT:
+ return 1;
+ case BTN_MIDDLE:
+ return 2;
+ case BTN_RIGHT:
+ return 3;
+ case SWAY_SCROLL_UP:
+ return 4;
+ case SWAY_SCROLL_DOWN:
+ return 5;
+ case SWAY_SCROLL_LEFT:
+ return 6;
+ case SWAY_SCROLL_RIGHT:
+ return 7;
+ case BTN_SIDE:
+ return 8;
+ case BTN_EXTRA:
+ return 9;
+ default:
+ return 0;
+ }
+}
+
static uint32_t wl_axis_to_button(uint32_t axis, wl_fixed_t value) {
bool negative = wl_fixed_to_double(value) < 0;
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(
int length = json_object_array_length(tray_bindings);
for (int i = 0; i < length; ++i) {
json_object *bind = json_object_array_get_idx(tray_bindings, i);
- json_object *button, *command;
- json_object_object_get_ex(bind, "input_code", &button);
- json_object_object_get_ex(bind, "command", &command);
- config->tray_bindings[json_object_get_int(button)] =
- strdup(json_object_get_string(command));
+ struct tray_binding *binding =
+ calloc(1, sizeof(struct tray_binding));
+ binding->button = json_object_get_int(
+ json_object_object_get(bind, "event_code"));
+ binding->command = strdup(json_object_get_string(
+ json_object_object_get(bind, "command")));
+ wl_list_insert(&config->tray_bindings, &binding->link);
}
}
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) {
}
static void handle_click(struct swaybar_sni *sni, int x, int y,
- enum x11_button button, int delta) {
- const char *method = sni->tray->bar->config->tray_bindings[button];
+ uint32_t button, int delta) {
+ const char *method = NULL;
+ struct tray_binding *binding = NULL;
+ wl_list_for_each(binding, &sni->tray->bar->config->tray_bindings, link) {
+ if (binding->button == button) {
+ method = binding->command;
+ break;
+ }
+ }
if (!method) {
static const char *default_bindings[10] = {
"nop",
@@ -316,7 +323,7 @@ static void handle_click(struct swaybar_sni *sni, int x, int y,
"nop",
"nop"
};
- method = default_bindings[button];
+ method = default_bindings[event_to_x11_button(button)];
}
if (strcmp(method, "nop") == 0) {
return;
@@ -345,7 +352,7 @@ static int cmp_sni_id(const void *item, const void *cmp_to) {
static enum hotspot_event_handling icon_hotspot_callback(
struct swaybar_output *output, struct swaybar_hotspot *hotspot,
- int x, int y, enum x11_button button, void *data) {
+ int x, int y, uint32_t button, void *data) {
wlr_log(WLR_DEBUG, "Clicked on %s", (char *)data);
struct swaybar_tray *tray = output->bar->tray;