2024-01-03 gestures wayland libinput
This new gestures package works for both Wayland and X11. To start, grab the sources and compile or use the Bit Powder repo to fetch the binary version for recent Debian/Raspbian versions. It uses libinput to track the input and executes a shell script based on the gestures. It executes the script $HOME/.config/gestures/three-to-left
(with either three
or four
, and either left
/`right`/`top`/`bottom`). This avoids a config script, and parsing it.
The original gebaar-libinput can be found at GitHub.
To go back/forward with three fingers, use the following scripts, listed below.
$HOME/.config/gestures/three-to-right
Swipe to right to go back in browsers.
#!/bin/sh
# Space thing is needed for Chromium based browsers in wayland
if [ -n "$WAYLAND_DISPLAY" ]; then
wtype -P space -s 1 -p space -s 1 -M alt -P left -s 10 -m alt -p left
elif [ -n "$DISPLAY" ]; then
xdotool key Alt+Left
fi
$HOME/.config/gestures/three-to-left
Swipe to left to go forward in browsers.
#!/bin/sh
# Space thing is needed for Chromium based browsers in wayland
if [ -n "$WAYLAND_DISPLAY" ]; then
wtype -P space -s 1 -p space -s 1 -M alt -P right -s 10 -m alt -p right
elif [ -n "$DISPLAY" ]; then
xdotool key Alt+Right
fi
$HOME/.config/gestures/four-to-left
Swipe to right to go in i3/sway to the previous workspace.
#!/bin/sh
i3-msg workspace next
$HOME/.config/gestures/four-to-right
Swipe to right to go in i3/sway to the previous workspace.
#!/bin/sh
i3-msg workspace prev
The complete C++ version
#include <poll.h>
#include <libinput.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <string>
static int libinput_open(const char* path, int flags, void*) {
int fd = open(path, flags);
return fd<0 ? -errno : fd;
}
static void libinput_close(int fd, void*) {
close(fd);
}
static struct libinput_interface libinput_interface = {
.open_restricted = libinput_open,
.close_restricted = libinput_close,
};
int fingers = 0;
double x = 0.0;
double y = 0.0;
void handle_swipe_event_without_coords(libinput_event_gesture* gev) {
int swipe_type = 5; // middle = no swipe
// 1 = left_up, 2 = up, 3 = right_up...
// 1 2 3
// 4 5 6
// 7 8 9
const double OBLIQUE_RATIO = 0.414; // =~ tan(22.5);
fingers = 0;
x = y = 0;
}
int main(int argc, char** argv) {
auto udev = udev_new();
auto libinput = libinput_udev_create_context(&libinput_interface, nullptr, udev);
if (libinput_udev_assign_seat(libinput, "seat0") != 0)
return -1;
// event loop
struct pollfd fds{};
fds.fd = libinput_get_fd(libinput);
fds.events = POLLIN;
fds.revents = 0;
while (poll(&fds, 1, -1)>-1) {
libinput_dispatch(libinput);
while (auto libinput_event = libinput_get_event(libinput)) {
switch (libinput_event_get_type(libinput_event)) {
case LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN: {
auto ge = libinput_event_get_gesture_event(libinput_event);
fingers = libinput_event_gesture_get_finger_count(ge);
x = y = 0;
break;
}
case LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE: {
auto ge = libinput_event_get_gesture_event(libinput_event);
x += libinput_event_gesture_get_dx(ge);
y += libinput_event_gesture_get_dy(ge);
break;
}
case LIBINPUT_EVENT_GESTURE_SWIPE_END: {
auto ge = libinput_event_get_gesture_event(libinput_event);
std::string type;
if (abs(x) > abs(y)) {
type = x < 0 ? "left" : "right";
} else {
type = y < 0 ? "top" : "bottom";
}
fprintf(stderr, "gesture %s with %i fingers\n", type.c_str(), fingers);
if (fingers == 3) {
std::system((std::string(".config/gestures/three-to-") + type).c_str());
} else if (fingers == 4) {
std::system((std::string(".config/gestures/four-to-") + type).c_str());
}
break;
}
default:
break;
}
libinput_event_destroy(libinput_event);
libinput_dispatch(libinput);
}
}
return 0;
}