diff options
Diffstat (limited to 'osdep/ar/HIDRemote.m')
-rw-r--r-- | osdep/ar/HIDRemote.m | 3450 |
1 files changed, 1725 insertions, 1725 deletions
diff --git a/osdep/ar/HIDRemote.m b/osdep/ar/HIDRemote.m index 4e5b88e770..977b9cbdb9 100644 --- a/osdep/ar/HIDRemote.m +++ b/osdep/ar/HIDRemote.m @@ -52,23 +52,23 @@ #import "HIDRemote.h" // Callback Prototypes -static void HIDEventCallback( void * target, - IOReturn result, - void * refcon, - void * sender); +static void HIDEventCallback( void * target, + IOReturn result, + void * refcon, + void * sender); -static void ServiceMatchingCallback( void *refCon, - io_iterator_t iterator); +static void ServiceMatchingCallback( void *refCon, + io_iterator_t iterator); -static void ServiceNotificationCallback(void * refCon, - io_service_t service, - natural_t messageType, - void * messageArgument); +static void ServiceNotificationCallback(void * refCon, + io_service_t service, + natural_t messageType, + void * messageArgument); -static void SecureInputNotificationCallback( void * refCon, - io_service_t service, - natural_t messageType, - void * messageArgument); +static void SecureInputNotificationCallback( void * refCon, + io_service_t service, + natural_t messageType, + void * messageArgument); // Shared HIDRemote instance static HIDRemote *sHIDRemote = nil; @@ -79,1947 +79,1947 @@ static HIDRemote *sHIDRemote = nil; + (HIDRemote *)sharedHIDRemote { - if (sHIDRemote==nil) - { - sHIDRemote = [[HIDRemote alloc] init]; - } - - return (sHIDRemote); + if (sHIDRemote==nil) + { + sHIDRemote = [[HIDRemote alloc] init]; + } + + return (sHIDRemote); } - (id)init { - if ((self = [super init]) != nil) - { - #ifdef HIDREMOTE_THREADSAFETY_HARDENED_NOTIFICATION_HANDLING - _runOnThread = [[NSThread currentThread] retain]; - #endif - - // Detect application becoming active/inactive - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_appStatusChanged:) name:NSApplicationDidBecomeActiveNotification object:NSApp]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_appStatusChanged:) name:NSApplicationWillResignActiveNotification object:NSApp]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_appStatusChanged:) name:NSApplicationWillTerminateNotification object:NSApp]; - - // Handle distributed notifications - _pidString = [[NSString alloc] initWithFormat:@"%d", getpid()]; - - [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(_handleNotifications:) name:kHIDRemoteDNHIDRemotePing object:nil]; - [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(_handleNotifications:) name:kHIDRemoteDNHIDRemoteRetry object:kHIDRemoteDNHIDRemoteRetryGlobalObject]; - [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(_handleNotifications:) name:kHIDRemoteDNHIDRemoteRetry object:_pidString]; - - // Enabled by default: simulate hold events for plus/minus - _simulateHoldEvents = YES; - - // Enabled by default: work around for a locking issue introduced with Security Update 2008-004 / 10.4.9 and beyond (credit for finding this workaround goes to Martin Kahr) - _secureEventInputWorkAround = YES; - _secureInputNotification = 0; - - // Initialize instance variables - _lastSeenRemoteID = -1; - _lastSeenModel = kHIDRemoteModelUndetermined; - _unusedButtonCodes = [[NSMutableArray alloc] init]; - _exclusiveLockLending = NO; - _sendExclusiveResourceReuseNotification = YES; - _applicationIsTerminating = NO; - - // Send status notifications - _sendStatusNotifications = YES; - } - - return (self); + if ((self = [super init]) != nil) + { + #ifdef HIDREMOTE_THREADSAFETY_HARDENED_NOTIFICATION_HANDLING + _runOnThread = [[NSThread currentThread] retain]; + #endif + + // Detect application becoming active/inactive + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_appStatusChanged:) name:NSApplicationDidBecomeActiveNotification object:NSApp]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_appStatusChanged:) name:NSApplicationWillResignActiveNotification object:NSApp]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_appStatusChanged:) name:NSApplicationWillTerminateNotification object:NSApp]; + + // Handle distributed notifications + _pidString = [[NSString alloc] initWithFormat:@"%d", getpid()]; + + [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(_handleNotifications:) name:kHIDRemoteDNHIDRemotePing object:nil]; + [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(_handleNotifications:) name:kHIDRemoteDNHIDRemoteRetry object:kHIDRemoteDNHIDRemoteRetryGlobalObject]; + [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(_handleNotifications:) name:kHIDRemoteDNHIDRemoteRetry object:_pidString]; + + // Enabled by default: simulate hold events for plus/minus + _simulateHoldEvents = YES; + + // Enabled by default: work around for a locking issue introduced with Security Update 2008-004 / 10.4.9 and beyond (credit for finding this workaround goes to Martin Kahr) + _secureEventInputWorkAround = YES; + _secureInputNotification = 0; + + // Initialize instance variables + _lastSeenRemoteID = -1; + _lastSeenModel = kHIDRemoteModelUndetermined; + _unusedButtonCodes = [[NSMutableArray alloc] init]; + _exclusiveLockLending = NO; + _sendExclusiveResourceReuseNotification = YES; + _applicationIsTerminating = NO; + + // Send status notifications + _sendStatusNotifications = YES; + } + + return (self); } - (void)dealloc { - [[NSNotificationCenter defaultCenter] removeObserver:self name:NSApplicationWillTerminateNotification object:NSApp]; - [[NSNotificationCenter defaultCenter] removeObserver:self name:NSApplicationWillResignActiveNotification object:NSApp]; - [[NSNotificationCenter defaultCenter] removeObserver:self name:NSApplicationDidBecomeActiveNotification object:NSApp]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:NSApplicationWillTerminateNotification object:NSApp]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:NSApplicationWillResignActiveNotification object:NSApp]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:NSApplicationDidBecomeActiveNotification object:NSApp]; - [[NSDistributedNotificationCenter defaultCenter] removeObserver:self name:kHIDRemoteDNHIDRemotePing object:nil]; - [[NSDistributedNotificationCenter defaultCenter] removeObserver:self name:kHIDRemoteDNHIDRemoteRetry object:kHIDRemoteDNHIDRemoteRetryGlobalObject]; - [[NSDistributedNotificationCenter defaultCenter] removeObserver:self name:kHIDRemoteDNHIDRemoteRetry object:_pidString]; - [[NSDistributedNotificationCenter defaultCenter] removeObserver:self name:nil object:nil]; /* As demanded by the documentation for -[NSDistributedNotificationCenter removeObserver:name:object:] */ - - [self stopRemoteControl]; + [[NSDistributedNotificationCenter defaultCenter] removeObserver:self name:kHIDRemoteDNHIDRemotePing object:nil]; + [[NSDistributedNotificationCenter defaultCenter] removeObserver:self name:kHIDRemoteDNHIDRemoteRetry object:kHIDRemoteDNHIDRemoteRetryGlobalObject]; + [[NSDistributedNotificationCenter defaultCenter] removeObserver:self name:kHIDRemoteDNHIDRemoteRetry object:_pidString]; + [[NSDistributedNotificationCenter defaultCenter] removeObserver:self name:nil object:nil]; /* As demanded by the documentation for -[NSDistributedNotificationCenter removeObserver:name:object:] */ + + [self stopRemoteControl]; - [self setExclusiveLockLendingEnabled:NO]; + [self setExclusiveLockLendingEnabled:NO]; - [self setDelegate:nil]; + [self setDelegate:nil]; - if (_unusedButtonCodes != nil) - { - [_unusedButtonCodes release]; - _unusedButtonCodes = nil; - } + if (_unusedButtonCodes != nil) + { + [_unusedButtonCodes release]; + _unusedButtonCodes = nil; + } - #ifdef HIDREMOTE_THREADSAFETY_HARDENED_NOTIFICATION_HANDLING - [_runOnThread release]; - _runOnThread = nil; - #endif + #ifdef HIDREMOTE_THREADSAFETY_HARDENED_NOTIFICATION_HANDLING + [_runOnThread release]; + _runOnThread = nil; + #endif - [_pidString release]; - _pidString = nil; + [_pidString release]; + _pidString = nil; - [super dealloc]; + [super dealloc]; } #pragma mark -- PUBLIC: System Information -- + (BOOL)isCandelairInstalled { - mach_port_t masterPort = 0; - kern_return_t kernResult; - io_service_t matchingService = 0; - BOOL isInstalled = NO; + mach_port_t masterPort = 0; + kern_return_t kernResult; + io_service_t matchingService = 0; + BOOL isInstalled = NO; - kernResult = IOMasterPort(MACH_PORT_NULL, &masterPort); - if ((kernResult!=kIOReturnSuccess) || (masterPort==0)) { return(NO); } + kernResult = IOMasterPort(MACH_PORT_NULL, &masterPort); + if ((kernResult!=kIOReturnSuccess) || (masterPort==0)) { return(NO); } - if ((matchingService = IOServiceGetMatchingService(masterPort, IOServiceMatching("IOSPIRITIRController"))) != 0) - { - isInstalled = YES; - IOObjectRelease((io_object_t) matchingService); - } + if ((matchingService = IOServiceGetMatchingService(masterPort, IOServiceMatching("IOSPIRITIRController"))) != 0) + { + isInstalled = YES; + IOObjectRelease((io_object_t) matchingService); + } - mach_port_deallocate(mach_task_self(), masterPort); + mach_port_deallocate(mach_task_self(), masterPort); - return (isInstalled); + return (isInstalled); } + (BOOL)isCandelairInstallationRequiredForRemoteMode:(HIDRemoteMode)remoteMode { - return (NO); + return (NO); } - (HIDRemoteAluminumRemoteSupportLevel)aluminiumRemoteSystemSupportLevel { - HIDRemoteAluminumRemoteSupportLevel supportLevel = kHIDRemoteAluminumRemoteSupportLevelNone; - NSEnumerator *attribDictsEnum; - NSDictionary *hidAttribsDict; - - attribDictsEnum = [_serviceAttribMap objectEnumerator]; - - while ((hidAttribsDict = [attribDictsEnum nextObject]) != nil) - { - NSNumber *deviceSupportLevel; - - if ((deviceSupportLevel = [hidAttribsDict objectForKey:kHIDRemoteAluminumRemoteSupportLevel]) != nil) - { - if ([deviceSupportLevel intValue] > (int)supportLevel) - { - supportLevel = [deviceSupportLevel intValue]; - } - } - } - - return (supportLevel); + HIDRemoteAluminumRemoteSupportLevel supportLevel = kHIDRemoteAluminumRemoteSupportLevelNone; + NSEnumerator *attribDictsEnum; + NSDictionary *hidAttribsDict; + + attribDictsEnum = [_serviceAttribMap objectEnumerator]; + + while ((hidAttribsDict = [attribDictsEnum nextObject]) != nil) + { + NSNumber *deviceSupportLevel; + + if ((deviceSupportLevel = [hidAttribsDict objectForKey:kHIDRemoteAluminumRemoteSupportLevel]) != nil) + { + if ([deviceSupportLevel intValue] > (int)supportLevel) + { + supportLevel = [deviceSupportLevel intValue]; + } + } + } + + return (supportLevel); } #pragma mark -- PUBLIC: Interface / API -- - (BOOL)startRemoteControl:(HIDRemoteMode)hidRemoteMode { - if ((_mode == kHIDRemoteModeNone) && (hidRemoteMode != kHIDRemoteModeNone)) - { - kern_return_t kernReturn; - CFMutableDictionaryRef matchDict=NULL; - io_service_t rootService; - - do - { - // Get IOKit master port - kernReturn = IOMasterPort(bootstrap_port, &_masterPort); - if ((kernReturn!=kIOReturnSuccess) || (_masterPort==0)) { break; } - - // Setup notification port - _notifyPort = IONotificationPortCreate(_masterPort); - - if ((_notifyRLSource = IONotificationPortGetRunLoopSource(_notifyPort)) != NULL) - { - CFRunLoopAddSource( CFRunLoopGetCurrent(), - _notifyRLSource, - kCFRunLoopCommonModes); - } - else - { - break; - } - - // Setup SecureInput notification - if ((hidRemoteMode == kHIDRemoteModeExclusive) || (hidRemoteMode == kHIDRemoteModeExclusiveAuto)) - { - if ((rootService = IORegistryEntryFromPath(_masterPort, kIOServicePlane ":/")) != 0) - { - kernReturn = IOServiceAddInterestNotification( _notifyPort, - rootService, - kIOBusyInterest, - SecureInputNotificationCallback, - (void *)self, - &_secureInputNotification); - if (kernReturn != kIOReturnSuccess) { break; } - - [self _updateSessionInformation]; - } - else - { - break; - } - } - - // Setup notification matching dict - matchDict = IOServiceMatching(kIOHIDDeviceKey); - CFRetain(matchDict); - - // Actually add notification - kernReturn = IOServiceAddMatchingNotification( _notifyPort, - kIOFirstMatchNotification, - matchDict, // one reference count consumed by this call - ServiceMatchingCallback, - (void *) self, - &_matchingServicesIterator); - if (kernReturn != kIOReturnSuccess) { break; } - - // Setup serviceAttribMap - _serviceAttribMap = [[NSMutableDictionary alloc] init]; - if (_serviceAttribMap==nil) { break; } - - // Phew .. everything went well! - _mode = hidRemoteMode; - CFRelease(matchDict); - - [self _serviceMatching:_matchingServicesIterator]; - - [self _postStatusWithAction:kHIDRemoteDNStatusActionStart]; - - return (YES); - - }while(0); - - // An error occured. Do necessary clean up. - if (matchDict!=NULL) - { - CFRelease(matchDict); - matchDict = NULL; - } - - [self stopRemoteControl]; - } - - return (NO); + if ((_mode == kHIDRemoteModeNone) && (hidRemoteMode != kHIDRemoteModeNone)) + { + kern_return_t kernReturn; + CFMutableDictionaryRef matchDict=NULL; + io_service_t rootService; + + do + { + // Get IOKit master port + kernReturn = IOMasterPort(bootstrap_port, &_masterPort); + if ((kernReturn!=kIOReturnSuccess) || (_masterPort==0)) { break; } + + // Setup notification port + _notifyPort = IONotificationPortCreate(_masterPort); + + if ((_notifyRLSource = IONotificationPortGetRunLoopSource(_notifyPort)) != NULL) + { + CFRunLoopAddSource( CFRunLoopGetCurrent(), + _notifyRLSource, + kCFRunLoopCommonModes); + } + else + { + break; + } + + // Setup SecureInput notification + if ((hidRemoteMode == kHIDRemoteModeExclusive) || (hidRemoteMode == kHIDRemoteModeExclusiveAuto)) + { + if ((rootService = IORegistryEntryFromPath(_masterPort, kIOServicePlane ":/")) != 0) + { + kernReturn = IOServiceAddInterestNotification( _notifyPort, + rootService, + kIOBusyInterest, + SecureInputNotificationCallback, + (void *)self, + &_secureInputNotification); + if (kernReturn != kIOReturnSuccess) { break; } + + [self _updateSessionInformation]; + } + else + { + break; + } + } + + // Setup notification matching dict + matchDict = IOServiceMatching(kIOHIDDeviceKey); + CFRetain(matchDict); + + // Actually add notification + kernReturn = IOServiceAddMatchingNotification( _notifyPort, + kIOFirstMatchNotification, + matchDict, // one reference count consumed by this call + ServiceMatchingCallback, + (void *) self, + &_matchingServicesIterator); + if (kernReturn != kIOReturnSuccess) { break; } + + // Setup serviceAttribMap + _serviceAttribMap = [[NSMutableDictionary alloc] init]; + if (_serviceAttribMap==nil) { break; } + + // Phew .. everything went well! + _mode = hidRemoteMode; + CFRelease(matchDict); + + [self _serviceMatching:_matchingServicesIterator]; + + [self _postStatusWithAction:kHIDRemoteDNStatusActionStart]; + + return (YES); + + }while(0); + + // An error occured. Do necessary clean up. + if (matchDict!=NULL) + { + CFRelease(matchDict); + matchDict = NULL; + } + + [self stopRemoteControl]; + } + + return (NO); } - (void)stopRemoteControl { - UInt32 serviceCount = 0; - - _autoRecover = NO; - _isStopping = YES; - - if (_autoRecoveryTimer!=nil) - { - [_autoRecoveryTimer invalidate]; - [_autoRecoveryTimer release]; - _autoRecoveryTimer = nil; - } - - if (_serviceAttribMap!=nil) - { - NSDictionary *cloneDict = [[NSDictionary alloc] initWithDictionary:_serviceAttribMap]; - - if (cloneDict!=nil) - { - NSEnumerator *mapKeyEnum = [cloneDict keyEnumerator]; - NSNumber *serviceValue; - - while ((serviceValue = [mapKeyEnum nextObject]) != nil) - { - [self _destructService:(io_object_t)[serviceValue unsignedIntValue]]; - serviceCount++; - }; - - [cloneDict release]; - cloneDict = nil; - } - - [_serviceAttribMap release]; - _serviceAttribMap = nil; - } - - if (_matchingServicesIterator!=0) - { - IOObjectRelease((io_object_t) _matchingServicesIterator); - _matchingServicesIterator = 0; - } - - if (_secureInputNotification!=0) - { - IOObjectRelease((io_object_t) _secureInputNotification); - _secureInputNotification = 0; - } - - if (_notifyRLSource!=NULL) - { - CFRunLoopSourceInvalidate(_notifyRLSource); - _notifyRLSource = NULL; - } - - if (_notifyPort!=NULL) - { - IONotificationPortDestroy(_notifyPort); - _notifyPort = NULL; - } - - if (_masterPort!=0) - { - mach_port_deallocate(mach_task_self(), _masterPort); - _masterPort = 0; - } - - if (_returnToPID!=nil) - { - [_returnToPID release]; - _returnToPID = nil; - } - - if (_mode!=kHIDRemoteModeNone) - { - // Post status - [self _postStatusWithAction:kHIDRemoteDNStatusActionStop]; - - if (_sendStatusNotifications) - { - // In case we were not ready to lend it earlier, tell other HIDRemote apps that the resources (if any were used) are now again available for use by other applications - if (((_mode==kHIDRemoteModeExclusive) || (_mode==kHIDRemoteModeExclusiveAuto)) && (_sendExclusiveResourceReuseNotification==YES) && (_exclusiveLockLending==NO) && (serviceCount>0)) - { - _mode = kHIDRemoteModeNone; - - if (!_isRestarting) - { - [[NSDistributedNotificationCenter defaultCenter] postNotificationName:kHIDRemoteDNHIDRemoteRetry - object:kHIDRemoteDNHIDRemoteRetryGlobalObject - userInfo:[NSDictionary dictionaryWithObjectsAndKeys: - [NSNumber numberWithUnsignedInt:(unsigned int)getpid()], kHIDRemoteDNStatusPIDKey, - [[NSBundle mainBundle] bundleIdentifier], (NSString *)kCFBundleIdentifierKey, - nil] - deliverImmediately:YES]; - } - } - } - } - - _mode = kHIDRemoteModeNone; - _isStopping = NO; + UInt32 serviceCount = 0; + + _autoRecover = NO; + _isStopping = YES; + + if (_autoRecoveryTimer!=nil) + { + [_autoRecoveryTimer invalidate]; + [_autoRecoveryTimer release]; + _autoRecoveryTimer = nil; + } + + if (_serviceAttribMap!=nil) + { + NSDictionary *cloneDict = [[NSDictionary alloc] initWithDictionary:_serviceAttribMap]; + + if (cloneDict!=nil) + { + NSEnumerator *mapKeyEnum = [cloneDict keyEnumerator]; + NSNumber *serviceValue; + + while ((serviceValue = [mapKeyEnum nextObject]) != nil) + { + [self _destructService:(io_object_t)[serviceValue unsignedIntValue]]; + serviceCount++; + }; + + [cloneDict release]; + cloneDict = nil; + } + + [_serviceAttribMap release]; + _serviceAttribMap = nil; + } + + if (_matchingServicesIterator!=0) + { + IOObjectRelease((io_object_t) _matchingServicesIterator); + _matchingServicesIterator = 0; + } + + if (_secureInputNotification!=0) + { + IOObjectRelease((io_object_t) _secureInputNotification); + _secureInputNotification = 0; + } + + if (_notifyRLSource!=NULL) + { + CFRunLoopSourceInvalidate(_notifyRLSource); + _notifyRLSource = NULL; + } + + if (_notifyPort!=NULL) + { + IONotificationPortDestroy(_notifyPort); + _notifyPort = NULL; + } + + if (_masterPort!=0) + { + mach_port_deallocate(mach_task_self(), _masterPort); + _masterPort = 0; + } + + if (_returnToPID!=nil) + { + [_returnToPID release]; + _returnToPID = nil; + } + + if (_mode!=kHIDRemoteModeNone) + { + // Post status + [self _postStatusWithAction:kHIDRemoteDNStatusActionStop]; + + if (_sendStatusNotifications) + { + // In case we were not ready to lend it earlier, tell other HIDRemote apps that the resources (if any were used) are now again available for use by other applications + if (((_mode==kHIDRemoteModeExclusive) || (_mode==kHIDRemoteModeExclusiveAuto)) && (_sendExclusiveResourceReuseNotification==YES) && (_exclusiveLockLending==NO) && (serviceCount>0)) + { + _mode = kHIDRemoteModeNone; + + if (!_isRestarting) + { + [[NSDistributedNotificationCenter defaultCenter] postNotificationName:kHIDRemoteDNHIDRemoteRetry + object:kHIDRemoteDNHIDRemoteRetryGlobalObject + userInfo:[NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithUnsignedInt:(unsigned int)getpid()], kHIDRemoteDNStatusPIDKey, + [[NSBundle mainBundle] bundleIdentifier], (NSString *)kCFBundleIdentifierKey, + nil] + deliverImmediately:YES]; + } + } + } + } + + _mode = kHIDRemoteModeNone; + _isStopping = NO; } - (BOOL)isStarted { - return (_mode != kHIDRemoteModeNone); + return (_mode != kHIDRemoteModeNone); } - (HIDRemoteMode)startedInMode { - return (_mode); + return (_mode); } - (unsigned)activeRemoteControlCount { - return ([_serviceAttribMap count]); + return ([_serviceAttribMap count]); } - (SInt32)lastSeenRemoteControlID { - return (_lastSeenRemoteID); + return (_lastSeenRemoteID); } - (HIDRemoteModel)lastSeenModel { - return (_lastSeenModel); + return (_lastSeenModel); } - (void)setLastSeenModel:(HIDRemoteModel)aModel { - _lastSeenModel = aModel; + _lastSeenModel = aModel; } - (void)setSimulateHoldEvents:(BOOL)newSimulateHoldEvents { - _simulateHoldEvents = newSimulateHoldEvents; + _simulateHoldEvents = newSimulateHoldEvents; } - (BOOL)simulateHoldEvents { - return (_simulateHoldEvents); + return (_simulateHoldEvents); } - (NSArray *)unusedButtonCodes { - return (_unusedButtonCodes); + return (_unusedButtonCodes); } - (void)setUnusedButtonCodes:(NSArray *)newArrayWithUnusedButtonCodesAsNSNumbers { - [newArrayWithUnusedButtonCodesAsNSNumbers retain]; - [_unusedButtonCodes release]; - - _unusedButtonCodes = newArrayWithUnusedButtonCodesAsNSNumbers; + [newArrayWithUnusedButtonCodesAsNSNumbers retain]; + [_unusedButtonCodes release]; + + _unusedButtonCodes = newArrayWithUnusedButtonCodesAsNSNumbers; - [self _postStatusWithAction:kHIDRemoteDNStatusActionUpdate]; + [self _postStatusWithAction:kHIDRemoteDNStatusActionUpdate]; } - (void)setDelegate:(NSObject <HIDRemoteDelegate> *)newDelegate { - _delegate = newDelegate; + _delegate = newDelegate; } - (NSObject <HIDRemoteDelegate> *)delegate { - return (_delegate); + return (_delegate); } #pragma mark -- PUBLIC: Expert APIs -- - (void)setEnableSecureEventInputWorkaround:(BOOL)newEnableSecureEventInputWorkaround { - _secureEventInputWorkAround = newEnableSecureEventInputWorkaround; + _secureEventInputWorkAround = newEnableSecureEventInputWorkaround; } - (BOOL)enableSecureEventInputWorkaround { - return (_secureEventInputWorkAround); + return (_secureEventInputWorkAround); } - (void)setExclusiveLockLendingEnabled:(BOOL)newExclusiveLockLendingEnabled { - if (newExclusiveLockLendingEnabled != _exclusiveLockLending) - { - _exclusiveLockLending = newExclusiveLockLendingEnabled; - - if (_exclusiveLockLending) - { - [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(_handleNotifications:) name:kHIDRemoteDNHIDRemoteStatus object:nil]; - } - else - { - [[NSDistributedNotificationCenter defaultCenter] removeObserver:self name:kHIDRemoteDNHIDRemoteStatus object:nil]; - - [_waitForReturnByPID release]; - _waitForReturnByPID = nil; - } - } + if (newExclusiveLockLendingEnabled != _exclusiveLockLending) + { + _exclusiveLockLending = newExclusiveLockLendingEnabled; + + if (_exclusiveLockLending) + { + [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(_handleNotifications:) name:kHIDRemoteDNHIDRemoteStatus object:nil]; + } + else + { + [[NSDistributedNotificationCenter defaultCenter] removeObserver:self name:kHIDRemoteDNHIDRemoteStatus object:nil]; + + [_waitForReturnByPID release]; + _waitForReturnByPID = nil; + } + } } - (BOOL)exclusiveLockLendingEnabled { - return (_exclusiveLockLending); + return (_exclusiveLockLending); } - (void)setSendExclusiveResourceReuseNotification:(BOOL)newSendExclusiveResourceReuseNotification { - _sendExclusiveResourceReuseNotification = newSendExclusiveResourceReuseNotification; + _sendExclusiveResourceReuseNotification = newSendExclusiveResourceReuseNotification; } - (BOOL)sendExclusiveResourceReuseNotification { - return (_sendExclusiveResourceReuseNotification); + return (_sendExclusiveResourceReuseNotification); } - (BOOL)isApplicationTerminating { - return (_applicationIsTerminating); + return (_applicationIsTerminating); } - (BOOL)isStopping { - return (_isStopping); + return (_isStopping); } #pragma mark -- PRIVATE: Application becomes active / inactive handling for kHIDRemoteModeExclusiveAuto -- - (void)_appStatusChanged:(NSNotification *)notification { - #ifdef HIDREMOTE_THREADSAFETY_HARDENED_NOTIFICATION_HANDLING - if ([self respondsToSelector:@selector(performSelector:onThread:withObject:waitUntilDone:)]) // OS X 10.5+ only - { - if ([NSThread currentThread] != _runOnThread) - { - if ([[notification name] isEqual:NSApplicationDidBecomeActiveNotification]) - { - if (!_autoRecover) - { - return; - } - } - - if ([[notification name] isEqual:NSApplicationWillResignActiveNotification]) - { - if (_mode != kHIDRemoteModeExclusiveAuto) - { - return; - } - } - - [self performSelector:@selector(_appStatusChanged:) onThread:_runOnThread withObject:notification waitUntilDone:[[notification name] isEqual:NSApplicationWillTerminateNotification]]; - return; - } - } - #endif - - if (notification!=nil) - { - if (_autoRecoveryTimer!=nil) - { - [_autoRecoveryTimer invalidate]; - [_autoRecoveryTimer release]; - _autoRecoveryTimer = nil; - } - - if ([[notification name] isEqual:NSApplicationDidBecomeActiveNotification]) - { - if (_autoRecover) - { - // Delay autorecover by 0.1 to avoid race conditions - if ((_autoRecoveryTimer = [[NSTimer alloc] initWithFireDate:[NSDate dateWithTimeIntervalSinceNow:0.1] interval:0.1 target:self selector:@selector(_delayedAutoRecovery:) userInfo:nil repeats:NO]) != nil) - { - // Using CFRunLoopAddTimer instead of [[NSRunLoop currentRunLoop] addTimer:.. for consistency with run loop modes. - // The kCFRunLoopCommonModes counterpart NSRunLoopCommonModes is only available in 10.5 and later, whereas this code - // is designed to be also compatible with 10.4. CFRunLoopTimerRef is "toll-free-bridged" with NSTimer since 10.0. - CFRunLoopAddTimer(CFRunLoopGetCurrent(), (CFRunLoopTimerRef)_autoRecoveryTimer, kCFRunLoopCommonModes); - } - } - } - - if ([[notification name] isEqual:NSApplicationWillResignActiveNotification]) - { - if (_mode == kHIDRemoteModeExclusiveAuto) - { - [self stopRemoteControl]; - _autoRecover = YES; - } - } - - if ([[notification name] isEqual:NSApplicationWillTerminateNotification]) - { - _applicationIsTerminating = YES; - - if ([self isStarted]) - { - [self stopRemoteControl]; - } - } - } + #ifdef HIDREMOTE_THREADSAFETY_HARDENED_NOTIFICATION_HANDLING + if ([self respondsToSelector:@selector(performSelector:onThread:withObject:waitUntilDone:)]) // OS X 10.5+ only + { + if ([NSThread currentThread] != _runOnThread) + { + if ([[notification name] isEqual:NSApplicationDidBecomeActiveNotification]) + { + if (!_autoRecover) + { + return; + } + } + + if ([[notification name] isEqual:NSApplicationWillResignActiveNotification]) + { + if (_mode != kHIDRemoteModeExclusiveAuto) + { + return; + } + } + + [self performSelector:@selector(_appStatusChanged:) onThread:_runOnThread withObject:notification waitUntilDone:[[notification name] isEqual:NSApplicationWillTerminateNotification]]; + return; + } + } + #endif + + if (notification!=nil) + { + if (_autoRecoveryTimer!=nil) + { + [_autoRecoveryTimer invalidate]; + [_autoRecoveryTimer release]; + _autoRecoveryTimer = nil; + } + + if ([[notification name] isEqual:NSApplicationDidBecomeActiveNotification]) + { + if (_autoRecover) + { + // Delay autorecover by 0.1 to avoid race conditions + if ((_autoRecoveryTimer = [[NSTimer alloc] initWithFireDate:[NSDate dateWithTimeIntervalSinceNow:0.1] interval:0.1 target:self selector:@selector(_delayedAutoRecovery:) userInfo:nil repeats:NO]) != nil) + { + // Using CFRunLoopAddTimer instead of [[NSRunLoop currentRunLoop] addTimer:.. for consistency with run loop modes. + // The kCFRunLoopCommonModes counterpart NSRunLoopCommonModes is only available in 10.5 and later, whereas this code + // is designed to be also compatible with 10.4. CFRunLoopTimerRef is "toll-free-bridged" with NSTimer since 10.0. + CFRunLoopAddTimer(CFRunLoopGetCurrent(), (CFRunLoopTimerRef)_autoRecoveryTimer, kCFRunLoopCommonModes); + } + } + } + + if ([[notification name] isEqual:NSApplicationWillResignActiveNotification]) + { + if (_mode == kHIDRemoteModeExclusiveAuto) + { + [self stopRemoteControl]; + _autoRecover = YES; + } + } + + if ([[notification name] isEqual:NSApplicationWillTerminateNotification]) + { + _applicationIsTerminating = YES; + + if ([self isStarted]) + { + [self stopRemoteControl]; + |