diff --git a/.gitignore b/.gitignore index 2fca53d..f71ba51 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ # C++ generated headers *.gch +*.o # IDE-specific .idea diff --git a/CHANGELOG b/CHANGELOG index 601e2be..cf43744 100644 --- a/CHANGELOG +++ b/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) * Add mouse hold gestures * Add experimental `hold3` configuration diff --git a/README.md b/README.md index c4cfe5d..3038380 100644 --- a/README.md +++ b/README.md @@ -3,81 +3,217 @@ [![comfortable-swipe version](https://img.shields.io/github/release/Hikari9/comfortable-swipe.svg?label=comfortable-swipe&color=orange)](https://github.com/Hikari9/comfortable-swipe/releases) [![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blue.svg)](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`. +> **_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 -1. Install git, libinput, and g++ +1. Install git and g++ ```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 libconfuse-dev libxdo-dev + ``` + +1. Clone this repository ```bash git clone https://github.com/Hikari9/comfortable-swipe.git --depth 1 cd comfortable-swipe ``` -3. Install +1. Install ```bash 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 1. You'll need some group permissions to read touchpad input data. Run + ```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 + +## List of Commands + +1. Start the Program + ``` comfortable-swipe start ``` -4. _Optional_: Automatically run on startup + + You will see this output: + ``` - comfortable-swipe autostart - ``` -5. Check the status of your application by running - ``` - comfortable-swipe status + $ comfortable-swipe start + Comfortable swipe is RUNNING in the background ``` -## Swipe Configurations +1. Autostart (this is turned on by default) -Comfortable swipe makes use of keyboard shortcuts for configurations. Edit by running: + ```bash + comfortable-swipe autostart [on|off|toggle|status|path] + ``` + +1. List configurations + + ```bash + If you want to list down configurations, you can run: + + comfortable-swipe config list + + Configuration: + + comfortable-swipe gets configuration property + comfortable-swipe [=] sets configuration to a value + + Valid props: left3, left4, right3, right4, up3, up4, down3, down4, threshold, mouse3, mouse4 + ``` + +1. Get config (examples) + + ```bash + $ comfortable-swipe left3 + ctrl+alt+Right + + $ comfortable-swipe left4 + ctrl+alt+shift+Right + + $ comfortable-swipe right3 + ctrl+alt+Left + + $ comfortable-swipe right4 + ctrl+alt+shift+Left + + $ comfortable-swipe up3 + ctrl+alt+Down + + $ comfortable-swipe up4 + ctrl+alt+shift+Down + + $ comfortable-swipe down3 + ctrl+alt+Up + + $ comfortable-swipe down4 + ctrl+alt+shift+Up + + $ comfortable-swipe threshold + 1.0 + ``` + +1. Set config (examples) + + ```bash + $ comfortable-swipe left3 = super+Right + left3 = super+Right + + $ comfortable-swipe right3 = super+Left + right3 = super+Left + + $ comfortable-swipe right4 = super + Left + alt + right4 = super+Left+alt + ``` + +1. Delete config + + ```bash + $ comfortable-swipe config delete mouse3 + Deleted: + mouse3 = button1 + ``` + +1. List all cofigurations + + ```bash + $ comfortable-swipe config list + threshold = 1.0 + left4 = ctrl+super+shift+Right + right3 = ctrl+super+Left + right4 = ctrl+super+shift+Left + up3 = ctrl+F12 + up4 = super+d + down3 = ctrl+F12 + down4 = super+d + mouse4 = button1 + left3 = ctrl+super+Right + ``` + +1. Show path to config file: + + ```bash + $ comfortable-swipe config path + /home/hikari9/.config/comfortable-swipe.conf + ``` + +1. (Advanced) 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 + ... + ``` + + You can also pass `--bare` to attach without actually swiping. + +## Swipe 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`. + +Edit the configuration file by running: ``` -gedit $(comfortable-swipe config) +gedit ~/.config/comfortable-swipe.conf ``` -| Property | Description | Default Value | Default Behavior | -| --------- | :------------------------------------------: | -------------------- | -------------------------------------------------------------------------------------------------------------------------- | -| 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 +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 + +| Key | Value | Defaults | +| --------- | :--------------------------------------------------------------------: | ----------------------------------------------------------------- | +| 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
(see [Mouse Gestures](#mouse-gestures-experimental)) | | +| mouse4 | mouses a mouse button when 4 fingers are down | button1
(see [Mouse Gestures](#mouse-gestures-experimental) | + +### Keystrokes + Taken from `man xdotool`: > Type a given keystroke. Examples being "alt+r", "Control_L+J", @@ -94,42 +230,50 @@ Taken from `man xdotool`: Refer to https://www.linux.org/threads/xdotool-keyboard.10528/ for a complete list of keycodes you can use. -**Keyboard Shortcuts**: +Keyboard shortcuts: -- Unity: https://cheatography.com/sapemeg/cheat-sheets/ubuntu-unity-16-04/ -- GNOME: https://wiki.gnome.org/Design/OS/KeyboardShortcuts -- KDE: https://community.linuxmint.com/tutorial/view/47 +- [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) -## Swipe Gesture Templates +## Example Configurations -1. Switching workspaces +This section includes some example configurations which you can use for your swipe experience. + +1. Switch workspace (horizontal) ```bash - # Unity, KDE - left3 = ctrl+alt+Right - right3 = ctrl+alt+Left + comfortable-swipe config set left3 = ctrl+alt+Right + comfortable-swipe config set right3 = ctrl+alt+Left + ``` + +1. Switch workspace (vertical) + + ``` up3 = ctrl+alt+Down down3 = ctrl+alt+Up ``` ```bash - # GNOME up3 = super+PgDown down3 = super+PgUp ``` -1. Move window to workspace +1. Move window to workspace (horizontal) ```bash - # Unity, KDE left4 = ctrl+alt+shift+Right right4 = ctrl+alt+shift+Left + ``` + +1. Move window to workspace (vertical) + + ```bash up4 = ctrl+alt+shift+Down down4 = ctrl+alt+shift+Up ``` ```bash - # GNOME up4 = super+shift+PgDown down4 = super+shift+PgUp ``` @@ -137,7 +281,6 @@ Refer to https://www.linux.org/threads/xdotool-keyboard.10528/ for a complete li 1. Move window to other monitor ```bash - # GNOME left4 = super+shift+Right right4 = super+shift+Left ``` @@ -148,20 +291,17 @@ Refer to https://www.linux.org/threads/xdotool-keyboard.10528/ for a complete li up3 = super+s ``` -1. Show desktop ([setup manually](https://www.itsupportguides.com/knowledge-base/ubuntu/ubuntu-how-to-make-windows-d-show-desktop/)) +1. Show desktop ```bash - # Ubuntu - down3 = ctrl+super+d - ``` - - ```bash - # GNOME down3 = super+d ``` ```bash - # KDE + down3 = ctrl+super+d + ``` + + ```bash down3 = ctrl+alt+d ``` @@ -193,64 +333,67 @@ Refer to https://www.linux.org/threads/xdotool-keyboard.10528/ for a complete li ## 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 -Possible Values (hold3, hold4): +Keys: -move # just move the mouse cursor (no mousedown) -button1 # hold left click on finger swipe -button2 # hold middle click on finger swipe -button3 # hold right click on finger swipe -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) -``` +- mouse3 - for 3-finger mouse gestures +- mouse4 - for 4-finger mosue gestures +- hold3 (deprecated) - old equivalent of mouse3 +- hold4 (deprecated) - old equivalent of mouse4 -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) Examples: -- 3-finger drag +- 3/4-finger drag + ```bash + mouse3 = button1 + ``` + ```bash + mouse4 = button1 + ``` +- 3/4-finger natural scroll ```bash - hold3 = button1 + mouse3 = scroll ``` -- 4-finger drag (with middle click) - ```bash - hold4 = button2 + mouse4 = scroll ``` -- 3-finger natural scroll +- 3/4-finger reverse scroll ```bash - hold3 = scroll + mouse3 = scroll_reverse ``` -- 4-finger reverse scroll - ```bash - hold4 = scroll_reverse + mouse4 = scroll_reverse ``` -- Just move the cursor +- Move 3/4-fingers with the cursor ```bash - hold3 = move - hold4 = move + mouse3 = move ``` -- Any other command will disable the mouse hold - ```bash - hold3 = disabled - hold4 = nothing + mouse4 = move ``` -**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. +**Note**: Applying any mouse-mouse configuration may disable up/left/right/down behavior to avoid gesture conflicts. The logic of this will be improved in the future. ## Debugging @@ -270,25 +413,151 @@ $ 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 - ... +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 +... ``` 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 near-zero-overhead implementation (that's why C++) +2. Running a new shell command with unpredictable process time will break our unthreaded optimizations (unlike native keystrokes) +3. 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 + +That's why it's not possible... + +**Answer 2**: _... but actually **YES**!_ + +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. + +**Use Case**: _"I want to run `gnome-terminal` if I swipe up with 3 fingers."_ + +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@ ) | \ + tee >(grep "SWIPE left4" --line-buffered | xargs -I@ ) | \ + tee >(grep "SWIPE right3" --line-buffered | xargs -I@ ) | \ + tee >(grep "SWIPE right4" --line-buffered | xargs -I@ ) | \ + tee >(grep "SWIPE up3" --line-buffered | xargs -I@ ) | \ + tee >(grep "SWIPE up4" --line-buffered | xargs -I@ ) | \ + tee >(grep "SWIPE down3" --line-buffered | xargs -I@ ) | \ + tee >(grep "SWIPE down4" --line-buffered | xargs -I@ ) + ``` + + Substitute `` with the shell command of your choice. + ## Uninstall +Run the following script: + ```bash wget -qO - https://raw.githubusercontent.com/Hikari9/comfortable-swipe/master/uninstall | bash ``` diff --git a/VERSION b/VERSION index 758fc0b..1a0e369 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v1.1.0 +v1.2.0 diff --git a/comfortable-swipe b/comfortable-swipe new file mode 100755 index 0000000..c343cef --- /dev/null +++ b/comfortable-swipe @@ -0,0 +1,503 @@ +#!/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 <] + +Configuration: + + $BASENAME gets configuration property + $BASENAME [=] sets configuration to a value + +EOF +} +# show help +function help { + usage +cat <&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 &1 | "$BASENAME" buffer $@ >/dev/null 2>&1 & + 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 # +########## + + +# verbosely show comfortable-swipe status +function status { + # TODO: show configuration status as well + echo "Autostart is $("$BASENAME" autostart status)" + if pgrep -f "$BASENAME" | fgrep -v $$ > /dev/null 2>&1; then + echo "Program is RUNNING" + else + echo "Program is STOPPED" + fi +} + + +########## +# 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 " + 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 [...]" + } + # 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 [[ "$(status)" == ON ]]; then + stop > /dev/null 2>&1 + 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 [=] " + 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 [[ "$(status)" == ON ]]; then + stop > /dev/null 2>&1 + 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 + "$BASENAME" config get "$1" || abort + else + # multiple arguments, use shorthand set + "$BASENAME" config set "$@" 2> /dev/null || abort + fi +fi diff --git a/comfortable-swipe-defines.cpp b/comfortable-swipe-defines.cpp new file mode 100644 index 0000000..1f99873 --- /dev/null +++ b/comfortable-swipe-defines.cpp @@ -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 . +*/ +/** + * 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__ */ diff --git a/comfortable-swipe-gesture-swipe-xdokey.cpp b/comfortable-swipe-gesture-swipe-xdokey.cpp new file mode 100644 index 0000000..ae48584 --- /dev/null +++ b/comfortable-swipe-gesture-swipe-xdokey.cpp @@ -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 . +*/ + +#include // std::array +#include // std::cout, std::endl +#include // std::string + +extern "C" { +#include // 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 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 + * + * 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 + // | | + "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 + 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__ */ diff --git a/comfortable-swipe-gesture-swipe-xdomouse.cpp b/comfortable-swipe-gesture-swipe-xdomouse.cpp new file mode 100644 index 0000000..91c6602 --- /dev/null +++ b/comfortable-swipe-gesture-swipe-xdomouse.cpp @@ -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 . +*/ +#include // std::sscanf +#include // strncmp +#include // std::cout, std::endl + +extern "C" { +#include // 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__ */ diff --git a/comfortable-swipe-gesture-swipe.cpp b/comfortable-swipe-gesture-swipe.cpp new file mode 100644 index 0000000..20ec0b1 --- /dev/null +++ b/comfortable-swipe-gesture-swipe.cpp @@ -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 . +*/ +#include // std::cout, std::endl +#include // std::regex, std::regex_match, std::cmatch +#include // std::stoi, std::stof +extern "C" { +#include // 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__ */ diff --git a/comfortable-swipe-main.cpp b/comfortable-swipe-main.cpp new file mode 100644 index 0000000..d7e8e82 --- /dev/null +++ b/comfortable-swipe-main.cpp @@ -0,0 +1,132 @@ +#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 . +*/ +#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 // std::ios, std::cin, std::getline +#include // std::map +#include // std::set +#include // std::string + +extern "C" { +#include // 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 *)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 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(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 (std::invalid_argument) { + } + // 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"]; + // 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);) { + // 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 diff --git a/comfortable_swipe/all_headers.hpp b/comfortable_swipe/all_headers.hpp deleted file mode 100644 index 19d74ec..0000000 --- a/comfortable_swipe/all_headers.hpp +++ /dev/null @@ -1,78 +0,0 @@ -/** - * Add header files will be imported here. - * You can import this as a shorthand: - * - * #include "../all_headers.hpp" - */ - -#ifndef __COMFORTABLE_SWIPE__all_headers_hpp__ -#define __COMFORTABLE_SWIPE__all_headers_hpp__ - -/* -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 . -*/ - -// 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 // std::map -#include // std::string - -extern "C" { -namespace comfortable_swipe { -// driver method -int driver(); -// this is found in the util/ folder -namespace util { -const char *autostart_filename(); -constexpr const char *conf_filename(); -std::map 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" - -#endif /* __COMFORTABLE_SWIPE__all_headers_hpp__ */ diff --git a/comfortable_swipe/driver.cpp b/comfortable_swipe/driver.cpp deleted file mode 100644 index 0c3d4cf..0000000 --- a/comfortable_swipe/driver.cpp +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef __COMFORTABLE_SWIPE__driver__ -#define __COMFORTABLE_SWIPE__driver__ - -/* -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 . -*/ - -#include "all_headers.hpp" -#include // fgets_unlocked, stdin -#include // std::ios, std::cout, std::cin - -/** - * The main driver program. - */ -namespace comfortable_swipe { -int driver() { - // 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 - comfortable_swipe::gesture::mouse_hold_gesture mouse_hold( - config["hold3"].c_str(), config["hold4"].c_str()); - - // initialize keyboard swipe gesture handler - comfortable_swipe::gesture::keyboard_swipe_gesture keyboard_swipe( - config.count("threshold") ? std::stof(config["threshold"]) : 0.0, - config["left3"].c_str(), config["left4"].c_str(), - config["right3"].c_str(), config["right4"].c_str(), config["up3"].c_str(), - config["up4"].c_str(), config["down3"].c_str(), config["down4"].c_str()); - - // prepare data containers - std::array 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 fails, try keyboard hold - if (!mouse_hold.is_mousedown()) { - // attempt to parse keyboard gestures - keyboard_swipe.parse_line(line.data()); - } - } - - return 0; -} -} // namespace comfortable_swipe - -#endif /* __COMFORTABLE_SWIPE__driver__ */ diff --git a/comfortable_swipe/gesture/keyboard_swipe_gesture.cpp b/comfortable_swipe/gesture/keyboard_swipe_gesture.cpp deleted file mode 100644 index c4b2c72..0000000 --- a/comfortable_swipe/gesture/keyboard_swipe_gesture.cpp +++ /dev/null @@ -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 . -*/ - -#include "keyboard_swipe_gesture.h" -#include // std::cout, std::endl - -extern "C" { -#include // 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__ */ diff --git a/comfortable_swipe/gesture/keyboard_swipe_gesture.h b/comfortable_swipe/gesture/keyboard_swipe_gesture.h deleted file mode 100644 index 957077a..0000000 --- a/comfortable_swipe/gesture/keyboard_swipe_gesture.h +++ /dev/null @@ -1,84 +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 . -*/ - -#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]; - }; -} - -#ifdef __cplusplus -} -#endif - -#endif /* __COMFORTABLE_SWIPE__gesture_keyboard_swipe_gesture_h__ */ diff --git a/comfortable_swipe/gesture/mouse_hold_gesture.cpp b/comfortable_swipe/gesture/mouse_hold_gesture.cpp deleted file mode 100644 index c0fa724..0000000 --- a/comfortable_swipe/gesture/mouse_hold_gesture.cpp +++ /dev/null @@ -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 . -*/ - -#include "mouse_hold_gesture.h" -#include // std::sscanf -#include // strncmp -#include // std::cout, std::endl - -extern "C" { -#include // 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__ */ diff --git a/comfortable_swipe/gesture/mouse_hold_gesture.h b/comfortable_swipe/gesture/mouse_hold_gesture.h deleted file mode 100644 index a1d59c1..0000000 --- a/comfortable_swipe/gesture/mouse_hold_gesture.h +++ /dev/null @@ -1,71 +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 . -*/ - -#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; - }; -} - -#ifdef __cplusplus -} -#endif - -#endif /* __COMFORTABLE_SWIPE__gesture_mouse_hold_gesture_h__ */ diff --git a/comfortable_swipe/gesture/swipe_gesture.cpp b/comfortable_swipe/gesture/swipe_gesture.cpp deleted file mode 100644 index 8402c76..0000000 --- a/comfortable_swipe/gesture/swipe_gesture.cpp +++ /dev/null @@ -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 . -*/ - -#include "swipe_gesture.h" -#include // std::cout, std::endl -#include // std::regex, std::regex_match, std::cmatch -#include // std::stoi, std::stof - -extern "C" { -#include // 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__ */ diff --git a/comfortable_swipe/gesture/swipe_gesture.h b/comfortable_swipe/gesture/swipe_gesture.h deleted file mode 100644 index 36a0744..0000000 --- a/comfortable_swipe/gesture/swipe_gesture.h +++ /dev/null @@ -1,73 +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 . -*/ - -#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; - }; -} - -#ifdef __cplusplus -} -#endif - -#endif /* __COMFORTABLE_SWIPE__gesture_swipe_gesture_h__ */ diff --git a/comfortable_swipe/gesture/swipe_gesture.regex.cpp b/comfortable_swipe/gesture/swipe_gesture.regex.cpp deleted file mode 100644 index 2fe32cd..0000000 --- a/comfortable_swipe/gesture/swipe_gesture.regex.cpp +++ /dev/null @@ -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 . -*/ - -#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__ */ diff --git a/comfortable_swipe/gesture/xdo_gesture.cpp b/comfortable_swipe/gesture/xdo_gesture.cpp deleted file mode 100644 index f9d0d47..0000000 --- a/comfortable_swipe/gesture/xdo_gesture.cpp +++ /dev/null @@ -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 . -*/ - -extern "C" { -#include // 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__ */ diff --git a/comfortable_swipe/gesture/xdo_gesture.h b/comfortable_swipe/gesture/xdo_gesture.h deleted file mode 100644 index a6d5625..0000000 --- a/comfortable_swipe/gesture/xdo_gesture.h +++ /dev/null @@ -1,51 +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 . -*/ - -extern "C" -{ - #include // 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(); - }; - } -} - -#ifdef __cplusplus -} -#endif - -#endif /* __COMFORTABLE_SWIPE__xdo_gesture_h__ */ diff --git a/comfortable_swipe/lib b/comfortable_swipe/lib deleted file mode 100644 index 4854836..0000000 --- a/comfortable_swipe/lib +++ /dev/null @@ -1,47 +0,0 @@ -#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 . -*/ - -#include "all_headers.hpp" - -/** - * Add all cpp files below to be ready for export. - */ - -#include "driver.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__ */ diff --git a/comfortable_swipe/service/autostart.cpp b/comfortable_swipe/service/autostart.cpp deleted file mode 100644 index 6a10d07..0000000 --- a/comfortable_swipe/service/autostart.cpp +++ /dev/null @@ -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 . -*/ - -#include "../all_headers.hpp" -#include // std::remove -#include // std::system -#include // std::ifstream, std::ofstream -#include // std::cerr, std::cout, std::endl -#include // 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__ */ diff --git a/comfortable_swipe/service/buffer.cpp b/comfortable_swipe/service/buffer.cpp deleted file mode 100644 index 6094390..0000000 --- a/comfortable_swipe/service/buffer.cpp +++ /dev/null @@ -1,32 +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 . -*/ - -#include "../all_headers.hpp" -#include // std::exit - -/** - * Starts the comfortable-swipe service by buffering libinput debug-events. - */ -namespace comfortable_swipe::service { -void buffer() { std::exit(comfortable_swipe::driver()); } -} // namespace comfortable_swipe::service - -#endif /* __COMFORTABLE_SWIPE__service_buffer__ */ diff --git a/comfortable_swipe/service/config.cpp b/comfortable_swipe/service/config.cpp deleted file mode 100644 index 0363793..0000000 --- a/comfortable_swipe/service/config.cpp +++ /dev/null @@ -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 . -*/ - -#include "../all_headers.hpp" -#include // 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__ */ diff --git a/comfortable_swipe/service/debug.cpp b/comfortable_swipe/service/debug.cpp deleted file mode 100644 index 07bda31..0000000 --- a/comfortable_swipe/service/debug.cpp +++ /dev/null @@ -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 . -*/ - -#include // 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__ */ diff --git a/comfortable_swipe/service/help.cpp b/comfortable_swipe/service/help.cpp deleted file mode 100644 index 47f76e6..0000000 --- a/comfortable_swipe/service/help.cpp +++ /dev/null @@ -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 . -*/ - -#include "../all_headers.hpp" -#include // 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__ */ diff --git a/comfortable_swipe/service/restart.cpp b/comfortable_swipe/service/restart.cpp deleted file mode 100644 index 8485707..0000000 --- a/comfortable_swipe/service/restart.cpp +++ /dev/null @@ -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 . -*/ - -#include "../all_headers.hpp" -#include // 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__ */ diff --git a/comfortable_swipe/service/start.cpp b/comfortable_swipe/service/start.cpp deleted file mode 100644 index 6505284..0000000 --- a/comfortable_swipe/service/start.cpp +++ /dev/null @@ -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 . -*/ - -#include "../all_headers.hpp" -#include // 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__ */ diff --git a/comfortable_swipe/service/status.cpp b/comfortable_swipe/service/status.cpp deleted file mode 100644 index 877e315..0000000 --- a/comfortable_swipe/service/status.cpp +++ /dev/null @@ -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 . -*/ - -#include "../all_headers.hpp" -#include // std::array -#include // FILE, std::feof, std::fgets, std::printf -#include // std::atoi -#include // std::unique_ptr -#include // std::cmatch, std::regex, std::regex_match -#include // std::runtime_error -#include // 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 buffer; - std::unique_ptr 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__ */ diff --git a/comfortable_swipe/service/stop.cpp b/comfortable_swipe/service/stop.cpp deleted file mode 100644 index ef9196b..0000000 --- a/comfortable_swipe/service/stop.cpp +++ /dev/null @@ -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 . -*/ - -#include // std::array -#include // std::FILE, std::feof, std::fgets -#include // std::atoi, std::system -#include // std::unique_ptr -#include // std::runtime_error -#include // std::string, std::to_string -#include // popen, pclose, getpid - -namespace comfortable_swipe::service { -/** - * Stops all comfortable-swipe instances. - */ -void stop() { - - // read all service names from process (pgrep) - std::array buffer; - std::unique_ptr 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__ */ diff --git a/comfortable_swipe/util/autostart_filename.cpp b/comfortable_swipe/util/autostart_filename.cpp deleted file mode 100644 index a9f24b2..0000000 --- a/comfortable_swipe/util/autostart_filename.cpp +++ /dev/null @@ -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 . -*/ - -#include // std::string -#include // 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__ */ diff --git a/comfortable_swipe/util/conf_filename.cpp b/comfortable_swipe/util/conf_filename.cpp deleted file mode 100644 index 250a9e7..0000000 --- a/comfortable_swipe/util/conf_filename.cpp +++ /dev/null @@ -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 . -*/ - -#include "../all_headers.hpp" - -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__ */ diff --git a/comfortable_swipe/util/read_config_file.cpp b/comfortable_swipe/util/read_config_file.cpp deleted file mode 100644 index 11a9d79..0000000 --- a/comfortable_swipe/util/read_config_file.cpp +++ /dev/null @@ -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 . -*/ - -#include // std::isspace -#include // exit -#include // std::ifstream -#include // std::endl, std::getline -#include // std::map -#include // std::ostringstream -#include // std::runtime_error -#include // 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 read_config_file(const char *filename) { - - std::map 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__ */ diff --git a/command_line.cpp b/command_line.cpp deleted file mode 100644 index 39e20f3..0000000 --- a/command_line.cpp +++ /dev/null @@ -1,67 +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 . -*/ - -#include "comfortable_swipe/lib" -#include // std::ios -#include // std::cin, std::cout, std::cerr -#include // std::string - -/* 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; -} diff --git a/compile b/compile new file mode 100755 index 0000000..8718da7 --- /dev/null +++ b/compile @@ -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\"" diff --git a/config/comfortable-swipe.conf b/config/comfortable-swipe.conf new file mode 100644 index 0000000..4b78b35 --- /dev/null +++ b/config/comfortable-swipe.conf @@ -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) diff --git a/config/comfortable-swipe.desktop b/config/comfortable-swipe.desktop new file mode 100644 index 0000000..c680906 --- /dev/null +++ b/config/comfortable-swipe.desktop @@ -0,0 +1,8 @@ +[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 diff --git a/cpp.compile.sh b/cpp.compile.sh deleted file mode 100755 index 6dcd0ac..0000000 --- a/cpp.compile.sh +++ /dev/null @@ -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\"" diff --git a/defaults.conf b/defaults.conf deleted file mode 100644 index 8cdb545..0000000 --- a/defaults.conf +++ /dev/null @@ -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 diff --git a/install b/install index 81af670..ed2cdbb 100755 --- a/install +++ b/install @@ -2,95 +2,180 @@ set -e -function install { - # prefer running as root - local dir="$(dirname "$0")" - local program="comfortable-swipe" - local program_exe="/usr/local/bin/$program" - local compile_command="$dir/cpp.compile.sh" - local compile_target="$dir/command_line.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" +DIR="$(dirname "$0")" +VERSION="$(cat $DIR/VERSION | tr -d '[:space:]')" - if [ -x "$(command -v "$program_exe")" ]; then - # stop any running $program if it exists - "$program_exe" stop > /dev/null - fi +# target executable +SOURCE="$DIR/comfortable-swipe" +TARGET="/usr/local/bin/comfortable-swipe" - #copy config file - abort () { - exec echo "Installation aborted" - } - sudo mkdir -p "$(dirname $conf_path)" || abort +# compile targets +COMPILE="$DIR/compile" +COMPILE_SOURCE="$DIR/comfortable-swipe-main.cpp" +COMPILE_TARGET="/usr/local/bin/comfortable-swipe-buffer" - # check if "-y" or "--yes" is passed as an argument - YES=false - while test $# -gt 0 - do - case "$1" in - -y) YES=true - ;; - --yes) YES=true - ;; - esac - shift - done +# configurations +CONF_SOURCE="$DIR/config/comfortable-swipe.conf" +CONF_TARGET="$HOME/.config/comfortable-swipe.conf" +OLD_CONF_TARGET="/usr/local/share/comfortable-swipe/comfortable-swipe.conf" - sudo chown $USER "$(dirname $conf_path)" - if [ ! -f "$conf_path" ]; then - if [ ! -f "$old_conf_path" ]; then - # old config file not found, create from scratch - 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 +# autostart +AUTOSTART_SOURCE="$DIR/config/comfortable-swipe.desktop" +AUTOSTART_TARGET="$HOME/.config/autostart/comfortable-swipe.desktop" - echo "Installing to $program_exe ..." +# stop any running comfortable-swipe if it exists +comfortable-swipe stop > /dev/null 2>&1 || true - # remove existing $program - if [ -x "$(command -v "$program_exe")" ]; then - sudo rm -f "$(which "$program")" - fi - # compile library - sudo "$compile_command" "$compile_target" -o "$program_exe" || abort - - # add permissions to input group (defer) - # GROUP=$(ls -l /dev/input/event* | awk '{print $4}' | head --line=1) || abort - - # turn on autostart by default - 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" +# shorthand to abort the installation +function abort { + echo "Installation aborted" + exit 1 } -install -unset -f install +# shorthand to try a command with sudo if it fails +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,,}" =~ ^(yes|y)$ ]]; then + # MAKE SURE they really want to overwrite + read -r -p "Conf file will be overwritten! Are you sure? [Y/n] " response >&2 + if [[ "${response,,}" =~ ^(yes|y)$ ]]; then + # They agreed... replace configuration + cat "$CONF_SOURCE" > "$CONF_TARGET" + else + abort + 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 + TRYSUDO= + if ! touch "$TARGET" 2> /dev/null; then + TRYSUDO=sudo + fi + # install to target, with hardcoded version + $TRYSUDO sed -E "s/^VERSION=.*/VERSION=$VERSION/" "$SOURCE" > "$TARGET" + # allow execute permissions + $TRYSUDO chmod +x "$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 + # eheck permissions maybe if will need sudo + TRYSUDO= + if ! touch "$COMPILE_TARGET" 2> /dev/null; then + TRYSUDO=sudo + fi + # move executable to target + $TRYSUDO mv "$TMP_TARGET" "$COMPILE_TARGET" + echo "Installed: $COMPILE_TARGET" +} + + + +## Installation of Autostart Desktop file +# +# /home/$USER/.config/autostart/comfortable-swipe.desktop +# +function install_autostart { + 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 <&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 < #include #include @@ -53,8 +52,7 @@ void gesture_begin_test(const std::regex &matcher, const char *data, } void gesture_begin_should_match_regex() { - std::regex matcher( - comfortable_swipe::gesture::swipe_gesture::GESTURE_BEGIN_REGEX_PATTERN); + std::regex matcher = comfortable_swipe::gesture_swipe::GESTURE_SWIPE_BEGIN; test::gesture_begin_test(matcher, " event15 GESTURE_SWIPE_BEGIN +34.33s 3\n", "3"); 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() { const char *data = " event15 GESTURE_SWIPE_UPDATE +34.70s 3 -0.12/ 4.99 " "(-0.33/13.50 unaccelerated)\n"; - std::regex matcher( - comfortable_swipe::gesture::swipe_gesture::GESTURE_UPDATE_REGEX_PATTERN); + std::regex matcher = comfortable_swipe::gesture_swipe::GESTURE_SWIPE_UPDATE; std::cmatch matches; auto result = std::regex_match(data, matches, matcher); assert(result != 0); @@ -82,8 +79,7 @@ void gesture_update_should_match_regex() { void gesture_end_should_match_regex() { const char *data = " event15 GESTURE_SWIPE_END +35.03s 3\n"; - std::regex matcher( - comfortable_swipe::gesture::swipe_gesture::GESTURE_END_REGEX_PATTERN); + std::regex matcher = comfortable_swipe::gesture_swipe::GESTURE_SWIPE_END; std::cmatch matches; auto result = std::regex_match(data, matches, matcher); assert(result != 0); diff --git a/tests/test_swipe.sh b/tests/test_swipe.sh new file mode 100755 index 0000000..c862b6b --- /dev/null +++ b/tests/test_swipe.sh @@ -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" < "$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 diff --git a/uninstall b/uninstall index 1c7a9fc..f0f5257 100644 --- a/uninstall +++ b/uninstall @@ -1,8 +1,37 @@ #!/bin/bash -echo "Uninstalling..." -rm "${XDG_CONFIG_HOME:-$HOME/.config}/autostart/comfortable-swipe.desktop" 2> /dev/null -comfortable-swipe stop 2> /dev/null -rm "$HOME/.local/bin/comfortable-swipe" 2> /dev/null # compat -sudo rm /usr/local/bin/comfortable-swipe 2> /dev/null -echo "Successfully uninstalled comfortable-swipe" +set -e + +function trysudo { + $@ 2> /dev/null || sudo $@ +} + +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 <