aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/sway/commands.h1
-rw-r--r--include/swaybar/i3bar.h2
-rw-r--r--include/swaybar/input.h9
-rw-r--r--sway/commands/bar.c1
-rw-r--r--sway/commands/bar/bind.c106
-rw-r--r--sway/commands/bar/bindsym.c68
-rw-r--r--sway/ipc-json.c29
-rw-r--r--sway/meson.build2
-rw-r--r--sway/sway-bar.5.scd16
-rw-r--r--swaybar/i3bar.c31
-rw-r--r--swaybar/input.c36
-rw-r--r--swaybar/ipc.c2
-rw-r--r--swaybar/render.c19
13 files changed, 208 insertions, 114 deletions
diff --git a/include/sway/commands.h b/include/sway/commands.h
index 04f93ba9..ec21f4e1 100644
--- a/include/sway/commands.h
+++ b/include/sway/commands.h
@@ -183,6 +183,7 @@ sway_cmd cmd_workspace;
sway_cmd cmd_ws_auto_back_and_forth;
sway_cmd cmd_workspace_layout;
+sway_cmd bar_cmd_bindcode;
sway_cmd bar_cmd_binding_mode_indicator;
sway_cmd bar_cmd_bindsym;
sway_cmd bar_cmd_colors;
diff --git a/include/swaybar/i3bar.h b/include/swaybar/i3bar.h
index ab4744a5..aa4415ff 100644
--- a/include/swaybar/i3bar.h
+++ b/include/swaybar/i3bar.h
@@ -28,6 +28,6 @@ void i3bar_block_unref(struct i3bar_block *block);
bool i3bar_handle_readable(struct status_line *status);
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,
- enum x11_button button);
+ uint32_t button);
#endif
diff --git a/include/swaybar/input.h b/include/swaybar/input.h
index f480d009..4b46b0de 100644
--- a/include/swaybar/input.h
+++ b/include/swaybar/input.h
@@ -4,6 +4,11 @@
#include <wayland-client.h>
#include "list.h"
+#define SWAY_SCROLL_UP KEY_MAX + 1
+#define SWAY_SCROLL_DOWN KEY_MAX + 2
+#define SWAY_SCROLL_LEFT KEY_MAX + 3
+#define SWAY_SCROLL_RIGHT KEY_MAX + 4
+
struct swaybar;
struct swaybar_output;
@@ -39,8 +44,8 @@ struct swaybar_hotspot {
struct wl_list link; // swaybar_output::hotspots
int x, y, width, height;
enum hotspot_event_handling (*callback)(struct swaybar_output *output,
- struct swaybar_hotspot *hotspot, int x, int y,
- enum x11_button button, void *data);
+ struct swaybar_hotspot *hotspot, int x, int y, uint32_t button,
+ void *data);
void (*destroy)(void *data);
void *data;
};
diff --git a/sway/commands/bar.c b/sway/commands/bar.c
index 3e7c1b0f..2a82d508 100644
--- a/sway/commands/bar.c
+++ b/sway/commands/bar.c
@@ -8,6 +8,7 @@
// Must be in alphabetical order for bsearch
static struct cmd_handler bar_handlers[] = {
+ { "bindcode", bar_cmd_bindcode },
{ "binding_mode_indicator", bar_cmd_binding_mode_indicator },
{ "bindsym", bar_cmd_bindsym },
{ "colors", bar_cmd_colors },
diff --git a/sway/commands/bar/bind.c b/sway/commands/bar/bind.c
new file mode 100644
index 00000000..a4c65ec4
--- /dev/null
+++ b/sway/commands/bar/bind.c
@@ -0,0 +1,106 @@
+#include <libevdev/libevdev.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include "sway/commands.h"
+#include "sway/config.h"
+#include "sway/input/cursor.h"
+#include "list.h"
+#include "log.h"
+#include "stringop.h"
+
+static struct cmd_results *bar_cmd_bind(int argc, char **argv, bool code) {
+ const char *command = code ? "bar bindcode" : "bar bindsym";
+ struct cmd_results *error = NULL;
+ if ((error = checkarg(argc, command, EXPECTED_AT_LEAST, 2))) {
+ return error;
+ }
+ if (!config->current_bar) {
+ return cmd_results_new(CMD_FAILURE, command, "No bar defined.");
+ }
+
+ struct bar_binding *binding = calloc(1, sizeof(struct bar_binding));
+ if (!binding) {
+ return cmd_results_new(CMD_FAILURE, command,
+ "Unable to allocate bar binding");
+ }
+
+ binding->release = false;
+ if (strcmp("--release", argv[0]) == 0) {
+ binding->release = true;
+ argv++;
+ argc--;
+ }
+
+ 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_bar_binding(binding);
+ error = cmd_results_new(CMD_INVALID, command, message);
+ free(message);
+ return error;
+ } else if (!binding->button) {
+ free_bar_binding(binding);
+ return cmd_results_new(CMD_INVALID, command,
+ "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;
+ }
+ }
+
+ binding->command = join_args(argv + 1, argc - 1);
+
+ list_t *bindings = config->current_bar->bindings;
+ bool overwritten = false;
+ for (int i = 0; i < bindings->length; i++) {
+ struct bar_binding *other = bindings->items[i];
+ if (other->button == binding->button &&
+ other->release == binding->release) {
+ overwritten = true;
+ bindings->items[i] = binding;
+ free_bar_binding(other);
+ wlr_log(WLR_DEBUG, "[bar %s] Updated binding for %u (%s)%s",
+ config->current_bar->id, binding->button, name,
+ binding->release ? " - release" : "");
+ break;
+ }
+ }
+ if (!overwritten) {
+ list_add(bindings, binding);
+ wlr_log(WLR_DEBUG, "[bar %s] Added binding for %u (%s)%s",
+ config->current_bar->id, binding->button, name,
+ binding->release ? " - release" : "");
+ }
+
+ return cmd_results_new(CMD_SUCCESS, NULL, NULL);
+}
+
+struct cmd_results *bar_cmd_bindcode(int argc, char **argv) {
+ return bar_cmd_bind(argc, argv, true);
+}
+
+struct cmd_results *bar_cmd_bindsym(int argc, char **argv) {
+ return bar_cmd_bind(argc, argv, false);
+}
diff --git a/sway/commands/bar/bindsym.c b/sway/commands/bar/bindsym.c
deleted file mode 100644
index e6d6220e..00000000
--- a/sway/commands/bar/bindsym.c
+++ /dev/null
@@ -1,68 +0,0 @@
-#include <stdlib.h>
-#include <string.h>
-#include <strings.h>
-#include "sway/commands.h"
-#include "sway/config.h"
-#include "list.h"
-#include "log.h"
-#include "stringop.h"
-
-struct cmd_results *bar_cmd_bindsym(int argc, char **argv) {
- struct cmd_results *error = NULL;
- if ((error = checkarg(argc, "bar bindsym", EXPECTED_AT_LEAST, 2))) {
- return error;
- }
- if (!config->current_bar) {
- return cmd_results_new(CMD_FAILURE, "bar bindsym", "No bar defined.");
- }
-
- struct bar_binding *binding = calloc(1, sizeof(struct bar_binding));
- if (!binding) {
- return cmd_results_new(CMD_FAILURE, "bar bindsym",
- "Unable to allocate bar binding");
- }
-
- binding->release = false;
- if (strcmp("--release", argv[0]) == 0) {
- binding->release = true;
- argv++;
- argc--;
- }
-
- binding->button = 0;
- if (strncasecmp(argv[0], "button", strlen("button")) == 0 &&
- strlen(argv[0]) == strlen("button0")) {
- binding->button = argv[0][strlen("button")] - '0';
- }
- if (binding->button < 1 || binding->button > 9) {
- free_bar_binding(binding);
- return cmd_results_new(CMD_FAILURE, "bar bindsym",
- "Only button<1-9> is supported");
- }
-
- binding->command = join_args(argv + 1, argc - 1);
-
- list_t *bindings = config->current_bar->bindings;
- bool overwritten = false;
- for (int i = 0; i < bindings->length; i++) {
- struct bar_binding *other = bindings->items[i];
- if (other->button == binding->button &&
- other->release == binding->release) {
- overwritten = true;
- bindings->items[i] = binding;
- free_bar_binding(other);
- wlr_log(WLR_DEBUG, "[bar %s] Updated binding for button%u%s",
- config->current_bar->id, binding->button,
- binding->release ? " (release)" : "");
- break;
- }
- }
- if (!overwritten) {
- list_add(bindings, binding);
- wlr_log(WLR_DEBUG, "[bar %s] Added binding for button%u%s",
- config->current_bar->id, binding->button,
- binding->release ? " (release)" : "");
- }
-
- return cmd_results_new(CMD_SUCCESS, NULL, NULL);
-}
diff --git a/sway/ipc-json.c b/sway/ipc-json.c
index 15f89f65..6e5ba4fd 100644
--- a/sway/ipc-json.c
+++ b/sway/ipc-json.c
@@ -1,4 +1,5 @@
#include <json-c/json.h>
+#include <libevdev/libevdev.h>
#include <stdio.h>
#include <ctype.h>
#include "config.h"
@@ -10,6 +11,7 @@
#include "sway/tree/workspace.h"
#include "sway/output.h"
#include "sway/input/input-manager.h"
+#include "sway/input/cursor.h"
#include "sway/input/seat.h"
#include <wlr/backend/libinput.h>
#include <wlr/types/wlr_box.h>
@@ -647,6 +649,31 @@ json_object *ipc_json_describe_seat(struct sway_seat *seat) {
return object;
}
+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;
+ }
+}
+
json_object *ipc_json_describe_bar_config(struct bar_config *bar) {
if (!sway_assert(bar, "Bar must not be NULL")) {
return NULL;
@@ -792,6 +819,8 @@ json_object *ipc_json_describe_bar_config(struct bar_config *bar) {
struct bar_binding *binding = bar->bindings->items[i];
json_object *bind = json_object_new_object();
json_object_object_add(bind, "input_code",
+ json_object_new_int(event_to_x11_button(binding->button)));
+ json_object_object_add(bind, "event_code",
json_object_new_int(binding->button));
json_object_object_add(bind, "command",
json_object_new_string(binding->command));
diff --git a/sway/meson.build b/sway/meson.build
index b49d550a..93858336 100644
--- a/sway/meson.build
+++ b/sway/meson.build
@@ -105,8 +105,8 @@ sway_sources = files(
'commands/workspace_layout.c',
'commands/ws_auto_back_and_forth.c',
+ 'commands/bar/bind.c',
'commands/bar/binding_mode_indicator.c',
- 'commands/bar/bindsym.c',
'commands/bar/colors.c',
'commands/bar/font.c',
'commands/bar/gaps.c',
diff --git a/sway/sway-bar.5.scd b/sway/sway-bar.5.scd
index e1a4a937..3f6b4298 100644
--- a/sway/sway-bar.5.scd
+++ b/sway/sway-bar.5.scd
@@ -71,10 +71,18 @@ Sway allows configuring swaybar in the sway configuration file.
*height* <height>
Sets the height of the bar. Default height (0) will match the font size.
-*bindsym* [--release] button<n> <command>
- Executes _command_ when mouse button _n_ has been pressed (or if _released_
- is given, when mouse button _n_ has been released). To disable the default
- behavior for a button, use the command _nop_.
+*bindcode* [--release] <event-code> <command>
+ Executes _command_ when the mouse button has been pressed (or if _released_
+ is given, when the button has been released). The buttons can be given as
+ an event code, which can be obtaining from `libinput debug-events`. To
+ disable the default behavior for a button, use the command _nop_.
+
+*bindsym* [--release] button[1-9]|<event-name> <command>
+ Executes _command_ when the mouse button has been pressed (or if _released_
+ is given, when the button has been released). The buttons can be given as a
+ x11 button number or an event name, which can be obtained from `libinput
+ debug-events`. To disable the default behavior for a button, use the
+ command _nop_.
*mode* dock|hide|invisible
Specifies the visibility of the bar. In _dock_ mode, it is permanently
diff --git a/swaybar/i3bar.c b/swaybar/i3bar.c
index 54607a3a..116c8f6e 100644
--- a/swaybar/i3bar.c
+++ b/swaybar/i3bar.c
@@ -259,9 +259,34 @@ 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,
- enum x11_button button) {
+ uint32_t button) {
wlr_log(WLR_DEBUG, "block %s clicked", block->name);
if (!block->name || !status->click_events) {
return HOTSPOT_PROCESS;
@@ -275,7 +300,9 @@ enum hotspot_event_handling i3bar_block_send_click(struct status_line *status,
json_object_new_string(block->instance));
}
- json_object_object_add(event_json, "button", json_object_new_int(button));
+ json_object_object_add(event_json, "button",
+ json_object_new_int(event_to_x11_button(button)));
+ json_object_object_add(event_json, "event", json_object_new_int(button));
json_object_object_add(event_json, "x", json_object_new_int(x));
json_object_object_add(event_json, "y", json_object_new_int(y));
json_object_object_add(event_json, "relative_x", json_object_new_int(rx));
diff --git a/swaybar/input.c b/swaybar/input.c
index 620da977..bdd55e58 100644
--- a/swaybar/input.c
+++ b/swaybar/input.c
@@ -22,32 +22,16 @@ void free_hotspots(struct wl_list *list) {
}
}
-static enum x11_button wl_button_to_x11_button(uint32_t button) {
- switch (button) {
- case BTN_LEFT:
- return LEFT;
- case BTN_MIDDLE:
- return MIDDLE;
- case BTN_RIGHT:
- return RIGHT;
- case BTN_SIDE:
- return BACK;
- case BTN_EXTRA:
- return FORWARD;
- default:
- return NONE;
- }
-}
-
-static enum x11_button wl_axis_to_x11_button(uint32_t axis, wl_fixed_t value) {
+static uint32_t wl_axis_to_button(uint32_t axis, wl_fixed_t value) {
+ bool negative = wl_fixed_to_double(value) < 0;
switch (axis) {
case WL_POINTER_AXIS_VERTICAL_SCROLL:
- return wl_fixed_to_double(value) < 0 ? SCROLL_UP : SCROLL_DOWN;
+ return negative ? SWAY_SCROLL_UP : SWAY_SCROLL_DOWN;
case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
- return wl_fixed_to_double(value) < 0 ? SCROLL_LEFT : SCROLL_RIGHT;
+ return negative ? SWAY_SCROLL_LEFT : SWAY_SCROLL_RIGHT;
default:
wlr_log(WLR_DEBUG, "Unexpected axis value on mouse scroll");
- return NONE;
+ return 0;
}
}
@@ -102,12 +86,12 @@ static void wl_pointer_motion(void *data, struct wl_pointer *wl_pointer,
bar->pointer.y = wl_fixed_to_int(surface_y);
}
-static bool check_bindings(struct swaybar *bar, uint32_t x11_button,
+static bool check_bindings(struct swaybar *bar, uint32_t button,
uint32_t state) {
bool released = state == WL_POINTER_BUTTON_STATE_RELEASED;
for (int i = 0; i < bar->config->bindings->length; i++) {
struct swaybar_binding *binding = bar->config->bindings->items[i];
- if (binding->button == x11_button && binding->release == released) {
+ if (binding->button == button && binding->release == released) {
ipc_execute_binding(bar, binding);
return true;
}
@@ -124,7 +108,7 @@ static void wl_pointer_button(void *data, struct wl_pointer *wl_pointer,
return;
}
- if (check_bindings(bar, wl_button_to_x11_button(button), state)) {
+ if (check_bindings(bar, button, state)) {
return;
}
@@ -140,7 +124,7 @@ static void wl_pointer_button(void *data, struct wl_pointer *wl_pointer,
&& x < hotspot->x + hotspot->width
&& y < hotspot->y + hotspot->height) {
if (HOTSPOT_IGNORE == hotspot->callback(output, hotspot,
- pointer->x, pointer->y, wl_button_to_x11_button(button), hotspot->data)) {
+ pointer->x, pointer->y, button, hotspot->data)) {
return;
}
}
@@ -158,7 +142,7 @@ static void wl_pointer_axis(void *data, struct wl_pointer *wl_pointer,
// If there is a button press binding, execute it, skip default behavior,
// and check button release bindings
- enum x11_button button = wl_axis_to_x11_button(axis, value);
+ uint32_t button = wl_axis_to_button(axis, value);
if (check_bindings(bar, button, WL_POINTER_BUTTON_STATE_PRESSED)) {
check_bindings(bar, button, WL_POINTER_BUTTON_STATE_RELEASED);
return;
diff --git a/swaybar/ipc.c b/swaybar/ipc.c
index bc5c28b4..097f9161 100644
--- a/swaybar/ipc.c
+++ b/swaybar/ipc.c
@@ -246,7 +246,7 @@ static bool ipc_parse_config(
struct swaybar_binding *binding =
calloc(1, sizeof(struct swaybar_binding));
binding->button = json_object_get_int(
- json_object_object_get(bindobj, "input_code"));
+ json_object_object_get(bindobj, "event_code"));
binding->command = strdup(json_object_get_string(
json_object_object_get(bindobj, "command")));
binding->release = json_object_get_boolean(
diff --git a/swaybar/render.c b/swaybar/render.c
index 12dd3b07..55f680ed 100644
--- a/swaybar/render.c
+++ b/swaybar/render.c
@@ -1,5 +1,6 @@
#define _POSIX_C_SOURCE 200809L
#include <assert.h>
+#include <linux/input-event-codes.h>
#include <limits.h>
#include <stdlib.h>
#include <stdint.h>
@@ -129,13 +130,13 @@ static void render_sharp_line(cairo_t *cairo, uint32_t color,
}
}
-static enum hotspot_event_handling block_hotspot_callback(struct swaybar_output *output,
- struct swaybar_hotspot *hotspot,
- int x, int y, enum x11_button button, void *data) {
+static enum hotspot_event_handling block_hotspot_callback(
+ struct swaybar_output *output, struct swaybar_hotspot *hotspot,
+ int x, int y, uint32_t button, void *data) {
struct i3bar_block *block = data;
struct status_line *status = output->bar->status;
- return i3bar_block_send_click(status, block, x, y, x - hotspot->x, y - hotspot->y,
- hotspot->width, hotspot->height, button);
+ return i3bar_block_send_click(status, block, x, y, x - hotspot->x,
+ y - hotspot->y, hotspot->width, hotspot->height, button);
}
static void i3bar_block_unref_callback(void *data) {
@@ -366,10 +367,10 @@ static uint32_t render_binding_mode_indicator(cairo_t *cairo,
return output->height;
}
-static enum hotspot_event_handling workspace_hotspot_callback(struct swaybar_output *output,
- struct swaybar_hotspot *hotspot,
- int x, int y, enum x11_button button, void *data) {
- if (button != LEFT) {
+static enum hotspot_event_handling workspace_hotspot_callback(
+ struct swaybar_output *output, struct swaybar_hotspot *hotspot,
+ int x, int y, uint32_t button, void *data) {
+ if (button != BTN_LEFT) {
return HOTSPOT_PROCESS;
}
ipc_send_workspace_command(output->bar, (const char *)data);