Skip to content

Commit 07b0ca8

Browse files
committed
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.
1 parent 5771f01 commit 07b0ca8

File tree

6 files changed

+141
-82
lines changed

6 files changed

+141
-82
lines changed

README.md

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ swipe.threshold = ""
8080

8181
_~/.config/gebaar/gebaard.toml_
8282
```toml
83-
[commands.swipe.three]
83+
[swipe.commands.three]
8484
left_up = ""
8585
right_up = ""
8686
up = "bspc node -f north"
@@ -91,7 +91,7 @@ left = "bspc node -f west"
9191
right = "bspc node -f east"
9292

9393

94-
[commands.swipe.four]
94+
[swipe.commands.four]
9595
left_up = ""
9696
right_up = ""
9797
up = "rofi -show combi"
@@ -101,13 +101,18 @@ down = ""
101101
left = "bspc desktop -f prev"
102102
right = "bspc desktop -f next"
103103

104-
[commands.pinch]
104+
[pinch.commands.two]
105105
in = "xdotool key Control_L+equal"
106106
out = "xdotool key Control_L+minus"
107107

108-
[settings]
109-
pinch.ditance="0.5"
110-
swipe.threshold = "100"
108+
[pinch.settings]
109+
threshold=0.25
110+
one_shot=false
111+
112+
[swipe.settings]
113+
threshold = 0.5
114+
one_shot = true
115+
trigger_on_release = true
111116
```
112117

113118
Add `gebaard -b` to `~/.config/bspwm/bspwmrc`
@@ -117,8 +122,8 @@ Add `gebaard -b` to `~/.config/bspwm/bspwmrc`
117122
- [x] Receiving swipe events from libinput
118123
- [x] Swipe gesture have trigger treshold
119124
- [x] Receiving pinch/zoom events from libinput
120-
- [ ] Support continous pinch
121-
- [ ] Support pinch-and-rotate gestures
125+
- [x] Support continous pinch
126+
- [ ] Support pinch-and-rotate gestures
122127
- [ ] Receiving rotation events from libinput
123128
- [x] Converting libinput events to motions
124129
- [x] Running commands based on motions

src/config/config.cpp

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -43,29 +43,37 @@ void gebaar::config::Config::load_config()
4343
std::cerr << e.what() << std::endl;
4444
exit(EXIT_FAILURE);
4545
}
46-
swipe_three_commands[1] = *config->get_qualified_as<std::string>("commands.swipe.three.left_up");
47-
swipe_three_commands[2] = *config->get_qualified_as<std::string>("commands.swipe.three.up");
48-
swipe_three_commands[3] = *config->get_qualified_as<std::string>("commands.swipe.three.right_up");
49-
swipe_three_commands[4] = *config->get_qualified_as<std::string>("commands.swipe.three.left");
50-
swipe_three_commands[6] = *config->get_qualified_as<std::string>("commands.swipe.three.right");
51-
swipe_three_commands[7] = *config->get_qualified_as<std::string>("commands.swipe.three.left_down");
52-
swipe_three_commands[8] = *config->get_qualified_as<std::string>("commands.swipe.three.down");
53-
swipe_three_commands[9] = *config->get_qualified_as<std::string>("commands.swipe.three.right_down");
54-
55-
swipe_four_commands[1] = *config->get_qualified_as<std::string>("commands.swipe.four.left_up");
56-
swipe_four_commands[2] = *config->get_qualified_as<std::string>("commands.swipe.four.up");
57-
swipe_four_commands[3] = *config->get_qualified_as<std::string>("commands.swipe.four.right_up");
58-
swipe_four_commands[4] = *config->get_qualified_as<std::string>("commands.swipe.four.left");
59-
swipe_four_commands[6] = *config->get_qualified_as<std::string>("commands.swipe.four.right");
60-
swipe_four_commands[7] = *config->get_qualified_as<std::string>("commands.swipe.four.left_down");
61-
swipe_four_commands[8] = *config->get_qualified_as<std::string>("commands.swipe.four.down");
62-
swipe_four_commands[9] = *config->get_qualified_as<std::string>("commands.swipe.four.right_down");
63-
64-
pinch_commands[PINCH_IN] = *config->get_qualified_as<std::string>("commands.pinch.out");
65-
pinch_commands[PINCH_OUT] = *config->get_qualified_as<std::string>("commands.pinch.in");
66-
67-
settings[PINCH_THRESHOLD] = *config->get_qualified_as<std::string>("settings.pinch.threshold");
68-
settings[SWIPE_THRESHOLD] = *config->get_qualified_as<std::string>("settings.swipe.threshold");
46+
47+
/* Swipe Settings */
48+
swipe_three_commands[1] = *config->get_qualified_as<std::string>("swipe.commands.three.left_up");
49+
swipe_three_commands[2] = *config->get_qualified_as<std::string>("swipe.commands.three.up");
50+
swipe_three_commands[3] = *config->get_qualified_as<std::string>("swipe.commands.three.right_up");
51+
swipe_three_commands[4] = *config->get_qualified_as<std::string>("swipe.commands.three.left");
52+
swipe_three_commands[6] = *config->get_qualified_as<std::string>("swipe.commands.three.right");
53+
swipe_three_commands[7] = *config->get_qualified_as<std::string>("swipe.commands.three.left_down");
54+
swipe_three_commands[8] = *config->get_qualified_as<std::string>("swipe.commands.three.down");
55+
swipe_three_commands[9] = *config->get_qualified_as<std::string>("swipe.commands.three.right_down");
56+
57+
swipe_four_commands[1] = *config->get_qualified_as<std::string>("swipe.commands.four.left_up");
58+
swipe_four_commands[2] = *config->get_qualified_as<std::string>("swipe.commands.four.up");
59+
swipe_four_commands[3] = *config->get_qualified_as<std::string>("swipe.commands.four.right_up");
60+
swipe_four_commands[4] = *config->get_qualified_as<std::string>("swipe.commands.four.left");
61+
swipe_four_commands[6] = *config->get_qualified_as<std::string>("swipe.commands.four.right");
62+
swipe_four_commands[7] = *config->get_qualified_as<std::string>("swipe.commands.four.left_down");
63+
swipe_four_commands[8] = *config->get_qualified_as<std::string>("swipe.commands.four.down");
64+
swipe_four_commands[9] = *config->get_qualified_as<std::string>("swipe.commands.four.right_down");
65+
66+
settings.swipe_threshold = config->get_qualified_as<double>("swipe.settings.threshold").value_or(0.5);
67+
settings.swipe_one_shot = config->get_qualified_as<bool>("swipe.settings.one_shot").value_or(true);
68+
settings.swipe_trigger_on_release = config->get_qualified_as<bool>("swipe.settings.trigger_on_release").value_or(true);
69+
70+
/* Pinch settings */
71+
pinch_commands[PINCH_IN] = *config->get_qualified_as<std::string>("pinch.commands.two.out");
72+
pinch_commands[PINCH_OUT] = *config->get_qualified_as<std::string>("pinch.commands.two.in");
73+
74+
settings.pinch_threshold = config->get_qualified_as<double>("pinch.settings.threshold").value_or(0.25);
75+
settings.pinch_one_shot = config->get_qualified_as<bool>("pinch.settings.one_shot").value_or(false);
76+
6977

7078
loaded = true;
7179
}

src/config/config.h

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,21 +34,31 @@ namespace gebaar::config {
3434
void load_config();
3535

3636

37-
enum pinch {PINCH_IN, PINCH_OUT};
38-
enum settings {SWIPE_THRESHOLD, PINCH_THRESHOLD};
37+
struct settings {
38+
bool pinch_one_shot;
39+
double pinch_threshold;
40+
41+
bool swipe_one_shot;
42+
double swipe_threshold;
43+
bool swipe_trigger_on_release;
44+
} settings;
3945

46+
enum pinch {PINCH_IN, PINCH_OUT};
4047
std::string swipe_three_commands[10];
4148
std::string swipe_four_commands[10];
4249
std::string pinch_commands[10];
43-
std::string settings[10];
4450

4551
private:
52+
4653
bool config_file_exists();
4754

4855
bool find_config_file();
4956

57+
5058
std::string config_file_path;
5159
std::shared_ptr<cpptoml::table> config;
60+
61+
5262
};
5363
}
5464
#endif //GEBAAR_CONFIG_H

src/io/input.cpp

Lines changed: 62 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@ gebaar::io::Input::Input(std::shared_ptr<gebaar::config::Config> const& config_p
2828
{
2929
config = config_ptr;
3030
gesture_swipe_event = {};
31+
3132
gesture_pinch_event = {};
33+
gesture_pinch_event.scale = DEFAULT_SCALE;
3234
}
3335

3436
/**
@@ -48,31 +50,60 @@ bool gebaar::io::Input::initialize_context()
4850
*/
4951
void gebaar::io::Input::reset_swipe_event() {
5052
gesture_swipe_event = {};
51-
try {
52-
gesture_swipe_event.threshold = std::stoi(config->settings[config->THRESHOLD]);
53-
}
54-
catch (const std::invalid_argument& ia){
55-
gesture_swipe_event.threshold = DEFAULT_THRESHOLD;
56-
}
53+
gesture_swipe_event.executed = false;
5754
}
5855

5956
/**
6057
* Reset pinch event struct to defaults
6158
*/
6259
void gebaar::io::Input::reset_pinch_event() {
63-
// Get pinch distance
64-
try {
65-
gesture_pinch_event.distance = std::stod(config->settings[config->DISTANCE]);
60+
gesture_pinch_event = {};
61+
gesture_pinch_event.scale = DEFAULT_SCALE;
62+
gesture_pinch_event.executed = false;
63+
}
64+
65+
/**
66+
* Pinch one_shot gesture handle
67+
* @param new_scale last reported scale between the fingers
68+
*/
69+
void gebaar::io::Input::handle_one_shot_pinch(double new_scale) {
70+
if (new_scale > gesture_pinch_event.scale) { // Scale up
71+
// Add 1 to required distance to get 2 > x > 1
72+
if (new_scale > 1 + config->settings.pinch_threshold) {
73+
std::system(config->pinch_commands[config->PINCH_IN].c_str());
74+
gesture_pinch_event.executed = true;
6675
}
67-
catch (const std::invalid_argument &ia) {
68-
// Set default distance
69-
gesture_pinch_event.distance = DEFAULT_DISTANCE;
76+
}
77+
else { // Scale Down
78+
// Substract from 1 to have inverted value for pinch in gesture
79+
if (gesture_pinch_event.scale < 1 - config->settings.pinch_threshold) {
80+
std::system(config->pinch_commands[config->PINCH_OUT].c_str());
81+
gesture_pinch_event.executed = true;
7082
}
71-
// Reset pinch data
72-
gesture_pinch_event.scale = DEFAULT_SCALE;
73-
gesture_pinch_event.executed = false;
83+
}
7484
}
7585

86+
/**
87+
* Pinch continous gesture handle
88+
* Calculates the trigger value according to current step
89+
* @param new_scale last reported scale between the fingers
90+
*/
91+
void gebaar::io::Input::handle_continouos_pinch(double new_scale) {
92+
int step = gesture_pinch_event.step == 0 ? gesture_pinch_event.step + 1 : gesture_pinch_event.step;
93+
double trigger = 1 + (config->settings.pinch_threshold * step);
94+
95+
if (new_scale > gesture_pinch_event.scale) { // Scale up
96+
if (new_scale >= trigger){
97+
std::system(config->pinch_commands[config->PINCH_IN].c_str());
98+
inc_step(gesture_pinch_event.step);
99+
}
100+
} else { // Scale down
101+
if (new_scale <= trigger){
102+
std::system(config->pinch_commands[config->PINCH_OUT].c_str());
103+
dec_step(gesture_pinch_event.step);
104+
}
105+
}
106+
}
76107

77108
/**
78109
* Pinch Gesture
@@ -83,31 +114,13 @@ void gebaar::io::Input::reset_pinch_event() {
83114
void gebaar::io::Input::handle_pinch_event(libinput_event_gesture* gev, bool begin)
84115
{
85116
if (begin) {
86-
reset_pinch_event();
87-
gesture_pinch_event.fingers = libinput_event_gesture_get_finger_count(gev);
117+
reset_pinch_event();
118+
gesture_pinch_event.fingers = libinput_event_gesture_get_finger_count(gev);
88119
}
89120
else {
90-
if (gesture_swipe_event.executed) return;
91-
92-
// Ignore input after command execution
93-
if (gesture_pinch_event.executed) return;
94121
double new_scale = libinput_event_gesture_get_scale(gev);
95-
if (new_scale > gesture_pinch_event.scale) {
96-
// Scale up
97-
// Add 1 to required distance to get 2 > x > 1
98-
if (new_scale > 1 + gesture_pinch_event.distance) {
99-
std::system(config->pinch_commands[config->PINCH_IN].c_str());
100-
gesture_pinch_event.executed = true;
101-
}
102-
}
103-
else {
104-
// Scale Down
105-
// Substract from 1 to have inverted value for pinch in gesture
106-
if (gesture_pinch_event.scale < 1 - gesture_pinch_event.distance) {
107-
std::system(config->pinch_commands[config->PINCH_OUT].c_str());
108-
gesture_pinch_event.executed = true;
109-
}
110-
}
122+
if (config->settings.pinch_one_shot && !gesture_pinch_event.executed) handle_one_shot_pinch(new_scale);
123+
if (!config->settings.pinch_one_shot) handle_continouos_pinch(new_scale);
111124
gesture_pinch_event.scale = new_scale;
112125
}
113126
}
@@ -127,7 +140,7 @@ void gebaar::io::Input::handle_swipe_event_without_coords(libinput_event_gesture
127140
}
128141
// This executed when fingers left the touchpad
129142
else {
130-
if (!gesture_swipe_event.executed) {
143+
if (!gesture_swipe_event.executed && config->settings.swipe_trigger_on_release) {
131144
trigger_swipe_command();
132145
}
133146
reset_swipe_event();
@@ -140,8 +153,10 @@ void gebaar::io::Input::handle_swipe_event_without_coords(libinput_event_gesture
140153
*/
141154
void gebaar::io::Input::handle_swipe_event_with_coords(libinput_event_gesture* gev)
142155
{
143-
if (gesture_swipe_event.executed) return;
144-
int threshold = std::stoi(config->settings[config->THRESHOLD]);
156+
if (config->settings.swipe_one_shot && gesture_swipe_event.executed) return;
157+
158+
// Since swipe gesture counts in dpi we have to convert
159+
int threshold = config->settings.swipe_threshold * 100;
145160
gesture_swipe_event.x += libinput_event_gesture_get_dx(gev);
146161
gesture_swipe_event.y += libinput_event_gesture_get_dy(gev);
147162
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
150165
}
151166
}
152167

168+
169+
/**
170+
* Making calculation for swipe direction and triggering
171+
* command accordingly
172+
*/
153173
void gebaar::io::Input::trigger_swipe_command() {
154174
double x = gesture_swipe_event.x;
155175
double y = gesture_swipe_event.y;
@@ -223,7 +243,8 @@ gebaar::io::Input::~Input()
223243
bool gebaar::io::Input::gesture_device_exists()
224244
{
225245
bool device_found = false;
226-
while ((libinput_event = libinput_get_event(libinput))!=nullptr) {
246+
247+
while ((libinput_event = libinput_get_event(libinput)) != nullptr) {
227248
auto device = libinput_event_get_device(libinput_event);
228249
if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_GESTURE)) {
229250
device_found = true;

src/io/input.h

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,28 +24,25 @@
2424
#include <zconf.h>
2525
#include "../config/config.h"
2626

27-
#define DEFAULT_SCALE 1.0
28-
#define DEFAULT_DISTANCE 0.5
29-
#define DEFAULT_THRESHOLD 100
30-
27+
#define DEFAULT_SCALE 1.0
3128

3229
namespace gebaar::io {
3330
struct gesture_swipe_event {
3431
int fingers;
3532
double x;
3633
double y;
3734

38-
int threshold;
3935
bool executed;
36+
int step;
4037
};
4138

4239
struct gesture_pinch_event {
4340
int fingers;
4441
double scale;
4542
double angle;
4643

47-
double distance;
4844
bool executed;
45+
int step;
4946
};
5047

5148
class Input {
@@ -64,6 +61,7 @@ namespace gebaar::io {
6461
struct libinput* libinput;
6562
struct libinput_event* libinput_event;
6663
struct udev* udev;
64+
6765
struct gesture_swipe_event gesture_swipe_event;
6866
struct gesture_pinch_event gesture_pinch_event;
6967

@@ -74,7 +72,7 @@ namespace gebaar::io {
7472
static int open_restricted(const char* path, int flags, void* user_data)
7573
{
7674
int fd = open(path, flags);
77-
return fd<0 ? -errno : fd;
75+
return fd < 0 ? -errno : fd;
7876
}
7977

8078
static void close_restricted(int fd, void* user_data)
@@ -87,6 +85,18 @@ namespace gebaar::io {
8785
.close_restricted = close_restricted,
8886
};
8987

88+
/*
89+
* Decrements step of current trigger. Just to skip 0
90+
* @param cur current step
91+
*/
92+
inline void dec_step(int &cur) { --cur == 0 ? --cur : cur; }
93+
94+
/*
95+
* Increase step of current trigger. Just to pass -1
96+
* @param cur current step
97+
*/
98+
inline void inc_step(int &cur) { ++cur == 0 ? ++cur : cur; }
99+
90100
void handle_event();
91101

92102
/* Swipe event */
@@ -101,6 +111,10 @@ namespace gebaar::io {
101111
/* Pinch event */
102112
void reset_pinch_event();
103113

114+
void handle_one_shot_pinch(double new_scale);
115+
116+
void handle_continouos_pinch(double new_scale);
117+
104118
void handle_pinch_event(libinput_event_gesture* gev, bool begin);
105119

106120
};

0 commit comments

Comments
 (0)