TTKMusicPlayer  4.3.0.0
TTKMusicPlayer imitates Kugou UI, the music player uses of qmmp core library based on Qt for windows and linux
qglobalshortcut_osx.cpp
Go to the documentation of this file.
1 #include <Carbon/Carbon.h>
2 #include "qglobalshortcut_p.h"
3 #include <QHash>
4 #include <QApplication>
5 
6 typedef QPair<quint32, quint32> Identifier;
7 static QHash<Identifier, EventHotKeyRef> keyRefs;
8 static bool q_mac_handler_installed = false;
9 
10 OSStatus q_mac_handle_hot_key(EventHandlerCallRef nextHandler, EventRef event, void *data)
11 {
12  // pass event to the app event filter
13  Q_UNUSED(nextHandler);
14  Q_UNUSED(data);
15 #if !TTK_QT_VERSION_CHECK(5,0,0)
16  QAbstractEventDispatcher::instance()->filterEvent((void*)event);
17 #else
18  QAbstractEventDispatcher::instance()->filterNativeEvent({}, (void*)event, nullptr);
19 #endif
20  return noErr;
21 }
22 
23 #if !TTK_QT_VERSION_CHECK(5,0,0)
25 #else
26 bool QGlobalShortcutPrivate::nativeEventFilter(const QByteArray &, void *message, qint *)
27 #endif
28 {
29  EventRef event = (EventRef) message;
30  if(GetEventClass(event) == kEventClassKeyboard && GetEventKind(event) == kEventHotKeyPressed)
31  {
32  EventHotKeyID keyID;
33  GetEventParameter(event, kEventParamDirectObject, typeEventHotKeyID, nullptr, sizeof(keyID), nullptr, &keyID);
34  activateShortcut(keyID.signature, keyID.id);
35  }
36  return false;
37 }
38 
39 quint32 QGlobalShortcutPrivate::nativeModifiers(Qt::KeyboardModifiers modifiers)
40 {
41  quint32 native = 0;
42  if(modifiers & Qt::ShiftModifier)
43  native |= shiftKey;
44  if(modifiers & Qt::ControlModifier)
45  native |= cmdKey;
46  if(modifiers & Qt::AltModifier)
47  native |= optionKey;
48  if(modifiers & Qt::MetaModifier)
49  native |= controlKey;
50  if(modifiers & Qt::KeypadModifier)
51  native |= kEventKeyModifierNumLockMask;
52  return native;
53 }
54 
56 {
57  // Constants found in NSEvent.h from AppKit.framework
58  if(key == Qt::Key_Return) return kVK_Return;
59  else if(key == Qt::Key_Enter) return kVK_ANSI_KeypadEnter;
60  else if(key == Qt::Key_Tab) return kVK_Tab;
61  else if(key == Qt::Key_Space) return kVK_Space;
62  else if(key == Qt::Key_Backspace) return kVK_Delete;
63  else if(key == Qt::Key_Escape) return kVK_Escape;
64  else if(key == Qt::Key_CapsLock) return kVK_CapsLock;
65  else if(key == Qt::Key_Option) return kVK_Option;
66  else if(key == Qt::Key_F17) return kVK_F17;
67  else if(key == Qt::Key_VolumeUp) return kVK_VolumeUp;
68  else if(key == Qt::Key_VolumeDown) return kVK_VolumeDown;
69  else if(key == Qt::Key_F18) return kVK_F18;
70  else if(key == Qt::Key_F19) return kVK_F19;
71  else if(key == Qt::Key_F20) return kVK_F20;
72  else if(key == Qt::Key_F5) return kVK_F5;
73  else if(key == Qt::Key_F6) return kVK_F6;
74  else if(key == Qt::Key_F7) return kVK_F7;
75  else if(key == Qt::Key_F3) return kVK_F3;
76  else if(key == Qt::Key_F8) return kVK_F8;
77  else if(key == Qt::Key_F9) return kVK_F9;
78  else if(key == Qt::Key_F11) return kVK_F11;
79  else if(key == Qt::Key_F13) return kVK_F13;
80  else if(key == Qt::Key_F16) return kVK_F16;
81  else if(key == Qt::Key_F14) return kVK_F14;
82  else if(key == Qt::Key_F10) return kVK_F10;
83  else if(key == Qt::Key_F12) return kVK_F12;
84  else if(key == Qt::Key_F15) return kVK_F15;
85  else if(key == Qt::Key_Help) return kVK_Help;
86  else if(key == Qt::Key_Home) return kVK_Home;
87  else if(key == Qt::Key_PageUp) return kVK_PageUp;
88  else if(key == Qt::Key_Delete) return kVK_ForwardDelete;
89  else if(key == Qt::Key_F4) return kVK_F4;
90  else if(key == Qt::Key_End) return kVK_End;
91  else if(key == Qt::Key_F2) return kVK_F2;
92  else if(key == Qt::Key_PageDown) return kVK_PageDown;
93  else if(key == Qt::Key_F1) return kVK_F1;
94  else if(key == Qt::Key_Left) return kVK_LeftArrow;
95  else if(key == Qt::Key_Right) return kVK_RightArrow;
96  else if(key == Qt::Key_Down) return kVK_DownArrow;
97  else if(key == Qt::Key_Up) return kVK_UpArrow;
98 
99  CFDataRef currentLayoutData;
100  TISInputSourceRef currentKeyboard = TISCopyCurrentASCIICapableKeyboardLayoutInputSource();
101 
102  if(currentKeyboard == nullptr)
103  return 0;
104 
105  currentLayoutData = (CFDataRef)TISGetInputSourceProperty(currentKeyboard, kTISPropertyUnicodeKeyLayoutData);
106  CFRelease(currentKeyboard);
107 
108  if(currentLayoutData == nullptr)
109  return 0;
110 
111  UCKeyboardLayout *header = (UCKeyboardLayout*)CFDataGetBytePtr(currentLayoutData);
112  UCKeyboardTypeHeader *table = header->keyboardTypeList;
113 
114  UTF16Char ch = key;
115  uint8_t *data = (uint8_t*)header;
116  for(quint32 i = 0; i < header->keyboardTypeCount; ++i)
117  {
118  UCKeyStateRecordsIndex *stateRec = 0;
119  if(table[i].keyStateRecordsIndexOffset != 0)
120  {
121  stateRec = TTKReinterpretCast(UCKeyStateRecordsIndex*, data + table[i].keyStateRecordsIndexOffset);
122  if(stateRec->keyStateRecordsIndexFormat != kUCKeyStateRecordsIndexFormat)
123  {
124  stateRec = 0;
125  }
126  }
127 
128  UCKeyToCharTableIndex *charTable = TTKReinterpretCast(UCKeyToCharTableIndex*, data + table[i].keyToCharTableIndexOffset);
129  if(charTable->keyToCharTableIndexFormat != kUCKeyToCharTableIndexFormat)
130  {
131  continue;
132  }
133 
134  for(quint32 j = 0; j < charTable->keyToCharTableCount; ++j)
135  {
136  UCKeyOutput *keyToChar = TTKReinterpretCast(UCKeyOutput*, data + charTable->keyToCharTableOffsets[j]);
137  for(quint32 k = 0; k < charTable->keyToCharTableSize; ++k)
138  {
139  if(keyToChar[k] & kUCKeyOutputTestForIndexMask)
140  {
141  long idx = keyToChar[k] & kUCKeyOutputGetIndexMask;
142  if(stateRec && idx < stateRec->keyStateRecordCount)
143  {
144  UCKeyStateRecord *rec = TTKReinterpretCast(UCKeyStateRecord*, data + stateRec->keyStateRecordOffsets[idx]);
145  if(rec->stateZeroCharData == ch)
146  {
147  return k;
148  }
149  }
150  }
151  else if(!(keyToChar[k] & kUCKeyOutputSequenceIndexMask) && keyToChar[k] < 0xFFFE)
152  {
153  if(keyToChar[k] == ch)
154  {
155  return k;
156  }
157  }
158  } // for k
159  } // for j
160  } // for i
161 
162  return 0;
163 }
164 
165 bool QGlobalShortcutPrivate::registerShortcut(quint32 nativeKey, quint32 nativeMods)
166 {
168  {
169  EventTypeSpec t;
170  t.eventClass = kEventClassKeyboard;
171  t.eventKind = kEventHotKeyPressed;
172  InstallApplicationEventHandler(&q_mac_handle_hot_key, 1, &t, nullptr, nullptr);
173  }
174 
175  EventHotKeyID keyID;
176  keyID.signature = nativeKey;
177  keyID.id = nativeMods;
178 
179  EventHotKeyRef ref = 0;
180  const bool rv = !RegisterEventHotKey(nativeKey, nativeMods, keyID, GetApplicationEventTarget(), 0, &ref);
181  if(rv)
182  {
183  keyRefs.insert(Identifier(nativeMods, nativeKey), ref);
184  }
185  return rv;
186 }
187 
188 bool QGlobalShortcutPrivate::unregisterShortcut(quint32 nativeKey, quint32 nativeMods)
189 {
190  Identifier id(nativeMods, nativeKey);
191  if(!keyRefs.contains(id))
192  {
193  return false;
194  }
195 
196  return !UnregisterEventHotKey(keyRefs.take(id));
197 }
static quint32 nativeKeycode(Qt::Key keycode)
static QString message(const TTK::Attribute attr)
static bool q_mac_handler_installed
QPair< quint32, quint32 > Identifier
static quint32 nativeModifiers(Qt::KeyboardModifiers modifiers)
static constexpr wchar_t key[]
#define qint
Definition: ttkqtglobal.h:180
static bool unregisterShortcut(quint32 nativeKey, quint32 nativeMods)
static bool eventFilter(void *message)
static bool registerShortcut(quint32 nativeKey, quint32 nativeMods)
static QHash< Identifier, EventHotKeyRef > keyRefs
QPair< quint32, quint32 > Identifier
#define TTKReinterpretCast(x, y)
Definition: ttkglobal.h:225
OSStatus q_mac_handle_hot_key(EventHandlerCallRef nextHandler, EventRef event, void *data)