diff --git a/src/linux/server/keyboard.cpp b/src/linux/server/keyboard.cpp index f1635a90..98d5b78d 100644 --- a/src/linux/server/keyboard.cpp +++ b/src/linux/server/keyboard.cpp @@ -91,33 +91,52 @@ int open_event_device(int index) { return -1; } -int grab_first_keyboard() { +std::vector grab_keyboards() { + auto fds = std::vector(); for (auto i = 0; i < EVDEV_MINORS; ++i) { const auto fd = open_event_device(i); if (fd >= 0) { if (is_keyboard(fd) && wait_until_keys_released(fd) && - grab_keyboard(fd, true)) - return fd; - ::close(fd); + grab_keyboard(fd, true)) { + fds.push_back(fd); + } + else { + ::close(fd); + } } } - return -1; + return fds; } -void release_keyboard(int fd) { - if (fd >= 0) { - grab_keyboard(fd, false); - ::close(fd); - } +void release_keyboards(const std::vector& fds) { + for (auto fd : fds) + if (fd >= 0) { + grab_keyboard(fd, false); + ::close(fd); + } } -bool read_event(int fd, int* type, int* code, int* value) { - auto ev = input_event{ }; - if (!read_all(fd, reinterpret_cast(&ev), sizeof(input_event))) - return false; - *type = ev.type; - *code = ev.code; - *value = ev.value; - return true; +bool read_event(const std::vector& fds, int* type, int* code, int* value) { + auto rfds = fd_set{ }; + FD_ZERO(&rfds); + auto max_fd = 0; + for (auto fd : fds) { + max_fd = std::max(max_fd, fd); + FD_SET(fd, &rfds); + } + + if (::select(max_fd + 1, &rfds, nullptr, nullptr, nullptr) > 0) + for (auto fd : fds) + if (FD_ISSET(fd, &rfds)) { + auto ev = input_event{ }; + if (!read_all(fd, reinterpret_cast(&ev), sizeof(input_event))) + return false; + *type = ev.type; + *code = ev.code; + *value = ev.value; + return true; + } + + return false; } diff --git a/src/linux/server/keyboard.h b/src/linux/server/keyboard.h index 8072d75d..bfce2faf 100644 --- a/src/linux/server/keyboard.h +++ b/src/linux/server/keyboard.h @@ -1,5 +1,7 @@ #pragma once -int grab_first_keyboard(); -void release_keyboard(int fd); -bool read_event(int fd, int* type, int* code, int* value); +#include + +std::vector grab_keyboards(); +void release_keyboards(const std::vector& fds); +bool read_event(const std::vector& fds, int* type, int* code, int* value); diff --git a/src/linux/server/main.cpp b/src/linux/server/main.cpp index e6eb8397..e2c2fe98 100644 --- a/src/linux/server/main.cpp +++ b/src/linux/server/main.cpp @@ -18,8 +18,8 @@ int main() { const auto stage = read_config(ipc_fd); if (stage) { - const auto event_fd = grab_first_keyboard(); - if (event_fd >= 0) { + const auto event_fds = grab_keyboards(); + if (!event_fds.empty()) { const auto uinput_fd = create_uinput_keyboard(uinput_keyboard_name); if (uinput_fd >= 0) { // main loop @@ -28,7 +28,7 @@ int main() { auto type = 0; auto code = 0; auto value = 0; - if (!read_event(event_fd, &type, &code, &value)) + if (!read_event(event_fds, &type, &code, &value)) break; // let client update configuration @@ -54,7 +54,7 @@ int main() { } destroy_uinput_keyboard(uinput_fd); } - release_keyboard(event_fd); + release_keyboards(event_fds); } } shutdown_ipc(ipc_fd);