From 440331d319526c204247d05b845a1da1b656a850 Mon Sep 17 00:00:00 2001 From: Jonathan White Date: Sun, 3 Nov 2019 21:26:19 -0500 Subject: [PATCH] Revert "Remove Carbon from Mac Auto-Type (#3347)" This reverts commit ce1f19cacc229c2097189620288f50ee512f6c29. --- src/autotype/mac/AutoTypeMac.cpp | 595 ++++++++++++------------- src/autotype/mac/AutoTypeMac.h | 19 +- src/autotype/mac/AutoTypeMacKeyCodes.h | 160 ------- src/autotype/mac/CMakeLists.txt | 2 +- src/gui/macutils/AppKit.h | 6 +- src/gui/macutils/AppKitImpl.h | 3 - src/gui/macutils/AppKitImpl.mm | 32 +- src/gui/macutils/MacUtils.cpp | 14 +- src/gui/macutils/MacUtils.h | 4 +- 9 files changed, 310 insertions(+), 525 deletions(-) delete mode 100644 src/autotype/mac/AutoTypeMacKeyCodes.h diff --git a/src/autotype/mac/AutoTypeMac.cpp b/src/autotype/mac/AutoTypeMac.cpp index c88ae6fca..56a07acca 100644 --- a/src/autotype/mac/AutoTypeMac.cpp +++ b/src/autotype/mac/AutoTypeMac.cpp @@ -17,43 +17,47 @@ */ #include "AutoTypeMac.h" -#include "AutoTypeMacKeyCodes.h" #include "gui/macutils/MacUtils.h" +#include + +#define HOTKEY_ID 1 #define MAX_WINDOW_TITLE_LENGTH 1024 #define INVALID_KEYCODE 0xFFFF AutoTypePlatformMac::AutoTypePlatformMac() - : m_globalMonitor(nullptr) + : m_hotkeyRef(nullptr) + , m_hotkeyId({ 'kpx2', HOTKEY_ID }) { + EventTypeSpec eventSpec; + eventSpec.eventClass = kEventClassKeyboard; + eventSpec.eventKind = kEventHotKeyPressed; + + ::InstallApplicationEventHandler(AutoTypePlatformMac::hotkeyHandler, 1, &eventSpec, this, nullptr); } -/** - * Request accessibility permissions required for keyboard control - * - * @return true on success - */ +// +// Keepassx requires mac os 10.7 +// bool AutoTypePlatformMac::isAvailable() { - return macUtils()->enableAccessibility(); + return true; } -/** - * Get a list of the currently open window titles - * - * @return list of window titles - */ +// +// Get list of visible window titles +// see: Quartz Window Services +// QStringList AutoTypePlatformMac::windowTitles() { QStringList list; - auto windowList = ::CGWindowListCopyWindowInfo( - kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements, kCGNullWindowID); - if (windowList) { - auto count = ::CFArrayGetCount(windowList); + CFArrayRef windowList = ::CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements, kCGNullWindowID); + if (windowList != nullptr) { + CFIndex count = ::CFArrayGetCount(windowList); for (CFIndex i = 0; i < count; i++) { - auto window = static_cast(::CFArrayGetValueAtIndex(windowList, i)); + CFDictionaryRef window = static_cast(::CFArrayGetValueAtIndex(windowList, i)); if (windowLayer(window) != 0) { continue; } @@ -70,28 +74,24 @@ QStringList AutoTypePlatformMac::windowTitles() return list; } -/** - * Get active window ID - * - * @return window ID - */ +// +// Get active window process id +// WId AutoTypePlatformMac::activeWindow() { return macUtils()->activeWindow(); } -/** - * Get active window title - * - * @return window title - */ +// +// Get active window title +// see: Quartz Window Services +// QString AutoTypePlatformMac::activeWindowTitle() { QString title; - CFArrayRef windowList = ::CGWindowListCopyWindowInfo( - kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements, kCGNullWindowID); - if (windowList) { + CFArrayRef windowList = ::CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements, kCGNullWindowID); + if (windowList != nullptr) { CFIndex count = ::CFArrayGetCount(windowList); for (CFIndex i = 0; i < count; i++) { @@ -111,62 +111,41 @@ QString AutoTypePlatformMac::activeWindowTitle() return title; } -/** - * Register global hotkey using NS global event monitor. - * Note that this hotkey is not trapped and may trigger - * actions in the local application where it is issued. - * - * @param key key used for hotkey - * @param modifiers modifiers required in addition to key - * @return true on success - */ +// +// Register global hotkey +// bool AutoTypePlatformMac::registerGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers) { - auto nativeKeyCode = qtToNativeKeyCode(key); + uint16 nativeKeyCode = qtToNativeKeyCode(key); if (nativeKeyCode == INVALID_KEYCODE) { qWarning("Invalid key code"); return false; } - auto nativeModifiers = qtToNativeModifiers(modifiers); - m_globalMonitor = - macUtils()->addGlobalMonitor(nativeKeyCode, nativeModifiers, this, AutoTypePlatformMac::hotkeyHandler); + CGEventFlags nativeModifiers = qtToNativeModifiers(modifiers, false); + if (::RegisterEventHotKey(nativeKeyCode, nativeModifiers, m_hotkeyId, GetApplicationEventTarget(), 0, &m_hotkeyRef) != noErr) { + qWarning("Register hotkey failed"); + return false; + } + return true; } -/** - * Handle global hotkey presses by emitting the trigger signal - * - * @param userData pointer to AutoTypePlatform - */ -void AutoTypePlatformMac::hotkeyHandler(void* userData) -{ - auto* self = static_cast(userData); - emit self->globalShortcutTriggered(); -} - -/** - * Unregister a previously registered global hotkey - * - * @param key unused - * @param modifiers unused - */ +// +// Unregister global hotkey +// void AutoTypePlatformMac::unregisterGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers) { Q_UNUSED(key); Q_UNUSED(modifiers); - if (m_globalMonitor) { - macUtils()->removeGlobalMonitor(m_globalMonitor); - m_globalMonitor = nullptr; - } + + ::UnregisterEventHotKey(m_hotkeyRef); } -/** - * Unused - */ int AutoTypePlatformMac::platformEventFilter(void* event) { Q_UNUSED(event); Q_ASSERT(false); + return -1; } @@ -175,21 +154,17 @@ AutoTypeExecutor* AutoTypePlatformMac::createExecutor() return new AutoTypeExecutorMac(this); } -/** - * Raise the given window ID - * - * @return true on success - */ +// +// Activate window by process id +// bool AutoTypePlatformMac::raiseWindow(WId pid) { return macUtils()->raiseWindow(pid); } -/** - * Hide the KeePassXC window - * - * @return true on success - */ +// +// Activate last active window +// bool AutoTypePlatformMac::hideOwnWindow() { return macUtils()->hideOwnWindow(); @@ -203,293 +178,309 @@ bool AutoTypePlatformMac::raiseOwnWindow() return macUtils()->raiseOwnWindow(); } -/** - * Send provided character as key event to the active window - * - * @param ch unicode character - * @param isKeyDown whether the key is pressed - */ +// +// Send unicode character to active window +// see: Quartz Event Services +// void AutoTypePlatformMac::sendChar(const QChar& ch, bool isKeyDown) { - auto keyEvent = ::CGEventCreateKeyboardEvent(nullptr, 0, isKeyDown); - if (keyEvent) { - auto unicode = ch.unicode(); + CGEventRef keyEvent = ::CGEventCreateKeyboardEvent(nullptr, 0, isKeyDown); + if (keyEvent != nullptr) { + UniChar unicode = ch.unicode(); ::CGEventKeyboardSetUnicodeString(keyEvent, 1, &unicode); ::CGEventPost(kCGSessionEventTap, keyEvent); ::CFRelease(keyEvent); } } -/** - * Send provided Qt key as key event to the active window - * - * @param key Qt key code - * @param isKeyDown whether the key is pressed - * @param modifiers any modifiers to apply to key - */ -void AutoTypePlatformMac::sendKey(Qt::Key key, bool isKeyDown, Qt::KeyboardModifiers modifiers) +// +// Send key code to active window +// see: Quartz Event Services +// +void AutoTypePlatformMac::sendKey(Qt::Key key, bool isKeyDown, Qt::KeyboardModifiers modifiers = 0) { - auto keyCode = qtToNativeKeyCode(key); + uint16 keyCode = qtToNativeKeyCode(key); if (keyCode == INVALID_KEYCODE) { return; } - auto keyEvent = ::CGEventCreateKeyboardEvent(nullptr, keyCode, isKeyDown); - auto nativeModifiers = qtToNativeModifiers(modifiers); - if (keyEvent) { + CGEventRef keyEvent = ::CGEventCreateKeyboardEvent(nullptr, keyCode, isKeyDown); + CGEventFlags nativeModifiers = qtToNativeModifiers(modifiers, true); + if (keyEvent != nullptr) { ::CGEventSetFlags(keyEvent, nativeModifiers); ::CGEventPost(kCGSessionEventTap, keyEvent); ::CFRelease(keyEvent); } } -/** - * Translate Qt key to macOS key code provided by - * AutoTypeMacKeyCodes.h which are derived from - * legacy Carbon "HIToolbox/Events.h" - * - * @param key key to translate - * @returns macOS key code - */ -CGKeyCode AutoTypePlatformMac::qtToNativeKeyCode(Qt::Key key) +// +// Translate qt key code to mac os key code +// see: HIToolbox/Events.h +// +uint16 AutoTypePlatformMac::qtToNativeKeyCode(Qt::Key key) { switch (key) { - case Qt::Key_A: - return kVK_ANSI_A; - case Qt::Key_B: - return kVK_ANSI_B; - case Qt::Key_C: - return kVK_ANSI_C; - case Qt::Key_D: - return kVK_ANSI_D; - case Qt::Key_E: - return kVK_ANSI_E; - case Qt::Key_F: - return kVK_ANSI_F; - case Qt::Key_G: - return kVK_ANSI_G; - case Qt::Key_H: - return kVK_ANSI_H; - case Qt::Key_I: - return kVK_ANSI_I; - case Qt::Key_J: - return kVK_ANSI_J; - case Qt::Key_K: - return kVK_ANSI_K; - case Qt::Key_L: - return kVK_ANSI_L; - case Qt::Key_M: - return kVK_ANSI_M; - case Qt::Key_N: - return kVK_ANSI_N; - case Qt::Key_O: - return kVK_ANSI_O; - case Qt::Key_P: - return kVK_ANSI_P; - case Qt::Key_Q: - return kVK_ANSI_Q; - case Qt::Key_R: - return kVK_ANSI_R; - case Qt::Key_S: - return kVK_ANSI_S; - case Qt::Key_T: - return kVK_ANSI_T; - case Qt::Key_U: - return kVK_ANSI_U; - case Qt::Key_V: - return kVK_ANSI_V; - case Qt::Key_W: - return kVK_ANSI_W; - case Qt::Key_X: - return kVK_ANSI_X; - case Qt::Key_Y: - return kVK_ANSI_Y; - case Qt::Key_Z: - return kVK_ANSI_Z; + case Qt::Key_A: + return kVK_ANSI_A; + case Qt::Key_B: + return kVK_ANSI_B; + case Qt::Key_C: + return kVK_ANSI_C; + case Qt::Key_D: + return kVK_ANSI_D; + case Qt::Key_E: + return kVK_ANSI_E; + case Qt::Key_F: + return kVK_ANSI_F; + case Qt::Key_G: + return kVK_ANSI_G; + case Qt::Key_H: + return kVK_ANSI_H; + case Qt::Key_I: + return kVK_ANSI_I; + case Qt::Key_J: + return kVK_ANSI_J; + case Qt::Key_K: + return kVK_ANSI_K; + case Qt::Key_L: + return kVK_ANSI_L; + case Qt::Key_M: + return kVK_ANSI_M; + case Qt::Key_N: + return kVK_ANSI_N; + case Qt::Key_O: + return kVK_ANSI_O; + case Qt::Key_P: + return kVK_ANSI_P; + case Qt::Key_Q: + return kVK_ANSI_Q; + case Qt::Key_R: + return kVK_ANSI_R; + case Qt::Key_S: + return kVK_ANSI_S; + case Qt::Key_T: + return kVK_ANSI_T; + case Qt::Key_U: + return kVK_ANSI_U; + case Qt::Key_V: + return kVK_ANSI_V; + case Qt::Key_W: + return kVK_ANSI_W; + case Qt::Key_X: + return kVK_ANSI_X; + case Qt::Key_Y: + return kVK_ANSI_Y; + case Qt::Key_Z: + return kVK_ANSI_Z; - case Qt::Key_0: - return kVK_ANSI_0; - case Qt::Key_1: - return kVK_ANSI_1; - case Qt::Key_2: - return kVK_ANSI_2; - case Qt::Key_3: - return kVK_ANSI_3; - case Qt::Key_4: - return kVK_ANSI_4; - case Qt::Key_5: - return kVK_ANSI_5; - case Qt::Key_6: - return kVK_ANSI_6; - case Qt::Key_7: - return kVK_ANSI_7; - case Qt::Key_8: - return kVK_ANSI_8; - case Qt::Key_9: - return kVK_ANSI_9; + case Qt::Key_0: + return kVK_ANSI_0; + case Qt::Key_1: + return kVK_ANSI_1; + case Qt::Key_2: + return kVK_ANSI_2; + case Qt::Key_3: + return kVK_ANSI_3; + case Qt::Key_4: + return kVK_ANSI_4; + case Qt::Key_5: + return kVK_ANSI_5; + case Qt::Key_6: + return kVK_ANSI_6; + case Qt::Key_7: + return kVK_ANSI_7; + case Qt::Key_8: + return kVK_ANSI_8; + case Qt::Key_9: + return kVK_ANSI_9; - case Qt::Key_Equal: - return kVK_ANSI_Equal; - case Qt::Key_Minus: - return kVK_ANSI_Minus; - case Qt::Key_BracketRight: - return kVK_ANSI_RightBracket; - case Qt::Key_BracketLeft: - return kVK_ANSI_LeftBracket; - case Qt::Key_QuoteDbl: - return kVK_ANSI_Quote; - case Qt::Key_Semicolon: - return kVK_ANSI_Semicolon; - case Qt::Key_Backslash: - return kVK_ANSI_Backslash; - case Qt::Key_Comma: - return kVK_ANSI_Comma; - case Qt::Key_Slash: - return kVK_ANSI_Slash; - case Qt::Key_Period: - return kVK_ANSI_Period; + case Qt::Key_Equal: + return kVK_ANSI_Equal; + case Qt::Key_Minus: + return kVK_ANSI_Minus; + case Qt::Key_BracketRight: + return kVK_ANSI_RightBracket; + case Qt::Key_BracketLeft: + return kVK_ANSI_LeftBracket; + case Qt::Key_QuoteDbl: + return kVK_ANSI_Quote; + case Qt::Key_Semicolon: + return kVK_ANSI_Semicolon; + case Qt::Key_Backslash: + return kVK_ANSI_Backslash; + case Qt::Key_Comma: + return kVK_ANSI_Comma; + case Qt::Key_Slash: + return kVK_ANSI_Slash; + case Qt::Key_Period: + return kVK_ANSI_Period; - case Qt::Key_Shift: - return kVK_Shift; - case Qt::Key_Control: - return kVK_Command; - case Qt::Key_Backspace: - return kVK_Delete; - case Qt::Key_Tab: - case Qt::Key_Backtab: - return kVK_Tab; - case Qt::Key_Enter: - case Qt::Key_Return: - return kVK_Return; - case Qt::Key_CapsLock: - return kVK_CapsLock; - case Qt::Key_Escape: - return kVK_Escape; - case Qt::Key_Space: - return kVK_Space; - case Qt::Key_PageUp: - return kVK_PageUp; - case Qt::Key_PageDown: - return kVK_PageDown; - case Qt::Key_End: - return kVK_End; - case Qt::Key_Home: - return kVK_Home; - case Qt::Key_Left: - return kVK_LeftArrow; - case Qt::Key_Up: - return kVK_UpArrow; - case Qt::Key_Right: - return kVK_RightArrow; - case Qt::Key_Down: - return kVK_DownArrow; - case Qt::Key_Delete: - return kVK_ForwardDelete; - case Qt::Key_Help: - return kVK_Help; + case Qt::Key_Shift: + return kVK_Shift; + case Qt::Key_Control: + return kVK_Command; + case Qt::Key_Backspace: + return kVK_Delete; + case Qt::Key_Tab: + case Qt::Key_Backtab: + return kVK_Tab; + case Qt::Key_Enter: + case Qt::Key_Return: + return kVK_Return; + case Qt::Key_CapsLock: + return kVK_CapsLock; + case Qt::Key_Escape: + return kVK_Escape; + case Qt::Key_Space: + return kVK_Space; + case Qt::Key_PageUp: + return kVK_PageUp; + case Qt::Key_PageDown: + return kVK_PageDown; + case Qt::Key_End: + return kVK_End; + case Qt::Key_Home: + return kVK_Home; + case Qt::Key_Left: + return kVK_LeftArrow; + case Qt::Key_Up: + return kVK_UpArrow; + case Qt::Key_Right: + return kVK_RightArrow; + case Qt::Key_Down: + return kVK_DownArrow; + case Qt::Key_Delete: + return kVK_ForwardDelete; + case Qt::Key_Help: + return kVK_Help; - case Qt::Key_F1: - return kVK_F1; - case Qt::Key_F2: - return kVK_F2; - case Qt::Key_F3: - return kVK_F3; - case Qt::Key_F4: - return kVK_F4; - case Qt::Key_F5: - return kVK_F5; - case Qt::Key_F6: - return kVK_F6; - case Qt::Key_F7: - return kVK_F7; - case Qt::Key_F8: - return kVK_F8; - case Qt::Key_F9: - return kVK_F9; - case Qt::Key_F10: - return kVK_F10; - case Qt::Key_F11: - return kVK_F11; - case Qt::Key_F12: - return kVK_F12; - case Qt::Key_F13: - return kVK_F13; - case Qt::Key_F14: - return kVK_F14; - case Qt::Key_F15: - return kVK_F15; - case Qt::Key_F16: - return kVK_F16; + case Qt::Key_F1: + return kVK_F1; + case Qt::Key_F2: + return kVK_F2; + case Qt::Key_F3: + return kVK_F3; + case Qt::Key_F4: + return kVK_F4; + case Qt::Key_F5: + return kVK_F5; + case Qt::Key_F6: + return kVK_F6; + case Qt::Key_F7: + return kVK_F7; + case Qt::Key_F8: + return kVK_F8; + case Qt::Key_F9: + return kVK_F9; + case Qt::Key_F10: + return kVK_F10; + case Qt::Key_F11: + return kVK_F11; + case Qt::Key_F12: + return kVK_F12; + case Qt::Key_F13: + return kVK_F13; + case Qt::Key_F14: + return kVK_F14; + case Qt::Key_F15: + return kVK_F15; + case Qt::Key_F16: + return kVK_F16; - default: - return INVALID_KEYCODE; + default: + Q_ASSERT(false); + return INVALID_KEYCODE; } } -/** - * Translate Qt key modifiers to macOS key modifiers - * provided by the Core Graphics component - * - * @param modifiers Qt keyboard modifier(s) - * @returns macOS key modifier(s) - */ -CGEventFlags AutoTypePlatformMac::qtToNativeModifiers(Qt::KeyboardModifiers modifiers) +// +// Translate qt key modifiers to mac os modifiers +// see: https://doc.qt.io/qt-5/osx-issues.html#special-keys +// +CGEventFlags AutoTypePlatformMac::qtToNativeModifiers(Qt::KeyboardModifiers modifiers, bool native) { - auto nativeModifiers = CGEventFlags(0); + CGEventFlags nativeModifiers = CGEventFlags(0); + + CGEventFlags shiftMod = CGEventFlags(shiftKey); + CGEventFlags cmdMod = CGEventFlags(cmdKey); + CGEventFlags optionMod = CGEventFlags(optionKey); + CGEventFlags controlMod = CGEventFlags(controlKey); + + if (native) { + shiftMod = kCGEventFlagMaskShift; + cmdMod = kCGEventFlagMaskCommand; + optionMod = kCGEventFlagMaskAlternate; + controlMod = kCGEventFlagMaskControl; + } + if (modifiers & Qt::ShiftModifier) { - nativeModifiers = CGEventFlags(nativeModifiers | kCGEventFlagMaskShift); + nativeModifiers = CGEventFlags(nativeModifiers | shiftMod); } if (modifiers & Qt::ControlModifier) { - nativeModifiers = CGEventFlags(nativeModifiers | kCGEventFlagMaskCommand); + nativeModifiers = CGEventFlags(nativeModifiers | cmdMod); } if (modifiers & Qt::AltModifier) { - nativeModifiers = CGEventFlags(nativeModifiers | kCGEventFlagMaskAlternate); + nativeModifiers = CGEventFlags(nativeModifiers | optionMod); } if (modifiers & Qt::MetaModifier) { - nativeModifiers = CGEventFlags(nativeModifiers | kCGEventFlagMaskControl); + nativeModifiers = CGEventFlags(nativeModifiers | controlMod); } return nativeModifiers; } -/** - * Get window layer / level - * - * @param window macOS window ref - * @returns layer number or -1 if window not found - */ +// +// Get window layer/level +// int AutoTypePlatformMac::windowLayer(CFDictionaryRef window) { int layer; - auto layerRef = static_cast(::CFDictionaryGetValue(window, kCGWindowLayer)); - if (layerRef && ::CFNumberGetValue(layerRef, kCFNumberIntType, &layer)) { + CFNumberRef layerRef = static_cast(::CFDictionaryGetValue(window, kCGWindowLayer)); + if (layerRef != nullptr + && ::CFNumberGetValue(layerRef, kCFNumberIntType, &layer)) { return layer; } return -1; } -/** - * Get window title for macOS window ref - * - * @param window macOS window ref - * @returns window title if found - */ +// +// Get window title +// QString AutoTypePlatformMac::windowTitle(CFDictionaryRef window) { char buffer[MAX_WINDOW_TITLE_LENGTH]; QString title; - auto titleRef = static_cast(::CFDictionaryGetValue(window, kCGWindowName)); - if (titleRef && ::CFStringGetCString(titleRef, buffer, MAX_WINDOW_TITLE_LENGTH, kCFStringEncodingUTF8)) { + CFStringRef titleRef = static_cast(::CFDictionaryGetValue(window, kCGWindowName)); + if (titleRef != nullptr + && ::CFStringGetCString(titleRef, buffer, MAX_WINDOW_TITLE_LENGTH, kCFStringEncodingUTF8)) { title = QString::fromUtf8(buffer); } return title; } +// +// Carbon hotkey handler +// +OSStatus AutoTypePlatformMac::hotkeyHandler(EventHandlerCallRef nextHandler, EventRef theEvent, void* userData) +{ + Q_UNUSED(nextHandler); + + AutoTypePlatformMac* self = static_cast(userData); + EventHotKeyID hotkeyId; + + if (::GetEventParameter(theEvent, kEventParamDirectObject, typeEventHotKeyID, nullptr, sizeof(hotkeyId), nullptr, &hotkeyId) == noErr + && hotkeyId.id == HOTKEY_ID) { + emit self->globalShortcutTriggered(); + } + + return noErr; +} + // // ------------------------------ AutoTypeExecutorMac ------------------------------ // @@ -511,7 +502,7 @@ void AutoTypeExecutorMac::execKey(AutoTypeKey* action) m_platform->sendKey(action->key, false); } -void AutoTypeExecutorMac::execClearField(AutoTypeClearField* action) +void AutoTypeExecutorMac::execClearField(AutoTypeClearField* action = nullptr) { Q_UNUSED(action); diff --git a/src/autotype/mac/AutoTypeMac.h b/src/autotype/mac/AutoTypeMac.h index 904046e33..56c35fd2c 100644 --- a/src/autotype/mac/AutoTypeMac.h +++ b/src/autotype/mac/AutoTypeMac.h @@ -19,12 +19,12 @@ #ifndef KEEPASSX_AUTOTYPEMAC_H #define KEEPASSX_AUTOTYPEMAC_H -#include +#include #include #include -#include "autotype/AutoTypeAction.h" #include "autotype/AutoTypePlatformPlugin.h" +#include "autotype/AutoTypeAction.h" class AutoTypePlatformMac : public QObject, public AutoTypePlatformInterface { @@ -48,19 +48,20 @@ public: bool raiseOwnWindow() override; void sendChar(const QChar& ch, bool isKeyDown); - void sendKey(Qt::Key key, bool isKeyDown, Qt::KeyboardModifiers modifiers = 0); + void sendKey(Qt::Key key, bool isKeyDown, Qt::KeyboardModifiers modifiers); signals: void globalShortcutTriggered(); private: - static void hotkeyHandler(void* userData); - static CGKeyCode qtToNativeKeyCode(Qt::Key key); - static CGEventFlags qtToNativeModifiers(Qt::KeyboardModifiers modifiers); + EventHotKeyRef m_hotkeyRef; + EventHotKeyID m_hotkeyId; + + static uint16 qtToNativeKeyCode(Qt::Key key); + static CGEventFlags qtToNativeModifiers(Qt::KeyboardModifiers modifiers, bool native); static int windowLayer(CFDictionaryRef window); static QString windowTitle(CFDictionaryRef window); - - void* m_globalMonitor; + static OSStatus hotkeyHandler(EventHandlerCallRef nextHandler, EventRef theEvent, void* userData); }; class AutoTypeExecutorMac : public AutoTypeExecutor @@ -76,4 +77,4 @@ private: AutoTypePlatformMac* const m_platform; }; -#endif // KEEPASSX_AUTOTYPEMAC_H +#endif // KEEPASSX_AUTOTYPEMAC_H diff --git a/src/autotype/mac/AutoTypeMacKeyCodes.h b/src/autotype/mac/AutoTypeMacKeyCodes.h deleted file mode 100644 index c89cf0346..000000000 --- a/src/autotype/mac/AutoTypeMacKeyCodes.h +++ /dev/null @@ -1,160 +0,0 @@ -// -// Taken from HIToolbox/Events.h -// - -/* - * Summary: - * Virtual keycodes - * - * Discussion: - * These constants are the virtual keycodes defined originally in - * Inside Mac Volume V, pg. V-191. They identify physical keys on a - * keyboard. Those constants with "ANSI" in the name are labeled - * according to the key position on an ANSI-standard US keyboard. - * For example, kVK_ANSI_A indicates the virtual keycode for the key - * with the letter 'A' in the US keyboard layout. Other keyboard - * layouts may have the 'A' key label on a different physical key; - * in this case, pressing 'A' will generate a different virtual - * keycode. - */ - -#ifndef KEEPASSXC_AUTOTYPEMAC_KEYCODES_H -#define KEEPASSXC_AUTOTYPEMAC_KEYCODES_H - -// clang-format off -enum { - kVK_ANSI_A = 0x00, - kVK_ANSI_S = 0x01, - kVK_ANSI_D = 0x02, - kVK_ANSI_F = 0x03, - kVK_ANSI_H = 0x04, - kVK_ANSI_G = 0x05, - kVK_ANSI_Z = 0x06, - kVK_ANSI_X = 0x07, - kVK_ANSI_C = 0x08, - kVK_ANSI_V = 0x09, - kVK_ANSI_B = 0x0B, - kVK_ANSI_Q = 0x0C, - kVK_ANSI_W = 0x0D, - kVK_ANSI_E = 0x0E, - kVK_ANSI_R = 0x0F, - kVK_ANSI_Y = 0x10, - kVK_ANSI_T = 0x11, - kVK_ANSI_1 = 0x12, - kVK_ANSI_2 = 0x13, - kVK_ANSI_3 = 0x14, - kVK_ANSI_4 = 0x15, - kVK_ANSI_6 = 0x16, - kVK_ANSI_5 = 0x17, - kVK_ANSI_Equal = 0x18, - kVK_ANSI_9 = 0x19, - kVK_ANSI_7 = 0x1A, - kVK_ANSI_Minus = 0x1B, - kVK_ANSI_8 = 0x1C, - kVK_ANSI_0 = 0x1D, - kVK_ANSI_RightBracket = 0x1E, - kVK_ANSI_O = 0x1F, - kVK_ANSI_U = 0x20, - kVK_ANSI_LeftBracket = 0x21, - kVK_ANSI_I = 0x22, - kVK_ANSI_P = 0x23, - kVK_ANSI_L = 0x25, - kVK_ANSI_J = 0x26, - kVK_ANSI_Quote = 0x27, - kVK_ANSI_K = 0x28, - kVK_ANSI_Semicolon = 0x29, - kVK_ANSI_Backslash = 0x2A, - kVK_ANSI_Comma = 0x2B, - kVK_ANSI_Slash = 0x2C, - kVK_ANSI_N = 0x2D, - kVK_ANSI_M = 0x2E, - kVK_ANSI_Period = 0x2F, - kVK_ANSI_Grave = 0x32, - kVK_ANSI_KeypadDecimal = 0x41, - kVK_ANSI_KeypadMultiply = 0x43, - kVK_ANSI_KeypadPlus = 0x45, - kVK_ANSI_KeypadClear = 0x47, - kVK_ANSI_KeypadDivide = 0x4B, - kVK_ANSI_KeypadEnter = 0x4C, - kVK_ANSI_KeypadMinus = 0x4E, - kVK_ANSI_KeypadEquals = 0x51, - kVK_ANSI_Keypad0 = 0x52, - kVK_ANSI_Keypad1 = 0x53, - kVK_ANSI_Keypad2 = 0x54, - kVK_ANSI_Keypad3 = 0x55, - kVK_ANSI_Keypad4 = 0x56, - kVK_ANSI_Keypad5 = 0x57, - kVK_ANSI_Keypad6 = 0x58, - kVK_ANSI_Keypad7 = 0x59, - kVK_ANSI_Keypad8 = 0x5B, - kVK_ANSI_Keypad9 = 0x5C -}; - -/* keycodes for keys that are independent of keyboard layout*/ -enum { - kVK_Return = 0x24, - kVK_Tab = 0x30, - kVK_Space = 0x31, - kVK_Delete = 0x33, - kVK_Escape = 0x35, - kVK_Command = 0x37, - kVK_Shift = 0x38, - kVK_CapsLock = 0x39, - kVK_Option = 0x3A, - kVK_Control = 0x3B, - kVK_RightCommand = 0x36, - kVK_RightShift = 0x3C, - kVK_RightOption = 0x3D, - kVK_RightControl = 0x3E, - kVK_Function = 0x3F, - kVK_F17 = 0x40, - kVK_VolumeUp = 0x48, - kVK_VolumeDown = 0x49, - kVK_Mute = 0x4A, - kVK_F18 = 0x4F, - kVK_F19 = 0x50, - kVK_F20 = 0x5A, - kVK_F5 = 0x60, - kVK_F6 = 0x61, - kVK_F7 = 0x62, - kVK_F3 = 0x63, - kVK_F8 = 0x64, - kVK_F9 = 0x65, - kVK_F11 = 0x67, - kVK_F13 = 0x69, - kVK_F16 = 0x6A, - kVK_F14 = 0x6B, - kVK_F10 = 0x6D, - kVK_F12 = 0x6F, - kVK_F15 = 0x71, - kVK_Help = 0x72, - kVK_Home = 0x73, - kVK_PageUp = 0x74, - kVK_ForwardDelete = 0x75, - kVK_F4 = 0x76, - kVK_End = 0x77, - kVK_F2 = 0x78, - kVK_PageDown = 0x79, - kVK_F1 = 0x7A, - kVK_LeftArrow = 0x7B, - kVK_RightArrow = 0x7C, - kVK_DownArrow = 0x7D, - kVK_UpArrow = 0x7E -}; - -/* ISO keyboards only*/ -enum { - kVK_ISO_Section = 0x0A -}; - -/* JIS keyboards only*/ -enum { - kVK_JIS_Yen = 0x5D, - kVK_JIS_Underscore = 0x5E, - kVK_JIS_KeypadComma = 0x5F, - kVK_JIS_Eisu = 0x66, - kVK_JIS_Kana = 0x68 -}; -// clang-format on - -#endif diff --git a/src/autotype/mac/CMakeLists.txt b/src/autotype/mac/CMakeLists.txt index 0179b4a0c..7427450a1 100644 --- a/src/autotype/mac/CMakeLists.txt +++ b/src/autotype/mac/CMakeLists.txt @@ -1,7 +1,7 @@ set(autotype_mac_SOURCES AutoTypeMac.cpp) add_library(keepassx-autotype-cocoa MODULE ${autotype_mac_SOURCES}) -set_target_properties(keepassx-autotype-cocoa PROPERTIES LINK_FLAGS "-framework Foundation -framework AppKit") +set_target_properties(keepassx-autotype-cocoa PROPERTIES LINK_FLAGS "-framework Foundation -framework AppKit -framework Carbon") target_link_libraries(keepassx-autotype-cocoa ${PROGNAME} Qt5::Core Qt5::Widgets) if(WITH_APP_BUNDLE) diff --git a/src/gui/macutils/AppKit.h b/src/gui/macutils/AppKit.h index d7a5ba16e..eaccb15a5 100644 --- a/src/gui/macutils/AppKit.h +++ b/src/gui/macutils/AppKit.h @@ -20,7 +20,7 @@ #define KEEPASSX_APPKIT_H #include -#include +#include class AppKit : public QObject { @@ -37,8 +37,6 @@ public: bool hideProcess(pid_t pid); bool isHidden(pid_t pid); bool isDarkMode(); - void* addGlobalMonitor(CGKeyCode keycode, CGEventFlags modifier, void* userData, void (*handler)(void*)); - void removeGlobalMonitor(void* monitor); bool enableAccessibility(); signals: @@ -48,4 +46,4 @@ private: void* self; }; -#endif // KEEPASSX_APPKIT_H +#endif // KEEPASSX_APPKIT_H diff --git a/src/gui/macutils/AppKitImpl.h b/src/gui/macutils/AppKitImpl.h index 54f695919..895e7cc03 100644 --- a/src/gui/macutils/AppKitImpl.h +++ b/src/gui/macutils/AppKitImpl.h @@ -19,7 +19,6 @@ #import "AppKit.h" #import -#import #import @interface AppKitImpl : NSObject @@ -37,8 +36,6 @@ - (bool) isHidden:(pid_t) pid; - (bool) isDarkMode; - (void) userSwitchHandler:(NSNotification*) notification; -- (id) addGlobalMonitor:(NSEventMask) mask handler:(void (^)(NSEvent*)) handler; -- (void) removeGlobalMonitor:(id) monitor; - (bool) enableAccessibility; @end diff --git a/src/gui/macutils/AppKitImpl.mm b/src/gui/macutils/AppKitImpl.mm index fa0128569..bf9068e6d 100644 --- a/src/gui/macutils/AppKitImpl.mm +++ b/src/gui/macutils/AppKitImpl.mm @@ -123,22 +123,6 @@ static const NSEventMask NSEventMaskKeyDown = NSKeyDownMask; } } -// -// Add global event monitor -// -- (id) addGlobalMonitor:(NSEventMask) mask handler:(void (^)(NSEvent*)) handler -{ - return [NSEvent addGlobalMonitorForEventsMatchingMask:mask handler:handler]; -} - -// -// Remove global event monitor -// -- (void) removeGlobalMonitor:(id) monitor -{ - [NSEvent removeMonitor:monitor]; -} - // // Check if accessibility is enabled, may show an popup asking for permissions // @@ -211,21 +195,7 @@ bool AppKit::isDarkMode() return [static_cast(self) isDarkMode]; } -void* AppKit::addGlobalMonitor(CGKeyCode keycode, CGEventFlags modifier, void* userData, void (*handler)(void*)) -{ - return [static_cast(self) addGlobalMonitor:NSEventMaskKeyDown handler:^(NSEvent* event) { - if (event.keyCode == keycode && (event.modifierFlags & modifier) == modifier) { - handler(userData); - } - }]; -} - -void AppKit::removeGlobalMonitor(void* monitor) -{ - [static_cast(self) removeGlobalMonitor:static_cast(monitor)]; -} - bool AppKit::enableAccessibility() { return [static_cast(self) enableAccessibility]; -} +} \ No newline at end of file diff --git a/src/gui/macutils/MacUtils.cpp b/src/gui/macutils/MacUtils.cpp index 653eb0832..5e6aaca11 100644 --- a/src/gui/macutils/MacUtils.cpp +++ b/src/gui/macutils/MacUtils.cpp @@ -21,7 +21,8 @@ MacUtils* MacUtils::m_instance = nullptr; -MacUtils::MacUtils(QObject* parent) : QObject(parent) +MacUtils::MacUtils(QObject* parent) + : QObject(parent) , m_appkit(new AppKit()) { connect(m_appkit.data(), SIGNAL(lockDatabases()), SIGNAL(lockDatabases())); @@ -29,7 +30,6 @@ MacUtils::MacUtils(QObject* parent) : QObject(parent) MacUtils::~MacUtils() { - } MacUtils* MacUtils::instance() @@ -76,16 +76,6 @@ bool MacUtils::isDarkMode() return m_appkit->isDarkMode(); } -void* MacUtils::addGlobalMonitor(CGKeyCode keycode, CGEventFlags modifier, void* userData, void (*handler)(void*)) -{ - return m_appkit->addGlobalMonitor(keycode, modifier, userData, handler); -} - -void MacUtils::removeGlobalMonitor(void* monitor) -{ - m_appkit->removeGlobalMonitor(monitor); -} - bool MacUtils::enableAccessibility() { return m_appkit->enableAccessibility(); diff --git a/src/gui/macutils/MacUtils.h b/src/gui/macutils/MacUtils.h index ced612749..a895623cd 100644 --- a/src/gui/macutils/MacUtils.h +++ b/src/gui/macutils/MacUtils.h @@ -19,9 +19,9 @@ #ifndef KEEPASSXC_MACUTILS_H #define KEEPASSXC_MACUTILS_H +#include "AppKit.h" #include #include -#include "AppKit.h" class MacUtils : public QObject { @@ -38,8 +38,6 @@ public: bool hideOwnWindow(); bool isHidden(); bool isDarkMode(); - void* addGlobalMonitor(CGKeyCode keycode, CGEventFlags modifier, void* userData, void (*handler)(void*)); - void removeGlobalMonitor(void* monitor); bool enableAccessibility(); signals: