From c261b6582c8e900dc49b0afb9c3071c9c910eefc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3f=20Marussy?= Date: Mon, 14 Dec 2020 19:49:28 +0100 Subject: [PATCH 1/5] Cleanup in InputDevice --- src/logid/InputDevice.cpp | 4 +++- src/logid/InputDevice.h | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/logid/InputDevice.cpp b/src/logid/InputDevice.cpp index 30b448b..cc36e3b 100644 --- a/src/logid/InputDevice.cpp +++ b/src/logid/InputDevice.cpp @@ -54,8 +54,10 @@ InputDevice::InputDevice(const char* name) int err = libevdev_uinput_create_from_device(device, LIBEVDEV_UINPUT_OPEN_MANAGED, &ui_device); - if(err != 0) + if(err != 0) { + libevdev_free(device); throw std::system_error(-err, std::generic_category()); + } } InputDevice::~InputDevice() diff --git a/src/logid/InputDevice.h b/src/logid/InputDevice.h index 8815d05..d5e5a47 100644 --- a/src/logid/InputDevice.h +++ b/src/logid/InputDevice.h @@ -20,6 +20,7 @@ #define LOGID_INPUTDEVICE_H #include +#include extern "C" { From 911e91eeebf72417d081e2b0f7e3d4c6db83c37b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3f=20Marussy?= Date: Mon, 14 Dec 2020 19:49:51 +0100 Subject: [PATCH 2/5] Enable fewer EV_KEY events in InputDevice Fixes #166 Starting with systemd 247 (?), desktop environments fail to recognize the virtual input device if it has too many enabled libinput events. It seems like KEY_ROTATE_LOCK_TOGGLE as the highest enabled event is a good limit. This is the highest evdev event mapped by xkb, so the usefulness higher events is limited, anyways. --- src/logid/InputDevice.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/logid/InputDevice.cpp b/src/logid/InputDevice.cpp index cc36e3b..644b907 100644 --- a/src/logid/InputDevice.cpp +++ b/src/logid/InputDevice.cpp @@ -45,7 +45,9 @@ InputDevice::InputDevice(const char* name) ///TODO: Is it really a good idea to enable all events? libevdev_enable_event_type(device, EV_KEY); - for(unsigned int i = 0; i < KEY_CNT; i++) + // KEY_ROTATE_LOCK_TOGGLE is the highest key mapped by + // /usr/share/X11/xkb/keycodes/evdev + for(unsigned int i = 0; i <= KEY_ROTATE_LOCK_TOGGLE; i++) libevdev_enable_event_code(device, EV_KEY, i, nullptr); libevdev_enable_event_type(device, EV_REL); for(unsigned int i = 0; i < REL_CNT; i++) From f8eb77cad7b3326b15c4a24729071304f9c8e236 Mon Sep 17 00:00:00 2001 From: max Date: Mon, 14 Dec 2020 20:02:44 +0100 Subject: [PATCH 3/5] Register keys for keypress only when needed there seems to be an issue that with too many registered events some window manager cannot recognize the device as input device with systemd 247. PixlOne#166 --- src/logid/InputDevice.cpp | 19 +++++++++++++------ src/logid/InputDevice.h | 1 + src/logid/actions/KeypressAction.cpp | 2 ++ 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/logid/InputDevice.cpp b/src/logid/InputDevice.cpp index 644b907..9fdd333 100644 --- a/src/logid/InputDevice.cpp +++ b/src/logid/InputDevice.cpp @@ -43,12 +43,7 @@ InputDevice::InputDevice(const char* name) device = libevdev_new(); libevdev_set_name(device, name); - ///TODO: Is it really a good idea to enable all events? libevdev_enable_event_type(device, EV_KEY); - // KEY_ROTATE_LOCK_TOGGLE is the highest key mapped by - // /usr/share/X11/xkb/keycodes/evdev - for(unsigned int i = 0; i <= KEY_ROTATE_LOCK_TOGGLE; i++) - libevdev_enable_event_code(device, EV_KEY, i, nullptr); libevdev_enable_event_type(device, EV_REL); for(unsigned int i = 0; i < REL_CNT; i++) libevdev_enable_event_code(device, EV_REL, i, nullptr); @@ -68,6 +63,18 @@ InputDevice::~InputDevice() libevdev_free(device); } +void InputDevice::registerKey(uint code) +{ + libevdev_enable_event_code(device, EV_KEY, code, nullptr); + int err = libevdev_uinput_create_from_device(device, + LIBEVDEV_UINPUT_OPEN_MANAGED, &ui_device); + + if(err != 0) { + libevdev_free(device); + throw std::system_error(-err, std::generic_category()); + } +} + void InputDevice::moveAxis(uint axis, int movement) { _sendEvent(EV_REL, axis, movement); @@ -123,4 +130,4 @@ void InputDevice::_sendEvent(uint type, uint code, int value) { libevdev_uinput_write_event(ui_device, type, code, value); libevdev_uinput_write_event(ui_device, EV_SYN, SYN_REPORT, 0); -} \ No newline at end of file +} diff --git a/src/logid/InputDevice.h b/src/logid/InputDevice.h index d5e5a47..5bd1eee 100644 --- a/src/logid/InputDevice.h +++ b/src/logid/InputDevice.h @@ -44,6 +44,7 @@ namespace logid explicit InputDevice(const char *name); ~InputDevice(); + void registerKey(uint code); void moveAxis(uint axis, int movement); void pressKey(uint code); void releaseKey(uint code); diff --git a/src/logid/actions/KeypressAction.cpp b/src/logid/actions/KeypressAction.cpp index da097cc..a71546b 100644 --- a/src/logid/actions/KeypressAction.cpp +++ b/src/logid/actions/KeypressAction.cpp @@ -64,9 +64,11 @@ KeypressAction::Config::Config(Device* device, libconfig::Setting& config) : auto& key = keys[i]; if(key.isNumber()) { _keys.push_back(key); + virtual_input->registerKey(key); } else if(key.getType() == libconfig::Setting::TypeString) { try { _keys.push_back(virtual_input->toKeyCode(key)); + virtual_input->registerKey(virtual_input->toKeyCode(key)); } catch(InputDevice::InvalidEventCode& e) { logPrintf(WARN, "Line %d: Invalid keycode %s, skipping." , key.getSourceLine(), key.c_str()); From 8280bc2505295c11f034de9230ef68d80e390785 Mon Sep 17 00:00:00 2001 From: max Date: Mon, 14 Dec 2020 22:10:07 +0100 Subject: [PATCH 4/5] Enable some keys by default and enable more on request if the user chooses to use such keys in the config. --- src/logid/InputDevice.cpp | 20 ++++++++++++++++++++ src/logid/InputDevice.h | 3 ++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/logid/InputDevice.cpp b/src/logid/InputDevice.cpp index 9fdd333..92ba479 100644 --- a/src/logid/InputDevice.cpp +++ b/src/logid/InputDevice.cpp @@ -44,6 +44,18 @@ InputDevice::InputDevice(const char* name) libevdev_set_name(device, name); libevdev_enable_event_type(device, EV_KEY); + for (unsigned int i = 0; i < KEY_CNT; i++) { + // Enable some keys which a normal keyboard should have + // by default, i.e. a-z, modifier keys and so on, see: + // /usr/include/linux/input-event-codes.h + if (i < 128) { + registered_keys[i] = true; + libevdev_enable_event_code(device, EV_KEY, i, nullptr); + } else { + registered_keys[i] = false; + } + } + libevdev_enable_event_type(device, EV_REL); for(unsigned int i = 0; i < REL_CNT; i++) libevdev_enable_event_code(device, EV_REL, i, nullptr); @@ -65,6 +77,12 @@ InputDevice::~InputDevice() void InputDevice::registerKey(uint code) { + if (registered_keys[code]) { + return; + } + + libevdev_uinput_destroy(ui_device); + libevdev_enable_event_code(device, EV_KEY, code, nullptr); int err = libevdev_uinput_create_from_device(device, LIBEVDEV_UINPUT_OPEN_MANAGED, &ui_device); @@ -73,6 +91,8 @@ void InputDevice::registerKey(uint code) libevdev_free(device); throw std::system_error(-err, std::generic_category()); } + + registered_keys[code] = true; } void InputDevice::moveAxis(uint axis, int movement) diff --git a/src/logid/InputDevice.h b/src/logid/InputDevice.h index 5bd1eee..4846a15 100644 --- a/src/logid/InputDevice.h +++ b/src/logid/InputDevice.h @@ -58,6 +58,7 @@ namespace logid static uint _toEventCode(uint type, const std::string& name); + bool registered_keys[KEY_CNT]; libevdev* device; libevdev_uinput* ui_device{}; }; @@ -65,4 +66,4 @@ namespace logid extern std::unique_ptr virtual_input; } -#endif //LOGID_INPUTDEVICE_H \ No newline at end of file +#endif //LOGID_INPUTDEVICE_H From 15de10344a9f5080eaecb2fea91e78e837e9aed4 Mon Sep 17 00:00:00 2001 From: max Date: Tue, 15 Dec 2020 12:26:52 +0100 Subject: [PATCH 5/5] In error case set device and ui_device to nullptr --- src/logid/InputDevice.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/logid/InputDevice.cpp b/src/logid/InputDevice.cpp index 92ba479..a97daf8 100644 --- a/src/logid/InputDevice.cpp +++ b/src/logid/InputDevice.cpp @@ -89,6 +89,8 @@ void InputDevice::registerKey(uint code) if(err != 0) { libevdev_free(device); + device = nullptr; + ui_device = nullptr; throw std::system_error(-err, std::generic_category()); }