aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/sway/input/cursor.h5
-rw-r--r--meson.build1
-rw-r--r--sway/commands/bind.c25
-rw-r--r--sway/input/cursor.c59
-rw-r--r--sway/meson.build1
-rw-r--r--sway/sway.5.scd7
6 files changed, 89 insertions, 9 deletions
diff --git a/include/sway/input/cursor.h b/include/sway/input/cursor.h
index 50ac453b..f7e82721 100644
--- a/include/sway/input/cursor.h
+++ b/include/sway/input/cursor.h
@@ -5,6 +5,11 @@
#define SWAY_CURSOR_PRESSED_BUTTONS_CAP 32
+#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 sway_cursor {
struct sway_seat *seat;
struct wlr_cursor *cursor;
diff --git a/meson.build b/meson.build
index 6dc5bd8d..e1e0fc2d 100644
--- a/meson.build
+++ b/meson.build
@@ -46,6 +46,7 @@ pango = dependency('pango')
pangocairo = dependency('pangocairo')
gdk_pixbuf = dependency('gdk-pixbuf-2.0', required: false)
pixman = dependency('pixman-1')
+libevdev = dependency('libevdev')
libinput = dependency('libinput', version: '>=1.6.0')
libpam = cc.find_library('pam', required: false)
crypt = cc.find_library('crypt', required: false)
diff --git a/sway/commands/bind.c b/sway/commands/bind.c
index 01a35cf2..5990166a 100644
--- a/sway/commands/bind.c
+++ b/sway/commands/bind.c
@@ -1,4 +1,5 @@
#define _POSIX_C_SOURCE 200809L
+#include <libevdev/libevdev.h>
#ifdef __linux__
#include <linux/input-event-codes.h>
#elif __FreeBSD__
@@ -10,6 +11,7 @@
#include <strings.h>
#include "sway/commands.h"
#include "sway/config.h"
+#include "sway/input/cursor.h"
#include "sway/ipc-server.h"
#include "list.h"
#include "log.h"
@@ -102,9 +104,26 @@ static struct cmd_results *identify_key(const char* name, bool first_key,
// Check for mouse binding
uint32_t button = 0;
- if (strncasecmp(name, "button", strlen("button")) == 0 &&
- strlen(name) == strlen("button0")) {
- button = name[strlen("button")] - '1' + BTN_LEFT;
+ if (strncasecmp(name, "button", strlen("button")) == 0) {
+ // Map to x11 mouse buttons
+ button = name[strlen("button")] - '0';
+ if (button < 1 || button > 9 || strlen(name) > strlen("button0")) {
+ return cmd_results_new(CMD_INVALID, "bindsym",
+ "Only buttons 1-9 are supported. For other mouse "
+ "buttons, use the name of the event code.");
+ }
+ uint32_t buttons[] = {BTN_LEFT, BTN_MIDDLE, BTN_RIGHT,
+ SWAY_SCROLL_UP, SWAY_SCROLL_DOWN, SWAY_SCROLL_LEFT,
+ SWAY_SCROLL_RIGHT, BTN_SIDE, BTN_EXTRA};
+ button = buttons[button - 1];
+ } else if (strncmp(name, "BTN_", strlen("BTN_")) == 0) {
+ // Get event code
+ int code = libevdev_event_code_from_name(EV_KEY, name);
+ if (code == -1) {
+ return cmd_results_new(CMD_INVALID, "bindsym",
+ "Invalid event code name %s", name);
+ }
+ button = code;
}
if (*type == BINDING_KEYSYM) {
diff --git a/sway/input/cursor.c b/sway/input/cursor.c
index ad9b9835..444fe81d 100644
--- a/sway/input/cursor.c
+++ b/sway/input/cursor.c
@@ -1,5 +1,6 @@
#define _POSIX_C_SOURCE 200809L
#include <math.h>
+#include <libevdev/libevdev.h>
#ifdef __linux__
#include <linux/input-event-codes.h>
#elif __FreeBSD__
@@ -982,6 +983,18 @@ static void handle_cursor_button(struct wl_listener *listener, void *data) {
transaction_commit_dirty();
}
+static uint32_t wl_axis_to_button(struct wlr_event_pointer_axis *event) {
+ switch (event->orientation) {
+ case WLR_AXIS_ORIENTATION_VERTICAL:
+ return event->delta < 0 ? SWAY_SCROLL_UP : SWAY_SCROLL_DOWN;
+ case WLR_AXIS_ORIENTATION_HORIZONTAL:
+ return event->delta < 0 ? SWAY_SCROLL_LEFT : SWAY_SCROLL_RIGHT;
+ default:
+ wlr_log(WLR_DEBUG, "Unknown axis orientation");
+ return 0;
+ }
+}
+
static void dispatch_cursor_axis(struct sway_cursor *cursor,
struct wlr_event_pointer_axis *event) {
struct sway_seat *seat = cursor->seat;
@@ -998,11 +1011,32 @@ static void dispatch_cursor_axis(struct sway_cursor *cursor,
enum wlr_edges edge = cont ? find_edge(cont, cursor) : WLR_EDGE_NONE;
bool on_border = edge != WLR_EDGE_NONE;
bool on_titlebar = cont && !on_border && !surface;
+ bool on_contents = cont && !on_border && surface;
float scroll_factor =
(ic == NULL || ic->scroll_factor == FLT_MIN) ? 1.0f : ic->scroll_factor;
- // Scrolling on a tabbed or stacked title bar
- if (on_titlebar) {
+ bool handled = false;
+
+ // Gather information needed for mouse bindings
+ struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat->wlr_seat);
+ uint32_t modifiers = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0;
+ struct wlr_input_device *device = input_device->wlr_device;
+ char *dev_id = device ? input_device_get_identifier(device) : strdup("*");
+ uint32_t button = wl_axis_to_button(event);
+
+ // Handle mouse bindings - x11 mouse buttons 4-7 - press event
+ struct sway_binding *binding = NULL;
+ state_add_button(cursor, button);
+ binding = get_active_mouse_binding(cursor,
+ config->current_mode->mouse_bindings, modifiers, false,
+ on_titlebar, on_border, on_contents, dev_id);
+ if (binding) {
+ seat_execute_command(seat, binding);
+ handled = true;
+ }
+
+ // Scrolling on a tabbed or stacked title bar (handled as press event)
+ if (!handled && on_titlebar) {
enum sway_container_layout layout = container_parent_layout(cont);
if (layout == L_TABBED || layout == L_STACKED) {
struct sway_node *tabcontainer = node_get_parent(node);
@@ -1029,13 +1063,26 @@ static void dispatch_cursor_axis(struct sway_cursor *cursor,
seat_set_raw_focus(seat, new_focus);
seat_set_raw_focus(seat, old_focus);
}
- return;
+ handled = true;
}
}
- wlr_seat_pointer_notify_axis(cursor->seat->wlr_seat, event->time_msec,
- event->orientation, scroll_factor * event->delta,
- round(scroll_factor * event->delta_discrete), event->source);
+ // Handle mouse bindings - x11 mouse buttons 4-7 - release event
+ binding = get_active_mouse_binding(cursor,
+ config->current_mode->mouse_bindings, modifiers, true,
+ on_titlebar, on_border, on_contents, dev_id);
+ state_erase_button(cursor, button);
+ if (binding) {
+ seat_execute_command(seat, binding);
+ handled = true;
+ }
+ free(dev_id);
+
+ if (!handled) {
+ wlr_seat_pointer_notify_axis(cursor->seat->wlr_seat, event->time_msec,
+ event->orientation, scroll_factor * event->delta,
+ round(scroll_factor * event->delta_discrete), event->source);
+ }
}
static void handle_cursor_axis(struct wl_listener *listener, void *data) {
diff --git a/sway/meson.build b/sway/meson.build
index 51b40020..2f977fd2 100644
--- a/sway/meson.build
+++ b/sway/meson.build
@@ -174,6 +174,7 @@ sway_deps = [
cairo,
gdk_pixbuf,
jsonc,
+ libevdev,
libinput,
math,
pango,
diff --git a/sway/sway.5.scd b/sway/sway.5.scd
index 2fe4e372..e6abef56 100644
--- a/sway/sway.5.scd
+++ b/sway/sway.5.scd
@@ -288,6 +288,13 @@ runtime.
overwrite a binding, swaynag will give you a warning. To silence this, use
the _--no-warn_ flag.
+ Mouse buttons can either be specified in the form _button[1-9]_ or by using
+ the name of the event code (ex _BTN\_LEFT_ or _BTN\_RIGHT_). For the former
+ option, the buttons will be mapped to their values in X11 (1=left, 2=middle,
+ 3=right, 4=scroll up, 5=scroll down, 6=scroll left, 7=scroll right, 8=back,
+ 9=forward). For the latter option, you can find the event names using
+ _libinput debug-events_.
+
Example:
```
# Execute firefox when alt, shift, and f are pressed together