From 025b37ded86700b90e4ae9d8ecaac695d5ba58f7 Mon Sep 17 00:00:00 2001 From: Alex Zaslavsky Date: Sun, 27 Oct 2019 19:14:50 +0200 Subject: [PATCH 1/2] 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% the distance between the fingers. --- README.md | 14 ++++++++++- src/config/config.cpp | 9 ++++--- src/config/config.h | 7 +++--- src/io/input.cpp | 58 ++++++++++++++++++++++++++++++++++++------- src/io/input.h | 17 ++++++++++--- 5 files changed, 86 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index bb51f9e..f77d3b7 100644 --- a/README.md +++ b/README.md @@ -55,6 +55,10 @@ right_down = "" down = "" left = "" right = "" + +[commands.pinch] +in = "" +out = "" ``` ### Repository versions @@ -77,6 +81,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 +91,10 @@ 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" ``` Add `gebaard -b` to `~/.config/bspwm/bspwmrc` @@ -93,9 +102,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..5b13635 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,9 @@ 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[0] = *config->get_qualified_as("commands.pinch.out"); + pinch_commands[1] = *config->get_qualified_as("commands.pinch.in"); + loaded = true; } } diff --git a/src/config/config.h b/src/config/config.h index 499eb51..02c601c 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 . */ @@ -35,6 +35,7 @@ namespace gebaar::config { 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..b3e95a3 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 . */ @@ -42,6 +42,43 @@ 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); + // Reset pinch data + gesture_pinch_event.scale = 1.0; + gesture_pinch_event.executed = false; + } + else { + if (gesture_pinch_event.executed) return; + double new_scale = libinput_event_gesture_get_scale(gev); + if (new_scale > gesture_pinch_event.scale) { + // Scale up + if (gesture_pinch_event.scale * new_scale > 1.5) { + std::system(config->pinch_commands[0].c_str()); + gesture_pinch_event.executed = true; + } + } + else { + // Scale Down + if (gesture_pinch_event.scale * new_scale < 0.5) { + std::system(config->pinch_commands[1].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 +206,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 +255,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..8363c8b 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 . */ @@ -31,6 +31,13 @@ namespace gebaar::io { double y; }; + struct gesture_pinch_event { + int fingers; + double scale; + double angle; + bool executed; + }; + class Input { public: Input(std::shared_ptr const& config_ptr); @@ -48,6 +55,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 +82,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 b6ea3b824f2e9360c83aec152c49e1d3a36d53bb Mon Sep 17 00:00:00 2001 From: Alex Zaslavsky Date: Tue, 29 Oct 2019 20:34:12 +0200 Subject: [PATCH 2/2] 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 | 6 ++++++ src/config/config.cpp | 5 +++-- src/config/config.h | 3 +++ src/io/input.cpp | 24 ++++++++++++++++++------ src/io/input.h | 6 ++++++ 5 files changed, 36 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index f77d3b7..741395f 100644 --- a/README.md +++ b/README.md @@ -59,8 +59,13 @@ 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) @@ -95,6 +100,7 @@ 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` diff --git a/src/config/config.cpp b/src/config/config.cpp index 5b13635..d13dcef 100644 --- a/src/config/config.cpp +++ b/src/config/config.cpp @@ -61,8 +61,9 @@ 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[0] = *config->get_qualified_as("commands.pinch.out"); - pinch_commands[1] = *config->get_qualified_as("commands.pinch.in"); + 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 02c601c..45e7642 100644 --- a/src/config/config.h +++ b/src/config/config.h @@ -33,6 +33,9 @@ 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]; diff --git a/src/io/input.cpp b/src/io/input.cpp index b3e95a3..22f1409 100644 --- a/src/io/input.cpp +++ b/src/io/input.cpp @@ -28,6 +28,7 @@ gebaar::io::Input::Input(std::shared_ptr const& config_p { config = config_ptr; gesture_swipe_event = {}; + gesture_pinch_event = {}; } /** @@ -54,24 +55,35 @@ void gebaar::io::Input::handle_pinch_event(libinput_event_gesture* gev, bool beg { 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 = 1.0; + 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 - if (gesture_pinch_event.scale * new_scale > 1.5) { - std::system(config->pinch_commands[0].c_str()); + // 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 - if (gesture_pinch_event.scale * new_scale < 0.5) { - std::system(config->pinch_commands[1].c_str()); + // 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; } } diff --git a/src/io/input.h b/src/io/input.h index 8363c8b..af52637 100644 --- a/src/io/input.h +++ b/src/io/input.h @@ -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; @@ -35,6 +39,8 @@ namespace gebaar::io { int fingers; double scale; double angle; + + double distance; bool executed; };