1 /* This file is part of the KDE libraries
2 Copyright (C) 2001,2002 Ellis Whitehead <ellis@kde.org>
3 Copyright (C) 2006 Marijn Kruisselbrink <m.kruisselbrink@student.tue.nl>
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
21 #include "kglobalaccel_mac.h"
30 #include "globalshortcutsregistry.h"
31 #include "kkeyserver.h"
33 OSStatus
hotKeyEventHandler(EventHandlerCallRef inHandlerCallRef
, EventRef inEvent
, void * inUserData
)
35 UInt32 eventKind
= GetEventKind(inEvent
);
36 if (eventKind
== kEventRawKeyDown
) {
38 if (GetEventParameter(inEvent
, kEventParamKeyCode
, typeUInt32
, NULL
, sizeof(keycode
), NULL
, &keycode
) != noErr
) {
39 kWarning(125) << "Error retrieving keycode parameter from event";
41 kDebug() << " key down, keycode = " << keycode
;
42 } else if (eventKind
== kEventHotKeyPressed
) {
43 KGlobalAccelImpl
* impl
= static_cast<KGlobalAccelImpl
*>(inUserData
);
45 if (GetEventParameter(inEvent
, kEventParamDirectObject
, typeEventHotKeyID
, NULL
, sizeof(hotkey
), NULL
, &hotkey
) != noErr
) {
46 kWarning(125) << "Error retrieving hotkey parameter from event";
47 return eventNotHandledErr
;
49 // Typecasts necesary to prevent a warning from gcc
50 return (impl
->keyPressed(hotkey
.id
) ? (OSStatus
) noErr
: (OSStatus
) eventNotHandledErr
);
52 return eventNotHandledErr
;
55 void layoutChanged(CFNotificationCenterRef center
, void *observer
, CFStringRef name
, const void *object
, CFDictionaryRef userInfo
) {
56 static_cast<KGlobalAccelImpl
*>(observer
)->keyboardLayoutChanged();
59 KGlobalAccelImpl::KGlobalAccelImpl(GlobalShortcutsRegistry
* owner
)
61 , m_eventTarget(GetApplicationEventTarget())
62 , m_eventHandler(NewEventHandlerUPP(hotKeyEventHandler
))
64 m_eventType
[0].eventClass
= kEventClassKeyboard
;
65 m_eventType
[0].eventKind
= kEventHotKeyPressed
;
66 m_eventType
[1].eventClass
= kEventClassKeyboard
; // only useful for testing, is not used because count passed in call to InstallEventHandler is 1
67 m_eventType
[1].eventKind
= kEventRawKeyDown
;
68 refs
= new QMap
<int, QList
<EventHotKeyRef
> >();
70 CFStringRef str
= CFStringCreateWithCString(NULL
, "AppleKeyboardPreferencesChangedNotification", kCFStringEncodingASCII
);
72 CFNotificationCenterAddObserver(CFNotificationCenterGetDistributedCenter(), this, layoutChanged
, str
, NULL
, CFNotificationSuspensionBehaviorHold
);
75 kWarning(125) << "Couldn't create CFString to register for keyboard notifications";
79 KGlobalAccelImpl::~KGlobalAccelImpl()
81 DisposeEventHandlerUPP(hotKeyEventHandler
);
82 CFNotificationCenterRemoveObserver(CFNotificationCenterGetDistributedCenter(), this, NULL
, NULL
);
86 bool KGlobalAccelImpl::grabKey( int keyQt
, bool grab
)
89 kDebug() << "Grabbing key " << keyQt
;
92 KKeyServer::keyQtToCodeMac( keyQt
, keyCodes
);
93 KKeyServer::keyQtToModMac( keyQt
, mod
);
95 kDebug() << "keyQt: " << keyQt
<< " mod: " << mod
;
96 foreach (uint keyCode
, keyCodes
) {
97 kDebug() << " keyCode: " << keyCode
;
101 ehkid
.signature
= 'Kgai';
103 QList
<EventHotKeyRef
> hotkeys
;
104 foreach (uint keyCode
, keyCodes
) {
106 if (RegisterEventHotKey(keyCode
, mod
, ehkid
, m_eventTarget
, 0, &ref
) != noErr
) {
107 kWarning(125) << "RegisterEventHotKey failed!";
111 refs
->insert(keyQt
, hotkeys
);
113 kDebug() << "Ungrabbing key " << keyQt
;
114 if (refs
->count(keyQt
) == 0) kWarning(125) << "Trying to ungrab a key thas is not grabbed";
115 foreach (const EventHotKeyRef
&ref
, refs
->value(keyQt
)) {
116 if (UnregisterEventHotKey(ref
) != noErr
) {
117 kWarning(125) << "UnregisterEventHotKey should not fail!";
125 void KGlobalAccelImpl::setEnabled(bool enable
)
128 if (InstallEventHandler(m_eventTarget
, m_eventHandler
, 1, m_eventType
, this, &m_curHandler
) != noErr
)
129 kWarning(125) << "InstallEventHandler failed!";
131 if (RemoveEventHandler(m_curHandler
) != noErr
)
132 kWarning(125) << "RemoveEventHandler failed!";
136 bool KGlobalAccelImpl::keyPressed( int key
)
138 return m_owner
->keyPressed(key
);
141 void KGlobalAccelImpl::keyboardLayoutChanged()
143 // Keyboard layout might have changed, first ungrab all keys
144 QList
<int> keys
; // Array to store all the keys that were grabbed
145 while (!refs
->empty()) {
146 int key
= refs
->begin().key();
150 // Now re-grab all the keys
151 foreach (int key
, keys
) {
156 #include "kglobalaccel_mac.moc"