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

@@ -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);
+
};
}