diff --git a/.gitignore b/.gitignore index 2fca53d..f71ba51 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ # C++ generated headers *.gch +*.o # IDE-specific .idea diff --git a/comfortable-swipe b/comfortable-swipe index 42267f2..d3fa6e3 100755 --- a/comfortable-swipe +++ b/comfortable-swipe @@ -1,19 +1,19 @@ #!/bin/bash -## Comfortable Swipe (comfortable-swipe) -basename="$(basename "$0")" -version="$(cat VERSION)" # this will be hardcoded upon install - +# Comfortable Swipe # turn on errors per line set -e -usage= +DIR="$(dirname "$0")" +BASENAME="$(basename "$0")" +VERSION="$(cat "$DIR/VERSION" | tr -d '[:space:]')" # note: this will be hardcoded upon install + # show help function help { cat < [] +Usage: $BASENAME [--help|--version] [] -h, --help show this help text -v, --version print the program version @@ -84,7 +84,8 @@ function restart { # parse input from a buffer -# internally calls comfortable-swipe-buffer (make sure installed) +# internally calls comfortable-swipe-main.cpp, which is +# installed as: comfortable-swipe-buffer function buffer { exec comfortable-swipe-buffer "$@" } @@ -180,12 +181,14 @@ case $i in exit 0 ;; -v | --version) # eagerly print version - echo "comfortable-swipe $version" + echo "comfortable-swipe $VERSION" exit 0 ;; *) # unknown option - echo "Unknown option: $i" >&2 - exit 1 + if [[ "$i" == -* ]]; then + echo "Unknown option: $i" >&2 + exit 1 + fi ;; esac done diff --git a/comfortable-swipe-buffer.cpp b/comfortable-swipe-buffer.cpp deleted file mode 100644 index 57edac0..0000000 --- a/comfortable-swipe-buffer.cpp +++ /dev/null @@ -1,89 +0,0 @@ -#ifndef __comfortable_swipe_buffer__ -#define __comfortable_swipe_buffer__ - -/* -Comfortable Swipe (as of v1.2.0) -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 . -*/ - -#include // fgets_unlocked, stdin -#include // ios, cout, cin -#include // cfg_t - -#include "comfortable-swipe-config.cpp" -#include "comfortable-swipe-defines.cpp" -#include "comfortable-swipe-gesture-mousehold.cpp" -#include "comfortable-swipe-gesture-swipe.cpp" - -/** - * The main driver program. - */ -int main() { - using namespace std; - using namespace comfortable_swipe; - - // unsync with for faster IO - ios::sync_with_stdio(false); - cin.tie(0); - cout.tie(0); - cout.flush(); - - // prepare config file - - cfg_ auto config = - comfortable_swipe::read_config_file(COMFORTABLE_SWIPE_CONFIG); - - // initialize mouse hold gesture handler - // for now, this supports 3-finger and 4-finger hold - // Examples: - // hold3=move move mouse on 3 fingers - // hold3=button1 hold button 1 on 3 fingers - // hold4=button3 hold button 3 (right click) on 3 fingers - // hold3=ignore - gesture_mousehold mouse_hold(config_get_string("hold3"), config_get_string("hold4")); - - // initialize keyboard swipe gesture handler - gesture_swipe = keyboard_swipe( - config_get_float("threshold"), - config_get_string("left3"), - config_get_string("left4"), - config_get_string("right3"), - config_get_string("right4"), - config_get_string("up3"), - config_get_string("up4"), - config_get_string("down3"), - config_get_string("down4"), - ); - - // prepare data containers - array line; - - // start reading lines from input one by one - while (fgets_unlocked(line.data(), line.size(), stdin) != NULL) { - // prioritize mouse hold gesture first - mouse_hold.parse_line(line.data()); - - // if mouse hold fails, try keyboard hold - if (!mouse_hold.is_mousedown()) { - // attempt to parse keyboard gestures - keyboard_swipe.parse_line(line.data()); - } - } - - return 0; -} - -#endif diff --git a/comfortable-swipe-config.cpp b/comfortable-swipe-config.cpp deleted file mode 100644 index d7caf29..0000000 --- a/comfortable-swipe-config.cpp +++ /dev/null @@ -1,84 +0,0 @@ -#ifndef __comfortable_swipe_config__ -#define __comfortable_swipe_config__ - -/* -Comfortable Swipe (as of v1.2.0) -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 . -*/ - -#include // std::array -#include // std::cout -#include // std::unique_ptr -extern "C" { -#include // cfg_t -} -#include "comfortable-swipe-defines.cpp" - -namespace comfortable_swipe { -// prepare config file -// Examples: cfg_getstr(get_config(), "left3") -// cfg_getfloat(get_config(), "threshold") -cfg_t *get_config() { - using namespace std; - - // use std::unique_ptr for auto garbage collection - static std::unique_ptr config; - - // try to return existing config - if (config != nullptr) - return config.get(); - - // list down possible options here - // second argument is the default value - // make sure to end with CFG_END() - array cfg_options = { - CFG_STR("left3", "", CFGF_NONE), - CFG_STR("left4", "", CFGF_NONE), - CFG_STR("right3", "", CFGF_NONE), - CFG_STR("right4", "", CFGF_NONE), - CFG_STR("up3", "", CFGF_NONE), - CFG_STR("up4", "", CFGF_NONE), - CFG_STR("down3", "", CFGF_NONE), - CFG_STR("down4", "", CFGF_NONE), - CFG_FLOAT("threshold", 0.0, CFGF_NONE), - CFG_STR("hold3", "", CFGF_NONE), - CFG_STR("hold4", "", CFGF_NONE), - // make sure to end here - CFG_END() - ); - - // initialize - config = std::auto_ptr(cfg_init(cfg_options.data(), CFGF_NONE)): - - if (cfg_parse(config.get(), COMFORTABLE_SWIPE_CONFIG) == CFG_PARSE_ERROR) { - throw runtime_error( - "cannot parse config file at: " COMFORTABLE_SWIPE_CONFIG); - } - - return config.get(); -} - -// utility methods -inline const char *get_config_string(const char *key) { - return cfg_getstr(get_config(), key); -} - -inline double get_config_float(const char *key) { - return cfg_getfloat(get_config(), key); -} -} // namespace comfortable_swipe - -#endif /* __comfortable_swipe_config__ */ diff --git a/comfortable-swipe-defines.cpp b/comfortable-swipe-defines.cpp index 43d2c7f..9bc6bcf 100644 --- a/comfortable-swipe-defines.cpp +++ b/comfortable-swipe-defines.cpp @@ -1,9 +1,8 @@ #ifndef __comfortable_swipe_defines__ #define __comfortable_swipe_defines__ -// Place #define statements here - +/** All global #define statements go here */ /* -Comfortable Swipe (as of v1.2.0) +Comfortable Swipe by Rico Tiongson This program is free software: you can redistribute it and/or modify @@ -19,19 +18,35 @@ 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 . */ - +/** + * COMFORTABLE_SWIPE_CONFIG + * + * This definition points to the location of the configuration file. + * A warning will be issued to the compiler if you do not define this at compile time. + */ #ifndef COMFORTABLE_SWIPE_CONFIG -#warning Please define COMFORTABLE_SWIPE_CONFIG during compilation!\ - (g++ -DCOMFORTABLE_SWIPE_CONFIG="\"/home/$USER/.config/comfortable-swipe.conf\"") +#pragma message "Please define COMFORTABLE_SWIPE_CONFIG during compilation!" +// just point to config from source directory +#define COMFORTABLE_SWIPE_CONFIG "/dev/null" #endif /* COMFORTABLE_SWIPE_CONFIG */ - +/** + * COMFORTABLE_SWIPE_AUTOSTART + * + * This definition points to the location of the autostart (.desktop) file. + * A warning will be issued to the compiler if you do not define this at compile time. + */ #ifndef COMFORTABLE_SWIPE_AUTOSTART -#warning Please define COMFORTABLE_SWIPE_AUTOSTART during compilation!\ - (g++ -DCOMFORTABLE_SWIPE_AUTOSTART="\"/home/$USER/.config/autostart/comfortable-swipe.desktop\"") +#pragma message "Please define COMFORTABLE_SWIPE_AUTOSTART during compilation!" +// just point to autostart from source directory +#define COMFORTABLE_SWIPE_AUTOSTART "/dev/null" #endif /* COMFORTABLE_SWIPE_AUTOSTART */ - +/** + * COMFORTABLE_SWIPE_VERSION + * + * This is an optional definition for the version string of comfortable-swipe. + */ #ifndef COMFORTABLE_SWIPE_VERSION -#warning COMFORTABLE_SWIPE_VERSION is not defined +#pragma message "Please define COMFORTABLE_SWIPE_VERSION during compilation!" #define COMFORTABLE_SWIPE_VERSION "v(UNKNOWN)" #endif /* COMFORTABLE_SWIPE_VERSION */ diff --git a/comfortable-swipe-gesture-swipe-xdokey.cpp b/comfortable-swipe-gesture-swipe-xdokey.cpp new file mode 100644 index 0000000..36aaada --- /dev/null +++ b/comfortable-swipe-gesture-swipe-xdokey.cpp @@ -0,0 +1,191 @@ +#ifndef __comfortable_swipe_gesture_swipe_xdokey__ +#define __comfortable_swipe_gesture_swipe_xdokey__ + +/* +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 . +*/ + +#include // std::cout, std::endl +#include // std::array +#include // std::string + +extern "C" { +#include // xdo_send_keysequence_window + // CURRENT_WINDOW +} + +#include "comfortable-swipe-gesture-swipe.cpp" + +namespace comfortable_swipe { +/** + * Gesture Swipe keyboard-swipe gestures class with xdo. + * + * Performs a swipe in one of the four cardinal directions: + * left, right, up, down. Applicable for 3 or 4 fingers. + * + * When constructing, please mind the order in the + * `gesture_swipe_xdokey::command_name[]` static array. + */ +class gesture_swipe_xdokey : public gesture_swipe +{ +public: +// stores the 8 command strings for xdo to execute +std::array commands; +// constructor +gesture_swipe_xdokey(const decltype(commands)& commands, float threshold=0); +// destructor +virtual ~gesture_swipe_xdokey(); +// hooks that we override +virtual void begin() override; +virtual void update() override; +virtual void end() override; +// override this when keyboard gesture is to be performed +virtual void do_keyboard_gesture(int mask); +protected: + // stores square of threshold so we can compute faster + float threshold_squared; + // stores previous gesture so we don't repeat action + int previous_gesture; +public: +// static enums we will use for gesture matching +static const int FRESH = -1; +static const int MSK_THREE_FINGERS = 0; +static const int MSK_FOUR_FINGERS = 1; +static const int MSK_NEGATIVE = 0; +static const int MSK_POSITIVE = 2; +static const int MSK_HORIZONTAL = 0; +static const int MSK_VERTICAL = 4; +// mappings to our command string names +static const std::string command_name[]; +}; +/** + * Our mapped directional command names. These will be + * printed to the console during execution: + * + * SWIPE + * + * Refer to the order of this array for the "commands" + * paramter in the constructor. + */ +decltype(gesture_swipe_xdokey::command_name) +gesture_swipe_xdokey::command_name = { + // the order of variables is based on bitmasking + // | | + "left3", // 000 + "left4", // 001 + "right3", // 010 + "right4", // 011 + "up3", // 100 + "up4", // 101 + "down3", // 110 + "down4" // 111 +}; +/** + * Constructs a new keyboard-based swipe gesture, given configurations + * for certain swipe events. Here, we construct our definition based on + * the four directions (left, up, right, down) for 3-finger and 4-finger + * swipes. Note that the direction is based on the Australian natural + * scrolling direction (ie. left3 is natural movement of 3 fingers left). + */ +gesture_swipe_xdokey::gesture_swipe_xdokey( + const decltype(gesture_swipe_xdokey::commands)& commands, + float threshold +): gesture_swipe(), commands(commands), threshold_squared(threshold * threshold) {} +/** + * Destructs this keyboard swipe gesture. + */ +gesture_swipe_xdokey::~gesture_swipe_xdokey() { } +/** + * Hook on begin of swipe gesture. + */ +void gesture_swipe_xdokey::begin() { + // call superclass method + gesture_swipe::begin(); + // assign previous gesture to FRESH + this->previous_gesture = gesture_swipe_xdokey::FRESH; +} +/** + * Hook on update of swipe gesture. + */ +void gesture_swipe_xdokey::update() { + // call superclass method + gesture_swipe::update(); + // scale threshold to 1/10 when gesture is not fresh + float scale = 1; + if (this->previous_gesture == gesture_swipe_xdokey::FRESH) + scale = 0.01f; // square root of 1/10 + // we are working with floating points which are not exact + // make sure we compare with a very small value (epsilon) + static const float EPSILON = 1e-6f; + const float distance_squared = this->x * this->x + this->y * this->y; + const float beyond_threshold = this->threshold_squared * scale; + // if distance goes out of threshold, perform our swipe + if (distance_squared > beyond_threshold + EPSILON) { + // we parse our mask based on the values obtained from the regex + int mask = 0; + if (this->fingers == 3) + mask |= gesture_swipe_xdokey::MSK_THREE_FINGERS; + else if (this->fingers == 4) + mask |= gesture_swipe_xdokey::MSK_FOUR_FINGERS; + const float absx = x >= 0 ? x : -x; + const float absy = y >= 0 ? y : -y; + if (absx > absy) { + // gesture is horizontal + mask |= gesture_swipe_xdokey::MSK_HORIZONTAL; + if (x < 0) + mask |= gesture_swipe_xdokey::MSK_NEGATIVE; + else + mask |= gesture_swipe_xdokey::MSK_POSITIVE; + } + else /* std::abs(x) <= std::abs(y) */ + { + // gesture is vertical + mask |= gesture_swipe_xdokey::MSK_VERTICAL; + if (y < 0) + mask |= gesture_swipe_xdokey::MSK_NEGATIVE; + else + mask |= gesture_swipe_xdokey::MSK_POSITIVE; + } + // send command on fresh OR opposite gesture + if (this->previous_gesture == gesture_swipe_xdokey::FRESH || + this->previous_gesture == + (mask ^ gesture_swipe_xdokey::MSK_POSITIVE)) { + // finally, perform keyboard gesture + this->do_keyboard_gesture(mask); + } + } +} +/** + * Perform our maske command to xdo. + */ +void gesture_swipe_xdokey::do_keyboard_gesture(int mask) { + // perform our keyboard command with xdo_send_keysequence + xdo_send_keysequence_window(this->xdo, CURRENTWINDOW, commands[mask].data(), 0); + std::cout << "SWIPE " << command_name[mask] << std::endl; + // reset our location variables + this->x = this->y = 0; + this->previous_gesture = mask; +} +/** + * Hook on end of swipe gesture. + */ +void gesture_swipe_xdokey::end() { + // just call superclass method + gesture_swipe::end(); +} +} +#endif /* __comfortable_swipe_gesture_swipe_xdokey__ */ diff --git a/comfortable-swipe-gesture-mousehold.cpp b/comfortable-swipe-gesture-swipe-xdomouse.cpp similarity index 65% rename from comfortable-swipe-gesture-mousehold.cpp rename to comfortable-swipe-gesture-swipe-xdomouse.cpp index 5a3d865..ed136a7 100644 --- a/comfortable-swipe-gesture-mousehold.cpp +++ b/comfortable-swipe-gesture-swipe-xdomouse.cpp @@ -1,6 +1,10 @@ -#ifndef __comfortable_swipe_gesture_mousehold__ -#define __comfortable_swipe_gesture_mousehold__ - +#ifndef __comfortable_swipe_gesture_swipe_xdomouse__ +#define __comfortable_swipe_gesture_swipe_xdomouse__ +/** + * File: comfortable-swipe-gesture-swipe-xdomouse.cpp + * + * + */ /* Comfortable Swipe by Rico Tiongson @@ -18,21 +22,20 @@ 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 . */ - #include // std::sscanf #include // strncmp #include // std::cout, std::endl extern "C" { -#include // xdo, xdo_new, xdo_free, - // xdo_get_mouse_location - // CURRENT_WINDOW +#include // xdo_mouse_down + // xdo_mouse_up + // xdo_move_mouse_relative + // CURRENTWINDOW } #include "comfortable-swipe-gesture-swipe.cpp" namespace comfortable_swipe { - // enumerations for mouse hold gesture types enum { MOUSE_NONE = -1, @@ -45,100 +48,77 @@ enum { MOUSE_SCROLL = 6, MOUSE_SCROLL_REVERSE = 7 }; - -class gesture_mousehold : public gesture_swipe { +/** + * Gesture Swipe mouse gestures class with xdo. + * + * If type is MOUSE_*_CLICK, we apply: + * - xdo_mouse_down on begin() + * - xdo_mouse_up on end() + * + * If type is MOUSE_MOVE, we apply: + * - xdo_mouse_move_relative on update(). + * + * If type is MOUSE_WHEEL* or MOUSE_SCROLL*, we apply: + * - xdo_mouse_down on update() + * - xdo_mouse_up on update() + */ +class gesture_swipe_xdomouse : public gesture_swipe { public: + // the button number being clicked + int button; // constructor - gesture_mousehold(const char *hold3, // 3 finger mouse down + gesture_swipe_xdomouse(const char *hold3, // 3 finger mouse down const char *hold4 // 4 finger mouse down ); - - // the button being clicked - int button; - - virtual ~gesture_mousehold(); - + // destructor + virtual ~gesture_swipe_xdomouse(); // override begin and end for mousedown virtual void begin() override; virtual void update() override; virtual void end() override; - - // provide our own mouse functions + // provide our own mouse dispatch functions virtual void do_mousedown(const char *); virtual void do_mouseup(const char *); - virtual bool is_mousedown() const; - + // utility method to check if mouse is being held + virtual bool is_holding() const; // utility method to parse mouse input given config characters static int parse_mouse_button(const char *); - protected: // command holders const char *hold3; const char *hold4; - +private: // flag we can use to check if mouse is down - bool flag_mousedown; + bool flag_is_holding; }; -} // namespace comfortable_swipe - /** * Constructs a new mouse gesture, given "hold3" and "hold4" configurations. */ -gesture_mousehold::gesture_mousehold(const char *hold3, const char *hold4) +gesture_swipe_xdomouse::gesture_swipe_xdomouse(const char *hold3, const char *hold4) : gesture_swipe(), button(MOUSE_NONE), hold3(hold3), hold4(hold4), - flag_mousedown(false) {} - + flag_is_holding(false) {} /** * Destructs this mouse swipe gesture. */ -gesture_mousehold::~gesture_mousehold() {} - +gesture_swipe_xdomouse::~gesture_swipe_xdomouse() {} /** - * Run mousedown command on hold input. + * Determines if some mousehold command is being run. */ -void gesture_mousehold::do_mousedown(const char *mouseinput) { - const int button = this->button = this->parse_mouse_button(mouseinput); - if (button != MOUSE_NONE) { - // eg. MOUSE DOWN hold3 mouse1 - std::printf("MOUSE DOWN hold%d %s\n", this->fingers, mouseinput); - if (MOUSE_LEFT_CLICK <= button && button <= MOUSE_RIGHT_CLICK) { - // send mouse down on associated button - xdo_mouse_down(this->xdo, CURRENTWINDOW, button); - } - this->flag_mousedown = true; - } +bool gesture_swipe_xdomouse::is_holding() const { + return this->flag_is_holding; } - -/** - * Run mouseup command on hold output. - */ -void gesture_mousehold::do_mouseup(const char *mouseinput) { - const int button = this->button = this->parse_mouse_button(mouseinput); - if (button != MOUSE_NONE) { - std::printf("MOUSE UP hold%d %s\n", this->fingers, mouseinput); - if (MOUSE_LEFT_CLICK <= button && button <= MOUSE_RIGHT_CLICK) { - // send mouse up on associated button - xdo_mouse_up(this->xdo, CURRENTWINDOW, button); - } - this->flag_mousedown = false; - } -} - /** * Utility method to parse mouse number from input. - * Returns -1 on failure. + * Returns MOUSE_NONE on failure. */ -int gesture_mousehold::parse_mouse_button(const char *input) { +int gesture_swipe_xdomouse::parse_mouse_button(const char *input) { // just move without holding button down if (std::strcmp(input, "move") == 0) return MOUSE_MOVE; - if (std::strcmp(input, "scroll") == 0) return MOUSE_SCROLL; - if (std::strcmp(input, "scroll_reverse") == 0) return MOUSE_SCROLL_REVERSE; - // get button number int button; if (std::sscanf(input, "button%d", &button) == 1) { @@ -146,14 +126,41 @@ int gesture_mousehold::parse_mouse_button(const char *input) { return button; } } - return MOUSE_NONE; } - +/** + * Perform mousedown command on hold input. + */ +void gesture_swipe_xdomouse::do_mousedown(const char *input) { + const int button = this->button = this->parse_mouse_button(input); + if (button != MOUSE_NONE) { + // eg. MOUSE DOWN hold3 mouse1 + std::printf("MOUSE DOWN hold%d %s\n", this->fingers, input); + if (MOUSE_LEFT_CLICK <= button && button <= MOUSE_RIGHT_CLICK) { + // send mouse down on associated button + xdo_mouse_down(this->xdo, CURRENTWINDOW, button); + } + this->flag_is_holding = true; + } +} +/** + * Run mouseup command on hold output. + */ +void gesture_swipe_xdomouse::do_mouseup(const char *input) { + const int button = this->button = this->parse_mouse_button(input); + if (button != MOUSE_NONE) { + std::printf("MOUSE UP hold%d %s\n", this->fingers, input); + if (MOUSE_LEFT_CLICK <= button && button <= MOUSE_RIGHT_CLICK) { + // send mouse up on associated button + xdo_mouse_up(this->xdo, CURRENTWINDOW, button); + } + this->flag_is_holding = false; + } +} /** * Hook on begin of mouse swipe gesture. */ -void gesture_mousehold::begin() { +void gesture_swipe_xdomouse::begin() { // call superclass method gesture_swipe::begin(); // dispatch mouse down event @@ -163,14 +170,14 @@ void gesture_mousehold::begin() { this->do_mousedown(this->hold4); } } - /** * Hook on end of mouse swipe gesture. */ -void gesture_mousehold::update() { +void gesture_swipe_xdomouse::update() { // call superclass method gesture_swipe::update(); - if (this->is_mousedown()) { + if (this->is_holding()) { + // if MOUSE_MOVE or MOUSE_CLICK* if (0 <= this->button && this->button <= 3) { // drag mouse with pointer during update xdo_move_mouse_relative(this->xdo, this->udx, this->udy); @@ -192,27 +199,21 @@ void gesture_mousehold::update() { } } } - /** * Hook on end of swipe gesture. */ -void gesture_mousehold::end() { - if (this->is_mousedown()) { +void gesture_swipe_xdomouse::end() { + // optimization: only perform mouseup when flag is set + if (this->is_holding()) { if (this->fingers == 3) { this->do_mouseup(this->hold3); } else if (this->fingers == 4) { this->do_mouseup(this->hold4); } } - // call superclass method gesture_swipe::end(); } - -/** - * Utility method to check if mouse is current held. - */ -bool gesture_mousehold::is_mousedown() const { return this->flag_mousedown; } } -#endif /* __comfortable_swipe_gesture_mousehold__ */ +#endif /* __comfortable_swipe_gesture_swipe_xdomouse__ */ diff --git a/comfortable-swipe-gesture-swipe.cpp b/comfortable-swipe-gesture-swipe.cpp index 22d8c88..8ae6122 100644 --- a/comfortable-swipe-gesture-swipe.cpp +++ b/comfortable-swipe-gesture-swipe.cpp @@ -1,6 +1,26 @@ #ifndef __comfortable_swipe_gesture_swipe__ #define __comfortable_swipe_gesture_swipe__ - +/** + * File: comfortable-swipe-gesture-swipe.cpp + * + * The definition of the class comfortable_swipe::gesture_swipe. + * + * The class `comfortable_swipe::gesture_swipe` handles dispatching + * of swipe gestures. The method `gesture_swipe::run(const char*)` + * parses a line from libinput debug-events and dispatches a begin(), + * update(), or end() function based on a compiled regex pattern. + * + * We statically compile our swipe gesture regex patterns here. + * This is for parsing `libinput debug-events` console output: + * + * GESTURE_SWIPE_BEGIN - libinput's begin wipe command + * GESTURE_SWIPE_UPDATE - libinput's update swipe command + * GESTURE_SWIPE_END - libinput's end swipe command + * + * We dispatch our events based on the regex patterns above, and + * extract important information, such as number of fingers, in + * an efficient way with Regular Expressions (regex). + */ /* Comfortable Swipe by Rico Tiongson @@ -18,52 +38,51 @@ 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 . */ - #include // std::cout, std::endl #include // std::regex, std::regex_match, std::cmatch #include // std::stoi, std::stof +extern "C" { +#include // xdo, xdo_new, xdo_free, + // xdo_get_mouse_location + // CURRENT_WINDOW +} + namespace comfortable_swipe { +/** + * Handles swipe gesture input from libinput debug-events. + * Dispatches keyboard commands on swipe using libxdo. + */ class gesture_swipe { public: // constructor gesture_swipe(); - // destructor virtual ~gesture_swipe(); - // fields for xdo int fingers; - // normal values (for touchpad mapping) float x, y, dx, dy; - // unaccelerated values (for screen mapping) float ux, uy, udx, udy; - // hooks that we can override (mark as virtual) virtual void begin(); virtual void update(); virtual void end(); - virtual bool parse_line(const char *); - + virtual bool run(const char *); protected: // xdo container xdo_t *xdo; - // location of mouse int screen_num, ix, iy; - // optimization flag for checking if GESTURE_SWIPE_BEGIN was dispatched bool flag_swiping; - public: - // regex patterns - static const std::regex *GESTURE_BEGIN_REGEX; - static const std::regex *GESTURE_UPDATE_REGEX; - static const std::regex *GESTURE_END_REGEX; + // defined in: comfortable-swipe-gesture-swipe.regex.cpp + static const std::regex GESTURE_SWIPE_BEGIN; + static const std::regex GESTURE_SWIPE_UPDATE; + static const std::regex GESTURE_SWIPE_END; }; - /** * Constructs a new fresh swipe gesture container. */ @@ -71,12 +90,10 @@ gesture_swipe::gesture_swipe() : xdo(xdo_new(NULL)), flag_swiping(false) { // improve responsiveness of first gesture by pre-empting xdotool xdo_get_mouse_location(this->xdo, &this->ix, &this->iy, &this->screen_num); } - /** * Destructs this swipe gesture. */ gesture_swipe::~gesture_swipe() { xdo_free(this->xdo); } - /** * Hook on begin of swipe gesture (you can override this). */ @@ -88,7 +105,6 @@ void gesture_swipe::begin() { this->ux = 0; this->uy = 0; } - /** * Hook on update of swipe gesture (you can override this). */ @@ -98,27 +114,36 @@ void gesture_swipe::update() { this->ux += this->udx; this->uy += this->udy; } - /** * Hook on end of swipe gesture (you can override this). */ -void gesture_swipe::end() {} - +void gesture_swipe::end() { + // do nothing +} /** * Dispatches begin/update/end depending on the regex pattern provided by this - * class. + * class. Returns true if a gesture begin/update/end was parsed. * * @param line the line from libinput debug-events to parse * @return true if begin/update/end was dispatched */ -bool gesture_swipe::parse_line(const char *line) { - +bool gesture_swipe::run(const char *line) { // prepare holder for regex matches static std::cmatch matches; - - if (this->flag_swiping) { + if (!this->flag_swiping) { + // not swiping, check if swipe will begin + if (std::regex_match(line, matches, GESTURE_SWIPE_BEGIN) != 0) { + // assign necessary variables for swipe begin + this->flag_swiping = true; + this->fingers = std::stoi(matches[1]); + // dispatch begin + this->begin(); + return true; + } + } + else { // currently swiping - if (std::regex_match(line, matches, GESTURE_UPDATE_REGEX) != 0) { + if (std::regex_match(line, matches, GESTURE_SWIPE_UPDATE) != 0) { // assign necessary variables for swipe update this->fingers = std::stoi(matches[1]); this->dx = std::stof(matches[2]); @@ -128,7 +153,7 @@ bool gesture_swipe::parse_line(const char *line) { // dispatch update this->update(); return true; - } else if (std::regex_match(line, matches, GESTURE_END_REGEX) != 0) { + } else if (std::regex_match(line, matches, GESTURE_SWIPE_END) != 0) { // assign necessary variables for swipe end this->flag_swiping = false; this->fingers = std::stoi(matches[1]); @@ -136,21 +161,68 @@ bool gesture_swipe::parse_line(const char *line) { this->end(); return true; } - } else { - // not swiping, check if swipe will begin - if (std::regex_match(line, matches, GESTURE_BEGIN_REGEX) != 0 || - std::regex_match(line, matches, GESTURE_UPDATE_REGEX) != 0) { - // assign necessary variables for swipe begin - this->flag_swiping = true; - this->fingers = std::stoi(matches[1]); - // dispatch begin - this->begin(); - return true; - } } - return false; } +/** + * 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 std::regex gesture_swipe::GESTURE_SWIPE_BEGIN( + "^" // 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 std::regex gesture_swipe::GESTURE_SWIPE_END( + "^" // 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 _NUMBER_REGEX "-?\\d+(?:\\.\\d+)" +// matches and extracts a space-prefixed signed fraction (eg. "-3.00/ 5.12") +#define _NUMBER_DIVISION "\\s*(" _NUMBER_REGEX ")/\\s*(" _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 std::regex gesture_swipe::GESTURE_SWIPE_UPDATE( + "^" // start of string + "[ -]event\\d+" // event + "\\s+GESTURE_SWIPE_UPDATE" // gesture + "\\s+\\S+" // timestamp + "\\s+(\\d+)" // fingers + "\\s+" _NUMBER_DIVISION // speed (dx/dy) + "\\s+\\(" _NUMBER_DIVISION + "\\s+unaccelerated\\)" // unaccelerated speed (udx/udy) + "\\s*$" // end of string +); +// clean up temporary macros +#undef _NUMBER_DIVISION +#undef _NUMBER_REGEX } // namespace comfortable_swipe - #endif /* __comfortable_swipe_gesture_swipe__ */ diff --git a/comfortable-swipe-main.cpp b/comfortable-swipe-main.cpp new file mode 100644 index 0000000..99e2448 --- /dev/null +++ b/comfortable-swipe-main.cpp @@ -0,0 +1,105 @@ +#ifndef __comfortable_swipe_main__ +#define __comfortable_swipe_main__ +/** + * The main driver program for `comfortable-swipe-buffer` + * + * This C++ program parses the output from libinput debug-events + * into a buffer and dispatches C++ libxdo commands upon swipe. + * + * Possible paths of the executable: + * + * /usr/bin/comfortable-swipe-buffer + * /usr/local/bin/comfortable-swipe-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 . +*/ +#include // std::ios, std::cin, std::getline +#include // std::string +#include // std::map +#include "comfortable-swipe-defines.cpp" +#include "comfortable-swipe-gesture-swipe.cpp" +#include "comfortable-swipe-gesture-swipe-xdokey.cpp" +#include "comfortable-swipe-gesture-swipe-xdomouse.cpp" + +extern "C" { + #include // ini_parse +} + +/** + * Registers keys and values from the config file to a map. + */ +int parse_config(void* config, const char section[], const char name[], const char value[]) +{ + auto& configmap = *(std::map*) config; + configmap[name] = value; + return 0; +} + +/** + * The main driver program. + */ +int main() { + using namespace std; + using namespace comfortable_swipe; + // unsync stdio for faster IO + ios::sync_with_stdio(false); + cin.tie(0); + cout.tie(0); + cout.flush(); + // get configuration file + map config; + if (ini_parse(COMFORTABLE_SWIPE_CONFIG, parse_config, &config) < 0) { + cerr << "error: config " << COMFORTABLE_SWIPE_CONFIG << endl; + return EXIT_FAILURE; + } + // initialize keyboard swipe gesture handler + // commands are: [left|up|right|down][3|4] + // we will fetch our commands from the config in correct order + // Examples: + // left3=ctrl+alt+Right shift to right workspace + // right3=ctrl+alt+Left shift to left workspace + // up3=super+Up maximize + // down3=super+Down minimize + decltype(gesture_swipe_xdokey::commands) commands; + for (size_t i = 0; i < commands.size(); ++i) + { + commands[i] = config[gesture_swipe_xdokey::command_name[i]]; + } + gesture_swipe_xdokey keyswipe(commands, stof(config["threshold"])); + // initialize mouse hold gesture handler + // for now, this supports 3-finger and 4-finger hold + // Examples: + // hold3=move move mouse on 3 fingers + // hold3=button1 hold button 1 on 3 fingers + // hold4=button3 hold button 3 (right click) on 3 fingers + // hold3=ignore + gesture_swipe_xdomouse mousehold(config["hold3"].data(), config["hold4"].data()); + // start reading lines from input one by one + for (string line; getline(cin, line);) { + // prioritize mouse hold gesture first before keyboard gesture + mousehold.run(line.data()); + // if mouse hold fails, try keyboard swipe + // attempt to parse keyboard gestures + if (!mousehold.is_holding()) { + keyswipe.run(line.data()); + } + } + return EXIT_SUCCESS; +} + +#endif diff --git a/comfortable_swipe/all_headers.hpp b/comfortable_swipe/all_headers.hpp deleted file mode 100644 index 19d74ec..0000000 --- a/comfortable_swipe/all_headers.hpp +++ /dev/null @@ -1,78 +0,0 @@ -/** - * Add header files will be imported here. - * You can import this as a shorthand: - * - * #include "../all_headers.hpp" - */ - -#ifndef __COMFORTABLE_SWIPE__all_headers_hpp__ -#define __COMFORTABLE_SWIPE__all_headers_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 . -*/ - -// 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__ */ - -#ifndef COMFORTABLE_SWIPE_VERSION -#warning COMFORTABLE_SWIPE_VERSION is not defined -#define COMFORTABLE_SWIPE_VERSION "v(UNKNOWN)" -#endif /* COMFORTABLE_SWIPE_VERSION */ - -#include // std::map -#include // std::string - -extern "C" { -namespace comfortable_swipe { -// driver method -int driver(); -// this is found in the util/ folder -namespace util { -const char *autostart_filename(); -constexpr const char *conf_filename(); -std::map read_config_file(const char *); -} // namespace util -// this is found in the service/ folder -namespace service { -void autostart(); -void buffer(); -void config(); -void debug(); -void help(); -void restart(); -void start(); -void status(); -void stop(); -} // namespace service -} // namespace comfortable_swipe -} - -// add headers for classes here so it can be imported during include -#include "gesture/keyboard_swipe_gesture.h" -#include "gesture/mouse_hold_gesture.h" -#include "gesture/swipe_gesture.h" -#include "gesture/xdo_gesture.h" - -#endif /* __COMFORTABLE_SWIPE__all_headers_hpp__ */ diff --git a/comfortable_swipe/driver.cpp b/comfortable_swipe/driver.cpp deleted file mode 100644 index 0c3d4cf..0000000 --- a/comfortable_swipe/driver.cpp +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef __COMFORTABLE_SWIPE__driver__ -#define __COMFORTABLE_SWIPE__driver__ - -/* -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 . -*/ - -#include "all_headers.hpp" -#include // fgets_unlocked, stdin -#include // std::ios, std::cout, std::cin - -/** - * The main driver program. - */ -namespace comfortable_swipe { -int driver() { - // unsync for faster IO - std::ios::sync_with_stdio(false); - std::cin.tie(0); - std::cout.tie(0); - std::cout.flush(); - - // read config file - auto config = comfortable_swipe::util::read_config_file( - comfortable_swipe::util::conf_filename()); - - // initialize mouse hold gesture handler - // for now, this supports 3-finger and 4-finger hold - // Examples: - // hold3=move move mouse on 3 fingers - // hold3=button1 hold button 1 on 3 fingers - // hold4=button3 hold button 3 (right click) on 3 fingers - // hold3=ignore - comfortable_swipe::gesture::mouse_hold_gesture mouse_hold( - config["hold3"].c_str(), config["hold4"].c_str()); - - // initialize keyboard swipe gesture handler - comfortable_swipe::gesture::keyboard_swipe_gesture keyboard_swipe( - config.count("threshold") ? std::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()); - - // prepare data containers - std::array line; - - // start reading lines from input one by one - while (fgets_unlocked(line.data(), line.size(), stdin) != NULL) { - // prioritize mouse hold gesture first - mouse_hold.parse_line(line.data()); - - // if mouse hold fails, try keyboard hold - if (!mouse_hold.is_mousedown()) { - // attempt to parse keyboard gestures - keyboard_swipe.parse_line(line.data()); - } - } - - return 0; -} -} // namespace comfortable_swipe - -#endif /* __COMFORTABLE_SWIPE__driver__ */ diff --git a/comfortable_swipe/gesture/keyboard_swipe_gesture.cpp b/comfortable_swipe/gesture/keyboard_swipe_gesture.cpp deleted file mode 100644 index c4b2c72..0000000 --- a/comfortable_swipe/gesture/keyboard_swipe_gesture.cpp +++ /dev/null @@ -1,168 +0,0 @@ -#ifndef __COMFORTABLE_SWIPE__gesture_keyboard_swipe_gesture__ -#define __COMFORTABLE_SWIPE__gesture_keyboard_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 . -*/ - -#include "keyboard_swipe_gesture.h" -#include // std::cout, std::endl - -extern "C" { -#include // xdo, xdo_new, xdo_free, - // xdo_get_mouse_location - // CURRENT_WINDOW -} - -namespace comfortable_swipe::gesture { - -/* STATICS DEFINITIONS */ -const int keyboard_swipe_gesture::MSK_THREE_FINGERS = 0; -const int keyboard_swipe_gesture::MSK_FOUR_FINGERS = 1; -const int keyboard_swipe_gesture::MSK_NEGATIVE = 0; -const int keyboard_swipe_gesture::MSK_POSITIVE = 2; -const int keyboard_swipe_gesture::MSK_HORIZONTAL = 0; -const int keyboard_swipe_gesture::MSK_VERTICAL = 4; -const int keyboard_swipe_gesture::FRESH = -1; -const char *const keyboard_swipe_gesture::command_map[8] = { - "left3", "left4", "right3", "right4", "up3", "up4", "down3", "down4"}; - -/** - * Constructs a new keyboard-based swipe gesture, given configurations - * for certain swipe events. Here, we construct our definition based on - * the four directions (left, up, right, down) for 3-finger and 4-finger - * swipes. Note that the direction is based on the Australian natural - * scrolling direction (ie. left3 is natural movement of 3 fingers left). - */ -keyboard_swipe_gesture::keyboard_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 */ - ) - : // construct superclass - comfortable_swipe::gesture::swipe_gesture(), - // compute square of threshold because we will use squared distances - threshold_squared(threshold * threshold), - // register our commands - commands(new const char *[8] { - left3, left4, right3, right4, up3, up4, down3, down4 - }) {} - -/** - * Destructs this keyboard swipe gesture. - */ -keyboard_swipe_gesture::~keyboard_swipe_gesture() { delete[] commands; } - -/** - * Hook on begin of swipe gesture. - */ -void keyboard_swipe_gesture::begin() { - // call superclass method - swipe_gesture::begin(); - - // assign previous gesture to FRESH - this->previous_gesture = keyboard_swipe_gesture::FRESH; -} - -/** - * Hook on update of swipe gesture. - */ -void keyboard_swipe_gesture::update() { - // call superclass method - swipe_gesture::update(); - - // scale threshold to 1/10 when gesture is not fresh - float scale = this->previous_gesture == keyboard_swipe_gesture::FRESH - ? 1.00f - : 0.01f; // square root of 1/10 - - // we are working with floating points which are not exact - // make sure we compare with a very small value (epsilon) - static const float EPSILON = 1e-6f; - const float distance_squared = this->x * this->x + this->y * this->y; - const float beyond_threshold = this->threshold_squared * scale; - - // apply if strictly beyond threshold - if (distance_squared > beyond_threshold + EPSILON) { - // we parse our mask based on the values obtained from the regex - int mask = 0; - - if (this->fingers == 3) - mask |= keyboard_swipe_gesture::MSK_THREE_FINGERS; - - else if (this->fingers == 4) - mask |= keyboard_swipe_gesture::MSK_FOUR_FINGERS; - - const float absx = x >= 0 ? x : -x; - const float absy = y >= 0 ? y : -y; - - if (absx > absy) { - // gesture is horizontal - mask |= keyboard_swipe_gesture::MSK_HORIZONTAL; - if (x < 0) - mask |= keyboard_swipe_gesture::MSK_NEGATIVE; - else - mask |= keyboard_swipe_gesture::MSK_POSITIVE; - } else /* std::abs(x) <= std::abs(y) */ - { - // gesture is vertical - mask |= keyboard_swipe_gesture::MSK_VERTICAL; - if (y < 0) - mask |= keyboard_swipe_gesture::MSK_NEGATIVE; - else - mask |= keyboard_swipe_gesture::MSK_POSITIVE; - } - - // send command on fresh OR opposite gesture - if (this->previous_gesture == keyboard_swipe_gesture::FRESH || - this->previous_gesture == - (mask ^ keyboard_swipe_gesture::MSK_POSITIVE)) { - this->do_keyboard_gesture(mask); - } - } -} - -/** - * Apply the update given a mask. - */ -void keyboard_swipe_gesture::do_keyboard_gesture(int mask) { - // perform our keyboard command with xdo_send_keysequence - const char *command = keyboard_swipe_gesture::commands[mask]; - xdo_send_keysequence_window(this->xdo, CURRENTWINDOW, command, 0); - - // reset our location variables - this->x = this->y = 0; - this->previous_gesture = mask; - - // log our command name in stdout - const char *command_name = keyboard_swipe_gesture::command_map[mask]; - std::cout << "SWIPE " << command_name << std::endl; -} - -/** - * Hook on end of swipe gesture. - */ -void keyboard_swipe_gesture::end() { - // call superclass method - swipe_gesture::end(); -} - -} // namespace comfortable_swipe::gesture - -#endif /* __COMFORTABLE_SWIPE__gesture_keyboard_swipe_gesture__ */ diff --git a/comfortable_swipe/gesture/keyboard_swipe_gesture.h b/comfortable_swipe/gesture/keyboard_swipe_gesture.h deleted file mode 100644 index 957077a..0000000 --- a/comfortable_swipe/gesture/keyboard_swipe_gesture.h +++ /dev/null @@ -1,84 +0,0 @@ -#ifndef __COMFORTABLE_SWIPE__gesture_keyboard_swipe_gesture_h__ -#define __COMFORTABLE_SWIPE__gesture_keyboard_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 . -*/ - -#include "swipe_gesture.h" - -#ifdef __cplusplus -extern "C" { -#endif - -namespace comfortable_swipe::gesture -{ - class keyboard_swipe_gesture : public swipe_gesture - { - public: - // constructor - keyboard_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 */ - ); - - // destructor - virtual ~keyboard_swipe_gesture(); - - // hooks that we override - virtual void begin() override; - virtual void update() override; - virtual void end() override; - - // override this when keyboard gesture is to be performed - virtual void do_keyboard_gesture(int mask); - - protected: - // stores square of threshold so we can compute faster - float threshold_squared; - - // stores previous gesture so we don't repeat action - int previous_gesture; - - // stores all command strings for xdo to execute - const char ** commands; - - public: - // static enums we will use for gesture matching - static const int FRESH; - 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 char * const command_map[8]; - }; -} - -#ifdef __cplusplus -} -#endif - -#endif /* __COMFORTABLE_SWIPE__gesture_keyboard_swipe_gesture_h__ */ diff --git a/comfortable_swipe/gesture/mouse_hold_gesture.cpp b/comfortable_swipe/gesture/mouse_hold_gesture.cpp deleted file mode 100644 index c0fa724..0000000 --- a/comfortable_swipe/gesture/mouse_hold_gesture.cpp +++ /dev/null @@ -1,180 +0,0 @@ -#ifndef __COMFORTABLE_SWIPE__gesture_mouse_hold_gesture__ -#define __COMFORTABLE_SWIPE__gesture_mouse_hold_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 . -*/ - -#include "mouse_hold_gesture.h" -#include // std::sscanf -#include // strncmp -#include // std::cout, std::endl - -extern "C" { -#include // xdo, xdo_new, xdo_free, - // xdo_get_mouse_location - // CURRENT_WINDOW -} - -namespace comfortable_swipe::gesture { -enum { - MOUSE_NONE = -1, - MOUSE_MOVE = 0, - MOUSE_LEFT_CLICK = 1, - MOUSE_MIDDLE_CLICK = 2, - MOUSE_RIGHT_CLICK = 3, - MOUSE_WHEEL_UP = 4, - MOUSE_WHEEL_DOWN = 5, - MOUSE_SCROLL = 6, - MOUSE_SCROLL_REVERSE = 7 -}; - -/** - * Constructs a new mouse gesture, given "hold3" and "hold4" configurations. - */ -mouse_hold_gesture::mouse_hold_gesture(const char *hold3, const char *hold4) - : comfortable_swipe::gesture::swipe_gesture(), button(MOUSE_NONE), - hold3(hold3), hold4(hold4), flag_mousedown(false) {} - -/** - * Destructs this mouse swipe gesture. - */ -mouse_hold_gesture::~mouse_hold_gesture() {} - -/** - * Run mousedown command on hold input. - */ -void mouse_hold_gesture::do_mousedown(const char *mouseinput) { - const int button = this->button = this->parse_mouse_button(mouseinput); - if (button != MOUSE_NONE) { - // eg. MOUSE DOWN hold3 mouse1 - std::printf("MOUSE DOWN hold%d %s\n", this->fingers, mouseinput); - if (MOUSE_LEFT_CLICK <= button && button <= MOUSE_RIGHT_CLICK) { - // send mouse down on associated button - xdo_mouse_down(this->xdo, CURRENTWINDOW, button); - } - this->flag_mousedown = true; - } -} - -/** - * Run mouseup command on hold output. - */ -void mouse_hold_gesture::do_mouseup(const char *mouseinput) { - const int button = this->button = this->parse_mouse_button(mouseinput); - if (button != MOUSE_NONE) { - std::printf("MOUSE UP hold%d %s\n", this->fingers, mouseinput); - if (MOUSE_LEFT_CLICK <= button && button <= MOUSE_RIGHT_CLICK) { - // send mouse up on associated button - xdo_mouse_up(this->xdo, CURRENTWINDOW, button); - } - this->flag_mousedown = false; - } -} - -/** - * Utility method to parse mouse number from input. - * Returns -1 on failure. - */ -int mouse_hold_gesture::parse_mouse_button(const char *input) { - // just move without holding button down - if (std::strcmp(input, "move") == 0) - return MOUSE_MOVE; - - if (std::strcmp(input, "scroll") == 0) - return MOUSE_SCROLL; - - if (std::strcmp(input, "scroll_reverse") == 0) - return MOUSE_SCROLL_REVERSE; - - // get button number - int button; - if (std::sscanf(input, "button%d", &button) == 1) { - if (1 <= button && button <= 6) { - return button; - } - } - - return MOUSE_NONE; -} - -/** - * Hook on begin of mouse swipe gesture. - */ -void mouse_hold_gesture::begin() { - // call superclass method - swipe_gesture::begin(); - // dispatch mouse down event - if (this->fingers == 3) { - this->do_mousedown(this->hold3); - } else if (this->fingers == 4) { - this->do_mousedown(this->hold4); - } -} - -/** - * Hook on end of mouse swipe gesture. - */ -void mouse_hold_gesture::update() { - // call superclass method - swipe_gesture::update(); - if (this->is_mousedown()) { - if (0 <= this->button && this->button <= 3) { - // drag mouse with pointer during update - xdo_move_mouse_relative(this->xdo, this->udx, this->udy); - } else if (this->button == MOUSE_SCROLL || - this->button == MOUSE_SCROLL_REVERSE) { - // perform naive scroll depending on vertical direction - int wheel = MOUSE_WHEEL_DOWN; - if ((this->udy > 0) == (this->button == MOUSE_SCROLL)) - wheel = MOUSE_WHEEL_UP; - - // click wheel on update (note: this is not precise) - xdo_mouse_down(this->xdo, CURRENTWINDOW, wheel); - xdo_mouse_up(this->xdo, CURRENTWINDOW, wheel); - } else if (this->button == MOUSE_WHEEL_UP || - this->button == MOUSE_WHEEL_DOWN) { - // click wheel button on 4 or 5 - xdo_mouse_down(this->xdo, CURRENTWINDOW, this->button); - xdo_mouse_up(this->xdo, CURRENTWINDOW, this->button); - } - } -} - -/** - * Hook on end of swipe gesture. - */ -void mouse_hold_gesture::end() { - if (this->is_mousedown()) { - if (this->fingers == 3) { - this->do_mouseup(this->hold3); - } else if (this->fingers == 4) { - this->do_mouseup(this->hold4); - } - } - - // call superclass method - swipe_gesture::end(); -} - -/** - * Utility method to check if mouse is current held. - */ -bool mouse_hold_gesture::is_mousedown() const { return this->flag_mousedown; } -} // namespace comfortable_swipe::gesture - -#endif /* __COMFORTABLE_SWIPE__gesture_mouse_hold_gesture__ */ diff --git a/comfortable_swipe/gesture/mouse_hold_gesture.h b/comfortable_swipe/gesture/mouse_hold_gesture.h deleted file mode 100644 index a1d59c1..0000000 --- a/comfortable_swipe/gesture/mouse_hold_gesture.h +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef __COMFORTABLE_SWIPE__gesture_mouse_hold_gesture_h__ -#define __COMFORTABLE_SWIPE__gesture_mouse_hold_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 . -*/ - -#include "swipe_gesture.h" - -#ifdef __cplusplus -extern "C" { -#endif - -namespace comfortable_swipe::gesture -{ - class mouse_hold_gesture : public swipe_gesture - { - public: - // constructor - mouse_hold_gesture( - const char* hold3, // 3 finger mouse down - const char* hold4 // 4 finger mouse down - ); - - // the button being clicked - int button; - - virtual ~mouse_hold_gesture(); - - // override begin and end for mousedown - virtual void begin() override; - virtual void update() override; - virtual void end() override; - - // provide our own mouse functions - virtual void do_mousedown(const char*); - virtual void do_mouseup(const char*); - virtual bool is_mousedown() const; - - // utility method to parse mouse input given config characters - static int parse_mouse_button(const char*); - - protected: - // command holders - const char * hold3; - const char * hold4; - - // flag we can use to check if mouse is down - bool flag_mousedown; - }; -} - -#ifdef __cplusplus -} -#endif - -#endif /* __COMFORTABLE_SWIPE__gesture_mouse_hold_gesture_h__ */ diff --git a/comfortable_swipe/gesture/swipe_gesture.cpp b/comfortable_swipe/gesture/swipe_gesture.cpp deleted file mode 100644 index 8402c76..0000000 --- a/comfortable_swipe/gesture/swipe_gesture.cpp +++ /dev/null @@ -1,131 +0,0 @@ -#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 . -*/ - -#include "swipe_gesture.h" -#include // std::cout, std::endl -#include // std::regex, std::regex_match, std::cmatch -#include // std::stoi, std::stof - -extern "C" { -#include // xdo, xdo_new, xdo_free, - // xdo_get_mouse_location - // CURRENT_WINDOW -} - -namespace comfortable_swipe::gesture { -/** - * Constructs a new fresh swipe gesture container. - */ -swipe_gesture::swipe_gesture() - : // construct our superclass - comfortable_swipe::gesture::xdo_gesture(), flag_swiping(false) { - // improve responsiveness of first gesture by pre-empting xdotool - xdo_get_mouse_location(this->xdo, &this->ix, &this->iy, &this->screen_num); -} - -/** - * Destructs this swipe gesture. - */ -swipe_gesture::~swipe_gesture() {} - -/** - * Hook on begin of swipe gesture (you can override this). - */ -void swipe_gesture::begin() { - // save current screen location for gestured mouse movement - xdo_get_mouse_location(this->xdo, &this->ix, &this->iy, &this->screen_num); - this->x = 0; - this->y = 0; - this->ux = 0; - this->uy = 0; -} - -/** - * Hook on update of swipe gesture (you can override this). - */ -void swipe_gesture::update() { - this->x += this->dx; - this->y += this->dy; - this->ux += this->udx; - this->uy += this->udy; -} - -/** - * Hook on end of swipe gesture (you can override this). - */ -void swipe_gesture::end() {} - -/** - * Dispatches begin/update/end depending on the regex pattern provided by this - * class. - * - * @param line the line from libinput debug-events to parse - * @return true if begin/update/end was dispatched - */ -bool swipe_gesture::parse_line(const char *line) { - - // prepare regex matchers statically (will only load at most once) - static const std::regex gesture_swipe_begin( - swipe_gesture::GESTURE_BEGIN_REGEX_PATTERN), - gesture_swipe_update(swipe_gesture::GESTURE_UPDATE_REGEX_PATTERN), - gesture_swipe_end(swipe_gesture::GESTURE_END_REGEX_PATTERN); - - // prepare holder for regex matches - static std::cmatch matches; - - if (this->flag_swiping) { - // currently swiping - if (std::regex_match(line, matches, gesture_swipe_update) != 0) { - // assign necessary variables for swipe update - this->fingers = std::stoi(matches[1]); - this->dx = std::stof(matches[2]); - this->dy = std::stof(matches[3]); - this->udx = std::stof(matches[4]); - this->udy = std::stof(matches[5]); - // dispatch update - this->update(); - return true; - } else if (std::regex_match(line, matches, gesture_swipe_end) != 0) { - // assign necessary variables for swipe end - this->flag_swiping = false; - this->fingers = std::stoi(matches[1]); - // dispatch end - this->end(); - return true; - } - } else { - // not swiping, check if swipe will begin - if (std::regex_match(line, matches, gesture_swipe_begin) != 0 || - std::regex_match(line, matches, gesture_swipe_update) != 0) { - // assign necessary variables for swipe begin - this->flag_swiping = true; - this->fingers = std::stoi(matches[1]); - // dispatch begin - this->begin(); - return true; - } - } - - return false; -} -} // namespace comfortable_swipe::gesture - -#endif /* __COMFORTABLE_SWIPE__gesture_swipe_gesture__ */ diff --git a/comfortable_swipe/gesture/swipe_gesture.h b/comfortable_swipe/gesture/swipe_gesture.h deleted file mode 100644 index 36a0744..0000000 --- a/comfortable_swipe/gesture/swipe_gesture.h +++ /dev/null @@ -1,73 +0,0 @@ -#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 . -*/ - -#include "xdo_gesture.h" - -#ifdef __cplusplus -extern "C" { -#endif - -namespace comfortable_swipe::gesture -{ - class swipe_gesture : public xdo_gesture - { - public: - // constructor - swipe_gesture(); - - // destructor - virtual ~swipe_gesture(); - - // fields for xdo - int fingers; - - // normal values (for touchpad mapping) - float x, y, dx, dy; - - // unaccelerated values (for screen mapping) - float ux, uy, udx, udy; - - // hooks that we can override (mark as virtual) - virtual void begin(); - virtual void update(); - virtual void end(); - virtual bool parse_line(const char *); - - protected: - // location of mouse - int screen_num, ix, iy; - - // optimization flag for checking if GESTURE_SWIPE_BEGIN was dispatched - bool flag_swiping; - - public: - // regex patterns - static const char* GESTURE_BEGIN_REGEX_PATTERN; - static const char* GESTURE_UPDATE_REGEX_PATTERN; - static const char* GESTURE_END_REGEX_PATTERN; - }; -} - -#ifdef __cplusplus -} -#endif - -#endif /* __COMFORTABLE_SWIPE__gesture_swipe_gesture_h__ */ diff --git a/comfortable_swipe/gesture/swipe_gesture.regex.cpp b/comfortable_swipe/gesture/swipe_gesture.regex.cpp deleted file mode 100644 index 2fe32cd..0000000 --- a/comfortable_swipe/gesture/swipe_gesture.regex.cpp +++ /dev/null @@ -1,91 +0,0 @@ -#ifndef __COMFORTABLE_SWIPE__gesture_swipe_gesture_regex__ -#define __COMFORTABLE_SWIPE__gesture_swipe_gesture_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 . -*/ - -#include "swipe_gesture.h" - -namespace comfortable_swipe::gesture { -/** - * 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 *swipe_gesture::GESTURE_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 *swipe_gesture::GESTURE_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 *swipe_gesture::GESTURE_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 -} // namespace comfortable_swipe::gesture - -#endif /* __COMFORTABLE_SWIPE__gesture_swipe_gesture_regex__ */ diff --git a/comfortable_swipe/gesture/xdo_gesture.cpp b/comfortable_swipe/gesture/xdo_gesture.cpp deleted file mode 100644 index f9d0d47..0000000 --- a/comfortable_swipe/gesture/xdo_gesture.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef __COMFORTABLE_SWIPE__xdo_gesture__ -#define __COMFORTABLE_SWIPE__xdo_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 . -*/ - -extern "C" { -#include // xdo, xdo_new -} - -#include "xdo_gesture.h" - -namespace comfortable_swipe::gesture { -/** - * Constructs a new gesture handler with xdo. - */ -xdo_gesture::xdo_gesture() : xdo(xdo_new(NULL)) {} - -/** - * Constructs a new swipe gesture with xdo. - */ -xdo_gesture::~xdo_gesture() { xdo_free(this->xdo); } -} // namespace comfortable_swipe::gesture - -#endif /* __COMFORTABLE_SWIPE__xdo_gesture__ */ diff --git a/comfortable_swipe/gesture/xdo_gesture.h b/comfortable_swipe/gesture/xdo_gesture.h deleted file mode 100644 index a6d5625..0000000 --- a/comfortable_swipe/gesture/xdo_gesture.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef __COMFORTABLE_SWIPE__xdo_gesture_h__ -#define __COMFORTABLE_SWIPE__xdo_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 . -*/ - -extern "C" -{ - #include // xdo_t -} - -#ifdef __cplusplus -extern "C" { -#endif - -namespace comfortable_swipe -{ - namespace gesture - { - class xdo_gesture - { - protected: - xdo_t * xdo; - - public: - xdo_gesture(); - virtual ~xdo_gesture(); - }; - } -} - -#ifdef __cplusplus -} -#endif - -#endif /* __COMFORTABLE_SWIPE__xdo_gesture_h__ */ diff --git a/comfortable_swipe/lib b/comfortable_swipe/lib deleted file mode 100644 index 4854836..0000000 --- a/comfortable_swipe/lib +++ /dev/null @@ -1,47 +0,0 @@ -#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 . -*/ - -#include "all_headers.hpp" - -/** - * Add all cpp files below to be ready for export. - */ - -#include "driver.cpp" -#include "gesture/keyboard_swipe_gesture.cpp" -#include "gesture/mouse_hold_gesture.cpp" -#include "gesture/swipe_gesture.cpp" -#include "gesture/swipe_gesture.regex.cpp" -#include "gesture/xdo_gesture.cpp" -#include "service/autostart.cpp" -#include "service/buffer.cpp" -#include "service/config.cpp" -#include "service/debug.cpp" -#include "service/help.cpp" -#include "service/restart.cpp" -#include "service/start.cpp" -#include "service/status.cpp" -#include "service/stop.cpp" -#include "util/autostart_filename.cpp" -#include "util/conf_filename.cpp" -#include "util/read_config_file.cpp" - -#endif /* __COMFORTABLE_SWIPE__ */ diff --git a/comfortable_swipe/service/autostart.cpp b/comfortable_swipe/service/autostart.cpp deleted file mode 100644 index 6a10d07..0000000 --- a/comfortable_swipe/service/autostart.cpp +++ /dev/null @@ -1,66 +0,0 @@ -#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 . -*/ - -#include "../all_headers.hpp" -#include // std::remove -#include // std::system -#include // std::ifstream, std::ofstream -#include // std::cerr, std::cout, std::endl -#include // std::string - -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; - } - } -} -} // namespace comfortable_swipe::service - -#endif /* __COMFORTABLE_SWIPE__service_autostart__ */ diff --git a/comfortable_swipe/service/buffer.cpp b/comfortable_swipe/service/buffer.cpp deleted file mode 100644 index 6094390..0000000 --- a/comfortable_swipe/service/buffer.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#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 . -*/ - -#include "../all_headers.hpp" -#include // std::exit - -/** - * Starts the comfortable-swipe service by buffering libinput debug-events. - */ -namespace comfortable_swipe::service { -void buffer() { std::exit(comfortable_swipe::driver()); } -} // namespace comfortable_swipe::service - -#endif /* __COMFORTABLE_SWIPE__service_buffer__ */ diff --git a/comfortable_swipe/service/config.cpp b/comfortable_swipe/service/config.cpp deleted file mode 100644 index 0363793..0000000 --- a/comfortable_swipe/service/config.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef __COMFORTABLE_SWIPE__service_config__ -#define __COMFORTABLE_SWIPE__service_config__ - -/* -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 . -*/ - -#include "../all_headers.hpp" -#include // std::puts - -namespace comfortable_swipe::service { -/** - * Prints where the config file of comfortable swipe is located. - * - * Usage: nano $(comfortable-swipe config) - */ -void config() { std::puts(comfortable_swipe::util::conf_filename()); } -} // namespace comfortable_swipe::service - -#endif /* __COMFORTABLE_SWIPE__service_config__ */ diff --git a/comfortable_swipe/service/debug.cpp b/comfortable_swipe/service/debug.cpp deleted file mode 100644 index 07bda31..0000000 --- a/comfortable_swipe/service/debug.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef __COMFORTABLE_SWIPE__service_debug__ -#define __COMFORTABLE_SWIPE__service_debug__ - -/* -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 . -*/ - -#include // std::system - -namespace comfortable_swipe::service { -/** - * Debugs output from `libinput debug-events`. - */ -void debug() { - (void)std::system("bash -c \"stdbuf -oL -e0 libinput debug-events 2> >(grep " - "-v 'double tracking')\""); -} -} // namespace comfortable_swipe::service - -#endif /* __COMFORTABLE_SWIPE__service_debug__ */ diff --git a/comfortable_swipe/service/help.cpp b/comfortable_swipe/service/help.cpp deleted file mode 100644 index 47f76e6..0000000 --- a/comfortable_swipe/service/help.cpp +++ /dev/null @@ -1,50 +0,0 @@ -#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 . -*/ - -#include "../all_headers.hpp" -#include // std::puts, std::printf - -namespace comfortable_swipe::service { -/** - * Shows the help window. - */ -void help() { - using comfortable_swipe::util::conf_filename; - std::puts("comfortable-swipe " COMFORTABLE_SWIPE_VERSION - " [start|stop|restart|autostart|buffer|help|config|debug|status]"); - 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("config - locates the config file " - "[/usr/share/comfortable-swipe/comfortable-swipe.conf]"); - std::puts( - "debug - logs raw output from input events taken from libinput"); - std::puts("status - checks status of program and autostart"); - std::puts(""); - std::printf("Configuration file can be found in %s\n", conf_filename()); -} -} // namespace comfortable_swipe::service - -#endif /* __COMFORTABLE_SWIPE__service_help__ */ diff --git a/comfortable_swipe/service/restart.cpp b/comfortable_swipe/service/restart.cpp deleted file mode 100644 index 8485707..0000000 --- a/comfortable_swipe/service/restart.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#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 . -*/ - -#include "../all_headers.hpp" -#include // freopen, stdout - -namespace comfortable_swipe::service { -/** - * Restarts the comfortable-swipe service. - */ -void restart() { - // dont show stdout on stop - freopen("/dev/null", "a", stdout); - comfortable_swipe::service::stop(); - - // show back on start - freopen("/dev/tty", "a", stdout); - comfortable_swipe::service::start(); -} -} // namespace comfortable_swipe::service - -#endif /* __COMFORTABLE_SWIPE__service_restart__ */ diff --git a/comfortable_swipe/service/start.cpp b/comfortable_swipe/service/start.cpp deleted file mode 100644 index 6505284..0000000 --- a/comfortable_swipe/service/start.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#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 . -*/ - -#include "../all_headers.hpp" -#include // std::system - -namespace comfortable_swipe::service { -/** - * Starts the comfortable-swipe service by buffering libinput debug-events. - * This method is deferred. Please refer to comfortable_swipe::service::buffer() - * for the technical implementation. - */ -void start() { - (void)std::system(__COMFORTABLE_SWIPE__PROGRAM__ - " debug | " __COMFORTABLE_SWIPE__PROGRAM__ " buffer"); -} -} // namespace comfortable_swipe::service - -#endif /* __COMFORTABLE_SWIPE__service_start__ */ diff --git a/comfortable_swipe/service/status.cpp b/comfortable_swipe/service/status.cpp deleted file mode 100644 index 877e315..0000000 --- a/comfortable_swipe/service/status.cpp +++ /dev/null @@ -1,127 +0,0 @@ -#ifndef __COMFORTABLE_SWIPE__service_status__ -#define __COMFORTABLE_SWIPE__service_status__ - -/* -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 . -*/ - -#include "../all_headers.hpp" -#include // std::array -#include // FILE, std::feof, std::fgets, std::printf -#include // std::atoi -#include // std::unique_ptr -#include // std::cmatch, std::regex, std::regex_match -#include // std::runtime_error -#include // popen, pclose, getpid, access, F_OK - -namespace comfortable_swipe::service { -/** - * Prints the status of comfortable-swipe. - */ -void status() { - // check if comfortable-swipe is running - bool running = false; - std::array buffer; - std::unique_ptr pipe( - popen("pgrep -f comfortable-swipe", "r"), pclose); - if (pipe && !std::feof(pipe.get()) && - std::fgets(buffer.data(), buffer.size(), pipe.get()) != NULL) { - int pid = std::atoi(buffer.data()); - if (pid != getpid()) - running = true; - } - - // check if autostart is on - auto autostart_f = comfortable_swipe::util::autostart_filename(); - bool autostart_on = access(autostart_f, F_OK) != -1; - - std::puts(comfortable_swipe::util::conf_filename()); - - // check status of configuration file - try { - auto config = comfortable_swipe::util::read_config_file( - comfortable_swipe::util::conf_filename()); - - // formatting - const char *FORMAT_NO_ARGS = " %9s is %9s\n"; - const char *FORMAT_ARGS = " %9s is %9s (%s)\n"; - - // print threshold - if (config.count("threshold") > 0) { - auto &threshold = config["threshold"]; - - // check if regex pattern matches threshold - std::cmatch matches; - bool ok = (std::regex_match(threshold.data(), matches, - std::regex("^\\d+(?:\\.\\d+)??$")) != 0); - - // print status of threshold - std::printf(FORMAT_ARGS, "threshold", ok ? "VALID" : "INVALID", - threshold.data()); - } else - std::printf(FORMAT_NO_ARGS, "threshold", "NOTSET"); - - // print mouse hold commands - const char *mouse_hold_commands[] = {"hold3", "hold4"}; - bool has_mouse_hold[] = {false, false}; - int index = 0; - for (const auto *command : mouse_hold_commands) { - if (config.count(command) > 0) { - // check if command is valid - const auto &input = config[command]; - int button = - comfortable_swipe::gesture::mouse_hold_gesture::parse_mouse_button( - input.c_str()); - if (button != comfortable_swipe::gesture::MOUSE_NONE) { - std::printf(FORMAT_ARGS, command, "VALID", input.c_str()); - has_mouse_hold[index] = button; - } else { - std::printf(FORMAT_ARGS, command, "INVALID", input.c_str()); - } - } else - std::printf(FORMAT_NO_ARGS, command, "NOTSET"); - index += 1; - } - - // print swipe commands - for (auto &command : - comfortable_swipe::gesture::keyboard_swipe_gesture::command_map) { - if (config.count(command) > 0) { - int fingers = int(command[strlen(command) - 1] - '0'); - if (has_mouse_hold[fingers - 3]) { - // command is disabled because mouse hold exists - std::printf(FORMAT_ARGS, command, "DISABLED", config[command].data()); - } else { - // check if it's disabled by checking button - std::printf(FORMAT_ARGS, command, "VALID", config[command].data()); - } - } else - std::printf(FORMAT_NO_ARGS, command, "NOTSET"); - } - - } catch (const std::runtime_error &e) { - std::printf("config error: %s\n", e.what()); - } - - // print status - std::printf("\nautostart is %s\n", autostart_on ? "ON" : "OFF"); - std::printf("comfortable-swipe program is %s\n", - running ? "RUNNING" : "STOPPED"); -} -} // namespace comfortable_swipe::service - -#endif /* __COMFORTABLE_SWIPE__service_restart__ */ diff --git a/comfortable_swipe/service/stop.cpp b/comfortable_swipe/service/stop.cpp deleted file mode 100644 index ef9196b..0000000 --- a/comfortable_swipe/service/stop.cpp +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef __COMFORTABLE_SWIPE__service_stop__ -#define __COMFORTABLE_SWIPE__service_stop__ - -/* -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 . -*/ - -#include // std::array -#include // std::FILE, std::feof, std::fgets -#include // std::atoi, std::system -#include // std::unique_ptr -#include // std::runtime_error -#include // std::string, std::to_string -#include // popen, pclose, getpid - -namespace comfortable_swipe::service { -/** - * Stops all comfortable-swipe instances. - */ -void stop() { - - // read all service names from process (pgrep) - std::array buffer; - std::unique_ptr pipe( - popen("pgrep -f \"$(which comfortable-swipe)\"", "r"), pclose); - - // make sure pipe exists - if (!pipe) - throw std::runtime_error("stop command failed"); - - // buffer what to kill - std::string kill = ""; - - // read until end of line - while (!std::feof(pipe.get())) { - if (std::fgets(buffer.data(), buffer.size(), pipe.get()) != NULL) { - int pid = std::atoi(buffer.data()); - if (pid != getpid()) { - kill += " "; - kill += std::to_string(pid); - } - } - } - - // run "kill {pid1} {pid2}..." - if (kill.length()) { - std::printf("Stopped%s\n", kill.c_str()); - (void)std::system(("kill" + kill).c_str()); - } else { - std::printf("No program to stop\n"); - } -} -} // namespace comfortable_swipe::service - -#endif /* __COMFORTABLE_SWIPE__service_stop__ */ diff --git a/comfortable_swipe/util/autostart_filename.cpp b/comfortable_swipe/util/autostart_filename.cpp deleted file mode 100644 index a9f24b2..0000000 --- a/comfortable_swipe/util/autostart_filename.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#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 . -*/ - -#include // std::string -#include // 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(); -} -} // namespace comfortable_swipe::util - -#endif /* __COMFORTABLE_SWIPE__util_autostart_filename__ */ diff --git a/comfortable_swipe/util/conf_filename.cpp b/comfortable_swipe/util/conf_filename.cpp deleted file mode 100644 index 250a9e7..0000000 --- a/comfortable_swipe/util/conf_filename.cpp +++ /dev/null @@ -1,31 +0,0 @@ -#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 . -*/ - -#include "../all_headers.hpp" - -namespace comfortable_swipe::util { -/** - * The path where the configuration file is located. - */ -constexpr const char *conf_filename() { return __COMFORTABLE_SWIPE__CONFIG__; } -} // namespace comfortable_swipe::util - -#endif /* __COMFORTABLE_SWIPE__util_conf_filename__ */ diff --git a/comfortable_swipe/util/read_config_file.cpp b/comfortable_swipe/util/read_config_file.cpp deleted file mode 100644 index 11a9d79..0000000 --- a/comfortable_swipe/util/read_config_file.cpp +++ /dev/null @@ -1,94 +0,0 @@ -#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 . -*/ - -#include // std::isspace -#include // exit -#include // std::ifstream -#include // std::endl, std::getline -#include // std::map -#include // std::ostringstream -#include // std::runtime_error -#include // std::string - -namespace comfortable_swipe::util { -/** - * A utility method for reading the config file. - * - * @param filename (const char*) the path of the config file. - */ -std::map read_config_file(const char *filename) { - - std::map conf; - std::ifstream fin(filename); - - if (!fin.is_open()) { - throw std::runtime_error("config file does not exist"); - } - - 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::ostringstream stream; - stream << "error in conf file " << filename << std::endl; - stream << "multiple equal signs in line " << line_number << std::endl; - throw std::runtime_error(stream.str()); - } - } 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::ostringstream stream; - stream << "error in conf file: " << filename << std::endl; - stream << "equal sign expected in line " << line_number << std::endl; - throw std::runtime_error(stream.str()); - } - - // equal sign found, add to tokens - if (token[1].length() > 0) - conf[token[0]] = token[1]; - } - - return conf; -} -} // namespace comfortable_swipe::util -#endif /* __COMFORTABLE_SWIPE__util_read_config_file__ */ diff --git a/compile.sh b/compile.sh index 86b9b76..d9a664d 100755 --- a/compile.sh +++ b/compile.sh @@ -1,13 +1,9 @@ #!/bin/bash +# main compile script +# usage: ./compile.sh *.cpp +set -e -dir="$(dirname $0)" -version="$(cat "$dir/VERSION" | tr -d '[:space:]')" -libraries=-lxdo -lconfig++ +DIR="$(dirname $0)" +VERSION="$(cat "$DIR/VERSION" | tr -d '[:space:]')" -exec g++ $@ \ - -std=c++14 \ - -O2 \ - -lxdo \ - -lconfig++ \ - -Wno-unused-result \ - -DCOMFORTABLE_SWIPE_VERSION="\"$version\"" +g++ "$@" -std=c++14 -O2 -Wall -lxdo -linih -DCOMFORTABLE_SWIPE_VERSION="\"$VERSION\"" diff --git a/install b/install index 81af670..87a6587 100755 --- a/install +++ b/install @@ -2,95 +2,181 @@ set -e -function install { - # prefer running as root - local dir="$(dirname "$0")" - local program="comfortable-swipe" - local program_exe="/usr/local/bin/$program" - local compile_command="$dir/cpp.compile.sh" - local compile_target="$dir/command_line.cpp" - local conf_path="/usr/local/share/$program/$program.conf" - local dconf_path="$dir/defaults.conf" - local old_conf_path="${XDG_CONFIG_HOME:-$HOME/.config}/$program.conf" +DIR="$(dirname "$0")" +VERSION="$(cat $DIR/VERSION | tr -d '[:space:]')" - if [ -x "$(command -v "$program_exe")" ]; then - # stop any running $program if it exists - "$program_exe" stop > /dev/null - fi +# target executable +SOURCE="$DIR/comfortable-swipe" +TARGET="/usr/local/bin/comfortable-swipe" - #copy config file - abort () { - exec echo "Installation aborted" - } - sudo mkdir -p "$(dirname $conf_path)" || abort +# compile targets +COMPILE="$DIR/compile.sh" +COMPILE_SOURCE="$DIR/comfortable-swipe-main.cpp" +COMPILE_TARGET="/usr/local/bin/comfortable-swipe-buffer" - # check if "-y" or "--yes" is passed as an argument - YES=false - while test $# -gt 0 - do - case "$1" in - -y) YES=true - ;; - --yes) YES=true - ;; - esac - shift - done +# configurations +CONF_SOURCE="$DIR/defaults.conf" +CONF_TARGET="$HOME/.config/comfortable-swipe.conf" +OLD_CONF_TARGET="/usr/local/share/comfortable-swipe/comfortable-swipe.conf" - sudo chown $USER "$(dirname $conf_path)" - if [ ! -f "$conf_path" ]; then - if [ ! -f "$old_conf_path" ]; then - # old config file not found, create from scratch - cat "$dconf_path" > "$conf_path" || abort - else - # old config file found, move to the new path - cat "$old_conf_path" > "$conf_path" || abort - echo "Configuration copied from $old_conf_path to $conf_path" - fi - else - # config file found, ask user if overwrite - echo "Old conf file found in $conf_path" - if [ "$YES" == false ]; then - read -r -p "Keep the old conf file? (default: yes) [Y/n] " response - response="${response,,}" # tolower - if [[ "$response" =~ ^(no|n)$ ]]; then - read -r -p "Conf file will be overwritten. Are you sure? [Y/n] " response - response="${response,,}" - if [[ "$response" =~ ^(yes|y)$ ]]; then - cat "$dconf_path" > "$conf_path" || abort - else - abort - fi - fi - fi - fi +# autostart +AUTOSTART_SOURCE="$DIR/comfortable-swipe.desktop" +AUTOSTART_TARGET="$HOME/.config/autostart/comfortable-swipe.desktop" - echo "Installing to $program_exe ..." +# stop any running comfortable-swipe if it exists +comfortable-swipe stop > /dev/null 2>&1 || true - # remove existing $program - if [ -x "$(command -v "$program_exe")" ]; then - sudo rm -f "$(which "$program")" - fi - # compile library - sudo "$compile_command" "$compile_target" -o "$program_exe" || abort - - # add permissions to input group (defer) - # GROUP=$(ls -l /dev/input/event* | awk '{print $4}' | head --line=1) || abort - - # turn on autostart by default - local autostart_status="$("$program_exe" autostart)" - if [[ "$autostart_status" == *off* ]]; then - autostart_status="$("$program_exe" autostart)" - fi - - echo "Successfully installed $program $(cat $dir/VERSION | tr -d '[:space:]')" - echo "" - echo "$autostart_status" - echo "Edit configuration file: gedit \$($program config)" - echo "" - echo "Try running: $program start" +# shorthand to abort the installation +function abort { + echo "Installation aborted" + exit 1 } -install -unset -f install +# shorthand to try a command with sudo if it fails +function trysudo { + $@ 2> /dev/null || sudo $@ +} + +# uninstall existing program +function uninstall_existing { + local PROGRAM="${1:?missing program name}" + # remove existing comfortable-swipe + if [[ -x "$(command -v "$PROGRAM")" ]]; then + echo "Removing existing $(which "$PROGRAM") ..." + trysudo rm -f "$(which "$PROGRAM")" + fi +} + + +## CONFIGURATION FILE LOADING +# This section handles installation of configuration file. +# We determine first if any old configuration files exists. +# make sure config directory exists +function install_configuration_file { + mkdir -p "$(dirname "$CONF_TARGET")" + + # check if configuration already exists + if [[ -f "$CONF_TARGET" ]]; then + # ask user if we overwrite configuration + echo "Old conf file found in $CONF_TARGET" >&2 + read -r -p "Keep the old conf file? (default: yes) [Y/n] " response >&2 + if ! [[ "${response,,}" =~ ^(yes|y)$ ]]; then + # MAKE SURE they really want to overwrite + read -r -p "Conf file will be overwritten! Are you sure? [Y/n] " response >&2 + if [[ "${response,,}" =~ ^(yes|y)$ ]]; then + # They agreed... replace configuration + cat "$CONF_SOURCE" > "$CONF_TARGET" + else + abort + fi + fi + else + # target does not exist yet + # try copying from older configurations + if [[ -f "$OLD_CONF_TARGET" ]]; then + # move configuration from an older version (< v1.2) + echo "Moving configuration from $OLD_CONF_TARGET to $CONF_TARGET ..." + mv "$OLD_CONF_TARGET" "$CONF_TARGET" + # clean up old directory if possible + rmdir "$(dirname "$OLD_CONF_TARGET")" > /dev/null 2>&1 || true + else + # fresh installation! just copy default configuration + cat "$CONF_SOURCE" > "$CONF_TARGET" + fi + fi + + echo "Installed: $CONF_TARGET" +} + + +## Installation of main program +# +# /usr/local/bin/comfortable-swipe +# +function install_main_program { + # copy source to target with executable permissions + TRYSUDO= + if ! touch "$TARGET" 2> /dev/null; then + TRYSUDO=sudo + fi + # install to target, with hardcoded version + $TRYSUDO sed -E "s/^VERSION=.*/VERSION=$VERSION/" "$SOURCE" > "$TARGET" + # allow execute permissions + $TRYSUDO chmod +x "$TARGET" + echo "Installed: $TARGET" +} + + + +## Compilation and installation of C++ buffer program: +# +# /usr/local/bin/comfortable-swipe-buffer +# +function install_cpp_program { + # compile program to temporary file first + TMP_TARGET="$(mktemp)" + $COMPILE "$COMPILE_SOURCE" -o "$TMP_TARGET" -DCOMFORTABLE_SWIPE_VERSION="\"$VERSION\"" -DCOMFORTABLE_SWIPE_CONFIG="\"$CONF_TARGET\"" -DCOMFORTABLE_SWIPE_AUTOSTART="\"$AUTOSTART_TARGET\"" + # compilation ok, now try to install + # eheck permissions maybe if will need sudo + TRYSUDO= + if ! touch "$COMPILE_TARGET" 2> /dev/null; then + TRYSUDO=sudo + fi + # move executable to target + $TRYSUDO mv "$TMP_TARGET" "$COMPILE_TARGET" + echo "Installed: $COMPILE_TARGET" +} + + + +## Installation of Autostart Desktop file +# +# /home/$USER/.config/autostart/comfortable-swipe.desktop +# +function install_autostart { + cat "$AUTOSTART_SOURCE" > "$AUTOSTART_TARGET" + echo "Installed: $AUTOSTART_TARGET" +} + + +# uninstall existing commands +uninstall_existing comfortable-swipe +uninstall_existing comfortable-swipe-buffer + +# run install +INSTALLED_CONF="$(install_configuration_file)" +echo "Installing binaries ..." + +install_cpp_program +install_main_program +echo "$INSTALLED_CONF" +install_autostart + +# add permissions to input group (defer) +# GROUP=$(ls -l /dev/input/event* | awk '{print $4}' | head --line=1) || abort + +# make sure comfortable-swipe is in path +if ! command -v comfortable-swipe > /dev/null 2>&1; then +cat <&2 +WARNING: $(dirname "$TARGET") is not in PATH! +Make sure to add the following in your ~/.profile: + + export PATH="$PATH:$(dirname "$TARGET")" + +EOF +fi + +cat < /dev/null -comfortable-swipe stop 2> /dev/null -rm "$HOME/.local/bin/comfortable-swipe" 2> /dev/null # compat -sudo rm /usr/local/bin/comfortable-swipe 2> /dev/null -echo "Successfully uninstalled comfortable-swipe" +set -e + +function trysudo { + $@ 2> /dev/null || sudo $@ +} + +function uninstall { + TARGET="${1?missing uninstall parameter}" + if [[ -f "$TARGET" ]]; then + trysudo rm -f "$TARGET" + echo "Removed: $TARGET" + elif [[ ! -z "$TARGET" ]]; then + echo "Not found: $TARGET" + fi +} + +# stop program first if it is still running +comfortable-swipe stop 2> /dev/null || true + +# uninstall binaries +uninstall "$(which comfortable-swipe || echo /usr/share/bin/comfortable-swipe)" +uninstall "$(which comfortable-swipe-buffer || echo /usr/share/bin/comfortable-swipe-buffer)" + +# uninstall desktop file +uninstall "$HOME/.config/autostart/comfortable-swipe.desktop" + +# tell user we are keeping configuration file +CONF_TARGET="$HOME/.config/comfortable-swipe.conf" +if [ -f "$CONF_TARGET" ]; then + echo "Keeping your configuration file: $CONF_TARGET" +fi + +cat <