Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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 = ""
Expand All @@ -86,16 +99,27 @@ 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`

### 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


12 changes: 9 additions & 3 deletions src/config/config.cpp
Original file line number Diff line number Diff line change
@@ -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 <http://www.gnu.org/licenses/>.
*/
Expand Down Expand Up @@ -61,6 +61,12 @@ void gebaar::config::Config::load_config()
swipe_four_commands[8] = *config->get_qualified_as<std::string>("commands.swipe.four.down");
swipe_four_commands[9] = *config->get_qualified_as<std::string>("commands.swipe.four.right_down");

pinch_commands[PINCH_IN] = *config->get_qualified_as<std::string>("commands.pinch.out");
pinch_commands[PINCH_OUT] = *config->get_qualified_as<std::string>("commands.pinch.in");

settings[DISTANCE] = *config->get_qualified_as<std::string>("settings.pinch.distance");
settings[THRESHOLD] = *config->get_qualified_as<std::string>("settings.swipe.threshold");

loaded = true;
}
}
Expand Down
12 changes: 9 additions & 3 deletions src/config/config.h
Original file line number Diff line number Diff line change
@@ -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 <http://www.gnu.org/licenses/>.
*/
Expand All @@ -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();
Expand Down
170 changes: 128 additions & 42 deletions src/io/input.cpp
Original file line number Diff line number Diff line change
@@ -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 <http://www.gnu.org/licenses/>.
*/
Expand All @@ -28,6 +28,7 @@ gebaar::io::Input::Input(std::shared_ptr<gebaar::config::Config> const& config_p
{
config = config_ptr;
gesture_swipe_event = {};
gesture_pinch_event = {};
}

/**
Expand All @@ -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.
Expand All @@ -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();
}
}

Expand All @@ -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());
}

}

/**
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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;
}
Expand Down
Loading