Skip to content

Commit

Permalink
Verbose output for linux/server
Browse files Browse the repository at this point in the history
  • Loading branch information
houmain committed Jan 24, 2021
1 parent bd0d20c commit 09abcaa
Show file tree
Hide file tree
Showing 7 changed files with 143 additions and 75 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/linux/client/Settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
7 changes: 3 additions & 4 deletions src/linux/client/main.cpp
Original file line number Diff line number Diff line change
@@ -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 <string>
#include <cstdarg>
#include <unistd.h>

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -121,5 +119,6 @@ int main(int argc, char* argv[]) {
}
}
shutdown_ipc(ipc_fd);
verbose("---------------");
}
}
100 changes: 61 additions & 39 deletions src/linux/server/GrabbedKeyboards.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@

#include "output.h"
#include "GrabbedKeyboards.h"
#include <vector>
#include <cstdio>
Expand Down Expand Up @@ -112,7 +113,7 @@ namespace {
}

bool read_event(const std::vector<int>& 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);
Expand All @@ -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)) {
Expand All @@ -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 {
Expand All @@ -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<int>();
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();
}
};

Expand All @@ -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();
}
}
1 change: 1 addition & 0 deletions src/linux/server/Settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
103 changes: 72 additions & 31 deletions src/linux/server/main.cpp
Original file line number Diff line number Diff line change
@@ -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 <cstdarg>
#include <linux/uinput.h>

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[]) {
Expand All @@ -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<KeyCode>(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<KeyCode>(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("---------------");
}
}
4 changes: 4 additions & 0 deletions src/linux/server/output.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#pragma once

void error(const char* format, ...);
void verbose(const char* format, ...);

0 comments on commit 09abcaa

Please sign in to comment.