X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?p=xscreensaver;a=blobdiff_plain;f=OSX%2FUpdater.m;fp=OSX%2FUpdater.m;h=1bf29fa2e841d99fb9662125ae83b1c520978671;hp=2e3ccbe1a2acf1b69b53e0bc65a915b36eea8851;hb=8afc01a67be4fbf3f1cc0fce9adf01b5289a21c6;hpb=3f1091236d800c43a3124c44c7da54e53f205b13 diff --git a/OSX/Updater.m b/OSX/Updater.m index 2e3ccbe1..1bf29fa2 100644 --- a/OSX/Updater.m +++ b/OSX/Updater.m @@ -27,39 +27,54 @@ NSUserDefaults *defs = [NSUserDefaults standardUserDefaults]; [defs registerDefaults:UPDATER_DEFAULTS]; - SUUpdater *updater = [SUUpdater updaterForBundle: - [NSBundle bundleForClass:[self class]]]; - [updater setDelegate:self]; + // If it's not time to run the updater, then bail immediately. + // I'm not sure why this is necessary, but Sparkle seems to be + // checking too often. + // + if (! [self timeToCheck]) + [[NSApplication sharedApplication] terminate:self]; - [self awaitScreenSaverTermination:updater]; + // If the screen saver is not running, then launch the updater now. + // Otherwise, wait until the screen saver deactivates, and then do + // it. 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. You'd expect the dialog to just map below the + // screen saver window, but no. + + if (! [self screenSaverActive]) { + [self runUpdater]; + } else { + // Run the updater when the "screensaver.didstop" notification arrives. + [[NSDistributedNotificationCenter defaultCenter] + addObserver:self + selector:@selector(saverStoppedNotification:) + name:@"com.apple.screensaver.didstop" + object:nil]; + + // But I'm not sure I trust that, so also poll every couple minutes. + timer = [NSTimer scheduledTimerWithTimeInterval: 60 * 2 + target:self + selector:@selector(pollSaverTermination:) + userInfo:nil + repeats:YES]; + } } -// Delegate method that lets us append extra info to the system-info URL. -// -- (NSArray *) feedParametersForUpdater:(SUUpdater *)updater - sendingSystemProfile:(BOOL)sending +- (BOOL) timeToCheck { - // 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 - } - ]; + NSUserDefaults *defs = [NSUserDefaults standardUserDefaults]; + NSTimeInterval interval = [defs doubleForKey:@SUScheduledCheckIntervalKey]; + NSDate *last = [defs objectForKey:@SULastCheckTimeKey]; + if (!interval || !last) + return YES; + NSTimeInterval since = [[NSDate date] timeIntervalSinceDate:last]; + return (since > interval); } // Whether ScreenSaverEngine is currently running, meaning screen is blanked. +// There's no easy way to determine this other than scanning the process table. // - (BOOL) screenSaverActive { @@ -84,49 +99,70 @@ } -// 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 +- (void) saverStoppedNotification:(NSNotification *)note { - 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]; + [self runUpdater]; +} + + +- (void) pollSaverTermination:(NSTimer *)t +{ + if (! [self screenSaverActive]) + [self runUpdater]; +} + + +- (void) runUpdater +{ + if (timer) { + [timer invalidate]; + timer = nil; } + + 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(pollUpdaterTermination:) + userInfo:updater + repeats:YES]; } -- (void) awaitScreenSaverTerminationTimer:(NSTimer *)timer +// Delegate method that lets us append extra info to the system-info URL. +// +- (NSArray *) feedParametersForUpdater:(SUUpdater *)updater + sendingSystemProfile:(BOOL)sending { - [self awaitScreenSaverTermination:[timer userInfo]]; + // 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 @[]; + NSString *head = @"org.jwz.xscreensaver."; + if ([saver hasPrefix:head]) + saver = [saver substringFromIndex:[head length]]; + + return @[ @{ @"key": @"saver", + @"value": saver, + @"displayKey": @"Current Saver", + @"displayValue": saver + } + ]; } -- (void) exitWhenDone:(NSTimer *)timer +- (void) pollUpdaterTermination:(NSTimer *)t { - SUUpdater *updater = [timer userInfo]; + SUUpdater *updater = [t userInfo]; if (![updater updateInProgress]) [[NSApplication sharedApplication] terminate:self]; }