TTKMusicPlayer  3.7.0.0
TTKMusicPlayer imitates Kugou UI, the music player uses of qmmp core library based on Qt for windows and linux
qglobalshortcut_mac.cpp
Go to the documentation of this file.
1 #include <Carbon/Carbon.h>
2 #include "qglobalshortcut_p.h"
3 #include <QMap>
4 #include <QApplication>
5 
6 typedef QPair<uint, uint> Identifier;
7 static QMap<quint32, EventHotKeyRef> keyRefs;
8 static QHash<Identifier, quint32> keyIDs;
9 static quint32 hotKeySerial = 0;
10 static bool q_mac_handler_installed = false;
11 
12 OSStatus q_mac_handle_hot_key(EventHandlerCallRef nextHandler, EventRef event, void *data)
13 {
14  // pass event to the app event filter
15  Q_UNUSED(data);
16  qApp->macEventFilter(nextHandler, event);
17  return noErr;
18 }
19 
20 #if !TTK_QT_VERSION_CHECK(5,0,0)
22 //bool QGlobalShortcutPrivate::macEventFilter(EventHandlerCallRef caller, EventRef event)
23 {
24  EventRef event = (EventRef) message;
25  if(GetEventClass(event) == kEventClassKeyboard && GetEventKind(event) == kEventHotKeyPressed)
26  {
27  EventHotKeyID keyID;
28  GetEventParameter(event, kEventParamDirectObject, typeEventHotKeyID, nullptr, sizeof(keyID), nullptr, &keyID);
29  Identifier id = keyIDs.key(keyID.id);
30  activateShortcut(id.second, id.first);
31  }
32  return false;
33 }
34 #else
35 bool QGlobalShortcutPrivate::nativeEventFilter(const QByteArray &, void *message, qint *)
36 {
37  EventRef event = (EventRef) message;
38  if(GetEventClass(event) == kEventClassKeyboard && GetEventKind(event) == kEventHotKeyPressed)
39  {
40  EventHotKeyID keyID;
41  GetEventParameter(event, kEventParamDirectObject, typeEventHotKeyID, nullptr, sizeof(keyID), nullptr, &keyID);
42  Identifier id = keyIDs.key(keyID.id);
43  activateShortcut(id.second, id.first);
44  }
45  return false;
46 }
47 #endif
48 
49 quint32 QGlobalShortcutPrivate::nativeModifiers(Qt::KeyboardModifiers modifiers)
50 {
51  quint32 native = 0;
52  if(modifiers & Qt::ShiftModifier)
53  native |= shiftKey;
54  if(modifiers & Qt::ControlModifier)
55  native |= cmdKey;
56  if(modifiers & Qt::AltModifier)
57  native |= optionKey;
58  if(modifiers & Qt::MetaModifier)
59  native |= controlKey;
60  if(modifiers & Qt::KeypadModifier)
61  native |= kEventKeyModifierNumLockMask;
62  return native;
63 }
64 
66 {
67  UTF16Char ch;
68  // Constants found in NSEvent.h from AppKit.framework
69  if(key == Qt::Key_Up) ch = 0xF700;
70  else if(key == Qt::Key_Down) ch = 0xF701;
71  else if(key == Qt::Key_Left) ch = 0xF702;
72  else if(key == Qt::Key_Right) ch = 0xF703;
73  else if(key >= Qt::Key_F1 && key <= Qt::Key_F35)
74  ch = key - Qt::Key_F1 + 0xF704;
75  else if(key == Qt::Key_Insert) ch = 0xF727;
76  else if(key == Qt::Key_Delete) ch = 0xF728;
77  else if(key == Qt::Key_Home) ch = 0xF729;
78  else if(key == Qt::Key_End) ch = 0xF72B;
79  else if(key == Qt::Key_PageUp) ch = 0xF72C;
80  else if(key == Qt::Key_PageDown) ch = 0xF72D;
81  else if(key == Qt::Key_Print) ch = 0xF72E;
82  else if(key == Qt::Key_ScrollLock) ch = 0xF72F;
83  else if(key == Qt::Key_Pause) ch = 0xF730;
84  else if(key == Qt::Key_SysReq) ch = 0xF731;
85  else if(key == Qt::Key_Stop) ch = 0xF734;
86  else if(key == Qt::Key_Menu) ch = 0xF735;
87  else if(key == Qt::Key_Select) ch = 0xF741;
88  else if(key == Qt::Key_Execute) ch = 0xF742;
89  else if(key == Qt::Key_Help) ch = 0xF746;
90  else if(key == Qt::Key_Mode_switch) ch = 0xF747;
91  else if(key == Qt::Key_Escape) ch = 27;
92  else if(key == Qt::Key_Return) ch = 13;
93  else if(key == Qt::Key_Enter) ch = 3;
94  else if(key == Qt::Key_Tab) ch = 9;
95  else ch = key;
96 
97  KeyboardLayoutRef layout;
98  KeyboardLayoutKind layoutKind;
99  KLGetCurrentKeyboardLayout(&layout);
100  KLGetKeyboardLayoutProperty(layout, kKLKind, TTKConstCast(const void**, TTKReinterpretCast(void**, &layoutKind)));
101 
102  if(layoutKind == kKLKCHRKind)
103  { // no Unicode available
104  if(ch > 255) return 0;
105 
106  char *data;
107  KLGetKeyboardLayoutProperty(layout, kKLKCHRData, TTKConstCast(const void**, TTKReinterpretCast(void**, &data)));
108  int ct = *TTKReinterpretCast(short*, data + 258);
109  for(int i = 0; i < ct; ++i)
110  {
111  char *keyTable = data + 260 + 128 * i;
112  for(int j = 0; j < 128; ++j)
113  {
114  if(keyTable[j] == ch) return j;
115  }
116  }
117 
118  return 0;
119  }
120 
121  char *data;
122  KLGetKeyboardLayoutProperty(layout, kKLuchrData, TTKConstCast(const void**, TTKReinterpretCast(void**, &data)));
123  UCKeyboardLayout *header = TTKReinterpretCast(UCKeyboardLayout*, data);
124  UCKeyboardTypeHeader *table = header->keyboardTypeList;
125 
126  for (quint32 i=0; i < header->keyboardTypeCount; i++)
127  {
128  UCKeyStateRecordsIndex *stateRec = 0;
129  if(table[i].keyStateRecordsIndexOffset != 0)
130  {
131  stateRec = TTKReinterpretCast(UCKeyStateRecordsIndex*, data + table[i].keyStateRecordsIndexOffset);
132  if(stateRec->keyStateRecordsIndexFormat != kUCKeyStateRecordsIndexFormat) stateRec = 0;
133  }
134 
135  UCKeyToCharTableIndex *charTable = TTKReinterpretCast(UCKeyToCharTableIndex*, data + table[i].keyToCharTableIndexOffset);
136  if(charTable->keyToCharTableIndexFormat != kUCKeyToCharTableIndexFormat) continue;
137 
138  for (quint32 j=0; j < charTable->keyToCharTableCount; j++)
139  {
140  UCKeyOutput *keyToChar = TTKReinterpretCast(UCKeyOutput*, data + charTable->keyToCharTableOffsets[j]);
141  for (quint32 k=0; k < charTable->keyToCharTableSize; k++)
142  {
143  if(keyToChar[k] & kUCKeyOutputTestForIndexMask)
144  {
145  long idx = keyToChar[k] & kUCKeyOutputGetIndexMask;
146  if(stateRec && idx < stateRec->keyStateRecordCount)
147  {
148  UCKeyStateRecord *rec = TTKReinterpretCast(UCKeyStateRecord*, data + stateRec->keyStateRecordOffsets[idx]);
149  if(rec->stateZeroCharData == ch) return k;
150  }
151  }
152  else if(!(keyToChar[k] & kUCKeyOutputSequenceIndexMask) && keyToChar[k] < 0xFFFE)
153  {
154  if(keyToChar[k] == ch) return k;
155  }
156  } // for k
157  } // for j
158  } // for i
159 
160  return 0;
161 }
162 
163 bool QGlobalShortcutPrivate::registerShortcut(quint32 nativeKey, quint32 nativeMods)
164 {
166  {
167  EventTypeSpec t;
168  t.eventClass = kEventClassKeyboard;
169  t.eventKind = kEventHotKeyPressed;
170  InstallApplicationEventHandler(&q_mac_handle_hot_key, 1, &t, nullptr, nullptr);
171  }
172 
173  EventHotKeyID keyID;
174  keyID.signature = 'cute';
175  keyID.id = ++hotKeySerial;
176 
177  EventHotKeyRef ref = 0;
178  bool rv = !RegisterEventHotKey(nativeKey, nativeMods, keyID, GetApplicationEventTarget(), 0, &ref);
179  if(rv)
180  {
181  keyIDs.insert(Identifier(nativeMods, nativeKey), keyID.id);
182  keyRefs.insert(keyID.id, ref);
183  }
184 
185  return rv;
186 }
187 
188 bool QGlobalShortcutPrivate::unregisterShortcut(quint32 nativeKey, quint32 nativeMods)
189 {
190  Identifier id(nativeMods, nativeKey);
191  if(!keyIDs.contains(id)) return false;
192 
193  EventHotKeyRef ref = keyRefs.take(keyIDs[id]);
194  keyIDs.remove(id);
195  return !UnregisterEventHotKey(ref);
196 }
static quint32 nativeKeycode(Qt::Key keycode)
#define TTKConstCast(x, y)
Definition: ttkglobal.h:141
static bool q_mac_handler_installed
static QMap< quint32, EventHotKeyRef > keyRefs
static QHash< Identifier, quint32 > keyIDs
static constexpr wchar_t key[]
static quint32 nativeModifiers(Qt::KeyboardModifiers modifiers)
OSStatus q_mac_handle_hot_key(EventHandlerCallRef nextHandler, EventRef event, void *data)
#define qint
Definition: ttkqtglobal.h:168
static bool unregisterShortcut(quint32 nativeKey, quint32 nativeMods)
static bool eventFilter(void *message)
static bool registerShortcut(quint32 nativeKey, quint32 nativeMods)
QPair< uint, uint > Identifier
static quint32 hotKeySerial
#define TTKReinterpretCast(x, y)
Definition: ttkglobal.h:153
static void activateShortcut(quint32 nativeKey, quint32 nativeMods)