From 09abcaaf4fa389bf850f6ab0cb8cfc0289b02bab Mon Sep 17 00:00:00 2001 From: houmain Date: Sun, 24 Jan 2021 16:05:38 +0100 Subject: [PATCH] Verbose output for linux/server --- CMakeLists.txt | 1 + src/linux/client/Settings.cpp | 2 +- src/linux/client/main.cpp | 7 +- src/linux/server/GrabbedKeyboards.cpp | 100 +++++++++++++++---------- src/linux/server/Settings.cpp | 1 + src/linux/server/main.cpp | 103 ++++++++++++++++++-------- src/linux/server/output.h | 4 + 7 files changed, 143 insertions(+), 75 deletions(-) create mode 100644 src/linux/server/output.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 7f7369c1..4a1b2932 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,6 +61,7 @@ if(NOT WIN32) src/linux/server/ipc.h src/linux/server/GrabbedKeyboards.cpp src/linux/server/GrabbedKeyboards.h + src/linux/server/output.h src/linux/server/main.cpp src/linux/server/uinput_keyboard.cpp src/linux/server/uinput_keyboard.h diff --git a/src/linux/client/Settings.cpp b/src/linux/client/Settings.cpp index f4ca9acb..a2d6725c 100644 --- a/src/linux/client/Settings.cpp +++ b/src/linux/client/Settings.cpp @@ -13,7 +13,7 @@ bool interpret_commandline(Settings& settings, int argc, char* argv[]) { return false; settings.config_file_path = argv[i]; } - if (argument == "-v" || argument == "--verbose") { + else if (argument == "-v" || argument == "--verbose") { settings.verbose = true; } else { diff --git a/src/linux/client/main.cpp b/src/linux/client/main.cpp index 439ec51f..9ef28750 100644 --- a/src/linux/client/main.cpp +++ b/src/linux/client/main.cpp @@ -1,11 +1,10 @@ +#include "output.h" #include "ipc.h" #include "FocusedWindow.h" #include "Settings.h" #include "ConfigFile.h" #include "config/Config.h" -#include "output.h" -#include #include #include @@ -69,9 +68,8 @@ int main(int argc, char* argv[]) { // send configuration verbose("sending configuration to keymapperd"); if (send_config(ipc_fd, config_file.config())) { - verbose("entering update loop"); - // main loop + verbose("entering update loop"); auto active_override_set = -1; for (;;) { // update configuration, reset on success @@ -121,5 +119,6 @@ int main(int argc, char* argv[]) { } } shutdown_ipc(ipc_fd); + verbose("---------------"); } } diff --git a/src/linux/server/GrabbedKeyboards.cpp b/src/linux/server/GrabbedKeyboards.cpp index 693b4040..b55dbafa 100644 --- a/src/linux/server/GrabbedKeyboards.cpp +++ b/src/linux/server/GrabbedKeyboards.cpp @@ -1,4 +1,5 @@ +#include "output.h" #include "GrabbedKeyboards.h" #include #include @@ -112,7 +113,7 @@ namespace { } bool read_event(const std::vector& fds, int cancel_fd, - int* type, int* code, int* value) { + int* type, int* code, int* value, bool* cancelled) { auto rfds = fd_set{ }; FD_ZERO(&rfds); @@ -130,8 +131,10 @@ namespace { if (::select(max_fd + 1, &rfds, nullptr, nullptr, nullptr) == -1) return false; - if (cancel_fd >= 0 && FD_ISSET(cancel_fd, &rfds)) - return false; + if (cancel_fd >= 0 && FD_ISSET(cancel_fd, &rfds)) { + *cancelled = true; + return false; + } for (auto fd : fds) if (FD_ISSET(fd, &rfds)) { @@ -157,13 +160,10 @@ class GrabbedKeyboards { public: ~GrabbedKeyboards() { - for (auto keyboard_fd : m_grabbed_keyboard_fds) { - grab_event_device(keyboard_fd, false); - ::close(keyboard_fd); - } + for (auto event_id = 0; event_id < EVDEV_MINORS; ++event_id) + release_keyboard(event_id); - if (m_device_monitor_fd >= 0) - ::close(m_device_monitor_fd); + release_device_monitor(); } int device_monitor_fd() const { @@ -177,56 +177,75 @@ class GrabbedKeyboards { bool initialize(const char* ignore_device_name) { m_ignore_device_name = ignore_device_name; m_event_fds.resize(EVDEV_MINORS, -1); - reset_device_monitor(); - return update(); + update(); + return true; + } + + void release_device_monitor() { + if (m_device_monitor_fd >= 0) + ::close(m_device_monitor_fd); } - void reset_device_monitor() { + void initialize_device_monitor() { if (m_device_monitor_fd >= 0) ::close(m_device_monitor_fd); m_device_monitor_fd = create_event_device_monitor(); } - bool update() { + void grab_keyboard(int event_id, int fd) { + auto& event_fd = m_event_fds[event_id]; + if (event_fd < 0) { + const auto device_name = get_device_name(fd); + if (device_name != m_ignore_device_name) { + verbose("grabbing device event%i '%s'", event_id, device_name.c_str()); + wait_until_keys_released(fd); + if (grab_event_device(fd, true)) { + event_fd = ::dup(fd); + } + else { + error("grabbing device failed"); + } + } + } + } + + void release_keyboard(int event_id) { + auto& event_fd = m_event_fds[event_id]; + if (event_fd >= 0) { + verbose("releasing device event%i", event_id); + grab_event_device(event_fd, false); + ::close(event_fd); + event_fd = -1; + } + } + + void update() { + verbose("updating device list"); + // update grabbed keyboards - auto event_id = 0; - for (auto& event_fd : m_event_fds) { + for (auto event_id = 0; event_id < EVDEV_MINORS; ++event_id) { const auto fd = open_event_device(event_id); if (fd >= 0 && is_keyboard(fd)) { // keyboard, grab new ones - if (event_fd < 0 && - get_device_name(fd) != m_ignore_device_name && - wait_until_keys_released(fd) && - grab_event_device(fd, true)) { - event_fd = ::dup(fd); - } + grab_keyboard(event_id, fd); } else { // no keyboard, ungrab previously grabbed - if (event_fd >= 0) { - grab_event_device(event_fd, false); - ::close(event_fd); - event_fd = -1; - } + release_keyboard(event_id); } if (fd >= 0) ::close(fd); - ++event_id; } // collect grabbed keyboard fds - auto grabbed_keyboard_fds = std::vector(); + m_grabbed_keyboard_fds.clear(); for (auto event_fd : m_event_fds) if (event_fd >= 0) - grabbed_keyboard_fds.push_back(event_fd); + m_grabbed_keyboard_fds.push_back(event_fd); - // check if they differ from previous list - if (grabbed_keyboard_fds != m_grabbed_keyboard_fds) { - m_grabbed_keyboard_fds = std::move(grabbed_keyboard_fds); - reset_device_monitor(); - return true; - } - return false; + // reset device monitor + release_device_monitor(); + initialize_device_monitor(); } }; @@ -243,12 +262,15 @@ GrabbedKeyboardsPtr grab_keyboards(const char* ignore_device_name) { bool read_keyboard_event(GrabbedKeyboards& keyboards, int* type, int* code, int* value) { for (;;) { + auto devices_changed = false; if (read_event(keyboards.grabbed_keyboard_fds(), - keyboards.device_monitor_fd(), type, code, value)) + keyboards.device_monitor_fd(), type, code, value, + &devices_changed)) return true; - // cancelled because a device was detected? - if (!keyboards.update()) + if (!devices_changed) return false; + + keyboards.update(); } } diff --git a/src/linux/server/Settings.cpp b/src/linux/server/Settings.cpp index 7588138b..5bf1cc64 100644 --- a/src/linux/server/Settings.cpp +++ b/src/linux/server/Settings.cpp @@ -35,6 +35,7 @@ void print_help_message(const char* argv0) { "\n" "Usage: %s [-options]\n" " -v, --verbose enable verbose output.\n" + " -h, --help print this help.\n" "\n" "All Rights Reserved.\n" "This program comes with absolutely no warranty.\n" diff --git a/src/linux/server/main.cpp b/src/linux/server/main.cpp index c0507084..f895cbba 100644 --- a/src/linux/server/main.cpp +++ b/src/linux/server/main.cpp @@ -1,14 +1,36 @@ +#include "output.h" #include "ipc.h" #include "GrabbedKeyboards.h" #include "uinput_keyboard.h" #include "Settings.h" #include "runtime/Stage.h" +#include #include namespace { const auto ipc_fifo_filename = "/tmp/keymapper"; const auto uinput_keyboard_name = "Keymapper"; + bool g_verbose_output = false; +} + +void error(const char* format, ...) { + va_list args; + va_start(args, format); + std::vfprintf(stderr, format, args); + va_end(args); + std::fputc('\n', stderr); +} + +void verbose(const char* format, ...) { + if (g_verbose_output) { + va_list args; + va_start(args, format); + std::vfprintf(stdout, format, args); + va_end(args); + std::fputc('\n', stdout); + std::fflush(stdout); + } } int main(int argc, char* argv[]) { @@ -18,54 +40,73 @@ int main(int argc, char* argv[]) { print_help_message(argv[0]); return 1; } + g_verbose_output = settings.verbose; // wait for client connection loop for (;;) { + verbose("waiting for keymapper to connect"); const auto ipc_fd = initialize_ipc(ipc_fifo_filename); - if (ipc_fd < 0) + if (ipc_fd < 0) { + error("initializing keymapper connection failed"); return 1; + } + verbose("reading configuration"); const auto stage = read_config(ipc_fd); if (stage) { // client connected + verbose("creating uinput keyboard '%s'", uinput_keyboard_name); const auto uinput_fd = create_uinput_keyboard(uinput_keyboard_name); - if (uinput_fd >= 0) { - const auto grabbed_keyboards = grab_keyboards(uinput_keyboard_name); - if (grabbed_keyboards) { - // main loop - for (;;) { - // wait for next key event - auto type = 0; - auto code = 0; - auto value = 0; - if (!read_keyboard_event(*grabbed_keyboards, &type, &code, &value)) - break; + if (uinput_fd < 0) { + error("creating uinput keyboard failed"); + return 1; + } + + const auto grabbed_keyboards = grab_keyboards(uinput_keyboard_name); + if (!grabbed_keyboards) { + error("initializing keyboard grabbing failed"); + return 1; + } - // let client update configuration - if (!stage->is_output_down()) - if (!update_ipc(ipc_fd, *stage)) - break; + // main loop + verbose("entering update loop"); + for (;;) { + // wait for next key event + auto type = 0; + auto code = 0; + auto value = 0; + if (!read_keyboard_event(*grabbed_keyboards, &type, &code, &value)) { + verbose("reading keyboard event failed"); + break; + } - if (type == EV_KEY) { - // translate key events - const auto event = KeyEvent{ - static_cast(code), - (value == 0 ? KeyState::Up : KeyState::Down), - }; - auto output = stage->apply_input(event); - send_key_sequence(uinput_fd, output); - stage->reuse_buffer(std::move(output)); - } - else if (type != EV_SYN && - type != EV_MSC) { - // forward other events - send_event(uinput_fd, type, code, value); - } + // let client update configuration + if (!stage->is_output_down()) + if (!update_ipc(ipc_fd, *stage)) { + verbose("connection to keymapper reset"); + break; } + + if (type == EV_KEY) { + // translate key events + const auto event = KeyEvent{ + static_cast(code), + (value == 0 ? KeyState::Up : KeyState::Down), + }; + auto output = stage->apply_input(event); + send_key_sequence(uinput_fd, output); + stage->reuse_buffer(std::move(output)); + } + else if (type != EV_SYN && + type != EV_MSC) { + // forward other events + send_event(uinput_fd, type, code, value); } } + verbose("destroying uinput keyboard"); destroy_uinput_keyboard(uinput_fd); } shutdown_ipc(ipc_fd); + verbose("---------------"); } } diff --git a/src/linux/server/output.h b/src/linux/server/output.h new file mode 100644 index 00000000..6b2ff0e9 --- /dev/null +++ b/src/linux/server/output.h @@ -0,0 +1,4 @@ +#pragma once + +void error(const char* format, ...); +void verbose(const char* format, ...);