1cdf0e10cSrcweir/***************************************************************************** 2cdf0e10cSrcweir * GlobalKeyboardDevice.m 3cdf0e10cSrcweir * RemoteControlWrapper 4cdf0e10cSrcweir * 5cdf0e10cSrcweir * Created by Martin Kahr on 11.03.06 under a MIT-style license. 6cdf0e10cSrcweir * Copyright (c) 2006 martinkahr.com. All rights reserved. 7cdf0e10cSrcweir * 8cdf0e10cSrcweir * Code modified and adapted to OpenOffice.org 9cdf0e10cSrcweir * by Eric Bachard on 11.08.2008 under the same license 10cdf0e10cSrcweir * 11cdf0e10cSrcweir * Permission is hereby granted, free of charge, to any person obtaining a 12cdf0e10cSrcweir * copy of this software and associated documentation files (the "Software"), 13cdf0e10cSrcweir * to deal in the Software without restriction, including without limitation 14cdf0e10cSrcweir * the rights to use, copy, modify, merge, publish, distribute, sublicense, 15cdf0e10cSrcweir * and/or sell copies of the Software, and to permit persons to whom the 16cdf0e10cSrcweir * Software is furnished to do so, subject to the following conditions: 17cdf0e10cSrcweir * 18cdf0e10cSrcweir * The above copyright notice and this permission notice shall be included 19cdf0e10cSrcweir * in all copies or substantial portions of the Software. 20cdf0e10cSrcweir * 21cdf0e10cSrcweir * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22cdf0e10cSrcweir * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23cdf0e10cSrcweir * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 24cdf0e10cSrcweir * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25cdf0e10cSrcweir * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26cdf0e10cSrcweir * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27cdf0e10cSrcweir * THE SOFTWARE. 28cdf0e10cSrcweir * 29cdf0e10cSrcweir *****************************************************************************/ 30cdf0e10cSrcweir 31cdf0e10cSrcweir 32cdf0e10cSrcweir#import "GlobalKeyboardDevice.h" 33cdf0e10cSrcweir 34cdf0e10cSrcweir#define F1 122 35cdf0e10cSrcweir#define F2 120 36cdf0e10cSrcweir#define F3 99 37cdf0e10cSrcweir#define F4 118 38cdf0e10cSrcweir#define F5 96 39cdf0e10cSrcweir#define F6 97 40cdf0e10cSrcweir#define F7 98 41cdf0e10cSrcweir 42cdf0e10cSrcweir/* 43cdf0e10cSrcweir the following default keys are read and shall be used to change the keyboard mapping 44cdf0e10cSrcweir 45cdf0e10cSrcweir mac.remotecontrols.GlobalKeyboardDevice.plus_modifiers 46cdf0e10cSrcweir mac.remotecontrols.GlobalKeyboardDevice.plus_keycode 47cdf0e10cSrcweir mac.remotecontrols.GlobalKeyboardDevice.minus_modifiers 48cdf0e10cSrcweir mac.remotecontrols.GlobalKeyboardDevice.minus_keycode 49cdf0e10cSrcweir mac.remotecontrols.GlobalKeyboardDevice.play_modifiers 50cdf0e10cSrcweir mac.remotecontrols.GlobalKeyboardDevice.play_keycode 51cdf0e10cSrcweir mac.remotecontrols.GlobalKeyboardDevice.left_modifiers 52cdf0e10cSrcweir mac.remotecontrols.GlobalKeyboardDevice.left_keycode 53cdf0e10cSrcweir mac.remotecontrols.GlobalKeyboardDevice.right_modifiers 54cdf0e10cSrcweir mac.remotecontrols.GlobalKeyboardDevice.right_keycode 55cdf0e10cSrcweir mac.remotecontrols.GlobalKeyboardDevice.menu_modifiers 56cdf0e10cSrcweir mac.remotecontrols.GlobalKeyboardDevice.menu_keycode 57cdf0e10cSrcweir mac.remotecontrols.GlobalKeyboardDevice.playhold_modifiers 58cdf0e10cSrcweir mac.remotecontrols.GlobalKeyboardDevice.playhold_keycode 59cdf0e10cSrcweir */ 60cdf0e10cSrcweir 61cdf0e10cSrcweirstatic OSStatus hotKeyEventHandler(EventHandlerCallRef, EventRef, void*); 62cdf0e10cSrcweir 63cdf0e10cSrcweir@implementation GlobalKeyboardDevice 64cdf0e10cSrcweir 65cdf0e10cSrcweir- (id) initWithDelegate: (id) _remoteControlDelegate { 66cdf0e10cSrcweir if ( (self = [super initWithDelegate: _remoteControlDelegate]) ) { 67cdf0e10cSrcweir hotKeyRemoteEventMapping = [[NSMutableDictionary alloc] init]; 68cdf0e10cSrcweir 69cdf0e10cSrcweir unsigned int modifiers = cmdKey + shiftKey /*+ optionKey*/ + controlKey; 70cdf0e10cSrcweir 71cdf0e10cSrcweir [self mapRemoteButton:kRemoteButtonPlus defaultKeycode:F1 defaultModifiers:modifiers]; 72cdf0e10cSrcweir [self mapRemoteButton:kRemoteButtonMinus defaultKeycode:F2 defaultModifiers:modifiers]; 73cdf0e10cSrcweir [self mapRemoteButton:kRemoteButtonPlay defaultKeycode:F3 defaultModifiers:modifiers]; 74cdf0e10cSrcweir [self mapRemoteButton:kRemoteButtonLeft defaultKeycode:F4 defaultModifiers:modifiers]; 75cdf0e10cSrcweir [self mapRemoteButton:kRemoteButtonRight defaultKeycode:F5 defaultModifiers:modifiers]; 76cdf0e10cSrcweir [self mapRemoteButton:kRemoteButtonMenu defaultKeycode:F6 defaultModifiers:modifiers]; 77cdf0e10cSrcweir [self mapRemoteButton:kRemoteButtonPlay_Hold defaultKeycode:F7 defaultModifiers:modifiers]; 78cdf0e10cSrcweir } 79cdf0e10cSrcweir return self; 80cdf0e10cSrcweir} 81cdf0e10cSrcweir 82cdf0e10cSrcweir- (void) dealloc { 83cdf0e10cSrcweir [hotKeyRemoteEventMapping release]; 84cdf0e10cSrcweir [super dealloc]; 85cdf0e10cSrcweir} 86cdf0e10cSrcweir 87cdf0e10cSrcweir- (void) mapRemoteButton: (RemoteControlEventIdentifier) remoteButtonIdentifier defaultKeycode: (unsigned int) defaultKeycode defaultModifiers: (unsigned int) defaultModifiers { 88cdf0e10cSrcweir NSString* defaultsKey = NULL; 89cdf0e10cSrcweir 90cdf0e10cSrcweir switch(remoteButtonIdentifier) { 91cdf0e10cSrcweir case kRemoteButtonPlus: 92cdf0e10cSrcweir defaultsKey = @"plus"; 93cdf0e10cSrcweir break; 94cdf0e10cSrcweir case kRemoteButtonMinus: 95cdf0e10cSrcweir defaultsKey = @"minus"; 96cdf0e10cSrcweir break; 97cdf0e10cSrcweir case kRemoteButtonMenu: 98cdf0e10cSrcweir defaultsKey = @"menu"; 99cdf0e10cSrcweir break; 100cdf0e10cSrcweir case kRemoteButtonPlay: 101cdf0e10cSrcweir defaultsKey = @"play"; 102cdf0e10cSrcweir break; 103cdf0e10cSrcweir case kRemoteButtonRight: 104cdf0e10cSrcweir defaultsKey = @"right"; 105cdf0e10cSrcweir break; 106cdf0e10cSrcweir case kRemoteButtonLeft: 107cdf0e10cSrcweir defaultsKey = @"left"; 108cdf0e10cSrcweir break; 109cdf0e10cSrcweir case kRemoteButtonPlay_Hold: 110cdf0e10cSrcweir defaultsKey = @"playhold"; 111cdf0e10cSrcweir break; 112cdf0e10cSrcweir default: 113cdf0e10cSrcweir#ifdef DEBUG 11453e04a5dSHerbert Dürr NSLog( @"Apple Remote: Unknown global keyboard defaults key for button identifier %d", remoteButtonIdentifier); 115cdf0e10cSrcweir#endif 116cdf0e10cSrcweir break; 117cdf0e10cSrcweir } 118cdf0e10cSrcweir 119cdf0e10cSrcweir NSNumber* modifiersCfg = [[NSUserDefaults standardUserDefaults] objectForKey: [NSString stringWithFormat: @"mac.remotecontrols.GlobalKeyboardDevice.%@_modifiers", defaultsKey]]; 120cdf0e10cSrcweir NSNumber* keycodeCfg = [[NSUserDefaults standardUserDefaults] objectForKey: [NSString stringWithFormat: @"mac.remotecontrols.GlobalKeyboardDevice.%@_keycode", defaultsKey]]; 121cdf0e10cSrcweir 122cdf0e10cSrcweir unsigned int modifiers = defaultModifiers; 123cdf0e10cSrcweir if (modifiersCfg) modifiers = [modifiersCfg unsignedIntValue]; 124cdf0e10cSrcweir 125cdf0e10cSrcweir unsigned int keycode = defaultKeycode; 126cdf0e10cSrcweir if (keycodeCfg) keycode = [keycodeCfg unsignedIntValue]; 127cdf0e10cSrcweir 128cdf0e10cSrcweir [self registerHotKeyCode: keycode modifiers: modifiers remoteEventIdentifier: remoteButtonIdentifier]; 129cdf0e10cSrcweir} 130cdf0e10cSrcweir 131cdf0e10cSrcweir- (void) setListeningToRemote: (BOOL) value { 132cdf0e10cSrcweir if (value == [self isListeningToRemote]) return; 133cdf0e10cSrcweir if (value) { 134cdf0e10cSrcweir [self startListening: self]; 135cdf0e10cSrcweir } else { 136cdf0e10cSrcweir [self stopListening: self]; 137cdf0e10cSrcweir } 138cdf0e10cSrcweir} 139cdf0e10cSrcweir- (BOOL) isListeningToRemote { 140cdf0e10cSrcweir return (eventHandlerRef!=NULL); 141cdf0e10cSrcweir} 142cdf0e10cSrcweir 143cdf0e10cSrcweir- (void) startListening: (id) sender { 144cdf0e10cSrcweir 145cdf0e10cSrcweir if (eventHandlerRef) return; 146cdf0e10cSrcweir 147cdf0e10cSrcweir EventTypeSpec eventSpec[2] = { 148cdf0e10cSrcweir { kEventClassKeyboard, kEventHotKeyPressed }, 149cdf0e10cSrcweir { kEventClassKeyboard, kEventHotKeyReleased } 150cdf0e10cSrcweir }; 151cdf0e10cSrcweir 152cdf0e10cSrcweir InstallEventHandler( GetEventDispatcherTarget(), 153cdf0e10cSrcweir (EventHandlerProcPtr)hotKeyEventHandler, 154cdf0e10cSrcweir 2, eventSpec, self, &eventHandlerRef); 155cdf0e10cSrcweir} 156cdf0e10cSrcweir- (void) stopListening: (id) sender { 157cdf0e10cSrcweir RemoveEventHandler(eventHandlerRef); 158cdf0e10cSrcweir eventHandlerRef = NULL; 159cdf0e10cSrcweir} 160cdf0e10cSrcweir 161cdf0e10cSrcweir- (BOOL) sendsEventForButtonIdentifier: (RemoteControlEventIdentifier) identifier { 162cdf0e10cSrcweir NSEnumerator* values = [hotKeyRemoteEventMapping objectEnumerator]; 163cdf0e10cSrcweir NSNumber* remoteIdentifier; 164cdf0e10cSrcweir while( (remoteIdentifier = [values nextObject]) ) { 165cdf0e10cSrcweir if ([remoteIdentifier unsignedIntValue] == identifier) return YES; 166cdf0e10cSrcweir } 167cdf0e10cSrcweir return NO; 168cdf0e10cSrcweir} 169cdf0e10cSrcweir 170cdf0e10cSrcweir+ (const char*) remoteControlDeviceName { 171cdf0e10cSrcweir return "Keyboard"; 172cdf0e10cSrcweir} 173cdf0e10cSrcweir 174cdf0e10cSrcweir- (BOOL)registerHotKeyCode: (unsigned int) keycode modifiers: (unsigned int) modifiers remoteEventIdentifier: (RemoteControlEventIdentifier) identifier { 175cdf0e10cSrcweir OSStatus err; 176cdf0e10cSrcweir EventHotKeyID hotKeyID; 177cdf0e10cSrcweir EventHotKeyRef carbonHotKey; 178cdf0e10cSrcweir 179cdf0e10cSrcweir hotKeyID.signature = 'PTHk'; 180cdf0e10cSrcweir hotKeyID.id = (long)keycode; 181cdf0e10cSrcweir 182cdf0e10cSrcweir err = RegisterEventHotKey(keycode, modifiers, hotKeyID, GetEventDispatcherTarget(), 0, &carbonHotKey ); 183cdf0e10cSrcweir 184cdf0e10cSrcweir if( err ) 185cdf0e10cSrcweir return NO; 186cdf0e10cSrcweir 187cdf0e10cSrcweir [hotKeyRemoteEventMapping setObject: [NSNumber numberWithInt:identifier] forKey: [NSNumber numberWithUnsignedInt: hotKeyID.id]]; 188cdf0e10cSrcweir 189cdf0e10cSrcweir return YES; 190cdf0e10cSrcweir} 191cdf0e10cSrcweir/* 192cdf0e10cSrcweir- (void)unregisterHotKey: (PTHotKey*)hotKey 193cdf0e10cSrcweir{ 194cdf0e10cSrcweir OSStatus err; 195cdf0e10cSrcweir EventHotKeyRef carbonHotKey; 196cdf0e10cSrcweir NSValue* key; 197cdf0e10cSrcweir 198cdf0e10cSrcweir if( [[self allHotKeys] containsObject: hotKey] == NO ) 199cdf0e10cSrcweir return; 200cdf0e10cSrcweir 201cdf0e10cSrcweir carbonHotKey = [self _carbonHotKeyForHotKey: hotKey]; 202cdf0e10cSrcweir NSAssert( carbonHotKey != nil, @"" ); 203cdf0e10cSrcweir 204cdf0e10cSrcweir err = UnregisterEventHotKey( carbonHotKey ); 205cdf0e10cSrcweir //Watch as we ignore 'err': 206cdf0e10cSrcweir 207cdf0e10cSrcweir key = [NSValue valueWithPointer: carbonHotKey]; 208cdf0e10cSrcweir [mHotKeys removeObjectForKey: key]; 209cdf0e10cSrcweir 210cdf0e10cSrcweir [self _updateEventHandler]; 211cdf0e10cSrcweir 212cdf0e10cSrcweir //See that? Completely ignored 213cdf0e10cSrcweir} 214cdf0e10cSrcweir*/ 215cdf0e10cSrcweir 216cdf0e10cSrcweir- (RemoteControlEventIdentifier) remoteControlEventIdentifierForID: (unsigned int) id { 217cdf0e10cSrcweir NSNumber* remoteEventIdentifier = [hotKeyRemoteEventMapping objectForKey:[NSNumber numberWithUnsignedInt: id]]; 218cdf0e10cSrcweir return [remoteEventIdentifier unsignedIntValue]; 219cdf0e10cSrcweir} 220cdf0e10cSrcweir 221cdf0e10cSrcweir- (void) sendRemoteButtonEvent: (RemoteControlEventIdentifier) event pressedDown: (BOOL) pressedDown { 222cdf0e10cSrcweir [delegate sendRemoteButtonEvent: event pressedDown: pressedDown remoteControl:self]; 223cdf0e10cSrcweir} 224cdf0e10cSrcweir 225cdf0e10cSrcweirstatic RemoteControlEventIdentifier lastEvent; 226cdf0e10cSrcweir 227cdf0e10cSrcweir 228cdf0e10cSrcweirstatic OSStatus hotKeyEventHandler(EventHandlerCallRef inHandlerRef, EventRef inEvent, void* userData ) 229cdf0e10cSrcweir{ 230cdf0e10cSrcweir GlobalKeyboardDevice* keyboardDevice = (GlobalKeyboardDevice*) userData; 231cdf0e10cSrcweir EventHotKeyID hkCom; 232cdf0e10cSrcweir GetEventParameter(inEvent,kEventParamDirectObject,typeEventHotKeyID,NULL,sizeof(hkCom),NULL,&hkCom); 233cdf0e10cSrcweir 234cdf0e10cSrcweir RemoteControlEventIdentifier identifier = [keyboardDevice remoteControlEventIdentifierForID:hkCom.id]; 235cdf0e10cSrcweir if (identifier == 0) return noErr; 236cdf0e10cSrcweir 237cdf0e10cSrcweir BOOL pressedDown = YES; 238cdf0e10cSrcweir if (identifier != lastEvent) { 239cdf0e10cSrcweir lastEvent = identifier; 240cdf0e10cSrcweir } else { 241cdf0e10cSrcweir lastEvent = 0; 242cdf0e10cSrcweir pressedDown = NO; 243cdf0e10cSrcweir } 244cdf0e10cSrcweir [keyboardDevice sendRemoteButtonEvent: identifier pressedDown: pressedDown]; 245cdf0e10cSrcweir 246cdf0e10cSrcweir return noErr; 247cdf0e10cSrcweir} 248cdf0e10cSrcweir 249cdf0e10cSrcweir@end 250