├── .clang-format ├── .clang-tidy ├── .copr └── Makefile ├── .editorconfig ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── images │ ├── CHANGE_DESKTOP.gif │ ├── CLOSE_WINDOW.gif │ ├── MAXIMIZE_RESTORE_WINDOW.gif │ ├── MINIMIZE_WINDOW.gif │ ├── SEND_KEYS.gif │ ├── SHOW_DESKTOP.gif │ ├── TILE_WINDOW.gif │ ├── Ubuntu.gif │ └── twitter.png └── workflows │ ├── lint.yml │ ├── release-ppa.yml │ └── release.yml ├── .gitignore ├── .vscode └── settings.json ├── CHANGELOG.md ├── CMakeLists.txt ├── COPYING ├── COPYRIGHT ├── HACKING.md ├── README.md ├── cmake ├── Modules │ ├── FindCAIRO.cmake │ ├── FindGIO.cmake │ ├── FindGLIB.cmake │ ├── FindGTK3.cmake │ ├── FindLIBINPUT.cmake │ ├── FindLIBUDEV.cmake │ ├── FindPUGIXML.cmake │ ├── FindX11.cmake │ ├── FindXINPUT.cmake │ ├── FindXRANDR.cmake │ └── FindXTEST.cmake ├── check-code-style.cmake ├── cpplint.py ├── run-clang-format.sh └── run-cpplint-py.sh ├── debian ├── changelog ├── control ├── copyright ├── rules ├── source │ └── format └── touchegg.lintian-overrides ├── documentation └── doxyfile ├── installation ├── README.md ├── touchegg.conf ├── touchegg.desktop └── touchegg.service.in ├── rpm └── touchegg.spec └── src ├── actions ├── action-direction.h ├── action-factory.cpp ├── action-factory.h ├── action-type.h ├── action.cpp ├── action.h ├── animated-action.cpp ├── animated-action.h ├── change-desktop.cpp ├── change-desktop.h ├── close-window.cpp ├── close-window.h ├── execute-action-on.h ├── fullscreen-window.cpp ├── fullscreen-window.h ├── maximize-restore-window.cpp ├── maximize-restore-window.h ├── minimize-window.cpp ├── minimize-window.h ├── mouse-click.cpp ├── mouse-click.h ├── repeated-action.cpp ├── repeated-action.h ├── run-command.cpp ├── run-command.h ├── send-keys.cpp ├── send-keys.h ├── show-desktop.cpp ├── show-desktop.h ├── tile-window.cpp └── tile-window.h ├── animations ├── animation-factory.cpp ├── animation-factory.h ├── animation-type.h ├── animation.cpp ├── animation.h ├── change-desktop-animation.cpp ├── change-desktop-animation.h ├── close-window-animation.cpp ├── close-window-animation.h ├── maximize-window-animation.cpp ├── maximize-window-animation.h ├── minimize-window-animation.cpp ├── minimize-window-animation.h ├── restore-window-animation.cpp ├── restore-window-animation.h ├── show-desktop-animation.cpp ├── show-desktop-animation.h ├── tile-window-animation.cpp └── tile-window-animation.h ├── config ├── config.cpp ├── config.h ├── xml-config-loader.cpp └── xml-config-loader.h ├── daemon ├── daemon-client.cpp ├── daemon-client.h ├── daemon-server.cpp ├── daemon-server.h └── dbus.h ├── gesture-controller ├── gesture-controller-delegate.h ├── gesture-controller.cpp └── gesture-controller.h ├── gesture-gatherer ├── gesture-gatherer.h ├── libinput-device-handler.cpp ├── libinput-device-handler.h ├── libinput-device-info.h ├── libinput-gesture-gatherer.cpp ├── libinput-gesture-gatherer.h ├── libinput-handler.cpp ├── libinput-handler.h ├── libinput-pinch-handler.cpp ├── libinput-pinch-handler.h ├── libinput-swipe-handler.cpp ├── libinput-swipe-handler.h ├── libinput-touch-handler.cpp └── libinput-touch-handler.h ├── gesture ├── device-type.h ├── gesture-direction.h ├── gesture-type.h └── gesture.h ├── main.cpp ├── utils ├── args-parser.cpp ├── args-parser.h ├── client-lock.cpp ├── client-lock.h ├── color.cpp ├── color.h ├── filesystem.h ├── logger.cpp ├── logger.h ├── paths.cpp ├── paths.h ├── rectangle.h ├── string.cpp └── string.h └── window-system ├── cairo-surface.h ├── window-system.h ├── x11-cairo-surface.cpp ├── x11-cairo-surface.h ├── x11.cpp └── x11.h /.clang-format: -------------------------------------------------------------------------------- 1 | # Code style options: 2 | # https://releases.llvm.org/9.0.0/tools/clang/docs/ClangFormatStyleOptions.html 3 | 4 | # Google C++ Style Guide 5 | # https://google.github.io/styleguide/cppguide.html 6 | BasedOnStyle: Google 7 | -------------------------------------------------------------------------------- /.clang-tidy: -------------------------------------------------------------------------------- 1 | Checks: 'clang-diagnostic-*,clang-analyzer-*,google-*,cppcoreguidelines-*,modernize-*,performance-*,portability-*,readability-*,misc-*,-modernize-use-trailing-return-type,-readability-magic-numbers,-cppcoreguidelines-avoid-magic-numbers','-readability-identifier-length' 2 | WarningsAsErrors: '*,-modernize-use-using' 3 | FormatStyle: file 4 | -------------------------------------------------------------------------------- /.copr/Makefile: -------------------------------------------------------------------------------- 1 | outdir ?= $(HOME)/rpmbuild 2 | 3 | .PHONY: srpm 4 | srpm: 5 | dnf install -y git 6 | mkdir -p $(outdir)/{RPMS,SRPMS,BUILD,SOURCES,SPECS} 7 | tar -czvf $(outdir)/SOURCES/touchegg.tar.gz -C .. touchegg --transform s/^touchegg/touchegg-$$(git describe --tags --abbrev=0)/ 8 | rpmbuild -D'_topdir $(outdir)' -D'_srcrpmdir $(outdir)' -bs rpm/touchegg.spec 9 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # https://editorconfig.org/ 2 | 3 | root = true 4 | 5 | [*] 6 | charset = utf-8 7 | end_of_line = lf 8 | indent_size = 2 9 | indent_style = space 10 | insert_final_newline = true 11 | trim_trailing_whitespace = true 12 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: JoseExposito 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | ### Describe the bug 11 | 12 | A clear and concise description of what the bug is and how to reproduce it. 13 | 14 | ### Expected behaviour 15 | 16 | Tell us what should happen. 17 | 18 | ### Actual behaviour 19 | 20 | Tell us what happens instead. 21 | 22 | ### Logs 23 | 24 | If required, include logs of the bug: 25 | 26 | 27 | ``` 28 | $ touchegg --debug 29 | 30 | ``` 31 | 32 | ### Your environment 33 | 34 | * Version of Touchégg: Run `touchegg --version` in the terminal to check the version 35 | * Operating System: Ubuntu, Fedora, Arch Linux... 36 | * Desktop Environment: Gnome, KDE, Xfce... 37 | * Are you using Wayland? If the anwser is yes, please have in mind that [Touchégg is a X11 only tool](https://github.com/JoseExposito/touchegg#does-touch%C3%A9gg-work-on-wayland) 38 | 39 | 43 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | ### Is your feature request related to a problem? Please describe 11 | 12 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 13 | 14 | ### Describe the solution you'd like 15 | 16 | A clear and concise description of what you want to happen. 17 | 18 | ### Describe alternatives you've considered 19 | 20 | A clear and concise description of any alternative solutions or features you've considered. 21 | 22 | ### Additional context 23 | 24 | Add any other context or screenshots about the feature request here. 25 | 26 | 30 | -------------------------------------------------------------------------------- /.github/images/CHANGE_DESKTOP.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoseExposito/touchegg/fc30d316e163f4504043353d6610e670ce5c6439/.github/images/CHANGE_DESKTOP.gif -------------------------------------------------------------------------------- /.github/images/CLOSE_WINDOW.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoseExposito/touchegg/fc30d316e163f4504043353d6610e670ce5c6439/.github/images/CLOSE_WINDOW.gif -------------------------------------------------------------------------------- /.github/images/MAXIMIZE_RESTORE_WINDOW.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoseExposito/touchegg/fc30d316e163f4504043353d6610e670ce5c6439/.github/images/MAXIMIZE_RESTORE_WINDOW.gif -------------------------------------------------------------------------------- /.github/images/MINIMIZE_WINDOW.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoseExposito/touchegg/fc30d316e163f4504043353d6610e670ce5c6439/.github/images/MINIMIZE_WINDOW.gif -------------------------------------------------------------------------------- /.github/images/SEND_KEYS.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoseExposito/touchegg/fc30d316e163f4504043353d6610e670ce5c6439/.github/images/SEND_KEYS.gif -------------------------------------------------------------------------------- /.github/images/SHOW_DESKTOP.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoseExposito/touchegg/fc30d316e163f4504043353d6610e670ce5c6439/.github/images/SHOW_DESKTOP.gif -------------------------------------------------------------------------------- /.github/images/TILE_WINDOW.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoseExposito/touchegg/fc30d316e163f4504043353d6610e670ce5c6439/.github/images/TILE_WINDOW.gif -------------------------------------------------------------------------------- /.github/images/Ubuntu.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoseExposito/touchegg/fc30d316e163f4504043353d6610e670ce5c6439/.github/images/Ubuntu.gif -------------------------------------------------------------------------------- /.github/images/twitter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoseExposito/touchegg/fc30d316e163f4504043353d6610e670ce5c6439/.github/images/twitter.png -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | # Compile and run clang-format, clang-tidy and cpplint.py on every commit 2 | 3 | name: Lint 4 | 5 | on: [push, pull_request] 6 | 7 | jobs: 8 | lint: 9 | runs-on: ubuntu-24.04 10 | steps: 11 | - name: Checkout code 12 | uses: actions/checkout@v3 13 | 14 | - name: Install dependencies 15 | run: | 16 | sudo apt update 17 | sudo apt build-dep -y . 18 | sudo apt install -y clang clang-format clang-tidy python3 19 | 20 | - name: Compile 21 | run: | 22 | mkdir build 23 | cd build 24 | cmake -DCMAKE_BUILD_TYPE=Debug .. 25 | make 26 | -------------------------------------------------------------------------------- /.github/workflows/release-ppa.yml: -------------------------------------------------------------------------------- 1 | # Workflow to update the "ppa" branch once a release is created 2 | # This will trigger a build in the stable PPA: 3 | # https://launchpad.net/~touchegg 4 | # 5 | # And also the COPR RPM repo: 6 | # https://copr.fedorainfracloud.org/coprs/jose_exposito/touchegg/ 7 | 8 | name: Release PPA 9 | 10 | on: 11 | release: 12 | types: [published] 13 | 14 | jobs: 15 | update-ppa-branch: 16 | runs-on: ubuntu-24.04 17 | steps: 18 | - name: Checkout code 19 | uses: actions/checkout@v3 20 | 21 | - name: Merge master branch into ppa branch 22 | uses: devmasx/merge-branch@v1.3.1 23 | with: 24 | type: now 25 | from_branch: master 26 | target_branch: ppa 27 | github_token: ${{ github.token }} 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Build folder 2 | build/ 3 | installation/touchegg.service 4 | 5 | # CMake 6 | CMakeLists.txt.user 7 | CMakeCache.txt 8 | CMakeFiles 9 | CMakeScripts 10 | Testing 11 | Makefile 12 | cmake_install.cmake 13 | install_manifest.txt 14 | compile_commands.json 15 | CTestTestfile.cmake 16 | _deps 17 | 18 | # Doxygen documentation 19 | documentation/html/ 20 | documentation/log 21 | 22 | # Visual Studio Code 23 | .vscode/* 24 | !.vscode/settings.json 25 | !.vscode/tasks.json 26 | !.vscode/launch.json 27 | !.vscode/extensions.json 28 | *.code-workspace 29 | .history/ 30 | 31 | # ctags 32 | .cpptags 33 | 34 | # Debian packaging 35 | debian/*.log 36 | debian/*.substvars 37 | debian/.debhelper/ 38 | debian/tmp/ 39 | debian/touchegg/ 40 | debian/touchegg-dbg/ 41 | debian/files 42 | obj-*-linux-gnu/ 43 | 44 | # COPR 45 | !.copr/Makefile 46 | 47 | # macOS 48 | .DS_Store 49 | ._* 50 | .Spotlight-V100 51 | .Trashes 52 | 53 | # Windows 54 | Thumbs.db 55 | ehthumbs.db 56 | Desktop.ini 57 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "filesystem": "cpp", 4 | "array": "cpp", 5 | "atomic": "cpp", 6 | "*.tcc": "cpp", 7 | "cctype": "cpp", 8 | "chrono": "cpp", 9 | "clocale": "cpp", 10 | "cmath": "cpp", 11 | "codecvt": "cpp", 12 | "cstdarg": "cpp", 13 | "cstddef": "cpp", 14 | "cstdint": "cpp", 15 | "cstdio": "cpp", 16 | "cstdlib": "cpp", 17 | "ctime": "cpp", 18 | "cwchar": "cpp", 19 | "cwctype": "cpp", 20 | "deque": "cpp", 21 | "unordered_map": "cpp", 22 | "vector": "cpp", 23 | "exception": "cpp", 24 | "algorithm": "cpp", 25 | "memory": "cpp", 26 | "memory_resource": "cpp", 27 | "optional": "cpp", 28 | "ratio": "cpp", 29 | "string": "cpp", 30 | "string_view": "cpp", 31 | "system_error": "cpp", 32 | "tuple": "cpp", 33 | "type_traits": "cpp", 34 | "utility": "cpp", 35 | "fstream": "cpp", 36 | "initializer_list": "cpp", 37 | "iosfwd": "cpp", 38 | "iostream": "cpp", 39 | "istream": "cpp", 40 | "limits": "cpp", 41 | "new": "cpp", 42 | "ostream": "cpp", 43 | "sstream": "cpp", 44 | "stdexcept": "cpp", 45 | "streambuf": "cpp", 46 | "typeinfo": "cpp", 47 | "thread": "cpp", 48 | "cstring": "cpp", 49 | "iterator": "cpp", 50 | "functional": "cpp", 51 | "bitset": "cpp", 52 | "map": "cpp", 53 | "regex": "cpp", 54 | "cinttypes": "cpp", 55 | "condition_variable": "cpp", 56 | "mutex": "cpp", 57 | "bit": "cpp", 58 | "list": "cpp", 59 | "numeric": "cpp", 60 | "random": "cpp", 61 | "iomanip": "cpp", 62 | "shared_mutex": "cpp" 63 | } 64 | } -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0.0) 2 | 3 | project(touchegg) 4 | set(MAJOR_VERSION "2") 5 | set(MINOR_VERSION "0") 6 | set(PATCH_VERSION "18") 7 | add_definitions(-D_VERSION="v${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_VERSION}") 8 | 9 | set(CMAKE_CXX_STANDARD 17) 10 | set(CMAKE_CXX_STANDARD_REQUIRED True) 11 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake/Modules") 12 | 13 | # In debug mode check code style issues 14 | if(CMAKE_BUILD_TYPE MATCHES Debug) 15 | include(./cmake/check-code-style.cmake) 16 | endif() 17 | 18 | find_package(Threads REQUIRED) # Required to use std threads 19 | find_package(LIBUDEV REQUIRED) 20 | find_package(LIBINPUT REQUIRED) 21 | find_package(PUGIXML REQUIRED) 22 | find_package(CAIRO REQUIRED) 23 | find_package(X11 REQUIRED) 24 | find_package(XTEST REQUIRED) 25 | find_package(XRANDR REQUIRED) 26 | find_package(XINPUT REQUIRED) 27 | find_package(GLIB REQUIRED) 28 | find_package(GIO REQUIRED) 29 | 30 | # libinput 1.18 filters unaccelerated deltas for gestures and we need to adjust our thresholds: 31 | # https://gitlab.freedesktop.org/libinput/libinput/-/commit/60d5172e15728cc25db889a7a6bcf37a06a15a3a 32 | if(LIBINPUT_VERSION VERSION_GREATER_EQUAL "1.18") 33 | message(STATUS "Found libinput >= 1.18: LIBINPUT_FILTER_DELTAS=ON") 34 | add_definitions(-DLIBINPUT_FILTER_DELTAS=ON) 35 | endif() 36 | 37 | include_directories(${PROJECT_SOURCE_DIR}/src) 38 | file(GLOB_RECURSE SOURCE_FILES RELATIVE ${PROJECT_SOURCE_DIR} src/*.h src/*.cpp) 39 | 40 | add_executable(touchegg ${SOURCE_FILES}) 41 | target_include_directories(touchegg PUBLIC 42 | ${LIBUDEV_INCLUDE_DIRS} 43 | ${LIBINPUT_INCLUDE_DIRS} 44 | ${PUGIXML_INCLUDE_DIRS} 45 | ${CAIRO_INCLUDE_DIRS} 46 | ${X11_INCLUDE_DIRS} 47 | ${XTEST_INCLUDE_DIRS} 48 | ${XRANDR_INCLUDE_DIRS} 49 | ${XINPUT_INCLUDE_DIRS} 50 | ${GLIB_INCLUDE_DIRS} 51 | ${GIO_INCLUDE_DIRS} 52 | ) 53 | target_link_libraries(touchegg 54 | stdc++fs # std::filesystem 55 | Threads::Threads # std::thread 56 | ${LIBUDEV_LIBRARIES} 57 | ${LIBINPUT_LIBRARIES} 58 | ${PUGIXML_LIBRARIES} 59 | ${CAIRO_LIBRARIES} 60 | ${X11_LIBRARIES} 61 | ${XTEST_LIBRARIES} 62 | ${XRANDR_LIBRARIES} 63 | ${XINPUT_LIBRARIES} 64 | ${GLIB_LIBRARIES} 65 | ${GIO_LIBRARIES} 66 | ) 67 | 68 | if(NOT DEFINED AUTO_COLORS OR AUTO_COLORS) 69 | find_package(GTK3 REQUIRED) 70 | target_include_directories(touchegg PUBLIC ${GTK3_INCLUDE_DIRS}) 71 | target_link_libraries(touchegg ${GTK3_LIBRARIES}) 72 | add_definitions(-DAUTO_COLORS=ON) 73 | else() 74 | message(WARNING "AUTO_COLORS OFF: GTK will NOT be used to and auto colors will NOT be available") 75 | endif() 76 | 77 | 78 | # Installation 79 | # https://cmake.org/cmake/help/v3.4/module/GNUInstallDirs.html 80 | if(CMAKE_BUILD_TYPE MATCHES Debug) 81 | set(CMAKE_INSTALL_PREFIX "/usr") 82 | endif() 83 | 84 | include(GNUInstallDirs) 85 | 86 | set(SYSTEM_CONFIG_FILE_PATH "${CMAKE_INSTALL_FULL_DATAROOTDIR}/touchegg/touchegg.conf") 87 | target_compile_definitions(touchegg PUBLIC SYSTEM_CONFIG_FILE_PATH=\"${SYSTEM_CONFIG_FILE_PATH}\") 88 | 89 | install(FILES ${PROJECT_SOURCE_DIR}/installation/touchegg.conf DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/touchegg) # /usr/share/touchegg/touchegg.conf 90 | install(FILES ${PROJECT_SOURCE_DIR}/installation/touchegg.desktop DESTINATION ${CMAKE_INSTALL_FULL_SYSCONFDIR}/xdg/autostart) 91 | install(PROGRAMS ${PROJECT_BINARY_DIR}/touchegg DESTINATION ${CMAKE_INSTALL_BINDIR}) # /usr/bin/touchegg 92 | 93 | if(NOT DEFINED USE_SYSTEMD OR USE_SYSTEMD) 94 | # configure systemd service unit to use the right path, e.g. @CMAKE_INSTALL_BINDIR@/touchegg 95 | configure_file(${PROJECT_SOURCE_DIR}/installation/touchegg.service.in ${PROJECT_SOURCE_DIR}/installation/touchegg.service @ONLY) 96 | pkg_get_variable(SYSTEMD_SERVICE_DIR systemd systemdsystemunitdir) 97 | 98 | install(FILES ${PROJECT_SOURCE_DIR}/installation/touchegg.service DESTINATION ${SYSTEMD_SERVICE_DIR}) 99 | else() 100 | message(WARNING "USE_SYSTEMD OFF: Systemd related file will NOT be installed") 101 | endif() 102 | -------------------------------------------------------------------------------- /COPYRIGHT: -------------------------------------------------------------------------------- 1 | Copyright (C) 2011 - 2021 José Expósito 2 | -------------------------------------------------------------------------------- /cmake/Modules/FindCAIRO.cmake: -------------------------------------------------------------------------------- 1 | find_package(PkgConfig) 2 | pkg_check_modules(CAIRO REQUIRED cairo) 3 | 4 | include(FindPackageHandleStandardArgs) 5 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(CAIRO DEFAULT_MSG CAIRO_FOUND) 6 | -------------------------------------------------------------------------------- /cmake/Modules/FindGIO.cmake: -------------------------------------------------------------------------------- 1 | find_package(PkgConfig) 2 | pkg_check_modules(GIO REQUIRED gio-2.0) 3 | 4 | include(FindPackageHandleStandardArgs) 5 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(GIO DEFAULT_MSG GIO_FOUND) 6 | -------------------------------------------------------------------------------- /cmake/Modules/FindGLIB.cmake: -------------------------------------------------------------------------------- 1 | find_package(PkgConfig) 2 | pkg_check_modules(GLIB REQUIRED glib-2.0) 3 | 4 | include(FindPackageHandleStandardArgs) 5 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(GLIB DEFAULT_MSG GLIB_FOUND) 6 | -------------------------------------------------------------------------------- /cmake/Modules/FindGTK3.cmake: -------------------------------------------------------------------------------- 1 | find_package(PkgConfig) 2 | pkg_check_modules(GTK3 REQUIRED gtk+-3.0) 3 | 4 | include(FindPackageHandleStandardArgs) 5 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(GTK3 DEFAULT_MSG GTK3_FOUND) 6 | -------------------------------------------------------------------------------- /cmake/Modules/FindLIBINPUT.cmake: -------------------------------------------------------------------------------- 1 | find_package(PkgConfig) 2 | pkg_check_modules(LIBINPUT REQUIRED libinput) 3 | 4 | include(FindPackageHandleStandardArgs) 5 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBINPUT DEFAULT_MSG LIBINPUT_FOUND) 6 | -------------------------------------------------------------------------------- /cmake/Modules/FindLIBUDEV.cmake: -------------------------------------------------------------------------------- 1 | find_package(PkgConfig) 2 | pkg_check_modules(LIBUDEV REQUIRED libudev) 3 | 4 | include(FindPackageHandleStandardArgs) 5 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBUDEV DEFAULT_MSG LIBUDEV_FOUND) 6 | -------------------------------------------------------------------------------- /cmake/Modules/FindPUGIXML.cmake: -------------------------------------------------------------------------------- 1 | find_package(PkgConfig) 2 | pkg_check_modules(PUGIXML REQUIRED pugixml) 3 | 4 | include(FindPackageHandleStandardArgs) 5 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(PUGIXML DEFAULT_MSG PUGIXML_FOUND) 6 | -------------------------------------------------------------------------------- /cmake/Modules/FindX11.cmake: -------------------------------------------------------------------------------- 1 | find_package(PkgConfig) 2 | pkg_check_modules(X11 REQUIRED x11) 3 | 4 | include(FindPackageHandleStandardArgs) 5 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(X11 DEFAULT_MSG X11_FOUND) 6 | -------------------------------------------------------------------------------- /cmake/Modules/FindXINPUT.cmake: -------------------------------------------------------------------------------- 1 | find_package(PkgConfig) 2 | pkg_check_modules(XINPUT REQUIRED xi) 3 | 4 | include(FindPackageHandleStandardArgs) 5 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(XINPUT DEFAULT_MSG XINPUT_FOUND) 6 | -------------------------------------------------------------------------------- /cmake/Modules/FindXRANDR.cmake: -------------------------------------------------------------------------------- 1 | find_package(PkgConfig) 2 | pkg_check_modules(XRANDR REQUIRED xrandr) 3 | 4 | include(FindPackageHandleStandardArgs) 5 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(XRANDR DEFAULT_MSG XRANDR_FOUND) 6 | -------------------------------------------------------------------------------- /cmake/Modules/FindXTEST.cmake: -------------------------------------------------------------------------------- 1 | find_package(PkgConfig) 2 | pkg_check_modules(XTEST REQUIRED xtst) 3 | 4 | include(FindPackageHandleStandardArgs) 5 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(XTEST DEFAULT_MSG XTEST_FOUND) 6 | -------------------------------------------------------------------------------- /cmake/check-code-style.cmake: -------------------------------------------------------------------------------- 1 | # If clang-tidy, clang-format and/or cpplint are present run them and stop the compilation on error 2 | 3 | find_program(CLANG_TIDY_EXEC NAMES "clang-tidy") 4 | if(NOT CLANG_TIDY_EXEC) 5 | message(WARNING "Check for clang-tidy: Not found, clang-tidy will not be executed") 6 | else() 7 | message(STATUS "Check for clang-tidy: Found") 8 | set(CMAKE_CXX_CLANG_TIDY "clang-tidy") 9 | endif() 10 | 11 | find_program(CLANG_FORMAT_EXEC NAMES "clang-format") 12 | if(NOT CLANG_FORMAT_EXEC) 13 | message(WARNING "Check for clang-format: Not found, clang-format will not be executed") 14 | else() 15 | message(STATUS "Check for clang-format: Found") 16 | execute_process( 17 | COMMAND ./cmake/run-clang-format.sh 18 | WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} 19 | RESULT_VARIABLE status 20 | ) 21 | if(NOT status EQUAL 0) 22 | message(FATAL_ERROR "Code Style issues found (clang-format)") 23 | endif() 24 | endif() 25 | 26 | find_program(PYTHON_EXEC NAMES "python3") 27 | if(NOT PYTHON_EXEC) 28 | message(WARNING "Check for python3: Not found, cpplint.py will not be executed") 29 | else() 30 | message(STATUS "Check for python3: Found") 31 | execute_process( 32 | COMMAND ./cmake/run-cpplint-py.sh 33 | WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} 34 | RESULT_VARIABLE status 35 | ) 36 | if(NOT status EQUAL 0) 37 | message(FATAL_ERROR "Code Style issues found (cpplint.py)") 38 | endif() 39 | endif() 40 | -------------------------------------------------------------------------------- /cmake/run-clang-format.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Bash script check code style issues with clang-format and show a nice diff 3 | 4 | hasWerror=$(clang-format --help | grep Werror) 5 | if [ -z "$hasWerror" ]; then 6 | WerrorFlag="" 7 | else 8 | WerrorFlag="--Werror" 9 | fi 10 | 11 | result=$(find src -type f \( -name \*.cpp -o -name \*.h \) -exec sh -c 'clang-format --style=file $1 "$0" | diff -u "$0" -' {} $WerrorFlag \;) 12 | 13 | if [ -z "$result" ]; then 14 | exit 0 15 | else 16 | echo "$result" 17 | exit 1 18 | fi 19 | -------------------------------------------------------------------------------- /cmake/run-cpplint-py.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Bash script check code style issues with cpplint.py 3 | 4 | find src -type f \( -name \*.cpp -o -name \*.h \) -print0 | xargs -0 python3 ./cmake/cpplint.py --root src 5 | -------------------------------------------------------------------------------- /debian/control: -------------------------------------------------------------------------------- 1 | Source: touchegg 2 | Section: misc 3 | Priority: optional 4 | Maintainer: José Expósito 5 | Build-Depends: cmake, 6 | debhelper-compat (= 12), 7 | libc6-dev (>= 2.14), 8 | libcairo2-dev (>= 1.2.4), 9 | libgtk-3-dev, 10 | libinput-dev (>= 0.21.0), 11 | libpugixml-dev (>= 1.4), 12 | libudev-dev (>= 183), 13 | libx11-dev, 14 | libxi-dev (>= 2:1.7.0), 15 | libxrandr-dev (>= 2:1.2.0), 16 | libxtst-dev 17 | Standards-Version: 4.5.0 18 | Homepage: https://github.com/JoseExposito/touchegg 19 | Vcs-Browser: https://github.com/JoseExposito/touchegg 20 | Vcs-Git: https://github.com/JoseExposito/touchegg.git 21 | 22 | Package: touchegg 23 | Architecture: any 24 | Depends: ${misc:Depends}, ${shlibs:Depends} 25 | Description: Multi-touch gesture recognizer 26 | Touchégg is an app that runs in the background and transform the gestures you 27 | make in your touchpad into visible actions in your desktop. 28 | For example, you can swipe up with 3 fingers to maximize a window or swipe left 29 | with 4 finger to switch to the next desktop. 30 | -------------------------------------------------------------------------------- /debian/copyright: -------------------------------------------------------------------------------- 1 | Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ 2 | Upstream-Name: touchegg 3 | Source: https://github.com/JoseExposito/touchegg 4 | 5 | Files: * 6 | Copyright: Copyright 2021 José Expósito 7 | License: GPL-3+ 8 | 9 | License: GPL-3+ 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License version 3 as 12 | published by the Free Software Foundation. 13 | . 14 | This package is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | GNU General Public License for more details. 18 | . 19 | You should have received a copy of the GNU General Public License 20 | along with this program. If not, see . 21 | . 22 | On Debian systems, the complete text of the GNU General 23 | Public License version 3 can be found in "/usr/share/common-licenses/GPL-3". 24 | -------------------------------------------------------------------------------- /debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | 3 | %: 4 | dh $@ 5 | -------------------------------------------------------------------------------- /debian/source/format: -------------------------------------------------------------------------------- 1 | 3.0 (native) 2 | -------------------------------------------------------------------------------- /debian/touchegg.lintian-overrides: -------------------------------------------------------------------------------- 1 | touchegg: no-manual-page usr/bin/touchegg 2 | -------------------------------------------------------------------------------- /installation/README.md: -------------------------------------------------------------------------------- 1 | # Installation Files 2 | 3 | ## touchegg.conf - _Touchégg configuration file_ 4 | 5 | This file handles all of the default gestures on installing Touchégg. 6 | 7 | ## touchegg.desktop - _Touchégg application XDG desktop entry file_ 8 | 9 | This file contains a combination of meta information resources and a shortcut to the Touchégg application, in accordance with the [XDG Desktop Entry specification](https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html) which defines a standard for applications to integrate into application menus of desktop environments. 10 | 11 | This file is installed into the system-wide XDG Autostart directory (`/etc/xdg/autostart`), which allows autostarting ordinary desktop entries on desktop environment startup. 12 | 13 | ## touchegg.service.in - _Touchégg systemd service_ 14 | 15 | This service runs Touchégg in daemon mode (`touchegg --daemon`) as part of the "input" group. 16 | The daemon will open a Unix domain socket so any service (usually `touchegg --client`) can have access to libinput's multi-touch gestures. 17 | 18 | CMake configures the path for ExecStart and saves the result in `touchegg.service`. 19 | 20 | ### Learn more about systemd 21 | https://wiki.archlinux.org/index.php/Systemd#Basic_systemctl_usage 22 | 23 | ### Installation 24 | ```bash 25 | sudo cp installation/touchegg.service /lib/systemd/system 26 | sudo systemctl enable touchegg.service 27 | sudo systemctl start touchegg 28 | systemctl status touchegg 29 | journalctl -u touchegg -b -f # Monitor the logs since last boot 30 | ``` 31 | 32 | ### Debugging 33 | Change the ExecStart to your binary path: 34 | 35 | ``` 36 | ExecStart=/home/jose/Devel/touchegg/build/touchegg --daemon 37 | ``` 38 | 39 | Copy the service file and restart it: 40 | 41 | ```bash 42 | sudo systemctl daemon-reload && sudo systemctl restart touchegg 43 | ``` 44 | -------------------------------------------------------------------------------- /installation/touchegg.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Type=Application 3 | Name=Touchégg 4 | Comment=Multi-touch gesture recognizer 5 | Exec=touchegg 6 | Terminal=false 7 | Categories=Utility; 8 | NoDisplay=true 9 | StartupNotify=true 10 | -------------------------------------------------------------------------------- /installation/touchegg.service.in: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Touchégg Daemon 3 | Documentation=https://github.com/JoseExposito/touchegg/tree/master/installation#readme 4 | 5 | [Service] 6 | Type=simple 7 | Group=input 8 | ExecStart=@CMAKE_INSTALL_FULL_BINDIR@/touchegg --daemon 9 | Restart=on-failure 10 | RestartSec=5s 11 | 12 | [Install] 13 | WantedBy=multi-user.target 14 | -------------------------------------------------------------------------------- /src/actions/action-direction.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #ifndef ACTIONS_ACTION_DIRECTION_H_ 19 | #define ACTIONS_ACTION_DIRECTION_H_ 20 | 21 | #include 22 | 23 | enum class ActionDirection { 24 | UNKNOWN, 25 | UP, 26 | DOWN, 27 | LEFT, 28 | RIGHT, 29 | PREVIOUS, 30 | NEXT, 31 | AUTO, 32 | // Adding a new ActionDirection? Don't forget to add it in 33 | // actionDirectionFromStr 34 | }; 35 | 36 | inline ActionDirection actionDirectionFromStr(const std::string &str) { 37 | if (str == "up") { 38 | return ActionDirection::UP; 39 | } 40 | if (str == "down") { 41 | return ActionDirection::DOWN; 42 | } 43 | if (str == "left") { 44 | return ActionDirection::LEFT; 45 | } 46 | if (str == "right") { 47 | return ActionDirection::RIGHT; 48 | } 49 | if (str == "previous") { 50 | return ActionDirection::PREVIOUS; 51 | } 52 | if (str == "next") { 53 | return ActionDirection::NEXT; 54 | } 55 | if (str == "auto") { 56 | return ActionDirection::AUTO; 57 | } 58 | return ActionDirection::UNKNOWN; 59 | } 60 | 61 | #endif // ACTIONS_ACTION_DIRECTION_H_ 62 | -------------------------------------------------------------------------------- /src/actions/action-factory.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #include "actions/action-factory.h" 19 | 20 | #include 21 | 22 | #include "actions/action.h" 23 | #include "actions/change-desktop.h" 24 | #include "actions/close-window.h" 25 | #include "actions/fullscreen-window.h" 26 | #include "actions/maximize-restore-window.h" 27 | #include "actions/minimize-window.h" 28 | #include "actions/mouse-click.h" 29 | #include "actions/run-command.h" 30 | #include "actions/send-keys.h" 31 | #include "actions/show-desktop.h" 32 | #include "actions/tile-window.h" 33 | 34 | std::unique_ptr ActionFactory::buildAction( 35 | ActionType type, std::unordered_map settings, 36 | const WindowSystem &windowSystem, const WindowT &window, 37 | const Config &config) { 38 | switch (type) { 39 | case ActionType::MAXIMIZE_RESTORE_WINDOW: 40 | return std::make_unique( 41 | std::move(settings), windowSystem, window, config); 42 | case ActionType::FULLSCREEN_WINDOW: 43 | return std::make_unique(std::move(settings), 44 | windowSystem, window, config); 45 | case ActionType::MINIMIZE_WINDOW: 46 | return std::make_unique(std::move(settings), windowSystem, 47 | window, config); 48 | case ActionType::TILE_WINDOW: 49 | return std::make_unique(std::move(settings), windowSystem, 50 | window, config); 51 | case ActionType::CLOSE_WINDOW: 52 | return std::make_unique(std::move(settings), windowSystem, 53 | window, config); 54 | case ActionType::CHANGE_DESKTOP: 55 | return std::make_unique(std::move(settings), windowSystem, 56 | window, config); 57 | case ActionType::SHOW_DESKTOP: 58 | return std::make_unique(std::move(settings), windowSystem, 59 | window, config); 60 | case ActionType::SEND_KEYS: 61 | return std::make_unique(std::move(settings), windowSystem, 62 | window, config); 63 | case ActionType::RUN_COMMAND: 64 | return std::make_unique(std::move(settings), windowSystem, 65 | window, config); 66 | case ActionType::MOUSE_CLICK: 67 | return std::make_unique(std::move(settings), windowSystem, 68 | window, config); 69 | default: 70 | return nullptr; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/actions/action-factory.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #ifndef ACTIONS_ACTION_FACTORY_H_ 19 | #define ACTIONS_ACTION_FACTORY_H_ 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | #include "actions/action-type.h" 26 | #include "actions/action.h" 27 | #include "config/config.h" 28 | 29 | class ActionFactory { 30 | public: 31 | static std::unique_ptr buildAction( 32 | ActionType type, std::unordered_map settings, 33 | const WindowSystem &windowSystem, const WindowT &window, 34 | const Config &config); 35 | }; 36 | 37 | #endif // ACTIONS_ACTION_FACTORY_H_ 38 | -------------------------------------------------------------------------------- /src/actions/action-type.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #ifndef ACTIONS_ACTION_TYPE_H_ 19 | #define ACTIONS_ACTION_TYPE_H_ 20 | 21 | #include 22 | 23 | enum class ActionType { 24 | NOT_SUPPORTED, 25 | MAXIMIZE_RESTORE_WINDOW, 26 | FULLSCREEN_WINDOW, 27 | MINIMIZE_WINDOW, 28 | TILE_WINDOW, 29 | CLOSE_WINDOW, 30 | CHANGE_DESKTOP, 31 | SHOW_DESKTOP, 32 | SEND_KEYS, 33 | RUN_COMMAND, 34 | MOUSE_CLICK, 35 | // Adding a new action? Don't forget to add it in actionTypeToStr, 36 | // actionTypeFromStr and ActionFactory::buildAction 37 | }; 38 | 39 | inline std::string actionTypeToStr(ActionType actionType) { 40 | switch (actionType) { 41 | case ActionType::MAXIMIZE_RESTORE_WINDOW: 42 | return "MAXIMIZE_RESTORE_WINDOW"; 43 | case ActionType::FULLSCREEN_WINDOW: 44 | return "FULLSCREEN_WINDOW"; 45 | case ActionType::MINIMIZE_WINDOW: 46 | return "MINIMIZE_WINDOW"; 47 | case ActionType::TILE_WINDOW: 48 | return "TILE_WINDOW"; 49 | case ActionType::CLOSE_WINDOW: 50 | return "CLOSE_WINDOW"; 51 | case ActionType::CHANGE_DESKTOP: 52 | return "CHANGE_DESKTOP"; 53 | case ActionType::SHOW_DESKTOP: 54 | return "SHOW_DESKTOP"; 55 | case ActionType::SEND_KEYS: 56 | return "SEND_KEYS"; 57 | case ActionType::RUN_COMMAND: 58 | return "RUN_COMMAND"; 59 | case ActionType::MOUSE_CLICK: 60 | return "MOUSE_CLICK"; 61 | default: 62 | return "NOT_SUPPORTED"; 63 | } 64 | } 65 | 66 | inline ActionType actionTypeFromStr(const std::string &str) { 67 | if (str == "MAXIMIZE_RESTORE_WINDOW") { 68 | return ActionType::MAXIMIZE_RESTORE_WINDOW; 69 | } 70 | if (str == "FULLSCREEN_WINDOW") { 71 | return ActionType::FULLSCREEN_WINDOW; 72 | } 73 | if (str == "MINIMIZE_WINDOW") { 74 | return ActionType::MINIMIZE_WINDOW; 75 | } 76 | if (str == "TILE_WINDOW") { 77 | return ActionType::TILE_WINDOW; 78 | } 79 | if (str == "CLOSE_WINDOW") { 80 | return ActionType::CLOSE_WINDOW; 81 | } 82 | if (str == "CHANGE_DESKTOP") { 83 | return ActionType::CHANGE_DESKTOP; 84 | } 85 | if (str == "SHOW_DESKTOP") { 86 | return ActionType::SHOW_DESKTOP; 87 | } 88 | if (str == "SEND_KEYS") { 89 | return ActionType::SEND_KEYS; 90 | } 91 | if (str == "RUN_COMMAND") { 92 | return ActionType::RUN_COMMAND; 93 | } 94 | if (str == "MOUSE_CLICK") { 95 | return ActionType::MOUSE_CLICK; 96 | } 97 | return ActionType::NOT_SUPPORTED; 98 | } 99 | 100 | #endif // ACTIONS_ACTION_TYPE_H_ 101 | -------------------------------------------------------------------------------- /src/actions/action.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #include "actions/action.h" 19 | 20 | #include 21 | 22 | #include "utils/logger.h" 23 | 24 | int Action::readThreshold(const Config &config) { 25 | int threshold = 20; 26 | 27 | try { 28 | threshold = std::stoi(config.getGlobalSetting("action_execute_threshold")); 29 | } catch (std::exception &e) { 30 | tlg::error << "Bad action_execute_threshold value: " << e.what() 31 | << std::endl; 32 | // Leave default 20 if numeric conversion failed 33 | } 34 | 35 | return std::clamp(threshold, 0, 100); 36 | } 37 | -------------------------------------------------------------------------------- /src/actions/action.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #ifndef ACTIONS_ACTION_H_ 19 | #define ACTIONS_ACTION_H_ 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | #include "config/config.h" 26 | #include "gesture/gesture.h" 27 | #include "window-system/window-system.h" 28 | 29 | /** 30 | * Base class for all actions. Use the ActionFactory to build actions. 31 | */ 32 | class Action { 33 | public: 34 | /** 35 | * Default constructor. 36 | * @param settings Action settings. 37 | * @param windowSystem Object to access the underlaying window system. 38 | * @param window The window the gesture is performed on. 39 | * @param config Configuration. 40 | */ 41 | Action(std::unordered_map settings, 42 | const WindowSystem &windowSystem, const WindowT &window, 43 | const Config &config) 44 | : settings(std::move(settings)), 45 | windowSystem(windowSystem), 46 | window(window), 47 | config(config), 48 | threshold(Action::readThreshold(config)) {} 49 | virtual ~Action() = default; 50 | 51 | /** 52 | * The action must return a bool indicating if it can be executed in system 53 | * windows (dock, panel, desktop, etc). 54 | */ 55 | virtual bool runOnSystemWindows() = 0; 56 | 57 | virtual void onGestureBegin(const Gesture &gesture) = 0; 58 | virtual void onGestureUpdate(const Gesture &gesture) = 0; 59 | virtual void onGestureEnd(const Gesture &gesture) = 0; 60 | 61 | protected: 62 | std::unordered_map settings; 63 | const WindowSystem &windowSystem; 64 | const WindowT &window; 65 | const Config &config; 66 | /** 67 | * Special config value: threshold to execute action. All derived actions 68 | * must respect this. 69 | */ 70 | const int threshold; 71 | 72 | private: 73 | /** 74 | * Fail-safe read gesture threshold property from config. 75 | * @param config Config to read threshold value from. 76 | * @returns action_execute_threshold. 77 | */ 78 | static int readThreshold(const Config &config); 79 | }; 80 | 81 | #endif // ACTIONS_ACTION_H_ 82 | -------------------------------------------------------------------------------- /src/actions/animated-action.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #include "actions/animated-action.h" 19 | 20 | #include 21 | 22 | AnimatedAction::AnimatedAction( 23 | std::unordered_map settings, 24 | const WindowSystem &windowSystem, const WindowT &window, 25 | const Config &config) 26 | : Action(std::move(settings), windowSystem, window, config) { 27 | this->animationDelay = 28 | std::stoull(this->config.getGlobalSetting("animation_delay")); 29 | 30 | if (this->settings.count("animate") == 1) { 31 | this->animate = this->settings.at("animate") == "true"; 32 | } 33 | 34 | if (this->animate) { 35 | std::string color; 36 | std::string borderColor; 37 | 38 | if (this->config.hasGlobalSetting("color")) { 39 | color = this->config.getGlobalSetting("color"); 40 | } 41 | 42 | if (this->config.hasGlobalSetting("borderColor")) { 43 | borderColor = this->config.getGlobalSetting("borderColor"); 44 | } 45 | 46 | if (this->settings.count("color") == 1) { 47 | color = this->settings.at("color"); 48 | } 49 | 50 | if (this->settings.count("borderColor") == 1) { 51 | borderColor = this->settings.at("borderColor"); 52 | } 53 | 54 | if (!color.empty()) { 55 | this->color = Color{color, ColorType::BACKGROUND}; 56 | } 57 | 58 | if (!borderColor.empty()) { 59 | this->borderColor = Color{borderColor, ColorType::BORDER}; 60 | } 61 | } 62 | } 63 | 64 | void AnimatedAction::onGestureUpdate(const Gesture &gesture) { 65 | if (this->animation && gesture.elapsedTime() > this->animationDelay) { 66 | this->animation->onUpdate(gesture.percentage()); 67 | } 68 | } 69 | 70 | void AnimatedAction::onGestureEnd(const Gesture &gesture) { 71 | if (!this->animate || gesture.percentage() >= this->threshold) { 72 | this->executeAction(gesture); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/actions/animated-action.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #ifndef ACTIONS_ANIMATED_ACTION_H_ 19 | #define ACTIONS_ANIMATED_ACTION_H_ 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | #include "actions/action.h" 26 | #include "animations/animation.h" 27 | #include "utils/color.h" 28 | 29 | /** 30 | * Base class for animated actions. 31 | */ 32 | class AnimatedAction : public Action { 33 | public: 34 | /** 35 | * Default constructor. 36 | * @see Action. 37 | */ 38 | AnimatedAction(std::unordered_map settings, 39 | const WindowSystem &windowSystem, const WindowT &window, 40 | const Config &config); 41 | ~AnimatedAction() override = default; 42 | 43 | /** 44 | * Override this method to configure the animation. 45 | */ 46 | // virtual void onGestureBegin(const Gesture &gesture) = 0; 47 | 48 | /** 49 | * Run the animation. 50 | */ 51 | void onGestureUpdate(const Gesture &gesture) override; 52 | 53 | /** 54 | * This method calls "executeAction" if the animation passed the configured 55 | * threshold. 56 | */ 57 | void onGestureEnd(const Gesture &gesture) override; 58 | virtual void executeAction(const Gesture &gesture) = 0; 59 | 60 | protected: 61 | /** 62 | * The animation to show. 63 | */ 64 | std::unique_ptr animation = nullptr; 65 | 66 | /** 67 | * If we should show the animation or not. 68 | */ 69 | bool animate = true; 70 | 71 | /** 72 | * Animation color. 73 | */ 74 | Color color; 75 | 76 | /** 77 | * Animation border color. 78 | */ 79 | Color borderColor; 80 | 81 | /** 82 | * "animation_delay" in global config. 83 | */ 84 | uint64_t animationDelay; 85 | }; 86 | 87 | #endif // ACTIONS_ANIMATED_ACTION_H_ 88 | -------------------------------------------------------------------------------- /src/actions/change-desktop.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #ifndef ACTIONS_CHANGE_DESKTOP_H_ 19 | #define ACTIONS_CHANGE_DESKTOP_H_ 20 | 21 | #include "actions/action-direction.h" 22 | #include "actions/animated-action.h" 23 | #include "animations/animation-type.h" 24 | 25 | /** 26 | * Action to change to the next or previous desktop. 27 | */ 28 | class ChangeDesktop : public AnimatedAction { 29 | public: 30 | using AnimatedAction::AnimatedAction; 31 | bool runOnSystemWindows() override { return true; } 32 | void onGestureBegin(const Gesture &gesture) override; 33 | void executeAction(const Gesture &gesture) override; 34 | 35 | private: 36 | ActionDirection direction = ActionDirection::AUTO; 37 | bool cyclic = false; 38 | 39 | ActionDirection getAnimationAutoDirection(const Gesture &gesture) const; 40 | ActionDirection getActionAutoDirection(const Gesture &gesture) const; 41 | static AnimationType directionToAnimation(ActionDirection direction); 42 | }; 43 | 44 | #endif // ACTIONS_CHANGE_DESKTOP_H_ 45 | -------------------------------------------------------------------------------- /src/actions/close-window.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #include "actions/close-window.h" 19 | 20 | #include 21 | 22 | #include "animations/animation-factory.h" 23 | 24 | void CloseWindow::onGestureBegin(const Gesture& /*gesture*/) { 25 | if (this->animate) { 26 | this->animation = AnimationFactory::buildAnimation( 27 | AnimationType::CLOSE_WINDOW, this->windowSystem, this->window, 28 | this->color, this->borderColor); 29 | } 30 | } 31 | 32 | void CloseWindow::executeAction(const Gesture& /*gesture*/) { 33 | this->windowSystem.closeWindow(this->window); 34 | } 35 | -------------------------------------------------------------------------------- /src/actions/close-window.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #ifndef ACTIONS_CLOSE_WINDOW_H_ 19 | #define ACTIONS_CLOSE_WINDOW_H_ 20 | 21 | #include "actions/animated-action.h" 22 | 23 | /** 24 | * Minimize the window under the pointer. 25 | */ 26 | class CloseWindow : public AnimatedAction { 27 | public: 28 | using AnimatedAction::AnimatedAction; 29 | bool runOnSystemWindows() override { return false; } 30 | void onGestureBegin(const Gesture &gesture) override; 31 | void executeAction(const Gesture &gesture) override; 32 | }; 33 | 34 | #endif // ACTIONS_CLOSE_WINDOW_H_ 35 | -------------------------------------------------------------------------------- /src/actions/execute-action-on.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2024 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #ifndef ACTIONS_EXECUTE_ACTION_ON_H_ 19 | #define ACTIONS_EXECUTE_ACTION_ON_H_ 20 | 21 | #include 22 | 23 | enum class ExecuteActionOn { 24 | NOT_SUPPORTED, 25 | BEGIN, 26 | END, 27 | BEGIN_AND_END, 28 | // Adding a new value? Don't forget to add it in executeActionOnFromStr and 29 | // shouldExecuteAction 30 | }; 31 | 32 | inline ExecuteActionOn executeActionOnFromStr(const std::string &str) { 33 | if (str == "begin") { 34 | return ExecuteActionOn::BEGIN; 35 | } 36 | if (str == "end") { 37 | return ExecuteActionOn::END; 38 | } 39 | if (str == "begin-and-end") { 40 | return ExecuteActionOn::BEGIN_AND_END; 41 | } 42 | return ExecuteActionOn::NOT_SUPPORTED; 43 | } 44 | 45 | inline bool shouldExecuteAction(ExecuteActionOn phase, ExecuteActionOn config) { 46 | switch (config) { 47 | case ExecuteActionOn::BEGIN: 48 | return phase == ExecuteActionOn::BEGIN; 49 | case ExecuteActionOn::END: 50 | return phase == ExecuteActionOn::END; 51 | case ExecuteActionOn::BEGIN_AND_END: 52 | return true; 53 | default: 54 | return false; 55 | } 56 | } 57 | 58 | #endif // ACTIONS_EXECUTE_ACTION_ON_H_ 59 | -------------------------------------------------------------------------------- /src/actions/fullscreen-window.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #include "actions/fullscreen-window.h" 19 | 20 | #include 21 | 22 | #include "animations/animation-factory.h" 23 | 24 | void FullscreenWindow::onGestureBegin(const Gesture& /*gesture*/) { 25 | if (this->animate) { 26 | AnimationType animationType = 27 | this->windowSystem.isWindowFullscreen(this->window) 28 | ? AnimationType::RESTORE_WINDOW 29 | : AnimationType::MAXIMIZE_WINDOW; 30 | 31 | this->animation = AnimationFactory::buildAnimation( 32 | animationType, this->windowSystem, this->window, this->color, 33 | this->borderColor); 34 | } 35 | } 36 | 37 | void FullscreenWindow::executeAction(const Gesture& /*gesture*/) { 38 | this->windowSystem.toggleFullscreenWindow(this->window); 39 | } 40 | -------------------------------------------------------------------------------- /src/actions/fullscreen-window.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #ifndef ACTIONS_FULLSCREEN_WINDOW_H_ 19 | #define ACTIONS_FULLSCREEN_WINDOW_H_ 20 | 21 | #include "actions/animated-action.h" 22 | 23 | /** 24 | * Action to make the window under the pointer use the whole screen. 25 | */ 26 | class FullscreenWindow : public AnimatedAction { 27 | public: 28 | using AnimatedAction::AnimatedAction; 29 | bool runOnSystemWindows() override { return false; } 30 | void onGestureBegin(const Gesture &gesture) override; 31 | void executeAction(const Gesture &gesture) override; 32 | }; 33 | 34 | #endif // ACTIONS_FULLSCREEN_WINDOW_H_ 35 | -------------------------------------------------------------------------------- /src/actions/maximize-restore-window.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #include "actions/maximize-restore-window.h" 19 | 20 | #include 21 | 22 | #include "animations/animation-factory.h" 23 | 24 | void MaximizeRestoreWindow::onGestureBegin(const Gesture& /*gesture*/) { 25 | if (this->animate) { 26 | AnimationType animationType = 27 | this->windowSystem.isWindowMaximized(this->window) 28 | ? AnimationType::RESTORE_WINDOW 29 | : AnimationType::MAXIMIZE_WINDOW; 30 | 31 | this->animation = AnimationFactory::buildAnimation( 32 | animationType, this->windowSystem, this->window, this->color, 33 | this->borderColor); 34 | } 35 | } 36 | 37 | void MaximizeRestoreWindow::executeAction(const Gesture& /*gesture*/) { 38 | this->windowSystem.maximizeOrRestoreWindow(this->window); 39 | } 40 | -------------------------------------------------------------------------------- /src/actions/maximize-restore-window.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #ifndef ACTIONS_MAXIMIZE_RESTORE_WINDOW_H_ 19 | #define ACTIONS_MAXIMIZE_RESTORE_WINDOW_H_ 20 | 21 | #include "actions/animated-action.h" 22 | 23 | /** 24 | * Action to maximize or restore the window under the pointer. 25 | * If the window is not maximized, maximize it, otherwise restore its size. 26 | */ 27 | class MaximizeRestoreWindow : public AnimatedAction { 28 | public: 29 | using AnimatedAction::AnimatedAction; 30 | bool runOnSystemWindows() override { return false; } 31 | void onGestureBegin(const Gesture &gesture) override; 32 | void executeAction(const Gesture &gesture) override; 33 | }; 34 | 35 | #endif // ACTIONS_MAXIMIZE_RESTORE_WINDOW_H_ 36 | -------------------------------------------------------------------------------- /src/actions/minimize-window.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #include "actions/minimize-window.h" 19 | 20 | #include 21 | 22 | #include "animations/animation-factory.h" 23 | 24 | void MinimizeWindow::onGestureBegin(const Gesture& /*gesture*/) { 25 | if (this->animate) { 26 | this->animation = AnimationFactory::buildAnimation( 27 | AnimationType::MINIMIZE_WINDOW, this->windowSystem, this->window, 28 | this->color, this->borderColor); 29 | } 30 | } 31 | 32 | void MinimizeWindow::executeAction(const Gesture& /*gesture*/) { 33 | this->windowSystem.minimizeWindow(this->window); 34 | } 35 | -------------------------------------------------------------------------------- /src/actions/minimize-window.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #ifndef ACTIONS_MINIMIZE_WINDOW_H_ 19 | #define ACTIONS_MINIMIZE_WINDOW_H_ 20 | 21 | #include "actions/animated-action.h" 22 | 23 | /** 24 | * Minimize the window under the pointer. 25 | */ 26 | class MinimizeWindow : public AnimatedAction { 27 | public: 28 | using AnimatedAction::AnimatedAction; 29 | bool runOnSystemWindows() override { return false; } 30 | void onGestureBegin(const Gesture &gesture) override; 31 | void executeAction(const Gesture &gesture) override; 32 | }; 33 | 34 | #endif // ACTIONS_MINIMIZE_WINDOW_H_ 35 | -------------------------------------------------------------------------------- /src/actions/mouse-click.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #include "actions/mouse-click.h" 19 | 20 | void MouseClick::onGestureBegin(const Gesture& /*gesture*/) { 21 | if (this->settings.count("button") == 1) { 22 | this->button = std::stoi(this->settings.at("button")); 23 | } 24 | 25 | if (this->settings.count("on") == 1) { 26 | this->executeActionOn = executeActionOnFromStr(this->settings.at("on")); 27 | } 28 | 29 | if (shouldExecuteAction(ExecuteActionOn::BEGIN, this->executeActionOn)) { 30 | this->windowSystem.sendMouseDown(this->button); 31 | 32 | if (this->executeActionOn != ExecuteActionOn::BEGIN_AND_END) { 33 | this->windowSystem.sendMouseUp(this->button); 34 | } 35 | } 36 | } 37 | 38 | void MouseClick::onGestureUpdate(const Gesture& /*gesture*/) {} 39 | 40 | void MouseClick::onGestureEnd(const Gesture& /*gesture*/) { 41 | if (shouldExecuteAction(ExecuteActionOn::END, this->executeActionOn)) { 42 | if (this->executeActionOn != ExecuteActionOn::BEGIN_AND_END) { 43 | this->windowSystem.sendMouseDown(this->button); 44 | } 45 | 46 | this->windowSystem.sendMouseUp(this->button); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/actions/mouse-click.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #ifndef ACTIONS_MOUSE_CLICK_H_ 19 | #define ACTIONS_MOUSE_CLICK_H_ 20 | 21 | #include 22 | 23 | #include "actions/action.h" 24 | #include "actions/execute-action-on.h" 25 | 26 | /** 27 | * Action to emulate a shortcut. 28 | */ 29 | class MouseClick : public Action { 30 | public: 31 | using Action::Action; 32 | bool runOnSystemWindows() override { return true; } 33 | void onGestureBegin(const Gesture &gesture) override; 34 | void onGestureUpdate(const Gesture &gesture) override; 35 | void onGestureEnd(const Gesture &gesture) override; 36 | 37 | private: 38 | int button = 1; 39 | ExecuteActionOn executeActionOn = ExecuteActionOn::BEGIN; 40 | }; 41 | 42 | #endif // ACTIONS_MOUSE_CLICK_H_ 43 | -------------------------------------------------------------------------------- /src/actions/repeated-action.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #include "actions/repeated-action.h" 19 | 20 | #include 21 | 22 | void RepeatedAction::executePrelude() {} 23 | void RepeatedAction::executePostlude() {} 24 | 25 | void RepeatedAction::onGestureBegin(const Gesture &gesture) { 26 | // read repeated action settings 27 | if (this->settings.count("repeat") == 1) { 28 | this->repeat = (this->settings.at("repeat") == "true"); 29 | } 30 | 31 | if (this->settings.count("times") == 1) { 32 | const int times = std::clamp(std::stoi(this->settings.at("times")), 2, 15); 33 | this->repeatPercentageStep = (100 / times); 34 | } 35 | 36 | if (this->settings.count("on") == 1) { 37 | this->executeActionOn = executeActionOnFromStr(this->settings.at("on")); 38 | } 39 | 40 | // execute supplied prelude 41 | this->executePrelude(); 42 | 43 | // run action on begin 44 | if (!this->repeat && 45 | shouldExecuteAction(ExecuteActionOn::BEGIN, this->executeActionOn)) { 46 | this->executeAction(gesture); 47 | } 48 | } 49 | 50 | void RepeatedAction::onGestureUpdate(const Gesture &gesture) { 51 | AnimatedAction::onGestureUpdate(gesture); 52 | 53 | if (this->repeat) { 54 | const bool increased = 55 | (gesture.percentage() >= 56 | (this->repeatPercentage + this->repeatPercentageStep)); 57 | const bool decreased = 58 | (gesture.percentage() <= 59 | (this->repeatPercentage - this->repeatPercentageStep)); 60 | 61 | if (increased) { 62 | this->executeAction(gesture); 63 | this->repeatPercentage += this->repeatPercentageStep; 64 | } 65 | 66 | if (decreased) { 67 | this->executeReverse(gesture); 68 | this->repeatPercentage -= this->repeatPercentageStep; 69 | } 70 | } 71 | } 72 | 73 | void RepeatedAction::onGestureEnd(const Gesture &gesture) { 74 | if (!this->repeat && 75 | shouldExecuteAction(ExecuteActionOn::END, this->executeActionOn)) { 76 | // Do not take into account the threshold is the action is executed on begin 77 | // and end. Otherwise, we could miss could execute only the on begin part. 78 | if (this->executeActionOn == ExecuteActionOn::BEGIN_AND_END || 79 | gesture.percentage() >= this->threshold) { 80 | this->executeAction(gesture); 81 | } 82 | } 83 | 84 | this->executePostlude(); 85 | } 86 | -------------------------------------------------------------------------------- /src/actions/repeated-action.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #ifndef ACTIONS_REPEATED_ACTION_H_ 19 | #define ACTIONS_REPEATED_ACTION_H_ 20 | 21 | #include "actions/animated-action.h" 22 | #include "actions/execute-action-on.h" 23 | 24 | class RepeatedAction : public AnimatedAction { 25 | public: 26 | using AnimatedAction::AnimatedAction; 27 | virtual ~RepeatedAction() = default; 28 | 29 | /** 30 | * Execute gesture on begin 31 | */ 32 | void onGestureBegin(const Gesture &gesture) override; 33 | 34 | /** 35 | * Execute gesture repeatedly 36 | */ 37 | void onGestureUpdate(const Gesture &gesture) override; 38 | 39 | /** 40 | * Execute gesture on end if threshold passed 41 | */ 42 | void onGestureEnd(const Gesture &gesture) override; 43 | 44 | /** 45 | * If your action requires some pre-setup, override this method. This is 46 | * executed unconditionally upon gesture beginning 47 | */ 48 | virtual void executePrelude(); 49 | 50 | /** 51 | * If your action requires some post-setup, override this method. This is 52 | * executed unconditionally upon gesture ending 53 | */ 54 | virtual void executePostlude(); 55 | 56 | /** 57 | * Override this method to configure what is executed for succesful gesture 58 | * @param gesture The gesture that triggered the action 59 | */ 60 | void executeAction(const Gesture &gesture) override = 0; 61 | 62 | /** 63 | * Override this method to configure what is executed for reversed gesture 64 | * @param gesture The gesture that triggered the action 65 | */ 66 | virtual void executeReverse(const Gesture &gesture) = 0; 67 | 68 | protected: 69 | /** 70 | * Whether the action should be repeated or not. 71 | */ 72 | bool repeat = false; 73 | 74 | /** 75 | * If "repeat" is true, the total gesture percentage accumulated. 76 | */ 77 | double repeatPercentage = 0; 78 | 79 | /** 80 | * If "repeat" is true, the percentage that should be accumulated to execute 81 | * the action. 82 | */ 83 | double repeatPercentageStep = 10; 84 | 85 | /** 86 | * Whether the action should be executed on gesture begin or end. 87 | */ 88 | ExecuteActionOn executeActionOn = ExecuteActionOn::BEGIN; 89 | }; 90 | 91 | #endif // ACTIONS_REPEATED_ACTION_H_ 92 | -------------------------------------------------------------------------------- /src/actions/run-command.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #include "actions/run-command.h" 19 | 20 | #include 21 | 22 | #include "animations/animation-factory.h" 23 | 24 | void RunCommand::onGestureBegin(const Gesture &gesture) { 25 | setenv("TOUCHEGG_GESTURE_ON", "begin", 1); 26 | RepeatedAction::onGestureBegin(gesture); 27 | 28 | if (!this->animate) { 29 | return; 30 | } 31 | 32 | if (this->settings.count("animation") == 1) { 33 | std::string animationTypeStr = this->settings.at("animation"); 34 | AnimationType animationType = animationTypeFromStr(animationTypeStr); 35 | 36 | this->animation = AnimationFactory::buildAnimation( 37 | animationType, this->windowSystem, this->window, this->color, 38 | this->borderColor); 39 | } 40 | } 41 | 42 | void RunCommand::onGestureUpdate(const Gesture &gesture) { 43 | setenv("TOUCHEGG_GESTURE_ON", "update", 1); 44 | RepeatedAction::onGestureUpdate(gesture); 45 | } 46 | 47 | void RunCommand::onGestureEnd(const Gesture &gesture) { 48 | setenv("TOUCHEGG_GESTURE_ON", "end", 1); 49 | RepeatedAction::onGestureEnd(gesture); 50 | } 51 | 52 | void RunCommand::executePrelude() { 53 | if (this->settings.count("command") == 1) { 54 | this->command = this->settings.at("command"); 55 | } 56 | 57 | if (this->settings.count("decreaseCommand") == 1) { 58 | this->decreaseCommand = this->settings.at("decreaseCommand"); 59 | } 60 | } 61 | 62 | void RunCommand::executeAction(const Gesture &gesture) { 63 | RunCommand::runCommand(this->command, gesture); 64 | } 65 | 66 | void RunCommand::executeReverse(const Gesture &gesture) { 67 | RunCommand::runCommand(this->decreaseCommand, gesture); 68 | } 69 | 70 | bool RunCommand::runCommand(const std::string &command, 71 | const Gesture &gesture) { 72 | setenv("TOUCHEGG_DEVICE_TYPE", 73 | deviceTypeToStr(gesture.performedOnDeviceType()).c_str(), 1); 74 | int ret = system(command.c_str()); 75 | unsetenv("TOUCHEGG_DEVICE_TYPE"); 76 | return (ret == 0); 77 | } 78 | -------------------------------------------------------------------------------- /src/actions/run-command.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #ifndef ACTIONS_RUN_COMMAND_H_ 19 | #define ACTIONS_RUN_COMMAND_H_ 20 | 21 | #include 22 | 23 | #include "actions/repeated-action.h" 24 | 25 | /** 26 | * Action to emulate a shortcut. 27 | */ 28 | class RunCommand : public RepeatedAction { 29 | public: 30 | using RepeatedAction::RepeatedAction; 31 | void onGestureBegin(const Gesture &gesture) override; 32 | void onGestureUpdate(const Gesture &gesture) override; 33 | void onGestureEnd(const Gesture &gesture) override; 34 | bool runOnSystemWindows() override { return true; } 35 | void executePrelude() override; 36 | void executeAction(const Gesture &gesture) override; 37 | void executeReverse(const Gesture &gesture) override; 38 | 39 | private: 40 | std::string command; 41 | std::string decreaseCommand; 42 | 43 | static bool runCommand(const std::string &command, const Gesture &gesture); 44 | }; 45 | 46 | #endif // ACTIONS_RUN_COMMAND_H_ 47 | -------------------------------------------------------------------------------- /src/actions/send-keys.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #include "actions/send-keys.h" 19 | 20 | #include "animations/animation-factory.h" 21 | #include "utils/string.h" 22 | 23 | void SendKeys::onGestureBegin(const Gesture& gesture) { 24 | RepeatedAction::onGestureBegin(gesture); 25 | 26 | if (!this->animate) { 27 | return; 28 | } 29 | 30 | if (this->settings.count("animation") == 1) { 31 | std::string animationTypeStr = this->settings.at("animation"); 32 | AnimationType animationType = animationTypeFromStr(animationTypeStr); 33 | 34 | this->animation = AnimationFactory::buildAnimation( 35 | animationType, this->windowSystem, this->window, this->color, 36 | this->borderColor); 37 | } 38 | } 39 | 40 | void SendKeys::executePrelude() { 41 | if (this->settings.count("modifiers") == 1) { 42 | this->modifiers = split(this->settings.at("modifiers"), '+'); 43 | } 44 | 45 | if (this->settings.count("keys") == 1) { 46 | this->keys = split(this->settings.at("keys"), '+'); 47 | } 48 | 49 | if (this->settings.count("decreaseKeys") == 1) { 50 | this->decreaseKeys = split(this->settings.at("decreaseKeys"), '+'); 51 | } 52 | 53 | // Only the active window receives shortcuts 54 | if (!this->windowSystem.isSystemWindow(this->window)) { 55 | this->windowSystem.activateWindow(this->window); 56 | } 57 | 58 | // "Press" the modifiers and keys if required 59 | this->windowSystem.sendKeys(this->modifiers, true); 60 | } 61 | 62 | void SendKeys::executePostlude() { 63 | // "Release" the modifiers and keys if required 64 | this->windowSystem.sendKeys(this->modifiers, false); 65 | } 66 | 67 | void SendKeys::executeAction(const Gesture& /*gesture*/) { 68 | this->windowSystem.sendKeys(this->keys, true); 69 | this->windowSystem.sendKeys(this->keys, false); 70 | } 71 | 72 | void SendKeys::executeReverse(const Gesture& /*gesture*/) { 73 | this->windowSystem.sendKeys(this->decreaseKeys, true); 74 | this->windowSystem.sendKeys(this->decreaseKeys, false); 75 | } 76 | -------------------------------------------------------------------------------- /src/actions/send-keys.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #ifndef ACTIONS_SEND_KEYS_H_ 19 | #define ACTIONS_SEND_KEYS_H_ 20 | 21 | #include 22 | #include 23 | 24 | #include "actions/repeated-action.h" 25 | 26 | /** 27 | * Action to emulate a shortcut. 28 | */ 29 | class SendKeys : public RepeatedAction { 30 | public: 31 | using RepeatedAction::RepeatedAction; 32 | void onGestureBegin(const Gesture &gesture) override; 33 | bool runOnSystemWindows() override { return true; } 34 | void executePrelude() override; 35 | void executePostlude() override; 36 | void executeAction(const Gesture &gesture) override; 37 | void executeReverse(const Gesture &gesture) override; 38 | 39 | private: 40 | std::vector modifiers; 41 | std::vector keys; 42 | std::vector decreaseKeys; 43 | }; 44 | 45 | #endif // ACTIONS_SEND_KEYS_H_ 46 | -------------------------------------------------------------------------------- /src/actions/show-desktop.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #include "actions/show-desktop.h" 19 | 20 | #include 21 | 22 | #include "animations/animation-factory.h" 23 | 24 | void ShowDesktop::onGestureBegin(const Gesture& /*gesture*/) { 25 | this->showingDesktop = this->windowSystem.isShowingDesktop(); 26 | 27 | if (this->animate) { 28 | AnimationType animationType = this->showingDesktop 29 | ? AnimationType::EXIST_SHOW_DESKTOP 30 | : AnimationType::SHOW_DESKTOP; 31 | 32 | this->animation = AnimationFactory::buildAnimation( 33 | animationType, this->windowSystem, this->window, this->color, 34 | this->borderColor); 35 | } 36 | } 37 | 38 | void ShowDesktop::executeAction(const Gesture& /*gesture*/) { 39 | this->windowSystem.showDesktop(!this->showingDesktop); 40 | } 41 | -------------------------------------------------------------------------------- /src/actions/show-desktop.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #ifndef ACTIONS_SHOW_DESKTOP_H_ 19 | #define ACTIONS_SHOW_DESKTOP_H_ 20 | 21 | #include "actions/animated-action.h" 22 | 23 | /** 24 | * Minimize the window under the pointer. 25 | */ 26 | class ShowDesktop : public AnimatedAction { 27 | public: 28 | using AnimatedAction::AnimatedAction; 29 | bool runOnSystemWindows() override { return true; } 30 | void onGestureBegin(const Gesture &gesture) override; 31 | void executeAction(const Gesture &gesture) override; 32 | 33 | private: 34 | bool showingDesktop = false; 35 | }; 36 | 37 | #endif // ACTIONS_SHOW_DESKTOP_H_ 38 | -------------------------------------------------------------------------------- /src/actions/tile-window.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #include "actions/tile-window.h" 19 | 20 | #include "animations/animation-factory.h" 21 | 22 | void TileWindow::onGestureBegin(const Gesture& /*gesture*/) { 23 | if (this->settings.count("direction") == 1) { 24 | this->toTheLeft = this->settings.at("direction") == "left"; 25 | } 26 | 27 | if (this->animate) { 28 | AnimationType animationType = this->toTheLeft 29 | ? AnimationType::TILE_WINDOW_LEFT 30 | : AnimationType::TILE_WINDOW_RIGHT; 31 | 32 | this->animation = AnimationFactory::buildAnimation( 33 | animationType, this->windowSystem, this->window, this->color, 34 | this->borderColor); 35 | } 36 | } 37 | 38 | void TileWindow::executeAction(const Gesture& /*gesture*/) { 39 | this->windowSystem.tileWindow(this->window, this->toTheLeft); 40 | } 41 | -------------------------------------------------------------------------------- /src/actions/tile-window.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #ifndef ACTIONS_TILE_WINDOW_H_ 19 | #define ACTIONS_TILE_WINDOW_H_ 20 | 21 | #include 22 | 23 | #include "actions/animated-action.h" 24 | 25 | class TileWindow : public AnimatedAction { 26 | public: 27 | using AnimatedAction::AnimatedAction; 28 | bool runOnSystemWindows() override { return false; } 29 | void onGestureBegin(const Gesture &gesture) override; 30 | void executeAction(const Gesture &gesture) override; 31 | 32 | private: 33 | bool toTheLeft = true; 34 | }; 35 | 36 | #endif // ACTIONS_TILE_WINDOW_H_ 37 | -------------------------------------------------------------------------------- /src/animations/animation-factory.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #include "animations/animation-factory.h" 19 | 20 | #include 21 | 22 | #include "actions/action-direction.h" 23 | #include "animations/animation.h" 24 | #include "animations/change-desktop-animation.h" 25 | #include "animations/close-window-animation.h" 26 | #include "animations/maximize-window-animation.h" 27 | #include "animations/minimize-window-animation.h" 28 | #include "animations/restore-window-animation.h" 29 | #include "animations/show-desktop-animation.h" 30 | #include "animations/tile-window-animation.h" 31 | 32 | std::unique_ptr AnimationFactory::buildAnimation( 33 | AnimationType type, const WindowSystem &windowSystem, const WindowT &window, 34 | Color color, Color borderColor) { 35 | switch (type) { 36 | case AnimationType::CHANGE_DESKTOP_UP: 37 | return std::make_unique( 38 | windowSystem, window, color, borderColor, ActionDirection::UP); 39 | case AnimationType::CHANGE_DESKTOP_DOWN: 40 | return std::make_unique( 41 | windowSystem, window, color, borderColor, ActionDirection::DOWN); 42 | case AnimationType::CHANGE_DESKTOP_LEFT: 43 | return std::make_unique( 44 | windowSystem, window, color, borderColor, ActionDirection::LEFT); 45 | case AnimationType::CHANGE_DESKTOP_RIGHT: 46 | return std::make_unique( 47 | windowSystem, window, color, borderColor, ActionDirection::RIGHT); 48 | case AnimationType::CLOSE_WINDOW: 49 | return std::make_unique(windowSystem, window, color, 50 | borderColor); 51 | case AnimationType::MAXIMIZE_WINDOW: 52 | return std::make_unique(windowSystem, window, 53 | color, borderColor); 54 | case AnimationType::MINIMIZE_WINDOW: 55 | return std::make_unique(windowSystem, window, 56 | color, borderColor); 57 | case AnimationType::RESTORE_WINDOW: 58 | return std::make_unique(windowSystem, window, 59 | color, borderColor); 60 | case AnimationType::SHOW_DESKTOP: 61 | return std::make_unique(windowSystem, window, color, 62 | borderColor, false); 63 | case AnimationType::EXIST_SHOW_DESKTOP: 64 | return std::make_unique(windowSystem, window, color, 65 | borderColor, true); 66 | case AnimationType::TILE_WINDOW_LEFT: 67 | return std::make_unique(windowSystem, window, color, 68 | borderColor, true); 69 | case AnimationType::TILE_WINDOW_RIGHT: 70 | return std::make_unique(windowSystem, window, color, 71 | borderColor, false); 72 | default: 73 | return nullptr; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/animations/animation-factory.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #ifndef ANIMATIONS_ANIMATION_FACTORY_H_ 19 | #define ANIMATIONS_ANIMATION_FACTORY_H_ 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | #include "animations/animation-type.h" 26 | #include "animations/animation.h" 27 | #include "utils/color.h" 28 | 29 | class AnimationFactory { 30 | public: 31 | static std::unique_ptr buildAnimation( 32 | AnimationType type, const WindowSystem &windowSystem, 33 | const WindowT &window, Color color, Color borderColor); 34 | }; 35 | 36 | #endif // ANIMATIONS_ANIMATION_FACTORY_H_ 37 | -------------------------------------------------------------------------------- /src/animations/animation-type.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #ifndef ANIMATIONS_ANIMATION_TYPE_H_ 19 | #define ANIMATIONS_ANIMATION_TYPE_H_ 20 | 21 | #include 22 | 23 | enum class AnimationType { 24 | NONE, 25 | CHANGE_DESKTOP_UP, 26 | CHANGE_DESKTOP_DOWN, 27 | CHANGE_DESKTOP_LEFT, 28 | CHANGE_DESKTOP_RIGHT, 29 | CLOSE_WINDOW, 30 | MAXIMIZE_WINDOW, 31 | MINIMIZE_WINDOW, 32 | RESTORE_WINDOW, 33 | SHOW_DESKTOP, 34 | EXIST_SHOW_DESKTOP, 35 | TILE_WINDOW_LEFT, 36 | TILE_WINDOW_RIGHT, 37 | // Adding a new animation? Don't forget to add it in animationTypeToStr, 38 | // animationTypeFromStr and AnimationFactory::buildAnimation 39 | }; 40 | 41 | inline std::string animationTypeToStr(AnimationType animationType) { 42 | switch (animationType) { 43 | case AnimationType::CHANGE_DESKTOP_UP: 44 | return "CHANGE_DESKTOP_UP"; 45 | case AnimationType::CHANGE_DESKTOP_DOWN: 46 | return "CHANGE_DESKTOP_DOWN"; 47 | case AnimationType::CHANGE_DESKTOP_LEFT: 48 | return "CHANGE_DESKTOP_LEFT"; 49 | case AnimationType::CHANGE_DESKTOP_RIGHT: 50 | return "CHANGE_DESKTOP_RIGHT"; 51 | case AnimationType::CLOSE_WINDOW: 52 | return "CLOSE_WINDOW"; 53 | case AnimationType::MAXIMIZE_WINDOW: 54 | return "MAXIMIZE_WINDOW"; 55 | case AnimationType::MINIMIZE_WINDOW: 56 | return "MINIMIZE_WINDOW"; 57 | case AnimationType::RESTORE_WINDOW: 58 | return "RESTORE_WINDOW"; 59 | case AnimationType::SHOW_DESKTOP: 60 | return "SHOW_DESKTOP"; 61 | case AnimationType::EXIST_SHOW_DESKTOP: 62 | return "EXIST_SHOW_DESKTOP"; 63 | case AnimationType::TILE_WINDOW_LEFT: 64 | return "TILE_WINDOW_LEFT"; 65 | case AnimationType::TILE_WINDOW_RIGHT: 66 | return "TILE_WINDOW_RIGHT"; 67 | default: 68 | return "NONE"; 69 | } 70 | } 71 | 72 | inline AnimationType animationTypeFromStr(const std::string &str) { 73 | if (str == "CHANGE_DESKTOP_UP") { 74 | return AnimationType::CHANGE_DESKTOP_UP; 75 | } 76 | if (str == "CHANGE_DESKTOP_DOWN") { 77 | return AnimationType::CHANGE_DESKTOP_DOWN; 78 | } 79 | if (str == "CHANGE_DESKTOP_LEFT") { 80 | return AnimationType::CHANGE_DESKTOP_LEFT; 81 | } 82 | if (str == "CHANGE_DESKTOP_RIGHT") { 83 | return AnimationType::CHANGE_DESKTOP_RIGHT; 84 | } 85 | if (str == "CLOSE_WINDOW") { 86 | return AnimationType::CLOSE_WINDOW; 87 | } 88 | if (str == "MAXIMIZE_WINDOW") { 89 | return AnimationType::MAXIMIZE_WINDOW; 90 | } 91 | if (str == "MINIMIZE_WINDOW") { 92 | return AnimationType::MINIMIZE_WINDOW; 93 | } 94 | if (str == "RESTORE_WINDOW") { 95 | return AnimationType::RESTORE_WINDOW; 96 | } 97 | if (str == "SHOW_DESKTOP") { 98 | return AnimationType::SHOW_DESKTOP; 99 | } 100 | if (str == "EXIST_SHOW_DESKTOP") { 101 | return AnimationType::EXIST_SHOW_DESKTOP; 102 | } 103 | if (str == "TILE_WINDOW_LEFT") { 104 | return AnimationType::TILE_WINDOW_LEFT; 105 | } 106 | if (str == "TILE_WINDOW_RIGHT") { 107 | return AnimationType::TILE_WINDOW_RIGHT; 108 | } 109 | return AnimationType::NONE; 110 | } 111 | 112 | #endif // ANIMATIONS_ANIMATION_TYPE_H_ 113 | -------------------------------------------------------------------------------- /src/animations/animation.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #include "animations/animation.h" 19 | 20 | #include // NOLINT 21 | 22 | void Animation::onUpdate(double percentage) { 23 | constexpr uint64_t frameRate = (1000 / 30); 24 | 25 | // Discard draws that exceed the frame rate 26 | auto now = std::chrono::system_clock::now().time_since_epoch(); 27 | uint64_t millis = 28 | std::chrono::duration_cast(now).count(); 29 | 30 | if (millis < (this->lastRenderTimestamp + frameRate)) { 31 | return; 32 | } 33 | this->lastRenderTimestamp = millis; 34 | 35 | // Rely on the base class for rendering the animation 36 | this->render(percentage); 37 | } 38 | 39 | double Animation::value(double initialValue, double targetValue, 40 | double percentage) { 41 | return (((targetValue - initialValue) * percentage) / 100) + initialValue; 42 | } 43 | -------------------------------------------------------------------------------- /src/animations/animation.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #ifndef ANIMATIONS_ANIMATION_H_ 19 | #define ANIMATIONS_ANIMATION_H_ 20 | 21 | #include 22 | 23 | #include 24 | #include 25 | 26 | #include "window-system/cairo-surface.h" 27 | #include "window-system/window-system.h" 28 | 29 | /** 30 | * Base class form animations. 31 | */ 32 | class Animation { 33 | public: 34 | Animation(const WindowSystem &windowSystem, const WindowT &window) 35 | : windowSystem(windowSystem), 36 | window(window), 37 | cairoSurface(this->windowSystem.createCairoSurface()) {} 38 | 39 | virtual ~Animation() = default; 40 | 41 | /** 42 | * Called every time an action request an update. 43 | * Decide if rendering is required or not. 44 | */ 45 | void onUpdate(double percentage); 46 | 47 | /** 48 | * Draw the animation on screen. 49 | * @param percentage A number between 0 and 100 indicating the percentage of 50 | * the animation. 51 | */ 52 | virtual void render(double percentage) = 0; 53 | 54 | protected: 55 | const WindowSystem &windowSystem; 56 | const WindowT &window; 57 | std::unique_ptr cairoSurface; 58 | 59 | /** 60 | * Animation maximun alpha value. 61 | */ 62 | static constexpr double MAX_ALPHA = 0.6; 63 | 64 | /** 65 | * Utility method to calculate the current animation value based on the 66 | * percentage of the gesture performed. 67 | * Animations are always linear, as they are 1:1 to the user's movement. 68 | * @param initialValue Animation start value. 69 | * @param targetValue Animation end value. 70 | * @param percentage Current animation percentage. 71 | * @returns The linear animation value at the specified percentage. 72 | */ 73 | static double value(double initialValue, double targetValue, 74 | double percentage); 75 | 76 | private: 77 | uint64_t lastRenderTimestamp = 0; 78 | }; 79 | 80 | #endif // ANIMATIONS_ANIMATION_H_ 81 | -------------------------------------------------------------------------------- /src/animations/change-desktop-animation.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #ifndef ANIMATIONS_CHANGE_DESKTOP_ANIMATION_H_ 19 | #define ANIMATIONS_CHANGE_DESKTOP_ANIMATION_H_ 20 | 21 | #include 22 | 23 | #include "actions/action-direction.h" 24 | #include "animations/animation.h" 25 | #include "utils/color.h" 26 | #include "utils/rectangle.h" 27 | 28 | class ChangeDesktopAnimation : public Animation { 29 | public: 30 | using Animation::Animation; 31 | ChangeDesktopAnimation(const WindowSystem &windowSystem, 32 | const WindowT &window, Color color, Color borderColor, 33 | ActionDirection animationPosition); 34 | void render(double percentage) override; 35 | 36 | private: 37 | Rectangle maxSize; 38 | Color color; 39 | Color borderColor; 40 | double angle; 41 | }; 42 | 43 | #endif // ANIMATIONS_CHANGE_DESKTOP_ANIMATION_H_ 44 | -------------------------------------------------------------------------------- /src/animations/close-window-animation.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #include "animations/close-window-animation.h" 19 | 20 | #include 21 | #include 22 | 23 | CloseWindowAnimation::CloseWindowAnimation(const WindowSystem &windowSystem, 24 | const WindowT &window, Color color, 25 | Color borderColor) 26 | : Animation(windowSystem, window), 27 | maxSize(this->windowSystem.getWindowSize(this->window)), 28 | color(color), 29 | borderColor(borderColor) {} 30 | 31 | void CloseWindowAnimation::render(double percentage) { 32 | cairo_t *ctx = this->cairoSurface->getContext(); 33 | 34 | // Clear the background 35 | cairo_set_source_rgba(ctx, 0, 0, 0, 0); 36 | cairo_set_operator(ctx, CAIRO_OPERATOR_SOURCE); 37 | cairo_paint(ctx); 38 | 39 | // This animation draws a rectangle inside the window to close with color and 40 | // a smaller transparent rectangle inside 41 | 42 | // Full-screen colored rectangle 43 | double alpha = Animation::value(0, Animation::MAX_ALPHA, percentage); 44 | cairo_set_source_rgba(ctx, color.r(), color.g(), color.b(), alpha); 45 | cairo_rectangle(ctx, maxSize.x, maxSize.y, maxSize.width, maxSize.height); 46 | cairo_fill(ctx); 47 | 48 | // Calculate the size of the transparent rectangle 49 | double maxDiff = (5 * std::max(maxSize.width, maxSize.height)) / 100; 50 | double width = 51 | Animation::value(maxSize.width, maxSize.width - maxDiff, percentage); 52 | double height = 53 | Animation::value(maxSize.height, maxSize.height - maxDiff, percentage); 54 | 55 | cairo_set_line_width(ctx, 2); 56 | cairo_set_source_rgba(ctx, borderColor.r(), borderColor.g(), borderColor.b(), 57 | alpha); 58 | cairo_rectangle(ctx, maxSize.x + (maxSize.width - width) / 2, 59 | maxSize.y + (maxSize.height - height) / 2, width, height); 60 | cairo_stroke_preserve(ctx); 61 | 62 | cairo_set_source_rgba(ctx, 0, 0, 0, 0); 63 | cairo_fill(ctx); 64 | 65 | this->cairoSurface->flush(); 66 | } 67 | -------------------------------------------------------------------------------- /src/animations/close-window-animation.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #ifndef ANIMATIONS_CLOSE_WINDOW_ANIMATION_H_ 19 | #define ANIMATIONS_CLOSE_WINDOW_ANIMATION_H_ 20 | 21 | #include "animations/animation.h" 22 | #include "utils/color.h" 23 | #include "utils/rectangle.h" 24 | 25 | class CloseWindowAnimation : public Animation { 26 | public: 27 | using Animation::Animation; 28 | CloseWindowAnimation(const WindowSystem &windowSystem, const WindowT &window, 29 | Color color, Color borderColor); 30 | void render(double percentage) override; 31 | 32 | private: 33 | Rectangle maxSize; 34 | Color color; 35 | Color borderColor; 36 | }; 37 | 38 | #endif // ANIMATIONS_CLOSE_WINDOW_ANIMATION_H_ 39 | -------------------------------------------------------------------------------- /src/animations/maximize-window-animation.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #include "animations/maximize-window-animation.h" 19 | 20 | MaximizeWindowAnimation::MaximizeWindowAnimation( 21 | const WindowSystem &windowSystem, const WindowT &window, Color color, 22 | Color borderColor) 23 | : Animation(windowSystem, window), 24 | maxSize(this->windowSystem.getDesktopWorkarea()), 25 | color(color), 26 | borderColor(borderColor) {} 27 | 28 | void MaximizeWindowAnimation::render(double percentage) { 29 | cairo_t *ctx = this->cairoSurface->getContext(); 30 | 31 | // Clear the background 32 | cairo_set_source_rgba(ctx, 0, 0, 0, 0); 33 | cairo_set_operator(ctx, CAIRO_OPERATOR_SOURCE); 34 | cairo_paint(ctx); 35 | 36 | // Draw the rectangle 37 | double width = Animation::value(0, maxSize.width, percentage); 38 | double height = Animation::value(0, maxSize.height, percentage); 39 | double alpha = Animation::value(0, Animation::MAX_ALPHA, percentage); 40 | 41 | cairo_set_line_width(ctx, 2); 42 | cairo_set_source_rgba(ctx, borderColor.r(), borderColor.g(), borderColor.b(), 43 | alpha); 44 | cairo_rectangle(ctx, maxSize.x + ((maxSize.width - width) / 2), maxSize.y, 45 | width, height); 46 | cairo_stroke_preserve(ctx); 47 | 48 | cairo_set_source_rgba(ctx, color.r(), color.g(), color.b(), alpha); 49 | cairo_fill(ctx); 50 | 51 | this->cairoSurface->flush(); 52 | } 53 | -------------------------------------------------------------------------------- /src/animations/maximize-window-animation.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #ifndef ANIMATIONS_MAXIMIZE_WINDOW_ANIMATION_H_ 19 | #define ANIMATIONS_MAXIMIZE_WINDOW_ANIMATION_H_ 20 | 21 | #include "animations/animation.h" 22 | #include "utils/color.h" 23 | #include "utils/rectangle.h" 24 | 25 | class MaximizeWindowAnimation : public Animation { 26 | public: 27 | using Animation::Animation; 28 | MaximizeWindowAnimation(const WindowSystem &windowSystem, 29 | const WindowT &window, Color color, 30 | Color borderColor); 31 | void render(double percentage) override; 32 | 33 | private: 34 | Rectangle maxSize; 35 | Color color; 36 | Color borderColor; 37 | }; 38 | 39 | #endif // ANIMATIONS_MAXIMIZE_WINDOW_ANIMATION_H_ 40 | -------------------------------------------------------------------------------- /src/animations/minimize-window-animation.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #include "animations/minimize-window-animation.h" 19 | 20 | #include 21 | #include 22 | 23 | MinimizeWindowAnimation::MinimizeWindowAnimation( 24 | const WindowSystem &windowSystem, const WindowT &window, Color color, 25 | Color borderColor) 26 | : Animation(windowSystem, window), 27 | initialSize(this->windowSystem.getWindowSize(this->window)), 28 | finalSize(this->windowSystem.minimizeWindowIconSize(this->window)), 29 | color(color), 30 | borderColor(borderColor) { 31 | // If the icon size is not set (for example, Ubuntu 20.04) set the finale size 32 | // to the center of the window 33 | if (this->finalSize.x == 0 && this->finalSize.y == 0 && 34 | this->finalSize.width == 0 && this->finalSize.height == 0) { 35 | this->finalSize.x = this->initialSize.x + (this->initialSize.width / 2); 36 | this->finalSize.y = this->initialSize.y + (this->initialSize.height / 2); 37 | this->finalSize.width = 0; 38 | this->finalSize.height = 0; 39 | } 40 | } 41 | 42 | void MinimizeWindowAnimation::render(double percentage) { 43 | cairo_t *ctx = this->cairoSurface->getContext(); 44 | 45 | // Clear the background 46 | cairo_set_source_rgba(ctx, 0, 0, 0, 0); 47 | cairo_set_operator(ctx, CAIRO_OPERATOR_SOURCE); 48 | cairo_paint(ctx); 49 | 50 | // Draw the rectangle 51 | double x = Animation::value(initialSize.x, finalSize.x, percentage); 52 | double y = Animation::value(initialSize.y, finalSize.y, percentage); 53 | double width = 54 | Animation::value(initialSize.width, finalSize.width, percentage); 55 | double height = 56 | Animation::value(initialSize.height, finalSize.height, percentage); 57 | double alpha = Animation::value(0, Animation::MAX_ALPHA, percentage); 58 | 59 | cairo_set_line_width(ctx, 2); 60 | cairo_set_source_rgba(ctx, borderColor.r(), borderColor.g(), borderColor.b(), 61 | alpha); 62 | cairo_rectangle(ctx, x, y, width, height); 63 | cairo_stroke_preserve(ctx); 64 | 65 | cairo_set_source_rgba(ctx, color.r(), color.g(), color.b(), alpha); 66 | cairo_fill(ctx); 67 | 68 | this->cairoSurface->flush(); 69 | } 70 | -------------------------------------------------------------------------------- /src/animations/minimize-window-animation.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #ifndef ANIMATIONS_MINIMIZE_WINDOW_ANIMATION_H_ 19 | #define ANIMATIONS_MINIMIZE_WINDOW_ANIMATION_H_ 20 | 21 | #include "animations/animation.h" 22 | #include "utils/color.h" 23 | #include "utils/rectangle.h" 24 | 25 | class MinimizeWindowAnimation : public Animation { 26 | public: 27 | using Animation::Animation; 28 | MinimizeWindowAnimation(const WindowSystem &windowSystem, 29 | const WindowT &window, Color color, 30 | Color borderColor); 31 | void render(double percentage) override; 32 | 33 | private: 34 | Rectangle initialSize; 35 | Rectangle finalSize; 36 | Color color; 37 | Color borderColor; 38 | }; 39 | 40 | #endif // ANIMATIONS_MINIMIZE_WINDOW_ANIMATION_H_ 41 | -------------------------------------------------------------------------------- /src/animations/restore-window-animation.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #include "animations/restore-window-animation.h" 19 | 20 | #include 21 | #include 22 | 23 | RestoreWindowAnimation::RestoreWindowAnimation(const WindowSystem &windowSystem, 24 | const WindowT &window, 25 | Color color, Color borderColor) 26 | : Animation(windowSystem, window), 27 | maxSize(this->windowSystem.getDesktopWorkarea()), 28 | color(color), 29 | borderColor(borderColor) {} 30 | 31 | void RestoreWindowAnimation::render(double percentage) { 32 | cairo_t *ctx = this->cairoSurface->getContext(); 33 | 34 | // Clear the background 35 | cairo_set_source_rgba(ctx, 0, 0, 0, 0); 36 | cairo_set_operator(ctx, CAIRO_OPERATOR_SOURCE); 37 | cairo_paint(ctx); 38 | 39 | // This animation draws a full-screen rectangle with color and a smaller 40 | // transparent rectangle inside 41 | 42 | // Full-screen colored rectangle 43 | double alpha = Animation::value(0, Animation::MAX_ALPHA, percentage); 44 | cairo_set_source_rgba(ctx, color.r(), color.g(), color.b(), alpha); 45 | cairo_rectangle(ctx, maxSize.x, maxSize.y, maxSize.width, maxSize.height); 46 | cairo_fill(ctx); 47 | 48 | // Calculate the size of the transparent rectangle 49 | double maxDiff = (5 * std::max(maxSize.width, maxSize.height)) / 100; 50 | double width = 51 | Animation::value(maxSize.width, maxSize.width - maxDiff, percentage); 52 | double height = 53 | Animation::value(maxSize.height, maxSize.height - maxDiff, percentage); 54 | 55 | cairo_set_line_width(ctx, 2); 56 | cairo_set_source_rgba(ctx, borderColor.r(), borderColor.g(), borderColor.b(), 57 | alpha); 58 | cairo_rectangle(ctx, maxSize.x + (maxSize.width - width) / 2, 59 | maxSize.y + (maxSize.height - height) / 2, width, height); 60 | cairo_stroke_preserve(ctx); 61 | 62 | cairo_set_source_rgba(ctx, 0, 0, 0, 0); 63 | cairo_fill(ctx); 64 | 65 | this->cairoSurface->flush(); 66 | } 67 | -------------------------------------------------------------------------------- /src/animations/restore-window-animation.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #ifndef ANIMATIONS_RESTORE_WINDOW_ANIMATION_H_ 19 | #define ANIMATIONS_RESTORE_WINDOW_ANIMATION_H_ 20 | 21 | #include "animations/animation.h" 22 | #include "utils/color.h" 23 | #include "utils/rectangle.h" 24 | 25 | class RestoreWindowAnimation : public Animation { 26 | public: 27 | using Animation::Animation; 28 | RestoreWindowAnimation(const WindowSystem &windowSystem, 29 | const WindowT &window, Color color, Color borderColor); 30 | void render(double percentage) override; 31 | 32 | private: 33 | Rectangle maxSize; 34 | Color color; 35 | Color borderColor; 36 | }; 37 | 38 | #endif // ANIMATIONS_RESTORE_WINDOW_ANIMATION_H_ 39 | -------------------------------------------------------------------------------- /src/animations/show-desktop-animation.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #include "animations/show-desktop-animation.h" 19 | 20 | #include 21 | #include 22 | 23 | ShowDesktopAnimation::ShowDesktopAnimation(const WindowSystem &windowSystem, 24 | const WindowT &window, Color color, 25 | Color borderColor, 26 | bool showingDesktop) 27 | : Animation(windowSystem, window), 28 | maxSize(this->windowSystem.getDesktopWorkarea()), 29 | color(color), 30 | borderColor(borderColor), 31 | showingDesktop(showingDesktop) {} 32 | 33 | void ShowDesktopAnimation::render(double percentage) { 34 | cairo_t *ctx = this->cairoSurface->getContext(); 35 | 36 | // Clear the background 37 | cairo_set_source_rgba(ctx, 0, 0, 0, 0); 38 | cairo_set_operator(ctx, CAIRO_OPERATOR_SOURCE); 39 | cairo_paint(ctx); 40 | 41 | // This animation draws a full-screen rectangle with color and a smaller 42 | // transparent rectangle inside 43 | 44 | // Full-screen colored rectangle 45 | double alpha = Animation::value(0, Animation::MAX_ALPHA, percentage); 46 | cairo_set_source_rgba(ctx, color.r(), color.g(), color.b(), alpha); 47 | cairo_rectangle(ctx, maxSize.x, maxSize.y, maxSize.width, maxSize.height); 48 | cairo_fill(ctx); 49 | 50 | // Calculate the size of the transparent rectangle 51 | double maxDiff = (5 * std::max(maxSize.width, maxSize.height)) / 100; 52 | double width = 0; 53 | double height = 0; 54 | 55 | if (this->showingDesktop) { 56 | width = 57 | Animation::value(maxSize.width, maxSize.width - maxDiff, percentage); 58 | height = 59 | Animation::value(maxSize.height, maxSize.height - maxDiff, percentage); 60 | } else { 61 | width = 62 | Animation::value(maxSize.width - maxDiff, maxSize.width, percentage); 63 | height = 64 | Animation::value(maxSize.height - maxDiff, maxSize.height, percentage); 65 | } 66 | 67 | cairo_set_line_width(ctx, 2); 68 | cairo_set_source_rgba(ctx, borderColor.r(), borderColor.g(), borderColor.b(), 69 | alpha); 70 | cairo_rectangle(ctx, maxSize.x + (maxSize.width - width) / 2, 71 | maxSize.y + (maxSize.height - height) / 2, width, height); 72 | cairo_stroke_preserve(ctx); 73 | 74 | cairo_set_source_rgba(ctx, 0, 0, 0, 0); 75 | cairo_fill(ctx); 76 | 77 | this->cairoSurface->flush(); 78 | } 79 | -------------------------------------------------------------------------------- /src/animations/show-desktop-animation.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #ifndef ANIMATIONS_SHOW_DESKTOP_ANIMATION_H_ 19 | #define ANIMATIONS_SHOW_DESKTOP_ANIMATION_H_ 20 | 21 | #include "animations/animation.h" 22 | #include "utils/color.h" 23 | #include "utils/rectangle.h" 24 | 25 | class ShowDesktopAnimation : public Animation { 26 | public: 27 | using Animation::Animation; 28 | ShowDesktopAnimation(const WindowSystem &windowSystem, const WindowT &window, 29 | Color color, Color borderColor, bool showingDesktop); 30 | void render(double percentage) override; 31 | 32 | private: 33 | Rectangle maxSize; 34 | Color color; 35 | Color borderColor; 36 | bool showingDesktop; 37 | }; 38 | 39 | #endif // ANIMATIONS_SHOW_DESKTOP_ANIMATION_H_ 40 | -------------------------------------------------------------------------------- /src/animations/tile-window-animation.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #include "animations/tile-window-animation.h" 19 | 20 | #include 21 | #include 22 | 23 | TileWindowAnimation::TileWindowAnimation(const WindowSystem &windowSystem, 24 | const WindowT &window, Color color, 25 | Color borderColor, bool toTheLeft) 26 | : Animation(windowSystem, window), 27 | color(color), 28 | borderColor(borderColor), 29 | toTheLeft(toTheLeft) { 30 | Rectangle workarea = this->windowSystem.getDesktopWorkarea(); 31 | maxSize.x = toTheLeft ? workarea.x : workarea.x + (workarea.width / 2); 32 | maxSize.y = workarea.y; 33 | maxSize.width = (workarea.width / 2); 34 | maxSize.height = workarea.height; 35 | } 36 | 37 | void TileWindowAnimation::render(double percentage) { 38 | cairo_t *ctx = this->cairoSurface->getContext(); 39 | 40 | // Clear the background 41 | cairo_set_source_rgba(ctx, 0, 0, 0, 0); 42 | cairo_set_operator(ctx, CAIRO_OPERATOR_SOURCE); 43 | cairo_paint(ctx); 44 | 45 | // Draw the rectangle 46 | double width = Animation::value(0, maxSize.width, percentage); 47 | double height = Animation::value(0, maxSize.height, percentage); 48 | double x = this->toTheLeft ? maxSize.x : maxSize.x + (maxSize.width - width); 49 | double y = maxSize.y + ((maxSize.height - height) / 2); 50 | double alpha = Animation::value(0, Animation::MAX_ALPHA, percentage); 51 | 52 | cairo_set_line_width(ctx, 2); 53 | cairo_set_source_rgba(ctx, borderColor.r(), borderColor.g(), borderColor.b(), 54 | alpha); 55 | cairo_rectangle(ctx, x, y, width, height); 56 | cairo_stroke_preserve(ctx); 57 | 58 | cairo_set_source_rgba(ctx, color.r(), color.g(), color.b(), alpha); 59 | cairo_fill(ctx); 60 | 61 | this->cairoSurface->flush(); 62 | } 63 | -------------------------------------------------------------------------------- /src/animations/tile-window-animation.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #ifndef ANIMATIONS_TILE_WINDOW_ANIMATION_H_ 19 | #define ANIMATIONS_TILE_WINDOW_ANIMATION_H_ 20 | 21 | #include "animations/animation.h" 22 | #include "utils/color.h" 23 | #include "utils/rectangle.h" 24 | 25 | class TileWindowAnimation : public Animation { 26 | public: 27 | using Animation::Animation; 28 | TileWindowAnimation(const WindowSystem &windowSystem, const WindowT &window, 29 | Color color, Color borderColor, bool toTheLeft); 30 | void render(double percentage) override; 31 | 32 | private: 33 | Rectangle maxSize; 34 | Color color; 35 | Color borderColor; 36 | bool toTheLeft; 37 | }; 38 | 39 | #endif // ANIMATIONS_TILE_WINDOW_ANIMATION_H_ 40 | -------------------------------------------------------------------------------- /src/config/config.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #include "config/config.h" 19 | 20 | #include 21 | #include 22 | 23 | #include "utils/string.h" 24 | 25 | Config::Config() { this->loadDefaultGlobalSettings(); } 26 | 27 | void Config::clear() { 28 | this->globalSettings.clear(); 29 | this->config.clear(); 30 | this->loadDefaultGlobalSettings(); 31 | } 32 | 33 | void Config::saveGlobalSetting(const std::string &name, 34 | const std::string &value) { 35 | this->globalSettings[name] = value; 36 | } 37 | 38 | bool Config::hasGlobalSetting(const std::string &name) const { 39 | return (this->globalSettings.count(name) == 1); 40 | } 41 | 42 | std::string Config::getGlobalSetting(const std::string &name) const { 43 | return this->globalSettings.at(name); 44 | } 45 | 46 | void Config::saveGestureConfig( 47 | const std::string &application, GestureType gestureType, 48 | const std::string &numFingers, GestureDirection gestureDirection, 49 | ActionType actionType, 50 | const std::unordered_map &actionSettings) { 51 | std::string key = Config::getConfigKey(application, gestureType, numFingers, 52 | gestureDirection); 53 | this->config[key] = std::make_pair(actionType, actionSettings); 54 | } 55 | 56 | bool Config::hasGestureConfig(const std::string &application, 57 | GestureType gestureType, int numFingers, 58 | GestureDirection gestureDirection) const { 59 | std::string key = Config::getConfigKey( 60 | application, gestureType, std::to_string(numFingers), gestureDirection); 61 | return (this->config.count(key) == 1); 62 | } 63 | 64 | std::pair> 65 | Config::getGestureConfig(const std::string &application, 66 | GestureType gestureType, int numFingers, 67 | GestureDirection gestureDirection) const { 68 | std::string key = Config::getConfigKey( 69 | application, gestureType, std::to_string(numFingers), gestureDirection); 70 | return this->config.at(key); 71 | } 72 | 73 | void Config::loadDefaultGlobalSettings() { 74 | this->globalSettings["animation_delay"] = "150"; 75 | this->globalSettings["action_execute_threshold"] = "20"; 76 | } 77 | 78 | std::string Config::getConfigKey(const std::string &application, 79 | GestureType gestureType, 80 | const std::string &numFingers, 81 | GestureDirection gestureDirection) { 82 | auto gestureTypeInt = static_cast(gestureType); 83 | auto gestureDirectionInt = static_cast(gestureDirection); 84 | return toLower(application) + "_" + std::to_string(gestureTypeInt) + "_" + 85 | numFingers + "_" + std::to_string(gestureDirectionInt); 86 | } 87 | -------------------------------------------------------------------------------- /src/config/xml-config-loader.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #ifndef CONFIG_XML_CONFIG_LOADER_H_ 19 | #define CONFIG_XML_CONFIG_LOADER_H_ 20 | 21 | #include 22 | 23 | #include "actions/action-type.h" 24 | #include "gesture/gesture-direction.h" 25 | #include "gesture/gesture-type.h" 26 | #include "utils/filesystem.h" 27 | class Config; 28 | namespace pugi { 29 | class xml_node; 30 | } 31 | 32 | /** 33 | * Default config loader. It reads the configuration from 34 | * "~/.config/touchegg/touchegg.conf" if it exists. Otherwise it fallbacks to 35 | * "/usr/share/touchegg/touchegg.conf". 36 | * @see Config 37 | */ 38 | class XmlConfigLoader { 39 | public: 40 | /** 41 | * Default contructor, it takes a pointer to the `Config` object where the 42 | * configuration will be stored. 43 | * @param config Pointer to the `Config` object. 44 | */ 45 | explicit XmlConfigLoader(Config *config); 46 | 47 | /** 48 | * Store the configuration from the XML configuration file in the `Config` 49 | * object passed in the constructor. 50 | */ 51 | void load(); 52 | 53 | private: 54 | /** 55 | * Pointer to the `Config` object injected in the constructor. 56 | */ 57 | Config *config; 58 | 59 | /** 60 | * @returns Path to the config file to use. 61 | */ 62 | static std::filesystem::path getConfigFilePath(); 63 | 64 | /** 65 | * Parse the XML configuration file placed in path. 66 | */ 67 | void parseConfig(); 68 | 69 | /** 70 | * Parse the global settings. 71 | * @param rootNode XML root node, usually named "touchégg". 72 | */ 73 | void parseGlobalSettings(const pugi::xml_node &rootNode); 74 | 75 | /** 76 | * Parse the "application" nodes in the XML. 77 | * @param rootNode XML root node, usually named "touchégg". 78 | */ 79 | void parseApplicationXmlNodes(const pugi::xml_node &rootNode); 80 | 81 | /** 82 | * Watch the configuration file and parse it on change or creation. 83 | */ 84 | void watchConfig(); 85 | }; 86 | 87 | #endif // CONFIG_XML_CONFIG_LOADER_H_ 88 | -------------------------------------------------------------------------------- /src/daemon/daemon-client.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #ifndef DAEMON_DAEMON_CLIENT_H_ 19 | #define DAEMON_DAEMON_CLIENT_H_ 20 | 21 | #include 22 | 23 | #include 24 | #include 25 | 26 | #include "gesture-controller/gesture-controller-delegate.h" 27 | #include "gesture/gesture.h" 28 | #include "window-system/window-system.h" 29 | 30 | /** 31 | * Class to connect to the daemon server and send the gestures received from the 32 | * server to the GestureControllerDelegate. 33 | */ 34 | class DaemonClient { 35 | public: 36 | explicit DaemonClient(GestureControllerDelegate *gestureController) 37 | : gestureController(gestureController) {} 38 | 39 | void run(); 40 | 41 | private: 42 | GestureControllerDelegate *gestureController; 43 | 44 | /* 45 | * Store the last received signal and signal parameters so in case of 46 | * disconnection in the middle of a gesture we can finish it. 47 | */ 48 | std::string lastSignalName = ""; 49 | GVariant *lastSignalParams = nullptr; 50 | 51 | /** 52 | * Stablish a connection with the daemon server. 53 | */ 54 | void connect(); 55 | 56 | /** 57 | * Callback invoked when a new message is received. 58 | * @param connection The D-Bus connection. 59 | * @param senderName Unique bus name of the sender of the signal. 60 | * @param objectPath The object path that the signal was emitted on. 61 | * @param interfaceName The name of the interface. 62 | * @param signalName DBUS_ON_GESTURE_BEGIN, DBUS_ON_GESTURE_UPDATE or 63 | * DBUS_ON_GESTURE_END. 64 | * @param parameters Gesture params. 65 | * @param thisPointer this. 66 | */ 67 | static void onNewMessage(GDBusConnection *connection, const gchar *senderName, 68 | const gchar *objectPath, const gchar *interfaceName, 69 | const gchar *signalName, GVariant *parameters, 70 | gpointer thisPointer); 71 | 72 | /** 73 | * Callback invoked when the connection is closed. 74 | * @param connection The D-Bus connection. 75 | * @param remotePeerVanished TRUE if connection is closed because the remote 76 | * peer closed its end of the connection. 77 | * @param error Error reason or null. 78 | * @param self this. 79 | */ 80 | static void onDisconnected(GDBusConnection *connection, 81 | gboolean remotePeerVanished, GError *error, 82 | DaemonClient *self); 83 | 84 | /** 85 | * Transform the signal into a gesture and send it to the controller. 86 | * @param signalName DBUS_ON_GESTURE_BEGIN, DBUS_ON_GESTURE_UPDATE or 87 | * DBUS_ON_GESTURE_END. 88 | * @param parameters Gesture params. 89 | */ 90 | void sendToGestureController(const std::string &signalName, 91 | GVariant *signalParameters); 92 | 93 | /** 94 | * Create a gesture from the received signal message. 95 | * @param signalParameters Received signal parameters. 96 | * @returns The gesture. 97 | */ 98 | static std::unique_ptr makeGestureFromSignalParams( 99 | GVariant *signalParameters); 100 | }; 101 | 102 | #endif // DAEMON_DAEMON_CLIENT_H_ 103 | -------------------------------------------------------------------------------- /src/daemon/daemon-server.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #ifndef DAEMON_DAEMON_SERVER_H_ 19 | #define DAEMON_DAEMON_SERVER_H_ 20 | 21 | #include 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | #include "gesture-controller/gesture-controller-delegate.h" 28 | 29 | /** 30 | * Access to libinput is limited to users in the "input" group or, in the case 31 | * of Wayland, to the compositor. However, adding your user to the "input" group 32 | * is insecure because then any process you execute will have full access, for 33 | * example, to your keyboard input. 34 | * 35 | * To avoid this security issue, Touchégg can be executed as a daemon by systemd 36 | * so only the daemon have access to libinput. 37 | * The daemon uses this class to start a Unix domain socket server and expose 38 | * only the minimum required libinput information. 39 | */ 40 | class DaemonServer : public GestureControllerDelegate { 41 | public: 42 | void run(); 43 | 44 | void onGestureBegin(std::unique_ptr gesture) override; 45 | void onGestureUpdate(std::unique_ptr gesture) override; 46 | void onGestureEnd(std::unique_ptr gesture) override; 47 | 48 | private: 49 | GDBusNodeInfo *introspectionData; 50 | std::vector connections; 51 | 52 | /** 53 | * Callback invoked when a new connection is established. 54 | * @param server The D-Bus server. 55 | * @param connection The D-Bus connection. 56 | * @param self this. 57 | * @returns TRUE if the connection is accepted. 58 | */ 59 | static gboolean onNewConnection(GDBusServer *server, 60 | GDBusConnection *connection, 61 | DaemonServer *self); 62 | 63 | /** 64 | * Send a gesture event message to every connected client. 65 | * @param signalName D-Bus signal name. 66 | * @param gesture The gesture to send. 67 | */ 68 | void send(const std::string &signalName, std::unique_ptr gesture); 69 | }; 70 | 71 | #endif // DAEMON_DAEMON_SERVER_H_ 72 | -------------------------------------------------------------------------------- /src/daemon/dbus.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #ifndef DAEMON_DBUS_H_ 19 | #define DAEMON_DBUS_H_ 20 | 21 | #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) 22 | constexpr auto DBUS_ADDRESS = "unix:path=/tmp/touchegg#0"; 23 | #else 24 | constexpr auto DBUS_ADDRESS = "unix:abstract=touchegg"; 25 | #endif 26 | 27 | constexpr auto DBUS_OBJECT_PATH = "/io/github/joseexposito/Touchegg"; 28 | 29 | constexpr auto DBUS_INTERFACE_NAME = "io.github.joseexposito.Touchegg"; 30 | 31 | constexpr auto DBUS_ON_GESTURE_BEGIN = "OnGestureBegin"; 32 | constexpr auto DBUS_ON_GESTURE_UPDATE = "OnGestureUpdate"; 33 | constexpr auto DBUS_ON_GESTURE_END = "OnGestureEnd"; 34 | 35 | constexpr auto DBUS_INTROSPECTION_XML = 36 | "" 37 | " " 38 | " " 39 | " " 40 | " " 41 | " " 42 | " " 43 | " " 44 | " " 45 | " " 46 | " " 47 | " " 48 | " " 49 | " " 50 | " " 51 | " " 52 | " " 53 | " " 54 | " " 55 | " " 56 | " " 57 | " " 58 | " " 59 | " " 60 | " " 61 | " " 62 | " " 63 | ""; 64 | 65 | #endif // DAEMON_DBUS_H_ 66 | -------------------------------------------------------------------------------- /src/gesture-controller/gesture-controller-delegate.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #ifndef GESTURE_CONTROLLER_GESTURE_CONTROLLER_DELEGATE_H_ 19 | #define GESTURE_CONTROLLER_GESTURE_CONTROLLER_DELEGATE_H_ 20 | 21 | #include 22 | 23 | #include "gesture/gesture.h" 24 | 25 | /** 26 | * Instead of passing the GestureController to the GestureGatherer, this 27 | * delegate interface is passed instead. 28 | * This interface allows us to decouple the GestureController implementation 29 | * from the GestureGatherer exposing the minimal interface of the last. 30 | */ 31 | class GestureControllerDelegate { 32 | public: 33 | virtual ~GestureControllerDelegate() = default; 34 | 35 | virtual void onGestureBegin(std::unique_ptr gesture) = 0; 36 | virtual void onGestureUpdate(std::unique_ptr gesture) = 0; 37 | virtual void onGestureEnd(std::unique_ptr gesture) = 0; 38 | }; 39 | 40 | #endif // GESTURE_CONTROLLER_GESTURE_CONTROLLER_DELEGATE_H_ 41 | -------------------------------------------------------------------------------- /src/gesture-controller/gesture-controller.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #ifndef GESTURE_CONTROLLER_GESTURE_CONTROLLER_H_ 19 | #define GESTURE_CONTROLLER_GESTURE_CONTROLLER_H_ 20 | 21 | #include 22 | 23 | #include "actions/action.h" 24 | #include "gesture-controller/gesture-controller-delegate.h" 25 | class Config; 26 | class Gesture; 27 | class WindowSystem; 28 | 29 | /** 30 | * The GestureController is in charge of receiving events from the outside and 31 | * dispatching actions according to the user configuration. 32 | */ 33 | class GestureController : public GestureControllerDelegate { 34 | public: 35 | explicit GestureController(const Config &config, 36 | const WindowSystem &windowSystem); 37 | virtual ~GestureController() = default; 38 | 39 | void onGestureBegin(std::unique_ptr gesture) override; 40 | void onGestureUpdate(std::unique_ptr gesture) override; 41 | void onGestureEnd(std::unique_ptr gesture) override; 42 | 43 | private: 44 | const Config &config; 45 | const WindowSystem &windowSystem; 46 | 47 | /** 48 | * The action to perform. 49 | */ 50 | std::unique_ptr action = nullptr; 51 | 52 | /** 53 | * The window the action is performed on. 54 | */ 55 | std::unique_ptr window; 56 | 57 | /** 58 | * A flag indicating if we should run the action. 59 | */ 60 | bool executeAction = false; 61 | 62 | /** 63 | * If the screen is rotated, this values is set on gesture begin to match the 64 | * screen rotation. 65 | */ 66 | GestureDirection rotatedDirection = GestureDirection::UNKNOWN; 67 | 68 | /** 69 | * @returns The action associated to a gesture or nullptr. 70 | */ 71 | std::unique_ptr getActionForGesture(const Gesture &gesture, 72 | const WindowT &window) const; 73 | }; 74 | 75 | #endif // GESTURE_CONTROLLER_GESTURE_CONTROLLER_H_ 76 | -------------------------------------------------------------------------------- /src/gesture-gatherer/gesture-gatherer.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #ifndef GESTURE_GATHERER_GESTURE_GATHERER_H_ 19 | #define GESTURE_GATHERER_GESTURE_GATHERER_H_ 20 | 21 | class Config; 22 | class GestureControllerDelegate; 23 | 24 | /** 25 | * A GestureGatherer is in charge of gathering the gestures performed by the 26 | * user and sending them to the GestureController. 27 | * 28 | * In this way, the underlying driver used to gather those gestures is 29 | * abstracted from the rest of the program, allowing to easily support multiple 30 | * backends. 31 | * 32 | * This abstract class is the interface every GestureGatherer must implement. 33 | */ 34 | class GestureGatherer { 35 | public: 36 | /** 37 | * Default contructor. 38 | * @param gestureController GestureController where the GestureGatherer will 39 | * send the gestures. 40 | * @param startThreshold Amount of motion to be made on the touchpad before a 41 | * gesture is started. 42 | * For example: put 3 fingers on your touchpad. You will notice that the 43 | * action does not start until you move them a little bit. This property 44 | * configures how much you should move your fingers before the action starts. 45 | * @param finishThreshold Amount of motion to be made on the touchpad to reach 46 | * the 100% of an animation. 47 | * For example, use the MAXIMIZE_RESTORE_WINDOW action. You will notice that 48 | * you need to move your fingers a certain ammount until the animation fills 49 | * your entire screen. This property configures how much you need to move your 50 | * fingers 51 | */ 52 | GestureGatherer(GestureControllerDelegate *gestureController, 53 | double startThreshold = -1, double finishThreshold = -1) 54 | : gestureController(gestureController), 55 | startThreshold(startThreshold), 56 | finishThreshold(finishThreshold) {} 57 | 58 | virtual ~GestureGatherer() = default; 59 | 60 | /** 61 | * Run the GestureGatherer event loop. 62 | */ 63 | virtual void run() = 0; 64 | 65 | protected: 66 | GestureControllerDelegate *gestureController; 67 | double startThreshold = -1; 68 | double finishThreshold = -1; 69 | }; 70 | 71 | #endif // GESTURE_GATHERER_GESTURE_GATHERER_H_ 72 | -------------------------------------------------------------------------------- /src/gesture-gatherer/libinput-device-handler.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #ifndef GESTURE_GATHERER_LIBINPUT_DEVICE_HANDLER_H_ 19 | #define GESTURE_GATHERER_LIBINPUT_DEVICE_HANDLER_H_ 20 | 21 | #include 22 | 23 | #include "gesture-controller/gesture-controller-delegate.h" 24 | #include "gesture-gatherer/libinput-handler.h" 25 | #include "gesture/gesture-direction.h" 26 | 27 | /** 28 | * Class to handle libinput devices: 29 | * https://wayland.freedesktop.org/libinput/doc/latest/api/group__device.html 30 | */ 31 | class LininputDeviceHandler : public LininputHandler { 32 | public: 33 | LininputDeviceHandler(GestureControllerDelegate *gestureController, 34 | double startThreshold, double finishThreshold) 35 | : LininputHandler(gestureController), 36 | startThreshold(startThreshold), 37 | finishThreshold(finishThreshold) {} 38 | 39 | /** 40 | * Called on startup for each device and every time a device is added. 41 | * Print useful information and calculates LibinputDeviceInfo. 42 | */ 43 | void handleDeviceAdded(struct libinput_event *event) const; 44 | 45 | private: 46 | double startThreshold = -1; 47 | double finishThreshold = -1; 48 | 49 | /** 50 | * Calculates LibinputDeviceInfo on touchpads. 51 | * 52 | * Calculating optimal "start_threshold" and "finish_threshold" is really 53 | * complicated on touchpads with DPI < 1000, that's why this values are 54 | * configurable. However this methods works with the bast majority of devices 55 | * out there. 56 | */ 57 | static void calculateTouchpadThreshold(double widthMm, double heightMm, 58 | LibinputDeviceInfo *outInfo); 59 | static double mmToDpi(double mm); 60 | 61 | /** 62 | * Calculates LibinputDeviceInfo on touchscreens. 63 | */ 64 | static void calculateTouchscreenThreshold(double widthMm, double heightMm, 65 | LibinputDeviceInfo *outInfo); 66 | }; 67 | #endif // GESTURE_GATHERER_LIBINPUT_DEVICE_HANDLER_H_ 68 | -------------------------------------------------------------------------------- /src/gesture-gatherer/libinput-device-info.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #ifndef GESTURE_GATHERER_LIBINPUT_DEVICE_INFO_H_ 19 | #define GESTURE_GATHERER_LIBINPUT_DEVICE_INFO_H_ 20 | 21 | /** 22 | * Data structure to save pre-calculated device information in the device user 23 | * data: 24 | * https://wayland.freedesktop.org/libinput/doc/latest/api/group__device.html#ga6243ad6005b2ce2a5ecfd1b04787fe93 25 | */ 26 | struct LibinputDeviceInfo { 27 | double startThreshold = 200; 28 | double finishThresholdHorizontal = 2500; 29 | double finishThresholdVertical = 2500; 30 | }; 31 | 32 | #endif // GESTURE_GATHERER_LIBINPUT_DEVICE_INFO_H_ 33 | -------------------------------------------------------------------------------- /src/gesture-gatherer/libinput-gesture-gatherer.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #ifndef GESTURE_GATHERER_LIBINPUT_GESTURE_GATHERER_H_ 19 | #define GESTURE_GATHERER_LIBINPUT_GESTURE_GATHERER_H_ 20 | 21 | #include 22 | #include 23 | 24 | #include 25 | 26 | #include "gesture-gatherer/gesture-gatherer.h" 27 | #include "gesture-gatherer/libinput-device-handler.h" 28 | #include "gesture-gatherer/libinput-device-info.h" 29 | #include "gesture-gatherer/libinput-pinch-handler.h" 30 | #include "gesture-gatherer/libinput-swipe-handler.h" 31 | #include "gesture-gatherer/libinput-touch-handler.h" 32 | class Config; 33 | class GestureControllerDelegate; 34 | class LibinputGesture; 35 | 36 | /** 37 | * Libinput backed GestureGatherer. 38 | */ 39 | class LibinputGestureGatherer : public GestureGatherer { 40 | public: 41 | LibinputGestureGatherer(GestureControllerDelegate *gestureController, 42 | double startThreshold = -1, 43 | double finishThreshold = -1); 44 | ~LibinputGestureGatherer(); 45 | 46 | /** 47 | * Run libinput's event loop. 48 | */ 49 | void run() override; 50 | 51 | private: 52 | /** 53 | * udev context. 54 | */ 55 | struct udev *udevContext = nullptr; 56 | 57 | /** 58 | * libinput context. 59 | */ 60 | struct libinput *libinputContext = nullptr; 61 | 62 | // Handlers 63 | LininputDeviceHandler deviceHandler; 64 | LininputSwipeHandler swipeHandler; 65 | LininputPinchHandler pinchHandler; 66 | LibinputTouchHandler touchHandler; 67 | 68 | /** 69 | * Handles the supported libinput events. 70 | */ 71 | void handleEvent(struct libinput_event *event); 72 | 73 | /** 74 | * libinput structure with pointers to the open/close callbacks. 75 | */ 76 | struct libinput_interface libinputInterface { 77 | LibinputGestureGatherer::openRestricted, 78 | LibinputGestureGatherer::closeRestricted 79 | }; 80 | static int openRestricted(const char *path, int flags, void *userData); 81 | static void closeRestricted(int fd, void *userData); 82 | }; 83 | 84 | #endif // GESTURE_GATHERER_LIBINPUT_GESTURE_GATHERER_H_ 85 | -------------------------------------------------------------------------------- /src/gesture-gatherer/libinput-handler.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #ifndef GESTURE_GATHERER_LIBINPUT_HANDLER_H_ 19 | #define GESTURE_GATHERER_LIBINPUT_HANDLER_H_ 20 | 21 | #include 22 | 23 | #include "gesture-controller/gesture-controller-delegate.h" 24 | #include "gesture-gatherer/libinput-device-info.h" 25 | 26 | /** 27 | * Base class for every libinput handler. 28 | */ 29 | class LininputHandler { 30 | public: 31 | explicit LininputHandler(GestureControllerDelegate *gestureController) 32 | : gestureController(gestureController) {} 33 | 34 | protected: 35 | GestureControllerDelegate *gestureController; 36 | 37 | /** 38 | * @return The LibinputDeviceInfo for the device that generated the gesture. 39 | */ 40 | static LibinputDeviceInfo getDeviceInfo(struct libinput_event *event); 41 | 42 | /** 43 | * @returns The current epoch time in milliseconds. 44 | */ 45 | static uint64_t getTimestamp(); 46 | 47 | /** 48 | * @return Elapsed milliseconds since the beginning of the gesture. 49 | */ 50 | static uint64_t calculateElapsedTime(uint64_t startTimestamp); 51 | 52 | /** 53 | * @returns The direction of a swipe gesture. 54 | */ 55 | static GestureDirection calculateSwipeDirection(double deltaX, double deltaY); 56 | 57 | /** 58 | * @returns The percentage (between 0 and 100) of the gesture animation. 59 | */ 60 | static double calculateSwipeAnimationPercentage( 61 | const LibinputDeviceInfo &info, GestureDirection direction, double deltaX, 62 | double deltaY); 63 | 64 | /** 65 | * @returns The percentage (between 0 and 100) of the gesture animation. 66 | */ 67 | static double calculatePinchAnimationPercentage(GestureDirection direction, 68 | double delta); 69 | }; 70 | #endif // GESTURE_GATHERER_LIBINPUT_HANDLER_H_ 71 | -------------------------------------------------------------------------------- /src/gesture-gatherer/libinput-pinch-handler.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #include "gesture-gatherer/libinput-pinch-handler.h" 19 | 20 | #include 21 | #include 22 | 23 | #include "gesture/device-type.h" 24 | 25 | void LininputPinchHandler::handlePinchBegin(struct libinput_event * /*event*/) { 26 | this->state.reset(); 27 | } 28 | 29 | void LininputPinchHandler::handlePinchUpdate(struct libinput_event *event) { 30 | struct libinput_event_gesture *gestureEvent = 31 | libinput_event_get_gesture_event(event); 32 | this->state.delta = libinput_event_gesture_get_scale(gestureEvent); 33 | 34 | if (!this->state.started) { 35 | this->state.started = true; 36 | this->state.startTimestamp = LininputHandler::getTimestamp(); 37 | this->state.direction = 38 | (this->state.delta > 1) ? GestureDirection::OUT : GestureDirection::IN; 39 | this->state.percentage = LininputHandler::calculatePinchAnimationPercentage( 40 | this->state.direction, this->state.delta); 41 | this->state.fingers = libinput_event_gesture_get_finger_count(gestureEvent); 42 | uint64_t elapsedTime = 0; 43 | 44 | auto gesture = std::make_unique( 45 | GestureType::PINCH, this->state.direction, this->state.percentage, 46 | this->state.fingers, DeviceType::TOUCHPAD, elapsedTime); 47 | this->gestureController->onGestureBegin(std::move(gesture)); 48 | } else { 49 | this->state.percentage = LininputHandler::calculatePinchAnimationPercentage( 50 | this->state.direction, this->state.delta); 51 | uint64_t elapsedTime = 52 | LininputHandler::calculateElapsedTime(this->state.startTimestamp); 53 | 54 | auto gesture = std::make_unique( 55 | GestureType::PINCH, this->state.direction, this->state.percentage, 56 | this->state.fingers, DeviceType::TOUCHPAD, elapsedTime); 57 | this->gestureController->onGestureUpdate(std::move(gesture)); 58 | } 59 | } 60 | 61 | void LininputPinchHandler::handlePinchEnd(struct libinput_event *event) { 62 | if (this->state.started) { 63 | struct libinput_event_gesture *gestureEvent = 64 | libinput_event_get_gesture_event(event); 65 | this->state.delta = libinput_event_gesture_get_scale(gestureEvent); 66 | this->state.percentage = LininputHandler::calculatePinchAnimationPercentage( 67 | this->state.direction, this->state.delta); 68 | uint64_t elapsedTime = 69 | LininputHandler::calculateElapsedTime(this->state.startTimestamp); 70 | 71 | auto gesture = std::make_unique( 72 | GestureType::PINCH, this->state.direction, this->state.percentage, 73 | this->state.fingers, DeviceType::TOUCHPAD, elapsedTime); 74 | this->gestureController->onGestureEnd(std::move(gesture)); 75 | } 76 | 77 | this->state.reset(); 78 | } 79 | -------------------------------------------------------------------------------- /src/gesture-gatherer/libinput-pinch-handler.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #ifndef GESTURE_GATHERER_LIBINPUT_PINCH_HANDLER_H_ 19 | #define GESTURE_GATHERER_LIBINPUT_PINCH_HANDLER_H_ 20 | 21 | #include 22 | 23 | #include "gesture-controller/gesture-controller-delegate.h" 24 | #include "gesture-gatherer/libinput-handler.h" 25 | #include "gesture/gesture-direction.h" 26 | 27 | /** 28 | * Data structure to save pinch state in a single place. 29 | */ 30 | struct LibinputPinchState { 31 | bool started = false; 32 | uint64_t startTimestamp = 0; 33 | double delta = 1; 34 | GestureDirection direction = GestureDirection::UNKNOWN; 35 | double percentage = 0; 36 | int fingers = 0; 37 | 38 | void reset() { 39 | started = false; 40 | startTimestamp = 0; 41 | delta = 1; 42 | direction = GestureDirection::UNKNOWN; 43 | percentage = 0; 44 | fingers = 0; 45 | } 46 | }; 47 | 48 | /** 49 | * Class to handle libinput pinch gestures on a touchpad: 50 | * https://wayland.freedesktop.org/libinput/doc/latest/gestures.html#swipe-gestures 51 | */ 52 | class LininputPinchHandler : public LininputHandler { 53 | public: 54 | explicit LininputPinchHandler(GestureControllerDelegate *gestureController) 55 | : LininputHandler(gestureController) {} 56 | 57 | /** 58 | * When the user starts a pinch, we still don't know the direction, so here we 59 | * just reset this->swipeState. 60 | * @param gesture Libinput specialized gesture. 61 | */ 62 | void handlePinchBegin(struct libinput_event *event); 63 | 64 | /** 65 | * Unlike swipe, a threshold is not required for this gesture. 66 | * The first update sends a begin event to the GestureControllerDelegate. 67 | * Consecutive updates send a update event to the GestureControllerDelegate. 68 | * @param gesture Libinput specialized gesture. 69 | */ 70 | void handlePinchUpdate(struct libinput_event *event); 71 | 72 | /** 73 | * Send a end event to the GestureControllerDelegate if a gesture was 74 | * detected. 75 | * @param gesture Libinput specialized gesture. 76 | */ 77 | void handlePinchEnd(struct libinput_event *event); 78 | 79 | private: 80 | LibinputPinchState state; 81 | }; 82 | #endif // GESTURE_GATHERER_LIBINPUT_PINCH_HANDLER_H_ 83 | -------------------------------------------------------------------------------- /src/gesture-gatherer/libinput-swipe-handler.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #include "gesture-gatherer/libinput-swipe-handler.h" 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | #include "gesture-gatherer/libinput-device-info.h" 25 | #include "gesture/device-type.h" 26 | #include "gesture/gesture.h" 27 | 28 | void LininputSwipeHandler::handleSwipeBegin(struct libinput_event * /*event*/) { 29 | this->state.reset(); 30 | } 31 | 32 | void LininputSwipeHandler::handleSwipeUpdate(struct libinput_event *event) { 33 | struct libinput_event_gesture *gestureEvent = 34 | libinput_event_get_gesture_event(event); 35 | this->state.deltaX += 36 | libinput_event_gesture_get_dx_unaccelerated(gestureEvent); 37 | this->state.deltaY += 38 | libinput_event_gesture_get_dy_unaccelerated(gestureEvent); 39 | 40 | LibinputDeviceInfo info = LininputHandler::getDeviceInfo(event); 41 | 42 | if (!this->state.started) { 43 | if (std::abs(this->state.deltaX) > info.startThreshold || 44 | std::abs(this->state.deltaY) > info.startThreshold) { 45 | this->state.started = true; 46 | this->state.startTimestamp = LininputHandler::getTimestamp(); 47 | this->state.direction = LininputHandler::calculateSwipeDirection( 48 | this->state.deltaX, this->state.deltaY); 49 | this->state.percentage = 50 | LininputHandler::calculateSwipeAnimationPercentage( 51 | info, this->state.direction, this->state.deltaX, 52 | this->state.deltaY); 53 | this->state.fingers = 54 | libinput_event_gesture_get_finger_count(gestureEvent); 55 | uint64_t elapsedTime = 0; 56 | 57 | auto gesture = std::make_unique( 58 | GestureType::SWIPE, this->state.direction, this->state.percentage, 59 | this->state.fingers, DeviceType::TOUCHPAD, elapsedTime); 60 | this->gestureController->onGestureBegin(std::move(gesture)); 61 | } 62 | } else { 63 | this->state.percentage = LininputHandler::calculateSwipeAnimationPercentage( 64 | info, this->state.direction, this->state.deltaX, this->state.deltaY); 65 | uint64_t elapsedTime = 66 | LininputHandler::calculateElapsedTime(this->state.startTimestamp); 67 | 68 | auto gesture = std::make_unique( 69 | GestureType::SWIPE, this->state.direction, this->state.percentage, 70 | this->state.fingers, DeviceType::TOUCHPAD, elapsedTime); 71 | this->gestureController->onGestureUpdate(std::move(gesture)); 72 | } 73 | } 74 | 75 | void LininputSwipeHandler::handleSwipeEnd(struct libinput_event *event) { 76 | if (this->state.started) { 77 | LibinputDeviceInfo info = LininputHandler::getDeviceInfo(event); 78 | this->state.percentage = LininputHandler::calculateSwipeAnimationPercentage( 79 | info, this->state.direction, this->state.deltaX, this->state.deltaY); 80 | uint64_t elapsedTime = 81 | LininputHandler::calculateElapsedTime(this->state.startTimestamp); 82 | 83 | auto gesture = std::make_unique( 84 | GestureType::SWIPE, this->state.direction, this->state.percentage, 85 | this->state.fingers, DeviceType::TOUCHPAD, elapsedTime); 86 | this->gestureController->onGestureEnd(std::move(gesture)); 87 | } 88 | 89 | this->state.reset(); 90 | } 91 | -------------------------------------------------------------------------------- /src/gesture-gatherer/libinput-swipe-handler.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #ifndef GESTURE_GATHERER_LIBINPUT_SWIPE_HANDLER_H_ 19 | #define GESTURE_GATHERER_LIBINPUT_SWIPE_HANDLER_H_ 20 | 21 | #include 22 | 23 | #include "gesture-controller/gesture-controller-delegate.h" 24 | #include "gesture-gatherer/libinput-handler.h" 25 | #include "gesture/gesture-direction.h" 26 | 27 | /** 28 | * Data structure to save swipe state in a single place. 29 | */ 30 | struct LibinputSwipeState { 31 | bool started = false; 32 | uint64_t startTimestamp = 0; 33 | double deltaX = 0; 34 | double deltaY = 0; 35 | GestureDirection direction = GestureDirection::UNKNOWN; 36 | double percentage = 0; 37 | int fingers = 0; 38 | 39 | void reset() { 40 | started = false; 41 | startTimestamp = 0; 42 | deltaX = 0; 43 | deltaY = 0; 44 | direction = GestureDirection::UNKNOWN; 45 | percentage = 0; 46 | fingers = 0; 47 | } 48 | }; 49 | 50 | /** 51 | * Class to handle libinput swipe gestures on a touchpad: 52 | * https://wayland.freedesktop.org/libinput/doc/latest/gestures.html#swipe-gestures 53 | */ 54 | class LininputSwipeHandler : public LininputHandler { 55 | public: 56 | explicit LininputSwipeHandler(GestureControllerDelegate *gestureController) 57 | : LininputHandler(gestureController) {} 58 | 59 | /** 60 | * When the user starts a swipe, we still don't know the direction, so here we 61 | * just reset the state. 62 | * @param gesture Libinput specialized gesture. 63 | */ 64 | void handleSwipeBegin(struct libinput_event *event); 65 | 66 | /** 67 | * On every update we increase or decrease "this->state.deltaX" and 68 | * "this->state.deltaY". Once any of them passes the configured threshold we 69 | * send a begin event to the GestureControllerDelegate. Once the threshold is 70 | * passed we send update events to the GestureControllerDelegate until the 71 | * gesture ends. 72 | * @param gesture Libinput specialized gesture. 73 | */ 74 | void handleSwipeUpdate(struct libinput_event *event); 75 | 76 | /** 77 | * Send a end event to the GestureControllerDelegate if a gesture was 78 | * detected. 79 | * If the gesture didn't pass the threshold we should not notify it. 80 | * @param gesture Libinput specialized gesture. 81 | */ 82 | void handleSwipeEnd(struct libinput_event *event); 83 | 84 | private: 85 | LibinputSwipeState state; 86 | }; 87 | 88 | #endif // GESTURE_GATHERER_LIBINPUT_SWIPE_HANDLER_H_ 89 | -------------------------------------------------------------------------------- /src/gesture-gatherer/libinput-touch-handler.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #ifndef GESTURE_GATHERER_LIBINPUT_TOUCH_HANDLER_H_ 19 | #define GESTURE_GATHERER_LIBINPUT_TOUCH_HANDLER_H_ 20 | 21 | #include 22 | #include 23 | 24 | #include "gesture-gatherer/libinput-handler.h" 25 | #include "gesture/gesture-direction.h" 26 | #include "gesture/gesture-type.h" 27 | 28 | /** 29 | * Data structure to save touch state in a single place. 30 | */ 31 | struct LibinputTouchState { 32 | bool started = false; 33 | GestureType type = GestureType::NOT_SUPPORTED; 34 | GestureDirection direction = GestureDirection::UNKNOWN; 35 | uint64_t startTimestamp = 0; 36 | int startFingers = 0; 37 | std::unordered_map startX; 38 | std::unordered_map startY; 39 | int currentFingers = 0; 40 | std::unordered_map currentX; 41 | std::unordered_map currentY; 42 | int tapFingers = 0; 43 | 44 | void reset() { 45 | started = false; 46 | type = GestureType::NOT_SUPPORTED; 47 | direction = GestureDirection::UNKNOWN; 48 | startTimestamp = 0; 49 | startFingers = 0; 50 | tapFingers = 0; 51 | 52 | // Do not reset this data as gestures finish when 1 finger is on the screen 53 | // startX.clear(); 54 | // startY.clear(); 55 | // currentFingers = 0; 56 | // currentX.clear(); 57 | // currentY.clear(); 58 | } 59 | }; 60 | 61 | class LibinputTouchHandler : public LininputHandler { 62 | public: 63 | explicit LibinputTouchHandler(GestureControllerDelegate *gestureController) 64 | : LininputHandler(gestureController) {} 65 | 66 | void handleTouchDown(struct libinput_event *event); 67 | void handleTouchUp(struct libinput_event *event); 68 | void handleTouchMotion(struct libinput_event *event); 69 | 70 | private: 71 | LibinputTouchState state; 72 | 73 | /** 74 | * @return Average for the current active fingers. 75 | */ 76 | std::pair getAverageDelta() const; 77 | 78 | /** 79 | * @returns When the gestures starts, uses "this->state" to differentiate 80 | * between SWIPE and PINCH gestures. 81 | */ 82 | GestureType getGestureType() const; 83 | 84 | /** 85 | * @returns GestureDirection::IN or GestureDirection::OUT. 86 | */ 87 | GestureDirection calculatePinchDirection() const; 88 | 89 | /** 90 | * @returns Delta (similar to libinput_event_gesture_get_scale but for touch 91 | * screens) of a pinch gesture. 92 | */ 93 | double getPinchDelta() const; 94 | 95 | /** 96 | * Pinch deltas are calculated "drawing" a bounding box containing every 97 | * finger involved in the gesture. 98 | * This method returns that bounding box width (on the X axis) at the 99 | * beginning of the gesture and in the moment it is called. 100 | */ 101 | std::pair getStartCurrentPinchBBox() const; 102 | }; 103 | 104 | #endif // GESTURE_GATHERER_LIBINPUT_TOUCH_HANDLER_H_ 105 | -------------------------------------------------------------------------------- /src/gesture/device-type.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #ifndef GESTURE_DEVICE_TYPE_H_ 19 | #define GESTURE_DEVICE_TYPE_H_ 20 | 21 | #include 22 | 23 | enum class DeviceType { 24 | UNKNOWN = 0, 25 | TOUCHPAD = 1, 26 | TOUCHSCREEN = 2, 27 | 28 | // Adding a new device type? Don't forget to add it in deviceTypeToStr and 29 | // deviceTypeFromStr 30 | }; 31 | 32 | inline std::string deviceTypeToStr(DeviceType deviceType) { 33 | switch (deviceType) { 34 | case DeviceType::TOUCHPAD: 35 | return "TOUCHPAD"; 36 | case DeviceType::TOUCHSCREEN: 37 | return "TOUCHSCREEN"; 38 | default: 39 | return "UNKNOWN"; 40 | } 41 | } 42 | 43 | inline DeviceType deviceTypeFromStr(const std::string &str) { 44 | if (str == "TOUCHPAD") { 45 | return DeviceType::TOUCHPAD; 46 | } 47 | if (str == "TOUCHSCREEN") { 48 | return DeviceType::TOUCHSCREEN; 49 | } 50 | return DeviceType::UNKNOWN; 51 | } 52 | 53 | #endif // GESTURE_DEVICE_TYPE_H_ 54 | -------------------------------------------------------------------------------- /src/gesture/gesture-direction.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #ifndef GESTURE_GESTURE_DIRECTION_H_ 19 | #define GESTURE_GESTURE_DIRECTION_H_ 20 | 21 | #include 22 | 23 | enum class GestureDirection { 24 | // A gesture may have an unknow direction until we have more information 25 | UNKNOWN = 0, 26 | 27 | // GestureType::SWIPE 28 | UP = 1, 29 | DOWN = 2, 30 | LEFT = 3, 31 | RIGHT = 4, 32 | 33 | // GestureType::PINCH 34 | IN = 5, 35 | OUT = 6, 36 | 37 | // Adding a new GestureDirection? Don't forget to add it in 38 | // gestureDirectionToStr and gestureDirectionFromStr as well 39 | }; 40 | 41 | inline std::string gestureDirectionToStr(GestureDirection gestureDirection) { 42 | switch (gestureDirection) { 43 | case GestureDirection::UP: 44 | return "UP"; 45 | case GestureDirection::DOWN: 46 | return "DOWN"; 47 | case GestureDirection::LEFT: 48 | return "LEFT"; 49 | case GestureDirection::RIGHT: 50 | return "RIGHT"; 51 | case GestureDirection::IN: 52 | return "IN"; 53 | case GestureDirection::OUT: 54 | return "OUT"; 55 | default: 56 | return "UNKNOWN"; 57 | } 58 | } 59 | 60 | inline GestureDirection gestureDirectionFromStr(const std::string &str) { 61 | if (str == "UP") { 62 | return GestureDirection::UP; 63 | } 64 | if (str == "DOWN") { 65 | return GestureDirection::DOWN; 66 | } 67 | if (str == "LEFT") { 68 | return GestureDirection::LEFT; 69 | } 70 | if (str == "RIGHT") { 71 | return GestureDirection::RIGHT; 72 | } 73 | if (str == "IN") { 74 | return GestureDirection::IN; 75 | } 76 | if (str == "OUT") { 77 | return GestureDirection::OUT; 78 | } 79 | return GestureDirection::UNKNOWN; 80 | } 81 | 82 | #endif // GESTURE_GESTURE_DIRECTION_H_ 83 | -------------------------------------------------------------------------------- /src/gesture/gesture-type.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #ifndef GESTURE_GESTURE_TYPE_H_ 19 | #define GESTURE_GESTURE_TYPE_H_ 20 | 21 | #include 22 | 23 | enum class GestureType { 24 | NOT_SUPPORTED = 0, 25 | SWIPE = 1, 26 | PINCH = 2, 27 | TAP = 3, 28 | // Adding a new GestureType? Don't forget to add it in gestureTypeToStr and 29 | // gestureTypeFromStr as well 30 | }; 31 | 32 | inline std::string gestureTypeToStr(GestureType gestureType) { 33 | switch (gestureType) { 34 | case GestureType::SWIPE: 35 | return "SWIPE"; 36 | case GestureType::PINCH: 37 | return "PINCH"; 38 | case GestureType::TAP: 39 | return "TAP"; 40 | default: 41 | return "NOT_SUPPORTED"; 42 | } 43 | } 44 | 45 | inline GestureType gestureTypeFromStr(const std::string &str) { 46 | // Support "DRAG" for compatibility with v0 and v1 47 | if (str == "SWIPE" || str == "DRAG") { 48 | return GestureType::SWIPE; 49 | } 50 | if (str == "PINCH") { 51 | return GestureType::PINCH; 52 | } 53 | if (str == "TAP") { 54 | return GestureType::TAP; 55 | } 56 | return GestureType::NOT_SUPPORTED; 57 | } 58 | 59 | #endif // GESTURE_GESTURE_TYPE_H_ 60 | -------------------------------------------------------------------------------- /src/gesture/gesture.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #ifndef GESTURE_GESTURE_H_ 19 | #define GESTURE_GESTURE_H_ 20 | 21 | #include 22 | 23 | #include "gesture/device-type.h" 24 | #include "gesture/gesture-direction.h" 25 | #include "gesture/gesture-type.h" 26 | 27 | /** 28 | * Gestures implementations change depending on the driver/backend. This is the 29 | * basic interface of a gesture. 30 | */ 31 | class Gesture { 32 | public: 33 | Gesture(GestureType type, GestureDirection direction, double percentage, 34 | int fingers, DeviceType performedOnDeviceType, uint64_t elapsedTime) 35 | : gestureType(type), 36 | gestureDirection(direction), 37 | gesturePercentage(percentage), 38 | gestureFingers(fingers), 39 | deviceType(performedOnDeviceType), 40 | gestureElapsedTime(elapsedTime) {} 41 | 42 | /** 43 | * @returns The gesture type. 44 | * @see GestureType 45 | */ 46 | GestureType type() const { return this->gestureType; } 47 | 48 | /** 49 | * @returns The gesture direction. 50 | * @see GestureDirection 51 | */ 52 | GestureDirection direction() const { return this->gestureDirection; } 53 | 54 | /** 55 | * Percentage of the gesture performed, used for animations. 56 | * @return Value between 0 and 100. 57 | */ 58 | double percentage() const { return this->gesturePercentage; } 59 | 60 | /** 61 | * @returns The number of fingers used to perform the gesture. 62 | */ 63 | int fingers() const { return this->gestureFingers; } 64 | 65 | /** 66 | * @returns The device type the gesture was performed on. 67 | */ 68 | DeviceType performedOnDeviceType() const { return this->deviceType; } 69 | 70 | /** 71 | * Elapsed time since the beginning of the gesture. 72 | * @returns The elapsed time in milliseconds. 73 | */ 74 | uint64_t elapsedTime() const { return this->gestureElapsedTime; } 75 | 76 | /** 77 | * Set the gesture direction. 78 | * @see GestureDirection 79 | */ 80 | void setDirection(GestureDirection direction) { 81 | this->gestureDirection = direction; 82 | } 83 | 84 | protected: 85 | GestureType gestureType = GestureType::NOT_SUPPORTED; 86 | GestureDirection gestureDirection = GestureDirection::UNKNOWN; 87 | double gesturePercentage = -1; 88 | int gestureFingers = -1; 89 | DeviceType deviceType = DeviceType::UNKNOWN; 90 | uint64_t gestureElapsedTime = -1; 91 | }; 92 | 93 | #endif // GESTURE_GESTURE_H_ 94 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #include 19 | #include 20 | 21 | #include "config/config.h" 22 | #include "config/xml-config-loader.h" 23 | #include "daemon/daemon-client.h" 24 | #include "daemon/daemon-server.h" 25 | #include "gesture-controller/gesture-controller.h" 26 | #include "gesture-gatherer/libinput-gesture-gatherer.h" 27 | #include "utils/args-parser.h" 28 | #include "utils/client-lock.h" 29 | #include "utils/logger.h" 30 | #include "window-system/window-system.h" 31 | #include "window-system/x11.h" 32 | 33 | int main(int argc, char** argv) { 34 | // Parse the command line arguments 35 | ArgsParser args(argc, argv); 36 | if (args.exit) { 37 | return 0; 38 | } 39 | ArgsParser::printVersion(); 40 | 41 | // Configure the logger 42 | tlg::configure(args.debug, args.quiet); 43 | 44 | if (args.daemonMode == args.clientMode) { 45 | tlg::error << "Invalid command line arguments" << std::endl; 46 | return -1; 47 | } 48 | 49 | tlg::info << "Starting Touchégg in " 50 | << (args.daemonMode ? std::string{"daemon mode"} 51 | : std::string{"client mode"}) 52 | << std::endl; 53 | 54 | // Execute the daemon/client bits 55 | if (args.daemonMode) { 56 | // Start the daemon server 57 | DaemonServer daemonServer{}; 58 | daemonServer.run(); 59 | 60 | // Use libinput as gesture gatherer 61 | tlg::info 62 | << "A list of detected compatible devices will be displayed below:" 63 | << std::endl; 64 | 65 | LibinputGestureGatherer gestureGatherer(&daemonServer, args.startThreshold, 66 | args.finishThreshold); 67 | gestureGatherer.run(); 68 | } else { // clientMode 69 | // Use X11 as window system 70 | X11 windowSystem; 71 | 72 | try { 73 | // Avoid running multiple client instances in parallel 74 | ClientLock lock(windowSystem.getConnectionName()); 75 | } catch (const std::runtime_error& error) { 76 | tlg::error << error.what() << std::endl; 77 | return -1; 78 | } 79 | // Load the configuration using the XML loader 80 | tlg::info << "Parsing your configuration file..." << std::endl; 81 | Config config; 82 | XmlConfigLoader loader(&config); 83 | loader.load(); 84 | tlg::info << "Configuration parsed successfully" << std::endl; 85 | 86 | // Initialize the gesture controller 87 | GestureController gestureController(config, windowSystem); 88 | 89 | // Connect to the daemon 90 | DaemonClient daemonClient{&gestureController}; 91 | daemonClient.run(); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/utils/args-parser.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021 John Mifsud 3 | * Copyright 2011 - 2022 José Expósito 4 | * 5 | * This file is part of Touchégg. 6 | * 7 | * Touchégg is free software: you can redistribute it and/or modify it under the 8 | * terms of the GNU General Public License as published by the Free Software 9 | * Foundation, either version 3 of the License, or (at your option) any later 10 | * version. 11 | * 12 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 13 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 14 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License along with 17 | * Touchégg. If not, see . 18 | */ 19 | #ifndef UTILS_ARGS_PARSER_H_ 20 | #define UTILS_ARGS_PARSER_H_ 21 | 22 | #include 23 | #include 24 | 25 | class ArgsParser { 26 | public: 27 | /** 28 | * When constructed the obj parses the given args and sets the option flags 29 | * 30 | * @param argc The standard arg count passed to main() 31 | * @param argv The standard arg array passed to main() 32 | */ 33 | ArgsParser(int argc, char **argv); 34 | 35 | /** 36 | * Print version number. 37 | */ 38 | static void printVersion(); 39 | 40 | /** 41 | * If should run in daemon mode. 42 | */ 43 | bool daemonMode = false; 44 | 45 | /** 46 | * If should run in client mode. 47 | */ 48 | bool clientMode = false; 49 | 50 | /** 51 | * If should show every log message. 52 | */ 53 | bool debug = false; 54 | 55 | /** 56 | * If should not show any log message. 57 | */ 58 | bool quiet = false; 59 | 60 | /** 61 | * Amount of motion to be made on the touchpad before a gesture is started. 62 | */ 63 | double startThreshold = -1; 64 | 65 | /** 66 | * Amount of motion to be made on the touchpad to reach the end of the 67 | * gesture. 68 | */ 69 | double finishThreshold = -1; 70 | 71 | /** 72 | * Flag indicating if the process should exit (--help, --version, etc). 73 | */ 74 | bool exit = false; 75 | 76 | private: 77 | std::vector tokens; 78 | 79 | bool cmdOptionExists(const std::string &option); 80 | 81 | /** 82 | * When 2 number are set after --daemon, use them as start and finish 83 | * thresholds. 84 | */ 85 | void getDaemonThresholds(); 86 | 87 | /** 88 | * Print help. 89 | */ 90 | static void printHelp(); 91 | }; 92 | 93 | #endif // UTILS_ARGS_PARSER_H_ 94 | -------------------------------------------------------------------------------- /src/utils/client-lock.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #include "utils/client-lock.h" 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | #include "utils/paths.h" 29 | 30 | ClientLock::ClientLock(const std::string &lockInstance) { 31 | Paths::createUserConfigDir(); 32 | 33 | std::filesystem::path lockPath = Paths::getUserLockFilePath(lockInstance); 34 | this->fd = open(lockPath.c_str(), O_CREAT | O_RDWR, 0640); // NOLINT 35 | 36 | std::string errorMessage{ 37 | "Another instance of Touchégg is already running. If you are sure that " 38 | "Touchégg is not already running, delete the lock file with the " 39 | "following command and try again:\n$ rm " + 40 | lockPath.string()}; 41 | 42 | if (this->fd < 0) { 43 | throw std::runtime_error{errorMessage}; 44 | } 45 | 46 | if (flock(this->fd, LOCK_EX | LOCK_NB) < 0) { 47 | close(this->fd); 48 | throw std::runtime_error{errorMessage}; 49 | } 50 | } 51 | 52 | ClientLock::~ClientLock() { 53 | flock(this->fd, LOCK_UN); 54 | close(this->fd); 55 | } 56 | -------------------------------------------------------------------------------- /src/utils/client-lock.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #ifndef UTILS_CLIENT_LOCK_H_ 19 | #define UTILS_CLIENT_LOCK_H_ 20 | 21 | #include 22 | 23 | /** 24 | * Creates a lock file to avoid multiple client instances to run in parallel. 25 | */ 26 | class ClientLock { 27 | public: 28 | explicit ClientLock(const std::string &lockInstance); 29 | ~ClientLock(); 30 | 31 | private: 32 | int fd; 33 | }; 34 | 35 | #endif // UTILS_CLIENT_LOCK_H_ 36 | -------------------------------------------------------------------------------- /src/utils/color.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #include "utils/color.h" 19 | 20 | #include 21 | 22 | #include "utils/logger.h" 23 | 24 | #ifdef AUTO_COLORS 25 | #include 26 | #include 27 | #endif 28 | 29 | Color::Color(const std::string &hexString, ColorType colorType) { 30 | if (hexString == "auto") { 31 | this->setFromAutoColor(colorType); 32 | } else { 33 | this->setFromHexString(hexString); 34 | } 35 | } 36 | 37 | void Color::setFromHexString(const std::string &hexString) { 38 | if (hexString.size() != 6 && 39 | (hexString.size() != 7 && hexString.front() != '#')) { 40 | return; 41 | } 42 | 43 | size_t offset = (hexString.size() == 6) ? 0 : 1; 44 | 45 | try { 46 | this->red = std::stoi(hexString.substr(offset, 2), nullptr, 16) / 255.0; 47 | this->green = 48 | std::stoi(hexString.substr(offset + 2, 2), nullptr, 16) / 255.0; 49 | this->blue = 50 | std::stoi(hexString.substr(offset + 4, 2), nullptr, 16) / 255.0; 51 | } catch (const std::exception & /* error */) { 52 | tlg::error << "Error: Invalid animation color, using default color" 53 | << std::endl; 54 | } 55 | } 56 | 57 | void Color::setFromAutoColor(ColorType colorType) { 58 | #ifdef AUTO_COLORS 59 | gtk_init_check(nullptr, nullptr); 60 | 61 | GtkWidget *label = gtk_label_new(""); 62 | g_object_ref_sink(label); 63 | GtkStyleContext *labelStyleContext = gtk_widget_get_style_context(label); 64 | GtkWidgetPath *path = 65 | gtk_widget_path_copy(gtk_style_context_get_path(labelStyleContext)); 66 | gtk_widget_path_iter_set_object_name(path, -1, "selection"); 67 | 68 | GtkStyleContext *colorStyleContext = gtk_style_context_new(); 69 | gtk_style_context_set_path(colorStyleContext, path); 70 | gtk_style_context_set_parent(colorStyleContext, labelStyleContext); 71 | 72 | GdkRGBA *color = nullptr; 73 | // NOLINTNEXTLINE 74 | gtk_style_context_get( 75 | colorStyleContext, GTK_STATE_FLAG_NORMAL, 76 | (colorType == ColorType::BACKGROUND ? GTK_STYLE_PROPERTY_BACKGROUND_COLOR 77 | : GTK_STYLE_PROPERTY_BORDER_COLOR), 78 | &color, nullptr); 79 | 80 | this->red = color->red; 81 | this->green = color->green; 82 | this->blue = color->blue; 83 | 84 | gdk_rgba_free(color); 85 | g_object_unref(colorStyleContext); 86 | gtk_widget_path_free(path); 87 | gtk_widget_destroy(label); 88 | g_object_unref(label); 89 | #endif 90 | } 91 | -------------------------------------------------------------------------------- /src/utils/color.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #ifndef UTILS_COLOR_H_ 19 | #define UTILS_COLOR_H_ 20 | 21 | #include 22 | 23 | enum class ColorType { 24 | BACKGROUND, 25 | BORDER, 26 | }; 27 | 28 | /** 29 | * Simple class to parse color from config and use them with Cairo. 30 | */ 31 | class Color { 32 | public: 33 | Color() = default; 34 | 35 | /** 36 | * @param hexString A string like "RRGGBB", "#RRGGBB" or "auto". 37 | */ 38 | Color(const std::string &hexString, ColorType colorType); 39 | 40 | double r() const { return this->red; } 41 | double g() const { return this->green; } 42 | double b() const { return this->blue; } 43 | 44 | private: 45 | double red = 0.6; 46 | double green = 0.6; 47 | double blue = 0.6; 48 | 49 | void setFromHexString(const std::string &hexString); 50 | void setFromAutoColor(ColorType colorType); 51 | }; 52 | 53 | #endif // UTILS_COLOR_H_ 54 | -------------------------------------------------------------------------------- /src/utils/filesystem.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #ifndef UTILS_FILESYSTEM_H_ 19 | #define UTILS_FILESYSTEM_H_ 20 | 21 | /* 22 | * Ubuntu 18 (gcc < 8.0.0) doesn't support plain "filesystem" include and 23 | * namespace. This utility simplifies the process of including "filesystem". 24 | */ 25 | 26 | #if __has_include() 27 | 28 | #include 29 | 30 | #else 31 | 32 | #include 33 | namespace std { 34 | namespace filesystem = experimental::filesystem; 35 | } 36 | 37 | #endif 38 | 39 | #endif // UTILS_FILESYSTEM_H_ 40 | -------------------------------------------------------------------------------- /src/utils/logger.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021 John Mifsud 3 | * Copyright 2011 - 2022 José Expósito 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #include "utils/logger.h" 19 | 20 | #include 21 | 22 | namespace tlg { 23 | LogLevel error = LogLevel::ERROR; 24 | LogLevel warning = LogLevel::WARNING; 25 | LogLevel info = LogLevel::INFO; 26 | LogLevel debug = LogLevel::DEBUG; 27 | 28 | void configure(bool debug, bool quiet) { Logger::obj(debug, quiet); } 29 | 30 | } // namespace tlg 31 | 32 | bool Logger::enabled(const LogLevel &lvl) const { 33 | switch (lvl) { 34 | case LogLevel::INFO: 35 | return logInfo; 36 | case LogLevel::WARNING: 37 | return logWarning; 38 | case LogLevel::ERROR: 39 | return logError; 40 | case LogLevel::DEBUG: 41 | return logDebug; 42 | 43 | default: 44 | std::cerr << "Unknown LogLevel!" << std::endl; 45 | return false; 46 | } 47 | } 48 | 49 | std::ostream &Logger::getStream(const LogLevel &lvl) { 50 | switch (lvl) { 51 | case LogLevel::ERROR: 52 | return std::cerr; 53 | 54 | default: 55 | return std::cout; 56 | } 57 | } 58 | 59 | /** 60 | * I hate that the following func isn't DRY, (the body repeats the template in 61 | * the class header), but I don't see any way around this. Just keep this in 62 | * mind if/when you modify the function: it should probably be the same in both 63 | * places. 64 | */ 65 | LogLevel operator<<(const LogLevel &lvl, std::ostream &(*msg)(std::ostream &)) { 66 | if (Logger::obj().enabled(lvl)) { 67 | Logger::obj().getStream(lvl) << msg; 68 | } 69 | 70 | return lvl; 71 | } 72 | 73 | Logger::Logger() { 74 | uninitialized = true; 75 | 76 | // defaults 77 | logError = true; 78 | logWarning = true; 79 | logInfo = true; 80 | logDebug = false; 81 | } 82 | 83 | void Logger::init(const bool debug, const bool quiet) { 84 | uninitialized = false; 85 | 86 | // primary logging options 87 | if (quiet) { 88 | logError = false; 89 | logWarning = false; 90 | logInfo = false; 91 | } else if (debug) { 92 | logDebug = true; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/utils/logger.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021 John Mifsud 3 | * Copyright 2011 - 2022 José Expósito 4 | * 5 | * This file is part of Touchégg. 6 | * 7 | * Touchégg is free software: you can redistribute it and/or modify it under the 8 | * terms of the GNU General Public License as published by the Free Software 9 | * Foundation, either version 3 of the License, or (at your option) any later 10 | * version. 11 | * 12 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 13 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 14 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License along with 17 | * Touchégg. If not, see . 18 | */ 19 | #ifndef UTILS_LOGGER_H_ 20 | #define UTILS_LOGGER_H_ 21 | 22 | #include 23 | 24 | enum class LogLevel { INFO, WARNING, ERROR, DEBUG }; 25 | 26 | /** 27 | * USAGE: tlg.LEVEL << "A very informative message!" << std::endl; 28 | * 29 | * LEVEL: error | warning | info | debug 30 | */ 31 | namespace tlg { 32 | void configure(bool debug = false, bool quiet = false); 33 | 34 | extern LogLevel error; 35 | extern LogLevel warning; 36 | extern LogLevel info; 37 | extern LogLevel debug; 38 | } // namespace tlg 39 | 40 | /** 41 | * Singleton class to provide simple logging functionality. 42 | */ 43 | class Logger { 44 | public: 45 | /** 46 | * USAGE: LogLevel.LEVEL << "A very informative message!" << std::endl; 47 | * 48 | * LEVEL: error | warning | info | debug 49 | */ 50 | friend LogLevel operator<<(const LogLevel &lvl, 51 | std::ostream &(*msg)(std::ostream &)); 52 | template 53 | friend LogLevel operator<<(const LogLevel &lvl, T const &msg); 54 | 55 | /** 56 | * This static method controls the access to the singleton. 57 | * 58 | * The following parameters are only applied on the first call when the 59 | * singleton is created. 60 | * @param debug Show all log msgs. 61 | * @param quiet Suppress all msgs. 62 | * 63 | * @return ref to the Logger singleton 64 | */ 65 | static Logger &obj(const bool debug = false, const bool quiet = false) { 66 | static Logger singleton; 67 | 68 | if (singleton.uninitialized) { 69 | singleton.init(debug, quiet); 70 | } 71 | 72 | return singleton; 73 | } 74 | 75 | // Should not be cloneable. 76 | Logger(Logger const &) = delete; 77 | 78 | // Should not be assignable. 79 | void operator=(Logger const &) = delete; 80 | 81 | private: 82 | // These indicate if the various logging levels should be enabled. 83 | bool logInfo, logWarning, logError, logDebug; 84 | 85 | /** 86 | * If true then the logging levels & options will be set on first call to 87 | * Logger::Obj() 88 | */ 89 | bool uninitialized; 90 | 91 | Logger(); 92 | 93 | /** 94 | * Sets the logging levels & options. 95 | */ 96 | void init(const bool debug, const bool quiet); 97 | 98 | bool enabled(const LogLevel &lvl) const; 99 | static std::ostream &getStream(const LogLevel &lvl); 100 | }; 101 | 102 | /** 103 | * USAGE: LogLevel.LEVEL << "A very informative message!" << std::endl; 104 | * 105 | * LEVEL: error | warning | info | debug 106 | */ 107 | LogLevel operator<<(const LogLevel &lvl, std::ostream &(*msg)(std::ostream &)); 108 | template 109 | LogLevel operator<<(const LogLevel &lvl, T const &msg) { 110 | if (Logger::obj().enabled(lvl)) { 111 | Logger::obj().getStream(lvl) << msg; 112 | } 113 | 114 | return lvl; 115 | } 116 | 117 | #endif // UTILS_LOGGER_H_ 118 | -------------------------------------------------------------------------------- /src/utils/paths.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #ifndef UTILS_PATHS_H_ 19 | #define UTILS_PATHS_H_ 20 | 21 | #include 22 | 23 | #include "utils/filesystem.h" 24 | 25 | /** 26 | * Utility class to get usefull paths. 27 | */ 28 | class Paths { 29 | public: 30 | /** 31 | * @return User's home directory path. 32 | */ 33 | static std::filesystem::path getHomePath(); 34 | 35 | /** 36 | * @return User's config directory path (~/.config/touchegg). 37 | */ 38 | static std::filesystem::path getUserConfigDirPath(); 39 | 40 | /** 41 | * @return User's config file path (~/.config/touchegg/touchegg.conf). 42 | */ 43 | static std::filesystem::path getUserConfigFilePath(); 44 | 45 | /** 46 | * @return User's lock file path 47 | * (~/.config/touchegg/.touchegg{lockInstance}.lock). 48 | */ 49 | static std::filesystem::path getUserLockFilePath( 50 | const std::string &lockInstance); 51 | 52 | /** 53 | * @return System config file path (/usr/share/touchegg/touchegg.conf). 54 | */ 55 | static std::filesystem::path getSystemConfigFilePath(); 56 | 57 | /** 58 | * Creates the "getUserConfigDirPath" directory. 59 | */ 60 | static void createUserConfigDir(); 61 | }; 62 | 63 | #endif // UTILS_PATHS_H_ 64 | -------------------------------------------------------------------------------- /src/utils/rectangle.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #ifndef UTILS_RECTANGLE_H_ 19 | #define UTILS_RECTANGLE_H_ 20 | 21 | struct Rectangle { 22 | int x = 0; 23 | int y = 0; 24 | int width = 0; 25 | int height = 0; 26 | }; 27 | 28 | #endif // UTILS_RECTANGLE_H_ 29 | -------------------------------------------------------------------------------- /src/utils/string.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #include "utils/string.h" 19 | 20 | #include 21 | #include 22 | #include // NOLINT 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | std::vector split(const std::string &string, char delimiter) { 29 | std::stringstream ss(string); 30 | std::string item; 31 | std::vector elems; 32 | 33 | while (std::getline(ss, item, delimiter)) { 34 | elems.push_back(std::move(item)); 35 | } 36 | 37 | return elems; 38 | } 39 | 40 | std::string ltrim(const std::string &s) { 41 | return std::regex_replace(s, std::regex("^\\s+"), std::string("")); 42 | } 43 | 44 | std::string rtrim(const std::string &s) { 45 | return std::regex_replace(s, std::regex("\\s+$"), std::string("")); 46 | } 47 | 48 | std::string trim(const std::string &s) { return ltrim(rtrim(s)); } 49 | 50 | std::string toLower(const std::string &string) { 51 | std::string lower = string; 52 | std::transform(lower.begin(), lower.end(), lower.begin(), 53 | [](unsigned char c) { return std::tolower(c); }); 54 | return lower; 55 | } 56 | -------------------------------------------------------------------------------- /src/utils/string.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #ifndef UTILS_STRING_H_ 19 | #define UTILS_STRING_H_ 20 | 21 | #include 22 | #include 23 | 24 | std::vector split(const std::string &string, char delimiter); 25 | 26 | std::string ltrim(const std::string &s); 27 | std::string rtrim(const std::string &s); 28 | std::string trim(const std::string &s); 29 | 30 | std::string toLower(const std::string &string); 31 | 32 | #endif // UTILS_STRING_H_ 33 | -------------------------------------------------------------------------------- /src/window-system/cairo-surface.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #ifndef WINDOW_SYSTEM_CAIRO_SURFACE_H_ 19 | #define WINDOW_SYSTEM_CAIRO_SURFACE_H_ 20 | 21 | #include 22 | 23 | #include 24 | 25 | /** 26 | * Window system independent cairo surface abstraction. 27 | */ 28 | class CairoSurface { 29 | public: 30 | virtual ~CairoSurface() = default; 31 | 32 | /** 33 | * @returns The cairo context. 34 | */ 35 | virtual cairo_t *getContext() = 0; 36 | 37 | /** 38 | * Flush and display on screen. 39 | */ 40 | virtual void flush() = 0; 41 | }; 42 | 43 | #endif // WINDOW_SYSTEM_CAIRO_SURFACE_H_ 44 | -------------------------------------------------------------------------------- /src/window-system/x11-cairo-surface.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2011 - 2022 José Expósito 3 | * 4 | * This file is part of Touchégg. 5 | * 6 | * Touchégg is free software: you can redistribute it and/or modify it under the 7 | * terms of the GNU General Public License as published by the Free Software 8 | * Foundation, either version 3 of the License, or (at your option) any later 9 | * version. 10 | * 11 | * Touchégg is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * Touchégg. If not, see . 17 | */ 18 | #ifndef WINDOW_SYSTEM_X11_CAIRO_SURFACE_H_ 19 | #define WINDOW_SYSTEM_X11_CAIRO_SURFACE_H_ 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | #include "window-system/cairo-surface.h" 26 | 27 | /** 28 | * X11 cairo surface. 29 | */ 30 | class X11CairoSurface : public CairoSurface { 31 | public: 32 | explicit X11CairoSurface(Display *display); 33 | ~X11CairoSurface(); 34 | cairo_t *getContext() override; 35 | void flush() override; 36 | 37 | private: 38 | /** 39 | * X11 connection. 40 | */ 41 | Display *display; 42 | 43 | /** 44 | * X11 window where the animation is drawn. 45 | */ 46 | Window window = None; 47 | 48 | /** 49 | * Cairo surface and context for the window. 50 | */ 51 | cairo_surface_t *windowSurface = nullptr; 52 | cairo_t *windowContext = nullptr; 53 | 54 | /** 55 | * Cairo surface and context to draw in memory. 56 | */ 57 | cairo_surface_t *bufferSurface = nullptr; 58 | cairo_t *bufferContext = nullptr; 59 | }; 60 | 61 | #endif // WINDOW_SYSTEM_X11_CAIRO_SURFACE_H_ 62 | --------------------------------------------------------------------------------