From http://www.jwz.org/xscreensaver/xscreensaver-5.32.tar.gz
authorZygo Blaxell <zblaxell@faye.furryterror.org>
Mon, 1 Dec 2014 19:55:18 +0000 (14:55 -0500)
committerZygo Blaxell <zblaxell@faye.furryterror.org>
Mon, 1 Dec 2014 19:57:05 +0000 (14:57 -0500)
-rw-r--r-- 1 zblaxell zblaxell 10571502 Nov 19 02:35 xscreensaver-5.32.tar.gz
3131d45295b9a18a2901737c9b95f1c5434f53a6  xscreensaver-5.32.tar.gz

27 files changed:
OSX/SaverRunner.m
OSX/SaverRunner.plist
OSX/Updater.plist
OSX/XScreenSaver.plist
OSX/XScreenSaverConfigSheet.m
OSX/XScreenSaverGLView.m
OSX/XScreenSaverView.h
OSX/XScreenSaverView.m
OSX/bindist.rtf
OSX/iSaverRunner.plist
OSX/jwxyz.m
OSX/updates.xml
README
android/README [new file with mode: 0644]
driver/XScreenSaver.ad.in
hacks/binaryring.c
hacks/config/README
hacks/fps.c
hacks/glx/cityflow.c
hacks/glx/fps-gl.c
hacks/glx/jwzgles.c
hacks/glx/texfont.c
po/POTFILES.in
utils/utf8wc.c
utils/version.h
xscreensaver.spec
xscreensaver.xcodeproj/project.pbxproj

index 80031e775f6456b895cda3c6da664462e5a4317c..2a105056ba464b71722b5186b0448d3c1727ddc2 100644 (file)
 
 @end
 
+
+/* This subclass exists to ensure that all events on the saverWindow actually
+   go to the saverView.  For some reason, the rootViewController's
+   UILayoutContainerView was capturing all of our events (touches and shakes).
+ */
+
+@interface EventCapturingWindow : UIWindow
+@property(assign) UIView *eventView;
+@end
+
+@implementation EventCapturingWindow
+@synthesize eventView;
+
+/* Always deliver touch events to the eventView if we have one.
+ */
+- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
+{
+  if (eventView)
+    return eventView;
+  else
+    return [super hitTest:point withEvent:event];
+}
+
+/* Always deliver motion events to the eventView if we have one.
+ */
+- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event
+{
+  if (eventView)
+    [eventView motionBegan:motion withEvent:event];
+  else
+    [super motionBegan:motion withEvent:event];
+}
+
+- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event
+{
+  if (eventView)
+    [eventView motionEnded:motion withEvent:event];
+  else
+    [super motionEnded:motion withEvent:event];
+}
+
+- (void)motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent *)event
+{
+  if (eventView)
+    [eventView motionCancelled:motion withEvent:event];
+  else
+    [super motionCancelled:motion withEvent:event];
+}
+
+@end
+
+
 #endif // USE_IPHONE
 
 
@@ -449,12 +501,14 @@ relabel_menus (NSObject *v, NSString *old_str, NSString *new_str)
   [prefs setObject:name forKey:@"selectedSaverName"];
   [prefs synchronize];
 
+/* Cacheing this screws up rotation when starting a saver twice in a row.
   if (saverName && [saverName isEqualToString: name]) {
     if ([saverView isAnimating])
       return;
     else
       goto LAUNCH;
   }
+*/
 
   saverName = name;
 
@@ -467,26 +521,118 @@ relabel_menus (NSObject *v, NSString *old_str, NSString *new_str)
     [saverView release];
   }
 
-  /* We can't just use [window bounds] because that is the *rotated* rectangle
-     and we need the *unrotated* rectangle, so that the view is always created
-     in portrait orientation.  Without that, the initial rotation event that
-     takes us from unknown->landscape will be out of step with reality.
-   */
   UIScreen *screen = [UIScreen mainScreen];
-# ifndef __IPHONE_8_0                          // iOS 7 SDK
-  NSSize size = [screen bounds].size;
-  int ss = [screen scale];
-# else                                         // iOS 8 SDK
-  NSSize size = ([screen respondsToSelector:@selector(nativeBounds)]
-                 ? [screen nativeBounds].size  //  iOS 8
-                 : [screen bounds].size);      //  iOS 7
-  int ss = ([screen respondsToSelector:@selector(nativeScale)]
-            ? [screen nativeScale]             //  iOS 8
-            : [screen scale]);                 //  iOS 7
-# endif                                                // iOS 8 SDK
+  NSSize size;
+  double scale;
+
+# ifndef __IPHONE_8_0                          // iOS 7 SDK or earlier
+
+  size = [screen bounds].size;                 //  points, not pixels
+  scale = [screen scale];                      //  available in iOS 4
+
+# else                                         // iOS 8 SDK or later
+
+  if ([screen respondsToSelector:@selector(nativeBounds)]) {
+    size = [screen nativeBounds].size;         //  available in iOS 8
+    scale = 1;  // nativeBounds is in pixels.
+
+    /* 'nativeScale' is very confusing.
+
+       iPhone 4s:
+          bounds:        320x480   scale:        2
+          nativeBounds:  640x960   nativeScale:  2
+       iPhone 5s:
+          bounds:        320x568   scale:        2
+          nativeBounds:  640x1136  nativeScale:  2
+       iPad 2:
+          bounds:       768x1024   scale:        1
+          nativeBounds: 768x1024   nativeScale:  1
+       iPad Retina/Air:
+          bounds:       768x1024   scale:        2
+          nativeBounds: 1536x2048  nativeScale:  2
+       iPhone 6:
+          bounds:        320x568   scale:        2
+          nativeBounds:  640x1136  nativeScale:  2
+       iPhone 6+:
+          bounds:        320x568   scale:        2
+          nativeBounds:  960x1704  nativeScale:  3
+
+       According to a StackOverflow comment:
+
+         The iPhone 6+ renders internally using @3x assets at a virtual
+         resolution of 2208x1242 (with 736x414 points), then samples that down
+         for display. The same as using a scaled resolution on a Retina MacBook
+         -- it lets them hit an integral multiple for pixel assets while still
+         having e.g. 12pt text look the same size on the screen.
+
+         The 6, the 5s, the 5, the 4s and the 4 are all 326 pixels per inch,
+         and use @2x assets to stick to the approximately 160 points per inch
+         of all previous devices.
+
+         The 6+ is 401 pixels per inch. So it'd hypothetically need roughly
+         @2.46x assets. Instead Apple uses @3x assets and scales the complete
+         output down to about 84% of its natural size.
+
+         In practice Apple has decided to go with more like 87%, turning the
+         1080 into 1242. No doubt that was to find something as close as
+         possible to 84% that still produced integral sizes in both directions
+         -- 1242/1080 = 2208/1920 exactly, whereas if you'd turned the 1080
+         into, say, 1286, you'd somehow need to render 2286.22 pixels
+         vertically to scale well.
+     */
+
+  } else {
+    size = [screen bounds].size;               //  points, not pixels
+    scale = [screen scale];                    //  available in iOS 4
+  }
+# endif  // iOS 8
+
+  size.width  = ceilf (size.width  / scale);
+  size.height = ceilf (size.height / scale);
+
+
+# if TARGET_IPHONE_SIMULATOR
+  NSLog(@"screen: %.0fx%0.f",
+        [[screen currentMode] size].width,
+        [[screen currentMode] size].height);
+  NSLog(@"bounds: %.0fx%0.f x %.1f = %.0fx%0.f",
+        [screen bounds].size.width,
+        [screen bounds].size.height,
+        [screen scale],
+        [screen scale] * [screen bounds].size.width,
+        [screen scale] * [screen bounds].size.height);
+
+#  ifdef __IPHONE_8_0
+  if ([screen respondsToSelector:@selector(nativeBounds)])
+    NSLog(@"native: %.0fx%0.f / %.1f = %.0fx%0.f",
+          [screen nativeBounds].size.width,
+          [screen nativeBounds].size.height,
+          [screen nativeScale],
+          [screen nativeBounds].size.width  / [screen nativeScale],
+          [screen nativeBounds].size.height / [screen nativeScale]);
+#  endif
+
+
+  /* Our view must be full screen, and view sizes are measured in points,
+     not pixels.  However, since our view is on a UINavigationController
+     that does not rotate, the size must be portrait-mode even if the
+     device is landscape.
+
+     On iOS 7, [screen bounds] always returned portrait-mode values.
+     On iOS 8, it rotates.  So swap as necessary.
+     On iOS 8, [screen nativeBounds] is unrotated, in pixels not points.
+   */
+  size = [screen bounds].size;
+  if (size.width > size.height) {
+    double s = size.width;
+    size.width = size.height;
+    size.height = s;
+  }
+
+  NSLog(@"saverView: %.0fx%.0f", size.width, size.height);
+# endif // TARGET_IPHONE_SIMULATOR
+
 
-  size.width  /= ss;
-  size.height /= ss;
   saverView = [self makeSaverView:name withSize:size];
 
   if (! saverView) {
@@ -504,33 +650,41 @@ relabel_menus (NSObject *v, NSString *old_str, NSString *new_str)
     selector:@selector(didRotate:)
     name:UIDeviceOrientationDidChangeNotification object:nil];
 
- LAUNCH:
+  /* LAUNCH: */
 
   if (launch) {
     [self saveScreenshot];
-    NSRect f = [saverWindow bounds];
+    NSRect f;
+    f.origin.x = 0;
+    f.origin.y = 0;
+    f.size = [[UIScreen mainScreen] bounds].size;
+    if (f.size.width > f.size.height) {  // Force portrait
+      double swap = f.size.width;
+      f.size.width = f.size.height;
+      f.size.height = swap;
+    }
     [backgroundView setFrame:f];
     [saverView setFrame:f];
     [saverWindow addSubview: backgroundView];
     [backgroundView addSubview: saverView];
+    [saverWindow setFrame:f];
     [saverView setBackgroundColor:[NSColor blackColor]];
 
-    /* WTF! Without creating and keying this window, we get no events
-       delivered on the saverView/saverWindow!  Bad craziness.
-     */
-    {
-      UIWindow *dummy = [[UIWindow alloc] initWithFrame:CGRectMake(0,0,0,0)];
-      [dummy setRootViewController: nonrotating_nav];  // Must be this one.
-      [dummy setHidden:NO];  // required
-      [dummy setHidden:YES];
-      [dummy release];
-    }
-
     [saverWindow setHidden:NO];
     [saverWindow makeKeyAndVisible];
     [saverView startAnimation];
     [self aboutPanel:nil];
 
+    // Tell the UILayoutContainerView to stop intercepting our events.
+    //    [[saverWindow rootViewController] view].userInteractionEnabled = NO;
+    //    saverView.userInteractionEnabled = YES;
+
+    // Tell the saverWindow that all events should go to saverView.
+    //
+    NSAssert ([saverWindow isKindOfClass:[EventCapturingWindow class]],
+              @"saverWindow is not an EventCapturingWindow");
+    ((EventCapturingWindow *) saverWindow).eventView = saverView;
+
     // Doing this makes savers cut back to the list instead of fading,
     // even though [XScreenSaverView stopAndClose] does setHidden:NO first.
     // [window setHidden:YES];
@@ -1233,7 +1387,7 @@ FAIL:
 # endif                                                // iOS 8 SDK
   frame.size.width  /= ss;
   frame.size.height /= ss;
-  saverWindow = [[UIWindow alloc] initWithFrame:frame];
+  saverWindow = [[EventCapturingWindow alloc] initWithFrame:frame];
   [saverWindow setRootViewController: nonrotating_nav];
   [saverWindow setHidden:YES];
 
index 9cd51e508f1382b489dc638c218f22ed4584dfae..05ba03ae57ff8a75c268c4f0ed4feaa207504113 100644 (file)
@@ -7,7 +7,7 @@
        <key>CFBundleExecutable</key>
        <string>${EXECUTABLE_NAME}</string>
        <key>CFBundleGetInfoString</key>
-       <string>5.31</string>
+       <string>5.32</string>
        <key>CFBundleIconFile</key>
        <string>SaverRunner</string>
        <key>CFBundleIdentifier</key>
        <key>CFBundleInfoDictionaryVersion</key>
        <string>6.0</string>
        <key>CFBundleLongVersionString</key>
-       <string>5.31</string>
+       <string>5.32</string>
        <key>CFBundleName</key>
        <string>${PRODUCT_NAME}</string>
        <key>CFBundlePackageType</key>
        <string>APPL</string>
        <key>CFBundleShortVersionString</key>
-       <string>5.31</string>
+       <string>5.32</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>5.31</string>
+       <string>5.32</string>
        <key>LSMinimumSystemVersion</key>
        <string>${MACOSX_DEPLOYMENT_TARGET}</string>
        <key>NSHumanReadableCopyright</key>
-       <string>5.31</string>
+       <string>5.32</string>
        <key>NSMainNibFile</key>
        <string>SaverRunner</string>
        <key>NSPrincipalClass</key>
index cc937af9fbcf5be4656098f80e85593d15359ac8..4566e7486114ad387045ea5339f45cb58a786355 100644 (file)
@@ -7,7 +7,7 @@
        <key>CFBundleExecutable</key>
        <string>${EXECUTABLE_NAME}</string>
        <key>CFBundleGetInfoString</key>
-       <string>5.31</string>
+       <string>5.32</string>
        <key>CFBundleIconFile</key>
        <string>SaverRunner</string>
        <key>CFBundleIdentifier</key>
@@ -15,7 +15,7 @@
        <key>CFBundleInfoDictionaryVersion</key>
        <string>6.0</string>
        <key>CFBundleLongVersionString</key>
-       <string>5.31</string>
+       <string>5.32</string>
        <key>CFBundleName</key>
        <string>${PRODUCT_NAME}</string>
        <key>CFBundleDisplayName</key>
        <key>CFBundlePackageType</key>
        <string>APPL</string>
        <key>CFBundleShortVersionString</key>
-       <string>5.31</string>
+       <string>5.32</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>5.31</string>
+       <string>5.32</string>
        <key>LSMinimumSystemVersion</key>
        <string>${MACOSX_DEPLOYMENT_TARGET}</string>
        <key>LSUIElement</key>
        <true/>
        <key>NSHumanReadableCopyright</key>
-       <string>5.31</string>
+       <string>5.32</string>
        <key>NSMainNibFile</key>
        <string>Updater</string>
        <key>NSPrincipalClass</key>
index 93d7dca4d8c8bead5ea8bd96c7f2a132bb3103bf..291a0946abdd03fcb89c799871775b025d7a0b78 100644 (file)
        <key>CFBundlePackageType</key>
        <string>BNDL</string>
        <key>CFBundleShortVersionString</key>
-       <string>5.31</string>
+       <string>5.32</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>5.31</string>
+       <string>5.32</string>
        <key>LSMinimumSystemVersion</key>
        <string>10.4</string>
        <key>NSMainNibFile</key>
index 6dceacf7010a921894f7509ccccbebc649880eaa..5a6484366df0ca2bb7ca0bd1b5d22ac0c72f9e96 100644 (file)
@@ -3357,10 +3357,15 @@ wrap_with_buttons (NSWindow *window, NSView *panel)
   CGFloat ww = [tv frame].size.width;
   CGFloat hh = [self tableView:tv heightForRowAtIndexPath:ip];
 
+  float os_version = [[[UIDevice currentDevice] systemVersion] floatValue];
+
   // Width of the column of labels on the left.
   CGFloat left_width = ww * 0.4;
   CGFloat right_edge = ww - LEFT_MARGIN;
 
+  if (os_version < 7)  // margins were wider on iOS 6.1
+    right_edge -= 10;
+
   CGFloat max = FONT_SIZE * 12;
   if (left_width > max) left_width = max;
 
@@ -3383,6 +3388,10 @@ wrap_with_buttons (NSWindow *window, NSView *panel)
         if ([ctl isKindOfClass:[UISwitch class]]) {    // Checkboxes.
           r.size.width = 80;  // Magic.
           r.origin.x = right_edge - r.size.width + 30;  // beats me
+
+          if (os_version < 7)  // checkboxes were wider on iOS 6.1
+            r.origin.x -= 25;
+
         } else {
           r.origin.x = left_width;                     // Text fields, etc.
           r.size.width = right_edge - r.origin.x;
index 7af44038bc7c900eacd57a184f1b7657240c0939..da77021c89f63f489970a054f7b1d8e30d03edcb 100644 (file)
@@ -87,7 +87,13 @@ extern void check_gl_error (const char *type);
  */
 - (CGFloat) hackedContentScaleFactor
 {
-  return [self contentScaleFactor];
+  NSSize ssize = [[[UIScreen mainScreen] currentMode] size];
+  NSSize bsize = [self bounds].size;
+
+  // Ratio of screen size in pixels to view size in points.
+  GLfloat s = ((ssize.width > ssize.height ? ssize.width : ssize.height) /
+               (bsize.width > bsize.height ? bsize.width : bsize.height));
+  return s;
 }
 #endif // USE_IPHONE
 
index 28d1f51fab258d6647b17dfd5d63db6a801736d2..c60dfc8a1129a8f2a2f22a24387b81d1d261f78c 100644 (file)
   UIDeviceOrientation orientation, new_orientation;
   BOOL screenLocked;
 
-  CGSize initial_bounds;       // portrait-mode geometry
+  CGSize initial_bounds;       // portrait-mode size (pixels, not points).
        
-  GLfloat rotation_ratio;      // ratio thru rotation anim, or -1
-  NSSize rot_from, rot_to;     // start size rect, end size rect
-  GLfloat angle_from, angle_to;        // start angle, end angle
+  GLfloat rotation_ratio;      // ratio [0-1] thru rotation anim, or -1
+  NSSize rot_current_size;     // intermediate or at-rest orientation.
+  NSSize rot_from, rot_to;     // start/end size rect (pixels, not points)
+  GLfloat rot_current_angle;   // only right angles when rotation complete.
+  GLfloat angle_from, angle_to;        // start angle, end angle (degrees)
   double rot_start_time;
-  BOOL ignore_rotation_p;      // hack requests "always portrait".
-                               // some want this, some do not.
 
-  NSSize rot_current_size;     // current intermediate or final orientation.
-  GLfloat rot_current_angle;   // only right angles when rotation complete.
+  BOOL ignore_rotation_p;      // whether hack requested "always portrait".
+                               // some want this, some do not.
 
   NSTimer *crash_timer;
 
 
 # ifdef USE_BACKBUFFER
   CGContextRef backbuffer;
-  CGSize backbuffer_size;
+  CGSize backbuffer_size;      // pixels, not points.
   CGColorSpaceRef colorspace;
 
 #  ifdef BACKBUFFER_CGCONTEXT
index 3f0cd8f0fc6239e6958b3661d8635d64e5a6a87d..602629533f4c691cb90e5bc904b5cf08a9cf34a0 100644 (file)
@@ -141,8 +141,7 @@ extern NSDictionary *make_function_table_dict(void);  // ios-function-table.m
     NSLog (@"no symbol \"%@\" for \"%@\"", table_name, path);
 
 # else  // USE_IPHONE
-  // Remember: any time you add a new saver to the iOS app,
-  // manually run "make ios-function-table.m"!
+  // Depends on the auto-generated "ios-function-table.m" being up to date.
   if (! function_tables)
     function_tables = [make_function_table_dict() retain];
   NSValue *v = [function_tables objectForKey: name];
@@ -379,14 +378,6 @@ orientname(unsigned long o)
            saverName:(NSString *)saverName
            isPreview:(BOOL)isPreview
 {
-# ifdef USE_IPHONE
-  initial_bounds = frame.size;
-  rot_current_size = frame.size;       // needs to be early, because
-  rot_from = rot_current_size;         // [self setFrame] is called by
-  rot_to = rot_current_size;           // [super initWithFrame].
-  rotation_ratio = -1;
-# endif
-
   if (! (self = [super initWithFrame:frame isPreview:isPreview]))
     return 0;
   
@@ -398,13 +389,6 @@ orientname(unsigned long o)
 
   [self setShellPath];
 
-# ifdef USE_IPHONE
-  [self setMultipleTouchEnabled:YES];
-  orientation = UIDeviceOrientationUnknown;
-  [self didRotate:nil];
-  [self initGestures];
-# endif // USE_IPHONE
-
   setup_p = YES;
   if (xsft->setup_cb)
     xsft->setup_cb (xsft, xsft->setup_arg);
@@ -431,17 +415,34 @@ orientname(unsigned long o)
   progname = progclass = xsft->progclass;
 
   next_frame_time = 0;
-  
-# ifdef USE_BACKBUFFER
-  [self createBackbuffer:NSSizeToCGSize(frame.size)];
-  [self initLayer];
+
+# ifdef USE_IPHONE
+  double s = [self hackedContentScaleFactor];
+# else
+  double s = 1;
 # endif
 
+  CGSize bb_size;      // pixels, not points
+  bb_size.width  = s * frame.size.width;
+  bb_size.height = s * frame.size.height;
+
 # ifdef USE_IPHONE
+  initial_bounds = rot_current_size = rot_from = rot_to = bb_size;
+  rotation_ratio = -1;
+
+  orientation = UIDeviceOrientationUnknown;
+  [self didRotate:nil];
+  [self initGestures];
+
   // So we can tell when we're docked.
   [UIDevice currentDevice].batteryMonitoringEnabled = YES;
 # endif // USE_IPHONE
 
+# ifdef USE_BACKBUFFER
+  [self createBackbuffer:bb_size];
+  [self initLayer];
+# endif
+
   return self;
 }
 
@@ -653,10 +654,16 @@ screenhack_do_fps (Display *dpy, Window w, fps_state *fpst, void *closure)
  */
 - (CGFloat) hackedContentScaleFactor
 {
-  GLfloat s = [self contentScaleFactor];
-  if (initial_bounds.width  >= 1024 ||
-      initial_bounds.height >= 1024)
+  NSSize ssize = [[[UIScreen mainScreen] currentMode] size];
+  NSSize bsize = [self bounds].size;
+
+  // Ratio of screen size in pixels to view size in points.
+  GLfloat s = ((ssize.width > ssize.height ? ssize.width : ssize.height) /
+               (bsize.width > bsize.height ? bsize.width : bsize.height));
+
+  if (ssize.width >= 1024 && ssize.height >= 1024)
     s = 1;
+
   return s;
 }
 
@@ -721,12 +728,11 @@ double current_device_rotation (void)
 
 #   undef CLAMP180
 
-  double s = [self hackedContentScaleFactor];
   CGSize rotsize = ((ignore_rotation_p || ![self reshapeRotatedWindow])
                     ? initial_bounds
                     : rot_current_size);
-  if ((int) backbuffer_size.width  != (int) (s * rotsize.width) ||
-      (int) backbuffer_size.height != (int) (s * rotsize.height))
+  if ((int) backbuffer_size.width  != (int) rotsize.width ||
+      (int) backbuffer_size.height != (int) rotsize.height)
     [self resize_x11];
 }
 
@@ -764,6 +770,8 @@ double current_device_rotation (void)
 
 /* Create a bitmap context into which we render everything.
    If the desired size has changed, re-created it.
+   new_size is in rotated pixels, not points: the same size
+   and shape as the X11 window as seen by the hacks.
  */
 - (void) createBackbuffer:(CGSize)new_size
 {
@@ -840,13 +848,13 @@ double current_device_rotation (void)
       (int)backbuffer_size.height == (int)new_size.height)
     return;
 
-  CGSize osize = backbuffer_size;
   CGContextRef ob = backbuffer;
 
-  backbuffer_size = new_size;
+  CGSize osize = backbuffer_size;      // pixels, not points.
+  backbuffer_size = new_size;          // pixels, not points.
 
 # if TARGET_IPHONE_SIMULATOR
-  NSLog(@"backbuffer %.0f %.0f",
+  NSLog(@"backbuffer %.0fx%.0f",
         backbuffer_size.width, backbuffer_size.height);
 # endif
 
@@ -871,10 +879,12 @@ double current_device_rotation (void)
 
   if (ob) {
     // Restore old bits, as much as possible, to the X11 upper left origin.
-    CGRect rect;
+
+    CGRect rect;   // pixels, not points
     rect.origin.x = 0;
     rect.origin.y = (backbuffer_size.height - osize.height);
-    rect.size  = osize;
+    rect.size = osize;
+
     CGImageRef img = CGBitmapContextCreateImage (ob);
     CGContextDrawImage (backbuffer, rect, img);
     CGImageRelease (img);
@@ -891,18 +901,18 @@ double current_device_rotation (void)
 {
   if (!xwindow) return;  // early
 
-  CGSize new_size;
+  CGSize new_size;     // pixels, not points
+
 # ifdef USE_BACKBUFFER
 #  ifdef USE_IPHONE
-  double s = [self hackedContentScaleFactor];
   CGSize rotsize = ((ignore_rotation_p || ![self reshapeRotatedWindow])
                     ? initial_bounds
                     : rot_current_size);
-  new_size.width  = s * rotsize.width;
-  new_size.height = s * rotsize.height;
-#  else
+  new_size.width  = rotsize.width;
+  new_size.height = rotsize.height;
+#  else  // !USE_IPHONE
   new_size = NSSizeToCGSize([self bounds].size);
-#  endif
+#  endif // !USE_IPHONE
 
   [self createBackbuffer:new_size];
   jwxyz_window_resized (xdpy, xwindow, 0, 0, new_size.width, new_size.height,
@@ -914,7 +924,7 @@ double current_device_rotation (void)
 # endif  // !USE_BACKBUFFER
 
 # if TARGET_IPHONE_SIMULATOR
-  NSLog(@"reshape %.0f x %.0f", new_size.width, new_size.height);
+  NSLog(@"reshape %.0fx%.0f", new_size.width, new_size.height);
 # endif
 
   // Next time render_x11 is called, run the saver's reshape_cb.
@@ -1196,25 +1206,31 @@ double current_device_rotation (void)
 # endif
 
 # ifdef USE_IPHONE
-  // Then compute the transformations for rotation.
-  double hs = [self hackedContentScaleFactor];
-  double s = [self contentScaleFactor];
-
   // The rotation origin for layer.affineTransform is in the center already.
   CGAffineTransform t = ignore_rotation_p ?
     CGAffineTransformIdentity :
     CGAffineTransformMakeRotation (rot_current_angle / (180.0 / M_PI));
 
-  CGFloat f = s / hs;
-  self.layer.affineTransform = CGAffineTransformScale(t, f, f);
+  // Ratio of backbuffer size in pixels to layer size in points.
+  CGSize ssize = backbuffer_size;
+  CGSize bsize = [self bounds].size;
+  GLfloat s = ((ssize.width > ssize.height ? ssize.width : ssize.height) /
+               (bsize.width > bsize.height ? bsize.width : bsize.height));
+
+  self.layer.contentsScale = s;
+  self.layer.affineTransform = t;
 
+  /* Setting the layer's bounds also sets the view's bounds.
+     The view's bounds must be in points, not pixels, and it
+     must be rotated to the current orientation.
+   */
   CGRect bounds;
   bounds.origin.x = 0;
   bounds.origin.y = 0;
-
-  bounds.size.width = backbuffer_size.width / s;
-  bounds.size.height = backbuffer_size.height / s;
+  bounds.size.width  = ssize.width  / s;
+  bounds.size.height = ssize.height / s;
   self.layer.bounds = bounds;
+
 # endif // USE_IPHONE
  
 # if defined(BACKBUFFER_CALAYER)
@@ -1908,6 +1924,8 @@ double current_device_rotation (void)
   [dtap requireGestureRecognizerToFail: hold];
   [pan  requireGestureRecognizerToFail: hold];
 
+  [self setMultipleTouchEnabled:YES];
+
   [self addGestureRecognizer: dtap];
   [self addGestureRecognizer: stap];
   [self addGestureRecognizer: pan];
index 3c75a6eef80960cf7018b923cf9ba783e6fdc8dc..27f3d57062f762ee656428e7463ae047fc6648a0 100644 (file)
@@ -16,8 +16,8 @@
 \b0 by Jamie Zawinski\
 and many others\
 \
-version 5.31\
-15-Nov-2014\
+version 5.32\
+18-Nov-2014\
 \
 {\field{\*\fldinst{HYPERLINK "http://www.jwz.org/xscreensaver/"}}{\fldrslt \cf2 \ul \ulc2 http://www.jwz.org/xscreensaver/}}\
 \pard\pardeftab720
index ad17fa9b4eba0cd391189a5202fe0411bed91e39..391ed443eadc4bca8df69516c00dac879f0124a5 100644 (file)
@@ -9,7 +9,7 @@
        <key>CFBundleExecutable</key>
        <string>${EXECUTABLE_NAME}</string>
        <key>CFBundleGetInfoString</key>
-       <string>5.31</string>
+       <string>5.32</string>
        <key>CFBundleIconFile</key>
        <string>iSaverRunner57.png</string>
        <key>CFBundleIconFiles</key>
        <key>CFBundleInfoDictionaryVersion</key>
        <string>6.0</string>
        <key>CFBundleLongVersionString</key>
-       <string>5.31</string>
+       <string>5.32</string>
        <key>CFBundleName</key>
        <string>${PRODUCT_NAME}</string>
        <key>CFBundlePackageType</key>
        <string>APPL</string>
        <key>CFBundleShortVersionString</key>
-       <string>5.31</string>
+       <string>5.32</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>5.31</string>
+       <string>5.32</string>
        <key>LSRequiresIPhoneOS</key>
        <true/>
        <key>NSHumanReadableCopyright</key>
-       <string>5.31</string>
+       <string>5.32</string>
        <key>NSMainNibFile</key>
        <string>iSaverRunner</string>
        <key>UIRequiredDeviceCapabilities</key>
index 78a9bc56043bbf7bf8eac7d2601e37aa4eff1831..720569573fd5385dff404fad7ae5287438c8f882 100644 (file)
@@ -2967,8 +2967,15 @@ XLoadFont (Display *dpy, const char *name)
   float scale = 1;
 
 # ifdef USE_IPHONE
-  // Scale up fonts on Retina displays.
-  scale = dpy->main_window->window.view.contentScaleFactor;
+  /* Since iOS screens are physically smaller than desktop screens, scale up
+     the fonts to make them more readable.
+
+     Note that X11 apps on iOS also have the backbuffer sized in points
+     instead of pixels, resulting in an effective X11 screen size of 768x1024
+     or so, even if the display has significantly higher resolution.  That is
+     unrelated to this hack, which is really about DPI.
+   */
+  scale = 2;
 # endif
 
   fid->nsfont = try_native_font (name, scale, &fid->ps_name, &fid->size);
@@ -3509,13 +3516,8 @@ XQueryPointer (Display *dpy, Window w, Window *root_ret, Window *child_ret,
   NSScreen *screen = (screens && [screens count] > 0
                       ? [screens objectAtIndex:0]
                       : [NSScreen mainScreen]);
-#ifdef USE_IPHONE
-  double s = w->window.view.contentScaleFactor;
-#else
-  int s = 1;
-#endif
   NSRect srect = [screen frame];
-  vpos.y = (s * srect.size.height) - vpos.y;
+  vpos.y = srect.size.height - vpos.y;
   
   // get the mouse position on window, from bottom left
   NSEvent *e = [NSApp currentEvent];
@@ -3579,13 +3581,8 @@ XTranslateCoordinates (Display *dpy, Window w, Window dest_w,
   NSScreen *screen = (screens && [screens count] > 0
                       ? [screens objectAtIndex:0]
                       : [NSScreen mainScreen]);
-# ifdef USE_IPHONE
-  double s = w->window.view.contentScaleFactor;
-# else
-  int s = 1;
-# endif
   NSRect srect = [screen frame];
-  vpos.y = (s * srect.size.height) - vpos.y;
+  vpos.y = srect.size.height - vpos.y;
   
   // point starts out relative to top left of view
   NSPoint p;
index 0e17790f955e9430829de3c63c3d51d1555e8467..0da62370a2b2f2c07870f9c761054e67c723d0ea 100644 (file)
@@ -7,6 +7,17 @@
   <link>http://www.jwz.org/xscreensaver/updates.xml</link>
   <description>Updates to xscreensaver.</description>
   <language>en</language>
+  <item>
+   <title>Version 5.31</title>
+   <link>http://www.jwz.org/xscreensaver/xscreensaver-5.31.dmg</link>
+   <description><![CDATA[&bull; New hacks, `geodesicgears', `binaryring' and `cityflow'. <BR>&bull; UTF-8 text support (instead of only Latin1) and antialiased text on X11 with Xft (instead of only on OSX/iOS) in `fontglide', `noseguy', `fliptext', `starwars', and `winduprobot'. The other text-displaying hacks (`apple2', `phosphor', `xmatrix', and `gltext') also now accept UTF-8 input, though they convert it to Latin1 or ASCII. <BR>&bull; `glplanet' now has both day and night maps, and a sharp terminator. <BR>&bull; Fixed `webcollage' on OSX. <BR>&bull; Fixed a transparency glitch in `winduprobot'. <BR>&bull; `lockward' works on iOS. <BR>&bull; Text and image loading work on OSX 10.10. <BR>&bull; Rotation works properly on iOS 8. <BR>&bull; Added a search field on iOS. <BR>&bull; Preliminary, unfinished support for Android.]]></description>
+   <pubDate>Sat, 15 Nov 2014 15:38:27 -0800</pubDate>
+   <enclosure url="http://www.jwz.org/xscreensaver/xscreensaver-5.31.dmg"
+    sparkle:version="5.31"
+    sparkle:dsaSignature="MC4CFQCdDs107OqBIERPG9dULT0g49uc4wIVALUB7StXIXaAKxuklWvNO2y80pNf"
+    length="55131377"
+    type="application/octet-stream" />
+  </item>
   <item>
    <title>Version 5.30</title>
    <link>http://www.jwz.org/xscreensaver/xscreensaver-5.30.dmg</link>
diff --git a/README b/README
index a6184dab932d010739d9ed701c242b3233e626bc..acacae2ec211966f6c3d4257221034c078f1cfad 100644 (file)
--- a/README
+++ b/README
@@ -38,6 +38,8 @@ XScreenSaver has an extensive manual -- please read it!
 
 ===============================================================================
 
+5.32   * Fixed some X11 compilation problems.
+       * Fixed display size and shake gestures on iOS.
 5.31   * New hacks, `geodesicgears', `binaryring' and `cityflow'.
         * UTF-8 text support (instead of only Latin1) and antialiased text
           on X11 with Xft (instead of only on OSX/iOS) in `fontglide',
diff --git a/android/README b/android/README
new file mode 100644 (file)
index 0000000..501aafe
--- /dev/null
@@ -0,0 +1,9 @@
+
+This directory contains the Android-specific code for building xscreensaver.
+
+It is preliminary, and very much a work in progress.
+
+If you're messing with this, please let us know!
+
+        dennis@panaceasupplies.com
+        jwz@jwz.org
index d1bbbe3ac6a46b5728bf6c15062ad86d9e9a8dd1..98e4cbbecb4224dbbd1992cc04964e5d09ecbb51 100644 (file)
@@ -4,8 +4,8 @@
 !            a screen saver and locker for the X window system
 !                            by Jamie Zawinski
 !
-!                              version 5.31
-!                              15-Nov-2014
+!                              version 5.32
+!                              18-Nov-2014
 !
 ! See "man xscreensaver" for more info.  The latest version is always
 ! available at http://www.jwz.org/xscreensaver/
index 24320739d17bd6b778162d5a8c533bf9512e1eba..48d72e9ddbba3bc901d5ef56a7fdb35728121b8e 100644 (file)
 #include "colors.h"
 #include "hsv.h"
 
+#if HAVE_STDINT_H
+# include <stdint.h>
+#else
+typedef unsigned long uint32_t;
+#endif
+
 #define ANTIALIAS   1
 #define BLACK       0
 #define WHITE       1
index d57f1af3c3c94a63e2ceedd1f2505eb705747f72..0c1914fab7b82c53d83c3b569b08189461efcbfb 100644 (file)
@@ -4,8 +4,8 @@
             a screen saver and locker for the X window system
                             by Jamie Zawinski
 
-                              version 5.31
-                               15-Nov-2014
+                              version 5.32
+                               18-Nov-2014
 
                      http://www.jwz.org/xscreensaver/
 
index 44171730461de142a3d80c6cd9528bc075f3b1c7..5704337408f5bff2c9038ea4f0e5c61b61c94e5f 100644 (file)
@@ -1,4 +1,4 @@
-/* fps, Copyright (c) 2001-2011 Jamie Zawinski <jwz@jwz.org>
+/* fps, Copyright (c) 2001-2014 Jamie Zawinski <jwz@jwz.org>
  * Draw a frames-per-second display (Xlib and OpenGL).
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
@@ -56,8 +56,7 @@ fps_init (Display *dpy, Window window)
   st->x = 10;
   st->y = 10;
   if (get_boolean_resource (dpy, "fpsTop", "FPSTop"))
-    /* don't leave a blank line in GL top-fps. */
-    st->y = - (/*st->font->ascent +*/ st->font->descent + 10);
+    st->y = - (st->font->ascent + st->font->descent + 10);
 
   strcpy (st->string, "FPS: ... ");
 
index acdf3222a9449d7965a74781ca5b52f5320aa911..0199fc338775b5e2d570aa9a6d59a76648c19f27 100644 (file)
@@ -327,7 +327,7 @@ init_cube (ModeInfo *mi)
       cube->y = (frand(1)-0.5);
 
       cube->z = frand(0.12);
-      double th = (skew ? frand(skew) : 0) * M_PI / 180;
+      double th = -(skew ? frand(skew) : 0) * M_PI / 180;
       cube->cth = cos(th);
       cube->sth = sin(th);
 
index 46757708c937c6bb3698b543b3cdb30553a6dd83..17b05656135daca1fa1f03263ba45c3e8b9aa989 100644 (file)
@@ -38,6 +38,7 @@ extern void check_gl_error (const char *type);
 typedef struct {
   texture_font_data *texfont;
   int line_height;
+  Bool top_p;
 } gl_fps_data;
 
 
@@ -45,6 +46,7 @@ static void
 xlockmore_gl_fps_init (fps_state *st)
 {
   gl_fps_data *data = (gl_fps_data *) calloc (1, sizeof(*data));
+  data->top_p = get_boolean_resource (st->dpy, "fpsTop", "FPSTop");
   data->texfont = load_texture_font (st->dpy, "fpsFont");
   texture_string_width (data->texfont, "M", &data->line_height);
   st->gl_fps_data = data;
@@ -93,6 +95,7 @@ xlockmore_gl_draw_fps (ModeInfo *mi)
       glColor3f (1, 1, 1);
       print_texture_label (st->dpy, data->texfont,
                            xgwa.width, xgwa.height,
-                           2, st->string);
+                           (data->top_p ? 1 : 2),
+                           st->string);
     }
 }
index 094192c76ba61cc2feaba1d6d751ea2460e4ab9d..ff915a021064510f2f10bbf5ce3d507fb11e363a 100644 (file)
@@ -3977,6 +3977,15 @@ jwzgles_gluProject (GLdouble objx, GLdouble objy, GLdouble objz,
 }
 
 
+void jwzgles_glViewport (GLuint x, GLuint y, GLuint w, GLuint h)
+{
+# if TARGET_IPHONE_SIMULATOR
+/*  fprintf (stderr, "glViewport %dx%d\n", w, h); */
+# endif
+  glViewport (x, y, w, h);  /* the real one */
+}
+
+
 /* The following functions are present in both OpenGL 1.1 and in OpenGLES 1,
    but are allowed within glNewList/glEndList, so we must wrap them to allow
    them to either be recorded in lists, or run directly.
@@ -4143,7 +4152,6 @@ WRAP (glStencilOp,        III)
 WRAP (glTexEnvf,       IIF)
 WRAP (glTexEnvi,       III)
 WRAP (glTranslatef,    FFF)
-WRAP (glViewport,      IIII)
 #undef  TYPE_IV
 #define TYPE_IV GLuint
 WRAP (glDeleteTextures,        IIV)
index 0602344de7a779284a0d0381fcdae1a0663cdd7f..2592626954058272a489aa44e20433d71287da2a 100644 (file)
@@ -713,6 +713,24 @@ print_texture_label (Display *dpy,
       lh = texture_string_width (data, "M", 0);
       w = texture_string_width (data, string, &h);
 
+# ifdef USE_IPHONE
+      /* Size of the font is in points, so scale iOS pixels to points. */
+      {
+        GLfloat scale = 1;
+        scale = window_width / 768.0;
+        if (scale < 1) scale = 1;
+
+        /* jwxyz-XLoadFont has already doubled the font size, to compensate
+           for physically smaller screens.  Undo that, since OpenGL hacks
+           use full-resolution framebuffers, unlike X11 hacks. */
+        scale /= 2;
+
+        window_width  /= scale;
+        window_height /= scale;
+        glScalef (scale, scale, scale);
+      }
+# endif /* USE_IPHONE */
+
       if (rot > 135 || rot < -135)             /* 180 */
         {
           glTranslatef (window_width, window_height, 0);
index c6c95c1629300d80e059b5dca041e752a08b3ea2..e56216dd000ed91c8b2e9f8834aaa69058441a8d 100644 (file)
@@ -1,4 +1,4 @@
-# Auto-generated: Sat Nov 15 15:33:42 PST 2014
+# Auto-generated: Tue Nov 18 23:24:06 PST 2014
 driver/demo-Gtk-conf.c
 driver/demo-Gtk.c
 driver/screensaver-properties.desktop.in
index e2db24170aadecef6caa7992e3fe402a5f90c08d..ba6806f602fd54a3e223d5cdba34ff3b5e9dbeb4 100644 (file)
@@ -342,7 +342,11 @@ utf8_to_latin1 (const char *string, Bool ascii_p)
       long len2 = utf8_decode (in, in_end - in, &uc);
       in += len2;
 
-      if (uc > 0xFF)
+      if (uc == '\240')        /* &nbsp; */
+        uc = ' ';
+      else if (uc >= 0x2300 && uc <= 0x36F)
+        uc = 0;                /* Discard "Unicode Combining Diacriticals Block" */
+      else if (uc > 0xFF)
         switch (uc) {
 
         /* Map "Unicode General Punctuation Block" to Latin1 equivalents. */
@@ -403,15 +407,11 @@ utf8_to_latin1 (const char *string, Bool ascii_p)
         default:
           break;
         }
-      else if (uc >= 0x2300 && uc <= 0x36F)
-        uc = 0;                /* Discard "Unicode Combining Diacriticals Block" */
-      else if (uc == '\240')
-        uc = ' ';      /* &nbsp; */
 
       if (uc > 0xFF)
         /* "Inverted question mark" looks enough like 0xFFFD,
            the "Unicode Replacement Character". */
-        uc = (ascii_p ? '#' : 0xBF);
+        uc = (ascii_p ? '#' : '\277');
 
       if (ascii_p)     /* Map Latin1 to the closest ASCII versions. */
         {
index 998fde8325b1b522ee6b64da49d6198099de76c1..d97e8b48bbaab046c2b214007f87e22acae6d73d 100644 (file)
@@ -1,2 +1,2 @@
 static const char screensaver_id[] =
-       "@(#)xscreensaver 5.31 (15-Nov-2014), by Jamie Zawinski (jwz@jwz.org)";
+       "@(#)xscreensaver 5.32 (18-Nov-2014), by Jamie Zawinski (jwz@jwz.org)";
index 4ce7ce1c8ee8cc0a84e7872aba2060a2ed99ac28..ddb00adde6c80cca7fdddba005d4b8c73f0c59c8 100644 (file)
@@ -1,5 +1,5 @@
 %define        name xscreensaver
-%define        version 5.31
+%define        version 5.32
 
 Summary:       X screen saver and locker
 Name:          %{name}
index ac7290ae424a653dd877f33ef80613a17e1513fe..daf533af6b941cbf0b7d960abd92cb5aa8566cdf 100644 (file)
                                "GCC_WARN_64_TO_32_BIT_CONVERSION[arch=*64]" = NO;
                                INFOPLIST_FILE = OSX/iSaverRunner.plist;
                                INSTALL_PATH = "$(HOME)/Applications";
-                               IPHONEOS_DEPLOYMENT_TARGET = 7.0;
                                PRODUCT_NAME = XScreenSaver;
                                PROVISIONING_PROFILE = "";
                                SDKROOT = iphoneos;
                                "GCC_WARN_64_TO_32_BIT_CONVERSION[arch=*64]" = NO;
                                INFOPLIST_FILE = OSX/iSaverRunner.plist;
                                INSTALL_PATH = "$(HOME)/Applications";
-                               IPHONEOS_DEPLOYMENT_TARGET = 7.0;
                                PRODUCT_NAME = XScreenSaver;
                                PROVISIONING_PROFILE = "";
                                SDKROOT = iphoneos;
                                        "HAVE_GETADDRINFO=1",
                                        "HAVE_STRUCT_SOCKADDR_SA_LEN=1",
                                        "HAVE_XUTF8DRAWSTRING=1",
+                                       "HAVE_STDINT_H=1",
                                        "$(GCC_PREPROCESSOR_DEFINITIONS)",
                                );
                                GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
                                        "HAVE_GETADDRINFO=1",
                                        "HAVE_STRUCT_SOCKADDR_SA_LEN=1",
                                        "HAVE_XUTF8DRAWSTRING=1",
+                                       "HAVE_STDINT_H=1",
                                        "$(GCC_PREPROCESSOR_DEFINITIONS)",
                                );
                                GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (