diff --git a/src/device_controller/keyboard/linux/keyboard_capturer.cpp b/src/device_controller/keyboard/linux/keyboard_capturer.cpp index 2d84ce3..8739de3 100644 --- a/src/device_controller/keyboard/linux/keyboard_capturer.cpp +++ b/src/device_controller/keyboard/linux/keyboard_capturer.cpp @@ -11,10 +11,28 @@ namespace crossdesk { static OnKeyAction g_on_key_action = nullptr; static void* g_user_ptr = nullptr; +static KeySym NormalizeKeySym(KeySym key_sym) { + if (key_sym >= XK_a && key_sym <= XK_z) { + return key_sym - XK_a + XK_A; + } + return key_sym; +} + static int KeyboardEventHandler(Display* display, XEvent* event) { + (void)display; if (event->xkey.type == KeyPress || event->xkey.type == KeyRelease) { - KeySym keySym = XLookupKeysym(&event->xkey, 0); - int key_code = XKeysymToKeycode(display, keySym); + KeySym key_sym = NormalizeKeySym(XLookupKeysym(&event->xkey, 0)); + auto key_it = x11KeySymToVkCode.find(static_cast(key_sym)); + if (key_it == x11KeySymToVkCode.end()) { + key_sym = NormalizeKeySym(XLookupKeysym(&event->xkey, 1)); + key_it = x11KeySymToVkCode.find(static_cast(key_sym)); + } + + if (key_it == x11KeySymToVkCode.end()) { + return 0; + } + + int key_code = key_it->second; bool is_key_down = (event->xkey.type == KeyPress); if (g_on_key_action) { @@ -135,4 +153,4 @@ int KeyboardCapturer::SendKeyboardCommand(int key_code, bool is_down) { } return 0; } -} // namespace crossdesk \ No newline at end of file +} // namespace crossdesk diff --git a/src/device_controller/keyboard/mac/keyboard_capturer.cpp b/src/device_controller/keyboard/mac/keyboard_capturer.cpp index 6ca9b60..f570a9c 100644 --- a/src/device_controller/keyboard/mac/keyboard_capturer.cpp +++ b/src/device_controller/keyboard/mac/keyboard_capturer.cpp @@ -10,6 +10,7 @@ static void* g_user_ptr = nullptr; CGEventRef eventCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void* userInfo) { + (void)proxy; if (!g_on_key_action) { return event; } @@ -20,84 +21,72 @@ CGEventRef eventCallback(CGEventTapProxy proxy, CGEventType type, return event; } - int vk_code = 0; - if (type == kCGEventKeyDown || type == kCGEventKeyUp) { CGKeyCode key_code = static_cast( CGEventGetIntegerValueField(event, kCGKeyboardEventKeycode)); - if (CGKeyCodeToVkCode.find(key_code) != CGKeyCodeToVkCode.end()) { - g_on_key_action(CGKeyCodeToVkCode[key_code], type == kCGEventKeyDown, - g_user_ptr); + auto key_it = CGKeyCodeToVkCode.find(key_code); + if (key_it != CGKeyCodeToVkCode.end()) { + g_on_key_action(key_it->second, type == kCGEventKeyDown, g_user_ptr); } } else if (type == kCGEventFlagsChanged) { CGEventFlags current_flags = CGEventGetFlags(event); CGKeyCode key_code = static_cast( CGEventGetIntegerValueField(event, kCGKeyboardEventKeycode)); + auto key_it = CGKeyCodeToVkCode.find(key_code); + if (key_it == CGKeyCodeToVkCode.end()) { + return nullptr; + } + const int vk_code = key_it->second; // caps lock bool caps_lock_state = (current_flags & kCGEventFlagMaskAlphaShift) != 0; if (caps_lock_state != keyboard_capturer->caps_lock_flag_) { keyboard_capturer->caps_lock_flag_ = caps_lock_state; - if (keyboard_capturer->caps_lock_flag_) { - g_on_key_action(CGKeyCodeToVkCode[key_code], true, g_user_ptr); - } else { - g_on_key_action(CGKeyCodeToVkCode[key_code], false, g_user_ptr); - } + g_on_key_action(vk_code, keyboard_capturer->caps_lock_flag_, g_user_ptr); } // shift bool shift_state = (current_flags & kCGEventFlagMaskShift) != 0; if (shift_state != keyboard_capturer->shift_flag_) { keyboard_capturer->shift_flag_ = shift_state; - if (keyboard_capturer->shift_flag_) { - g_on_key_action(CGKeyCodeToVkCode[key_code], true, g_user_ptr); - } else { - g_on_key_action(CGKeyCodeToVkCode[key_code], false, g_user_ptr); - } + g_on_key_action(vk_code, keyboard_capturer->shift_flag_, g_user_ptr); } // control bool control_state = (current_flags & kCGEventFlagMaskControl) != 0; if (control_state != keyboard_capturer->control_flag_) { keyboard_capturer->control_flag_ = control_state; - if (keyboard_capturer->control_flag_) { - g_on_key_action(CGKeyCodeToVkCode[key_code], true, g_user_ptr); - } else { - g_on_key_action(CGKeyCodeToVkCode[key_code], false, g_user_ptr); - } + g_on_key_action(vk_code, keyboard_capturer->control_flag_, g_user_ptr); } // option bool option_state = (current_flags & kCGEventFlagMaskAlternate) != 0; if (option_state != keyboard_capturer->option_flag_) { keyboard_capturer->option_flag_ = option_state; - if (keyboard_capturer->option_flag_) { - g_on_key_action(CGKeyCodeToVkCode[key_code], true, g_user_ptr); - } else { - g_on_key_action(CGKeyCodeToVkCode[key_code], false, g_user_ptr); - } + g_on_key_action(vk_code, keyboard_capturer->option_flag_, g_user_ptr); } // command bool command_state = (current_flags & kCGEventFlagMaskCommand) != 0; if (command_state != keyboard_capturer->command_flag_) { keyboard_capturer->command_flag_ = command_state; - if (keyboard_capturer->command_flag_) { - g_on_key_action(CGKeyCodeToVkCode[key_code], true, g_user_ptr); - } else { - g_on_key_action(CGKeyCodeToVkCode[key_code], false, g_user_ptr); - } + g_on_key_action(vk_code, keyboard_capturer->command_flag_, g_user_ptr); } } return nullptr; } -KeyboardCapturer::KeyboardCapturer() {} +KeyboardCapturer::KeyboardCapturer() + : event_tap_(nullptr), run_loop_source_(nullptr) {} -KeyboardCapturer::~KeyboardCapturer() {} +KeyboardCapturer::~KeyboardCapturer() { Unhook(); } int KeyboardCapturer::Hook(OnKeyAction on_key_action, void* user_ptr) { + if (event_tap_) { + return 0; + } + g_on_key_action = on_key_action; g_user_ptr = user_ptr; @@ -115,10 +104,24 @@ int KeyboardCapturer::Hook(OnKeyAction on_key_action, void* user_ptr) { run_loop_source_ = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, event_tap_, 0); + if (!run_loop_source_) { + LOG_ERROR("CFMachPortCreateRunLoopSource failed"); + CFRelease(event_tap_); + event_tap_ = nullptr; + return -1; + } CFRunLoopAddSource(CFRunLoopGetCurrent(), run_loop_source_, kCFRunLoopCommonModes); + const CGEventFlags current_flags = + CGEventSourceFlagsState(kCGEventSourceStateCombinedSessionState); + caps_lock_flag_ = (current_flags & kCGEventFlagMaskAlphaShift) != 0; + shift_flag_ = (current_flags & kCGEventFlagMaskShift) != 0; + control_flag_ = (current_flags & kCGEventFlagMaskControl) != 0; + option_flag_ = (current_flags & kCGEventFlagMaskAlternate) != 0; + command_flag_ = (current_flags & kCGEventFlagMaskCommand) != 0; + CGEventTapEnable(event_tap_, true); return 0; } @@ -170,9 +173,12 @@ int KeyboardCapturer::SendKeyboardCommand(int key_code, bool is_down) { if (vkCodeToCGKeyCode.find(key_code) != vkCodeToCGKeyCode.end()) { CGKeyCode cg_key_code = vkCodeToCGKeyCode[key_code]; CGEventRef event = CGEventCreateKeyboardEvent(NULL, cg_key_code, is_down); - CGEventRef clearFlags = - CGEventCreateKeyboardEvent(NULL, (CGKeyCode)0, true); - CGEventSetFlags(clearFlags, 0); + if (!event) { + LOG_ERROR("CGEventCreateKeyboardEvent failed"); + return -1; + } + + CGEventSetFlags(event, 0); CGEventPost(kCGHIDEventTap, event); CFRelease(event); @@ -188,4 +194,4 @@ int KeyboardCapturer::SendKeyboardCommand(int key_code, bool is_down) { return 0; } -} // namespace crossdesk \ No newline at end of file +} // namespace crossdesk diff --git a/src/device_controller/keyboard/mac/keyboard_capturer.h b/src/device_controller/keyboard/mac/keyboard_capturer.h index cb61cdb..3220835 100644 --- a/src/device_controller/keyboard/mac/keyboard_capturer.h +++ b/src/device_controller/keyboard/mac/keyboard_capturer.h @@ -24,8 +24,8 @@ class KeyboardCapturer : public DeviceController { virtual int SendKeyboardCommand(int key_code, bool is_down); private: - CFMachPortRef event_tap_; - CFRunLoopSourceRef run_loop_source_; + CFMachPortRef event_tap_ = nullptr; + CFRunLoopSourceRef run_loop_source_ = nullptr; public: bool caps_lock_flag_ = false; @@ -36,4 +36,4 @@ class KeyboardCapturer : public DeviceController { int fn_key_code_ = 0x3F; }; } // namespace crossdesk -#endif \ No newline at end of file +#endif diff --git a/src/device_controller/keyboard_converter.h b/src/device_controller/keyboard_converter.h index b2b4bdb..54616c5 100644 --- a/src/device_controller/keyboard_converter.h +++ b/src/device_controller/keyboard_converter.h @@ -73,13 +73,13 @@ std::map vkCodeToCGKeyCode = { {0x20, 0x31}, // Space {0x08, 0x33}, // Backspace {0x09, 0x30}, // Tab - {0x2C, 0x74}, // Print Screen + {0x2C, 0x69}, // Print Screen(F13) {0x2D, 0x72}, // Insert {0x2E, 0x75}, // Delete {0x24, 0x73}, // Home {0x23, 0x77}, // End - {0x21, 0x79}, // Page Up - {0x22, 0x7A}, // Page Down + {0x21, 0x74}, // Page Up + {0x22, 0x79}, // Page Down // arrow keys {0x25, 0x7B}, // Left Arrow @@ -191,13 +191,13 @@ std::map CGKeyCodeToVkCode = { {0x31, 0x20}, // Space {0x33, 0x08}, // Backspace {0x30, 0x09}, // Tab - {0x74, 0x2C}, // Print Screen + {0x69, 0x2C}, // Print Screen(F13) {0x72, 0x2D}, // Insert {0x75, 0x2E}, // Delete {0x73, 0x24}, // Home {0x77, 0x23}, // End - {0x79, 0x21}, // Page Up - {0x7A, 0x22}, // Page Down + {0x74, 0x21}, // Page Up + {0x79, 0x22}, // Page Down // arrow keys {0x7B, 0x25}, // Left Arrow @@ -326,21 +326,21 @@ std::map vkCodeToX11KeySym = { {0x28, 0xFF54}, // Down Arrow // numpad - {0x60, 0x0030}, // Numpad 0 - {0x61, 0x0031}, // Numpad 1 - {0x62, 0x0032}, // Numpad 2 - {0x63, 0x0033}, // Numpad 3 - {0x64, 0x0034}, // Numpad 4 - {0x65, 0x0035}, // Numpad 5 - {0x66, 0x0036}, // Numpad 6 - {0x67, 0x0037}, // Numpad 7 - {0x68, 0x0038}, // Numpad 8 - {0x69, 0x0039}, // Numpad 9 - {0x6E, 0x003A}, // Numpad . - {0x6F, 0x002F}, // Numpad / - {0x6A, 0x002A}, // Numpad * - {0x6D, 0x002D}, // Numpad - - {0x6B, 0x002B}, // Numpad + + {0x60, 0xFFB0}, // Numpad 0 + {0x61, 0xFFB1}, // Numpad 1 + {0x62, 0xFFB2}, // Numpad 2 + {0x63, 0xFFB3}, // Numpad 3 + {0x64, 0xFFB4}, // Numpad 4 + {0x65, 0xFFB5}, // Numpad 5 + {0x66, 0xFFB6}, // Numpad 6 + {0x67, 0xFFB7}, // Numpad 7 + {0x68, 0xFFB8}, // Numpad 8 + {0x69, 0xFFB9}, // Numpad 9 + {0x6E, 0xFFAE}, // Numpad . + {0x6F, 0xFFAF}, // Numpad / + {0x6A, 0xFFAA}, // Numpad * + {0x6D, 0xFFAD}, // Numpad - + {0x6B, 0xFFAB}, // Numpad + // symbol keys {0xBA, 0x003B}, // ; (Semicolon) @@ -454,21 +454,21 @@ std::map x11KeySymToVkCode = { {0xFF54, 0x28}, // Down Arrow // numpad - {0x0030, 0x60}, // Numpad 0 - {0x0031, 0x61}, // Numpad 1 - {0x0032, 0x62}, // Numpad 2 - {0x0033, 0x63}, // Numpad 3 - {0x0034, 0x64}, // Numpad 4 - {0x0035, 0x65}, // Numpad 5 - {0x0036, 0x66}, // Numpad 6 - {0x0037, 0x67}, // Numpad 7 - {0x0038, 0x68}, // Numpad 8 - {0x0039, 0x69}, // Numpad 9 - {0x003A, 0x6E}, // Numpad . - {0x002F, 0x6F}, // Numpad / - {0x002A, 0x6A}, // Numpad * - {0x002D, 0x6D}, // Numpad - - {0x002B, 0x6B}, // Numpad + + {0xFFB0, 0x60}, // Numpad 0 + {0xFFB1, 0x61}, // Numpad 1 + {0xFFB2, 0x62}, // Numpad 2 + {0xFFB3, 0x63}, // Numpad 3 + {0xFFB4, 0x64}, // Numpad 4 + {0xFFB5, 0x65}, // Numpad 5 + {0xFFB6, 0x66}, // Numpad 6 + {0xFFB7, 0x67}, // Numpad 7 + {0xFFB8, 0x68}, // Numpad 8 + {0xFFB9, 0x69}, // Numpad 9 + {0xFFAE, 0x6E}, // Numpad . + {0xFFAF, 0x6F}, // Numpad / + {0xFFAA, 0x6A}, // Numpad * + {0xFFAD, 0x6D}, // Numpad - + {0xFFAB, 0x6B}, // Numpad + // symbol keys {0x003B, 0xBA}, // ; (Semicolon) @@ -557,13 +557,13 @@ std::map cgKeyCodeToX11KeySym = { {0x31, 0x0020}, // Space {0x33, 0xFF08}, // Backspace {0x30, 0xFF09}, // Tab - {0x74, 0xFF15}, // Print Screen + {0x69, 0xFF15}, // Print Screen(F13) {0x72, 0xFF63}, // Insert {0x75, 0xFFFF}, // Delete {0x73, 0xFF50}, // Home {0x77, 0xFF57}, // End - {0x79, 0xFF55}, // Page Up - {0x7A, 0xFF56}, // Page Down + {0x74, 0xFF55}, // Page Up + {0x79, 0xFF56}, // Page Down // arrow keys {0x7B, 0xFF51}, // Left Arrow @@ -572,21 +572,21 @@ std::map cgKeyCodeToX11KeySym = { {0x7D, 0xFF54}, // Down Arrow // numpad - {0x52, 0x0030}, // Numpad 0 - {0x53, 0x0031}, // Numpad 1 - {0x54, 0x0032}, // Numpad 2 - {0x55, 0x0033}, // Numpad 3 - {0x56, 0x0034}, // Numpad 4 - {0x57, 0x0035}, // Numpad 5 - {0x58, 0x0036}, // Numpad 6 - {0x59, 0x0037}, // Numpad 7 - {0x5B, 0x0038}, // Numpad 8 - {0x5C, 0x0039}, // Numpad 9 - {0x41, 0x003A}, // Numpad . - {0x4B, 0x002F}, // Numpad / - {0x43, 0x002A}, // Numpad * - {0x4E, 0x002D}, // Numpad - - {0x45, 0x002B}, // Numpad + + {0x52, 0xFFB0}, // Numpad 0 + {0x53, 0xFFB1}, // Numpad 1 + {0x54, 0xFFB2}, // Numpad 2 + {0x55, 0xFFB3}, // Numpad 3 + {0x56, 0xFFB4}, // Numpad 4 + {0x57, 0xFFB5}, // Numpad 5 + {0x58, 0xFFB6}, // Numpad 6 + {0x59, 0xFFB7}, // Numpad 7 + {0x5B, 0xFFB8}, // Numpad 8 + {0x5C, 0xFFB9}, // Numpad 9 + {0x41, 0xFFAE}, // Numpad . + {0x4B, 0xFFAF}, // Numpad / + {0x43, 0xFFAA}, // Numpad * + {0x4E, 0xFFAD}, // Numpad - + {0x45, 0xFFAB}, // Numpad + // symbol keys {0x29, 0x003B}, // ; (Semicolon) @@ -683,13 +683,13 @@ std::map x11KeySymToCgKeyCode = { {0x0020, 0x31}, // Space {0xFF08, 0x33}, // Backspace {0xFF09, 0x30}, // Tab - {0xFF15, 0x74}, // Print Screen + {0xFF15, 0x69}, // Print Screen(F13) {0xFF63, 0x72}, // Insert {0xFFFF, 0x75}, // Delete {0xFF50, 0x73}, // Home {0xFF57, 0x77}, // End - {0xFF55, 0x79}, // Page Up - {0xFF56, 0x7A}, // Page Down + {0xFF55, 0x74}, // Page Up + {0xFF56, 0x79}, // Page Down // arrow keys {0xFF51, 0x7B}, // Left Arrow @@ -698,21 +698,21 @@ std::map x11KeySymToCgKeyCode = { {0xFF54, 0x7D}, // Down Arrow // numpad - {0x0030, 0x52}, // Numpad 0 - {0x0031, 0x53}, // Numpad 1 - {0x0032, 0x54}, // Numpad 2 - {0x0033, 0x55}, // Numpad 3 - {0x0034, 0x56}, // Numpad 4 - {0x0035, 0x57}, // Numpad 5 - {0x0036, 0x58}, // Numpad 6 - {0x0037, 0x59}, // Numpad 7 - {0x0038, 0x5B}, // Numpad 8 - {0x0039, 0x5C}, // Numpad 9 - {0x003A, 0x41}, // Numpad . - {0x002F, 0x4B}, // Numpad / - {0x002A, 0x43}, // Numpad * - {0x002D, 0x4E}, // Numpad - - {0x002B, 0x45}, // Numpad + + {0xFFB0, 0x52}, // Numpad 0 + {0xFFB1, 0x53}, // Numpad 1 + {0xFFB2, 0x54}, // Numpad 2 + {0xFFB3, 0x55}, // Numpad 3 + {0xFFB4, 0x56}, // Numpad 4 + {0xFFB5, 0x57}, // Numpad 5 + {0xFFB6, 0x58}, // Numpad 6 + {0xFFB7, 0x59}, // Numpad 7 + {0xFFB8, 0x5B}, // Numpad 8 + {0xFFB9, 0x5C}, // Numpad 9 + {0xFFAE, 0x41}, // Numpad . + {0xFFAF, 0x4B}, // Numpad / + {0xFFAA, 0x43}, // Numpad * + {0xFFAD, 0x4E}, // Numpad - + {0xFFAB, 0x45}, // Numpad + // symbol keys {0x003B, 0x29}, // ; (Semicolon) @@ -739,4 +739,4 @@ std::map x11KeySymToCgKeyCode = { {0xFFEC, 0x36}, // Right Command }; } // namespace crossdesk -#endif \ No newline at end of file +#endif diff --git a/src/gui/render.cpp b/src/gui/render.cpp index 93d0833..3f12abd 100644 --- a/src/gui/render.cpp +++ b/src/gui/render.cpp @@ -734,7 +734,7 @@ int Render::StartKeyboardCapturer() { LOG_INFO("Start keyboard capturer"); } - return 0; + return keyboard_capturer_init_ret; } int Render::StopKeyboardCapturer() { @@ -1018,8 +1018,9 @@ void Render::UpdateInteractions() { if (start_keyboard_capturer_ && focus_on_stream_window_) { if (!keyboard_capturer_is_started_) { - StartKeyboardCapturer(); - keyboard_capturer_is_started_ = true; + if (StartKeyboardCapturer() == 0) { + keyboard_capturer_is_started_ = true; + } } } else if (keyboard_capturer_is_started_) { StopKeyboardCapturer();