From 9c2d1532c771c1a81b927e20a03ee7e5acfbcc86 Mon Sep 17 00:00:00 2001 From: Rico Tiongson Date: Mon, 25 Sep 2017 23:18:07 +0800 Subject: [PATCH] Add comfortable-swipe source file --- README.md | 6 +- install | 10 ++ src/comfortable-swipe-serve | 2 + src/comfortable-swipe.cpp | 196 ++++++++++++++++++++++++++++++++++++ 4 files changed, 213 insertions(+), 1 deletion(-) create mode 100755 install create mode 100644 src/comfortable-swipe-serve create mode 100644 src/comfortable-swipe.cpp diff --git a/README.md b/README.md index 5a5b2fd..c6d376e 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,6 @@ # Ubuntu-Comfortable-3-Finger-Swipe -Comfortable 3-finger and 4-finger swipe gesture using Xdotool in native C++ +Comfortable 3-finger and 4-finger swipe gesture using Xdotool in native C++, for Ubuntu 16.04LTS and beyond. + +## Installation Instructions +1. `sudo apt install libxdo-dev` +2. ` \ No newline at end of file diff --git a/install b/install new file mode 100755 index 0000000..6f30eb9 --- /dev/null +++ b/install @@ -0,0 +1,10 @@ +#!/bin/bash +DIR=$(dirname $0) +echo "Compiling..." +g++ -std=c++11 -O2 $DIR/src/comfortable-swipe.cpp -lxdo -o ~/.local/bin/comfortable-swipe || exec echo "Installation aborted" +cat $DIR/src/comfortable-swipe-serve > ~/.local/bin/comfortable-swipe-serve +chmod +x ~/.local/bin/comfortable-swipe-serve +echo "Successfully installed. You may now try running 'comfortable-swipe-serve'." +echo "--------------------------------------------------------------------------" +echo "If you want 'comfortable-swipe-serve' to automatically load on login, add it to your Startup Applications." +echo "See https://help.ubuntu.com/stable/ubuntu-help/startup-applications.html" diff --git a/src/comfortable-swipe-serve b/src/comfortable-swipe-serve new file mode 100644 index 0000000..9e98f4b --- /dev/null +++ b/src/comfortable-swipe-serve @@ -0,0 +1,2 @@ +#!/bin/sh +stdbuf -oL -eL libinput-debug-events | comfortable-swipe "$@" diff --git a/src/comfortable-swipe.cpp b/src/comfortable-swipe.cpp new file mode 100644 index 0000000..98a7137 --- /dev/null +++ b/src/comfortable-swipe.cpp @@ -0,0 +1,196 @@ +// you may tweak these before calling `build` +#define THRESHOLD 20 + +#define CMD_THREE_FINGERS_RIGHT "ctrl+alt+Left" +#define CMD_THREE_FINGERS_LEFT "ctrl+alt+Right" +#define CMD_THREE_FINGERS_UP "super+w" +#define CMD_THREE_FINGERS_DOWN "super+w" + +#define CMD_FOUR_FINGERS_RIGHT "ctrl+shift+alt+Left" +#define CMD_FOUR_FINGERS_LEFT "ctrl+shift+alt+Right" +#define CMD_FOUR_FINGERS_UP "super+d" +#define CMD_FOUR_FINGERS_DOWN "super+d" + +#define MSK_THREE_FINGERS 0 +#define MSK_FOUR_FINGERS 1 +#define MSK_NEGATIVE 0 +#define MSK_POSITIVE 2 +#define MSK_HORIZONTAL 0 +#define MSK_VERTICAL 4 + +const char* commands[] = { + CMD_THREE_FINGERS_LEFT /* 000 */, CMD_FOUR_FINGERS_LEFT /* 001 */, + CMD_THREE_FINGERS_RIGHT /* 010 */ , CMD_FOUR_FINGERS_RIGHT /* 011 */, + CMD_THREE_FINGERS_UP /* 100 */ , CMD_FOUR_FINGERS_UP /* 101 */, + CMD_THREE_FINGERS_DOWN /* 110 */, CMD_FOUR_FINGERS_DOWN /* 111 */ +}; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +extern "C" { + // sudo apt install libxdo-dev + #include +} +using namespace std; +#define cstr const string& + +/* FORWARD DECLARATIONS */ + +namespace util { + string join(cstr, string[], int); + string build_gesture_begin(); + string build_gesture_update(); + string build_gesture_end(); +} + +struct swipe_gesture { + string device, stamp, fingers; + string dx, dy, udx, udy; + xdo_t* xdo; + virtual void on_update() = 0; + virtual void on_begin() = 0; + virtual void on_end() = 0; + swipe_gesture(): xdo(xdo_new(NULL)) {} + ~swipe_gesture() {xdo_free(xdo);} +}; + +struct swipe_gesture_impl : swipe_gesture { + int screen_num, ix, iy; + double x, y; + bool gesture_done; + swipe_gesture_impl(): swipe_gesture() {} + ~swipe_gesture_impl() {} + void key(const char* cmd) const { + xdo_send_keysequence_window(xdo, CURRENTWINDOW, cmd, 0); + } + void on_begin() override { + // cout << "BEGIN" << endl; + xdo_get_mouse_location(xdo, &ix, &iy, &screen_num); + gesture_done = false; + x = 0; + y = 0; + } + void on_update() override { + if (gesture_done) return; + // cout << "UPDATE " << x << ' ' << y << " [" << dx << ", " << dy << "]" << endl; + x += stod(dx); + y += stod(dy); + if (x*x + y*y > THRESHOLD*THRESHOLD) { + gesture_done = true; + int mask = 0; + if (fingers == "3") mask |= MSK_THREE_FINGERS; else + if (fingers == "4") mask |= MSK_FOUR_FINGERS; + if (abs(x) > abs(y)) { + mask |= MSK_HORIZONTAL; + if (x < 0) mask |= MSK_NEGATIVE; + else mask |= MSK_POSITIVE; + } else { + mask |= MSK_VERTICAL; + if (y < 0) mask |= MSK_NEGATIVE; + else mask |= MSK_POSITIVE; + } + // cout << "FLICK " << mask << ' ' << commands[mask] << endl; + key(commands[mask]); + } + } + void on_end() override { + // pass + } +}; + + +/* MAIN DRIVER FUNCTION */ + +int main(int argc, char** args) { + ios::sync_with_stdio(false); + cin.tie(0); + const regex gesture_begin(util::build_gesture_begin()); + const regex gesture_update(util::build_gesture_update()); + const regex gesture_end(util::build_gesture_end()); + string sentence; + swipe_gesture_impl swipe; + while (getline(cin, sentence)) { + auto data = sentence.data(); + cmatch matches; + if (regex_match(data, matches, gesture_begin)) { + swipe.device = matches[1]; + swipe.stamp = matches[2]; + swipe.fingers = matches[3]; + swipe.on_begin(); + } + else if (regex_match(data, matches, gesture_end)) { + swipe.device = matches[1]; + swipe.stamp = matches[2]; + swipe.fingers = matches[3]; + swipe.on_end(); + } + else if (regex_match(data, matches, gesture_update)) { + swipe.device = matches[1]; + swipe.stamp = matches[2]; + swipe.fingers = matches[3]; + swipe.dx = matches[4]; + swipe.dy = matches[5]; + swipe.udx = matches[6]; + swipe.udy = matches[7]; + swipe.on_update(); + } + } +} + +/* UTILITY FUNCTIONS */ + +namespace util { + + string number_regex() { + return "-?\\d+(?:\\.\\d+)"; + } + + string join(cstr delim, string arr[], int n) { + string ans = arr[0]; + for (int i = 1; i < n; ++i) { + ans += delim; + ans += arr[i]; + } + return ans; + } + + string build_gesture_begin() { + string device = "\\s*(\\S+)\\s*"; + string gesture = "\\s*GESTURE_SWIPE_BEGIN\\s*"; + string seconds = "\\s*(\\S+)\\s*"; + string fingers = "\\s*(\\d+)\\s*"; + string arr[] = {device, gesture, seconds, fingers}; + return join("\\s+", arr, 4); + } + + string build_gesture_update() { + string device = "\\s*(\\S+)\\s*"; + string gesture = "\\s*GESTURE_SWIPE_UPDATE\\s*"; + string seconds = "\\s*(\\S+)\\s*"; + string fingers = "\\s*(\\d+)\\s*"; + string num_1 = "\\s*(" + number_regex() + ")\\s*"; + string num_2 = num_1; + string num_div = num_1 + "/" + num_2; + string num_accel = "\\s*\\(\\s*" + num_div + "\\s*unaccelerated\\s*\\)\\s*"; + string arr[] = {device, gesture, seconds, fingers, num_div, num_accel}; + return join("\\s+", arr, 6); + } + + string build_gesture_end() { + string device = "\\s*(\\S+)\\s*"; + string gesture = "\\s*GESTURE_SWIPE_END\\s*"; + string seconds = "\\s*(\\S+)\\s*"; + string fingers = "\\s*(\\d+)\\s*"; + string arr[] = {device, gesture, seconds, fingers}; + return join("\\s+", arr, 4); + } + +}