[vlc-devel] [VLC 3.x 2/4] macosx: SPMediaKeyTap: Move to main thread

Marvin Scholz epirat07 at gmail.com
Thu Apr 22 15:39:58 UTC 2021


Move the event tap to the main thread, as the event tap callback
makes use of NSEvent APIs which apparently crash at least on M1
machines running Big Sur when called from a non-main thread.

Additionally remove the now unnecessary @synchronized recursive lock.

Fix videolan/vlc#25650
---
 modules/gui/macosx/SPMediaKeyTap.m | 62 +++++++-----------------------
 1 file changed, 13 insertions(+), 49 deletions(-)

diff --git a/modules/gui/macosx/SPMediaKeyTap.m b/modules/gui/macosx/SPMediaKeyTap.m
index 1981b45775..03e8e67920 100644
--- a/modules/gui/macosx/SPMediaKeyTap.m
+++ b/modules/gui/macosx/SPMediaKeyTap.m
@@ -32,19 +32,15 @@ NSString *kIgnoreMediaKeysDefaultsKey = @"SPIgnoreMediaKeys";
 @interface SPMediaKeyTap () {
     CFMachPortRef _eventPort;
     CFRunLoopSourceRef _eventPortSource;
-    CFRunLoopRef _tapThreadRL;
-    NSThread *_tapThread;
     BOOL _shouldInterceptMediaKeyEvents;
     id _delegate;
     // The app that is frontmost in this list owns media keys
     NSMutableArray<NSRunningApplication *> *_mediaKeyAppList;
 }
 
-- (BOOL)shouldInterceptMediaKeyEvents;
 - (void)setShouldInterceptMediaKeyEvents:(BOOL)newSetting;
 - (void)startWatchingAppSwitching;
 - (void)stopWatchingAppSwitching;
-- (void)eventTapThread;
 @end
 
 static CGEventRef tapEventCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon);
@@ -121,21 +117,16 @@ static CGEventRef tapEventCallback(CGEventTapProxy proxy, CGEventType type, CGEv
     if (_eventPortSource == NULL)
         return NO;
 
-    // Let's do this in a separate thread so that a slow app doesn't lag the event tap
-    _tapThread = [[NSThread alloc] initWithTarget:self
-                                         selector:@selector(eventTapThread)
-                                           object:nil];
-    [_tapThread start];
+    CFRunLoopAddSource(CFRunLoopGetCurrent(), _eventPortSource, kCFRunLoopCommonModes);
 
     return YES;
 }
 
 - (void)stopWatchingMediaKeys
 {
-    // Shut down tap thread
-    if(_tapThreadRL){
-        CFRunLoopStop(_tapThreadRL);
-        _tapThreadRL = nil;
+    // Remove runloop source
+    if(_eventPortSource){
+        CFRunLoopRemoveSource(CFRunLoopGetCurrent(), _eventPortSource, kCFRunLoopCommonModes);
     }
 
     // Remove tap port
@@ -199,35 +190,15 @@ static CGEventRef tapEventCallback(CGEventTapProxy proxy, CGEventType type, CGEv
     return bundleIdentifiers;
 }
 
-
-- (BOOL)shouldInterceptMediaKeyEvents
-{
-    BOOL shouldIntercept = NO;
-    @synchronized(self) {
-        shouldIntercept = _shouldInterceptMediaKeyEvents;
-    }
-    return shouldIntercept;
-}
-
-- (void)pauseTapOnTapThread:(NSNumber *)yeahno
-{
-    CGEventTapEnable(self->_eventPort, [yeahno boolValue]);
-}
-
 - (void)setShouldInterceptMediaKeyEvents:(BOOL)newSetting
 {
-    BOOL oldSetting;
-    @synchronized(self) {
-        oldSetting = _shouldInterceptMediaKeyEvents;
-        _shouldInterceptMediaKeyEvents = newSetting;
-    }
-    if(_tapThreadRL && oldSetting != newSetting) {
-        [self performSelector:@selector(pauseTapOnTapThread:)
-                     onThread:_tapThread
-                   withObject:@(newSetting)
-                waitUntilDone:NO];
+    if (_eventPort == NULL)
+        return;
+    if (_shouldInterceptMediaKeyEvents == newSetting)
+        return;
+    _shouldInterceptMediaKeyEvents = newSetting;
 
-    }
+    CGEventTapEnable(_eventPort, newSetting);
 }
 
 
@@ -265,9 +236,6 @@ static CGEventRef tapEventCallback2(CGEventTapProxy proxy, CGEventType type, CGE
     if (keyCode != NX_KEYTYPE_PLAY && keyCode != NX_KEYTYPE_FAST && keyCode != NX_KEYTYPE_REWIND && keyCode != NX_KEYTYPE_PREVIOUS && keyCode != NX_KEYTYPE_NEXT)
         return event;
 
-    if (![self shouldInterceptMediaKeyEvents])
-        return event;
-
     [self performSelectorOnMainThread:@selector(handleAndReleaseMediaKeyEvent:) withObject:nsEvent waitUntilDone:NO];
 
     return NULL;
@@ -283,14 +251,10 @@ static CGEventRef tapEventCallback(CGEventTapProxy proxy, CGEventType type, CGEv
 
 - (void)handleAndReleaseMediaKeyEvent:(NSEvent *)event
 {
-    [_delegate mediaKeyTap:self receivedMediaKeyEvent:event];
-}
+    if (!_shouldInterceptMediaKeyEvents)
+        return;
 
-- (void)eventTapThread
-{
-    _tapThreadRL = CFRunLoopGetCurrent();
-    CFRunLoopAddSource(_tapThreadRL, _eventPortSource, kCFRunLoopCommonModes);
-    CFRunLoopRun();
+    [_delegate mediaKeyTap:self receivedMediaKeyEvent:event];
 }
 
 
-- 
2.30.1



More information about the vlc-devel mailing list