00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "kglobalaccel_mac.h"
00022
00023 #include <config.h>
00024
00025 #include <kdebug.h>
00026
00027 #ifdef Q_WS_MAC
00028
00029 #include <QMultiMap>
00030 #include <QList>
00031
00032 #include "kglobalaccel.h"
00033 #include "kdedglobalaccel.h"
00034 #include "kkeyserver.h"
00035
00036 OSStatus hotKeyEventHandler(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void * inUserData)
00037 {
00038 UInt32 eventKind = GetEventKind(inEvent);
00039 if (eventKind == kEventRawKeyDown) {
00040 UInt32 keycode;
00041 if (GetEventParameter(inEvent, kEventParamKeyCode, typeUInt32, NULL, sizeof(keycode), NULL, &keycode) != noErr) {
00042 kWarning(125) << "Error retrieving keycode parameter from event";
00043 }
00044 kDebug() << " key down, keycode = " << keycode;
00045 } else if (eventKind == kEventHotKeyPressed) {
00046 KGlobalAccelImpl* impl = static_cast<KGlobalAccelImpl *>(inUserData);
00047 EventHotKeyID hotkey;
00048 if (GetEventParameter(inEvent, kEventParamDirectObject, typeEventHotKeyID, NULL, sizeof(hotkey), NULL, &hotkey) != noErr) {
00049 kWarning(125) << "Error retrieving hotkey parameter from event";
00050 return eventNotHandledErr;
00051 }
00052
00053 return (impl->keyPressed(hotkey.id) ? (OSStatus) noErr : (OSStatus) eventNotHandledErr);
00054 }
00055 return eventNotHandledErr;
00056 }
00057
00058 void layoutChanged(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) {
00059 static_cast<KGlobalAccelImpl *>(observer)->keyboardLayoutChanged();
00060 }
00061
00062 KGlobalAccelImpl::KGlobalAccelImpl(KdedGlobalAccel* owner)
00063 : m_owner(owner)
00064 , m_eventTarget(GetApplicationEventTarget())
00065 , m_eventHandler(NewEventHandlerUPP(hotKeyEventHandler))
00066 {
00067 m_eventType[0].eventClass = kEventClassKeyboard;
00068 m_eventType[0].eventKind = kEventHotKeyPressed;
00069 m_eventType[1].eventClass = kEventClassKeyboard;
00070 m_eventType[1].eventKind = kEventRawKeyDown;
00071 refs = new QMap<int, QList<EventHotKeyRef> >();
00072
00073 CFStringRef str = CFStringCreateWithCString(NULL, "AppleKeyboardPreferencesChangedNotification", kCFStringEncodingASCII);
00074 if (str) {
00075 CFNotificationCenterAddObserver(CFNotificationCenterGetDistributedCenter(), this, layoutChanged, str, NULL, CFNotificationSuspensionBehaviorHold);
00076 CFRelease(str);
00077 } else {
00078 kWarning(125) << "Couldn't create CFString to register for keyboard notifications";
00079 }
00080 }
00081
00082 KGlobalAccelImpl::~KGlobalAccelImpl()
00083 {
00084 DisposeEventHandlerUPP(hotKeyEventHandler);
00085 CFNotificationCenterRemoveObserver(CFNotificationCenterGetDistributedCenter(), this, NULL, NULL);
00086 delete refs;
00087 }
00088
00089 bool KGlobalAccelImpl::grabKey( int keyQt, bool grab )
00090 {
00091 if (grab) {
00092 kDebug(125) << "Grabbing key " << keyQt;
00093 QList<uint> keyCodes;
00094 uint mod;
00095 KKeyServer::keyQtToCodeMac( keyQt, keyCodes );
00096 KKeyServer::keyQtToModMac( keyQt, mod );
00097
00098 kDebug(125) << "keyQt: " << keyQt << " mod: " << mod;
00099 foreach (uint keyCode, keyCodes) {
00100 kDebug(125) << " keyCode: " << keyCode;
00101 }
00102
00103 EventHotKeyID ehkid;
00104 ehkid.signature = 'Kgai';
00105 ehkid.id = keyQt;
00106 QList<EventHotKeyRef> hotkeys;
00107 foreach (uint keyCode, keyCodes) {
00108 EventHotKeyRef ref;
00109 if (RegisterEventHotKey(keyCode, mod, ehkid, m_eventTarget, 0, &ref) != noErr) {
00110 kWarning(125) << "RegisterEventHotKey failed!";
00111 }
00112 hotkeys.append(ref);
00113 }
00114 refs->insert(keyQt, hotkeys);
00115 } else {
00116 kDebug(125) << "Ungrabbing key " << keyQt;
00117 if (refs->count(keyQt) == 0) kWarning(125) << "Trying to ungrab a key thas is not grabbed";
00118 foreach (EventHotKeyRef ref, refs->value(keyQt)) {
00119 if (UnregisterEventHotKey(ref) != noErr) {
00120 kWarning(125) << "UnregisterEventHotKey should not fail!";
00121 }
00122 }
00123 refs->remove(keyQt);
00124 }
00125 return true;
00126 }
00127
00128 void KGlobalAccelImpl::setEnabled(bool enable)
00129 {
00130 if (enable) {
00131 if (InstallEventHandler(m_eventTarget, m_eventHandler, 1, m_eventType, this, &m_curHandler) != noErr)
00132 kWarning(125) << "InstallEventHandler failed!";
00133 } else {
00134 if (RemoveEventHandler(m_curHandler) != noErr)
00135 kWarning(125) << "RemoveEventHandler failed!";
00136 }
00137 }
00138
00139 bool KGlobalAccelImpl::keyPressed( int key )
00140 {
00141 return m_owner->keyPressed(key);
00142 }
00143
00144 void KGlobalAccelImpl::keyboardLayoutChanged()
00145 {
00146
00147 QList<int> keys;
00148 while (!refs->empty()) {
00149 int key = refs->begin().key();
00150 keys.append(key);
00151 grabKey(key, false);
00152 }
00153
00154 foreach (int key, keys) {
00155 grabKey(key, true);
00156 }
00157 }
00158
00159 #include "kglobalaccel_mac.moc"
00160
00161 #endif // !Q_WS_MAC