Files
santa/Source/SantaGUI/SNTAppDelegate.m

125 lines
4.6 KiB
Objective-C

/// Copyright 2015 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
#import "SNTAppDelegate.h"
#import "SNTAboutWindowController.h"
#import "SNTConfigurator.h"
#import "SNTFileWatcher.h"
#import "SNTNotificationManager.h"
#import "SNTStrengthify.h"
#import "SNTXPCConnection.h"
#import "SNTXPCControlInterface.h"
@interface SNTAppDelegate ()
@property SNTAboutWindowController *aboutWindowController;
@property SNTFileWatcher *configFileWatcher;
@property SNTNotificationManager *notificationManager;
@property SNTXPCConnection *listener;
@end
@implementation SNTAppDelegate
#pragma mark App Delegate methods
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
[self setupMenu];
self.configFileWatcher = [[SNTFileWatcher alloc] initWithFilePath:kDefaultConfigFilePath
handler:^(unsigned long data) {
if (! (data & DISPATCH_VNODE_ATTRIB)) [[SNTConfigurator configurator] reloadConfigData];
}];
self.notificationManager = [[SNTNotificationManager alloc] init];
NSNotificationCenter *workspaceNotifications = [[NSWorkspace sharedWorkspace] notificationCenter];
[workspaceNotifications addObserverForName:NSWorkspaceSessionDidResignActiveNotification
object:nil
queue:[NSOperationQueue currentQueue]
usingBlock:^(NSNotification *note) {
self.listener.invalidationHandler = nil;
[self.listener invalidate];
self.listener = nil;
}];
[workspaceNotifications addObserverForName:NSWorkspaceSessionDidBecomeActiveNotification
object:nil
queue:[NSOperationQueue currentQueue]
usingBlock:^(NSNotification *note) {
[self attemptReconnection];
}];
[self createConnection];
}
- (BOOL)applicationShouldHandleReopen:(NSApplication *)sender hasVisibleWindows:(BOOL)flag {
self.aboutWindowController = [[SNTAboutWindowController alloc] init];
[self.aboutWindowController showWindow:self];
return NO;
}
#pragma mark Connection handling
- (void)createConnection {
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
WEAKIFY(self);
// Create listener for return connection from daemon.
NSXPCListener *listener = [NSXPCListener anonymousListener];
self.listener = [[SNTXPCConnection alloc] initServerWithListener:listener];
self.listener.exportedInterface = [SNTXPCNotifierInterface notifierInterface];
self.listener.exportedObject = self.notificationManager;
self.listener.acceptedHandler = ^{
dispatch_semaphore_signal(sema);
};
self.listener.invalidationHandler = ^{
STRONGIFY(self);
[self attemptReconnection];
};
[self.listener resume];
// Tell daemon to connect back to the above listener.
SNTXPCConnection *daemonConn = [SNTXPCControlInterface configuredConnection];
[daemonConn resume];
[[daemonConn remoteObjectProxy] setNotificationListener:listener.endpoint];
// Now wait for the connection to come in.
if (dispatch_semaphore_wait(sema, dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC))) {
[self attemptReconnection];
}
}
- (void)attemptReconnection {
[self performSelectorInBackground:@selector(createConnection) withObject:nil];
}
#pragma mark Menu Management
- (void)setupMenu {
// Whilst the user will never see the menu, having one with the Copy and Select All options
// allows the shortcuts for these items to work, which is useful for being able to copy
// information from notifications. The mainMenu must have a nested menu for this to work properly.
NSMenu *mainMenu = [[NSMenu alloc] init];
NSMenu *editMenu = [[NSMenu alloc] init];
[editMenu addItemWithTitle:@"Copy" action:@selector(copy:) keyEquivalent:@"c"];
[editMenu addItemWithTitle:@"Select All" action:@selector(selectAll:) keyEquivalent:@"a"];
NSMenuItem *editMenuItem = [[NSMenuItem alloc] init];
[editMenuItem setSubmenu:editMenu];
[mainMenu addItem:editMenuItem];
[NSApp setMainMenu:mainMenu];
}
@end