From 9baf02468bee87fe30fd7e22bbc8c28789cdcd79 Mon Sep 17 00:00:00 2001 From: theropfather Date: Sun, 24 Jun 2018 22:05:34 +0100 Subject: [PATCH] Fix mac key modifiers --- src/arch/InputHandler/InputHandler.cpp | 86 +- src/arch/InputHandler/InputHandler.h | 1 + .../InputHandler/InputHandler_MacOSX_HID.cpp | 761 +++++++-------- src/archutils/Darwin/KeyboardDevice.cpp | 892 +++++++++--------- src/archutils/Darwin/SMMain.mm | 261 ++--- 5 files changed, 1004 insertions(+), 997 deletions(-) diff --git a/src/arch/InputHandler/InputHandler.cpp b/src/arch/InputHandler/InputHandler.cpp index 20aaf3f38b..cffd8c9f1d 100644 --- a/src/arch/InputHandler/InputHandler.cpp +++ b/src/arch/InputHandler/InputHandler.cpp @@ -38,6 +38,51 @@ void InputHandler::ButtonPressed( DeviceInput di ) } } + +wchar_t InputHandler::ApplyKeyModifiers(wchar_t c) +{ + bool bHoldingShift = + INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD, KEY_LSHIFT)) || + INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD, KEY_RSHIFT)); + + bool bHoldingCtrl = + INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD, KEY_LCTRL)) || + INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD, KEY_RCTRL)); + + // todo: handle Caps Lock -freem + if( bHoldingShift && !bHoldingCtrl ) + { + MakeUpper( &c, 1 ); + + switch( c ) + { + case L'`': c = L'~'; break; + case L'1': c = L'!'; break; + case L'2': c = L'@'; break; + case L'§': c = L'±'; break; + case L'3': c = L'#'; break; + case L'4': c = L'$'; break; + case L'5': c = L'%'; break; + case L'6': c = L'^'; break; + case L'7': c = L'&'; break; + case L'8': c = L'*'; break; + case L'9': c = L'('; break; + case L'0': c = L')'; break; + case L'-': c = L'_'; break; + case L'=': c = L'+'; break; + case L'[': c = L'{'; break; + case L']': c = L'}'; break; + case L'\'': c = L'"'; break; + case L'\\': c = L'|'; break; + case L';': c = L':'; break; + case L',': c = L'<'; break; + case L'.': c = L'>'; break; + case L'/': c = L'?'; break; + } + } + + return c; +} wchar_t InputHandler::DeviceButtonToChar( DeviceButton button, bool bUseCurrentKeyModifiers ) { wchar_t c = L'\0'; @@ -61,46 +106,7 @@ wchar_t InputHandler::DeviceButtonToChar( DeviceButton button, bool bUseCurrentK // don't implement DeviceButtonToChar. if( bUseCurrentKeyModifiers ) { - bool bHoldingShift = - INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD, KEY_LSHIFT)) || - INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD, KEY_RSHIFT)); - - bool bHoldingCtrl = - INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD, KEY_LCTRL)) || - INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD, KEY_RCTRL)); - - // todo: handle Caps Lock -freem - - if( bHoldingShift && !bHoldingCtrl ) - { - MakeUpper( &c, 1 ); - - switch( c ) - { - case L'`': c = L'~'; break; - case L'1': c = L'!'; break; - case L'2': c = L'@'; break; - case L'3': c = L'#'; break; - case L'4': c = L'$'; break; - case L'5': c = L'%'; break; - case L'6': c = L'^'; break; - case L'7': c = L'&'; break; - case L'8': c = L'*'; break; - case L'9': c = L'('; break; - case L'0': c = L')'; break; - case L'-': c = L'_'; break; - case L'=': c = L'+'; break; - case L'[': c = L'{'; break; - case L']': c = L'}'; break; - case L'\'': c = L'"'; break; - case L'\\': c = L'|'; break; - case L';': c = L':'; break; - case L',': c = L'<'; break; - case L'.': c = L'>'; break; - case L'/': c = L'?'; break; - } - } - + c = ApplyKeyModifiers(c); } return c; diff --git a/src/arch/InputHandler/InputHandler.h b/src/arch/InputHandler/InputHandler.h index bcba11ea0c..d55d27face 100644 --- a/src/arch/InputHandler/InputHandler.h +++ b/src/arch/InputHandler/InputHandler.h @@ -33,6 +33,7 @@ class InputHandler: public RageDriver // Override to return a pretty string that's specific to the controller type. virtual RString GetDeviceSpecificInputString( const DeviceInput &di ); + static wchar_t ApplyKeyModifiers(wchar_t c); virtual RString GetLocalizedInputString( const DeviceInput &di ); virtual wchar_t DeviceButtonToChar( DeviceButton button, bool bUseCurrentKeyModifiers ); diff --git a/src/arch/InputHandler/InputHandler_MacOSX_HID.cpp b/src/arch/InputHandler/InputHandler_MacOSX_HID.cpp index dd91c07ca0..019e24160f 100644 --- a/src/arch/InputHandler/InputHandler_MacOSX_HID.cpp +++ b/src/arch/InputHandler/InputHandler_MacOSX_HID.cpp @@ -17,360 +17,360 @@ REGISTER_INPUT_HANDLER_CLASS2( HID, MacOSX_HID ); void InputHandler_MacOSX_HID::QueueCallback( void *target, int result, void *refcon, void *sender ) { - // The result seems useless as you can't actually return anything... - // refcon is the Device number - - auto now = std::chrono::steady_clock::now(); - InputHandler_MacOSX_HID *This = (InputHandler_MacOSX_HID *)target; - IOHIDQueueInterface **queue = (IOHIDQueueInterface **)sender; - IOHIDEventStruct event; - AbsoluteTime zeroTime = { 0, 0 }; - HIDDevice *dev = This->m_vDevices[size_t( refcon )]; - vector vPresses; - - while( (result = CALL(queue, getNextEvent, &event, zeroTime, 0)) == kIOReturnSuccess ) - { - if( event.longValueSize != 0 && event.longValue != NULL ) - { - free( event.longValue ); - continue; - } - //LOG->Trace( "Got event with cookie %p, value %d", event.elementCookie, int(event.value) ); - dev->GetButtonPresses( vPresses, event.elementCookie, event.value, now); - } - FOREACH_CONST( DeviceInput, vPresses, i ) - INPUTFILTER->ButtonPressed( *i ); + // The result seems useless as you can't actually return anything... + // refcon is the Device number + + auto now = std::chrono::steady_clock::now(); + InputHandler_MacOSX_HID *This = (InputHandler_MacOSX_HID *)target; + IOHIDQueueInterface **queue = (IOHIDQueueInterface **)sender; + IOHIDEventStruct event; + AbsoluteTime zeroTime = { 0, 0 }; + HIDDevice *dev = This->m_vDevices[size_t( refcon )]; + vector vPresses; + + while( (result = CALL(queue, getNextEvent, &event, zeroTime, 0)) == kIOReturnSuccess ) + { + if( event.longValueSize != 0 && event.longValue != NULL ) + { + free( event.longValue ); + continue; + } + //LOG->Trace( "Got event with cookie %p, value %d", event.elementCookie, int(event.value) ); + dev->GetButtonPresses( vPresses, event.elementCookie, event.value, now ); + } + FOREACH_CONST( DeviceInput, vPresses, i ) + INPUTFILTER->ButtonPressed( *i ); } static void RunLoopStarted( CFRunLoopObserverRef o, CFRunLoopActivity a, void *sem ) { - CFRunLoopObserverInvalidate( o ); - CFRelease( o ); // we don't need this any longer - ((RageSemaphore *)sem)->Post(); + CFRunLoopObserverInvalidate( o ); + CFRelease( o ); // we don't need this any longer + ((RageSemaphore *)sem)->Post(); } int InputHandler_MacOSX_HID::Run( void *data ) { - InputHandler_MacOSX_HID *This = (InputHandler_MacOSX_HID *)data; - - This->m_LoopRef = CFRunLoopGetCurrent(); - CFRetain( This->m_LoopRef ); - - This->StartDevices(); - { - const RString sError = SetThreadPrecedence( 1.0f ); - if( !sError.empty() ) - LOG->Warn( "Could not set precedence of the input thread: %s", sError.c_str() ); - } - // Add an observer for the start of the run loop - { - /* The function copies the information out of the structure, so the memory - * pointed to by context does not need to persist beyond the function call. */ - CFRunLoopObserverContext context = { 0, &This->m_Sem, NULL, NULL, NULL }; - CFRunLoopObserverRef o = CFRunLoopObserverCreate( kCFAllocatorDefault, kCFRunLoopEntry, - false, 0, RunLoopStarted, &context); - CFRunLoopAddObserver( This->m_LoopRef, o, kCFRunLoopDefaultMode ); - } - - /* Add a source for ending the run loop. This serves two purposes: - * 1. it provides a way to terminate the run loop when IH_MacOSX_HID exists, - * and 2. it ensures that CFRunLoopRun() doesn't return immediately if - * there are no other sources. */ - { - /* Being a little tricky here, the perform callback takes a void* and - * returns nothing. CFRunLoopStop takes a CFRunLoopRef (a pointer) so - * cast the function and pass the loop ref. */ - void *info = This->m_LoopRef; - void (*perform)(void *) = (void (*)(void *))CFRunLoopStop; - // { version, info, retain, release, copyDescription, equal, hash, schedule, cancel, perform } - CFRunLoopSourceContext context = { 0, info, NULL, NULL, NULL, NULL, NULL, NULL, NULL, perform }; - - // Pass 1 so that it is called after all inputs have been handled (they will have order = 0) - This->m_SourceRef = CFRunLoopSourceCreate( kCFAllocatorDefault, 1, &context ); - - CFRunLoopAddSource( This->m_LoopRef, This->m_SourceRef, kCFRunLoopDefaultMode ); - } - CFRunLoopRun(); - LOG->Trace( "Shutting down input handler thread..." ); - return 0; + InputHandler_MacOSX_HID *This = (InputHandler_MacOSX_HID *)data; + + This->m_LoopRef = CFRunLoopGetCurrent(); + CFRetain( This->m_LoopRef ); + + This->StartDevices(); + { + const RString sError = SetThreadPrecedence( 1.0f ); + if( !sError.empty() ) + LOG->Warn( "Could not set precedence of the input thread: %s", sError.c_str() ); + } + // Add an observer for the start of the run loop + { + /* The function copies the information out of the structure, so the memory + * pointed to by context does not need to persist beyond the function call. */ + CFRunLoopObserverContext context = { 0, &This->m_Sem, NULL, NULL, NULL }; + CFRunLoopObserverRef o = CFRunLoopObserverCreate( kCFAllocatorDefault, kCFRunLoopEntry, + false, 0, RunLoopStarted, &context); + CFRunLoopAddObserver( This->m_LoopRef, o, kCFRunLoopDefaultMode ); + } + + /* Add a source for ending the run loop. This serves two purposes: + * 1. it provides a way to terminate the run loop when IH_MacOSX_HID exists, + * and 2. it ensures that CFRunLoopRun() doesn't return immediately if + * there are no other sources. */ + { + /* Being a little tricky here, the perform callback takes a void* and + * returns nothing. CFRunLoopStop takes a CFRunLoopRef (a pointer) so + * cast the function and pass the loop ref. */ + void *info = This->m_LoopRef; + void (*perform)(void *) = (void (*)(void *))CFRunLoopStop; + // { version, info, retain, release, copyDescription, equal, hash, schedule, cancel, perform } + CFRunLoopSourceContext context = { 0, info, NULL, NULL, NULL, NULL, NULL, NULL, NULL, perform }; + + // Pass 1 so that it is called after all inputs have been handled (they will have order = 0) + This->m_SourceRef = CFRunLoopSourceCreate( kCFAllocatorDefault, 1, &context ); + + CFRunLoopAddSource( This->m_LoopRef, This->m_SourceRef, kCFRunLoopDefaultMode ); + } + CFRunLoopRun(); + LOG->Trace( "Shutting down input handler thread..." ); + return 0; } void InputHandler_MacOSX_HID::DeviceAdded( void *refCon, io_iterator_t ) { - InputHandler_MacOSX_HID *This = (InputHandler_MacOSX_HID *)refCon; - - LockMut( This->m_ChangeLock ); - This->m_bChanged = true; + InputHandler_MacOSX_HID *This = (InputHandler_MacOSX_HID *)refCon; + + LockMut( This->m_ChangeLock ); + This->m_bChanged = true; } void InputHandler_MacOSX_HID::DeviceChanged( void *refCon, io_service_t service, natural_t messageType, void *arg ) { - if( messageType == kIOMessageServiceIsTerminated ) - { - InputHandler_MacOSX_HID *This = (InputHandler_MacOSX_HID *)refCon; - - LockMut( This->m_ChangeLock ); - This->m_bChanged = true; - } + if( messageType == kIOMessageServiceIsTerminated ) + { + InputHandler_MacOSX_HID *This = (InputHandler_MacOSX_HID *)refCon; + + LockMut( This->m_ChangeLock ); + This->m_bChanged = true; + } } // m_LoopRef needs to be set before this is called void InputHandler_MacOSX_HID::StartDevices() { - int n = 0; - - ASSERT( m_LoopRef ); - FOREACH( HIDDevice *, m_vDevices, i ) - (*i)->StartQueue( m_LoopRef, InputHandler_MacOSX_HID::QueueCallback, this, n++ ); - - CFRunLoopSourceRef runLoopSource = IONotificationPortGetRunLoopSource( m_NotifyPort ); - - CFRunLoopAddSource( m_LoopRef, runLoopSource, kCFRunLoopDefaultMode ); + int n = 0; + + ASSERT( m_LoopRef ); + FOREACH( HIDDevice *, m_vDevices, i ) + (*i)->StartQueue( m_LoopRef, InputHandler_MacOSX_HID::QueueCallback, this, n++ ); + + CFRunLoopSourceRef runLoopSource = IONotificationPortGetRunLoopSource( m_NotifyPort ); + + CFRunLoopAddSource( m_LoopRef, runLoopSource, kCFRunLoopDefaultMode ); } InputHandler_MacOSX_HID::~InputHandler_MacOSX_HID() { - FOREACH( HIDDevice *, m_vDevices, i ) - delete *i; - if( PREFSMAN->m_bThreadedInput ) - { - CFRunLoopSourceSignal( m_SourceRef ); - CFRunLoopWakeUp( m_LoopRef ); - m_InputThread.Wait(); - CFRelease( m_SourceRef ); - CFRelease( m_LoopRef ); - LOG->Trace( "Input handler thread shut down." ); - } - - FOREACH( io_iterator_t, m_vIters, i ) - IOObjectRelease( *i ); - IONotificationPortDestroy( m_NotifyPort ); + FOREACH( HIDDevice *, m_vDevices, i ) + delete *i; + if( PREFSMAN->m_bThreadedInput ) + { + CFRunLoopSourceSignal( m_SourceRef ); + CFRunLoopWakeUp( m_LoopRef ); + m_InputThread.Wait(); + CFRelease( m_SourceRef ); + CFRelease( m_LoopRef ); + LOG->Trace( "Input handler thread shut down." ); + } + + FOREACH( io_iterator_t, m_vIters, i ) + IOObjectRelease( *i ); + IONotificationPortDestroy( m_NotifyPort ); } static CFDictionaryRef GetMatchingDictionary( int usagePage, int usage ) { - // Build the matching dictionary. - CFMutableDictionaryRef dict; - - if( (dict = IOServiceMatching(kIOHIDDeviceKey)) == NULL ) - FAIL_M( "Couldn't create a matching dictionary." ); - // Refine the search by only looking for joysticks - CFNumberRef usagePageRef = CFInt( usagePage ); - CFNumberRef usageRef = CFInt( usage ); - - CFDictionarySetValue( dict, CFSTR(kIOHIDPrimaryUsagePageKey), usagePageRef ); - CFDictionarySetValue( dict, CFSTR(kIOHIDPrimaryUsageKey), usageRef ); - - // Cleanup after ourselves - CFRelease( usagePageRef ); - CFRelease( usageRef ); - - return dict; + // Build the matching dictionary. + CFMutableDictionaryRef dict; + + if( (dict = IOServiceMatching(kIOHIDDeviceKey)) == NULL ) + FAIL_M( "Couldn't create a matching dictionary." ); + // Refine the search by only looking for joysticks + CFNumberRef usagePageRef = CFInt( usagePage ); + CFNumberRef usageRef = CFInt( usage ); + + CFDictionarySetValue( dict, CFSTR(kIOHIDPrimaryUsagePageKey), usagePageRef ); + CFDictionarySetValue( dict, CFSTR(kIOHIDPrimaryUsageKey), usageRef ); + + // Cleanup after ourselves + CFRelease( usagePageRef ); + CFRelease( usageRef ); + + return dict; } // Factor this out because nothing else in IH_C::AddDevices() needs to know the type of the device. static HIDDevice *MakeDevice( InputDevice id ) { - if( id == DEVICE_KEYBOARD ) - return new KeyboardDevice; - if( id == DEVICE_MOUSE ) - return new MouseDevice; - if( IsJoystick(id) ) - return new JoystickDevice; - if( IsPump(id) ) - return new PumpDevice; - return NULL; + if( id == DEVICE_KEYBOARD ) + return new KeyboardDevice; + /* + if( id == DEVICE_MOUSE ) + return new MouseDevice; + */ + if( IsJoystick(id) ) + return new JoystickDevice; + if( IsPump(id) ) + return new PumpDevice; + return NULL; } void InputHandler_MacOSX_HID::AddDevices( int usagePage, int usage, InputDevice &id ) { - io_iterator_t iter; - CFDictionaryRef dict = GetMatchingDictionary( usagePage, usage ); - kern_return_t ret = IOServiceAddMatchingNotification( m_NotifyPort, kIOFirstMatchNotification, dict, - InputHandler_MacOSX_HID::DeviceAdded, this, &iter ); - io_object_t device; - - if( ret != KERN_SUCCESS ) - return; - - m_vIters.push_back( iter ); - - // Iterate over the devices and add them - while( (device = IOIteratorNext(iter)) ) - { - LOG->Trace( "\tFound device %d", id ); - HIDDevice *dev = MakeDevice( id ); - int num; - - if( !dev ) - { - LOG->Trace( "\t\tInvalid id, deleting device" ); - IOObjectRelease( device ); - continue; - } - - if( !dev->Open(device) || (num = dev->AssignIDs(id)) == -1 ) - { - LOG->Trace( "\tFailed top open or assign id, deleting device" ); - delete dev; - IOObjectRelease( device ); - continue; - } - io_iterator_t i; - - enum_add( id, num ); - m_vDevices.push_back( dev ); - - ret = IOServiceAddInterestNotification( - m_NotifyPort, device, kIOGeneralInterest, - InputHandler_MacOSX_HID::DeviceChanged, - this, &i - ); - - if( ret == KERN_SUCCESS ) - m_vIters.push_back( i ); - else - LOG->Trace( "\t\tFailed to add device changed notification, deleting device" ); - IOObjectRelease( device ); - } + io_iterator_t iter; + CFDictionaryRef dict = GetMatchingDictionary( usagePage, usage ); + kern_return_t ret = IOServiceAddMatchingNotification( m_NotifyPort, kIOFirstMatchNotification, dict, + InputHandler_MacOSX_HID::DeviceAdded, this, &iter ); + io_object_t device; + + if( ret != KERN_SUCCESS ) + return; + + m_vIters.push_back( iter ); + + // Iterate over the devices and add them + while( (device = IOIteratorNext(iter)) ) + { + LOG->Trace( "\tFound device %d", id ); + HIDDevice *dev = MakeDevice( id ); + int num; + + if( !dev ) + { + LOG->Trace( "\t\tInvalid id, deleting device" ); + IOObjectRelease( device ); + continue; + } + + if( !dev->Open(device) || (num = dev->AssignIDs(id)) == -1 ) + { + LOG->Trace( "\tFailed top open or assign id, deleting device" ); + delete dev; + IOObjectRelease( device ); + continue; + } + io_iterator_t i; + + enum_add( id, num ); + m_vDevices.push_back( dev ); + + ret = IOServiceAddInterestNotification( + m_NotifyPort, device, kIOGeneralInterest, + InputHandler_MacOSX_HID::DeviceChanged, + this, &i + ); + + if( ret == KERN_SUCCESS ) + m_vIters.push_back( i ); + else + LOG->Trace( "\t\tFailed to add device changed notification, deleting device" ); + IOObjectRelease( device ); + } } InputHandler_MacOSX_HID::InputHandler_MacOSX_HID() : m_Sem( "Input thread started" ), m_ChangeLock( "Input handler change lock" ) { - InputDevice id = DEVICE_KEYBOARD; - - // Set up the notify ports. - m_NotifyPort = IONotificationPortCreate( kIOMasterPortDefault ); - - // Add devices. - LOG->Trace( "Finding keyboards" ); - AddDevices( kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard, id ); - - id = DEVICE_MOUSE; + InputDevice id = DEVICE_KEYBOARD; - LOG->Trace( "Finding mice" ); - AddDevices( kHIDPage_GenericDesktop, kHIDUsage_GD_Mouse, id ); - - LOG->Trace( "Finding joysticks" ); - id = DEVICE_JOY1; - AddDevices( kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick, id ); - AddDevices( kHIDPage_GenericDesktop, kHIDUsage_GD_GamePad, id ); - LOG->Trace( "Finding pump" ); - id = DEVICE_PUMP1; - AddDevices( kHIDPage_VendorDefinedStart, 0x0001, id ); // Pump pads use the first vendor specific usage page. - m_bChanged = false; - - if( PREFSMAN->m_bThreadedInput ) - { - m_InputThread.SetName( "Input thread" ); - m_InputThread.Create( InputHandler_MacOSX_HID::Run, this ); - // Wait for the run loop to start before returning. - m_Sem.Wait(); - } - else - { - m_LoopRef = CFRunLoopRef( GetCFRunLoopFromEventLoop(GetMainEventLoop()) ); - CFRetain( m_LoopRef ); - StartDevices(); - } + // Set up the notify ports. + m_NotifyPort = IONotificationPortCreate( kIOMasterPortDefault ); + + // Add devices. + LOG->Trace( "Finding keyboards" ); + AddDevices( kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard, id ); + + LOG->Trace( "Finding mice" ); + AddDevices( kHIDPage_GenericDesktop, kHIDUsage_GD_Mouse, id ); + + LOG->Trace( "Finding joysticks" ); + id = DEVICE_JOY1; + AddDevices( kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick, id ); + AddDevices( kHIDPage_GenericDesktop, kHIDUsage_GD_GamePad, id ); + LOG->Trace( "Finding pump" ); + id = DEVICE_PUMP1; + AddDevices( kHIDPage_VendorDefinedStart, 0x0001, id ); // Pump pads use the first vendor specific usage page. + m_bChanged = false; + + if( PREFSMAN->m_bThreadedInput ) + { + m_InputThread.SetName( "Input thread" ); + m_InputThread.Create( InputHandler_MacOSX_HID::Run, this ); + // Wait for the run loop to start before returning. + m_Sem.Wait(); + } + else + { + m_LoopRef = CFRunLoopRef( GetCFRunLoopFromEventLoop(GetMainEventLoop()) ); + CFRetain( m_LoopRef ); + StartDevices(); + } } void InputHandler_MacOSX_HID::GetDevicesAndDescriptions( vector& vDevices ) { - FOREACH_CONST( HIDDevice *, m_vDevices, i ) - (*i)->GetDevicesAndDescriptions( vDevices ); + FOREACH_CONST( HIDDevice *, m_vDevices, i ) + (*i)->GetDevicesAndDescriptions( vDevices ); } RString InputHandler_MacOSX_HID::GetDeviceSpecificInputString( const DeviceInput &di ) { - if( di.device == DEVICE_KEYBOARD ) - { + if( di.device == DEVICE_KEYBOARD ) + { #define OTHER(n) (KEY_OTHER_0 + (n)) - switch( di.button ) - { - case KEY_DEL: return "del"; - case KEY_BACK: return "delete"; - case KEY_ENTER: return "return"; - case KEY_LALT: return "left option"; - case KEY_RALT: return "right option"; - case KEY_LMETA: return "left cmd"; - case KEY_RMETA: return "right cmd"; - case KEY_INSERT: return "help"; - case OTHER(0): return "F17"; - case OTHER(1): return "F18"; - case OTHER(2): return "F19"; - case OTHER(3): return "F20"; - case OTHER(4): return "F21"; - case OTHER(5): return "F22"; - case OTHER(6): return "F23"; - case OTHER(7): return "F25"; - case OTHER(8): return "execute"; - case OTHER(9): return "select"; - case OTHER(10): return "stop"; - case OTHER(11): return "again"; - case OTHER(12): return "undo"; - case OTHER(13): return "cut"; - case OTHER(14): return "copy"; - case OTHER(15): return "paste"; - case OTHER(16): return "find"; - case OTHER(17): return "mute"; - case OTHER(18): return "volume up"; - case OTHER(19): return "volume down"; - case OTHER(20): return "AS/400 equal"; - case OTHER(21): return "international 1"; - case OTHER(22): return "international 2"; - case OTHER(23): return "international 3"; - case OTHER(24): return "international 4"; - case OTHER(25): return "international 5"; - case OTHER(26): return "international 6"; - case OTHER(27): return "international 7"; - case OTHER(28): return "international 8"; - case OTHER(29): return "international 9"; - case OTHER(30): return "lang 1"; - case OTHER(31): return "lang 2"; - case OTHER(32): return "lang 3"; - case OTHER(33): return "lang 4"; - case OTHER(34): return "lang 5"; - case OTHER(35): return "lang 6"; - case OTHER(36): return "lang 7"; - case OTHER(37): return "lang 8"; - case OTHER(38): return "lang 9"; - case OTHER(39): return "alt erase"; - case OTHER(40): return "sys req"; - case OTHER(41): return "cancel"; - case OTHER(42): return "separator"; - case OTHER(43): return "out"; - case OTHER(44): return "oper"; - case OTHER(45): return "clear/again"; // XXX huh? - case OTHER(46): return "cr sel/props"; // XXX - case OTHER(47): return "ex sel"; - case OTHER(48): return "non US backslash"; - case OTHER(49): return "application"; - case OTHER(50): return "prior"; - default: break; - } + switch( di.button ) + { + case KEY_DEL: return "del"; + case KEY_BACK: return "delete"; + case KEY_ENTER: return "return"; + case KEY_LALT: return "left option"; + case KEY_RALT: return "right option"; + case KEY_LMETA: return "left cmd"; + case KEY_RMETA: return "right cmd"; + case KEY_INSERT: return "help"; + case OTHER(0): return "F17"; + case OTHER(1): return "F18"; + case OTHER(2): return "F19"; + case OTHER(3): return "F20"; + case OTHER(4): return "F21"; + case OTHER(5): return "F22"; + case OTHER(6): return "F23"; + case OTHER(7): return "F25"; + case OTHER(8): return "execute"; + case OTHER(9): return "select"; + case OTHER(10): return "stop"; + case OTHER(11): return "again"; + case OTHER(12): return "undo"; + case OTHER(13): return "cut"; + case OTHER(14): return "copy"; + case OTHER(15): return "paste"; + case OTHER(16): return "find"; + case OTHER(17): return "mute"; + case OTHER(18): return "volume up"; + case OTHER(19): return "volume down"; + case OTHER(20): return "AS/400 equal"; + case OTHER(21): return "international 1"; + case OTHER(22): return "international 2"; + case OTHER(23): return "international 3"; + case OTHER(24): return "international 4"; + case OTHER(25): return "international 5"; + case OTHER(26): return "international 6"; + case OTHER(27): return "international 7"; + case OTHER(28): return "international 8"; + case OTHER(29): return "international 9"; + case OTHER(30): return "lang 1"; + case OTHER(31): return "lang 2"; + case OTHER(32): return "lang 3"; + case OTHER(33): return "lang 4"; + case OTHER(34): return "lang 5"; + case OTHER(35): return "lang 6"; + case OTHER(36): return "lang 7"; + case OTHER(37): return "lang 8"; + case OTHER(38): return "lang 9"; + case OTHER(39): return "alt erase"; + case OTHER(40): return "sys req"; + case OTHER(41): return "cancel"; + case OTHER(42): return "separator"; + case OTHER(43): return "out"; + case OTHER(44): return "oper"; + case OTHER(45): return "clear/again"; // XXX huh? + case OTHER(46): return "cr sel/props"; // XXX + case OTHER(47): return "ex sel"; + case OTHER(48): return "non US backslash"; + case OTHER(49): return "application"; + case OTHER(50): return "prior"; + default: break; + } #undef OTHER - } - if( di.device == DEVICE_PUMP1 || di.device == DEVICE_PUMP2 ) - { - switch( di.button ) - { - case JOY_BUTTON_1: return "UL"; - case JOY_BUTTON_2: return "UR"; - case JOY_BUTTON_3: return "MID"; - case JOY_BUTTON_4: return "DL"; - case JOY_BUTTON_5: return "DR"; - case JOY_BUTTON_6: return "Esc"; - case JOY_BUTTON_7: return "P2 UL"; - case JOY_BUTTON_8: return "P2 UR"; - case JOY_BUTTON_9: return "P2 MID"; - case JOY_BUTTON_10: return "P2 DL"; - case JOY_BUTTON_11: return "P2 DR"; - default: break; - } - } - - return InputHandler::GetDeviceSpecificInputString( di ); + } + if( di.device == DEVICE_PUMP1 || di.device == DEVICE_PUMP2 ) + { + switch( di.button ) + { + case JOY_BUTTON_1: return "UL"; + case JOY_BUTTON_2: return "UR"; + case JOY_BUTTON_3: return "MID"; + case JOY_BUTTON_4: return "DL"; + case JOY_BUTTON_5: return "DR"; + case JOY_BUTTON_6: return "Esc"; + case JOY_BUTTON_7: return "P2 UL"; + case JOY_BUTTON_8: return "P2 UR"; + case JOY_BUTTON_9: return "P2 MID"; + case JOY_BUTTON_10: return "P2 DL"; + case JOY_BUTTON_11: return "P2 DR"; + default: break; + } + } + + return InputHandler::GetDeviceSpecificInputString( di ); } // Modified from NESControllerInterface of Macifom project, @@ -378,93 +378,94 @@ RString InputHandler_MacOSX_HID::GetDeviceSpecificInputString( const DeviceInput // Used under MIT license from http://inquisitivecocoa.com/2009/04/05/key-code-translator/ static wchar_t KeyCodeToChar(CGKeyCode keyCode, unsigned int modifierFlags) { - TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource(); - CFDataRef uchr = (CFDataRef)TISGetInputSourceProperty(currentKeyboard, kTISPropertyUnicodeKeyLayoutData); - const UCKeyboardLayout *keyboardLayout = uchr ? (const UCKeyboardLayout*)CFDataGetBytePtr(uchr) : NULL; - - if( keyboardLayout ) - { - UInt32 deadKeyState = 0; - UniCharCount maxStringLength = 255; - UniCharCount actualStringLength = 0; - UniChar unicodeString[maxStringLength]; - - OSStatus status = UCKeyTranslate(keyboardLayout, - keyCode, kUCKeyActionDown, modifierFlags, - LMGetKbdType(), 0, - &deadKeyState, - maxStringLength, - &actualStringLength, unicodeString); - - if( status != noErr ) - { - fprintf(stderr, "There was an %s error translating from the '%d' key code to a human readable string: %s\n", - GetMacOSStatusErrorString(status), (int)status, GetMacOSStatusCommentString(status)); - } - else if( actualStringLength == 0 ) - { - fprintf(stderr, "Couldn't find a translation for the '%d' key code\n", keyCode); - } - else - { - return unicodeString[0]; - } - } - else - { - fprintf(stderr, "Couldn't find a translation for the '%d' key code\n", keyCode); - } - return 0; + TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource(); + CFDataRef uchr = (CFDataRef)TISGetInputSourceProperty(currentKeyboard, kTISPropertyUnicodeKeyLayoutData); + const UCKeyboardLayout *keyboardLayout = uchr ? (const UCKeyboardLayout*)CFDataGetBytePtr(uchr) : NULL; + + if( keyboardLayout ) + { + UInt32 deadKeyState = 0; + UniCharCount maxStringLength = 255; + UniCharCount actualStringLength = 0; + UniChar unicodeString[maxStringLength]; + + OSStatus status = UCKeyTranslate(keyboardLayout, + keyCode, kUCKeyActionDown, modifierFlags, + LMGetKbdType(), 0, + &deadKeyState, + maxStringLength, + &actualStringLength, unicodeString); + + if( status != noErr ) + { + fprintf(stderr, "There was an %s error translating from the '%d' key code to a human readable string: %s\n", + GetMacOSStatusErrorString(status), (int)status, GetMacOSStatusCommentString(status)); + } + else if( actualStringLength == 0 ) + { + fprintf(stderr, "Couldn't find a translation for the '%d' key code\n", keyCode); + } + else + { + return unicodeString[0]; + } + } + else + { + fprintf(stderr, "Couldn't find a translation for the '%d' key code\n", keyCode); + } + return 0; } wchar_t InputHandler_MacOSX_HID::DeviceButtonToChar( DeviceButton button, bool bUseCurrentKeyModifiers ) { - // KeyTranslate maps these keys to a character. They shouldn't be mapped to any character. - switch( button ) - { - default: - if( (button >= KEY_F1 && button <= KEY_F16) ) - return L'\0'; - break; - case KEY_UP: - case KEY_DOWN: - case KEY_LEFT: - case KEY_RIGHT: - case KEY_ESC: - case KEY_TAB: - case KEY_ENTER: - case KEY_PRTSC: - case KEY_SCRLLOCK: - case KEY_PAUSE: - case KEY_DEL: - case KEY_HOME: - case KEY_END: - case KEY_PGUP: - case KEY_PGDN: - case KEY_NUMLOCK: - case KEY_KP_ENTER: - return L'\0'; - } - - // Use Text Input Source services to convert the key code to character code. - UInt8 iMacVirtualKey; - if( KeyboardDevice::DeviceButtonToMacVirtualKey( button, iMacVirtualKey ) ) - { - UInt32 nModifiers = bUseCurrentKeyModifiers ? GetCurrentKeyModifiers() : 0; - wchar_t sCharCode = KeyCodeToChar( iMacVirtualKey, nModifiers ); - if( sCharCode != 0 ) - { - return sCharCode; - } - } - - return InputHandler::DeviceButtonToChar( button, bUseCurrentKeyModifiers ); + // KeyTranslate maps these keys to a character. They shouldn't be mapped to any character. + switch( button ) + { + default: + if( (button >= KEY_F1 && button <= KEY_F16) ) + return L'\0'; + break; + case KEY_UP: + case KEY_DOWN: + case KEY_LEFT: + case KEY_RIGHT: + case KEY_ESC: + case KEY_TAB: + case KEY_ENTER: + case KEY_PRTSC: + case KEY_SCRLLOCK: + case KEY_PAUSE: + case KEY_DEL: + case KEY_HOME: + case KEY_END: + case KEY_PGUP: + case KEY_PGDN: + case KEY_NUMLOCK: + case KEY_KP_ENTER: + return L'\0'; + } + + // Use Text Input Source services to convert the key code to character code. + UInt8 iMacVirtualKey; + if( KeyboardDevice::DeviceButtonToMacVirtualKey( button, iMacVirtualKey ) ) + { + UInt32 nModifiers = bUseCurrentKeyModifiers ? GetCurrentKeyModifiers() : 0; + wchar_t sCharCode = KeyCodeToChar( iMacVirtualKey, nModifiers ); + + if( sCharCode != 0 ) + { + return ApplyKeyModifiers(sCharCode); + } + } + + return InputHandler::DeviceButtonToChar( button, bUseCurrentKeyModifiers ); } /* * (c) 2005, 2006 Steve Checkoway * All rights reserved. - * + * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including @@ -474,7 +475,7 @@ wchar_t InputHandler_MacOSX_HID::DeviceButtonToChar( DeviceButton button, bool b * copyright notice(s) and this permission notice appear in all copies of * the Software and that both the above copyright notice(s) and this * permission notice appear in supporting documentation. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF diff --git a/src/archutils/Darwin/KeyboardDevice.cpp b/src/archutils/Darwin/KeyboardDevice.cpp index 793ba771bb..ec7c4ba9a8 100644 --- a/src/archutils/Darwin/KeyboardDevice.cpp +++ b/src/archutils/Darwin/KeyboardDevice.cpp @@ -1,492 +1,489 @@ #include "global.h" #include "KeyboardDevice.h" -#include "InputFilter.h" - using namespace __gnu_cxx; bool KeyboardDevice::AddLogicalDevice( int usagePage, int usage ) { - return usagePage == kHIDPage_GenericDesktop && usage == kHIDUsage_GD_Keyboard; + return usagePage == kHIDPage_GenericDesktop && usage == kHIDUsage_GD_Keyboard; } static bool UsbKeyToDeviceButton( UInt8 iUsbKey, DeviceButton &buttonOut ) { - UInt8 usage = iUsbKey; - - if( usage < kHIDUsage_KeyboardA ) - return false; - - if( usage <= kHIDUsage_KeyboardZ ) - { - buttonOut = enum_add2( KEY_Ca, usage - kHIDUsage_KeyboardA ); - return true; - } - - // KEY_C0 = KEY_C1 - 1, kHIDUsage_Keyboard0 = kHIDUsage_Keyboard9 + 1 - if( usage <= kHIDUsage_Keyboard9 ) - { - buttonOut = enum_add2( KEY_C1, usage - kHIDUsage_Keyboard1 ); - return true; - } - - if( usage >= kHIDUsage_KeyboardF1 && usage <= kHIDUsage_KeyboardF12 ) - { - buttonOut = enum_add2( KEY_F1, usage - kHIDUsage_KeyboardF1 ); - return true; - } - - if( usage >= kHIDUsage_KeyboardF13 && usage <= kHIDUsage_KeyboardF16 ) - { - buttonOut = enum_add2( KEY_F13, usage - kHIDUsage_KeyboardF13 ); - return true; - } - - // keypad 0 is again backward - if( usage >= kHIDUsage_Keypad1 && usage <= kHIDUsage_Keypad9 ) - { - buttonOut = enum_add2( KEY_KP_C1, usage - kHIDUsage_Keypad1 ); - return true; - } - + UInt8 usage = iUsbKey; + + if( usage < kHIDUsage_KeyboardA ) + return false; + + if( usage <= kHIDUsage_KeyboardZ ) + { + buttonOut = enum_add2( KEY_Ca, usage - kHIDUsage_KeyboardA ); + return true; + } + + // KEY_C0 = KEY_C1 - 1, kHIDUsage_Keyboard0 = kHIDUsage_Keyboard9 + 1 + if( usage <= kHIDUsage_Keyboard9 ) + { + buttonOut = enum_add2( KEY_C1, usage - kHIDUsage_Keyboard1 ); + return true; + } + + if( usage >= kHIDUsage_KeyboardF1 && usage <= kHIDUsage_KeyboardF12 ) + { + buttonOut = enum_add2( KEY_F1, usage - kHIDUsage_KeyboardF1 ); + return true; + } + + if( usage >= kHIDUsage_KeyboardF13 && usage <= kHIDUsage_KeyboardF16 ) + { + buttonOut = enum_add2( KEY_F13, usage - kHIDUsage_KeyboardF13 ); + return true; + } + + // keypad 0 is again backward + if( usage >= kHIDUsage_Keypad1 && usage <= kHIDUsage_Keypad9 ) + { + buttonOut = enum_add2( KEY_KP_C1, usage - kHIDUsage_Keypad1 ); + return true; + } + #define OTHER(n) (enum_add2(KEY_OTHER_0, (n))) - - // [0, 8] - if( usage >= kHIDUsage_KeyboardF17 && usage <= kHIDUsage_KeyboardExecute ) - { - buttonOut = OTHER( 0 + usage - kHIDUsage_KeyboardF17 ); - return true; - } - - // [9, 19] - if( usage >= kHIDUsage_KeyboardSelect && usage <= kHIDUsage_KeyboardVolumeDown ) - { - buttonOut = OTHER( 9 + usage - kHIDUsage_KeyboardSelect ); - return true; - } - - // [20, 41] - if( usage >= kHIDUsage_KeypadEqualSignAS400 && usage <= kHIDUsage_KeyboardCancel ) - { - buttonOut = OTHER( 20 + usage - kHIDUsage_KeypadEqualSignAS400 ); - return true; - } - - // [42, 47] - // XXX kHIDUsage_KeyboardClearOrAgain - if( usage >= kHIDUsage_KeyboardSeparator && usage <= kHIDUsage_KeyboardExSel ) - { - buttonOut = OTHER( 32 + usage - kHIDUsage_KeyboardSeparator ); - return true; - } - + + // [0, 8] + if( usage >= kHIDUsage_KeyboardF17 && usage <= kHIDUsage_KeyboardExecute ) + { + buttonOut = OTHER( 0 + usage - kHIDUsage_KeyboardF17 ); + return true; + } + + // [9, 19] + if( usage >= kHIDUsage_KeyboardSelect && usage <= kHIDUsage_KeyboardVolumeDown ) + { + buttonOut = OTHER( 9 + usage - kHIDUsage_KeyboardSelect ); + return true; + } + + // [20, 41] + if( usage >= kHIDUsage_KeypadEqualSignAS400 && usage <= kHIDUsage_KeyboardCancel ) + { + buttonOut = OTHER( 20 + usage - kHIDUsage_KeypadEqualSignAS400 ); + return true; + } + + // [42, 47] + // XXX kHIDUsage_KeyboardClearOrAgain + if( usage >= kHIDUsage_KeyboardSeparator && usage <= kHIDUsage_KeyboardExSel ) + { + buttonOut = OTHER( 32 + usage - kHIDUsage_KeyboardSeparator ); + return true; + } + #define X(x,y) case x: buttonOut = y; return true - - // Time for the special cases - switch( usage ) - { - X( kHIDUsage_Keyboard0, KEY_C0 ); - X( kHIDUsage_Keypad0, KEY_KP_C0 ); - X( kHIDUsage_KeyboardReturnOrEnter, KEY_ENTER ); - X( kHIDUsage_KeyboardEscape, KEY_ESC ); - X( kHIDUsage_KeyboardDeleteOrBackspace, KEY_BACK ); - X( kHIDUsage_KeyboardTab, KEY_TAB ); - X( kHIDUsage_KeyboardSpacebar, KEY_SPACE ); - X( kHIDUsage_KeyboardHyphen, KEY_HYPHEN ); - X( kHIDUsage_KeyboardEqualSign, KEY_EQUAL ); - X( kHIDUsage_KeyboardOpenBracket, KEY_LBRACKET ); - X( kHIDUsage_KeyboardCloseBracket, KEY_RBRACKET ); - X( kHIDUsage_KeyboardBackslash, KEY_BACKSLASH ); - X( kHIDUsage_KeyboardNonUSPound, KEY_HASH ); - X( kHIDUsage_KeyboardSemicolon, KEY_SEMICOLON ); - X( kHIDUsage_KeyboardQuote, KEY_SQUOTE ); - X( kHIDUsage_KeyboardGraveAccentAndTilde, KEY_ACCENT ); - X( kHIDUsage_KeyboardComma, KEY_COMMA ); - X( kHIDUsage_KeyboardPeriod, KEY_PERIOD ); - X( kHIDUsage_KeyboardSlash, KEY_SLASH ); - X( kHIDUsage_KeyboardCapsLock, KEY_CAPSLOCK ); - X( kHIDUsage_KeyboardPrintScreen, KEY_PRTSC ); - X( kHIDUsage_KeyboardScrollLock, KEY_SCRLLOCK ); - X( kHIDUsage_KeyboardPause, KEY_PAUSE ); - X( kHIDUsage_KeyboardInsert, KEY_INSERT ); - X( kHIDUsage_KeyboardHome, KEY_HOME ); - X( kHIDUsage_KeyboardPageUp, KEY_PGUP ); - X( kHIDUsage_KeyboardDeleteForward, KEY_DEL ); - X( kHIDUsage_KeyboardEnd, KEY_END ); - X( kHIDUsage_KeyboardPageDown, KEY_PGDN ); - X( kHIDUsage_KeyboardRightArrow, KEY_RIGHT ); - X( kHIDUsage_KeyboardLeftArrow, KEY_LEFT ); - X( kHIDUsage_KeyboardDownArrow, KEY_DOWN ); - X( kHIDUsage_KeyboardUpArrow, KEY_UP ); - X( kHIDUsage_KeypadNumLock, KEY_NUMLOCK ); - X( kHIDUsage_KeypadSlash, KEY_KP_SLASH ); - X( kHIDUsage_KeypadEqualSign, KEY_KP_EQUAL ); - X( kHIDUsage_KeypadAsterisk, KEY_KP_ASTERISK ); - X( kHIDUsage_KeypadHyphen, KEY_KP_HYPHEN ); - X( kHIDUsage_KeypadPlus, KEY_KP_PLUS ); - X( kHIDUsage_KeypadEnter, KEY_KP_ENTER ); - X( kHIDUsage_KeypadPeriod, KEY_KP_PERIOD ); - X( kHIDUsage_KeyboardNonUSBackslash, OTHER(48) ); - X( kHIDUsage_KeyboardApplication, OTHER(49) ); - X( kHIDUsage_KeyboardClear, KEY_NUMLOCK ); // XXX - X( kHIDUsage_KeyboardHelp, KEY_INSERT ); - X( kHIDUsage_KeyboardMenu, KEY_MENU ); - // XXX kHIDUsage_KeyboardLockingCapsLock - // XXX kHIDUsage_KeyboardLockingNumLock - // XXX kHIDUsage_KeyboardLockingScrollLock - X( kHIDUsage_KeypadComma, KEY_KP_PERIOD ); // XXX - X( kHIDUsage_KeyboardReturn, KEY_ENTER ); - X( kHIDUsage_KeyboardPrior, OTHER(50) ); - X( kHIDUsage_KeyboardLeftControl, KEY_LCTRL ); - X( kHIDUsage_KeyboardLeftShift, KEY_LSHIFT ); - X( kHIDUsage_KeyboardLeftAlt, KEY_LALT ); - X( kHIDUsage_KeyboardLeftGUI, KEY_LMETA ); - X( kHIDUsage_KeyboardRightControl, KEY_RCTRL ); - X( kHIDUsage_KeyboardRightShift, KEY_RSHIFT ); - X( kHIDUsage_KeyboardRightAlt, KEY_RALT ); - X( kHIDUsage_KeyboardRightGUI, KEY_RMETA ); - } + + // Time for the special cases + switch( usage ) + { + X( kHIDUsage_Keyboard0, KEY_C0 ); + X( kHIDUsage_Keypad0, KEY_KP_C0 ); + X( kHIDUsage_KeyboardReturnOrEnter, KEY_ENTER ); + X( kHIDUsage_KeyboardEscape, KEY_ESC ); + X( kHIDUsage_KeyboardDeleteOrBackspace, KEY_BACK ); + X( kHIDUsage_KeyboardTab, KEY_TAB ); + X( kHIDUsage_KeyboardSpacebar, KEY_SPACE ); + X( kHIDUsage_KeyboardHyphen, KEY_HYPHEN ); + X( kHIDUsage_KeyboardEqualSign, KEY_EQUAL ); + X( kHIDUsage_KeyboardOpenBracket, KEY_LBRACKET ); + X( kHIDUsage_KeyboardCloseBracket, KEY_RBRACKET ); + X( kHIDUsage_KeyboardBackslash, KEY_BACKSLASH ); + X( kHIDUsage_KeyboardNonUSPound, KEY_HASH ); + X( kHIDUsage_KeyboardSemicolon, KEY_SEMICOLON ); + X( kHIDUsage_KeyboardQuote, KEY_SQUOTE ); + X( kHIDUsage_KeyboardGraveAccentAndTilde, KEY_ACCENT ); + X( kHIDUsage_KeyboardComma, KEY_COMMA ); + X( kHIDUsage_KeyboardPeriod, KEY_PERIOD ); + X( kHIDUsage_KeyboardSlash, KEY_SLASH ); + X( kHIDUsage_KeyboardCapsLock, KEY_CAPSLOCK ); + X( kHIDUsage_KeyboardPrintScreen, KEY_PRTSC ); + X( kHIDUsage_KeyboardScrollLock, KEY_SCRLLOCK ); + X( kHIDUsage_KeyboardPause, KEY_PAUSE ); + X( kHIDUsage_KeyboardInsert, KEY_INSERT ); + X( kHIDUsage_KeyboardHome, KEY_HOME ); + X( kHIDUsage_KeyboardPageUp, KEY_PGUP ); + X( kHIDUsage_KeyboardDeleteForward, KEY_DEL ); + X( kHIDUsage_KeyboardEnd, KEY_END ); + X( kHIDUsage_KeyboardPageDown, KEY_PGDN ); + X( kHIDUsage_KeyboardRightArrow, KEY_RIGHT ); + X( kHIDUsage_KeyboardLeftArrow, KEY_LEFT ); + X( kHIDUsage_KeyboardDownArrow, KEY_DOWN ); + X( kHIDUsage_KeyboardUpArrow, KEY_UP ); + X( kHIDUsage_KeypadNumLock, KEY_NUMLOCK ); + X( kHIDUsage_KeypadSlash, KEY_KP_SLASH ); + X( kHIDUsage_KeypadEqualSign, KEY_KP_EQUAL ); + X( kHIDUsage_KeypadAsterisk, KEY_KP_ASTERISK ); + X( kHIDUsage_KeypadHyphen, KEY_KP_HYPHEN ); + X( kHIDUsage_KeypadPlus, KEY_KP_PLUS ); + X( kHIDUsage_KeypadEnter, KEY_KP_ENTER ); + X( kHIDUsage_KeypadPeriod, KEY_KP_PERIOD ); + X( kHIDUsage_KeyboardNonUSBackslash, OTHER(48) ); + X( kHIDUsage_KeyboardApplication, OTHER(49) ); + X( kHIDUsage_KeyboardClear, KEY_NUMLOCK ); // XXX + X( kHIDUsage_KeyboardHelp, KEY_INSERT ); + X( kHIDUsage_KeyboardMenu, KEY_MENU ); + // XXX kHIDUsage_KeyboardLockingCapsLock + // XXX kHIDUsage_KeyboardLockingNumLock + // XXX kHIDUsage_KeyboardLockingScrollLock + X( kHIDUsage_KeypadComma, KEY_KP_PERIOD ); // XXX + X( kHIDUsage_KeyboardReturn, KEY_ENTER ); + X( kHIDUsage_KeyboardPrior, OTHER(50) ); + X( kHIDUsage_KeyboardLeftControl, KEY_LCTRL ); + X( kHIDUsage_KeyboardLeftShift, KEY_LSHIFT ); + X( kHIDUsage_KeyboardLeftAlt, KEY_LALT ); + X( kHIDUsage_KeyboardLeftGUI, KEY_LMETA ); + X( kHIDUsage_KeyboardRightControl, KEY_RCTRL ); + X( kHIDUsage_KeyboardRightShift, KEY_RSHIFT ); + X( kHIDUsage_KeyboardRightAlt, KEY_RALT ); + X( kHIDUsage_KeyboardRightGUI, KEY_RMETA ); + } #undef X #undef OTHER - - return false; + + return false; } void KeyboardDevice::AddElement( int usagePage, int usage, IOHIDElementCookie cookie, const CFDictionaryRef properties ) { - if( usagePage != kHIDPage_KeyboardOrKeypad ) - return; - - DeviceButton button; - if( UsbKeyToDeviceButton(usage,button) ) - m_Mapping[cookie] = button; + if( usagePage != kHIDPage_KeyboardOrKeypad ) + return; + + DeviceButton button; + if( UsbKeyToDeviceButton(usage,button) ) + m_Mapping[cookie] = button; } void KeyboardDevice::Open() { - for( hash_map::const_iterator i = m_Mapping.begin(); i != m_Mapping.end(); ++i ) - { - //LOG->Trace( "Adding %s to queue, cookie %p", DeviceButtonToString(i->second).c_str(), i->first ); - AddElementToQueue( i->first ); - } + for( hash_map::const_iterator i = m_Mapping.begin(); i != m_Mapping.end(); ++i ) + { + //LOG->Trace( "Adding %s to queue, cookie %p", DeviceButtonToString(i->second).c_str(), i->first ); + AddElementToQueue( i->first ); + } } -void KeyboardDevice::GetButtonPresses( vector& vPresses, IOHIDElementCookie cookie, int value, const std::chrono::time_point &now) const +void KeyboardDevice::GetButtonPresses( vector& vPresses, IOHIDElementCookie cookie, int value, const std::chrono::time_point& now ) const { - hash_map::const_iterator iter = m_Mapping.find( cookie ); - - if( iter != m_Mapping.end() ) - { - //LOG->Trace( "Pushed %s", DeviceButtonToString(iter->second).c_str() ); - vPresses.push_back( DeviceInput(DEVICE_KEYBOARD, iter->second, value, now)); - INPUTFILTER->ButtonPressed(DeviceInput(DEVICE_KEYBOARD, iter->second, value, now)); - } + hash_map::const_iterator iter = m_Mapping.find( cookie ); + + if( iter != m_Mapping.end() ) + { + //LOG->Trace( "Pushed %s", DeviceButtonToString(iter->second).c_str() ); + vPresses.push_back( DeviceInput(DEVICE_KEYBOARD, iter->second, value, now) ); + } } void KeyboardDevice::GetDevicesAndDescriptions( vector& vDevices ) const { - if( vDevices.size() && vDevices[0].id == DEVICE_KEYBOARD ) - return; - vDevices.insert( vDevices.begin(), InputDeviceInfo(DEVICE_KEYBOARD, "Keyboard") ); + if( vDevices.size() && vDevices[0].id == DEVICE_KEYBOARD ) + return; + vDevices.insert( vDevices.begin(), InputDeviceInfo(DEVICE_KEYBOARD, "Keyboard") ); } // http://lists.apple.com/archives/carbon-dev/2005/Feb/msg00071.html // index represents USB keyboard usage value, content is Mac virtual keycode static UInt8 g_iUsbKeyToMacVirtualKey[256] = { - 0xFF, // 00 no event - 0xFF, // 01 ErrorRollOver - 0xFF, // 02 POSTFail - 0xFF, // 03 ErrorUndefined - 0x00, // 04 A - 0x0B, // 05 B - 0x08, // 06 C - 0x02, // 07 D - 0x0E, // 08 E - 0x03, // 09 F - 0x05, // 0A G - 0x04, // 0B H - 0x22, // 0C I - 0x26, // 0D J - 0x28, // 0E K - 0x25, // 0F L - - 0x2E, // 10 M - 0x2D, // 11 N - 0x1F, // 12 O - 0x23, // 13 P - 0x0C, // 14 Q - 0x0F, // 15 R - 0x01, // 16 S - 0x11, // 17 T - 0x20, // 18 U - 0x09, // 19 V - 0x0D, // 1A W - 0x07, // 1B X - 0x10, // 1C Y - 0x06, // 1D Z - 0x12, // 1E 1/! - 0x13, // 1F 2/@ - - 0x14, // 20 3 # - 0x15, // 21 4 $ - 0x17, // 22 5 % - 0x16, // 23 6 ^ - 0x1A, // 24 7 & - 0x1C, // 25 8 * - 0x19, // 26 9 ( - 0x1D, // 27 0 ) - 0x24, // 28 Return (Enter) - 0x35, // 29 ESC - 0x33, // 2A Delete (Backspace) - 0x30, // 2B Tab - 0x31, // 2C Spacebar - 0x1B, // 2D - _ - 0x18, // 2E = + - 0x21, // 2F [ { - - 0x1E, // 30 ] } - 0x2A, // 31 \ | - 0xFF, // 32 Non-US # and ~ (what?!!!) - 0x29, // 33 ; : - 0x27, // 34 ' " - 0x32, // 35 ` ~ - 0x2B, // 36 , < - 0x2F, // 37 . > - 0x2C, // 38 / ? - 0x39, // 39 Caps Lock - 0x7A, // 3A F1 - 0x78, // 3B F2 - 0x63, // 3C F3 - 0x76, // 3D F4 - 0x60, // 3E F5 - 0x61, // 3F F6 - - 0x62, // 40 F7 - 0x64, // 41 F8 - 0x65, // 42 F9 - 0x6D, // 43 F10 - 0x67, // 44 F11 - 0x6F, // 45 F12 - 0x69, // 46 F13/PrintScreen - 0x6B, // 47 F14/ScrollLock - 0x71, // 48 F15/Pause - 0x72, // 49 Insert - 0x73, // 4A Home - 0x74, // 4B PageUp - 0x75, // 4C Delete Forward - 0x77, // 4D End - 0x79, // 4E PageDown - 0x7C, // 4F RightArrow - - 0x7B, // 50 LeftArrow - 0x7D, // 51 DownArrow - 0x7E, // 52 UpArrow - 0x47, // 53 NumLock/Clear - 0x4B, // 54 Keypad / - 0x43, // 55 Keypad * - 0x4E, // 56 Keypad - - 0x45, // 57 Keypad + - 0x4C, // 58 Keypad Enter - 0x53, // 59 Keypad 1 - 0x54, // 5A Keypad 2 - 0x55, // 5B Keypad 3 - 0x56, // 5C Keypad 4 - 0x57, // 5D Keypad 5 - 0x58, // 5E Keypad 6 - 0x59, // 5F Keypad 7 - - 0x5B, // 60 Keypad 8 - 0x5C, // 61 Keypad 9 - 0x52, // 62 Keypad 0 - 0x41, // 63 Keypad . - 0xFF, // 64 Non-US \ and | (what ??!!) - 0x6E, // 65 ApplicationKey (not on Apple keyboards) - 0x7F, // 66 PowerKey - 0x51, // 67 Keypad = - 0x69, // 68 F13 - 0x6B, // 69 F14 - 0x71, // 6A F15 - 0xFF, // 6B F16 - 0xFF, // 6C F17 - 0xFF, // 6D F18 - 0xFF, // 6E F19 - 0xFF, // 6F F20 - - 0x5B, // 70 F21 - 0x5C, // 71 F22 - 0x52, // 72 F23 - 0x41, // 73 F24 - 0xFF, // 74 Execute - 0xFF, // 75 Help - 0x7F, // 76 Menu - 0x4C, // 77 Select - 0x69, // 78 Stop - 0x6B, // 79 Again - 0x71, // 7A Undo - 0xFF, // 7B Cut - 0xFF, // 7C Copy - 0xFF, // 7D Paste - 0xFF, // 7E Find - 0xFF, // 7F Mute - - 0xFF, // 80 no event - 0xFF, // 81 no event - 0xFF, // 82 no event - 0xFF, // 83 no event - 0xFF, // 84 no event - 0xFF, // 85 no event - 0xFF, // 86 no event - 0xFF, // 87 no event - 0xFF, // 88 no event - 0xFF, // 89 no event - 0xFF, // 8A no event - 0xFF, // 8B no event - 0xFF, // 8C no event - 0xFF, // 8D no event - 0xFF, // 8E no event - 0xFF, // 8F no event - - 0xFF, // 90 no event - 0xFF, // 91 no event - 0xFF, // 92 no event - 0xFF, // 93 no event - 0xFF, // 94 no event - 0xFF, // 95 no event - 0xFF, // 96 no event - 0xFF, // 97 no event - 0xFF, // 98 no event - 0xFF, // 99 no event - 0xFF, // 9A no event - 0xFF, // 9B no event - 0xFF, // 9C no event - 0xFF, // 9D no event - 0xFF, // 9E no event - 0xFF, // 9F no event - - 0xFF, // A0 no event - 0xFF, // A1 no event - 0xFF, // A2 no event - 0xFF, // A3 no event - 0xFF, // A4 no event - 0xFF, // A5 no event - 0xFF, // A6 no event - 0xFF, // A7 no event - 0xFF, // A8 no event - 0xFF, // A9 no event - 0xFF, // AA no event - 0xFF, // AB no event - 0xFF, // AC no event - 0xFF, // AD no event - 0xFF, // AE no event - 0xFF, // AF no event - - 0xFF, // B0 no event - 0xFF, // B1 no event - 0xFF, // B2 no event - 0xFF, // B3 no event - 0xFF, // B4 no event - 0xFF, // B5 no event - 0xFF, // B6 no event - 0xFF, // B7 no event - 0xFF, // B8 no event - 0xFF, // B9 no event - 0xFF, // BA no event - 0xFF, // BB no event - 0xFF, // BC no event - 0xFF, // BD no event - 0xFF, // BE no event - 0xFF, // BF no event - - 0xFF, // C0 no event - 0xFF, // C1 no event - 0xFF, // C2 no event - 0xFF, // C3 no event - 0xFF, // C4 no event - 0xFF, // C5 no event - 0xFF, // C6 no event - 0xFF, // C7 no event - 0xFF, // C8 no event - 0xFF, // C9 no event - 0xFF, // CA no event - 0xFF, // CB no event - 0xFF, // CC no event - 0xFF, // CD no event - 0xFF, // CE no event - 0xFF, // CF no event - - 0xFF, // D0 no event - 0xFF, // D1 no event - 0xFF, // D2 no event - 0xFF, // D3 no event - 0xFF, // D4 no event - 0xFF, // D5 no event - 0xFF, // D6 no event - 0xFF, // D7 no event - 0xFF, // D8 no event - 0xFF, // D9 no event - 0xFF, // DA no event - 0xFF, // DB no event - 0xFF, // DC no event - 0xFF, // DD no event - 0xFF, // DE no event - 0xFF, // DF no event - - 0x3B, // E0 left control key - 0x38, // E1 left shift key key - 0x3A, // E2 left alt/option key - 0x37, // E3 left GUI (windows/cmd) key - - 0x3B, // E4 right control key - 0x38, // E5 right shift key key - 0x3A, // E6 right alt/option key - 0x37, // E7 right GUI (windows/cmd) key - 0xFF, // E8 no event - 0xFF, // E9 no event - 0xFF, // EA no event - 0xFF, // EB no event - 0xFF, // EC no event - 0xFF, // ED no event - 0xFF, // EE no event - 0xFF, // EF no event - - 0xFF, // F0 no event - 0xFF, // F1 no event - 0xFF, // F2 no event - 0xFF, // F3 no event - 0xFF, // F4 no event - 0xFF, // F5 no event - 0xFF, // F6 no event - 0xFF, // F7 no event - 0xFF, // F8 no event - 0xFF, // F9 no event - 0xFF, // FA no event - 0xFF, // FB no event - 0xFF, // FC no event - 0xFF, // FD no event - 0xFF, // FE no event - 0xFF, // FF no event + 0xFF, // 00 no event + 0xFF, // 01 ErrorRollOver + 0xFF, // 02 POSTFail + 0xFF, // 03 ErrorUndefined + 0x00, // 04 A + 0x0B, // 05 B + 0x08, // 06 C + 0x02, // 07 D + 0x0E, // 08 E + 0x03, // 09 F + 0x05, // 0A G + 0x04, // 0B H + 0x22, // 0C I + 0x26, // 0D J + 0x28, // 0E K + 0x25, // 0F L + + 0x2E, // 10 M + 0x2D, // 11 N + 0x1F, // 12 O + 0x23, // 13 P + 0x0C, // 14 Q + 0x0F, // 15 R + 0x01, // 16 S + 0x11, // 17 T + 0x20, // 18 U + 0x09, // 19 V + 0x0D, // 1A W + 0x07, // 1B X + 0x10, // 1C Y + 0x06, // 1D Z + 0x12, // 1E 1/! + 0x13, // 1F 2/@ + + 0x14, // 20 3 # + 0x15, // 21 4 $ + 0x17, // 22 5 % + 0x16, // 23 6 ^ + 0x1A, // 24 7 & + 0x1C, // 25 8 * + 0x19, // 26 9 ( + 0x1D, // 27 0 ) + 0x24, // 28 Return (Enter) + 0x35, // 29 ESC + 0x33, // 2A Delete (Backspace) + 0x30, // 2B Tab + 0x31, // 2C Spacebar + 0x1B, // 2D - _ + 0x18, // 2E = + + 0x21, // 2F [ { + + 0x1E, // 30 ] } + 0x2A, // 31 \ | + 0xFF, // 32 Non-US # and ~ (what?!!!) + 0x29, // 33 ; : + 0x27, // 34 ' " + 0x32, // 35 ` ~ + 0x2B, // 36 , < + 0x2F, // 37 . > + 0x2C, // 38 / ? + 0x39, // 39 Caps Lock + 0x7A, // 3A F1 + 0x78, // 3B F2 + 0x63, // 3C F3 + 0x76, // 3D F4 + 0x60, // 3E F5 + 0x61, // 3F F6 + + 0x62, // 40 F7 + 0x64, // 41 F8 + 0x65, // 42 F9 + 0x6D, // 43 F10 + 0x67, // 44 F11 + 0x6F, // 45 F12 + 0x69, // 46 F13/PrintScreen + 0x6B, // 47 F14/ScrollLock + 0x71, // 48 F15/Pause + 0x72, // 49 Insert + 0x73, // 4A Home + 0x74, // 4B PageUp + 0x75, // 4C Delete Forward + 0x77, // 4D End + 0x79, // 4E PageDown + 0x7C, // 4F RightArrow + + 0x7B, // 50 LeftArrow + 0x7D, // 51 DownArrow + 0x7E, // 52 UpArrow + 0x47, // 53 NumLock/Clear + 0x4B, // 54 Keypad / + 0x43, // 55 Keypad * + 0x4E, // 56 Keypad - + 0x45, // 57 Keypad + + 0x4C, // 58 Keypad Enter + 0x53, // 59 Keypad 1 + 0x54, // 5A Keypad 2 + 0x55, // 5B Keypad 3 + 0x56, // 5C Keypad 4 + 0x57, // 5D Keypad 5 + 0x58, // 5E Keypad 6 + 0x59, // 5F Keypad 7 + + 0x5B, // 60 Keypad 8 + 0x5C, // 61 Keypad 9 + 0x52, // 62 Keypad 0 + 0x41, // 63 Keypad . + 0xFF, // 64 Non-US \ and | (what ??!!) + 0x6E, // 65 ApplicationKey (not on Apple keyboards) + 0x7F, // 66 PowerKey + 0x51, // 67 Keypad = + 0x69, // 68 F13 + 0x6B, // 69 F14 + 0x71, // 6A F15 + 0xFF, // 6B F16 + 0xFF, // 6C F17 + 0xFF, // 6D F18 + 0xFF, // 6E F19 + 0xFF, // 6F F20 + + 0x5B, // 70 F21 + 0x5C, // 71 F22 + 0x52, // 72 F23 + 0x41, // 73 F24 + 0xFF, // 74 Execute + 0xFF, // 75 Help + 0x7F, // 76 Menu + 0x4C, // 77 Select + 0x69, // 78 Stop + 0x6B, // 79 Again + 0x71, // 7A Undo + 0xFF, // 7B Cut + 0xFF, // 7C Copy + 0xFF, // 7D Paste + 0xFF, // 7E Find + 0xFF, // 7F Mute + + 0xFF, // 80 no event + 0xFF, // 81 no event + 0xFF, // 82 no event + 0xFF, // 83 no event + 0xFF, // 84 no event + 0xFF, // 85 no event + 0xFF, // 86 no event + 0xFF, // 87 no event + 0xFF, // 88 no event + 0xFF, // 89 no event + 0xFF, // 8A no event + 0xFF, // 8B no event + 0xFF, // 8C no event + 0xFF, // 8D no event + 0xFF, // 8E no event + 0xFF, // 8F no event + + 0xFF, // 90 no event + 0xFF, // 91 no event + 0xFF, // 92 no event + 0xFF, // 93 no event + 0xFF, // 94 no event + 0xFF, // 95 no event + 0xFF, // 96 no event + 0xFF, // 97 no event + 0xFF, // 98 no event + 0xFF, // 99 no event + 0xFF, // 9A no event + 0xFF, // 9B no event + 0xFF, // 9C no event + 0xFF, // 9D no event + 0xFF, // 9E no event + 0xFF, // 9F no event + + 0xFF, // A0 no event + 0xFF, // A1 no event + 0xFF, // A2 no event + 0xFF, // A3 no event + 0xFF, // A4 no event + 0xFF, // A5 no event + 0xFF, // A6 no event + 0xFF, // A7 no event + 0xFF, // A8 no event + 0xFF, // A9 no event + 0xFF, // AA no event + 0xFF, // AB no event + 0xFF, // AC no event + 0xFF, // AD no event + 0xFF, // AE no event + 0xFF, // AF no event + + 0xFF, // B0 no event + 0xFF, // B1 no event + 0xFF, // B2 no event + 0xFF, // B3 no event + 0xFF, // B4 no event + 0xFF, // B5 no event + 0xFF, // B6 no event + 0xFF, // B7 no event + 0xFF, // B8 no event + 0xFF, // B9 no event + 0xFF, // BA no event + 0xFF, // BB no event + 0xFF, // BC no event + 0xFF, // BD no event + 0xFF, // BE no event + 0xFF, // BF no event + + 0xFF, // C0 no event + 0xFF, // C1 no event + 0xFF, // C2 no event + 0xFF, // C3 no event + 0xFF, // C4 no event + 0xFF, // C5 no event + 0xFF, // C6 no event + 0xFF, // C7 no event + 0xFF, // C8 no event + 0xFF, // C9 no event + 0xFF, // CA no event + 0xFF, // CB no event + 0xFF, // CC no event + 0xFF, // CD no event + 0xFF, // CE no event + 0xFF, // CF no event + + 0xFF, // D0 no event + 0xFF, // D1 no event + 0xFF, // D2 no event + 0xFF, // D3 no event + 0xFF, // D4 no event + 0xFF, // D5 no event + 0xFF, // D6 no event + 0xFF, // D7 no event + 0xFF, // D8 no event + 0xFF, // D9 no event + 0xFF, // DA no event + 0xFF, // DB no event + 0xFF, // DC no event + 0xFF, // DD no event + 0xFF, // DE no event + 0xFF, // DF no event + + 0x3B, // E0 left control key + 0x38, // E1 left shift key key + 0x3A, // E2 left alt/option key + 0x37, // E3 left GUI (windows/cmd) key + + 0x3B, // E4 right control key + 0x38, // E5 right shift key key + 0x3A, // E6 right alt/option key + 0x37, // E7 right GUI (windows/cmd) key + 0xFF, // E8 no event + 0xFF, // E9 no event + 0xFF, // EA no event + 0xFF, // EB no event + 0xFF, // EC no event + 0xFF, // ED no event + 0xFF, // EE no event + 0xFF, // EF no event + + 0xFF, // F0 no event + 0xFF, // F1 no event + 0xFF, // F2 no event + 0xFF, // F3 no event + 0xFF, // F4 no event + 0xFF, // F5 no event + 0xFF, // F6 no event + 0xFF, // F7 no event + 0xFF, // F8 no event + 0xFF, // F9 no event + 0xFF, // FA no event + 0xFF, // FB no event + 0xFF, // FC no event + 0xFF, // FD no event + 0xFF, // FE no event + 0xFF, // FF no event }; static UInt8 g_iDeviceButtonToMacVirtualKey[KEY_OTHER_0]; bool KeyboardDevice::DeviceButtonToMacVirtualKey( DeviceButton button, UInt8 &iMacVKOut ) { - static bool bInited = false; - - if( !bInited ) - { - memset( g_iDeviceButtonToMacVirtualKey, 0xFF, sizeof(g_iDeviceButtonToMacVirtualKey) ); - for( int iUsbKey = 0; iUsbKey < 256; ++iUsbKey ) - { - DeviceButton button2; - if( UsbKeyToDeviceButton(iUsbKey, button2) && size_t(button2) < sizeof(g_iDeviceButtonToMacVirtualKey) ) - g_iDeviceButtonToMacVirtualKey[button2] = g_iUsbKeyToMacVirtualKey[iUsbKey]; - } - bInited = true; - } - iMacVKOut = g_iDeviceButtonToMacVirtualKey[button]; - return iMacVKOut != 0xFF; + static bool bInited = false; + + if( !bInited ) + { + memset( g_iDeviceButtonToMacVirtualKey, 0xFF, sizeof(g_iDeviceButtonToMacVirtualKey) ); + for( int iUsbKey = 0; iUsbKey < 256; ++iUsbKey ) + { + DeviceButton button2; + if( UsbKeyToDeviceButton(iUsbKey, button2) && size_t(button2) < sizeof(g_iDeviceButtonToMacVirtualKey) ) + g_iDeviceButtonToMacVirtualKey[button2] = g_iUsbKeyToMacVirtualKey[iUsbKey]; + } + bInited = true; + } + iMacVKOut = g_iDeviceButtonToMacVirtualKey[button]; + return iMacVKOut != 0xFF; } @@ -514,3 +511,4 @@ bool KeyboardDevice::DeviceButtonToMacVirtualKey( DeviceButton button, UInt8 &iM * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ + diff --git a/src/archutils/Darwin/SMMain.mm b/src/archutils/Darwin/SMMain.mm index 089430edca..6dc2e9dcb3 100644 --- a/src/archutils/Darwin/SMMain.mm +++ b/src/archutils/Darwin/SMMain.mm @@ -35,6 +35,7 @@ float MACWindowWidth() return frame.size.width; } + @interface NSApplication (PrivateShutUpWarning) - (void) setAppleMenu:(NSMenu *)menu; @end @@ -50,24 +51,25 @@ - (void) fullscreen:(id)sender; @implementation SMApplication - (void)fullscreen:(id)sender { - [[self mainWindow] toggleFullScreen:nil]; + // don't use ArchHooks::SetToggleWindowed(), it makes the screen black + [[self mainWindow] toggleFullScreen:nil]; } - (void)sendEvent:(NSEvent *)event { - if( [event type] == NSKeyDown ) - [[self mainMenu] performKeyEquivalent:event]; - else - [super sendEvent:event]; + if( [event type] == NSKeyDown ) + [[self mainMenu] performKeyEquivalent:event]; + else + [super sendEvent:event]; } @end // The main class of the application, the application's delegate. @interface SMMain : NSObject { - int m_iArgc; - char **m_pArgv; - BOOL m_bApplicationLaunched; + int m_iArgc; + char **m_pArgv; + BOOL m_bApplicationLaunched; } - (id) initWithArgc:(int)argc argv:(char **)argv; - (void) startGame:(id)sender; @@ -81,182 +83,181 @@ @implementation SMMain - (id) initWithArgc:(int)argc argv:(char **)argv { - [super init]; - if( argc == 2 && !strncmp(argv[1], "-psn_", 5) ) - argc = 1; - m_iArgc = argc; - m_pArgv = new char*[argc]; - for( int i = 0; i < argc; ++i ) - m_pArgv[i] = argv[i]; - m_bApplicationLaunched = NO; - return self; + [super init]; + if( argc == 2 && !strncmp(argv[1], "-psn_", 5) ) + argc = 1; + m_iArgc = argc; + m_pArgv = new char*[argc]; + for( int i = 0; i < argc; ++i ) + m_pArgv[i] = argv[i]; + m_bApplicationLaunched = NO; + return self; } - (void) startGame:(id)sender { - // Hand off to main application code. - exit( sm_main(m_iArgc, m_pArgv) ); + // Hand off to main application code. + exit( sm_main(m_iArgc, m_pArgv) ); } /* From here: * http://www.cocoadev.com/index.pl?HowToRegisterURLHandler */ - (void) getUrl:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent { - const char *url = [[[event paramDescriptorForKeyword:keyDirectObject] stringValue] UTF8String]; - - LOG->Info("Parsing URL: %s", url); - - // I'm not sure this handles everything it needs to. - Colby - CommandLineActions::CommandLineArgs args; - args.argv.push_back(url); - - CommandLineActions::ToProcess.push_back(args); + const char *url = [[[event paramDescriptorForKeyword:keyDirectObject] stringValue] UTF8String]; + + LOG->Info("Parsing URL: %s", url); + + // I'm not sure this handles everything it needs to. - Colby + CommandLineActions::CommandLineArgs args; + args.argv.push_back(url); + + CommandLineActions::ToProcess.push_back(args); } // Called when the internal event loop has just started running. - (void) applicationDidFinishLaunching:(NSNotification *)note { - m_bApplicationLaunched = YES; - [NSThread detachNewThreadSelector:@selector(startGame:) toTarget:self withObject:nil]; - - // Register ourselves as a URL handler. - [ - [NSAppleEventManager sharedAppleEventManager] setEventHandler:self - andSelector:@selector(getUrl:withReplyEvent:) - forEventClass:kInternetEventClass - andEventID:kAEGetURL - ]; + m_bApplicationLaunched = YES; + [NSThread detachNewThreadSelector:@selector(startGame:) toTarget:self withObject:nil]; + + // Register ourselves as a URL handler. + [ + [NSAppleEventManager sharedAppleEventManager] setEventHandler:self + andSelector:@selector(getUrl:withReplyEvent:) + forEventClass:kInternetEventClass + andEventID:kAEGetURL + ]; } - (BOOL) application:(NSApplication *)app openFile:(NSString *)file { - NSArray *files = [NSArray arrayWithObject:file]; - if( m_bApplicationLaunched ) - [NSTask launchedTaskWithLaunchPath:[NSString stringWithUTF8String:m_pArgv[0]] arguments:files]; - else - [self setForInstall:files]; - return YES; + NSArray *files = [NSArray arrayWithObject:file]; + if( m_bApplicationLaunched ) + [NSTask launchedTaskWithLaunchPath:[NSString stringWithUTF8String:m_pArgv[0]] arguments:files]; + else + [self setForInstall:files]; + return YES; } - (void) application:(NSApplication *)app openFiles:(NSArray *)files { - if( m_bApplicationLaunched ) - [NSTask launchedTaskWithLaunchPath:[NSString stringWithUTF8String:m_pArgv[0]] arguments:files]; - else - [self setForInstall:files]; - [app replyToOpenOrPrint:NSApplicationDelegateReplySuccess]; + if( m_bApplicationLaunched ) + [NSTask launchedTaskWithLaunchPath:[NSString stringWithUTF8String:m_pArgv[0]] arguments:files]; + else + [self setForInstall:files]; + [app replyToOpenOrPrint:NSApplicationDelegateReplySuccess]; } - - (void) setForInstall:(NSArray *)files { - char **temp = new char*[[files count] + m_iArgc]; - for( int i = 0; i < m_iArgc; ++i ) - temp[i] = m_pArgv[i]; - for( unsigned i = 0; i < [files count]; ++i, ++m_iArgc ) - { - const char *p = [[files objectAtIndex:i] fileSystemRepresentation]; - temp[m_iArgc] = new char[strlen(p)+1]; - strcpy( temp[m_iArgc], p ); - } - delete[] m_pArgv; - m_pArgv = temp; + char **temp = new char*[[files count] + m_iArgc]; + for( int i = 0; i < m_iArgc; ++i ) + temp[i] = m_pArgv[i]; + for( unsigned i = 0; i < [files count]; ++i, ++m_iArgc ) + { + const char *p = [[files objectAtIndex:i] fileSystemRepresentation]; + temp[m_iArgc] = new char[strlen(p)+1]; + strcpy( temp[m_iArgc], p ); + } + delete[] m_pArgv; + m_pArgv = temp; } - (NSApplicationTerminateReply) applicationShouldTerminate:(NSApplication *)sender { - ArchHooks::SetUserQuit(); - return NSTerminateCancel; + ArchHooks::SetUserQuit(); + return NSTerminateCancel; } @end static void HandleNSException( NSException *exception ) { - FAIL_M( ssprintf("%s raised: %s", [[exception name] UTF8String], [[exception reason] UTF8String]) ); + FAIL_M( ssprintf("%s raised: %s", [[exception name] UTF8String], [[exception reason] UTF8String]) ); } static NSMenuItem *MenuItem( NSString *title, SEL action, NSString *code ) { - // Autorelease these because they'll be retained by the NSMenu. - return [[[NSMenuItem alloc] initWithTitle:title action:action keyEquivalent:code] autorelease]; + // Autorelease these because they'll be retained by the NSMenu. + return [[[NSMenuItem alloc] initWithTitle:title action:action keyEquivalent:code] autorelease]; } static void SetupMenus( void ) { - // Get the localized strings from the file. - NSString *sWindow = NSLocalizedString( @"Window", @"Menu title" ); - NSString *sHideOthers = NSLocalizedString( @"Hide Others", @"Menu item" ); - NSString *sAbout = NSLocalizedString( @"About " PRODUCT_FAMILY, @"Menu item" ); - NSString *sHide = NSLocalizedString( @"Hide " PRODUCT_FAMILY, @"Menu item" ); - NSString *sShowAll = NSLocalizedString( @"Show All", @"Menu item" ); - NSString *sQuit = NSLocalizedString( @"Quit " PRODUCT_FAMILY, @"Menu item" ); - NSString *sMinimize = NSLocalizedString( @"Minimize", @"Menu item" ); - NSString *sEnterFullScreen = NSLocalizedString( @"Enter Full Screen", @"Menu item" ); - - NSMenu *mainMenu = [[[NSMenu alloc] initWithTitle:@""] autorelease]; - NSMenu *appMenu = [[[NSMenu alloc] initWithTitle:@PRODUCT_FAMILY] autorelease]; - NSMenu *windowMenu = [[[NSMenu alloc] initWithTitle:sWindow] autorelease]; - NSMenuItem *hideOthers = MenuItem( sHideOthers, @selector(hideOtherApplications:), @"h" ); - - [hideOthers setKeyEquivalentModifierMask:NSAlternateKeyMask | NSCommandKeyMask ]; - - [appMenu addItem:MenuItem( sAbout, @selector(orderFrontStandardAboutPanel:), @"" )]; - [appMenu addItem:[NSMenuItem separatorItem]]; - [appMenu addItem:MenuItem( sHide, @selector(hide:), @"h" )]; - [appMenu addItem:hideOthers]; - [appMenu addItem:MenuItem( sShowAll, @selector(unhideAllApplications:), @"" )]; - [appMenu addItem:[NSMenuItem separatorItem]]; - [appMenu addItem:MenuItem( sQuit, @selector(terminate:), @"q" )]; - - [windowMenu addItem:MenuItem( sMinimize, @selector(performMiniaturize:), @"m" )]; - [windowMenu addItem:[NSMenuItem separatorItem]]; - - // Add a Full Screen item. - NSMenuItem *item = MenuItem( sEnterFullScreen, @selector(fullscreen:), @"\n" ); - - [item setKeyEquivalentModifierMask:NSAlternateKeyMask]; // opt-enter - [windowMenu addItem:item]; - - [[mainMenu addItemWithTitle:[appMenu title] action:NULL keyEquivalent:@""] setSubmenu:appMenu]; - [[mainMenu addItemWithTitle:[windowMenu title] action:NULL keyEquivalent:@""] setSubmenu:windowMenu]; - - [NSApp setMainMenu:mainMenu]; - [NSApp setAppleMenu:appMenu]; // This isn't the apple menu, but it doesn't work without this. - [NSApp setWindowsMenu:windowMenu]; + // Get the localized strings from the file. + NSString *sWindow = NSLocalizedString( @"Window", @"Menu title" ); + NSString *sHideOthers = NSLocalizedString( @"Hide Others", @"Menu item" ); + NSString *sAbout = NSLocalizedString( @"About " PRODUCT_FAMILY, @"Menu item" ); + NSString *sHide = NSLocalizedString( @"Hide " PRODUCT_FAMILY, @"Menu item" ); + NSString *sShowAll = NSLocalizedString( @"Show All", @"Menu item" ); + NSString *sQuit = NSLocalizedString( @"Quit " PRODUCT_FAMILY, @"Menu item" ); + NSString *sMinimize = NSLocalizedString( @"Minimize", @"Menu item" ); + NSString *sEnterFullScreen = NSLocalizedString( @"Enter Full Screen", @"Menu item" ); + + NSMenu *mainMenu = [[[NSMenu alloc] initWithTitle:@""] autorelease]; + NSMenu *appMenu = [[[NSMenu alloc] initWithTitle:@PRODUCT_FAMILY] autorelease]; + NSMenu *windowMenu = [[[NSMenu alloc] initWithTitle:sWindow] autorelease]; + NSMenuItem *hideOthers = MenuItem( sHideOthers, @selector(hideOtherApplications:), @"h" ); + + [hideOthers setKeyEquivalentModifierMask:NSAlternateKeyMask | NSCommandKeyMask ]; + + [appMenu addItem:MenuItem( sAbout, @selector(orderFrontStandardAboutPanel:), @"" )]; + [appMenu addItem:[NSMenuItem separatorItem]]; + [appMenu addItem:MenuItem( sHide, @selector(hide:), @"h" )]; + [appMenu addItem:hideOthers]; + [appMenu addItem:MenuItem( sShowAll, @selector(unhideAllApplications:), @"" )]; + [appMenu addItem:[NSMenuItem separatorItem]]; + [appMenu addItem:MenuItem( sQuit, @selector(terminate:), @"q" )]; + + [windowMenu addItem:MenuItem( sMinimize, @selector(performMiniaturize:), @"m" )]; + [windowMenu addItem:[NSMenuItem separatorItem]]; + + // Add a Full Screen item. + NSMenuItem *item = MenuItem( sEnterFullScreen, @selector(fullscreen:), @"\n" ); + + [item setKeyEquivalentModifierMask:NSAlternateKeyMask]; // opt-enter + [windowMenu addItem:item]; + + [[mainMenu addItemWithTitle:[appMenu title] action:NULL keyEquivalent:@""] setSubmenu:appMenu]; + [[mainMenu addItemWithTitle:[windowMenu title] action:NULL keyEquivalent:@""] setSubmenu:windowMenu]; + + [NSApp setMainMenu:mainMenu]; + [NSApp setAppleMenu:appMenu]; // This isn't the apple menu, but it doesn't work without this. + [NSApp setWindowsMenu:windowMenu]; } #undef main int main( int argc, char **argv ) { - RageThreadRegister guiThread( "GUI thread" ); - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - SMMain *sm; - - // Ensure the application object is initialised, this sets NSApp. - [SMApplication sharedApplication]; - - // Set up NSException handler. - NSSetUncaughtExceptionHandler( HandleNSException ); - - // Set up the menubar. - SetupMenus(); - - // Create SMMain and make it the app delegate. - sm = [[SMMain alloc] initWithArgc:argc argv:argv]; - [NSApp setDelegate:sm]; - - [pool release]; - // Start the main event loop. - [NSApp run]; - [sm release]; - return 0; + RageThreadRegister guiThread( "GUI thread" ); + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + SMMain *sm; + + // Ensure the application object is initialised, this sets NSApp. + [SMApplication sharedApplication]; + + // Set up NSException handler. + NSSetUncaughtExceptionHandler( HandleNSException ); + + // Set up the menubar. + SetupMenus(); + + // Create SMMain and make it the app delegate. + sm = [[SMMain alloc] initWithArgc:argc argv:argv]; + [NSApp setDelegate:static_cast>(sm)]; + + [pool release]; + // Start the main event loop. + [NSApp run]; + [sm release]; + return 0; } /* * (c) 2005-2009 Steve Checkoway * All rights reserved. - * + * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including @@ -266,7 +267,7 @@ int main( int argc, char **argv ) * copyright notice(s) and this permission notice appear in all copies of * the Software and that both the above copyright notice(s) and this * permission notice appear in supporting documentation. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF