Rename displayLink to _displayLink.
[enjoyable.git] / Classes / NJInputController.m
index cd665de..ed0d72d 100644 (file)
 #import "NJOutput.h"
 #import "NJEvents.h"
 
+#import <CoreVideo/CoreVideo.h>
+
+@interface NJInputController ()
+
+- (void)updateContinuousOutputs;
+
+@end
+
+static CVReturn _updateDL(CVDisplayLinkRef displayLink,
+                          const CVTimeStamp *inNow,
+                          const CVTimeStamp *inOutputTime,
+                          CVOptionFlags flagsIn,
+                          CVOptionFlags *flagsOut,
+                          void *ctxManager) {
+    NJInputController *manager = (__bridge NJInputController *)ctxManager;
+    [manager performSelectorOnMainThread:@selector(updateContinuousOutputs)
+                              withObject:nil
+                           waitUntilDone:NO];
+    return kCVReturnSuccess;
+}
+
 @implementation NJInputController {
     NJHIDManager *_HIDManager;
-    NSTimer *_continuousOutputsTick;
     NSMutableArray *_continousOutputs;
     NSMutableArray *_devices;
     NSMutableArray *_mappings;
     NJMapping *_manualMapping;
-
+    CVDisplayLinkRef _displayLink;
 }
 
 #define NSSTR(e) ((NSString *)CFSTR(e))
     if ((self = [super init])) {
         _devices = [[NSMutableArray alloc] initWithCapacity:16];
         _continousOutputs = [[NSMutableArray alloc] initWithCapacity:32];
+
+        CVReturn cvErr = CVDisplayLinkCreateWithActiveCGDisplays(&_displayLink);
+        if (cvErr) {
+            NSError *error = [NSError errorWithDomain:NSCocoaErrorDomain
+                                                 code:cvErr
+                                             userInfo:nil];
+            [self.delegate inputController:self didError:error];
+            NSLog(@"DisplayLink failed creation with error: %@", error);
+            _displayLink = NULL;
+        }
+        CVDisplayLinkSetOutputCallback(_displayLink, _updateDL, (__bridge void *)self);
         
         _HIDManager = [[NJHIDManager alloc] initWithCriteria:@[
                        @{ NSSTR(kIOHIDDeviceUsagePageKey) : @(kHIDPage_GenericDesktop),
 
 - (void)dealloc {
     [NSNotificationCenter.defaultCenter removeObserver:self];
-    [_continuousOutputsTick invalidate];
+    if (_displayLink) {
+        CVDisplayLinkStop(_displayLink);
+        CVDisplayLinkRelease(_displayLink);
+    }
 }
 
 - (void)addRunningOutput:(NJOutput *)output {
     // re-adding them or they trigger multiple times each time.
     if (![_continousOutputs containsObject:output])
         [_continousOutputs addObject:output];
-    if (!_continuousOutputsTick) {
-        _continuousOutputsTick = [NSTimer scheduledTimerWithTimeInterval:1.0/60.0
-                                                           target:self
-                                                         selector:@selector(updateContinuousOutputs:)
-                                                         userInfo:nil
-                                                          repeats:YES];
-    }
+    if (_displayLink && !CVDisplayLinkIsRunning(_displayLink))
+        CVDisplayLinkStart(_displayLink);
 }
 
 - (void)runOutputForDevice:(IOHIDDeviceRef)device value:(IOHIDValueRef)value {
     }
 }
 
-- (void)updateContinuousOutputs:(NSTimer *)timer {
+- (void)updateContinuousOutputs {
     self.mouseLoc = [NSEvent mouseLocation];
     for (NJOutput *output in [_continousOutputs copy]) {
         if (![output update:self]) {
             [_continousOutputs removeObject:output];
         }
     }
-    if (!_continousOutputs.count) {
-        [_continuousOutputsTick invalidate];
-        _continuousOutputsTick = nil;
+    if (!_continousOutputs.count && _displayLink) {
+        CVDisplayLinkStop(_displayLink);
     }
 }
 
 - (void)HIDManager:(NJHIDManager *)manager didError:(NSError *)error {
     [self.delegate inputController:self didError:error];
     self.simulatingEvents = NO;
+    if (_displayLink)
+        CVDisplayLinkStop(_displayLink);
 }
 
 - (void)HIDManagerDidStart:(NJHIDManager *)manager {
 
 - (void)HIDManagerDidStop:(NJHIDManager *)manager {
     [_devices removeAllObjects];
+    if (_displayLink)
+        CVDisplayLinkStop(_displayLink);
     [self.delegate inputControllerDidStopHID:self];
 }
 
 - (void)mappingsSet {
     [self postLoadProcess];
     [NSNotificationCenter.defaultCenter
-     postNotificationName:NJEventMappingListChanged
-     object:self
-     userInfo:@{ NJMappingListKey: _mappings,
-     NJMappingKey: _currentMapping }];
+        postNotificationName:NJEventMappingListChanged
+        object:self
+        userInfo:@{ NJMappingListKey: _mappings,
+                    NJMappingKey: _currentMapping }];
 }
 
 - (void)mappingsChanged {
         if ([oldMapping.name.lowercaseString isEqualToString:@"@application"]
             || [oldMapping.name.lowercaseString isEqualToString:
                 NSLocalizedString(@"@Application", nil).lowercaseString]) {
-                oldMapping.name = app.bestMappingName;
-                [self mappingsChanged];
+                [self renameMapping:oldMapping to:app.bestMappingName];
             }
     }
     _manualMapping = oldMapping;
     _currentMapping = mapping;
     NSUInteger idx = [self indexOfMapping:_currentMapping];
     [NSNotificationCenter.defaultCenter
-     postNotificationName:NJEventMappingChanged
-     object:self
-     userInfo:@{ NJMappingKey : _currentMapping,
-     NJMappingIndexKey: @(idx) }];
+        postNotificationName:NJEventMappingChanged
+        object:self
+        userInfo:@{ NJMappingKey : _currentMapping,
+                    NJMappingIndexKey: @(idx) }];
 }
 
 - (void)activateMapping:(NJMapping *)mapping {