123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328 |
- #include "qhotkey.h"
- #include "qhotkey_p.h"
- #include <Carbon/Carbon.h>
- #include <QDebug>
- class QHotkeyPrivateMac : public QHotkeyPrivate
- {
- public:
- // QAbstractNativeEventFilter interface
- bool nativeEventFilter(const QByteArray& eventType,
- void* message,
- long* result) Q_DECL_OVERRIDE;
- static OSStatus hotkeyPressEventHandler(EventHandlerCallRef nextHandler,
- EventRef event,
- void* data);
- static OSStatus hotkeyReleaseEventHandler(EventHandlerCallRef nextHandler,
- EventRef event,
- void* data);
- protected:
- // QHotkeyPrivate interface
- quint32 nativeKeycode(Qt::Key keycode, bool& ok) Q_DECL_OVERRIDE;
- quint32 nativeModifiers(Qt::KeyboardModifiers modifiers,
- bool& ok) Q_DECL_OVERRIDE;
- bool registerShortcut(QHotkey::NativeShortcut shortcut) Q_DECL_OVERRIDE;
- bool unregisterShortcut(QHotkey::NativeShortcut shortcut) Q_DECL_OVERRIDE;
- private:
- static bool isHotkeyHandlerRegistered;
- static QHash<QHotkey::NativeShortcut, EventHotKeyRef> hotkeyRefs;
- };
- NATIVE_INSTANCE(QHotkeyPrivateMac)
- bool QHotkeyPrivate::isPlatformSupported()
- {
- return true;
- }
- bool QHotkeyPrivateMac::isHotkeyHandlerRegistered = false;
- QHash<QHotkey::NativeShortcut, EventHotKeyRef> QHotkeyPrivateMac::hotkeyRefs;
- bool QHotkeyPrivateMac::nativeEventFilter(const QByteArray& eventType,
- void* message,
- long* result)
- {
- Q_UNUSED(eventType)
- Q_UNUSED(message)
- Q_UNUSED(result)
- return false;
- }
- quint32 QHotkeyPrivateMac::nativeKeycode(Qt::Key keycode, bool& ok)
- {
- // Constants found in NSEvent.h from AppKit.framework
- ok = true;
- switch (keycode) {
- case Qt::Key_Return:
- return kVK_Return;
- case Qt::Key_Enter:
- return kVK_ANSI_KeypadEnter;
- case Qt::Key_Tab:
- return kVK_Tab;
- case Qt::Key_Space:
- return kVK_Space;
- case Qt::Key_Backspace:
- return kVK_Delete;
- case Qt::Key_Escape:
- return kVK_Escape;
- case Qt::Key_CapsLock:
- return kVK_CapsLock;
- case Qt::Key_Option:
- return kVK_Option;
- case Qt::Key_F17:
- return kVK_F17;
- case Qt::Key_VolumeUp:
- return kVK_VolumeUp;
- case Qt::Key_VolumeDown:
- return kVK_VolumeDown;
- case Qt::Key_F18:
- return kVK_F18;
- case Qt::Key_F19:
- return kVK_F19;
- case Qt::Key_F20:
- return kVK_F20;
- case Qt::Key_F5:
- return kVK_F5;
- case Qt::Key_F6:
- return kVK_F6;
- case Qt::Key_F7:
- return kVK_F7;
- case Qt::Key_F3:
- return kVK_F3;
- case Qt::Key_F8:
- return kVK_F8;
- case Qt::Key_F9:
- return kVK_F9;
- case Qt::Key_F11:
- return kVK_F11;
- case Qt::Key_F13:
- return kVK_F13;
- case Qt::Key_F16:
- return kVK_F16;
- case Qt::Key_F14:
- return kVK_F14;
- case Qt::Key_F10:
- return kVK_F10;
- case Qt::Key_F12:
- return kVK_F12;
- case Qt::Key_F15:
- return kVK_F15;
- case Qt::Key_Help:
- return kVK_Help;
- case Qt::Key_Home:
- return kVK_Home;
- case Qt::Key_PageUp:
- return kVK_PageUp;
- case Qt::Key_Delete:
- return kVK_ForwardDelete;
- case Qt::Key_F4:
- return kVK_F4;
- case Qt::Key_End:
- return kVK_End;
- case Qt::Key_F2:
- return kVK_F2;
- case Qt::Key_PageDown:
- return kVK_PageDown;
- case Qt::Key_F1:
- return kVK_F1;
- case Qt::Key_Left:
- return kVK_LeftArrow;
- case Qt::Key_Right:
- return kVK_RightArrow;
- case Qt::Key_Down:
- return kVK_DownArrow;
- case Qt::Key_Up:
- return kVK_UpArrow;
- default:
- ok = false;
- break;
- }
- UTF16Char ch = keycode;
- CFDataRef currentLayoutData;
- TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource();
- if (currentKeyboard == NULL)
- return 0;
- currentLayoutData = (CFDataRef)TISGetInputSourceProperty(
- currentKeyboard, kTISPropertyUnicodeKeyLayoutData);
- CFRelease(currentKeyboard);
- if (currentLayoutData == NULL)
- return 0;
- UCKeyboardLayout* header =
- (UCKeyboardLayout*)CFDataGetBytePtr(currentLayoutData);
- UCKeyboardTypeHeader* table = header->keyboardTypeList;
- uint8_t* data = (uint8_t*)header;
- for (quint32 i = 0; i < header->keyboardTypeCount; i++) {
- UCKeyStateRecordsIndex* stateRec = 0;
- if (table[i].keyStateRecordsIndexOffset != 0) {
- stateRec = reinterpret_cast<UCKeyStateRecordsIndex*>(
- data + table[i].keyStateRecordsIndexOffset);
- if (stateRec->keyStateRecordsIndexFormat !=
- kUCKeyStateRecordsIndexFormat)
- stateRec = 0;
- }
- UCKeyToCharTableIndex* charTable =
- reinterpret_cast<UCKeyToCharTableIndex*>(
- data + table[i].keyToCharTableIndexOffset);
- if (charTable->keyToCharTableIndexFormat !=
- kUCKeyToCharTableIndexFormat)
- continue;
- for (quint32 j = 0; j < charTable->keyToCharTableCount; j++) {
- UCKeyOutput* keyToChar = reinterpret_cast<UCKeyOutput*>(
- data + charTable->keyToCharTableOffsets[j]);
- for (quint32 k = 0; k < charTable->keyToCharTableSize; k++) {
- if (keyToChar[k] & kUCKeyOutputTestForIndexMask) {
- long idx = keyToChar[k] & kUCKeyOutputGetIndexMask;
- if (stateRec && idx < stateRec->keyStateRecordCount) {
- UCKeyStateRecord* rec =
- reinterpret_cast<UCKeyStateRecord*>(
- data + stateRec->keyStateRecordOffsets[idx]);
- if (rec->stateZeroCharData == ch) {
- ok = true;
- return k;
- }
- }
- } else if (!(keyToChar[k] & kUCKeyOutputSequenceIndexMask) &&
- keyToChar[k] < 0xFFFE) {
- if (keyToChar[k] == ch) {
- ok = true;
- return k;
- }
- }
- }
- }
- }
- return 0;
- }
- quint32 QHotkeyPrivateMac::nativeModifiers(Qt::KeyboardModifiers modifiers,
- bool& ok)
- {
- quint32 nMods = 0;
- if (modifiers & Qt::ShiftModifier)
- nMods |= shiftKey;
- if (modifiers & Qt::ControlModifier)
- nMods |= cmdKey;
- if (modifiers & Qt::AltModifier)
- nMods |= optionKey;
- if (modifiers & Qt::MetaModifier)
- nMods |= controlKey;
- if (modifiers & Qt::KeypadModifier)
- nMods |= kEventKeyModifierNumLockMask;
- ok = true;
- return nMods;
- }
- bool QHotkeyPrivateMac::registerShortcut(QHotkey::NativeShortcut shortcut)
- {
- if (!this->isHotkeyHandlerRegistered) {
- EventTypeSpec pressEventSpec;
- pressEventSpec.eventClass = kEventClassKeyboard;
- pressEventSpec.eventKind = kEventHotKeyPressed;
- InstallApplicationEventHandler(
- &QHotkeyPrivateMac::hotkeyPressEventHandler,
- 1,
- &pressEventSpec,
- NULL,
- NULL);
- EventTypeSpec releaseEventSpec;
- releaseEventSpec.eventClass = kEventClassKeyboard;
- releaseEventSpec.eventKind = kEventHotKeyReleased;
- InstallApplicationEventHandler(
- &QHotkeyPrivateMac::hotkeyReleaseEventHandler,
- 1,
- &releaseEventSpec,
- NULL,
- NULL);
- }
- EventHotKeyID hkeyID;
- hkeyID.signature = shortcut.key;
- hkeyID.id = shortcut.modifier;
- EventHotKeyRef eventRef = 0;
- OSStatus status = RegisterEventHotKey(shortcut.key,
- shortcut.modifier,
- hkeyID,
- GetApplicationEventTarget(),
- 0,
- &eventRef);
- if (status != noErr) {
- error = QString::number(status);
- return false;
- } else {
- this->hotkeyRefs.insert(shortcut, eventRef);
- return true;
- }
- }
- bool QHotkeyPrivateMac::unregisterShortcut(QHotkey::NativeShortcut shortcut)
- {
- EventHotKeyRef eventRef = QHotkeyPrivateMac::hotkeyRefs.value(shortcut);
- OSStatus status = UnregisterEventHotKey(eventRef);
- if (status != noErr) {
- error = QString::number(status);
- return false;
- } else {
- this->hotkeyRefs.remove(shortcut);
- return true;
- }
- }
- OSStatus QHotkeyPrivateMac::hotkeyPressEventHandler(
- EventHandlerCallRef nextHandler,
- EventRef event,
- void* data)
- {
- Q_UNUSED(nextHandler);
- Q_UNUSED(data);
- if (GetEventClass(event) == kEventClassKeyboard &&
- GetEventKind(event) == kEventHotKeyPressed) {
- EventHotKeyID hkeyID;
- GetEventParameter(event,
- kEventParamDirectObject,
- typeEventHotKeyID,
- NULL,
- sizeof(EventHotKeyID),
- NULL,
- &hkeyID);
- hotkeyPrivate->activateShortcut({ hkeyID.signature, hkeyID.id });
- }
- return noErr;
- }
- OSStatus QHotkeyPrivateMac::hotkeyReleaseEventHandler(
- EventHandlerCallRef nextHandler,
- EventRef event,
- void* data)
- {
- Q_UNUSED(nextHandler);
- Q_UNUSED(data);
- if (GetEventClass(event) == kEventClassKeyboard &&
- GetEventKind(event) == kEventHotKeyReleased) {
- EventHotKeyID hkeyID;
- GetEventParameter(event,
- kEventParamDirectObject,
- typeEventHotKeyID,
- NULL,
- sizeof(EventHotKeyID),
- NULL,
- &hkeyID);
- hotkeyPrivate->releaseShortcut({ hkeyID.signature, hkeyID.id });
- }
- return noErr;
- }
|