Reorganize source files (#41)
* Remove unused device and stamp from swipe_impl
* Use constants for regex patterns
* Compile regex outside of buffer function to avoid runtime hiccup
* Optimize reading of config file
* Revert "Optimize reading of config file"
This reverts commit 88b85d3941.
* Improve tokenizing of config file
* Make sentence string static
* Improve README; change default threshold to 20.0
* Add a flag for gesture begin to ignore unneeded update/end
* Pre-compute for square of threshold and scale to lessen computation
* Compare fingers string with only one digit
* Use fgets_unlocked for faster input stream reading
* Don't buffer error stream
* Set some variables to static
* Catch dash symbol before event, remove trimming
* Use const char* for conf_filename
* Fix error in printing help
* Add some test scripts
* Add service module
* Add gesture module
* Add util module
* Add index files
* Decouple header files
* Add licenses in headers
* Move files to lib
* Modify install script
* Update install script
This commit is contained in:
parent
e3453c1bbb
commit
e2e534ea2f
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# C++ generated headers
|
||||||
|
*.gch
|
||||||
20
install
20
install
@ -9,8 +9,6 @@ OLD_CONF_PATH=${XDG_CONFIG_HOME:-$HOME/.config}/comfortable-swipe.conf
|
|||||||
if [ -x "$(command -v $PROGRAM)" ]; then
|
if [ -x "$(command -v $PROGRAM)" ]; then
|
||||||
# stop any running comfortable-swipe if it exists
|
# stop any running comfortable-swipe if it exists
|
||||||
$PROGRAM stop
|
$PROGRAM stop
|
||||||
# remove existing comfortable-swipe
|
|
||||||
rm $(which comfortable-swipe)
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
#copy config file
|
#copy config file
|
||||||
@ -43,11 +41,19 @@ else
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
echo "Installing..."
|
|
||||||
# mkdir -p ~/.local/bin
|
|
||||||
sudo g++ -std=c++11 -O2 $DIR/src/comfortable-swipe.cpp -lxdo -o $PROGRAM || exec echo "Installation aborted"
|
|
||||||
|
|
||||||
GROUP=$(ls -l /dev/input/event* | awk '{print $4}' | head --line=1) || abort
|
echo "Installing..."
|
||||||
|
|
||||||
|
# remove existing comfortable-swipe
|
||||||
|
if [ -x "$(command -v $PROGRAM)" ]; then
|
||||||
|
sudo rm -f $(which comfortable-swipe)
|
||||||
|
fi
|
||||||
|
|
||||||
|
# compile library
|
||||||
|
sudo $DIR/src/compile $PROGRAM || abort
|
||||||
|
|
||||||
|
# add permissions to input group (defer)
|
||||||
|
# GROUP=$(ls -l /dev/input/event* | awk '{print $4}' | head --line=1) || abort
|
||||||
|
|
||||||
# toggle autostart twice to refresh any changes
|
# toggle autostart twice to refresh any changes
|
||||||
$PROGRAM autostart > /dev/null || abort
|
$PROGRAM autostart > /dev/null || abort
|
||||||
@ -56,4 +62,4 @@ $PROGRAM autostart > /dev/null || abort
|
|||||||
echo "Successfully installed comfortable-swipe."
|
echo "Successfully installed comfortable-swipe."
|
||||||
echo "Configuration file is located at $CONF_PATH"
|
echo "Configuration file is located at $CONF_PATH"
|
||||||
echo ""
|
echo ""
|
||||||
echo "Try running 'comfortable-swipe start' to test."
|
echo "Try running 'comfortable-swipe start' to test."
|
||||||
|
|||||||
@ -1,17 +0,0 @@
|
|||||||
#include "comfortable-swipe.hpp"
|
|
||||||
/* MAIN DRIVER FUNCTION */
|
|
||||||
|
|
||||||
int main(int argc, char** args) {
|
|
||||||
if (argc > 1) {
|
|
||||||
string arg = args[1];
|
|
||||||
// select based on argument
|
|
||||||
if (arg == "start") service::start();
|
|
||||||
else if (arg == "stop") service::stop();
|
|
||||||
else if (arg == "restart") service::restart();
|
|
||||||
else if (arg == "buffer") service::buffer();
|
|
||||||
else if (arg == "autostart") service::autostart();
|
|
||||||
else service::help();
|
|
||||||
} else {
|
|
||||||
service::help();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,439 +0,0 @@
|
|||||||
/*
|
|
||||||
Comfortable Swipe
|
|
||||||
by Rico Tiongson
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <fstream>
|
|
||||||
#include <sstream>
|
|
||||||
#include <map>
|
|
||||||
#include <cstdio>
|
|
||||||
#include <cstring>
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <cstdarg>
|
|
||||||
#include <cassert>
|
|
||||||
#include <cmath>
|
|
||||||
#include <regex>
|
|
||||||
#include <chrono>
|
|
||||||
#include <ctime>
|
|
||||||
#include <unistd.h>
|
|
||||||
#define cstr const string&
|
|
||||||
#define PROGRAM "/usr/local/bin/comfortable-swipe"
|
|
||||||
#define CONFIG "/usr/local/share/comfortable-swipe/comfortable-swipe.conf"
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
// sudo apt install libxdo-dev
|
|
||||||
#include <xdo.h>
|
|
||||||
}
|
|
||||||
|
|
||||||
/* MASKS FOR GESTURES */
|
|
||||||
|
|
||||||
#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
|
|
||||||
|
|
||||||
/* GESTURE MNEMONYMS */
|
|
||||||
#define FRESH -1
|
|
||||||
#define OPPOSITE (mask ^ MSK_POSITIVE)
|
|
||||||
|
|
||||||
/* FORWARD DECLARATIONS */
|
|
||||||
|
|
||||||
namespace util {
|
|
||||||
extern const char* GESTURE_SWIPE_BEGIN_REGEX_PATTERN;
|
|
||||||
extern const char* GESTURE_SWIPE_UPDATE_REGEX_PATTERN;
|
|
||||||
extern const char* GESTURE_SWIPE_END_REGEX_PATTERN;
|
|
||||||
map<string, string> read_config_file(const char*);
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace service {
|
|
||||||
void buffer();
|
|
||||||
void start();
|
|
||||||
void stop();
|
|
||||||
void restart();
|
|
||||||
void autostart();
|
|
||||||
void help();
|
|
||||||
}
|
|
||||||
|
|
||||||
struct swipe_gesture {
|
|
||||||
string 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);}
|
|
||||||
};
|
|
||||||
|
|
||||||
const char* const command_map[] = {
|
|
||||||
"left 3",
|
|
||||||
"left 4",
|
|
||||||
"right 3",
|
|
||||||
"right 4",
|
|
||||||
"up 3",
|
|
||||||
"up 4",
|
|
||||||
"down 3",
|
|
||||||
"down 4"
|
|
||||||
};
|
|
||||||
|
|
||||||
struct swipe_gesture_impl : swipe_gesture {
|
|
||||||
int screen_num, ix, iy;
|
|
||||||
float x, y, threshold_squared;
|
|
||||||
int previous_gesture;
|
|
||||||
const char** commands;
|
|
||||||
swipe_gesture_impl(
|
|
||||||
const float threshold,
|
|
||||||
const char* left3 /* 000 */,
|
|
||||||
const char* left4 /* 001 */,
|
|
||||||
const char* right3 /* 010 */,
|
|
||||||
const char* right4 /* 011 */,
|
|
||||||
const char* up3 /* 100 */,
|
|
||||||
const char* up4 /* 101 */,
|
|
||||||
const char* down3 /* 110 */,
|
|
||||||
const char* down4 /* 111 */
|
|
||||||
): swipe_gesture(), threshold_squared(threshold*threshold) {
|
|
||||||
commands = new const char*[8];
|
|
||||||
commands[0] = left3;
|
|
||||||
commands[1] = left4;
|
|
||||||
commands[2] = right3;
|
|
||||||
commands[3] = right4;
|
|
||||||
commands[4] = up3;
|
|
||||||
commands[5] = up4;
|
|
||||||
commands[6] = down3;
|
|
||||||
commands[7] = down4;
|
|
||||||
}
|
|
||||||
~swipe_gesture_impl() {
|
|
||||||
delete[] commands;
|
|
||||||
}
|
|
||||||
void key(const char* cmd) const {
|
|
||||||
xdo_send_keysequence_window(xdo, CURRENTWINDOW, cmd, 0);
|
|
||||||
}
|
|
||||||
void on_begin() override {
|
|
||||||
xdo_get_mouse_location(xdo, &ix, &iy, &screen_num);
|
|
||||||
previous_gesture = FRESH;
|
|
||||||
x = 0;
|
|
||||||
y = 0;
|
|
||||||
}
|
|
||||||
void on_update() override {
|
|
||||||
x += stof(dx);
|
|
||||||
y += stof(dy);
|
|
||||||
// scale threshold to 1/10 when gesture is not fresh
|
|
||||||
float scale = previous_gesture == FRESH
|
|
||||||
? 1.00f
|
|
||||||
: 0.01f; // square root of 1/10
|
|
||||||
if (x*x + y*y > threshold_squared*scale) {
|
|
||||||
int mask = 0;
|
|
||||||
if (fingers[0] == '3') mask |= MSK_THREE_FINGERS; else
|
|
||||||
if (fingers[0] == '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;
|
|
||||||
}
|
|
||||||
// send command on fresh OR opposite gesture
|
|
||||||
if (previous_gesture == FRESH or previous_gesture == OPPOSITE) {
|
|
||||||
x = y = 0;
|
|
||||||
previous_gesture = mask;
|
|
||||||
cout << "SWIPE " << command_map[mask] << endl;
|
|
||||||
key(commands[mask]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void on_end() override {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// path services
|
|
||||||
namespace service {
|
|
||||||
// get the full path of the .conf file
|
|
||||||
const char* conf_filename() {
|
|
||||||
return CONFIG;
|
|
||||||
}
|
|
||||||
// get the full path of the .desktop file associated
|
|
||||||
// with the autostart feature
|
|
||||||
string autostart_filename() {
|
|
||||||
static string *filename = NULL;
|
|
||||||
if (filename == NULL) {
|
|
||||||
const char* xdg_config = getenv("XDG_CONFIG_HOME");
|
|
||||||
string config(
|
|
||||||
xdg_config == NULL
|
|
||||||
? string(getenv("HOME")) + "/.config"
|
|
||||||
: xdg_config
|
|
||||||
);
|
|
||||||
filename = new string(config
|
|
||||||
+ "/autostart/comfortable-swipe.desktop");
|
|
||||||
}
|
|
||||||
return *filename;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace service {
|
|
||||||
|
|
||||||
// process regex at compile time
|
|
||||||
const regex gesture_begin(util::GESTURE_SWIPE_BEGIN_REGEX_PATTERN);
|
|
||||||
const regex gesture_update(util::GESTURE_SWIPE_UPDATE_REGEX_PATTERN);
|
|
||||||
const regex gesture_end(util::GESTURE_SWIPE_END_REGEX_PATTERN);
|
|
||||||
|
|
||||||
// parses output from libinput debug-events
|
|
||||||
void buffer() {
|
|
||||||
int c = clock();
|
|
||||||
// check first if $user
|
|
||||||
ios::sync_with_stdio(false);
|
|
||||||
cin.tie(0); cout.tie(0);
|
|
||||||
// read config file
|
|
||||||
auto config = util::read_config_file(conf_filename());
|
|
||||||
// initialize gesture handler
|
|
||||||
swipe_gesture_impl swipe(
|
|
||||||
config.count("threshold") ? stof(config["threshold"]) : 0.0,
|
|
||||||
config["left3"].c_str(),
|
|
||||||
config["left4"].c_str(),
|
|
||||||
config["right3"].c_str(),
|
|
||||||
config["right4"].c_str(),
|
|
||||||
config["up3"].c_str(),
|
|
||||||
config["up4"].c_str(),
|
|
||||||
config["down3"].c_str(),
|
|
||||||
config["down4"].c_str()
|
|
||||||
);
|
|
||||||
// start reading lines from input one by one
|
|
||||||
static const int MAX_LINE_LENGTH = 256;
|
|
||||||
static char data[MAX_LINE_LENGTH];
|
|
||||||
static cmatch matches;
|
|
||||||
bool flag_begin = false;
|
|
||||||
while (fgets_unlocked(data, MAX_LINE_LENGTH, stdin) != NULL) {
|
|
||||||
if (!flag_begin) {
|
|
||||||
if (regex_match(data, matches, gesture_begin)) {
|
|
||||||
swipe.fingers = matches[1];
|
|
||||||
swipe.on_begin();
|
|
||||||
flag_begin = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (regex_match(data, matches, gesture_update)) {
|
|
||||||
swipe.fingers = matches[1];
|
|
||||||
swipe.dx = matches[2];
|
|
||||||
swipe.dy = matches[3];
|
|
||||||
swipe.udx = matches[4];
|
|
||||||
swipe.udy = matches[5];
|
|
||||||
swipe.on_update();
|
|
||||||
} else if (regex_match(data, matches, gesture_end)) {
|
|
||||||
swipe.fingers = matches[1];
|
|
||||||
swipe.on_end();
|
|
||||||
flag_begin = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// starts service
|
|
||||||
void start() {
|
|
||||||
int x = system("stdbuf -oL -e0 libinput debug-events | " PROGRAM " buffer");
|
|
||||||
}
|
|
||||||
// stops service
|
|
||||||
void stop() {
|
|
||||||
// kill all comfortable-swipe, except self
|
|
||||||
char* buffer = new char[20];
|
|
||||||
FILE* pipe = popen("pgrep -f comfortable-swipe", "r");
|
|
||||||
if (!pipe) throw std::runtime_error("stop command failed");
|
|
||||||
string kill = "kill";
|
|
||||||
while (!feof(pipe)) {
|
|
||||||
if (fgets(buffer, 20, pipe) != NULL) {
|
|
||||||
int pid = atoi(buffer);
|
|
||||||
if (pid != getpid()) {
|
|
||||||
kill += " " + to_string(pid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int result = system(kill.data());
|
|
||||||
delete[] buffer;
|
|
||||||
pclose(pipe);
|
|
||||||
}
|
|
||||||
// stops then starts service
|
|
||||||
void restart() {
|
|
||||||
service::stop();
|
|
||||||
service::start();
|
|
||||||
}
|
|
||||||
// toggle automatically start application on startup
|
|
||||||
void autostart() {
|
|
||||||
cstr path = autostart_filename();
|
|
||||||
if (ifstream(path.data()).good()) {
|
|
||||||
// file found, delete it
|
|
||||||
if (remove(path.data()) != 0)
|
|
||||||
cerr << "Error: failed to switch off autostart. "
|
|
||||||
<< "Maybe the autostart file is in use?"
|
|
||||||
<< endl;
|
|
||||||
else
|
|
||||||
cout << "Autostart switched off" << endl;
|
|
||||||
} else {
|
|
||||||
// file not found, create it
|
|
||||||
int result = system(("mkdir -p $(dirname " + path + ")").data());
|
|
||||||
ofstream fout(path.data());
|
|
||||||
if (result != 0 || !fout.good())
|
|
||||||
cerr << "Error: failed to switch on autostart. "
|
|
||||||
<< "Are you sure you have the permissions?"
|
|
||||||
<< endl;
|
|
||||||
else {
|
|
||||||
fout <<
|
|
||||||
"[Desktop Entry]\n"
|
|
||||||
"Type=Application\n"
|
|
||||||
"Exec=bash -c \"" PROGRAM " start\"\n"
|
|
||||||
"Hidden=false\n"
|
|
||||||
"NoDisplay=false\n"
|
|
||||||
"X-GNOME-Autostart-enabled=true\n"
|
|
||||||
"Name=Comfortable Swipe\n"
|
|
||||||
"Comment=3 or 4 touchpad gestures\n";
|
|
||||||
cout << "Autostart switched on" << endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// shows help
|
|
||||||
void help() {
|
|
||||||
puts("comfortable-swipe [start|stop|restart|autostart|buffer|help]");
|
|
||||||
puts("");
|
|
||||||
puts("start - starts 3/4-finger gesture service");
|
|
||||||
puts("stop - stops 3/4-finger gesture service");
|
|
||||||
puts("restart - stops then starts 3/4-finger gesture service");
|
|
||||||
puts("autostart - automatically run on startup (toggleable)");
|
|
||||||
puts("buffer - parses output of libinput debug-events");
|
|
||||||
puts("help - shows the help dialog");
|
|
||||||
puts("");
|
|
||||||
printf("Configuration file can be found in %s", conf_filename());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* UTILITY FUNCTIONS */
|
|
||||||
|
|
||||||
namespace util {
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Regex pattern for the libinput entry for start of swipe.
|
|
||||||
* Extracts one match for the number of fingers used during the swipe.
|
|
||||||
*
|
|
||||||
* eg. event15 GESTURE_SWIPE_BEGIN +34.33s 3
|
|
||||||
* ^
|
|
||||||
* fingers
|
|
||||||
*/
|
|
||||||
const char* GESTURE_SWIPE_BEGIN_REGEX_PATTERN =
|
|
||||||
"^" // start of string
|
|
||||||
"[ -]event\\d+" // event
|
|
||||||
"\\s+GESTURE_SWIPE_BEGIN" // gesture
|
|
||||||
"\\s+\\S+" // timestamp
|
|
||||||
"\\s+(\\d+)" // fingers
|
|
||||||
"\\s*$" // end of string
|
|
||||||
;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Regex pattern for the libinput entry for the end of swipe.
|
|
||||||
* Extracts one match for the number of fingers used during the swipe.
|
|
||||||
*
|
|
||||||
* eg. event15 GESTURE_SWIPE_END +35.03s 3
|
|
||||||
* ^
|
|
||||||
* fingers
|
|
||||||
*/
|
|
||||||
const char* GESTURE_SWIPE_END_REGEX_PATTERN =
|
|
||||||
"^" // start of string
|
|
||||||
"[ -]event\\d+" // event
|
|
||||||
"\\s+GESTURE_SWIPE_END" // gesture
|
|
||||||
"\\s+\\S+" // timestamp
|
|
||||||
"\\s+(\\d+)" // fingers
|
|
||||||
"\\s*$" // end of string
|
|
||||||
;
|
|
||||||
|
|
||||||
// matches signed decimal numbers (eg. "6.02" "-1.1")
|
|
||||||
#define CF_NUMBER_REGEX "-?\\d+(?:\\.\\d+)"
|
|
||||||
|
|
||||||
// matches and extracts a space-prefixed signed fraction (eg. "-3.00/ 5.12")
|
|
||||||
#define CF_NUMBER_DIVISION "\\s*(" CF_NUMBER_REGEX ")/\\s*(" CF_NUMBER_REGEX ")"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Regex pattern for the libinput entry for during a swipe.
|
|
||||||
* Extracts number of fingers used and the speed (normal and accelerated) of the swipe.
|
|
||||||
*
|
|
||||||
* eg. event15 GESTURE_SWIPE_UPDATE +34.70s 3 -0.12/ 4.99 (-0.33/13.50 unaccelerated)
|
|
||||||
* ^ ^ ^ ^ ^
|
|
||||||
* fingers dx dy udx udy
|
|
||||||
*/
|
|
||||||
const char* GESTURE_SWIPE_UPDATE_REGEX_PATTERN =
|
|
||||||
"^" // start of string
|
|
||||||
"[ -]event\\d+" // event
|
|
||||||
"\\s+GESTURE_SWIPE_UPDATE" // gesture
|
|
||||||
"\\s+\\S+" // timestamp
|
|
||||||
"\\s+(\\d+)" // fingers
|
|
||||||
"\\s+" CF_NUMBER_DIVISION // speed (dx/dy)
|
|
||||||
"\\s+\\(" CF_NUMBER_DIVISION "\\s+unaccelerated\\)" // unaccelerated speed (udx/udy)
|
|
||||||
"\\s*$" // end of string
|
|
||||||
;
|
|
||||||
|
|
||||||
// delete macros
|
|
||||||
#undef CF_NUMBER_DIVISION
|
|
||||||
#undef CF_NUMBER_EXTRACT
|
|
||||||
#undef CF_NUMBER_REGEX
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A utility method for reading the config file.
|
|
||||||
*
|
|
||||||
* @param filename (const char*) the path of the config file.
|
|
||||||
*/
|
|
||||||
map<string, string> read_config_file(const char* filename) {
|
|
||||||
map<string, string> conf;
|
|
||||||
ifstream fin(filename);
|
|
||||||
if (!fin.is_open()) {
|
|
||||||
cerr << "file \"" << filename << "\" does not exist!" << endl;
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
static string line, token[2];
|
|
||||||
int line_number = 0;
|
|
||||||
while (getline(fin, line)) {
|
|
||||||
++line_number;
|
|
||||||
token[0].clear();
|
|
||||||
token[1].clear();
|
|
||||||
int length = line.length();
|
|
||||||
int equal_flag = 0;
|
|
||||||
for (int i = 0; i < length; ++i) {
|
|
||||||
if (line[i] == '#')
|
|
||||||
break;
|
|
||||||
if (line[i] == '=') {
|
|
||||||
if (++equal_flag > 1) {
|
|
||||||
cerr << "error in conf file " << filename << endl;
|
|
||||||
cerr << "multiple equal signs in line " << line_number << endl;
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
} else if (!isspace(line[i])) {
|
|
||||||
token[equal_flag].push_back(line[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// ignore empty lines
|
|
||||||
if (equal_flag == 0 && token[0].length() == 0)
|
|
||||||
continue;
|
|
||||||
if (equal_flag == 0) {
|
|
||||||
cerr << "error in conf file: " << filename << endl;
|
|
||||||
cerr << "equal sign expected in line " << line_number << endl;
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
if (equal_flag == 1 && token[1].length() > 0) {
|
|
||||||
conf[token[0]] = token[1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return conf;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
2
src/compile
Executable file
2
src/compile
Executable file
@ -0,0 +1,2 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
g++ $(dirname $0)/main.cpp -std=c++11 -O2 -lxdo -Wno-unused-result -o $1
|
||||||
40
src/lib/comfortable_swipe
Normal file
40
src/lib/comfortable_swipe
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#ifndef __COMFORTABLE_SWIPE__
|
||||||
|
#define __COMFORTABLE_SWIPE__
|
||||||
|
|
||||||
|
/*
|
||||||
|
Comfortable Swipe
|
||||||
|
by Rico Tiongson
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "index.hpp"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make sure to include all implementation (.cpp) files below to be ready for export.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "gesture/swipe_gesture.cpp"
|
||||||
|
#include "service/autostart.cpp"
|
||||||
|
#include "service/buffer.cpp"
|
||||||
|
#include "service/help.cpp"
|
||||||
|
#include "service/restart.cpp"
|
||||||
|
#include "service/start.cpp"
|
||||||
|
#include "service/stop.cpp"
|
||||||
|
#include "util/autostart_filename.cpp"
|
||||||
|
#include "util/conf_filename.cpp"
|
||||||
|
#include "util/read_config_file.cpp"
|
||||||
|
#include "util/regex.cpp"
|
||||||
|
|
||||||
|
#endif /* __COMFORTABLE_SWIPE__ */
|
||||||
150
src/lib/gesture/swipe_gesture.cpp
Normal file
150
src/lib/gesture/swipe_gesture.cpp
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
#ifndef __COMFORTABLE_SWIPE__gesture_swipe_gesture__
|
||||||
|
#define __COMFORTABLE_SWIPE__gesture_swipe_gesture__
|
||||||
|
|
||||||
|
/*
|
||||||
|
Comfortable Swipe
|
||||||
|
by Rico Tiongson
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream> // std::cout, std::endl
|
||||||
|
#include "../index.hpp"
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#include <xdo.h> // xdo, xdo_new, xdo_free,
|
||||||
|
// xdo_get_mouse_location
|
||||||
|
// CURRENT_WINDOW
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace comfortable_swipe
|
||||||
|
{
|
||||||
|
namespace gesture
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Constructs a new swipe gesture with xdo.
|
||||||
|
*/
|
||||||
|
swipe_gesture::swipe_gesture
|
||||||
|
(
|
||||||
|
const float threshold,
|
||||||
|
const char* left3 /* 000 */,
|
||||||
|
const char* left4 /* 001 */,
|
||||||
|
const char* right3 /* 010 */,
|
||||||
|
const char* right4 /* 011 */,
|
||||||
|
const char* up3 /* 100 */,
|
||||||
|
const char* up4 /* 101 */,
|
||||||
|
const char* down3 /* 110 */,
|
||||||
|
const char* down4 /* 111 */
|
||||||
|
):
|
||||||
|
xdo(xdo_new(NULL)),
|
||||||
|
commands(new const char*[8]{left3, left4, right3, right4, up3, up4, down3, down4})
|
||||||
|
{ }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new swipe gesture with xdo.
|
||||||
|
*/
|
||||||
|
swipe_gesture::~swipe_gesture()
|
||||||
|
{
|
||||||
|
xdo_free(this->xdo);
|
||||||
|
delete[] commands;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook on begin of swipe gesture.
|
||||||
|
*/
|
||||||
|
void swipe_gesture::begin()
|
||||||
|
{
|
||||||
|
xdo_get_mouse_location(this->xdo, &this->ix, &this->iy, &this->screen_num);
|
||||||
|
this->previous_gesture = swipe_gesture::FRESH;
|
||||||
|
this->x = 0;
|
||||||
|
this->y = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook on update of swipe gesture.
|
||||||
|
*/
|
||||||
|
void swipe_gesture::update()
|
||||||
|
{
|
||||||
|
this->x += this->dx;
|
||||||
|
this->y += this->dy;
|
||||||
|
// scale threshold to 1/10 when gesture is not fresh
|
||||||
|
float scale = this->previous_gesture == swipe_gesture::FRESH
|
||||||
|
? 1.00f
|
||||||
|
: 0.01f; // square root of 1/10
|
||||||
|
if (this->x * this->x + this->y * this->y > this->threshold_squared * scale)
|
||||||
|
{
|
||||||
|
int mask = 0;
|
||||||
|
if (this->fingers == 3) mask |= swipe_gesture::MSK_THREE_FINGERS;
|
||||||
|
else if (this->fingers == 4) mask |= swipe_gesture::MSK_FOUR_FINGERS;
|
||||||
|
|
||||||
|
const float absx = x >= 0 ? x : -x;
|
||||||
|
const float absy = y >= 0 ? y : -y;
|
||||||
|
if (absx > absy)
|
||||||
|
{ // horizontal
|
||||||
|
mask |= swipe_gesture::MSK_HORIZONTAL;
|
||||||
|
if (x < 0)
|
||||||
|
mask |= swipe_gesture::MSK_NEGATIVE;
|
||||||
|
else
|
||||||
|
mask |= swipe_gesture::MSK_POSITIVE;
|
||||||
|
}
|
||||||
|
else /* std::abs(x) <= std::abs(y) */
|
||||||
|
{ // vertical
|
||||||
|
mask |= swipe_gesture::MSK_VERTICAL;
|
||||||
|
if (y < 0)
|
||||||
|
mask |= swipe_gesture::MSK_NEGATIVE;
|
||||||
|
else
|
||||||
|
mask |= swipe_gesture::MSK_POSITIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// send command on fresh OR opposite gesture
|
||||||
|
if (this->previous_gesture == swipe_gesture::FRESH
|
||||||
|
|| this->previous_gesture == (mask ^ swipe_gesture::MSK_POSITIVE))
|
||||||
|
{
|
||||||
|
this->x = this->y = 0;
|
||||||
|
this->previous_gesture = mask;
|
||||||
|
std::cout << "SWIPE " << swipe_gesture::command_map[mask] << std::endl;
|
||||||
|
xdo_send_keysequence_window(xdo, CURRENTWINDOW, swipe_gesture::commands[mask], 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook on end of swipe gesture.
|
||||||
|
*/
|
||||||
|
void swipe_gesture::end()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
/* STATICS DEFINITIONS */
|
||||||
|
const int swipe_gesture::MSK_THREE_FINGERS = 0;
|
||||||
|
const int swipe_gesture::MSK_FOUR_FINGERS = 1;
|
||||||
|
const int swipe_gesture::MSK_NEGATIVE = 0;
|
||||||
|
const int swipe_gesture::MSK_POSITIVE = 2;
|
||||||
|
const int swipe_gesture::MSK_HORIZONTAL = 0;
|
||||||
|
const int swipe_gesture::MSK_VERTICAL = 4;
|
||||||
|
const int swipe_gesture::FRESH = -1;
|
||||||
|
const char * const swipe_gesture::command_map[8] = {
|
||||||
|
"left 3",
|
||||||
|
"left 4",
|
||||||
|
"right 3",
|
||||||
|
"right 4",
|
||||||
|
"up 3",
|
||||||
|
"up 4",
|
||||||
|
"down 3",
|
||||||
|
"down 4"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __COMFORTABLE_SWIPE__gesture_swipe_gesture__ */
|
||||||
87
src/lib/gesture/swipe_gesture.h
Normal file
87
src/lib/gesture/swipe_gesture.h
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
#ifndef __COMFORTABLE_SWIPE__gesture_swipe_gesture_h__
|
||||||
|
#define __COMFORTABLE_SWIPE__gesture_swipe_gesture_h__
|
||||||
|
|
||||||
|
/*
|
||||||
|
Comfortable Swipe
|
||||||
|
by Rico Tiongson
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#include <xdo.h> // xdo_t
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace comfortable_swipe
|
||||||
|
{
|
||||||
|
namespace gesture
|
||||||
|
{
|
||||||
|
struct swipe_gesture
|
||||||
|
{
|
||||||
|
// constructor
|
||||||
|
swipe_gesture(
|
||||||
|
const float,
|
||||||
|
const char*,
|
||||||
|
const char*,
|
||||||
|
const char*,
|
||||||
|
const char*,
|
||||||
|
const char*,
|
||||||
|
const char*,
|
||||||
|
const char*,
|
||||||
|
const char*
|
||||||
|
);
|
||||||
|
|
||||||
|
~swipe_gesture();
|
||||||
|
|
||||||
|
// fields for xdo
|
||||||
|
int fingers;
|
||||||
|
float dx, dy, udx, udy;
|
||||||
|
xdo_t * xdo;
|
||||||
|
|
||||||
|
// location of mouse
|
||||||
|
int screen_num, ix, iy;
|
||||||
|
|
||||||
|
// current location
|
||||||
|
float x, y, threshold_squared;
|
||||||
|
int previous_gesture;
|
||||||
|
const char ** commands;
|
||||||
|
|
||||||
|
// hooks
|
||||||
|
void update();
|
||||||
|
void begin();
|
||||||
|
void end();
|
||||||
|
|
||||||
|
// statics
|
||||||
|
static const int MSK_THREE_FINGERS;
|
||||||
|
static const int MSK_FOUR_FINGERS;
|
||||||
|
static const int MSK_NEGATIVE;
|
||||||
|
static const int MSK_POSITIVE;
|
||||||
|
static const int MSK_HORIZONTAL;
|
||||||
|
static const int MSK_VERTICAL;
|
||||||
|
static const int FRESH;
|
||||||
|
static const char * const command_map[8];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __COMFORTABLE_SWIPE__gesture_swipe_gesture_h__ */
|
||||||
60
src/lib/index.hpp
Normal file
60
src/lib/index.hpp
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
#ifndef __COMFORTABLE_SWIPE__index_hpp__
|
||||||
|
#define __COMFORTABLE_SWIPE__index_hpp__
|
||||||
|
|
||||||
|
/*
|
||||||
|
Comfortable Swipe
|
||||||
|
by Rico Tiongson
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// global defines
|
||||||
|
#ifndef __COMFORTABLE_SWIPE__PROGRAM__
|
||||||
|
#define __COMFORTABLE_SWIPE__PROGRAM__ "/usr/local/bin/comfortable-swipe"
|
||||||
|
#endif /* __COMFORTABLE_SWIPE__PROGRAM__ */
|
||||||
|
|
||||||
|
#ifndef __COMFORTABLE_SWIPE__CONFIG__
|
||||||
|
#define __COMFORTABLE_SWIPE__CONFIG__ "/usr/local/share/comfortable-swipe/comfortable-swipe.conf"
|
||||||
|
#endif /* __COMFORTABLE_SWIPE__CONFIG__ */
|
||||||
|
|
||||||
|
#include <map> // std::map
|
||||||
|
#include <string> // std::string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make sure to include your header files here so that they can be imported by other modules.
|
||||||
|
*/
|
||||||
|
#include "gesture/swipe_gesture.h"
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
namespace comfortable_swipe::util
|
||||||
|
{
|
||||||
|
extern const char* GESTURE_SWIPE_BEGIN_REGEX_PATTERN;
|
||||||
|
extern const char* GESTURE_SWIPE_UPDATE_REGEX_PATTERN;
|
||||||
|
extern const char* GESTURE_SWIPE_END_REGEX_PATTERN;
|
||||||
|
const char* autostart_filename();
|
||||||
|
constexpr const char* conf_filename();
|
||||||
|
std::map<std::string, std::string> read_config_file(const char*);
|
||||||
|
}
|
||||||
|
namespace comfortable_swipe::service
|
||||||
|
{
|
||||||
|
void autostart();
|
||||||
|
void buffer();
|
||||||
|
void help();
|
||||||
|
void restart();
|
||||||
|
void start();
|
||||||
|
void stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __COMFORTABLE_SWIPE__index_hpp__ */
|
||||||
75
src/lib/service/autostart.cpp
Normal file
75
src/lib/service/autostart.cpp
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
#ifndef __COMFORTABLE_SWIPE__service_autostart__
|
||||||
|
#define __COMFORTABLE_SWIPE__service_autostart__
|
||||||
|
|
||||||
|
/*
|
||||||
|
Comfortable Swipe
|
||||||
|
by Rico Tiongson
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream> // std::cerr, std::cout, std::endl
|
||||||
|
#include <fstream> // std::ifstream, std::ofstream
|
||||||
|
#include <string> // std::string
|
||||||
|
#include <cstdio> // std::remove
|
||||||
|
#include <cstdlib> // std::system
|
||||||
|
#include "../index.hpp"
|
||||||
|
|
||||||
|
namespace comfortable_swipe::service
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Toggles automatic startup of comfortable swipe.
|
||||||
|
*/
|
||||||
|
void autostart()
|
||||||
|
{
|
||||||
|
using comfortable_swipe::util::autostart_filename;
|
||||||
|
|
||||||
|
const std::string& path = autostart_filename();
|
||||||
|
if (std::ifstream(path.data()).good())
|
||||||
|
{
|
||||||
|
// file found, delete it
|
||||||
|
if (std::remove(path.data()) != 0)
|
||||||
|
std::cerr << "Error: failed to switch off autostart. "
|
||||||
|
<< "Maybe the autostart file is in use?"
|
||||||
|
<< std::endl;
|
||||||
|
else
|
||||||
|
std::cout << "Autostart switched off" << std::endl;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// file not found, create it
|
||||||
|
int result = std::system(("mkdir -p $(dirname " + path + ")").data());
|
||||||
|
std::ofstream fout(path.data());
|
||||||
|
if (result != 0 || !fout.good())
|
||||||
|
std::cerr << "Error: failed to switch on autostart. "
|
||||||
|
<< "Are you sure you have the permissions?"
|
||||||
|
<< std::endl;
|
||||||
|
else {
|
||||||
|
fout <<
|
||||||
|
"[Desktop Entry]\n"
|
||||||
|
"Type=Application\n"
|
||||||
|
"Exec=bash -c \""
|
||||||
|
__COMFORTABLE_SWIPE__PROGRAM__
|
||||||
|
" start\"\n"
|
||||||
|
"Hidden=false\n"
|
||||||
|
"NoDisplay=false\n"
|
||||||
|
"X-GNOME-Autostart-enabled=true\n"
|
||||||
|
"Name=Comfortable Swipe\n"
|
||||||
|
"Comment=3 or 4 touchpad gestures\n";
|
||||||
|
std::cout << "Autostart switched on" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __COMFORTABLE_SWIPE__service_autostart__ */
|
||||||
106
src/lib/service/buffer.cpp
Normal file
106
src/lib/service/buffer.cpp
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
#ifndef __COMFORTABLE_SWIPE__service_buffer__
|
||||||
|
#define __COMFORTABLE_SWIPE__service_buffer__
|
||||||
|
|
||||||
|
/*
|
||||||
|
Comfortable Swipe
|
||||||
|
by Rico Tiongson
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string> // std::stoi, std::stof
|
||||||
|
#include <cstdio> // std::fgets_unlocked, stdin
|
||||||
|
#include <regex> // std::regex, std::regex_match, std::cmatch
|
||||||
|
#include "../index.hpp"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts the comfortable-swipe service by buffering libinput debug-events.
|
||||||
|
*/
|
||||||
|
void comfortable_swipe::service::buffer()
|
||||||
|
{
|
||||||
|
|
||||||
|
// import utility methods
|
||||||
|
using comfortable_swipe::util::read_config_file;
|
||||||
|
using comfortable_swipe::util::conf_filename;
|
||||||
|
using comfortable_swipe::gesture::swipe_gesture;
|
||||||
|
|
||||||
|
// import regex patterns
|
||||||
|
using comfortable_swipe::util::GESTURE_SWIPE_BEGIN_REGEX_PATTERN;
|
||||||
|
using comfortable_swipe::util::GESTURE_SWIPE_UPDATE_REGEX_PATTERN;
|
||||||
|
using comfortable_swipe::util::GESTURE_SWIPE_END_REGEX_PATTERN;
|
||||||
|
|
||||||
|
// pre-compile regex patterns
|
||||||
|
static const std::regex gesture_begin(GESTURE_SWIPE_BEGIN_REGEX_PATTERN);
|
||||||
|
static const std::regex gesture_update(GESTURE_SWIPE_UPDATE_REGEX_PATTERN);
|
||||||
|
static const std::regex gesture_end(GESTURE_SWIPE_END_REGEX_PATTERN);
|
||||||
|
|
||||||
|
// read config file
|
||||||
|
auto config = read_config_file(conf_filename());
|
||||||
|
|
||||||
|
// initialize swipegesture handler
|
||||||
|
swipe_gesture swipe
|
||||||
|
(
|
||||||
|
config.count("threshold") ? std::atof(config["threshold"].data()) : 0.0,
|
||||||
|
config["left3"].c_str(),
|
||||||
|
config["left4"].c_str(),
|
||||||
|
config["right3"].c_str(),
|
||||||
|
config["right4"].c_str(),
|
||||||
|
config["up3"].c_str(),
|
||||||
|
config["up4"].c_str(),
|
||||||
|
config["down3"].c_str(),
|
||||||
|
config["down4"].c_str()
|
||||||
|
);
|
||||||
|
|
||||||
|
// prepare data containers
|
||||||
|
static const int MAX_LINE_LENGTH = 256;
|
||||||
|
static char data[MAX_LINE_LENGTH];
|
||||||
|
static std::cmatch matches;
|
||||||
|
|
||||||
|
// optimization flag for checking if GESTURE_SWIPE_BEGIN was dispatched
|
||||||
|
bool flag_begin = false;
|
||||||
|
|
||||||
|
// start reading lines from input one by one
|
||||||
|
while (fgets_unlocked(data, MAX_LINE_LENGTH, stdin) != NULL)
|
||||||
|
{
|
||||||
|
if (!flag_begin)
|
||||||
|
{
|
||||||
|
if (std::regex_match(data, matches, gesture_begin) != 0)
|
||||||
|
{
|
||||||
|
swipe.fingers = std::stoi(matches[1]);
|
||||||
|
swipe.begin();
|
||||||
|
flag_begin = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else /* flag_begin == true */
|
||||||
|
{
|
||||||
|
if (std::regex_match(data, matches, gesture_update) != 0)
|
||||||
|
{
|
||||||
|
swipe.fingers = std::stoi(matches[1]);
|
||||||
|
swipe.dx = std::stof(matches[2]);
|
||||||
|
swipe.dy = std::stof(matches[3]);
|
||||||
|
swipe.udx = std::stof(matches[4]);
|
||||||
|
swipe.udy = std::stof(matches[5]);
|
||||||
|
swipe.update();
|
||||||
|
}
|
||||||
|
else if (std::regex_match(data, matches, gesture_end) != 0)
|
||||||
|
{
|
||||||
|
swipe.fingers = std::stoi(matches[1]);
|
||||||
|
swipe.end();
|
||||||
|
flag_begin = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __COMFORTABLE_SWIPE__service_buffer__ */
|
||||||
46
src/lib/service/help.cpp
Normal file
46
src/lib/service/help.cpp
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
#ifndef __COMFORTABLE_SWIPE__service_help__
|
||||||
|
#define __COMFORTABLE_SWIPE__service_help__
|
||||||
|
|
||||||
|
/*
|
||||||
|
Comfortable Swipe
|
||||||
|
by Rico Tiongson
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cstdio> // std::puts, std::printf
|
||||||
|
#include "../index.hpp"
|
||||||
|
|
||||||
|
namespace comfortable_swipe::service
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Shows the help window.
|
||||||
|
*/
|
||||||
|
void help()
|
||||||
|
{
|
||||||
|
using comfortable_swipe::util::conf_filename;
|
||||||
|
std::puts("comfortable-swipe [start|stop|restart|autostart|buffer|help]");
|
||||||
|
std::puts("");
|
||||||
|
std::puts("start - starts 3/4-finger gesture service");
|
||||||
|
std::puts("stop - stops 3/4-finger gesture service");
|
||||||
|
std::puts("restart - stops then starts 3/4-finger gesture service");
|
||||||
|
std::puts("autostart - automatically run on startup (toggleable)");
|
||||||
|
std::puts("buffer - parses output of libinput debug-events");
|
||||||
|
std::puts("help - shows the help dialog");
|
||||||
|
std::puts("");
|
||||||
|
std::printf("Configuration file can be found in %s\n", conf_filename());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __COMFORTABLE_SWIPE__service_help__ */
|
||||||
36
src/lib/service/restart.cpp
Normal file
36
src/lib/service/restart.cpp
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#ifndef __COMFORTABLE_SWIPE__service_restart__
|
||||||
|
#define __COMFORTABLE_SWIPE__service_restart__
|
||||||
|
|
||||||
|
/*
|
||||||
|
Comfortable Swipe
|
||||||
|
by Rico Tiongson
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../index.hpp"
|
||||||
|
|
||||||
|
namespace comfortable_swipe::service
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Restarts the comfortable-swipe service.
|
||||||
|
*/
|
||||||
|
void restart()
|
||||||
|
{
|
||||||
|
comfortable_swipe::service::start();
|
||||||
|
comfortable_swipe::service::stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __COMFORTABLE_SWIPE__service_restart__ */
|
||||||
36
src/lib/service/start.cpp
Normal file
36
src/lib/service/start.cpp
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#ifndef __COMFORTABLE_SWIPE__service_start__
|
||||||
|
#define __COMFORTABLE_SWIPE__service_start__
|
||||||
|
|
||||||
|
/*
|
||||||
|
Comfortable Swipe
|
||||||
|
by Rico Tiongson
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../index.hpp"
|
||||||
|
#include <cstdlib> // std::system
|
||||||
|
|
||||||
|
namespace comfortable_swipe::service
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Starts the comfortable-swipe service by buffering libinput debug-events.
|
||||||
|
*/
|
||||||
|
void start()
|
||||||
|
{
|
||||||
|
(void) std::system("stdbuf -oL -e0 libinput debug-events | " __COMFORTABLE_SWIPE__PROGRAM__ " buffer");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __COMFORTABLE_SWIPE__service_start__ */
|
||||||
73
src/lib/service/stop.cpp
Normal file
73
src/lib/service/stop.cpp
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
#ifndef __COMFORTABLE_SWIPE__service_stop__
|
||||||
|
#define __COMFORTABLE_SWIPE__service_stop__
|
||||||
|
|
||||||
|
#include <cstdio> // std::FILE, std::feof, std::fgets
|
||||||
|
#include <cstdlib> // std::atoi, std::system
|
||||||
|
#include <string> // std::string, std::to_string
|
||||||
|
/*
|
||||||
|
Comfortable Swipe
|
||||||
|
by Rico Tiongson
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdexcept> // std::runtime_error
|
||||||
|
#include <unistd.h> // popen, pclose, getpid
|
||||||
|
|
||||||
|
namespace comfortable_swipe::service
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Stops all comfortable-swipe instances.
|
||||||
|
*/
|
||||||
|
void stop()
|
||||||
|
{
|
||||||
|
|
||||||
|
// read all service names from process (pgrep)
|
||||||
|
char* buffer = new char[20];
|
||||||
|
FILE* pipe = popen("pgrep -f comfortable-swipe", "r");
|
||||||
|
|
||||||
|
// make sure pipe exists
|
||||||
|
if (pipe == NULL)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("stop command failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
// buffer what to kill
|
||||||
|
std::string kill = "kill";
|
||||||
|
|
||||||
|
// read until end of line
|
||||||
|
while (!std::feof(pipe))
|
||||||
|
{
|
||||||
|
if (std::fgets(buffer, 20, pipe) != NULL)
|
||||||
|
{
|
||||||
|
int pid = std::atoi(buffer);
|
||||||
|
if (pid != getpid())
|
||||||
|
{
|
||||||
|
kill += " ";
|
||||||
|
kill += std::to_string(pid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// run "kill {pid1} {pid2}..."
|
||||||
|
(void) std::system(kill.data());
|
||||||
|
delete[] buffer;
|
||||||
|
|
||||||
|
// close the pipe
|
||||||
|
pclose(pipe);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __COMFORTABLE_SWIPE__service_stop__ */
|
||||||
46
src/lib/util/autostart_filename.cpp
Normal file
46
src/lib/util/autostart_filename.cpp
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
#ifndef __COMFORTABLE_SWIPE__util_autostart_filename__
|
||||||
|
#define __COMFORTABLE_SWIPE__util_autostart_filename__
|
||||||
|
|
||||||
|
/*
|
||||||
|
Comfortable Swipe
|
||||||
|
by Rico Tiongson
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string> // std::string
|
||||||
|
#include <unistd.h> // getenv
|
||||||
|
|
||||||
|
namespace comfortable_swipe::util
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The path where the autostart configuration is located.
|
||||||
|
*/
|
||||||
|
const char* autostart_filename()
|
||||||
|
{
|
||||||
|
static std::string filename;
|
||||||
|
if (filename.empty()) {
|
||||||
|
const char* xdg_config = getenv("XDG_CONFIG_HOME");
|
||||||
|
std::string config(
|
||||||
|
xdg_config == NULL
|
||||||
|
? std::string(getenv("HOME")) + "/.config"
|
||||||
|
: xdg_config
|
||||||
|
);
|
||||||
|
filename = config + "/autostart/comfortable-swipe.desktop";
|
||||||
|
}
|
||||||
|
return filename.data();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __COMFORTABLE_SWIPE__util_autostart_filename__ */
|
||||||
35
src/lib/util/conf_filename.cpp
Normal file
35
src/lib/util/conf_filename.cpp
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#ifndef __COMFORTABLE_SWIPE__util_conf_filename__
|
||||||
|
#define __COMFORTABLE_SWIPE__util_conf_filename__
|
||||||
|
|
||||||
|
/*
|
||||||
|
Comfortable Swipe
|
||||||
|
by Rico Tiongson
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../index.hpp"
|
||||||
|
|
||||||
|
namespace comfortable_swipe::util
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The path where the configuration file is located.
|
||||||
|
*/
|
||||||
|
constexpr const char* conf_filename()
|
||||||
|
{
|
||||||
|
return __COMFORTABLE_SWIPE__CONFIG__;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __COMFORTABLE_SWIPE__util_conf_filename__ */
|
||||||
100
src/lib/util/read_config_file.cpp
Normal file
100
src/lib/util/read_config_file.cpp
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
#ifndef __COMFORTABLE_SWIPE__util_read_config_file__
|
||||||
|
#define __COMFORTABLE_SWIPE__util_read_config_file__
|
||||||
|
|
||||||
|
/*
|
||||||
|
Comfortable Swipe
|
||||||
|
by Rico Tiongson
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <map> // std::map
|
||||||
|
#include <string> // std::string
|
||||||
|
#include <fstream> // std::ifstream
|
||||||
|
#include <iostream> // std::cerr, std::endl, std::getline
|
||||||
|
#include <cstdlib> // exit
|
||||||
|
#include <cctype> // std::isspace
|
||||||
|
|
||||||
|
namespace comfortable_swipe::util
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* A utility method for reading the config file.
|
||||||
|
*
|
||||||
|
* @param filename (const char*) the path of the config file.
|
||||||
|
*/
|
||||||
|
std::map<std::string, std::string> read_config_file(const char* filename)
|
||||||
|
{
|
||||||
|
|
||||||
|
std::map<std::string, std::string> conf;
|
||||||
|
std::ifstream fin(filename);
|
||||||
|
|
||||||
|
if (!fin.is_open())
|
||||||
|
{
|
||||||
|
std::cerr << "file \"" << filename << "\" does not exist!" << std::endl;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string line, token[2];
|
||||||
|
int line_number = 0;
|
||||||
|
|
||||||
|
while (std::getline(fin, line))
|
||||||
|
{
|
||||||
|
++line_number;
|
||||||
|
token[0].clear();
|
||||||
|
token[1].clear();
|
||||||
|
int length = line.length();
|
||||||
|
int equal_flag = 0;
|
||||||
|
|
||||||
|
// tokenize comfig config
|
||||||
|
for (int i = 0; i < length; ++i)
|
||||||
|
{
|
||||||
|
if (line[i] == '#') // skip comments
|
||||||
|
break;
|
||||||
|
if (line[i] == '=') // flag equal sign
|
||||||
|
{
|
||||||
|
if (++equal_flag > 1)
|
||||||
|
{
|
||||||
|
std::cerr << "error in conf file " << filename << std::endl;
|
||||||
|
std::cerr << "multiple equal signs in line " << line_number << std::endl;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!std::isspace(line[i]))
|
||||||
|
{
|
||||||
|
// add to buffer
|
||||||
|
token[equal_flag].push_back(line[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore empty lines
|
||||||
|
if (equal_flag == 0 && token[0].length() == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// no equal sign found in non-empty line
|
||||||
|
if (equal_flag == 0)
|
||||||
|
{
|
||||||
|
std::cerr << "error in conf file: " << filename << std::endl;
|
||||||
|
std::cerr << "equal sign expected in line " << line_number << std::endl;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// equal sign found, add to tokens
|
||||||
|
if (token[1].length() > 0)
|
||||||
|
conf[token[0]] = token[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
return conf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* __COMFORTABLE_SWIPE__util_read_config_file__ */
|
||||||
89
src/lib/util/regex.cpp
Normal file
89
src/lib/util/regex.cpp
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
#ifndef __COMFORTABLE_SWIPE__util_regex__
|
||||||
|
#define __COMFORTABLE_SWIPE__util_regex__
|
||||||
|
|
||||||
|
/*
|
||||||
|
Comfortable Swipe
|
||||||
|
by Rico Tiongson
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace comfortable_swipe::util
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Regex pattern for the libinput entry for start of swipe.
|
||||||
|
* Extracts one match for the number of fingers used during the swipe.
|
||||||
|
*
|
||||||
|
* eg. event15 GESTURE_SWIPE_BEGIN +34.33s 3
|
||||||
|
* ^
|
||||||
|
* fingers
|
||||||
|
*/
|
||||||
|
const char* GESTURE_SWIPE_BEGIN_REGEX_PATTERN =
|
||||||
|
"^" // start of string
|
||||||
|
"[ -]event\\d+" // event
|
||||||
|
"\\s+GESTURE_SWIPE_BEGIN" // gesture
|
||||||
|
"\\s+\\S+" // timestamp
|
||||||
|
"\\s+(\\d+)" // fingers
|
||||||
|
"\\s*$" // end of string
|
||||||
|
;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Regex pattern for the libinput entry for the end of swipe.
|
||||||
|
* Extracts one match for the number of fingers used during the swipe.
|
||||||
|
*
|
||||||
|
* eg. event15 GESTURE_SWIPE_END +35.03s 3
|
||||||
|
* ^
|
||||||
|
* fingers
|
||||||
|
*/
|
||||||
|
const char* GESTURE_SWIPE_END_REGEX_PATTERN =
|
||||||
|
"^" // start of string
|
||||||
|
"[ -]event\\d+" // event
|
||||||
|
"\\s+GESTURE_SWIPE_END" // gesture
|
||||||
|
"\\s+\\S+" // timestamp
|
||||||
|
"\\s+(\\d+)" // fingers
|
||||||
|
"\\s*$" // end of string
|
||||||
|
;
|
||||||
|
|
||||||
|
// matches signed decimal numbers (eg. "6.02" "-1.1")
|
||||||
|
#define CF_NUMBER_REGEX "-?\\d+(?:\\.\\d+)"
|
||||||
|
|
||||||
|
// matches and extracts a space-prefixed signed fraction (eg. "-3.00/ 5.12")
|
||||||
|
#define CF_NUMBER_DIVISION "\\s*(" CF_NUMBER_REGEX ")/\\s*(" CF_NUMBER_REGEX ")"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Regex pattern for the libinput entry for during a swipe.
|
||||||
|
* Extracts number of fingers used and the speed (normal and accelerated) of the swipe.
|
||||||
|
*
|
||||||
|
* eg. event15 GESTURE_SWIPE_UPDATE +34.70s 3 -0.12/ 4.99 (-0.33/13.50 unaccelerated)
|
||||||
|
* ^ ^ ^ ^ ^
|
||||||
|
* fingers dx dy udx udy
|
||||||
|
*/
|
||||||
|
const char* GESTURE_SWIPE_UPDATE_REGEX_PATTERN =
|
||||||
|
"^" // start of string
|
||||||
|
"[ -]event\\d+" // event
|
||||||
|
"\\s+GESTURE_SWIPE_UPDATE" // gesture
|
||||||
|
"\\s+\\S+" // timestamp
|
||||||
|
"\\s+(\\d+)" // fingers
|
||||||
|
"\\s+" CF_NUMBER_DIVISION // speed (dx/dy)
|
||||||
|
"\\s+\\(" CF_NUMBER_DIVISION "\\s+unaccelerated\\)" // unaccelerated speed (udx/udy)
|
||||||
|
"\\s*$" // end of string
|
||||||
|
;
|
||||||
|
|
||||||
|
// delete macros
|
||||||
|
#undef CF_NUMBER_DIVISION
|
||||||
|
#undef CF_NUMBER_EXTRACT
|
||||||
|
#undef CF_NUMBER_REGEX
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __COMFORTABLE_SWIPE__util_regex__ */
|
||||||
46
src/main.cpp
Normal file
46
src/main.cpp
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
Comfortable Swipe
|
||||||
|
by Rico Tiongson
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Compile: g++ main.cpp -std=c++11 -lxdo
|
||||||
|
|
||||||
|
#include <string> // std::string
|
||||||
|
#include "lib/comfortable_swipe"
|
||||||
|
|
||||||
|
/* MAIN DRIVER FUNCTION */
|
||||||
|
|
||||||
|
int main(int argc, char** args)
|
||||||
|
{
|
||||||
|
using namespace comfortable_swipe::service;
|
||||||
|
|
||||||
|
if (argc > 1)
|
||||||
|
{
|
||||||
|
std::string arg = args[1];
|
||||||
|
// select based on argument
|
||||||
|
if (arg == "start") start();
|
||||||
|
else if (arg == "stop") stop();
|
||||||
|
else if (arg == "restart") restart();
|
||||||
|
else if (arg == "buffer") buffer();
|
||||||
|
else if (arg == "autostart") autostart();
|
||||||
|
else help();
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
help();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user