// // MBFrontFileMonitor.m // MBMenuExtra // // Created by Work on 6/9/09. // Copyright 2009 __MyCompanyName__. All rights reserved. // #import "NGAActiveFileMonitor.h" #import "NGAUtilities.h" #import "NGARemoteAccessibleObject.h" /* Useful Accesibility links http://developer.apple.com/mac/library/DOCUMENTATION/Accessibility/Reference/AccessibilityLowlevel/AXNotificationConstants_h/CompositePage.html#//apple_ref/c/macro/kAXWindowMovedNotification http://markmail.org/message/742lqkyxlri6k3hv#query:AXObserverAddNotification+page:1+mid:kwfyt6qqzjok2myo+state:results http://markmail.org/thread/kwfyt6qqzjok2myo */ NSString * const NGAActiveFileChangedNotification = @"MBActiveFileChangedNotification"; NSString * const NGAWindowTitleChangedNotification = @"NGAWindowTitleChangedNotification"; NSString * const kMonitoredApplicationElementKey = @"monitoredApplicationElement"; RUNTIME_CONSTANT_FUNCTION( NSString *, keyPathToMainWindowTitle, ([[NSString stringWithFormat:@"%@.%@.%@", kMonitoredApplicationElementKey, NSAccessibilityMainWindowAttribute, NSAccessibilityTitleAttribute] retain]) ) //RUNTIME_CONSTANT_FUNCTION( NSString *, alternativeKeyPathToMainWindowTitle, // ([[NSString stringWithFormat:@"%@.%@.%@.%@", kMonitoredApplicationElementKey, NSAccessibilityMainWindowAttribute, NSAccessibilityTitleUIElementAttribute, NSAccessibilityValueAttribute] retain]) ) RUNTIME_CONSTANT_FUNCTION( NSString *, keyPathToMainWindowDocument, ([[NSString stringWithFormat:@"%@.%@.%@", kMonitoredApplicationElementKey, NSAccessibilityMainWindowAttribute, NSAccessibilityDocumentAttribute] retain]) ) @interface NGAActiveFileMonitor () -(void)valueDidChangeForForegroundApplication; @property (nonatomic, readwrite, assign) BOOL isMonitoring; @property (nonatomic, readwrite, retain) NGARemoteAccessibleObject * monitoredApplicationElement; @property (nonatomic, readonly,) NSString * mainWindowDocumentPathURL; @end @implementation NGAActiveFileMonitor @synthesize ignoredProcessBundleIDs = _ignoredProcessBundleIDs , monitoredApplicationElement = _monitoredApplicationElement , isMonitoring = _isMonitoring , mainWindowTitle = _mainWindowTitle ; SINGLETON_IMPLEMENTATION(NGAActiveFileMonitor, sharedMonitor) -(id)init { if ( (self = [super init]) == nil ) return nil; [self registerAllAutoObservationMethods]; return self; } - (void)dealloc { [self stopMonitoring]; self.ignoredProcessBundleIDs = nil; [self unregisterAllAutoObservationMethods]; [super dealloc]; } -(void)applicationDidActivate:(NSNotification*)note { LOG_DEBUG(@"Foregound application did change"); [self valueDidChangeForForegroundApplication]; } -(void)startMonitoring { self.isMonitoring = YES; [self valueDidChangeForForegroundApplication]; [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self selector:@selector(applicationDidActivate:) name:NSWorkspaceDidActivateApplicationNotification object:nil]; } -(void)stopMonitoring { LOG_DEBUG(@"Stopping monitoring"); [[[NSWorkspace sharedWorkspace] notificationCenter] removeObserver:self]; self.monitoredApplicationElement = nil; self.isMonitoring = NO; } #pragma mark monitoredApplication -(NSSet*)keyPathsForValuesAffectingMonitoredApplication { return [NSSet setWithObject:kMonitoredApplicationElementKey]; } -(NSRunningApplication*)monitoredApplication { return [NSRunningApplication runningApplicationWithProcessIdentifier:self.monitoredApplicationElement.processIdentifier]; } -(void)valueDidChangeForForegroundApplication { NSRunningApplication * foregroundApplication = [NSRunningApplication foregroundApplication]; if ([self.ignoredProcessBundleIDs containsObject:foregroundApplication.bundleIdentifier] || foregroundApplication.isAgent) { LOG_DEBUG(@"Ignoring process: %@", foregroundApplication.bundleIdentifier); return; } LOG_DEBUG(@"Observing process: %@", foregroundApplication.bundleIdentifier); self.monitoredApplicationElement = [NGARemoteAccessibleObject applicationElementForProcessIdentifier:foregroundApplication.processIdentifier]; } #pragma mark mainWindowDocumentPath +(NSSet*)keyPathsForValuesAffectingMainWindowDocumentPath { return [NSSet setWithObject:@"mainWindowDocumentPathURL"]; } -(NSString*)mainWindowDocumentPath { if (!self.mainWindowDocumentPathURL) return nil; NSURL * url = [NSURL URLWithString:self.mainWindowDocumentPathURL]; if ([url isFileURL]) return [url path]; return nil; } +(NSSet*)keyPathsForValuesAffectingMainWindowDocumentPathURL { return [NSSet setWithObject:keyPathToMainWindowDocument()]; } -(NSString*)mainWindowDocumentPathURL { return [self valueForKeyPath:keyPathToMainWindowDocument()]; } #pragma mark mainWindowDocumentTitle +(NSSet*)keyPathsForValuesAffectingMainWindowTitle { return [NSSet setWithObjects:keyPathToMainWindowTitle(), nil]; //alternativeKeyPathToMainWindowTitle(), nil]; } -(NSString*)mainWindowTitle { NSString * title = nil;//[self valueForKeyPath:alternativeKeyPathToMainWindowTitle()]; if (!title) title = [self valueForKeyPath:keyPathToMainWindowTitle()]; return title; } #pragma mark sending notifications -(void)valueDidChangeForMainWindowDocumentPath:(NSDictionary*)change { NSNotification * notification = [NSNotification notificationWithName:NGAActiveFileChangedNotification object:self userInfo:change]; [[NSNotificationCenter defaultCenter] postNotification:notification]; // LOG_DEBUG(@"NGAActiveFileChangedNotification posted! %@", change); } -(void)valueDidChangeForMainWindowTitle:(NSDictionary*)change { NSNotification * notification = [NSNotification notificationWithName:NGAWindowTitleChangedNotification object:self userInfo:change]; // LOG_DEBUG(@"NGAWindowTitleChangedNotification posted! %@", change); [[NSNotificationCenter defaultCenter] postNotification:notification]; } @end