From 33c737177a67b216eaa29b304eb9af6fb5478239 Mon Sep 17 00:00:00 2001 From: Alex Zaslavsky Date: Sun, 27 Oct 2019 19:14:50 +0200 Subject: [PATCH 1/8] - Added pinch gestures Basic implementation enables one shot pinch gesture. That is the command from config file will run only once as soon as fingers move 50% from the initial fingers position. - Added a configurable distance variable to pinch gesture. I felt that pinch gesture is kinda tricky to execute on touchpad, so I changed a way of calculation when to trigger the command and added the distance for fingers travel to configuration. Basically a `0.5` distance feels quite ok to me, but it becomes really snappy at `0.1`. --- README.md | 20 ++++++++++++- src/config/config.cpp | 10 +++++-- src/config/config.h | 10 +++++-- src/io/input.cpp | 70 +++++++++++++++++++++++++++++++++++++------ src/io/input.h | 23 ++++++++++++-- 5 files changed, 114 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index bb51f9e..741395f 100644 --- a/README.md +++ b/README.md @@ -55,8 +55,17 @@ right_down = "" down = "" left = "" right = "" + +[commands.pinch] +in = "" +out = "" +distance="" ``` +* `distance` variable in `commands.pinch` sets the distance between fingers where it shold trigger. + Defaults to `0.5` which means fingers should travel exactly half way from their initial position. + + ### Repository versions ![](https://img.shields.io/aur/version/gebaar.svg?style=flat) @@ -77,6 +86,7 @@ down = "bspc node -f south" left = "bspc node -f west" right = "bspc node -f east" + [commands.swipe.four] left_up = "" right_up = "" @@ -86,6 +96,11 @@ right_down = "" down = "" left = "bspc desktop -f prev" right = "bspc desktop -f next" + +[commands.pinch] +in = "xdotool key Control_L+equal" +out = "xdotool key Control_L+minus" +ditance="0.1" ``` Add `gebaard -b` to `~/.config/bspwm/bspwmrc` @@ -93,9 +108,12 @@ Add `gebaard -b` to `~/.config/bspwm/bspwmrc` ### State of the project - [x] Receiving swipe events from libinput -- [ ] Receiving pinch/zoom events from libinput +- [x] Receiving pinch/zoom events from libinput + - [ ] Support continous pinch + - [ ] Support pinch-and-rotate gestures - [ ] Receiving rotation events from libinput - [x] Converting libinput events to motions - [x] Running commands based on motions - [x] Refactor code to be up to Release standards, instead of testing-hell + diff --git a/src/config/config.cpp b/src/config/config.cpp index bafa3c6..d13dcef 100644 --- a/src/config/config.cpp +++ b/src/config/config.cpp @@ -1,17 +1,17 @@ /* gebaar Copyright (C) 2019 coffee2code - + 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 . */ @@ -61,6 +61,10 @@ void gebaar::config::Config::load_config() swipe_four_commands[8] = *config->get_qualified_as("commands.swipe.four.down"); swipe_four_commands[9] = *config->get_qualified_as("commands.swipe.four.right_down"); + pinch_commands[PINCH_IN] = *config->get_qualified_as("commands.pinch.out"); + pinch_commands[PINCH_OUT] = *config->get_qualified_as("commands.pinch.in"); + pinch_commands[DISTANCE] = *config->get_qualified_as("commands.pinch.distance"); + loaded = true; } } diff --git a/src/config/config.h b/src/config/config.h index 499eb51..45e7642 100644 --- a/src/config/config.h +++ b/src/config/config.h @@ -1,17 +1,17 @@ /* gebaar Copyright (C) 2019 coffee2code - + 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 . */ @@ -33,8 +33,12 @@ namespace gebaar::config { void load_config(); + + enum pinches {PINCH_IN, PINCH_OUT, DISTANCE}; + std::string swipe_three_commands[10]; std::string swipe_four_commands[10]; + std::string pinch_commands[10]; private: bool config_file_exists(); diff --git a/src/io/input.cpp b/src/io/input.cpp index 943dc96..22f1409 100644 --- a/src/io/input.cpp +++ b/src/io/input.cpp @@ -1,17 +1,17 @@ /* gebaar Copyright (C) 2019 coffee2code - + 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 . */ @@ -28,6 +28,7 @@ gebaar::io::Input::Input(std::shared_ptr const& config_p { config = config_ptr; gesture_swipe_event = {}; + gesture_pinch_event = {}; } /** @@ -42,6 +43,54 @@ bool gebaar::io::Input::initialize_context() return libinput_udev_assign_seat(libinput, "seat0")==0; } + + +/** + * Pinch Gesture + * Currently supporting only "one shot" pinch-in and pinch-out gestures. + * @param gev Gesture Event + * @param begin Boolean to denote begin or continuation of gesture. + **/ +void gebaar::io::Input::handle_pinch_event(libinput_event_gesture* gev, bool begin) +{ + if (begin) { + gesture_pinch_event.fingers = libinput_event_gesture_get_finger_count(gev); + // Get pinch distance + try { + gesture_pinch_event.distance = std::stod(config->pinch_commands[config->DISTANCE]); + } + catch (const std::invalid_argument &ia) { + // Set default distance + gesture_pinch_event.distance = DEFAULT_DISTANCE; + } + // Reset pinch data + gesture_pinch_event.scale = DEFAULT_SCALE; + gesture_pinch_event.executed = false; + } + else { + // Ignore input after command execution + if (gesture_pinch_event.executed) return; + double new_scale = libinput_event_gesture_get_scale(gev); + if (new_scale > gesture_pinch_event.scale) { + // Scale up + // Add 1 to required distance to get 2 > x > 1 + if (new_scale > 1 + gesture_pinch_event.distance) { + std::system(config->pinch_commands[config->PINCH_IN].c_str()); + gesture_pinch_event.executed = true; + } + } + else { + // Scale Down + // Substract from 1 to have inverted value for pinch in gesture + if (gesture_pinch_event.scale < 1 - gesture_pinch_event.distance) { + std::system(config->pinch_commands[config->PINCH_OUT].c_str()); + gesture_pinch_event.executed = true; + } + } + gesture_pinch_event.scale = new_scale; + } +} + /** * This event has no coordinates, so it's an event that gives us a begin or end signal. * If it begins, we get the amount of fingers used. @@ -169,6 +218,15 @@ void gebaar::io::Input::handle_event() case LIBINPUT_EVENT_GESTURE_SWIPE_END: handle_swipe_event_without_coords(libinput_event_get_gesture_event(libinput_event), false); break; + case LIBINPUT_EVENT_GESTURE_PINCH_BEGIN: + handle_pinch_event(libinput_event_get_gesture_event(libinput_event), true); + break; + case LIBINPUT_EVENT_GESTURE_PINCH_UPDATE: + handle_pinch_event(libinput_event_get_gesture_event(libinput_event), false); + break; + case LIBINPUT_EVENT_GESTURE_PINCH_END: + handle_pinch_event(libinput_event_get_gesture_event(libinput_event), false); + break; case LIBINPUT_EVENT_NONE: break; case LIBINPUT_EVENT_DEVICE_ADDED: @@ -209,12 +267,6 @@ void gebaar::io::Input::handle_event() break; case LIBINPUT_EVENT_TABLET_PAD_STRIP: break; - case LIBINPUT_EVENT_GESTURE_PINCH_BEGIN: - break; - case LIBINPUT_EVENT_GESTURE_PINCH_UPDATE: - break; - case LIBINPUT_EVENT_GESTURE_PINCH_END: - break; case LIBINPUT_EVENT_SWITCH_TOGGLE: break; } diff --git a/src/io/input.h b/src/io/input.h index b40d61f..af52637 100644 --- a/src/io/input.h +++ b/src/io/input.h @@ -1,17 +1,17 @@ /* gebaar Copyright (C) 2019 coffee2code - + 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 . */ @@ -24,6 +24,10 @@ #include #include "../config/config.h" +#define DEFAULT_SCALE 1.0 +#define DEFAULT_DISTANCE 0.5 + + namespace gebaar::io { struct gesture_swipe_event { int fingers; @@ -31,6 +35,15 @@ namespace gebaar::io { double y; }; + struct gesture_pinch_event { + int fingers; + double scale; + double angle; + + double distance; + bool executed; + }; + class Input { public: Input(std::shared_ptr const& config_ptr); @@ -48,6 +61,7 @@ namespace gebaar::io { struct libinput_event* libinput_event; struct udev* udev; struct gesture_swipe_event gesture_swipe_event; + struct gesture_pinch_event gesture_pinch_event; bool initialize_context(); @@ -74,6 +88,9 @@ namespace gebaar::io { void handle_swipe_event_without_coords(libinput_event_gesture* gev, bool begin); void handle_swipe_event_with_coords(libinput_event_gesture* gev); + + void handle_pinch_event(libinput_event_gesture* gev, bool begin); + }; } From 42b068f463fa6434d87b3790d65d47dff39d2079 Mon Sep 17 00:00:00 2001 From: Alex Zaslavsky Date: Thu, 31 Oct 2019 13:31:45 +0200 Subject: [PATCH 2/8] Added swipe gestures threshold * Reorganized code a little bit - Previously swipe gesture was triggered only when fingers leaving touchpad thus threshold was useless. Moved trigger function outside of event handling. - Created reset functions for gestures to reset struct holding event data to default values. * Added swipe threshold. - Added new config keys * `settings.pinch.distance` - now instead of `pinch.commands.distance` holds the value required for fingers to travel before executing pinch gesture. * `settings.swipe.threshold` - new key to set how long should be swipe to execute command. --- src/config/config.cpp | 4 +- src/config/config.h | 4 +- src/io/input.cpp | 122 +++++++++++++++++++++++++++--------------- src/io/input.h | 16 +++++- 4 files changed, 98 insertions(+), 48 deletions(-) diff --git a/src/config/config.cpp b/src/config/config.cpp index d13dcef..6292580 100644 --- a/src/config/config.cpp +++ b/src/config/config.cpp @@ -63,7 +63,9 @@ void gebaar::config::Config::load_config() pinch_commands[PINCH_IN] = *config->get_qualified_as("commands.pinch.out"); pinch_commands[PINCH_OUT] = *config->get_qualified_as("commands.pinch.in"); - pinch_commands[DISTANCE] = *config->get_qualified_as("commands.pinch.distance"); + + settings[DISTANCE] = *config->get_qualified_as("settings.pinch.distance"); + settings[THRESHOLD] = *config->get_qualified_as("settings.swipe.threshold"); loaded = true; } diff --git a/src/config/config.h b/src/config/config.h index 45e7642..1841e49 100644 --- a/src/config/config.h +++ b/src/config/config.h @@ -34,11 +34,13 @@ namespace gebaar::config { void load_config(); - enum pinches {PINCH_IN, PINCH_OUT, DISTANCE}; + enum pinch {PINCH_IN, PINCH_OUT}; + enum settings {THRESHOLD, DISTANCE}; std::string swipe_three_commands[10]; std::string swipe_four_commands[10]; std::string pinch_commands[10]; + std::string settings[10]; private: bool config_file_exists(); diff --git a/src/io/input.cpp b/src/io/input.cpp index 22f1409..380c374 100644 --- a/src/io/input.cpp +++ b/src/io/input.cpp @@ -43,21 +43,26 @@ bool gebaar::io::Input::initialize_context() return libinput_udev_assign_seat(libinput, "seat0")==0; } - +/** + * Reset swipe event struct to defaults + */ +void gebaar::io::Input::reset_swipe_event() { + gesture_swipe_event = {}; + try { + gesture_swipe_event.threshold = std::stoi(config->settings[config->THRESHOLD]); + } + catch (const std::invalid_argument& ia){ + gesture_swipe_event.threshold = DEFAULT_THRESHOLD; + } +} /** - * Pinch Gesture - * Currently supporting only "one shot" pinch-in and pinch-out gestures. - * @param gev Gesture Event - * @param begin Boolean to denote begin or continuation of gesture. - **/ -void gebaar::io::Input::handle_pinch_event(libinput_event_gesture* gev, bool begin) -{ - if (begin) { - gesture_pinch_event.fingers = libinput_event_gesture_get_finger_count(gev); + * Reset pinch event struct to defaults + */ +void gebaar::io::Input::reset_pinch_event() { // Get pinch distance try { - gesture_pinch_event.distance = std::stod(config->pinch_commands[config->DISTANCE]); + gesture_pinch_event.distance = std::stod(config->settings[config->DISTANCE]); } catch (const std::invalid_argument &ia) { // Set default distance @@ -66,8 +71,24 @@ void gebaar::io::Input::handle_pinch_event(libinput_event_gesture* gev, bool beg // Reset pinch data gesture_pinch_event.scale = DEFAULT_SCALE; gesture_pinch_event.executed = false; +} + + +/** + * Pinch Gesture + * Currently supporting only "one shot" pinch-in and pinch-out gestures. + * @param gev Gesture Event + * @param begin Boolean to denote begin or continuation of gesture. + **/ +void gebaar::io::Input::handle_pinch_event(libinput_event_gesture* gev, bool begin) +{ + if (begin) { + reset_pinch_event(); + gesture_pinch_event.fingers = libinput_event_gesture_get_finger_count(gev); } else { + if (gesture_swipe_event.executed) return; + // Ignore input after command execution if (gesture_pinch_event.executed) return; double new_scale = libinput_event_gesture_get_scale(gev); @@ -104,41 +125,12 @@ void gebaar::io::Input::handle_swipe_event_without_coords(libinput_event_gesture if (begin) { gesture_swipe_event.fingers = libinput_event_gesture_get_finger_count(gev); } + // This executed when fingers left the touchpad else { - double x = gesture_swipe_event.x; - double y = gesture_swipe_event.y; - int swipe_type = 5; // middle = no swipe - // 1 = left_up, 2 = up, 3 = right_up... - // 1 2 3 - // 4 5 6 - // 7 8 9 - const double OBLIQUE_RATIO = 0.414; // =~ tan(22.5); - - if (abs(x) > abs(y)) { - // left or right swipe - swipe_type += x < 0 ? -1 : 1; - - // check for oblique swipe - if (abs(y) / abs(x) > OBLIQUE_RATIO) { - swipe_type += y < 0 ? -3 : 3; - } - } else { - // up of down swipe - swipe_type += y < 0 ? -3 : 3; - - // check for oblique swipe - if (abs(x) / abs(y) > OBLIQUE_RATIO) { - swipe_type += x < 0 ? -1 : 1; - } + if (!gesture_swipe_event.executed) { + trigger_swipe_command(); } - - if (gesture_swipe_event.fingers == 3) { - std::system(config->swipe_three_commands[swipe_type].c_str()); - } else if (gesture_swipe_event.fingers == 4) { - std::system(config->swipe_four_commands[swipe_type].c_str()); - } - - gesture_swipe_event = {}; + reset_swipe_event(); } } @@ -148,8 +140,50 @@ void gebaar::io::Input::handle_swipe_event_without_coords(libinput_event_gesture */ void gebaar::io::Input::handle_swipe_event_with_coords(libinput_event_gesture* gev) { + if (gesture_swipe_event.executed) return; + int threshold = std::stoi(config->settings[config->THRESHOLD]); gesture_swipe_event.x += libinput_event_gesture_get_dx(gev); gesture_swipe_event.y += libinput_event_gesture_get_dy(gev); + if (abs(gesture_swipe_event.x) > threshold || abs(gesture_swipe_event.y) > threshold) { + trigger_swipe_command(); + gesture_swipe_event.executed = true; + } +} + +void gebaar::io::Input::trigger_swipe_command() { + double x = gesture_swipe_event.x; + double y = gesture_swipe_event.y; + int swipe_type = 5; // middle = no swipe + // 1 = left_up, 2 = up, 3 = right_up... + // 1 2 3 + // 4 5 6 + // 7 8 9 + const double OBLIQUE_RATIO = 0.414; // =~ tan(22.5); + + if (abs(x) > abs(y)) { + // left or right swipe + swipe_type += x < 0 ? -1 : 1; + + // check for oblique swipe + if (abs(y) / abs(x) > OBLIQUE_RATIO) { + swipe_type += y < 0 ? -3 : 3; + } + } else { + // up of down swipe + swipe_type += y < 0 ? -3 : 3; + + // check for oblique swipe + if (abs(x) / abs(y) > OBLIQUE_RATIO) { + swipe_type += x < 0 ? -1 : 1; + } + } + + if (gesture_swipe_event.fingers == 3) { + std::system(config->swipe_three_commands[swipe_type].c_str()); + } else if (gesture_swipe_event.fingers == 4) { + std::system(config->swipe_four_commands[swipe_type].c_str()); + } + } /** diff --git a/src/io/input.h b/src/io/input.h index af52637..e391c0f 100644 --- a/src/io/input.h +++ b/src/io/input.h @@ -24,8 +24,9 @@ #include #include "../config/config.h" -#define DEFAULT_SCALE 1.0 -#define DEFAULT_DISTANCE 0.5 +#define DEFAULT_SCALE 1.0 +#define DEFAULT_DISTANCE 0.5 +#define DEFAULT_THRESHOLD 100 namespace gebaar::io { @@ -33,6 +34,9 @@ namespace gebaar::io { int fingers; double x; double y; + + int threshold; + bool executed; }; struct gesture_pinch_event { @@ -85,10 +89,18 @@ namespace gebaar::io { void handle_event(); + /* Swipe event */ + void reset_swipe_event(); + void handle_swipe_event_without_coords(libinput_event_gesture* gev, bool begin); void handle_swipe_event_with_coords(libinput_event_gesture* gev); + void trigger_swipe_command(); + + /* Pinch event */ + void reset_pinch_event(); + void handle_pinch_event(libinput_event_gesture* gev, bool begin); }; From 2d57aabd06a612f9df7e825b8758a94d07018ef9 Mon Sep 17 00:00:00 2001 From: Alex Zaslavsky Date: Thu, 31 Oct 2019 15:58:00 +0200 Subject: [PATCH 3/8] Updated README.md with settings examples --- README.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 741395f..833868f 100644 --- a/README.md +++ b/README.md @@ -59,12 +59,15 @@ right = "" [commands.pinch] in = "" out = "" -distance="" + +[settings] +pinch.distance = "" +swipe.threshold = "" ``` -* `distance` variable in `commands.pinch` sets the distance between fingers where it shold trigger. +* `settings.pinch.distance` key sets the distance between fingers where it shold trigger. Defaults to `0.5` which means fingers should travel exactly half way from their initial position. - +* `settings.swipe.threshold` sets the limit when swipe gesture should be executed. Defaults to 100. ### Repository versions @@ -100,7 +103,10 @@ right = "bspc desktop -f next" [commands.pinch] in = "xdotool key Control_L+equal" out = "xdotool key Control_L+minus" -ditance="0.1" + +[settings] +pinch.ditance="0.5" +swipe.threshold = "100" ``` Add `gebaard -b` to `~/.config/bspwm/bspwmrc` From 3047c04ac36f5836709a795647430db191c22bec Mon Sep 17 00:00:00 2001 From: Alex Kir Date: Thu, 31 Oct 2019 18:05:46 +0200 Subject: [PATCH 4/8] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 833868f..b37208f 100644 --- a/README.md +++ b/README.md @@ -114,6 +114,7 @@ Add `gebaard -b` to `~/.config/bspwm/bspwmrc` ### State of the project - [x] Receiving swipe events from libinput +- [x] Swipe gesture have trigger treshold - [x] Receiving pinch/zoom events from libinput - [ ] Support continous pinch - [ ] Support pinch-and-rotate gestures From 3178dc84a01ee15077e92eda8353d88a4711a137 Mon Sep 17 00:00:00 2001 From: Alex Kir Date: Thu, 31 Oct 2019 18:06:53 +0200 Subject: [PATCH 5/8] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index b37208f..b98047a 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ Gebaar ========= +Forked from Coffee2CodeNL/gebaar-libinput since original repo unmaintained for half a year. WM Independent Touchpad Gesture Daemon for libinput From 5771f0139e8a384823e9dba33439321d774e34ad Mon Sep 17 00:00:00 2001 From: Alex Zaslavsky Date: Fri, 1 Nov 2019 00:29:13 +0200 Subject: [PATCH 6/8] Unified setting names --- src/config/config.cpp | 4 ++-- src/config/config.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/config/config.cpp b/src/config/config.cpp index 6292580..0355f58 100644 --- a/src/config/config.cpp +++ b/src/config/config.cpp @@ -64,8 +64,8 @@ void gebaar::config::Config::load_config() pinch_commands[PINCH_IN] = *config->get_qualified_as("commands.pinch.out"); pinch_commands[PINCH_OUT] = *config->get_qualified_as("commands.pinch.in"); - settings[DISTANCE] = *config->get_qualified_as("settings.pinch.distance"); - settings[THRESHOLD] = *config->get_qualified_as("settings.swipe.threshold"); + settings[PINCH_THRESHOLD] = *config->get_qualified_as("settings.pinch.threshold"); + settings[SWIPE_THRESHOLD] = *config->get_qualified_as("settings.swipe.threshold"); loaded = true; } diff --git a/src/config/config.h b/src/config/config.h index 1841e49..273d05a 100644 --- a/src/config/config.h +++ b/src/config/config.h @@ -35,7 +35,7 @@ namespace gebaar::config { enum pinch {PINCH_IN, PINCH_OUT}; - enum settings {THRESHOLD, DISTANCE}; + enum settings {SWIPE_THRESHOLD, PINCH_THRESHOLD}; std::string swipe_three_commands[10]; std::string swipe_four_commands[10]; From 07b0ca898cc99ec9dbcc954fd80d2338a82531b3 Mon Sep 17 00:00:00 2001 From: Alex Zaslavsky Date: Sun, 3 Nov 2019 14:48:20 +0200 Subject: [PATCH 7/8] Continous pinch and swipe gestres This commit introduces breaking changes due to changes in config file format. Hopefully that's the last time. * Config keys changed format, see readme for examples. * Both swipe and pinch gestures now have `settings.threshold` key which can be values 0.0 - 1.0. Defaults: Swipe: 1.0 Pinch: 0.25 * Both swipe and pinch now have `settings.one_shot` which, if set, allows only one execution of command per gesture. Defaults: Swipe: true Pinch: false * Swipe gesture now has `settings.trigger_on_release` defaulting to false. If set to true the command for swipe will be triggered when fingers are moved from touchpad UNLESS it is also one_shot gesture and gesture was already triggered. --- README.md | 21 +++++---- src/config/config.cpp | 54 ++++++++++++---------- src/config/config.h | 16 +++++-- src/io/input.cpp | 103 +++++++++++++++++++++++++----------------- src/io/input.h | 28 +++++++++--- src/main.cpp | 1 + 6 files changed, 141 insertions(+), 82 deletions(-) diff --git a/README.md b/README.md index b98047a..8f5a73a 100644 --- a/README.md +++ b/README.md @@ -80,7 +80,7 @@ swipe.threshold = "" _~/.config/gebaar/gebaard.toml_ ```toml -[commands.swipe.three] +[swipe.commands.three] left_up = "" right_up = "" up = "bspc node -f north" @@ -91,7 +91,7 @@ left = "bspc node -f west" right = "bspc node -f east" -[commands.swipe.four] +[swipe.commands.four] left_up = "" right_up = "" up = "rofi -show combi" @@ -101,13 +101,18 @@ down = "" left = "bspc desktop -f prev" right = "bspc desktop -f next" -[commands.pinch] +[pinch.commands.two] in = "xdotool key Control_L+equal" out = "xdotool key Control_L+minus" -[settings] -pinch.ditance="0.5" -swipe.threshold = "100" +[pinch.settings] +threshold=0.25 +one_shot=false + +[swipe.settings] +threshold = 0.5 +one_shot = true +trigger_on_release = true ``` Add `gebaard -b` to `~/.config/bspwm/bspwmrc` @@ -117,8 +122,8 @@ Add `gebaard -b` to `~/.config/bspwm/bspwmrc` - [x] Receiving swipe events from libinput - [x] Swipe gesture have trigger treshold - [x] Receiving pinch/zoom events from libinput - - [ ] Support continous pinch - - [ ] Support pinch-and-rotate gestures +- [x] Support continous pinch +- [ ] Support pinch-and-rotate gestures - [ ] Receiving rotation events from libinput - [x] Converting libinput events to motions - [x] Running commands based on motions diff --git a/src/config/config.cpp b/src/config/config.cpp index 0355f58..0bbd0cc 100644 --- a/src/config/config.cpp +++ b/src/config/config.cpp @@ -43,29 +43,37 @@ void gebaar::config::Config::load_config() std::cerr << e.what() << std::endl; exit(EXIT_FAILURE); } - swipe_three_commands[1] = *config->get_qualified_as("commands.swipe.three.left_up"); - swipe_three_commands[2] = *config->get_qualified_as("commands.swipe.three.up"); - swipe_three_commands[3] = *config->get_qualified_as("commands.swipe.three.right_up"); - swipe_three_commands[4] = *config->get_qualified_as("commands.swipe.three.left"); - swipe_three_commands[6] = *config->get_qualified_as("commands.swipe.three.right"); - swipe_three_commands[7] = *config->get_qualified_as("commands.swipe.three.left_down"); - swipe_three_commands[8] = *config->get_qualified_as("commands.swipe.three.down"); - swipe_three_commands[9] = *config->get_qualified_as("commands.swipe.three.right_down"); - - swipe_four_commands[1] = *config->get_qualified_as("commands.swipe.four.left_up"); - swipe_four_commands[2] = *config->get_qualified_as("commands.swipe.four.up"); - swipe_four_commands[3] = *config->get_qualified_as("commands.swipe.four.right_up"); - swipe_four_commands[4] = *config->get_qualified_as("commands.swipe.four.left"); - swipe_four_commands[6] = *config->get_qualified_as("commands.swipe.four.right"); - swipe_four_commands[7] = *config->get_qualified_as("commands.swipe.four.left_down"); - swipe_four_commands[8] = *config->get_qualified_as("commands.swipe.four.down"); - swipe_four_commands[9] = *config->get_qualified_as("commands.swipe.four.right_down"); - - pinch_commands[PINCH_IN] = *config->get_qualified_as("commands.pinch.out"); - pinch_commands[PINCH_OUT] = *config->get_qualified_as("commands.pinch.in"); - - settings[PINCH_THRESHOLD] = *config->get_qualified_as("settings.pinch.threshold"); - settings[SWIPE_THRESHOLD] = *config->get_qualified_as("settings.swipe.threshold"); + + /* Swipe Settings */ + swipe_three_commands[1] = *config->get_qualified_as("swipe.commands.three.left_up"); + swipe_three_commands[2] = *config->get_qualified_as("swipe.commands.three.up"); + swipe_three_commands[3] = *config->get_qualified_as("swipe.commands.three.right_up"); + swipe_three_commands[4] = *config->get_qualified_as("swipe.commands.three.left"); + swipe_three_commands[6] = *config->get_qualified_as("swipe.commands.three.right"); + swipe_three_commands[7] = *config->get_qualified_as("swipe.commands.three.left_down"); + swipe_three_commands[8] = *config->get_qualified_as("swipe.commands.three.down"); + swipe_three_commands[9] = *config->get_qualified_as("swipe.commands.three.right_down"); + + swipe_four_commands[1] = *config->get_qualified_as("swipe.commands.four.left_up"); + swipe_four_commands[2] = *config->get_qualified_as("swipe.commands.four.up"); + swipe_four_commands[3] = *config->get_qualified_as("swipe.commands.four.right_up"); + swipe_four_commands[4] = *config->get_qualified_as("swipe.commands.four.left"); + swipe_four_commands[6] = *config->get_qualified_as("swipe.commands.four.right"); + swipe_four_commands[7] = *config->get_qualified_as("swipe.commands.four.left_down"); + swipe_four_commands[8] = *config->get_qualified_as("swipe.commands.four.down"); + swipe_four_commands[9] = *config->get_qualified_as("swipe.commands.four.right_down"); + + settings.swipe_threshold = config->get_qualified_as("swipe.settings.threshold").value_or(0.5); + settings.swipe_one_shot = config->get_qualified_as("swipe.settings.one_shot").value_or(true); + settings.swipe_trigger_on_release = config->get_qualified_as("swipe.settings.trigger_on_release").value_or(true); + + /* Pinch settings */ + pinch_commands[PINCH_IN] = *config->get_qualified_as("pinch.commands.two.out"); + pinch_commands[PINCH_OUT] = *config->get_qualified_as("pinch.commands.two.in"); + + settings.pinch_threshold = config->get_qualified_as("pinch.settings.threshold").value_or(0.25); + settings.pinch_one_shot = config->get_qualified_as("pinch.settings.one_shot").value_or(false); + loaded = true; } diff --git a/src/config/config.h b/src/config/config.h index 273d05a..34d7a42 100644 --- a/src/config/config.h +++ b/src/config/config.h @@ -34,21 +34,31 @@ namespace gebaar::config { void load_config(); - enum pinch {PINCH_IN, PINCH_OUT}; - enum settings {SWIPE_THRESHOLD, PINCH_THRESHOLD}; + struct settings { + bool pinch_one_shot; + double pinch_threshold; + + bool swipe_one_shot; + double swipe_threshold; + bool swipe_trigger_on_release; + } settings; + enum pinch {PINCH_IN, PINCH_OUT}; std::string swipe_three_commands[10]; std::string swipe_four_commands[10]; std::string pinch_commands[10]; - std::string settings[10]; private: + bool config_file_exists(); bool find_config_file(); + std::string config_file_path; std::shared_ptr config; + + }; } #endif //GEBAAR_CONFIG_H diff --git a/src/io/input.cpp b/src/io/input.cpp index 380c374..4c95cf4 100644 --- a/src/io/input.cpp +++ b/src/io/input.cpp @@ -28,7 +28,9 @@ gebaar::io::Input::Input(std::shared_ptr const& config_p { config = config_ptr; gesture_swipe_event = {}; + gesture_pinch_event = {}; + gesture_pinch_event.scale = DEFAULT_SCALE; } /** @@ -48,31 +50,60 @@ bool gebaar::io::Input::initialize_context() */ void gebaar::io::Input::reset_swipe_event() { gesture_swipe_event = {}; - try { - gesture_swipe_event.threshold = std::stoi(config->settings[config->THRESHOLD]); - } - catch (const std::invalid_argument& ia){ - gesture_swipe_event.threshold = DEFAULT_THRESHOLD; - } + gesture_swipe_event.executed = false; } /** * Reset pinch event struct to defaults */ void gebaar::io::Input::reset_pinch_event() { - // Get pinch distance - try { - gesture_pinch_event.distance = std::stod(config->settings[config->DISTANCE]); + gesture_pinch_event = {}; + gesture_pinch_event.scale = DEFAULT_SCALE; + gesture_pinch_event.executed = false; +} + +/** + * Pinch one_shot gesture handle + * @param new_scale last reported scale between the fingers + */ +void gebaar::io::Input::handle_one_shot_pinch(double new_scale) { + if (new_scale > gesture_pinch_event.scale) { // Scale up + // Add 1 to required distance to get 2 > x > 1 + if (new_scale > 1 + config->settings.pinch_threshold) { + std::system(config->pinch_commands[config->PINCH_IN].c_str()); + gesture_pinch_event.executed = true; } - catch (const std::invalid_argument &ia) { - // Set default distance - gesture_pinch_event.distance = DEFAULT_DISTANCE; + } + else { // Scale Down + // Substract from 1 to have inverted value for pinch in gesture + if (gesture_pinch_event.scale < 1 - config->settings.pinch_threshold) { + std::system(config->pinch_commands[config->PINCH_OUT].c_str()); + gesture_pinch_event.executed = true; } - // Reset pinch data - gesture_pinch_event.scale = DEFAULT_SCALE; - gesture_pinch_event.executed = false; + } } +/** + * Pinch continous gesture handle + * Calculates the trigger value according to current step + * @param new_scale last reported scale between the fingers + */ +void gebaar::io::Input::handle_continouos_pinch(double new_scale) { + int step = gesture_pinch_event.step == 0 ? gesture_pinch_event.step + 1 : gesture_pinch_event.step; + double trigger = 1 + (config->settings.pinch_threshold * step); + + if (new_scale > gesture_pinch_event.scale) { // Scale up + if (new_scale >= trigger){ + std::system(config->pinch_commands[config->PINCH_IN].c_str()); + inc_step(gesture_pinch_event.step); + } + } else { // Scale down + if (new_scale <= trigger){ + std::system(config->pinch_commands[config->PINCH_OUT].c_str()); + dec_step(gesture_pinch_event.step); + } + } +} /** * Pinch Gesture @@ -83,31 +114,13 @@ void gebaar::io::Input::reset_pinch_event() { void gebaar::io::Input::handle_pinch_event(libinput_event_gesture* gev, bool begin) { if (begin) { - reset_pinch_event(); - gesture_pinch_event.fingers = libinput_event_gesture_get_finger_count(gev); + reset_pinch_event(); + gesture_pinch_event.fingers = libinput_event_gesture_get_finger_count(gev); } else { - if (gesture_swipe_event.executed) return; - - // Ignore input after command execution - if (gesture_pinch_event.executed) return; double new_scale = libinput_event_gesture_get_scale(gev); - if (new_scale > gesture_pinch_event.scale) { - // Scale up - // Add 1 to required distance to get 2 > x > 1 - if (new_scale > 1 + gesture_pinch_event.distance) { - std::system(config->pinch_commands[config->PINCH_IN].c_str()); - gesture_pinch_event.executed = true; - } - } - else { - // Scale Down - // Substract from 1 to have inverted value for pinch in gesture - if (gesture_pinch_event.scale < 1 - gesture_pinch_event.distance) { - std::system(config->pinch_commands[config->PINCH_OUT].c_str()); - gesture_pinch_event.executed = true; - } - } + if (config->settings.pinch_one_shot && !gesture_pinch_event.executed) handle_one_shot_pinch(new_scale); + if (!config->settings.pinch_one_shot) handle_continouos_pinch(new_scale); gesture_pinch_event.scale = new_scale; } } @@ -127,7 +140,7 @@ void gebaar::io::Input::handle_swipe_event_without_coords(libinput_event_gesture } // This executed when fingers left the touchpad else { - if (!gesture_swipe_event.executed) { + if (!gesture_swipe_event.executed && config->settings.swipe_trigger_on_release) { trigger_swipe_command(); } reset_swipe_event(); @@ -140,8 +153,10 @@ void gebaar::io::Input::handle_swipe_event_without_coords(libinput_event_gesture */ void gebaar::io::Input::handle_swipe_event_with_coords(libinput_event_gesture* gev) { - if (gesture_swipe_event.executed) return; - int threshold = std::stoi(config->settings[config->THRESHOLD]); + if (config->settings.swipe_one_shot && gesture_swipe_event.executed) return; + + // Since swipe gesture counts in dpi we have to convert + int threshold = config->settings.swipe_threshold * 100; gesture_swipe_event.x += libinput_event_gesture_get_dx(gev); gesture_swipe_event.y += libinput_event_gesture_get_dy(gev); if (abs(gesture_swipe_event.x) > threshold || abs(gesture_swipe_event.y) > threshold) { @@ -150,6 +165,11 @@ void gebaar::io::Input::handle_swipe_event_with_coords(libinput_event_gesture* g } } + +/** + * Making calculation for swipe direction and triggering + * command accordingly + */ void gebaar::io::Input::trigger_swipe_command() { double x = gesture_swipe_event.x; double y = gesture_swipe_event.y; @@ -223,7 +243,8 @@ gebaar::io::Input::~Input() bool gebaar::io::Input::gesture_device_exists() { bool device_found = false; - while ((libinput_event = libinput_get_event(libinput))!=nullptr) { + + while ((libinput_event = libinput_get_event(libinput)) != nullptr) { auto device = libinput_event_get_device(libinput_event); if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_GESTURE)) { device_found = true; diff --git a/src/io/input.h b/src/io/input.h index e391c0f..17eacd1 100644 --- a/src/io/input.h +++ b/src/io/input.h @@ -24,10 +24,7 @@ #include #include "../config/config.h" -#define DEFAULT_SCALE 1.0 -#define DEFAULT_DISTANCE 0.5 -#define DEFAULT_THRESHOLD 100 - +#define DEFAULT_SCALE 1.0 namespace gebaar::io { struct gesture_swipe_event { @@ -35,8 +32,8 @@ namespace gebaar::io { double x; double y; - int threshold; bool executed; + int step; }; struct gesture_pinch_event { @@ -44,8 +41,8 @@ namespace gebaar::io { double scale; double angle; - double distance; bool executed; + int step; }; class Input { @@ -64,6 +61,7 @@ namespace gebaar::io { struct libinput* libinput; struct libinput_event* libinput_event; struct udev* udev; + struct gesture_swipe_event gesture_swipe_event; struct gesture_pinch_event gesture_pinch_event; @@ -74,7 +72,7 @@ namespace gebaar::io { static int open_restricted(const char* path, int flags, void* user_data) { int fd = open(path, flags); - return fd<0 ? -errno : fd; + return fd < 0 ? -errno : fd; } static void close_restricted(int fd, void* user_data) @@ -87,6 +85,18 @@ namespace gebaar::io { .close_restricted = close_restricted, }; + /* + * Decrements step of current trigger. Just to skip 0 + * @param cur current step + */ + inline void dec_step(int &cur) { --cur == 0 ? --cur : cur; } + + /* + * Increase step of current trigger. Just to pass -1 + * @param cur current step + */ + inline void inc_step(int &cur) { ++cur == 0 ? ++cur : cur; } + void handle_event(); /* Swipe event */ @@ -101,6 +111,10 @@ namespace gebaar::io { /* Pinch event */ void reset_pinch_event(); + void handle_one_shot_pinch(double new_scale); + + void handle_continouos_pinch(double new_scale); + void handle_pinch_event(libinput_event_gesture* gev, bool begin); }; diff --git a/src/main.cpp b/src/main.cpp index 9a61700..982ce3d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -48,6 +48,7 @@ int main(int argc, char* argv[]) } std::shared_ptr config = std::make_shared(); input = new gebaar::io::Input(config); + if (input->initialize()) { input->start_loop(); } From b9a3c6df4d94509040cfe6cacda78375c03e1e2d Mon Sep 17 00:00:00 2001 From: Alex Kir Date: Wed, 6 Nov 2019 13:17:22 +0200 Subject: [PATCH 8/8] Update README.md Removed fork info --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 8f5a73a..030d725 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,5 @@ Gebaar ========= -Forked from Coffee2CodeNL/gebaar-libinput since original repo unmaintained for half a year. - WM Independent Touchpad Gesture Daemon for libinput _Gebaar means Gesture in Dutch_