X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=OSX%2FUpdater.m;h=2e3ccbe1a2acf1b69b53e0bc65a915b36eea8851;hb=3f1091236d800c43a3124c44c7da54e53f205b13;hp=94a3afaeb9b64000873599eba852e86b55e8454f;hpb=019de959b265701cd0c3fccbb61f2b69f06bf9ee;p=xscreensaver diff --git a/OSX/Updater.m b/OSX/Updater.m index 94a3afae..2e3ccbe1 100644 --- a/OSX/Updater.m +++ b/OSX/Updater.m @@ -24,23 +24,106 @@ - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { - SUUpdater *updater = [SUUpdater updaterForBundle: - [NSBundle bundleForClass:[self class]]]; NSUserDefaults *defs = [NSUserDefaults standardUserDefaults]; [defs registerDefaults:UPDATER_DEFAULTS]; - // Launch the updater thread. - [updater checkForUpdatesInBackground]; + SUUpdater *updater = [SUUpdater updaterForBundle: + [NSBundle bundleForClass:[self class]]]; + [updater setDelegate:self]; + + [self awaitScreenSaverTermination:updater]; +} + + +// Delegate method that lets us append extra info to the system-info URL. +// +- (NSArray *) feedParametersForUpdater:(SUUpdater *)updater + sendingSystemProfile:(BOOL)sending +{ + // Get the name of the saver that invoked us, and include that in the + // system info. + NSString *saver = [[[NSProcessInfo + processInfo]environment]objectForKey: + @"XSCREENSAVER_CLASSPATH"]; + if (! saver) return nil; + NSString *head = @"org.jwz.xscreensaver."; + if ([saver hasPrefix:head]) + saver = [saver substringFromIndex:[head length]]; + + return @[ @{ @"key": @"saver", + @"value": saver, + @"displayKey": @"Current Saver", + @"displayValue": saver + } + ]; +} + - // 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]; +// 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]; @@ -48,6 +131,7 @@ [[NSApplication sharedApplication] terminate:self]; } + - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)app { return YES;