1 /* -*- Mode: ObjC; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*****************************************************************************
3 * GlobalKeyboardDevice.m
6 * Created by Martin Kahr on 11.03.06 under a MIT-style license.
7 * Copyright (c) 2006 martinkahr.com. All rights reserved.
9 * Code modified and adapted to OpenOffice.org
10 * by Eric Bachard on 11.08.2008 under the same license
12 * Permission is hereby granted, free of charge, to any person obtaining a
13 * copy of this software and associated documentation files (the "Software"),
14 * to deal in the Software without restriction, including without limitation
15 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 * and/or sell copies of the Software, and to permit persons to whom the
17 * Software is furnished to do so, subject to the following conditions:
19 * The above copyright notice and this permission notice shall be included
20 * in all copies or substantial portions of the Software.
22 * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
30 *****************************************************************************/
33 #import "GlobalKeyboardDevice.h"
44 the following default keys are read and shall be used to change the keyboard mapping
46 mac.remotecontrols.GlobalKeyboardDevice.plus_modifiers
47 mac.remotecontrols.GlobalKeyboardDevice.plus_keycode
48 mac.remotecontrols.GlobalKeyboardDevice.minus_modifiers
49 mac.remotecontrols.GlobalKeyboardDevice.minus_keycode
50 mac.remotecontrols.GlobalKeyboardDevice.play_modifiers
51 mac.remotecontrols.GlobalKeyboardDevice.play_keycode
52 mac.remotecontrols.GlobalKeyboardDevice.left_modifiers
53 mac.remotecontrols.GlobalKeyboardDevice.left_keycode
54 mac.remotecontrols.GlobalKeyboardDevice.right_modifiers
55 mac.remotecontrols.GlobalKeyboardDevice.right_keycode
56 mac.remotecontrols.GlobalKeyboardDevice.menu_modifiers
57 mac.remotecontrols.GlobalKeyboardDevice.menu_keycode
58 mac.remotecontrols.GlobalKeyboardDevice.playhold_modifiers
59 mac.remotecontrols.GlobalKeyboardDevice.playhold_keycode
62 static OSStatus hotKeyEventHandler(EventHandlerCallRef, EventRef, void*);
64 @implementation GlobalKeyboardDevice
66 - (id) initWithDelegate: (id) _remoteControlDelegate {
67 if ( (self = [super initWithDelegate: _remoteControlDelegate]) ) {
68 hotKeyRemoteEventMapping = [[NSMutableDictionary alloc] init];
70 unsigned int modifiers = cmdKey + shiftKey /*+ optionKey*/ + controlKey;
72 [self mapRemoteButton:kRemoteButtonPlus defaultKeycode:F1 defaultModifiers:modifiers];
73 [self mapRemoteButton:kRemoteButtonMinus defaultKeycode:F2 defaultModifiers:modifiers];
74 [self mapRemoteButton:kRemoteButtonPlay defaultKeycode:F3 defaultModifiers:modifiers];
75 [self mapRemoteButton:kRemoteButtonLeft defaultKeycode:F4 defaultModifiers:modifiers];
76 [self mapRemoteButton:kRemoteButtonRight defaultKeycode:F5 defaultModifiers:modifiers];
77 [self mapRemoteButton:kRemoteButtonMenu defaultKeycode:F6 defaultModifiers:modifiers];
78 [self mapRemoteButton:kRemoteButtonPlay_Hold defaultKeycode:F7 defaultModifiers:modifiers];
84 [hotKeyRemoteEventMapping release];
88 - (void) mapRemoteButton: (RemoteControlEventIdentifier) remoteButtonIdentifier defaultKeycode: (unsigned int) defaultKeycode defaultModifiers: (unsigned int) defaultModifiers {
89 NSString* defaultsKey = NULL;
91 switch(remoteButtonIdentifier) {
92 case kRemoteButtonPlus:
93 defaultsKey = @"plus";
95 case kRemoteButtonMinus:
96 defaultsKey = @"minus";
98 case kRemoteButtonMenu:
99 defaultsKey = @"menu";
101 case kRemoteButtonPlay:
102 defaultsKey = @"play";
104 case kRemoteButtonRight:
105 defaultsKey = @"right";
107 case kRemoteButtonLeft:
108 defaultsKey = @"left";
110 case kRemoteButtonPlay_Hold:
111 defaultsKey = @"playhold";
115 NSLog( @"Apple Remote: Unknown global keyboard defaults key for button identifier %d", remoteButtonIdentifier);
120 NSNumber* modifiersCfg = [[NSUserDefaults standardUserDefaults] objectForKey: [NSString stringWithFormat: @"mac.remotecontrols.GlobalKeyboardDevice.%@_modifiers", defaultsKey]];
121 NSNumber* keycodeCfg = [[NSUserDefaults standardUserDefaults] objectForKey: [NSString stringWithFormat: @"mac.remotecontrols.GlobalKeyboardDevice.%@_keycode", defaultsKey]];
123 unsigned int modifiers = defaultModifiers;
124 if (modifiersCfg) modifiers = [modifiersCfg unsignedIntValue];
126 unsigned int keycode = defaultKeycode;
127 if (keycodeCfg) keycode = [keycodeCfg unsignedIntValue];
129 [self registerHotKeyCode: keycode modifiers: modifiers remoteEventIdentifier: remoteButtonIdentifier];
132 - (void) setListeningToRemote: (BOOL) value {
133 if (value == [self isListeningToRemote]) return;
135 [self startListening: self];
137 [self stopListening: self];
140 - (BOOL) isListeningToRemote {
141 return (eventHandlerRef!=NULL);
144 - (void) startListening: (id) sender {
146 if (eventHandlerRef) return;
148 EventTypeSpec eventSpec[2] = {
149 { kEventClassKeyboard, kEventHotKeyPressed },
150 { kEventClassKeyboard, kEventHotKeyReleased }
153 InstallEventHandler( GetEventDispatcherTarget(),
154 (EventHandlerProcPtr)hotKeyEventHandler,
155 2, eventSpec, self, &eventHandlerRef);
159 - (void) stopListening: (id) sender {
160 RemoveEventHandler(eventHandlerRef);
161 eventHandlerRef = NULL;
165 - (BOOL) sendsEventForButtonIdentifier: (RemoteControlEventIdentifier) identifier {
166 NSEnumerator* values = [hotKeyRemoteEventMapping objectEnumerator];
167 NSNumber* remoteIdentifier;
168 while( (remoteIdentifier = [values nextObject]) ) {
169 if ([remoteIdentifier unsignedIntValue] == identifier) return YES;
174 + (const char*) remoteControlDeviceName {
178 - (BOOL)registerHotKeyCode: (unsigned int) keycode modifiers: (unsigned int) modifiers remoteEventIdentifier: (RemoteControlEventIdentifier) identifier {
180 EventHotKeyID hotKeyID;
181 EventHotKeyRef carbonHotKey;
183 hotKeyID.signature = 'PTHk';
184 hotKeyID.id = (long)keycode;
186 err = RegisterEventHotKey(keycode, modifiers, hotKeyID, GetEventDispatcherTarget(), 0, &carbonHotKey );
191 [hotKeyRemoteEventMapping setObject: [NSNumber numberWithInt:identifier] forKey: [NSNumber numberWithUnsignedInt: hotKeyID.id]];
196 - (void)unregisterHotKey: (PTHotKey*)hotKey
199 EventHotKeyRef carbonHotKey;
202 if( [[self allHotKeys] containsObject: hotKey] == NO )
205 carbonHotKey = [self _carbonHotKeyForHotKey: hotKey];
206 NSAssert( carbonHotKey != nil, @"" );
208 err = UnregisterEventHotKey( carbonHotKey );
209 //Watch as we ignore 'err':
211 key = [NSValue valueWithPointer: carbonHotKey];
212 [mHotKeys removeObjectForKey: key];
214 [self _updateEventHandler];
216 //See that? Completely ignored
220 - (RemoteControlEventIdentifier) remoteControlEventIdentifierForID: (unsigned int) id {
221 NSNumber* remoteEventIdentifier = [hotKeyRemoteEventMapping objectForKey:[NSNumber numberWithUnsignedInt: id]];
222 return [remoteEventIdentifier unsignedIntValue];
225 - (void) sendRemoteButtonEvent: (RemoteControlEventIdentifier) event pressedDown: (BOOL) pressedDown {
226 [delegate sendRemoteButtonEvent: event pressedDown: pressedDown remoteControl:self];
229 static RemoteControlEventIdentifier lastEvent;
232 static OSStatus hotKeyEventHandler(EventHandlerCallRef inHandlerRef, EventRef inEvent, void* userData )
235 GlobalKeyboardDevice* keyboardDevice = (GlobalKeyboardDevice*) userData;
237 GetEventParameter(inEvent,kEventParamDirectObject,typeEventHotKeyID,NULL,sizeof(hkCom),NULL,&hkCom);
239 RemoteControlEventIdentifier identifier = [keyboardDevice remoteControlEventIdentifierForID:hkCom.id];
240 if (identifier == 0) return noErr;
242 BOOL pressedDown = YES;
243 if (identifier != lastEvent) {
244 lastEvent = identifier;
249 [keyboardDevice sendRemoteButtonEvent: identifier pressedDown: pressedDown];
256 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */