From 81ac92fea48f87a1ae95b15e3cc7c42088ea1c43 Mon Sep 17 00:00:00 2001 From: Coffee2Code Date: Wed, 13 Feb 2019 22:52:44 +0100 Subject: [PATCH 1/2] End of day commit - Add .idea folder - Add cxxopts library (checkout @ v2.1.2) - Add and edit spdlog stuff in main.cpp in preparation of further refactoring - Moving input logic into its own namespace - Finish properly renaming the project --- .gitmodules | 3 + .idea/.name | 1 + .idea/codeStyles/codeStyleConfig.xml | 5 + .idea/encodings.xml | 4 + .idea/gebaar.iml | 2 + .idea/misc.xml | 7 + .idea/modules.xml | 8 + .idea/vcs.xml | 6 + CMakeLists.txt | 8 +- libs/cxxopts | 1 + src/io/input.cpp | 66 +++++++ src/io/input.hpp | 67 +++++++ src/main.cpp | 262 ++++++++++++++++----------- 13 files changed, 327 insertions(+), 113 deletions(-) create mode 100644 .gitmodules create mode 100644 .idea/.name create mode 100644 .idea/codeStyles/codeStyleConfig.xml create mode 100644 .idea/encodings.xml create mode 100644 .idea/gebaar.iml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml create mode 160000 libs/cxxopts create mode 100644 src/io/input.cpp create mode 100644 src/io/input.hpp diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..f402951 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "libs/cxxopts"] + path = libs/cxxopts + url = git@github.com:jarro2783/cxxopts.git diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..31854ac --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +gebaar diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..a55e7a1 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..15a15b2 --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/gebaar.iml b/.idea/gebaar.iml new file mode 100644 index 0000000..f08604b --- /dev/null +++ b/.idea/gebaar.iml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..8822db8 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..759731e --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 27f16de..f2d88ad 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,11 +1,11 @@ cmake_minimum_required(VERSION 3.13) -project(sxgd) +project(gebaar) set(CMAKE_VERBOSE_MAKEFILE on) set(CMAKE_EXPORT_COMPILE_COMMANDS on) set(CMAKE_CXX_STANDARD 17) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/") -add_executable(gebaard src/main.cpp) +add_executable(gebaard src/main.cpp src/io/input.cpp src/io/input.hpp) find_package(PkgConfig) if (PKG_CONFIG_FOUND) @@ -16,5 +16,5 @@ find_package(udev) find_package(spdlog) target_link_libraries(gebaard ${LIBINPUT_LIBRARIES} ${UDEV_LIBRARIES}) -target_include_directories(gebaard PUBLIC ${LIBINPUT_INCLUDE_DIRS} ${UDEV_INCLUDE_DIRS}) -target_compile_options(gebaard PUBLIC ${LIBINPUT_CFLAGS_OTHER} ${UDEV_CFLAGS_OTHER}) \ No newline at end of file +target_include_directories(gebaard PUBLIC ${LIBINPUT_INCLUDE_DIRS} ${UDEV_INCLUDE_DIRS} libs/cxxopts/include) +target_compile_options(gebaard PUBLIC ${LIBINPUT_CFLAGS_OTHER} ${UDEV_CFLAGS_OTHER}) diff --git a/libs/cxxopts b/libs/cxxopts new file mode 160000 index 0000000..9990f73 --- /dev/null +++ b/libs/cxxopts @@ -0,0 +1 @@ +Subproject commit 9990f73845d76106063536d7cd630ac15cb4a065 diff --git a/src/io/input.cpp b/src/io/input.cpp new file mode 100644 index 0000000..6bcf2fc --- /dev/null +++ b/src/io/input.cpp @@ -0,0 +1,66 @@ +/* + gebaar + Copyright (C) 2019 coffee2code + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "input.hpp" + +gebaar::io::Input::Input() +{ + gesture_swipe_event = {}; + logger = spdlog::get("logger"); +} + +void gebaar::io::Input::initialize_context() +{ + udev = udev_new(); + libinput = libinput_udev_create_context(&libinput_interface, nullptr, udev); + return libinput_udev_assign_seat(libinput, "seat0"); +} + +void gebaar::io::Input::handle_swipe_event_without_coords(libinput_event_gesture* gev, bool begin) +{ + if (begin) { + gesture_swipe_event.fingers = libinput_event_gesture_get_finger_count(gev); + } + else { + if (abs(gesture_swipe_event.x)>abs(gesture_swipe_event.y)) { + if (gesture_swipe_event.x<0) { + logger->info("{} Finger Swipe Left", swipe_event.fingers); + } + else { + logger->info("{} Finger Swipe Right", swipe_event.fingers); + } + } + else { + if (gesture_swipe_event.y<0) { + logger->info("{} Finger Swipe Up", swipe_event.fingers); + } + else { + logger->info("{} Finger Swipe Down", swipe_event.fingers); + } + } + gesture_swipe_event = {}; + } +} + +void gebaar::io::Input::handle_swipe_event_with_coords(libinput_event_gesture* gev) +{ + gesture_swipe_event.x += libinput_event_gesture_get_dx(gev); + gesture_swipe_event.y += libinput_event_gesture_get_dy(gev); +} + + diff --git a/src/io/input.hpp b/src/io/input.hpp new file mode 100644 index 0000000..aece425 --- /dev/null +++ b/src/io/input.hpp @@ -0,0 +1,67 @@ +/* + gebaar + Copyright (C) 2019 coffee2code + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef GEBAAR_INPUT_HPP +#define GEBAAR_INPUT_HPP + +#include +#include + +namespace gebaar::io { + struct gesture_swipe_event { + int fingers; + double x; + double y; + }; + + class Input { + public: + Input(); + + int initialize_context(); + + private: + shared_ptr logger; + struct libinput* libinput; + struct libinput_event* libinput_event; + struct udev* udev; + gesture_swipe_event gesture_swipe_event; + + static int open_restricted(const char* path, int flags, void* user_data) + { + int fd = open(path, flags); + return fd<0 ? -errno : fd; + } + + static void close_restricted(int fd, void* user_data) + { + close(fd); + } + + const static struct libinput_interface libinput_interface = { + .open_restricted = open_restricted, + .close_restricted = close_restricted, + }; + + void handle_swipe_event_without_coords(libinput_event_gesture* gev, bool begin); + + void handle_swipe_event_with_coords(libinput_event_gesture* gev); + }; +} + +#endif //GEBAAR_INPUT_HPP diff --git a/src/main.cpp b/src/main.cpp index 87e4b83..a8ad66a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,20 +1,21 @@ -// -// Gebaar -// Copyright (C) 2019 Coffee2Code -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// +/* + gebaar + Copyright (C) 2019 coffee2code + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + #include #include @@ -23,15 +24,22 @@ #include #include #include +#include +#include +#include using namespace std; -static int open_restricted(const char *path, int flags, void *user_data) { +shared_ptr logger; + +static int open_restricted(const char* path, int flags, void* user_data) +{ int fd = open(path, flags); - return fd < 0 ? -errno : fd; + return fd<0 ? -errno : fd; } -static void close_restricted(int fd, void *user_data) { +static void close_restricted(int fd, void* user_data) +{ close(fd); } @@ -40,103 +48,110 @@ const static struct libinput_interface interface = { .close_restricted = close_restricted, }; struct swipe_event { - int fingers; - double x; - double y; + int fingers; + double x; + double y; }; static swipe_event swipeEvent = {}; -static void handleSwipeEventWithoutCoords(libinput_event_gesture *gev, bool begin) { +static void handleSwipeEventWithoutCoords(libinput_event_gesture* gev, bool begin) +{ auto fingers = libinput_event_gesture_get_finger_count(gev); - if(begin) { + if (begin) { swipeEvent.fingers = fingers; - } else { + } + else { auto absX = abs(swipeEvent.x); auto absY = abs(swipeEvent.y); - if(absX > absY) { - if(swipeEvent.x < 0) { - spdlog::info("{} Finger Swipe Left", swipeEvent.fingers); - } else { - spdlog::info("{} Finger Swipe Right", swipeEvent.fingers); + if (absX>absY) { + if (swipeEvent.x<0) { + logger->debug("{} Finger Swipe Left", swipeEvent.fingers); + } + else { + logger->debug("{} Finger Swipe Right", swipeEvent.fingers); + } + } + else { + if (swipeEvent.y<0) { + logger->debug("{} Finger Swipe Up", swipeEvent.fingers); } - } else { - if(swipeEvent.y < 0) { - spdlog::info("{} Finger Swipe Up", swipeEvent.fingers); - } else { - spdlog::info("{} Finger Swipe Down", swipeEvent.fingers); + else { + logger->debug("{} Finger Swipe Down", swipeEvent.fingers); } } swipeEvent = {}; } } -static void handleSwipeEventWithCoords(libinput_event_gesture *gev) { +static void handleSwipeEventWithCoords(libinput_event_gesture* gev) +{ swipeEvent.x += libinput_event_gesture_get_dx(gev); swipeEvent.y += libinput_event_gesture_get_dy(gev); } -static int handleEvents(libinput *li) { - struct libinput_event *liEv; +static int handleEvents(libinput* li) +{ + struct libinput_event* liEv; libinput_dispatch(li); while ((liEv = libinput_get_event(li))) { switch (libinput_event_get_type(liEv)) { - case LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN: - handleSwipeEventWithoutCoords(libinput_event_get_gesture_event(liEv), true); - break; - case LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE: - handleSwipeEventWithCoords(libinput_event_get_gesture_event(liEv)); - break; - case LIBINPUT_EVENT_GESTURE_SWIPE_END: - handleSwipeEventWithoutCoords(libinput_event_get_gesture_event(liEv), false); - break; - case LIBINPUT_EVENT_NONE: - break; - case LIBINPUT_EVENT_DEVICE_ADDED: - break; - case LIBINPUT_EVENT_DEVICE_REMOVED: - break; - case LIBINPUT_EVENT_KEYBOARD_KEY: - break; - case LIBINPUT_EVENT_POINTER_MOTION: - break; - case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE: - break; - case LIBINPUT_EVENT_POINTER_BUTTON: - break; - case LIBINPUT_EVENT_POINTER_AXIS: - break; - case LIBINPUT_EVENT_TOUCH_DOWN: - break; - case LIBINPUT_EVENT_TOUCH_UP: - break; - case LIBINPUT_EVENT_TOUCH_MOTION: - break; - case LIBINPUT_EVENT_TOUCH_CANCEL: - break; - case LIBINPUT_EVENT_TOUCH_FRAME: - break; - case LIBINPUT_EVENT_TABLET_TOOL_AXIS: - break; - case LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY: - break; - case LIBINPUT_EVENT_TABLET_TOOL_TIP: - break; - case LIBINPUT_EVENT_TABLET_TOOL_BUTTON: - break; - case LIBINPUT_EVENT_TABLET_PAD_BUTTON: - break; - case LIBINPUT_EVENT_TABLET_PAD_RING: - break; - case LIBINPUT_EVENT_TABLET_PAD_STRIP: - break; - case LIBINPUT_EVENT_GESTURE_PINCH_BEGIN: - break; - case LIBINPUT_EVENT_GESTURE_PINCH_UPDATE: - break; - case LIBINPUT_EVENT_GESTURE_PINCH_END: - break; - case LIBINPUT_EVENT_SWITCH_TOGGLE: - break; + case LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN: + handleSwipeEventWithoutCoords(libinput_event_get_gesture_event(liEv), true); + break; + case LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE: + handleSwipeEventWithCoords(libinput_event_get_gesture_event(liEv)); + break; + case LIBINPUT_EVENT_GESTURE_SWIPE_END: + handleSwipeEventWithoutCoords(libinput_event_get_gesture_event(liEv), false); + break; + case LIBINPUT_EVENT_NONE: + break; + case LIBINPUT_EVENT_DEVICE_ADDED: + break; + case LIBINPUT_EVENT_DEVICE_REMOVED: + break; + case LIBINPUT_EVENT_KEYBOARD_KEY: + break; + case LIBINPUT_EVENT_POINTER_MOTION: + break; + case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE: + break; + case LIBINPUT_EVENT_POINTER_BUTTON: + break; + case LIBINPUT_EVENT_POINTER_AXIS: + break; + case LIBINPUT_EVENT_TOUCH_DOWN: + break; + case LIBINPUT_EVENT_TOUCH_UP: + break; + case LIBINPUT_EVENT_TOUCH_MOTION: + break; + case LIBINPUT_EVENT_TOUCH_CANCEL: + break; + case LIBINPUT_EVENT_TOUCH_FRAME: + break; + case LIBINPUT_EVENT_TABLET_TOOL_AXIS: + break; + case LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY: + break; + case LIBINPUT_EVENT_TABLET_TOOL_TIP: + break; + case LIBINPUT_EVENT_TABLET_TOOL_BUTTON: + break; + case LIBINPUT_EVENT_TABLET_PAD_BUTTON: + break; + case LIBINPUT_EVENT_TABLET_PAD_RING: + break; + case LIBINPUT_EVENT_TABLET_PAD_STRIP: + break; + case LIBINPUT_EVENT_GESTURE_PINCH_BEGIN: + break; + case LIBINPUT_EVENT_GESTURE_PINCH_UPDATE: + break; + case LIBINPUT_EVENT_GESTURE_PINCH_END: + break; + case LIBINPUT_EVENT_SWITCH_TOGGLE: + break; } libinput_event_destroy(liEv); @@ -144,42 +159,70 @@ static int handleEvents(libinput *li) { } } -static void mainLoop(libinput *li) { +static void mainLoop(libinput* li) +{ struct pollfd fds{}; fds.fd = libinput_get_fd(li); fds.events = POLLIN; fds.revents = 0; if (handleEvents(li)) { - spdlog::info("Handled already existing events"); + logger->info("Handled already existing events"); } - while (poll(&fds, 1, -1) > -1) { + while (poll(&fds, 1, -1)>-1) { handleEvents(li); } } -int main() { - uid_t userId = geteuid(); +int main(int argc, char* argv[]) +{ + /*uid_t userId = geteuid(); if (userId != 0) { spdlog::info("You have to run this as root! Exiting now..."); exit(EXIT_SUCCESS); + }*/ + + cxxopts::Options options("gebaard", "Gebaard Gestures Daemon"); + struct libinput* li; + struct libinput_event* liEv; + struct udev* ud; + bool debug_mode = false; + bool daemonize = false; + + options.add_options() + ("d,debug", "Debug Mode - Output to console", cxxopts::value(debug_mode)) + ("b,background", "Daemonize", cxxopts::value(daemonize)) + ("h,help", "Prints this help text"); + + auto result = options.parse(argc, argv); + spdlog::set_level(spdlog::level::info); + if (debug_mode) { + spdlog::set_level(spdlog::level::debug); + logger = spdlog::stdout_color_mt("logger"); + } + else { + logger = spdlog::syslog_logger_mt("logger", "gebaard"); + } + + logger->debug("Debug mode: {}", debug_mode); + + if (result.count("help")) { + std::cout << options.help() << std::endl; + exit(EXIT_SUCCESS); } - struct libinput *li; - struct libinput_event *liEv; - struct udev *ud; + ud = udev_new(); li = libinput_udev_create_context(&interface, nullptr, ud); libinput_udev_assign_seat(li, "seat0"); libinput_dispatch(li); bool deviceWithGestureSupportExists = false; - while ((liEv = libinput_get_event(li)) != nullptr) { - auto eventType = libinput_event_get_type(liEv); + while ((liEv = libinput_get_event(li))!=nullptr) { auto device = libinput_event_get_device(liEv); auto devName = libinput_device_get_name(device); if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_GESTURE)) { - spdlog::info("Found a device with gesture support: {}", devName); + logger->info("Found a device with gesture support: {}", devName); deviceWithGestureSupportExists = true; } @@ -189,8 +232,9 @@ int main() { if (deviceWithGestureSupportExists) { mainLoop(li); - } else { - spdlog::warn("No supported devices found, this won't work"); + } + else { + logger->warn("No supported devices found, this won't work"); } libinput_unref(li); From 24a61c4580f2f08dbfa39db1656c3e8c947e00e3 Mon Sep 17 00:00:00 2001 From: Coffee2Code Date: Thu, 14 Feb 2019 20:27:55 +0100 Subject: [PATCH 2/2] Working state commit - Add cxxtoml library (checkout @ v0.1.1) - Remove all spdlog references - Add configuration file support - Further compartmentalize input system - Add support for running commands - Add daemonizing mode --- .gitignore | 4 +- .gitmodules | 3 + .idea/vcs.xml | 1 + CMakeLists.txt | 6 +- libs/cpptoml | 1 + src/config/config.cpp | 71 +++++++++++ src/config/config.h | 53 +++++++++ src/daemonizer.cpp | 61 ++++++++++ src/daemonizer.h | 33 ++++++ src/io/input.cpp | 146 +++++++++++++++++++++-- src/io/{input.hpp => input.h} | 25 +++- src/main.cpp | 214 +++------------------------------- 12 files changed, 399 insertions(+), 219 deletions(-) create mode 160000 libs/cpptoml create mode 100644 src/config/config.cpp create mode 100644 src/config/config.h create mode 100644 src/daemonizer.cpp create mode 100644 src/daemonizer.h rename src/io/{input.hpp => input.h} (76%) diff --git a/.gitignore b/.gitignore index 4f54420..c24e01f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ -# Created by .ignore support plugin (hsz.mobi) +### Personal Testing Files +gebaard.toml + ### CMake template CMakeCache.txt CMakeFiles diff --git a/.gitmodules b/.gitmodules index f402951..1c2462a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "libs/cxxopts"] path = libs/cxxopts url = git@github.com:jarro2783/cxxopts.git +[submodule "libs/cpptoml"] + path = libs/cpptoml + url = git@github.com:skystrife/cpptoml.git diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 94a25f7..c2df53a 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -2,5 +2,6 @@ + \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index f2d88ad..dff7a92 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS on) set(CMAKE_CXX_STANDARD 17) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/") -add_executable(gebaard src/main.cpp src/io/input.cpp src/io/input.hpp) +add_executable(gebaard src/main.cpp src/io/input.cpp src/io/input.h src/config/config.cpp src/config/config.h src/daemonizer.cpp src/daemonizer.h) find_package(PkgConfig) if (PKG_CONFIG_FOUND) @@ -15,6 +15,6 @@ endif () find_package(udev) find_package(spdlog) -target_link_libraries(gebaard ${LIBINPUT_LIBRARIES} ${UDEV_LIBRARIES}) -target_include_directories(gebaard PUBLIC ${LIBINPUT_INCLUDE_DIRS} ${UDEV_INCLUDE_DIRS} libs/cxxopts/include) +target_link_libraries(gebaard ${LIBINPUT_LIBRARIES} ${UDEV_LIBRARIES} stdc++fs) +target_include_directories(gebaard PUBLIC ${LIBINPUT_INCLUDE_DIRS} ${UDEV_INCLUDE_DIRS} libs/cxxopts/include libs/cpptoml/include) target_compile_options(gebaard PUBLIC ${LIBINPUT_CFLAGS_OTHER} ${UDEV_CFLAGS_OTHER}) diff --git a/libs/cpptoml b/libs/cpptoml new file mode 160000 index 0000000..fededad --- /dev/null +++ b/libs/cpptoml @@ -0,0 +1 @@ +Subproject commit fededad7169e538ca47e11a9ee9251bc361a9a65 diff --git a/src/config/config.cpp b/src/config/config.cpp new file mode 100644 index 0000000..9317772 --- /dev/null +++ b/src/config/config.cpp @@ -0,0 +1,71 @@ +/* + gebaar + Copyright (C) 2019 coffee2code + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + + +#include +#include "config.h" + +bool gebaar::config::Config::find_config_file() +{ + auto true_path = std::filesystem::path(config_file_path); + return std::filesystem::exists(true_path); +} + +void gebaar::config::Config::load_config() +{ + if (find_home_folder()) { + if (find_config_file()) { + config = cpptoml::parse_file(std::filesystem::path(config_file_path)); + swipe_three_up_command = *config->get_qualified_as("commands.swipe.three.up"); + swipe_three_down_command = *config->get_qualified_as("commands.swipe.three.down"); + swipe_three_left_command = *config->get_qualified_as("commands.swipe.three.left"); + swipe_three_right_command = *config->get_qualified_as("commands.swipe.three.right"); + swipe_four_up_command = *config->get_qualified_as("commands.swipe.four.up"); + swipe_four_down_command = *config->get_qualified_as("commands.swipe.four.down"); + swipe_four_left_command = *config->get_qualified_as("commands.swipe.four.left"); + swipe_four_right_command = *config->get_qualified_as("commands.swipe.four.right"); + loaded = true; + } + } + +} + +bool gebaar::config::Config::find_home_folder() +{ + const char* temp_path; + temp_path = getenv("XDG_CONFIG_HOME"); + if (temp_path==nullptr) { + temp_path = getenv("HOME"); + if (temp_path==nullptr) { + temp_path = getpwuid(getuid())->pw_dir; + } + } + if (temp_path!=nullptr) { + config_file_path = temp_path; + config_file_path.append("/.config/gebaar/gebaard.toml"); + return true; + } + return false; +} + +gebaar::config::Config::Config() +{ + if (!loaded) { + load_config(); + } +} diff --git a/src/config/config.h b/src/config/config.h new file mode 100644 index 0000000..baa7c35 --- /dev/null +++ b/src/config/config.h @@ -0,0 +1,53 @@ +/* + gebaar + Copyright (C) 2019 coffee2code + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef GEBAAR_CONFIG_H +#define GEBAAR_CONFIG_H + +#include +#include +#include +#include + +namespace gebaar::config { + class Config { + public: + Config(); + + bool loaded = false; + + void load_config(); + + std::string swipe_four_up_command; + std::string swipe_four_down_command; + std::string swipe_four_left_command; + std::string swipe_four_right_command; + std::string swipe_three_up_command; + std::string swipe_three_down_command; + std::string swipe_three_left_command; + std::string swipe_three_right_command; + private: + bool find_config_file(); + + bool find_home_folder(); + + std::string config_file_path; + std::shared_ptr config; + }; +} +#endif //GEBAAR_CONFIG_H diff --git a/src/daemonizer.cpp b/src/daemonizer.cpp new file mode 100644 index 0000000..191c9f2 --- /dev/null +++ b/src/daemonizer.cpp @@ -0,0 +1,61 @@ +/* + gebaar + Copyright (C) 2019 coffee2code + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + + +#include "daemonizer.h" + + +bool gebaar::daemonizer::Daemonizer::daemonize() +{ + pid_t pid = 0; + pid = fork(); + if (pid<0) { + exit(EXIT_FAILURE); + } + if (pid>0) { + exit(EXIT_SUCCESS); + } + if (setsid()<0) { + // Boo. + } + signal(SIGCHLD, SIG_IGN); + signal(SIGTRAP, SIG_IGN); + pid = fork(); + if (pid<0) { + exit(EXIT_FAILURE); + } + if (pid>0) { + exit(EXIT_SUCCESS); + } + umask(0); + if ((chdir("/"))<0) { + return false; + } + close(STDOUT_FILENO); + close(STDIN_FILENO); + close(STDERR_FILENO); + if (getpid()!=getsid(getpid())) { + // + } + return true; + +} + +gebaar::daemonizer::Daemonizer::Daemonizer() = default; + +gebaar::daemonizer::Daemonizer::~Daemonizer() = default; diff --git a/src/daemonizer.h b/src/daemonizer.h new file mode 100644 index 0000000..ca60a15 --- /dev/null +++ b/src/daemonizer.h @@ -0,0 +1,33 @@ +/* + gebaar + Copyright (C) 2019 coffee2code + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +#include +#include +#include +#include + +#ifndef GEBAAR_DAEMONIZER_H +#define GEBAAR_DAEMONIZER_H +namespace gebaar::daemonizer { + class Daemonizer { + public: + Daemonizer(); + ~Daemonizer(); + bool daemonize(); + }; +} +#endif //GEBAAR_DAEMONIZER_H diff --git a/src/io/input.cpp b/src/io/input.cpp index 6bcf2fc..7c06486 100644 --- a/src/io/input.cpp +++ b/src/io/input.cpp @@ -16,19 +16,20 @@ along with this program. If not, see . */ -#include "input.hpp" +#include +#include "input.h" -gebaar::io::Input::Input() +gebaar::io::Input::Input(std::shared_ptr const& config_ptr) { + config = config_ptr; gesture_swipe_event = {}; - logger = spdlog::get("logger"); } -void gebaar::io::Input::initialize_context() +bool gebaar::io::Input::initialize_context() { udev = udev_new(); libinput = libinput_udev_create_context(&libinput_interface, nullptr, udev); - return libinput_udev_assign_seat(libinput, "seat0"); + return libinput_udev_assign_seat(libinput, "seat0")==0; } void gebaar::io::Input::handle_swipe_event_without_coords(libinput_event_gesture* gev, bool begin) @@ -39,18 +40,38 @@ void gebaar::io::Input::handle_swipe_event_without_coords(libinput_event_gesture else { if (abs(gesture_swipe_event.x)>abs(gesture_swipe_event.y)) { if (gesture_swipe_event.x<0) { - logger->info("{} Finger Swipe Left", swipe_event.fingers); + if (gesture_swipe_event.fingers==3) { + std::system(config->swipe_three_left_command.c_str()); + } + else if (gesture_swipe_event.fingers==4) { + std::system(config->swipe_four_left_command.c_str()); + } } else { - logger->info("{} Finger Swipe Right", swipe_event.fingers); + if (gesture_swipe_event.fingers==3) { + std::system(config->swipe_three_right_command.c_str()); + } + else if (gesture_swipe_event.fingers==4) { + std::system(config->swipe_four_right_command.c_str()); + } } } else { if (gesture_swipe_event.y<0) { - logger->info("{} Finger Swipe Up", swipe_event.fingers); + if (gesture_swipe_event.fingers==3) { + std::system(config->swipe_three_up_command.c_str()); + } + else if (gesture_swipe_event.fingers==4) { + std::system(config->swipe_four_up_command.c_str()); + } } else { - logger->info("{} Finger Swipe Down", swipe_event.fingers); + if (gesture_swipe_event.fingers==3) { + std::system(config->swipe_three_down_command.c_str()); + } + else if (gesture_swipe_event.fingers==4) { + std::system(config->swipe_four_down_command.c_str()); + } } } gesture_swipe_event = {}; @@ -63,4 +84,111 @@ void gebaar::io::Input::handle_swipe_event_with_coords(libinput_event_gesture* g gesture_swipe_event.y += libinput_event_gesture_get_dy(gev); } +bool gebaar::io::Input::initialize() +{ + initialize_context(); + return find_gesture_device(); +} + +void gebaar::io::Input::start_loop() +{ + struct pollfd fds{}; + fds.fd = libinput_get_fd(libinput); + fds.events = POLLIN; + fds.revents = 0; + + while (poll(&fds, 1, -1)>-1) { + handle_event(); + } +} + +gebaar::io::Input::~Input() +{ + libinput_unref(libinput); +} + +bool gebaar::io::Input::find_gesture_device() +{ + bool device_found = false; + while ((libinput_event = libinput_get_event(libinput))!=nullptr) { + auto device = libinput_event_get_device(libinput_event); + if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_GESTURE)) { + device_found = true; + } + + libinput_event_destroy(libinput_event); + libinput_dispatch(libinput); + } + return device_found; +} + +void gebaar::io::Input::handle_event() +{ + libinput_dispatch(libinput); + while ((libinput_event = libinput_get_event(libinput))) { + switch (libinput_event_get_type(libinput_event)) { + case LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN: + handle_swipe_event_without_coords(libinput_event_get_gesture_event(libinput_event), true); + break; + case LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE: + handle_swipe_event_with_coords(libinput_event_get_gesture_event(libinput_event)); + break; + case LIBINPUT_EVENT_GESTURE_SWIPE_END: + handle_swipe_event_without_coords(libinput_event_get_gesture_event(libinput_event), false); + break; + case LIBINPUT_EVENT_NONE: + break; + case LIBINPUT_EVENT_DEVICE_ADDED: + break; + case LIBINPUT_EVENT_DEVICE_REMOVED: + break; + case LIBINPUT_EVENT_KEYBOARD_KEY: + break; + case LIBINPUT_EVENT_POINTER_MOTION: + break; + case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE: + break; + case LIBINPUT_EVENT_POINTER_BUTTON: + break; + case LIBINPUT_EVENT_POINTER_AXIS: + break; + case LIBINPUT_EVENT_TOUCH_DOWN: + break; + case LIBINPUT_EVENT_TOUCH_UP: + break; + case LIBINPUT_EVENT_TOUCH_MOTION: + break; + case LIBINPUT_EVENT_TOUCH_CANCEL: + break; + case LIBINPUT_EVENT_TOUCH_FRAME: + break; + case LIBINPUT_EVENT_TABLET_TOOL_AXIS: + break; + case LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY: + break; + case LIBINPUT_EVENT_TABLET_TOOL_TIP: + break; + case LIBINPUT_EVENT_TABLET_TOOL_BUTTON: + break; + case LIBINPUT_EVENT_TABLET_PAD_BUTTON: + break; + case LIBINPUT_EVENT_TABLET_PAD_RING: + break; + case LIBINPUT_EVENT_TABLET_PAD_STRIP: + break; + case LIBINPUT_EVENT_GESTURE_PINCH_BEGIN: + break; + case LIBINPUT_EVENT_GESTURE_PINCH_UPDATE: + break; + case LIBINPUT_EVENT_GESTURE_PINCH_END: + break; + case LIBINPUT_EVENT_SWITCH_TOGGLE: + break; + } + + libinput_event_destroy(libinput_event); + libinput_dispatch(libinput); + } +} + diff --git a/src/io/input.hpp b/src/io/input.h similarity index 76% rename from src/io/input.hpp rename to src/io/input.h index aece425..1775f01 100644 --- a/src/io/input.hpp +++ b/src/io/input.h @@ -20,7 +20,9 @@ #define GEBAAR_INPUT_HPP #include -#include +#include +#include +#include "../config/config.h" namespace gebaar::io { struct gesture_swipe_event { @@ -31,16 +33,25 @@ namespace gebaar::io { class Input { public: - Input(); + Input(std::shared_ptr const& config_ptr); - int initialize_context(); + ~Input(); + + bool initialize(); + + void start_loop(); private: - shared_ptr logger; + std::shared_ptr config; + struct libinput* libinput; struct libinput_event* libinput_event; struct udev* udev; - gesture_swipe_event gesture_swipe_event; + struct gesture_swipe_event gesture_swipe_event; + + bool initialize_context(); + + bool find_gesture_device(); static int open_restricted(const char* path, int flags, void* user_data) { @@ -53,11 +64,13 @@ namespace gebaar::io { close(fd); } - const static struct libinput_interface libinput_interface = { + constexpr static struct libinput_interface libinput_interface = { .open_restricted = open_restricted, .close_restricted = close_restricted, }; + void handle_event(); + void handle_swipe_event_without_coords(libinput_event_gesture* gev, bool begin); void handle_swipe_event_with_coords(libinput_event_gesture* gev); diff --git a/src/main.cpp b/src/main.cpp index a8ad66a..9a61700 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -17,226 +17,40 @@ */ -#include #include -#include -#include -#include -#include -#include -#include -#include #include +#include "config/config.h" +#include "io/input.h" +#include "daemonizer.h" -using namespace std; - -shared_ptr logger; - -static int open_restricted(const char* path, int flags, void* user_data) -{ - int fd = open(path, flags); - return fd<0 ? -errno : fd; -} - -static void close_restricted(int fd, void* user_data) -{ - close(fd); -} - -const static struct libinput_interface interface = { - .open_restricted = open_restricted, - .close_restricted = close_restricted, -}; -struct swipe_event { - int fingers; - double x; - double y; -}; -static swipe_event swipeEvent = {}; - -static void handleSwipeEventWithoutCoords(libinput_event_gesture* gev, bool begin) -{ - auto fingers = libinput_event_gesture_get_finger_count(gev); - if (begin) { - swipeEvent.fingers = fingers; - } - else { - auto absX = abs(swipeEvent.x); - auto absY = abs(swipeEvent.y); - if (absX>absY) { - if (swipeEvent.x<0) { - logger->debug("{} Finger Swipe Left", swipeEvent.fingers); - } - else { - logger->debug("{} Finger Swipe Right", swipeEvent.fingers); - } - } - else { - if (swipeEvent.y<0) { - logger->debug("{} Finger Swipe Up", swipeEvent.fingers); - } - else { - logger->debug("{} Finger Swipe Down", swipeEvent.fingers); - } - } - swipeEvent = {}; - } -} - -static void handleSwipeEventWithCoords(libinput_event_gesture* gev) -{ - swipeEvent.x += libinput_event_gesture_get_dx(gev); - swipeEvent.y += libinput_event_gesture_get_dy(gev); -} - -static int handleEvents(libinput* li) -{ - struct libinput_event* liEv; - libinput_dispatch(li); - while ((liEv = libinput_get_event(li))) { - switch (libinput_event_get_type(liEv)) { - case LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN: - handleSwipeEventWithoutCoords(libinput_event_get_gesture_event(liEv), true); - break; - case LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE: - handleSwipeEventWithCoords(libinput_event_get_gesture_event(liEv)); - break; - case LIBINPUT_EVENT_GESTURE_SWIPE_END: - handleSwipeEventWithoutCoords(libinput_event_get_gesture_event(liEv), false); - break; - case LIBINPUT_EVENT_NONE: - break; - case LIBINPUT_EVENT_DEVICE_ADDED: - break; - case LIBINPUT_EVENT_DEVICE_REMOVED: - break; - case LIBINPUT_EVENT_KEYBOARD_KEY: - break; - case LIBINPUT_EVENT_POINTER_MOTION: - break; - case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE: - break; - case LIBINPUT_EVENT_POINTER_BUTTON: - break; - case LIBINPUT_EVENT_POINTER_AXIS: - break; - case LIBINPUT_EVENT_TOUCH_DOWN: - break; - case LIBINPUT_EVENT_TOUCH_UP: - break; - case LIBINPUT_EVENT_TOUCH_MOTION: - break; - case LIBINPUT_EVENT_TOUCH_CANCEL: - break; - case LIBINPUT_EVENT_TOUCH_FRAME: - break; - case LIBINPUT_EVENT_TABLET_TOOL_AXIS: - break; - case LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY: - break; - case LIBINPUT_EVENT_TABLET_TOOL_TIP: - break; - case LIBINPUT_EVENT_TABLET_TOOL_BUTTON: - break; - case LIBINPUT_EVENT_TABLET_PAD_BUTTON: - break; - case LIBINPUT_EVENT_TABLET_PAD_RING: - break; - case LIBINPUT_EVENT_TABLET_PAD_STRIP: - break; - case LIBINPUT_EVENT_GESTURE_PINCH_BEGIN: - break; - case LIBINPUT_EVENT_GESTURE_PINCH_UPDATE: - break; - case LIBINPUT_EVENT_GESTURE_PINCH_END: - break; - case LIBINPUT_EVENT_SWITCH_TOGGLE: - break; - } - - libinput_event_destroy(liEv); - libinput_dispatch(li); - } -} - -static void mainLoop(libinput* li) -{ - struct pollfd fds{}; - fds.fd = libinput_get_fd(li); - fds.events = POLLIN; - fds.revents = 0; - - if (handleEvents(li)) { - logger->info("Handled already existing events"); - } - - while (poll(&fds, 1, -1)>-1) { - handleEvents(li); - } -} +gebaar::io::Input* input; int main(int argc, char* argv[]) { - /*uid_t userId = geteuid(); - if (userId != 0) { - spdlog::info("You have to run this as root! Exiting now..."); - exit(EXIT_SUCCESS); - }*/ + cxxopts::Options options(argv[0], "Gebaard Gestures Daemon"); - cxxopts::Options options("gebaard", "Gebaard Gestures Daemon"); - struct libinput* li; - struct libinput_event* liEv; - struct udev* ud; - bool debug_mode = false; - bool daemonize = false; + bool should_daemonize = false; options.add_options() - ("d,debug", "Debug Mode - Output to console", cxxopts::value(debug_mode)) - ("b,background", "Daemonize", cxxopts::value(daemonize)) + ("b,background", "Daemonize", cxxopts::value(should_daemonize)) ("h,help", "Prints this help text"); auto result = options.parse(argc, argv); - spdlog::set_level(spdlog::level::info); - if (debug_mode) { - spdlog::set_level(spdlog::level::debug); - logger = spdlog::stdout_color_mt("logger"); - } - else { - logger = spdlog::syslog_logger_mt("logger", "gebaard"); - } - - logger->debug("Debug mode: {}", debug_mode); if (result.count("help")) { std::cout << options.help() << std::endl; exit(EXIT_SUCCESS); } - ud = udev_new(); - li = libinput_udev_create_context(&interface, nullptr, ud); - libinput_udev_assign_seat(li, "seat0"); - libinput_dispatch(li); - bool deviceWithGestureSupportExists = false; - while ((liEv = libinput_get_event(li))!=nullptr) { - auto device = libinput_event_get_device(liEv); - auto devName = libinput_device_get_name(device); - - if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_GESTURE)) { - logger->info("Found a device with gesture support: {}", devName); - deviceWithGestureSupportExists = true; - } - - libinput_event_destroy(liEv); - libinput_dispatch(li); - } - - if (deviceWithGestureSupportExists) { - mainLoop(li); + if (should_daemonize) { + auto *daemonizer = new gebaar::daemonizer::Daemonizer(); + daemonizer->daemonize(); } - else { - logger->warn("No supported devices found, this won't work"); + std::shared_ptr config = std::make_shared(); + input = new gebaar::io::Input(config); + if (input->initialize()) { + input->start_loop(); } - libinput_unref(li); return 0; }