Remove old library files
This commit is contained in:
parent
a4089a80ba
commit
4509b57f8f
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,5 +1,6 @@
|
||||
# C++ generated headers
|
||||
*.gch
|
||||
*.o
|
||||
|
||||
# IDE-specific
|
||||
.idea
|
||||
|
||||
@ -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 <<EOF
|
||||
Usage: $basename [--help|--version] <command> [<args>]
|
||||
Usage: $BASENAME [--help|--version] <command> [<args>]
|
||||
|
||||
-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
|
||||
|
||||
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <cstdio> // fgets_unlocked, stdin
|
||||
#include <iostream> // ios, cout, cin
|
||||
#include <confuse.h> // 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 <do nothing>
|
||||
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<char, 256> 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
|
||||
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <array> // std::array
|
||||
#include <iostream> // std::cout
|
||||
#include <memory> // std::unique_ptr
|
||||
extern "C" {
|
||||
#include <confuse.h> // 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<cfg_t, decltype(&cfg_free)> 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_opt_t> 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__ */
|
||||
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* 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 */
|
||||
|
||||
|
||||
191
comfortable-swipe-gesture-swipe-xdokey.cpp
Normal file
191
comfortable-swipe-gesture-swipe-xdokey.cpp
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <iostream> // std::cout, std::endl
|
||||
#include <array> // std::array
|
||||
#include <string> // std::string
|
||||
|
||||
extern "C" {
|
||||
#include <xdo.h> // 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<std::string, 8> 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 <command_name>
|
||||
*
|
||||
* 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
|
||||
// <VERTICAL?> | <POSITIVE?> | <FOUR FINGERS?>
|
||||
"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__ */
|
||||
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <cstdio> // std::sscanf
|
||||
#include <cstring> // strncmp
|
||||
#include <iostream> // std::cout, std::endl
|
||||
|
||||
extern "C" {
|
||||
#include <xdo.h> // xdo, xdo_new, xdo_free,
|
||||
// xdo_get_mouse_location
|
||||
// CURRENT_WINDOW
|
||||
#include <xdo.h> // 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__ */
|
||||
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <iostream> // std::cout, std::endl
|
||||
#include <regex> // std::regex, std::regex_match, std::cmatch
|
||||
#include <string> // std::stoi, std::stof
|
||||
|
||||
extern "C" {
|
||||
#include <xdo.h> // 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__ */
|
||||
|
||||
105
comfortable-swipe-main.cpp
Normal file
105
comfortable-swipe-main.cpp
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <iostream> // std::ios, std::cin, std::getline
|
||||
#include <string> // std::string
|
||||
#include <map> // 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.h> // 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<std::string, std::string>*) 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<string, string> 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 <do nothing>
|
||||
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
|
||||
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// global defines
|
||||
#ifndef __COMFORTABLE_SWIPE__PROGRAM__
|
||||
#define __COMFORTABLE_SWIPE__PROGRAM__ "/usr/local/bin/comfortable-swipe"
|
||||
#endif /* __COMFORTABLE_SWIPE__PROGRAM__ */
|
||||
|
||||
#ifndef __COMFORTABLE_SWIPE__CONFIG__
|
||||
#define __COMFORTABLE_SWIPE__CONFIG__ \
|
||||
"/usr/local/share/comfortable-swipe/comfortable-swipe.conf"
|
||||
#endif /* __COMFORTABLE_SWIPE__CONFIG__ */
|
||||
|
||||
#ifndef COMFORTABLE_SWIPE_VERSION
|
||||
#warning COMFORTABLE_SWIPE_VERSION is not defined
|
||||
#define COMFORTABLE_SWIPE_VERSION "v(UNKNOWN)"
|
||||
#endif /* COMFORTABLE_SWIPE_VERSION */
|
||||
|
||||
#include <map> // std::map
|
||||
#include <string> // 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<std::string, std::string> 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__ */
|
||||
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "all_headers.hpp"
|
||||
#include <cstdio> // fgets_unlocked, stdin
|
||||
#include <iostream> // 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 <do nothing>
|
||||
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<char, 256> 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__ */
|
||||
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "keyboard_swipe_gesture.h"
|
||||
#include <iostream> // std::cout, std::endl
|
||||
|
||||
extern "C" {
|
||||
#include <xdo.h> // 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__ */
|
||||
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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__ */
|
||||
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "mouse_hold_gesture.h"
|
||||
#include <cstdio> // std::sscanf
|
||||
#include <cstring> // strncmp
|
||||
#include <iostream> // std::cout, std::endl
|
||||
|
||||
extern "C" {
|
||||
#include <xdo.h> // 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__ */
|
||||
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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__ */
|
||||
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "swipe_gesture.h"
|
||||
#include <iostream> // std::cout, std::endl
|
||||
#include <regex> // std::regex, std::regex_match, std::cmatch
|
||||
#include <string> // std::stoi, std::stof
|
||||
|
||||
extern "C" {
|
||||
#include <xdo.h> // 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__ */
|
||||
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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__ */
|
||||
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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__ */
|
||||
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
extern "C" {
|
||||
#include <xdo.h> // 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__ */
|
||||
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include <xdo.h> // 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__ */
|
||||
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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__ */
|
||||
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../all_headers.hpp"
|
||||
#include <cstdio> // std::remove
|
||||
#include <cstdlib> // std::system
|
||||
#include <fstream> // std::ifstream, std::ofstream
|
||||
#include <iostream> // std::cerr, std::cout, std::endl
|
||||
#include <string> // 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__ */
|
||||
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../all_headers.hpp"
|
||||
#include <cstdlib> // 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__ */
|
||||
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../all_headers.hpp"
|
||||
#include <cstdio> // 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__ */
|
||||
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <cstdlib> // 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__ */
|
||||
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../all_headers.hpp"
|
||||
#include <cstdio> // 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__ */
|
||||
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../all_headers.hpp"
|
||||
#include <cstdio> // 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__ */
|
||||
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../all_headers.hpp"
|
||||
#include <cstdlib> // 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__ */
|
||||
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../all_headers.hpp"
|
||||
#include <array> // std::array
|
||||
#include <cstdio> // FILE, std::feof, std::fgets, std::printf
|
||||
#include <cstdlib> // std::atoi
|
||||
#include <memory> // std::unique_ptr
|
||||
#include <regex> // std::cmatch, std::regex, std::regex_match
|
||||
#include <stdexcept> // std::runtime_error
|
||||
#include <unistd.h> // 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<char, 128> buffer;
|
||||
std::unique_ptr<FILE, decltype(&pclose)> 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__ */
|
||||
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <array> // std::array
|
||||
#include <cstdio> // std::FILE, std::feof, std::fgets
|
||||
#include <cstdlib> // std::atoi, std::system
|
||||
#include <memory> // std::unique_ptr
|
||||
#include <stdexcept> // std::runtime_error
|
||||
#include <string> // std::string, std::to_string
|
||||
#include <unistd.h> // popen, pclose, getpid
|
||||
|
||||
namespace comfortable_swipe::service {
|
||||
/**
|
||||
* Stops all comfortable-swipe instances.
|
||||
*/
|
||||
void stop() {
|
||||
|
||||
// read all service names from process (pgrep)
|
||||
std::array<char, 128> buffer;
|
||||
std::unique_ptr<FILE, decltype(&pclose)> 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__ */
|
||||
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <string> // std::string
|
||||
#include <unistd.h> // getenv
|
||||
|
||||
namespace comfortable_swipe::util {
|
||||
/**
|
||||
* The path where the autostart configuration is located.
|
||||
*/
|
||||
const char *autostart_filename() {
|
||||
static std::string filename;
|
||||
if (filename.empty()) {
|
||||
const char *xdg_config = getenv("XDG_CONFIG_HOME");
|
||||
std::string config(xdg_config == NULL
|
||||
? std::string(getenv("HOME")) + "/.config"
|
||||
: xdg_config);
|
||||
filename = config + "/autostart/comfortable-swipe.desktop";
|
||||
}
|
||||
return filename.data();
|
||||
}
|
||||
} // namespace comfortable_swipe::util
|
||||
|
||||
#endif /* __COMFORTABLE_SWIPE__util_autostart_filename__ */
|
||||
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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__ */
|
||||
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <cctype> // std::isspace
|
||||
#include <cstdlib> // exit
|
||||
#include <fstream> // std::ifstream
|
||||
#include <iostream> // std::endl, std::getline
|
||||
#include <map> // std::map
|
||||
#include <sstream> // std::ostringstream
|
||||
#include <stdexcept> // std::runtime_error
|
||||
#include <string> // 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<std::string, std::string> read_config_file(const char *filename) {
|
||||
|
||||
std::map<std::string, std::string> conf;
|
||||
std::ifstream fin(filename);
|
||||
|
||||
if (!fin.is_open()) {
|
||||
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__ */
|
||||
16
compile.sh
16
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\""
|
||||
|
||||
252
install
252
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 <<EOF >&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 <<EOF
|
||||
Autostart: $("$TARGET" autostart status)
|
||||
|
||||
To edit your configuration file, run:
|
||||
|
||||
gedit \$(comfortable-swipe config)
|
||||
|
||||
To start comfortable-swipe, run:
|
||||
|
||||
comfortable-swipe start
|
||||
|
||||
Successfully installed Comfortable Swipe $VERSION
|
||||
EOF
|
||||
|
||||
42
uninstall
42
uninstall
@ -1,8 +1,38 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "Uninstalling..."
|
||||
rm "${XDG_CONFIG_HOME:-$HOME/.config}/autostart/comfortable-swipe.desktop" 2> /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 <<EOF
|
||||
|
||||
Successfully uninstalled comfortable-swipe
|
||||
EOF
|
||||
|
||||
Loading…
Reference in New Issue
Block a user