Branch libreoffice-5-0-4
[LibreOffice.git] / apple_remote / source / GlobalKeyboardDevice.m
blobf5ecb1f41a1e5d30af597fb047960e9ab3c7d9f6
1 /* -*- Mode: ObjC; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*****************************************************************************
3  * GlobalKeyboardDevice.m
4  * RemoteControlWrapper
5  *
6  * Created by Martin Kahr on 11.03.06 under a MIT-style license.
7  * Copyright (c) 2006 martinkahr.com. All rights reserved.
8  *
9  * Code modified and adapted to OpenOffice.org
10  * by Eric Bachard on 11.08.2008 under the same license
11  *
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:
18  *
19  * The above copyright notice and this permission notice shall be included
20  * in all copies or substantial portions of the Software.
21  *
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
28  * THE SOFTWARE.
29  *
30  *****************************************************************************/
33 #import "GlobalKeyboardDevice.h"
35 #define F1 122
36 #define F2 120
37 #define F3 99
38 #define F4 118
39 #define F5 96
40 #define F6 97
41 #define F7 98
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
60  */
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];
79         }
80         return self;
83 - (void) dealloc {
84         [hotKeyRemoteEventMapping release];
85         [super dealloc];
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";
94                         break;
95                 case kRemoteButtonMinus:
96                         defaultsKey = @"minus";
97                         break;
98                 case kRemoteButtonMenu:
99                         defaultsKey = @"menu";
100                         break;
101                 case kRemoteButtonPlay:
102                         defaultsKey = @"play";
103                         break;
104                 case kRemoteButtonRight:
105                         defaultsKey = @"right";
106                         break;
107                 case kRemoteButtonLeft:
108                         defaultsKey = @"left";
109                         break;
110                 case kRemoteButtonPlay_Hold:
111                         defaultsKey = @"playhold";
112                         break;
113                 default:
114 #ifdef DEBUG
115                         NSLog( @"Apple Remote: Unknown global keyboard defaults key for button identifier %d", remoteButtonIdentifier);
116 #endif
117             break;
118         }
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;
134         if (value) {
135                 [self startListening: self];
136         } else {
137                 [self stopListening: self];
138         }
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 }
151         };
153         InstallEventHandler( GetEventDispatcherTarget(),
154                                                  (EventHandlerProcPtr)hotKeyEventHandler,
155                                                  2, eventSpec, self, &eventHandlerRef);
156     (void)sender;
159 - (void) stopListening: (id) sender {
160         RemoveEventHandler(eventHandlerRef);
161         eventHandlerRef = NULL;
162     (void)sender;
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;
170         }
171         return NO;
174 + (const char*) remoteControlDeviceName {
175         return "Keyboard";
178 - (BOOL)registerHotKeyCode: (unsigned int) keycode modifiers: (unsigned int) modifiers remoteEventIdentifier: (RemoteControlEventIdentifier) identifier {
179         OSStatus err;
180         EventHotKeyID hotKeyID;
181         EventHotKeyRef carbonHotKey;
183         hotKeyID.signature = 'PTHk';
184         hotKeyID.id = (long)keycode;
186         err = RegisterEventHotKey(keycode, modifiers, hotKeyID, GetEventDispatcherTarget(), 0, &carbonHotKey );
188         if( err )
189                 return NO;
191         [hotKeyRemoteEventMapping setObject: [NSNumber numberWithInt:identifier] forKey: [NSNumber numberWithUnsignedInt: hotKeyID.id]];
193         return YES;
196 - (void)unregisterHotKey: (PTHotKey*)hotKey
198         OSStatus err;
199         EventHotKeyRef carbonHotKey;
200         NSValue* key;
202         if( [[self allHotKeys] containsObject: hotKey] == NO )
203                 return;
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 )
234     (void)inHandlerRef;
235         GlobalKeyboardDevice* keyboardDevice = (GlobalKeyboardDevice*) userData;
236         EventHotKeyID hkCom;
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;
245         } else {
246                 lastEvent = 0;
247             pressedDown = NO;
248         }
249         [keyboardDevice sendRemoteButtonEvent: identifier pressedDown: pressedDown];
251         return noErr;
254 @end
256 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */