1 /*****************************************************************************
2 * GlobalKeyboardDevice.m
5 * Created by Martin Kahr on 11.03.06 under a MIT-style license.
6 * Copyright (c) 2006 martinkahr.com. All rights reserved.
8 * Code modified and adapted to OpenOffice.org
9 * by Eric Bachard on 11.08.2008 under the same license
11 * Permission is hereby granted, free of charge, to any person obtaining a
12 * copy of this software and associated documentation files (the "Software"),
13 * to deal in the Software without restriction, including without limitation
14 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 * and/or sell copies of the Software, and to permit persons to whom the
16 * Software is furnished to do so, subject to the following conditions:
18 * The above copyright notice and this permission notice shall be included
19 * in all copies or substantial portions of the Software.
21 * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29 *****************************************************************************/
32 #import "GlobalKeyboardDevice.h"
43 the following default keys are read and shall be used to change the keyboard mapping
45 mac.remotecontrols.GlobalKeyboardDevice.plus_modifiers
46 mac.remotecontrols.GlobalKeyboardDevice.plus_keycode
47 mac.remotecontrols.GlobalKeyboardDevice.minus_modifiers
48 mac.remotecontrols.GlobalKeyboardDevice.minus_keycode
49 mac.remotecontrols.GlobalKeyboardDevice.play_modifiers
50 mac.remotecontrols.GlobalKeyboardDevice.play_keycode
51 mac.remotecontrols.GlobalKeyboardDevice.left_modifiers
52 mac.remotecontrols.GlobalKeyboardDevice.left_keycode
53 mac.remotecontrols.GlobalKeyboardDevice.right_modifiers
54 mac.remotecontrols.GlobalKeyboardDevice.right_keycode
55 mac.remotecontrols.GlobalKeyboardDevice.menu_modifiers
56 mac.remotecontrols.GlobalKeyboardDevice.menu_keycode
57 mac.remotecontrols.GlobalKeyboardDevice.playhold_modifiers
58 mac.remotecontrols.GlobalKeyboardDevice.playhold_keycode
61 static OSStatus hotKeyEventHandler(EventHandlerCallRef, EventRef, void*);
63 @implementation GlobalKeyboardDevice
65 - (id) initWithDelegate: (id) _remoteControlDelegate {
66 if ( (self = [super initWithDelegate: _remoteControlDelegate]) ) {
67 hotKeyRemoteEventMapping = [[NSMutableDictionary alloc] init];
69 unsigned int modifiers = cmdKey + shiftKey /*+ optionKey*/ + controlKey;
71 [self mapRemoteButton:kRemoteButtonPlus defaultKeycode:F1 defaultModifiers:modifiers];
72 [self mapRemoteButton:kRemoteButtonMinus defaultKeycode:F2 defaultModifiers:modifiers];
73 [self mapRemoteButton:kRemoteButtonPlay defaultKeycode:F3 defaultModifiers:modifiers];
74 [self mapRemoteButton:kRemoteButtonLeft defaultKeycode:F4 defaultModifiers:modifiers];
75 [self mapRemoteButton:kRemoteButtonRight defaultKeycode:F5 defaultModifiers:modifiers];
76 [self mapRemoteButton:kRemoteButtonMenu defaultKeycode:F6 defaultModifiers:modifiers];
77 [self mapRemoteButton:kRemoteButtonPlay_Hold defaultKeycode:F7 defaultModifiers:modifiers];
83 [hotKeyRemoteEventMapping release];
87 - (void) mapRemoteButton: (RemoteControlEventIdentifier) remoteButtonIdentifier defaultKeycode: (unsigned int) defaultKeycode defaultModifiers: (unsigned int) defaultModifiers {
88 NSString* defaultsKey = NULL;
90 switch(remoteButtonIdentifier) {
91 case kRemoteButtonPlus:
92 defaultsKey = @"plus";
94 case kRemoteButtonMinus:
95 defaultsKey = @"minus";
97 case kRemoteButtonMenu:
98 defaultsKey = @"menu";
100 case kRemoteButtonPlay:
101 defaultsKey = @"play";
103 case kRemoteButtonRight:
104 defaultsKey = @"right";
106 case kRemoteButtonLeft:
107 defaultsKey = @"left";
109 case kRemoteButtonPlay_Hold:
110 defaultsKey = @"playhold";
114 NSLog(@"Unknown global keyboard defaults key for remote button identifier %d", remoteButtonIdentifier);
119 NSNumber* modifiersCfg = [[NSUserDefaults standardUserDefaults] objectForKey: [NSString stringWithFormat: @"mac.remotecontrols.GlobalKeyboardDevice.%@_modifiers", defaultsKey]];
120 NSNumber* keycodeCfg = [[NSUserDefaults standardUserDefaults] objectForKey: [NSString stringWithFormat: @"mac.remotecontrols.GlobalKeyboardDevice.%@_keycode", defaultsKey]];
122 unsigned int modifiers = defaultModifiers;
123 if (modifiersCfg) modifiers = [modifiersCfg unsignedIntValue];
125 unsigned int keycode = defaultKeycode;
126 if (keycodeCfg) keycode = [keycodeCfg unsignedIntValue];
128 [self registerHotKeyCode: keycode modifiers: modifiers remoteEventIdentifier: remoteButtonIdentifier];
131 - (void) setListeningToRemote: (BOOL) value {
132 if (value == [self isListeningToRemote]) return;
134 [self startListening: self];
136 [self stopListening: self];
139 - (BOOL) isListeningToRemote {
140 return (eventHandlerRef!=NULL);
143 - (void) startListening: (id) sender {
145 if (eventHandlerRef) return;
147 EventTypeSpec eventSpec[2] = {
148 { kEventClassKeyboard, kEventHotKeyPressed },
149 { kEventClassKeyboard, kEventHotKeyReleased }
152 InstallEventHandler( GetEventDispatcherTarget(),
153 (EventHandlerProcPtr)hotKeyEventHandler,
154 2, eventSpec, self, &eventHandlerRef);
156 - (void) stopListening: (id) sender {
157 RemoveEventHandler(eventHandlerRef);
158 eventHandlerRef = NULL;
161 - (BOOL) sendsEventForButtonIdentifier: (RemoteControlEventIdentifier) identifier {
162 NSEnumerator* values = [hotKeyRemoteEventMapping objectEnumerator];
163 NSNumber* remoteIdentifier;
164 while( (remoteIdentifier = [values nextObject]) ) {
165 if ([remoteIdentifier unsignedIntValue] == identifier) return YES;
170 + (const char*) remoteControlDeviceName {
174 - (BOOL)registerHotKeyCode: (unsigned int) keycode modifiers: (unsigned int) modifiers remoteEventIdentifier: (RemoteControlEventIdentifier) identifier {
176 EventHotKeyID hotKeyID;
177 EventHotKeyRef carbonHotKey;
179 hotKeyID.signature = 'PTHk';
180 hotKeyID.id = (long)keycode;
182 err = RegisterEventHotKey(keycode, modifiers, hotKeyID, GetEventDispatcherTarget(), 0, &carbonHotKey );
187 [hotKeyRemoteEventMapping setObject: [NSNumber numberWithInt:identifier] forKey: [NSNumber numberWithUnsignedInt: hotKeyID.id]];
192 - (void)unregisterHotKey: (PTHotKey*)hotKey
195 EventHotKeyRef carbonHotKey;
198 if( [[self allHotKeys] containsObject: hotKey] == NO )
201 carbonHotKey = [self _carbonHotKeyForHotKey: hotKey];
202 NSAssert( carbonHotKey != nil, @"" );
204 err = UnregisterEventHotKey( carbonHotKey );
205 //Watch as we ignore 'err':
207 key = [NSValue valueWithPointer: carbonHotKey];
208 [mHotKeys removeObjectForKey: key];
210 [self _updateEventHandler];
212 //See that? Completely ignored
216 - (RemoteControlEventIdentifier) remoteControlEventIdentifierForID: (unsigned int) id {
217 NSNumber* remoteEventIdentifier = [hotKeyRemoteEventMapping objectForKey:[NSNumber numberWithUnsignedInt: id]];
218 return [remoteEventIdentifier unsignedIntValue];
221 - (void) sendRemoteButtonEvent: (RemoteControlEventIdentifier) event pressedDown: (BOOL) pressedDown {
222 [delegate sendRemoteButtonEvent: event pressedDown: pressedDown remoteControl:self];
225 static RemoteControlEventIdentifier lastEvent;
228 static OSStatus hotKeyEventHandler(EventHandlerCallRef inHandlerRef, EventRef inEvent, void* userData )
230 GlobalKeyboardDevice* keyboardDevice = (GlobalKeyboardDevice*) userData;
232 GetEventParameter(inEvent,kEventParamDirectObject,typeEventHotKeyID,NULL,sizeof(hkCom),NULL,&hkCom);
234 RemoteControlEventIdentifier identifier = [keyboardDevice remoteControlEventIdentifierForID:hkCom.id];
235 if (identifier == 0) return noErr;
237 BOOL pressedDown = YES;
238 if (identifier != lastEvent) {
239 lastEvent = identifier;
244 [keyboardDevice sendRemoteButtonEvent: identifier pressedDown: pressedDown];