- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
- SUUpdater *updater = [SUUpdater updaterForBundle:
- [NSBundle bundleForClass:[self class]]];
NSUserDefaults *defs = [NSUserDefaults standardUserDefaults];
[defs registerDefaults:UPDATER_DEFAULTS];
+ SUUpdater *updater = [SUUpdater updaterForBundle:
+ [NSBundle bundleForClass:[self class]]];
[updater setDelegate:self];
- // Launch the updater thread.
- [updater checkForUpdatesInBackground];
-
- // Now we need to wait for the Sparkle thread to finish before we can
- // exit, so just poll waiting for it.
- [NSTimer scheduledTimerWithTimeInterval:1
- target:self
- selector:@selector(exitWhenDone:)
- userInfo:updater
- repeats:YES];
+ [self awaitScreenSaverTermination:updater];
}
+
// Delegate method that lets us append extra info to the system-info URL.
//
- (NSArray *) feedParametersForUpdater:(SUUpdater *)updater
}
+// Whether ScreenSaverEngine is currently running, meaning screen is blanked.
+//
+- (BOOL) screenSaverActive
+{
+ BOOL found = NO;
+ NSString *target = @"/ScreenSaverEngine.app";
+ ProcessSerialNumber psn = { kNoProcess, kNoProcess };
+ while (GetNextProcess(&psn) == noErr) {
+ CFDictionaryRef cfdict =
+ ProcessInformationCopyDictionary (&psn,
+ kProcessDictionaryIncludeAllInformationMask);
+ if (cfdict) {
+ NSDictionary *dict = (NSDictionary *) cfdict;
+ NSString *path = [dict objectForKey:@"BundlePath"];
+ if (path && [path hasSuffix:target])
+ found = YES;
+ CFRelease (cfdict);
+ }
+ if (found)
+ break;
+ }
+ return found;
+}
+
+
+// If the screen saver is not running, then launch the updater.
+// Otherwise, wait a while and try again. This is because if the
+// updater tries to pop up a dialog box while the screen saver is
+// active, everything goes to hell and it never shows up.
+//
+- (void) awaitScreenSaverTermination:(SUUpdater *)updater
+{
+ if ([self screenSaverActive]) {
+ static float delay = 1;
+ [NSTimer scheduledTimerWithTimeInterval: delay
+ target:self
+ selector:@selector(awaitScreenSaverTerminationTimer:)
+ userInfo:updater
+ repeats:NO];
+ // slightly exponential back-off
+ delay *= 1.3;
+ if (delay > 120)
+ delay = 120;
+ } else {
+ // Launch the updater thread.
+ [updater checkForUpdatesInBackground];
+
+ // Now we need to wait for the Sparkle thread to finish before we can
+ // exit, so just poll waiting for it.
+ //
+ [NSTimer scheduledTimerWithTimeInterval:1
+ target:self
+ selector:@selector(exitWhenDone:)
+ userInfo:updater
+ repeats:YES];
+ }
+}
+
+
+- (void) awaitScreenSaverTerminationTimer:(NSTimer *)timer
+{
+ [self awaitScreenSaverTermination:[timer userInfo]];
+}
+
+
- (void) exitWhenDone:(NSTimer *)timer
{
SUUpdater *updater = [timer userInfo];
[[NSApplication sharedApplication] terminate:self];
}
+
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)app
{
return YES;