diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt index 38d133c951..027d4551b7 100644 --- a/Telegram/CMakeLists.txt +++ b/Telegram/CMakeLists.txt @@ -1246,8 +1246,6 @@ if (WIN32) # $ # ) elseif (APPLE) - target_link_libraries(Telegram PRIVATE desktop-app::external_sp_media_key_tap) - if (NOT DESKTOP_APP_USE_PACKAGED) target_link_libraries(Telegram PRIVATE desktop-app::external_iconv) endif() diff --git a/Telegram/SourceFiles/platform/mac/main_window_mac.mm b/Telegram/SourceFiles/platform/mac/main_window_mac.mm index d583fe442f..44cc8bc5a4 100644 --- a/Telegram/SourceFiles/platform/mac/main_window_mac.mm +++ b/Telegram/SourceFiles/platform/mac/main_window_mac.mm @@ -45,7 +45,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include #include #include -#include @interface MainWindowObserver : NSObject { } @@ -106,25 +105,6 @@ private: #endif // OS_MAC_OLD -class EventFilter : public QAbstractNativeEventFilter { -public: - EventFilter(not_null window) : _window(window) { - } - - bool nativeEventFilter( - const QByteArray &eventType, - void *message, - long *result) { - return Core::Sandbox::Instance().customEnterFromEventLoop([&] { - return _window->psFilterNativeEvent(message); - }); - } - -private: - not_null _window; - -}; - [[nodiscard]] QImage TrayIconBack(bool darkMode) { static const auto WithColor = [](QColor color) { return st::macTrayIcon.instance(color, 100); @@ -153,8 +133,6 @@ public: void enableShadow(WId winId); - bool filterNativeEvent(void *event); - void willEnterFullScreen(); void willExitFullScreen(); void didExitFullScreen(); @@ -188,8 +166,6 @@ private: int _generalPasteboardChangeCount = -1; bool _generalPasteboardHasText = false; - EventFilter _nativeEventFilter; - }; } // namespace Platform @@ -260,8 +236,7 @@ void ForceDisabled(QAction *action, bool disabled) { MainWindow::Private::Private(not_null window) : _public(window) -, _observer([[MainWindowObserver alloc] init:this]) -, _nativeEventFilter(window) { +, _observer([[MainWindowObserver alloc] init:this]) { _generalPasteboard = [NSPasteboard generalPasteboard]; @autoreleasepool { @@ -271,11 +246,6 @@ MainWindow::Private::Private(not_null window) [[NSDistributedNotificationCenter defaultCenter] addObserver:_observer selector:@selector(screenIsLocked:) name:Q2NSString(strNotificationAboutScreenLocked()) object:nil]; [[NSDistributedNotificationCenter defaultCenter] addObserver:_observer selector:@selector(screenIsUnlocked:) name:Q2NSString(strNotificationAboutScreenUnlocked()) object:nil]; -#ifndef OS_MAC_STORE - // Register defaults for the whitelist of apps that want to use media keys - [[NSUserDefaults standardUserDefaults] registerDefaults:[NSDictionary dictionaryWithObjectsAndKeys:[SPMediaKeyTap defaultMediaKeyUserBundleIdentifiers], kMediaKeyUsingBundleIdentifiersDefaultsKey, nil]]; -#endif // !OS_MAC_STORE - } } @@ -467,21 +437,6 @@ void MainWindow::Private::enableShadow(WId winId) { // [[(NSView*)winId window] setHasShadow:YES]; } -bool MainWindow::Private::filterNativeEvent(void *event) { - NSEvent *e = static_cast(event); - if (e && [e type] == NSSystemDefined && [e subtype] == SPSystemDefinedEventMediaKeys) { -#ifndef OS_MAC_STORE - // If event tap is not installed, handle events that reach the app instead - if (![SPMediaKeyTap usesGlobalMediaKeyTap]) { - return objc_handleMediaKeyEvent(e); - } -#else // !OS_MAC_STORE - return objc_handleMediaKeyEvent(e); -#endif // else for !OS_MAC_STORE - } - return false; -} - MainWindow::Private::~Private() { [_observer release]; } @@ -489,8 +444,6 @@ MainWindow::Private::~Private() { MainWindow::MainWindow(not_null controller) : Window::MainWindow(controller) , _private(std::make_unique(this)) { - QCoreApplication::instance()->installNativeEventFilter( - &_private->_nativeEventFilter); #ifndef OS_MAC_OLD auto forceOpenGL = std::make_unique(this); @@ -931,10 +884,6 @@ void MainWindow::updateGlobalMenuHook() { ForceDisabled(psClearFormat, !canApplyMarkdown); } -bool MainWindow::psFilterNativeEvent(void *event) { - return _private->filterNativeEvent(event); -} - bool MainWindow::eventFilter(QObject *obj, QEvent *evt) { QEvent::Type t = evt->type(); if (t == QEvent::FocusIn || t == QEvent::FocusOut) { diff --git a/Telegram/SourceFiles/platform/mac/specific_mac.mm b/Telegram/SourceFiles/platform/mac/specific_mac.mm index 57456f608c..6b283d4618 100644 --- a/Telegram/SourceFiles/platform/mac/specific_mac.mm +++ b/Telegram/SourceFiles/platform/mac/specific_mac.mm @@ -33,7 +33,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include #include #include -#include #include #include diff --git a/Telegram/SourceFiles/platform/mac/specific_mac_p.mm b/Telegram/SourceFiles/platform/mac/specific_mac_p.mm index c5a7f6e591..edd85a6660 100644 --- a/Telegram/SourceFiles/platform/mac/specific_mac_p.mm +++ b/Telegram/SourceFiles/platform/mac/specific_mac_p.mm @@ -33,7 +33,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include #include #include -#include using Platform::Q2NSString; using Platform::NS2QString; @@ -131,15 +130,10 @@ NSMenuItem *CreateMenuItem( } - (BOOL) applicationShouldHandleReopen:(NSApplication *)theApplication hasVisibleWindows:(BOOL)flag; -- (void) applicationDidFinishLaunching:(NSNotification *)aNotification; - (void) applicationDidBecomeActive:(NSNotification *)aNotification; - (void) applicationDidResignActive:(NSNotification *)aNotification; - (void) receiveWakeNote:(NSNotification*)note; -- (void) setWatchingMediaKeys:(bool)watching; -- (bool) isWatchingMediaKeys; -- (void) mediaKeyTap:(SPMediaKeyTap*)keyTap receivedMediaKeyEvent:(NSEvent*)event; - - (void) ignoreApplicationActivationRightNow; - (NSMenu *) applicationDockMenu:(NSApplication *)sender; @@ -149,8 +143,6 @@ NSMenuItem *CreateMenuItem( ApplicationDelegate *_sharedDelegate = nil; @implementation ApplicationDelegate { - SPMediaKeyTap *_keyTap; - bool _watchingMediaKeys; bool _ignoreActivation; base::Timer _ignoreActivationStop; } @@ -165,24 +157,10 @@ ApplicationDelegate *_sharedDelegate = nil; } - (void) applicationDidFinishLaunching:(NSNotification *)aNotification { - _keyTap = nullptr; - _watchingMediaKeys = false; _ignoreActivation = false; _ignoreActivationStop.setCallback([self] { _ignoreActivation = false; }); -#ifndef OS_MAC_STORE - if ([SPMediaKeyTap usesGlobalMediaKeyTap]) { - if (!Platform::IsMac10_14OrGreater()) { - _keyTap = [[SPMediaKeyTap alloc] initWithDelegate:self]; - } else { - // In macOS Mojave it requires accessibility features. - LOG(("Media key monitoring disabled starting with Mojave.")); - } - } else { - LOG(("Media key monitoring disabled")); - } -#endif // else for !OS_MAC_STORE } - (void) applicationDidBecomeActive:(NSNotification *)aNotification { @@ -216,33 +194,6 @@ ApplicationDelegate *_sharedDelegate = nil; }); } -- (void) setWatchingMediaKeys:(bool)watching { - if (_watchingMediaKeys != watching) { - _watchingMediaKeys = watching; - if (_keyTap) { -#ifndef OS_MAC_STORE - if (_watchingMediaKeys) { - [_keyTap startWatchingMediaKeys]; - } else { - [_keyTap stopWatchingMediaKeys]; - } -#endif // else for !OS_MAC_STORE - } - } -} - -- (bool) isWatchingMediaKeys { - return _watchingMediaKeys; -} - -- (void) mediaKeyTap:(SPMediaKeyTap*)keyTap receivedMediaKeyEvent:(NSEvent*)e { - Core::Sandbox::Instance().customEnterFromEventLoop([&] { - if (e && [e type] == NSSystemDefined && [e subtype] == SPSystemDefinedEventMediaKeys) { - objc_handleMediaKeyEvent(e); - } - }); -} - - (void) ignoreApplicationActivationRightNow { _ignoreActivation = true; _ignoreActivationStop.callOnce(kIgnoreActivationTimeoutMs); @@ -293,9 +244,6 @@ ApplicationDelegate *_sharedDelegate = nil; namespace Platform { void SetWatchingMediaKeys(bool watching) { - if (_sharedDelegate) { - [_sharedDelegate setWatchingMediaKeys:watching]; - } } void SetApplicationIcon(const QIcon &icon) { @@ -310,43 +258,6 @@ void SetApplicationIcon(const QIcon &icon) { } // namespace Platform -bool objc_handleMediaKeyEvent(void *ev) { - auto e = reinterpret_cast(ev); - - int keyCode = (([e data1] & 0xFFFF0000) >> 16); - int keyFlags = ([e data1] & 0x0000FFFF); - int keyState = (((keyFlags & 0xFF00) >> 8)) == 0xA; - int keyRepeat = (keyFlags & 0x1); - - if (!_sharedDelegate || ![_sharedDelegate isWatchingMediaKeys]) { - return false; - } - - switch (keyCode) { - case NX_KEYTYPE_PLAY: - if (keyState == 0) { // Play pressed and released - Media::Player::instance()->playPause(); - return true; - } - break; - - case NX_KEYTYPE_FAST: - if (keyState == 0) { // Next pressed and released - Media::Player::instance()->next(); - return true; - } - break; - - case NX_KEYTYPE_REWIND: - if (keyState == 0) { // Previous pressed and released - Media::Player::instance()->previous(); - return true; - } - break; - } - return false; -} - void objc_debugShowAlert(const QString &str) { @autoreleasepool { diff --git a/Telegram/ThirdParty/SPMediaKeyTap/SPInvocationGrabbing/NSObject+SPInvocationGrabbing.h b/Telegram/ThirdParty/SPMediaKeyTap/SPInvocationGrabbing/NSObject+SPInvocationGrabbing.h deleted file mode 100644 index d30233daf2..0000000000 --- a/Telegram/ThirdParty/SPMediaKeyTap/SPInvocationGrabbing/NSObject+SPInvocationGrabbing.h +++ /dev/null @@ -1,30 +0,0 @@ -#import - -@interface SPInvocationGrabber : NSObject { - id _object; - NSInvocation *_invocation; - int frameCount; - char **frameStrings; - BOOL backgroundAfterForward; - BOOL onMainAfterForward; - BOOL waitUntilDone; -} --(id)initWithObject:(id)obj; --(id)initWithObject:(id)obj stacktraceSaving:(BOOL)saveStack; -@property (readonly, retain, nonatomic) id object; -@property (readonly, retain, nonatomic) NSInvocation *invocation; -@property BOOL backgroundAfterForward; -@property BOOL onMainAfterForward; -@property BOOL waitUntilDone; --(void)invoke; // will release object and invocation --(void)printBacktrace; --(void)saveBacktrace; -@end - -@interface NSObject (SPInvocationGrabbing) --(id)grab; --(id)invokeAfter:(NSTimeInterval)delta; --(id)nextRunloop; --(id)inBackground; --(id)onMainAsync:(BOOL)async; -@end diff --git a/Telegram/ThirdParty/SPMediaKeyTap/SPInvocationGrabbing/NSObject+SPInvocationGrabbing.m b/Telegram/ThirdParty/SPMediaKeyTap/SPInvocationGrabbing/NSObject+SPInvocationGrabbing.m deleted file mode 100644 index b7ce592b15..0000000000 --- a/Telegram/ThirdParty/SPMediaKeyTap/SPInvocationGrabbing/NSObject+SPInvocationGrabbing.m +++ /dev/null @@ -1,127 +0,0 @@ -#import "NSObject+SPInvocationGrabbing.h" -#import - -#pragma mark Invocation grabbing -@interface SPInvocationGrabber () -@property (readwrite, retain, nonatomic) id object; -@property (readwrite, retain, nonatomic) NSInvocation *invocation; - -@end - -@implementation SPInvocationGrabber -- (id)initWithObject:(id)obj -{ - return [self initWithObject:obj stacktraceSaving:YES]; -} - --(id)initWithObject:(id)obj stacktraceSaving:(BOOL)saveStack -{ - self.object = obj; - - if(saveStack) - [self saveBacktrace]; - - return self; -} --(void)dealloc -{ - free(frameStrings); - self.object = nil; - self.invocation = nil; - [super dealloc]; -} -@synthesize invocation = _invocation, object = _object; - -@synthesize backgroundAfterForward, onMainAfterForward, waitUntilDone; -- (void)runInBackground -{ - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - @try { - [self invoke]; - } - @finally { - [pool drain]; - } -} - - -- (void)forwardInvocation:(NSInvocation *)anInvocation { - [anInvocation retainArguments]; - anInvocation.target = _object; - self.invocation = anInvocation; - - if(backgroundAfterForward) - [NSThread detachNewThreadSelector:@selector(runInBackground) toTarget:self withObject:nil]; - else if(onMainAfterForward) - [self performSelectorOnMainThread:@selector(invoke) withObject:nil waitUntilDone:waitUntilDone]; -} -- (NSMethodSignature *)methodSignatureForSelector:(SEL)inSelector { - NSMethodSignature *signature = [super methodSignatureForSelector:inSelector]; - if (signature == NULL) - signature = [_object methodSignatureForSelector:inSelector]; - - return signature; -} - -- (void)invoke -{ - - @try { - [_invocation invoke]; - } - @catch (NSException * e) { - NSLog(@"SPInvocationGrabber's target raised %@:\n\t%@\nInvocation was originally scheduled at:", e.name, e); - [self printBacktrace]; - printf("\n"); - [e raise]; - } - - self.invocation = nil; - self.object = nil; -} - --(void)saveBacktrace -{ - void *backtraceFrames[128]; - frameCount = backtrace(&backtraceFrames[0], 128); - frameStrings = backtrace_symbols(&backtraceFrames[0], frameCount); -} --(void)printBacktrace -{ - for(int x = 3; x < frameCount; x++) { - if(frameStrings[x] == NULL) { break; } - printf("%s\n", frameStrings[x]); - } -} -@end - -@implementation NSObject (SPInvocationGrabbing) --(id)grab -{ - return [[[SPInvocationGrabber alloc] initWithObject:self] autorelease]; -} --(id)invokeAfter:(NSTimeInterval)delta -{ - id grabber = [self grab]; - [NSTimer scheduledTimerWithTimeInterval:delta target:grabber selector:@selector(invoke) userInfo:nil repeats:NO]; - return grabber; -} -- (id)nextRunloop -{ - return [self invokeAfter:0]; -} --(id)inBackground -{ - SPInvocationGrabber *grabber = [self grab]; - grabber.backgroundAfterForward = YES; - return grabber; -} --(id)onMainAsync:(BOOL)async -{ - SPInvocationGrabber *grabber = [self grab]; - grabber.onMainAfterForward = YES; - grabber.waitUntilDone = !async; - return grabber; -} - -@end diff --git a/Telegram/ThirdParty/SPMediaKeyTap/SPMediaKeyTap.h b/Telegram/ThirdParty/SPMediaKeyTap/SPMediaKeyTap.h deleted file mode 100644 index aa974d238d..0000000000 --- a/Telegram/ThirdParty/SPMediaKeyTap/SPMediaKeyTap.h +++ /dev/null @@ -1,43 +0,0 @@ -#include -#import -#import - -// http://overooped.com/post/2593597587/mediakeys - -#define SPSystemDefinedEventMediaKeys 8 - -@interface SPMediaKeyTap : NSObject { - EventHandlerRef _app_switching_ref; - EventHandlerRef _app_terminating_ref; - CFMachPortRef _eventPort; - CFRunLoopSourceRef _eventPortSource; - CFRunLoopRef _tapThreadRL; - BOOL _shouldInterceptMediaKeyEvents; - id _delegate; - // The app that is frontmost in this list owns media keys - NSMutableArray *_mediaKeyAppList; -} -+ (NSArray*)defaultMediaKeyUserBundleIdentifiers; - --(id)initWithDelegate:(id)delegate; - -+(BOOL)usesGlobalMediaKeyTap; --(void)startWatchingMediaKeys; --(void)stopWatchingMediaKeys; --(void)handleAndReleaseMediaKeyEvent:(NSEvent *)event; -@end - -@interface NSObject (SPMediaKeyTapDelegate) --(void)mediaKeyTap:(SPMediaKeyTap*)keyTap receivedMediaKeyEvent:(NSEvent*)event; -@end - -#ifdef __cplusplus -extern "C" { -#endif - -extern NSString *kMediaKeyUsingBundleIdentifiersDefaultsKey; -extern NSString *kIgnoreMediaKeysDefaultsKey; - -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/Telegram/ThirdParty/SPMediaKeyTap/SPMediaKeyTap.m b/Telegram/ThirdParty/SPMediaKeyTap/SPMediaKeyTap.m deleted file mode 100644 index 5e7587a325..0000000000 --- a/Telegram/ThirdParty/SPMediaKeyTap/SPMediaKeyTap.m +++ /dev/null @@ -1,354 +0,0 @@ -// Copyright (c) 2010 Spotify AB -#import "SPMediaKeyTap.h" -#import "SPInvocationGrabbing/NSObject+SPInvocationGrabbing.h" // https://gist.github.com/511181, in submodule - -@interface SPMediaKeyTap () --(BOOL)shouldInterceptMediaKeyEvents; --(void)setShouldInterceptMediaKeyEvents:(BOOL)newSetting; --(void)startWatchingAppSwitching; --(void)stopWatchingAppSwitching; --(void)eventTapThread; -@end -static SPMediaKeyTap *singleton = nil; - -static pascal OSStatus appSwitched (EventHandlerCallRef nextHandler, EventRef evt, void* userData); -static pascal OSStatus appTerminated (EventHandlerCallRef nextHandler, EventRef evt, void* userData); -static CGEventRef tapEventCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon); - -// Inspired by http://gist.github.com/546311 - -@implementation SPMediaKeyTap - -#pragma mark - -#pragma mark Setup and teardown --(id)initWithDelegate:(id)delegate -{ - _delegate = delegate; - [self startWatchingAppSwitching]; - singleton = self; - _mediaKeyAppList = [NSMutableArray new]; - _tapThreadRL=nil; - _eventPort=nil; - _eventPortSource=nil; - return self; -} --(void)dealloc -{ - [self stopWatchingMediaKeys]; - [self stopWatchingAppSwitching]; - [_mediaKeyAppList release]; - [super dealloc]; -} - --(void)startWatchingAppSwitching -{ - // Listen to "app switched" event, so that we don't intercept media keys if we - // weren't the last "media key listening" app to be active - EventTypeSpec eventType = { kEventClassApplication, kEventAppFrontSwitched }; - OSStatus err = InstallApplicationEventHandler(NewEventHandlerUPP(appSwitched), 1, &eventType, self, &_app_switching_ref); - assert(err == noErr); - - eventType.eventKind = kEventAppTerminated; - err = InstallApplicationEventHandler(NewEventHandlerUPP(appTerminated), 1, &eventType, self, &_app_terminating_ref); - assert(err == noErr); -} --(void)stopWatchingAppSwitching -{ - if(!_app_switching_ref) return; - RemoveEventHandler(_app_switching_ref); - _app_switching_ref = NULL; - - if(!_app_terminating_ref) return; - RemoveEventHandler(_app_terminating_ref); - _app_terminating_ref = NULL; -} - --(void)startWatchingMediaKeys -{ - // Prevent having multiple mediaKeys threads - [self stopWatchingMediaKeys]; - - [self setShouldInterceptMediaKeyEvents:YES]; - - // Add an event tap to intercept the system defined media key events - _eventPort = CGEventTapCreate(kCGSessionEventTap, - kCGHeadInsertEventTap, - kCGEventTapOptionDefault, - CGEventMaskBit(NX_SYSDEFINED), - tapEventCallback, - self); - if (!_eventPort) { - [self stopWatchingMediaKeys]; - return; - } - - _eventPortSource = CFMachPortCreateRunLoopSource(kCFAllocatorSystemDefault, _eventPort, 0); - assert(_eventPortSource != NULL); - - // Let's do this in a separate thread so that a slow app doesn't lag the event tap - [NSThread detachNewThreadSelector:@selector(eventTapThread) toTarget:self withObject:nil]; -} --(void)stopWatchingMediaKeys -{ - // TODO: Shut down thread, remove event tap port and source - - if(_tapThreadRL){ - CFRunLoopStop(_tapThreadRL); - _tapThreadRL=nil; - } - - if(_eventPort){ - CFMachPortInvalidate(_eventPort); - CFRelease(_eventPort); - _eventPort=nil; - } - - if(_eventPortSource){ - CFRelease(_eventPortSource); - _eventPortSource=nil; - } -} - -#pragma mark - -#pragma mark Accessors - -+(BOOL)usesGlobalMediaKeyTap -{ -#ifdef _DEBUG - // breaking in gdb with a key tap inserted sometimes locks up all mouse and keyboard input forever, forcing reboot - return NO; -#else - // XXX(nevyn): MediaKey event tap doesn't work on 10.4, feel free to figure out why if you have the energy. - return - ![[NSUserDefaults standardUserDefaults] boolForKey:kIgnoreMediaKeysDefaultsKey] - && floor(NSAppKitVersionNumber) >= 949/*NSAppKitVersionNumber10_5*/; -#endif -} - -+ (NSArray*)defaultMediaKeyUserBundleIdentifiers -{ - return [NSArray arrayWithObjects: - [[NSBundle mainBundle] bundleIdentifier], // your app - @"com.spotify.client", - @"com.apple.iTunes", - @"com.apple.QuickTimePlayerX", - @"com.apple.quicktimeplayer", - @"com.apple.iWork.Keynote", - @"com.apple.iPhoto", - @"org.videolan.vlc", - @"com.apple.Aperture", - @"com.plexsquared.Plex", - @"com.soundcloud.desktop", - @"org.niltsh.MPlayerX", - @"com.ilabs.PandorasHelper", - @"com.mahasoftware.pandabar", - @"com.bitcartel.pandorajam", - @"org.clementine-player.clementine", - @"fm.last.Last.fm", - @"fm.last.Scrobbler", - @"com.beatport.BeatportPro", - @"com.Timenut.SongKey", - @"com.macromedia.fireworks", // the tap messes up their mouse input - @"at.justp.Theremin", - @"ru.ya.themblsha.YandexMusic", - @"com.jriver.MediaCenter18", - @"com.jriver.MediaCenter19", - @"com.jriver.MediaCenter20", - @"co.rackit.mate", - @"com.ttitt.b-music", - @"com.beardedspice.BeardedSpice", - @"com.plug.Plug", - @"com.plug.Plug2", - @"com.netease.163music", - @"org.quodlibet.quodlibet", - nil - ]; -} - - --(BOOL)shouldInterceptMediaKeyEvents -{ - BOOL shouldIntercept = NO; - @synchronized(self) { - shouldIntercept = _shouldInterceptMediaKeyEvents; - } - return shouldIntercept; -} - --(void)pauseTapOnTapThread:(BOOL)yeahno -{ - CGEventTapEnable(self->_eventPort, yeahno); -} --(void)setShouldInterceptMediaKeyEvents:(BOOL)newSetting -{ - BOOL oldSetting; - @synchronized(self) { - oldSetting = _shouldInterceptMediaKeyEvents; - _shouldInterceptMediaKeyEvents = newSetting; - } - if(_tapThreadRL && oldSetting != newSetting) { - id grab = [self grab]; - [grab pauseTapOnTapThread:newSetting]; - NSTimer *timer = [NSTimer timerWithTimeInterval:0 invocation:[grab invocation] repeats:NO]; - CFRunLoopAddTimer(_tapThreadRL, (CFRunLoopTimerRef)timer, kCFRunLoopCommonModes); - } -} - -#pragma mark -#pragma mark - -#pragma mark Event tap callbacks - -// Note: method called on background thread - -static CGEventRef tapEventCallback2(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) -{ - SPMediaKeyTap *self = refcon; - - if(type == kCGEventTapDisabledByTimeout) { - NSLog(@"Media key event tap was disabled by timeout"); - CGEventTapEnable(self->_eventPort, TRUE); - return event; - } else if(type == kCGEventTapDisabledByUserInput) { - // Was disabled manually by -[pauseTapOnTapThread] - return event; - } - NSEvent *nsEvent = nil; - @try { - nsEvent = [NSEvent eventWithCGEvent:event]; - } - @catch (NSException * e) { - NSLog(@"Strange CGEventType: %d: %@", type, e); - assert(0); - return event; - } - - if (type != NX_SYSDEFINED || [nsEvent subtype] != SPSystemDefinedEventMediaKeys) - return event; - - int keyCode = (([nsEvent data1] & 0xFFFF0000) >> 16); - 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; - - [nsEvent retain]; // matched in handleAndReleaseMediaKeyEvent: - [self performSelectorOnMainThread:@selector(handleAndReleaseMediaKeyEvent:) withObject:nsEvent waitUntilDone:NO]; - - return NULL; -} - -static CGEventRef tapEventCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) -{ - NSAutoreleasePool *pool = [NSAutoreleasePool new]; - CGEventRef ret = tapEventCallback2(proxy, type, event, refcon); - [pool drain]; - return ret; -} - - -// event will have been retained in the other thread --(void)handleAndReleaseMediaKeyEvent:(NSEvent *)event { - [event autorelease]; - - [_delegate mediaKeyTap:self receivedMediaKeyEvent:event]; -} - - --(void)eventTapThread -{ - _tapThreadRL = CFRunLoopGetCurrent(); - CFRunLoopAddSource(_tapThreadRL, _eventPortSource, kCFRunLoopCommonModes); - CFRunLoopRun(); -} - -#pragma mark Task switching callbacks - -NSString *kMediaKeyUsingBundleIdentifiersDefaultsKey = @"SPApplicationsNeedingMediaKeys"; -NSString *kIgnoreMediaKeysDefaultsKey = @"SPIgnoreMediaKeys"; - - - --(void)mediaKeyAppListChanged -{ - if([_mediaKeyAppList count] == 0) return; - - /*NSLog(@"--"); - int i = 0; - for (NSValue *psnv in _mediaKeyAppList) { - ProcessSerialNumber psn; [psnv getValue:&psn]; - NSDictionary *processInfo = [(id)ProcessInformationCopyDictionary( - &psn, - kProcessDictionaryIncludeAllInformationMask - ) autorelease]; - NSString *bundleIdentifier = [processInfo objectForKey:(id)kCFBundleIdentifierKey]; - NSLog(@"%d: %@", i++, bundleIdentifier); - }*/ - - ProcessSerialNumber mySerial, topSerial; - GetCurrentProcess(&mySerial); - [[_mediaKeyAppList objectAtIndex:0] getValue:&topSerial]; - - Boolean same; - OSErr err = SameProcess(&mySerial, &topSerial, &same); - [self setShouldInterceptMediaKeyEvents:(err == noErr && same)]; - -} --(void)appIsNowFrontmost:(ProcessSerialNumber)psn -{ - NSValue *psnv = [NSValue valueWithBytes:&psn objCType:@encode(ProcessSerialNumber)]; - - NSDictionary *processInfo = [(id)ProcessInformationCopyDictionary( - &psn, - kProcessDictionaryIncludeAllInformationMask - ) autorelease]; - NSString *bundleIdentifier = [processInfo objectForKey:(id)kCFBundleIdentifierKey]; - - NSArray *whitelistIdentifiers = [[NSUserDefaults standardUserDefaults] arrayForKey:kMediaKeyUsingBundleIdentifiersDefaultsKey]; - if(![whitelistIdentifiers containsObject:bundleIdentifier]) return; - - [_mediaKeyAppList removeObject:psnv]; - [_mediaKeyAppList insertObject:psnv atIndex:0]; - [self mediaKeyAppListChanged]; -} --(void)appTerminated:(ProcessSerialNumber)psn -{ - NSValue *psnv = [NSValue valueWithBytes:&psn objCType:@encode(ProcessSerialNumber)]; - [_mediaKeyAppList removeObject:psnv]; - [self mediaKeyAppListChanged]; -} - -static pascal OSStatus appSwitched (EventHandlerCallRef nextHandler, EventRef evt, void* userData) -{ - SPMediaKeyTap *self = (id)userData; - - ProcessSerialNumber newSerial; - GetFrontProcess(&newSerial); - - [self appIsNowFrontmost:newSerial]; - - return CallNextEventHandler(nextHandler, evt); -} - -static pascal OSStatus appTerminated (EventHandlerCallRef nextHandler, EventRef evt, void* userData) -{ - SPMediaKeyTap *self = (id)userData; - - ProcessSerialNumber deadPSN; - - GetEventParameter( - evt, - kEventParamProcessID, - typeProcessSerialNumber, - NULL, - sizeof(deadPSN), - NULL, - &deadPSN - ); - - - [self appTerminated:deadPSN]; - return CallNextEventHandler(nextHandler, evt); -} - -@end diff --git a/cmake b/cmake index 03efe01ff9..97b9c3f6d8 160000 --- a/cmake +++ b/cmake @@ -1 +1 @@ -Subproject commit 03efe01ff978b84745414e046e4766225ffffb7f +Subproject commit 97b9c3f6d899b8a24137b9e6c076f5752d13a037