From http://www.jwz.org/xscreensaver/xscreensaver-5.38.tar.gz
[xscreensaver] / OSX / SaverRunner.m
index ac010b9fa760d1bbb6e0c6ccea8b6ff96086307e..f358fb754500f5c27cb3bf78404163b23beed1db 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 2006-2016 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 2006-2017 Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
     _showAboutBox = showAboutBox;
 
     self.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
-    self.wantsFullScreenLayout = YES;
+
+# ifndef __IPHONE_7_0
+    self.wantsFullScreenLayout = YES;    // Deprecated as of iOS 7
+# endif
   }
   return self;
 }
 
+- (BOOL) prefersStatusBarHidden
+{
+  // Requires UIViewControllerBasedStatusBarAppearance = true in plist
+  return YES;
+}
 
 - (void)dealloc
 {
                             withSize:parentView.bounds.size];
 
   if (! _saverView) {
-    [[[UIAlertView alloc] initWithTitle: _saverName
-                          message: @"Unable to load!"
-                          delegate: nil
-                          cancelButtonTitle: @"Bummer"
-                          otherButtonTitles: nil]
-     show];
+    UIAlertController *c = [UIAlertController
+                             alertControllerWithTitle:@"Unable to load!"
+                             message:@""
+                             preferredStyle:UIAlertControllerStyleAlert];
+    [c addAction: [UIAlertAction actionWithTitle: @"Bummer"
+                                 style: UIAlertActionStyleDefault
+                                 handler: ^(UIAlertAction *a) {
+      // #### Should expose the SaverListController...
+    }]];
+    [self presentViewController:c animated:YES completion:nil];
+
     return;
   }
 
 
 - (BOOL)shouldAutorotate                       /* Added in iOS 6 */
 {
-  return YES;
+  return
+    NSFoundationVersionNumber < NSFoundationVersionNumber_iOS_8_0 ?
+    ![_saverView suppressRotationAnimation] :
+    YES;
 }
 
 
@@ -548,8 +564,8 @@ static ScreenSaverView *
 find_saverView_child (NSView *v)
 {
   NSArray *kids = [v subviews];
-  int nkids = [kids count];
-  int i;
+  NSUInteger nkids = [kids count];
+  NSUInteger i;
   for (i = 0; i < nkids; i++) {
     NSObject *kid = [kids objectAtIndex:i];
     if ([kid isKindOfClass:[ScreenSaverView class]]) {
@@ -586,8 +602,8 @@ relabel_menus (NSObject *v, NSString *old_str, NSString *new_str)
     [m setTitle: [[m title] stringByReplacingOccurrencesOfString:old_str
                             withString:new_str]];
     NSArray *kids = [m itemArray];
-    int nkids = [kids count];
-    int i;
+    NSUInteger nkids = [kids count];
+    NSUInteger i;
     for (i = 0; i < nkids; i++) {
       relabel_menus ([kids objectAtIndex:i], old_str, new_str);
     }
@@ -607,7 +623,7 @@ relabel_menus (NSObject *v, NSString *old_str, NSString *new_str)
   if ([sender isKindOfClass:[NSView class]]) { // Sent from button
     sv = find_saverView ((NSView *) sender);
   } else {
-    int i;
+    long i;
     NSWindow *w = 0;
     for (i = [windows count]-1; i >= 0; i--) { // Sent from menubar
       w = [windows objectAtIndex:i];
@@ -625,7 +641,7 @@ relabel_menus (NSObject *v, NSString *old_str, NSString *new_str)
       modalDelegate:self
      didEndSelector:@selector(preferencesClosed:returnCode:contextInfo:)
         contextInfo:nil];
-  int code = [NSApp runModalForWindow:prefs];
+  NSUInteger code = [NSApp runModalForWindow:prefs];
   
   /* Restart the animation if the "OK" button was hit, but not if "Cancel".
      We have to restart *both* animations, because the xlockmore-style
@@ -662,13 +678,12 @@ relabel_menus (NSObject *v, NSString *old_str, NSString *new_str)
 
   CGSize size = [[UIScreen mainScreen] bounds].size;
 
-  // iOS 7: Needs to be the actual device orientation.
+  // iOS 7: Needs to be [[window rootViewController] interfaceOrientation].
   // iOS 8: Needs to be UIInterfaceOrientationPortrait.
+  // (interfaceOrientation deprecated in iOS 8)
 
-  UIInterfaceOrientation orient =
-    NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_7_1 ?
-    UIInterfaceOrientationPortrait /* iOS 8 broke -[UIScreen bounds]. */ :
-    [[window rootViewController] interfaceOrientation];
+  UIInterfaceOrientation orient = UIInterfaceOrientationPortrait;
+  /* iOS 8 broke -[UIScreen bounds]. */
 
   if (orient == UIInterfaceOrientationLandscapeLeft ||
       orient == UIInterfaceOrientationLandscapeRight) {
@@ -684,10 +699,7 @@ relabel_menus (NSObject *v, NSString *old_str, NSString *new_str)
   // take the scale into consideration
   // On iOS prior to 4, fall back to use UIGraphicsBeginImageContext
 
-  if (UIGraphicsBeginImageContextWithOptions)
-    UIGraphicsBeginImageContextWithOptions (size, NO, 0);
-  else
-    UIGraphicsBeginImageContext (size);
+  UIGraphicsBeginImageContextWithOptions (size, NO, 0);
 
   CGContextRef ctx = UIGraphicsGetCurrentContext();
 
@@ -1404,7 +1416,7 @@ FAIL:
                                   backing:NSBackingStoreBuffered
                                     defer:YES
                                    screen:screen];
-  [win setMinSize:[win frameRectForContentRect:rect].size];
+//  [win setMinSize:[win frameRectForContentRect:rect].size];
   [[win contentView] addSubview: (pbox ? (NSView *) pbox : (NSView *) sv)];
   [pbox release];
 
@@ -1453,6 +1465,7 @@ FAIL:
   // or two windows for SaverTester.app.
   for (i = 0; i < window_count; i++) {
     NSWindow *win = [self makeWindow];
+    [win setDelegate:self];
     // Get the last-saved window position out of preferences.
     [win setFrameAutosaveName:
               [NSString stringWithFormat:@"XScreenSaverWindow%d", i]];
@@ -1460,6 +1473,7 @@ FAIL:
     [a addObject: win];
     // This prevents clicks from being seen by savers.
     // [win setMovableByWindowBackground:YES];
+    win.releasedWhenClosed = NO;
     [win release];
   }
 # else  // USE_IPHONE
@@ -1572,7 +1586,7 @@ FAIL:
   if (!anim_timer) {
     Class ssm = NSClassFromString (@"ScreenSaverModule");
     if (ssm && [ssm instancesRespondToSelector:
-                      @selector(needsAnimationTimer)]) {
+                      NSSelectorFromString(@"needsAnimationTimer")]) {
       NSWindow *win = [windows objectAtIndex:0];
       ScreenSaverView *sv = find_saverView ([win contentView]);
       anim_timer = [NSTimer scheduledTimerWithTimeInterval:
@@ -1596,6 +1610,18 @@ FAIL:
   return YES;
 }
 
+/* When the window is about to close, stop its animation.
+   Without this, timers might fire after the window is dead.
+ */
+- (void)windowWillClose:(NSNotification *)notification
+{
+  NSWindow *win = [notification object];
+  NSView *cv = win ? [win contentView] : 0;
+  ScreenSaverView *sv = cv ? find_saverView (cv) : 0;
+  if (sv && [sv isAnimating])
+    [sv stopAnimation];
+}
+
 # else // USE_IPHONE
 
 - (void)applicationWillResignActive:(UIApplication *)app