Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bc117c0ab5 | ||
|
|
4cf3bf3d8d | ||
|
|
9393a96d3f | ||
|
|
179083a152 | ||
|
|
99f659c9db | ||
|
|
7728495350 | ||
|
|
9d25f1cc9f | ||
|
|
9deaf2da2c | ||
|
|
6bd7603694 | ||
|
|
57a6e4f217 | ||
|
|
404e8febcc | ||
|
|
b2d1674ba4 | ||
|
|
548199bc38 | ||
|
|
cb018bf335 | ||
|
|
859d3f3c3c | ||
|
|
f56e0a69d3 | ||
|
|
66b2568c86 |
58
.gitignore
vendored
58
.gitignore
vendored
@ -1,57 +1,7 @@
|
|||||||
|
# C++ generated headers
|
||||||
|
*.gch
|
||||||
|
*.o
|
||||||
|
|
||||||
# IDE-specific
|
# IDE-specific
|
||||||
.idea
|
.idea
|
||||||
.vscode
|
.vscode
|
||||||
|
|
||||||
# Generated binary
|
|
||||||
/comfortable-swipe
|
|
||||||
/build
|
|
||||||
|
|
||||||
# CMake
|
|
||||||
CMakeLists.txt.user
|
|
||||||
CMakeCache.txt
|
|
||||||
CMakeFiles
|
|
||||||
CMakeScripts
|
|
||||||
Testing
|
|
||||||
Makefile
|
|
||||||
cmake_install.cmake
|
|
||||||
install_manifest.txt
|
|
||||||
compile_commands.json
|
|
||||||
CTestTestfile.cmake
|
|
||||||
_deps
|
|
||||||
*.cmake
|
|
||||||
|
|
||||||
# Library
|
|
||||||
.lib
|
|
||||||
|
|
||||||
# Prerequisites
|
|
||||||
*.d
|
|
||||||
|
|
||||||
# Compiled Object files
|
|
||||||
*.slo
|
|
||||||
*.lo
|
|
||||||
*.o
|
|
||||||
*.obj
|
|
||||||
|
|
||||||
# Precompiled Headers
|
|
||||||
*.gch
|
|
||||||
*.pch
|
|
||||||
|
|
||||||
# Compiled Dynamic libraries
|
|
||||||
*.so
|
|
||||||
*.dylib
|
|
||||||
*.dll
|
|
||||||
|
|
||||||
# Fortran module files
|
|
||||||
*.mod
|
|
||||||
*.smod
|
|
||||||
|
|
||||||
# Compiled Static libraries
|
|
||||||
*.lai
|
|
||||||
*.la
|
|
||||||
*.a
|
|
||||||
*.lib
|
|
||||||
|
|
||||||
# Executables
|
|
||||||
*.exe
|
|
||||||
*.out
|
|
||||||
*.app
|
|
||||||
|
|||||||
12
CHANGELOG
12
CHANGELOG
@ -1,3 +1,13 @@
|
|||||||
|
v1.2.0 (2020-04-20)
|
||||||
|
* Simplified source files
|
||||||
|
* Add `config get|set|list|delete` to command line
|
||||||
|
* Add specific autostart toggles
|
||||||
|
* Use clang-format and prettier for formatting
|
||||||
|
* Add `--bare` and `--attach` flags to buffer
|
||||||
|
* Remove `restart` and integrated single-instance to `start`
|
||||||
|
* Provide separate `comfortable-swipe-buffer` program
|
||||||
|
* Improve README
|
||||||
|
|
||||||
v1.1.0 (2020-04-18)
|
v1.1.0 (2020-04-18)
|
||||||
* Add mouse hold gestures
|
* Add mouse hold gestures
|
||||||
* Add experimental `hold3` configuration
|
* Add experimental `hold3` configuration
|
||||||
@ -7,7 +17,7 @@ v1.1.0 (2020-04-18)
|
|||||||
* Add `mouse_hold_gestures.cpp`
|
* Add `mouse_hold_gestures.cpp`
|
||||||
* Bugfix `comfortable-swipe stop`
|
* Bugfix `comfortable-swipe stop`
|
||||||
* Bugfix `comfortable-swipe restart`
|
* Bugfix `comfortable-swipe restart`
|
||||||
* Rename `index.hpp` to `comfortable_swipe.h`
|
* Rename `index.hpp` to `all_headers.hpp`
|
||||||
* Rename source directory `lib` to `comfortable_swipe`
|
* Rename source directory `lib` to `comfortable_swipe`
|
||||||
* Separate `swipe_gesture.cpp` from `keyboard_swipe_gesture.cpp`
|
* Separate `swipe_gesture.cpp` from `keyboard_swipe_gesture.cpp`
|
||||||
* Update compiler scripts
|
* Update compiler scripts
|
||||||
|
|||||||
@ -1,58 +0,0 @@
|
|||||||
# Run with: cmake . && make && make install
|
|
||||||
cmake_minimum_required(VERSION 3.10.2)
|
|
||||||
|
|
||||||
project(comfortable-swipe)
|
|
||||||
set(CMAKE_PROJECT_NAME "Comfortable Swipe")
|
|
||||||
set(CMAKE_PROJECT_DESCRIPTION "Comfortable 3/4-finger swipe gestures")
|
|
||||||
|
|
||||||
# set flags to use C++ 11
|
|
||||||
set(CMAKE_CXX_STANDARD 11)
|
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
|
||||||
set(CMAKE_CXX_FLAGS_DISTRIBUTION "-O2")
|
|
||||||
|
|
||||||
# set main directories
|
|
||||||
set(comfortable_swipe_bin "${CMAKE_INSTALL_PREFIX}/bin")
|
|
||||||
set(comfortable_swipe_lib "${CMAKE_INSTALL_PREFIX}/lib")
|
|
||||||
set(comfortable_swipe_share "${CMAKE_INSTALL_PREFIX}/share")
|
|
||||||
set(comfortable_swipe_include "${CMAKE_INSTALL_PREFIX}/include")
|
|
||||||
|
|
||||||
|
|
||||||
# set version from VERSION file
|
|
||||||
file(STRINGS "VERSION" comfortable_swipe_version)
|
|
||||||
|
|
||||||
# set project variables
|
|
||||||
set(comfortable_swipe_exe_path "${comfortable_swipe_bin}/comfortable-swipe")
|
|
||||||
set(comfortable_swipe_conf_path "/usr/local/share/comfortable-swipe/comfortable-swipe.conf")
|
|
||||||
|
|
||||||
# C++ definitions
|
|
||||||
add_definitions(
|
|
||||||
-DCOMFORTABLE_SWIPE_VERSION="${comfortable_swipe_version}"
|
|
||||||
-DCOMFORTABLE_SWIPE_PROGRAM="${comfortable_swipe_exe_path}"
|
|
||||||
-DCOMFORTABLE_SWIPE_CONFIG="${comfortable_swipe_conf_path}"
|
|
||||||
)
|
|
||||||
|
|
||||||
# add our build-time only static library
|
|
||||||
add_library(comfortable-swipe.lib STATIC "src/comfortable_swipe.cpp")
|
|
||||||
target_include_directories(comfortable-swipe.lib PUBLIC "src")
|
|
||||||
|
|
||||||
# register comfortable-swipe command line program
|
|
||||||
add_executable("comfortable-swipe" "comfortable-swipe.cpp")
|
|
||||||
|
|
||||||
# link libraries here
|
|
||||||
find_library(XDO libxdo.so)
|
|
||||||
target_link_libraries(comfortable-swipe.lib "${XDO}")
|
|
||||||
target_link_libraries(comfortable-swipe comfortable-swipe.lib)
|
|
||||||
|
|
||||||
# perform installation
|
|
||||||
install(TARGETS comfortable-swipe DESTINATION bin)
|
|
||||||
|
|
||||||
# set where .desktop file should be installed
|
|
||||||
if (DEFINED ENV{XDG_CONFIG_HOME})
|
|
||||||
set (comfortable_swipe_desktop "$ENV{XDG_CONFIG_HOME}/autostart/")
|
|
||||||
else()
|
|
||||||
set(comfortable_swipe_desktop "$ENV{HOME}/.config/autostart/")
|
|
||||||
endif()
|
|
||||||
install(FILES "share/comfortable-swipe.desktop" DESTINATION "${comfortable_swipe_desktop}")
|
|
||||||
|
|
||||||
# set platform-specific info
|
|
||||||
include(cmake/cpack.cmake)
|
|
||||||
620
README.md
620
README.md
@ -3,81 +3,259 @@
|
|||||||
[](https://github.com/Hikari9/comfortable-swipe/releases)
|
[](https://github.com/Hikari9/comfortable-swipe/releases)
|
||||||
[](https://www.gnu.org/licenses/gpl-3.0)
|
[](https://www.gnu.org/licenses/gpl-3.0)
|
||||||
|
|
||||||
> **_New in Version 1.1.0!_** Added mouse gestures, see [#mouse-gestures-experimental](#mouse-gestures-experimental)
|
|
||||||
|
|
||||||
Comfortable, seamless, and fast 3-finger (and 4-finger) touchpad swipe gestures for Ubuntu 14.04 LTS and beyond. May work for other Linux distros that support `libinput`.
|
Comfortable, seamless, and fast 3-finger (and 4-finger) touchpad swipe gestures for Ubuntu 14.04 LTS and beyond. May work for other Linux distros that support `libinput`.
|
||||||
|
|
||||||
|
> **_New in Version 1.1.0_**: Added mouse gestures, see [#mouse-gestures-experimental](#mouse-gestures-experimental)
|
||||||
|
|
||||||
|
> **_New in Version 1.2.0_**: Autostart now switched ON by default
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
1. Install git, libinput, and g++
|
1. Install git and g++ ≥ 7.5
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo apt-get install git libinput-tools libxdo-dev g++
|
sudo apt install git g++
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Clone this repository
|
1. Install libinput-tools and C libraries
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo apt install libinput-tools libinih-dev libxdo-dev
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Clone this repository
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/Hikari9/comfortable-swipe.git --depth 1
|
git clone https://github.com/Hikari9/comfortable-swipe.git --depth 1
|
||||||
cd comfortable-swipe
|
cd comfortable-swipe
|
||||||
```
|
```
|
||||||
|
|
||||||
3. Install
|
1. Install
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
bash install
|
bash install
|
||||||
```
|
```
|
||||||
|
|
||||||
4. You may delete the downloaded `comfortable-swipe` folder after installation.
|
1. You may delete the downloaded `comfortable-swipe` folder after installation.
|
||||||
|
|
||||||
## How to Run
|
## How to Run
|
||||||
|
|
||||||
1. You'll need some group permissions to read touchpad input data. Run
|
1. You'll need some group permissions to read touchpad input data. Run
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo gpasswd -a $USER $(ls -l /dev/input/event* | awk '{print $4}' | head --line=1)
|
sudo gpasswd -a "$USER" "$(ls -l /dev/input/event* | awk '{print $4}' | head --line=1)"
|
||||||
```
|
```
|
||||||
2. **_Important_**: After inputing your `sudo` password, log out then log back in
|
|
||||||
3. Run
|
1. **_Important_**: After inputing your `sudo` password, log out then log back in
|
||||||
|
|
||||||
|
1. Start the Program
|
||||||
|
|
||||||
```
|
```
|
||||||
comfortable-swipe start
|
comfortable-swipe start
|
||||||
```
|
```
|
||||||
4. _Optional_: Automatically run on startup
|
|
||||||
|
You will see this output:
|
||||||
|
|
||||||
```
|
```
|
||||||
comfortable-swipe autostart
|
$ comfortable-swipe start
|
||||||
|
Comfortable swipe is RUNNING in the background
|
||||||
```
|
```
|
||||||
5. Check the status of your application by running
|
|
||||||
|
1. (Optional) Toggle autostart
|
||||||
|
|
||||||
|
```bash
|
||||||
|
comfortable-swipe autostart on
|
||||||
```
|
```
|
||||||
|
|
||||||
|
1. (Optional) Stop the Program
|
||||||
|
|
||||||
|
```
|
||||||
|
comfortable-swipe stop
|
||||||
|
```
|
||||||
|
|
||||||
|
1. (Optional) See program status
|
||||||
|
|
||||||
|
```bash
|
||||||
comfortable-swipe status
|
comfortable-swipe status
|
||||||
```
|
```
|
||||||
|
|
||||||
## Swipe Configurations
|
Example:
|
||||||
|
|
||||||
Comfortable swipe makes use of keyboard shortcuts for configurations. Edit by running:
|
```
|
||||||
|
$ comfortable-swipe status
|
||||||
|
|
||||||
|
Autostart is ON
|
||||||
|
Program is RUNNING
|
||||||
|
--------------------
|
||||||
|
Configuration: /home/user/.config/comfortable-swipe.conf
|
||||||
|
left3 is VALID (ctrl+super+Right)
|
||||||
|
left4 is VALID (ctrl+super+shift+Right)
|
||||||
|
right3 is VALID (ctrl+super+Left)
|
||||||
|
right4 is VALID (ctrl+super+shift+Left)
|
||||||
|
up3 is VALID (ctrl+F12)
|
||||||
|
up4 is VALID (super+d)
|
||||||
|
down3 is VALID (ctrl+F12)
|
||||||
|
down4 is VALID (super+d)
|
||||||
|
threshold is VALID (1.0)
|
||||||
|
mouse3 is NOTSET
|
||||||
|
mouse4 is NOTSET
|
||||||
|
```
|
||||||
|
|
||||||
|
1. (Optional) Get config
|
||||||
|
|
||||||
|
```
|
||||||
|
comfortable-swipe <PROPERTY>
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
comfortable-swipe left3
|
||||||
|
comfortable-swipe left4
|
||||||
|
comfortable-swipe right3
|
||||||
|
comfortable-swipe right4
|
||||||
|
comfortable-swipe up3
|
||||||
|
comfortable-swipe up4
|
||||||
|
comfortable-swipe down3
|
||||||
|
comfortable-swipe down4
|
||||||
|
comfortable-swipe threshold
|
||||||
|
comfortable-swipe mouse3
|
||||||
|
comfortable-swipe mouse4
|
||||||
|
```
|
||||||
|
|
||||||
|
1. (Optional) Set config
|
||||||
|
|
||||||
|
```bash
|
||||||
|
comfortable-swipe <PROPERTY> [=] <VALUES>
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
comfortable-swipe left3 = super+Right
|
||||||
|
comfortable-swipe right3 = super+Left
|
||||||
|
comfortable-swipe right4 = ctrl+alt+Left
|
||||||
|
comfortable-swipe down4 = super+d
|
||||||
|
comfortable-swipe up3 = ctrl+shift+Up
|
||||||
|
```
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary><b>Other Commands</b></summary>
|
||||||
|
|
||||||
|
1. All Configuration commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
comfortable-swipe config list
|
||||||
|
comfortable-swipe config get <PROPERTY>
|
||||||
|
comfortable-swipe config set <PROPERTY> [=] <VALUE>
|
||||||
|
comfortable-swipe config path
|
||||||
|
comfortable-swipe config keys
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Help and Version
|
||||||
|
|
||||||
|
```bash
|
||||||
|
comfortable-swipe --version
|
||||||
|
comfortable-swipe --help
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Autostart commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
comfortable-swipe autostart on
|
||||||
|
comfortable-swipe autostart off
|
||||||
|
comfortable-swipe autostart toggle
|
||||||
|
comfortable-swipe autostart status
|
||||||
|
comfortable-swipe autostart path
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Show output with `--attach`
|
||||||
|
|
||||||
|
Example output of 3-finger left, 4-finger left, 3-finger right, 3-finger up:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ comfortable-swipe start --attach
|
||||||
|
SWIPE left3
|
||||||
|
SWIPE left4
|
||||||
|
SWIPE right3
|
||||||
|
SWIPE up3
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Test output with `--bare` to attach without actually swiping
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ comfortable-swipe start --bare
|
||||||
|
SWIPE left3
|
||||||
|
SWIPE left4
|
||||||
|
SWIPE right3
|
||||||
|
SWIPE up3
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Debug
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ comfortable-swipe debug
|
||||||
|
...
|
||||||
|
-event9 DEVICE_ADDED TouchPad seat0 default group7 cap:pg size 70x50mm tap(dl off) left scroll-nat scroll-2fg-edge click-buttonareas-clickfinger dwt-on
|
||||||
|
...
|
||||||
|
event9 GESTURE_SWIPE_BEGIN +2.03s 3
|
||||||
|
event9 GESTURE_SWIPE_UPDATE +2.03s 3 -9.95/ 2.64 (-26.90/ 7.12 unaccelerated)
|
||||||
|
event9 GESTURE_SWIPE_UPDATE +2.03s 3 -10.44/ 3.19 (-28.22/ 8.62 unaccelerated)
|
||||||
|
event9 GESTURE_SWIPE_UPDATE +2.04s 3 -9.71/ 2.64 (-26.25/ 7.12 unaccelerated)
|
||||||
|
event9 GESTURE_SWIPE_UPDATE +2.05s 3 -8.98/ 2.64 (-24.28/ 7.12 unaccelerated)
|
||||||
|
event9 GESTURE_SWIPE_UPDATE +2.06s 3 -7.40/ 2.36 (-20.01/ 6.37 unaccelerated)
|
||||||
|
event9 GESTURE_SWIPE_UPDATE +2.06s 3 -6.31/ 2.50 (-17.06/ 6.75 unaccelerated)
|
||||||
|
event9 GESTURE_SWIPE_UPDATE +2.07s 3 -5.34/ 1.80 (-14.44/ 4.87 unaccelerated)
|
||||||
|
event9 GESTURE_SWIPE_UPDATE +2.08s 3 -4.61/ 2.08 (-12.47/ 5.62 unaccelerated)
|
||||||
|
event9 GESTURE_SWIPE_UPDATE +2.09s 3 -4.49/ 1.53 (-12.14/ 4.12 unaccelerated)
|
||||||
|
event9 GESTURE_SWIPE_UPDATE +2.09s 3 -4.01/ 1.25 (-10.83/ 3.37 unaccelerated)
|
||||||
|
event9 GESTURE_SWIPE_UPDATE +2.10s 3 -4.13/ 0.42 (-11.15/ 1.12 unaccelerated)
|
||||||
|
event9 GESTURE_SWIPE_END +2.11s 3
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
## Gesture Configurations
|
||||||
|
|
||||||
|
The default configuration file is located at `~/.config/comfortable-swipe.conf`.
|
||||||
|
Comfortable swipe makes use of **keyboard shortcuts** to perform swipes, through `xdotool`.
|
||||||
|
|
||||||
|
Set a property directly with:
|
||||||
|
|
||||||
```
|
```
|
||||||
gedit $(comfortable-swipe config)
|
comfortable-swipe <PROPERTY> [=] <VALUE>
|
||||||
```
|
```
|
||||||
|
|
||||||
| Property | Description | Default Value | Default Behavior |
|
Or edit the configuration file manually:
|
||||||
| --------- | :------------------------------------------: | -------------------- | -------------------------------------------------------------------------------------------------------------------------- |
|
|
||||||
| left3 | 3-finger swipe left | ctrl+alt+Right | switch to right workspace |
|
|
||||||
| left4 | 4-finger swipe left | ctrl+alt+shift+Right | move window to right workspace |
|
|
||||||
| right3 | 3-finger swipe right | ctrl+alt+Left | switch to left workspace |
|
|
||||||
| right4 | 4-finger swipe right | ctrl+alt+shift+Left | move window to left workspace |
|
|
||||||
| up3 | 3-finger swipe up | ctrl+alt+Down | switch to bottom workspace |
|
|
||||||
| up4 | 4-finger swipe up | ctrl+alt+shift+Down | move window to bottom workspace |
|
|
||||||
| down3 | 3-finger swipe down | ctrl+alt+Up | switch to above workspace |
|
|
||||||
| down4 | 4-finger swipe down | ctrl+alt+shift+Up | move window to above workpace |
|
|
||||||
| threshold | mouse pixels to activate swipe | 0.0 | tweak this if you're having troubles with touchpad sensitivity (higher = less sensitive, values can be as large as 1000.0) |
|
|
||||||
| hold3 | holds a mouse button when 3 fingers are down | (none) | See [Mouse Gestures (Experimental)](#mouse-gestures-experimental) |
|
|
||||||
| hold4 | holds a mouse button when 4 fingers are down | (none) | See [Mouse Gestures (Experimental)](#mouse-gestures-experimental) |
|
|
||||||
|
|
||||||
After making changes, make sure to restart the program:
|
|
||||||
|
|
||||||
```
|
```
|
||||||
comfortable-swipe restart
|
gedit ~/.config/comfortable-swipe.conf
|
||||||
```
|
```
|
||||||
|
|
||||||
|
After editing, make sure to restart with `comfortable-swipe start`.
|
||||||
|
|
||||||
|
> **Warning**: For v1.1.0 below, the configuration file is located at
|
||||||
|
> `/usr/local/share/comfortable-swipe/comfortable-swipe.conf`
|
||||||
|
|
||||||
|
> **Note**: You can locate the absolute path to your configuration by running: `comfortable-swipe config path`
|
||||||
|
|
||||||
|
## Configuration Reference
|
||||||
|
|
||||||
|
| Property | Value | Examples |
|
||||||
|
| --------- | :--------------------------------------------------------------------: | ---------------------------------------------------------------------------------- |
|
||||||
|
| left3 | 3-finger swipe left | ctrl+alt+Right |
|
||||||
|
| left4 | 4-finger swipe left | ctrl+alt+shift+Right |
|
||||||
|
| right3 | 3-finger swipe right | ctrl+alt+Left |
|
||||||
|
| right4 | 4-finger swipe right | ctrl+alt+shift+Left |
|
||||||
|
| up3 | 3-finger swipe up | ctrl+alt+Down |
|
||||||
|
| up4 | 4-finger swipe up | ctrl+alt+shift+Down |
|
||||||
|
| down3 | 3-finger swipe down | ctrl+alt+Up |
|
||||||
|
| down4 | 4-finger swipe down | ctrl+alt+shift+Up |
|
||||||
|
| threshold | mouse movement pixels that trigger a swipe (can be as large as 1000.0) | 0.0 / 240.0 / 1000.0 |
|
||||||
|
| mouse3 | mouses a mouse button when 3 fingers are down | button1 / move / scroll<br> _(see [Mouse Gestures](#mouse-gestures-experimental))_ | |
|
||||||
|
| mouse4 | mouses a mouse button when 4 fingers are down | button1 / move / scroll <br> _(see [Mouse Gestures](#mouse-gestures-experimental)_ |
|
||||||
|
|
||||||
|
### Keystrokes
|
||||||
|
|
||||||
Taken from `man xdotool`:
|
Taken from `man xdotool`:
|
||||||
|
|
||||||
> Type a given keystroke. Examples being "alt+r", "Control_L+J",
|
> Type a given keystroke. Examples being "alt+r", "Control_L+J",
|
||||||
@ -94,163 +272,209 @@ Taken from `man xdotool`:
|
|||||||
|
|
||||||
Refer to https://www.linux.org/threads/xdotool-keyboard.10528/ for a complete list of keycodes you can use.
|
Refer to https://www.linux.org/threads/xdotool-keyboard.10528/ for a complete list of keycodes you can use.
|
||||||
|
|
||||||
**Keyboard Shortcuts**:
|
- [DEFKEY - All Linux keyboard shortcuts](https://defkey.com/)
|
||||||
|
- [Unity Keyboard Shortcuts](https://cheatography.com/sapemeg/cheat-sheets/ubuntu-unity-16-04/)
|
||||||
|
- [GNOME Keyboard Shortcuts](https://wiki.gnome.org/Design/OS/KeyboardShortcuts)
|
||||||
|
- [KDE Keyboard Shortcuts](https://community.linuxmint.com/tutorial/view/47)
|
||||||
|
- [PopOS Keyboard Shortcuts](https://support.system76.com/articles/pop-keyboard-shortcuts/)
|
||||||
|
|
||||||
- Unity: https://cheatography.com/sapemeg/cheat-sheets/ubuntu-unity-16-04/
|
## Known Issues: Pop!_OS 20.04+
|
||||||
- GNOME: https://wiki.gnome.org/Design/OS/KeyboardShortcuts
|
|
||||||
- KDE: https://community.linuxmint.com/tutorial/view/47
|
|
||||||
|
|
||||||
## Swipe Gesture Templates
|
Pop!_OS 20.04+ may be sensitive to capitalization (#76, #82). Make sure to capitalize every first letter:
|
||||||
|
|
||||||
1. Switching workspaces
|
```bash
|
||||||
|
# Pop!_OS
|
||||||
|
comfortable-swipe up3 = Super+Ctrl+Down
|
||||||
|
comfortable-swipe down3 = Super+Ctrl+Up
|
||||||
|
```
|
||||||
|
|
||||||
|
## Example Configurations
|
||||||
|
|
||||||
|
This section includes some example configurations which you can use for your swipe experience.
|
||||||
|
|
||||||
|
1. Switch workspace (horizontal)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Unity, KDE
|
# Ubuntu flavors + GNOME
|
||||||
left3 = ctrl+alt+Right
|
comfortable-swipe left3 = ctrl+alt+Right
|
||||||
right3 = ctrl+alt+Left
|
comfortable-swipe right3 = ctrl+alt+Left
|
||||||
up3 = ctrl+alt+Down
|
```
|
||||||
down3 = ctrl+alt+Up
|
|
||||||
|
1. Switch workspace (vertical)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Ubuntu flavors + GNOME
|
||||||
|
comfortable-swipe up3 = ctrl+alt+Down
|
||||||
|
comfortable-swipe down3 = ctrl+alt+Up
|
||||||
```
|
```
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# GNOME
|
# GNOME alt.
|
||||||
up3 = super+PgDown
|
comfortable-swipe up3 = super+PgDown
|
||||||
down3 = super+PgUp
|
comfortable-swipe down3 = super+PgUp
|
||||||
```
|
|
||||||
|
|
||||||
1. Move window to workspace
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Unity, KDE
|
|
||||||
left4 = ctrl+alt+shift+Right
|
|
||||||
right4 = ctrl+alt+shift+Left
|
|
||||||
up4 = ctrl+alt+shift+Down
|
|
||||||
down4 = ctrl+alt+shift+Up
|
|
||||||
```
|
```
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# GNOME
|
# Pop OS
|
||||||
up4 = super+shift+PgDown
|
comfortable-swipe up3 = Super+Ctrl+Down
|
||||||
down4 = super+shift+PgUp
|
comfortable-swipe down3 = Super+Ctrl+Up
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Move window to workspace (horizontal)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Ubuntu flavors + GNOME + Kali
|
||||||
|
comfortable-swipe left4 = ctrl+alt+shift+Right
|
||||||
|
comfortable-swipe right4 = ctrl+alt+shift+Left
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Elementary OS
|
||||||
|
comfortable-swipe left4 = super+alt+Right
|
||||||
|
comfortable-swipe right4 = super+alt+Left
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Move window to workspace (vertical)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Ubuntu flavors + GNOME + Kali
|
||||||
|
comfortable-swipe up4 = ctrl+alt+shift+Down
|
||||||
|
comfortable-swipe down4 = ctrl+alt+shift+Up
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# GNOME alt.
|
||||||
|
comfortable-swipe up4 = super+shift+PgDown
|
||||||
|
comfortable-swipe down4 = super+shift+PgUp
|
||||||
```
|
```
|
||||||
|
|
||||||
1. Move window to other monitor
|
1. Move window to other monitor
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# GNOME
|
# Ubuntu flavors + GNOME
|
||||||
left4 = super+shift+Right
|
comfortable-swipe left4 = super+shift+Right
|
||||||
right4 = super+shift+Left
|
comfortable-swipe right4 = super+shift+Left
|
||||||
```
|
```
|
||||||
|
|
||||||
1. Toggle workspace overview
|
1. Toggle workspace overview
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
up3 = super+s
|
# Ubuntu flavors + Elementary OS
|
||||||
```
|
comfortable-swipe up3 = super+s
|
||||||
|
|
||||||
1. Show desktop ([setup manually](https://www.itsupportguides.com/knowledge-base/ubuntu/ubuntu-how-to-make-windows-d-show-desktop/))
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Ubuntu
|
|
||||||
down3 = ctrl+super+d
|
|
||||||
```
|
```
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# GNOME
|
# Elementary OS (all workspaces)
|
||||||
down3 = super+d
|
comfortable-swipe up4 = super+a
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Show desktop
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Ubuntu flavors
|
||||||
|
comfortable-swipe down3 = ctrl+super+d
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Linux Mint
|
||||||
|
comfortable-swipe down3 = super+d
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Kali
|
||||||
|
comfortable-swipe down3 = ctrl+alt+d
|
||||||
```
|
```
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# KDE
|
# KDE
|
||||||
down3 = ctrl+alt+d
|
comfortable-swipe down3 = ctrl+F12
|
||||||
```
|
```
|
||||||
|
|
||||||
1. Snap windows to the left/right
|
1. Snap windows to the left/right
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
left3 = super+Left
|
comfortable-swipe left3 = super+Left
|
||||||
right3 = super+Right
|
comfortable-swipe right3 = super+Right
|
||||||
```
|
```
|
||||||
|
|
||||||
1. Toggle maximize
|
1. Toggle maximize
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
up3 = super+Up
|
comfortable-swipe up3 = super+Up
|
||||||
```
|
```
|
||||||
|
|
||||||
1. Toggle minimize
|
1. Toggle minimize
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
down3 = super+Down
|
comfortable-swipe down3 = super+Down
|
||||||
```
|
|
||||||
|
|
||||||
1. Alt+Tab switch application (experimental)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
left3 = alt+Tab
|
|
||||||
right3 = alt+shift+Tab
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Mouse Gestures (Experimental)
|
## Mouse Gestures (Experimental)
|
||||||
|
|
||||||
We have included simple mouse gestures on swipe by setting `hold3` and `hold4`.
|
You can also play around with mouse gestures during swipe.
|
||||||
|
This enables certain mouse behaviour to trigger along with a 3/4-finger swipe.
|
||||||
|
|
||||||
```bash
|
Keys:
|
||||||
Possible Values (hold3, hold4):
|
|
||||||
|
|
||||||
move # just move the mouse cursor (no mousedown)
|
- mouse3 - for 3-finger mouse gestures
|
||||||
button1 # hold left click on finger swipe
|
- mouse4 - for 4-finger mosue gestures
|
||||||
button2 # hold middle click on finger swipe
|
- hold3 (deprecated) - old equivalent of mouse3
|
||||||
button3 # hold right click on finger swipe
|
- hold4 (deprecated) - old equivalent of mouse4
|
||||||
button4 # wheel up on finger swipe (experimental)
|
|
||||||
button5 # wheel down on finger swipe (experimental)
|
|
||||||
scroll # naive 3/4 finger natural scroll (no acceleration, very experimental)
|
|
||||||
scroll_reverse # naive 3/4 finger reverse scroll (no acceleration, very experimental)
|
|
||||||
```
|
|
||||||
|
|
||||||
Any value not mentioned above disables the mouse-hold.
|
Possible Values:
|
||||||
|
|
||||||
|
- button1 - left click
|
||||||
|
- button2 - middle click
|
||||||
|
- button3 - right click
|
||||||
|
- button4 - wheel up (experimental)
|
||||||
|
- button5 - wheel down (experimental)
|
||||||
|
- move - just move the mouse cursor while fingers are down
|
||||||
|
- scroll - 3/4 finger natural scroll (no acceleration, very experimental)
|
||||||
|
- scroll_reverse - 3/4 finger reverse scroll (no acceleration, very experimental)
|
||||||
|
|
||||||
|
> **Tip**: You can clear mouse gestures by setting them blank
|
||||||
|
>
|
||||||
|
> ```
|
||||||
|
> comfortable-swipe mouse3 =
|
||||||
|
> comfortable-swipe mouse4 =
|
||||||
|
> ```
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
- 3-finger drag
|
✔️ swipes OK
|
||||||
|
⭕ swipes DISABLED
|
||||||
|
|
||||||
|
- 3/4-finger drag ⭕
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
hold3 = button1
|
comfortable-swipe mouse3 = button1
|
||||||
|
comfortable-swipe mouse4 = button1
|
||||||
```
|
```
|
||||||
|
|
||||||
- 4-finger drag (with middle click)
|
You can also use `button2` for middle click and `button3` for right click.
|
||||||
|
|
||||||
|
- 3/4-finger natural scroll ⭕
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
hold4 = button2
|
comfortable-swipe mouse3 = scroll
|
||||||
|
comfortable-swipe mouse4 = scroll
|
||||||
```
|
```
|
||||||
|
|
||||||
- 3-finger natural scroll
|
- 3/4-finger reverse scroll ⭕
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
hold3 = scroll
|
comfortable-swipe mouse3 = scroll_reverse
|
||||||
|
comfortable-swipe mouse4 = scroll_reverse
|
||||||
```
|
```
|
||||||
|
|
||||||
- 4-finger reverse scroll
|
- Move 3/4-fingers with the cursor ✔️
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
hold4 = scroll_reverse
|
comfortable-swipe mouse3 = move
|
||||||
|
comfortable-swipe mouse4 = move
|
||||||
```
|
```
|
||||||
|
|
||||||
- Just move the cursor
|
> **Warning**: Some mouse configuration will **disable up/left/right/down behavior** to avoid gesture conflicts. The logic of this will be improved in the future.
|
||||||
|
|
||||||
```bash
|
|
||||||
hold3 = move
|
|
||||||
hold4 = move
|
|
||||||
```
|
|
||||||
|
|
||||||
- Any other command will disable the mouse hold
|
|
||||||
|
|
||||||
```bash
|
|
||||||
hold3 = disabled
|
|
||||||
hold4 = nothing
|
|
||||||
```
|
|
||||||
|
|
||||||
**Note**: Applying any mouse-hold configuration will disable up/left/right/down behavior to avoid gesture conflicts. The logic of this will be improved in the future.
|
|
||||||
|
|
||||||
## Debugging
|
## Debugging
|
||||||
|
|
||||||
@ -270,25 +494,155 @@ $ comfortable-swipe debug
|
|||||||
-event9 DEVICE_ADDED TouchPad seat0 default group7 cap:pg size 70x50mm tap(dl off) left scroll-nat scroll-2fg-edge click-buttonareas-clickfinger dwt-on
|
-event9 DEVICE_ADDED TouchPad seat0 default group7 cap:pg size 70x50mm tap(dl off) left scroll-nat scroll-2fg-edge click-buttonareas-clickfinger dwt-on
|
||||||
...
|
...
|
||||||
event9 GESTURE_SWIPE_BEGIN +2.03s 3
|
event9 GESTURE_SWIPE_BEGIN +2.03s 3
|
||||||
event9 GESTURE_SWIPE_UPDATE +2.03s 3 -9.95/ 2.64 (-26.90/ 7.12 unaccelerated)
|
event9 GESTURE_SWIPE_UPDATE +2.03s 3 -9.95/ 2.64 (-26.90/ 7.12 unaccelerated)
|
||||||
event9 GESTURE_SWIPE_UPDATE +2.03s 3 -10.44/ 3.19 (-28.22/ 8.62 unaccelerated)
|
event9 GESTURE_SWIPE_UPDATE +2.03s 3 -10.44/ 3.19 (-28.22/ 8.62 unaccelerated)
|
||||||
event9 GESTURE_SWIPE_UPDATE +2.04s 3 -9.71/ 2.64 (-26.25/ 7.12 unaccelerated)
|
event9 GESTURE_SWIPE_UPDATE +2.04s 3 -9.71/ 2.64 (-26.25/ 7.12 unaccelerated)
|
||||||
event9 GESTURE_SWIPE_UPDATE +2.05s 3 -8.98/ 2.64 (-24.28/ 7.12 unaccelerated)
|
event9 GESTURE_SWIPE_UPDATE +2.05s 3 -8.98/ 2.64 (-24.28/ 7.12 unaccelerated)
|
||||||
event9 GESTURE_SWIPE_UPDATE +2.06s 3 -7.40/ 2.36 (-20.01/ 6.37 unaccelerated)
|
event9 GESTURE_SWIPE_UPDATE +2.06s 3 -7.40/ 2.36 (-20.01/ 6.37 unaccelerated)
|
||||||
event9 GESTURE_SWIPE_UPDATE +2.06s 3 -6.31/ 2.50 (-17.06/ 6.75 unaccelerated)
|
event9 GESTURE_SWIPE_UPDATE +2.06s 3 -6.31/ 2.50 (-17.06/ 6.75 unaccelerated)
|
||||||
event9 GESTURE_SWIPE_UPDATE +2.07s 3 -5.34/ 1.80 (-14.44/ 4.87 unaccelerated)
|
event9 GESTURE_SWIPE_UPDATE +2.07s 3 -5.34/ 1.80 (-14.44/ 4.87 unaccelerated)
|
||||||
event9 GESTURE_SWIPE_UPDATE +2.08s 3 -4.61/ 2.08 (-12.47/ 5.62 unaccelerated)
|
event9 GESTURE_SWIPE_UPDATE +2.08s 3 -4.61/ 2.08 (-12.47/ 5.62 unaccelerated)
|
||||||
event9 GESTURE_SWIPE_UPDATE +2.09s 3 -4.49/ 1.53 (-12.14/ 4.12 unaccelerated)
|
event9 GESTURE_SWIPE_UPDATE +2.09s 3 -4.49/ 1.53 (-12.14/ 4.12 unaccelerated)
|
||||||
event9 GESTURE_SWIPE_UPDATE +2.09s 3 -4.01/ 1.25 (-10.83/ 3.37 unaccelerated)
|
event9 GESTURE_SWIPE_UPDATE +2.09s 3 -4.01/ 1.25 (-10.83/ 3.37 unaccelerated)
|
||||||
event9 GESTURE_SWIPE_UPDATE +2.10s 3 -4.13/ 0.42 (-11.15/ 1.12 unaccelerated)
|
event9 GESTURE_SWIPE_UPDATE +2.10s 3 -4.13/ 0.42 (-11.15/ 1.12 unaccelerated)
|
||||||
event9 GESTURE_SWIPE_END +2.11s 3
|
event9 GESTURE_SWIPE_END +2.11s 3
|
||||||
...
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
If you can see `GESTURE_SWIPE_XXX` in your output, that means your touchpad supports multi-touch swipe gestures.
|
If you can see `GESTURE_SWIPE_XXX` in your output, that means your touchpad supports multi-touch swipe gestures.
|
||||||
|
|
||||||
|
## FAQ: Can I run a _shell command_ instead of a keystroke?
|
||||||
|
|
||||||
|
**Answer 1**: _Unfortunately **NO**..._
|
||||||
|
|
||||||
|
For the following reasons:
|
||||||
|
|
||||||
|
1. We want prioritize "comfort" over functionality, which we deliver through performance in our negligible-overhead implementation (that's why C++)
|
||||||
|
1. There are other gesture libraries that already do this properly (eg. [libinput gestures](https://github.com/bulletmark/libinput-gestures), [Fusuma](https://github.com/iberianpig/fusuma)), we don't want to be a clone of them
|
||||||
|
1. Running a new shell command with unpredictable process time will break our unthreaded optimizations (unlike native keystrokes)
|
||||||
|
|
||||||
|
That's why it's not possible... or not?
|
||||||
|
|
||||||
|
**Answer 2**: _... but actually **IT'S POSSIBLE**!_
|
||||||
|
|
||||||
|
Although we don't provide this out of the box in our config, this can definitely be
|
||||||
|
done with the default bash tools.
|
||||||
|
|
||||||
|
## Hack: Shell command on swipe
|
||||||
|
|
||||||
|
Running shell commands our **NOT** part of the core features of comfortable-swipe,
|
||||||
|
but through the default bash tools you can _mimic_ this functionality via our program output.
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary> <b>Use Case</b>: <i>"I want to run <code>gnome-terminal</code> if I swipe up with 3 fingers."</i>
|
||||||
|
</summary>
|
||||||
|
|
||||||
|
1. Attach the program to the shell:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
comfortable-swipe start --attach
|
||||||
|
```
|
||||||
|
|
||||||
|
Verify it outputs when you swipe left, left, up, right, up with 3 fingers:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ comfortable-swipe start --attach
|
||||||
|
SWIPE left3
|
||||||
|
SWIPE left3
|
||||||
|
SWIPE up3
|
||||||
|
SWIPE right3
|
||||||
|
SWIPE up3
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Filter out the wanted gesture with `grep`.
|
||||||
|
|
||||||
|
In our case, we want 3-finger swipe up which is "SWIPE up3":
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ comfortable-swipe start --attach | grep --line-buffered "SWIPE up3"
|
||||||
|
SWIPE up3
|
||||||
|
SWIPE up3
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
> **Note**: The flag `--line-buffered` ensures the output prints line-by-line.
|
||||||
|
|
||||||
|
1. Now we can execute our shell command with `xargs`.
|
||||||
|
|
||||||
|
So if we want "SWIPE up3" to open the terminal,
|
||||||
|
|
||||||
|
```bash
|
||||||
|
comfortable-swipe start --attach | grep "SWIPE up3" --line-buffered | xargs -I@ gnome-terminal
|
||||||
|
```
|
||||||
|
|
||||||
|
> **Note**: The flag `-I@` in xargs substitutes the line "SWIPE xxx" to the charatcter "@", which you can use for your program.
|
||||||
|
|
||||||
|
1. _Bonus_: Add to autostart
|
||||||
|
|
||||||
|
Open our autostart file:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
gedit "$(comfortable-swipe autostart path)"
|
||||||
|
```
|
||||||
|
|
||||||
|
Tweak the `Exec` section:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[Desktop Entry]
|
||||||
|
Type=Application
|
||||||
|
Exec=comfortable-swipe start
|
||||||
|
Name=Comfortable Swipe
|
||||||
|
Comment=Comfortable 3/4-finger touchpad gestures
|
||||||
|
Hidden=false
|
||||||
|
NoDisplay=false
|
||||||
|
X-GNOME-Autostart-enabled=true
|
||||||
|
```
|
||||||
|
|
||||||
|
To:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[Desktop Entry]
|
||||||
|
Type=Application
|
||||||
|
Exec=comfortable-swipe start --attach | grep "SWIPE up3" --line-buffered | xargs -I@ gnome-terminal
|
||||||
|
Name=Comfortable Swipe
|
||||||
|
Comment=Comfortable 3/4-finger touchpad gestures
|
||||||
|
Hidden=false
|
||||||
|
NoDisplay=false
|
||||||
|
X-GNOME-Autostart-enabled=true
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Log out and log back in.
|
||||||
|
You should now be able to run your custom shell commands on startup.
|
||||||
|
|
||||||
|
1. _Bonus_: Use `--bare` instead of `--attach` to NOT run keystrokes while swiping
|
||||||
|
|
||||||
|
```bash
|
||||||
|
comfortable-swipe start --bare | grep "SWIPE up3" --line-buffered | xargs -I@ gnome-terminal
|
||||||
|
```
|
||||||
|
|
||||||
|
1. _Bonus_: You can pipe multiple gestures with `tee`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
comfortable-swipe start --attach | \
|
||||||
|
tee >(grep "SWIPE left3" --line-buffered | xargs -I@ <COMMAND>) | \
|
||||||
|
tee >(grep "SWIPE left4" --line-buffered | xargs -I@ <COMMAND>) | \
|
||||||
|
tee >(grep "SWIPE right3" --line-buffered | xargs -I@ <COMMAND>) | \
|
||||||
|
tee >(grep "SWIPE right4" --line-buffered | xargs -I@ <COMMAND>) | \
|
||||||
|
tee >(grep "SWIPE up3" --line-buffered | xargs -I@ <COMMAND>) | \
|
||||||
|
tee >(grep "SWIPE up4" --line-buffered | xargs -I@ <COMMAND>) | \
|
||||||
|
tee >(grep "SWIPE down3" --line-buffered | xargs -I@ <COMMAND>) | \
|
||||||
|
tee >(grep "SWIPE down4" --line-buffered | xargs -I@ <COMMAND>)
|
||||||
|
```
|
||||||
|
|
||||||
|
Substitute `<COMMAND>` with the shell command of your choice.
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
## Uninstall
|
## Uninstall
|
||||||
|
|
||||||
|
Run the following script:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
wget -qO - https://raw.githubusercontent.com/Hikari9/comfortable-swipe/master/uninstall | bash
|
wget -qO - https://raw.githubusercontent.com/Hikari9/comfortable-swipe/master/uninstall | bash
|
||||||
```
|
```
|
||||||
|
|||||||
539
comfortable-swipe
Executable file
539
comfortable-swipe
Executable file
@ -0,0 +1,539 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Comfortable Swipe
|
||||||
|
|
||||||
|
# turn on errors per line
|
||||||
|
set -e
|
||||||
|
|
||||||
|
DIR="$(dirname "$0")"
|
||||||
|
BASENAME="$(basename "$0")"
|
||||||
|
VERSION="$(cat "$DIR/VERSION" | tr -d '[:space:]')" # note: this will be hardcoded upon install
|
||||||
|
KEYS="left3|left4|right3|right4|up3|up4|down3|down4|threshold|mouse3|mouse4"
|
||||||
|
DEPRECATED="hold3|hold4"
|
||||||
|
|
||||||
|
|
||||||
|
#########
|
||||||
|
# USAGE #
|
||||||
|
#########
|
||||||
|
|
||||||
|
function usage {
|
||||||
|
cat <<EOF
|
||||||
|
Usage: $BASENAME [--help|--version] [start|stop|config|autostart|buffer|debug|status] [<args>]
|
||||||
|
|
||||||
|
Configuration:
|
||||||
|
|
||||||
|
$BASENAME <PROPERTY> gets configuration property
|
||||||
|
$BASENAME <PROPERTY> [=] <VALUE> sets configuration to a value
|
||||||
|
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
# show help
|
||||||
|
function help {
|
||||||
|
usage
|
||||||
|
cat <<EOF
|
||||||
|
|
||||||
|
Global Options:
|
||||||
|
|
||||||
|
-h, --help show this help text
|
||||||
|
-v, --version print the program version
|
||||||
|
|
||||||
|
Commands:
|
||||||
|
start [--attach|--bare]
|
||||||
|
starts 3/4-finger gesture service in a detached process
|
||||||
|
--attach attach process to console
|
||||||
|
--bare attach with bare configurations
|
||||||
|
|
||||||
|
stop
|
||||||
|
stops 3/4-finger gesture service
|
||||||
|
|
||||||
|
edit
|
||||||
|
edits the configuration file with gedit
|
||||||
|
|
||||||
|
autostart [on|off|toggle|status|path]
|
||||||
|
toggle to automatically run on startup automatically run on startup (toggleable)
|
||||||
|
|
||||||
|
buffer
|
||||||
|
parses output of libinput debug-events
|
||||||
|
|
||||||
|
config [get|set|delete|list|properties|path] [...]
|
||||||
|
shows the location of the config file
|
||||||
|
|
||||||
|
debug
|
||||||
|
logs raw output from input events taken from libinput
|
||||||
|
|
||||||
|
status
|
||||||
|
checks status of program and autostart
|
||||||
|
|
||||||
|
Report bugs to https://github.com/Hikari9/comfortable-swipe/issues/new
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
####################
|
||||||
|
# COMMAND OPTIONS #
|
||||||
|
####################
|
||||||
|
|
||||||
|
|
||||||
|
for i in "$@"; do
|
||||||
|
case $i in
|
||||||
|
-h | --help) # eagerly show help
|
||||||
|
help
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
-v | --version) # eagerly print version
|
||||||
|
echo "comfortable-swipe $VERSION"
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
--attach | --bare) # for start
|
||||||
|
if [[ "$1" != start ]]; then
|
||||||
|
if [[ "$1" != buffer ]]; then
|
||||||
|
echo "Unknown option: $i" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
OPTION_ATTACH="true"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
if [[ "$i" == -* ]]; then
|
||||||
|
echo "Unknown option: $i" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
#########
|
||||||
|
# START #
|
||||||
|
#########
|
||||||
|
|
||||||
|
|
||||||
|
# start comfortable-swipe
|
||||||
|
# internally pipes debug text to the buffer
|
||||||
|
function start {
|
||||||
|
stop > /dev/null 2>&1
|
||||||
|
if [[ "$OPTION_ATTACH" == "true" ]]; then
|
||||||
|
# attach the buffered output
|
||||||
|
debug | buffer $@
|
||||||
|
else
|
||||||
|
# detach buffered output
|
||||||
|
nohup "$BASENAME" debug </dev/null 2>&1 | "$BASENAME" buffer $@ >/dev/null 2>&1 & disown
|
||||||
|
echo "Comfortable swipe is RUNNING in the background"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
########
|
||||||
|
# STOP #
|
||||||
|
########
|
||||||
|
|
||||||
|
|
||||||
|
# stop running comfortable-swipe commands (except self)
|
||||||
|
function stop {
|
||||||
|
function stop_prop {
|
||||||
|
pgrep -f "${1:?}" | fgrep -v $$ | xargs -I{} kill -- "{}"
|
||||||
|
}
|
||||||
|
stop_prop "$BASENAME"
|
||||||
|
stop_prop "$(which comfortable-swipe)"
|
||||||
|
stop_prop "$(which comfortable-swipe-buffer)"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#########
|
||||||
|
# DEBUG #
|
||||||
|
#########
|
||||||
|
|
||||||
|
|
||||||
|
# show debug text
|
||||||
|
# internally just calls libinput debug-events
|
||||||
|
function debug {
|
||||||
|
if command -v libinput-debug-events > /dev/null 2>&1; then
|
||||||
|
# compat for old Ubuntu
|
||||||
|
local COMMAND="libinput-debug-events"
|
||||||
|
else
|
||||||
|
local COMMAND="libinput debug-events"
|
||||||
|
fi
|
||||||
|
stdbuf -oL -e0 $COMMAND 2> >(fgrep -v 'double tracking')
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
##########
|
||||||
|
# BUFFER #
|
||||||
|
##########
|
||||||
|
|
||||||
|
|
||||||
|
# parse input from a buffer
|
||||||
|
# internally calls comfortable-swipe-main.cpp, which is
|
||||||
|
# installed as: /usr/local/bin/ comfortable-swipe-buffer
|
||||||
|
function buffer {
|
||||||
|
exec comfortable-swipe-buffer "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
##########
|
||||||
|
# STATUS #
|
||||||
|
##########
|
||||||
|
|
||||||
|
|
||||||
|
function _program_running {
|
||||||
|
pgrep -f "$BASENAME" | fgrep -v $$ > /dev/null 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# verbosely show comfortable-swipe status
|
||||||
|
function status {
|
||||||
|
# show autostart status
|
||||||
|
echo "Autostart is $("$BASENAME" autostart status)"
|
||||||
|
# show program status
|
||||||
|
if _program_running; then
|
||||||
|
echo "Program is RUNNING"
|
||||||
|
else
|
||||||
|
echo "Program is STOPPED"
|
||||||
|
fi
|
||||||
|
# show configuration status
|
||||||
|
echo --------------------
|
||||||
|
echo "Configuration: $(config path)"
|
||||||
|
mouse3="$(config get mouse3)"
|
||||||
|
mouse4="$(config get mouse4)"
|
||||||
|
for key in $(config keys); do
|
||||||
|
value="$(config get "$key")"
|
||||||
|
if [[ -z "$value" ]]; then
|
||||||
|
vstatus="NOTSET"
|
||||||
|
else
|
||||||
|
vstatus="VALID"
|
||||||
|
if [[ "$key" != mouse* ]]; then
|
||||||
|
if [[ "$key" == *3 && -n "$mouse3" && "$mouse3" != move ]]; then
|
||||||
|
vstatus="DISABLED"
|
||||||
|
elif [[ "$key" == *4 && -n "$mouse4" && "$mouse4" != move ]]; then
|
||||||
|
vstatus="DISABLED"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [[ "$key" == threshold ]]; then
|
||||||
|
if ! [[ "$value" =~ ^[+-]?[0-9]+\.?[0-9]*$ ]]; then
|
||||||
|
# not a float
|
||||||
|
vstatus="INVALID"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo "$key $vstatus" | awk '{printf "%9s is %7s", $1, $2}'
|
||||||
|
if [[ ! -z "$value" ]]; then
|
||||||
|
echo " ($value)"
|
||||||
|
else
|
||||||
|
echo
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
##########
|
||||||
|
# CONFIG #
|
||||||
|
##########
|
||||||
|
|
||||||
|
|
||||||
|
# get location of configuration file
|
||||||
|
function config {
|
||||||
|
local CONFIG="$HOME/.config/comfortable-swipe.conf"
|
||||||
|
|
||||||
|
############
|
||||||
|
# show usage
|
||||||
|
function usage {
|
||||||
|
echo "Usage: $BASENAME config [get|set|delete|list|keys|edit|path] ..."
|
||||||
|
}
|
||||||
|
|
||||||
|
#####################
|
||||||
|
# show path to config
|
||||||
|
function path {
|
||||||
|
echo "$CONFIG"
|
||||||
|
}
|
||||||
|
|
||||||
|
##############################################
|
||||||
|
# list config, show only last among duplicates
|
||||||
|
function list {
|
||||||
|
# dispatch subcommands
|
||||||
|
if [[ $# -eq 0 ]]; then
|
||||||
|
# no options; just show path
|
||||||
|
tac "$CONFIG" |\
|
||||||
|
sed -E "s/[#;].*//g" |\
|
||||||
|
egrep '\s+' |\
|
||||||
|
tr -d ' ' |\
|
||||||
|
egrep "^($KEYS|$DEPRECATED)=" |\
|
||||||
|
awk '!a[$1]++' |\
|
||||||
|
tac |\
|
||||||
|
sed 's/=/ = /g'
|
||||||
|
else
|
||||||
|
# filter list to match arguments as pattern
|
||||||
|
local pattern="$1"
|
||||||
|
for arg in "${@:2}"; do
|
||||||
|
pattern="$pattern|$arg"
|
||||||
|
done
|
||||||
|
list | egrep "($pattern)[^=]* ="
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
############################################
|
||||||
|
# get a list of all valid keys, one per line
|
||||||
|
function keys {
|
||||||
|
echo "$KEYS" | sed 's/|/\n/g'
|
||||||
|
}
|
||||||
|
|
||||||
|
##################################
|
||||||
|
# Get a specific key in the config
|
||||||
|
function get {
|
||||||
|
function usage {
|
||||||
|
echo "Usage: $BASENAME config get <PROPERTY>"
|
||||||
|
echo -n "Props: "
|
||||||
|
echo "$KEYS" | sed 's/|/, /g'
|
||||||
|
}
|
||||||
|
# no next argument: show list
|
||||||
|
if [[ $# -eq 0 ]]; then
|
||||||
|
list
|
||||||
|
exit $?
|
||||||
|
fi
|
||||||
|
local KEY="$1"
|
||||||
|
# check if key is valid
|
||||||
|
if ! [[ "$KEY" =~ ^($KEYS|$DEPRECATED)$ ]]; then
|
||||||
|
# echo "'$KEY' is an invalid property" >&2
|
||||||
|
# echo >&2
|
||||||
|
usage >&2
|
||||||
|
echo >&2
|
||||||
|
echo "If you want to list down configurations, you can run:" >&2
|
||||||
|
echo >&2
|
||||||
|
echo " $BASENAME config list" >&2
|
||||||
|
echo >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
# get key from config file
|
||||||
|
list | fgrep -m1 "$KEY =" | sed -E "s/^$KEY = //"
|
||||||
|
}
|
||||||
|
|
||||||
|
############################
|
||||||
|
# delete a key in the config
|
||||||
|
function delete {
|
||||||
|
# helper function to print usage
|
||||||
|
function usage {
|
||||||
|
echo "Usage: $BASENAME config delete [<PROPERTY>...]"
|
||||||
|
}
|
||||||
|
# no next argument: show help
|
||||||
|
if [[ $# -eq 0 ]]; then
|
||||||
|
echo "Property name is required!" >&2
|
||||||
|
# no key; show usage
|
||||||
|
usage >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
local DELETE="$(list "$@")"
|
||||||
|
# check if there is something to delete
|
||||||
|
if [[ -z "$DELETE" ]]; then
|
||||||
|
echo "No config entry to delete" >&2
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
echo "Deleted:"
|
||||||
|
echo "$DELETE"
|
||||||
|
local RESULT="$(egrep -v "^\\s*($(echo "$DELETE" | awk '{print $1}' | paste -s -d '|'))\\s*=" "$CONFIG")"
|
||||||
|
echo "$RESULT" > "$CONFIG"
|
||||||
|
# restart comfortable-swipe if it is running
|
||||||
|
if _program_running; then
|
||||||
|
start > /dev/null
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
##################################
|
||||||
|
# set a specific key in the config
|
||||||
|
function set {
|
||||||
|
# helper function to print usage
|
||||||
|
function usage {
|
||||||
|
echo "Usage: $BASENAME config set <PROPERTY> [=] <VALUE>"
|
||||||
|
echo -n "Valid properties: "
|
||||||
|
echo "$KEYS" | sed 's/|/, /g'
|
||||||
|
echo
|
||||||
|
echo "Example:"
|
||||||
|
echo
|
||||||
|
echo " $BASENAME config set left3 = ctrl+super+Right"
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
# no next argument: show help
|
||||||
|
if [[ $# -eq 0 ]]; then
|
||||||
|
echo "Property name is required!" >&2
|
||||||
|
echo >&2
|
||||||
|
# no key; show usage
|
||||||
|
usage >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
# parse key and value option
|
||||||
|
local KEYVALUE="${@:1}"
|
||||||
|
local KEY=
|
||||||
|
local VALUE=
|
||||||
|
case "$KEYVALUE" in
|
||||||
|
*=*)
|
||||||
|
# key has equal sign, we split it
|
||||||
|
KEY="${KEYVALUE%%=*}"
|
||||||
|
VALUE="${KEYVALUE#*=}"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
# default: just get from next arguments combined
|
||||||
|
if [[ $# -eq 1 ]]; then
|
||||||
|
echo "Property value is required!" >&2
|
||||||
|
usage >&2
|
||||||
|
echo >&2
|
||||||
|
echo "If you want to set value to blank, explicitly pass a blank string:" >&2
|
||||||
|
echo >&2
|
||||||
|
echo " $BASENAME config set $@ \"\"" >&2
|
||||||
|
echo >&2
|
||||||
|
echo "Or delete explicitly:" >&2
|
||||||
|
echo >&2
|
||||||
|
echo " $BASENAME config delete $1"
|
||||||
|
echo >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
KEY="$1"
|
||||||
|
VALUE="${@:2}"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
# trim leading and trailing spaces from key and value
|
||||||
|
KEY="$(echo "$KEY" | awk '{$1=$1};1')"
|
||||||
|
VALUE="$(echo "$VALUE" | awk '{$1=$1};1')"
|
||||||
|
# check if key is valid
|
||||||
|
if ! [[ "$KEY" =~ ^($KEYS|$DEPRECATED)$ ]]; then
|
||||||
|
echo "'$KEY' is an invalid property name" >&2
|
||||||
|
echo >&2
|
||||||
|
usage
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
# if the key is present in the config, perform a replace
|
||||||
|
# replace the last value from the config with the given key
|
||||||
|
if list | grep -P "^\Q$KEY =" > /dev/null 2>&1; then
|
||||||
|
# apply sed to keep our formatting
|
||||||
|
# \\1 - keep any kind of indentation
|
||||||
|
# \\2 - keep any comments after the value (with the whitespace instact)
|
||||||
|
local RESULT="$(tac "$CONFIG" |\
|
||||||
|
sed -E "s/^(\\s*)$KEY\\s*=\\s*(\?!(\\s*[#;]))*(.*)\$/\\1$KEY = $VALUE\\2/1" |\
|
||||||
|
tac)"
|
||||||
|
# make sure we separate piping from outputing
|
||||||
|
echo "$RESULT" > "$CONFIG"
|
||||||
|
else
|
||||||
|
# otherwise, key is not present so we simply append
|
||||||
|
echo "$KEY = $VALUE" >> "$CONFIG"
|
||||||
|
fi
|
||||||
|
# show newly set value
|
||||||
|
echo "$KEY = $(get "$KEY")"
|
||||||
|
# restart comfortable-swipe if it is running
|
||||||
|
if _program_running; then
|
||||||
|
start > /dev/null
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
######################
|
||||||
|
# dispatch subcommands
|
||||||
|
if [[ $# -eq 0 ]]; then
|
||||||
|
# no options; just show usage
|
||||||
|
usage
|
||||||
|
echo "Try:"
|
||||||
|
echo
|
||||||
|
echo " $BASENAME config list"
|
||||||
|
echo
|
||||||
|
elif declare -f "$1" >/dev/null 2>&1; then
|
||||||
|
# invoke subcommand function, passing arguments through
|
||||||
|
# TODO: unset all nonlocal functions
|
||||||
|
"$@" # same as "$1" "$2" "$3" ... for full argument list
|
||||||
|
else
|
||||||
|
echo "Error: function $1 not recognized" >&2
|
||||||
|
echo "$USAGE" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
#############
|
||||||
|
# AUTOSTART #
|
||||||
|
#############
|
||||||
|
|
||||||
|
# enable or disable autostart
|
||||||
|
function autostart {
|
||||||
|
# path to autostart files
|
||||||
|
local AUTOSTART="$HOME/.config/autostart/comfortable-swipe.desktop"
|
||||||
|
local ENABLED="X-GNOME-Autostart-enabled"
|
||||||
|
|
||||||
|
##########################
|
||||||
|
# show autostart file path
|
||||||
|
function path {
|
||||||
|
echo "$AUTOSTART"
|
||||||
|
}
|
||||||
|
|
||||||
|
##################################################
|
||||||
|
# echo autostart status: ON, OFF, MISSING, INVALID
|
||||||
|
function status {
|
||||||
|
if [[ ! -f "$AUTOSTART" ]]; then
|
||||||
|
echo "MISSING"
|
||||||
|
elif fgrep "$ENABLED=true" < "$AUTOSTART" > /dev/null; then
|
||||||
|
echo "ON"
|
||||||
|
elif fgrep "$ENABLED=false" < "$AUTOSTART" > /dev/null; then
|
||||||
|
echo "OFF"
|
||||||
|
else
|
||||||
|
echo "INVALID"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
##################
|
||||||
|
# enable autostart
|
||||||
|
function on {
|
||||||
|
sed -i "s/$ENABLED=false/$ENABLED=true/" "$AUTOSTART"
|
||||||
|
echo "Autostart switched on"
|
||||||
|
}
|
||||||
|
|
||||||
|
###################
|
||||||
|
# disable autostart
|
||||||
|
function off {
|
||||||
|
sed -i "s/$ENABLED=true/$ENABLED=false/" "$AUTOSTART"
|
||||||
|
echo "Autostart switched off"
|
||||||
|
}
|
||||||
|
|
||||||
|
#####################################
|
||||||
|
# toggle to opposite autostart status
|
||||||
|
function toggle {
|
||||||
|
[[ $(status) == ON ]] && off || on
|
||||||
|
}
|
||||||
|
|
||||||
|
######################
|
||||||
|
# dispatch subcommands
|
||||||
|
if [[ $# -eq 0 ]]; then
|
||||||
|
# default behavior is to toggle
|
||||||
|
toggle
|
||||||
|
elif declare -f "$1" >/dev/null 2>&1; then
|
||||||
|
# invoke subcommand function, passing arguments through
|
||||||
|
# TODO: unset all nonlocal functions
|
||||||
|
"$@" # same as "$1" "$2" "$3" ... for full argument list
|
||||||
|
else
|
||||||
|
echo "Function $1 not recognized" >&2
|
||||||
|
echo "Usage: $BASENAME autostart [on|off|toggle|status|path]" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
############
|
||||||
|
# DISPATCH #
|
||||||
|
############
|
||||||
|
|
||||||
|
|
||||||
|
# dispatch subcommands
|
||||||
|
if [[ $# -eq 0 ]]; then
|
||||||
|
# no options; just show help
|
||||||
|
help
|
||||||
|
elif declare -f "$1" >/dev/null 2>&1; then
|
||||||
|
# invoke subcommand function, passing arguments through
|
||||||
|
# TODO: unset all nonlocal functions
|
||||||
|
"$@" # same as "$1" "$2" "$3" ... for full argument list
|
||||||
|
else
|
||||||
|
function abort {
|
||||||
|
# echo "Error: $1 not recognized" >&2
|
||||||
|
# echo >&2
|
||||||
|
usage >&2
|
||||||
|
echo -n "Valid props: " >&2
|
||||||
|
echo "$KEYS" | sed 's/|/, /g' >&2
|
||||||
|
}
|
||||||
|
# try to invoke config set / get depending on number of arguments
|
||||||
|
if [[ $# -eq 1 ]]; then
|
||||||
|
# one argument, use shorthand get
|
||||||
|
config get "$1" || abort
|
||||||
|
else
|
||||||
|
# multiple arguments, use shorthand set
|
||||||
|
config set "$@" 2> /dev/null || abort
|
||||||
|
fi
|
||||||
|
fi
|
||||||
55
comfortable-swipe-defines.cpp
Normal file
55
comfortable-swipe-defines.cpp
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
#ifndef __comfortable_swipe_defines__
|
||||||
|
#define __comfortable_swipe_defines__
|
||||||
|
// all global #define statements go here
|
||||||
|
/*
|
||||||
|
Comfortable Swipe
|
||||||
|
by Rico Tiongson
|
||||||
|
|
||||||
|
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/>.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* COMFORTABLE_SWIPE_CONFIG
|
||||||
|
*
|
||||||
|
* This definition points to the location of the configuration file.
|
||||||
|
* A warning will be issued to the compiler if you do not define this at compile
|
||||||
|
* time.
|
||||||
|
*/
|
||||||
|
#ifndef COMFORTABLE_SWIPE_CONFIG
|
||||||
|
#pragma message "Please define COMFORTABLE_SWIPE_CONFIG during compilation!"
|
||||||
|
// just point to config from source directory
|
||||||
|
#define COMFORTABLE_SWIPE_CONFIG "/dev/null"
|
||||||
|
#endif /* COMFORTABLE_SWIPE_CONFIG */
|
||||||
|
/**
|
||||||
|
* COMFORTABLE_SWIPE_AUTOSTART
|
||||||
|
*
|
||||||
|
* This definition points to the location of the autostart (.desktop) file.
|
||||||
|
* A warning will be issued to the compiler if you do not define this at compile
|
||||||
|
* time.
|
||||||
|
*/
|
||||||
|
#ifndef COMFORTABLE_SWIPE_AUTOSTART
|
||||||
|
#pragma message "Please define COMFORTABLE_SWIPE_AUTOSTART during compilation!"
|
||||||
|
// just point to autostart from source directory
|
||||||
|
#define COMFORTABLE_SWIPE_AUTOSTART "/dev/null"
|
||||||
|
#endif /* COMFORTABLE_SWIPE_AUTOSTART */
|
||||||
|
/**
|
||||||
|
* COMFORTABLE_SWIPE_VERSION
|
||||||
|
*
|
||||||
|
* This is an optional definition for the version string of comfortable-swipe.
|
||||||
|
*/
|
||||||
|
#ifndef COMFORTABLE_SWIPE_VERSION
|
||||||
|
#pragma message "Please define COMFORTABLE_SWIPE_VERSION during compilation!"
|
||||||
|
#define COMFORTABLE_SWIPE_VERSION "v(UNKNOWN)"
|
||||||
|
#endif /* COMFORTABLE_SWIPE_VERSION */
|
||||||
|
|
||||||
|
#endif /* __comfortable_swipe_defines__ */
|
||||||
197
comfortable-swipe-gesture-swipe-xdokey.cpp
Normal file
197
comfortable-swipe-gesture-swipe-xdokey.cpp
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
#ifndef __comfortable_swipe_gesture_swipe_xdokey__
|
||||||
|
#define __comfortable_swipe_gesture_swipe_xdokey__
|
||||||
|
|
||||||
|
/*
|
||||||
|
Comfortable Swipe
|
||||||
|
by Rico Tiongson
|
||||||
|
|
||||||
|
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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <array> // std::array
|
||||||
|
#include <iostream> // std::cout, std::endl
|
||||||
|
#include <string> // std::string
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include <xdo.h> // xdo_send_keysequence_window
|
||||||
|
// CURRENT_WINDOW
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "comfortable-swipe-gesture-swipe.cpp"
|
||||||
|
|
||||||
|
namespace comfortable_swipe {
|
||||||
|
/**
|
||||||
|
* Gesture Swipe keyboard-swipe gestures class with xdo.
|
||||||
|
*
|
||||||
|
* Performs a swipe in one of the four cardinal directions:
|
||||||
|
* left, right, up, down. Applicable for 3 or 4 fingers.
|
||||||
|
*
|
||||||
|
* When constructing, please mind the order in the
|
||||||
|
* `gesture_swipe_xdokey::command_name[]` static array.
|
||||||
|
*/
|
||||||
|
class gesture_swipe_xdokey : public gesture_swipe {
|
||||||
|
public:
|
||||||
|
// stores the 8 command strings for xdo to execute
|
||||||
|
std::array<std::string, 8> commands;
|
||||||
|
// constructor
|
||||||
|
gesture_swipe_xdokey(const decltype(commands) &commands, float threshold = 0);
|
||||||
|
// destructor
|
||||||
|
virtual ~gesture_swipe_xdokey();
|
||||||
|
// hooks that we override
|
||||||
|
virtual void begin() override;
|
||||||
|
virtual void update() override;
|
||||||
|
virtual void end() override;
|
||||||
|
// override this when keyboard gesture is to be performed
|
||||||
|
virtual void do_keyboard_gesture(int mask);
|
||||||
|
// public accessors
|
||||||
|
virtual int get_previous_gesture() const { return this->previous_gesture; }
|
||||||
|
virtual int get_current_mask() const { return this->current_mask; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// stores square of threshold so we can compute faster
|
||||||
|
float threshold_squared;
|
||||||
|
// stores previous gesture so we don't repeat action
|
||||||
|
int previous_gesture;
|
||||||
|
int current_mask;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// static enums we will use for gesture matching
|
||||||
|
static const int FRESH = -1;
|
||||||
|
static const int MSK_THREE_FINGERS = 0;
|
||||||
|
static const int MSK_FOUR_FINGERS = 1;
|
||||||
|
static const int MSK_NEGATIVE = 0;
|
||||||
|
static const int MSK_POSITIVE = 2;
|
||||||
|
static const int MSK_HORIZONTAL = 0;
|
||||||
|
static const int MSK_VERTICAL = 4;
|
||||||
|
// mappings to our command string names
|
||||||
|
static const std::string command_name[];
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Our mapped directional command names. These will be
|
||||||
|
* printed to the console during execution:
|
||||||
|
*
|
||||||
|
* SWIPE <command_name>
|
||||||
|
*
|
||||||
|
* Refer to the order of this array for the "commands"
|
||||||
|
* paramter in the constructor.
|
||||||
|
*/
|
||||||
|
decltype(
|
||||||
|
gesture_swipe_xdokey::command_name) gesture_swipe_xdokey::command_name = {
|
||||||
|
// the order of variables is based on bitmasking
|
||||||
|
// <VERTICAL?> | <POSITIVE?> | <FOUR FINGERS?>
|
||||||
|
"left3", // 000
|
||||||
|
"left4", // 001
|
||||||
|
"right3", // 010
|
||||||
|
"right4", // 011
|
||||||
|
"up3", // 100
|
||||||
|
"up4", // 101
|
||||||
|
"down3", // 110
|
||||||
|
"down4" // 111
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Constructs a new keyboard-based swipe gesture, given configurations
|
||||||
|
* for certain swipe events. Here, we construct our definition based on
|
||||||
|
* the four directions (left, up, right, down) for 3-finger and 4-finger
|
||||||
|
* swipes. Note that the direction is based on the Australian natural
|
||||||
|
* scrolling direction (ie. left3 is natural movement of 3 fingers left).
|
||||||
|
*/
|
||||||
|
gesture_swipe_xdokey::gesture_swipe_xdokey(
|
||||||
|
const decltype(gesture_swipe_xdokey::commands) &commands, float threshold)
|
||||||
|
: gesture_swipe(), commands(commands),
|
||||||
|
threshold_squared(threshold * threshold),
|
||||||
|
previous_gesture(gesture_swipe_xdokey::FRESH),
|
||||||
|
current_mask(gesture_swipe_xdokey::FRESH) {}
|
||||||
|
/**
|
||||||
|
* Destructs this keyboard swipe gesture.
|
||||||
|
*/
|
||||||
|
gesture_swipe_xdokey::~gesture_swipe_xdokey() {}
|
||||||
|
/**
|
||||||
|
* Hook on begin of swipe gesture.
|
||||||
|
*/
|
||||||
|
void gesture_swipe_xdokey::begin() {
|
||||||
|
// call superclass method
|
||||||
|
gesture_swipe::begin();
|
||||||
|
// assign gesture to FRESH
|
||||||
|
current_mask = FRESH;
|
||||||
|
previous_gesture = FRESH;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Hook on update of swipe gesture.
|
||||||
|
*/
|
||||||
|
void gesture_swipe_xdokey::update() {
|
||||||
|
// call superclass method
|
||||||
|
gesture_swipe::update();
|
||||||
|
// scale threshold to 1/10 when gesture is fresh
|
||||||
|
// acts like our static friction coefficient
|
||||||
|
const float scale = get_previous_gesture() == FRESH ? 0.01f : 1.0f;
|
||||||
|
// we are working with floating points which are not exact
|
||||||
|
// make sure we compare with a very small value (1e-6f)
|
||||||
|
// if distance goes out of threshold, perform our swipe
|
||||||
|
if (x * x + y * y > threshold_squared * scale + 1e-6f) {
|
||||||
|
// we parse our mask based on the values obtained from the regex
|
||||||
|
int mask = 0;
|
||||||
|
if (fingers == 3)
|
||||||
|
mask |= MSK_THREE_FINGERS;
|
||||||
|
else if (fingers == 4)
|
||||||
|
mask |= MSK_FOUR_FINGERS;
|
||||||
|
const float absx = x >= 0 ? x : -x;
|
||||||
|
const float absy = y >= 0 ? y : -y;
|
||||||
|
if (absx > absy) {
|
||||||
|
// gesture is horizontal
|
||||||
|
mask |= MSK_HORIZONTAL;
|
||||||
|
if (x < 0)
|
||||||
|
mask |= MSK_NEGATIVE;
|
||||||
|
else
|
||||||
|
mask |= MSK_POSITIVE;
|
||||||
|
} else /* std::abs(x) <= std::abs(y) */
|
||||||
|
{
|
||||||
|
// gesture is vertical
|
||||||
|
mask |= MSK_VERTICAL;
|
||||||
|
if (y < 0)
|
||||||
|
mask |= MSK_NEGATIVE;
|
||||||
|
else
|
||||||
|
mask |= MSK_POSITIVE;
|
||||||
|
}
|
||||||
|
// update our mask
|
||||||
|
current_mask = mask;
|
||||||
|
// send command on fresh OR opposite gesture
|
||||||
|
if (previous_gesture == FRESH ||
|
||||||
|
previous_gesture == (mask ^ MSK_POSITIVE)) {
|
||||||
|
// do keyboard gesture
|
||||||
|
do_keyboard_gesture(mask);
|
||||||
|
// reset our location variables
|
||||||
|
x = y = 0;
|
||||||
|
previous_gesture = mask;
|
||||||
|
}
|
||||||
|
} else { // not in threshold, set mask to fresh
|
||||||
|
current_mask = FRESH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Perform our maske command to xdo.
|
||||||
|
*/
|
||||||
|
void gesture_swipe_xdokey::do_keyboard_gesture(int mask) {
|
||||||
|
// perform our keyboard command with xdo_send_keysequence
|
||||||
|
xdo_send_keysequence_window(xdo, CURRENTWINDOW, commands[mask].data(), 0);
|
||||||
|
std::cout << "SWIPE " << command_name[mask] << std::endl;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Hook on end of swipe gesture.
|
||||||
|
*/
|
||||||
|
void gesture_swipe_xdokey::end() {
|
||||||
|
// just call superclass method
|
||||||
|
gesture_swipe::end();
|
||||||
|
}
|
||||||
|
} // namespace comfortable_swipe
|
||||||
|
#endif /* __comfortable_swipe_gesture_swipe_xdokey__ */
|
||||||
202
comfortable-swipe-gesture-swipe-xdomouse.cpp
Normal file
202
comfortable-swipe-gesture-swipe-xdomouse.cpp
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
#ifndef __comfortable_swipe_gesture_swipe_xdomouse__
|
||||||
|
#define __comfortable_swipe_gesture_swipe_xdomouse__
|
||||||
|
/**
|
||||||
|
* File: comfortable-swipe-gesture-swipe-xdomouse.cpp
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
Comfortable Swipe
|
||||||
|
by Rico Tiongson
|
||||||
|
|
||||||
|
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/>.
|
||||||
|
*/
|
||||||
|
#include <cstdio> // std::sscanf
|
||||||
|
#include <cstring> // strncmp
|
||||||
|
#include <iostream> // std::cout, std::endl
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include <xdo.h> // xdo_mouse_down
|
||||||
|
// xdo_mouse_up
|
||||||
|
// xdo_move_mouse_relative
|
||||||
|
// CURRENTWINDOW
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "comfortable-swipe-gesture-swipe.cpp"
|
||||||
|
|
||||||
|
namespace comfortable_swipe {
|
||||||
|
// enumerations for mouse hold gesture types
|
||||||
|
enum {
|
||||||
|
MOUSE_NONE = -1,
|
||||||
|
MOUSE_MOVE = 0,
|
||||||
|
MOUSE_LEFT_CLICK = 1,
|
||||||
|
MOUSE_MIDDLE_CLICK = 2,
|
||||||
|
MOUSE_RIGHT_CLICK = 3,
|
||||||
|
MOUSE_WHEEL_UP = 4,
|
||||||
|
MOUSE_WHEEL_DOWN = 5,
|
||||||
|
MOUSE_SCROLL = 6,
|
||||||
|
MOUSE_SCROLL_REVERSE = 7
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Gesture Swipe mouse gestures class with xdo.
|
||||||
|
*
|
||||||
|
* If type is MOUSE_*_CLICK, we apply:
|
||||||
|
* - xdo_mouse_down on begin()
|
||||||
|
* - xdo_mouse_up on end()
|
||||||
|
*
|
||||||
|
* If type is MOUSE_MOVE, we apply:
|
||||||
|
* - xdo_mouse_move_relative on update().
|
||||||
|
*
|
||||||
|
* If type is MOUSE_WHEEL* or MOUSE_SCROLL*, we apply:
|
||||||
|
* - xdo_mouse_down on update()
|
||||||
|
* - xdo_mouse_up on update()
|
||||||
|
*/
|
||||||
|
class gesture_swipe_xdomouse : public gesture_swipe {
|
||||||
|
public:
|
||||||
|
// the button number being clicked
|
||||||
|
int button;
|
||||||
|
// constructor
|
||||||
|
gesture_swipe_xdomouse(const char *mouse3, // 3 finger mouse gesture
|
||||||
|
const char *mouse4 // 4 finger mouse gesture
|
||||||
|
);
|
||||||
|
// destructor
|
||||||
|
virtual ~gesture_swipe_xdomouse();
|
||||||
|
// override begin and end for mousedown
|
||||||
|
virtual void begin() override;
|
||||||
|
virtual void update() override;
|
||||||
|
virtual void end() override;
|
||||||
|
// provide our own mouse dispatch functions
|
||||||
|
virtual void do_mousedown(int button, int fingers);
|
||||||
|
virtual void do_mouseup(int button, int fingers);
|
||||||
|
// utility method to parse mouse input given config characters
|
||||||
|
static int parse_mouse_button(const char *);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// command holders
|
||||||
|
const char *mouse3;
|
||||||
|
const char *mouse4;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Constructs a new mouse gesture, given "mouse3" and "mouse4" configurations.
|
||||||
|
*/
|
||||||
|
gesture_swipe_xdomouse::gesture_swipe_xdomouse(const char *mouse3,
|
||||||
|
const char *mouse4)
|
||||||
|
: gesture_swipe(), button(MOUSE_NONE), mouse3(mouse3), mouse4(mouse4) {}
|
||||||
|
/**
|
||||||
|
* Destructs this mouse swipe gesture.
|
||||||
|
*/
|
||||||
|
gesture_swipe_xdomouse::~gesture_swipe_xdomouse() {}
|
||||||
|
/**
|
||||||
|
* Utility method to parse mouse number from input.
|
||||||
|
* Returns MOUSE_NONE on failure.
|
||||||
|
*/
|
||||||
|
int gesture_swipe_xdomouse::parse_mouse_button(const char *input) {
|
||||||
|
// just move without holding button down
|
||||||
|
if (std::strcmp(input, "move") == 0)
|
||||||
|
return MOUSE_MOVE;
|
||||||
|
if (std::strcmp(input, "scroll") == 0)
|
||||||
|
return MOUSE_SCROLL;
|
||||||
|
if (std::strcmp(input, "scroll_reverse") == 0)
|
||||||
|
return MOUSE_SCROLL_REVERSE;
|
||||||
|
// get button number
|
||||||
|
int button;
|
||||||
|
if (std::sscanf(input, "button%d", &button) == 1) {
|
||||||
|
if (1 <= button && button <= 6) {
|
||||||
|
return button;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return MOUSE_NONE;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Run mousedown command on a mouse button input.
|
||||||
|
*/
|
||||||
|
void gesture_swipe_xdomouse::do_mousedown(int button, int fingers) {
|
||||||
|
if (MOUSE_LEFT_CLICK <= button && button <= MOUSE_RIGHT_CLICK) {
|
||||||
|
// send mouse down on associated button
|
||||||
|
xdo_mouse_down(xdo, CURRENTWINDOW, button);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Run mouseup command on a mouse button output.
|
||||||
|
*/
|
||||||
|
void gesture_swipe_xdomouse::do_mouseup(int button, int fingers) {
|
||||||
|
if (MOUSE_LEFT_CLICK <= button && button <= MOUSE_RIGHT_CLICK) {
|
||||||
|
// send mouse up on associated button
|
||||||
|
xdo_mouse_up(xdo, CURRENTWINDOW, button);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Hook on begin of mouse swipe gesture.
|
||||||
|
*/
|
||||||
|
void gesture_swipe_xdomouse::begin() {
|
||||||
|
// call superclass method
|
||||||
|
gesture_swipe::begin();
|
||||||
|
// map fingers to gesture command
|
||||||
|
auto command = fingers == 3 ? mouse3 : (fingers == 4 ? mouse4 : NULL);
|
||||||
|
if (command != NULL) {
|
||||||
|
// get button int from the command
|
||||||
|
button = parse_mouse_button(command);
|
||||||
|
// perform mousedown on the button and print to console
|
||||||
|
if (button != MOUSE_NONE) {
|
||||||
|
do_mousedown(button, fingers);
|
||||||
|
std::printf("MOUSE DOWN mouse%d %s\n", this->fingers, command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Hook on end of mouse swipe gesture.
|
||||||
|
*/
|
||||||
|
void gesture_swipe_xdomouse::update() {
|
||||||
|
// call superclass method
|
||||||
|
gesture_swipe::update();
|
||||||
|
if (button != MOUSE_NONE) {
|
||||||
|
// if MOUSE_MOVE or MOUSE_CLICK*
|
||||||
|
if (0 <= button && button <= 3) {
|
||||||
|
// drag mouse with pointer during update
|
||||||
|
xdo_move_mouse_relative(xdo, udx, udy);
|
||||||
|
} else if (button == MOUSE_SCROLL || button == MOUSE_SCROLL_REVERSE) {
|
||||||
|
// perform naive scroll depending on vertical direction
|
||||||
|
int wheel = MOUSE_WHEEL_DOWN;
|
||||||
|
if ((udy > 0) == (button == MOUSE_SCROLL))
|
||||||
|
wheel = MOUSE_WHEEL_UP;
|
||||||
|
// click wheel on update (note: this is not precise)
|
||||||
|
xdo_mouse_down(xdo, CURRENTWINDOW, wheel);
|
||||||
|
xdo_mouse_up(xdo, CURRENTWINDOW, wheel);
|
||||||
|
} else if (button == MOUSE_WHEEL_UP || button == MOUSE_WHEEL_DOWN) {
|
||||||
|
// click wheel button on 4 or 5
|
||||||
|
xdo_mouse_down(xdo, CURRENTWINDOW, button);
|
||||||
|
xdo_mouse_up(xdo, CURRENTWINDOW, button);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Hook on end of swipe gesture.
|
||||||
|
*/
|
||||||
|
void gesture_swipe_xdomouse::end() {
|
||||||
|
// optimization: only perform mouseup when flag is set
|
||||||
|
if (button != MOUSE_NONE) {
|
||||||
|
// map fingers to gesture command
|
||||||
|
// perform mouseup on the button and print to console
|
||||||
|
do_mouseup(button, fingers);
|
||||||
|
std::printf("MOUSE UP mouse%d %s\n", fingers,
|
||||||
|
fingers == 3 ? mouse3 : mouse4);
|
||||||
|
}
|
||||||
|
// reset button
|
||||||
|
button = MOUSE_NONE;
|
||||||
|
// call superclass method
|
||||||
|
gesture_swipe::end();
|
||||||
|
}
|
||||||
|
} // namespace comfortable_swipe
|
||||||
|
|
||||||
|
#endif /* __comfortable_swipe_gesture_swipe_xdomouse__ */
|
||||||
229
comfortable-swipe-gesture-swipe.cpp
Normal file
229
comfortable-swipe-gesture-swipe.cpp
Normal file
@ -0,0 +1,229 @@
|
|||||||
|
#ifndef __comfortable_swipe_gesture_swipe__
|
||||||
|
#define __comfortable_swipe_gesture_swipe__
|
||||||
|
/**
|
||||||
|
* File: comfortable-swipe-gesture-swipe.cpp
|
||||||
|
*
|
||||||
|
* This is the base class of all comfortable swipe gestures.
|
||||||
|
*
|
||||||
|
* The class `comfortable_swipe::gesture_swipe` handles dispatching
|
||||||
|
* of swipe gestures. The method `gesture_swipe::run(const char*)`
|
||||||
|
* parses a line from libinput debug-events and dispatches a begin(),
|
||||||
|
* update(), or end() function based on a compiled regex pattern.
|
||||||
|
*
|
||||||
|
* We statically compile our swipe gesture regex patterns here.
|
||||||
|
* This is for parsing `libinput debug-events` console output:
|
||||||
|
*
|
||||||
|
* GESTURE_SWIPE_BEGIN - libinput's begin wipe command
|
||||||
|
* GESTURE_SWIPE_UPDATE - libinput's update swipe command
|
||||||
|
* GESTURE_SWIPE_END - libinput's end swipe command
|
||||||
|
*
|
||||||
|
* We dispatch our events based on the regex patterns above, and
|
||||||
|
* extract important information, such as number of fingers, in
|
||||||
|
* an efficient way with Regular Expressions (regex).
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
Comfortable Swipe
|
||||||
|
by Rico Tiongson
|
||||||
|
|
||||||
|
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/>.
|
||||||
|
*/
|
||||||
|
#include <iostream> // std::cout, std::endl
|
||||||
|
#include <regex> // std::regex, std::regex_match, std::cmatch
|
||||||
|
#include <string> // std::stoi, std::stof
|
||||||
|
extern "C" {
|
||||||
|
#include <xdo.h> // xdo, xdo_new, xdo_free,
|
||||||
|
// xdo_get_mouse_location
|
||||||
|
// CURRENT_WINDOW
|
||||||
|
}
|
||||||
|
namespace comfortable_swipe {
|
||||||
|
/**
|
||||||
|
* Handles swipe gesture input from libinput debug-events.
|
||||||
|
* Dispatches keyboard commands on swipe using libxdo.
|
||||||
|
*/
|
||||||
|
class gesture_swipe {
|
||||||
|
public:
|
||||||
|
// constructor
|
||||||
|
gesture_swipe();
|
||||||
|
// destructor
|
||||||
|
virtual ~gesture_swipe();
|
||||||
|
// fields for xdo
|
||||||
|
int fingers;
|
||||||
|
// normal values (for touchpad mapping)
|
||||||
|
float x, y, dx, dy;
|
||||||
|
// unaccelerated values (for screen mapping)
|
||||||
|
float ux, uy, udx, udy;
|
||||||
|
// hooks that we can override (mark as virtual)
|
||||||
|
virtual void begin();
|
||||||
|
virtual void update();
|
||||||
|
virtual void end();
|
||||||
|
virtual bool run(const char *);
|
||||||
|
// public check if currently swiping
|
||||||
|
virtual bool is_swiping() const { return this->flag_swiping; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// xdo container
|
||||||
|
xdo_t *xdo;
|
||||||
|
// location of mouse
|
||||||
|
int screen_num, ix, iy;
|
||||||
|
// optimization flag for checking if GESTURE_SWIPE_BEGIN was dispatched
|
||||||
|
bool flag_swiping;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// defined in: comfortable-swipe-gesture-swipe.regex.cpp
|
||||||
|
static const std::regex GESTURE_SWIPE_BEGIN;
|
||||||
|
static const std::regex GESTURE_SWIPE_UPDATE;
|
||||||
|
static const std::regex GESTURE_SWIPE_END;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Constructs a new fresh swipe gesture container.
|
||||||
|
*/
|
||||||
|
gesture_swipe::gesture_swipe() : xdo(xdo_new(NULL)), flag_swiping(false) {
|
||||||
|
// improve responsiveness of first gesture by pre-empting xdotool
|
||||||
|
xdo_get_mouse_location(this->xdo, &this->ix, &this->iy, &this->screen_num);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Destructs this swipe gesture.
|
||||||
|
*/
|
||||||
|
gesture_swipe::~gesture_swipe() { xdo_free(this->xdo); }
|
||||||
|
/**
|
||||||
|
* Hook on begin of swipe gesture (you can override this).
|
||||||
|
*/
|
||||||
|
void gesture_swipe::begin() {
|
||||||
|
// save current screen location for gestured mouse movement
|
||||||
|
xdo_get_mouse_location(this->xdo, &this->ix, &this->iy, &this->screen_num);
|
||||||
|
this->x = 0;
|
||||||
|
this->y = 0;
|
||||||
|
this->ux = 0;
|
||||||
|
this->uy = 0;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Hook on update of swipe gesture (you can override this).
|
||||||
|
*/
|
||||||
|
void gesture_swipe::update() {
|
||||||
|
this->x += this->dx;
|
||||||
|
this->y += this->dy;
|
||||||
|
this->ux += this->udx;
|
||||||
|
this->uy += this->udy;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Hook on end of swipe gesture (you can override this).
|
||||||
|
*/
|
||||||
|
void gesture_swipe::end() {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Dispatches begin/update/end depending on the regex pattern provided by this
|
||||||
|
* class. Returns true if a gesture begin/update/end was parsed.
|
||||||
|
*
|
||||||
|
* @param line the line from libinput debug-events to parse
|
||||||
|
* @return true if begin/update/end was dispatched
|
||||||
|
*/
|
||||||
|
bool gesture_swipe::run(const char *line) {
|
||||||
|
// prepare holder for regex matches
|
||||||
|
static std::cmatch matches;
|
||||||
|
if (!this->flag_swiping) {
|
||||||
|
// not swiping, check if swipe will begin
|
||||||
|
if (std::regex_match(line, matches, GESTURE_SWIPE_BEGIN) != 0) {
|
||||||
|
// assign necessary variables for swipe begin
|
||||||
|
this->flag_swiping = true;
|
||||||
|
this->fingers = std::stoi(matches[1]);
|
||||||
|
// dispatch begin
|
||||||
|
this->begin();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// currently swiping
|
||||||
|
if (std::regex_match(line, matches, GESTURE_SWIPE_UPDATE) != 0) {
|
||||||
|
// assign necessary variables for swipe update
|
||||||
|
this->fingers = std::stoi(matches[1]);
|
||||||
|
this->dx = std::stof(matches[2]);
|
||||||
|
this->dy = std::stof(matches[3]);
|
||||||
|
this->udx = std::stof(matches[4]);
|
||||||
|
this->udy = std::stof(matches[5]);
|
||||||
|
// dispatch update
|
||||||
|
this->update();
|
||||||
|
return true;
|
||||||
|
} else if (std::regex_match(line, matches, GESTURE_SWIPE_END) != 0) {
|
||||||
|
// assign necessary variables for swipe end
|
||||||
|
this->flag_swiping = false;
|
||||||
|
this->fingers = std::stoi(matches[1]);
|
||||||
|
// dispatch end
|
||||||
|
this->end();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Regex pattern for the libinput entry for start of swipe.
|
||||||
|
* Extracts one match for the number of fingers used during the swipe.
|
||||||
|
*
|
||||||
|
* eg. event15 GESTURE_SWIPE_BEGIN +34.33s 3
|
||||||
|
* ^
|
||||||
|
* fingers
|
||||||
|
*/
|
||||||
|
const std::regex
|
||||||
|
gesture_swipe::GESTURE_SWIPE_BEGIN("^" // start of string
|
||||||
|
"[ -]event\\d+" // event
|
||||||
|
"\\s+GESTURE_SWIPE_BEGIN" // gesture
|
||||||
|
"\\s+\\S+" // timestamp
|
||||||
|
"\\s+(\\d+)" // fingers
|
||||||
|
"\\s*$" // end of string
|
||||||
|
);
|
||||||
|
/**
|
||||||
|
* Regex pattern for the libinput entry for the end of swipe.
|
||||||
|
* Extracts one match for the number of fingers used during the swipe.
|
||||||
|
*
|
||||||
|
* eg. event15 GESTURE_SWIPE_END +35.03s 3
|
||||||
|
* ^
|
||||||
|
* fingers
|
||||||
|
*/
|
||||||
|
const std::regex
|
||||||
|
gesture_swipe::GESTURE_SWIPE_END("^" // start of string
|
||||||
|
"[ -]event\\d+" // event
|
||||||
|
"\\s+GESTURE_SWIPE_END" // gesture
|
||||||
|
"\\s+\\S+" // timestamp
|
||||||
|
"\\s+(\\d+)" // fingers
|
||||||
|
"\\s*$" // end of string
|
||||||
|
);
|
||||||
|
// matches signed decimal numbers (eg. "6.02" "-1.1")
|
||||||
|
#define _NUMBER_REGEX "-?\\d+(?:\\.\\d+)"
|
||||||
|
// matches and extracts a space-prefixed signed fraction (eg. "-3.00/ 5.12")
|
||||||
|
#define _NUMBER_DIVISION "\\s*(" _NUMBER_REGEX ")/\\s*(" _NUMBER_REGEX ")"
|
||||||
|
/**
|
||||||
|
* Regex pattern for the libinput entry for during a swipe.
|
||||||
|
* Extracts number of fingers used and the speed (normal and accelerated) of the
|
||||||
|
* swipe.
|
||||||
|
*
|
||||||
|
* eg. event15 GESTURE_SWIPE_UPDATE \
|
||||||
|
* +34.70s 3 -0.12/ 4.99 (-0.33/13.50 unaccelerated)
|
||||||
|
* ^ ^ ^ ^ ^
|
||||||
|
* fingers dx dy udx udy
|
||||||
|
*/
|
||||||
|
const std::regex gesture_swipe::GESTURE_SWIPE_UPDATE(
|
||||||
|
"^" // start of string
|
||||||
|
"[ -]event\\d+" // event
|
||||||
|
"\\s+GESTURE_SWIPE_UPDATE" // gesture
|
||||||
|
"\\s+\\S+" // timestamp
|
||||||
|
"\\s+(\\d+)" // fingers
|
||||||
|
"\\s+" _NUMBER_DIVISION // speed (dx/dy)
|
||||||
|
"\\s+\\(" _NUMBER_DIVISION
|
||||||
|
"\\s+unaccelerated\\)" // unaccelerated speed (udx/udy)
|
||||||
|
"\\s*$" // end of string
|
||||||
|
);
|
||||||
|
// clean up temporary macros
|
||||||
|
#undef _NUMBER_DIVISION
|
||||||
|
#undef _NUMBER_REGEX
|
||||||
|
} // namespace comfortable_swipe
|
||||||
|
#endif /* __comfortable_swipe_gesture_swipe__ */
|
||||||
137
comfortable-swipe-main.cpp
Normal file
137
comfortable-swipe-main.cpp
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
#ifndef __comfortable_swipe_main__
|
||||||
|
#define __comfortable_swipe_main__
|
||||||
|
/**
|
||||||
|
* The main driver program for `comfortable-swipe-buffer`
|
||||||
|
*
|
||||||
|
* This C++ program parses the output from libinput debug-events
|
||||||
|
* into a buffer and dispatches C++ libxdo commands upon swipe.
|
||||||
|
*
|
||||||
|
* Possible paths of the executable:
|
||||||
|
*
|
||||||
|
* /usr/bin/comfortable-swipe-buffer
|
||||||
|
* /usr/local/bin/comfortable-swipe-buffer
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
Comfortable Swipe
|
||||||
|
by Rico Tiongson
|
||||||
|
|
||||||
|
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/>.
|
||||||
|
*/
|
||||||
|
#include "comfortable-swipe-defines.cpp"
|
||||||
|
#include "comfortable-swipe-gesture-swipe-xdokey.cpp"
|
||||||
|
#include "comfortable-swipe-gesture-swipe-xdomouse.cpp"
|
||||||
|
#include "comfortable-swipe-gesture-swipe.cpp"
|
||||||
|
#include <iostream> // std::ios, std::cin, std::getline
|
||||||
|
#include <map> // std::map
|
||||||
|
#include <set> // std::set
|
||||||
|
#include <string> // std::string
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include <ini.h> // ini_parse
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers keys and values from the config file to a map.
|
||||||
|
*/
|
||||||
|
int parse_config(void *config, const char section[], const char name[],
|
||||||
|
const char value[]) {
|
||||||
|
auto &configmap = *(std::map<std::string, std::string> *)config;
|
||||||
|
configmap[name] = value;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The main driver program.
|
||||||
|
*/
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
using namespace std;
|
||||||
|
using namespace comfortable_swipe;
|
||||||
|
// unsync stdio for faster IO
|
||||||
|
ios::sync_with_stdio(false);
|
||||||
|
cin.tie(0);
|
||||||
|
cout.tie(0);
|
||||||
|
// parse configuration file
|
||||||
|
map<string, string> config;
|
||||||
|
if (ini_parse(COMFORTABLE_SWIPE_CONFIG, parse_config, &config) < 0) {
|
||||||
|
cerr << "error: config " << COMFORTABLE_SWIPE_CONFIG << endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
// clear config and just use "threshold" if --bare
|
||||||
|
if (set<string>(argv + 1, argv + argc).count("--bare")) {
|
||||||
|
if (config.count("threshold")) {
|
||||||
|
auto threshold = config["threshold"];
|
||||||
|
config.clear();
|
||||||
|
config["threshold"] = threshold;
|
||||||
|
} else {
|
||||||
|
config.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// initialize keyboard swipe gesture handler
|
||||||
|
// commands are: [left|up|right|down][3|4]
|
||||||
|
// we will fetch our commands from the config in correct order
|
||||||
|
// Examples:
|
||||||
|
// left3=ctrl+alt+Right shift to right workspace
|
||||||
|
// right3=ctrl+alt+Left shift to left workspace
|
||||||
|
// up3=super+Up maximize
|
||||||
|
// down3=super+Down minimize
|
||||||
|
decltype(gesture_swipe_xdokey::commands) commands;
|
||||||
|
for (size_t i = 0; i < commands.size(); ++i)
|
||||||
|
commands[i] = config[gesture_swipe_xdokey::command_name[i]];
|
||||||
|
// correctly parse threshold as float
|
||||||
|
float threshold = 0.0f;
|
||||||
|
try {
|
||||||
|
threshold = stof(config["threshold"]);
|
||||||
|
} catch (...) {
|
||||||
|
}
|
||||||
|
// create swipe handler
|
||||||
|
gesture_swipe_xdokey keyswipe(commands, threshold);
|
||||||
|
// initialize mouse hold gesture handler
|
||||||
|
// for now, this supports 3-finger and 4-finger hold
|
||||||
|
// Examples:
|
||||||
|
// mouse3=move move mouse on 3 fingers
|
||||||
|
// mouse3=button1 hold button 1 on 3 fingers
|
||||||
|
// mouse4=button3 hold button 3 (right click) on 3 fingers
|
||||||
|
// warn user that hold3 is deprecated
|
||||||
|
if (config.count("hold3"))
|
||||||
|
std::cerr << "WARNING: hold3 is deprecated. Use mouse3 instead."
|
||||||
|
<< std::endl;
|
||||||
|
if (config.count("hold4"))
|
||||||
|
std::cerr << "WARNING: hold4 is deprecated. Use mouse4 instead."
|
||||||
|
<< std::endl;
|
||||||
|
// get input values
|
||||||
|
string mouse3 = config.count("mouse3") ? config["mouse3"] : config["hold3"];
|
||||||
|
string mouse4 = config.count("mouse4") ? config["mouse4"] : config["hold4"];
|
||||||
|
bool nomouse = mouse3.empty() || mouse4.empty(); // TODO: check if mouse invalid
|
||||||
|
// create our mouse gesture holder
|
||||||
|
gesture_swipe_xdomouse mousehold(mouse3.data(), mouse4.data());
|
||||||
|
// start reading lines from input one by one
|
||||||
|
for (string line; getline(cin, line);) {
|
||||||
|
if (nomouse) {
|
||||||
|
keyswipe.run(line.data());
|
||||||
|
} else {
|
||||||
|
// optimization: if no mouse config is set, just run keyboard
|
||||||
|
if (mousehold.is_swiping() && mousehold.button == MOUSE_NONE) {
|
||||||
|
keyswipe.run(line.data());
|
||||||
|
} else if (mousehold.run(line.data())) {
|
||||||
|
// only allow keyswipe gestures on mouse move
|
||||||
|
if (mousehold.button == MOUSE_NONE || mousehold.button == MOUSE_MOVE) {
|
||||||
|
keyswipe.run(line.data());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -1,72 +0,0 @@
|
|||||||
/*
|
|
||||||
Comfortable Swipe
|
|
||||||
by Rico Tiongson
|
|
||||||
|
|
||||||
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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <ios> // std::ios
|
|
||||||
#include <iostream> // std::cin, std::cout, std::cerr
|
|
||||||
#include <string> // std::string
|
|
||||||
#include "src/comfortable_swipe.h" // comfortable_swipe
|
|
||||||
|
|
||||||
// make sure implementation is also imported
|
|
||||||
#ifndef __COMFORTABLE_SWIPE__
|
|
||||||
#include "src/comfortable_swipe.cpp"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Command-line function. */
|
|
||||||
|
|
||||||
int main(int argc, char **args) {
|
|
||||||
// improve buffering by decoupling loggers from stdio
|
|
||||||
std::ios::sync_with_stdio(false);
|
|
||||||
std::cin.tie(0);
|
|
||||||
std::cout.tie(0);
|
|
||||||
std::cerr.tie(0);
|
|
||||||
|
|
||||||
if (argc > 1) {
|
|
||||||
std::string arg = args[1];
|
|
||||||
|
|
||||||
// select based on argument
|
|
||||||
if (arg == "start")
|
|
||||||
comfortable_swipe::service::start();
|
|
||||||
|
|
||||||
else if (arg == "stop")
|
|
||||||
comfortable_swipe::service::stop();
|
|
||||||
|
|
||||||
else if (arg == "restart")
|
|
||||||
comfortable_swipe::service::restart();
|
|
||||||
|
|
||||||
else if (arg == "buffer")
|
|
||||||
comfortable_swipe::service::buffer();
|
|
||||||
|
|
||||||
else if (arg == "autostart")
|
|
||||||
comfortable_swipe::service::autostart();
|
|
||||||
|
|
||||||
else if (arg == "config")
|
|
||||||
comfortable_swipe::service::config();
|
|
||||||
|
|
||||||
else if (arg == "debug")
|
|
||||||
comfortable_swipe::service::debug();
|
|
||||||
|
|
||||||
else if (arg == "status")
|
|
||||||
comfortable_swipe::service::status();
|
|
||||||
|
|
||||||
else /* if (arg == "help") */
|
|
||||||
comfortable_swipe::service::help();
|
|
||||||
} else
|
|
||||||
comfortable_swipe::service::help();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
12
compile
Executable file
12
compile
Executable file
@ -0,0 +1,12 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# usage: ./compile *.cpp
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
DIR="$(dirname $0)"
|
||||||
|
VERSION="$(cat "$DIR/VERSION" | tr -d '[:space:]')"
|
||||||
|
|
||||||
|
CXX='g++'
|
||||||
|
CXX_FLAGS='-std=c++14 -O2 -Wall -lxdo -linih -lxdo -linih'
|
||||||
|
|
||||||
|
g++ "$@" ${CXX_FLAGS} -DCOMFORTABLE_SWIPE_VERSION="\"$VERSION\""
|
||||||
42
config/comfortable-swipe.conf
Normal file
42
config/comfortable-swipe.conf
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
# Comfortable Swipe
|
||||||
|
#
|
||||||
|
# Feel free to edit this configuration file if you have different
|
||||||
|
# keyboard shortcuts that you would like to use. Comments starting
|
||||||
|
# with a pound (#) or semi-colon (;) are ignored.
|
||||||
|
#
|
||||||
|
# Refer to https://www.linux.org/threads/xdotool-keyboard.10528/ for
|
||||||
|
# a list of keycodes you can use.
|
||||||
|
|
||||||
|
left3 = ctrl+alt+Right
|
||||||
|
left4 = ctrl+alt+shift+Right
|
||||||
|
right3 = ctrl+alt+Left
|
||||||
|
right4 = ctrl+alt+shift+Left
|
||||||
|
up3 = ctrl+alt+Down
|
||||||
|
up4 = ctrl+alt+shift+Down
|
||||||
|
down3 = ctrl+alt+Up
|
||||||
|
down4 = ctrl+alt+shift+Up
|
||||||
|
|
||||||
|
# Tweak threshold depending on the sensitivity of your touchpad.
|
||||||
|
# Make this higher to lessen sensitivity.
|
||||||
|
# (note: values have no limit, can be as large as 1000.0)
|
||||||
|
threshold = 0.0
|
||||||
|
|
||||||
|
# Uncomment below to enable mouse gestures (3 fingers)
|
||||||
|
; mouse3 = button1 # drag left click
|
||||||
|
; mouse3 = button2 # drag middle click
|
||||||
|
; mouse3 = button3 # drag right click
|
||||||
|
; mouse3 = button4 # drag wheel up
|
||||||
|
; mouse3 = button5 # drag wheel down
|
||||||
|
; mouse3 = move # just move mouse along with the cursor
|
||||||
|
; mouse3 = scroll # natural scroll (experimental)
|
||||||
|
; mouse3 = scroll_reverse # reverse scroll (experimental)
|
||||||
|
|
||||||
|
# Uncomment below to enable mouse gestures (4 fingers)
|
||||||
|
; mouse4 = button1 # drag left click
|
||||||
|
; mouse4 = button2 # drag middle click
|
||||||
|
; mouse4 = button3 # drag right click
|
||||||
|
; mouse4 = button4 # drag wheel up
|
||||||
|
; mouse4 = button5 # drag wheel down
|
||||||
|
; mouse4 = move # just move mouse along with the cursor
|
||||||
|
; mouse4 = scroll # natural scroll (experimental)
|
||||||
|
; mouse4 = scroll_reverse # reverse scroll (experimental)
|
||||||
@ -1,8 +1,8 @@
|
|||||||
[Desktop Entry]
|
[Desktop Entry]
|
||||||
Type=Application
|
Type=Application
|
||||||
Name=Comfortable Swipe
|
|
||||||
Comment=Comfortable 3/4-finger swipe gestures
|
|
||||||
Exec=comfortable-swipe start
|
Exec=comfortable-swipe start
|
||||||
|
Name=Comfortable Swipe
|
||||||
|
Comment=Comfortable 3/4-finger touchpad gestures
|
||||||
Hidden=false
|
Hidden=false
|
||||||
NoDisplay=false
|
NoDisplay=false
|
||||||
X-GNOME-Autostart-enabled=true
|
X-GNOME-Autostart-enabled=true
|
||||||
@ -1,9 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
dir="$(dirname $0)"
|
|
||||||
version="$(cat "$dir/VERSION" | tr -d '[:space:]')"
|
|
||||||
|
|
||||||
exec g++ $@ \
|
|
||||||
-std=c++11 \
|
|
||||||
-O2 -lxdo -Wno-unused-result \
|
|
||||||
-DCOMFORTABLE_SWIPE_VERSION="\"$version\""
|
|
||||||
269
install
269
install
@ -2,95 +2,200 @@
|
|||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
function install {
|
if [[ "$USER" == root ]]; then
|
||||||
# prefer running as root
|
echo "Please run 'bash install' as non-root user" 2>&1
|
||||||
local dir="$(dirname "$0")"
|
exit 1
|
||||||
local program="comfortable-swipe"
|
fi
|
||||||
local program_exe="/usr/local/bin/$program"
|
|
||||||
local compile_command="$dir/cpp.compile.sh"
|
|
||||||
local compile_target="$dir/comfortable-swipe.cpp"
|
|
||||||
local conf_path="/usr/local/share/$program/$program.conf"
|
|
||||||
local dconf_path="$dir/defaults.conf"
|
|
||||||
local old_conf_path="${XDG_CONFIG_HOME:-$HOME/.config}/$program.conf"
|
|
||||||
|
|
||||||
if [ -x "$(command -v "$program_exe")" ]; then
|
DIR="$(dirname "$0")"
|
||||||
# stop any running $program if it exists
|
VERSION="$(cat $DIR/VERSION | tr -d '[:space:]')"
|
||||||
"$program_exe" stop > /dev/null
|
|
||||||
fi
|
|
||||||
|
|
||||||
#copy config file
|
# target executable
|
||||||
abort () {
|
SOURCE="$DIR/comfortable-swipe"
|
||||||
exec echo "Installation aborted"
|
TARGET="/usr/local/bin/comfortable-swipe"
|
||||||
}
|
|
||||||
sudo mkdir -p "$(dirname $conf_path)" || abort
|
|
||||||
|
|
||||||
# check if "-y" or "--yes" is passed as an argument
|
# compile targets
|
||||||
YES=false
|
COMPILE="$DIR/compile"
|
||||||
while test $# -gt 0
|
COMPILE_SOURCE="$DIR/comfortable-swipe-main.cpp"
|
||||||
do
|
COMPILE_TARGET="/usr/local/bin/comfortable-swipe-buffer"
|
||||||
case "$1" in
|
|
||||||
-y) YES=true
|
|
||||||
;;
|
|
||||||
--yes) YES=true
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
shift
|
|
||||||
done
|
|
||||||
|
|
||||||
sudo chown $USER "$(dirname $conf_path)"
|
# configurations
|
||||||
if [ ! -f "$conf_path" ]; then
|
CONF_SOURCE="$DIR/config/comfortable-swipe.conf"
|
||||||
if [ ! -f "$old_conf_path" ]; then
|
CONF_TARGET="$HOME/.config/comfortable-swipe.conf"
|
||||||
# old config file not found, create from scratch
|
OLD_CONF_TARGET="/usr/local/share/comfortable-swipe/comfortable-swipe.conf"
|
||||||
cat "$dconf_path" > "$conf_path" || abort
|
|
||||||
else
|
|
||||||
# old config file found, move to the new path
|
|
||||||
cat "$old_conf_path" > "$conf_path" || abort
|
|
||||||
echo "Configuration copied from $old_conf_path to $conf_path"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
# config file found, ask user if overwrite
|
|
||||||
echo "Old conf file found in $conf_path"
|
|
||||||
if [ "$YES" == false ]; then
|
|
||||||
read -r -p "Keep the old conf file? (default: yes) [Y/n] " response
|
|
||||||
response="${response,,}" # tolower
|
|
||||||
if [[ "$response" =~ ^(no|n)$ ]]; then
|
|
||||||
read -r -p "Conf file will be overwritten. Are you sure? [Y/n] " response
|
|
||||||
response="${response,,}"
|
|
||||||
if [[ "$response" =~ ^(yes|y)$ ]]; then
|
|
||||||
cat "$dconf_path" > "$conf_path" || abort
|
|
||||||
else
|
|
||||||
abort
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Installing to $program_exe ..."
|
# autostart
|
||||||
|
AUTOSTART_SOURCE="$DIR/config/comfortable-swipe.desktop"
|
||||||
|
AUTOSTART_TARGET="$HOME/.config/autostart/comfortable-swipe.desktop"
|
||||||
|
|
||||||
# remove existing $program
|
# stop any running comfortable-swipe if it exists
|
||||||
if [ -x "$(command -v "$program_exe")" ]; then
|
comfortable-swipe stop > /dev/null 2>&1 || true
|
||||||
sudo rm -f "$(which "$program")"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# compile library
|
|
||||||
sudo "$compile_command" "$compile_target" -o "$program_exe" || abort
|
|
||||||
|
|
||||||
# add permissions to input group (defer)
|
# shorthand to abort the installation
|
||||||
# GROUP=$(ls -l /dev/input/event* | awk '{print $4}' | head --line=1) || abort
|
function abort {
|
||||||
|
echo "Installation aborted" >&2
|
||||||
# turn on autostart by default
|
exit 1
|
||||||
local autostart_status="$("$program_exe" autostart)"
|
|
||||||
if [[ "$autostart_status" == *off* ]]; then
|
|
||||||
autostart_status="$("$program_exe" autostart)"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Successfully installed $program $(cat $dir/VERSION | tr -d '[:space:]')"
|
|
||||||
echo ""
|
|
||||||
echo "$autostart_status"
|
|
||||||
echo "Edit configuration file: gedit \$($program config)"
|
|
||||||
echo ""
|
|
||||||
echo "Try running: $program start"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
install
|
# shorthand to try a command with sudo if it fails
|
||||||
unset -f install
|
function trysudo {
|
||||||
|
$@ 2> /dev/null || sudo $@
|
||||||
|
}
|
||||||
|
|
||||||
|
# uninstall existing program
|
||||||
|
function uninstall_existing {
|
||||||
|
local PROGRAM="${1:?missing program name}"
|
||||||
|
# remove existing comfortable-swipe
|
||||||
|
if [[ -x "$(command -v "$PROGRAM")" ]]; then
|
||||||
|
echo -n "Removing previous $(which "$PROGRAM") ... "
|
||||||
|
trysudo rm -f "$(which "$PROGRAM")"
|
||||||
|
echo "ok"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
## CONFIGURATION FILE LOADING
|
||||||
|
# This section handles installation of configuration file.
|
||||||
|
# We determine first if any old configuration files exists.
|
||||||
|
# make sure config directory exists
|
||||||
|
function install_configuration_file {
|
||||||
|
mkdir -p "$(dirname "$CONF_TARGET")"
|
||||||
|
|
||||||
|
# check if configuration already exists
|
||||||
|
if [[ -f "$CONF_TARGET" ]]; then
|
||||||
|
# ask user if we overwrite configuration
|
||||||
|
echo "Old conf file found in $CONF_TARGET" >&2
|
||||||
|
read -r -p "Keep the old conf file? (default: yes) [Y/n] " response >&2
|
||||||
|
|
||||||
|
# If response is empty, consider it as 'yes' (default)
|
||||||
|
if [[ -z "$response" ]]; then
|
||||||
|
response="y"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "${response,,}" =~ ^(no|n)$ ]]; then
|
||||||
|
# MAKE SURE they really want to overwrite
|
||||||
|
read -r -p "Conf file will be overwritten! Are you sure? [Y/n] " response >&2
|
||||||
|
if [[ -z "$response" ]]; then
|
||||||
|
response="y"
|
||||||
|
fi
|
||||||
|
if [[ "${response,,}" =~ ^(no|n)$ ]]; then
|
||||||
|
abort
|
||||||
|
else
|
||||||
|
# They agreed... replace configuration
|
||||||
|
cat "$CONF_SOURCE" > "$CONF_TARGET"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# target does not exist yet
|
||||||
|
# try copying from older configurations
|
||||||
|
if [[ -f "$OLD_CONF_TARGET" ]]; then
|
||||||
|
# move configuration from an older version (< v1.2)
|
||||||
|
echo "Moving configuration from $OLD_CONF_TARGET to $CONF_TARGET ..."
|
||||||
|
mv "$OLD_CONF_TARGET" "$CONF_TARGET"
|
||||||
|
# clean up old directory if possible
|
||||||
|
rmdir "$(dirname "$OLD_CONF_TARGET")" > /dev/null 2>&1 || true
|
||||||
|
else
|
||||||
|
# fresh installation! just copy default configuration
|
||||||
|
cat "$CONF_SOURCE" > "$CONF_TARGET"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Installed: $CONF_TARGET"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
## Installation of main program
|
||||||
|
#
|
||||||
|
# /usr/local/bin/comfortable-swipe
|
||||||
|
#
|
||||||
|
function install_main_program {
|
||||||
|
# copy source to target with executable permissions
|
||||||
|
# install to target, with hardcoded version
|
||||||
|
if [[ -f "$TARGET" ]]; then
|
||||||
|
trysudo rm "$TARGET"
|
||||||
|
fi
|
||||||
|
trysudo cp "$SOURCE" "$TARGET"
|
||||||
|
trysudo sed -E "s/^VERSION=.*/VERSION=$VERSION/" -i "$TARGET"
|
||||||
|
# allow execute permissions with group
|
||||||
|
trysudo chmod +x "$TARGET"
|
||||||
|
# make sure non-root user is owner
|
||||||
|
trysudo chown "$USER" "$TARGET"
|
||||||
|
echo "Installed: $TARGET"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Compilation and installation of C++ buffer program:
|
||||||
|
#
|
||||||
|
# /usr/local/bin/comfortable-swipe-buffer
|
||||||
|
#
|
||||||
|
function install_cpp_program {
|
||||||
|
# compile program to temporary file first
|
||||||
|
TMP_TARGET="$(mktemp)"
|
||||||
|
$COMPILE "$COMPILE_SOURCE" -o "$TMP_TARGET" -DCOMFORTABLE_SWIPE_VERSION="\"$VERSION\"" -DCOMFORTABLE_SWIPE_CONFIG="\"$CONF_TARGET\"" -DCOMFORTABLE_SWIPE_AUTOSTART="\"$AUTOSTART_TARGET\""
|
||||||
|
# compilation ok, now try to install with sudo
|
||||||
|
trysudo mkdir -p "$(dirname "$COMPILE_TARGET")"
|
||||||
|
# remove existing file for permissions to work
|
||||||
|
if [[ -f "$COMPILE_TARGET" ]]; then
|
||||||
|
sudo rm "$COMPILE_TARGET"
|
||||||
|
fi
|
||||||
|
trysudo mv "$TMP_TARGET" "$COMPILE_TARGET"
|
||||||
|
# bugfix: add with group permissions
|
||||||
|
trysudo chmod go+x "$COMPILE_TARGET"
|
||||||
|
# make sure non-root user is owner
|
||||||
|
trysudo chown "$USER" "$COMPILE_TARGET"
|
||||||
|
echo "Installed: $COMPILE_TARGET"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Installation of Autostart Desktop file
|
||||||
|
#
|
||||||
|
# /home/$USER/.config/autostart/comfortable-swipe.desktop
|
||||||
|
#
|
||||||
|
function install_autostart {
|
||||||
|
mkdir -p "$(dirname "$AUTOSTART_TARGET")"
|
||||||
|
cat "$AUTOSTART_SOURCE" > "$AUTOSTART_TARGET"
|
||||||
|
echo "Installed: $AUTOSTART_TARGET"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# install configuration files first but defer output later
|
||||||
|
# this is to ensure that the prompt runs first in the script
|
||||||
|
INSTALL_CONF_OUTPUT="$(install_configuration_file)"
|
||||||
|
|
||||||
|
# uninstall existing commands
|
||||||
|
uninstall_existing comfortable-swipe
|
||||||
|
uninstall_existing comfortable-swipe-buffer
|
||||||
|
|
||||||
|
# install new binaries
|
||||||
|
echo "Installing binaries ..."
|
||||||
|
install_cpp_program
|
||||||
|
install_main_program
|
||||||
|
echo "$INSTALL_CONF_OUTPUT"
|
||||||
|
install_autostart
|
||||||
|
|
||||||
|
# add permissions to input group (defer)
|
||||||
|
# GROUP=$(ls -l /dev/input/event* | awk '{print $4}' | head --line=1) || abort
|
||||||
|
|
||||||
|
# make sure comfortable-swipe is in path
|
||||||
|
if ! command -v comfortable-swipe > /dev/null 2>&1; then
|
||||||
|
cat <<EOF >&2
|
||||||
|
WARNING: $(dirname "$TARGET") is not in PATH!
|
||||||
|
Make sure to add the following in your ~/.profile:
|
||||||
|
|
||||||
|
export PATH="$PATH:$(dirname "$TARGET")"
|
||||||
|
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
|
||||||
|
cat <<EOF
|
||||||
|
|
||||||
|
Successfully installed comfortable-swipe $VERSION
|
||||||
|
Autostart switched $("$TARGET" autostart status)
|
||||||
|
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# start the program
|
||||||
|
"$TARGET" start
|
||||||
|
|||||||
@ -1,80 +0,0 @@
|
|||||||
# Comfortable Swipe converts touchpad swipe gestures to keyboard commands. You
|
|
||||||
# may edit this configuration file if you have different keyboard shortcuts
|
|
||||||
# that you would like to use. You can ignore a gesture by commenting out with
|
|
||||||
# a pound(#) symbol.
|
|
||||||
#
|
|
||||||
# Refer to https://www.linux.org/threads/xdotool-keyboard.10528/ for a list of
|
|
||||||
# keycodes you can use.
|
|
||||||
|
|
||||||
#############################
|
|
||||||
# THREE / FOUR FINGER SWIPE #
|
|
||||||
#############################
|
|
||||||
|
|
||||||
# 3-finger swipe left
|
|
||||||
# The default shortcut is switching to the right workspace.
|
|
||||||
# Default: left3 = ctrl+alt+Right
|
|
||||||
left3 = ctrl+alt+Right
|
|
||||||
|
|
||||||
# 4-finger swipe left
|
|
||||||
# The default shortcut is moving current window to the right workspace.
|
|
||||||
# Default: left4=ctrl+alt+shift+Right
|
|
||||||
left4 = ctrl+alt+shift+Right
|
|
||||||
|
|
||||||
# 3-finger swipe right
|
|
||||||
# The default shortcut is switching to the left workspace.
|
|
||||||
# Default: right3 = ctrl+alt+Left
|
|
||||||
right3 = ctrl+alt+Left
|
|
||||||
|
|
||||||
# 4-finger swipe right
|
|
||||||
# The default shortcut is moving current window to the left workspace.
|
|
||||||
# Default: right4=ctrl+alt+shift+Left
|
|
||||||
right4 = ctrl+alt+shift+Left
|
|
||||||
|
|
||||||
# 3-finger swipe up
|
|
||||||
# The default shortcut is switching to the workspace below.
|
|
||||||
# Default: up3 = ctrl+alt+Down
|
|
||||||
up3 = ctrl+alt+Down
|
|
||||||
|
|
||||||
# 4-finger swipe up
|
|
||||||
# The default shortcut is moving current window to the bottom workspace.
|
|
||||||
# Default: ctrl+alt+shift+Down
|
|
||||||
up4 = ctrl+alt+shift+Down
|
|
||||||
|
|
||||||
# 3-finger swipe down
|
|
||||||
# The default shortcut is switching to the workspace above.
|
|
||||||
# Default: down3 = ctrl+alt+Up
|
|
||||||
down3 = ctrl+alt+Up
|
|
||||||
|
|
||||||
# 4-finger swipe down
|
|
||||||
# The default shortcut is moving current window to the above workspace.
|
|
||||||
# Default: ctrl+alt+shift+Up
|
|
||||||
down4 = ctrl+alt+shift+Up
|
|
||||||
|
|
||||||
#################
|
|
||||||
# MISCELLANEOUS #
|
|
||||||
#################
|
|
||||||
|
|
||||||
# Threshold
|
|
||||||
# Tweak this value depending on the sensitivity of your mousepad to perform
|
|
||||||
# gestures. A higher value means less sensitive (Sky is the limit! Can be as
|
|
||||||
# large as 1000.0).
|
|
||||||
# Default: threshold = 0.0
|
|
||||||
threshold = 0.0
|
|
||||||
|
|
||||||
#############################
|
|
||||||
# Experimental: MOUSE HOLD #
|
|
||||||
#############################
|
|
||||||
|
|
||||||
# (1: left click, 2: middle click, 3: right click, 4: wheel up, 5: wheel down)
|
|
||||||
|
|
||||||
# You can set mouse buttons to hold
|
|
||||||
# hold3 = button1
|
|
||||||
# hold3 = button2
|
|
||||||
# hold3 = button3
|
|
||||||
|
|
||||||
# Or you can just let the mouse move with the cursor
|
|
||||||
# hold3 = move
|
|
||||||
|
|
||||||
# Use wheel scroll (experimental)
|
|
||||||
# hold4 = scroll
|
|
||||||
# hold4 = scroll_reverse
|
|
||||||
@ -1,47 +0,0 @@
|
|||||||
/**
|
|
||||||
* Add all cpp implementation files are registered here.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __COMFORTABLE_SWIPE__
|
|
||||||
#define __COMFORTABLE_SWIPE__
|
|
||||||
|
|
||||||
/*
|
|
||||||
Comfortable Swipe
|
|
||||||
by Rico Tiongson
|
|
||||||
|
|
||||||
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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "comfortable_swipe.h"
|
|
||||||
#include "start.cpp"
|
|
||||||
|
|
||||||
#include "gesture/keyboard_swipe_gesture.cpp"
|
|
||||||
#include "gesture/mouse_hold_gesture.cpp"
|
|
||||||
#include "gesture/swipe_gesture.cpp"
|
|
||||||
#include "gesture/swipe_gesture.regex.cpp"
|
|
||||||
#include "gesture/xdo_gesture.cpp"
|
|
||||||
#include "service/autostart.cpp"
|
|
||||||
#include "service/buffer.cpp"
|
|
||||||
#include "service/config.cpp"
|
|
||||||
#include "service/debug.cpp"
|
|
||||||
#include "service/help.cpp"
|
|
||||||
#include "service/restart.cpp"
|
|
||||||
#include "service/start.cpp"
|
|
||||||
#include "service/status.cpp"
|
|
||||||
#include "service/stop.cpp"
|
|
||||||
#include "util/autostart_filename.cpp"
|
|
||||||
#include "util/conf_filename.cpp"
|
|
||||||
#include "util/read_config_file.cpp"
|
|
||||||
|
|
||||||
#endif /* __COMFORTABLE_SWIPE__ */
|
|
||||||
@ -1,77 +0,0 @@
|
|||||||
/**
|
|
||||||
* Add header files will be imported here.
|
|
||||||
* You can import this as a shorthand:
|
|
||||||
*
|
|
||||||
* #include "comfortable_swipe.h"
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __COMFORTABLE_SWIPE__comfortable_swipe_h__
|
|
||||||
#define __COMFORTABLE_SWIPE__comfortable_swipe_h__
|
|
||||||
|
|
||||||
/*
|
|
||||||
Comfortable Swipe
|
|
||||||
by Rico Tiongson
|
|
||||||
|
|
||||||
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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// global defines
|
|
||||||
#ifndef COMFORTABLE_SWIPE_PROGRAM
|
|
||||||
#define COMFORTABLE_SWIPE_PROGRAM "/usr/local/bin/comfortable-swipe"
|
|
||||||
#endif /* COMFORTABLE_SWIPE_PROGRAM */
|
|
||||||
|
|
||||||
#ifndef COMFORTABLE_SWIPE_CONFIG
|
|
||||||
#define COMFORTABLE_SWIPE_CONFIG \
|
|
||||||
"/usr/local/share/comfortable-swipe/comfortable-swipe.conf"
|
|
||||||
#endif /* COMFORTABLE_SWIPE_CONFIG */
|
|
||||||
|
|
||||||
#ifndef COMFORTABLE_SWIPE_VERSION
|
|
||||||
#warning COMFORTABLE_SWIPE_VERSION is not defined
|
|
||||||
#define COMFORTABLE_SWIPE_VERSION "v(UNKNOWN)"
|
|
||||||
#endif /* COMFORTABLE_SWIPE_VERSION */
|
|
||||||
|
|
||||||
#include <map> // std::map
|
|
||||||
#include <string> // std::string
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
namespace comfortable_swipe {
|
|
||||||
// this is found in the util/ folder
|
|
||||||
namespace util {
|
|
||||||
const char *autostart_filename();
|
|
||||||
constexpr const char *conf_filename();
|
|
||||||
std::map<std::string, std::string> read_config_file(const char *);
|
|
||||||
} // namespace util
|
|
||||||
// this is found in the service/ folder
|
|
||||||
namespace service {
|
|
||||||
void autostart();
|
|
||||||
void buffer();
|
|
||||||
void config();
|
|
||||||
void debug();
|
|
||||||
void help();
|
|
||||||
void restart();
|
|
||||||
void start();
|
|
||||||
void status();
|
|
||||||
void stop();
|
|
||||||
} // namespace service
|
|
||||||
} // namespace comfortable_swipe
|
|
||||||
}
|
|
||||||
|
|
||||||
// add headers for classes here so it can be imported during include
|
|
||||||
#include "gesture/keyboard_swipe_gesture.h"
|
|
||||||
#include "gesture/mouse_hold_gesture.h"
|
|
||||||
#include "gesture/swipe_gesture.h"
|
|
||||||
#include "gesture/xdo_gesture.h"
|
|
||||||
#include "start.h"
|
|
||||||
|
|
||||||
#endif /* __COMFORTABLE_SWIPE__comfortable_swipe_h__ */
|
|
||||||
@ -1,168 +0,0 @@
|
|||||||
#ifndef __COMFORTABLE_SWIPE__gesture_keyboard_swipe_gesture__
|
|
||||||
#define __COMFORTABLE_SWIPE__gesture_keyboard_swipe_gesture__
|
|
||||||
|
|
||||||
/*
|
|
||||||
Comfortable Swipe
|
|
||||||
by Rico Tiongson
|
|
||||||
|
|
||||||
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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "keyboard_swipe_gesture.h"
|
|
||||||
#include <iostream> // std::cout, std::endl
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#include <xdo.h> // xdo, xdo_new, xdo_free,
|
|
||||||
// xdo_get_mouse_location
|
|
||||||
// CURRENT_WINDOW
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace comfortable_swipe::gesture {
|
|
||||||
|
|
||||||
/* STATICS DEFINITIONS */
|
|
||||||
const int keyboard_swipe_gesture::MSK_THREE_FINGERS = 0;
|
|
||||||
const int keyboard_swipe_gesture::MSK_FOUR_FINGERS = 1;
|
|
||||||
const int keyboard_swipe_gesture::MSK_NEGATIVE = 0;
|
|
||||||
const int keyboard_swipe_gesture::MSK_POSITIVE = 2;
|
|
||||||
const int keyboard_swipe_gesture::MSK_HORIZONTAL = 0;
|
|
||||||
const int keyboard_swipe_gesture::MSK_VERTICAL = 4;
|
|
||||||
const int keyboard_swipe_gesture::FRESH = -1;
|
|
||||||
const char *const keyboard_swipe_gesture::command_map[8] = {
|
|
||||||
"left3", "left4", "right3", "right4", "up3", "up4", "down3", "down4"};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a new keyboard-based swipe gesture, given configurations
|
|
||||||
* for certain swipe events. Here, we construct our definition based on
|
|
||||||
* the four directions (left, up, right, down) for 3-finger and 4-finger
|
|
||||||
* swipes. Note that the direction is based on the Australian natural
|
|
||||||
* scrolling direction (ie. left3 is natural movement of 3 fingers left).
|
|
||||||
*/
|
|
||||||
keyboard_swipe_gesture::keyboard_swipe_gesture(
|
|
||||||
const float threshold, const char *left3 /* 000 */,
|
|
||||||
const char *left4 /* 001 */, const char *right3 /* 010 */,
|
|
||||||
const char *right4 /* 011 */, const char *up3 /* 100 */,
|
|
||||||
const char *up4 /* 101 */, const char *down3 /* 110 */,
|
|
||||||
const char *down4 /* 111 */
|
|
||||||
)
|
|
||||||
: // construct superclass
|
|
||||||
comfortable_swipe::gesture::swipe_gesture(),
|
|
||||||
// compute square of threshold because we will use squared distances
|
|
||||||
threshold_squared(threshold * threshold),
|
|
||||||
// register our commands
|
|
||||||
commands(new const char *[8] {
|
|
||||||
left3, left4, right3, right4, up3, up4, down3, down4
|
|
||||||
}) {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destructs this keyboard swipe gesture.
|
|
||||||
*/
|
|
||||||
keyboard_swipe_gesture::~keyboard_swipe_gesture() { delete[] commands; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hook on begin of swipe gesture.
|
|
||||||
*/
|
|
||||||
void keyboard_swipe_gesture::begin() {
|
|
||||||
// call superclass method
|
|
||||||
swipe_gesture::begin();
|
|
||||||
|
|
||||||
// assign previous gesture to FRESH
|
|
||||||
this->previous_gesture = keyboard_swipe_gesture::FRESH;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hook on update of swipe gesture.
|
|
||||||
*/
|
|
||||||
void keyboard_swipe_gesture::update() {
|
|
||||||
// call superclass method
|
|
||||||
swipe_gesture::update();
|
|
||||||
|
|
||||||
// scale threshold to 1/10 when gesture is not fresh
|
|
||||||
float scale = this->previous_gesture == keyboard_swipe_gesture::FRESH
|
|
||||||
? 1.00f
|
|
||||||
: 0.01f; // square root of 1/10
|
|
||||||
|
|
||||||
// we are working with floating points which are not exact
|
|
||||||
// make sure we compare with a very small value (epsilon)
|
|
||||||
static const float EPSILON = 1e-6f;
|
|
||||||
const float distance_squared = this->x * this->x + this->y * this->y;
|
|
||||||
const float beyond_threshold = this->threshold_squared * scale;
|
|
||||||
|
|
||||||
// apply if strictly beyond threshold
|
|
||||||
if (distance_squared > beyond_threshold + EPSILON) {
|
|
||||||
// we parse our mask based on the values obtained from the regex
|
|
||||||
int mask = 0;
|
|
||||||
|
|
||||||
if (this->fingers == 3)
|
|
||||||
mask |= keyboard_swipe_gesture::MSK_THREE_FINGERS;
|
|
||||||
|
|
||||||
else if (this->fingers == 4)
|
|
||||||
mask |= keyboard_swipe_gesture::MSK_FOUR_FINGERS;
|
|
||||||
|
|
||||||
const float absx = x >= 0 ? x : -x;
|
|
||||||
const float absy = y >= 0 ? y : -y;
|
|
||||||
|
|
||||||
if (absx > absy) {
|
|
||||||
// gesture is horizontal
|
|
||||||
mask |= keyboard_swipe_gesture::MSK_HORIZONTAL;
|
|
||||||
if (x < 0)
|
|
||||||
mask |= keyboard_swipe_gesture::MSK_NEGATIVE;
|
|
||||||
else
|
|
||||||
mask |= keyboard_swipe_gesture::MSK_POSITIVE;
|
|
||||||
} else /* std::abs(x) <= std::abs(y) */
|
|
||||||
{
|
|
||||||
// gesture is vertical
|
|
||||||
mask |= keyboard_swipe_gesture::MSK_VERTICAL;
|
|
||||||
if (y < 0)
|
|
||||||
mask |= keyboard_swipe_gesture::MSK_NEGATIVE;
|
|
||||||
else
|
|
||||||
mask |= keyboard_swipe_gesture::MSK_POSITIVE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// send command on fresh OR opposite gesture
|
|
||||||
if (this->previous_gesture == keyboard_swipe_gesture::FRESH ||
|
|
||||||
this->previous_gesture ==
|
|
||||||
(mask ^ keyboard_swipe_gesture::MSK_POSITIVE)) {
|
|
||||||
this->do_keyboard_gesture(mask);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Apply the update given a mask.
|
|
||||||
*/
|
|
||||||
void keyboard_swipe_gesture::do_keyboard_gesture(int mask) {
|
|
||||||
// perform our keyboard command with xdo_send_keysequence
|
|
||||||
const char *command = keyboard_swipe_gesture::commands[mask];
|
|
||||||
xdo_send_keysequence_window(this->xdo, CURRENTWINDOW, command, 0);
|
|
||||||
|
|
||||||
// reset our location variables
|
|
||||||
this->x = this->y = 0;
|
|
||||||
this->previous_gesture = mask;
|
|
||||||
|
|
||||||
// log our command name in stdout
|
|
||||||
const char *command_name = keyboard_swipe_gesture::command_map[mask];
|
|
||||||
std::cout << "SWIPE " << command_name << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hook on end of swipe gesture.
|
|
||||||
*/
|
|
||||||
void keyboard_swipe_gesture::end() {
|
|
||||||
// call superclass method
|
|
||||||
swipe_gesture::end();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace comfortable_swipe::gesture
|
|
||||||
|
|
||||||
#endif /* __COMFORTABLE_SWIPE__gesture_keyboard_swipe_gesture__ */
|
|
||||||
@ -1,79 +0,0 @@
|
|||||||
#ifndef __COMFORTABLE_SWIPE__gesture_keyboard_swipe_gesture_h__
|
|
||||||
#define __COMFORTABLE_SWIPE__gesture_keyboard_swipe_gesture_h__
|
|
||||||
|
|
||||||
/*
|
|
||||||
Comfortable Swipe
|
|
||||||
by Rico Tiongson
|
|
||||||
|
|
||||||
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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "swipe_gesture.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace comfortable_swipe::gesture {
|
|
||||||
class keyboard_swipe_gesture : public swipe_gesture {
|
|
||||||
public:
|
|
||||||
// constructor
|
|
||||||
keyboard_swipe_gesture(const float threshold, const char *left3 /* 000 */,
|
|
||||||
const char *left4 /* 001 */,
|
|
||||||
const char *right3 /* 010 */,
|
|
||||||
const char *right4 /* 011 */,
|
|
||||||
const char *up3 /* 100 */, const char *up4 /* 101 */,
|
|
||||||
const char *down3 /* 110 */,
|
|
||||||
const char *down4 /* 111 */
|
|
||||||
);
|
|
||||||
|
|
||||||
// destructor
|
|
||||||
virtual ~keyboard_swipe_gesture();
|
|
||||||
|
|
||||||
// hooks that we override
|
|
||||||
virtual void begin() override;
|
|
||||||
virtual void update() override;
|
|
||||||
virtual void end() override;
|
|
||||||
|
|
||||||
// override this when keyboard gesture is to be performed
|
|
||||||
virtual void do_keyboard_gesture(int mask);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// stores square of threshold so we can compute faster
|
|
||||||
float threshold_squared;
|
|
||||||
|
|
||||||
// stores previous gesture so we don't repeat action
|
|
||||||
int previous_gesture;
|
|
||||||
|
|
||||||
// stores all command strings for xdo to execute
|
|
||||||
const char **commands;
|
|
||||||
|
|
||||||
public:
|
|
||||||
// static enums we will use for gesture matching
|
|
||||||
static const int FRESH;
|
|
||||||
static const int MSK_THREE_FINGERS;
|
|
||||||
static const int MSK_FOUR_FINGERS;
|
|
||||||
static const int MSK_NEGATIVE;
|
|
||||||
static const int MSK_POSITIVE;
|
|
||||||
static const int MSK_HORIZONTAL;
|
|
||||||
static const int MSK_VERTICAL;
|
|
||||||
static const char *const command_map[8];
|
|
||||||
};
|
|
||||||
} // namespace comfortable_swipe::gesture
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* __COMFORTABLE_SWIPE__gesture_keyboard_swipe_gesture_h__ */
|
|
||||||
@ -1,180 +0,0 @@
|
|||||||
#ifndef __COMFORTABLE_SWIPE__gesture_mouse_hold_gesture__
|
|
||||||
#define __COMFORTABLE_SWIPE__gesture_mouse_hold_gesture__
|
|
||||||
|
|
||||||
/*
|
|
||||||
Comfortable Swipe
|
|
||||||
by Rico Tiongson
|
|
||||||
|
|
||||||
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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "mouse_hold_gesture.h"
|
|
||||||
#include <cstdio> // std::sscanf
|
|
||||||
#include <cstring> // strncmp
|
|
||||||
#include <iostream> // std::cout, std::endl
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#include <xdo.h> // xdo, xdo_new, xdo_free,
|
|
||||||
// xdo_get_mouse_location
|
|
||||||
// CURRENT_WINDOW
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace comfortable_swipe::gesture {
|
|
||||||
enum {
|
|
||||||
MOUSE_NONE = -1,
|
|
||||||
MOUSE_MOVE = 0,
|
|
||||||
MOUSE_LEFT_CLICK = 1,
|
|
||||||
MOUSE_MIDDLE_CLICK = 2,
|
|
||||||
MOUSE_RIGHT_CLICK = 3,
|
|
||||||
MOUSE_WHEEL_UP = 4,
|
|
||||||
MOUSE_WHEEL_DOWN = 5,
|
|
||||||
MOUSE_SCROLL = 6,
|
|
||||||
MOUSE_SCROLL_REVERSE = 7
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a new mouse gesture, given "hold3" and "hold4" configurations.
|
|
||||||
*/
|
|
||||||
mouse_hold_gesture::mouse_hold_gesture(const char *hold3, const char *hold4)
|
|
||||||
: comfortable_swipe::gesture::swipe_gesture(), button(MOUSE_NONE),
|
|
||||||
hold3(hold3), hold4(hold4), flag_mousedown(false) {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destructs this mouse swipe gesture.
|
|
||||||
*/
|
|
||||||
mouse_hold_gesture::~mouse_hold_gesture() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Run mousedown command on hold input.
|
|
||||||
*/
|
|
||||||
void mouse_hold_gesture::do_mousedown(const char *mouseinput) {
|
|
||||||
const int button = this->button = this->parse_mouse_button(mouseinput);
|
|
||||||
if (button != MOUSE_NONE) {
|
|
||||||
// eg. MOUSE DOWN hold3 mouse1
|
|
||||||
std::printf("MOUSE DOWN hold%d %s\n", this->fingers, mouseinput);
|
|
||||||
if (MOUSE_LEFT_CLICK <= button && button <= MOUSE_RIGHT_CLICK) {
|
|
||||||
// send mouse down on associated button
|
|
||||||
xdo_mouse_down(this->xdo, CURRENTWINDOW, button);
|
|
||||||
}
|
|
||||||
this->flag_mousedown = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Run mouseup command on hold output.
|
|
||||||
*/
|
|
||||||
void mouse_hold_gesture::do_mouseup(const char *mouseinput) {
|
|
||||||
const int button = this->button = this->parse_mouse_button(mouseinput);
|
|
||||||
if (button != MOUSE_NONE) {
|
|
||||||
std::printf("MOUSE UP hold%d %s\n", this->fingers, mouseinput);
|
|
||||||
if (MOUSE_LEFT_CLICK <= button && button <= MOUSE_RIGHT_CLICK) {
|
|
||||||
// send mouse up on associated button
|
|
||||||
xdo_mouse_up(this->xdo, CURRENTWINDOW, button);
|
|
||||||
}
|
|
||||||
this->flag_mousedown = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility method to parse mouse number from input.
|
|
||||||
* Returns -1 on failure.
|
|
||||||
*/
|
|
||||||
int mouse_hold_gesture::parse_mouse_button(const char *input) {
|
|
||||||
// just move without holding button down
|
|
||||||
if (std::strcmp(input, "move") == 0)
|
|
||||||
return MOUSE_MOVE;
|
|
||||||
|
|
||||||
if (std::strcmp(input, "scroll") == 0)
|
|
||||||
return MOUSE_SCROLL;
|
|
||||||
|
|
||||||
if (std::strcmp(input, "scroll_reverse") == 0)
|
|
||||||
return MOUSE_SCROLL_REVERSE;
|
|
||||||
|
|
||||||
// get button number
|
|
||||||
int button;
|
|
||||||
if (std::sscanf(input, "button%d", &button) == 1) {
|
|
||||||
if (1 <= button && button <= 6) {
|
|
||||||
return button;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return MOUSE_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hook on begin of mouse swipe gesture.
|
|
||||||
*/
|
|
||||||
void mouse_hold_gesture::begin() {
|
|
||||||
// call superclass method
|
|
||||||
swipe_gesture::begin();
|
|
||||||
// dispatch mouse down event
|
|
||||||
if (this->fingers == 3) {
|
|
||||||
this->do_mousedown(this->hold3);
|
|
||||||
} else if (this->fingers == 4) {
|
|
||||||
this->do_mousedown(this->hold4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hook on end of mouse swipe gesture.
|
|
||||||
*/
|
|
||||||
void mouse_hold_gesture::update() {
|
|
||||||
// call superclass method
|
|
||||||
swipe_gesture::update();
|
|
||||||
if (this->is_mousedown()) {
|
|
||||||
if (0 <= this->button && this->button <= 3) {
|
|
||||||
// drag mouse with pointer during update
|
|
||||||
xdo_move_mouse_relative(this->xdo, this->udx, this->udy);
|
|
||||||
} else if (this->button == MOUSE_SCROLL ||
|
|
||||||
this->button == MOUSE_SCROLL_REVERSE) {
|
|
||||||
// perform naive scroll depending on vertical direction
|
|
||||||
int wheel = MOUSE_WHEEL_DOWN;
|
|
||||||
if ((this->udy > 0) == (this->button == MOUSE_SCROLL))
|
|
||||||
wheel = MOUSE_WHEEL_UP;
|
|
||||||
|
|
||||||
// click wheel on update (note: this is not precise)
|
|
||||||
xdo_mouse_down(this->xdo, CURRENTWINDOW, wheel);
|
|
||||||
xdo_mouse_up(this->xdo, CURRENTWINDOW, wheel);
|
|
||||||
} else if (this->button == MOUSE_WHEEL_UP ||
|
|
||||||
this->button == MOUSE_WHEEL_DOWN) {
|
|
||||||
// click wheel button on 4 or 5
|
|
||||||
xdo_mouse_down(this->xdo, CURRENTWINDOW, this->button);
|
|
||||||
xdo_mouse_up(this->xdo, CURRENTWINDOW, this->button);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hook on end of swipe gesture.
|
|
||||||
*/
|
|
||||||
void mouse_hold_gesture::end() {
|
|
||||||
if (this->is_mousedown()) {
|
|
||||||
if (this->fingers == 3) {
|
|
||||||
this->do_mouseup(this->hold3);
|
|
||||||
} else if (this->fingers == 4) {
|
|
||||||
this->do_mouseup(this->hold4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// call superclass method
|
|
||||||
swipe_gesture::end();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility method to check if mouse is current held.
|
|
||||||
*/
|
|
||||||
bool mouse_hold_gesture::is_mousedown() const { return this->flag_mousedown; }
|
|
||||||
} // namespace comfortable_swipe::gesture
|
|
||||||
|
|
||||||
#endif /* __COMFORTABLE_SWIPE__gesture_mouse_hold_gesture__ */
|
|
||||||
@ -1,68 +0,0 @@
|
|||||||
#ifndef __COMFORTABLE_SWIPE__gesture_mouse_hold_gesture_h__
|
|
||||||
#define __COMFORTABLE_SWIPE__gesture_mouse_hold_gesture_h__
|
|
||||||
|
|
||||||
/*
|
|
||||||
Comfortable Swipe
|
|
||||||
by Rico Tiongson
|
|
||||||
|
|
||||||
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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "swipe_gesture.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace comfortable_swipe::gesture {
|
|
||||||
class mouse_hold_gesture : public swipe_gesture {
|
|
||||||
public:
|
|
||||||
// constructor
|
|
||||||
mouse_hold_gesture(const char *hold3, // 3 finger mouse down
|
|
||||||
const char *hold4 // 4 finger mouse down
|
|
||||||
);
|
|
||||||
|
|
||||||
// the button being clicked
|
|
||||||
int button;
|
|
||||||
|
|
||||||
virtual ~mouse_hold_gesture();
|
|
||||||
|
|
||||||
// override begin and end for mousedown
|
|
||||||
virtual void begin() override;
|
|
||||||
virtual void update() override;
|
|
||||||
virtual void end() override;
|
|
||||||
|
|
||||||
// provide our own mouse functions
|
|
||||||
virtual void do_mousedown(const char *);
|
|
||||||
virtual void do_mouseup(const char *);
|
|
||||||
virtual bool is_mousedown() const;
|
|
||||||
|
|
||||||
// utility method to parse mouse input given config characters
|
|
||||||
static int parse_mouse_button(const char *);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// command holders
|
|
||||||
const char *hold3;
|
|
||||||
const char *hold4;
|
|
||||||
|
|
||||||
// flag we can use to check if mouse is down
|
|
||||||
bool flag_mousedown;
|
|
||||||
};
|
|
||||||
} // namespace comfortable_swipe::gesture
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* __COMFORTABLE_SWIPE__gesture_mouse_hold_gesture_h__ */
|
|
||||||
@ -1,131 +0,0 @@
|
|||||||
#ifndef __COMFORTABLE_SWIPE__gesture_swipe_gesture__
|
|
||||||
#define __COMFORTABLE_SWIPE__gesture_swipe_gesture__
|
|
||||||
|
|
||||||
/*
|
|
||||||
Comfortable Swipe
|
|
||||||
by Rico Tiongson
|
|
||||||
|
|
||||||
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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "swipe_gesture.h"
|
|
||||||
#include <iostream> // std::cout, std::endl
|
|
||||||
#include <regex> // std::regex, std::regex_match, std::cmatch
|
|
||||||
#include <string> // std::stoi, std::stof
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#include <xdo.h> // xdo, xdo_new, xdo_free,
|
|
||||||
// xdo_get_mouse_location
|
|
||||||
// CURRENT_WINDOW
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace comfortable_swipe::gesture {
|
|
||||||
/**
|
|
||||||
* Constructs a new fresh swipe gesture container.
|
|
||||||
*/
|
|
||||||
swipe_gesture::swipe_gesture()
|
|
||||||
: // construct our superclass
|
|
||||||
comfortable_swipe::gesture::xdo_gesture(), flag_swiping(false) {
|
|
||||||
// improve responsiveness of first gesture by pre-empting xdotool
|
|
||||||
xdo_get_mouse_location(this->xdo, &this->ix, &this->iy, &this->screen_num);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destructs this swipe gesture.
|
|
||||||
*/
|
|
||||||
swipe_gesture::~swipe_gesture() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hook on begin of swipe gesture (you can override this).
|
|
||||||
*/
|
|
||||||
void swipe_gesture::begin() {
|
|
||||||
// save current screen location for gestured mouse movement
|
|
||||||
xdo_get_mouse_location(this->xdo, &this->ix, &this->iy, &this->screen_num);
|
|
||||||
this->x = 0;
|
|
||||||
this->y = 0;
|
|
||||||
this->ux = 0;
|
|
||||||
this->uy = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hook on update of swipe gesture (you can override this).
|
|
||||||
*/
|
|
||||||
void swipe_gesture::update() {
|
|
||||||
this->x += this->dx;
|
|
||||||
this->y += this->dy;
|
|
||||||
this->ux += this->udx;
|
|
||||||
this->uy += this->udy;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hook on end of swipe gesture (you can override this).
|
|
||||||
*/
|
|
||||||
void swipe_gesture::end() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dispatches begin/update/end depending on the regex pattern provided by this
|
|
||||||
* class.
|
|
||||||
*
|
|
||||||
* @param line the line from libinput debug-events to parse
|
|
||||||
* @return true if begin/update/end was dispatched
|
|
||||||
*/
|
|
||||||
bool swipe_gesture::parse_line(const char *line) {
|
|
||||||
|
|
||||||
// prepare regex matchers statically (will only load at most once)
|
|
||||||
static const std::regex gesture_swipe_begin(
|
|
||||||
swipe_gesture::GESTURE_BEGIN_REGEX_PATTERN),
|
|
||||||
gesture_swipe_update(swipe_gesture::GESTURE_UPDATE_REGEX_PATTERN),
|
|
||||||
gesture_swipe_end(swipe_gesture::GESTURE_END_REGEX_PATTERN);
|
|
||||||
|
|
||||||
// prepare holder for regex matches
|
|
||||||
static std::cmatch matches;
|
|
||||||
|
|
||||||
if (this->flag_swiping) {
|
|
||||||
// currently swiping
|
|
||||||
if (std::regex_match(line, matches, gesture_swipe_update) != 0) {
|
|
||||||
// assign necessary variables for swipe update
|
|
||||||
this->fingers = std::stoi(matches[1]);
|
|
||||||
this->dx = std::stof(matches[2]);
|
|
||||||
this->dy = std::stof(matches[3]);
|
|
||||||
this->udx = std::stof(matches[4]);
|
|
||||||
this->udy = std::stof(matches[5]);
|
|
||||||
// dispatch update
|
|
||||||
this->update();
|
|
||||||
return true;
|
|
||||||
} else if (std::regex_match(line, matches, gesture_swipe_end) != 0) {
|
|
||||||
// assign necessary variables for swipe end
|
|
||||||
this->flag_swiping = false;
|
|
||||||
this->fingers = std::stoi(matches[1]);
|
|
||||||
// dispatch end
|
|
||||||
this->end();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// not swiping, check if swipe will begin
|
|
||||||
if (std::regex_match(line, matches, gesture_swipe_begin) != 0 ||
|
|
||||||
std::regex_match(line, matches, gesture_swipe_update) != 0) {
|
|
||||||
// assign necessary variables for swipe begin
|
|
||||||
this->flag_swiping = true;
|
|
||||||
this->fingers = std::stoi(matches[1]);
|
|
||||||
// dispatch begin
|
|
||||||
this->begin();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} // namespace comfortable_swipe::gesture
|
|
||||||
|
|
||||||
#endif /* __COMFORTABLE_SWIPE__gesture_swipe_gesture__ */
|
|
||||||
@ -1,71 +0,0 @@
|
|||||||
#ifndef __COMFORTABLE_SWIPE__gesture_swipe_gesture_h__
|
|
||||||
#define __COMFORTABLE_SWIPE__gesture_swipe_gesture_h__
|
|
||||||
|
|
||||||
/*
|
|
||||||
Comfortable Swipe
|
|
||||||
by Rico Tiongson
|
|
||||||
|
|
||||||
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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "xdo_gesture.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace comfortable_swipe::gesture {
|
|
||||||
class swipe_gesture : public xdo_gesture {
|
|
||||||
public:
|
|
||||||
// constructor
|
|
||||||
swipe_gesture();
|
|
||||||
|
|
||||||
// destructor
|
|
||||||
virtual ~swipe_gesture();
|
|
||||||
|
|
||||||
// fields for xdo
|
|
||||||
int fingers;
|
|
||||||
|
|
||||||
// normal values (for touchpad mapping)
|
|
||||||
float x, y, dx, dy;
|
|
||||||
|
|
||||||
// unaccelerated values (for screen mapping)
|
|
||||||
float ux, uy, udx, udy;
|
|
||||||
|
|
||||||
// hooks that we can override (mark as virtual)
|
|
||||||
virtual void begin();
|
|
||||||
virtual void update();
|
|
||||||
virtual void end();
|
|
||||||
virtual bool parse_line(const char *);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// location of mouse
|
|
||||||
int screen_num, ix, iy;
|
|
||||||
|
|
||||||
// optimization flag for checking if GESTURE_SWIPE_BEGIN was dispatched
|
|
||||||
bool flag_swiping;
|
|
||||||
|
|
||||||
public:
|
|
||||||
// regex patterns
|
|
||||||
static const char *GESTURE_BEGIN_REGEX_PATTERN;
|
|
||||||
static const char *GESTURE_UPDATE_REGEX_PATTERN;
|
|
||||||
static const char *GESTURE_END_REGEX_PATTERN;
|
|
||||||
};
|
|
||||||
} // namespace comfortable_swipe::gesture
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* __COMFORTABLE_SWIPE__gesture_swipe_gesture_h__ */
|
|
||||||
@ -1,91 +0,0 @@
|
|||||||
#ifndef __COMFORTABLE_SWIPE__gesture_swipe_gesture_regex__
|
|
||||||
#define __COMFORTABLE_SWIPE__gesture_swipe_gesture_regex__
|
|
||||||
|
|
||||||
/*
|
|
||||||
Comfortable Swipe
|
|
||||||
by Rico Tiongson
|
|
||||||
|
|
||||||
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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "swipe_gesture.h"
|
|
||||||
|
|
||||||
namespace comfortable_swipe::gesture {
|
|
||||||
/**
|
|
||||||
* Regex pattern for the libinput entry for start of swipe.
|
|
||||||
* Extracts one match for the number of fingers used during the swipe.
|
|
||||||
*
|
|
||||||
* eg. event15 GESTURE_SWIPE_BEGIN +34.33s 3
|
|
||||||
* ^
|
|
||||||
* fingers
|
|
||||||
*/
|
|
||||||
const char *swipe_gesture::GESTURE_BEGIN_REGEX_PATTERN =
|
|
||||||
"^" // start of string
|
|
||||||
"[ -]event\\d+" // event
|
|
||||||
"\\s+GESTURE_SWIPE_BEGIN" // gesture
|
|
||||||
"\\s+\\S+" // timestamp
|
|
||||||
"\\s+(\\d+)" // fingers
|
|
||||||
"\\s*$" // end of string
|
|
||||||
;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Regex pattern for the libinput entry for the end of swipe.
|
|
||||||
* Extracts one match for the number of fingers used during the swipe.
|
|
||||||
*
|
|
||||||
* eg. event15 GESTURE_SWIPE_END +35.03s 3
|
|
||||||
* ^
|
|
||||||
* fingers
|
|
||||||
*/
|
|
||||||
const char *swipe_gesture::GESTURE_END_REGEX_PATTERN =
|
|
||||||
"^" // start of string
|
|
||||||
"[ -]event\\d+" // event
|
|
||||||
"\\s+GESTURE_SWIPE_END" // gesture
|
|
||||||
"\\s+\\S+" // timestamp
|
|
||||||
"\\s+(\\d+)" // fingers
|
|
||||||
"\\s*$" // end of string
|
|
||||||
;
|
|
||||||
|
|
||||||
// matches signed decimal numbers (eg. "6.02" "-1.1")
|
|
||||||
#define CF_NUMBER_REGEX "-?\\d+(?:\\.\\d+)"
|
|
||||||
|
|
||||||
// matches and extracts a space-prefixed signed fraction (eg. "-3.00/ 5.12")
|
|
||||||
#define CF_NUMBER_DIVISION "\\s*(" CF_NUMBER_REGEX ")/\\s*(" CF_NUMBER_REGEX ")"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Regex pattern for the libinput entry for during a swipe.
|
|
||||||
* Extracts number of fingers used and the speed (normal and accelerated) of the
|
|
||||||
* swipe.
|
|
||||||
*
|
|
||||||
* eg. event15 GESTURE_SWIPE_UPDATE +34.70s 3 -0.12/ 4.99 (-0.33/13.50
|
|
||||||
* unaccelerated) ^ ^ ^ ^ ^ fingers dx dy udx udy
|
|
||||||
*/
|
|
||||||
const char *swipe_gesture::GESTURE_UPDATE_REGEX_PATTERN =
|
|
||||||
"^" // start of string
|
|
||||||
"[ -]event\\d+" // event
|
|
||||||
"\\s+GESTURE_SWIPE_UPDATE" // gesture
|
|
||||||
"\\s+\\S+" // timestamp
|
|
||||||
"\\s+(\\d+)" // fingers
|
|
||||||
"\\s+" CF_NUMBER_DIVISION // speed (dx/dy)
|
|
||||||
"\\s+\\(" CF_NUMBER_DIVISION
|
|
||||||
"\\s+unaccelerated\\)" // unaccelerated speed (udx/udy)
|
|
||||||
"\\s*$" // end of string
|
|
||||||
;
|
|
||||||
|
|
||||||
// delete macros
|
|
||||||
#undef CF_NUMBER_DIVISION
|
|
||||||
#undef CF_NUMBER_EXTRACT
|
|
||||||
#undef CF_NUMBER_REGEX
|
|
||||||
} // namespace comfortable_swipe::gesture
|
|
||||||
|
|
||||||
#endif /* __COMFORTABLE_SWIPE__gesture_swipe_gesture_regex__ */
|
|
||||||
@ -1,40 +0,0 @@
|
|||||||
#ifndef __COMFORTABLE_SWIPE__xdo_gesture__
|
|
||||||
#define __COMFORTABLE_SWIPE__xdo_gesture__
|
|
||||||
|
|
||||||
/*
|
|
||||||
Comfortable Swipe
|
|
||||||
by Rico Tiongson
|
|
||||||
|
|
||||||
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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#include <xdo.h> // xdo, xdo_new
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "xdo_gesture.h"
|
|
||||||
|
|
||||||
namespace comfortable_swipe::gesture {
|
|
||||||
/**
|
|
||||||
* Constructs a new gesture handler with xdo.
|
|
||||||
*/
|
|
||||||
xdo_gesture::xdo_gesture() : xdo(xdo_new(NULL)) {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a new swipe gesture with xdo.
|
|
||||||
*/
|
|
||||||
xdo_gesture::~xdo_gesture() { xdo_free(this->xdo); }
|
|
||||||
} // namespace comfortable_swipe::gesture
|
|
||||||
|
|
||||||
#endif /* __COMFORTABLE_SWIPE__xdo_gesture__ */
|
|
||||||
@ -1,47 +0,0 @@
|
|||||||
#ifndef __COMFORTABLE_SWIPE__xdo_gesture_h__
|
|
||||||
#define __COMFORTABLE_SWIPE__xdo_gesture_h__
|
|
||||||
|
|
||||||
/*
|
|
||||||
Comfortable Swipe
|
|
||||||
by Rico Tiongson
|
|
||||||
|
|
||||||
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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#include <xdo.h> // xdo_t
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace comfortable_swipe {
|
|
||||||
namespace gesture {
|
|
||||||
class xdo_gesture {
|
|
||||||
protected:
|
|
||||||
xdo_t *xdo;
|
|
||||||
|
|
||||||
public:
|
|
||||||
xdo_gesture();
|
|
||||||
virtual ~xdo_gesture();
|
|
||||||
};
|
|
||||||
} // namespace gesture
|
|
||||||
} // namespace comfortable_swipe
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* __COMFORTABLE_SWIPE__xdo_gesture_h__ */
|
|
||||||
@ -1,66 +0,0 @@
|
|||||||
#ifndef __COMFORTABLE_SWIPE__service_autostart__
|
|
||||||
#define __COMFORTABLE_SWIPE__service_autostart__
|
|
||||||
|
|
||||||
/*
|
|
||||||
Comfortable Swipe
|
|
||||||
by Rico Tiongson
|
|
||||||
|
|
||||||
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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "../comfortable_swipe.h"
|
|
||||||
#include <cstdio> // std::remove
|
|
||||||
#include <cstdlib> // std::system
|
|
||||||
#include <fstream> // std::ifstream, std::ofstream
|
|
||||||
#include <iostream> // std::cerr, std::cout, std::endl
|
|
||||||
#include <string> // std::string
|
|
||||||
|
|
||||||
namespace comfortable_swipe::service {
|
|
||||||
/**
|
|
||||||
* Toggles automatic startup of comfortable swipe.
|
|
||||||
*/
|
|
||||||
void autostart() {
|
|
||||||
using comfortable_swipe::util::autostart_filename;
|
|
||||||
|
|
||||||
const std::string &path = autostart_filename();
|
|
||||||
if (std::ifstream(path.data()).good()) {
|
|
||||||
// file found, delete it
|
|
||||||
if (std::remove(path.data()) != 0)
|
|
||||||
std::cerr << "Error: failed to switch off autostart. "
|
|
||||||
<< "Maybe the autostart file is in use?" << std::endl;
|
|
||||||
else
|
|
||||||
std::cout << "Autostart switched off" << std::endl;
|
|
||||||
} else {
|
|
||||||
// file not found, create it
|
|
||||||
int result = std::system(("mkdir -p $(dirname " + path + ")").data());
|
|
||||||
std::ofstream fout(path.data());
|
|
||||||
if (result != 0 || !fout.good())
|
|
||||||
std::cerr << "Error: failed to switch on autostart. "
|
|
||||||
<< "Are you sure you have the permissions?" << std::endl;
|
|
||||||
else {
|
|
||||||
fout << "[Desktop Entry]\n"
|
|
||||||
"Type=Application\n"
|
|
||||||
"Exec=bash -c \"" COMFORTABLE_SWIPE_PROGRAM " start\"\n"
|
|
||||||
"Hidden=false\n"
|
|
||||||
"NoDisplay=false\n"
|
|
||||||
"X-GNOME-Autostart-enabled=true\n"
|
|
||||||
"Name=Comfortable Swipe\n"
|
|
||||||
"Comment=3 or 4 touchpad gestures\n";
|
|
||||||
std::cout << "Autostart switched on" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // namespace comfortable_swipe::service
|
|
||||||
|
|
||||||
#endif /* __COMFORTABLE_SWIPE__service_autostart__ */
|
|
||||||
@ -1,31 +0,0 @@
|
|||||||
#ifndef __COMFORTABLE_SWIPE__service_buffer__
|
|
||||||
#define __COMFORTABLE_SWIPE__service_buffer__
|
|
||||||
|
|
||||||
/*
|
|
||||||
Comfortable Swipe
|
|
||||||
by Rico Tiongson
|
|
||||||
|
|
||||||
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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "../start.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Starts the comfortable-swipe service by buffering libinput debug-events.
|
|
||||||
*/
|
|
||||||
namespace comfortable_swipe::service {
|
|
||||||
void buffer() { comfortable_swipe::start(); }
|
|
||||||
} // namespace comfortable_swipe::service
|
|
||||||
|
|
||||||
#endif /* __COMFORTABLE_SWIPE__service_buffer__ */
|
|
||||||
@ -1,34 +0,0 @@
|
|||||||
#ifndef __COMFORTABLE_SWIPE__service_config__
|
|
||||||
#define __COMFORTABLE_SWIPE__service_config__
|
|
||||||
|
|
||||||
/*
|
|
||||||
Comfortable Swipe
|
|
||||||
by Rico Tiongson
|
|
||||||
|
|
||||||
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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "../comfortable_swipe.h"
|
|
||||||
#include <cstdio> // std::puts
|
|
||||||
|
|
||||||
namespace comfortable_swipe::service {
|
|
||||||
/**
|
|
||||||
* Prints where the config file of comfortable swipe is located.
|
|
||||||
*
|
|
||||||
* Usage: nano $(comfortable-swipe config)
|
|
||||||
*/
|
|
||||||
void config() { std::puts(comfortable_swipe::util::conf_filename()); }
|
|
||||||
} // namespace comfortable_swipe::service
|
|
||||||
|
|
||||||
#endif /* __COMFORTABLE_SWIPE__service_config__ */
|
|
||||||
@ -1,34 +0,0 @@
|
|||||||
#ifndef __COMFORTABLE_SWIPE__service_debug__
|
|
||||||
#define __COMFORTABLE_SWIPE__service_debug__
|
|
||||||
|
|
||||||
/*
|
|
||||||
Comfortable Swipe
|
|
||||||
by Rico Tiongson
|
|
||||||
|
|
||||||
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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <cstdlib> // std::system
|
|
||||||
|
|
||||||
namespace comfortable_swipe::service {
|
|
||||||
/**
|
|
||||||
* Debugs output from `libinput debug-events`.
|
|
||||||
*/
|
|
||||||
void debug() {
|
|
||||||
(void)std::system("bash -c \"stdbuf -oL -e0 libinput debug-events 2> >(grep "
|
|
||||||
"-v 'double tracking')\"");
|
|
||||||
}
|
|
||||||
} // namespace comfortable_swipe::service
|
|
||||||
|
|
||||||
#endif /* __COMFORTABLE_SWIPE__service_debug__ */
|
|
||||||
@ -1,50 +0,0 @@
|
|||||||
#ifndef __COMFORTABLE_SWIPE__service_help__
|
|
||||||
#define __COMFORTABLE_SWIPE__service_help__
|
|
||||||
|
|
||||||
/*
|
|
||||||
Comfortable Swipe
|
|
||||||
by Rico Tiongson
|
|
||||||
|
|
||||||
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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "../comfortable_swipe.h"
|
|
||||||
#include <cstdio> // std::puts, std::printf
|
|
||||||
|
|
||||||
namespace comfortable_swipe::service {
|
|
||||||
/**
|
|
||||||
* Shows the help window.
|
|
||||||
*/
|
|
||||||
void help() {
|
|
||||||
using comfortable_swipe::util::conf_filename;
|
|
||||||
std::puts("comfortable-swipe " COMFORTABLE_SWIPE_VERSION
|
|
||||||
" [start|stop|restart|autostart|buffer|help|config|debug|status]");
|
|
||||||
std::puts("");
|
|
||||||
std::puts("start - starts 3/4-finger gesture service");
|
|
||||||
std::puts("stop - stops 3/4-finger gesture service");
|
|
||||||
std::puts("restart - stops then starts 3/4-finger gesture service");
|
|
||||||
std::puts("autostart - automatically run on startup (toggleable)");
|
|
||||||
std::puts("buffer - parses output of libinput debug-events");
|
|
||||||
std::puts("help - shows the help dialog");
|
|
||||||
std::puts("config - locates the config file "
|
|
||||||
"[/usr/share/comfortable-swipe/comfortable-swipe.conf]");
|
|
||||||
std::puts(
|
|
||||||
"debug - logs raw output from input events taken from libinput");
|
|
||||||
std::puts("status - checks status of program and autostart");
|
|
||||||
std::puts("");
|
|
||||||
std::printf("Configuration file can be found in %s\n", conf_filename());
|
|
||||||
}
|
|
||||||
} // namespace comfortable_swipe::service
|
|
||||||
|
|
||||||
#endif /* __COMFORTABLE_SWIPE__service_help__ */
|
|
||||||
@ -1,40 +0,0 @@
|
|||||||
#ifndef __COMFORTABLE_SWIPE__service_restart__
|
|
||||||
#define __COMFORTABLE_SWIPE__service_restart__
|
|
||||||
|
|
||||||
/*
|
|
||||||
Comfortable Swipe
|
|
||||||
by Rico Tiongson
|
|
||||||
|
|
||||||
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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "../comfortable_swipe.h"
|
|
||||||
#include <cstdio> // freopen, stdout
|
|
||||||
|
|
||||||
namespace comfortable_swipe::service {
|
|
||||||
/**
|
|
||||||
* Restarts the comfortable-swipe service.
|
|
||||||
*/
|
|
||||||
void restart() {
|
|
||||||
// dont show stdout on stop
|
|
||||||
freopen("/dev/null", "a", stdout);
|
|
||||||
comfortable_swipe::service::stop();
|
|
||||||
|
|
||||||
// show back on start
|
|
||||||
freopen("/dev/tty", "a", stdout);
|
|
||||||
comfortable_swipe::service::start();
|
|
||||||
}
|
|
||||||
} // namespace comfortable_swipe::service
|
|
||||||
|
|
||||||
#endif /* __COMFORTABLE_SWIPE__service_restart__ */
|
|
||||||
@ -1,37 +0,0 @@
|
|||||||
#ifndef __COMFORTABLE_SWIPE__service_start__
|
|
||||||
#define __COMFORTABLE_SWIPE__service_start__
|
|
||||||
|
|
||||||
/*
|
|
||||||
Comfortable Swipe
|
|
||||||
by Rico Tiongson
|
|
||||||
|
|
||||||
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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "../comfortable_swipe.h"
|
|
||||||
#include <cstdlib> // std::system
|
|
||||||
|
|
||||||
namespace comfortable_swipe::service {
|
|
||||||
/**
|
|
||||||
* Starts the comfortable-swipe service by buffering libinput debug-events.
|
|
||||||
* This method is deferred. Please refer to comfortable_swipe::service::buffer()
|
|
||||||
* for the technical implementation.
|
|
||||||
*/
|
|
||||||
void start() {
|
|
||||||
(void)std::system(COMFORTABLE_SWIPE_PROGRAM
|
|
||||||
" debug | " COMFORTABLE_SWIPE_PROGRAM " buffer");
|
|
||||||
}
|
|
||||||
} // namespace comfortable_swipe::service
|
|
||||||
|
|
||||||
#endif /* __COMFORTABLE_SWIPE__service_start__ */
|
|
||||||
@ -1,127 +0,0 @@
|
|||||||
#ifndef __COMFORTABLE_SWIPE__service_status__
|
|
||||||
#define __COMFORTABLE_SWIPE__service_status__
|
|
||||||
|
|
||||||
/*
|
|
||||||
Comfortable Swipe
|
|
||||||
by Rico Tiongson
|
|
||||||
|
|
||||||
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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "../comfortable_swipe.h"
|
|
||||||
#include <array> // std::array
|
|
||||||
#include <cstdio> // FILE, std::feof, std::fgets, std::printf
|
|
||||||
#include <cstdlib> // std::atoi
|
|
||||||
#include <memory> // std::unique_ptr
|
|
||||||
#include <regex> // std::cmatch, std::regex, std::regex_match
|
|
||||||
#include <stdexcept> // std::runtime_error
|
|
||||||
#include <unistd.h> // popen, pclose, getpid, access, F_OK
|
|
||||||
|
|
||||||
namespace comfortable_swipe::service {
|
|
||||||
/**
|
|
||||||
* Prints the status of comfortable-swipe.
|
|
||||||
*/
|
|
||||||
void status() {
|
|
||||||
// check if comfortable-swipe is running
|
|
||||||
bool running = false;
|
|
||||||
std::array<char, 128> buffer;
|
|
||||||
std::unique_ptr<FILE, decltype(&pclose)> pipe(
|
|
||||||
popen("pgrep -f comfortable-swipe", "r"), pclose);
|
|
||||||
if (pipe && !std::feof(pipe.get()) &&
|
|
||||||
std::fgets(buffer.data(), buffer.size(), pipe.get()) != NULL) {
|
|
||||||
int pid = std::atoi(buffer.data());
|
|
||||||
if (pid != getpid())
|
|
||||||
running = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if autostart is on
|
|
||||||
auto autostart_f = comfortable_swipe::util::autostart_filename();
|
|
||||||
bool autostart_on = access(autostart_f, F_OK) != -1;
|
|
||||||
|
|
||||||
std::puts(comfortable_swipe::util::conf_filename());
|
|
||||||
|
|
||||||
// check status of configuration file
|
|
||||||
try {
|
|
||||||
auto config = comfortable_swipe::util::read_config_file(
|
|
||||||
comfortable_swipe::util::conf_filename());
|
|
||||||
|
|
||||||
// formatting
|
|
||||||
const char *FORMAT_NO_ARGS = " %9s is %9s\n";
|
|
||||||
const char *FORMAT_ARGS = " %9s is %9s (%s)\n";
|
|
||||||
|
|
||||||
// print threshold
|
|
||||||
if (config.count("threshold") > 0) {
|
|
||||||
auto &threshold = config["threshold"];
|
|
||||||
|
|
||||||
// check if regex pattern matches threshold
|
|
||||||
std::cmatch matches;
|
|
||||||
bool ok = (std::regex_match(threshold.data(), matches,
|
|
||||||
std::regex("^\\d+(?:\\.\\d+)??$")) != 0);
|
|
||||||
|
|
||||||
// print status of threshold
|
|
||||||
std::printf(FORMAT_ARGS, "threshold", ok ? "VALID" : "INVALID",
|
|
||||||
threshold.data());
|
|
||||||
} else
|
|
||||||
std::printf(FORMAT_NO_ARGS, "threshold", "NOTSET");
|
|
||||||
|
|
||||||
// print mouse hold commands
|
|
||||||
const char *mouse_hold_commands[] = {"hold3", "hold4"};
|
|
||||||
bool has_mouse_hold[] = {false, false};
|
|
||||||
int index = 0;
|
|
||||||
for (const auto *command : mouse_hold_commands) {
|
|
||||||
if (config.count(command) > 0) {
|
|
||||||
// check if command is valid
|
|
||||||
const auto &input = config[command];
|
|
||||||
int button =
|
|
||||||
comfortable_swipe::gesture::mouse_hold_gesture::parse_mouse_button(
|
|
||||||
input.c_str());
|
|
||||||
if (button != comfortable_swipe::gesture::MOUSE_NONE) {
|
|
||||||
std::printf(FORMAT_ARGS, command, "VALID", input.c_str());
|
|
||||||
has_mouse_hold[index] = button;
|
|
||||||
} else {
|
|
||||||
std::printf(FORMAT_ARGS, command, "INVALID", input.c_str());
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
std::printf(FORMAT_NO_ARGS, command, "NOTSET");
|
|
||||||
index += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// print swipe commands
|
|
||||||
for (auto &command :
|
|
||||||
comfortable_swipe::gesture::keyboard_swipe_gesture::command_map) {
|
|
||||||
if (config.count(command) > 0) {
|
|
||||||
int fingers = int(command[strlen(command) - 1] - '0');
|
|
||||||
if (has_mouse_hold[fingers - 3]) {
|
|
||||||
// command is disabled because mouse hold exists
|
|
||||||
std::printf(FORMAT_ARGS, command, "DISABLED", config[command].data());
|
|
||||||
} else {
|
|
||||||
// check if it's disabled by checking button
|
|
||||||
std::printf(FORMAT_ARGS, command, "VALID", config[command].data());
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
std::printf(FORMAT_NO_ARGS, command, "NOTSET");
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (const std::runtime_error &e) {
|
|
||||||
std::printf("config error: %s\n", e.what());
|
|
||||||
}
|
|
||||||
|
|
||||||
// print status
|
|
||||||
std::printf("\nautostart is %s\n", autostart_on ? "ON" : "OFF");
|
|
||||||
std::printf("comfortable-swipe program is %s\n",
|
|
||||||
running ? "RUNNING" : "STOPPED");
|
|
||||||
}
|
|
||||||
} // namespace comfortable_swipe::service
|
|
||||||
|
|
||||||
#endif /* __COMFORTABLE_SWIPE__service_restart__ */
|
|
||||||
@ -1,69 +0,0 @@
|
|||||||
#ifndef __COMFORTABLE_SWIPE__service_stop__
|
|
||||||
#define __COMFORTABLE_SWIPE__service_stop__
|
|
||||||
|
|
||||||
/*
|
|
||||||
Comfortable Swipe
|
|
||||||
by Rico Tiongson
|
|
||||||
|
|
||||||
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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <array> // std::array
|
|
||||||
#include <cstdio> // std::FILE, std::feof, std::fgets
|
|
||||||
#include <cstdlib> // std::atoi, std::system
|
|
||||||
#include <memory> // std::unique_ptr
|
|
||||||
#include <stdexcept> // std::runtime_error
|
|
||||||
#include <string> // std::string, std::to_string
|
|
||||||
#include <unistd.h> // popen, pclose, getpid
|
|
||||||
|
|
||||||
namespace comfortable_swipe::service {
|
|
||||||
/**
|
|
||||||
* Stops all comfortable-swipe instances.
|
|
||||||
*/
|
|
||||||
void stop() {
|
|
||||||
|
|
||||||
// read all service names from process (pgrep)
|
|
||||||
std::array<char, 128> buffer;
|
|
||||||
std::unique_ptr<FILE, decltype(&pclose)> pipe(
|
|
||||||
popen("pgrep -f \"$(which comfortable-swipe)\"", "r"), pclose);
|
|
||||||
|
|
||||||
// make sure pipe exists
|
|
||||||
if (!pipe)
|
|
||||||
throw std::runtime_error("stop command failed");
|
|
||||||
|
|
||||||
// buffer what to kill
|
|
||||||
std::string kill = "";
|
|
||||||
|
|
||||||
// read until end of line
|
|
||||||
while (!std::feof(pipe.get())) {
|
|
||||||
if (std::fgets(buffer.data(), buffer.size(), pipe.get()) != NULL) {
|
|
||||||
int pid = std::atoi(buffer.data());
|
|
||||||
if (pid != getpid()) {
|
|
||||||
kill += " ";
|
|
||||||
kill += std::to_string(pid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// run "kill {pid1} {pid2}..."
|
|
||||||
if (kill.length()) {
|
|
||||||
std::printf("Stopped%s\n", kill.c_str());
|
|
||||||
(void)std::system(("kill" + kill).c_str());
|
|
||||||
} else {
|
|
||||||
std::printf("No program to stop\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // namespace comfortable_swipe::service
|
|
||||||
|
|
||||||
#endif /* __COMFORTABLE_SWIPE__service_stop__ */
|
|
||||||
@ -1,82 +0,0 @@
|
|||||||
#ifndef __COMFORTABLE_SWIPE__start__
|
|
||||||
#define __COMFORTABLE_SWIPE__start__
|
|
||||||
|
|
||||||
/*
|
|
||||||
Comfortable Swipe
|
|
||||||
by Rico Tiongson
|
|
||||||
|
|
||||||
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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "comfortable_swipe.h"
|
|
||||||
#include <cstdio> // fgets_unlocked, stdin
|
|
||||||
#include <iostream> // std::ios, std::cout, std::cin
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The main driver program.
|
|
||||||
*/
|
|
||||||
namespace comfortable_swipe {
|
|
||||||
void start() {
|
|
||||||
// unsync for faster IO
|
|
||||||
std::ios::sync_with_stdio(false);
|
|
||||||
std::cin.tie(0);
|
|
||||||
std::cout.tie(0);
|
|
||||||
std::cout.flush();
|
|
||||||
|
|
||||||
// read config file
|
|
||||||
auto config = comfortable_swipe::util::read_config_file(
|
|
||||||
comfortable_swipe::util::conf_filename());
|
|
||||||
|
|
||||||
// initialize mouse hold gesture handler
|
|
||||||
// for now, this supports 3-finger and 4-finger hold
|
|
||||||
// Examples:
|
|
||||||
// hold3=move move mouse on 3 fingers
|
|
||||||
// hold3=button1 hold button 1 on 3 fingers
|
|
||||||
// hold4=button3 hold button 3 (right click) on 3 fingers
|
|
||||||
// hold3=ignore <do nothing>
|
|
||||||
const char *const hold3 = config["hold3"].c_str();
|
|
||||||
const char *const hold4 = config["hold4"].c_str();
|
|
||||||
comfortable_swipe::gesture::mouse_hold_gesture mouse_hold(hold3, hold4);
|
|
||||||
|
|
||||||
// initialize keyboard swipe gesture handler
|
|
||||||
const float threshold =
|
|
||||||
config.count("threshold") ? std::stof(config["threshold"]) : 0.0;
|
|
||||||
const char *const left3 = config["left3"].c_str();
|
|
||||||
const char *const left4 = config["left4"].c_str();
|
|
||||||
const char *const right3 = config["right3"].c_str();
|
|
||||||
const char *const right4 = config["right4"].c_str();
|
|
||||||
const char *const up3 = config["up3"].c_str();
|
|
||||||
const char *const up4 = config["up4"].c_str();
|
|
||||||
const char *const down3 = config["down3"].c_str();
|
|
||||||
const char *const down4 = config["down4"].c_str();
|
|
||||||
comfortable_swipe::gesture::keyboard_swipe_gesture keyboard_swipe(
|
|
||||||
threshold, left3, left4, right3, right4, up3, up4, down3, down4);
|
|
||||||
|
|
||||||
// prepare data containers
|
|
||||||
std::array<char, 256> line;
|
|
||||||
|
|
||||||
// start reading lines from input one by one
|
|
||||||
while (fgets_unlocked(line.data(), line.size(), stdin) != NULL) {
|
|
||||||
// prioritize mouse hold gesture first
|
|
||||||
mouse_hold.parse_line(line.data());
|
|
||||||
if (!mouse_hold.is_mousedown()) {
|
|
||||||
// if mouse hold fails, try keyboard swipe
|
|
||||||
// attempt to parse keyboard gestures with the same line data
|
|
||||||
keyboard_swipe.parse_line(line.data());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // namespace comfortable_swipe
|
|
||||||
|
|
||||||
#endif /* __COMFORTABLE_SWIPE__start__ */
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
#ifndef __COMFORTABLE_SWIPE__start_h__
|
|
||||||
#define __COMFORTABLE_SWIPE__start_h__
|
|
||||||
|
|
||||||
namespace comfortable_swipe {
|
|
||||||
void start();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* __COMFORTABLE_SWIPE__start_h__ */
|
|
||||||
@ -1,42 +0,0 @@
|
|||||||
#ifndef __COMFORTABLE_SWIPE__util_autostart_filename__
|
|
||||||
#define __COMFORTABLE_SWIPE__util_autostart_filename__
|
|
||||||
|
|
||||||
/*
|
|
||||||
Comfortable Swipe
|
|
||||||
by Rico Tiongson
|
|
||||||
|
|
||||||
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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <string> // std::string
|
|
||||||
#include <unistd.h> // getenv
|
|
||||||
|
|
||||||
namespace comfortable_swipe::util {
|
|
||||||
/**
|
|
||||||
* The path where the autostart configuration is located.
|
|
||||||
*/
|
|
||||||
const char *autostart_filename() {
|
|
||||||
static std::string filename;
|
|
||||||
if (filename.empty()) {
|
|
||||||
const char *xdg_config = getenv("XDG_CONFIG_HOME");
|
|
||||||
std::string config(xdg_config == NULL
|
|
||||||
? std::string(getenv("HOME")) + "/.config"
|
|
||||||
: xdg_config);
|
|
||||||
filename = config + "/autostart/comfortable-swipe.desktop";
|
|
||||||
}
|
|
||||||
return filename.data();
|
|
||||||
}
|
|
||||||
} // namespace comfortable_swipe::util
|
|
||||||
|
|
||||||
#endif /* __COMFORTABLE_SWIPE__util_autostart_filename__ */
|
|
||||||
@ -1,31 +0,0 @@
|
|||||||
#ifndef __COMFORTABLE_SWIPE__util_conf_filename__
|
|
||||||
#define __COMFORTABLE_SWIPE__util_conf_filename__
|
|
||||||
|
|
||||||
/*
|
|
||||||
Comfortable Swipe
|
|
||||||
by Rico Tiongson
|
|
||||||
|
|
||||||
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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "../comfortable_swipe.h"
|
|
||||||
|
|
||||||
namespace comfortable_swipe::util {
|
|
||||||
/**
|
|
||||||
* The path where the configuration file is located.
|
|
||||||
*/
|
|
||||||
constexpr const char *conf_filename() { return COMFORTABLE_SWIPE_CONFIG; }
|
|
||||||
} // namespace comfortable_swipe::util
|
|
||||||
|
|
||||||
#endif /* __COMFORTABLE_SWIPE__util_conf_filename__ */
|
|
||||||
@ -1,94 +0,0 @@
|
|||||||
#ifndef __COMFORTABLE_SWIPE__util_read_config_file__
|
|
||||||
#define __COMFORTABLE_SWIPE__util_read_config_file__
|
|
||||||
|
|
||||||
/*
|
|
||||||
Comfortable Swipe
|
|
||||||
by Rico Tiongson
|
|
||||||
|
|
||||||
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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <cctype> // std::isspace
|
|
||||||
#include <cstdlib> // exit
|
|
||||||
#include <fstream> // std::ifstream
|
|
||||||
#include <iostream> // std::endl, std::getline
|
|
||||||
#include <map> // std::map
|
|
||||||
#include <sstream> // std::ostringstream
|
|
||||||
#include <stdexcept> // std::runtime_error
|
|
||||||
#include <string> // std::string
|
|
||||||
|
|
||||||
namespace comfortable_swipe::util {
|
|
||||||
/**
|
|
||||||
* A utility method for reading the config file.
|
|
||||||
*
|
|
||||||
* @param filename (const char*) the path of the config file.
|
|
||||||
*/
|
|
||||||
std::map<std::string, std::string> read_config_file(const char *filename) {
|
|
||||||
|
|
||||||
std::map<std::string, std::string> conf;
|
|
||||||
std::ifstream fin(filename);
|
|
||||||
|
|
||||||
if (!fin.is_open()) {
|
|
||||||
throw std::runtime_error("config file does not exist");
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::string line, token[2];
|
|
||||||
int line_number = 0;
|
|
||||||
|
|
||||||
while (std::getline(fin, line)) {
|
|
||||||
++line_number;
|
|
||||||
token[0].clear();
|
|
||||||
token[1].clear();
|
|
||||||
int length = line.length();
|
|
||||||
int equal_flag = 0;
|
|
||||||
|
|
||||||
// tokenize comfig config
|
|
||||||
for (int i = 0; i < length; ++i) {
|
|
||||||
if (line[i] == '#') // skip comments
|
|
||||||
break;
|
|
||||||
if (line[i] == '=') // flag equal sign
|
|
||||||
{
|
|
||||||
if (++equal_flag > 1) {
|
|
||||||
std::ostringstream stream;
|
|
||||||
stream << "error in conf file " << filename << std::endl;
|
|
||||||
stream << "multiple equal signs in line " << line_number << std::endl;
|
|
||||||
throw std::runtime_error(stream.str());
|
|
||||||
}
|
|
||||||
} else if (!std::isspace(line[i])) {
|
|
||||||
// add to buffer
|
|
||||||
token[equal_flag].push_back(line[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ignore empty lines
|
|
||||||
if (equal_flag == 0 && token[0].length() == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// no equal sign found in non-empty line
|
|
||||||
if (equal_flag == 0) {
|
|
||||||
std::ostringstream stream;
|
|
||||||
stream << "error in conf file: " << filename << std::endl;
|
|
||||||
stream << "equal sign expected in line " << line_number << std::endl;
|
|
||||||
throw std::runtime_error(stream.str());
|
|
||||||
}
|
|
||||||
|
|
||||||
// equal sign found, add to tokens
|
|
||||||
if (token[1].length() > 0)
|
|
||||||
conf[token[0]] = token[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
return conf;
|
|
||||||
}
|
|
||||||
} // namespace comfortable_swipe::util
|
|
||||||
#endif /* __COMFORTABLE_SWIPE__util_read_config_file__ */
|
|
||||||
@ -3,9 +3,10 @@
|
|||||||
set -e
|
set -e
|
||||||
|
|
||||||
DIR="$(dirname "$0")"
|
DIR="$(dirname "$0")"
|
||||||
|
COMPILER="$(dirname "$DIR")/compile"
|
||||||
|
|
||||||
# just call abort on error
|
# just call abort on error
|
||||||
tempout="$(mktemp)"
|
TEMPOUT="$(mktemp)"
|
||||||
abort () {
|
abort () {
|
||||||
rm "$tempout"
|
rm "$tempout"
|
||||||
echo "Test aborted"
|
echo "Test aborted"
|
||||||
@ -13,12 +14,15 @@ abort () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# run all shell files in this directory
|
# run all shell files in this directory
|
||||||
for sh in "$DIR/test_"*.sh; do
|
for SH in "$DIR/test_"*.sh; do
|
||||||
/bin/bash "$sh" || abort
|
"$SH" || abort
|
||||||
done
|
done
|
||||||
|
|
||||||
# run all cpp files in this directory
|
# run all cpp files in this directory
|
||||||
for cpp in "$DIR/test_"*.cpp; do
|
for CPP in "$DIR/test_"*.cpp; do
|
||||||
g++ -std=c++11 -O2 "$cpp" -lxdo -o "$tempout" || abort
|
# compile the test
|
||||||
"$tempout" || abort
|
"$COMPILER" "$CPP" -o "$TEMPOUT" || abort
|
||||||
|
# run the test
|
||||||
|
chmod +x "$TEMPOUT"
|
||||||
|
"$TEMPOUT"
|
||||||
done
|
done
|
||||||
|
|||||||
@ -1,32 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -ex
|
|
||||||
|
|
||||||
DIR="$(dirname "$0")"
|
|
||||||
root="$(dirname "$DIR")"
|
|
||||||
compiler="$root/cpp.compile.sh"
|
|
||||||
command_line="$root/command_line.cpp"
|
|
||||||
module="$root/comfortable_swipe"
|
|
||||||
|
|
||||||
# just call abort on error
|
|
||||||
tempout="$(mktemp)"
|
|
||||||
abort () {
|
|
||||||
rm "$tempout"
|
|
||||||
echo "Test aborted"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
# try to compile every cpp/hpp file in module
|
|
||||||
# header files first
|
|
||||||
# then compile cpp files
|
|
||||||
# finally, compile command line
|
|
||||||
shopt -s nullglob
|
|
||||||
for cpp in \
|
|
||||||
"$module"/**/*.h \
|
|
||||||
"$module"/**/*.hpp \
|
|
||||||
"$module"/**/*.cpp \
|
|
||||||
"$module"/lib \
|
|
||||||
"$command_line"
|
|
||||||
do
|
|
||||||
"$compiler" -c "$cpp" -o "$tempout" || abort
|
|
||||||
done
|
|
||||||
@ -1,5 +1,4 @@
|
|||||||
#include "../comfortable_swipe/gesture/swipe_gesture.h"
|
#include "../comfortable-swipe-gesture-swipe.cpp"
|
||||||
#include "../comfortable_swipe/gesture/swipe_gesture.regex.cpp"
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
@ -53,8 +52,7 @@ void gesture_begin_test(const std::regex &matcher, const char *data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void gesture_begin_should_match_regex() {
|
void gesture_begin_should_match_regex() {
|
||||||
std::regex matcher(
|
std::regex matcher = comfortable_swipe::gesture_swipe::GESTURE_SWIPE_BEGIN;
|
||||||
comfortable_swipe::gesture::swipe_gesture::GESTURE_BEGIN_REGEX_PATTERN);
|
|
||||||
test::gesture_begin_test(matcher, " event15 GESTURE_SWIPE_BEGIN +34.33s 3\n",
|
test::gesture_begin_test(matcher, " event15 GESTURE_SWIPE_BEGIN +34.33s 3\n",
|
||||||
"3");
|
"3");
|
||||||
test::gesture_begin_test(matcher, "-event4 GESTURE_SWIPE_BEGIN +3.12s 4\n",
|
test::gesture_begin_test(matcher, "-event4 GESTURE_SWIPE_BEGIN +3.12s 4\n",
|
||||||
@ -68,8 +66,7 @@ void gesture_begin_should_match_regex() {
|
|||||||
void gesture_update_should_match_regex() {
|
void gesture_update_should_match_regex() {
|
||||||
const char *data = " event15 GESTURE_SWIPE_UPDATE +34.70s 3 -0.12/ 4.99 "
|
const char *data = " event15 GESTURE_SWIPE_UPDATE +34.70s 3 -0.12/ 4.99 "
|
||||||
"(-0.33/13.50 unaccelerated)\n";
|
"(-0.33/13.50 unaccelerated)\n";
|
||||||
std::regex matcher(
|
std::regex matcher = comfortable_swipe::gesture_swipe::GESTURE_SWIPE_UPDATE;
|
||||||
comfortable_swipe::gesture::swipe_gesture::GESTURE_UPDATE_REGEX_PATTERN);
|
|
||||||
std::cmatch matches;
|
std::cmatch matches;
|
||||||
auto result = std::regex_match(data, matches, matcher);
|
auto result = std::regex_match(data, matches, matcher);
|
||||||
assert(result != 0);
|
assert(result != 0);
|
||||||
@ -82,8 +79,7 @@ void gesture_update_should_match_regex() {
|
|||||||
|
|
||||||
void gesture_end_should_match_regex() {
|
void gesture_end_should_match_regex() {
|
||||||
const char *data = " event15 GESTURE_SWIPE_END +35.03s 3\n";
|
const char *data = " event15 GESTURE_SWIPE_END +35.03s 3\n";
|
||||||
std::regex matcher(
|
std::regex matcher = comfortable_swipe::gesture_swipe::GESTURE_SWIPE_END;
|
||||||
comfortable_swipe::gesture::swipe_gesture::GESTURE_END_REGEX_PATTERN);
|
|
||||||
std::cmatch matches;
|
std::cmatch matches;
|
||||||
auto result = std::regex_match(data, matches, matcher);
|
auto result = std::regex_match(data, matches, matcher);
|
||||||
assert(result != 0);
|
assert(result != 0);
|
||||||
|
|||||||
103
tests/test_swipe.sh
Executable file
103
tests/test_swipe.sh
Executable file
@ -0,0 +1,103 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -ex
|
||||||
|
|
||||||
|
DIR="$(dirname "$0")"
|
||||||
|
ROOT="$(dirname "$DIR")"
|
||||||
|
COMPILER="$ROOT/compile"
|
||||||
|
|
||||||
|
# just call abort on error
|
||||||
|
TEMPOUT="$(mktemp)"
|
||||||
|
abort () {
|
||||||
|
echo "Test aborted"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# try to compile main test
|
||||||
|
# use empty configuration /dev/null
|
||||||
|
EMPTY_CONFIG="$(mktemp)"
|
||||||
|
echo "threshold = 0.0" >> "$EMPTY_CONFIG"
|
||||||
|
"$COMPILER" "$ROOT/comfortable-swipe-main.cpp" -o "$TEMPOUT" \
|
||||||
|
-DCOMFORTABLE_SWIPE_AUTOSTART="\"$ROOT/comfortable-swipe.desktop\"" \
|
||||||
|
-DCOMFORTABLE_SWIPE_CONFIG="\"$EMPTY_CONFIG\"" \
|
||||||
|
|| abort
|
||||||
|
chmod +x "$TEMPOUT"
|
||||||
|
|
||||||
|
set +x
|
||||||
|
|
||||||
|
# try to run start, then wait for the user to swipe
|
||||||
|
echo "Simulating swipe..."
|
||||||
|
|
||||||
|
# get output result
|
||||||
|
OUTPUT="$(mktemp)"
|
||||||
|
"$TEMPOUT" <<EOF > "$OUTPUT"
|
||||||
|
event7 GESTURE_SWIPE_BEGIN +1.72s 3
|
||||||
|
event7 GESTURE_SWIPE_UPDATE +1.72s 3 -12.26/-0.42 (-33.14/-1.12 unaccelerated)
|
||||||
|
event7 GESTURE_SWIPE_UPDATE +1.73s 3 -14.08/ 0.00 (-38.06/ 0.00 unaccelerated)
|
||||||
|
event7 GESTURE_SWIPE_UPDATE +1.74s 3 -15.78/-0.42 (-42.65/-1.12 unaccelerated)
|
||||||
|
event7 GESTURE_SWIPE_UPDATE +1.75s 3 -16.63/-0.14 (-44.95/-0.37 unaccelerated)
|
||||||
|
event7 GESTURE_SWIPE_UPDATE +1.75s 3 -16.63/-0.42 (-44.95/-1.12 unaccelerated)
|
||||||
|
event7 GESTURE_SWIPE_UPDATE +1.76s 3 -16.39/ 0.14 (-44.29/ 0.37 unaccelerated)
|
||||||
|
event7 GESTURE_SWIPE_UPDATE +1.77s 3 -15.66/ 0.28 (-42.32/ 0.75 unaccelerated)
|
||||||
|
event7 GESTURE_SWIPE_UPDATE +1.78s 3 -13.96/ 0.55 (-37.73/ 1.50 unaccelerated)
|
||||||
|
event7 GESTURE_SWIPE_UPDATE +1.78s 3 -12.38/ 0.28 (-33.46/ 0.75 unaccelerated)
|
||||||
|
event7 GESTURE_SWIPE_UPDATE +1.79s 3 -10.56/ 0.55 (-28.54/ 1.50 unaccelerated)
|
||||||
|
event7 GESTURE_SWIPE_UPDATE +1.80s 3 -8.86/ 0.69 (-23.95/ 1.87 unaccelerated)
|
||||||
|
event7 GESTURE_SWIPE_UPDATE +1.81s 3 -6.92/ 1.53 (-18.70/ 4.12 unaccelerated)
|
||||||
|
event7 GESTURE_SWIPE_UPDATE +1.81s 3 -5.10/ 1.53 (-13.78/ 4.12 unaccelerated)
|
||||||
|
event7 GESTURE_SWIPE_UPDATE +1.82s 3 -4.13/ 1.39 (-11.15/ 3.75 unaccelerated)
|
||||||
|
event7 GESTURE_SWIPE_UPDATE +1.83s 3 -3.40/ 0.97 (-9.19/ 2.62 unaccelerated)
|
||||||
|
event7 GESTURE_SWIPE_UPDATE +1.84s 3 -2.43/ 0.97 (-6.56/ 2.62 unaccelerated)
|
||||||
|
event7 GESTURE_SWIPE_UPDATE +1.84s 3 -1.82/ 0.69 (-4.92/ 1.87 unaccelerated)
|
||||||
|
event7 GESTURE_SWIPE_UPDATE +1.85s 3 -0.97/ 0.69 (-2.62/ 1.87 unaccelerated)
|
||||||
|
event7 GESTURE_SWIPE_UPDATE +1.86s 3 -0.36/ 0.69 (-0.98/ 1.87 unaccelerated)
|
||||||
|
event7 GESTURE_SWIPE_UPDATE +1.87s 3 -0.24/ 0.42 (-0.66/ 1.12 unaccelerated)
|
||||||
|
event7 GESTURE_SWIPE_UPDATE +1.88s 3 0.23/ 0.26 ( 0.66/ 0.75 unaccelerated)
|
||||||
|
event7 GESTURE_SWIPE_UPDATE +1.88s 3 0.99/ 0.13 ( 2.95/ 0.37 unaccelerated)
|
||||||
|
event7 GESTURE_SWIPE_UPDATE +1.89s 3 2.31/ 0.42 ( 6.23/ 1.12 unaccelerated)
|
||||||
|
event7 GESTURE_SWIPE_UPDATE +1.90s 3 3.88/ 0.97 (10.50/ 2.62 unaccelerated)
|
||||||
|
event7 GESTURE_SWIPE_UPDATE +1.91s 3 7.65/ 0.55 (20.67/ 1.50 unaccelerated)
|
||||||
|
event7 GESTURE_SWIPE_UPDATE +1.91s 3 12.26/ 0.55 (33.14/ 1.50 unaccelerated)
|
||||||
|
event7 GESTURE_SWIPE_UPDATE +1.92s 3 17.36/-0.42 (46.92/-1.12 unaccelerated)
|
||||||
|
event7 GESTURE_SWIPE_UPDATE +1.93s 3 21.73/-1.25 (58.73/-3.37 unaccelerated)
|
||||||
|
event7 GESTURE_SWIPE_UPDATE +1.94s 3 24.64/-2.64 (66.60/-7.12 unaccelerated)
|
||||||
|
event7 GESTURE_SWIPE_UPDATE +1.94s 3 26.95/-3.75 (72.83/-10.12 unaccelerated)
|
||||||
|
event7 GESTURE_SWIPE_UPDATE +1.95s 3 27.80/-4.72 (75.13/-12.75 unaccelerated)
|
||||||
|
event7 GESTURE_SWIPE_UPDATE +1.96s 3 27.07/-4.86 (73.16/-13.12 unaccelerated)
|
||||||
|
event7 GESTURE_SWIPE_UPDATE +1.97s 3 25.49/-5.27 (68.90/-14.25 unaccelerated)
|
||||||
|
event7 GESTURE_SWIPE_UPDATE +1.97s 3 23.06/-4.72 (62.34/-12.75 unaccelerated)
|
||||||
|
event7 GESTURE_SWIPE_UPDATE +1.98s 3 20.15/-4.16 (54.46/-11.25 unaccelerated)
|
||||||
|
event7 GESTURE_SWIPE_UPDATE +1.99s 3 17.24/-3.33 (46.59/-9.00 unaccelerated)
|
||||||
|
event7 GESTURE_SWIPE_UPDATE +2.00s 3 13.84/-2.64 (37.40/-7.12 unaccelerated)
|
||||||
|
event7 GESTURE_SWIPE_UPDATE +2.00s 3 10.80/-1.80 (29.20/-4.87 unaccelerated)
|
||||||
|
event7 GESTURE_SWIPE_UPDATE +2.01s 3 7.77/-0.83 (21.00/-2.25 unaccelerated)
|
||||||
|
event7 GESTURE_SWIPE_UPDATE +2.02s 3 5.46/ 0.14 (14.76/ 0.37 unaccelerated)
|
||||||
|
event7 GESTURE_SWIPE_UPDATE +2.03s 3 3.03/ 0.28 ( 8.20/ 0.75 unaccelerated)
|
||||||
|
event7 GESTURE_SWIPE_UPDATE +2.04s 3 1.82/ 0.00 ( 4.92/ 0.00 unaccelerated)
|
||||||
|
event7 GESTURE_SWIPE_UPDATE +2.04s 3 0.61/-0.28 ( 1.64/-0.75 unaccelerated)
|
||||||
|
event7 GESTURE_SWIPE_UPDATE +2.05s 3 0.24/-0.14 ( 0.66/-0.37 unaccelerated)
|
||||||
|
event7 GESTURE_SWIPE_UPDATE +2.06s 3 -0.22/ 0.13 (-0.66/ 0.37 unaccelerated)
|
||||||
|
event7 GESTURE_SWIPE_UPDATE +2.07s 3 0.00/ 0.06 ( 0.00/ 0.37 unaccelerated)
|
||||||
|
event7 GESTURE_SWIPE_UPDATE +2.09s 3 -0.05/ 0.06 (-0.33/ 0.37 unaccelerated)
|
||||||
|
event7 GESTURE_SWIPE_UPDATE +2.10s 3 -0.05/ 0.00 (-0.33/ 0.00 unaccelerated)
|
||||||
|
event7 GESTURE_SWIPE_UPDATE +2.10s 3 -0.05/ 0.05 (-0.33/ 0.37 unaccelerated)
|
||||||
|
event7 GESTURE_SWIPE_UPDATE +2.11s 3 -0.05/ 0.06 (-0.33/ 0.37 unaccelerated)
|
||||||
|
event7 GESTURE_SWIPE_UPDATE +2.12s 3 0.05/ 0.00 ( 0.33/ 0.00 unaccelerated)
|
||||||
|
event7 GESTURE_SWIPE_UPDATE +2.13s 3 -0.11/ 0.00 (-0.66/ 0.00 unaccelerated)
|
||||||
|
event7 GESTURE_SWIPE_UPDATE +2.13s 3 0.00/ 0.07 ( 0.00/ 0.37 unaccelerated)
|
||||||
|
event7 GESTURE_SWIPE_UPDATE +2.14s 3 -2.41/-0.50 (-7.22/-1.50 unaccelerated)
|
||||||
|
event7 GESTURE_SWIPE_END +2.19s 3
|
||||||
|
EOF
|
||||||
|
|
||||||
|
EXPECTED_OUTPUT="SWIPE left3 SWIPE right3"
|
||||||
|
ACTUAL_OUTPUT="$(cat "$OUTPUT" | xargs)"
|
||||||
|
echo "My output: $ACTUAL_OUTPUT"
|
||||||
|
echo "Expected: $EXPECTED_OUTPUT"
|
||||||
|
|
||||||
|
if [[ "$ACTUAL_OUTPUT" == "$EXPECTED_OUTPUT" ]]; then
|
||||||
|
echo "PASSED"
|
||||||
|
else
|
||||||
|
echo "Did not match expected output:" >&2
|
||||||
|
echo "$EXPECTED_OUTPUT" >&2
|
||||||
|
abort
|
||||||
|
fi
|
||||||
41
uninstall
41
uninstall
@ -1,8 +1,37 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
echo "Uninstalling..."
|
set -e
|
||||||
rm "${XDG_CONFIG_HOME:-$HOME/.config}/autostart/comfortable-swipe.desktop" 2> /dev/null
|
|
||||||
comfortable-swipe stop 2> /dev/null
|
function trysudo {
|
||||||
rm "$HOME/.local/bin/comfortable-swipe" 2> /dev/null # compat
|
$@ 2> /dev/null || sudo $@
|
||||||
sudo rm /usr/local/bin/comfortable-swipe 2> /dev/null
|
}
|
||||||
echo "Successfully uninstalled comfortable-swipe"
|
|
||||||
|
function uninstall {
|
||||||
|
TARGET="${1?missing uninstall parameter}"
|
||||||
|
if [[ -f "$TARGET" ]]; then
|
||||||
|
trysudo rm -f "$TARGET"
|
||||||
|
echo "Removed: $TARGET"
|
||||||
|
elif [[ ! -z "$TARGET" ]]; then
|
||||||
|
echo "Not found: $TARGET"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# stop program first if it is still running
|
||||||
|
comfortable-swipe stop 2> /dev/null || true
|
||||||
|
|
||||||
|
# uninstall binaries
|
||||||
|
uninstall "$(which comfortable-swipe || echo /usr/share/bin/comfortable-swipe)"
|
||||||
|
uninstall "$(which comfortable-swipe-buffer || echo /usr/share/bin/comfortable-swipe-buffer)"
|
||||||
|
|
||||||
|
# uninstall desktop file
|
||||||
|
uninstall "$HOME/.config/autostart/comfortable-swipe.desktop"
|
||||||
|
|
||||||
|
# tell user we are keeping configuration file
|
||||||
|
CONF_TARGET="$HOME/.config/comfortable-swipe.conf"
|
||||||
|
if [ -f "$CONF_TARGET" ]; then
|
||||||
|
echo "Keeping your configuration file: $CONF_TARGET"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cat <<EOF
|
||||||
|
Successfully uninstalled comfortable-swipe
|
||||||
|
EOF
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user