Apply clang-format

This commit is contained in:
Rico Tiongson 2020-04-18 04:57:17 +08:00
parent 1ecfc79fc4
commit cb51d47a60
24 changed files with 928 additions and 1098 deletions

View File

@ -1,9 +1,3 @@
<<<<<<< Updated upstream
v1.1.0
* Added mouse hold gestures
* Added `hold3` configuration
* Added `hold4` configuration
=======
v1.1.0 (2020-04-18)
* Add mouse hold gestures
* Add experimental `hold3` configuration
@ -36,4 +30,3 @@ v1.0.1
v1.0.0
* Initial version
>>>>>>> Stashed changes

View File

@ -32,7 +32,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#endif /* __COMFORTABLE_SWIPE__PROGRAM__ */
#ifndef __COMFORTABLE_SWIPE__CONFIG__
#define __COMFORTABLE_SWIPE__CONFIG__ "/usr/local/share/comfortable-swipe/comfortable-swipe.conf"
#define __COMFORTABLE_SWIPE__CONFIG__ \
"/usr/local/share/comfortable-swipe/comfortable-swipe.conf"
#endif /* __COMFORTABLE_SWIPE__CONFIG__ */
#ifndef COMFORTABLE_SWIPE_VERSION
@ -40,42 +41,38 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define COMFORTABLE_SWIPE_VERSION "v(UNKNOWN)"
#endif /* COMFORTABLE_SWIPE_VERSION */
#include <map> // std::map
#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*);
}
// 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();
}
}
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/xdo_gesture.h"
#include "gesture/swipe_gesture.h"
#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__ */

View File

@ -19,74 +19,59 @@ 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> // std::ios, std::cout, std::cin
#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();
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()
);
// 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 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()
);
// 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;
// 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());
// 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;
// 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__ */

View File

@ -19,177 +19,150 @@ 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 "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
extern "C" {
#include <xdo.h> // xdo, xdo_new, xdo_free,
// xdo_get_mouse_location
// CURRENT_WINDOW
}
namespace comfortable_swipe::gesture
{
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"
};
/* 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
})
{ }
/**
* 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;
}
/**
* 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();
}
/**
* 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__ */

View File

@ -19,204 +19,162 @@ 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 <cstdio> // std::sscanf
#include <cstring> // strncmp
#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
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
};
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)
{ }
/**
* 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()
{ }
/**
* 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) const
{
// 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;
/**
* 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) const {
// 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__ */

View File

@ -19,131 +19,113 @@ 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 <string> // std::stoi, std::stof
#include <regex> // std::regex, std::regex_match, std::cmatch
#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
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 {
/**
* 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__ */

View File

@ -21,71 +21,71 @@ 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
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
/**
* 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 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 ")"
// 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
/**
* 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
}
// 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__ */

View File

@ -19,29 +19,22 @@ 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
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))
{ }
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);
}
}
/**
* Constructs a new swipe gesture with xdo.
*/
xdo_gesture::~xdo_gesture() { xdo_free(this->xdo); }
} // namespace comfortable_swipe::gesture
#endif /* __COMFORTABLE_SWIPE__xdo_gesture__ */

View File

@ -25,11 +25,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
* Add all cpp files below to be ready for export.
*/
#include "gesture/xdo_gesture.cpp"
#include "gesture/swipe_gesture.cpp"
#include "gesture/swipe_gesture.regex.cpp"
#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"
@ -42,6 +43,5 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "util/autostart_filename.cpp"
#include "util/conf_filename.cpp"
#include "util/read_config_file.cpp"
#include "driver.cpp"
#endif /* __COMFORTABLE_SWIPE__ */

View File

@ -19,57 +19,48 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <iostream> // std::cerr, std::cout, std::endl
#include <fstream> // std::ifstream, std::ofstream
#include <string> // std::string
#include <cstdio> // std::remove
#include <cstdlib> // std::system
#include "../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;
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;
}
}
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__ */

View File

@ -19,18 +19,14 @@ 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::exit
#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 {
void buffer() { std::exit(comfortable_swipe::driver()); }
} // namespace comfortable_swipe::service
#endif /* __COMFORTABLE_SWIPE__service_buffer__ */

View File

@ -19,20 +19,16 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <cstdio> // std::puts
#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 {
/**
* 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__ */

View File

@ -21,15 +21,14 @@ 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 {
/**
* 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__ */

View File

@ -19,31 +19,32 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <cstdio> // std::puts, std::printf
#include "../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 {
/**
* 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__ */

View File

@ -19,25 +19,22 @@ 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> // freopen, stdout
#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();
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();
}
// show back on start
freopen("/dev/tty", "a", stdout);
comfortable_swipe::service::start();
}
} // namespace comfortable_swipe::service
#endif /* __COMFORTABLE_SWIPE__service_restart__ */

View File

@ -19,20 +19,19 @@ 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
#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 {
/**
* 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__ */

View File

@ -19,77 +19,75 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdexcept> // std::runtime_error
#include <unistd.h> // popen, pclose, getpid, access, F_OK
#include <memory> // std::unique_ptr
#include <array> // std::array
#include <cstdlib> // std::atoi
#include <cstdio> // FILE, std::feof, std::fgets, std::printf
#include <regex> // std::cmatch, std::regex, std::regex_match
#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;
}
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;
// 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());
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());
// check status of configuration file
try {
auto config = comfortable_swipe::util::read_config_file(
comfortable_swipe::util::conf_filename());
// print threshold
if (config.count("threshold") > 0)
{
auto & threshold = config["threshold"];
// 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);
// 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(" %9s is %s (%s)\n", "threshold", ok ? "OK" : "INVALID", threshold.data());
}
else
std::printf(" %9s is OFF\n", "threshold");
// print status of threshold
std::printf(" %9s is %s (%s)\n", "threshold", ok ? "OK" : "INVALID",
threshold.data());
} else
std::printf(" %9s is OFF\n", "threshold");
// print swipe commands
for (auto &command : comfortable_swipe::gesture::keyboard_swipe_gesture::command_map)
{
if (config.count(command) > 0)
std::printf(" %9s is OK (%s)\n", command, config[command].data());
else
std::printf(" %9s is OFF\n", command);
}
}
catch (const std::runtime_error& e)
{
std::printf("config error: %s\n", e.what());
}
// print status
std::printf("autostart is %s\n", autostart_on ? "ON" : "OFF");
std::printf("comfortable-swipe program is %s\n", running ? "RUNNING" : "STOPPED");
// print swipe commands
for (auto &command :
comfortable_swipe::gesture::keyboard_swipe_gesture::command_map) {
if (config.count(command) > 0)
std::printf(" %9s is OK (%s)\n", command, config[command].data());
else
std::printf(" %9s is OFF\n", command);
}
} catch (const std::runtime_error &e) {
std::printf("config error: %s\n", e.what());
}
// print status
std::printf("autostart 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__ */

View File

@ -19,58 +19,51 @@ 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 <unistd.h> // popen, pclose, getpid
#include <memory> // std::unique_ptr
#include <array> // std::array
#include <cstdio> // std::FILE, std::feof, std::fgets
#include <cstdlib> // std::atoi, std::system
#include <string> // std::string, std::to_string
#include <string> // std::string, std::to_string
#include <unistd.h> // popen, pclose, getpid
namespace comfortable_swipe::service
{
/**
* Stops all comfortable-swipe instances.
*/
void stop()
{
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);
// 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");
// make sure pipe exists
if (!pipe)
throw std::runtime_error("stop command failed");
// buffer what to kill
std::string kill = "";
// 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");
}
// 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__ */

View File

@ -19,28 +19,24 @@ 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 <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 {
/**
* 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__ */

View File

@ -21,15 +21,11 @@ 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 {
/**
* 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__ */

View File

@ -19,85 +19,76 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <map> // std::map
#include <string> // std::string
#include <fstream> // std::ifstream
#include <sstream> // std::ostringstream
#include <iostream> // std::endl, std::getline
#include <cstdlib> // exit
#include <cctype> // std::isspace
#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)
{
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);
std::map<std::string, std::string> conf;
std::ifstream fin(filename);
if (!fin.is_open())
{
throw std::runtime_error("config file does not exist");
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());
}
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;
} 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__ */

View File

@ -16,55 +16,52 @@ 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 <ios> // std::ios
#include <iostream> // std::cin, std::cout, std::cerr
#include <string> // std::string
#include "comfortable_swipe/lib"
#include <ios> // std::ios
#include <iostream> // std::cin, std::cout, std::cerr
#include <string> // std::string
/* Command-line function. */
int main(int argc, char** args)
{
// improve buffering by decoupling loggers from stdio
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
std::cerr.tie(0);
int main(int argc, char **args) {
// improve buffering by decoupling loggers from stdio
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
std::cerr.tie(0);
if (argc > 1)
{
std::string arg = args[1];
if (argc > 1) {
std::string arg = args[1];
// select based on argument
if (arg == "start")
comfortable_swipe::service::start();
// select based on argument
if (arg == "start")
comfortable_swipe::service::start();
else if (arg == "stop")
comfortable_swipe::service::stop();
else if (arg == "stop")
comfortable_swipe::service::stop();
else if (arg == "restart")
comfortable_swipe::service::restart();
else if (arg == "restart")
comfortable_swipe::service::restart();
else if (arg == "buffer")
comfortable_swipe::service::buffer();
else if (arg == "buffer")
comfortable_swipe::service::buffer();
else if (arg == "autostart")
comfortable_swipe::service::autostart();
else if (arg == "autostart")
comfortable_swipe::service::autostart();
else if (arg == "config")
comfortable_swipe::service::config();
else if (arg == "config")
comfortable_swipe::service::config();
else if (arg == "debug")
comfortable_swipe::service::debug();
else if (arg == "debug")
comfortable_swipe::service::debug();
else if (arg == "status")
comfortable_swipe::service::status();
else if (arg == "status")
comfortable_swipe::service::status();
else /* if (arg == "help") */
comfortable_swipe::service::help();
}
else
comfortable_swipe::service::help();
else /* if (arg == "help") */
comfortable_swipe::service::help();
} else
comfortable_swipe::service::help();
return 0;
return 0;
}

18
install
View File

@ -5,17 +5,17 @@ set -e
function install {
# prefer running as root
local dir="$(dirname "$0")"
local program=comfortable-swipe
local program_exe=/usr/local/bin/$program
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 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"
if [ -x "$(command -v $program_exe)" ]; then
if [ -x "$(command -v "$program_exe")" ]; then
# stop any running $program if it exists
$program_exe stop
"$program_exe" stop > /dev/null
fi
#copy config file
@ -68,8 +68,8 @@ function install {
echo "Installing to $program_exe ..."
# remove existing $program
if [ -x "$(command -v $program_exe)" ]; then
sudo rm -f "$(which $program)"
if [ -x "$(command -v "$program_exe")" ]; then
sudo rm -f "$(which "$program")"
fi
# compile library
@ -79,9 +79,9 @@ function install {
# GROUP=$(ls -l /dev/input/event* | awk '{print $4}' | head --line=1) || abort
# turn on autostart by default
local autostart_status="$($program_exe autostart)"
local autostart_status="$("$program_exe" autostart)"
if [[ "$autostart_status" == *off* ]]; then
autostart_status="$($program_exe autostart)"
autostart_status="$("$program_exe" autostart)"
fi
echo "Successfully installed $program $(cat $dir/VERSION | tr -d '[:space:]')"

133
tests/test_regex.cpp Executable file → Normal file
View File

@ -1,9 +1,9 @@
#include <iostream>
#include <cassert>
#include <regex>
#include <string>
#include "../comfortable_swipe/gesture/swipe_gesture.h"
#include "../comfortable_swipe/gesture/swipe_gesture.regex.cpp"
#include <cassert>
#include <iostream>
#include <regex>
#include <string>
/*
Comfortable Swipe
@ -23,71 +23,70 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace test
{
void gesture_begin_should_match_regex();
void gesture_update_should_match_regex();
void gesture_end_should_match_regex();
namespace test {
void gesture_begin_should_match_regex();
void gesture_update_should_match_regex();
void gesture_end_should_match_regex();
} // namespace test
int main() {
std::cout << "(1) Testing gesture_begin_should_match_regex()" << std::endl;
test::gesture_begin_should_match_regex();
std::cout << "(2) Testing gesture_begin_should_match_regex()" << std::endl;
test::gesture_update_should_match_regex();
std::cout << "(3) Testing gesture_begin_should_match_regex()" << std::endl;
test::gesture_end_should_match_regex();
std::cout << "ALL TEST PASSED" << std::endl;
}
int main()
{
std::cout << "(1) Testing gesture_begin_should_match_regex()" << std::endl;
test::gesture_begin_should_match_regex();
std::cout << "(2) Testing gesture_begin_should_match_regex()" << std::endl;
test::gesture_update_should_match_regex();
std::cout << "(3) Testing gesture_begin_should_match_regex()" << std::endl;
test::gesture_end_should_match_regex();
std::cout << "ALL TEST PASSED" << std::endl;
namespace test {
void gesture_begin_test(const std::regex &matcher, const char *data,
const char *expected_fingers) {
std::cout << " testing against \"" << data << "\"...";
std::cmatch matches;
int result = std::regex_match(data, matches, matcher);
assert(result != 0);
assert((std::string)matches[1] == expected_fingers);
std::cout << "PASSED" << std::endl;
}
namespace test
{
void gesture_begin_test(
const std::regex& matcher,
const char* data,
const char* expected_fingers)
{
std::cout << " testing against \"" << data << "\"...";
std::cmatch matches;
int result = std::regex_match(data, matches, matcher);
assert(result != 0);
assert((std::string) matches[1] == expected_fingers);
std::cout << "PASSED" << std::endl;
}
void gesture_begin_should_match_regex()
{
std::regex matcher(comfortable_swipe::gesture::swipe_gesture::GESTURE_BEGIN_REGEX_PATTERN);
test::gesture_begin_test(matcher, " event15 GESTURE_SWIPE_BEGIN +34.33s 3\n", "3");
test::gesture_begin_test(matcher, "-event4 GESTURE_SWIPE_BEGIN +3.12s 4\n", "4");
test::gesture_begin_test(matcher, "-event7 GESTURE_SWIPE_BEGIN +4.72s 3\n", "3");
test::gesture_begin_test(matcher, " event9 GESTURE_SWIPE_BEGIN +45.80s 4\n", "4");
}
void gesture_update_should_match_regex()
{
const char* data = " event15 GESTURE_SWIPE_UPDATE +34.70s 3 -0.12/ 4.99 (-0.33/13.50 unaccelerated)\n";
std::regex matcher(comfortable_swipe::gesture::swipe_gesture::GESTURE_UPDATE_REGEX_PATTERN);
std::cmatch matches;
auto result = std::regex_match(data, matches, matcher);
assert(result != 0);
assert((std::string) matches[1] == "3");
assert((std::string) matches[2] == "-0.12");
assert((std::string) matches[3] == "4.99");
assert((std::string) matches[4] == "-0.33");
assert((std::string) matches[5] == "13.50");
}
void gesture_end_should_match_regex()
{
const char* data = " event15 GESTURE_SWIPE_END +35.03s 3\n";
std::regex matcher(comfortable_swipe::gesture::swipe_gesture::GESTURE_END_REGEX_PATTERN);
std::cmatch matches;
auto result = std::regex_match(data, matches, matcher);
assert(result != 0);
assert((std::string) matches[1] == "3");
}
void gesture_begin_should_match_regex() {
std::regex matcher(
comfortable_swipe::gesture::swipe_gesture::GESTURE_BEGIN_REGEX_PATTERN);
test::gesture_begin_test(matcher, " event15 GESTURE_SWIPE_BEGIN +34.33s 3\n",
"3");
test::gesture_begin_test(matcher, "-event4 GESTURE_SWIPE_BEGIN +3.12s 4\n",
"4");
test::gesture_begin_test(matcher, "-event7 GESTURE_SWIPE_BEGIN +4.72s 3\n",
"3");
test::gesture_begin_test(matcher, " event9 GESTURE_SWIPE_BEGIN +45.80s 4\n",
"4");
}
void gesture_update_should_match_regex() {
const char *data = " event15 GESTURE_SWIPE_UPDATE +34.70s 3 -0.12/ 4.99 "
"(-0.33/13.50 unaccelerated)\n";
std::regex matcher(
comfortable_swipe::gesture::swipe_gesture::GESTURE_UPDATE_REGEX_PATTERN);
std::cmatch matches;
auto result = std::regex_match(data, matches, matcher);
assert(result != 0);
assert((std::string)matches[1] == "3");
assert((std::string)matches[2] == "-0.12");
assert((std::string)matches[3] == "4.99");
assert((std::string)matches[4] == "-0.33");
assert((std::string)matches[5] == "13.50");
}
void gesture_end_should_match_regex() {
const char *data = " event15 GESTURE_SWIPE_END +35.03s 3\n";
std::regex matcher(
comfortable_swipe::gesture::swipe_gesture::GESTURE_END_REGEX_PATTERN);
std::cmatch matches;
auto result = std::regex_match(data, matches, matcher);
assert(result != 0);
assert((std::string)matches[1] == "3");
}
} // namespace test