diff --git a/.gitignore b/.gitignore
index 2fca53d..05bf491 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,3 +4,123 @@
# IDE-specific
.idea
.vscode
+
+# PYTHON
+
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+*$py.class
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib/
+!/lib
+lib64/
+parts/
+sdist/
+var/
+wheels/
+pip-wheel-metadata/
+share/python-wheels/
+*.egg-info/
+.installed.cfg
+*.egg
+MANIFEST
+
+# PyInstaller
+# Usually these files are written by a python script from a template
+# before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.nox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*.cover
+.hypothesis/
+.pytest_cache/
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+*.log
+local_settings.py
+db.sqlite3
+
+# Flask stuff:
+instance/
+.webassets-cache
+
+# Scrapy stuff:
+.scrapy
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+target/
+
+# Jupyter Notebook
+.ipynb_checkpoints
+
+# IPython
+profile_default/
+ipython_config.py
+
+# pyenv
+.python-version
+
+# celery beat schedule file
+celerybeat-schedule
+
+# SageMath parsed files
+*.sage.py
+
+# Environments
+.env
+.venv
+env/
+venv/
+ENV/
+env.bak/
+venv.bak/
+
+# Spyder project settings
+.spyderproject
+.spyproject
+
+# Rope project settings
+.ropeproject
+
+# mkdocs documentation
+/site
+
+# mypy
+.mypy_cache/
+.dmypy.json
+dmypy.json
+
+# Pyre type checker
+.pyre/
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..885a2d6
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,25 @@
+dist: xenial
+language: python
+sudo: required
+python:
+ - 2.7
+ - 3.5
+ - 3.6
+ - 3.7
+ - 3.8-dev
+addons:
+ apt:
+ update: true
+ sources:
+ - ubuntu-toolchain-r-test
+ packages:
+ - libxdo-dev
+ - libinput-tools
+ - g++-7
+env:
+ CC: gcc-7
+ CXX: g++-7
+install:
+ - pip install .
+script:
+ - python setup.py test
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000..99782df
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1 @@
+include comfortable_swipe/res/comfortable-swipe.desktop
diff --git a/README.md b/README.md
index d1b85a0..81dddfa 100644
--- a/README.md
+++ b/README.md
@@ -1,30 +1,62 @@
-# Comfortable Swipe (Ubuntu)
-[](https://www.gnu.org/licenses/gpl-3.0)
+# Comfortable Swipe (Debian/Ubuntu)
-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`.
+[](https://github.com/Hikari9/comfortable-swipe/releases)
+[](https://github.com/Hikari9/comfortable-swipe/commits/master)
+[](https://github.com/Hikari9/comfortable-swipe/commits/develop)
+[](https://www.gnu.org/licenses/gpl-3.0)
+
+Comfortable, seamless, and fast 3-finger (and 4-finger) touchpad swipe gestures. Tested in Ubuntu 14.04 LTS and beyond, for Unity, GNOME, and KDE desktop environments.
+
+> **Note**: May work for other Linux distros that support `libinput` and `libxdo` (untested).
## Installation
-1. Install git, libinput, and g++
+1. Update and install essential tools and libraries
```bash
- sudo apt-get install git libinput-tools libxdo-dev g++
+ sudo apt update && sudo apt install git g++-7 python3-pip libinput-tools libxdo-dev
```
-2. Clone this repository
+2. Install `comfortable-swipe` for your user
```bash
- git clone https://github.com/Hikari9/comfortable-swipe-ubuntu.git
- cd comfortable-swipe-ubuntu
+ pip3 install --user git+https://github.com/Hikari9/comfortable-swipe
```
-3. Install
+3. You can check status with `comfortable-swipe status`
```bash
- bash install
+ $> comfortable-swipe status
+ usr/local/share/comfortable-swipe/comfortable-swipe.conf
+ threshold = 0.0
+ 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
+ autostart is ON
+ comfortable-swipe program is STOPPED
```
-4. You may delete the downloaded `comfortable-swipe-ubuntu` folder after installation.
+3. You can list down all commands with `comfortable-swipe` or `comfortable-swipe help`
+
+ ```bash
+ $> comfortable-swipe
+ comfortable-swipe [start|stop|restart|autostart|buffer|help|config|debug|status]
+
+ start - starts 3/4-finger gesture service
+ stop - stops 3/4-finger gesture service
+ restart - stops then starts 3/4-finger gesture service
+ autostart - automatically run on startup (toggleable)
+ buffer - parses output of libinput debug-events
+ help - shows the help dialog
+ config - locates the config file
+ debug - logs raw output from input events taken from libinput
+ status - checks status of program and autostart
+ ```
## How to Run
@@ -33,27 +65,84 @@ Comfortable, seamless, and fast 3-finger (and 4-finger) touchpad swipe gestures
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
- ```
+3. By default, comfortable-swipe should be running. Otherwise, run:
+ ```bash
comfortable-swipe start
```
-4. _Optional_: Automatically run on startup
+ You can see if gestures work correctly if you see `SWIPE xxx` in the output:
+
+ ```bash
+ $> comfortable-swipe start
+ SWIPE left3
+ SWIPE right3
+ ...
```
- comfortable-swipe autostart
+
+## How to Upgrade
+
+```bash
+pip3 install -U --user git+https://github.com/Hikari9/comfortable-swipe
+```
+
+## Uninstall
+
+```bash
+# Uncomment below to COMPLETELY remove configurations (not recommended)
+# rm $(comfortable-swipe config)
+
+pip3 uninstall comfortable-swipe
+```
+
+## Other Commands
+
+1. `comfortable-swipe config` - outputs location of configuration file
+
+ ```bash
+ $> comfortable-swipe config
+ /usr/local/share/comfortable-swipe/comfortable-swipe.conf
```
-5. Check the status of your application by running
+
+2. `comfortable-swipe autostart` - Toggles autostart
+ ```bash
+ $> comfortable-swipe autostart
+ Autostart switched off
```
- comfortable-swipe status
+
+3. `comfortable-swipe debug` - Debugs input (this is an unbuffered alias of `libinput debug-events`)
+
+ ```bash
+ $> comfortable-swipe debug
+ ...
+ -event9 DEVICE_ADDED TouchPad seat0 default group7 cap:pg size 70x50mm tap(dl off) left scroll-nat scroll-2fg-edge click-buttonareas-clickfinger dwt-on
+ ...
+ event9 GESTURE_SWIPE_BEGIN +2.03s 3
+ event9 GESTURE_SWIPE_UPDATE +2.03s 3 -9.95/ 2.64 (-26.90/ 7.12 unaccelerated)
+ event9 GESTURE_SWIPE_UPDATE +2.03s 3 -10.44/ 3.19 (-28.22/ 8.62 unaccelerated)
+ event9 GESTURE_SWIPE_UPDATE +2.04s 3 -9.71/ 2.64 (-26.25/ 7.12 unaccelerated)
+ event9 GESTURE_SWIPE_UPDATE +2.05s 3 -8.98/ 2.64 (-24.28/ 7.12 unaccelerated)
+ event9 GESTURE_SWIPE_UPDATE +2.06s 3 -7.40/ 2.36 (-20.01/ 6.37 unaccelerated)
+ event9 GESTURE_SWIPE_UPDATE +2.06s 3 -6.31/ 2.50 (-17.06/ 6.75 unaccelerated)
+ event9 GESTURE_SWIPE_UPDATE +2.07s 3 -5.34/ 1.80 (-14.44/ 4.87 unaccelerated)
+ event9 GESTURE_SWIPE_UPDATE +2.08s 3 -4.61/ 2.08 (-12.47/ 5.62 unaccelerated)
+ event9 GESTURE_SWIPE_UPDATE +2.09s 3 -4.49/ 1.53 (-12.14/ 4.12 unaccelerated)
+ event9 GESTURE_SWIPE_UPDATE +2.09s 3 -4.01/ 1.25 (-10.83/ 3.37 unaccelerated)
+ event9 GESTURE_SWIPE_UPDATE +2.10s 3 -4.13/ 0.42 (-11.15/ 1.12 unaccelerated)
+ event9 GESTURE_SWIPE_END +2.11s 3
+ ...
```
+ If you can see `GESTURE_SWIPE_XXX` in your output, that means your touchpad supports multi-touch swipe gestures.
+
## Configurations
+
Comfortable swipe makes use of keyboard shortcuts for configurations. Edit by running
-```
-nano $(comfortable-swipe config)
+
+```bash
+gedit $(comfortable-swipe config)
```
-Make sure to run after making changes:
-```
+Make sure to restart after making changes:
+```bash
comfortable-swipe restart
```
@@ -85,45 +174,6 @@ Taken from `man xdotool`:
Refer to https://www.linux.org/threads/xdotool-keyboard.10528/ for a complete list of keycodes you can use.
-
-## Debugging
-
-You can check your touchpad driver by running
-
-```bash
-comfortable-swipe debug
-```
-
-This is an alias of `libinput debug-events`. This logs all gestures you make on your touchpad, along with other input-based events that can be captured by libinput.
-
-A working swipe gesture will show the following:
-
-```bash
-$ comfortable-swipe debug
-...
--event9 DEVICE_ADDED TouchPad seat0 default group7 cap:pg size 70x50mm tap(dl off) left scroll-nat scroll-2fg-edge click-buttonareas-clickfinger dwt-on
-...
-event9 GESTURE_SWIPE_BEGIN +2.03s 3
- event9 GESTURE_SWIPE_UPDATE +2.03s 3 -9.95/ 2.64 (-26.90/ 7.12 unaccelerated)
- event9 GESTURE_SWIPE_UPDATE +2.03s 3 -10.44/ 3.19 (-28.22/ 8.62 unaccelerated)
- event9 GESTURE_SWIPE_UPDATE +2.04s 3 -9.71/ 2.64 (-26.25/ 7.12 unaccelerated)
- event9 GESTURE_SWIPE_UPDATE +2.05s 3 -8.98/ 2.64 (-24.28/ 7.12 unaccelerated)
- event9 GESTURE_SWIPE_UPDATE +2.06s 3 -7.40/ 2.36 (-20.01/ 6.37 unaccelerated)
- event9 GESTURE_SWIPE_UPDATE +2.06s 3 -6.31/ 2.50 (-17.06/ 6.75 unaccelerated)
- event9 GESTURE_SWIPE_UPDATE +2.07s 3 -5.34/ 1.80 (-14.44/ 4.87 unaccelerated)
- event9 GESTURE_SWIPE_UPDATE +2.08s 3 -4.61/ 2.08 (-12.47/ 5.62 unaccelerated)
- event9 GESTURE_SWIPE_UPDATE +2.09s 3 -4.49/ 1.53 (-12.14/ 4.12 unaccelerated)
- event9 GESTURE_SWIPE_UPDATE +2.09s 3 -4.01/ 1.25 (-10.83/ 3.37 unaccelerated)
- event9 GESTURE_SWIPE_UPDATE +2.10s 3 -4.13/ 0.42 (-11.15/ 1.12 unaccelerated)
- event9 GESTURE_SWIPE_END +2.11s 3
- ...
-```
-
-If you can see `GESTURE_SWIPE_XXX` in your output, that means your touchpad supports multi-touch swipe gestures.
-
-## Uninstall
-Download the `uninstall` script then run `bash uninstall`
-
-
## Bug Reports
+
Create an issue [here](https://github.com/Hikari9/comfortable-swipe-ubuntu/issues/new) to report a bug.
diff --git a/comfortable-swipe.compile.sh b/comfortable-swipe.compile.sh
deleted file mode 100755
index d839b64..0000000
--- a/comfortable-swipe.compile.sh
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/sh
-g++ $(dirname $0)/comfortable-swipe.cpp -std=c++11 -O2 -lxdo -Wno-unused-result -o $1
diff --git a/comfortable-swipe.cpp b/comfortable-swipe.cpp
deleted file mode 100644
index 65359b5..0000000
--- a/comfortable-swipe.cpp
+++ /dev/null
@@ -1,70 +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 // std::ios
-#include // std::cin, std::cout, std::cerr
-#include // std::string
-#include "lib/comfortable_swipe"
-
-/* MAIN DRIVER 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/comfortable_swipe/__init__.py b/comfortable_swipe/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/comfortable_swipe/__main__.py b/comfortable_swipe/__main__.py
new file mode 100644
index 0000000..ef34de2
--- /dev/null
+++ b/comfortable_swipe/__main__.py
@@ -0,0 +1,28 @@
+from __future__ import print_function
+
+import sys
+
+from comfortable_swipe.autostart import toggle_status
+from comfortable_swipe.constants import CONFIG
+from comfortable_swipe.status import print_status
+
+from comfortable_swipe.cpp import service as cpp_service
+
+def main():
+ if len(sys.argv) <= 1:
+ cpp_service.help()
+ else:
+ dict(
+ start=cpp_service.start,
+ stop=cpp_service.stop,
+ restart=cpp_service.restart,
+ buffer=cpp_service.buffer,
+ help=cpp_service.help,
+ debug=cpp_service.debug,
+ status=print_status,
+ autostart=lambda: print('Autostart switched', toggle_status()),
+ config=lambda: print(CONFIG),
+ )[sys.argv[1]]()
+
+if __name__ == '__main__':
+ main()
diff --git a/comfortable_swipe/autostart.py b/comfortable_swipe/autostart.py
new file mode 100644
index 0000000..2580e97
--- /dev/null
+++ b/comfortable_swipe/autostart.py
@@ -0,0 +1,66 @@
+from __future__ import print_function
+
+import os
+import sys
+
+from comfortable_swipe.constants import NAME, RES, exe
+
+
+# status enums
+OFF = 'off'
+ON = 'on'
+
+
+# the target path to the autostart desktop file
+def target_path():
+ return os.path.join(
+ os.getenv(
+ 'XDG_CONFIG_HOME',
+ os.path.join(os.getenv('HOME'), '.config')
+ ),
+ 'autostart',
+ '{}.desktop'.format(NAME)
+ )
+
+
+# path to the autostart template file to be copied
+def template_path():
+ return os.path.join(RES, '{}.desktop'.format(NAME))
+
+
+# parsed contents of the template file
+def template(raw=False):
+ with open(template_path(), 'r') as file:
+ contents = file.read()
+ if raw:
+ return contents
+ return contents.replace('Exec=' + NAME, 'Exec={} {}'.format(sys.executable, exe()))
+
+
+# gets the current autostart status
+def get_status():
+ return ON if os.path.exists(target_path()) else OFF
+
+
+# sets the autostart status
+def set_status(status=ON):
+ if status == ON:
+ # make sure dir exists
+ path = target_path()
+ path_dir = os.path.dirname(path)
+ if not os.path.exists(path_dir):
+ os.makedirs(path_dir)
+ with open(target_path(), 'w') as file:
+ file.write(template())
+ elif status == OFF:
+ if os.path.exists(target_path()):
+ os.remove(target_path())
+ else:
+ raise ValueError('invalid status for autostart')
+
+ return status
+
+
+# toggles autostart status
+def toggle_status():
+ return set_status(OFF if get_status() == ON else ON)
diff --git a/comfortable_swipe/constants.py b/comfortable_swipe/constants.py
new file mode 100644
index 0000000..f27af9e
--- /dev/null
+++ b/comfortable_swipe/constants.py
@@ -0,0 +1,17 @@
+import os
+import sys
+
+from distutils.spawn import find_executable
+
+
+NAME = 'comfortable-swipe'
+DESCRIPTION = 'Comfortable 3-finger and 4-finger swipe gestures'
+BIN = os.path.dirname(sys.executable)
+DIR = os.path.dirname(os.path.abspath(__file__))
+PYTHON_NAME = os.path.basename(DIR)
+RES = os.path.join(DIR, 'res')
+CONFIG = os.path.join(sys.prefix, 'local', 'share', NAME, '{}.conf'.format(NAME))
+DEFAULT_CONFIG = os.path.join(RES, 'defaults.conf')
+
+def exe():
+ return find_executable(NAME)
diff --git a/comfortable_swipe/cpp/__init__.py b/comfortable_swipe/cpp/__init__.py
new file mode 100644
index 0000000..ded284d
--- /dev/null
+++ b/comfortable_swipe/cpp/__init__.py
@@ -0,0 +1 @@
+# This is a placeholder module that will contain the C++ libraries.
diff --git a/comfortable_swipe/res/comfortable-swipe.desktop b/comfortable_swipe/res/comfortable-swipe.desktop
new file mode 100644
index 0000000..fc0cf02
--- /dev/null
+++ b/comfortable_swipe/res/comfortable-swipe.desktop
@@ -0,0 +1,8 @@
+[Desktop Entry]
+Type=Application
+Exec=comfortable-swipe start
+Hidden=false
+NoDisplay=false
+X-GNOME-Autostart-enabled=true
+Name=Comfortable Swipe
+Comment=3 or 4 finger swipe gestures
diff --git a/defaults.conf b/comfortable_swipe/res/defaults.conf
similarity index 99%
rename from defaults.conf
rename to comfortable_swipe/res/defaults.conf
index 7d201e3..9bb095b 100644
--- a/defaults.conf
+++ b/comfortable_swipe/res/defaults.conf
@@ -5,59 +5,46 @@
#
# Refer to https://www.linux.org/threads/xdotool-keyboard.10528/ for a list of
# keycodes you can use.
-
#################
# MISCELLANEOUS #
#################
-
# Threshold
# Tweak this value depending on the sensitivity of your mousepad to perform
# gestures. A higher value means less sensitive.
-#
# (Note: Sky is the limit! Can be as large as 1000.0)
-#
# Default: threshold = 0.0
threshold = 0.0
-
#############################
# 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 left
+# The default shortcut is moving current window to the right workspace.
+# Default: left4=ctrl+alt+shift+Right
+left4 = ctrl+alt+shift+Right
# 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 up
+# The default shortcut is moving current window to the bottom workspace.
+# Default: ctrl+alt+shift+Down
+up4 = ctrl+alt+shift+Down
# 4-finger swipe down
# The default shortcut is moving current window to the above workspace.
# Default: ctrl+alt+shift+Up
diff --git a/comfortable_swipe/status.py b/comfortable_swipe/status.py
new file mode 100644
index 0000000..6a51500
--- /dev/null
+++ b/comfortable_swipe/status.py
@@ -0,0 +1,22 @@
+from __future__ import print_function
+
+import os
+
+from comfortable_swipe import autostart
+from comfortable_swipe.cpp import service
+from comfortable_swipe.constants import NAME, exe
+
+def print_status():
+ service.status()
+ print('autostart is', autostart.get_status().upper())
+ print('{} program is {}'.format(NAME, 'RUNNING' if is_running() else 'STOPPED'))
+
+
+def is_running():
+ import psutil
+ for process in psutil.process_iter():
+ process_args = [process.name()] + process.cmdline()
+ for index in range(len(process_args) - 1):
+ if process_args[index + 1] == 'start' and process_args[index].endswith(NAME):
+ return True
+ return False
diff --git a/cpp/_index.cpp b/cpp/_index.cpp
new file mode 100644
index 0000000..e274cfb
--- /dev/null
+++ b/cpp/_index.cpp
@@ -0,0 +1,8 @@
+#ifndef __COMFORTABLE_SWIPE__index_cpp__
+#define __COMFORTABLE_SWIPE__index_cpp__
+
+#include "gesture/_index.cpp"
+#include "service/_index.cpp"
+#include "util/_index.cpp"
+
+#endif /* __COMFORTABLE_SWIPE__index_cpp__ */
diff --git a/cpp/_index.hpp b/cpp/_index.hpp
new file mode 100644
index 0000000..ce0849d
--- /dev/null
+++ b/cpp/_index.hpp
@@ -0,0 +1,8 @@
+#ifndef __COMFORTABLE_SWIPE__index_hpp__
+#define __COMFORTABLE_SWIPE__index_hpp__
+
+#include "gesture/_index.hpp"
+#include "service/_index.hpp"
+#include "util/_index.hpp"
+
+#endif /* __COMFORTABLE_SWIPE__index_hpp__ */
diff --git a/cpp/_macro.cpp b/cpp/_macro.cpp
new file mode 100644
index 0000000..bffa78a
--- /dev/null
+++ b/cpp/_macro.cpp
@@ -0,0 +1,12 @@
+#ifndef __COMFORTABLE_SWIPE__macro_hpp__
+#define __COMFORTABLE_SWIPE__macro_hpp__
+
+#ifndef COMFORTABLE_SWIPE_CONFIG
+#error "COMFORTABLE_SWIPE_CONFIG must be defined."
+#endif /* COMFORTABLE_SWIPE_CONFIG */
+
+#ifndef COMFORTABLE_SWIPE_VERSION
+#warning "COMFORTABLE_SWIPE_VERSION is not defined."
+#endif /* COMFORTABLE_SWIPE_VERSION */
+
+#endif /* __COMFORTABLE_SWIPE__macro_hpp__ */
diff --git a/cpp/_python.cpp b/cpp/_python.cpp
new file mode 100644
index 0000000..4f1cd9a
--- /dev/null
+++ b/cpp/_python.cpp
@@ -0,0 +1,7 @@
+#ifndef __COMFORTABLE_SWIPE__python_cpp__
+#define __COMFORTABLE_SWIPE__python_cpp__
+
+#include "service/_python.cpp"
+#include "comfortable-swipe.cpp"
+
+#endif /* __COMFORTABLE_SWIPE__python_cpp__ */
diff --git a/cpp/comfortable-swipe b/cpp/comfortable-swipe
new file mode 100644
index 0000000..6465c73
--- /dev/null
+++ b/cpp/comfortable-swipe
@@ -0,0 +1 @@
+#include "comfortable-swipe.cpp"
diff --git a/lib/util/conf_filename.cpp b/cpp/comfortable-swipe.cpp
similarity index 62%
rename from lib/util/conf_filename.cpp
rename to cpp/comfortable-swipe.cpp
index 5de5ae9..1f10dd1 100644
--- a/lib/util/conf_filename.cpp
+++ b/cpp/comfortable-swipe.cpp
@@ -1,5 +1,5 @@
-#ifndef __COMFORTABLE_SWIPE__util_conf_filename__
-#define __COMFORTABLE_SWIPE__util_conf_filename__
+#ifndef __COMFORTABLE_SWIPE__
+#define __COMFORTABLE_SWIPE__
/*
Comfortable Swipe
@@ -19,17 +19,8 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
-#include "../index.hpp"
+#include "_macro.cpp"
+#include "_index.hpp"
+#include "_index.cpp"
-namespace comfortable_swipe::util
-{
- /**
- * The path where the configuration file is located.
- */
- constexpr const char* conf_filename()
- {
- return __COMFORTABLE_SWIPE__CONFIG__;
- }
-}
-
-#endif /* __COMFORTABLE_SWIPE__util_conf_filename__ */
+#endif /* __COMFORTABLE_SWIPE__ */
diff --git a/cpp/gesture/_index.cpp b/cpp/gesture/_index.cpp
new file mode 100644
index 0000000..5de8bb2
--- /dev/null
+++ b/cpp/gesture/_index.cpp
@@ -0,0 +1,9 @@
+#ifndef __COMFORTABLE_SWIPE__gesture_index_cpp__
+#define __COMFORTABLE_SWIPE__gesture_index_cpp__
+
+#include "_index.hpp"
+#include "xdo_gesture.cpp"
+#include "swipe_gesture.cpp"
+#include "swipe_gesture.regex.cpp"
+
+#endif /* __COMFORTABLE_SWIPE__gesture_index_cpp__ */
diff --git a/cpp/gesture/_index.hpp b/cpp/gesture/_index.hpp
new file mode 100644
index 0000000..9c097c5
--- /dev/null
+++ b/cpp/gesture/_index.hpp
@@ -0,0 +1,7 @@
+#ifndef __COMFORTABLE_SWIPE__gesture_index_hpp__
+#define __COMFORTABLE_SWIPE__gesture_index_hpp__
+
+#include "xdo_gesture.h"
+#include "swipe_gesture.h"
+
+#endif /* __COMFORTABLE_SWIPE__gesture_index_hpp__ */
diff --git a/cpp/gesture/swipe_gesture.cpp b/cpp/gesture/swipe_gesture.cpp
new file mode 100644
index 0000000..b1c7ebc
--- /dev/null
+++ b/cpp/gesture/swipe_gesture.cpp
@@ -0,0 +1,216 @@
+#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 // std::cout, std::endl
+#include // std::stoi, std::stof
+#include // std::regex, std::regex_match, std::cmatch
+#include
+#include "swipe_gesture.h"
+
+extern "C"
+{
+ #include // xdo, xdo_new, xdo_free,
+ // xdo_get_mouse_location
+ // CURRENT_WINDOW
+}
+
+namespace comfortable_swipe
+{
+ namespace gesture
+ {
+ /**
+ * Constructs a new swipe gesture, given configurations for certain swipe events.
+ */
+ swipe_gesture::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 */
+ ):
+ comfortable_swipe::gesture::xdo_gesture(),
+ threshold_squared(threshold*threshold),
+ commands(new const char*[8]{left3, left4, right3, right4, up3, up4, down3, down4}),
+ flag_swiping(false)
+ {
+ // improve responsiveness of first gesture by pre-empting xdotool runtime
+ xdo_get_mouse_location(this->xdo, &this->ix, &this->iy, &this->screen_num);
+ }
+
+ /**
+ * Destructs this swipe gesture.
+ */
+ swipe_gesture::~swipe_gesture()
+ {
+ delete[] commands;
+ }
+
+ /**
+ * Hook on begin of swipe gesture.
+ */
+ void swipe_gesture::begin()
+ {
+ xdo_get_mouse_location(this->xdo, &this->ix, &this->iy, &this->screen_num);
+ this->previous_gesture = swipe_gesture::FRESH;
+ this->x = 0;
+ this->y = 0;
+ }
+
+ /**
+ * Hook on update of swipe gesture.
+ */
+ void swipe_gesture::update()
+ {
+ this->x += this->dx;
+ this->y += this->dy;
+ // scale threshold to 1/10 when gesture is not fresh
+ float scale = this->previous_gesture == swipe_gesture::FRESH
+ ? 1.00f
+ : 0.01f; // square root of 1/10
+ static const float EPSILON = 1e-6f;
+ if (this->x * this->x + this->y * this->y
+ > this->threshold_squared * scale + EPSILON)
+ {
+ int mask = 0;
+ if (this->fingers == 3) mask |= swipe_gesture::MSK_THREE_FINGERS;
+ else if (this->fingers == 4) mask |= swipe_gesture::MSK_FOUR_FINGERS;
+
+ const float absx = x >= 0 ? x : -x;
+ const float absy = y >= 0 ? y : -y;
+ if (absx > absy)
+ { // horizontal
+ mask |= swipe_gesture::MSK_HORIZONTAL;
+ if (x < 0)
+ mask |= swipe_gesture::MSK_NEGATIVE;
+ else
+ mask |= swipe_gesture::MSK_POSITIVE;
+ }
+ else /* std::abs(x) <= std::abs(y) */
+ { // vertical
+ mask |= swipe_gesture::MSK_VERTICAL;
+ if (y < 0)
+ mask |= swipe_gesture::MSK_NEGATIVE;
+ else
+ mask |= swipe_gesture::MSK_POSITIVE;
+ }
+
+ // send command on fresh OR opposite gesture
+ if (this->previous_gesture == swipe_gesture::FRESH
+ || this->previous_gesture == (mask ^ swipe_gesture::MSK_POSITIVE))
+ {
+ xdo_send_keysequence_window(this->xdo, CURRENTWINDOW, swipe_gesture::commands[mask], 0);
+ this->x = this->y = 0;
+ this->previous_gesture = mask;
+ std::cout << "SWIPE " << swipe_gesture::command_map[mask] << std::endl;
+ }
+ }
+ }
+
+ /**
+ * Hook on end of swipe gesture.
+ */
+ 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)
+ {
+ static const std::regex gesture_swipe_begin(swipe_gesture::GESTURE_BEGIN_REGEX_PATTERN);
+ static const std::regex gesture_swipe_update(swipe_gesture::GESTURE_UPDATE_REGEX_PATTERN);
+ static const std::regex 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)
+ {
+ // assign necessary variables for swipe begin
+ this->flag_swiping = true;
+ this->fingers = std::stoi(matches[1]);
+ // dispatch begin
+ this->begin();
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /* STATICS DEFINITIONS */
+ const int swipe_gesture::MSK_THREE_FINGERS = 0;
+ const int swipe_gesture::MSK_FOUR_FINGERS = 1;
+ const int swipe_gesture::MSK_NEGATIVE = 0;
+ const int swipe_gesture::MSK_POSITIVE = 2;
+ const int swipe_gesture::MSK_HORIZONTAL = 0;
+ const int swipe_gesture::MSK_VERTICAL = 4;
+ const int swipe_gesture::FRESH = -1;
+ const char * const swipe_gesture::command_map[8] = {
+ "left3",
+ "left4",
+ "right3",
+ "right4",
+ "up3",
+ "up4",
+ "down3",
+ "down4"
+ };
+ }
+}
+
+#endif /* __COMFORTABLE_SWIPE__gesture_swipe_gesture__ */
diff --git a/cpp/gesture/swipe_gesture.h b/cpp/gesture/swipe_gesture.h
new file mode 100644
index 0000000..4e843d6
--- /dev/null
+++ b/cpp/gesture/swipe_gesture.h
@@ -0,0 +1,85 @@
+#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"
+
+namespace comfortable_swipe
+{
+ namespace gesture
+ {
+ class swipe_gesture : protected xdo_gesture
+ {
+ public:
+ // constructor
+ 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 */
+ );
+
+ ~swipe_gesture();
+
+ // fields for xdo
+ int fingers;
+ float dx, dy, udx, udy;
+
+ void begin() override;
+ void update() override;
+ void end() override;
+ bool parse_line(const char *) override;
+
+ protected:
+ // location of mouse
+ int screen_num, ix, iy;
+
+ // current location
+ float x, y, threshold_squared;
+ int previous_gesture;
+ const char ** commands;
+
+ // optimization flag for checking if GESTURE_SWIPE_BEGIN was dispatched
+ bool flag_swiping;
+
+ public:
+ // static constants
+ 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 int FRESH;
+ static const char * const command_map[8];
+ // regex patterns
+ static const char* GESTURE_BEGIN_REGEX_PATTERN;
+ static const char* GESTURE_UPDATE_REGEX_PATTERN;
+ static const char* GESTURE_END_REGEX_PATTERN;
+ };
+ }
+}
+
+#endif /* __COMFORTABLE_SWIPE__gesture_swipe_gesture_h__ */
diff --git a/cpp/gesture/swipe_gesture.regex.cpp b/cpp/gesture/swipe_gesture.regex.cpp
new file mode 100644
index 0000000..ded720f
--- /dev/null
+++ b/cpp/gesture/swipe_gesture.regex.cpp
@@ -0,0 +1,94 @@
+#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
+{
+ namespace 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
+ }
+}
+
+#endif /* __COMFORTABLE_SWIPE__gesture_swipe_gesture_regex__ */
diff --git a/lib/gesture/xdo_gesture.cpp b/cpp/gesture/xdo_gesture.cpp
similarity index 70%
rename from lib/gesture/xdo_gesture.cpp
rename to cpp/gesture/xdo_gesture.cpp
index 3afda7d..7b044c7 100644
--- a/lib/gesture/xdo_gesture.cpp
+++ b/cpp/gesture/xdo_gesture.cpp
@@ -26,21 +26,24 @@ extern "C"
#include "xdo_gesture.h"
-namespace comfortable_swipe::gesture
+namespace comfortable_swipe
{
- /**
- * 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()
+ namespace gesture
{
- xdo_free(this->xdo);
+ /**
+ * 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);
+ }
}
}
diff --git a/lib/gesture/xdo_gesture.h b/cpp/gesture/xdo_gesture.h
similarity index 100%
rename from lib/gesture/xdo_gesture.h
rename to cpp/gesture/xdo_gesture.h
diff --git a/cpp/service/_index.cpp b/cpp/service/_index.cpp
new file mode 100644
index 0000000..3aeb559
--- /dev/null
+++ b/cpp/service/_index.cpp
@@ -0,0 +1,13 @@
+#ifndef __COMFORTABLE_SWIPE__service_index_cpp__
+#define __COMFORTABLE_SWIPE__service_index_cpp__
+
+#include "_index.hpp"
+#include "buffer.cpp"
+#include "debug.cpp"
+#include "help.cpp"
+#include "restart.cpp"
+#include "start.cpp"
+#include "status.cpp"
+#include "stop.cpp"
+
+#endif /* __COMFORTABLE_SWIPE__service_index_cpp__ */
diff --git a/cpp/service/_index.hpp b/cpp/service/_index.hpp
new file mode 100644
index 0000000..584787e
--- /dev/null
+++ b/cpp/service/_index.hpp
@@ -0,0 +1,21 @@
+#ifndef __COMFORTABLE_SWIPE__service_index_hpp__
+#define __COMFORTABLE_SWIPE__service_index_hpp__
+
+#include