diff --git a/README.md b/README.md index bb51f9e..833868f 100644 --- a/README.md +++ b/README.md @@ -55,8 +55,20 @@ right_down = "" down = "" left = "" right = "" + +[commands.pinch] +in = "" +out = "" + +[settings] +pinch.distance = "" +swipe.threshold = "" ``` +* `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 ![](https://img.shields.io/aur/version/gebaar.svg?style=flat) @@ -77,6 +89,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 +99,14 @@ 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" + +[settings] +pinch.ditance="0.5" +swipe.threshold = "100" ``` Add `gebaard -b` to `~/.config/bspwm/bspwmrc` @@ -93,9 +114,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..6292580 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,12 @@ 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"); + + 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 499eb51..1841e49 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,14 @@ namespace gebaar::config { void load_config(); + + 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 943dc96..380c374 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,75 @@ 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; + } +} + +/** + * 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]); + } + 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; +} + + +/** + * 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); + 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. @@ -55,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.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()); + if (!gesture_swipe_event.executed) { + trigger_swipe_command(); } - - gesture_swipe_event = {}; + reset_swipe_event(); } } @@ -99,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()); + } + } /** @@ -169,6 +252,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 +301,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..e391c0f 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,11 +24,28 @@ #include #include "../config/config.h" +#define DEFAULT_SCALE 1.0 +#define DEFAULT_DISTANCE 0.5 +#define DEFAULT_THRESHOLD 100 + + namespace gebaar::io { struct gesture_swipe_event { int fingers; double x; double y; + + int threshold; + bool executed; + }; + + struct gesture_pinch_event { + int fingers; + double scale; + double angle; + + double distance; + bool executed; }; class Input { @@ -48,6 +65,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(); @@ -71,9 +89,20 @@ 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); + }; }