From http://www.jwz.org/xscreensaver/xscreensaver-5.36.tar.gz master2
authorZygo Blaxell <zblaxell@faye.furryterror.org>
Mon, 17 Oct 2016 13:25:55 +0000 (09:25 -0400)
committerZygo Blaxell <zblaxell@faye.furryterror.org>
Mon, 24 Oct 2016 19:29:08 +0000 (15:29 -0400)
-rw-r--r-- 1 zblaxell zblaxell 10600872 Oct 11 14:19 xscreensaver-5.36.tar.gz
0353cbe76cb5e8aa55d0142d8733bf2924772f95  xscreensaver-5.36.tar.gz

135 files changed:
OSX/Makefile
OSX/README
OSX/SaverRunner.h
OSX/SaverRunner.m
OSX/SaverRunner.plist
OSX/Updater.plist
OSX/XScreenSaver.plist
OSX/XScreenSaverConfigSheet.m
OSX/XScreenSaverView.m
OSX/bindist.rtf
OSX/grabclient-ios.m [new file with mode: 0644]
OSX/grabclient-osx.m [new file with mode: 0644]
OSX/iSaverRunner.plist
OSX/installer.sh
OSX/ios-function-table.m
OSX/iosgrabimage.m [deleted file]
OSX/osxgrabscreen.m [deleted file]
OSX/seticon.pl
OSX/textclient-iOS.m [deleted file]
OSX/textclient-ios.m [new file with mode: 0644]
OSX/update-info-plist.pl
OSX/xscreensaver.xcodeproj/project.pbxproj
README
README.hacking
aclocal.m4
android/Makefile
android/README
android/XScreenSaverDaydream.java.in [deleted file]
android/XScreenSaverSettings.java.in [deleted file]
android/grabscreen-android.c [deleted file]
android/project/build.gradle
android/project/gradle/wrapper/gradle-wrapper.jar
android/project/gradle/wrapper/gradle-wrapper.properties
android/project/gradlew
android/project/project.iml [new file with mode: 0644]
android/project/xscreensaver/.idea/compiler.xml [new file with mode: 0644]
android/project/xscreensaver/.idea/gradle.xml [new file with mode: 0644]
android/project/xscreensaver/.idea/misc.xml [new file with mode: 0644]
android/project/xscreensaver/.idea/modules.xml [new file with mode: 0644]
android/project/xscreensaver/.idea/workspace.xml [new file with mode: 0644]
android/project/xscreensaver/build.gradle
android/project/xscreensaver/gradle/wrapper/gradle-wrapper.jar [new file with mode: 0644]
android/project/xscreensaver/gradle/wrapper/gradle-wrapper.properties [new file with mode: 0644]
android/project/xscreensaver/gradlew [new file with mode: 0644]
android/project/xscreensaver/gradlew.bat [new file with mode: 0644]
android/project/xscreensaver/jni/Android.mk
android/project/xscreensaver/jni/xscreensaver [deleted symlink]
android/project/xscreensaver/local.properties [new file with mode: 0644]
android/project/xscreensaver/src/org/jwz/xscreensaver/XScreenSaverDaydream.java
android/project/xscreensaver/src/org/jwz/xscreensaver/XScreenSaverRenderer.java
android/project/xscreensaver/src/org/jwz/xscreensaver/jwxyz.java
android/project/xscreensaver/xscreensaver.iml [new file with mode: 0644]
config.h.in
configure
configure.in
driver/Makefile.in
driver/XScreenSaver.ad.in
driver/XScreenSaver_ad.h
driver/subprocs.c
driver/xscreensaver-getimage.c
driver/xscreensaver-text
hacks/Makefile.in
hacks/analogtv.h
hacks/asm6502.c
hacks/check-configs.pl
hacks/config/README
hacks/config/cubestack.xml [new file with mode: 0644]
hacks/config/cubetwist.xml [new file with mode: 0644]
hacks/config/discoball.xml [new file with mode: 0644]
hacks/config/glplanet.xml
hacks/config/hexstrut.xml [new file with mode: 0644]
hacks/config/photopile.xml
hacks/config/rotzoomer.xml
hacks/config/splodesic.xml [new file with mode: 0644]
hacks/config/starwars.xml
hacks/decayscreen.c
hacks/distort.c
hacks/fontglide.c
hacks/glx/Makefile.in
hacks/glx/bouncingcow.c
hacks/glx/cubestack.c [new file with mode: 0644]
hacks/glx/cubestack.man [new file with mode: 0644]
hacks/glx/cubetwist.c [new file with mode: 0644]
hacks/glx/cubetwist.man [new file with mode: 0644]
hacks/glx/discoball.c [new file with mode: 0644]
hacks/glx/discoball.man [new file with mode: 0644]
hacks/glx/dymaxionmap.c
hacks/glx/extrusion.c
hacks/glx/gleidescope.c
hacks/glx/glplanet.c
hacks/glx/grab-ximage.c
hacks/glx/hexstrut.c [new file with mode: 0644]
hacks/glx/hexstrut.man [new file with mode: 0644]
hacks/glx/hydrostat.c
hacks/glx/lavalite.c
hacks/glx/molecules.sh
hacks/glx/photopile.c
hacks/glx/photopile.man
hacks/glx/polyhedra.c
hacks/glx/pulsar.c
hacks/glx/sonar-icmp.c
hacks/glx/splodesic.c [new file with mode: 0644]
hacks/glx/splodesic.man [new file with mode: 0644]
hacks/glx/starwars.h
hacks/glx/starwars.txt
hacks/glx/texfont.c
hacks/glx/timetunnel.c
hacks/glx/xpm-ximage.c
hacks/images/m6502/greynetic.asm [new file with mode: 0644]
hacks/images/m6502/life.asm [new file with mode: 0644]
hacks/images/m6502/sflake.asm [new file with mode: 0644]
hacks/images/m6502/sierpinski.asm [new file with mode: 0644]
hacks/m6502.sh
hacks/phosphor.c
hacks/rotzoomer.c
hacks/screenhackI.h
hacks/twang.c
jwxyz/Makefile.in
jwxyz/jwxyz-android.c
jwxyz/jwxyz-android.h
jwxyz/jwxyz-cocoa.m
jwxyz/jwxyz-common.c
jwxyz/jwxyz-gl.c
jwxyz/jwxyz.h
jwxyz/jwxyz.m
jwxyz/jwzgles.c
po/POTFILES.in
utils/Makefile.in
utils/grabclient.c
utils/grabscreen.c
utils/textclient-mobile.c
utils/textclient.c
utils/textclient.h
utils/version.h
xscreensaver.spec

index d8664552cbc383e4acc0a6c53de53240bbc6844e..4fd574ca19282a9f7378e31c9fc104d951872116 100644 (file)
@@ -11,8 +11,7 @@ XCODE_APP = /Applications/Xcode.app
 
 TARGETS    = All Savers
 ARCH       = -arch i386 -arch x86_64 ONLY_ACTIVE_ARCH=NO
-CERT       = 'Jamie Zawinski'
-CERT       = 'iPhone Developer: Jamie Zawinski (Y5M82TL69N)'
+CERT      = 'Developer ID Installer: Jamie Zawinski (4627ATJELP)'
 PKGID     = org.jwz.xscreensaver
 THUMBDIR   = build/screenshots
 XCODEBUILD = $(XCODE_APP)/Contents/Developer/usr/bin/xcodebuild
@@ -42,7 +41,6 @@ release:: distdepend
        $(XCODEBUILD) $(ARCH) -target "$(TARGETS)" -configuration Release build
 
 release:: check_versions
-release:: sign
 
 Sparkle.framework:
        unzip ../archive/Sparkle.framework-2013-12-04.zip
@@ -99,12 +97,6 @@ $(THUMBDIR)/%.png:
        fi
 
 
-sign:
-       @for f in build/Release/*.app/Contents/*/*.saver \
-                 build/Release/*.{saver,app} ; do \
-         codesign --deep -vfs $(CERT) $$f ; \
-        done
-
 check_versions:
        @\
   SRC=../utils/version.h ;                                             \
@@ -256,8 +248,9 @@ build/Release/installer.pkg: installer.rtf installer.xml installer.sh installer.
                                                                        \
   DIST="installer.xml" ;                                               \
   STAGE="build/Release/pkg_stage" ;                                    \
-  PKG1="$@" ;                                                          \
-  PKG2="$$STAGE/contents.pkg" ;                                                \
+  FINAL="$@" ;                                                         \
+  UNSIGNED="$$STAGE/contents.pkg" ;                                    \
+  PRODUCT="$$STAGE/product_unsigned.pkg" ;                             \
   SCRIPTS="$$STAGE/scripts" ;                                          \
   RES="$$STAGE/resources" ;                                            \
                                                                        \
@@ -270,14 +263,13 @@ build/Release/installer.pkg: installer.rtf installer.xml installer.sh installer.
   cp -p installer.rtf "$$RES/welcome.rtf" ;                            \
                                                                        \
   pkgbuild --identifier "$(PKGID)" --version "$$V"                     \
-          --scripts "$$SCRIPTS" --nopayload "$$PKG2" ;                 \
-  codesign -vfs $(CERT) "$$PKG2" ;                                     \
-  codesign -vd "$$PKG2" ;                                              \
+          --scripts "$$SCRIPTS" --nopayload "$$UNSIGNED" ;             \
                                                                        \
   productbuild --distribution "$$DIST" --resources "$$RES"             \
-              --package-path "$$STAGE" --version "$$V" "$$PKG1" ;      \
-  codesign -vfs $(CERT) "$$PKG1" ;                                     \
-  codesign -vd "$$PKG1" ;                                              \
+              --package-path "$$STAGE" --version "$$V" "$$PRODUCT" ;   \
+                                                                       \
+  productsign --sign $(CERT) "$$PRODUCT" "$$FINAL" ;                   \
+  spctl --assess --verbose=4 --type install "$$FINAL" ;                        \
                                                                        \
   rm -rf "$$STAGE" ;                                                   \
 
@@ -348,12 +340,24 @@ dmg::
   $(SETICON) -d ../../xdaliclock/OSX/daliclockSaver.icns                     \
                "$$DST/DaliClock.saver" ;                                     \
   $(SETICON) -d XScreenSaverFolder.icns "$$DST" ;                            \
+  $(SETICON) -d XScreenSaver.icns "$$DST"/*.saver ;                          \
+  $(SETICON) -d SaverRunner.icns "$$DST"/*.app ;                             \
   $(SETICON) -d XScreenSaverWebloc.icns "$$STAGE"/*.webloc ;                 \
   $(SETICON) -d XScreenSaverPkg.icns "$$STAGE"/*.pkg ;                       \
   mv "$$STAGE/bindist.webloc" "$$STAGE/Get the iPhone:iPad Version.webloc" ;  \
+                                                                             \
+  set +x ;                                                                   \
+  echo "Checking signatures..." ;                                            \
+  spctl --assess --type install "$$PKG" ;                                    \
+  spctl --assess --type execute "$$SRC/XScreenSaverUpdater.app" ;            \
+  spctl --assess --type execute "$$DST/"*.app ;                                      \
+  spctl --assess --type install "$$DST/"*.saver ;                            \
+  set -x ;                                                                   \
+                                                                             \
   hdiutil makehybrid -quiet -ov -hfs -hfs-volume-name "$$VOLNAME"            \
     -hfs-openfolder "$$STAGE" "$$STAGE" -o "$$TMPDMG" ;                              \
   rm -rf "$$STAGE" ;                                                         \
+                                                                             \
   hdiutil convert -quiet -ov -format UDBZ -imagekey zlib-level=9             \
     "$$TMPDMG" -o "$$DMG" ;                                                  \
   xattr -w com.apple.quarantine "0000;00000000;;" "$$DMG" ;                  \
index 555e8e2585186e9206d7fd7725b121029bc5514b..acf589b2f61c675dc4efafb6747b5a1c6955fb47 100644 (file)
@@ -18,7 +18,7 @@ ridiculously long list of steps!
   3: Delete the dangerball.c and dangerball.xml files from Build Phases.
   4: Delete the "DangerBall copy-Info.plist" file that got created.
   5: Delete the "DangerBall copy-Info.plist" from the Build Settings too.
-  6: Change PRODUCT_NAME in Build Settings (maybe this automatic now?)
+  6: -
   7: Manage Schemes, rename "DangerBall Copy".
   8: Move to the right place in the list.
   9: Scheme / Run / Info: Executable: SaverTester.app.
index bacfd3868a4e9aa53973668e1c12a9f5d09044f7..73b83e9d88a6a6495f6e2d33fec1205c34f8afff 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 2006-2015 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 2006-2016 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
@@ -67,6 +67,8 @@
 @interface SaverRunner : NSObject
 # ifdef USE_IPHONE
   <XScreenSaverViewDelegate>
+# else
+  <NSWindowDelegate>
 # endif
 {
   NSString *saverName;         // the one currently loaded
index ac010b9fa760d1bbb6e0c6ccea8b6ff96086307e..20ddd650fb25ab44473dfd79d0b76e74cb26f8cd 100644 (file)
 
 - (BOOL)shouldAutorotate                       /* Added in iOS 6 */
 {
-  return YES;
+  return
+    NSFoundationVersionNumber < NSFoundationVersionNumber_iOS_8_0 ?
+    ![_saverView suppressRotationAnimation] :
+    YES;
 }
 
 
@@ -1453,6 +1456,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 +1464,7 @@ FAIL:
     [a addObject: win];
     // This prevents clicks from being seen by savers.
     // [win setMovableByWindowBackground:YES];
+    win.releasedWhenClosed = NO;
     [win release];
   }
 # else  // USE_IPHONE
@@ -1596,6 +1601,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
index b3b74991c023158f18aadc443923e484cd5995d5..2384a81d88676b5109a80c8bf1534f8df4a8e2d8 100644 (file)
@@ -7,7 +7,7 @@
        <key>CFBundleExecutable</key>
        <string>${EXECUTABLE_NAME}</string>
        <key>CFBundleGetInfoString</key>
-       <string>5.35</string>
+       <string>5.36</string>
        <key>CFBundleIconFile</key>
        <string>SaverRunner</string>
        <key>CFBundleIdentifier</key>
        <key>CFBundleInfoDictionaryVersion</key>
        <string>6.0</string>
        <key>CFBundleLongVersionString</key>
-       <string>5.35</string>
+       <string>5.36</string>
        <key>CFBundleName</key>
        <string>${PRODUCT_NAME}</string>
        <key>CFBundlePackageType</key>
        <string>APPL</string>
        <key>CFBundleShortVersionString</key>
-       <string>5.35</string>
+       <string>5.36</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>5.35</string>
+       <string>5.36</string>
        <key>LSMinimumSystemVersion</key>
        <string>${MACOSX_DEPLOYMENT_TARGET}</string>
        <key>NSHumanReadableCopyright</key>
-       <string>5.35</string>
+       <string>5.36</string>
        <key>NSMainNibFile</key>
        <string>SaverRunner</string>
        <key>NSPrincipalClass</key>
index 692f7a012ca180f98a876dc9d9e15bb24249fad2..29f7f8d547d87a558c6545c501afd041bd1451da 100644 (file)
@@ -9,7 +9,7 @@
        <key>CFBundleExecutable</key>
        <string>${EXECUTABLE_NAME}</string>
        <key>CFBundleGetInfoString</key>
-       <string>5.35</string>
+       <string>5.36</string>
        <key>CFBundleIconFile</key>
        <string>SaverRunner</string>
        <key>CFBundleIdentifier</key>
        <key>CFBundleInfoDictionaryVersion</key>
        <string>6.0</string>
        <key>CFBundleLongVersionString</key>
-       <string>5.35</string>
+       <string>5.36</string>
        <key>CFBundleName</key>
        <string>${PRODUCT_NAME}</string>
        <key>CFBundlePackageType</key>
        <string>APPL</string>
        <key>CFBundleShortVersionString</key>
-       <string>5.35</string>
+       <string>5.36</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>5.35</string>
+       <string>5.36</string>
        <key>LSMinimumSystemVersion</key>
        <string>${MACOSX_DEPLOYMENT_TARGET}</string>
        <key>LSUIElement</key>
        <true/>
        <key>NSHumanReadableCopyright</key>
-       <string>5.35</string>
+       <string>5.36</string>
        <key>NSMainNibFile</key>
        <string>Updater</string>
        <key>NSPrincipalClass</key>
index 9af74f5fd0cb1bfaa9375e1f381bc967dea6e04e..fc21ef718d74005693d8ebb1b557e44b353cd8e4 100644 (file)
        <key>CFBundlePackageType</key>
        <string>BNDL</string>
        <key>CFBundleShortVersionString</key>
-       <string>5.35</string>
+       <string>5.36</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>5.35</string>
+       <string>5.36</string>
        <key>LSMinimumSystemVersion</key>
-       <string>10.4</string>
+       <string>10.8</string>
        <key>NSMainNibFile</key>
        <string>SaverRunner</string>
        <key>NSPrincipalClass</key>
index 576c8ab3e805f6efe71131c17a6b8dc88ab9a7e7..51c13af4c6ca1fd7842e13469bc63635cef2dff9 100644 (file)
@@ -712,6 +712,11 @@ static void layout_group (NSView *group, BOOL horiz_p);
   // Without the setAppliesImmediately:, when the saver restarts, it's still
   // got the old settings. -[XScreenSaverConfigSheet traverseTree] sets this
   // to NO; default is YES.
+
+  // #### However: I'm told that when these are set to YES, then changes to
+  // 'textLiteral', 'textURL' and 'textProgram' are ignored, but 'textFile'
+  // works.  In StarWars, at least...
+
   [userDefaultsController   setAppliesImmediately:YES];
   [globalDefaultsController setAppliesImmediately:YES];
   [userDefaultsController   commitEditing];
index bc7f21a3e79221f2f682b23082e84994172c0c5d..18f4a1aa1270591b72210a9d1bce3ab1d23e06fa 100644 (file)
 #ifndef  MAC_OS_X_VERSION_10_6
 # define MAC_OS_X_VERSION_10_6 1060  /* undefined in 10.4 SDK, grr */
 #endif
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6  /* 10.6 SDK */
+#ifndef  MAC_OS_X_VERSION_10_12
+# define MAC_OS_X_VERSION_10_12 101200
+#endif
+#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 && \
+     MAC_OS_X_VERSION_MAX_ALLOWED <  MAC_OS_X_VERSION_10_12)
+  /* 10.6 SDK or later, and earlier than 10.12 SDK */
 # import <objc/objc-auto.h>
 # define DO_GC_HACKERY
 #endif
@@ -433,6 +438,11 @@ add_default_options (const XrmOptionDescRec *opts,
   [self setBackgroundColor:[NSColor blackColor]];
 # endif // USE_IPHONE
 
+# ifdef JWXYZ_QUARTZ
+  // Colorspaces and CGContexts only happen with non-GL hacks.
+  colorspace = CGColorSpaceCreateDeviceRGB ();
+# endif
+
   return self;
 }
 
@@ -997,7 +1007,7 @@ gl_check_ver (const struct gl_version *caps,
   gl_texture_target = GL_TEXTURE_2D;
 # endif
 
-  glBindTexture (gl_texture_target, &backbuffer_texture);
+  glBindTexture (gl_texture_target, backbuffer_texture);
   glTexParameteri (gl_texture_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
   // GL_LINEAR might make sense on Retina iPads.
   glTexParameteri (gl_texture_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
@@ -1140,25 +1150,6 @@ to_pow2 (size_t x)
  */
 - (void) createBackbuffer:(CGSize)new_size
 {
-  // Colorspaces and CGContexts only happen with non-GL hacks.
-  if (colorspace)
-    CGColorSpaceRelease (colorspace);
-
-  NSWindow *window = [self window];
-
-  if (window && xdpy) {
-    [self lockFocus];
-
-# ifdef BACKBUFFER_OPENGL
-    // Was apparently faster until 10.9.
-    colorspace = CGColorSpaceCreateDeviceRGB ();
-# endif // BACKBUFFER_OPENGL
-
-    [self unlockFocus];
-  } else {
-    colorspace = CGColorSpaceCreateDeviceRGB();
-  }
-
   CGSize osize = CGSizeZero;
   if (backbuffer) {
     osize.width = CGBitmapContextGetWidth(backbuffer);
@@ -1475,7 +1466,8 @@ to_pow2 (size_t x)
   // landscape shape, swap width and height to keep the backbuffer
   // in portrait.
   //
-  if ([self ignoreRotation] && new_size.width > new_size.height) {
+  double rot = current_device_rotation();
+  if ([self ignoreRotation] && (rot == 90 || rot == -90)) {
     CGFloat swap    = new_size.width;
     new_size.width  = new_size.height;
     new_size.height = swap;
@@ -1486,6 +1478,7 @@ to_pow2 (size_t x)
   new_size.height *= s;
 #  endif // USE_IPHONE
 
+  [self prepareContext];
   [self setViewport];
 
   // On first resize, xwindow->frame is 0x0.
@@ -1493,8 +1486,6 @@ to_pow2 (size_t x)
       xwindow->frame.height == new_size.height)
     return;
 
-  [self prepareContext];
-
 #  if defined(BACKBUFFER_OPENGL) && !defined(USE_IPHONE)
   [ogl_ctx update];
 #  endif // BACKBUFFER_OPENGL && !USE_IPHONE
index a5ea639e104c9a41cd3e8c6a3ddc14981dbbc117..f9cb355bc3c4f71a40a196ec8e15889638b8fdd5 100644 (file)
@@ -16,8 +16,8 @@
 \b0 by Jamie Zawinski\
 and many others\
 \
-version 5.35\
-24-May-2016\
+version 5.36\
+10-Oct-2016\
 \
 {\field{\*\fldinst{HYPERLINK "https://www.jwz.org/xscreensaver/"}}{\fldrslt \cf2 \ul \ulc2 https://www.jwz.org/xscreensaver/}}\
 \pard\pardeftab720
diff --git a/OSX/grabclient-ios.m b/OSX/grabclient-ios.m
new file mode 100644 (file)
index 0000000..e3e4a8e
--- /dev/null
@@ -0,0 +1,128 @@
+/* xscreensaver, Copyright (c) 1992-2016 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
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation.  No representations are made about the suitability of this
+ * software for any purpose.  It is provided "as is" without express or 
+ * implied warranty.
+ */
+
+/* This iOS code to choose and return a random image from the user's
+ * photo gallery.
+ *
+ * Much of the following written by:
+ *
+ *  Created by David Oster on 6/23/12.
+ *  Copyright (c) 2012 Google. All rights reserved.
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+#ifdef USE_IPHONE  // whole file
+
+#import <AssetsLibrary/AssetsLibrary.h>
+#import "grabscreen.h"
+#import "yarandom.h"
+
+/* ALAssetsLibrary is an async API, so we need to fire it off and then
+   call a callback when it's done.  Fortunately, this fits the same
+   interaction model already used in xscreensaver by load_image_async(),
+   so it works out nicely.
+ */
+
+typedef struct {
+  void (*callback) (void *uiimage, const char *fn, int width, int height,
+                    void *closure);
+  void *closure;
+
+  ALAssetsLibrary *library;
+  NSMutableArray *assets;
+
+} ios_loader_data;
+
+
+static void
+ios_random_image_done (ios_loader_data *d, BOOL ok)
+{
+  UIImage *img = 0;
+  const char *fn = 0;
+  NSUInteger n = ok ? [d->assets count] : 0;
+  if (n > 0) {
+    ALAsset *asset = [d->assets objectAtIndex: random() % n];
+    ALAssetRepresentation *rep = [asset defaultRepresentation];
+
+    // "fullScreenImage" returns a smaller image than "fullResolutionImage",
+    // but this function still takes a significant fraction of a second,
+    // causing a visible glitch in e.g. "glslideshow".
+    CGImageRef cgi = [rep fullScreenImage];
+    if (cgi) {
+      UIImageOrientation orient = (UIImageOrientation) 
+        [[asset valueForProperty:ALAssetPropertyOrientation] intValue];
+      img = [UIImage imageWithCGImage: cgi
+                     scale: 1
+                     orientation: orient];
+      if (img)
+        fn = [[[rep filename] stringByDeletingPathExtension]
+               cStringUsingEncoding:NSUTF8StringEncoding];
+    }
+  }
+
+  [d->assets release];
+  [d->library release];
+
+  d->callback (img, fn, [img size].width, [img size].height, d->closure);
+  free (d);
+}
+
+
+void
+ios_load_random_image (void (*callback) (void *uiimage, const char *fn,
+                                         int width, int height,
+                                         void *closure),
+                       void *closure)
+{
+  ios_loader_data *d = (ios_loader_data *) calloc (1, sizeof(*d));
+  d->callback = callback;
+  d->closure = closure;
+
+  d->library = [[[ALAssetsLibrary alloc] init] retain];
+  d->assets = [[NSMutableArray array] retain];
+
+  // The closures passed in here are called later, after we have returned.
+  //
+  [d->library enumerateGroupsWithTypes: ALAssetsGroupAll
+              usingBlock: ^(ALAssetsGroup *group, BOOL *stop) {
+    NSString *name = [group valueForProperty:ALAssetsGroupPropertyName];
+    if ([name length]) {
+      [group enumerateAssetsUsingBlock: ^(ALAsset *asset, NSUInteger index,
+                                          BOOL *stop) {
+        if ([[asset valueForProperty: ALAssetPropertyType]
+              isEqual: ALAssetTypePhoto]) {
+          [d->assets addObject:asset];
+        }
+      }];
+    }
+
+    if (! group) {   // done
+      ios_random_image_done (d, YES);
+    }
+  } failureBlock:^(NSError *error) {
+    // E.g., ALAssetsLibraryErrorDomain: "The user has denied the
+    // application access to their media."
+    NSLog(@"reading Photo Library: %@", error);
+    ios_random_image_done (d, NO);
+  }];
+}
+
+#endif  // USE_IPHONE - whole file
diff --git a/OSX/grabclient-osx.m b/OSX/grabclient-osx.m
new file mode 100644 (file)
index 0000000..a0a949d
--- /dev/null
@@ -0,0 +1,470 @@
+/* xscreensaver, Copyright (c) 1992-2016 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
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation.  No representations are made about the suitability of this
+ * software for any purpose.  It is provided "as is" without express or 
+ * implied warranty.
+ */
+
+/* This is the OSX implementation of desktop-grabbing and image-loading.
+   This code is invoked by "utils/grabclient.c", which is linked directly
+   in to each screen saver bundle.
+
+   X11-based builds of the savers do not use this code (even on MacOS).
+   This is used only by the Cocoa build of the savers.
+ */
+
+#import <stdlib.h>
+#import <stdint.h>
+#ifndef USE_IPHONE
+# import <Cocoa/Cocoa.h>
+#else
+# import "SaverRunner.h"
+#endif
+#import "jwxyz-cocoa.h"
+#import "grabscreen.h"
+#import "colorbars.h"
+#import "resources.h"
+#import "usleep.h"
+
+
+#ifdef USE_IPHONE
+# define NSImage UIImage
+#endif
+
+
+#ifndef  MAC_OS_X_VERSION_10_6
+# define MAC_OS_X_VERSION_10_6 1060  /* undefined in 10.4 SDK, grr */
+#endif
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5
+
+     /* 10.4 code.
+
+        This version of the code works on 10.4, but is flaky.  There is
+        a better way to do it on 10.5 and newer, but taking this path,
+        then we are being compiled against the 10.4 SDK instead of the
+        10.5 SDK, and the newer API is not available to us.
+      */
+
+static void
+copy_framebuffer_to_ximage (CGDirectDisplayID cgdpy, XImage *xim,
+                            int window_x, int window_y)
+{
+  unsigned char *data = (unsigned char *) 
+    CGDisplayAddressForPosition (cgdpy, window_x, window_y);
+  int bpp = CGDisplayBitsPerPixel (cgdpy);
+  int spp = CGDisplaySamplesPerPixel (cgdpy);
+  int bps = CGDisplayBitsPerSample (cgdpy);
+  int bpr = CGDisplayBytesPerRow (cgdpy);
+
+  int y;
+  int ximw = xim->width;
+  int ximh = xim->height;
+
+  uint32_t *odata = (uint32_t *) xim->data;
+
+  switch (bpp) {
+  case 32:
+    if (spp != 3) abort();
+    if (bps != 8) abort();
+    int xwpl = xim->bytes_per_line/4;
+    for (y = 0; y < ximh; y++) {
+      // We can do this because the frame buffer and XImage are both ARGB 32.
+      // Both PPC and Intel use ARGB, viewed in word order (not byte-order).
+      memcpy (odata, data, ximw * 4);
+      odata += xwpl;
+      data += bpr;
+    }
+    break;
+
+  case 16:
+    if (spp != 3) abort();
+    if (bps != 5) abort();
+    for (y = 0; y < ximh; y++) {
+      uint16_t *ip = (uint16_t *) data;
+      int x;
+      for (x = 0; x < ximw; x++) {
+        uint16_t p = *ip++;
+        // This should be ok on both PPC and Intel (ARGB, word order)
+        unsigned char r = (p >> 10) & 0x1F;
+        unsigned char g = (p >>  5) & 0x1F;
+        unsigned char b = (p      ) & 0x1F;
+        r = (r << 3) | (r >> 2);
+        g = (g << 3) | (g >> 2);
+        b = (b << 3) | (b >> 2);
+        uint32_t pixel = 0xFF000000 | (r << 16) | (g << 8) | b;
+        // XPutPixel (xim, x, y, pixel);
+        *odata++ = pixel;
+      }
+      data += bpr;
+    }
+    break;
+
+  case 8:
+    {
+      /* Get the current palette of the display. */
+      CGDirectPaletteRef pal = CGPaletteCreateWithDisplay (cgdpy);
+
+      /* Map it to 32bpp pixels */
+      uint32_t map[256];
+      for (y = 0; y < 256; y++) {
+        CGDeviceColor c = CGPaletteGetColorAtIndex (pal, y);
+        unsigned char r = c.red   * 255.0;
+        unsigned char g = c.green * 255.0;
+        unsigned char b = c.blue  * 255.0;
+        uint32_t pixel = 0xFF000000 | (r << 16) | (g << 8) | b;
+        map[y] = pixel;
+      }
+
+      for (y = 0; y < ximh; y++) {
+        unsigned char *ip = data;
+        int x;
+        for (x = 0; x < ximw; x++) {
+          *odata++ = map[*ip++];
+        }
+        data += bpr;
+      }
+      CGPaletteRelease (pal);
+    }
+    break;
+
+  default:
+    abort();
+    break;
+  }
+}
+
+
+/* Loads an image into the Drawable, returning once the image is loaded.
+ */
+Bool
+osx_grab_desktop_image (Screen *screen, Window xwindow, Drawable drawable,
+                        XRectangle *geom_ret)
+{
+  Display *dpy = DisplayOfScreen (screen);
+  NSView *nsview = jwxyz_window_view (xwindow);
+  NSWindow *nswindow = [nsview window];
+  XWindowAttributes xgwa;
+  int window_x, window_y;
+  Window unused;
+
+  // Figure out where this window is on the screen.
+  //
+  XGetWindowAttributes (dpy, xwindow, &xgwa);
+  XTranslateCoordinates (dpy, xwindow, RootWindowOfScreen (screen), 0, 0, 
+                         &window_x, &window_y, &unused);
+
+  // Use the size of the Drawable, not the Window.
+  {
+    Window r;
+    int x, y;
+    unsigned int w, h, bbw, d;
+    XGetGeometry (dpy, drawable, &r, &x, &y, &w, &h, &bbw, &d);
+    xgwa.width = w;
+    xgwa.height = h;
+  }
+
+  // Create a tmp ximage to hold the screen data.
+  //
+  XImage *xim = XCreateImage (dpy, xgwa.visual, 32, ZPixmap, 0, 0,
+                              xgwa.width, xgwa.height, 8, 0);
+  xim->data = (char *) malloc (xim->height * xim->bytes_per_line);
+
+
+  // Find the address in the frame buffer of the top left of this window.
+  //
+  CGDirectDisplayID cgdpy = 0;
+  {
+    CGPoint p;
+    // #### this isn't quite right for screen 2: it's offset slightly.
+    p.x = window_x;
+    p.y = window_y;
+    CGDisplayCount n;
+    CGGetDisplaysWithPoint (p, 1, &cgdpy, &n);
+    if (!cgdpy) abort();
+  }
+
+  // Paint a transparent "hole" in this window.
+  //
+  BOOL oopaque = [nswindow isOpaque];
+  [nswindow setOpaque:NO];
+
+  [[NSColor clearColor] set];
+  NSRectFill ([nsview frame]);
+  [[nswindow graphicsContext] flushGraphics];
+
+
+  // Without this, we get a dozen black scanlines at the top.
+  // #### But with this, the screen saver loops, because calling this
+  //      seems to implicitly mark the display as non-idle!
+  // CGDisplayCaptureWithOptions (cgdpy, kCGCaptureNoFill);
+
+  // #### So let's try waiting for the vertical blank instead...
+  //      Nope, that doesn't work.
+  //
+  // CGDisplayWaitForBeamPositionOutsideLines (cgdpy, 0,
+  //   window_y + [nswindow frame].size.height);
+
+  // #### Ok, try a busy-wait?
+  //      Nope.
+  //
+
+  // #### Ok, just fuckin' sleep!
+  //
+  usleep (100000);
+
+
+  // Pull the bits out of the frame buffer.
+  //
+  copy_framebuffer_to_ximage (cgdpy, xim, window_x, window_y);
+
+  // CGDisplayRelease (cgdpy);
+
+  // Make the window visible again.
+  //
+  [nswindow setOpaque:oopaque];
+
+  // Splat the XImage onto the target drawable (probably the window)
+  // and free the bits.
+  //
+  XGCValues gcv;
+  GC gc = XCreateGC (dpy, drawable, 0, &gcv);
+  XPutImage (dpy, drawable, gc, xim, 0, 0, 0, 0, xim->width, xim->height);
+  XFreeGC (dpy, gc);
+
+  if (geom_ret) {
+    geom_ret->x = 0;
+    geom_ret->y = 0;
+    geom_ret->width  = xim->width;
+    geom_ret->height = xim->height;
+  }
+
+  XDestroyImage (xim);
+  return True;
+}
+
+
+#elif defined(USE_IPHONE)
+
+       /* What a hack!
+
+           On iOS, our application delegate, SaverRunner, grabs an image
+           of itself as a UIImage before mapping the XScreenSaverView.
+           In this code, we ask SaverRunner for that UIImage, then copy
+           it to the root window.
+         */
+
+Bool
+osx_grab_desktop_image (Screen *screen, Window xwindow, Drawable drawable,
+                        XRectangle *geom_ret)
+{
+  SaverRunner *s = 
+    (SaverRunner *) [[UIApplication sharedApplication] delegate];
+  if (! s)
+    return False;
+  if (! [s isKindOfClass:[SaverRunner class]])
+    return False;
+  UIImage *img = [s screenshot];
+  if (! img)
+    return False;
+  jwxyz_draw_NSImage_or_CGImage (DisplayOfScreen (screen), drawable,
+                                 True, img, geom_ret, 0);
+  return True;
+}
+
+
+#else /* MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
+
+         10.5+ code.
+
+         This version of the code is simpler and more reliable, but
+         uses an API that only exist on 10.5 and newer, so we can only
+         use it if when being compiled against the 10.5 SDK or later.
+       */
+
+/* Loads an image into the Drawable, returning once the image is loaded.
+ */
+Bool
+osx_grab_desktop_image (Screen *screen, Window xwindow, Drawable drawable,
+                        XRectangle *geom_ret)
+{
+  Display *dpy = DisplayOfScreen (screen);
+  NSView *nsview = jwxyz_window_view (xwindow);
+  XWindowAttributes xgwa;
+  int window_x, window_y;
+  Window unused;
+
+  // Figure out where this window is on the screen.
+  //
+  XGetWindowAttributes (dpy, xwindow, &xgwa);
+  XTranslateCoordinates (dpy, xwindow, RootWindowOfScreen (screen), 0, 0, 
+                         &window_x, &window_y, &unused);
+
+  // Grab only the rectangle of the screen underlying this window.
+  //
+  CGRect cgrect;
+  cgrect.origin.x    = window_x;
+  cgrect.origin.y    = window_y;
+  cgrect.size.width  = xgwa.width;
+  cgrect.size.height = xgwa.height;
+
+  /* If a password is required to unlock the screen, a large black
+     window will be on top of all of the desktop windows by the time
+     we reach here, making the screen-grab rather uninteresting.  If
+     we move ourselves temporarily below the login-window windows
+     before capturing the image, we capture the real desktop as
+     intended.
+
+     Oct 2016: Surprise, this trick no longer works on MacOS 10.12.  Sigh.
+   */
+
+  // save our current level so we can restore it later
+  int oldLevel = [[nsview window] level]; 
+
+# if 0
+  {
+    FILE *f = fopen("/tmp/log.txt", "w");
+    CFArrayRef L = CGWindowListCopyWindowInfo (kCGWindowListOptionOnScreenOnly,
+                                               kCGNullWindowID);
+
+    fprintf(f, "# %d\n", [[nsview window] windowNumber]);
+
+    int n = CFArrayGetCount(L);
+    for (int i = 0; i < n; i++) {
+      NSDictionary *dict = (NSDictionary *) CFArrayGetValueAtIndex(L, i);
+      fprintf(f,
+              "%d \"%s\"\n",
+              (int) [dict objectForKey:kCGWindowNumber],
+              [(NSString *) [dict objectForKey:kCGWindowOwnerName]
+                cStringUsingEncoding:[NSString defaultCStringEncoding]]);
+    }
+    fclose(f);
+  }
+#endif
+
+  [[nsview window] setLevel:CGWindowLevelForKey(kCGPopUpMenuWindowLevelKey)];
+
+  // Grab a screen shot of those windows below this one
+  // (hey, X11 can't do that!)
+  //
+  CGImageRef img = 
+    CGWindowListCreateImage (cgrect,
+                             kCGWindowListOptionOnScreenBelowWindow,
+                             [[nsview window] windowNumber],
+                             kCGWindowImageDefault);
+
+  // put us back above the login windows so the screensaver is visible.
+  [[nsview window] setLevel:oldLevel];
+
+  if (! img) return False;
+
+  // Render the grabbed CGImage into the Drawable.
+  jwxyz_draw_NSImage_or_CGImage (DisplayOfScreen (screen), drawable, 
+                                 False, img, geom_ret, 0);
+  CGImageRelease (img);
+  return True;
+}
+
+#endif /* 10.5+ code */
+
+
+# ifndef USE_IPHONE
+
+/* Returns the EXIF rotation property of the image, if any.
+ */
+static int
+exif_rotation (const char *filename)
+{
+  /* As of 10.6, NSImage rotates according to EXIF by default:
+     http://developer.apple.com/mac/library/releasenotes/cocoa/appkit.html
+     So this function should return -1 when *running* on 10.6 systems.
+     But when running against older systems, we need to examine the image
+     to figure out its rotation.
+   */
+
+# if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6  /* 10.6 SDK */
+
+  /* When we have compiled against the 10.6 SDK, we know that we are 
+     running on a 10.6 or later system.
+   */
+  return -1;
+
+# else /* Compiled against 10.5 SDK or earlier */
+
+  /* If this selector exists, then we are running against a 10.6 runtime
+     that does automatic EXIF rotation (despite the fact that we were
+     compiled against the 10.5 or earlier SDK).  So in that case, this
+     function should no-op.
+   */
+  if ([NSImage instancesRespondToSelector:
+                 @selector(initWithDataIgnoringOrientation:)])
+    return -1;
+
+  /* Otherwise, go ahead and figure out what the rotational characteristics
+     of this image are. */
+
+
+
+  /* This is a ridiculous amount of rigamarole to go through, but for some
+     reason the "Orientation" tag does not exist in the "NSImageEXIFData"
+     dictionary inside the NSBitmapImageRep of the NSImage.  Several other
+     EXIF tags are there (e.g., shutter speed) but not orientation.  WTF?
+   */
+  CFStringRef s = CFStringCreateWithCString (NULL, filename, 
+                                             kCFStringEncodingUTF8);
+  CFURLRef url = CFURLCreateWithFileSystemPath (NULL, s, 
+                                                kCFURLPOSIXPathStyle, 0);
+  CGImageSourceRef cgimg = CGImageSourceCreateWithURL (url, NULL);
+  if (! cgimg) return -1;
+
+  NSDictionary *props = (NSDictionary *)
+    CGImageSourceCopyPropertiesAtIndex (cgimg, 0, NULL);
+  int rot = [[props objectForKey:@"Orientation"] intValue];
+  CFRelease (cgimg);
+  CFRelease (url);
+  CFRelease (s);
+  return rot;
+
+# endif /* 10.5 */
+}
+
+# endif /* USE_IPHONE */
+
+
+
+/* Loads an image file and splats it onto the drawable.
+   The image is drawn as large as possible while preserving its aspect ratio.
+   If geom_ret is provided, the actual rectangle the rendered image takes
+   up will be returned there.
+ */
+Bool
+osx_load_image_file (Screen *screen, Window xwindow, Drawable drawable,
+                     const char *filename, XRectangle *geom_ret)
+{
+# ifndef USE_IPHONE
+
+  if (!filename || !*filename) return False;
+
+  NSImage *img = [[NSImage alloc] initWithContentsOfFile:
+                                    [NSString stringWithCString:filename
+                                              encoding:NSUTF8StringEncoding]];
+  if (!img)
+    return False;
+
+  jwxyz_draw_NSImage_or_CGImage (DisplayOfScreen (screen), drawable, 
+                                 True, img, geom_ret,
+                                 exif_rotation (filename));
+  [img release];
+  return True;
+
+# else  /* USE_IPHONE */
+
+  /* This is handled differently: see grabclient.c and grabclient-ios.m. */
+  return False;
+
+# endif /* USE_IPHONE */
+}
index e62769485a2c96fc5bbfbdaea1413861f1887b5c..2f7a19a5216266d27b9fbb1c4844ba11dcdff8fc 100644 (file)
@@ -9,7 +9,7 @@
        <key>CFBundleExecutable</key>
        <string>${EXECUTABLE_NAME}</string>
        <key>CFBundleGetInfoString</key>
-       <string>5.35</string>
+       <string>5.36</string>
        <key>CFBundleIcons</key>
        <dict/>
        <key>CFBundleIcons~ipad</key>
        <key>CFBundleInfoDictionaryVersion</key>
        <string>6.0</string>
        <key>CFBundleLongVersionString</key>
-       <string>5.35</string>
+       <string>5.36</string>
        <key>CFBundleName</key>
        <string>${PRODUCT_NAME}</string>
        <key>CFBundlePackageType</key>
        <string>APPL</string>
        <key>CFBundleShortVersionString</key>
-       <string>5.35</string>
+       <string>5.36</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>5.35</string>
+       <string>5.36</string>
        <key>LSRequiresIPhoneOS</key>
        <true/>
        <key>NSHumanReadableCopyright</key>
-       <string>5.35</string>
+       <string>5.36</string>
        <key>NSMainNibFile</key>
        <string>iSaverRunner</string>
        <key>UIAppFonts</key>
@@ -65,5 +65,6 @@
        </array>
        <key>UIViewControllerBasedStatusBarAppearance</key>
        <false/>
-</dict>
+       <key>NSPhotoLibraryUsageDescription</key>
+       <string>XScreenSaver displays manipulated versions of your photos.</string></dict>
 </plist>
index 05e1b23f36e0e3200a8f4e9f7e6749b8fdf752c4..fa92beb3a962e2ef84cb36da926d478e163aef3e 100755 (executable)
@@ -1,5 +1,5 @@
 #!/bin/sh
-# XScreenSaver, Copyright Â© 2013-2014 Jamie Zawinski <jwz@jwz.org>
+# XScreenSaver, Copyright Â© 2013-2016 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
@@ -67,9 +67,11 @@ DST1="$DSTVOLUME/Library/Screen Savers"
 DST2="$DSTVOLUME/Applications"
 PU="$DSTVOLUME/$HOME/Library/Screen Savers"
 
-# Because of Sparkle.framework weirdness, ".XScreenSaverUpdater.app"
-# is in the DMG, and we remove the leading dot when installing it.
-# Without this, auto-updates won't work right.
+# Because of Sparkle.framework weirdness, "XScreenSaverUpdater.app" is
+# in the DMG as a compressed tar file instead of an app, and we unpack
+# it when installing.  Without this, auto-updates won't work: If there's
+# an .app there, Sparkle thinks that "XScreenSaverUpdater.app" is the
+# thing it should be updating instead of "Install Everything.pkg".
 #
 UPDATER_SRC="XScreenSaver.updater"
 UPDATER_DST="XScreenSaverUpdater.app"
index b66570d0ae2af8091c457273454213d93fa9caab..52b8340d7ef788af03a06ae8cd241f255df7a1dd 100644 (file)
@@ -1,5 +1,5 @@
 /* Generated file, do not edit.
-   Created: Thu May  5 22:34:31 2016 by build-fntable.pl 1.5.
+   Created: Sat Sep  3 00:49:37 2016 by build-fntable.pl 1.5.
  */
 
 #import <Foundation/Foundation.h>
@@ -48,7 +48,9 @@ extern struct xscreensaver_function_table
  crystal_xscreensaver_function_table,
  cube21_xscreensaver_function_table,
  cubenetic_xscreensaver_function_table,
+ cubestack_xscreensaver_function_table,
  cubestorm_xscreensaver_function_table,
+ cubetwist_xscreensaver_function_table,
  cubicgrid_xscreensaver_function_table,
  cwaves_xscreensaver_function_table,
  cynosure_xscreensaver_function_table,
@@ -57,6 +59,7 @@ extern struct xscreensaver_function_table
  deco_xscreensaver_function_table,
  deluxe_xscreensaver_function_table,
  demon_xscreensaver_function_table,
+ discoball_xscreensaver_function_table,
  discrete_xscreensaver_function_table,
  distort_xscreensaver_function_table,
  dnalogo_xscreensaver_function_table,
@@ -103,6 +106,7 @@ extern struct xscreensaver_function_table
  halo_xscreensaver_function_table,
  helix_xscreensaver_function_table,
  hexadrop_xscreensaver_function_table,
+ hexstrut_xscreensaver_function_table,
  hilbert_xscreensaver_function_table,
  hopalong_xscreensaver_function_table,
  hydrostat_xscreensaver_function_table,
@@ -183,6 +187,7 @@ extern struct xscreensaver_function_table
  speedmine_xscreensaver_function_table,
  spheremonics_xscreensaver_function_table,
  splitflap_xscreensaver_function_table,
+ splodesic_xscreensaver_function_table,
  spotlight_xscreensaver_function_table,
  sproingies_xscreensaver_function_table,
  squiral_xscreensaver_function_table,
@@ -274,7 +279,9 @@ NSDictionary *make_function_table_dict(void)
        [NSValue valueWithPointer:&crystal_xscreensaver_function_table], @"crystal",
        [NSValue valueWithPointer:&cube21_xscreensaver_function_table], @"cube21",
        [NSValue valueWithPointer:&cubenetic_xscreensaver_function_table], @"cubenetic",
+       [NSValue valueWithPointer:&cubestack_xscreensaver_function_table], @"cubestack",
        [NSValue valueWithPointer:&cubestorm_xscreensaver_function_table], @"cubestorm",
+       [NSValue valueWithPointer:&cubetwist_xscreensaver_function_table], @"cubetwist",
        [NSValue valueWithPointer:&cubicgrid_xscreensaver_function_table], @"cubicgrid",
        [NSValue valueWithPointer:&cwaves_xscreensaver_function_table], @"cwaves",
        [NSValue valueWithPointer:&cynosure_xscreensaver_function_table], @"cynosure",
@@ -283,6 +290,7 @@ NSDictionary *make_function_table_dict(void)
        [NSValue valueWithPointer:&deco_xscreensaver_function_table], @"deco",
        [NSValue valueWithPointer:&deluxe_xscreensaver_function_table], @"deluxe",
        [NSValue valueWithPointer:&demon_xscreensaver_function_table], @"demon",
+       [NSValue valueWithPointer:&discoball_xscreensaver_function_table], @"discoball",
        [NSValue valueWithPointer:&discrete_xscreensaver_function_table], @"discrete",
        [NSValue valueWithPointer:&distort_xscreensaver_function_table], @"distort",
        [NSValue valueWithPointer:&dnalogo_xscreensaver_function_table], @"dnalogo",
@@ -329,6 +337,7 @@ NSDictionary *make_function_table_dict(void)
        [NSValue valueWithPointer:&halo_xscreensaver_function_table], @"halo",
        [NSValue valueWithPointer:&helix_xscreensaver_function_table], @"helix",
        [NSValue valueWithPointer:&hexadrop_xscreensaver_function_table], @"hexadrop",
+       [NSValue valueWithPointer:&hexstrut_xscreensaver_function_table], @"hexstrut",
        [NSValue valueWithPointer:&hilbert_xscreensaver_function_table], @"hilbert",
        [NSValue valueWithPointer:&hopalong_xscreensaver_function_table], @"hopalong",
        [NSValue valueWithPointer:&hydrostat_xscreensaver_function_table], @"hydrostat",
@@ -409,6 +418,7 @@ NSDictionary *make_function_table_dict(void)
        [NSValue valueWithPointer:&speedmine_xscreensaver_function_table], @"speedmine",
        [NSValue valueWithPointer:&spheremonics_xscreensaver_function_table], @"spheremonics",
        [NSValue valueWithPointer:&splitflap_xscreensaver_function_table], @"splitflap",
+       [NSValue valueWithPointer:&splodesic_xscreensaver_function_table], @"splodesic",
        [NSValue valueWithPointer:&spotlight_xscreensaver_function_table], @"spotlight",
        [NSValue valueWithPointer:&sproingies_xscreensaver_function_table], @"sproingies",
        [NSValue valueWithPointer:&squiral_xscreensaver_function_table], @"squiral",
diff --git a/OSX/iosgrabimage.m b/OSX/iosgrabimage.m
deleted file mode 100644 (file)
index c861d73..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-/* xscreensaver, Copyright (c) 1992-2014 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
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation.  No representations are made about the suitability of this
- * software for any purpose.  It is provided "as is" without express or 
- * implied warranty.
- */
-
-/* This iOS code to choose and return a random image from the user's
- * photo gallery.
- *
- * Much of the following written by:
- *
- *  Created by David Oster on 6/23/12.
- *  Copyright (c) 2012 Google. All rights reserved.
- *  Licensed under the Apache License, Version 2.0 (the "License");
- *  you may not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *       http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-#ifdef USE_IPHONE  // whole file
-
-#import <AssetsLibrary/AssetsLibrary.h>
-#import "grabscreen.h"
-#import "yarandom.h"
-
-/* ALAssetsLibrary is an async API, so we need to fire it off and then
-   call a callback when it's done.  Fortunately, this fits the same
-   interaction model already used in xscreensaver by load_image_async(),
-   so it works out nicely.
- */
-
-typedef struct {
-  void (*callback) (void *uiimage, const char *fn, int width, int height,
-                    void *closure);
-  void *closure;
-
-  ALAssetsLibrary *library;
-  NSMutableArray *assets;
-
-} ios_loader_data;
-
-
-static void
-ios_random_image_done (ios_loader_data *d, BOOL ok)
-{
-  UIImage *img = 0;
-  const char *fn = 0;
-  NSUInteger n = ok ? [d->assets count] : 0;
-  if (n > 0) {
-    ALAsset *asset = [d->assets objectAtIndex: random() % n];
-    ALAssetRepresentation *rep = [asset defaultRepresentation];
-
-    // "fullScreenImage" returns a smaller image than "fullResolutionImage",
-    // but this function still takes a significant fraction of a second,
-    // causing a visible glitch in e.g. "glslideshow".
-    CGImageRef cgi = [rep fullScreenImage];
-    if (cgi) {
-      UIImageOrientation orient = (UIImageOrientation) 
-        [[asset valueForProperty:ALAssetPropertyOrientation] intValue];
-      img = [UIImage imageWithCGImage: cgi
-                     scale: 1
-                     orientation: orient];
-      if (img)
-        fn = [[rep filename] cStringUsingEncoding:NSUTF8StringEncoding];
-    }
-  }
-
-  [d->assets release];
-  [d->library release];
-
-  d->callback (img, fn, [img size].width, [img size].height, d->closure);
-  free (d);
-}
-
-
-void
-ios_load_random_image (void (*callback) (void *uiimage, const char *fn,
-                                         int width, int height,
-                                         void *closure),
-                       void *closure)
-{
-  ios_loader_data *d = (ios_loader_data *) calloc (1, sizeof(*d));
-  d->callback = callback;
-  d->closure = closure;
-
-  d->library = [[[ALAssetsLibrary alloc] init] retain];
-  d->assets = [[NSMutableArray array] retain];
-
-  // The closures passed in here are called later, after we have returned.
-  //
-  [d->library enumerateGroupsWithTypes: ALAssetsGroupAll
-              usingBlock: ^(ALAssetsGroup *group, BOOL *stop) {
-    NSString *name = [group valueForProperty:ALAssetsGroupPropertyName];
-    if ([name length]) {
-      [group enumerateAssetsUsingBlock: ^(ALAsset *asset, NSUInteger index,
-                                          BOOL *stop) {
-        if ([[asset valueForProperty: ALAssetPropertyType]
-              isEqual: ALAssetTypePhoto]) {
-          [d->assets addObject:asset];
-        }
-      }];
-    }
-
-    if (! group) {   // done
-      ios_random_image_done (d, YES);
-    }
-  } failureBlock:^(NSError *error) {
-    // E.g., ALAssetsLibraryErrorDomain: "The user has denied the
-    // application access to their media."
-    NSLog(@"reading Photo Library: %@", error);
-    ios_random_image_done (d, NO);
-  }];
-}
-
-#endif  // USE_IPHONE - whole file
diff --git a/OSX/osxgrabscreen.m b/OSX/osxgrabscreen.m
deleted file mode 100644 (file)
index c7f4f15..0000000
+++ /dev/null
@@ -1,447 +0,0 @@
-/* xscreensaver, Copyright (c) 1992-2012 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
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation.  No representations are made about the suitability of this
- * software for any purpose.  It is provided "as is" without express or 
- * implied warranty.
- */
-
-/* This is the OSX implementation of desktop-grabbing and image-loading.
-   This code is invoked by "utils/grabclient.c", which is linked directly
-   in to each screen saver bundle.
-
-   X11-based builds of the savers do not use this code (even on MacOS).
-   This is used only by the Cocoa build of the savers.
- */
-
-#import <stdlib.h>
-#import <stdint.h>
-#ifndef USE_IPHONE
-# import <Cocoa/Cocoa.h>
-#else
-# import "SaverRunner.h"
-#endif
-#import "jwxyz-cocoa.h"
-#import "grabscreen.h"
-#import "colorbars.h"
-#import "resources.h"
-#import "usleep.h"
-
-
-#ifdef USE_IPHONE
-# define NSImage UIImage
-#endif
-
-
-#ifndef  MAC_OS_X_VERSION_10_6
-# define MAC_OS_X_VERSION_10_6 1060  /* undefined in 10.4 SDK, grr */
-#endif
-
-#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5
-
-     /* 10.4 code.
-
-        This version of the code works on 10.4, but is flaky.  There is
-        a better way to do it on 10.5 and newer, but taking this path,
-        then we are being compiled against the 10.4 SDK instead of the
-        10.5 SDK, and the newer API is not available to us.
-      */
-
-static void
-copy_framebuffer_to_ximage (CGDirectDisplayID cgdpy, XImage *xim,
-                            int window_x, int window_y)
-{
-  unsigned char *data = (unsigned char *) 
-    CGDisplayAddressForPosition (cgdpy, window_x, window_y);
-  int bpp = CGDisplayBitsPerPixel (cgdpy);
-  int spp = CGDisplaySamplesPerPixel (cgdpy);
-  int bps = CGDisplayBitsPerSample (cgdpy);
-  int bpr = CGDisplayBytesPerRow (cgdpy);
-
-  int y;
-  int ximw = xim->width;
-  int ximh = xim->height;
-
-  uint32_t *odata = (uint32_t *) xim->data;
-
-  switch (bpp) {
-  case 32:
-    if (spp != 3) abort();
-    if (bps != 8) abort();
-    int xwpl = xim->bytes_per_line/4;
-    for (y = 0; y < ximh; y++) {
-      // We can do this because the frame buffer and XImage are both ARGB 32.
-      // Both PPC and Intel use ARGB, viewed in word order (not byte-order).
-      memcpy (odata, data, ximw * 4);
-      odata += xwpl;
-      data += bpr;
-    }
-    break;
-
-  case 16:
-    if (spp != 3) abort();
-    if (bps != 5) abort();
-    for (y = 0; y < ximh; y++) {
-      uint16_t *ip = (uint16_t *) data;
-      int x;
-      for (x = 0; x < ximw; x++) {
-        uint16_t p = *ip++;
-        // This should be ok on both PPC and Intel (ARGB, word order)
-        unsigned char r = (p >> 10) & 0x1F;
-        unsigned char g = (p >>  5) & 0x1F;
-        unsigned char b = (p      ) & 0x1F;
-        r = (r << 3) | (r >> 2);
-        g = (g << 3) | (g >> 2);
-        b = (b << 3) | (b >> 2);
-        uint32_t pixel = 0xFF000000 | (r << 16) | (g << 8) | b;
-        // XPutPixel (xim, x, y, pixel);
-        *odata++ = pixel;
-      }
-      data += bpr;
-    }
-    break;
-
-  case 8:
-    {
-      /* Get the current palette of the display. */
-      CGDirectPaletteRef pal = CGPaletteCreateWithDisplay (cgdpy);
-
-      /* Map it to 32bpp pixels */
-      uint32_t map[256];
-      for (y = 0; y < 256; y++) {
-        CGDeviceColor c = CGPaletteGetColorAtIndex (pal, y);
-        unsigned char r = c.red   * 255.0;
-        unsigned char g = c.green * 255.0;
-        unsigned char b = c.blue  * 255.0;
-        uint32_t pixel = 0xFF000000 | (r << 16) | (g << 8) | b;
-        map[y] = pixel;
-      }
-
-      for (y = 0; y < ximh; y++) {
-        unsigned char *ip = data;
-        int x;
-        for (x = 0; x < ximw; x++) {
-          *odata++ = map[*ip++];
-        }
-        data += bpr;
-      }
-      CGPaletteRelease (pal);
-    }
-    break;
-
-  default:
-    abort();
-    break;
-  }
-}
-
-
-/* Loads an image into the Drawable, returning once the image is loaded.
- */
-Bool
-osx_grab_desktop_image (Screen *screen, Window xwindow, Drawable drawable,
-                        XRectangle *geom_ret)
-{
-  Display *dpy = DisplayOfScreen (screen);
-  NSView *nsview = jwxyz_window_view (xwindow);
-  NSWindow *nswindow = [nsview window];
-  XWindowAttributes xgwa;
-  int window_x, window_y;
-  Window unused;
-
-  // Figure out where this window is on the screen.
-  //
-  XGetWindowAttributes (dpy, xwindow, &xgwa);
-  XTranslateCoordinates (dpy, xwindow, RootWindowOfScreen (screen), 0, 0, 
-                         &window_x, &window_y, &unused);
-
-  // Use the size of the Drawable, not the Window.
-  {
-    Window r;
-    int x, y;
-    unsigned int w, h, bbw, d;
-    XGetGeometry (dpy, drawable, &r, &x, &y, &w, &h, &bbw, &d);
-    xgwa.width = w;
-    xgwa.height = h;
-  }
-
-  // Create a tmp ximage to hold the screen data.
-  //
-  XImage *xim = XCreateImage (dpy, xgwa.visual, 32, ZPixmap, 0, 0,
-                              xgwa.width, xgwa.height, 8, 0);
-  xim->data = (char *) malloc (xim->height * xim->bytes_per_line);
-
-
-  // Find the address in the frame buffer of the top left of this window.
-  //
-  CGDirectDisplayID cgdpy = 0;
-  {
-    CGPoint p;
-    // #### this isn't quite right for screen 2: it's offset slightly.
-    p.x = window_x;
-    p.y = window_y;
-    CGDisplayCount n;
-    CGGetDisplaysWithPoint (p, 1, &cgdpy, &n);
-    if (!cgdpy) abort();
-  }
-
-  // Paint a transparent "hole" in this window.
-  //
-  BOOL oopaque = [nswindow isOpaque];
-  [nswindow setOpaque:NO];
-
-  [[NSColor clearColor] set];
-  NSRectFill ([nsview frame]);
-  [[nswindow graphicsContext] flushGraphics];
-
-
-  // Without this, we get a dozen black scanlines at the top.
-  // #### But with this, the screen saver loops, because calling this
-  //      seems to implicitly mark the display as non-idle!
-  // CGDisplayCaptureWithOptions (cgdpy, kCGCaptureNoFill);
-
-  // #### So let's try waiting for the vertical blank instead...
-  //      Nope, that doesn't work.
-  //
-  // CGDisplayWaitForBeamPositionOutsideLines (cgdpy, 0,
-  //   window_y + [nswindow frame].size.height);
-
-  // #### Ok, try a busy-wait?
-  //      Nope.
-  //
-
-  // #### Ok, just fuckin' sleep!
-  //
-  usleep (100000);
-
-
-  // Pull the bits out of the frame buffer.
-  //
-  copy_framebuffer_to_ximage (cgdpy, xim, window_x, window_y);
-
-  // CGDisplayRelease (cgdpy);
-
-  // Make the window visible again.
-  //
-  [nswindow setOpaque:oopaque];
-
-  // Splat the XImage onto the target drawable (probably the window)
-  // and free the bits.
-  //
-  XGCValues gcv;
-  GC gc = XCreateGC (dpy, drawable, 0, &gcv);
-  XPutImage (dpy, drawable, gc, xim, 0, 0, 0, 0, xim->width, xim->height);
-  XFreeGC (dpy, gc);
-
-  if (geom_ret) {
-    geom_ret->x = 0;
-    geom_ret->y = 0;
-    geom_ret->width  = xim->width;
-    geom_ret->height = xim->height;
-  }
-
-  XDestroyImage (xim);
-  return True;
-}
-
-
-#elif defined(USE_IPHONE)
-
-       /* What a hack!
-
-           On iOS, our application delegate, SaverRunner, grabs an image
-           of itself as a UIImage before mapping the XScreenSaverView.
-           In this code, we ask SaverRunner for that UIImage, then copy
-           it to the root window.
-         */
-
-Bool
-osx_grab_desktop_image (Screen *screen, Window xwindow, Drawable drawable,
-                        XRectangle *geom_ret)
-{
-  SaverRunner *s = 
-    (SaverRunner *) [[UIApplication sharedApplication] delegate];
-  if (! s)
-    return False;
-  if (! [s isKindOfClass:[SaverRunner class]])
-    return False;
-  UIImage *img = [s screenshot];
-  if (! img)
-    return False;
-  jwxyz_draw_NSImage_or_CGImage (DisplayOfScreen (screen), drawable,
-                                 True, img, geom_ret, 0);
-  return True;
-}
-
-
-#else /* MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
-
-         10.5+ code.
-
-         This version of the code is simpler and more reliable, but
-         uses an API that only exist on 10.5 and newer, so we can only
-         use it if when being compiled against the 10.5 SDK or later.
-       */
-
-/* Loads an image into the Drawable, returning once the image is loaded.
- */
-Bool
-osx_grab_desktop_image (Screen *screen, Window xwindow, Drawable drawable,
-                        XRectangle *geom_ret)
-{
-  Display *dpy = DisplayOfScreen (screen);
-  NSView *nsview = jwxyz_window_view (xwindow);
-  XWindowAttributes xgwa;
-  int window_x, window_y;
-  Window unused;
-
-  // Figure out where this window is on the screen.
-  //
-  XGetWindowAttributes (dpy, xwindow, &xgwa);
-  XTranslateCoordinates (dpy, xwindow, RootWindowOfScreen (screen), 0, 0, 
-                         &window_x, &window_y, &unused);
-
-  // Grab only the rectangle of the screen underlying this window.
-  //
-  CGRect cgrect;
-  cgrect.origin.x    = window_x;
-  cgrect.origin.y    = window_y;
-  cgrect.size.width  = xgwa.width;
-  cgrect.size.height = xgwa.height;
-
-  /* If a password is required to unlock the screen, a large black
-     window will be on top of all of the desktop windows by the time
-     we reach here, making the screen-grab rather uninteresting.  If
-     we move ourselves temporarily below the login-window windows
-     before capturing the image, we capture the real desktop as
-     intended.
-   */
-
-  // save our current level so we can restore it later
-  int oldLevel = [[nsview window] level]; 
-
-  [[nsview window] setLevel:CGWindowLevelForKey(kCGPopUpMenuWindowLevelKey)];
-
-  // Grab a screen shot of those windows below this one
-  // (hey, X11 can't do that!)
-  //
-  CGImageRef img = 
-    CGWindowListCreateImage (cgrect,
-                             kCGWindowListOptionOnScreenBelowWindow,
-                             [[nsview window] windowNumber],
-                             kCGWindowImageDefault);
-
-  // put us back above the login windows so the screensaver is visible.
-  [[nsview window] setLevel:oldLevel];
-
-  if (! img) return False;
-
-  // Render the grabbed CGImage into the Drawable.
-  jwxyz_draw_NSImage_or_CGImage (DisplayOfScreen (screen), drawable, 
-                                 False, img, geom_ret, 0);
-  CGImageRelease (img);
-  return True;
-}
-
-#endif /* 10.5+ code */
-
-
-# ifndef USE_IPHONE
-
-/* Returns the EXIF rotation property of the image, if any.
- */
-static int
-exif_rotation (const char *filename)
-{
-  /* As of 10.6, NSImage rotates according to EXIF by default:
-     http://developer.apple.com/mac/library/releasenotes/cocoa/appkit.html
-     So this function should return -1 when *running* on 10.6 systems.
-     But when running against older systems, we need to examine the image
-     to figure out its rotation.
-   */
-
-# if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6  /* 10.6 SDK */
-
-  /* When we have compiled against the 10.6 SDK, we know that we are 
-     running on a 10.6 or later system.
-   */
-  return -1;
-
-# else /* Compiled against 10.5 SDK or earlier */
-
-  /* If this selector exists, then we are running against a 10.6 runtime
-     that does automatic EXIF rotation (despite the fact that we were
-     compiled against the 10.5 or earlier SDK).  So in that case, this
-     function should no-op.
-   */
-  if ([NSImage instancesRespondToSelector:
-                 @selector(initWithDataIgnoringOrientation:)])
-    return -1;
-
-  /* Otherwise, go ahead and figure out what the rotational characteristics
-     of this image are. */
-
-
-
-  /* This is a ridiculous amount of rigamarole to go through, but for some
-     reason the "Orientation" tag does not exist in the "NSImageEXIFData"
-     dictionary inside the NSBitmapImageRep of the NSImage.  Several other
-     EXIF tags are there (e.g., shutter speed) but not orientation.  WTF?
-   */
-  CFStringRef s = CFStringCreateWithCString (NULL, filename, 
-                                             kCFStringEncodingUTF8);
-  CFURLRef url = CFURLCreateWithFileSystemPath (NULL, s, 
-                                                kCFURLPOSIXPathStyle, 0);
-  CGImageSourceRef cgimg = CGImageSourceCreateWithURL (url, NULL);
-  if (! cgimg) return -1;
-
-  NSDictionary *props = (NSDictionary *)
-    CGImageSourceCopyPropertiesAtIndex (cgimg, 0, NULL);
-  int rot = [[props objectForKey:@"Orientation"] intValue];
-  CFRelease (cgimg);
-  CFRelease (url);
-  CFRelease (s);
-  return rot;
-
-# endif /* 10.5 */
-}
-
-# endif /* USE_IPHONE */
-
-
-
-/* Loads an image file and splats it onto the drawable.
-   The image is drawn as large as possible while preserving its aspect ratio.
-   If geom_ret is provided, the actual rectangle the rendered image takes
-   up will be returned there.
- */
-Bool
-osx_load_image_file (Screen *screen, Window xwindow, Drawable drawable,
-                     const char *filename, XRectangle *geom_ret)
-{
-# ifndef USE_IPHONE
-
-  if (!filename || !*filename) return False;
-
-  NSImage *img = [[NSImage alloc] initWithContentsOfFile:
-                                    [NSString stringWithCString:filename
-                                              encoding:NSUTF8StringEncoding]];
-  if (!img)
-    return False;
-
-  jwxyz_draw_NSImage_or_CGImage (DisplayOfScreen (screen), drawable, 
-                                 True, img, geom_ret,
-                                 exif_rotation (filename));
-  [img release];
-  return True;
-
-# else  /* USE_IPHONE */
-
-  /* This is handled differently: see grabclient.c and iosgrabimage.m. */
-  return False;
-
-# endif /* USE_IPHONE */
-}
index 69faf687ac3b912f4f47925c524ee4560fcbf0cd..e62bb29145c9c6a0ce3c084eade9f78b6635ff89 100755 (executable)
@@ -1,5 +1,5 @@
 #!/usr/bin/perl -w
-# Copyright Â© 2015 Dave Odell <dmo2118@gmail.com>
+# Copyright Â© 2015-2016 Dave Odell <dmo2118@gmail.com>
 #
 # Permission to use, copy, modify, distribute, and sell this software and its
 # documentation for any purpose is hereby granted without fee, provided that
@@ -18,7 +18,7 @@ use strict;
 use File::Temp;
 
 my $progname = $0; $progname =~ s@.*/@@g;
-my ($version) = ('$Revision: 1.4 $' =~ m/\s(\d[.\d]+)\s/s);
+my ($version) = ('$Revision: 1.5 $' =~ m/\s(\d[.\d]+)\s/s);
 
 my $verbose = 0;
 
@@ -84,18 +84,20 @@ sub usage() {
 }
 
 sub main() {
-  my ($d, $src, $dst);
+  my ($src, @dst);
   while ($#ARGV >= 0) {
     $_ = shift @ARGV;
     if (m/^--?verbose$/s)      { $verbose++; }
     elsif (m/^-v+$/s)          { $verbose += length($_)-1; }
-    elsif (m/^-d$/s)           { $d = 1; }
-    elsif (!defined($src))     { $src = $_; }
-    elsif (!defined($dst))     { $dst = $_; }
-    else { usage; }
+    elsif (m/^-d$/s)           { $src = shift @ARGV; }
+    elsif (m/^-/s)             { usage(); }
+    else { push @dst, $_; }
+  }
+  error ("no source") unless defined($src);
+  error ("no files") unless @dst;
+  foreach my $f (@dst) {
+    set_icon ($src, $f);
   }
-  usage() unless ($d && $src);
-  set_icon ($src, $dst);
 }
 
 main();
diff --git a/OSX/textclient-iOS.m b/OSX/textclient-iOS.m
deleted file mode 100644 (file)
index 7e57291..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-/* xscreensaver, Copyright (c) 2012-2016 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
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation.  No representations are made about the suitability of this
- * software for any purpose.  It is provided "as is" without express or 
- * implied warranty.
- *
- * Loading URLs and returning the underlying text.
- *
- * This is necessary because iOS doesn't have Perl installed, so we can't
- * run "xscreensaver-text" to do this.
- */
-
-#include "utils.h"
-
-#ifdef USE_IPHONE // whole file
-
-#include "textclient.h"
-
-char *
-textclient_mobile_date_string (void)
-{
-  UIDevice *dd = [UIDevice currentDevice];
-  NSString *name = [dd name];                  // My iPhone
-  NSString *model = [dd model];                        // iPad
-  // NSString *system = [dd systemName];       // iPhone OS
-  NSString *vers = [dd systemVersion];         // 5.0
-  NSString *date =
-    [NSDateFormatter
-      localizedStringFromDate:[NSDate date]
-      dateStyle: NSDateFormatterMediumStyle
-      timeStyle: NSDateFormatterMediumStyle];
-  NSString *nl = @"\n";
-
-  NSString *result = name;
-  result = [result stringByAppendingString: nl];
-  result = [result stringByAppendingString: model];
-  // result = [result stringByAppendingString: nl];
-  // result = [result stringByAppendingString: system];
-  result = [result stringByAppendingString: @" "];
-  result = [result stringByAppendingString: vers];
-  result = [result stringByAppendingString: nl];
-  result = [result stringByAppendingString: nl];
-  result = [result stringByAppendingString: date];
-  result = [result stringByAppendingString: nl];
-  result = [result stringByAppendingString: nl];
-  return strdup ([result cStringUsingEncoding:NSISOLatin1StringEncoding]);
-}
-
-
-/* Returns the contents of the URL. */
-char *
-textclient_mobile_url_string (Display *dpy, const char *url)
-{
-  NSURL *nsurl =
-    [NSURL URLWithString:
-             [NSString stringWithCString: url
-                       encoding:NSISOLatin1StringEncoding]];
-  NSString *body =
-    [NSString stringWithContentsOfURL: nsurl
-              encoding: NSUTF8StringEncoding
-              error: nil];
-  return (body
-          ? strdup ([body cStringUsingEncoding:NSUTF8StringEncoding])
-          : 0);
-}
-
-#endif // USE_IPHONE -- whole file
diff --git a/OSX/textclient-ios.m b/OSX/textclient-ios.m
new file mode 100644 (file)
index 0000000..5db5311
--- /dev/null
@@ -0,0 +1,129 @@
+/* xscreensaver, Copyright (c) 2012-2016 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
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation.  No representations are made about the suitability of this
+ * software for any purpose.  It is provided "as is" without express or 
+ * implied warranty.
+ *
+ * Loading URLs and returning the underlying text.
+ *
+ * This is necessary because iOS doesn't have Perl installed, so we can't
+ * run "xscreensaver-text" to do this.
+ */
+
+#include "utils.h"
+
+#ifdef USE_IPHONE // whole file
+
+#include "textclient.h"
+
+char *
+textclient_mobile_date_string (void)
+{
+  UIDevice *dd = [UIDevice currentDevice];
+  NSString *name = [dd name];                  // My iPhone
+  NSString *model = [dd model];                        // iPad
+  // NSString *system = [dd systemName];       // iPhone OS
+  NSString *vers = [dd systemVersion];         // 5.0
+  NSString *date =
+    [NSDateFormatter
+      localizedStringFromDate:[NSDate date]
+      dateStyle: NSDateFormatterMediumStyle
+      timeStyle: NSDateFormatterMediumStyle];
+  NSString *nl = @"\n";
+
+  NSString *result = name;
+  result = [result stringByAppendingString: nl];
+  result = [result stringByAppendingString: model];
+  // result = [result stringByAppendingString: nl];
+  // result = [result stringByAppendingString: system];
+  result = [result stringByAppendingString: @" "];
+  result = [result stringByAppendingString: vers];
+  result = [result stringByAppendingString: nl];
+  result = [result stringByAppendingString: nl];
+  result = [result stringByAppendingString: date];
+  result = [result stringByAppendingString: nl];
+  result = [result stringByAppendingString: nl];
+  return strdup ([result cStringUsingEncoding:NSISOLatin1StringEncoding]);
+}
+
+
+@interface TextLoader : NSObject
+@property (nonatomic, retain) NSURL *url;
+@property (nonatomic, retain) NSString *result;
+@end
+
+@implementation TextLoader
+{
+  NSURL    *_url;
+  NSString *_result;
+}
+
++ (TextLoader *) sharedLoader
+{
+  static TextLoader *singleton = nil;
+  @synchronized(self) {
+    if (!singleton)
+      singleton = [[self alloc] init];
+  }
+  return singleton;
+}
+
+- (void) startLoading
+{
+  // NSLog(@"textclient thread loading %@", self.url);
+  self.result = [NSString stringWithContentsOfURL: self.url
+                          encoding: NSUTF8StringEncoding
+                          error: nil];
+  // NSLog(@"textclient thread finished %@ (length %d)", self.url,
+  //      (unsigned int) [self.result length]);
+}
+
+@end
+
+
+
+/* Returns the contents of the URL.
+   Loads the URL in a background thread: if the URL has not yet loaded,
+   this will return NULL. Once the URL has completely loaded, the full
+   contents will be returned.  Calling this again after that starts the
+   URL loading again.
+ */
+char *
+textclient_mobile_url_string (Display *dpy, const char *url)
+{
+  TextLoader *loader = [TextLoader sharedLoader];
+  NSString *result = [loader result];
+
+  // Since this is a singleton, it's possible that if hack #1 starts
+  // URL #1 loading and then quickly exits, and then hack #2 asks for
+  // URL #2, it might get URL #1 instead.  Oh well, who cares.
+
+  if (result) {                                                // Thread finished
+    // NSLog(@"textclient finished %s (length %d)", url,
+    //       (unsigned int) [result length]);
+    char *s = strdup ([result cStringUsingEncoding:NSUTF8StringEncoding]);
+    loader.url    = nil;
+    loader.result = nil;
+    return s;
+
+  } else if ([loader url]) {                           // Waiting on thread
+    // NSLog(@"textclient waiting...");
+    return 0;
+
+  } else {                                             // Launch thread
+    // NSLog(@"textclient launching %s...", url);
+    loader.url =
+      [NSURL URLWithString:
+               [NSString stringWithCString: url
+                         encoding:NSISOLatin1StringEncoding]];
+    [NSThread detachNewThreadSelector: @selector(startLoading)
+              toTarget: loader withObject: nil];
+    return 0;
+  }
+}
+
+#endif // USE_IPHONE -- whole file
index 2b7968c320cb3b7691e1e5c464f70ee11a349cd6..72040c56924efd9bb9fc1ebfde413b0b5c8d9d6f 100755 (executable)
@@ -27,7 +27,7 @@ use IO::Compress::Gzip qw(gzip $GzipError);
 
 my ($exec_dir, $progname) = ($0 =~ m@^(.*?)/([^/]+)$@);
 
-my ($version) = ('$Revision: 1.45 $' =~ m/\s(\d[.\d]+)\s/s);
+my ($version) = ('$Revision: 1.46 $' =~ m/\s(\d[.\d]+)\s/s);
 
 $ENV{PATH} = "/usr/local/bin:$ENV{PATH}";   # for seticon
 $ENV{PATH} = "/opt/local/bin:$ENV{PATH}";   # for macports wget
@@ -463,7 +463,10 @@ sub update($) {
     }
   }
 
-  set_icon ($app_dir);
+  # MacOS 10.12: codesign says "resource fork, Finder information, or
+  # similar detritus not allowed" if any bundle has an Icon\r file.
+  # set_icon ($app_dir);
+
   set_thumb ($app_dir);
 # enable_gc ($app_dir);
   fix_coretext ($app_dir)
index ae75ecf71a0aad6a1bbba7ab8b01376ace3cfbaa..9e35b4f5578d33efecb3cd8dbe83a4e62b48aed8 100644 (file)
                                AF777A4909B660B500EA3033 /* PBXTargetDependency */,
                                AF777A4709B660B500EA3033 /* PBXTargetDependency */,
                                AF777A4509B660B500EA3033 /* PBXTargetDependency */,
+                               AFEE108A1D15EBF900AAC8F7 /* PBXTargetDependency */,
                                AF777A4309B660B500EA3033 /* PBXTargetDependency */,
+                               AFEE106B1D13424C00AAC8F7 /* PBXTargetDependency */,
                                AF4FF4D70D52CD0D00666F98 /* PBXTargetDependency */,
                                AF777A4109B660B500EA3033 /* PBXTargetDependency */,
+                               AF3938381D0FBF5300205406 /* PBXTargetDependency */,
                                AF777A3F09B660B500EA3033 /* PBXTargetDependency */,
                                AFEC23EB1CB6ED0800DE138F /* PBXTargetDependency */,
                                AF777A3D09B660B500EA3033 /* PBXTargetDependency */,
                                AF777A1D09B660B300EA3033 /* PBXTargetDependency */,
                                AF777A1B09B660B300EA3033 /* PBXTargetDependency */,
                                AF777A1909B660B300EA3033 /* PBXTargetDependency */,
+                               AF1B0FC51D7AB5740011DBE4 /* PBXTargetDependency */,
                                AF4F10F0143450C300E34F3F /* PBXTargetDependency */,
                                AFC0E8C91CDC6125008CAFAC /* PBXTargetDependency */,
                                AF777A1709B660B300EA3033 /* PBXTargetDependency */,
                                AFE2A46F0E2E908E00ADB298 /* PBXTargetDependency */,
                                AF7779EB09B660B000EA3033 /* PBXTargetDependency */,
                                AFCF835C1AF5B683008BB7E1 /* PBXTargetDependency */,
+                               AFEE10A91D17E32100AAC8F7 /* PBXTargetDependency */,
                                AF7779E909B660B000EA3033 /* PBXTargetDependency */,
                                AF7779E709B660B000EA3033 /* PBXTargetDependency */,
                                AF7779E509B660B000EA3033 /* PBXTargetDependency */,
                AF1ADA1A1850186B00932759 /* Sparkle.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = AF1ADA171850180E00932759 /* Sparkle.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
                AF1ADA1B18501B3D00932759 /* SaverRunner.icns in Resources */ = {isa = PBXBuildFile; fileRef = AF2D522513E954A0002AA818 /* SaverRunner.icns */; };
                AF1ADA1F18504A4F00932759 /* ScreenSaver.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF976ED30989BF59001F8B92 /* ScreenSaver.framework */; };
+               AF1B0FAE1D7AB4740011DBE4 /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
+               AF1B0FB01D7AB4740011DBE4 /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
+               AF1B0FB11D7AB4740011DBE4 /* ScreenSaver.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF976ED30989BF59001F8B92 /* ScreenSaver.framework */; };
+               AF1B0FB21D7AB4740011DBE4 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF2C31E515C0F7FE007A6896 /* QuartzCore.framework */; };
+               AF1B0FB31D7AB4740011DBE4 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
+               AF1B0FB41D7AB4740011DBE4 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF48112B0990A2C700FB32B8 /* Carbon.framework */; };
+               AF1B0FB51D7AB4740011DBE4 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE0BC611A6B0D6200C098BF /* OpenGL.framework */; };
+               AF1B0FB61D7AB4740011DBE4 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AF78369617DB9F25003B9FC0 /* libz.dylib */; };
+               AF1B0FC01D7AB5330011DBE4 /* hexstrut.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF1B0FBF1D7AB5210011DBE4 /* hexstrut.xml */; };
+               AF1B0FC11D7AB53A0011DBE4 /* hexstrut.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF1B0FBF1D7AB5210011DBE4 /* hexstrut.xml */; };
+               AF1B0FC21D7AB54D0011DBE4 /* hexstrut.c in Sources */ = {isa = PBXBuildFile; fileRef = AF1B0FBE1D7AB5210011DBE4 /* hexstrut.c */; };
+               AF1B0FC31D7AB5500011DBE4 /* hexstrut.c in Sources */ = {isa = PBXBuildFile; fileRef = AF1B0FBE1D7AB5210011DBE4 /* hexstrut.c */; settings = {COMPILER_FLAGS = "-DUSE_GL"; }; };
                AF1FD713158FF96500C40F17 /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
                AF1FD714158FF96500C40F17 /* ScreenSaver.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF976ED30989BF59001F8B92 /* ScreenSaver.framework */; };
                AF1FD715158FF96500C40F17 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
                AF35EB260E6382BA00691F2F /* jigsaw.c in Sources */ = {isa = PBXBuildFile; fileRef = AF35EB250E6382BA00691F2F /* jigsaw.c */; };
                AF3633FC18530DD90086A439 /* sparkle_dsa_pub.pem in Resources */ = {isa = PBXBuildFile; fileRef = AF3633F918530DD90086A439 /* sparkle_dsa_pub.pem */; };
                AF3633FD18530DD90086A439 /* Updater.m in Sources */ = {isa = PBXBuildFile; fileRef = AF3633FB18530DD90086A439 /* Updater.m */; };
+               AF3938211D0FBD6A00205406 /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
+               AF3938231D0FBD6A00205406 /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
+               AF3938241D0FBD6A00205406 /* ScreenSaver.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF976ED30989BF59001F8B92 /* ScreenSaver.framework */; };
+               AF3938251D0FBD6A00205406 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF2C31E515C0F7FE007A6896 /* QuartzCore.framework */; };
+               AF3938261D0FBD6A00205406 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
+               AF3938271D0FBD6A00205406 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF48112B0990A2C700FB32B8 /* Carbon.framework */; };
+               AF3938281D0FBD6A00205406 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE0BC611A6B0D6200C098BF /* OpenGL.framework */; };
+               AF3938291D0FBD6A00205406 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AF78369617DB9F25003B9FC0 /* libz.dylib */; };
+               AF3938331D0FBF0100205406 /* discoball.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF3938321D0FBEC800205406 /* discoball.xml */; };
+               AF3938341D0FBF1900205406 /* discoball.c in Sources */ = {isa = PBXBuildFile; fileRef = AF3938311D0FBEC800205406 /* discoball.c */; };
+               AF3938351D0FBF1D00205406 /* discoball.c in Sources */ = {isa = PBXBuildFile; fileRef = AF3938311D0FBEC800205406 /* discoball.c */; settings = {COMPILER_FLAGS = "-DUSE_GL"; }; };
+               AF3938361D0FBF2700205406 /* discoball.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF3938321D0FBEC800205406 /* discoball.xml */; };
                AF39483E15A164680000FFCD /* jigsaw.c in Sources */ = {isa = PBXBuildFile; fileRef = AF35EB250E6382BA00691F2F /* jigsaw.c */; settings = {COMPILER_FLAGS = "-DUSE_GL"; }; };
                AF39483F15A1647A0000FFCD /* jigsaw.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFC258CF0988A468000655EE /* jigsaw.xml */; };
                AF39E289198A11F60064A58D /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
                AF4FF4D10D52CC8400666F98 /* cubicgrid.c in Sources */ = {isa = PBXBuildFile; fileRef = AF4FF4D00D52CC8400666F98 /* cubicgrid.c */; };
                AF4FF4D40D52CCAA00666F98 /* cubicgrid.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF4FF4D30D52CCAA00666F98 /* cubicgrid.xml */; };
                AF51FD3915845FCB00E5741F /* SaverRunner.icns in Resources */ = {isa = PBXBuildFile; fileRef = AF2D522513E954A0002AA818 /* SaverRunner.icns */; };
-               AF561DF615969BC3007CA5ED /* iosgrabimage.m in Sources */ = {isa = PBXBuildFile; fileRef = AF561DF515969BC3007CA5ED /* iosgrabimage.m */; };
+               AF561DF615969BC3007CA5ED /* grabclient-ios.m in Sources */ = {isa = PBXBuildFile; fileRef = AF561DF515969BC3007CA5ED /* grabclient-ios.m */; };
                AF561DF815969C5B007CA5ED /* AssetsLibrary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF561DF715969C5B007CA5ED /* AssetsLibrary.framework */; };
+               AF5BEEFD1D2AFE21002E6D51 /* OCRAStd.otf in Resources */ = {isa = PBXBuildFile; fileRef = AFEC68361BD6CA85004C1B64 /* OCRAStd.otf */; };
                AF5C9AFD1A0CCE6E00B0147A /* dangerball.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFC258920988A468000655EE /* dangerball.xml */; };
                AF5C9B001A0CCE6E00B0147A /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
                AF5C9B021A0CCE6E00B0147A /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
                AF9D466D09B5109C006E59CF /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
                AF9D467909B5110B006E59CF /* decayscreen.c in Sources */ = {isa = PBXBuildFile; fileRef = AF9D467809B5110B006E59CF /* decayscreen.c */; };
                AF9D467A09B51126006E59CF /* decayscreen.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFC258930988A468000655EE /* decayscreen.xml */; };
-               AF9D468F09B51567006E59CF /* osxgrabscreen.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9D468E09B51567006E59CF /* osxgrabscreen.m */; };
+               AF9D468F09B51567006E59CF /* grabclient-osx.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9D468E09B51567006E59CF /* grabclient-osx.m */; };
                AF9D473809B52EE0006E59CF /* colorbars.c in Sources */ = {isa = PBXBuildFile; fileRef = AF9D473609B52EE0006E59CF /* colorbars.c */; };
                AF9D473909B52EE0006E59CF /* colorbars.h in Headers */ = {isa = PBXBuildFile; fileRef = AF9D473709B52EE0006E59CF /* colorbars.h */; };
                AF9D474A09B5300A006E59CF /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
                AFC43E7C1C6AA78800C89999 /* OCRAStd.otf in Resources */ = {isa = PBXBuildFile; fileRef = AFEC68361BD6CA85004C1B64 /* OCRAStd.otf */; };
                AFC7592D158D8E8B00C5458E /* textclient.c in Sources */ = {isa = PBXBuildFile; fileRef = AFC7592B158D8E8B00C5458E /* textclient.c */; };
                AFC7592E158D8E8B00C5458E /* textclient.h in Headers */ = {isa = PBXBuildFile; fileRef = AFC7592C158D8E8B00C5458E /* textclient.h */; };
-               AFC75930158D9A7A00C5458E /* textclient-iOS.m in Sources */ = {isa = PBXBuildFile; fileRef = AFC7592F158D9A7A00C5458E /* textclient-iOS.m */; };
+               AFC75930158D9A7A00C5458E /* textclient-ios.m in Sources */ = {isa = PBXBuildFile; fileRef = AFC7592F158D9A7A00C5458E /* textclient-ios.m */; };
                AFCCCBB009BFE4B000353F4D /* rdbomb.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFCCCBAD09BFE4B000353F4D /* rdbomb.xml */; };
                AFCCCBB309BFE51900353F4D /* thornbird.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFC259230988A469000655EE /* thornbird.xml */; };
                AFCF453715986A2100E6E8CC /* dnalogo.c in Sources */ = {isa = PBXBuildFile; fileRef = AF77787609B653DC00EA3033 /* dnalogo.c */; settings = {COMPILER_FLAGS = "-DUSE_GL"; }; };
                AFEC23E91CB6EC7F00DE138F /* dymaxionmap.c in Sources */ = {isa = PBXBuildFile; fileRef = AFEC23E41CB6EBC400DE138F /* dymaxionmap.c */; settings = {COMPILER_FLAGS = "-DUSE_GL"; }; };
                AFEC68371BD6CA85004C1B64 /* OCRAStd.otf in Resources */ = {isa = PBXBuildFile; fileRef = AFEC68361BD6CA85004C1B64 /* OCRAStd.otf */; };
                AFEC68391BD6CDF9004C1B64 /* YearlReg.ttf in Resources */ = {isa = PBXBuildFile; fileRef = AFEC68381BD6CDF9004C1B64 /* YearlReg.ttf */; };
+               AFEE10541D13406000AAC8F7 /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
+               AFEE10561D13406000AAC8F7 /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
+               AFEE10571D13406000AAC8F7 /* ScreenSaver.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF976ED30989BF59001F8B92 /* ScreenSaver.framework */; };
+               AFEE10581D13406000AAC8F7 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF2C31E515C0F7FE007A6896 /* QuartzCore.framework */; };
+               AFEE10591D13406000AAC8F7 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
+               AFEE105A1D13406000AAC8F7 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF48112B0990A2C700FB32B8 /* Carbon.framework */; };
+               AFEE105B1D13406000AAC8F7 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE0BC611A6B0D6200C098BF /* OpenGL.framework */; };
+               AFEE105C1D13406000AAC8F7 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AF78369617DB9F25003B9FC0 /* libz.dylib */; };
+               AFEE10661D1341F600AAC8F7 /* cubetwist.c in Sources */ = {isa = PBXBuildFile; fileRef = AFEE10641D1341E300AAC8F7 /* cubetwist.c */; };
+               AFEE10671D1341FA00AAC8F7 /* cubetwist.c in Sources */ = {isa = PBXBuildFile; fileRef = AFEE10641D1341E300AAC8F7 /* cubetwist.c */; settings = {COMPILER_FLAGS = "-DUSE_GL"; }; };
+               AFEE10681D1341FE00AAC8F7 /* cubetwist.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFEE10651D1341E300AAC8F7 /* cubetwist.xml */; };
+               AFEE10691D13420700AAC8F7 /* cubetwist.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFEE10651D1341E300AAC8F7 /* cubetwist.xml */; };
+               AFEE10731D15EB0800AAC8F7 /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
+               AFEE10751D15EB0800AAC8F7 /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
+               AFEE10761D15EB0800AAC8F7 /* ScreenSaver.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF976ED30989BF59001F8B92 /* ScreenSaver.framework */; };
+               AFEE10771D15EB0800AAC8F7 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF2C31E515C0F7FE007A6896 /* QuartzCore.framework */; };
+               AFEE10781D15EB0800AAC8F7 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
+               AFEE10791D15EB0800AAC8F7 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF48112B0990A2C700FB32B8 /* Carbon.framework */; };
+               AFEE107A1D15EB0800AAC8F7 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE0BC611A6B0D6200C098BF /* OpenGL.framework */; };
+               AFEE107B1D15EB0800AAC8F7 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AF78369617DB9F25003B9FC0 /* libz.dylib */; };
+               AFEE10851D15EBB900AAC8F7 /* cubestack.c in Sources */ = {isa = PBXBuildFile; fileRef = AFEE10831D15EBA600AAC8F7 /* cubestack.c */; settings = {COMPILER_FLAGS = "-DUSE_GL"; }; };
+               AFEE10861D15EBC800AAC8F7 /* cubestack.c in Sources */ = {isa = PBXBuildFile; fileRef = AFEE10831D15EBA600AAC8F7 /* cubestack.c */; };
+               AFEE10871D15EBD900AAC8F7 /* cubestack.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFEE10841D15EBA600AAC8F7 /* cubestack.xml */; };
+               AFEE10881D15EBDC00AAC8F7 /* cubestack.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFEE10841D15EBA600AAC8F7 /* cubestack.xml */; };
+               AFEE10921D17E20B00AAC8F7 /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
+               AFEE10941D17E20B00AAC8F7 /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
+               AFEE10951D17E20B00AAC8F7 /* ScreenSaver.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF976ED30989BF59001F8B92 /* ScreenSaver.framework */; };
+               AFEE10961D17E20B00AAC8F7 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF2C31E515C0F7FE007A6896 /* QuartzCore.framework */; };
+               AFEE10971D17E20B00AAC8F7 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
+               AFEE10981D17E20B00AAC8F7 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF48112B0990A2C700FB32B8 /* Carbon.framework */; };
+               AFEE10991D17E20B00AAC8F7 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE0BC611A6B0D6200C098BF /* OpenGL.framework */; };
+               AFEE109A1D17E20B00AAC8F7 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AF78369617DB9F25003B9FC0 /* libz.dylib */; };
+               AFEE10A41D17E2BA00AAC8F7 /* splodesic.c in Sources */ = {isa = PBXBuildFile; fileRef = AFEE10A21D17E2B300AAC8F7 /* splodesic.c */; settings = {COMPILER_FLAGS = "-DUSE_GL"; }; };
+               AFEE10A51D17E2C500AAC8F7 /* splodesic.c in Sources */ = {isa = PBXBuildFile; fileRef = AFEE10A21D17E2B300AAC8F7 /* splodesic.c */; };
+               AFEE10A61D17E2C900AAC8F7 /* splodesic.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFEE10A31D17E2B300AAC8F7 /* splodesic.xml */; };
+               AFEE10A71D17E2CD00AAC8F7 /* splodesic.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFEE10A31D17E2B300AAC8F7 /* splodesic.xml */; };
                AFF1BA0F19A96D8B0016A88D /* lament_model.c in Sources */ = {isa = PBXBuildFile; fileRef = AFF1BA0E19A96D8B0016A88D /* lament_model.c */; };
                AFF1BA1019A96D8B0016A88D /* lament_model.c in Sources */ = {isa = PBXBuildFile; fileRef = AFF1BA0E19A96D8B0016A88D /* lament_model.c */; settings = {COMPILER_FLAGS = "-DUSE_GL"; }; };
                AFF2868617860E830050A578 /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
                        remoteGlobalIDString = AF1A17610D6D6EE3008AF328;
                        remoteInfo = LCDscrub;
                };
+               AF1B0FA91D7AB4740011DBE4 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF4808C0098C3B6C00FB32B8;
+                       remoteInfo = jwxyz;
+               };
+               AF1B0FC41D7AB5740011DBE4 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF1B0FA71D7AB4740011DBE4;
+                       remoteInfo = Hexstrut;
+               };
                AF32D9E20F3AD0B40080F535 /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
                        remoteGlobalIDString = AF1AD9E118500F9F00932759;
                        remoteInfo = XScreenSaverUpdater;
                };
+               AF39381C1D0FBD6A00205406 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF4808C0098C3B6C00FB32B8;
+                       remoteInfo = jwxyz;
+               };
+               AF3938371D0FBF5300205406 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF39381A1D0FBD6A00205406;
+                       remoteInfo = Discoball;
+               };
                AF39E284198A11F60064A58D /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
                        remoteGlobalIDString = AFEC23CD1CB6EAE100DE138F;
                        remoteInfo = DymaxionMap;
                };
+               AFEE104F1D13406000AAC8F7 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF4808C0098C3B6C00FB32B8;
+                       remoteInfo = jwxyz;
+               };
+               AFEE106A1D13424C00AAC8F7 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AFEE104D1D13406000AAC8F7;
+                       remoteInfo = CubeTwist;
+               };
+               AFEE106E1D15EB0700AAC8F7 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF4808C0098C3B6C00FB32B8;
+                       remoteInfo = jwxyz;
+               };
+               AFEE10891D15EBF900AAC8F7 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AFEE106C1D15EB0700AAC8F7;
+                       remoteInfo = CubeStack;
+               };
+               AFEE108D1D17E20B00AAC8F7 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF4808C0098C3B6C00FB32B8;
+                       remoteInfo = jwxyz;
+               };
+               AFEE10A81D17E32100AAC8F7 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AFEE108B1D17E20B00AAC8F7;
+                       remoteInfo = Splodesic;
+               };
                AFF2868117860E830050A578 /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
                AF1ADA0118500FA100932759 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
                AF1ADA151850157400932759 /* Updater.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = Updater.xib; sourceTree = SOURCE_ROOT; };
                AF1ADA171850180E00932759 /* Sparkle.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Sparkle.framework; sourceTree = "<group>"; };
+               AF1B0FBC1D7AB4740011DBE4 /* Hexstrut.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Hexstrut.saver; sourceTree = BUILT_PRODUCTS_DIR; };
+               AF1B0FBE1D7AB5210011DBE4 /* hexstrut.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = hexstrut.c; path = hacks/glx/hexstrut.c; sourceTree = "<group>"; };
+               AF1B0FBF1D7AB5210011DBE4 /* hexstrut.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = hexstrut.xml; sourceTree = "<group>"; };
                AF241F81107C38DF00046A84 /* dropshadow.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = dropshadow.c; path = hacks/glx/dropshadow.c; sourceTree = "<group>"; };
                AF241F82107C38DF00046A84 /* dropshadow.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; name = dropshadow.h; path = hacks/glx/dropshadow.h; sourceTree = "<group>"; };
                AF2C31E515C0F7FE007A6896 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
                AF3633FA18530DD90086A439 /* Updater.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Updater.h; sourceTree = "<group>"; };
                AF3633FB18530DD90086A439 /* Updater.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Updater.m; sourceTree = "<group>"; };
                AF3633FE18530DFF0086A439 /* Updater.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Updater.plist; sourceTree = "<group>"; };
+               AF39382F1D0FBD6A00205406 /* Discoball.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Discoball.saver; sourceTree = BUILT_PRODUCTS_DIR; };
+               AF3938311D0FBEC800205406 /* discoball.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = discoball.c; path = hacks/glx/discoball.c; sourceTree = "<group>"; };
+               AF3938321D0FBEC800205406 /* discoball.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = discoball.xml; sourceTree = "<group>"; };
                AF39E296198A11F60064A58D /* WindupRobot.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = WindupRobot.saver; sourceTree = BUILT_PRODUCTS_DIR; };
                AF39E2A0198A13F50064A58D /* robot-wireframe.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "robot-wireframe.c"; path = "hacks/glx/robot-wireframe.c"; sourceTree = "<group>"; };
                AF39E2A1198A13F50064A58D /* winduprobot.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = winduprobot.c; path = hacks/glx/winduprobot.c; sourceTree = "<group>"; };
                AF4FF4D30D52CCAA00666F98 /* cubicgrid.xml */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.xml; path = cubicgrid.xml; sourceTree = "<group>"; };
                AF56019B157DAA3D00DB2055 /* iSaverRunner.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = iSaverRunner.xib; sourceTree = "<group>"; };
                AF561DF3159651A7007CA5ED /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.1.sdk/System/Library/Frameworks/AudioToolbox.framework; sourceTree = DEVELOPER_DIR; };
-               AF561DF515969BC3007CA5ED /* iosgrabimage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = iosgrabimage.m; sourceTree = "<group>"; };
+               AF561DF515969BC3007CA5ED /* grabclient-ios.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "grabclient-ios.m"; sourceTree = "<group>"; };
                AF561DF715969C5B007CA5ED /* AssetsLibrary.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AssetsLibrary.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.1.sdk/System/Library/Frameworks/AssetsLibrary.framework; sourceTree = DEVELOPER_DIR; };
                AF5C9B0D1A0CCE6E00B0147A /* Cityflow.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Cityflow.saver; sourceTree = BUILT_PRODUCTS_DIR; };
                AF5C9B0F1A0CCF4E00B0147A /* cityflow.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = cityflow.xml; sourceTree = "<group>"; };
                AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */ = {isa = PBXFileReference; fileEncoding = 5; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = XScreenSaverSubclass.m; sourceTree = "<group>"; };
                AF9D467609B5109C006E59CF /* DecayScreen.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DecayScreen.saver; sourceTree = BUILT_PRODUCTS_DIR; };
                AF9D467809B5110B006E59CF /* decayscreen.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = decayscreen.c; path = hacks/decayscreen.c; sourceTree = "<group>"; };
-               AF9D468E09B51567006E59CF /* osxgrabscreen.m */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.objc; path = osxgrabscreen.m; sourceTree = "<group>"; };
+               AF9D468E09B51567006E59CF /* grabclient-osx.m */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.objc; path = "grabclient-osx.m"; sourceTree = "<group>"; };
                AF9D473609B52EE0006E59CF /* colorbars.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = colorbars.c; path = utils/colorbars.c; sourceTree = "<group>"; };
                AF9D473709B52EE0006E59CF /* colorbars.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; name = colorbars.h; path = utils/colorbars.h; sourceTree = "<group>"; };
                AF9D475409B5300A006E59CF /* SlideScreen.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SlideScreen.saver; sourceTree = BUILT_PRODUCTS_DIR; };
                AFC43E731C68364B00C89999 /* PxPlus_IBM_VGA8.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = PxPlus_IBM_VGA8.ttf; sourceTree = "<group>"; };
                AFC7592B158D8E8B00C5458E /* textclient.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = textclient.c; path = utils/textclient.c; sourceTree = "<group>"; };
                AFC7592C158D8E8B00C5458E /* textclient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = textclient.h; path = utils/textclient.h; sourceTree = "<group>"; };
-               AFC7592F158D9A7A00C5458E /* textclient-iOS.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "textclient-iOS.m"; path = "OSX/textclient-iOS.m"; sourceTree = "<group>"; };
+               AFC7592F158D9A7A00C5458E /* textclient-ios.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "textclient-ios.m"; path = "OSX/textclient-ios.m"; sourceTree = "<group>"; };
                AFCCCBAD09BFE4B000353F4D /* rdbomb.xml */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.xml; path = rdbomb.xml; sourceTree = "<group>"; };
                AFCF83501AF5B515008BB7E1 /* SplitFlap.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SplitFlap.saver; sourceTree = BUILT_PRODUCTS_DIR; };
                AFCF83521AF5B5FD008BB7E1 /* splitflap.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = splitflap.xml; sourceTree = "<group>"; };
                AFE1FD410981E32E00F7970E /* InvertedSlider.h */ = {isa = PBXFileReference; fileEncoding = 12; lastKnownFileType = sourcecode.c.h; path = InvertedSlider.h; sourceTree = "<group>"; };
                AFE1FD420981E32E00F7970E /* InvertedSlider.m */ = {isa = PBXFileReference; fileEncoding = 12; lastKnownFileType = sourcecode.c.objc; path = InvertedSlider.m; sourceTree = "<group>"; };
                AFE1FD430981E32E00F7970E /* jwxyz.h */ = {isa = PBXFileReference; fileEncoding = 12; lastKnownFileType = sourcecode.c.h; name = jwxyz.h; path = ../jwxyz/jwxyz.h; sourceTree = "<group>"; };
-               AFE1FD440981E32E00F7970E /* jwxyz.m */ = {isa = PBXFileReference; fileEncoding = 12; lastKnownFileType = sourcecode.c.objc; path = ../jwxyz/jwxyz.m; sourceTree = "<group>"; };
+               AFE1FD440981E32E00F7970E /* jwxyz.m */ = {isa = PBXFileReference; fileEncoding = 12; lastKnownFileType = sourcecode.c.objc; name = jwxyz.m; path = ../jwxyz/jwxyz.m; sourceTree = "<group>"; };
                AFE1FD470981E32E00F7970E /* PrefsReader.h */ = {isa = PBXFileReference; fileEncoding = 12; lastKnownFileType = sourcecode.c.h; path = PrefsReader.h; sourceTree = "<group>"; };
                AFE1FD480981E32E00F7970E /* PrefsReader.m */ = {isa = PBXFileReference; fileEncoding = 12; lastKnownFileType = sourcecode.c.objc; path = PrefsReader.m; sourceTree = "<group>"; };
                AFE1FD530981E3CB00F7970E /* erase.c */ = {isa = PBXFileReference; fileEncoding = 12; lastKnownFileType = sourcecode.c.c; name = erase.c; path = utils/erase.c; sourceTree = "<group>"; };
                AFEC23E51CB6EBDA00DE138F /* dymaxionmap.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = dymaxionmap.xml; sourceTree = "<group>"; };
                AFEC68361BD6CA85004C1B64 /* OCRAStd.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = OCRAStd.otf; sourceTree = "<group>"; };
                AFEC68381BD6CDF9004C1B64 /* YearlReg.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = YearlReg.ttf; sourceTree = "<group>"; };
+               AFEE10621D13406000AAC8F7 /* CubeTwist.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CubeTwist.saver; sourceTree = BUILT_PRODUCTS_DIR; };
+               AFEE10641D1341E300AAC8F7 /* cubetwist.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = cubetwist.c; path = hacks/glx/cubetwist.c; sourceTree = "<group>"; };
+               AFEE10651D1341E300AAC8F7 /* cubetwist.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = cubetwist.xml; sourceTree = "<group>"; };
+               AFEE10811D15EB0800AAC8F7 /* CubeStack.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CubeStack.saver; sourceTree = BUILT_PRODUCTS_DIR; };
+               AFEE10831D15EBA600AAC8F7 /* cubestack.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = cubestack.c; path = hacks/glx/cubestack.c; sourceTree = "<group>"; };
+               AFEE10841D15EBA600AAC8F7 /* cubestack.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = cubestack.xml; sourceTree = "<group>"; };
+               AFEE10A01D17E20B00AAC8F7 /* Splodesic.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Splodesic.saver; sourceTree = BUILT_PRODUCTS_DIR; };
+               AFEE10A21D17E2B300AAC8F7 /* splodesic.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = splodesic.c; path = hacks/glx/splodesic.c; sourceTree = "<group>"; };
+               AFEE10A31D17E2B300AAC8F7 /* splodesic.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = splodesic.xml; sourceTree = "<group>"; };
                AFF1BA0E19A96D8B0016A88D /* lament_model.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = lament_model.c; path = hacks/glx/lament_model.c; sourceTree = "<group>"; };
                AFF2869217860E830050A578 /* QuasiCrystal.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = QuasiCrystal.saver; sourceTree = BUILT_PRODUCTS_DIR; };
                AFF28694178611720050A578 /* quasicrystal.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = quasicrystal.xml; sourceTree = "<group>"; };
                CE3D01661B76F4C100993C75 /* TestX11.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TestX11.saver; sourceTree = BUILT_PRODUCTS_DIR; };
                CE3D01681B76F83E00993C75 /* testx11.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = testx11.xml; sourceTree = "<group>"; };
                CE3D016A1B76F8E200993C75 /* testx11.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = testx11.c; path = hacks/testx11.c; sourceTree = "<group>"; };
-               CE43C2BE1C055157004C2BC6 /* jwxyz-cocoa.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "../jwxyz/jwxyz-cocoa.m"; sourceTree = "<group>"; };
+               CE43C2BE1C055157004C2BC6 /* jwxyz-cocoa.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "jwxyz-cocoa.m"; path = "../jwxyz/jwxyz-cocoa.m"; sourceTree = "<group>"; };
                CE5564591C25141000645458 /* jwxyz-gl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "jwxyz-gl.c"; path = "../jwxyz/jwxyz-gl.c"; sourceTree = "<group>"; };
-               CE8206741B89048800E35532 /* jwxyz-cocoa.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "../jwxyz/jwxyz-cocoa.h"; sourceTree = "<group>"; };
+               CE8206741B89048800E35532 /* jwxyz-cocoa.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jwxyz-cocoa.h"; path = "../jwxyz/jwxyz-cocoa.h"; sourceTree = "<group>"; };
                CE8C49CC1C011CC400BA2DCF /* jwxyzI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = jwxyzI.h; path = ../jwxyz/jwxyzI.h; sourceTree = "<group>"; };
                CE8EA1C11C35CF10002D1020 /* jwxyz-common.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "jwxyz-common.c"; path = "../jwxyz/jwxyz-common.c"; sourceTree = "<group>"; };
                CE9289D119BD00E200961F22 /* async_netdb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = async_netdb.c; path = utils/async_netdb.c; sourceTree = "<group>"; };
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AF1B0FAF1D7AB4740011DBE4 /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF1B0FB01D7AB4740011DBE4 /* libjwxyz.a in Frameworks */,
+                               AF1B0FB11D7AB4740011DBE4 /* ScreenSaver.framework in Frameworks */,
+                               AF1B0FB21D7AB4740011DBE4 /* QuartzCore.framework in Frameworks */,
+                               AF1B0FB31D7AB4740011DBE4 /* Cocoa.framework in Frameworks */,
+                               AF1B0FB41D7AB4740011DBE4 /* Carbon.framework in Frameworks */,
+                               AF1B0FB51D7AB4740011DBE4 /* OpenGL.framework in Frameworks */,
+                               AF1B0FB61D7AB4740011DBE4 /* libz.dylib in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AF32D9E80F3AD0B40080F535 /* Frameworks */ = {
                        isa = PBXFrameworksBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AF3938221D0FBD6A00205406 /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF3938231D0FBD6A00205406 /* libjwxyz.a in Frameworks */,
+                               AF3938241D0FBD6A00205406 /* ScreenSaver.framework in Frameworks */,
+                               AF3938251D0FBD6A00205406 /* QuartzCore.framework in Frameworks */,
+                               AF3938261D0FBD6A00205406 /* Cocoa.framework in Frameworks */,
+                               AF3938271D0FBD6A00205406 /* Carbon.framework in Frameworks */,
+                               AF3938281D0FBD6A00205406 /* OpenGL.framework in Frameworks */,
+                               AF3938291D0FBD6A00205406 /* libz.dylib in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AF39E28A198A11F60064A58D /* Frameworks */ = {
                        isa = PBXFrameworksBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AFEE10551D13406000AAC8F7 /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFEE10561D13406000AAC8F7 /* libjwxyz.a in Frameworks */,
+                               AFEE10571D13406000AAC8F7 /* ScreenSaver.framework in Frameworks */,
+                               AFEE10581D13406000AAC8F7 /* QuartzCore.framework in Frameworks */,
+                               AFEE10591D13406000AAC8F7 /* Cocoa.framework in Frameworks */,
+                               AFEE105A1D13406000AAC8F7 /* Carbon.framework in Frameworks */,
+                               AFEE105B1D13406000AAC8F7 /* OpenGL.framework in Frameworks */,
+                               AFEE105C1D13406000AAC8F7 /* libz.dylib in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AFEE10741D15EB0800AAC8F7 /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFEE10751D15EB0800AAC8F7 /* libjwxyz.a in Frameworks */,
+                               AFEE10761D15EB0800AAC8F7 /* ScreenSaver.framework in Frameworks */,
+                               AFEE10771D15EB0800AAC8F7 /* QuartzCore.framework in Frameworks */,
+                               AFEE10781D15EB0800AAC8F7 /* Cocoa.framework in Frameworks */,
+                               AFEE10791D15EB0800AAC8F7 /* Carbon.framework in Frameworks */,
+                               AFEE107A1D15EB0800AAC8F7 /* OpenGL.framework in Frameworks */,
+                               AFEE107B1D15EB0800AAC8F7 /* libz.dylib in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AFEE10931D17E20B00AAC8F7 /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFEE10941D17E20B00AAC8F7 /* libjwxyz.a in Frameworks */,
+                               AFEE10951D17E20B00AAC8F7 /* ScreenSaver.framework in Frameworks */,
+                               AFEE10961D17E20B00AAC8F7 /* QuartzCore.framework in Frameworks */,
+                               AFEE10971D17E20B00AAC8F7 /* Cocoa.framework in Frameworks */,
+                               AFEE10981D17E20B00AAC8F7 /* Carbon.framework in Frameworks */,
+                               AFEE10991D17E20B00AAC8F7 /* OpenGL.framework in Frameworks */,
+                               AFEE109A1D17E20B00AAC8F7 /* libz.dylib in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AFF2868717860E830050A578 /* Frameworks */ = {
                        isa = PBXFrameworksBuildPhase;
                        buildActionMask = 2147483647;
                080E96DDFE201D6D7F000001 /* libjwxyz */ = {
                        isa = PBXGroup;
                        children = (
-                               AF561DF515969BC3007CA5ED /* iosgrabimage.m */,
+                               AF561DF515969BC3007CA5ED /* grabclient-ios.m */,
                                AFE1FD410981E32E00F7970E /* InvertedSlider.h */,
                                AFE1FD420981E32E00F7970E /* InvertedSlider.m */,
                                AF2D8F301CEBA10300198014 /* jwxyz-timers.c */,
                                AF6048F8157C07C600CA21E4 /* jwzgles.c */,
                                AF6048F9157C07C600CA21E4 /* jwzgles.h */,
                                AF6048FA157C07C600CA21E4 /* jwzglesI.h */,
-                               AF9D468E09B51567006E59CF /* osxgrabscreen.m */,
+                               AF9D468E09B51567006E59CF /* grabclient-osx.m */,
                                AFE1FD470981E32E00F7970E /* PrefsReader.h */,
                                AFE1FD480981E32E00F7970E /* PrefsReader.m */,
                                32CA4F630368D1EE00C91783 /* xscreensaver_Prefix.pch */,
                                AFACE8881CC83458008B24CD /* EnergyStream.saver */,
                                AFA211A11CD59DAF00C0D2A1 /* RaverHoop.saver */,
                                AFC0E8C01CDC601A008CAFAC /* Hydrostat.saver */,
+                               AF39382F1D0FBD6A00205406 /* Discoball.saver */,
+                               AFEE10621D13406000AAC8F7 /* CubeTwist.saver */,
+                               AFEE10811D15EB0800AAC8F7 /* CubeStack.saver */,
+                               AFEE10A01D17E20B00AAC8F7 /* Splodesic.saver */,
+                               AF1B0FBC1D7AB4740011DBE4 /* Hexstrut.saver */,
                        );
                        name = Products;
                        path = ..;
                                AFA563290993957100F3E977 /* crackberg.c */,
                                AFA563660993970F00F3E977 /* cube21.c */,
                                AFA55D770993589300F3E977 /* cubenetic.c */,
+                               AFEE10831D15EBA600AAC8F7 /* cubestack.c */,
                                AFA55FF309936C4500F3E977 /* cubestorm.c */,
+                               AFEE10641D1341E300AAC8F7 /* cubetwist.c */,
                                AF4FF4D00D52CC8400666F98 /* cubicgrid.c */,
                                AF480DD1098F4F6200FB32B8 /* dangerball.c */,
+                               AF3938311D0FBEC800205406 /* discoball.c */,
                                AF77787609B653DC00EA3033 /* dnalogo.c */,
                                AF0839AA09930C4900277BE9 /* dolphin.c */,
                                AF241F81107C38DF00046A84 /* dropshadow.c */,
                                AF7777E709B64CF700EA3033 /* glslideshow.c */,
                                AFA55C8C099349EE00F3E977 /* glsnake.c */,
                                AFD56E080996A07A00BA26F7 /* gltext.c */,
+                               AF1B0FBE1D7AB5210011DBE4 /* hexstrut.c */,
                                AF78D18A142DD96E002AAF77 /* hilbert.c */,
                                AFC0E8C21CDC60A9008CAFAC /* hydrostat.c */,
                                AFA55F59099362DF00F3E977 /* hypertorus.c */,
                                AFA55D940993590F00F3E977 /* spheremonics.c */,
                                AFCF83541AF5B5FD008BB7E1 /* splitflap.c */,
                                AFCF83531AF5B5FD008BB7E1 /* splitflap_obj.c */,
+                               AFEE10A21D17E2B300AAC8F7 /* splodesic.c */,
                                AFA55A470993351F00F3E977 /* sproingies.c */,
                                AF7778C009B65C0F00EA3033 /* sproingies.h */,
                                AFA55A480993351F00F3E977 /* sproingiewrap.c */,
                                AFC2588D0988A468000655EE /* crystal.xml */,
                                AFC2588E0988A468000655EE /* cube21.xml */,
                                AFC2588F0988A468000655EE /* cubenetic.xml */,
+                               AFEE10841D15EBA600AAC8F7 /* cubestack.xml */,
                                AFC258900988A468000655EE /* cubestorm.xml */,
+                               AFEE10651D1341E300AAC8F7 /* cubetwist.xml */,
                                AF4FF4D30D52CCAA00666F98 /* cubicgrid.xml */,
                                AFF4634B0C44046500EE6509 /* cwaves.xml */,
                                AFC258910988A468000655EE /* cynosure.xml */,
                                AFC258940988A468000655EE /* deco.xml */,
                                AFC258950988A468000655EE /* deluxe.xml */,
                                AFC258960988A468000655EE /* demon.xml */,
+                               AF3938321D0FBEC800205406 /* discoball.xml */,
                                AFC258970988A468000655EE /* discrete.xml */,
                                AFC258980988A468000655EE /* distort.xml */,
                                AF77787909B6545E00EA3033 /* dnalogo.xml */,
                                AFC258C30988A468000655EE /* halo.xml */,
                                AFC258C40988A468000655EE /* helix.xml */,
                                AFB591BC178B81E600EA4005 /* hexadrop.xml */,
+                               AF1B0FBF1D7AB5210011DBE4 /* hexstrut.xml */,
                                AF78D18E142DD99A002AAF77 /* hilbert.xml */,
                                AFC258C50988A468000655EE /* hopalong.xml */,
                                AFC258C60988A468000655EE /* hyperball.xml */,
                                AFC259130988A469000655EE /* spheremonics.xml */,
                                AFC259140988A469000655EE /* spiral.xml */,
                                AFCF83521AF5B5FD008BB7E1 /* splitflap.xml */,
+                               AFEE10A31D17E2B300AAC8F7 /* splodesic.xml */,
                                AFC259150988A469000655EE /* spotlight.xml */,
                                AFC259160988A469000655EE /* sproingies.xml */,
                                AFC259170988A469000655EE /* squiral.xml */,
                                AF77780909B64F4900EA3033 /* texfont.h */,
                                AFC7592B158D8E8B00C5458E /* textclient.c */,
                                AFC7592C158D8E8B00C5458E /* textclient.h */,
-                               AFC7592F158D9A7A00C5458E /* textclient-iOS.m */,
+                               AFC7592F158D9A7A00C5458E /* textclient-ios.m */,
                                AFA211881CD1AA1800C0D2A1 /* textclient-mobile.c */,
                                AFDA11231934424D003D397F /* thread_util.c */,
                                AFDA11241934424D003D397F /* thread_util.h */,
                        productReference = AF1AD9E218500F9F00932759 /* XScreenSaverUpdater.app */;
                        productType = "com.apple.product-type.application";
                };
+               AF1B0FA71D7AB4740011DBE4 /* Hexstrut */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = AF1B0FB91D7AB4740011DBE4 /* Build configuration list for PBXNativeTarget "Hexstrut" */;
+                       buildPhases = (
+                               AF1B0FAA1D7AB4740011DBE4 /* Resources */,
+                               AF1B0FAC1D7AB4740011DBE4 /* Sources */,
+                               AF1B0FAF1D7AB4740011DBE4 /* Frameworks */,
+                               AF1B0FB71D7AB4740011DBE4 /* Rez */,
+                               AF1B0FB81D7AB4740011DBE4 /* Run Update Info Plist */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                               AF1B0FA81D7AB4740011DBE4 /* PBXTargetDependency */,
+                       );
+                       name = Hexstrut;
+                       productName = DangerBall;
+                       productReference = AF1B0FBC1D7AB4740011DBE4 /* Hexstrut.saver */;
+                       productType = "com.apple.product-type.bundle";
+               };
                AF32D9E00F3AD0B40080F535 /* RubikBlocks */ = {
                        isa = PBXNativeTarget;
                        buildConfigurationList = AF32D9F10F3AD0B40080F535 /* Build configuration list for PBXNativeTarget "RubikBlocks" */;
                        productReference = AF35E8A00E63823600691F2F /* Jigsaw.saver */;
                        productType = "com.apple.product-type.bundle";
                };
+               AF39381A1D0FBD6A00205406 /* Discoball */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = AF39382C1D0FBD6A00205406 /* Build configuration list for PBXNativeTarget "Discoball" */;
+                       buildPhases = (
+                               AF39381D1D0FBD6A00205406 /* Resources */,
+                               AF39381F1D0FBD6A00205406 /* Sources */,
+                               AF3938221D0FBD6A00205406 /* Frameworks */,
+                               AF39382A1D0FBD6A00205406 /* Rez */,
+                               AF39382B1D0FBD6A00205406 /* Run Update Info Plist */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                               AF39381B1D0FBD6A00205406 /* PBXTargetDependency */,
+                       );
+                       name = Discoball;
+                       productName = DangerBall;
+                       productReference = AF39382F1D0FBD6A00205406 /* Discoball.saver */;
+                       productType = "com.apple.product-type.bundle";
+               };
                AF39E282198A11F60064A58D /* WindupRobot */ = {
                        isa = PBXNativeTarget;
                        buildConfigurationList = AF39E293198A11F60064A58D /* Build configuration list for PBXNativeTarget "WindupRobot" */;
                        productReference = AFEC23E21CB6EAE100DE138F /* DymaxionMap.saver */;
                        productType = "com.apple.product-type.bundle";
                };
+               AFEE104D1D13406000AAC8F7 /* CubeTwist */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = AFEE105F1D13406000AAC8F7 /* Build configuration list for PBXNativeTarget "CubeTwist" */;
+                       buildPhases = (
+                               AFEE10501D13406000AAC8F7 /* Resources */,
+                               AFEE10521D13406000AAC8F7 /* Sources */,
+                               AFEE10551D13406000AAC8F7 /* Frameworks */,
+                               AFEE105D1D13406000AAC8F7 /* Rez */,
+                               AFEE105E1D13406000AAC8F7 /* Run Update Info Plist */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                               AFEE104E1D13406000AAC8F7 /* PBXTargetDependency */,
+                       );
+                       name = CubeTwist;
+                       productName = DangerBall;
+                       productReference = AFEE10621D13406000AAC8F7 /* CubeTwist.saver */;
+                       productType = "com.apple.product-type.bundle";
+               };
+               AFEE106C1D15EB0700AAC8F7 /* CubeStack */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = AFEE107E1D15EB0800AAC8F7 /* Build configuration list for PBXNativeTarget "CubeStack" */;
+                       buildPhases = (
+                               AFEE106F1D15EB0800AAC8F7 /* Resources */,
+                               AFEE10711D15EB0800AAC8F7 /* Sources */,
+                               AFEE10741D15EB0800AAC8F7 /* Frameworks */,
+                               AFEE107C1D15EB0800AAC8F7 /* Rez */,
+                               AFEE107D1D15EB0800AAC8F7 /* Run Update Info Plist */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                               AFEE106D1D15EB0700AAC8F7 /* PBXTargetDependency */,
+                       );
+                       name = CubeStack;
+                       productName = DangerBall;
+                       productReference = AFEE10811D15EB0800AAC8F7 /* CubeStack.saver */;
+                       productType = "com.apple.product-type.bundle";
+               };
+               AFEE108B1D17E20B00AAC8F7 /* Splodesic */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = AFEE109D1D17E20B00AAC8F7 /* Build configuration list for PBXNativeTarget "Splodesic" */;
+                       buildPhases = (
+                               AFEE108E1D17E20B00AAC8F7 /* Resources */,
+                               AFEE10901D17E20B00AAC8F7 /* Sources */,
+                               AFEE10931D17E20B00AAC8F7 /* Frameworks */,
+                               AFEE109B1D17E20B00AAC8F7 /* Rez */,
+                               AFEE109C1D17E20B00AAC8F7 /* Run Update Info Plist */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                               AFEE108C1D17E20B00AAC8F7 /* PBXTargetDependency */,
+                       );
+                       name = Splodesic;
+                       productName = DangerBall;
+                       productReference = AFEE10A01D17E20B00AAC8F7 /* Splodesic.saver */;
+                       productType = "com.apple.product-type.bundle";
+               };
                AFF2867F17860E830050A578 /* QuasiCrystal */ = {
                        isa = PBXNativeTarget;
                        buildConfigurationList = AFF2868F17860E830050A578 /* Build configuration list for PBXNativeTarget "QuasiCrystal" */;
                29B97313FDCFA39411CA2CEA /* Project object */ = {
                        isa = PBXProject;
                        attributes = {
-                               LastUpgradeCheck = 0730;
+                               LastUpgradeCheck = 0800;
                                TargetAttributes = {
+                                       AF08398F09930B6B00277BE9 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF083A32099311D700277BE9 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF0DC7AB0C4C73F600D76972 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF0DCA420C4CBB0D00D76972 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF137D410F075C9B004DE3B2 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF1A17610D6D6EE3008AF328 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF1AD9E118500F9F00932759 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF1B0FA71D7AB4740011DBE4 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF32D9E00F3AD0B40080F535 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF3581BF1431D47B00E09C51 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF3581FB143330F900E09C51 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF35E88A0E63823600691F2F = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF39381A1D0FBD6A00205406 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF39E282198A11F60064A58D = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF3C71450D624BF50030CC0D = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF46E9CF1CBBA2B300240FBC = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF476FB5099D154F001F091E = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF476FDA099D1686001F091E = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF47704C099D4385001F091E = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF477169099D4786001F091E = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF47717F099D4803001F091E = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF4771A7099D4949001F091E = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF4771DB099D4D9A001F091E = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF4771F2099D4E63001F091E = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF477208099D4EE8001F091E = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF47721E099D4F67001F091E = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF477253099D5717001F091E = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF47726B099D57B9001F091E = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF477283099D5926001F091E = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF477382099D65A1001F091E = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF47739A099D6648001F091E = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF4773C1099D67B9001F091E = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF477401099D69E7001F091E = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF477426099D7C70001F091E = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF477442099D7D33001F091E = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF477483099D89E4001F091E = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF477499099D8A74001F091E = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF4774B4099D8B5F001F091E = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF4774CE099D8BFF001F091E = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF47755D099D9A1A001F091E = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF477583099D9C28001F091E = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF47759F099D9CF7001F091E = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF4775D8099D9F69001F091E = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF4775F2099DA030001F091E = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF477613099DA26C001F091E = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF477644099DA6D0001F091E = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF47765A099DA78E001F091E = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF477670099DA849001F091E = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF47768F099DAA6F001F091E = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF4776AA099DABDD001F091E = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF4776C0099DAC8A001F091E = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF4776DB099DADDF001F091E = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF4776F1099DAE7A001F091E = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF47770D099DAF9F001F091E = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF477723099DB044001F091E = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF477752099DB61E001F091E = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF477774099DB965001F091E = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF477790099DBA90001F091E = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF4777D1099DC183001F091E = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF4778AB099DDB79001F091E = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF4778C7099DDCAE001F091E = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF4778E8099DDDC8001F091E = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF477909099DE379001F091E = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF47792A099DE4C7001F091E = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF4808C0098C3B6C00FB32B8 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF480AAF098C669800FB32B8 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF480C49098E301400FB32B8 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF480D58098EED3D00FB32B8 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF480D59098EED5100FB32B8 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF480D5A098EED5E00FB32B8 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF480D72098EEDDE00FB32B8 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF4810EB09909FBA00FB32B8 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF4812500990CE2700FB32B8 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF4812B30990D3D900FB32B8 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF48DEEF0A0C25E000F94CF9 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF4A3449102A593600A81B2A = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF4FD6E60CE7A486005EE58E = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF4FF4930D52CA0800666F98 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF4FF4BA0D52CBDE00666F98 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF5C9AF91A0CCE6E00B0147A = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF63A7F11AB4EDDB00593C75 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF63F2471C3465BE0033E133 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF63F4501C34682A0033E133 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF63F4781C3469FC0033E133 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF6423F2099FF9C2000F4CD4 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF6425CC09A18855000F4CD4 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF6425EC09A189EC000F4CD4 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF64260F09A18D6C000F4CD4 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF64262C09A18F54000F4CD4 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF64264F09A19229000F4CD4 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF64267B09A194B0000F4CD4 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF64277109A1D37A000F4CD4 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF6427A809A2DE36000F4CD4 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF68A47E19196CF800D41CD1 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF73FF221A09877F00E485E9 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF7510FF1782B5B900380EA1 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF7776E409B63ABF00EA3033 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF77771A09B6416100EA3033 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF77773E09B6446500EA3033 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF77777409B6497800EA3033 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF77778E09B64A5200EA3033 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF7777A809B64B2600EA3033 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF7777D009B64C6B00EA3033 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF7777EA09B64E3100EA3033 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF77781009B6504400EA3033 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF77784409B6528100EA3033 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF77786109B6536000EA3033 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF77787F09B6563500EA3033 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF7778A509B659C800EA3033 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF78D175142DD8F3002AAF77 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF794F64099748450059A8B0 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF794F8E09974A320059A8B0 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF794FCD09974FA60059A8B0 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF7ACFC019FF0A9200BD752B = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
                                        AF918977158FC00A002B5D1E = {
                                                DevelopmentTeam = 4627ATJELP;
                                        };
+                                       AF97572D099C317000B05160 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF975775099C374A00B05160 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF9757C2099C3E6300B05160 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF975808099C41D500B05160 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF975865099C475900B05160 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF975A36099C681F00B05160 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF975A6C099C6AB200B05160 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF975A86099C6BC300B05160 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF975AD7099C6EB100B05160 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF975AFC099C6FE400B05160 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF975C12099C8C1500B05160 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF975C3D099C8DCF00B05160 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF975C5D099C8F3F00B05160 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF975D52099CA0F000B05160 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF976FBB0989CAA2001F8B92 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF9770290989D1E6001F8B92 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF9770660989D2F6001F8B92 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF9771D60989DC4A001F8B92 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF998EDA0A083DB30051049D = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF9D466609B5109C006E59CF = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF9D474409B5300A006E59CF = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF9D475F09B53166006E59CF = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF9D48DB09B53322006E59CF = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF9D48F409B535DA006E59CF = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF9D492B09B53CBA006E59CF = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF9D495409B53FC9006E59CF = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF9D496C09B5411D006E59CF = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF9D499709B544C2006E59CF = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF9D4C6909B59F27006E59CF = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF9D4CE709B5AA8E006E59CF = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF9D4D7E09B5B2DC006E59CF = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF9D4DAF09B5B71E006E59CF = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF9D4DEC09B5BB19006E59CF = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AF9E7EBE190F4C1B00A8B01F = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA2118C1CD59DAF00C0D2A1 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA3392E0B058505002B0E7D = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA33BC60B058740002B0E7D = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA33C020B058E17002B0E7D = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA55946099330B000F3E977 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA5596D0993317900F3E977 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA559920993322100F3E977 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA559B50993328000F3E977 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA559CF0993330600F3E977 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA55A030993340300F3E977 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA55A20099334A000F3E977 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA55A790993364300F3E977 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA55ACF09933CEF00F3E977 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA55B0909933E0500F3E977 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA55B2509933E8D00F3E977 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA55B7909933F7200F3E977 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA55B9109933FDA00F3E977 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA55BAB099340CE00F3E977 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA55BE40993429100F3E977 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA55C0E0993431300F3E977 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA55C77099349A600F3E977 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA55CA909934BB200F3E977 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA55CCC09934CE400F3E977 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA55D3C0993565300F3E977 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA55D620993584B00F3E977 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA55D7F099358C400F3E977 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA55DC809935D7000F3E977 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA55DF009935E4900F3E977 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA55E0D09935EDC00F3E977 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA55E2F09935F8E00F3E977 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA55E4E09935FF900F3E977 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA55EC7099360E300F3E977 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA55F06099361B700F3E977 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA55F2A0993622F00F3E977 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA55F420993629000F3E977 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA55F720993643600F3E977 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA55FD309936BFA00F3E977 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA55FF909936C6D00F3E977 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA5601409936CC800F3E977 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA5603209936D5100F3E977 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA5604A09936E2100F3E977 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA5606209936F3800F3E977 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA560AE0993718D00F3E977 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA560FD0993781600F3E977 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA56119099378CB00F3E977 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA5615609937C0D00F3E977 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA5617B09937CF100F3E977 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA5619D09937D7E00F3E977 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA562060993849F00F3E977 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA5621F0993852500F3E977 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA562BF099392C600F3E977 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA562DA099393C900F3E977 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA562F20993943B00F3E977 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA563130993951000F3E977 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA56331099395ED00F3E977 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA56351099396C000F3E977 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA56379099397B300F3E977 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFA563A4099398BB00F3E977 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFACE8731CC83458008B24CD = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFB591A7178B812C00EA4005 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFBFE74B178642DC00432B21 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                               SystemCapabilities = {
+                                                       com.apple.Sandbox = {
+                                                               enabled = 0;
+                                                       };
+                                               };
+                                       };
+                                       AFBFE767178647FE00432B21 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFC0E8AB1CDC601A008CAFAC = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFCF833B1AF5B515008BB7E1 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFD51B1B0F063B4A00471C02 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFD56DF10996A03800BA26F7 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFD56EAE0996A72600BA26F7 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFD56EDA0996A95700BA26F7 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFD56F0B0996AAFA00BA26F7 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFD56F230996AB8A00BA26F7 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFD56F4F0996AEEE00BA26F7 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFD56F6B0996B01600BA26F7 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFD56F8C0996B09400BA26F7 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFD56FA30996B10F00BA26F7 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFD56FB90996B18F00BA26F7 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFD56FCF0996B20900BA26F7 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFD56FF80996B43800BA26F7 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFD5700F0996B4CC00BA26F7 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFD570260996B56D00BA26F7 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFD570430996B61600BA26F7 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFD570590996B6A300BA26F7 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFD5706F0996B72700BA26F7 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFD570850996B80300BA26F7 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFD5709B0996B88E00BA26F7 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFD570B10996B93000BA26F7 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFD570C90996B9F800BA26F7 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFD570EA0996BBBF00BA26F7 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFD571130996BE9300BA26F7 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFD5712C0996BF2E00BA26F7 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFD571430996C01700BA26F7 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFD571590996C0CE00BA26F7 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFD571B50996D9DC00BA26F7 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFD572220996E4A300BA26F7 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFD5726D0996EE8500BA26F7 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFD572A50996F99600BA26F7 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFD572C20996FC0F00BA26F7 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFD572F9099701C000BA26F7 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFD5735D0997411200BA26F7 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFDA658E178A52B70070D24B = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFE2A4560E2E904600ADB298 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFE30BE80E52B14700CCF4A5 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFE6A1820CDD7B2E002805BF = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFE6A41B0CDD7FAA002805BF = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFEC23CD1CB6EAE100DE138F = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFEE104D1D13406000AAC8F7 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFEE106C1D15EB0700AAC8F7 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFEE108B1D17E20B00AAC8F7 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFF2867F17860E830050A578 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFF3C9E817CCAC440028F240 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFF463360C4403E400EE6509 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFF463580C440AEF00EE6509 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       AFFAB31519158CE40020F021 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
+                                       CE3D01511B76F4C100993C75 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
                                };
                        };
                        buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "xscreensaver" */;
                                AFA563130993951000F3E977 /* Crackberg */,
                                AFA56351099396C000F3E977 /* Cube21 */,
                                AFA55D620993584B00F3E977 /* Cubenetic */,
+                               AFEE106C1D15EB0700AAC8F7 /* CubeStack */,
                                AFA55FD309936BFA00F3E977 /* CubeStorm */,
+                               AFEE104D1D13406000AAC8F7 /* CubeTwist */,
                                AF4FF4BA0D52CBDE00666F98 /* CubicGrid */,
                                AF4810EB09909FBA00FB32B8 /* DangerBall */,
+                               AF39381A1D0FBD6A00205406 /* Discoball */,
                                AF77786109B6536000EA3033 /* DNAlogo */,
                                AFEC23CD1CB6EAE100DE138F /* DymaxionMap */,
                                AFACE8731CC83458008B24CD /* EnergyStream */,
                                AF7777D009B64C6B00EA3033 /* GLSlideshow */,
                                AFA55C77099349A600F3E977 /* GLSnake */,
                                AFD56DF10996A03800BA26F7 /* GLText */,
+                               AF1B0FA71D7AB4740011DBE4 /* Hexstrut */,
                                AF78D175142DD8F3002AAF77 /* Hilbert */,
                                AFC0E8AB1CDC601A008CAFAC /* Hydrostat */,
                                AFA55F420993629000F3E977 /* Hypertorus */,
                                AFE30BE80E52B14700CCF4A5 /* Sonar */,
                                AFA55D7F099358C400F3E977 /* Spheremonics */,
                                AFCF833B1AF5B515008BB7E1 /* SplitFlap */,
+                               AFEE108B1D17E20B00AAC8F7 /* Splodesic */,
                                AFA55A20099334A000F3E977 /* Sproingies */,
                                AFA55A030993340300F3E977 /* Stairs */,
                                AF77781009B6504400EA3033 /* StarWars */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AF1B0FAA1D7AB4740011DBE4 /* Resources */ = {
+                       isa = PBXResourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF1B0FC11D7AB53A0011DBE4 /* hexstrut.xml in Resources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AF32D9E30F3AD0B40080F535 /* Resources */ = {
                        isa = PBXResourcesBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AF39381D1D0FBD6A00205406 /* Resources */ = {
+                       isa = PBXResourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF3938331D0FBF0100205406 /* discoball.xml in Resources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AF39E285198A11F60064A58D /* Resources */ = {
                        isa = PBXResourcesBuildPhase;
                        buildActionMask = 2147483647;
                                AF918ABF158FC53D002B5D1E /* atunnel.xml in Resources */,
                                AF918AC0158FC53D002B5D1E /* barcode.xml in Resources */,
                                AF73FF3D1A0988C500E485E9 /* binaryring.xml in Resources */,
+                               AFEE10681D1341FE00AAC8F7 /* cubetwist.xml in Resources */,
                                AF918AC1158FC53D002B5D1E /* blaster.xml in Resources */,
                                AF918AC2158FC53D002B5D1E /* blinkbox.xml in Resources */,
                                AF918AC3158FC53D002B5D1E /* blitspin.xml in Resources */,
                                AF918ADA158FC53D002B5D1E /* crystal.xml in Resources */,
                                AF918ADB158FC53D002B5D1E /* cube21.xml in Resources */,
                                AF918ADC158FC53D002B5D1E /* cubenetic.xml in Resources */,
+                               AFEE10881D15EBDC00AAC8F7 /* cubestack.xml in Resources */,
                                AF918ADD158FC53D002B5D1E /* cubestorm.xml in Resources */,
                                AF918ADE158FC53D002B5D1E /* cubicgrid.xml in Resources */,
                                AF918ADF158FC53D002B5D1E /* cwaves.xml in Resources */,
                                AF918AE4158FC53D002B5D1E /* deluxe.xml in Resources */,
                                AF918AE5158FC53D002B5D1E /* demon.xml in Resources */,
                                AF918AE6158FC53D002B5D1E /* discrete.xml in Resources */,
+                               AF3938361D0FBF2700205406 /* discoball.xml in Resources */,
                                AF918AE7158FC53D002B5D1E /* distort.xml in Resources */,
                                AFCF453815986A3000E6E8CC /* dnalogo.xml in Resources */,
                                AFEC23E81CB6EC6800DE138F /* dymaxionmap.xml in Resources */,
                                AF918B12158FC53D002B5D1E /* halo.xml in Resources */,
                                AF918B13158FC53D002B5D1E /* helix.xml in Resources */,
                                AFB591BF178B81E600EA4005 /* hexadrop.xml in Resources */,
+                               AF1B0FC01D7AB5330011DBE4 /* hexstrut.xml in Resources */,
                                AF918B14158FC53D002B5D1E /* hilbert.xml in Resources */,
                                AF918B15158FC53D002B5D1E /* hopalong.xml in Resources */,
                                AFC0E8C71CDC60DE008CAFAC /* hydrostat.xml in Resources */,
                                AF918B1F158FC53D002B5D1E /* jigglypuff.xml in Resources */,
                                AF39483F15A1647A0000FFCD /* jigsaw.xml in Resources */,
                                AF918B22158FC53D002B5D1E /* juggler3d.xml in Resources */,
-                               AF918B23158FC53D002B5D1E /* julia.xml in Resources */,
                                AFB8A69C1782BF6C004EDB85 /* kaleidocycle.xml in Resources */,
+                               AF918B23158FC53D002B5D1E /* julia.xml in Resources */,
                                AF918B24158FC53D002B5D1E /* kaleidescope.xml in Resources */,
                                AF918B25158FC53D002B5D1E /* klein.xml in Resources */,
                                AF918B26158FC53D002B5D1E /* kumppa.xml in Resources */,
                                AF918B67158FC53E002B5D1E /* speedmine.xml in Resources */,
                                AF918B69158FC53E002B5D1E /* spheremonics.xml in Resources */,
                                AFCF83561AF5B5FD008BB7E1 /* splitflap.xml in Resources */,
+                               AFEE10A71D17E2CD00AAC8F7 /* splodesic.xml in Resources */,
                                AF918B6B158FC53E002B5D1E /* spotlight.xml in Resources */,
                                AF918B6C158FC53E002B5D1E /* sproingies.xml in Resources */,
                                AF918B6D158FC53E002B5D1E /* squiral.xml in Resources */,
                        files = (
                                AFD51B200F063B4A00471C02 /* xscreensaver-getimage-file in Resources */,
                                AFD51DB90F063BE700471C02 /* photopile.xml in Resources */,
+                               AF5BEEFD1D2AFE21002E6D51 /* OCRAStd.otf in Resources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AFEE10501D13406000AAC8F7 /* Resources */ = {
+                       isa = PBXResourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFEE10691D13420700AAC8F7 /* cubetwist.xml in Resources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AFEE106F1D15EB0800AAC8F7 /* Resources */ = {
+                       isa = PBXResourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFEE10871D15EBD900AAC8F7 /* cubestack.xml in Resources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AFEE108E1D17E20B00AAC8F7 /* Resources */ = {
+                       isa = PBXResourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFEE10A61D17E2C900AAC8F7 /* splodesic.xml in Resources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AFF2868217860E830050A578 /* Resources */ = {
                        isa = PBXResourcesBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AF1B0FB71D7AB4740011DBE4 /* Rez */ = {
+                       isa = PBXRezBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AF32D9EF0F3AD0B40080F535 /* Rez */ = {
                        isa = PBXRezBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AF39382A1D0FBD6A00205406 /* Rez */ = {
+                       isa = PBXRezBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AF39E291198A11F60064A58D /* Rez */ = {
                        isa = PBXRezBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AFEE105D1D13406000AAC8F7 /* Rez */ = {
+                       isa = PBXRezBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AFEE107C1D15EB0800AAC8F7 /* Rez */ = {
+                       isa = PBXRezBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AFEE109B1D17E20B00AAC8F7 /* Rez */ = {
+                       isa = PBXRezBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AFF2868D17860E830050A578 /* Rez */ = {
                        isa = PBXRezBuildPhase;
                        buildActionMask = 2147483647;
                        shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX";
                        showEnvVarsInLog = 0;
                };
+               AF1B0FB81D7AB4740011DBE4 /* Run Update Info Plist */ = {
+                       isa = PBXShellScriptBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       inputPaths = (
+                       );
+                       name = "Run Update Info Plist";
+                       outputPaths = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+                       shellPath = /bin/sh;
+                       shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX";
+                       showEnvVarsInLog = 0;
+               };
                AF32D9F00F3AD0B40080F535 /* Run Update Info Plist */ = {
                        isa = PBXShellScriptBuildPhase;
                        buildActionMask = 2147483647;
                        shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX";
                        showEnvVarsInLog = 0;
                };
+               AF39382B1D0FBD6A00205406 /* Run Update Info Plist */ = {
+                       isa = PBXShellScriptBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       inputPaths = (
+                       );
+                       name = "Run Update Info Plist";
+                       outputPaths = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+                       shellPath = /bin/sh;
+                       shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX";
+                       showEnvVarsInLog = 0;
+               };
                AF39E292198A11F60064A58D /* Run Update Info Plist */ = {
                        isa = PBXShellScriptBuildPhase;
                        buildActionMask = 2147483647;
                        shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX";
                        showEnvVarsInLog = 0;
                };
+               AFEE105E1D13406000AAC8F7 /* Run Update Info Plist */ = {
+                       isa = PBXShellScriptBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       inputPaths = (
+                       );
+                       name = "Run Update Info Plist";
+                       outputPaths = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+                       shellPath = /bin/sh;
+                       shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX";
+                       showEnvVarsInLog = 0;
+               };
+               AFEE107D1D15EB0800AAC8F7 /* Run Update Info Plist */ = {
+                       isa = PBXShellScriptBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       inputPaths = (
+                       );
+                       name = "Run Update Info Plist";
+                       outputPaths = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+                       shellPath = /bin/sh;
+                       shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX";
+                       showEnvVarsInLog = 0;
+               };
+               AFEE109C1D17E20B00AAC8F7 /* Run Update Info Plist */ = {
+                       isa = PBXShellScriptBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       inputPaths = (
+                       );
+                       name = "Run Update Info Plist";
+                       outputPaths = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+                       shellPath = /bin/sh;
+                       shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX";
+                       showEnvVarsInLog = 0;
+               };
                AFF2868E17860E830050A578 /* Run Update Info Plist */ = {
                        isa = PBXShellScriptBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AF1B0FAC1D7AB4740011DBE4 /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF1B0FC21D7AB54D0011DBE4 /* hexstrut.c in Sources */,
+                               AF1B0FAE1D7AB4740011DBE4 /* XScreenSaverSubclass.m in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AF32D9E50F3AD0B40080F535 /* Sources */ = {
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AF39381F1D0FBD6A00205406 /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF3938211D0FBD6A00205406 /* XScreenSaverSubclass.m in Sources */,
+                               AF3938341D0FBF1900205406 /* discoball.c in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AF39E287198A11F60064A58D /* Sources */ = {
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
                                CE8EA1C21C35CF10002D1020 /* jwxyz-common.c in Sources */,
                                AF4774E8099D8D8C001F091E /* logo.c in Sources */,
                                AF4775C0099D9E79001F091E /* resources.c in Sources */,
-                               AF9D468F09B51567006E59CF /* osxgrabscreen.m in Sources */,
+                               AF9D468F09B51567006E59CF /* grabclient-osx.m in Sources */,
                                AF9D473809B52EE0006E59CF /* colorbars.c in Sources */,
                                AF77783409B6516900EA3033 /* grab-ximage.c in Sources */,
                                AF77783709B6518400EA3033 /* texfont.c in Sources */,
                                AFAD462309D5F4DA00AB5F95 /* grabclient.c in Sources */,
                                AF6048FB157C07C600CA21E4 /* jwzgles.c in Sources */,
                                AFC7592D158D8E8B00C5458E /* textclient.c in Sources */,
-                               AFC75930158D9A7A00C5458E /* textclient-iOS.m in Sources */,
-                               AF561DF615969BC3007CA5ED /* iosgrabimage.m in Sources */,
+                               AFC75930158D9A7A00C5458E /* textclient-ios.m in Sources */,
+                               AF561DF615969BC3007CA5ED /* grabclient-ios.m in Sources */,
                                CE9289D319BD00E300961F22 /* async_netdb.c in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                                AF918A35158FC3BB002B5D1E /* bubble3d.c in Sources */,
                                AF918A36158FC3BB002B5D1E /* buildlwo.c in Sources */,
                                AF918A37158FC3BB002B5D1E /* cage.c in Sources */,
+                               AF3938351D0FBF1D00205406 /* discoball.c in Sources */,
                                AF918A38158FC3BB002B5D1E /* carousel.c in Sources */,
                                AF918A39158FC3BB002B5D1E /* chessmodels.c in Sources */,
                                AF918A3A158FC3BB002B5D1E /* circuit.c in Sources */,
                                AF918A41158FC3BB002B5D1E /* crackberg.c in Sources */,
                                AF918A42158FC3BB002B5D1E /* cube21.c in Sources */,
                                AF918A43158FC3BB002B5D1E /* cubenetic.c in Sources */,
+                               AFEE10851D15EBB900AAC8F7 /* cubestack.c in Sources */,
                                AF918A44158FC3BB002B5D1E /* cubestorm.c in Sources */,
+                               AFEE10671D1341FA00AAC8F7 /* cubetwist.c in Sources */,
                                AF918A45158FC3BB002B5D1E /* cubicgrid.c in Sources */,
                                AF918A46158FC3BB002B5D1E /* dangerball.c in Sources */,
                                AFCF453715986A2100E6E8CC /* dnalogo.c in Sources */,
                                AF918A67158FC3E5002B5D1E /* glslideshow.c in Sources */,
                                AF918A68158FC3E5002B5D1E /* glsnake.c in Sources */,
                                AF918A69158FC3E5002B5D1E /* gltext.c in Sources */,
+                               AF1B0FC31D7AB5500011DBE4 /* hexstrut.c in Sources */,
                                AF918A6A158FC3E5002B5D1E /* hilbert.c in Sources */,
                                AFC0E8C41CDC60B0008CAFAC /* hydrostat.c in Sources */,
                                AF918A6B158FC3E5002B5D1E /* hypertorus.c in Sources */,
                                AF918A96158FC417002B5D1E /* spheremonics.c in Sources */,
                                AFCF835A1AF5B5FD008BB7E1 /* splitflap.c in Sources */,
                                AFCF83581AF5B5FD008BB7E1 /* splitflap_obj.c in Sources */,
+                               AFEE10A41D17E2BA00AAC8F7 /* splodesic.c in Sources */,
                                AF918A97158FC473002B5D1E /* sproingies.c in Sources */,
                                AF918A98158FC473002B5D1E /* sproingiewrap.c in Sources */,
                                AF918A99158FC473002B5D1E /* stairs.c in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AFEE10521D13406000AAC8F7 /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFEE10661D1341F600AAC8F7 /* cubetwist.c in Sources */,
+                               AFEE10541D13406000AAC8F7 /* XScreenSaverSubclass.m in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AFEE10711D15EB0800AAC8F7 /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFEE10731D15EB0800AAC8F7 /* XScreenSaverSubclass.m in Sources */,
+                               AFEE10861D15EBC800AAC8F7 /* cubestack.c in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AFEE10901D17E20B00AAC8F7 /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFEE10A51D17E2C500AAC8F7 /* splodesic.c in Sources */,
+                               AFEE10921D17E20B00AAC8F7 /* XScreenSaverSubclass.m in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AFF2868417860E830050A578 /* Sources */ = {
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
                        target = AF1A17610D6D6EE3008AF328 /* LCDscrub */;
                        targetProxy = AF1A17830D6D6FA7008AF328 /* PBXContainerItemProxy */;
                };
+               AF1B0FA81D7AB4740011DBE4 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
+                       targetProxy = AF1B0FA91D7AB4740011DBE4 /* PBXContainerItemProxy */;
+               };
+               AF1B0FC51D7AB5740011DBE4 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF1B0FA71D7AB4740011DBE4 /* Hexstrut */;
+                       targetProxy = AF1B0FC41D7AB5740011DBE4 /* PBXContainerItemProxy */;
+               };
                AF32D9E10F3AD0B40080F535 /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
                        target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
                        target = AF1AD9E118500F9F00932759 /* XScreenSaverUpdater */;
                        targetProxy = AF36340018540D050086A439 /* PBXContainerItemProxy */;
                };
+               AF39381B1D0FBD6A00205406 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
+                       targetProxy = AF39381C1D0FBD6A00205406 /* PBXContainerItemProxy */;
+               };
+               AF3938381D0FBF5300205406 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF39381A1D0FBD6A00205406 /* Discoball */;
+                       targetProxy = AF3938371D0FBF5300205406 /* PBXContainerItemProxy */;
+               };
                AF39E283198A11F60064A58D /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
                        target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
                        target = AFEC23CD1CB6EAE100DE138F /* DymaxionMap */;
                        targetProxy = AFEC23EA1CB6ED0800DE138F /* PBXContainerItemProxy */;
                };
+               AFEE104E1D13406000AAC8F7 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
+                       targetProxy = AFEE104F1D13406000AAC8F7 /* PBXContainerItemProxy */;
+               };
+               AFEE106B1D13424C00AAC8F7 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AFEE104D1D13406000AAC8F7 /* CubeTwist */;
+                       targetProxy = AFEE106A1D13424C00AAC8F7 /* PBXContainerItemProxy */;
+               };
+               AFEE106D1D15EB0700AAC8F7 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
+                       targetProxy = AFEE106E1D15EB0700AAC8F7 /* PBXContainerItemProxy */;
+               };
+               AFEE108A1D15EBF900AAC8F7 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AFEE106C1D15EB0700AAC8F7 /* CubeStack */;
+                       targetProxy = AFEE10891D15EBF900AAC8F7 /* PBXContainerItemProxy */;
+               };
+               AFEE108C1D17E20B00AAC8F7 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
+                       targetProxy = AFEE108D1D17E20B00AAC8F7 /* PBXContainerItemProxy */;
+               };
+               AFEE10A91D17E32100AAC8F7 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AFEE108B1D17E20B00AAC8F7 /* Splodesic */;
+                       targetProxy = AFEE10A81D17E32100AAC8F7 /* PBXContainerItemProxy */;
+               };
                AFF2868017860E830050A578 /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
                        target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
                        };
                        name = Release;
                };
+               AF1B0FBA1D7AB4740011DBE4 /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Debug;
+               };
+               AF1B0FBB1D7AB4740011DBE4 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Release;
+               };
                AF32D9F20F3AD0B40080F535 /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
                        };
                        name = Release;
                };
+               AF39382D1D0FBD6A00205406 /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Debug;
+               };
+               AF39382E1D0FBD6A00205406 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Release;
+               };
                AF39E294198A11F60064A58D /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
                        };
                        name = Release;
                };
+               AFEE10601D13406000AAC8F7 /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Debug;
+               };
+               AFEE10611D13406000AAC8F7 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Release;
+               };
+               AFEE107F1D15EB0800AAC8F7 /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Debug;
+               };
+               AFEE10801D15EB0800AAC8F7 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Release;
+               };
+               AFEE109E1D17E20B00AAC8F7 /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Debug;
+               };
+               AFEE109F1D17E20B00AAC8F7 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Release;
+               };
                AFF2869017860E830050A578 /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
                        buildSettings = {
                                ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
                                BUNDLE_IDENTIFIER = "org.jwz.${PROJECT_NAME:rfc1034identifier}.${PRODUCT_NAME:rfc1034identifier}";
+                               CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
+                               CLANG_WARN_INT_CONVERSION = YES;
                                "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
                                "CODE_SIGN_IDENTITY[sdk=iphonesimulator*]" = "iPhone Developer";
+                               "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Mac Developer";
                                COMBINE_HIDPI_IMAGES = YES;
+                               DEVELOPMENT_TEAM = 4627ATJELP;
                                ENABLE_TESTABILITY = YES;
                                GCC_OPTIMIZATION_LEVEL = 0;
                                GCC_PRECOMPILE_PREFIX_HEADER = YES;
                                );
                                INFOPLIST_FILE = XScreenSaver.plist;
                                INSTALL_PATH = "$(HOME)/Library/Screen Savers";
-                               IPHONEOS_DEPLOYMENT_TARGET = 6.0;
+                               IPHONEOS_DEPLOYMENT_TARGET = 8.0;
                                LIBRARY_SEARCH_PATHS = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)";
                                ONLY_ACTIVE_ARCH = YES;
                                OTHER_CFLAGS = "";
                        buildSettings = {
                                ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
                                BUNDLE_IDENTIFIER = "org.jwz.${PROJECT_NAME:rfc1034identifier}.${PRODUCT_NAME:rfc1034identifier}";
+                               CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
+                               CLANG_WARN_INT_CONVERSION = YES;
                                "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution: Jamie Zawinski (4627ATJELP)";
                                "CODE_SIGN_IDENTITY[sdk=iphonesimulator*]" = "iPhone Distribution: Jamie Zawinski (4627ATJELP)";
+                               "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Developer ID Application: Jamie Zawinski (4627ATJELP)";
                                COMBINE_HIDPI_IMAGES = YES;
+                               DEVELOPMENT_TEAM = 4627ATJELP;
                                GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
                                GCC_PRECOMPILE_PREFIX_HEADER = YES;
                                GCC_PREFIX_HEADER = xscreensaver_Prefix.pch;
                                );
                                INFOPLIST_FILE = XScreenSaver.plist;
                                INSTALL_PATH = "$(HOME)/Library/Screen Savers";
-                               IPHONEOS_DEPLOYMENT_TARGET = 6.0;
+                               IPHONEOS_DEPLOYMENT_TARGET = 8.0;
                                LIBRARY_SEARCH_PATHS = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)";
                                LLVM_LTO = NO;
                                "LLVM_LTO[sdk=macosx*]" = NO;
                        defaultConfigurationIsVisible = 0;
                        defaultConfigurationName = Release;
                };
+               AF1B0FB91D7AB4740011DBE4 /* Build configuration list for PBXNativeTarget "Hexstrut" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               AF1B0FBA1D7AB4740011DBE4 /* Debug */,
+                               AF1B0FBB1D7AB4740011DBE4 /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
                AF32D9F10F3AD0B40080F535 /* Build configuration list for PBXNativeTarget "RubikBlocks" */ = {
                        isa = XCConfigurationList;
                        buildConfigurations = (
                        defaultConfigurationIsVisible = 0;
                        defaultConfigurationName = Release;
                };
+               AF39382C1D0FBD6A00205406 /* Build configuration list for PBXNativeTarget "Discoball" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               AF39382D1D0FBD6A00205406 /* Debug */,
+                               AF39382E1D0FBD6A00205406 /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
                AF39E293198A11F60064A58D /* Build configuration list for PBXNativeTarget "WindupRobot" */ = {
                        isa = XCConfigurationList;
                        buildConfigurations = (
                        defaultConfigurationIsVisible = 0;
                        defaultConfigurationName = Release;
                };
+               AFEE105F1D13406000AAC8F7 /* Build configuration list for PBXNativeTarget "CubeTwist" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               AFEE10601D13406000AAC8F7 /* Debug */,
+                               AFEE10611D13406000AAC8F7 /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
+               AFEE107E1D15EB0800AAC8F7 /* Build configuration list for PBXNativeTarget "CubeStack" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               AFEE107F1D15EB0800AAC8F7 /* Debug */,
+                               AFEE10801D15EB0800AAC8F7 /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
+               AFEE109D1D17E20B00AAC8F7 /* Build configuration list for PBXNativeTarget "Splodesic" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               AFEE109E1D17E20B00AAC8F7 /* Debug */,
+                               AFEE109F1D17E20B00AAC8F7 /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
                AFF2868F17860E830050A578 /* Build configuration list for PBXNativeTarget "QuasiCrystal" */ = {
                        isa = XCConfigurationList;
                        buildConfigurations = (
diff --git a/README b/README
index 209e9688e78dc75526744c959a7a895cd58826fa..8f80f71d78f6bfbfe645b5ebf4b5d994be60e6c1 100644 (file)
--- a/README
+++ b/README
@@ -23,9 +23,12 @@ To compile for a Unix system with X11:
     make
     make install
 
+    If you are on an "apt"-based system, "apt-get build-dep xscreensaver"
+    might install most of the compilation dependencies.
+
 To compile for MacOS X or iOS:
 
-    Use the included XCode project.  Requires XCode 4 and MacOS X 10.5
+    Use the included XCode project.  Requires XCode 6 and MacOS X 10.8
     or newer.
 
 To compile for Android:
@@ -42,13 +45,20 @@ XScreenSaver has an extensive manual -- please read it!
 
 ===============================================================================
 
+5.36   * New hacks, `discoball', `cubetwist', `cubestack', `splodesic'
+          and `hexstrut'.
+       * OSX: loading image files works in `dymaxionmap', `glplanet',
+         `lavalite', `pulsar', `gleidescope' and `extrusion'.
+        * Several new programs in `m6502'.
+        * `rotzoomer -mode circle'.
+        * Better titles in `photopile'.
 5.35   * New hacks, `dymaxionmap', `unicrud', `energystream', `raverhoop'
           and `hydrostat'.
        * Added Windows 10 to `bsod'.
        * X11: ignore WM_USER_TIME property changes with days-old timestamps.
           Thanks, KDE.
-        * MacOS, iOS: Better fonts in 'BSOD' and 'memscroller'.
-       * MacOS 10.7 or later and iOS 6.0 or later are now required, since
+        * MacOS, iOS: Better fonts in `BSOD' and `memscroller'.
+       * MacOS 10.8 or later and iOS 6.0 or later are now required, since
          Xcode 6 can no longer build executables that work on older OSes.
        * Many, many Android improvements.
        * iOS: Fixed rotation to work with the new iOS 8+ API.
@@ -339,7 +349,7 @@ XScreenSaver has an extensive manual -- please read it!
          changes.
 
 5.02   * Reworked PAM code to support fingerprint readers, etc.
-       * Ported 'webcollage' to MacOS.
+       * Ported `webcollage' to MacOS.
        * Added MacOS 10.2 and 10.3 kernel panics to `bsod'.
        * Fixed a Xinerama crash when changing the screen count.
        * New blobbier `mirrorblob'.
index a716196295ac94730d664b85e1ce45ddff88d9e0..3cceb5773c0be4ea083002a2a73d604d23b7e9d2 100644 (file)
@@ -139,15 +139,18 @@ Programming Tips
   - Don't make assumptions about the depth of the display, or whether it
     is colormapped.  You must allocate all your colors explicitly: do not
     assume you can construct an RGB value and use that as a pixel value
-    directly.  Use the utility routines provided by "utils/colors.h" to
-    simplify color allocation.
+    directly.  In particular, you can't make assumptions about whether
+    pixels are RGB, RGBA, ARGB, ABGR, or even whether they are 32, 24,
+    16 or 8 bits.  Use the utility routines provided by "utils/colors.h"
+    to simplify color allocation.
 
   - It is better to eliminate flicker by double-buffering to a Pixmap
     than by erasing and re-drawing objects.  Do not use drawing tricks
     involving XOR.
 
-  - If you use double-buffering, have a resource to turn it off. (MacOS
-    has double-buffering built in, so you'd be triple-buffering.)
+  - If you use double-buffering, have a resource to turn it off. (MacOS,
+    iOS and Android have double-buffering built in, so you'd end up
+    triple-buffering.)
 
   - Understand the differences between Pixmaps and XImages, and keep in
     mind which operations are happening in client memory and which are in
@@ -160,20 +163,16 @@ Programming Tips
 
 
 ==========================================================================
-The MacOS X Port
+MacOS, iOS and Android
 ==========================================================================
 
   Though XScreenSaver started its life as an X11 program, it also now runs
-  on MacOS X.  If you do your development on an X11 system, and follow the
+  on MacOS, iOS and Android, due to a maniacal collection of compatibility
+  shims.  If you do your development on an X11 system, and follow the
   usual XScreenSaver APIs, you shouldn't need to do anything special for
-  it to also work on MacOS.
+  it to also work on MacOS and on phones.
 
-  The preprocessor macro HAVE_COCOA will be defined when being compiled in
-  a MacOS (Cocoa/Quartz) environment, and will be undefined when compiling
-  against "real" Xlib.
-
-  To compile on MacOS, use the XCode project included in the source
-  distribution.  You shouldn't need to have X11 installed, and shouldn't
-  need to run "configure" first.
+  See the READMEs in the OSX/ and android/ directories for instructions on
+  compiling for those platforms.
 
 ==========================================================================
index e9201d78ac72e08201a56dcea1555774e69a5627..03fbf5158016c09247081a3631a3bc115819ae7a 100644 (file)
@@ -327,7 +327,7 @@ msgstr ""
 # on various variables needed by the Makefile.in.in installed by 
 # glib-gettextize.
 dnl
-glib_DEFUN([GLIB_GNU_GETTEXT],
+AU_DEFUN([GLIB_GNU_GETTEXT],
   [AC_REQUIRE([AC_PROG_CC])dnl
    
    GLIB_LC_MESSAGES
@@ -397,7 +397,8 @@ glib_DEFUN([GLIB_GNU_GETTEXT],
    rm -f po/POTFILES
    sed -e "/^#/d" -e "/^\$/d" -e "s,.*,        $posrcprefix& \\\\," -e "\$s/\(.*\) \\\\/\1/" \
        < $srcdir/po/POTFILES.in > po/POTFILES
-  ])
+  ],
+  [[$0: This macro is deprecated. You should use upstream gettext instead.]])
 
 # AM_GLIB_DEFINE_LOCALEDIR(VARIABLE)
 # -------------------------------
@@ -618,8 +619,8 @@ AU_ALIAS([AC_PROG_INTLTOOL], [IT_PROG_INTLTOOL])
 
 
 # nls.m4 serial 5 (gettext-0.18)
-dnl Copyright (C) 1995-2003, 2005-2006, 2008-2014 Free Software Foundation,
-dnl Inc.
+dnl Copyright (C) 1995-2003, 2005-2006, 2008-2014, 2016 Free Software
+dnl Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
 dnl with or without modifications, as long as this notice is preserved.
index f296352011d29d9f3263e8a2ef0ad8e83de90659..35c24ec2050cdc060dd553f01a7a4ecf0c4e1b86 100644 (file)
@@ -59,7 +59,9 @@ export ANDROID_HACKS=         \
        compass                 \
        coral                   \
        crystal                 \
+       cubestack               \
        cubestorm               \
+       cubetwist               \
        cwaves                  \
        cynosure                \
        dangerball              \
@@ -67,6 +69,7 @@ export ANDROID_HACKS=         \
        deco                    \
        demon                   \
        discrete                \
+       discoball               \
        distort                 \
        dnalogo                 \
        drift                   \
@@ -98,6 +101,7 @@ export ANDROID_HACKS=                \
        greynetic               \
        helix                   \
        hexadrop                \
+       hexstrut                \
        hilbert                 \
        hopalong                \
        hypnowheel              \
@@ -147,6 +151,7 @@ export ANDROID_HACKS=               \
        sierpinski              \
        sierpinski3d            \
        slidescreen             \
+       splodesic               \
        squiral                 \
        stairs                  \
        starfish                \
@@ -269,6 +274,15 @@ CVT  = -thumbnail '150x150^' -gravity center -extent 150x150 \
     -quality 95 \
     +dither -colors 128
 
+# If we are making the m6502 hack, create the header file for Android
+m6502.h::
+       @for h in $(ANDROID_HACKS) ; do \
+               if [ $${h} = "m6502" ] ; then \
+                       echo "Making $${h} header ..."; \
+                       ../hacks/m6502.sh ../hacks/m6502.h ../hacks/images/m6502/*.asm ; \
+                       echo "Made $${h} header"; \
+               fi; \
+       done
 
 project/xscreensaver/res/drawable/%.png:
        @\
@@ -296,7 +310,8 @@ clean_thumbs::
        for f in $(ANDROID_HACKS) $(ANDROID_TODO) ; do                  \
          rm -f project/xscreensaver/res/drawable/$$f.png ;             \
        done
-distclean:: clean_thumbs
+
+distclean:: clean_thumbs clean
 
 
 EXTRA_TARFILES = project/xscreensaver/res/drawable/thumbnail.png \
@@ -326,9 +341,12 @@ echo_tarfiles:
                | sort` ;                       \
        echo $$FILES
 
-debug::
+run_check::
+       ../hacks/check-configs.pl --build-android $(ANDROID_HACKS)
+
+debug:: m6502.h run_check
        $(GRADLE) assembleDebug
-release::
+release:: m6502.h run_check
        export APP_ABI=all ; \
        $(GRADLE) assembleRelease
 
@@ -380,3 +398,8 @@ apk:: release
 #  dnalogo                     \
 #  twang                       \
 #  memscroller                 \
+#  phosphor                    \
+#  discoball                   \
+#  cubetwist                   \
+#  cubestack                   \
+#  splodesic                   \
index 74b8097ccfcece2d5151f72bd992a9eca251b4d8..78fda15de4391901c6719e00ef6d39bcfd90c6f1 100644 (file)
@@ -41,6 +41,9 @@ To build:
 
       $ANDROID_HOME/sdk/tools/android avd
 
+      E.g.: Nexus 5, Android 5, Intel Atom x86_64, RAM 2048 VM 64,
+        storage 200, use host GPU.
+
     Configuration options are in $HOME/.android/avd/*.avd/config.ini
 
     To launch it:
diff --git a/android/XScreenSaverDaydream.java.in b/android/XScreenSaverDaydream.java.in
deleted file mode 100644 (file)
index 46c3dc7..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/* -*- Mode: java; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * xscreensaver, Copyright (c) 2016 Jamie Zawinski <jwz@jwz.org>
- * and Dennis Sheil <dennis@panaceasupplies.com>
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation.  No representations are made about the suitability of this
- * software for any purpose.  It is provided "as is" without express or 
- * implied warranty.
- *
- * The template for the generated per-saver classes.
- */
-
-package org.jwz.xscreensaver.gen;
-
-import org.jwz.xscreensaver.XScreenSaverDaydream;
-import org.jwz.xscreensaver.jwxyz;
-
-public class @CLASS@ extends XScreenSaverDaydream {
-  public @CLASS@() {
-    super(jwxyz.API_@API@);
-  }
-}
diff --git a/android/XScreenSaverSettings.java.in b/android/XScreenSaverSettings.java.in
deleted file mode 100644 (file)
index 914c653..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/* -*- Mode: java; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * xscreensaver, Copyright (c) 2016 Jamie Zawinski <jwz@jwz.org>
- * and Dennis Sheil <dennis@panaceasupplies.com>
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation.  No representations are made about the suitability of this
- * software for any purpose.  It is provided "as is" without express or 
- * implied warranty.
- *
- * The template for the generated per-saver "Settings" classes.
- */
-
-package org.jwz.xscreensaver.gen;
-
-import android.content.SharedPreferences;
-import org.jwz.xscreensaver.XScreenSaverSettings;
-
-public class @CLASS@ extends XScreenSaverSettings
-  implements SharedPreferences.OnSharedPreferenceChangeListener {
-}
diff --git a/android/grabscreen-android.c b/android/grabscreen-android.c
deleted file mode 100644 (file)
index 3871075..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-#include <stdlib.h>
-#include <stdint.h>
-//
-//#import "SaverRunner.h"
-//
-#include "jwxyz.h"
-#include "grabscreen.h"
-#include "colorbars.h"
-#include "resources.h"
-#include "usleep.h"
-
-Bool
-osx_grab_desktop_image (Screen *screen, Window xwindow, Drawable drawable,
-                        XRectangle *geom_ret)
-{
-abort();
-}
-
-Bool
-osx_load_image_file (Screen *screen, Window xwindow, Drawable drawable,
-                     const char *filename, XRectangle *geom_ret)
-{
-abort();
-}
index 41cd0d1573e42f35248d8fb620613e099de4bfc8..613cb90828eeabee648c2141d5abcf46302b5f05 100644 (file)
@@ -1,11 +1,16 @@
 // Top-level build file where you can add configuration options common to all sub-projects/modules.
 buildscript {
     repositories {
-        mavenCentral()
+        jcenter()
     }
     dependencies {
-        classpath 'com.android.tools.build:gradle:1.1.0'
+        classpath 'com.android.tools.build:gradle:2.1.0'
     }
+
+    // This allows versions of Gradle past 2.9 to be used with the Gradle
+    // Android plugin.
+    // https://discuss.gradle.org/t/gradle-thinks-2-10-is-less-than-2-2-when-resolving-plugins/13434/2
+//    System.properties['com.android.build.gradle.overrideVersionCheck'] = 'true';
 }
 
 task clean(type: Delete) {
index 8c0fb64a8698b08ecc4158d828ca593c4928e9dd..13372aef5e24af05341d49695ee84e5f9b594659 100644 (file)
Binary files a/android/project/gradle/wrapper/gradle-wrapper.jar and b/android/project/gradle/wrapper/gradle-wrapper.jar differ
index 542898db097a53c5fb67dfc85c000b6720ef2ccc..729f41b70bf2b7a765f1f90c701c6ef5cb1c9fab 100644 (file)
@@ -1,7 +1,6 @@
-
-#Wed Apr 10 15:27:10 PDT 2013
+#Sun Jun 12 14:20:28 PDT 2016
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-bin.zip
index 91a7e269e19dfc62e27137a0b57ef3e430cee4fd..9d82f78915133e1c35a6ea51252590fb38efac2f 100755 (executable)
@@ -42,11 +42,6 @@ case "`uname`" in
     ;;
 esac
 
-# For Cygwin, ensure paths are in UNIX format before anything is touched.
-if $cygwin ; then
-    [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
-fi
-
 # Attempt to set APP_HOME
 # Resolve links: $0 may be a link
 PRG="$0"
@@ -61,9 +56,9 @@ while [ -h "$PRG" ] ; do
     fi
 done
 SAVED="`pwd`"
-cd "`dirname \"$PRG\"`/" >&-
+cd "`dirname \"$PRG\"`/" >/dev/null
 APP_HOME="`pwd -P`"
-cd "$SAVED" >&-
+cd "$SAVED" >/dev/null
 
 CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
 
@@ -114,6 +109,7 @@ fi
 if $cygwin ; then
     APP_HOME=`cygpath --path --mixed "$APP_HOME"`
     CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+    JAVACMD=`cygpath --unix "$JAVACMD"`
 
     # We build the pattern for arguments to be converted via cygpath
     ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
diff --git a/android/project/project.iml b/android/project/project.iml
new file mode 100644 (file)
index 0000000..de3d86e
--- /dev/null
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module external.linked.project.id="project" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/xscreensaver" external.system.id="GRADLE" type="JAVA_MODULE" version="4">
+  <component name="FacetManager">
+    <facet type="java-gradle" name="Java-Gradle">
+      <configuration>
+        <option name="BUILD_FOLDER_PATH" value="$MODULE_DIR$/build" />
+        <option name="BUILDABLE" value="false" />
+      </configuration>
+    </facet>
+  </component>
+  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="true">
+    <exclude-output />
+    <content url="file://$MODULE_DIR$">
+      <excludeFolder url="file://$MODULE_DIR$/.gradle" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>
\ No newline at end of file
diff --git a/android/project/xscreensaver/.idea/compiler.xml b/android/project/xscreensaver/.idea/compiler.xml
new file mode 100644 (file)
index 0000000..9a8b7e5
--- /dev/null
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="CompilerConfiguration">
+    <option name="DEFAULT_COMPILER" value="Javac" />
+    <resourceExtensions />
+    <wildcardResourcePatterns>
+      <entry name="!?*.java" />
+      <entry name="!?*.form" />
+      <entry name="!?*.class" />
+      <entry name="!?*.groovy" />
+      <entry name="!?*.scala" />
+      <entry name="!?*.flex" />
+      <entry name="!?*.kt" />
+      <entry name="!?*.clj" />
+    </wildcardResourcePatterns>
+    <annotationProcessing>
+      <profile default="true" name="Default" enabled="false">
+        <processorPath useClasspath="true" />
+      </profile>
+    </annotationProcessing>
+  </component>
+</project>
\ No newline at end of file
diff --git a/android/project/xscreensaver/.idea/gradle.xml b/android/project/xscreensaver/.idea/gradle.xml
new file mode 100644 (file)
index 0000000..19fd5f1
--- /dev/null
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="GradleSettings">
+    <option name="linkedExternalProjectsSettings">
+      <GradleProjectSettings>
+        <option name="distributionType" value="LOCAL" />
+        <option name="externalProjectPath" value="$PROJECT_DIR$" />
+        <option name="gradleHome" value="$APPLICATION_HOME_DIR$/gradle/gradle-2.14.1" />
+        <option name="modules">
+          <set>
+            <option value="$PROJECT_DIR$/.." />
+            <option value="$PROJECT_DIR$" />
+          </set>
+        </option>
+        <option name="resolveModulePerSourceSet" value="false" />
+      </GradleProjectSettings>
+    </option>
+  </component>
+</project>
\ No newline at end of file
diff --git a/android/project/xscreensaver/.idea/misc.xml b/android/project/xscreensaver/.idea/misc.xml
new file mode 100644 (file)
index 0000000..cc15a25
--- /dev/null
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectLevelVcsManager" settingsEditedManually="false">
+    <OptionsSetting value="true" id="Add" />
+    <OptionsSetting value="true" id="Remove" />
+    <OptionsSetting value="true" id="Checkout" />
+    <OptionsSetting value="true" id="Update" />
+    <OptionsSetting value="true" id="Status" />
+    <OptionsSetting value="true" id="Edit" />
+    <ConfirmationsSetting value="0" id="Add" />
+    <ConfirmationsSetting value="0" id="Remove" />
+  </component>
+  <component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK" />
+</project>
\ No newline at end of file
diff --git a/android/project/xscreensaver/.idea/modules.xml b/android/project/xscreensaver/.idea/modules.xml
new file mode 100644 (file)
index 0000000..f317927
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/../project.iml" filepath="$PROJECT_DIR$/../project.iml" />
+      <module fileurl="file://$PROJECT_DIR$/xscreensaver.iml" filepath="$PROJECT_DIR$/xscreensaver.iml" />
+    </modules>
+  </component>
+</project>
\ No newline at end of file
diff --git a/android/project/xscreensaver/.idea/workspace.xml b/android/project/xscreensaver/.idea/workspace.xml
new file mode 100644 (file)
index 0000000..516bf62
--- /dev/null
@@ -0,0 +1,1863 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ChangeListManager">
+    <list default="true" id="41008724-035d-4e24-92b6-6dfb9231c83c" name="Default" comment="" />
+    <ignored path="xscreensaver.iws" />
+    <ignored path=".idea/workspace.xml" />
+    <option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
+    <option name="TRACKING_ENABLED" value="true" />
+    <option name="SHOW_DIALOG" value="false" />
+    <option name="HIGHLIGHT_CONFLICTS" value="true" />
+    <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
+    <option name="LAST_RESOLUTION" value="IGNORE" />
+  </component>
+  <component name="ChangesViewManager" flattened_view="true" show_ignored="false" />
+  <component name="CreatePatchCommitExecutor">
+    <option name="PATCH_PATH" value="" />
+  </component>
+  <component name="ExecutionTargetManager" SELECTED_TARGET="default_target" />
+  <component name="ExternalProjectsData">
+    <projectState path="$PROJECT_DIR$">
+      <ProjectState />
+    </projectState>
+  </component>
+  <component name="FavoritesManager">
+    <favorites_list name="xscreensaver" />
+  </component>
+  <component name="GradleLocalSettings">
+    <option name="availableProjects">
+      <map>
+        <entry>
+          <key>
+            <ExternalProjectPojo>
+              <option name="name" value="project" />
+              <option name="path" value="$PROJECT_DIR$" />
+            </ExternalProjectPojo>
+          </key>
+          <value>
+            <list>
+              <ExternalProjectPojo>
+                <option name="name" value=":xscreensaver" />
+                <option name="path" value="$PROJECT_DIR$" />
+              </ExternalProjectPojo>
+              <ExternalProjectPojo>
+                <option name="name" value="project" />
+                <option name="path" value="$PROJECT_DIR$/.." />
+              </ExternalProjectPojo>
+            </list>
+          </value>
+        </entry>
+      </map>
+    </option>
+    <option name="availableTasks">
+      <map>
+        <entry key="$PROJECT_DIR$/..">
+          <value>
+            <list>
+              <ExternalTaskPojo>
+                <option name="description" value="Displays all buildscript dependencies declared in root project 'project'." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value=":buildEnvironment" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value=":clean" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Displays the components produced by root project 'project'. [incubating]" />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value=":components" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Displays all dependencies declared in root project 'project'." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value=":dependencies" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Displays the insight into a specific dependency in root project 'project'." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value=":dependencyInsight" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value=":distClean" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Displays a help message." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value=":help" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Initializes a new Gradle build. [incubating]" />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value=":init" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Displays the configuration model of root project 'project'. [incubating]" />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value=":model" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Displays the sub-projects of root project 'project'." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value=":projects" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Displays the properties of root project 'project'." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value=":properties" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Displays the tasks runnable from root project 'project' (some of the displayed tasks may belong to subprojects)." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value=":tasks" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Generates Gradle wrapper files. [incubating]" />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value=":wrapper" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Displays the Android dependencies of the project." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="androidDependencies" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Assembles all variants of all applications and secondary packages." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="assemble" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Assembles all the Test applications." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="assembleAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Assembles all Debug builds." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="assembleDebug" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="assembleDebugAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="assembleDebugUnitTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Assembles all Release builds." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="assembleRelease" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="assembleReleaseUnitTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Assembles and tests this project." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="build" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Assembles and tests this project and all projects that depend on it." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="buildDependents" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Assembles and tests this project and all projects it depends on." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="buildNeeded" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Runs all checks." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="check" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="checkDebugManifest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="checkReleaseManifest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugAidl" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugAndroidTestAidl" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugAndroidTestJavaWithJavac" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugAndroidTestNdk" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugAndroidTestRenderscript" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugAndroidTestShaders" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugAndroidTestSources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugJavaWithJavac" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugNdk" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugRenderscript" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugShaders" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugSources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugUnitTestJavaWithJavac" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugUnitTestSources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileLint" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileReleaseAidl" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileReleaseJavaWithJavac" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileReleaseNdk" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileReleaseRenderscript" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileReleaseShaders" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileReleaseSources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileReleaseUnitTestJavaWithJavac" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileReleaseUnitTestSources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="config_h" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Installs and runs instrumentation tests for all flavors on connected devices." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="connectedAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Runs all device checks on currently connected devices." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="connectedCheck" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Installs and runs the tests for debug on connected devices." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="connectedDebugAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Installs and runs instrumentation tests using all Device Providers." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="deviceAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Runs all device checks using Device Providers and Test Servers." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="deviceCheck" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="downloadNeededDrawables" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateDebugAndroidTestAssets" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateDebugAndroidTestBuildConfig" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateDebugAndroidTestResValues" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateDebugAndroidTestResources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateDebugAndroidTestSources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateDebugAssets" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateDebugBuildConfig" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateDebugResValues" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateDebugResources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateDebugSources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateReleaseAssets" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateReleaseBuildConfig" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateReleaseResValues" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateReleaseResources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateReleaseSources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="incrementalDebugAndroidTestJavaCompilationSafeguard" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="incrementalDebugJavaCompilationSafeguard" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="incrementalDebugUnitTestJavaCompilationSafeguard" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="incrementalReleaseJavaCompilationSafeguard" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="incrementalReleaseUnitTestJavaCompilationSafeguard" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Installs the Debug build." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="installDebug" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Installs the android (on device) tests for the Debug build." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="installDebugAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="jarDebugClasses" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="jarReleaseClasses" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Runs lint on all variants." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="lint" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Runs lint on the Debug build." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="lintDebug" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Runs lint on the Release build." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="lintRelease" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Runs lint on just the fatal issues in the Release build." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="lintVitalRelease" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mergeDebugAndroidTestAssets" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mergeDebugAndroidTestJniLibFolders" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mergeDebugAndroidTestResources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mergeDebugAndroidTestShaders" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mergeDebugAssets" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mergeDebugJniLibFolders" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mergeDebugResources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mergeDebugShaders" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mergeReleaseAssets" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mergeReleaseJniLibFolders" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mergeReleaseResources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mergeReleaseShaders" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Creates a version of android.jar that's suitable for unit tests." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mockableAndroidJar" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="ndkBuild" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="objlibClean" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="packageDebug" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="packageDebugAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="packageRelease" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="perlBuild" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="perlClean" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="preBuild" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="preDebugAndroidTestBuild" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="preDebugBuild" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="preDebugUnitTestBuild" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="prePackageMarkerForDebug" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="prePackageMarkerForDebugAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="prePackageMarkerForRelease" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="preReleaseBuild" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="preReleaseUnitTestBuild" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="prepareDebugAndroidTestDependencies" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="prepareDebugDependencies" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="prepareDebugUnitTestDependencies" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="prepareReleaseDependencies" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="prepareReleaseUnitTestDependencies" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="processDebugAndroidTestJavaRes" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="processDebugAndroidTestManifest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="processDebugAndroidTestResources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="processDebugJavaRes" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="processDebugManifest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="processDebugResources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="processDebugUnitTestJavaRes" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="processReleaseJavaRes" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="processReleaseManifest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="processReleaseResources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="processReleaseUnitTestJavaRes" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Displays the signing info for each variant." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="signingReport" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Prints out all the source sets defined in this project." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="sourceSets" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Run unit tests for all variants." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="test" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Run unit tests for the debug build." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="testDebugUnitTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Run unit tests for the release build." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="testReleaseUnitTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="transformClassesWithDexForDebug" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="transformClassesWithDexForDebugAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="transformClassesWithDexForRelease" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="transformNative_libsWithMergeJniLibsForDebug" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="transformNative_libsWithMergeJniLibsForDebugAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="transformNative_libsWithMergeJniLibsForRelease" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="transformResourcesWithMergeJavaResForDebug" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="transformResourcesWithMergeJavaResForDebugAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="transformResourcesWithMergeJavaResForDebugUnitTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="transformResourcesWithMergeJavaResForRelease" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="transformResourcesWithMergeJavaResForReleaseUnitTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Uninstall all applications." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="uninstallAll" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Uninstalls the Debug build." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="uninstallDebug" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Uninstalls the android (on device) tests for the Debug build." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="uninstallDebugAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Uninstalls the Release build." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="uninstallRelease" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="validateDebugSigning" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="zipalignDebug" />
+              </ExternalTaskPojo>
+            </list>
+          </value>
+        </entry>
+        <entry key="$PROJECT_DIR$">
+          <value>
+            <list>
+              <ExternalTaskPojo>
+                <option name="description" value="Displays the sub-projects of project ':xscreensaver'." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="projects" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="assembleReleaseUnitTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="prepareDebugDependencies" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="processReleaseJavaRes" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateReleaseAssets" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Runs lint on the Debug build." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="lintDebug" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="assembleDebugUnitTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="prePackageMarkerForDebug" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Creates a version of android.jar that's suitable for unit tests." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mockableAndroidJar" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Displays the configuration model of project ':xscreensaver'. [incubating]" />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="model" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Displays the tasks runnable from project ':xscreensaver'." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="tasks" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugSources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="incrementalDebugJavaCompilationSafeguard" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Runs all device checks using Device Providers and Test Servers." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="deviceCheck" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Displays all dependencies declared in project ':xscreensaver'." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="dependencies" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="processDebugResources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Runs lint on all variants." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="lint" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="packageDebug" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="prePackageMarkerForRelease" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileReleaseNdk" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateDebugResources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugJavaWithJavac" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Assembles and tests this project and all projects it depends on." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="buildNeeded" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateDebugAndroidTestBuildConfig" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="processDebugUnitTestJavaRes" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Run unit tests for the release build." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="testReleaseUnitTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugAndroidTestShaders" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mergeDebugShaders" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="transformNative_libsWithMergeJniLibsForDebugAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugAndroidTestJavaWithJavac" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Displays the components produced by project ':xscreensaver'. [incubating]" />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="components" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileReleaseRenderscript" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Assembles all Debug builds." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="assembleDebug" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="processDebugAndroidTestManifest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugUnitTestJavaWithJavac" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="transformResourcesWithMergeJavaResForReleaseUnitTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="prePackageMarkerForDebugAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="transformClassesWithDexForDebug" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="preDebugAndroidTestBuild" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="processDebugAndroidTestJavaRes" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="processReleaseUnitTestJavaRes" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Uninstalls the Release build." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="uninstallRelease" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileReleaseShaders" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mergeReleaseResources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateDebugAndroidTestSources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="prepareDebugAndroidTestDependencies" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="incrementalDebugAndroidTestJavaCompilationSafeguard" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="checkReleaseManifest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugAndroidTestSources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mergeReleaseJniLibFolders" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="prepareReleaseDependencies" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="processReleaseResources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Installs and runs instrumentation tests using all Device Providers." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="deviceAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mergeDebugAndroidTestAssets" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="processReleaseManifest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Uninstalls the android (on device) tests for the Debug build." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="uninstallDebugAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Displays the insight into a specific dependency in project ':xscreensaver'." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="dependencyInsight" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateReleaseSources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="incrementalReleaseUnitTestJavaCompilationSafeguard" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="preReleaseBuild" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Assembles all variants of all applications and secondary packages." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="assemble" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="incrementalDebugUnitTestJavaCompilationSafeguard" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="incrementalReleaseJavaCompilationSafeguard" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Displays a help message." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="help" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileReleaseUnitTestSources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Installs the android (on device) tests for the Debug build." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="installDebugAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mergeDebugAssets" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Runs all device checks on currently connected devices." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="connectedCheck" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Installs and runs the tests for debug on connected devices." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="connectedDebugAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Uninstall all applications." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="uninstallAll" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Assembles all the Test applications." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="assembleAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="processDebugAndroidTestResources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="zipalignDebug" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="transformNative_libsWithMergeJniLibsForDebug" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="packageRelease" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugAidl" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mergeDebugResources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="preDebugUnitTestBuild" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileLint" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateDebugAndroidTestResValues" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mergeReleaseShaders" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Displays the Android dependencies of the project." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="androidDependencies" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugAndroidTestNdk" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugUnitTestSources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateDebugSources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mergeDebugAndroidTestJniLibFolders" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="transformClassesWithDexForDebugAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="assembleDebugAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="objlibClean" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="processDebugJavaRes" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateDebugAndroidTestAssets" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileReleaseJavaWithJavac" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="jarReleaseClasses" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="transformResourcesWithMergeJavaResForDebugAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="downloadNeededDrawables" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="prepareReleaseUnitTestDependencies" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Run unit tests for all variants." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="test" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugNdk" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="transformNative_libsWithMergeJniLibsForRelease" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mergeDebugAndroidTestResources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="preReleaseUnitTestBuild" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateDebugResValues" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Runs all checks." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="check" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="validateDebugSigning" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Run unit tests for the debug build." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="testDebugUnitTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Installs and runs instrumentation tests for all flavors on connected devices." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="connectedAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="jarDebugClasses" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="transformClassesWithDexForRelease" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Installs the Debug build." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="installDebug" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="preBuild" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="transformResourcesWithMergeJavaResForRelease" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileReleaseSources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileReleaseUnitTestJavaWithJavac" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugShaders" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="transformResourcesWithMergeJavaResForDebug" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileReleaseAidl" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="config_h" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Runs lint on the Release build." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="lintRelease" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Assembles and tests this project and all projects that depend on it." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="buildDependents" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateDebugAssets" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Displays all buildscript dependencies declared in project ':xscreensaver'." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="buildEnvironment" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="checkDebugManifest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mergeDebugJniLibFolders" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Prints out all the source sets defined in this project." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="sourceSets" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="transformResourcesWithMergeJavaResForDebugUnitTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="perlBuild" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mergeReleaseAssets" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugRenderscript" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateReleaseBuildConfig" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="prepareDebugUnitTestDependencies" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="perlClean" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateReleaseResources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Runs lint on just the fatal issues in the Release build." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="lintVitalRelease" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="ndkBuild" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Uninstalls the Debug build." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="uninstallDebug" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Displays the signing info for each variant." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="signingReport" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugAndroidTestAidl" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mergeDebugAndroidTestShaders" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Deletes the build directory." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="clean" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="preDebugBuild" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateDebugBuildConfig" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Assembles and tests this project." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="build" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Assembles all Release builds." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="assembleRelease" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugAndroidTestRenderscript" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateDebugAndroidTestResources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="processDebugManifest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="packageDebugAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateReleaseResValues" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Displays the properties of project ':xscreensaver'." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="properties" />
+              </ExternalTaskPojo>
+            </list>
+          </value>
+        </entry>
+      </map>
+    </option>
+    <option name="modificationStamps">
+      <map>
+        <entry key="$PROJECT_DIR$" value="4395090424000" />
+      </map>
+    </option>
+    <option name="projectBuildClasspath">
+      <map>
+        <entry key="$PROJECT_DIR$">
+          <value>
+            <ExternalProjectBuildClasspathPojo>
+              <option name="modulesBuildClasspath">
+                <map>
+                  <entry key="$PROJECT_DIR$/..">
+                    <value>
+                      <ExternalModuleBuildClasspathPojo>
+                        <option name="entries">
+                          <list>
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/gradle/2.1.2/a15b8a1abdb158716cb2eca322c8c055dcf3c73d/gradle-2.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/gradle-core/2.1.2/23fa54cbd68abe0d190b3f19b8db553c22b1e95e/gradle-core-2.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/builder/2.1.2/b0f8f1b2be1cca433af04ac59c032bb65f104f68/builder-2.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.lint/lint/25.1.2/73b0fca79c61b7d4212354d2dc54310f18d3eab1/lint-25.1.2.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/android/tools/build/transform-api/2.0.0-deprecated-use-gradle-api/transform-api-2.0.0-deprecated-use-gradle-api.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/gradle-api/2.1.2/13a4ad6e82603eca38f0f46e308db7b2374bd33a/gradle-api-2.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.databinding/compilerCommon/2.1.2/658479d60a2ad7f511ea43028a9dbe6f7658779d/compilerCommon-2.1.2.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/ow2/asm/asm/5.0.3/asm-5.0.3-sources.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/ow2/asm/asm/5.0.3/asm-5.0.3.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/ow2/asm/asm-commons/5.0.3/asm-commons-5.0.3-sources.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/ow2/asm/asm-commons/5.0.3/asm-commons-5.0.3.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/net/sf/proguard/proguard-gradle/5.2.1/proguard-gradle-5.2.1-sources.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/net/sf/proguard/proguard-gradle/5.2.1/proguard-gradle-5.2.1.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/jacoco/org.jacoco.core/0.7.4.201502262128/org.jacoco.core-0.7.4.201502262128-sources.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/jacoco/org.jacoco.core/0.7.4.201502262128/org.jacoco.core-0.7.4.201502262128.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/antlr/antlr/3.5.2/antlr-3.5.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/builder-model/2.1.2/54929c8a9d8c2dd13c945c3f5ad0ec5546cdc006/builder-model-2.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/builder-test-api/2.1.2/ee73cc6c008005128538d86c1c56a27e2d96c32/builder-test-api-2.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/sdklib/25.1.2/59cdf46da07c365d456606d3985a51702db87c24/sdklib-25.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/sdk-common/25.1.2/1dcda99e022faddbf24336c0c8b37398773f4c36/sdk-common-25.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/common/25.1.2/c15c73c5ddedc9ac2afdfda827fa23a9b59b9b9d/common-25.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/manifest-merger/25.1.2/2f070c6b90be1642f37aafe15e42f21ba73394da/manifest-merger-25.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.ddms/ddmlib/25.1.2/521439862ec854d683a19a351fcc3beda4653346/ddmlib-25.1.2.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/android/tools/jack/jack-api/0.10.0/jack-api-0.10.0.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/android/tools/jill/jill-api/0.10.0/jill-api-0.10.0.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/squareup/javawriter/2.5.0/javawriter-2.5.0-sources.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/squareup/javawriter/2.5.0/javawriter-2.5.0.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/bouncycastle/bcpkix-jdk15on/1.48/bcpkix-jdk15on-1.48-sources.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/bouncycastle/bcpkix-jdk15on/1.48/bcpkix-jdk15on-1.48.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/bouncycastle/bcprov-jdk15on/1.48/bcprov-jdk15on-1.48-sources.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/bouncycastle/bcprov-jdk15on/1.48/bcprov-jdk15on-1.48.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/ow2/asm/asm-tree/5.0.3/asm-tree-5.0.3-sources.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/ow2/asm/asm-tree/5.0.3/asm-tree-5.0.3.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.lint/lint-checks/25.1.2/68583e445a033021d9792c9d84ac7ce8ea549c81/lint-checks-25.1.2.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/eclipse/jdt/core/compiler/ecj/4.4.2/ecj-4.4.2-sources.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/eclipse/jdt/core/compiler/ecj/4.4.2/ecj-4.4.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/annotations/25.1.2/9dbfadaaf19097c12787c68cf43a12c739936345/annotations-25.1.2.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/google/guava/guava/17.0/guava-17.0-sources.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/google/guava/guava/17.0/guava-17.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.databinding/baseLibrary/2.1.2/d0395908c940f4171fb024435b25f7458c1147f3/baseLibrary-2.1.2.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/tunnelvisionlabs/antlr4/4.5/antlr4-4.5.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/commons-io/commons-io/2.4/commons-io-2.4-sources.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/commons-io/commons-io/2.4/commons-io-2.4.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/googlecode/juniversalchardet/juniversalchardet/1.0.3/juniversalchardet-1.0.3.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/net/sf/proguard/proguard-base/5.2.1/proguard-base-5.2.1-sources.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/net/sf/proguard/proguard-base/5.2.1/proguard-base-5.2.1.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/ow2/asm/asm-debug-all/5.0.1/asm-debug-all-5.0.1-sources.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/ow2/asm/asm-debug-all/5.0.1/asm-debug-all-5.0.1.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/antlr/antlr-runtime/3.5.2/antlr-runtime-3.5.2.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/antlr/ST4/4.0.8/ST4-4.0.8.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.layoutlib/layoutlib-api/25.1.2/b93f0de181063ee2f673d7d6cac0bdbb94cc1b90/layoutlib-api-25.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/dvlib/25.1.2/bfcb16fb0e44568bd8e31c6aaf1850c1dcd06483/dvlib-25.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/repository/25.1.2/1a1f5f59b21a42817eec50b7aced4400bb72273b/repository-25.1.2.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/google/code/gson/gson/2.2.4/gson-2.2.4-sources.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/google/code/gson/gson/2.2.4/gson-2.2.4.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/apache/commons/commons-compress/1.8.1/commons-compress-1.8.1-sources.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/apache/commons/commons-compress/1.8.1/commons-compress-1.8.1.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/apache/httpcomponents/httpclient/4.1.1/httpclient-4.1.1-sources.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/apache/httpcomponents/httpclient/4.1.1/httpclient-4.1.1.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/apache/httpcomponents/httpmime/4.1/httpmime-4.1-sources.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/apache/httpcomponents/httpmime/4.1/httpmime-4.1.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/net/sf/kxml/kxml2/2.3.0/kxml2-2.3.0-sources.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/net/sf/kxml/kxml2/2.3.0/kxml2-2.3.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.lint/lint-api/25.1.2/f9f6807b68d486eaf34cc3f08b6f098f89cf3db8/lint-api-25.1.2.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/ow2/asm/asm-analysis/5.0.3/asm-analysis-5.0.3-sources.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/ow2/asm/asm-analysis/5.0.3/asm-analysis-5.0.3.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/tunnelvisionlabs/antlr4-runtime/4.5/antlr4-runtime-4.5.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/tunnelvisionlabs/antlr4-annotations/4.5/antlr4-annotations-4.5.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/intellij/annotations/12.0/annotations-12.0-sources.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/intellij/annotations/12.0/annotations-12.0.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/apache/httpcomponents/httpcore/4.1/httpcore-4.1-sources.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/apache/httpcomponents/httpcore/4.1/httpcore-4.1.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/commons-logging/commons-logging/1.1.1/commons-logging-1.1.1-sources.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/commons-logging/commons-logging/1.1.1/commons-logging-1.1.1.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/commons-codec/commons-codec/1.4/commons-codec-1.4-sources.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/commons-codec/commons-codec/1.4/commons-codec-1.4.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/android/tools/external/lombok/lombok-ast/0.2.3/lombok-ast-0.2.3-sources.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/android/tools/external/lombok/lombok-ast/0.2.3/lombok-ast-0.2.3.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/abego/treelayout/org.abego.treelayout.core/1.0.1/org.abego.treelayout.core-1.0.1.jar" />
+                          </list>
+                        </option>
+                        <option name="path" value="$PROJECT_DIR$/.." />
+                      </ExternalModuleBuildClasspathPojo>
+                    </value>
+                  </entry>
+                  <entry key="$PROJECT_DIR$">
+                    <value>
+                      <ExternalModuleBuildClasspathPojo>
+                        <option name="entries">
+                          <list>
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/gradle/2.1.2/a15b8a1abdb158716cb2eca322c8c055dcf3c73d/gradle-2.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/gradle-core/2.1.2/23fa54cbd68abe0d190b3f19b8db553c22b1e95e/gradle-core-2.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/builder/2.1.2/b0f8f1b2be1cca433af04ac59c032bb65f104f68/builder-2.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.lint/lint/25.1.2/73b0fca79c61b7d4212354d2dc54310f18d3eab1/lint-25.1.2.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/android/tools/build/transform-api/2.0.0-deprecated-use-gradle-api/transform-api-2.0.0-deprecated-use-gradle-api.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/gradle-api/2.1.2/13a4ad6e82603eca38f0f46e308db7b2374bd33a/gradle-api-2.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.databinding/compilerCommon/2.1.2/658479d60a2ad7f511ea43028a9dbe6f7658779d/compilerCommon-2.1.2.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/ow2/asm/asm/5.0.3/asm-5.0.3-sources.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/ow2/asm/asm/5.0.3/asm-5.0.3.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/ow2/asm/asm-commons/5.0.3/asm-commons-5.0.3-sources.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/ow2/asm/asm-commons/5.0.3/asm-commons-5.0.3.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/net/sf/proguard/proguard-gradle/5.2.1/proguard-gradle-5.2.1-sources.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/net/sf/proguard/proguard-gradle/5.2.1/proguard-gradle-5.2.1.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/jacoco/org.jacoco.core/0.7.4.201502262128/org.jacoco.core-0.7.4.201502262128-sources.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/jacoco/org.jacoco.core/0.7.4.201502262128/org.jacoco.core-0.7.4.201502262128.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/antlr/antlr/3.5.2/antlr-3.5.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/builder-model/2.1.2/54929c8a9d8c2dd13c945c3f5ad0ec5546cdc006/builder-model-2.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/builder-test-api/2.1.2/ee73cc6c008005128538d86c1c56a27e2d96c32/builder-test-api-2.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/sdklib/25.1.2/59cdf46da07c365d456606d3985a51702db87c24/sdklib-25.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/sdk-common/25.1.2/1dcda99e022faddbf24336c0c8b37398773f4c36/sdk-common-25.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/common/25.1.2/c15c73c5ddedc9ac2afdfda827fa23a9b59b9b9d/common-25.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/manifest-merger/25.1.2/2f070c6b90be1642f37aafe15e42f21ba73394da/manifest-merger-25.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.ddms/ddmlib/25.1.2/521439862ec854d683a19a351fcc3beda4653346/ddmlib-25.1.2.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/android/tools/jack/jack-api/0.10.0/jack-api-0.10.0.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/android/tools/jill/jill-api/0.10.0/jill-api-0.10.0.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/squareup/javawriter/2.5.0/javawriter-2.5.0-sources.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/squareup/javawriter/2.5.0/javawriter-2.5.0.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/bouncycastle/bcpkix-jdk15on/1.48/bcpkix-jdk15on-1.48-sources.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/bouncycastle/bcpkix-jdk15on/1.48/bcpkix-jdk15on-1.48.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/bouncycastle/bcprov-jdk15on/1.48/bcprov-jdk15on-1.48-sources.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/bouncycastle/bcprov-jdk15on/1.48/bcprov-jdk15on-1.48.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/ow2/asm/asm-tree/5.0.3/asm-tree-5.0.3-sources.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/ow2/asm/asm-tree/5.0.3/asm-tree-5.0.3.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.lint/lint-checks/25.1.2/68583e445a033021d9792c9d84ac7ce8ea549c81/lint-checks-25.1.2.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/eclipse/jdt/core/compiler/ecj/4.4.2/ecj-4.4.2-sources.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/eclipse/jdt/core/compiler/ecj/4.4.2/ecj-4.4.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/annotations/25.1.2/9dbfadaaf19097c12787c68cf43a12c739936345/annotations-25.1.2.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/google/guava/guava/17.0/guava-17.0-sources.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/google/guava/guava/17.0/guava-17.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.databinding/baseLibrary/2.1.2/d0395908c940f4171fb024435b25f7458c1147f3/baseLibrary-2.1.2.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/tunnelvisionlabs/antlr4/4.5/antlr4-4.5.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/commons-io/commons-io/2.4/commons-io-2.4-sources.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/commons-io/commons-io/2.4/commons-io-2.4.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/googlecode/juniversalchardet/juniversalchardet/1.0.3/juniversalchardet-1.0.3.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/net/sf/proguard/proguard-base/5.2.1/proguard-base-5.2.1-sources.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/net/sf/proguard/proguard-base/5.2.1/proguard-base-5.2.1.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/ow2/asm/asm-debug-all/5.0.1/asm-debug-all-5.0.1-sources.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/ow2/asm/asm-debug-all/5.0.1/asm-debug-all-5.0.1.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/antlr/antlr-runtime/3.5.2/antlr-runtime-3.5.2.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/antlr/ST4/4.0.8/ST4-4.0.8.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.layoutlib/layoutlib-api/25.1.2/b93f0de181063ee2f673d7d6cac0bdbb94cc1b90/layoutlib-api-25.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/dvlib/25.1.2/bfcb16fb0e44568bd8e31c6aaf1850c1dcd06483/dvlib-25.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/repository/25.1.2/1a1f5f59b21a42817eec50b7aced4400bb72273b/repository-25.1.2.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/google/code/gson/gson/2.2.4/gson-2.2.4-sources.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/google/code/gson/gson/2.2.4/gson-2.2.4.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/apache/commons/commons-compress/1.8.1/commons-compress-1.8.1-sources.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/apache/commons/commons-compress/1.8.1/commons-compress-1.8.1.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/apache/httpcomponents/httpclient/4.1.1/httpclient-4.1.1-sources.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/apache/httpcomponents/httpclient/4.1.1/httpclient-4.1.1.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/apache/httpcomponents/httpmime/4.1/httpmime-4.1-sources.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/apache/httpcomponents/httpmime/4.1/httpmime-4.1.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/net/sf/kxml/kxml2/2.3.0/kxml2-2.3.0-sources.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/net/sf/kxml/kxml2/2.3.0/kxml2-2.3.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.lint/lint-api/25.1.2/f9f6807b68d486eaf34cc3f08b6f098f89cf3db8/lint-api-25.1.2.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/ow2/asm/asm-analysis/5.0.3/asm-analysis-5.0.3-sources.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/ow2/asm/asm-analysis/5.0.3/asm-analysis-5.0.3.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/tunnelvisionlabs/antlr4-runtime/4.5/antlr4-runtime-4.5.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/tunnelvisionlabs/antlr4-annotations/4.5/antlr4-annotations-4.5.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/intellij/annotations/12.0/annotations-12.0-sources.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/intellij/annotations/12.0/annotations-12.0.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/apache/httpcomponents/httpcore/4.1/httpcore-4.1-sources.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/apache/httpcomponents/httpcore/4.1/httpcore-4.1.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/commons-logging/commons-logging/1.1.1/commons-logging-1.1.1-sources.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/commons-logging/commons-logging/1.1.1/commons-logging-1.1.1.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/commons-codec/commons-codec/1.4/commons-codec-1.4-sources.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/commons-codec/commons-codec/1.4/commons-codec-1.4.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/android/tools/external/lombok/lombok-ast/0.2.3/lombok-ast-0.2.3-sources.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/android/tools/external/lombok/lombok-ast/0.2.3/lombok-ast-0.2.3.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/abego/treelayout/org.abego.treelayout.core/1.0.1/org.abego.treelayout.core-1.0.1.jar" />
+                          </list>
+                        </option>
+                        <option name="path" value="$PROJECT_DIR$" />
+                      </ExternalModuleBuildClasspathPojo>
+                    </value>
+                  </entry>
+                </map>
+              </option>
+              <option name="name" value="xscreensaver" />
+              <option name="projectBuildClasspath">
+                <list>
+                  <option value="$PROJECT_DIR$/buildSrc/src/main/java" />
+                  <option value="$PROJECT_DIR$/buildSrc/src/main/groovy" />
+                </list>
+              </option>
+            </ExternalProjectBuildClasspathPojo>
+          </value>
+        </entry>
+      </map>
+    </option>
+    <option name="externalProjectsViewState">
+      <projects_view />
+    </option>
+  </component>
+  <component name="ProjectFrameBounds">
+    <option name="x" value="73" />
+    <option name="y" value="23" />
+    <option name="width" value="1137" />
+    <option name="height" value="1029" />
+  </component>
+  <component name="ProjectLevelVcsManager" settingsEditedManually="false">
+    <OptionsSetting value="true" id="Add" />
+    <OptionsSetting value="true" id="Remove" />
+    <OptionsSetting value="true" id="Checkout" />
+    <OptionsSetting value="true" id="Update" />
+    <OptionsSetting value="true" id="Status" />
+    <OptionsSetting value="true" id="Edit" />
+    <ConfirmationsSetting value="0" id="Add" />
+    <ConfirmationsSetting value="0" id="Remove" />
+  </component>
+  <component name="ProjectView">
+    <navigator currentView="AndroidView" proportions="" version="1">
+      <flattenPackages />
+      <showMembers />
+      <showModules />
+      <showLibraryContents />
+      <hideEmptyPackages />
+      <abbreviatePackageNames />
+      <autoscrollToSource />
+      <autoscrollFromSource />
+      <sortByType />
+      <manualOrder />
+      <foldersAlwaysOnTop value="true" />
+    </navigator>
+    <panes>
+      <pane id="ProjectPane" />
+      <pane id="PackagesPane" />
+      <pane id="Scope" />
+      <pane id="AndroidView">
+        <subPane>
+          <PATH>
+            <PATH_ELEMENT>
+              <option name="myItemId" value="xscreensaver" />
+              <option name="myItemType" value="com.android.tools.idea.navigator.nodes.AndroidViewProjectNode" />
+            </PATH_ELEMENT>
+          </PATH>
+        </subPane>
+      </pane>
+      <pane id="Scratches" />
+    </panes>
+  </component>
+  <component name="PropertiesComponent">
+    <property name="GoToClass.includeLibraries" value="false" />
+    <property name="GoToClass.toSaveIncludeLibraries" value="false" />
+    <property name="GoToFile.includeJavaFiles" value="false" />
+    <property name="MemberChooser.sorted" value="false" />
+    <property name="MemberChooser.showClasses" value="true" />
+    <property name="MemberChooser.copyJavadoc" value="false" />
+    <property name="settings.editor.selected.configurable" value="android.sdk-updates" />
+    <property name="settings.editor.splitter.proportion" value="0.2" />
+    <property name="SearchEverywhereHistoryKey" value="sdk manager&#9;ACTION&#9;WelcomeScreen.RunAndroidSdkManager" />
+  </component>
+  <component name="RunManager" selected="Android App.xscreensaver">
+    <configuration default="true" type="AndroidRunConfigurationType" factoryName="Android App">
+      <module name="" />
+      <option name="DEPLOY" value="true" />
+      <option name="ARTIFACT_NAME" value="" />
+      <option name="PM_INSTALL_OPTIONS" value="" />
+      <option name="ACTIVITY_EXTRA_FLAGS" value="" />
+      <option name="MODE" value="default_activity" />
+      <option name="TARGET_SELECTION_MODE" value="SHOW_DIALOG" />
+      <option name="PREFERRED_AVD" value="" />
+      <option name="CLEAR_LOGCAT" value="false" />
+      <option name="SHOW_LOGCAT_AUTOMATICALLY" value="false" />
+      <option name="SKIP_NOOP_APK_INSTALLATIONS" value="true" />
+      <option name="FORCE_STOP_RUNNING_APP" value="true" />
+      <option name="DEBUGGER_TYPE" value="Auto" />
+      <option name="USE_LAST_SELECTED_DEVICE" value="false" />
+      <option name="PREFERRED_AVD" value="" />
+      <option name="SELECTED_CLOUD_MATRIX_CONFIGURATION_ID" value="-1" />
+      <option name="SELECTED_CLOUD_MATRIX_PROJECT_ID" value="" />
+      <Auto>
+        <option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
+        <option name="WORKING_DIR" value="" />
+        <option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
+      </Auto>
+      <Hybrid>
+        <option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
+        <option name="WORKING_DIR" value="" />
+        <option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
+      </Hybrid>
+      <Java />
+      <Native>
+        <option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
+        <option name="WORKING_DIR" value="" />
+        <option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
+      </Native>
+      <Profilers>
+        <option name="ENABLE_ADVANCED_PROFILING" value="true" />
+        <option name="GAPID_ENABLED" value="false" />
+        <option name="GAPID_DISABLE_PCS" value="false" />
+        <option name="SUPPORT_LIB_ENABLED" value="true" />
+        <option name="INSTRUMENTATION_ENABLED" value="true" />
+      </Profilers>
+      <option name="DEEP_LINK" value="" />
+      <option name="ACTIVITY_CLASS" value="" />
+      <method />
+    </configuration>
+    <configuration default="true" type="Application" factoryName="Application">
+      <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
+      <option name="MAIN_CLASS_NAME" />
+      <option name="VM_PARAMETERS" />
+      <option name="PROGRAM_PARAMETERS" />
+      <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
+      <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
+      <option name="ALTERNATIVE_JRE_PATH" />
+      <option name="ENABLE_SWING_INSPECTOR" value="false" />
+      <option name="ENV_VARIABLES" />
+      <option name="PASS_PARENT_ENVS" value="true" />
+      <module name="" />
+      <envs />
+      <method />
+    </configuration>
+    <configuration default="true" type="JUnit" factoryName="JUnit">
+      <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
+      <module name="" />
+      <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
+      <option name="ALTERNATIVE_JRE_PATH" />
+      <option name="PACKAGE_NAME" />
+      <option name="MAIN_CLASS_NAME" />
+      <option name="METHOD_NAME" />
+      <option name="TEST_OBJECT" value="class" />
+      <option name="VM_PARAMETERS" value="-ea" />
+      <option name="PARAMETERS" />
+      <option name="WORKING_DIRECTORY" value="$MODULE_DIR$" />
+      <option name="ENV_VARIABLES" />
+      <option name="PASS_PARENT_ENVS" value="true" />
+      <option name="TEST_SEARCH_SCOPE">
+        <value defaultName="singleModule" />
+      </option>
+      <envs />
+      <patterns />
+      <method>
+        <option name="Make" enabled="false" />
+        <option name="Android.Gradle.BeforeRunTask" enabled="true" />
+      </method>
+    </configuration>
+    <configuration default="true" type="Remote" factoryName="Remote">
+      <option name="USE_SOCKET_TRANSPORT" value="true" />
+      <option name="SERVER_MODE" value="false" />
+      <option name="SHMEM_ADDRESS" value="javadebug" />
+      <option name="HOST" value="localhost" />
+      <option name="PORT" value="5005" />
+      <method />
+    </configuration>
+    <configuration default="true" type="TestNG" factoryName="TestNG">
+      <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
+      <module name="" />
+      <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
+      <option name="ALTERNATIVE_JRE_PATH" />
+      <option name="SUITE_NAME" />
+      <option name="PACKAGE_NAME" />
+      <option name="MAIN_CLASS_NAME" />
+      <option name="METHOD_NAME" />
+      <option name="GROUP_NAME" />
+      <option name="TEST_OBJECT" value="CLASS" />
+      <option name="VM_PARAMETERS" value="-ea" />
+      <option name="PARAMETERS" />
+      <option name="WORKING_DIRECTORY" value="$MODULE_DIR$" />
+      <option name="OUTPUT_DIRECTORY" />
+      <option name="ANNOTATION_TYPE" />
+      <option name="ENV_VARIABLES" />
+      <option name="PASS_PARENT_ENVS" value="true" />
+      <option name="TEST_SEARCH_SCOPE">
+        <value defaultName="singleModule" />
+      </option>
+      <option name="USE_DEFAULT_REPORTERS" value="false" />
+      <option name="PROPERTIES_FILE" />
+      <envs />
+      <properties />
+      <listeners />
+      <method />
+    </configuration>
+    <configuration default="false" name="xscreensaver" type="AndroidRunConfigurationType" factoryName="Android App">
+      <module name="xscreensaver" />
+      <option name="DEPLOY" value="true" />
+      <option name="ARTIFACT_NAME" value="" />
+      <option name="PM_INSTALL_OPTIONS" value="" />
+      <option name="ACTIVITY_EXTRA_FLAGS" value="" />
+      <option name="MODE" value="default_activity" />
+      <option name="TARGET_SELECTION_MODE" value="SHOW_DIALOG" />
+      <option name="PREFERRED_AVD" value="" />
+      <option name="CLEAR_LOGCAT" value="false" />
+      <option name="SHOW_LOGCAT_AUTOMATICALLY" value="false" />
+      <option name="SKIP_NOOP_APK_INSTALLATIONS" value="true" />
+      <option name="FORCE_STOP_RUNNING_APP" value="true" />
+      <option name="DEBUGGER_TYPE" value="Auto" />
+      <option name="USE_LAST_SELECTED_DEVICE" value="false" />
+      <option name="PREFERRED_AVD" value="" />
+      <option name="SELECTED_CLOUD_MATRIX_CONFIGURATION_ID" value="-1" />
+      <option name="SELECTED_CLOUD_MATRIX_PROJECT_ID" value="" />
+      <Auto>
+        <option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
+        <option name="WORKING_DIR" value="" />
+        <option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
+      </Auto>
+      <Hybrid>
+        <option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
+        <option name="WORKING_DIR" value="" />
+        <option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
+      </Hybrid>
+      <Java />
+      <Native>
+        <option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
+        <option name="WORKING_DIR" value="" />
+        <option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
+      </Native>
+      <Profilers>
+        <option name="ENABLE_ADVANCED_PROFILING" value="true" />
+        <option name="GAPID_ENABLED" value="false" />
+        <option name="GAPID_DISABLE_PCS" value="false" />
+        <option name="SUPPORT_LIB_ENABLED" value="true" />
+        <option name="INSTRUMENTATION_ENABLED" value="true" />
+      </Profilers>
+      <option name="DEEP_LINK" value="" />
+      <option name="ACTIVITY_CLASS" value="" />
+      <method />
+    </configuration>
+    <list size="1">
+      <item index="0" class="java.lang.String" itemvalue="Android App.xscreensaver" />
+    </list>
+    <configuration name="&lt;template&gt;" type="Applet" default="true" selected="false">
+      <option name="MAIN_CLASS_NAME" />
+      <option name="HTML_FILE_NAME" />
+      <option name="HTML_USED" value="false" />
+      <option name="WIDTH" value="400" />
+      <option name="HEIGHT" value="300" />
+      <option name="POLICY_FILE" value="$APPLICATION_HOME_DIR$/bin/appletviewer.policy" />
+      <option name="VM_PARAMETERS" />
+    </configuration>
+    <configuration name="&lt;template&gt;" type="#org.jetbrains.idea.devkit.run.PluginConfigurationType" default="true" selected="false">
+      <option name="VM_PARAMETERS" value="-Xmx512m -Xms256m -XX:MaxPermSize=250m -ea" />
+    </configuration>
+  </component>
+  <component name="ShelveChangesManager" show_recycled="false">
+    <option name="remove_strategy" value="false" />
+  </component>
+  <component name="SvnConfiguration">
+    <configuration />
+  </component>
+  <component name="TaskManager">
+    <task active="true" id="Default" summary="Default task">
+      <changelist id="41008724-035d-4e24-92b6-6dfb9231c83c" name="Default" comment="" />
+      <created>1475536195508</created>
+      <option name="number" value="Default" />
+      <option name="presentableId" value="Default" />
+      <updated>1475536195508</updated>
+    </task>
+    <servers />
+  </component>
+  <component name="ToolWindowManager">
+    <frame x="73" y="23" width="1137" height="1029" extended-state="0" />
+    <editor active="false" />
+    <layout>
+      <window_info id="Nl-Palette" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
+      <window_info id="Build Variants" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="true" content_ui="tabs" />
+      <window_info id="Event Log" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="true" content_ui="tabs" />
+      <window_info id="Android Monitor" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
+      <window_info id="Properties" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
+      <window_info id="Capture Tool" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
+      <window_info id="Designer" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
+      <window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
+      <window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
+      <window_info id="Android Model" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="true" content_ui="tabs" />
+      <window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" />
+      <window_info id="Messages" active="true" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.32968238" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
+      <window_info id="Palette&#9;" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
+      <window_info id="Image Layers" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
+      <window_info id="Capture Analysis" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
+      <window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
+      <window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
+      <window_info id="Terminal" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
+      <window_info id="Captures" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
+      <window_info id="Gradle Console" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="true" content_ui="tabs" />
+      <window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.2547945" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
+      <window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32968238" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
+      <window_info id="Gradle" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
+      <window_info id="Theme Preview" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
+      <window_info id="Favorites" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="true" content_ui="tabs" />
+      <window_info id="Cvs" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="4" side_tool="false" content_ui="tabs" />
+      <window_info id="Message" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
+      <window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="SLIDING" type="SLIDING" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
+      <window_info id="Inspection" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="5" side_tool="false" content_ui="tabs" />
+      <window_info id="Hierarchy" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="2" side_tool="false" content_ui="combo" />
+      <window_info id="Ant Build" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
+    </layout>
+  </component>
+  <component name="VcsContentAnnotationSettings">
+    <option name="myLimit" value="2678400000" />
+  </component>
+  <component name="XDebuggerManager">
+    <breakpoint-manager />
+    <watches-manager />
+  </component>
+</project>
\ No newline at end of file
index 0700c946e45c6943bce3c6e0bce710cdb5386038..c0f9f1009c49e7dabfd9f0c837aa49200890daef 100644 (file)
@@ -46,7 +46,8 @@ android {
        Properties properties = new Properties()
          properties.load(project.rootProject.file('local.properties').newDataInputStream())
        def ndkDir = properties.getProperty('ndk.dir')
-       commandLine "$ndkDir/ndk-build", '-C', file('jni').absolutePath
+       commandLine "$ndkDir/ndk-build", '-C', file('jni').absolutePath,
+          '-j' + Runtime.getRuntime().availableProcessors().toString()
     }
 
     // generate files early in the process
diff --git a/android/project/xscreensaver/gradle/wrapper/gradle-wrapper.jar b/android/project/xscreensaver/gradle/wrapper/gradle-wrapper.jar
new file mode 100644 (file)
index 0000000..13372ae
Binary files /dev/null and b/android/project/xscreensaver/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/android/project/xscreensaver/gradle/wrapper/gradle-wrapper.properties b/android/project/xscreensaver/gradle/wrapper/gradle-wrapper.properties
new file mode 100644 (file)
index 0000000..04e285f
--- /dev/null
@@ -0,0 +1,6 @@
+#Mon Dec 28 10:00:20 PST 2015
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip
diff --git a/android/project/xscreensaver/gradlew b/android/project/xscreensaver/gradlew
new file mode 100644 (file)
index 0000000..9d82f78
--- /dev/null
@@ -0,0 +1,160 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+##  Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+    echo "$*"
+}
+
+die ( ) {
+    echo
+    echo "$*"
+    echo
+    exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+  CYGWIN* )
+    cygwin=true
+    ;;
+  Darwin* )
+    darwin=true
+    ;;
+  MINGW* )
+    msys=true
+    ;;
+esac
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+        PRG="$link"
+    else
+        PRG=`dirname "$PRG"`"/$link"
+    fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+        JAVACMD="$JAVA_HOME/bin/java"
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD="java"
+    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+    MAX_FD_LIMIT=`ulimit -H -n`
+    if [ $? -eq 0 ] ; then
+        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+            MAX_FD="$MAX_FD_LIMIT"
+        fi
+        ulimit -n $MAX_FD
+        if [ $? -ne 0 ] ; then
+            warn "Could not set maximum file descriptor limit: $MAX_FD"
+        fi
+    else
+        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+    fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+    JAVACMD=`cygpath --unix "$JAVACMD"`
+
+    # We build the pattern for arguments to be converted via cygpath
+    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+    SEP=""
+    for dir in $ROOTDIRSRAW ; do
+        ROOTDIRS="$ROOTDIRS$SEP$dir"
+        SEP="|"
+    done
+    OURCYGPATTERN="(^($ROOTDIRS))"
+    # Add a user-defined pattern to the cygpath arguments
+    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+    fi
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    i=0
+    for arg in "$@" ; do
+        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
+
+        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
+            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+        else
+            eval `echo args$i`="\"$arg\""
+        fi
+        i=$((i+1))
+    done
+    case $i in
+        (0) set -- ;;
+        (1) set -- "$args0" ;;
+        (2) set -- "$args0" "$args1" ;;
+        (3) set -- "$args0" "$args1" "$args2" ;;
+        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+    esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+    JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/android/project/xscreensaver/gradlew.bat b/android/project/xscreensaver/gradlew.bat
new file mode 100644 (file)
index 0000000..aec9973
--- /dev/null
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off\r
+@rem ##########################################################################\r
+@rem\r
+@rem  Gradle startup script for Windows\r
+@rem\r
+@rem ##########################################################################\r
+\r
+@rem Set local scope for the variables with windows NT shell\r
+if "%OS%"=="Windows_NT" setlocal\r
+\r
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\r
+set DEFAULT_JVM_OPTS=\r
+\r
+set DIRNAME=%~dp0\r
+if "%DIRNAME%" == "" set DIRNAME=.\r
+set APP_BASE_NAME=%~n0\r
+set APP_HOME=%DIRNAME%\r
+\r
+@rem Find java.exe\r
+if defined JAVA_HOME goto findJavaFromJavaHome\r
+\r
+set JAVA_EXE=java.exe\r
+%JAVA_EXE% -version >NUL 2>&1\r
+if "%ERRORLEVEL%" == "0" goto init\r
+\r
+echo.\r
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\r
+echo.\r
+echo Please set the JAVA_HOME variable in your environment to match the\r
+echo location of your Java installation.\r
+\r
+goto fail\r
+\r
+:findJavaFromJavaHome\r
+set JAVA_HOME=%JAVA_HOME:"=%\r
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe\r
+\r
+if exist "%JAVA_EXE%" goto init\r
+\r
+echo.\r
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\r
+echo.\r
+echo Please set the JAVA_HOME variable in your environment to match the\r
+echo location of your Java installation.\r
+\r
+goto fail\r
+\r
+:init\r
+@rem Get command-line arguments, handling Windowz variants\r
+\r
+if not "%OS%" == "Windows_NT" goto win9xME_args\r
+if "%@eval[2+2]" == "4" goto 4NT_args\r
+\r
+:win9xME_args\r
+@rem Slurp the command line arguments.\r
+set CMD_LINE_ARGS=\r
+set _SKIP=2\r
+\r
+:win9xME_args_slurp\r
+if "x%~1" == "x" goto execute\r
+\r
+set CMD_LINE_ARGS=%*\r
+goto execute\r
+\r
+:4NT_args\r
+@rem Get arguments from the 4NT Shell from JP Software\r
+set CMD_LINE_ARGS=%$\r
+\r
+:execute\r
+@rem Setup the command line\r
+\r
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar\r
+\r
+@rem Execute Gradle\r
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%\r
+\r
+:end\r
+@rem End local scope for the variables with windows NT shell\r
+if "%ERRORLEVEL%"=="0" goto mainEnd\r
+\r
+:fail\r
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\r
+rem the _cmd.exe /c_ return code!\r
+if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1\r
+exit /b 1\r
+\r
+:mainEnd\r
+if "%OS%"=="Windows_NT" endlocal\r
+\r
+:omega\r
index b29a57816c69ade46f223ec81e1f8a711ac19408..d1f00b74848e11e995c653186b7699071e3acd37 100644 (file)
@@ -1,4 +1,4 @@
-LOCAL_PATH := $(call my-dir)
+LOCAL_PATH := $(call my-dir)/../../../..
 
 include $(CLEAR_VARS)
 
@@ -6,138 +6,137 @@ LOCAL_MODULE := xscreensaver
 
 # The base framework files:
 LOCAL_SRC_FILES := \
-    xscreensaver/android/screenhack-android.c \
-    xscreensaver/android/grabscreen-android.c \
-    xscreensaver/jwxyz/jwxyz-android.c \
-    xscreensaver/jwxyz/jwxyz-common.c \
-    xscreensaver/jwxyz/jwxyz-gl.c \
-    xscreensaver/jwxyz/jwxyz-timers.c \
-    xscreensaver/jwxyz/jwzgles.c \
+    android/screenhack-android.c \
+    jwxyz/jwxyz-android.c \
+    jwxyz/jwxyz-common.c \
+    jwxyz/jwxyz-gl.c \
+    jwxyz/jwxyz-timers.c \
+    jwxyz/jwzgles.c \
 
 # Utilities used by the hacks:
 LOCAL_SRC_FILES += \
-    xscreensaver/hacks/analogtv.c \
-    xscreensaver/hacks/delaunay.c \
-    xscreensaver/hacks/fps.c \
-    xscreensaver/hacks/glx/dropshadow.c \
-    xscreensaver/hacks/glx/chessmodels.c \
-    xscreensaver/hacks/glx/fps-gl.c \
-    xscreensaver/hacks/glx/gltrackball.c \
-    xscreensaver/hacks/glx/glut_stroke.c \
-    xscreensaver/hacks/glx/glut_swidth.c \
-    xscreensaver/hacks/glx/grab-ximage.c \
-    xscreensaver/hacks/glx/marching.c \
-    xscreensaver/hacks/glx/normals.c \
-    xscreensaver/hacks/glx/rotator.c \
-    xscreensaver/hacks/glx/sphere.c \
-    xscreensaver/hacks/glx/texfont.c \
-    xscreensaver/hacks/glx/trackball.c \
-    xscreensaver/hacks/glx/tube.c \
-    xscreensaver/hacks/glx/xpm-ximage.c \
-    xscreensaver/hacks/xlockmore.c \
-    xscreensaver/hacks/xpm-pixmap.c \
-    xscreensaver/utils/async_netdb.c \
-    xscreensaver/utils/aligned_malloc.c \
-    xscreensaver/utils/colorbars.c \
-    xscreensaver/utils/colors.c \
-    xscreensaver/utils/erase.c \
-    xscreensaver/utils/grabclient.c \
-    xscreensaver/utils/hsv.c \
-    xscreensaver/utils/logo.c \
-    xscreensaver/utils/minixpm.c \
-    xscreensaver/utils/resources.c \
-    xscreensaver/utils/spline.c \
-    xscreensaver/utils/textclient-mobile.c \
-    xscreensaver/utils/thread_util.c \
-    xscreensaver/utils/usleep.c \
-    xscreensaver/utils/utf8wc.c \
-    xscreensaver/utils/xft.c \
-    xscreensaver/utils/yarandom.c \
+    hacks/analogtv.c \
+    hacks/delaunay.c \
+    hacks/fps.c \
+    hacks/glx/dropshadow.c \
+    hacks/glx/chessmodels.c \
+    hacks/glx/fps-gl.c \
+    hacks/glx/gltrackball.c \
+    hacks/glx/glut_stroke.c \
+    hacks/glx/glut_swidth.c \
+    hacks/glx/grab-ximage.c \
+    hacks/glx/marching.c \
+    hacks/glx/normals.c \
+    hacks/glx/rotator.c \
+    hacks/glx/sphere.c \
+    hacks/glx/texfont.c \
+    hacks/glx/trackball.c \
+    hacks/glx/tube.c \
+    hacks/glx/xpm-ximage.c \
+    hacks/xlockmore.c \
+    hacks/xpm-pixmap.c \
+    utils/async_netdb.c \
+    utils/aligned_malloc.c \
+    utils/colorbars.c \
+    utils/colors.c \
+    utils/erase.c \
+    utils/grabclient.c \
+    utils/hsv.c \
+    utils/logo.c \
+    utils/minixpm.c \
+    utils/resources.c \
+    utils/spline.c \
+    utils/textclient-mobile.c \
+    utils/thread_util.c \
+    utils/usleep.c \
+    utils/utf8wc.c \
+    utils/xft.c \
+    utils/yarandom.c \
 
 # The source files of all of the currently active hacks:
 LOCAL_SRC_FILES += $(shell \
   for f in $$ANDROID_HACKS ; do \
     if [ "$$f" = "companioncube" ]; then f="companion"; fi ; \
     if [ -f "../../../../hacks/$$f.c" ]; then \
-      echo "xscreensaver/hacks/$$f.c" ; \
+      echo "hacks/$$f.c" ; \
     else \
-      echo "xscreensaver/hacks/glx/$$f.c" ; \
+      echo "hacks/glx/$$f.c" ; \
     fi ; \
   done )
 
 # Some savers occupy more than one source file:
 LOCAL_SRC_FILES += \
-    xscreensaver/hacks/apple2-main.c \
-    xscreensaver/hacks/asm6502.c \
-    xscreensaver/hacks/pacman_ai.c \
-    xscreensaver/hacks/pacman_level.c \
-    xscreensaver/hacks/glx/b_draw.c \
-    xscreensaver/hacks/glx/b_lockglue.c \
-    xscreensaver/hacks/glx/b_sphere.c \
-    xscreensaver/hacks/glx/buildlwo.c \
-    xscreensaver/hacks/glx/companion_quad.c \
-    xscreensaver/hacks/glx/companion_disc.c \
-    xscreensaver/hacks/glx/companion_heart.c \
-    xscreensaver/hacks/glx/cow_face.c \
-    xscreensaver/hacks/glx/cow_hide.c \
-    xscreensaver/hacks/glx/cow_hoofs.c \
-    xscreensaver/hacks/glx/cow_horns.c \
-    xscreensaver/hacks/glx/cow_tail.c \
-    xscreensaver/hacks/glx/cow_udder.c \
-    xscreensaver/hacks/glx/dolphin.c \
-    xscreensaver/hacks/glx/gllist.c \
-    xscreensaver/hacks/glx/glschool_alg.c \
-    xscreensaver/hacks/glx/glschool_gl.c \
-    xscreensaver/hacks/glx/involute.c \
-    xscreensaver/hacks/glx/lament_model.c \
-    xscreensaver/hacks/glx/pipeobjs.c \
-    xscreensaver/hacks/glx/robot.c \
-    xscreensaver/hacks/glx/robot-wireframe.c \
-    xscreensaver/hacks/glx/polyhedra-gl.c \
-    xscreensaver/hacks/glx/s1_1.c \
-    xscreensaver/hacks/glx/s1_2.c \
-    xscreensaver/hacks/glx/s1_3.c \
-    xscreensaver/hacks/glx/s1_4.c \
-    xscreensaver/hacks/glx/s1_5.c \
-    xscreensaver/hacks/glx/s1_6.c \
-    xscreensaver/hacks/glx/s1_b.c \
-    xscreensaver/hacks/glx/shark.c \
-    xscreensaver/hacks/glx/sonar-sim.c \
-    xscreensaver/hacks/glx/sonar-icmp.c \
-    xscreensaver/hacks/glx/splitflap_obj.c \
-    xscreensaver/hacks/glx/sproingiewrap.c \
-    xscreensaver/hacks/glx/stonerview-move.c \
-    xscreensaver/hacks/glx/stonerview-osc.c \
-    xscreensaver/hacks/glx/stonerview-view.c \
-    xscreensaver/hacks/glx/swim.c \
-    xscreensaver/hacks/glx/tangram_shapes.c \
-    xscreensaver/hacks/glx/teapot.c \
-    xscreensaver/hacks/glx/toast.c \
-    xscreensaver/hacks/glx/toast2.c \
-    xscreensaver/hacks/glx/toaster.c \
-    xscreensaver/hacks/glx/toaster_base.c \
-    xscreensaver/hacks/glx/toaster_handle.c \
-    xscreensaver/hacks/glx/toaster_handle2.c \
-    xscreensaver/hacks/glx/toaster_jet.c \
-    xscreensaver/hacks/glx/toaster_knob.c \
-    xscreensaver/hacks/glx/toaster_slots.c \
-    xscreensaver/hacks/glx/toaster_wing.c \
-    xscreensaver/hacks/glx/tronbit_idle1.c \
-    xscreensaver/hacks/glx/tronbit_idle2.c \
-    xscreensaver/hacks/glx/tronbit_no.c \
-    xscreensaver/hacks/glx/tronbit_yes.c \
-    xscreensaver/hacks/glx/tunnel_draw.c \
-    xscreensaver/hacks/glx/whale.c \
+    hacks/apple2-main.c \
+    hacks/asm6502.c \
+    hacks/pacman_ai.c \
+    hacks/pacman_level.c \
+    hacks/glx/b_draw.c \
+    hacks/glx/b_lockglue.c \
+    hacks/glx/b_sphere.c \
+    hacks/glx/buildlwo.c \
+    hacks/glx/companion_quad.c \
+    hacks/glx/companion_disc.c \
+    hacks/glx/companion_heart.c \
+    hacks/glx/cow_face.c \
+    hacks/glx/cow_hide.c \
+    hacks/glx/cow_hoofs.c \
+    hacks/glx/cow_horns.c \
+    hacks/glx/cow_tail.c \
+    hacks/glx/cow_udder.c \
+    hacks/glx/dolphin.c \
+    hacks/glx/gllist.c \
+    hacks/glx/glschool_alg.c \
+    hacks/glx/glschool_gl.c \
+    hacks/glx/involute.c \
+    hacks/glx/lament_model.c \
+    hacks/glx/pipeobjs.c \
+    hacks/glx/robot.c \
+    hacks/glx/robot-wireframe.c \
+    hacks/glx/polyhedra-gl.c \
+    hacks/glx/s1_1.c \
+    hacks/glx/s1_2.c \
+    hacks/glx/s1_3.c \
+    hacks/glx/s1_4.c \
+    hacks/glx/s1_5.c \
+    hacks/glx/s1_6.c \
+    hacks/glx/s1_b.c \
+    hacks/glx/shark.c \
+    hacks/glx/sonar-sim.c \
+    hacks/glx/sonar-icmp.c \
+    hacks/glx/splitflap_obj.c \
+    hacks/glx/sproingiewrap.c \
+    hacks/glx/stonerview-move.c \
+    hacks/glx/stonerview-osc.c \
+    hacks/glx/stonerview-view.c \
+    hacks/glx/swim.c \
+    hacks/glx/tangram_shapes.c \
+    hacks/glx/teapot.c \
+    hacks/glx/toast.c \
+    hacks/glx/toast2.c \
+    hacks/glx/toaster.c \
+    hacks/glx/toaster_base.c \
+    hacks/glx/toaster_handle.c \
+    hacks/glx/toaster_handle2.c \
+    hacks/glx/toaster_jet.c \
+    hacks/glx/toaster_knob.c \
+    hacks/glx/toaster_slots.c \
+    hacks/glx/toaster_wing.c \
+    hacks/glx/tronbit_idle1.c \
+    hacks/glx/tronbit_idle2.c \
+    hacks/glx/tronbit_no.c \
+    hacks/glx/tronbit_yes.c \
+    hacks/glx/tunnel_draw.c \
+    hacks/glx/whale.c \
 
 LOCAL_LDLIBS := -lGLESv1_CM -ldl -llog -lEGL
 
 LOCAL_C_INCLUDES := \
-       $(LOCAL_PATH)/xscreensaver \
-       $(LOCAL_PATH)/xscreensaver/android \
-       $(LOCAL_PATH)/xscreensaver/utils \
-       $(LOCAL_PATH)/xscreensaver/jwxyz \
-       $(LOCAL_PATH)/xscreensaver/hacks \
-       $(LOCAL_PATH)/xscreensaver/hacks/glx \
+       $(LOCAL_PATH) \
+       $(LOCAL_PATH)/android \
+       $(LOCAL_PATH)/utils \
+       $(LOCAL_PATH)/jwxyz \
+       $(LOCAL_PATH)/hacks \
+       $(LOCAL_PATH)/hacks/glx \
 
 # -Wnested-externs would also be here, but for Android unistd.h.
 LOCAL_CFLAGS += \
diff --git a/android/project/xscreensaver/jni/xscreensaver b/android/project/xscreensaver/jni/xscreensaver
deleted file mode 120000 (symlink)
index c866b86..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../../..
\ No newline at end of file
diff --git a/android/project/xscreensaver/local.properties b/android/project/xscreensaver/local.properties
new file mode 100644 (file)
index 0000000..d530e0d
--- /dev/null
@@ -0,0 +1,11 @@
+## This file is automatically generated by Android Studio.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must *NOT* be checked into Version Control Systems,
+# as it contains information specific to your local configuration.
+#
+# Location of the SDK. This is only used by Gradle.
+# For customization when using a Version Control System, please read the
+# header note.
+#Mon Oct 03 16:09:56 PDT 2016
+sdk.dir=/Users/jwz/Library/Android/sdk
index ea04df070cc333300ab9ad64abedb21ce8236352..8824dbe1d3f6071a49a39a871bd18020df913f15 100644 (file)
@@ -106,18 +106,21 @@ public class XScreenSaverDaydream extends DreamService
 
     // Extract the saver name from e.g. "BouncingCowDaydream"
     String name = this.getClass().getSimpleName();
-    String tail = "Daydream";
-    if (name.endsWith(tail))
-      name = name.substring (0, name.length() - tail.length());
+    int index = name.lastIndexOf('$');
+    if (index != -1) {
+      index++;
+      name = name.substring (index, name.length() - index);
+    }
     name = name.toLowerCase();
 
     WindowManager wm = (WindowManager) getSystemService (WINDOW_SERVICE);
+    glview = new GLSurfaceView (this);
     renderer =
       new XScreenSaverRenderer (name, api, getApplicationContext(), wm,
-                                screenshot, this);
-
-    glview = new GLSurfaceView (this);
+                                screenshot, this, glview);
+    glview.setEGLConfigChooser (8, 8, 8, 8, 16, 0);
     glview.setRenderer (renderer);
+    glview.setRenderMode (GLSurfaceView.RENDERMODE_WHEN_DIRTY);
     setContentView (glview);
 
     detector = new GestureDetector (this, this);
index 9889ea866306c16dad8a5a497c7c8d06496c6eec..f854636cdff40e6f397f1a4a86f5388ae96d4b92 100644 (file)
@@ -22,6 +22,8 @@ import android.view.KeyEvent;
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.opengl.GLSurfaceView;
+import java.util.Timer;
+import java.util.TimerTask;
 import javax.microedition.khronos.egl.EGLConfig;
 import javax.microedition.khronos.opengles.GL10;
 import org.jwz.xscreensaver.jwxyz;
@@ -44,6 +46,16 @@ public class XScreenSaverRenderer implements GLSurfaceView.Renderer {
   WindowManager wm;
   Bitmap screenshot;
 
+  GLSurfaceView glview;
+
+  class RenderTask extends TimerTask {
+    public void run() {
+      glview.requestRender();
+    }
+  };
+
+  Timer timer = new Timer();
+
   private void LOG (String fmt, Object... args) {
     Log.d ("xscreensaver",
            this.getClass().getSimpleName() + ": " +
@@ -59,7 +71,8 @@ public class XScreenSaverRenderer implements GLSurfaceView.Renderer {
   public XScreenSaverRenderer (String hack, int api,
                                Context app, WindowManager wm,
                                Bitmap screenshot,
-                               Handler.Callback abort_callback) {
+                               Handler.Callback abort_callback,
+                               GLSurfaceView glview) {
     super();
     this.hack   = hack;
     this.api    = api;
@@ -68,13 +81,18 @@ public class XScreenSaverRenderer implements GLSurfaceView.Renderer {
     this.prefs  = prefs;
     this.screenshot = screenshot;
     this.abort_callback = abort_callback;
+    this.glview = glview;
     LOG ("init %s %d", hack, api);
   }
 
   public void onDrawFrame (GL10 gl) {
     try {
-      if (jwxyz_obj != null)
-        jwxyz_obj.nativeRender();
+      if (jwxyz_obj != null) {
+        long delay = jwxyz_obj.nativeRender();
+        // java.util.Timer doesn't seem to like to re-use TimerTasks, so
+        // there's a slow object churn here: one TimerTask per frame.
+        timer.schedule(new RenderTask(), delay / 1000);
+      }
     } catch (RuntimeException e) {
       except (e);
     }
@@ -98,6 +116,8 @@ public class XScreenSaverRenderer implements GLSurfaceView.Renderer {
 
       jwxyz_obj.nativeResize (w, h, r);
 
+      glview.requestRender();
+
     } catch (RuntimeException e) {
       except (e);
     }
index a83e8cf9c8eaaff6de0d99c5b9edb15c8621d650..1982ca49f044b16f497a3c8733b96661545dc2b0 100644 (file)
@@ -40,6 +40,8 @@ import java.nio.ByteBuffer;
 import java.io.File;
 import java.io.InputStream;
 import java.io.FileOutputStream;
+import java.lang.Runnable;
+import java.lang.Thread;
 import android.database.Cursor;
 import android.provider.MediaStore;
 import android.provider.MediaStore.MediaColumns;
@@ -66,11 +68,6 @@ public class jwxyz {
   SharedPreferences prefs;
   Hashtable<String, String> defaults = new Hashtable<String, String>();
 
-  // Maps numeric IDs to Java objects, so that C code can reference them
-  // even if GC relocates them.
-  private Hashtable<Long, Object> rootset = new Hashtable<Long, Object>();
-  private long rootset_id = 1000;
-
 
   // Maps font names to either: String (system font) or Typeface (bundled).
   private Hashtable<String, Object> all_fonts =
@@ -83,7 +80,7 @@ public class jwxyz {
                                   Hashtable<String,String> defaults,
                                   int w, int h);
   public native void nativeResize (int w, int h, double rot);
-  public native void nativeRender ();
+  public native long nativeRender ();
   public native void nativeDone ();
   public native void sendButtonEvent (int x, int y, boolean down);
   public native void sendMotionEvent (int x, int y);
@@ -354,7 +351,7 @@ public class jwxyz {
   }
 
 
-  // Returns [ Long font_id, String name, Float size, ascent, descent ]
+  // Returns [ Paint paint, String name, Float size, ascent, descent ]
   public Object[] loadFont(String name) {
     Object pair[];
 
@@ -383,34 +380,24 @@ public class jwxyz {
     paint.setTextSize (size);
     paint.setColor (Color.argb (0xFF, 0xFF, 0xFF, 0xFF));
 
-    Long font_key = new Long(rootset_id++);
-    rootset.put (font_key, paint);
-
-    LOG ("load font %s, \"%s\" = \"%s %.1f\"",
-         font_key.toString(), name, name2, size);
+    LOG ("load font \"%s\" = \"%s %.1f\"", name, name2, size);
 
     FontMetrics fm = paint.getFontMetrics();
-    Object ret[] = { font_key, name2, new Float(size),
+    Object ret[] = { paint, name2, new Float(size),
                      new Float(-fm.ascent), new Float(fm.descent) };
     return ret;
   }
 
 
-  public void releaseFont(long font_id) {
-    rootset.remove (new Long(font_id));
-  }
-
   /* Returns a byte[] array containing XCharStruct with an optional
      bitmap appended to it.
      lbearing, rbearing, width, ascent, descent: 2 bytes each.
      Followed by a WxH pixmap, 32 bits per pixel.
    */
-  public ByteBuffer renderText (long font_id, String text, boolean render_p) {
-
-    Paint paint = (Paint) rootset.get(new Long(font_id));
+  public ByteBuffer renderText (Paint paint, String text, boolean render_p) {
 
     if (paint == null) {
-      LOG ("no font %d", font_id);
+      LOG ("no font");
       return null;
     }
 
@@ -483,44 +470,78 @@ public class jwxyz {
   }
 
 
-  // Returns the contents of the URL.  Blocking load.
-  public ByteBuffer loadURL (String url) {
+  /* Returns the contents of the URL.
+     Loads the URL in a background thread: if the URL has not yet loaded,
+     this will return null.  Once the URL has completely loaded, the full
+     contents will be returned.  Calling this again after that starts the
+     URL loading again.
+   */
+  private String loading_url = null;
+  private ByteBuffer loaded_url_body = null;
 
-    int size0 = 10240;
-    int size = size0;
-    int count = 0;
-    ByteBuffer body = ByteBuffer.allocateDirect (size);
+  public synchronized ByteBuffer loadURL (String url) {
 
-    try {
-      LOG ("load URL: %s", url);
-      URL u = new URL(url);
-      InputStream s = u.openStream();
-      byte buf[] = new byte[10240];
-      while (true) {
-        int n = s.read (buf);
-        if (n == -1) break;
-        // LOG ("read %d", n);
-        if (count + n + 1 >= size) {
-          int size2 = (int) (size * 1.2 + size0);
-          // LOG ("expand %d -> %d", size, size2);
-          ByteBuffer body2 = ByteBuffer.allocateDirect (size2);
-          body.rewind();
-          body2.put (body);
-          body2.position (count);
-          body = body2;
-          size = size2;
-        }
-        body.put (buf, 0, n);
-        count += n;
-      }
-    } catch (Exception e) {
-      LOG ("load URL error: %s", e.toString());
-      body.clear();
-      body.put (e.toString().getBytes());
-      body.put ((byte) 0);
-    }
+    if (loaded_url_body != null) {                     // Thread finished
+
+      // LOG ("textclient finished %s", loading_url);
+
+      ByteBuffer bb = loaded_url_body;
+      loading_url = null;
+      loaded_url_body = null;
+      return bb;
+
+    } else if (loading_url != null) {                  // Waiting on thread
+      // LOG ("textclient waiting...");
+      return null;
 
-    return body;
+    } else {                                           // Launch thread
+
+      loading_url = url;
+      LOG ("textclient launching %s...", url);
+
+      new Thread (new Runnable() {
+          public void run() {
+            int size0 = 10240;
+            int size = size0;
+            int count = 0;
+            ByteBuffer body = ByteBuffer.allocateDirect (size);
+
+            try {
+              URL u = new URL (loading_url);
+              // LOG ("textclient thread loading: %s", u.toString());
+              InputStream s = u.openStream();
+              byte buf[] = new byte[10240];
+              while (true) {
+                int n = s.read (buf);
+                if (n == -1) break;
+                // LOG ("textclient thread read %d", n);
+                if (count + n + 1 >= size) {
+                  int size2 = (int) (size * 1.2 + size0);
+                  // LOG ("textclient thread expand %d -> %d", size, size2);
+                  ByteBuffer body2 = ByteBuffer.allocateDirect (size2);
+                  body.rewind();
+                  body2.put (body);
+                  body2.position (count);
+                  body = body2;
+                  size = size2;
+                }
+                body.put (buf, 0, n);
+                count += n;
+              }
+            } catch (Exception e) {
+              LOG ("load URL error: %s", e.toString());
+              body.clear();
+              body.put (e.toString().getBytes());
+              body.put ((byte) 0);
+            }
+
+            // LOG ("textclient thread finished %s (%d)", loading_url, size);
+            loaded_url_body = body;
+          }
+        }).start();
+
+      return null;
+    }
   }
 
 
diff --git a/android/project/xscreensaver/xscreensaver.iml b/android/project/xscreensaver/xscreensaver.iml
new file mode 100644 (file)
index 0000000..1af1dc5
--- /dev/null
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module external.linked.project.id=":xscreensaver" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" type="JAVA_MODULE" version="4">
+  <component name="FacetManager">
+    <facet type="android-gradle" name="Android-Gradle">
+      <configuration>
+        <option name="GRADLE_PROJECT_PATH" value=":xscreensaver" />
+      </configuration>
+    </facet>
+    <facet type="android" name="Android">
+      <configuration>
+        <option name="SELECTED_BUILD_VARIANT" value="debug" />
+        <option name="SELECTED_TEST_ARTIFACT" value="_android_test_" />
+        <option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
+        <option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
+        <afterSyncTasks>
+          <task>generateDebugSources</task>
+        </afterSyncTasks>
+        <option name="ALLOW_USER_CONFIGURATION" value="false" />
+      </configuration>
+    </facet>
+  </component>
+  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="false">
+    <output url="file://$MODULE_DIR$/build/intermediates/classes/debug" />
+    <output-test url="file://$MODULE_DIR$/build/intermediates/classes/test/debug" />
+    <exclude-output />
+    <content url="file://$MODULE_DIR$">
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/debug" isTestSource="false" generated="true" />
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/debug" isTestSource="false" generated="true" />
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/debug" isTestSource="false" generated="true" />
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/debug" type="java-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/androidTest/debug" isTestSource="true" generated="true" />
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/androidTest/debug" isTestSource="true" generated="true" />
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/debug" isTestSource="true" generated="true" />
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/androidTest/debug" isTestSource="true" generated="true" />
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/androidTest/debug" type="java-test-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/androidTest/debug" type="java-test-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/build-types/debug/res" type="java-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/build-types/debug/resources" type="java-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/build-types/debug/assets" type="java-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/build-types/debug/aidl" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/build-types/debug/java" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/build-types/debug/jni" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/build-types/debug/rs" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/build-types/debug/shaders" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/src/testDebug/res" type="java-test-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/src/testDebug/resources" type="java-test-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/src/testDebug/assets" type="java-test-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/src/testDebug/aidl" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/src/testDebug/java" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/src/testDebug/jni" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/src/testDebug/rs" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/src/testDebug/shaders" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/res" type="java-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/src" type="java-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/assets" type="java-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/src/main/shaders" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/src/test/res" type="java-test-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/src/test/assets" type="java-test-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/src/test/aidl" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/src/test/jni" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/src/test/rs" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/src/test/shaders" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/shaders" isTestSource="true" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/blame" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/bundles" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-safeguard" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/instant-run-support" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/jniLibs" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/pre-dexed" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/shaders" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/transforms" />
+      <excludeFolder url="file://$MODULE_DIR$/build/outputs" />
+      <excludeFolder url="file://$MODULE_DIR$/build/tmp" />
+    </content>
+    <orderEntry type="jdk" jdkName="Android API 21 Platform" jdkType="Android SDK" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>
\ No newline at end of file
index 4f3251cd490bce33bc7a204ae3fd4f73768cc39d..c8b4fdfe9f23872b15d3bf187b10e8b1e33c890d 100644 (file)
 
 /* Define to `unsigned int' if <sys/types.h> does not define. */
 #undef size_t
+
+/* Define to `int' if <sys/types.h> or <sys/socket.h> does not define. */
+#undef socklen_t
index 75c16008e62509d01ea1dfcb39dcd4baabb71c32..b0a24cb0181dfd9683bb3ad1de2b246baea3bc39 100755 (executable)
--- a/configure
+++ b/configure
@@ -2796,6 +2796,7 @@ fi
 
 
 
+
 ###############################################################################
 #
 #       Some utility functions to make checking for X things easier.
@@ -6050,6 +6051,40 @@ $as_echo "$ac_cv_have_getifaddrs" >&6; }
    $as_echo "#define HAVE_GETIFADDRS 1" >>confdefs.h
 
  fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for socklen_t" >&5
+$as_echo_n "checking for socklen_t... " >&6; }
+if ${ac_cv_type_socklen_t+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+   #include <sys/types.h>
+   #include <sys/socket.h>
+int
+main ()
+{
+
+   socklen_t socklen;
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_type_socklen_t=yes
+else
+  ac_cv_type_socklen_t=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_socklen_t" >&5
+$as_echo "$ac_cv_type_socklen_t" >&6; }
+  if test "$ac_cv_type_socklen_t" != yes; then
+
+$as_echo "#define socklen_t int" >>confdefs.h
+
+  fi
 for ac_header in crypt.h sys/select.h
 do :
   as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
@@ -13272,7 +13307,7 @@ if ${ac_cv_mesagl_version_string+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 13279 "configure"
+#line 13314 "configure"
 #include "confdefs.h"
 #include <GL/gl.h>
 #ifndef MESA_MAJOR_VERSION
index 0098d909a83d6e72d9b8240bb487e1800ebacaa3..3c5583582f12c6efa2dd446f187edaf09d6ed5fd 100644 (file)
@@ -1048,6 +1048,17 @@ AC_DEFUN([AC_CHECK_GETIFADDRS],
    AC_DEFINE(HAVE_GETIFADDRS)
  fi])
 
+AC_DEFUN([AC_TYPE_SOCKLEN_T],
+ [AC_CACHE_CHECK([for socklen_t], ac_cv_type_socklen_t,
+  [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+   #include <sys/types.h>
+   #include <sys/socket.h>]], [[
+   socklen_t socklen;
+   ]])],[ac_cv_type_socklen_t=yes],[ac_cv_type_socklen_t=no])])
+  if test "$ac_cv_type_socklen_t" != yes; then
+    AC_DEFINE(socklen_t, int,
+  [Define to `int' if <sys/types.h> or <sys/socket.h> does not define.])
+  fi])
 
 ###############################################################################
 #
@@ -1254,6 +1265,7 @@ AC_CHECK_MEMBERS([struct sockaddr.sa_len],,, [[#include <sys/socket.h>]])
 AC_CHECK_ICMP
 AC_CHECK_ICMPHDR
 AC_CHECK_GETIFADDRS
+AC_TYPE_SOCKLEN_T
 AC_CHECK_HEADERS(crypt.h sys/select.h)
 AC_PROG_PERL
 
index c1323048c85ac9828a0a555e93f29b96bdc1b3d1..e2a600d2d82f4ccf6626c012c6a975c54bb096f6 100644 (file)
@@ -658,7 +658,6 @@ distdepend: check_men update_ad_version XScreenSaver_ad.h XScreenSaver_Xm_ad.h
              -e 's@ $$(srcdir)/\(.*config\.h\)@ \1@g' ;                    \
          echo ''                                                           \
        ) > /tmp/distdepend.$$$$ &&                                         \
-       mv Makefile.in Makefile.in.bak &&                                   \
        mv /tmp/distdepend.$$$$ Makefile.in
 
 # Updates the version number in the app-defaults file to be in sync with 
index 2b48a030e442c46e12a594fa42cf36c83ce13e4a..0e70efdc7b6c4010f2420f071f8add6b539f3b22 100644 (file)
@@ -4,8 +4,8 @@
 !            a screen saver and locker for the X window system
 !                            by Jamie Zawinski
 !
-!                              version 5.35
-!                              24-May-2016
+!                              version 5.36
+!                              10-Oct-2016
 !
 ! See "man xscreensaver" for more info.  The latest version is always
 ! available at https://www.jwz.org/xscreensaver/
@@ -371,10 +371,15 @@ GetViewPortIsFullOfLies: False
                                tessellimage -root                          \n\
 @GL_KLUDGE@ GL:                                winduprobot -root                           \n\
 @GL_KLUDGE@ GL:                                splitflap -root                             \n\
+@GL_KLUDGE@ GL:                                cubestack -root                             \n\
+@GL_KLUDGE@ GL:                                cubetwist -root                             \n\
+@GL_KLUDGE@ GL:                                discoball -root                             \n\
 @GL_KLUDGE@ GL:                                dymaxionmap -root                           \n\
 @GL_KLUDGE@ GL:                                energystream -root                          \n\
+@GL_KLUDGE@ GL:                                hexstrut -root                              \n\
 @GL_KLUDGE@ GL:                                hydrostat -root                             \n\
 @GL_KLUDGE@ GL:                                raverhoop -root                             \n\
+@GL_KLUDGE@ GL:                                splodesic -root                             \n\
 @GL_KLUDGE@ GL:                                unicrud -root                               \n
 
 
@@ -460,7 +465,9 @@ XScreenSaver.bourneShell:           /bin/sh
 *hacks.ccurve.name:         CCurve
 *hacks.cloudlife.name:      CloudLife
 *hacks.companioncube.name:  CompanionCube
+*hacks.cubestack.name:      CubeStack
 *hacks.cubestorm.name:      CubeStorm
+*hacks.cubetwist.name:      CubeTwist
 *hacks.cubicgrid.name:      CubicGrid
 *hacks.cwaves.name:         CWaves
 *hacks.dangerball.name:     DangerBall
index 5ca109b47463f9585f52d5bbb22f76121afdd178..7e0e279a4fb64d23ed7eb46d4baf1007402b7a4e 100644 (file)
                                tessellimage -root                          \\n\
   GL:                          winduprobot -root                           \\n\
   GL:                          splitflap -root                             \\n\
+  GL:                          cubestack -root                             \\n\
+  GL:                          cubetwist -root                             \\n\
+  GL:                          discoball -root                             \\n\
   GL:                          dymaxionmap -root                           \\n\
   GL:                          energystream -root                          \\n\
+  GL:                          hexstrut -root                              \\n\
   GL:                          hydrostat -root                             \\n\
   GL:                          raverhoop -root                             \\n\
+  GL:                          splodesic -root                             \\n\
   GL:                          unicrud -root                               \\n",
 "XScreenSaver.pointerPollTime:         0:00:05",
 "XScreenSaver.pointerHysteresis:               10",
 "*hacks.ccurve.name:         CCurve",
 "*hacks.cloudlife.name:      CloudLife",
 "*hacks.companioncube.name:  CompanionCube",
+"*hacks.cubestack.name:      CubeStack",
 "*hacks.cubestorm.name:      CubeStorm",
+"*hacks.cubetwist.name:      CubeTwist",
 "*hacks.cubicgrid.name:      CubicGrid",
 "*hacks.cwaves.name:         CWaves",
 "*hacks.dangerball.name:     DangerBall",
index 29ad60092daf40880afdae6d1acb064b122ec48f..0ccf7d2367bdb2d680221d4e628411b9b4a83694 100644 (file)
@@ -44,6 +44,7 @@
 #endif /* VMS */
 
 #include <signal.h>            /* for the signal names */
+#include <time.h>
 
 #if !defined(SIGCHLD) && defined(SIGCLD)
 # define SIGCHLD SIGCLD
@@ -1303,6 +1304,7 @@ get_best_gl_visual (saver_info *si, Screen *screen)
       {
         int result = 0;
         int wait_status = 0;
+        pid_t pid = -1;
 
         FILE *f = fdopen (in, "r");
         unsigned long v = 0;
@@ -1321,8 +1323,17 @@ get_best_gl_visual (saver_info *si, Screen *screen)
             close (errin);
           }
 
-        /* Wait for the child to die. */
-        waitpid (-1, &wait_status, 0);
+        /* Wait for the child to die - wait for this pid only, not others. */
+        pid = waitpid (forked, &wait_status, 0);
+        if (si->prefs.debug_p)
+          {
+            write_string (STDERR_FILENO, blurb());
+            write_string (STDERR_FILENO, ": waitpid(");
+            write_long   (STDERR_FILENO, (long) forked);
+            write_string (STDERR_FILENO, ") ==> ");
+            write_long   (STDERR_FILENO, (long) pid);
+            write_string (STDERR_FILENO, "\n");
+          }
 
         unblock_sigchld();   /* child is dead and waited, unblock now. */
 
index f22504e95e80e0f0042151c27a5aab6d027fe71f..f702f679294f7c05f353f1ed18ad5460e4987bb3 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 2001-2013 by Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 2001-2016 by 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
@@ -69,7 +69,7 @@
   /* On MacOS under X11, the usual X11 mechanism of getting a screen shot
      doesn't work, and we need to use an external program.  This is only
      used when running under X11 on MacOS.  If it's a Cocoa build, this
-     path is not taken, and OSX/osxgrabscreen.m is used instead.
+     path is not taken, and OSX/grabclient-osx.m is used instead.
    */
 # define USE_EXTERNAL_SCREEN_GRABBER
 #endif
index 1b55832d92c49422ba6675da8179d7388719f1a1..1d0170d9fbfaea30c2099a07807eace017082cc2 100755 (executable)
@@ -37,7 +37,7 @@ use Text::Wrap qw(wrap);
 use bytes;
 
 my $progname = $0; $progname =~ s@.*/@@g;
-my ($version) = ('$Revision: 1.41 $' =~ m/\s(\d[.\d]+)\s/s);
+my ($version) = ('$Revision: 1.44 $' =~ m/\s(\d[.\d]+)\s/s);
 
 my $verbose = 0;
 my $http_proxy = undef;
@@ -158,6 +158,7 @@ sub get_x11_prefs_1($) {
 
   my $got_any_p = 0;
   $body =~ s@\\\n@@gs;
+  $body =~ s@^[ \t]*#[^\n]*$@@gm;
 
   if ($body =~ m/^[.*]*textMode:[ \t]*([^\s]+)\s*$/im) {
     $text_mode = $1;
@@ -300,8 +301,9 @@ sub output() {
 
     $text_file =~ s@^~/@$ENV{HOME}/@s;     # allow literal "~/"
 
-    if (open (my $in, '<', $text_file)) {
+    if (open (my $in, '<:raw', $text_file)) {
       print STDERR "$progname: reading $text_file\n" if ($verbose);
+      binmode (STDOUT, ':raw');
 
       if (($wrap_columns && $wrap_columns > 0) || $truncate_lines) {
         # read it, then reformat it.
@@ -783,6 +785,8 @@ sub main() {
                               $load_p = 0; }
     elsif (m/^--?text$/)    { $text_mode = 'literal';
                               $text_literal = shift @ARGV || '';
+                              $text_literal =~ s@\\n@\n@gs;
+                              $text_literal =~ s@\\\n@\n@gs;
                               $load_p = 0; }
     elsif (m/^--?file$/)    { $text_mode = 'file';
                               $text_file = shift @ARGV || '';
index ccc0b6169b97e04ab749c3b321afb2ccee4bafd1..c1e25eba470a3ff8f6458cabf05fd6bdbcae99e1 100644 (file)
@@ -422,7 +422,6 @@ distdepend:: m6502.h
              -e 's@ $$(srcdir)/\(m6502.h\)@ \1@g' ;                        \
          echo ''                                                           \
        ) > /tmp/distdepend.$$$$ &&                                         \
-       mv Makefile.in Makefile.in.bak &&                                   \
        mv /tmp/distdepend.$$$$ Makefile.in
 
 TAGS: tags
index 99c7909d5b6098a1fec5bf911d224fe743bd4de3..0bc8b2603f548ea915eb3d726ef922d6b72e201a 100644 (file)
@@ -1,4 +1,4 @@
-/* analogtv, Copyright (c) 2003, 2004 Trevor Blackwell <tlb@tlb.org>
+/* analogtv, Copyright (c) 2003-2016 Trevor Blackwell <tlb@tlb.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -304,7 +304,7 @@ int analogtv_handle_events (analogtv *it);
 #else
   /* Need to really crank this up for it to look good on the iPhone screen. */
 # define ANALOGTV_DEF_BRIGHTNESS "3"
-# define ANALOGTV_DEF_CONTRAST "1000"
+# define ANALOGTV_DEF_CONTRAST "400"
 #endif
 
 #define ANALOGTV_DEFAULTS \
index 2228a38e4052b93e31d28a7f3077b2a0c7bed65e..b9b7e1e47930c88dc2e2dccea076e74f5150d2c1 100644 (file)
@@ -1874,7 +1874,7 @@ static BOOL translate(m6502_Opcodes *op,Param *param, machine_6502 *machine){
        if (op->BRA) {
          pushByte(machine, op->BRA);
           {
-            int diff = (param->lbladdr - machine->defaultCodePC);
+            int diff = abs((int)param->lbladdr - (int)machine->defaultCodePC);
             int backward = (param->lbladdr < machine->defaultCodePC);
             pushByte(machine, (backward) ? 0xff - diff : diff - 1);
           }
index d4ec71990875cf965b69944cc773b60208411a95..f8bba1decee5947a48ee4e9e0c61b7937443ee19 100755 (executable)
@@ -21,7 +21,7 @@ use diagnostics;
 use strict;
 
 my $progname = $0; $progname =~ s@.*/@@g;
-my ($version) = ('$Revision: 1.21 $' =~ m/\s(\d[.\d]+)\s/s);
+my ($version) = ('$Revision: 1.22 $' =~ m/\s(\d[.\d]+)\s/s);
 
 my $verbose = 0;
 my $debug_p = 0;
@@ -204,6 +204,8 @@ sub parse_src($) {
   return (\%res_to_val, \%switch_to_res);
 }
 
+my %video_dups;
+
 # Returns a list of:
 #    "resource = default value"
 # or "resource != non-default value"
@@ -427,6 +429,13 @@ sub parse_xml($$$) {
 #  error ("$file: no video") unless $video;
   print STDERR "\n$file: WARNING: no video\n\n" unless $video;
 
+  if ($video && $video_dups{$video} && 
+      $video_dups{$video} ne $saver_title) {
+    print STDERR "\n$file: WARNING: $saver_title: dup video with " .
+      $video_dups{$video} . "\n";
+  }
+  $video_dups{$video} = $saver_title if ($video);
+
   return ($saver_title, $gl_p, \@result, \@widgets);
 }
 
@@ -696,6 +705,8 @@ sub build_android(@) {
   my $xml_header = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
 
   my $manifest = '';
+  my $daydream_java = '';
+  my $settings_java = '';
   my $arrays   = '';
   my $strings  = '';
   my %write_files;
@@ -721,12 +732,9 @@ sub build_android(@) {
     my ($saver_title, $gl_p, $xml_opts, $widgets) =
       parse_xml ($saver, $switchmap, $src_opts);
 
-    my $daydream_class = "${saver_title}Daydream";
-    my $settings_class = "${saver_title}Settings";
-    foreach ($settings_class, $daydream_class) {
-      s/\s+//gs;
-      s/^([a-z])/\U$1/gs;  # upcase first letter
-    }
+    my $saver_class = "${saver_title}";
+    $saver_class =~ s/\s+//gs;
+    $saver_class =~ s/^([a-z])/\U$1/gs;  # upcase first letter
 
     $saver_title =~ s/(.[a-z])([A-Z\d])/$1 $2/gs;      # Spaces in InterCaps
     $saver_title =~ s/^(GL|RD)[- ]?(.)/$1 \U$2/gs;     # Space after "GL"
@@ -932,7 +940,7 @@ sub build_android(@) {
                   "  android:summary=\"" .
                        $localize0->("${saver_underscore}_saver_desc",
                                     $daydream_desc) . "\"\n" .
-                  "  android:name=\".gen.$daydream_class\"\n" .
+                  "  android:name=\".gen.Daydream\$$saver_class\"\n" .
                   "  android:permission=\"android.permission" .
                        ".BIND_DREAM_SERVICE\"\n" .
                   "  android:exported=\"true\"\n" .
@@ -947,23 +955,28 @@ sub build_android(@) {
                   "    android:resource=\"\@xml/${saver}_dream\" />\n" .
                   "</service>\n" .
                   "<activity android:name=\"" .
-                    "$package.gen.$settings_class\" />\n"
+                    "$package.gen.Settings\$$saver_class\" />\n"
                  );
 
     my $dream = ("<dream xmlns:android=\"" .
                    "http://schemas.android.com/apk/res/android\"\n" .
                  "  android:settingsActivity=\"" .
-                     "$package.gen.$settings_class\" />\n");
+                     "$package.gen.Settings\$$saver_class\" />\n");
     $write_files{"$xml_dir/${saver_underscore}_dream.xml"} = $dream;
 
-    $write_files{"$java_dir/$daydream_class.java"} =
-      read_template ("XScreenSaverDaydream.java.in",
-                     { CLASS => $daydream_class,
-                       API  => ($gl_p ? 'GL' : 'XLIB') });
-
-    $write_files{"$java_dir/$settings_class.java"} =
-      read_template ("XScreenSaverSettings.java.in",
-                     { CLASS => $settings_class });
+    $daydream_java .=
+      ("  public static class $saver_class extends XScreenSaverDaydream {\n" .
+       "    public $saver_class() {\n" .
+       "      super(jwxyz.API_" . ($gl_p ? 'GL' : 'XLIB') . ");\n" .
+       "    }\n" .
+       "  }\n" .
+       "\n");
+
+    $settings_java .=
+      ("  public static class $saver_class extends XScreenSaverSettings\n" .
+       "    implements SharedPreferences.OnSharedPreferenceChangeListener {\n" .
+       "  }\n" .
+       "\n");
   }
 
   $arrays =~ s/^/  /gm;
@@ -1032,9 +1045,29 @@ sub build_android(@) {
                "  </application>\n" .
                "</manifest>\n");
 
+  $daydream_java = ("package org.jwz.xscreensaver.gen;\n" .
+                    "\n" .
+                    "import org.jwz.xscreensaver.XScreenSaverDaydream;\n" .
+                    "import org.jwz.xscreensaver.jwxyz;\n" .
+                    "\n" .
+                    "public class Daydream {\n" .
+                    $daydream_java .
+                    "}\n");
+
+  $settings_java = ("package org.jwz.xscreensaver.gen;\n" .
+                    "\n" .
+                    "import android.content.SharedPreferences;\n" .
+                    "import org.jwz.xscreensaver.XScreenSaverSettings;\n" .
+                    "\n" .
+                    "public class Settings {\n" .
+                    $settings_java .
+                    "}\n");
+
   $write_files{"$project_dir/AndroidManifest.xml"}     = $manifest;
   $write_files{"$values_dir/settings.xml"} = $arrays;
   $write_files{"$values_dir/strings.xml"}  = $strings;
+  $write_files{"$java_dir/Daydream.java"}  = $daydream_java;
+  $write_files{"$java_dir/Settings.java"}  = $settings_java;
 
   my @s2 = ();
   foreach my $saver (sort @savers) {
@@ -1080,18 +1113,21 @@ sub build_android(@) {
   # if a hack is removed from $ANDROID_HACKS in android/Makefile but
   # the old XML files remain behind, the build blows up.
   #
-  opendir (my $dirp, $xml_dir) || error ("$xml_dir: $!");
-  my @files = readdir ($dirp);
-  closedir $dirp;
-  foreach my $f (sort @files) {
-    next if ($f eq '.' || $f eq '..');
-    $f = "$xml_dir/$f";
-    next if (defined ($write_files{$f}));
-    if ($f =~ m/_(settings|dream)\.xml$/s) {
-      print STDERR "$progname: rm $f\n";
-      unlink ($f) unless ($debug_p);
-    } else {
-      print STDERR "$progname: warning: unrecognised file: $f\n";
+  foreach my $dd ($xml_dir, $gen_dir, $java_dir) {
+    opendir (my $dirp, $dd) || error ("$dd: $!");
+    my @files = readdir ($dirp);
+    closedir $dirp;
+    foreach my $f (sort @files) {
+      next if ($f eq '.' || $f eq '..');
+      $f = "$dd/$f";
+      next if (defined ($write_files{$f}));
+      if ($f =~ m/_(settings|dream)\.xml$/s ||
+          $f =~ m/(Settings|Daydream)\.java$/s) {
+        print STDERR "$progname: rm $f\n";
+        unlink ($f) unless ($debug_p);
+      } else {
+        print STDERR "$progname: warning: unrecognised file: $f\n";
+      }
     }
   }
 }
index fa35d9420f7c0039ac74d1cc98139ce710b45ac7..c141b17d535f7946da970ea6f61a95a190d6623a 100644 (file)
@@ -4,8 +4,8 @@
             a screen saver and locker for the X window system
                             by Jamie Zawinski
 
-                              version 5.35
-                               24-May-2016
+                              version 5.36
+                               10-Oct-2016
 
                      https://www.jwz.org/xscreensaver/
 
diff --git a/hacks/config/cubestack.xml b/hacks/config/cubestack.xml
new file mode 100644 (file)
index 0000000..68c550e
--- /dev/null
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<screensaver name="cubestack" _label="CubeStack" gl="yes">
+
+  <command arg="-root"/>
+
+  <video href="https://www.youtube.com/watch?v=rZi5yav6sRo"/>
+
+  <hgroup>
+   <vgroup>
+    <number id="delay" type="slider" arg="-delay %"
+            _label="Frame rate" _low-label="Low" _high-label="High"
+            low="0" high="100000" default="30000"
+            convert="invert"/>
+
+    <number id="speed" type="slider" arg="-speed %"
+            _label="Animation speed" _low-label="Slow" _high-label="Fast"
+            low="0.1" high="10" default="1.0"/>
+   </vgroup>
+   <vgroup>
+    <number id="thickness" type="slider" arg="-thickness %"
+            _label="Thickness" _low-label="Thin" _high-label="Thick"
+            low="0.0" high="0.5" default="0.13"/>
+
+    <number id="opacity" type="slider" arg="-opacity %"
+            _label="Opacity" _low-label="Transparent" _high-label="Opaque"
+            low="0.01" high="1.0" default="0.7"/>
+   </vgroup>
+  </hgroup>
+
+  <hgroup>
+   <boolean id="wander" _label="Wander"    arg-unset="-no-wander"/>
+   <boolean id="wire"   _label="Wireframe" arg-set="-wireframe"/>
+   <boolean id="showfps" _label="Show frame rate" arg-set="-fps"/>
+  </hgroup>
+
+  <xscreensaver-updater />
+
+  <_description>
+An endless stack of unfolding, translucent cubes.
+
+Written by Jamie Zawinski; 2016.
+  </_description>
+</screensaver>
diff --git a/hacks/config/cubetwist.xml b/hacks/config/cubetwist.xml
new file mode 100644 (file)
index 0000000..00f54b8
--- /dev/null
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<screensaver name="cubetwist" _label="CubeTwist" gl="yes">
+
+  <command arg="-root"/>
+
+  <video href="https://www.youtube.com/watch?v=RjrtUtMEa_4"/>
+
+  <hgroup>
+   <vgroup>
+    <number id="delay" type="slider" arg="-delay %"
+            _label="Frame rate" _low-label="Low" _high-label="High"
+            low="0" high="100000" default="30000"
+            convert="invert"/>
+
+    <number id="speed" type="slider" arg="-speed %"
+            _label="Animation speed" _low-label="Slow" _high-label="Fast"
+            low="0.1" high="10" default="1.0"/>
+   </vgroup>
+   <vgroup>
+    <number id="thickness" type="slider" arg="-thickness %"
+            _label="Thickness" _low-label="Thin" _high-label="Thick"
+            low="0.0" high="0.5" default="0.0"/>
+
+    <number id="displacement" type="slider" arg="-displacement %"
+            _label="Displacement" _low-label="Tight" _high-label="Wide"
+            low="0.0" high="0.5" default="0.0"/>
+   </vgroup>
+  </hgroup>
+
+  <hgroup>
+   <boolean id="flat"   _label="Flat shading" arg-unset="-no-flat"/>
+   <boolean id="wander" _label="Wander"    arg-unset="-no-wander"/>
+   <boolean id="spin"   _label="Spin"      arg-unset="-no-spin"/>
+   <boolean id="wire"   _label="Wireframe" arg-set="-wireframe"/>
+   <boolean id="showfps" _label="Show frame rate" arg-set="-fps"/>
+  </hgroup>
+
+  <xscreensaver-updater />
+
+  <_description>
+A series of nested cubes rotate and slide recursively.
+
+Written by Jamie Zawinski; 2016.
+  </_description>
+</screensaver>
diff --git a/hacks/config/discoball.xml b/hacks/config/discoball.xml
new file mode 100644 (file)
index 0000000..61ed94c
--- /dev/null
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<screensaver name="discoball" _label="Discoball" gl="yes">
+
+  <command arg="-root"/>
+
+  <video href="https://www.youtube.com/watch?v=8yd4PYJQrMw"/>
+
+  <number id="delay" type="slider" arg="-delay %"
+          _label="Frame rate" _low-label="Low" _high-label="High"
+          low="0" high="100000" default="30000"
+          convert="invert"/>
+
+  <number id="speed" type="slider" arg="-speed %"
+          _label="Speed" _low-label="Slow" _high-label="Fast"
+          low="0.1" high="5" default="1.0"/>
+
+  <number id="count" type="slider" arg="-count %"
+          _label="Size" _low-label="Small" _high-label="Large"
+          low="10" high="100" default="30"/>
+
+  <hgroup>
+   <boolean id="wander" _label="Wander"    arg-unset="-no-wander"/>
+   <boolean id="spin"   _label="Spin"      arg-set="-spin"/>
+   <boolean id="wire"   _label="Wireframe" arg-set="-wireframe"/>
+  </hgroup>
+
+  <boolean id="showfps" _label="Show frame rate" arg-set="-fps"/>
+
+  <xscreensaver-updater />
+
+  <_description>
+A dusty, dented disco ball.  Woop woop.
+
+Written by Jamie Zawinski; 2016.
+  </_description>
+</screensaver>
index dc93c8b8bf69d0371cad87d060998c4fee2223b0..877cdfa88d46877bd59670957201485e459c5947 100644 (file)
@@ -13,7 +13,8 @@
 
   <!-- #### -no-texture -->
 
-  <file id="bitmap" _label="Image file" arg="-image %"/>
+  <file id="image"  _label="Day image"   arg="-image %"  />
+  <file id="image2" _label="Night image" arg="-image2 %" />
 
   <hgroup>
    <boolean id="wander" _label="Wander"    arg-unset="-no-wander"/>
diff --git a/hacks/config/hexstrut.xml b/hacks/config/hexstrut.xml
new file mode 100644 (file)
index 0000000..0823dc8
--- /dev/null
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<screensaver name="hexstrut" _label="Hexstrut" gl="yes">
+
+  <command arg="-root"/>
+
+  <video href="https://www.youtube.com/watch?v=iOCffj3ZmgE"/>
+
+  <hgroup>
+   <vgroup>
+    <number id="delay" type="slider" arg="-delay %"
+            _label="Frame rate" _low-label="Low" _high-label="High"
+            low="0" high="100000" default="30000"
+            convert="invert"/>
+
+    <number id="speed" type="slider" arg="-speed %"
+            _label="Speed" _low-label="Slow" _high-label="Fast"
+            low="0.1" high="5" default="1.0"/>
+   </vgroup>
+
+   <vgroup>
+    <number id="count" type="slider" arg="-count %"
+            _label="Hexagon Size" _low-label="Small" _high-label="Large"
+            low="2" high="80" default="20"
+            convert="invert"/>
+
+    <number id="thickness" type="slider" arg="-thickness %"
+            _label="Line Thickness" _low-label="Thin" _high-label="Thick"
+            low="0.01" high="1.7" default="0.2"/>
+   </vgroup>
+  </hgroup>
+
+  <hgroup>
+   <boolean id="wander" _label="Wander"    arg-unset="-no-wander"/>
+   <boolean id="spin"   _label="Spin"      arg-unset="-no-spin"/>
+   <boolean id="wire"   _label="Wireframe" arg-set="-wireframe"/>
+   <boolean id="showfps" _label="Show frame rate" arg-set="-fps"/>
+  </hgroup>
+
+  <xscreensaver-updater />
+
+  <_description>
+A grid of hexagons composed of rotating Y-shaped struts.
+Waves of rotation and color changes randomly propagate across the plane.
+
+Written by Jamie Zawinski; 2016.
+  </_description>
+</screensaver>
index 6337dbd8ecdc114844d214149d635fdbcb9be175..a174afd190be6fd8389625e62b9453a3de0d01a5 100644 (file)
@@ -45,7 +45,7 @@
             _low-label="Short" _high-label="Long"
             low="1" high="60" default="5"/>
 
-    <boolean id="titles" _label="Show file names" arg-set="-titles"/>
+    <boolean id="titles" _label="Show file names" arg-unset="-no-titles"/>
 
     <boolean id="showfps" _label="Show frame rate" arg-set="-fps"/>
 
index bd4ce740e2a7a222c0c06c08629b3b402351c997..d610fcbab1a7250c1e2087f2a84d0ce82473f471 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="https://www.youtube.com/watch?v=JVKDhd8gc7c"/>
+  <video href="https://www.youtube.com/watch?v=ecl8ykLswX8"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
           _label="Rectangle count" low="1" high="20" default="2"/>
 
   <select id="mode">
-   <option id="stationary" _label="Stationary rectangles"/>
+   <option id="random"     _label="Random"/>
+   <option id="stationary" _label="Stationary rectangles" arg-set="-mode stationary"/>
    <option id="move"       _label="Wandering rectangles" arg-set="-mode move"/>
    <option id="sweep"      _label="Sweeping arcs"        arg-set="-mode sweep"/>
+   <option id="circle"     _label="Rotating discs"       arg-set="-mode circle"/>
   </select>
 
   <boolean id="anim" _label="Animate" arg-unset="-no-anim"/>
@@ -36,6 +38,6 @@
   <_description>
 Distorts an image by rotating and scaling random sections of it.
 
-Written by Claudio Matsuoka; 2001.
+Written by Claudio Matsuoka and Jamie Zawinski; 2001.
   </_description>
 </screensaver>
diff --git a/hacks/config/splodesic.xml b/hacks/config/splodesic.xml
new file mode 100644 (file)
index 0000000..08b3bfb
--- /dev/null
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<screensaver name="splodesic" _label="Splodesic" gl="yes">
+
+  <command arg="-root"/>
+
+  <video href="https://www.youtube.com/watch?v=pwpTs1pEQmM"/>
+
+  <number id="delay" type="slider" arg="-delay %"
+          _label="Frame rate" _low-label="Low" _high-label="High"
+          low="0" high="100000" default="30000"
+          convert="invert"/>
+  <number id="speed" type="slider" arg="-speed %"
+          _label="Eruption frequency" _low-label="Seldom" _high-label="Often"
+          low="0.01" high="5.0" default="1.0"/>
+
+  <hgroup>
+   <number id="depth" type="spinbutton" arg="-depth %"
+           _label="Depth" low="0" high="5" default="4"/>
+   <boolean id="wander" _label="Wander"    arg-unset="-no-wander"/>
+   <boolean id="spin"   _label="Spin"      arg-unset="-no-spin"/>
+   <boolean id="showfps" _label="Show frame rate" arg-set="-fps"/>
+  </hgroup>
+
+  <xscreensaver-updater />
+
+  <_description>
+A geodesic sphere experiences a series of eruptions.
+
+Written by Jamie Zawinski; 2016.
+  </_description>
+</screensaver>
index b70eedaf69468601ffce3eb8b38eb774d42b7a06..caa005ee1f01c35568ad1e915dfcb0df2337b585 100644 (file)
@@ -58,6 +58,6 @@ same name.
 
 https://en.wikipedia.org/wiki/Star_Wars_opening_crawl
 
-Written by Jamie Zawinski and Claudio Matauoka; 2001.
+Written by Jamie Zawinski and Claudio Matsuoka; 2001.
   </_description>
 </screensaver>
index f0d4e95c6b2b4da8ca000f46f115b36628b47c2c..832b7ca7d3a71b72dead0b42db8623add01f7461 100644 (file)
@@ -330,6 +330,7 @@ decayscreen_reshape (Display *dpy, Window window, void *closure,
                  unsigned int w, unsigned int h)
 {
   struct state *st = (struct state *) closure;
+  if (! st->saved) return; /* Image might not be loaded yet */
   XClearWindow (st->dpy, st->window);
   XCopyArea (st->dpy, st->saved, st->window, st->gc,
              0, 0, st->saved_w, st->saved_h,
index 477ee63b77844dbdaae1a07bf68f628558a7627d..d7faf900e4975110c560ef1f62b1d53d83be74cc 100644 (file)
@@ -88,6 +88,7 @@ struct state {
   void (*draw_routine) (struct state *st, XImage *, XImage *, int, int, int *);
 
   async_load_state *img_loader;
+  Pixmap pm;
 };
 
 
@@ -288,8 +289,15 @@ distort_init (Display *dpy, Window window)
                gcflags |= GCSubwindowMode;
        st->gc = XCreateGC (st->dpy, st->window, gcflags, &gcv);
 
+    /* On MacOS X11, XGetImage on a Window often gets an inexplicable BadMatch,
+       possibly due to the window manager having occluded something?  It seems
+       nondeterministic. Loading the image into a pixmap instead fixes it. */
+    if (st->pm) XFreePixmap (st->dpy, st->pm);
+    st->pm = XCreatePixmap (st->dpy, st->window,
+                            st->xgwa.width, st->xgwa.height, st->xgwa.depth);
+
     st->img_loader = load_image_async_simple (0, st->xgwa.screen, st->window,
-                                              st->window, 0, 0);
+                                              st->pm, 0, 0);
     st->start_time = time ((time_t *) 0);
     return st;
 }
@@ -302,8 +310,13 @@ distort_finish_loading (struct state *st)
     st->start_time = time ((time_t *) 0);
 
        st->buffer_map = 0;
-       st->orig_map = XGetImage(st->dpy, st->window, 0, 0, st->xgwa.width, st->xgwa.height,
-                                                ~0L, ZPixmap);
+    if (! st->pm) abort();
+    XClearWindow (st->dpy, st->window);
+    XCopyArea (st->dpy, st->pm, st->window, st->gc, 
+               0, 0, st->xgwa.width, st->xgwa.height, 0, 0);
+       st->orig_map = XGetImage(st->dpy, st->pm, 0, 0,
+                             st->xgwa.width, st->xgwa.height,
+                             ~0L, ZPixmap);
        st->buffer_map_cache = malloc(sizeof(unsigned long)*(2*st->radius+st->speed+2)*(2*st->radius+st->speed+2));
 
        if (st->buffer_map_cache == NULL) {
@@ -773,8 +786,11 @@ distort_draw (Display *dpy, Window window, void *closure)
 
   if (!st->img_loader &&
       st->start_time + st->duration < time ((time_t *) 0)) {
+    if (st->pm) XFreePixmap (st->dpy, st->pm);
+    st->pm = XCreatePixmap (st->dpy, st->window,
+                            st->xgwa.width, st->xgwa.height, st->xgwa.depth);
     st->img_loader = load_image_async_simple (0, st->xgwa.screen, st->window,
-                                              st->window, 0, 0);
+                                              st->pm, 0, 0);
     return st->delay;
   }
 
@@ -815,6 +831,7 @@ distort_free (Display *dpy, Window window, void *closure)
 {
   struct state *st = (struct state *) closure;
   XFreeGC (st->dpy, st->gc);
+  if (st->pm) XFreePixmap (dpy, st->pm);
   if (st->orig_map) XDestroyImage (st->orig_map);
   if (st->buffer_map) XDestroyImage (st->buffer_map);
   if (st->from) free (st->from);
index 6a304171fa88e8ba142518e91d352e5c47efbd73..89305f5cbc518335f58c4d177165bda72dec692a 100644 (file)
@@ -1658,8 +1658,8 @@ fontglide_draw_metrics (state *s)
 
 # ifdef HAVE_JWXYZ
   {
-    char *name =
-      jwxyz_unicode_character_name (s->metrics_font1->fid, s->debug_metrics_p);
+    char *name = jwxyz_unicode_character_name (
+      s->dpy, s->metrics_font1->fid, s->debug_metrics_p);
     if (!name || !*name) name = strdup("unknown character name");
     XDrawString (s->dpy, dest, gc, 
                  10,
index 678a510c3697608b02776c69f0b7b45be51b411a..f788728c212fbfd3e0d06065a962f1d7aa83e099 100644 (file)
@@ -127,7 +127,8 @@ SRCS                = xscreensaver-gl-helper.c normals.c fps-gl.c \
                  projectiveplane.c winduprobot.c robot.c robot-wireframe.c \
                  cityflow.c romanboy.c splitflap.c splitflap_obj.c \
                  dymaxionmap.c unicrud.c energystream.c raverhoop.c \
-                 hydrostat.c
+                 hydrostat.c discoball.c cubetwist.c cubestack.c splodesic.c \
+                 hexstrut.c
 
 OBJS           = xscreensaver-gl-helper.o normals.o fps-gl.o \
                  atlantis.o b_draw.o b_lockglue.o b_sphere.o bubble3d.o \
@@ -171,7 +172,8 @@ OBJS                = xscreensaver-gl-helper.o normals.o fps-gl.o \
                  projectiveplane.o winduprobot.o robot.o robot-wireframe.o \
                  cityflow.o romanboy.o splitflap.o splitflap_obj.o \
                  dymaxionmap.o unicrud.o energystream.o raverhoop.o \
-                 hydrostat.o
+                 hydrostat.o discoball.o cubetwist.o cubestack.o splodesic.o \
+                 hexstrut.o
 
 GL_EXES                = cage gears moebius pipes sproingies stairs superquadrics \
                  morph3d rubik atlantis lament bubble3d glplanet pulsar \
@@ -190,7 +192,8 @@ GL_EXES             = cage gears moebius pipes sproingies stairs superquadrics \
                  kaleidocycle quasicrystal unknownpleasures geodesic \
                  geodesicgears projectiveplane winduprobot cityflow romanboy \
                  splitflap dymaxionmap unicrud energystream raverhoop \
-                 hydrostat
+                 hydrostat discoball cubetwist cubestack splodesic \
+                 hexstrut
 GLE_EXES       = extrusion
 SUID_EXES      = sonar
 GL_UTIL_EXES   = xscreensaver-gl-helper
@@ -251,7 +254,9 @@ GL_MEN              = atlantis.man boxed.man bubble3d.man cage.man circuit.man \
                  quasicrystal.man unknownpleasures.man geodesic.man \
                  geodesicgears.man projectiveplane.man winduprobot.man \
                  cityflow.man romanboy.man splitflap.man dymaxionmap.man \
-                 unicrud.man energystream.man raverhoop.man hydrostat.man
+                 unicrud.man energystream.man raverhoop.man hydrostat.man \
+                 discoball.man cubetwist.man cubestack.man splodesic.man \
+                 hexstrut.man
 MEN            = @GL_MEN@
 RETIRED_MEN    = glforestfire.man
 EXTRAS         = README Makefile.in dxf2gl.pl vrml2gl.pl wfront2gl.pl \
@@ -440,7 +445,6 @@ distdepend:: molecules.h
              -e 's@ $$(srcdir)/\(.*molecules.h\)@ \1@g' ;                  \
          echo ''                                                           \
        ) > /tmp/distdepend.$$$$ &&                                         \
-       mv Makefile.in Makefile.in.bak &&                                   \
        mv /tmp/distdepend.$$$$ Makefile.in
 
 
@@ -938,6 +942,21 @@ HSTAT_OBJS=sphere.o normals.o $(HACK_TRACK_OBJS)
 hydrostat:     hydrostat.o     $(HSTAT_OBJS)
        $(CC_HACK) -o $@ $@.o   $(HSTAT_OBJS) $(HACK_LIBS)
 
+discoball:     discoball.o     $(HACK_TRACK_OBJS)
+       $(CC_HACK) -o $@ $@.o   $(HACK_TRACK_OBJS) $(HACK_LIBS)
+
+cubetwist:     cubetwist.o     $(HACK_TRACK_OBJS)
+       $(CC_HACK) -o $@ $@.o   $(HACK_TRACK_OBJS) $(HACK_LIBS)
+
+cubestack:     cubestack.o     $(HACK_TRACK_OBJS)
+       $(CC_HACK) -o $@ $@.o   $(HACK_TRACK_OBJS) $(HACK_LIBS)
+
+splodesic:     splodesic.o     $(HACK_TRACK_OBJS)
+       $(CC_HACK) -o $@ $@.o   $(HACK_TRACK_OBJS) $(HACK_LIBS)
+
+hexstrut:      hexstrut.o       normals.o $(HACK_TRACK_OBJS)
+       $(CC_HACK) -o $@ $@.o    normals.o $(HACK_TRACK_OBJS) $(HACK_LIBS)
+
 ##############################################################################
 #
 # DO NOT DELETE: updated by make distdepend
@@ -1299,6 +1318,21 @@ cubenetic.o: $(UTILS_SRC)/xshm.h
 cubenetic.o: $(UTILS_SRC)/yarandom.h
 cubenetic.o: $(HACK_SRC)/xlockmoreI.h
 cubenetic.o: $(HACK_SRC)/xlockmore.h
+cubestack.o: ../../config.h
+cubestack.o: $(HACK_SRC)/fps.h
+cubestack.o: $(srcdir)/gltrackball.h
+cubestack.o: $(srcdir)/rotator.h
+cubestack.o: $(HACK_SRC)/screenhackI.h
+cubestack.o: $(UTILS_SRC)/colors.h
+cubestack.o: $(UTILS_SRC)/grabscreen.h
+cubestack.o: $(UTILS_SRC)/hsv.h
+cubestack.o: $(UTILS_SRC)/resources.h
+cubestack.o: $(UTILS_SRC)/usleep.h
+cubestack.o: $(UTILS_SRC)/visual.h
+cubestack.o: $(UTILS_SRC)/xshm.h
+cubestack.o: $(UTILS_SRC)/yarandom.h
+cubestack.o: $(HACK_SRC)/xlockmoreI.h
+cubestack.o: $(HACK_SRC)/xlockmore.h
 cubestorm.o: ../../config.h
 cubestorm.o: $(HACK_SRC)/fps.h
 cubestorm.o: $(srcdir)/gltrackball.h
@@ -1314,6 +1348,22 @@ cubestorm.o: $(UTILS_SRC)/xshm.h
 cubestorm.o: $(UTILS_SRC)/yarandom.h
 cubestorm.o: $(HACK_SRC)/xlockmoreI.h
 cubestorm.o: $(HACK_SRC)/xlockmore.h
+cubetwist.o: ../../config.h
+cubetwist.o: $(HACK_SRC)/fps.h
+cubetwist.o: $(srcdir)/gltrackball.h
+cubetwist.o: $(srcdir)/normals.h
+cubetwist.o: $(srcdir)/rotator.h
+cubetwist.o: $(HACK_SRC)/screenhackI.h
+cubetwist.o: $(UTILS_SRC)/colors.h
+cubetwist.o: $(UTILS_SRC)/grabscreen.h
+cubetwist.o: $(UTILS_SRC)/hsv.h
+cubetwist.o: $(UTILS_SRC)/resources.h
+cubetwist.o: $(UTILS_SRC)/usleep.h
+cubetwist.o: $(UTILS_SRC)/visual.h
+cubetwist.o: $(UTILS_SRC)/xshm.h
+cubetwist.o: $(UTILS_SRC)/yarandom.h
+cubetwist.o: $(HACK_SRC)/xlockmoreI.h
+cubetwist.o: $(HACK_SRC)/xlockmore.h
 cubicgrid.o: ../../config.h
 cubicgrid.o: $(HACK_SRC)/fps.h
 cubicgrid.o: $(srcdir)/gltrackball.h
@@ -1346,6 +1396,22 @@ dangerball.o: $(UTILS_SRC)/xshm.h
 dangerball.o: $(UTILS_SRC)/yarandom.h
 dangerball.o: $(HACK_SRC)/xlockmoreI.h
 dangerball.o: $(HACK_SRC)/xlockmore.h
+discoball.o: ../../config.h
+discoball.o: $(HACK_SRC)/fps.h
+discoball.o: $(srcdir)/gltrackball.h
+discoball.o: $(srcdir)/normals.h
+discoball.o: $(srcdir)/rotator.h
+discoball.o: $(HACK_SRC)/screenhackI.h
+discoball.o: $(UTILS_SRC)/colors.h
+discoball.o: $(UTILS_SRC)/grabscreen.h
+discoball.o: $(UTILS_SRC)/hsv.h
+discoball.o: $(UTILS_SRC)/resources.h
+discoball.o: $(UTILS_SRC)/usleep.h
+discoball.o: $(UTILS_SRC)/visual.h
+discoball.o: $(UTILS_SRC)/xshm.h
+discoball.o: $(UTILS_SRC)/yarandom.h
+discoball.o: $(HACK_SRC)/xlockmoreI.h
+discoball.o: $(HACK_SRC)/xlockmore.h
 dnalogo.o: ../../config.h
 dnalogo.o: $(HACK_SRC)/fps.h
 dnalogo.o: $(srcdir)/gltrackball.h
@@ -1884,6 +1950,22 @@ grab-ximage.o: $(UTILS_SRC)/grabscreen.h
 grab-ximage.o: $(UTILS_SRC)/resources.h
 grab-ximage.o: $(UTILS_SRC)/visual.h
 grab-ximage.o: $(UTILS_SRC)/xshm.h
+hexstrut.o: ../../config.h
+hexstrut.o: $(HACK_SRC)/fps.h
+hexstrut.o: $(srcdir)/gltrackball.h
+hexstrut.o: $(srcdir)/normals.h
+hexstrut.o: $(srcdir)/rotator.h
+hexstrut.o: $(HACK_SRC)/screenhackI.h
+hexstrut.o: $(UTILS_SRC)/colors.h
+hexstrut.o: $(UTILS_SRC)/grabscreen.h
+hexstrut.o: $(UTILS_SRC)/hsv.h
+hexstrut.o: $(UTILS_SRC)/resources.h
+hexstrut.o: $(UTILS_SRC)/usleep.h
+hexstrut.o: $(UTILS_SRC)/visual.h
+hexstrut.o: $(UTILS_SRC)/xshm.h
+hexstrut.o: $(UTILS_SRC)/yarandom.h
+hexstrut.o: $(HACK_SRC)/xlockmoreI.h
+hexstrut.o: $(HACK_SRC)/xlockmore.h
 hilbert.o: ../../config.h
 hilbert.o: $(HACK_SRC)/fps.h
 hilbert.o: $(srcdir)/gltrackball.h
@@ -2592,6 +2674,22 @@ splitflap.o: $(HACK_SRC)/xlockmore.h
 splitflap.o: $(srcdir)/xpm-ximage.h
 splitflap_obj.o: ../../config.h
 splitflap_obj.o: $(srcdir)/gllist.h
+splodesic.o: ../../config.h
+splodesic.o: $(HACK_SRC)/fps.h
+splodesic.o: $(srcdir)/gltrackball.h
+splodesic.o: $(srcdir)/normals.h
+splodesic.o: $(srcdir)/rotator.h
+splodesic.o: $(HACK_SRC)/screenhackI.h
+splodesic.o: $(UTILS_SRC)/colors.h
+splodesic.o: $(UTILS_SRC)/grabscreen.h
+splodesic.o: $(UTILS_SRC)/hsv.h
+splodesic.o: $(UTILS_SRC)/resources.h
+splodesic.o: $(UTILS_SRC)/usleep.h
+splodesic.o: $(UTILS_SRC)/visual.h
+splodesic.o: $(UTILS_SRC)/xshm.h
+splodesic.o: $(UTILS_SRC)/yarandom.h
+splodesic.o: $(HACK_SRC)/xlockmoreI.h
+splodesic.o: $(HACK_SRC)/xlockmore.h
 sproingies.o: ../../config.h
 sproingies.o: $(HACK_SRC)/fps.h
 sproingies.o: $(srcdir)/gllist.h
index a2faf1f8190549e002987f681d8c53b082fdf8db..122befa65a41024559dd2d24a1f878c2271ca52c 100644 (file)
@@ -211,6 +211,7 @@ load_texture (ModeInfo *mi, const char *filename)
     }
 
   image = xpm_file_to_ximage (dpy, visual, cmap, filename);
+  if (!image) return False;
 
   clear_gl_error();
   glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA,
diff --git a/hacks/glx/cubestack.c b/hacks/glx/cubestack.c
new file mode 100644 (file)
index 0000000..072bf9c
--- /dev/null
@@ -0,0 +1,462 @@
+/* cubestack, Copyright (c) 2016 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
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation.  No representations are made about the suitability of this
+ * software for any purpose.  It is provided "as is" without express or 
+ * implied warranty.
+ */
+
+#define DEFAULTS       "*delay:        30000       \n" \
+                       "*showFPS:      False       \n" \
+                       "*wireframe:    False       \n" \
+                       "*suppressRotationAnimation: True\n" \
+
+# define refresh_cube 0
+# define release_cube 0
+#undef countof
+#define countof(x) (sizeof((x))/sizeof((*x)))
+
+#include "xlockmore.h"
+#include "colors.h"
+#include "rotator.h"
+#include "gltrackball.h"
+#include <ctype.h>
+
+#ifdef USE_GL /* whole file */
+
+
+#define DEF_WANDER    "True"
+#define DEF_SPEED     "1.0"
+#define DEF_THICKNESS "0.13"
+#define DEF_OPACITY   "0.7"
+
+typedef struct {
+  GLXContext *glx_context;
+  rotator *rot;
+  trackball_state *trackball;
+  Bool button_down_p;
+  GLfloat state;
+  GLfloat r;
+  int length;
+  int ncolors;
+  XColor *colors;
+  int ccolor;
+} cube_configuration;
+
+static cube_configuration *bps = NULL;
+
+static GLfloat speed;
+static GLfloat thickness;
+static GLfloat opacity;
+static Bool do_wander;
+
+static XrmOptionDescRec opts[] = {
+  { "-wander", ".wander", XrmoptionNoArg, "True" },
+  { "+wander", ".wander", XrmoptionNoArg, "False" },
+  { "-speed",  ".speed",  XrmoptionSepArg, 0 },
+  { "-thickness",  ".thickness",  XrmoptionSepArg, 0 },
+  { "-opacity",  ".opacity",  XrmoptionSepArg, 0 },
+};
+
+static argtype vars[] = {
+  {&do_wander, "wander", "Wander", DEF_WANDER, t_Bool},
+  {&speed,     "speed",  "Speed",  DEF_SPEED,  t_Float},
+  {&thickness, "thickness", "Thickness", DEF_THICKNESS, t_Float},
+  {&opacity, "opacity", "Opacity", DEF_OPACITY, t_Float},
+};
+
+ENTRYPOINT ModeSpecOpt cube_opts = {countof(opts), opts, countof(vars), vars, NULL};
+
+
+static int
+draw_strut (ModeInfo *mi)
+{
+  int wire = MI_IS_WIREFRAME(mi);
+  int polys = 0;
+  GLfloat h;
+
+  glPushMatrix();
+  glFrontFace (GL_CCW);
+  glNormal3f (0, 0, -1);
+  glTranslatef (-0.5, -0.5, 0);
+  glBegin (wire ? GL_LINE_LOOP : GL_TRIANGLE_FAN);
+  glVertex3f (0, 0, 0);
+  glVertex3f (1, 0, 0);
+  glVertex3f (1 - thickness, thickness, 0);
+  glVertex3f (thickness, thickness, 0);
+  glEnd();
+  polys += 2;
+
+  h = 0.5 - thickness;
+  if (h >= 0.25)
+    {
+      glBegin (wire ? GL_LINE_LOOP : GL_TRIANGLE_FAN);
+      glVertex3f (0.5, 0.5, 0);
+      glVertex3f (0.5 - thickness/2, 0.5 - thickness/2, 0);
+      glVertex3f (0.5 - thickness/2, 0.5 - h/2, 0);
+      glVertex3f (0.5 + thickness/2, 0.5 - h/2, 0);
+      glVertex3f (0.5 + thickness/2, 0.5 - thickness/2, 0);
+      glEnd();
+      polys += 3;
+    }
+
+  glPopMatrix();
+
+  return polys;
+}
+
+
+static int
+draw_face (ModeInfo *mi)
+{
+  int i;
+  int polys = 0;
+  for (i = 0; i < 4; i++)
+    {
+      polys += draw_strut (mi);
+      glRotatef (90, 0, 0, 1);
+    }
+  return polys;
+}
+
+
+static GLfloat
+ease_fn (GLfloat r)
+{
+  return cos ((r/2 + 1) * M_PI) + 1; /* Smooth curve up, end at slope 1. */
+}
+
+
+static GLfloat
+ease_ratio (GLfloat r)
+{
+  GLfloat ease = 0.5;
+  if      (r <= 0)     return 0;
+  else if (r >= 1)     return 1;
+  else if (r <= ease)  return     ease * ease_fn (r / ease);
+  else if (r > 1-ease) return 1 - ease * ease_fn ((1 - r) / ease);
+  else                 return r;
+}
+
+
+static int
+draw_cube_1 (ModeInfo *mi, GLfloat state, GLfloat color[4], Bool bottom_p)
+{
+  int polys = 0;
+  int istate = state;
+  GLfloat r = state - istate;
+  GLfloat a = color[3];
+
+  r = ease_ratio (r);
+
+# define COLORIZE(R) \
+      color[3] = a * R; \
+      glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color); \
+      glColor4fv (color)
+
+  if (bottom_p)
+    {
+      GLfloat r2 = (state < 0 ? 1 + state : 1);
+      COLORIZE(r2);
+      polys += draw_face (mi);         /* Bottom */
+    }
+
+  if (state >= 0)                      /* Left */
+    {
+      GLfloat r2 = (istate == 0 ? r : 1);
+      COLORIZE(r2);
+      glPushMatrix();
+      glTranslatef (-0.5, 0.5, 0);
+      glRotatef (-r2 * 90, 0, 1, 0);
+      glTranslatef (0.5, -0.5, 0);
+      polys += draw_face (mi);
+      glPopMatrix();
+    }
+
+  if (state >= 1)                      /* Back */
+    {
+      GLfloat r2 = (istate == 1 ? r : 1);
+      COLORIZE(r2);
+      glPushMatrix();
+      glTranslatef (-0.5, 0.5, 0);
+      glRotatef ( 90, 0, 1, 0);
+      glRotatef (-90, 0, 0, 1);
+      glRotatef (-r2 * 90, 0, 1, 0);
+      glTranslatef (0.5, -0.5, 0);
+      polys += draw_face (mi);
+      glPopMatrix();
+    }
+
+  if (state >= 2)                      /* Right */
+    {
+      GLfloat r2 = (istate == 2 ? r : 1);
+      COLORIZE(r2);
+      glPushMatrix();
+      glTranslatef (0.5, 0.5, 0);
+      glRotatef ( 90, 0, 1, 0);
+      glRotatef (-90, 0, 0, 1);
+      glRotatef (-90, 0, 1, 0);
+      glRotatef (-r2 * 90, 0, 1, 0);
+      glTranslatef (-0.5, -0.5, 0);
+      polys += draw_face (mi);
+      glPopMatrix();
+    }
+
+  if (state >= 3)                      /* Front */
+    {
+      GLfloat r2 = (istate == 3 ? r : 1);
+      COLORIZE(r2);
+      glPushMatrix();
+      glTranslatef (0.5, 0.5, 0);
+      glRotatef ( 90, 0, 1, 0);
+      glRotatef (-90, 0, 0, 1);
+      glRotatef (-180, 0, 1, 0);
+      glTranslatef (-1, 0, 0);
+      glRotatef (-r2 * 90, 0, 1, 0);
+      glTranslatef (0.5, -0.5, 0);
+      polys += draw_face (mi);
+      glPopMatrix();
+    }
+
+  if (state >= 4)                      /* Top */
+    {
+      GLfloat r2 = (istate == 4 ? r : 1);
+      COLORIZE(r2);
+      glPushMatrix();
+      glTranslatef (0, 0, 1);
+      glRotatef (-90, 0, 0, 1);
+      glTranslatef (0.5, 0.5, 0);
+      glRotatef (-90, 0, 1, 0);
+      glRotatef (r2 * 90, 0, 1, 0);
+      glTranslatef (-0.5, -0.5, 0);
+      polys += draw_face (mi);
+      glPopMatrix();
+    }
+
+  return polys;
+}
+
+
+static int
+draw_cubes (ModeInfo *mi)
+{
+  cube_configuration *bp = &bps[MI_SCREEN(mi)];
+  int polys = 0;
+  GLfloat z = bp->state / 6;
+  int i;
+  GLfloat c[4];
+  int c0 = bp->ccolor;
+  GLfloat alpha = opacity;
+
+  glPushMatrix();
+  glTranslatef (0, 0, -1.5 - z);
+
+  glTranslatef (0, 0, -bp->length);
+  for (i = bp->length-1; i >= 0; i--)
+    {
+      int c1 = c0 - i - 1;
+      if (c1 < 0) c1 += bp->ncolors;
+      c[0] = bp->colors[c1].red   / 65536.0;
+      c[1] = bp->colors[c1].green / 65536.0;
+      c[2] = bp->colors[c1].blue  / 65536.0;
+      c[3] = alpha;
+
+      glTranslatef (0, 0, 1);
+      polys += draw_cube_1 (mi, 5, c, i == bp->length - 1);
+    }
+
+  c[0] = bp->colors[c0].red   / 65536.0;
+  c[1] = bp->colors[c0].green / 65536.0;
+  c[2] = bp->colors[c0].blue  / 65536.0;
+  c[3] = alpha;
+  glTranslatef (0, 0, 1);
+  polys += draw_cube_1 (mi, bp->state, c, bp->length == 0);
+
+  glPopMatrix();
+
+  return polys;
+}
+
+
+/* Window management, etc
+ */
+ENTRYPOINT void
+reshape_cube (ModeInfo *mi, int width, int height)
+{
+  GLfloat h = (GLfloat) height / (GLfloat) width;
+
+  glViewport (0, 0, (GLint) width, (GLint) height);
+
+  glMatrixMode(GL_PROJECTION);
+  glLoadIdentity();
+  gluPerspective (30.0, 1/h, 1.0, 100.0);
+
+  glMatrixMode(GL_MODELVIEW);
+  glLoadIdentity();
+  gluLookAt( 0.0, 0.0, 30.0,
+             0.0, 0.0, 0.0,
+             0.0, 1.0, 0.0);
+
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+  {
+    int o = (int) current_device_rotation();
+    if (o != 0 && o != 180 && o != -180)
+      glScalef (1/h, 1/h, 1/h);
+  }
+# endif
+
+  glClear(GL_COLOR_BUFFER_BIT);
+}
+
+
+ENTRYPOINT Bool
+cube_handle_event (ModeInfo *mi, XEvent *event)
+{
+  cube_configuration *bp = &bps[MI_SCREEN(mi)];
+
+  if (gltrackball_event_handler (event, bp->trackball,
+                                 MI_WIDTH (mi), MI_HEIGHT (mi),
+                                 &bp->button_down_p))
+    return True;
+  else if (event->xany.type == KeyPress)
+    {
+      KeySym keysym;
+      char c = 0;
+      XLookupString (&event->xkey, &c, 1, &keysym, 0);
+      if (c == ' ' || c == '\t')
+        {
+          bp->ncolors = 32;
+          make_smooth_colormap (0, 0, 0,
+                                bp->colors, &bp->ncolors,
+                                False, 0, False);
+          return True;
+        }
+    }
+
+
+  return False;
+}
+
+
+ENTRYPOINT void 
+init_cube (ModeInfo *mi)
+{
+  cube_configuration *bp;
+  int wire = MI_IS_WIREFRAME(mi);
+
+  if (!bps) {
+    bps = (cube_configuration *)
+      calloc (MI_NUM_SCREENS(mi), sizeof (cube_configuration));
+    if (!bps) {
+      fprintf(stderr, "%s: out of memory\n", progname);
+      exit(1);
+    }
+  }
+
+  bp = &bps[MI_SCREEN(mi)];
+
+  bp->glx_context = init_GL(mi);
+
+  reshape_cube (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
+
+  if (!wire)
+    {
+      glDisable (GL_LIGHTING);
+      glEnable(GL_DEPTH_TEST);
+      glShadeModel (GL_SMOOTH);
+      glEnable (GL_NORMALIZE);
+      glDisable (GL_CULL_FACE);
+      glEnable (GL_BLEND);
+      glDisable (GL_DEPTH_TEST);
+      glBlendFunc (GL_SRC_ALPHA, GL_ONE);
+    }
+
+  {
+    double wander_speed = 0.005;
+    bp->rot = make_rotator (0, 0, 0, 0,
+                            do_wander ? wander_speed : 0,
+                            False);
+    bp->trackball = gltrackball_init (True);
+  }
+
+  if (thickness > 0.5)
+    thickness = 0.5;
+  if (thickness < 0.001)
+    thickness = 0.001;
+
+  bp->ncolors = 32;
+  bp->colors = (XColor *) calloc(bp->ncolors, sizeof(XColor));
+  make_smooth_colormap (0, 0, 0,
+                        bp->colors, &bp->ncolors,
+                        False, 0, False);
+  bp->state = -1;
+}
+
+
+ENTRYPOINT void
+draw_cube (ModeInfo *mi)
+{
+  cube_configuration *bp = &bps[MI_SCREEN(mi)];
+  Display *dpy = MI_DISPLAY(mi);
+  Window window = MI_WINDOW(mi);
+
+  if (!bp->glx_context)
+    return;
+
+  glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(bp->glx_context));
+  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+  glPushMatrix ();
+
+  {
+    double x, y, z;
+    get_position (bp->rot, &x, &y, &z, !bp->button_down_p);
+    glTranslatef((x - 0.5) * 4,
+                 (y - 0.5) * 4,
+                 (z - 0.5) * 2);
+
+    gltrackball_rotate (bp->trackball);
+  }
+
+  mi->polygon_count = 0;
+
+  glScalef (6, 6, 6);
+  glRotatef (-45, 1, 0, 0);
+  glRotatef (20, 0, 0, 1);
+  glRotatef (bp->r, 0, 0, 1);
+
+  mi->polygon_count = draw_cubes (mi);
+  glPopMatrix ();
+
+  if (!bp->button_down_p)
+    {
+      int max = 6;
+      bp->state += speed * 0.015;
+      bp->r += speed * 0.05;
+      while (bp->r > 360)
+        bp->r -= 360;
+      while (bp->state > max)
+        {
+          bp->state -= max;
+          bp->length++;
+          bp->ccolor++;
+          if (bp->ccolor > bp->ncolors)
+            bp->ccolor = 0;
+        }
+
+      if (bp->length > 20)
+        bp->length = 20;
+    }
+
+  if (mi->fps_p) do_fps (mi);
+  glFinish();
+
+  glXSwapBuffers(dpy, window);
+}
+
+XSCREENSAVER_MODULE_2 ("CubeStack", cubestack, cube)
+
+#endif /* USE_GL */
diff --git a/hacks/glx/cubestack.man b/hacks/glx/cubestack.man
new file mode 100644 (file)
index 0000000..511d116
--- /dev/null
@@ -0,0 +1,72 @@
+.TH XScreenSaver 1 "" "X Version 11"
+.SH NAME
+cubestack - An endless stack of unfolding, translucent cubes.
+.SH SYNOPSIS
+.B cubestack
+[\-display \fIhost:display.screen\fP]
+[\-visual \fIvisual\fP]
+[\-window]
+[\-root]
+[\-delay \fInumber\fP]
+[\-speed \fInumber\fP]
+[\-thickness \fInumber\fP]
+[\-opacity \fInumber\fP]
+[\-no-wander]
+[\-wireframe]
+[\-fps]
+.SH DESCRIPTION
+An endless stack of unfolding, translucent cubes.
+.SH OPTIONS
+.TP 8
+.B \-visual \fIvisual\fP
+Specify which visual to use.  Legal values are the name of a visual class,
+or the id number (decimal or hex) of a specific visual.
+.TP 8
+.B \-window
+Draw on a newly-created window.  This is the default.
+.TP 8
+.B \-root
+Draw on the root window.
+.TP 8
+.B \-delay \fInumber\fP
+Per-frame delay, in microseconds.  Default: 30000 (0.03 seconds).
+.TP 8
+.B \-speed \fInumber\fP
+Animation speed.  2.0 means twice as fast, 0.5 means half as fast.
+.TP 8
+.B \-thickness \fInumber\fP
+Thickness of the face edges.  0.0 - 0.5.       Default: 0.13.
+.TP 8
+.B \-opacity \fInumber\fP
+Opacity of the cubes.  0.01 - 1.0.  Default: 0.7.
+.TP 8
+.B \-wander | \-no-wander
+Whether the object should wander around the screen.
+.TP 8
+.B \-wireframe | \-no-wireframe
+Render in wireframe instead of solid.
+.TP 8
+.B \-fps | \-no-fps
+Whether to show a frames-per-second display at the bottom of the screen.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1)
+.SH COPYRIGHT
+Copyright \(co 2016 by Jamie Zawinski.  Permission to use, copy, modify, 
+distribute, and sell this software and its documentation for any purpose is 
+hereby granted without fee, provided that the above copyright notice appear 
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation.  No representations are made about the 
+suitability of this software for any purpose.  It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+Jamie Zawinski.
diff --git a/hacks/glx/cubetwist.c b/hacks/glx/cubetwist.c
new file mode 100644 (file)
index 0000000..8205561
--- /dev/null
@@ -0,0 +1,594 @@
+/* cubetwist, Copyright (c) 2016 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
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation.  No representations are made about the suitability of this
+ * software for any purpose.  It is provided "as is" without express or 
+ * implied warranty.
+ */
+
+#define DEFAULTS       "*delay:        30000       \n" \
+                       "*showFPS:      False       \n" \
+                       "*wireframe:    False       \n" \
+                       "*suppressRotationAnimation: True\n" \
+
+# define refresh_cube 0
+#undef countof
+#define countof(x) (sizeof((x))/sizeof((*x)))
+
+#include "xlockmore.h"
+#include "normals.h"
+#include "rotator.h"
+#include "gltrackball.h"
+#include <ctype.h>
+
+#ifdef USE_GL /* whole file */
+
+
+#define DEF_SPIN         "True"
+#define DEF_WANDER       "True"
+#define DEF_SPEED        "1.0"
+#define DEF_FLAT         "True"
+#define DEF_THICKNESS    "0.0"
+#define DEF_DISPLACEMENT "0.0"
+
+typedef struct cube cube;
+struct cube {
+  GLfloat size, thickness;
+  XYZ pos, rot;
+  GLfloat color[4];
+  cube *next;
+};
+
+typedef struct oscillator oscillator;
+struct oscillator {
+  double ratio, from, to, speed, *var;
+  int remaining;
+  oscillator *next;
+};
+
+typedef struct {
+  GLXContext *glx_context;
+  rotator *rot;
+  trackball_state *trackball;
+  Bool button_down_p;
+  cube *cubes;
+  oscillator *oscillators;
+} cube_configuration;
+
+static cube_configuration *bps = NULL;
+
+static Bool do_flat;
+static Bool do_spin;
+static GLfloat speed;
+static GLfloat thickness;
+static GLfloat displacement;
+static Bool do_wander;
+
+static XrmOptionDescRec opts[] = {
+  { "-spin",   ".spin",   XrmoptionNoArg, "True" },
+  { "+spin",   ".spin",   XrmoptionNoArg, "False" },
+  { "-wander", ".wander", XrmoptionNoArg, "True" },
+  { "+wander", ".wander", XrmoptionNoArg, "False" },
+  { "-flat",   ".flat",   XrmoptionNoArg, "True" },
+  { "+flat",   ".flat",   XrmoptionNoArg, "False" },
+  { "-speed",  ".speed",  XrmoptionSepArg, 0 },
+  { "-thickness",  ".thickness",  XrmoptionSepArg, 0 },
+  { "-displacement",  ".displacement",  XrmoptionSepArg, 0 },
+};
+
+static argtype vars[] = {
+  {&do_flat,   "flat",   "flat",   DEF_FLAT,   t_Bool},
+  {&do_spin,   "spin",   "Spin",   DEF_SPIN,   t_Bool},
+  {&do_wander, "wander", "Wander", DEF_WANDER, t_Bool},
+  {&speed,     "speed",  "Speed",  DEF_SPEED,  t_Float},
+  {&thickness, "thickness", "Thickness", DEF_THICKNESS, t_Float},
+  {&displacement, "displacement", "Displacement", DEF_DISPLACEMENT, t_Float},
+};
+
+ENTRYPOINT ModeSpecOpt cube_opts = {countof(opts), opts, countof(vars), vars, NULL};
+
+
+static int
+draw_strut (ModeInfo *mi, cube *c)
+{
+  int wire = MI_IS_WIREFRAME(mi);
+  int polys = 0;
+
+  glPushMatrix();
+  glFrontFace (GL_CW);
+  glNormal3f (0, 0, -1);
+  glTranslatef (-c->size/2, -c->size/2, -c->size/2);
+
+  glBegin (wire ? GL_LINE_LOOP : GL_TRIANGLE_FAN);
+  glVertex3f (0, 0, 0);
+  glVertex3f (c->size, 0, 0);
+  glVertex3f (c->size - c->thickness, c->thickness, 0);
+  glVertex3f (c->thickness, c->thickness, 0);
+  glEnd();
+  polys += 2;
+
+  glNormal3f (0, 1, 0);
+  glBegin (wire ? GL_LINE_LOOP : GL_TRIANGLE_FAN);
+  glVertex3f (c->thickness, c->thickness, 0);
+  glVertex3f (c->size - c->thickness, c->thickness, 0);
+  glVertex3f (c->size - c->thickness, c->thickness, c->thickness);
+  glVertex3f (c->thickness, c->thickness, c->thickness);
+  glEnd();
+  polys += 2;
+  glPopMatrix();
+
+  return polys;
+}
+
+
+static int
+draw_cubes (ModeInfo *mi, cube *c)
+{
+  int polys = 0;
+  int i, j;
+
+  glPushMatrix();
+  glColor4fv (c->color);
+  glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, c->color);
+
+  glPushMatrix();
+  for (j = 0; j < 6; j++)
+    {
+      for (i = 0; i < 4; i++)
+        {
+          polys += draw_strut (mi, c);
+          glRotatef (90, 0, 0, 1);
+        }
+      if (j == 3)
+        glRotatef (90, 0, 0, 1);
+      if (j < 4)
+        glRotatef (90, 0, 1, 0);
+      else
+        glRotatef (180, 1, 0, 0);
+    }
+  glPopMatrix();
+
+  if (c->next)
+    {
+      glRotatef (c->rot.x, 1, 0, 0);
+      glRotatef (c->rot.y, 0, 1, 0);
+      glRotatef (c->rot.z, 0, 0, 1);
+      glTranslatef (c->pos.x, c->pos.y, c->pos.z);
+      c->next->pos = c->pos;
+      c->next->rot = c->rot;
+      polys += draw_cubes (mi, c->next);
+    }
+  glPopMatrix();
+
+  return polys;
+}
+
+
+static void
+make_cubes (ModeInfo *mi)
+{
+  cube_configuration *bp = &bps[MI_SCREEN(mi)];
+  GLfloat step = 2 * (thickness + displacement);
+  GLfloat size = 1.0;
+  cube *tail = 0;
+  GLfloat cc[4], cstep;
+  int depth = 0;
+  cube *c;
+
+  cc[0] = 0.3 + frand(0.7);
+  cc[1] = 0.3 + frand(0.7);
+  cc[2] = 0.3 + frand(0.7);
+  cc[3] = 1;
+
+  if (bp->cubes) abort();
+  while (1)
+    {
+      cube *c = (cube *) calloc (1, sizeof (*c));
+      c->size = size;
+      c->thickness = thickness;
+      if (tail)
+        tail->next = c;
+      else
+        bp->cubes = c;
+      tail = c;
+
+      depth++;
+      size -= step;
+      if (size <= step)
+        break;
+    }
+
+  cstep = 0.8 / depth;
+  for (c = bp->cubes; c; c = c->next)
+    {
+      memcpy (c->color, cc, sizeof(cc));
+      cc[0] -= cstep;
+      cc[1] -= cstep;
+      cc[2] -= cstep;
+    }
+}
+
+
+static GLfloat
+ease_fn (GLfloat r)
+{
+  return cos ((r/2 + 1) * M_PI) + 1; /* Smooth curve up, end at slope 1. */
+}
+
+
+static GLfloat
+ease_ratio (GLfloat r)
+{
+  GLfloat ease = 0.5;
+  if      (r <= 0)     return 0;
+  else if (r >= 1)     return 1;
+  else if (r <= ease)  return     ease * ease_fn (r / ease);
+  else if (r > 1-ease) return 1 - ease * ease_fn ((1 - r) / ease);
+  else                 return r;
+}
+
+
+static void
+tick_oscillators (ModeInfo *mi)
+{
+  cube_configuration *bp = &bps[MI_SCREEN(mi)];
+  oscillator *prev = 0;
+  oscillator *a = bp->oscillators;
+  GLfloat tick = 0.1 / speed;
+
+  while (a)
+    {
+      oscillator *next = a->next;
+      a->ratio += tick * a->speed;
+      if (a->ratio > 1)
+        a->ratio = 1;
+
+      *a->var = a->from + (a->to - a->from) * ease_ratio (a->ratio);
+
+      if (a->ratio < 1)                        /* mid cycle */
+        prev = a;
+      else if (--a->remaining <= 0)    /* ended, and expired */
+        {
+          if (prev)
+            prev->next = next;
+          else
+            bp->oscillators = next;
+          free (a);
+        }
+      else                             /* keep going the other way */
+        {
+          GLfloat swap = a->from;
+          a->from = a->to;
+          a->to = swap;
+          a->ratio = 0;
+          prev = a;
+        }
+
+      a = next;
+    }
+}
+
+
+static void
+add_oscillator (ModeInfo *mi, double *var, GLfloat speed, GLfloat to,
+                int repeat)
+{
+  cube_configuration *bp = &bps[MI_SCREEN(mi)];
+  oscillator *a;
+
+  /* If an oscillator is already running on this variable, don't
+     add another. */
+  for (a = bp->oscillators; a && a->next; a = a->next)
+    if (a->var == var)
+      return;
+
+  a = (oscillator *) calloc (1, sizeof (*a));
+  if (repeat <= 0) abort();
+  a->ratio = 0;
+  a->from = *var;
+  a->to = to;
+  a->speed = speed;
+  a->var = var;
+  a->remaining = repeat;
+  a->next = bp->oscillators;
+  bp->oscillators = a;
+# if 0
+  fprintf (stderr, "%s: %3d %6.2f -> %6.2f %s\n",
+           progname, repeat, *var, to,
+           (var == &bp->midpoint.z ? "z" :
+            var == &bp->tilt ? "tilt" :
+            var == &bp->axial_radius ? "r" :
+            var == &bp->speed ? "speed" : "?"));
+# endif
+}
+
+
+#undef RANDSIGN
+#define RANDSIGN() ((random() & 1) ? 1 : -1)
+
+static void
+add_random_oscillator (ModeInfo *mi)
+{
+  cube_configuration *bp = &bps[MI_SCREEN(mi)];
+  cube *c = bp->cubes;
+  double s1 = speed * 0.07;
+  double s2 = speed * 0.3;
+  double disp = (thickness + displacement);
+  int c1 = 1 + ((random() % 4) ? 0 : (random() % 3));
+  int c2 = 2;
+  int n = random() % 6;
+
+  switch (n) {
+  case 0: add_oscillator (mi, &c->rot.x, s1, 90 * RANDSIGN(), c1); break;
+  case 1: add_oscillator (mi, &c->rot.y, s1, 90 * RANDSIGN(), c1); break;
+  case 2: add_oscillator (mi, &c->rot.z, s1, 90 * RANDSIGN(), c1); break;
+  case 3: add_oscillator (mi, &c->pos.x, s2, disp * RANDSIGN(), c2); break;
+  case 4: add_oscillator (mi, &c->pos.y, s2, disp * RANDSIGN(), c2); break;
+  case 5: add_oscillator (mi, &c->pos.z, s2, disp * RANDSIGN(), c2); break;
+  default: abort(); break;
+  }
+}
+
+
+/* Window management, etc
+ */
+ENTRYPOINT void
+reshape_cube (ModeInfo *mi, int width, int height)
+{
+  GLfloat h = (GLfloat) height / (GLfloat) width;
+
+  glViewport (0, 0, (GLint) width, (GLint) height);
+
+  glMatrixMode(GL_PROJECTION);
+  glLoadIdentity();
+  gluPerspective (30.0, 1/h, 1.0, 100.0);
+
+  glMatrixMode(GL_MODELVIEW);
+  glLoadIdentity();
+  gluLookAt( 0.0, 0.0, 30.0,
+             0.0, 0.0, 0.0,
+             0.0, 1.0, 0.0);
+
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+  {
+    int o = (int) current_device_rotation();
+    if (o != 0 && o != 180 && o != -180)
+      glScalef (1/h, 1/h, 1/h);
+  }
+# endif
+
+  glClear(GL_COLOR_BUFFER_BIT);
+}
+
+
+ENTRYPOINT Bool
+cube_handle_event (ModeInfo *mi, XEvent *event)
+{
+  cube_configuration *bp = &bps[MI_SCREEN(mi)];
+
+  if (gltrackball_event_handler (event, bp->trackball,
+                                 MI_WIDTH (mi), MI_HEIGHT (mi),
+                                 &bp->button_down_p))
+    return True;
+  else if (event->xany.type == KeyPress)
+    {
+      KeySym keysym;
+      char c = 0;
+      XLookupString (&event->xkey, &c, 1, &keysym, 0);
+      if (c == ' ' || c == '\t')
+        {
+          while (bp->cubes)
+            {
+              cube *c = bp->cubes->next;
+              free (bp->cubes);
+              bp->cubes = c;
+            }
+
+          while (bp->oscillators)
+            {
+              oscillator *o = bp->oscillators->next;
+              free (bp->oscillators);
+              bp->oscillators = o;
+            }
+
+          if (random() & 1)
+            {
+              thickness = 0.03 + frand(0.02);
+              displacement = (random() & 1) ? 0 : (thickness / 3);
+            }
+          else
+            {
+              thickness = 0.001 + frand(0.02);
+              displacement = 0;
+            }
+
+          make_cubes (mi);
+
+          return True;
+        }
+    }
+
+  return False;
+}
+
+
+ENTRYPOINT void 
+init_cube (ModeInfo *mi)
+{
+  cube_configuration *bp;
+  int wire = MI_IS_WIREFRAME(mi);
+
+  if (!bps) {
+    bps = (cube_configuration *)
+      calloc (MI_NUM_SCREENS(mi), sizeof (cube_configuration));
+    if (!bps) {
+      fprintf(stderr, "%s: out of memory\n", progname);
+      exit(1);
+    }
+  }
+
+  bp = &bps[MI_SCREEN(mi)];
+
+  bp->glx_context = init_GL(mi);
+
+  reshape_cube (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
+
+  if (!wire && !do_flat)
+    {
+      GLfloat color[4] = {1, 1, 1, 1};
+      GLfloat cspec[4] = {1, 1, 0, 1};
+      static const GLfloat shiny = 30;
+
+      static GLfloat pos0[4] = { 0.5, -1, -0.5, 0};
+      static GLfloat pos1[4] = {-0.75, -1, 0, 0};
+      static GLfloat amb[4] = {0, 0, 0, 1};
+      static GLfloat dif[4] = {1, 1, 1, 1};
+      static GLfloat spc[4] = {1, 1, 1, 1};
+
+      glEnable(GL_LIGHTING);
+      glEnable(GL_LIGHT0);
+      glEnable(GL_LIGHT1);
+      glEnable(GL_DEPTH_TEST);
+      glEnable(GL_CULL_FACE);
+
+      glLightfv(GL_LIGHT0, GL_POSITION, pos0);
+      glLightfv(GL_LIGHT0, GL_AMBIENT,  amb);
+      glLightfv(GL_LIGHT0, GL_DIFFUSE,  dif);
+      glLightfv(GL_LIGHT0, GL_SPECULAR, spc);
+
+      glLightfv(GL_LIGHT1, GL_POSITION, pos1);
+      glLightfv(GL_LIGHT1, GL_AMBIENT,  amb);
+      glLightfv(GL_LIGHT1, GL_DIFFUSE,  dif);
+      glLightfv(GL_LIGHT1, GL_SPECULAR, spc);
+
+      glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, color);
+      glMaterialfv (GL_FRONT, GL_SPECULAR,  cspec);
+      glMateriali  (GL_FRONT, GL_SHININESS, shiny);
+    }
+
+  {
+    double spin_speed   = 0.05;
+    double wander_speed = 0.005;
+    double spin_accel   = 1.0;
+
+    bp->rot = make_rotator (do_spin ? spin_speed : 0,
+                            do_spin ? spin_speed : 0,
+                            do_spin ? spin_speed : 0,
+                            spin_accel,
+                            do_wander ? wander_speed : 0,
+                            True);
+    bp->trackball = gltrackball_init (True);
+  }
+
+  if (thickness > 0.5)
+    thickness = 0.5;
+  if (displacement > 0.5)
+    displacement = 0.5;
+
+  if (thickness <= 0.0001)
+    {
+      if (random() & 1)
+        {
+          thickness = 0.03 + frand(0.02);
+          displacement = (random() & 1) ? 0 : (thickness / 3);
+        }
+      else
+        {
+          thickness = 0.001 + frand(0.02);
+          displacement = 0;
+        }
+    }
+
+  make_cubes (mi);
+}
+
+
+ENTRYPOINT void
+draw_cube (ModeInfo *mi)
+{
+  cube_configuration *bp = &bps[MI_SCREEN(mi)];
+  Display *dpy = MI_DISPLAY(mi);
+  Window window = MI_WINDOW(mi);
+
+  if (!bp->glx_context)
+    return;
+
+  glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(bp->glx_context));
+
+  glShadeModel(GL_SMOOTH);
+  glEnable(GL_DEPTH_TEST);
+  glEnable(GL_NORMALIZE);
+  glEnable(GL_CULL_FACE);
+
+  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+  glPushMatrix ();
+
+  glScalef(1.1, 1.1, 1.1);
+
+  {
+    double x, y, z;
+    get_position (bp->rot, &x, &y, &z, !bp->button_down_p);
+    glTranslatef((x - 0.5) * 4,
+                 (y - 0.5) * 4,
+                 (z - 0.5) * 2);
+
+    gltrackball_rotate (bp->trackball);
+
+    get_rotation (bp->rot, &x, &y, &z, !bp->button_down_p);
+    glRotatef (x * 360, 1.0, 0.0, 0.0);
+    glRotatef (y * 360, 0.0, 1.0, 0.0);
+    glRotatef (z * 360, 0.0, 0.0, 1.0);
+  }
+
+  mi->polygon_count = 0;
+
+  glScalef (6, 6, 6);
+
+  mi->polygon_count = draw_cubes (mi, bp->cubes);
+  glPopMatrix ();
+
+  if (!bp->button_down_p)
+    tick_oscillators (mi);
+
+  if (! bp->oscillators &&
+      !bp->button_down_p &&
+      !(random() % 60))
+    {
+      bp->cubes->pos.x = bp->cubes->pos.y = bp->cubes->pos.z = 0;
+      bp->cubes->rot.x = bp->cubes->rot.y = bp->cubes->rot.z = 0;
+      add_random_oscillator (mi);
+    }
+
+  if (mi->fps_p) do_fps (mi);
+  glFinish();
+
+  glXSwapBuffers(dpy, window);
+}
+
+ENTRYPOINT void
+release_cube (ModeInfo *mi)
+{
+  cube_configuration *bp = &bps[MI_SCREEN(mi)];
+  while (bp->cubes)
+    {
+      cube *c = bp->cubes->next;
+      free (bp->cubes);
+      bp->cubes = c;
+    }
+
+  while (bp->oscillators)
+    {
+      oscillator *o = bp->oscillators->next;
+      free (bp->oscillators);
+      bp->oscillators = o;
+    }
+}
+
+
+XSCREENSAVER_MODULE_2 ("CubeTwist", cubetwist, cube)
+
+#endif /* USE_GL */
diff --git a/hacks/glx/cubetwist.man b/hacks/glx/cubetwist.man
new file mode 100644 (file)
index 0000000..3a6574b
--- /dev/null
@@ -0,0 +1,80 @@
+.TH XScreenSaver 1 "" "X Version 11"
+.SH NAME
+cubetwist - A series of nested cubes rotate and slide recursively.
+.SH SYNOPSIS
+.B cubetwist
+[\-display \fIhost:display.screen\fP]
+[\-visual \fIvisual\fP]
+[\-window]
+[\-root]
+[\-delay \fInumber\fP]
+[\-speed \fInumber\fP]
+[\-thickness \fInumber\fP]
+[\-displacement \fInumber\fP]
+[\-no-flat]
+[\-no-wander]
+[\-no-spin]
+[\-wireframe]
+[\-fps]
+.SH DESCRIPTION
+A series of nested cubes rotate and slide recursively.
+.SH OPTIONS
+.TP 8
+.B \-visual \fIvisual\fP
+Specify which visual to use.  Legal values are the name of a visual class,
+or the id number (decimal or hex) of a specific visual.
+.TP 8
+.B \-window
+Draw on a newly-created window.  This is the default.
+.TP 8
+.B \-root
+Draw on the root window.
+.TP 8
+.B \-delay \fInumber\fP
+Per-frame delay, in microseconds.  Default: 30000 (0.03 seconds).
+.TP 8
+.B \-speed \fInumber\fP
+Animation speed.  2.0 means twice as fast, 0.5 means half as fast.
+.TP 8
+.B \-thickness \fInumber\fP
+Thickness of the cube edges.  0.005 - 0.2.  Default: 0.05.
+.TP 8
+.B \-displacement \fInumber\fP
+Displacement between nested cubes.  0.0 - 0.2.  Default: 0.01.
+.TP 8
+.B \-flat | \-no-flat
+Whether to use flat shading, or lighting.  Default flat.
+.TP 8
+.B \-wander | \-no-wander
+Whether the object should wander around the screen.
+.TP 8
+.B \-spin | \-no-spin
+Whether the object should spin.
+.TP 8
+.B \-wireframe | \-no-wireframe
+Render in wireframe instead of solid.
+.TP 8
+.B \-fps | \-no-fps
+Whether to show a frames-per-second display at the bottom of the screen.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1)
+.SH COPYRIGHT
+Copyright \(co 2016 by Jamie Zawinski.  Permission to use, copy, modify, 
+distribute, and sell this software and its documentation for any purpose is 
+hereby granted without fee, provided that the above copyright notice appear 
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation.  No representations are made about the 
+suitability of this software for any purpose.  It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+Jamie Zawinski.
diff --git a/hacks/glx/discoball.c b/hacks/glx/discoball.c
new file mode 100644 (file)
index 0000000..5e8ee92
--- /dev/null
@@ -0,0 +1,707 @@
+/* discoball, Copyright (c) 2016 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
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation.  No representations are made about the suitability of this
+ * software for any purpose.  It is provided "as is" without express or 
+ * implied warranty.
+ */
+
+#define DEFAULTS       "*delay:        30000       \n" \
+                       "*count:        30          \n" \
+                       "*showFPS:      False       \n" \
+                       "*wireframe:    False       \n" \
+
+# define refresh_ball 0
+#undef countof
+#define countof(x) (sizeof((x))/sizeof((*x)))
+
+#include "xlockmore.h"
+#include "normals.h"
+#include "rotator.h"
+#include "gltrackball.h"
+#include <ctype.h>
+
+#ifdef USE_GL /* whole file */
+
+
+#define DEF_SPIN        "False"
+#define DEF_WANDER      "True"
+#define DEF_SPEED       "1.0"
+
+typedef struct tile tile;
+struct tile {
+  XYZ position, normal;
+  GLfloat size, tilt;
+  tile *next;
+};
+
+
+typedef struct {
+  XYZ normal;
+  GLfloat color[4];
+} ray;
+
+typedef struct {
+  GLXContext *glx_context;
+  rotator *rot;
+  GLfloat th;
+  trackball_state *trackball;
+  Bool button_down_p;
+  tile *tiles;
+  int nrays;
+  ray *rays;
+} ball_configuration;
+
+static ball_configuration *bps = NULL;
+
+static Bool do_spin;
+static GLfloat speed;
+static Bool do_wander;
+
+static XrmOptionDescRec opts[] = {
+  { "-spin",   ".spin",   XrmoptionNoArg, "True" },
+  { "+spin",   ".spin",   XrmoptionNoArg, "False" },
+  { "-speed",  ".speed",  XrmoptionSepArg, 0 },
+  { "-wander", ".wander", XrmoptionNoArg, "True" },
+  { "+wander", ".wander", XrmoptionNoArg, "False" }
+};
+
+static argtype vars[] = {
+  {&do_spin,   "spin",   "Spin",   DEF_SPIN,   t_Bool},
+  {&do_wander, "wander", "Wander", DEF_WANDER, t_Bool},
+  {&speed,     "speed",  "Speed",  DEF_SPEED,  t_Float},
+};
+
+ENTRYPOINT ModeSpecOpt ball_opts = {countof(opts), opts, countof(vars), vars, NULL};
+
+
+static XYZ
+normalize (XYZ p)
+{
+  GLfloat d = sqrt(p.x*p.x + p.y*p.y * p.z*p.z);
+  if (d < 0.0000001)
+    p.x = p.y = p.z = 0;
+  else
+    {
+      p.x /= d;
+      p.y /= d;
+      p.z /= d;
+    }
+    
+  return p;
+}
+
+
+static void
+build_texture (ModeInfo *mi)
+{
+  int x, y;
+  int size = 128;
+  int bpl = size * 2;
+  unsigned char *data = malloc (bpl * size);
+
+  for (y = 0; y < size; y++)
+    {
+      for (x = 0; x < size; x++)
+        {
+          unsigned char *c = &data [y * bpl + x * 2];
+          GLfloat X = (x / (GLfloat) (size-1)) - 0.5;
+          GLfloat Y = (y / (GLfloat) (size-1)) - 0.5;
+          X = cos (X * X * 6.2);
+          Y = cos (Y * Y * 6.2);
+          X = X < Y ? X : Y;
+          X *= 0.4;
+          c[0] = 0xFF;
+          c[1] = 0xFF * X;
+        }
+    }
+
+  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+  glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+  glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
+  check_gl_error ("texture param");
+
+  glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, size, size, 0,
+                GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, data);
+  check_gl_error ("light texture");
+  free (data);
+}
+
+
+static int
+draw_rays (ModeInfo *mi)
+{
+  ball_configuration *bp = &bps[MI_SCREEN(mi)];
+  int wire = MI_IS_WIREFRAME(mi);
+  int polys = 0;
+  int i;
+
+  glEnable (GL_TEXTURE_2D);
+  glDisable (GL_LIGHTING);
+  glEnable (GL_BLEND);
+  glDisable (GL_DEPTH_TEST);
+  glBlendFunc (GL_SRC_ALPHA, GL_ONE);
+
+  for (i = 0; i < bp->nrays; i++)
+    {
+      GLfloat x = bp->rays[i].normal.x;
+      GLfloat y = bp->rays[i].normal.y;
+      GLfloat z = bp->rays[i].normal.z;
+      glPushMatrix();
+
+      /* Orient to direction of ray. */
+      glRotatef (-atan2 (x, y)               * (180 / M_PI), 0, 0, 1);
+      glRotatef ( atan2 (z, sqrt(x*x + y*y)) * (180 / M_PI), 1, 0, 0);
+
+      glScalef (5, 5, 10);
+      glTranslatef(0, 0, 1.1);
+      glColor4fv (bp->rays[i].color);
+      glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
+      glTexCoord2f (0, 0); glVertex3f (-0.5, 0, -1);
+      glTexCoord2f (1, 0); glVertex3f ( 0.5, 0, -1);
+      glTexCoord2f (1, 1); glVertex3f ( 0.5, 0,  1);
+      glTexCoord2f (0, 1); glVertex3f (-0.5, 0,  1);
+      glEnd();
+      polys++;
+      glPopMatrix();
+    }
+
+  glDisable (GL_TEXTURE_2D);
+  glEnable (GL_LIGHTING);
+  glDisable (GL_BLEND);
+  glEnable (GL_DEPTH_TEST);
+  glDisable (GL_FOG);
+
+  return polys;
+}
+
+
+static int
+draw_ball_1 (ModeInfo *mi)
+{
+  ball_configuration *bp = &bps[MI_SCREEN(mi)];
+  int wire = MI_IS_WIREFRAME(mi);
+  int polys = 0;
+  tile *t;
+  GLfloat m[4][4];
+
+  glGetFloatv (GL_MODELVIEW_MATRIX, &m[0][0]);
+
+  glFrontFace (GL_CW);
+
+#if 0
+  /* Draw the back rays.
+   */
+  if (! wire)
+    {
+      glPushMatrix();
+      glLoadIdentity();
+      glMultMatrixf (&m[0][0]);
+      glTranslatef(0, 0, -4.1);
+      glRotatef (bp->th, 0, 0, 1);
+      polys += draw_rays (mi);
+      glPopMatrix();
+    }
+  glClear(GL_DEPTH_BUFFER_BIT);
+#endif
+
+
+  /* Instead of rendering polygons for the foam ball substrate, let's
+     just billboard a quad down the middle to mask out the back-facing
+     tiles. */
+  {
+    glPushMatrix();
+    m[0][0] = 1; m[1][0] = 0; m[2][0] = 0;
+    m[0][1] = 0; m[1][1] = 1; m[2][1] = 0;
+    m[0][2] = 0; m[1][2] = 0; m[2][2] = 1;
+    glLoadIdentity();
+    glMultMatrixf (&m[0][0]);
+    glScalef (40, 40, 40);
+    glTranslatef (-0.5, -0.5, -0.01);
+    if (! wire)
+      glDisable (GL_LIGHTING);
+    /* Draw into the depth buffer but not the frame buffer */
+    glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+    glColor3f (0, 0, 0);
+    glBegin (GL_QUADS);
+    glVertex3f (0, 0, 0);
+    glVertex3f (0, 1, 0);
+    glVertex3f (1, 1, 0);
+    glVertex3f (1, 0, 0);
+    glEnd();
+    polys++;
+    glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+    if (! wire)
+      glEnable (GL_LIGHTING);
+    glPopMatrix();
+    glColor3f (1, 1, 1);
+  }
+
+  /* Draw all the tiles.
+   */
+  for (t = bp->tiles; t; t = t->next)
+    {
+      GLfloat x = t->normal.x;
+      GLfloat y = t->normal.y;
+      GLfloat z = t->normal.z;
+      GLfloat s = t->size / 2;
+      glPushMatrix();
+
+      /* Move to location of tile. */
+      glTranslatef (t->position.x, t->position.y, t->position.z);
+
+      /* Orient to direction tile is facing. */
+      glRotatef (-atan2 (x, y)               * (180 / M_PI), 0, 0, 1);
+      glRotatef ( atan2 (z, sqrt(x*x + y*y)) * (180 / M_PI), 1, 0, 0);
+
+      glRotatef (t->tilt, 0, 1, 0);
+
+      glScalef (s, s, s);
+      glNormal3f (0, 1, 0);
+      glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
+      glVertex3f (-1, 0, -1);
+      glVertex3f ( 1, 0, -1);
+      glVertex3f ( 1, 0,  1);
+      glVertex3f (-1, 0,  1);
+      glEnd();
+      polys++;
+
+      if (! wire)
+        {
+          GLfloat d = 0.2;
+          glNormal3f (0, 0, -1);
+          glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
+          glVertex3f (-1,  0, -1);
+          glVertex3f (-1, -d, -1);
+          glVertex3f ( 1, -d, -1);
+          glVertex3f ( 1,  0, -1);
+          glEnd();
+          polys++;
+
+          glNormal3f (0, 0, 1);
+          glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
+          glVertex3f ( 1,  0,  1);
+          glVertex3f ( 1, -d,  1);
+          glVertex3f (-1, -d,  1);
+          glVertex3f (-1,  0,  1);
+          glEnd();
+          polys++;
+
+          glNormal3f (1, 0, 0);
+          glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
+          glVertex3f ( 1,  0, -1);
+          glVertex3f ( 1, -d, -1);
+          glVertex3f ( 1, -d,  1);
+          glVertex3f ( 1,  0,  1);
+          glEnd();
+          polys++;
+
+          glNormal3f (-1, 0, 0);
+          glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
+          glVertex3f (-1,  0,  1);
+          glVertex3f (-1, -d,  1);
+          glVertex3f (-1, -d, -1);
+          glVertex3f (-1,  0, -1);
+          glEnd();
+          polys++;
+        }
+
+      glPopMatrix();
+    }
+
+  /* Draw the front rays.
+   */
+  if (! wire)
+    {
+      glPushMatrix();
+      glLoadIdentity();
+      glMultMatrixf (&m[0][0]);
+      glTranslatef(0, 0, 4.1);
+      glRotatef (-bp->th, 0, 0, 1);
+      polys += draw_rays (mi);
+      glPopMatrix();
+    }
+
+  return polys;
+}
+
+
+static GLfloat
+vector_angle (XYZ a, XYZ b)
+{
+  double La = sqrt (a.x*a.x + a.y*a.y + a.z*a.z);
+  double Lb = sqrt (b.x*b.x + b.y*b.y + b.z*b.z);
+  double cc, angle;
+
+  if (La == 0 || Lb == 0) return 0;
+  if (a.x == b.x && a.y == b.y && a.z == b.z) return 0;
+
+  /* dot product of two vectors is defined as:
+       La * Lb * cos(angle between vectors)
+     and is also defined as:
+       ax*bx + ay*by + az*bz
+     so:
+      La * Lb * cos(angle) = ax*bx + ay*by + az*bz
+      cos(angle)  = (ax*bx + ay*by + az*bz) / (La * Lb)
+      angle = acos ((ax*bx + ay*by + az*bz) / (La * Lb));
+  */
+  cc = (a.x*b.x + a.y*b.y + a.z*b.z) / (La * Lb);
+  if (cc > 1) cc = 1;  /* avoid fp rounding error (1.000001 => sqrt error) */
+  angle = acos (cc);
+
+  return (angle);
+}
+
+
+#undef RANDSIGN
+#define RANDSIGN() ((random() & 1) ? 1 : -1)
+
+#undef BELLRAND
+#define BELLRAND(n) ((frand((n)) + frand((n)) + frand((n))) / 3)
+
+static void
+build_ball (ModeInfo *mi)
+{
+  ball_configuration *bp = &bps[MI_SCREEN(mi)];
+  int rows = MI_COUNT (mi);
+
+  GLfloat tile_size = M_PI / rows;
+  GLfloat th0, th1;
+
+  struct { XYZ position; GLfloat strength; } dents[5];
+  int dent_count = random() % countof(dents);
+  int i;
+  for (i = 0; i < dent_count; i++)
+    {
+      GLfloat dist;
+      dents[i].position.x = RANDSIGN() * (2 - BELLRAND(0.2));
+      dents[i].position.y = RANDSIGN() * (2 - BELLRAND(0.2));
+      dents[i].position.z = RANDSIGN() * (2 - BELLRAND(0.2));
+      dist = sqrt (dents[i].position.x * dents[i].position.x +
+                   dents[i].position.y * dents[i].position.y +
+                   dents[i].position.z * dents[i].position.z);
+      dents[i].strength = dist - (1 - BELLRAND(0.3));
+      dents[i].strength = dist - (1 - BELLRAND(0.3));
+    }
+
+
+  for (th1 = M_PI/2; th1 > -(M_PI/2 + tile_size/2); th1 -= tile_size)
+    {
+      GLfloat x  = cos (th1);
+      GLfloat y  = sin (th1);
+      GLfloat x0 = cos (th1 - tile_size/2);
+      GLfloat x1 = cos (th1 + tile_size/2);
+      GLfloat circ0 = M_PI * x0 * 2;
+      GLfloat circ1 = M_PI * x1 * 2;
+      GLfloat circ  = (circ0 < circ1 ? circ0 : circ1);
+      int row_tiles = floor ((circ < 0 ? 0 : circ) / tile_size);
+      GLfloat spacing;
+      GLfloat dropsy = 0.13 + frand(0.04);
+
+      if (row_tiles <= 0) row_tiles = 1;
+      spacing = M_PI*2 / row_tiles;
+
+      for (th0 = 0; th0 < M_PI*2; th0 += spacing)
+        {
+          tile *t = (tile *) calloc (1, sizeof(*t));
+          t->size = tile_size * 0.85;
+          t->position.x = cos (th0) * x;
+          t->position.y = sin (th0) * x;
+          t->position.z = y;
+
+          t->normal = t->position;
+
+          /* Apply pressure on position from the dents. */
+          for (i = 0; i < dent_count; i++)
+            {
+              GLfloat dist;
+              XYZ direction;
+
+              if (! (random() % 150))  /* Drop tiles randomly */
+                {
+                  free (t);
+                  goto SKIP;
+                }
+
+              direction.x = t->position.x - dents[i].position.x;
+              direction.y = t->position.y - dents[i].position.y;
+              direction.z = t->position.z - dents[i].position.z;
+              dist = sqrt (direction.x * direction.x +
+                           direction.y * direction.y +
+                           direction.z * direction.z);
+              if (dist < dents[i].strength)
+                {
+                  GLfloat s = 1 - (dents[i].strength - dist) * 0.66;
+                  XYZ n2 = t->normal;
+                  GLfloat angle = vector_angle (t->position, dents[i].position);
+
+                  /* Drop out the tiles near the apex of the dent. */
+                  if (angle < dropsy)
+                    {
+                      free (t);
+                      goto SKIP;
+                    }
+
+                  t->position.x *= s;
+                  t->position.y *= s;
+                  t->position.z *= s;
+
+                  direction = normalize (direction);
+                  n2.x -= direction.x;
+                  n2.y -= direction.y;
+                  n2.z -= direction.z;
+
+                  t->normal.x = (t->normal.x + n2.x) / 2;
+                  t->normal.y = (t->normal.y + n2.y) / 2;
+                  t->normal.z = (t->normal.z + n2.z) / 2;
+                }
+            }
+
+          /* Skew the direction the tile is facing slightly. */
+          t->normal.x += 0.12 - frand(0.06);
+          t->normal.y += 0.12 - frand(0.06);
+          t->normal.z += 0.12 - frand(0.06);
+          t->tilt = 4 - BELLRAND(8);
+
+          t->next = bp->tiles;
+          bp->tiles = t;
+        SKIP: ;
+        }
+    }
+
+  bp->nrays = 5 + BELLRAND(10);
+  bp->rays = (ray *) calloc (bp->nrays, sizeof(*bp->rays));
+  for (i = 0; i < bp->nrays; i++)
+    {
+      GLfloat th = frand(M_PI * 2);
+      bp->rays[i].normal.x = cos (th);
+      bp->rays[i].normal.y = sin (th);
+      bp->rays[i].normal.z = 1;
+      bp->rays[i].normal = normalize (bp->rays[i].normal);
+      bp->rays[i].color[0] = 0.9 + frand(0.1);
+      bp->rays[i].color[1] = 0.6 + frand(0.4);
+      bp->rays[i].color[2] = 0.6 + frand(0.2);
+      bp->rays[i].color[3] = 1;
+    }
+}
+
+
+/* Window management, etc
+ */
+ENTRYPOINT void
+reshape_ball (ModeInfo *mi, int width, int height)
+{
+  GLfloat h = (GLfloat) height / (GLfloat) width;
+
+  glViewport (0, 0, (GLint) width, (GLint) height);
+
+  glMatrixMode(GL_PROJECTION);
+  glLoadIdentity();
+  gluPerspective (30.0, 1/h, 1.0, 100.0);
+
+  glMatrixMode(GL_MODELVIEW);
+  glLoadIdentity();
+  gluLookAt( 0.0, 0.0, 30.0,
+             0.0, 0.0, 0.0,
+             0.0, 1.0, 0.0);
+
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+  {
+    int o = (int) current_device_rotation();
+    if (o != 0 && o != 180 && o != -180)
+      glScalef (1/h, 1/h, 1/h);
+  }
+# endif
+
+  glClear(GL_COLOR_BUFFER_BIT);
+}
+
+
+ENTRYPOINT Bool
+ball_handle_event (ModeInfo *mi, XEvent *event)
+{
+  ball_configuration *bp = &bps[MI_SCREEN(mi)];
+
+  if (gltrackball_event_handler (event, bp->trackball,
+                                 MI_WIDTH (mi), MI_HEIGHT (mi),
+                                 &bp->button_down_p))
+    return True;
+
+  return False;
+}
+
+
+ENTRYPOINT void 
+init_ball (ModeInfo *mi)
+{
+  ball_configuration *bp;
+  int wire = MI_IS_WIREFRAME(mi);
+
+  if (!bps) {
+    bps = (ball_configuration *)
+      calloc (MI_NUM_SCREENS(mi), sizeof (ball_configuration));
+    if (!bps) {
+      fprintf(stderr, "%s: out of memory\n", progname);
+      exit(1);
+    }
+  }
+
+  bp = &bps[MI_SCREEN(mi)];
+
+  bp->glx_context = init_GL(mi);
+
+  if (! wire)
+    build_texture (mi);
+
+  reshape_ball (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
+
+  bp->th = 180 - frand(360);
+
+  if (MI_COUNT(mi) < 10)
+    MI_COUNT(mi) = 10;
+  if (MI_COUNT(mi) > 200)
+    MI_COUNT(mi) = 200;
+
+  {
+    double spin_speed   = 0.1;
+    double wander_speed = 0.003;
+    double spin_accel   = 1;
+
+    bp->rot = make_rotator (do_spin ? spin_speed : 0,
+                            do_spin ? spin_speed : 0,
+                            do_spin ? spin_speed : 0,
+                            spin_accel,
+                            do_wander ? wander_speed : 0,
+                            False);
+    bp->trackball = gltrackball_init (True);
+  }
+
+  build_ball (mi);
+
+  if (!wire)
+    {
+      GLfloat color[4] = {0.5, 0.5, 0.5, 1};
+      GLfloat cspec[4] = {1, 1, 1, 1};
+      static const GLfloat shiny = 10;
+
+      static GLfloat pos0[4] = { 0.5, -1, -0.5, 0};
+      static GLfloat pos1[4] = {-0.75, -1, 0, 0};
+      static GLfloat amb[4] = {0, 0, 0, 1};
+      static GLfloat dif[4] = {1, 1, 1, 1};
+      static GLfloat spc[4] = {1, 1, 1, 1};
+
+      glEnable(GL_LIGHTING);
+      glEnable(GL_LIGHT0);
+      glEnable(GL_LIGHT1);
+      glEnable(GL_DEPTH_TEST);
+      glEnable(GL_CULL_FACE);
+
+      color[0] += frand(0.2);
+      color[1] += frand(0.2);
+      color[2] += frand(0.2);
+
+      cspec[0] -= frand(0.2);
+      cspec[1] -= frand(0.2);
+      cspec[2] -= frand(0.2);
+
+      glLightfv(GL_LIGHT0, GL_POSITION, pos0);
+      glLightfv(GL_LIGHT0, GL_AMBIENT,  amb);
+      glLightfv(GL_LIGHT0, GL_DIFFUSE,  dif);
+      glLightfv(GL_LIGHT0, GL_SPECULAR, spc);
+
+      glLightfv(GL_LIGHT1, GL_POSITION, pos1);
+      glLightfv(GL_LIGHT1, GL_AMBIENT,  amb);
+      glLightfv(GL_LIGHT1, GL_DIFFUSE,  dif);
+      glLightfv(GL_LIGHT1, GL_SPECULAR, spc);
+
+      glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, color);
+      glMaterialfv (GL_FRONT, GL_SPECULAR,  cspec);
+      glMateriali  (GL_FRONT, GL_SHININESS, shiny);
+    }
+}
+
+
+ENTRYPOINT void
+draw_ball (ModeInfo *mi)
+{
+  ball_configuration *bp = &bps[MI_SCREEN(mi)];
+  Display *dpy = MI_DISPLAY(mi);
+  Window window = MI_WINDOW(mi);
+
+  if (!bp->glx_context)
+    return;
+
+  glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(bp->glx_context));
+
+  glShadeModel(GL_SMOOTH);
+
+  glEnable(GL_DEPTH_TEST);
+  glEnable(GL_NORMALIZE);
+  glEnable(GL_CULL_FACE);
+
+  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+  glPushMatrix ();
+
+  glRotatef(current_device_rotation(), 0, 0, 1);
+
+  {
+    double x, y, z;
+    get_position (bp->rot, &x, &y, &z, !bp->button_down_p);
+    glTranslatef((x - 0.5) * 6,
+                 (y - 0.5) * 6,
+                 (z - 0.5) * 2);
+
+    gltrackball_rotate (bp->trackball);
+
+    get_rotation (bp->rot, &x, &y, &z, !bp->button_down_p);
+    glRotatef (x * 360, 1.0, 0.0, 0.0);
+    glRotatef (y * 360, 0.0, 1.0, 0.0);
+    glRotatef (z * 360, 0.0, 0.0, 1.0);
+  }
+
+  mi->polygon_count = 0;
+
+  glRotatef (50, 1, 0, 0);
+
+  glScalef (4, 4, 4);
+  glRotatef (bp->th, 0, 0, 1);
+  if (! bp->button_down_p)
+    {
+      bp->th += (bp->th > 0 ? speed : -speed);
+      while (bp->th >  360) bp->th -= 360;
+      while (bp->th < -360) bp->th += 360;
+    }
+
+  mi->polygon_count += draw_ball_1 (mi);
+  glPopMatrix ();
+
+  if (mi->fps_p) do_fps (mi);
+  glFinish();
+
+  glXSwapBuffers(dpy, window);
+}
+
+
+ENTRYPOINT void
+release_ball (ModeInfo *mi)
+{
+  ball_configuration *bp = &bps[MI_SCREEN(mi)];
+  while (bp->tiles)
+    {
+      tile *t = bp->tiles->next;
+      free (bp->tiles);
+      bp->tiles = t;
+    }
+  free (bp->rays);
+}
+
+XSCREENSAVER_MODULE_2 ("Discoball", discoball, ball)
+
+#endif /* USE_GL */
diff --git a/hacks/glx/discoball.man b/hacks/glx/discoball.man
new file mode 100644 (file)
index 0000000..041cbd2
--- /dev/null
@@ -0,0 +1,72 @@
+.TH XScreenSaver 1 "" "X Version 11"
+.SH NAME
+discoball - A dusty, dented disco ball screen saver.
+.SH SYNOPSIS
+.B discoball
+[\-display \fIhost:display.screen\fP]
+[\-visual \fIvisual\fP]
+[\-window]
+[\-root]
+[\-delay \fInumber\fP]
+[\-speed \fInumber\fP]
+[\-count \fInumber\fP]
+[\-no-wander]
+[\-spin]
+[\-wireframe]
+[\-fps]
+.SH DESCRIPTION
+A dusty, dented disco ball. Woop woop.
+.SH OPTIONS
+.TP 8
+.B \-visual \fIvisual\fP
+Specify which visual to use.  Legal values are the name of a visual class,
+or the id number (decimal or hex) of a specific visual.
+.TP 8
+.B \-window
+Draw on a newly-created window.  This is the default.
+.TP 8
+.B \-root
+Draw on the root window.
+.TP 8
+.B \-delay \fInumber\fP
+Per-frame delay, in microseconds.  Default: 30000 (0.03 seconds).
+.TP 8
+.B \-speed \fInumber\fP
+Animation speed.  2.0 means twice as fast, 0.5 means half as fast.
+.TP 8
+.B \-count \fInumber\fP
+Number of rows of tiles on the ball.  10 - 100.  Default: 30.
+.TP 8
+.B \-wander | \-no-wander
+Whether the object should wander around the screen.
+.TP 8
+.B \-spin | \-no-spin
+Whether the scene should spin.
+.TP 8
+.B \-wireframe | \-no-wireframe
+Render in wireframe instead of solid.
+.TP 8
+.B \-fps | \-no-fps
+Whether to show a frames-per-second display at the bottom of the screen.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1)
+.SH COPYRIGHT
+Copyright \(co 2016 by Jamie Zawinski.  Permission to use, copy, modify, 
+distribute, and sell this software and its documentation for any purpose is 
+hereby granted without fee, provided that the above copyright notice appear 
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation.  No representations are made about the 
+suitability of this software for any purpose.  It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+Jamie Zawinski.
index f82a98dd6231351bfa4e5f88ed599ac6d54ed18b..b4e8dba50bcb2ccbe60dfc89e8765f6b1a491c97 100644 (file)
@@ -134,6 +134,10 @@ setup_xpm_texture (ModeInfo *mi, char **xpm_data)
                                  MI_COLORMAP (mi), xpm_data);
   char buf[1024];
   clear_gl_error();
+  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+  /* iOS invalid enum:
+  glPixelStorei(GL_UNPACK_ROW_LENGTH, image->width);
+  */
   glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
               image->width, image->height, 0,
               GL_RGBA,
@@ -142,18 +146,10 @@ setup_xpm_texture (ModeInfo *mi, char **xpm_data)
               image->data);
   sprintf (buf, "builtin texture (%dx%d)", image->width, image->height);
   check_gl_error(buf);
-
-  /* setup parameters for texturing */
-  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
-  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
-  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 }
 
 
-static void
+static Bool
 setup_file_texture (ModeInfo *mi, char *filename)
 {
   Display *dpy = mi->dpy;
@@ -162,7 +158,11 @@ setup_file_texture (ModeInfo *mi, char *filename)
 
   Colormap cmap = mi->xgwa.colormap;
   XImage *image = xpm_file_to_ximage (dpy, visual, cmap, filename);
+  if (!image) return False;
+
   clear_gl_error();
+  glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+  glPixelStorei(GL_UNPACK_ROW_LENGTH, image->width);
   glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
               image->width, image->height, 0,
               GL_RGBA,
@@ -172,16 +172,7 @@ setup_file_texture (ModeInfo *mi, char *filename)
   sprintf (buf, "texture: %.100s (%dx%d)",
           filename, image->width, image->height);
   check_gl_error(buf);
-
-  /* setup parameters for texturing */
-  glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
-  glPixelStorei(GL_UNPACK_ROW_LENGTH, image->width);
-
-  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
-  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
-  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+  return True;
 }
 
 
@@ -190,23 +181,39 @@ setup_texture(ModeInfo * mi)
 {
   planetstruct *gp = &planets[MI_SCREEN(mi)];
 
+  glGenTextures (1, &gp->tex1);
+  glBindTexture (GL_TEXTURE_2D, gp->tex1);
+
+  /* Must be after glBindTexture */
+  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+
   if (!which_image ||
       !*which_image ||
       !strcmp(which_image, "BUILTIN"))
     {
-      glGenTextures (1, &gp->tex1);
-      glBindTexture (GL_TEXTURE_2D, gp->tex1);
+    BUILTIN:
       setup_xpm_texture (mi, dymaxionmap_xpm);
     }
   else
     {
-      glGenTextures (1, &gp->tex1);
-      glBindTexture (GL_TEXTURE_2D, gp->tex1);
-      setup_file_texture (mi, which_image);
+      if (! setup_file_texture (mi, which_image))
+        goto BUILTIN;
     }
 
   glGenTextures (1, &gp->tex2);
   glBindTexture (GL_TEXTURE_2D, gp->tex2);
+
+  /* Must be after glBindTexture */
+  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+
   setup_xpm_texture (mi, ground);
 
   check_gl_error("texture initialization");
index 1073b7465e5c467eb4f207753545ac15b8e06a99..08786b29be7195f45c017eaa1ed7d0dbcfcf3459 100644 (file)
@@ -218,11 +218,16 @@ static void Create_Texture(ModeInfo *mi, const char *filename)
   int format;
 
   if ( !strncmp(filename, "BUILTIN", 7))
-    image = Generate_Image(&width, &height, &format);
+    {
+    BUILTIN:
+      image = Generate_Image(&width, &height, &format);
+    }
   else
     {
       XImage *ximage = xpm_file_to_ximage (MI_DISPLAY (mi), MI_VISUAL (mi),
                                            MI_COLORMAP (mi), filename);
+      if (!ximage)
+        goto BUILTIN;
       image  = (GLubyte *) ximage->data;
       width  = ximage->width;
       height = ximage->height;
index 9a49b20af138759a19c87a1e1291c43813174d5b..184b4e82ae932314f3cd905ff570cd7e887a4f57 100644 (file)
@@ -875,7 +875,7 @@ setup_random_texture (ModeInfo *mi, texture *texture)
        texture->start_time = time((time_t *)0);
 }
 
-static void
+static Bool
 setup_file_texture (ModeInfo *mi, char *filename, texture *texture)
 {
        Display *dpy = mi->dpy;
@@ -884,6 +884,7 @@ setup_file_texture (ModeInfo *mi, char *filename, texture *texture)
 
        Colormap cmap = mi->xgwa.colormap;
        XImage *image = xpm_file_to_ximage (dpy, visual, cmap, filename);
+    if (!image) return False;
 
 #ifdef DEBUG
        printf("FileTexture\n");
@@ -916,6 +917,7 @@ setup_file_texture (ModeInfo *mi, char *filename, texture *texture)
        texture->min_ty = 0.0;
        texture->max_ty = 1.0;
        texture->start_time = time((time_t *)0);
+    return True;
 }
 
 static void
@@ -924,6 +926,7 @@ setup_texture(ModeInfo * mi, texture *texture)
        gleidestruct *gp = &gleidescope[MI_SCREEN(mi)];
 
        if (!image || !*image || !strcmp(image, "DEFAULT")) {
+    BUILTIN:
                /* no image specified - use system settings */
 #ifdef DEBUG
                printf("SetupTexture: get_snapshot\n");
@@ -940,7 +943,8 @@ setup_texture(ModeInfo * mi, texture *texture)
 #ifdef DEBUG
                        printf("SetupTexture: file_texture\n");
 #endif
-                       setup_file_texture(mi, image, texture);
+                       if (! setup_file_texture(mi, image, texture))
+              goto BUILTIN;
                }
        }
        /* copy start time from texture */
index 3657e4c4f9c67e67ae0113652ff65fe68ab2fab8..20ccc5841f5a16db4e3469eff00bdd5a8e779f37 100644 (file)
@@ -64,6 +64,7 @@
 #define DEF_STARS   "True"
 #define DEF_RESOLUTION "128"
 #define DEF_IMAGE   "BUILTIN"
+#define DEF_IMAGE2  "BUILTIN"
 
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
@@ -77,6 +78,7 @@ static int do_wander;
 static int do_texture;
 static int do_stars;
 static char *which_image;
+static char *which_image2;
 static int resolution;
 
 static XrmOptionDescRec opts[] = {
@@ -91,7 +93,8 @@ static XrmOptionDescRec opts[] = {
   {"-stars",   ".glplanet.stars",   XrmoptionNoArg, "true" },
   {"+stars",   ".glplanet.stars",   XrmoptionNoArg, "false" },
   {"-spin",    ".glplanet.spin",    XrmoptionSepArg, 0 },
-  {"-image",   ".glplanet.image",  XrmoptionSepArg, 0 },
+  {"-image",   ".glplanet.image",   XrmoptionSepArg, 0 },
+  {"-image2",  ".glplanet.image2",  XrmoptionSepArg, 0 },
   {"-resolution", ".glplanet.resolution", XrmoptionSepArg, 0 },
 };
 
@@ -102,6 +105,7 @@ static argtype vars[] = {
   {&do_texture,  "texture", "Texture", DEF_TEXTURE, t_Bool},
   {&do_stars,    "stars",   "Stars",   DEF_STARS,   t_Bool},
   {&which_image, "image",   "Image",   DEF_IMAGE,   t_String},
+  {&which_image2,"image2",  "Image",   DEF_IMAGE2,  t_String},
   {&resolution,  "resolution","Resolution", DEF_RESOLUTION, t_Int},
 };
 
@@ -167,6 +171,10 @@ setup_xpm_texture (ModeInfo *mi, char **xpm_data)
                                   MI_COLORMAP (mi), xpm_data);
   char buf[1024];
   clear_gl_error();
+  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+  /* iOS invalid enum:
+  glPixelStorei(GL_UNPACK_ROW_LENGTH, image->width);
+  */
   glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
                image->width, image->height, 0,
                GL_RGBA,
@@ -175,18 +183,10 @@ setup_xpm_texture (ModeInfo *mi, char **xpm_data)
                image->data);
   sprintf (buf, "builtin texture (%dx%d)", image->width, image->height);
   check_gl_error(buf);
-
-  /* setup parameters for texturing */
-  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
-  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
-  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 }
 
 
-static void
+static Bool
 setup_file_texture (ModeInfo *mi, char *filename)
 {
   Display *dpy = mi->dpy;
@@ -195,8 +195,11 @@ setup_file_texture (ModeInfo *mi, char *filename)
 
   Colormap cmap = mi->xgwa.colormap;
   XImage *image = xpm_file_to_ximage (dpy, visual, cmap, filename);
+  if (!image) return False;
 
   clear_gl_error();
+  glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+  glPixelStorei(GL_UNPACK_ROW_LENGTH, image->width);
   glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
                image->width, image->height, 0,
                GL_RGBA,
@@ -206,16 +209,7 @@ setup_file_texture (ModeInfo *mi, char *filename)
   sprintf (buf, "texture: %.100s (%dx%d)",
            filename, image->width, image->height);
   check_gl_error(buf);
-
-  /* setup parameters for texturing */
-  glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
-  glPixelStorei(GL_UNPACK_ROW_LENGTH, image->width);
-
-  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
-  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
-  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+  return True;
 }
 
 
@@ -224,25 +218,55 @@ setup_texture(ModeInfo * mi)
 {
   planetstruct *gp = &planets[MI_SCREEN(mi)];
 
+  glGenTextures (1, &gp->tex1);
+  glBindTexture (GL_TEXTURE_2D, gp->tex1);
+
+  /* Must be after glBindTexture */
+  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+
   if (!which_image ||
          !*which_image ||
          !strcmp(which_image, "BUILTIN"))
     {
-      glGenTextures (1, &gp->tex1);
-      glBindTexture (GL_TEXTURE_2D, gp->tex1);
+    BUILTIN1:
       setup_xpm_texture (mi, earth_xpm);
-      glGenTextures (1, &gp->tex2);
-      glBindTexture (GL_TEXTURE_2D, gp->tex2);
+    }
+  else
+    {
+      if (! setup_file_texture (mi, which_image))
+        goto BUILTIN1;
+    }
+
+  check_gl_error("texture 1 initialization");
+
+  glGenTextures (1, &gp->tex2);
+  glBindTexture (GL_TEXTURE_2D, gp->tex2);
+
+  /* Must be after glBindTexture */
+  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+
+  if (!which_image2 ||
+         !*which_image2 ||
+         !strcmp(which_image2, "BUILTIN"))
+    {
+    BUILTIN2:
       setup_xpm_texture (mi, earth_night_xpm);
     }
   else
     {
-      glGenTextures (1, &gp->tex1);
-      glBindTexture (GL_TEXTURE_2D, gp->tex1);
-      setup_file_texture (mi, which_image);
+      if (! setup_file_texture (mi, which_image2))
+        goto BUILTIN2;
     }
 
-  check_gl_error("texture initialization");
+  check_gl_error("texture initialization");
 
   /* Need to flip the texture top for bottom for some reason. */
   glMatrixMode (GL_TEXTURE);
index f57bd9aa5436ce770f78dbb13cc93db0c785d5f7..49e7a8e7d0fca228119fec6fc56ea958c645b0ee 100644 (file)
@@ -159,10 +159,10 @@ convert_ximage_to_rgba32 (Screen *screen, XImage *image)
    */
   XImage *from = image;
   XImage *to = XCreateImage (dpy, visual, 32,  /* depth */
-                             ZPixmap, 0, 0, from->width, from->height + 2,
+                             ZPixmap, 0, 0, from->width, from->height,
                              32, /* bitmap pad */
                              0);
-  to->data = (char *) calloc (to->height, to->bytes_per_line);
+  to->data = (char *) calloc (to->height + 2, to->bytes_per_line);
 
   /* Set the bit order in the XImage structure to whatever the
      local host's native bit order is.
@@ -735,7 +735,7 @@ load_texture_async_cb (Screen *screen, Window window, Drawable drawable,
   if (geometry->width <= 0 || geometry->height <= 0)
     {
       /* This can happen if an old version of xscreensaver-getimage
-         is installed. */
+         is installed. Or if we have no image (checkerboard). */
       geometry->x = 0;
       geometry->y = 0;
       geometry->width  = dd.pix_width;
diff --git a/hacks/glx/hexstrut.c b/hacks/glx/hexstrut.c
new file mode 100644 (file)
index 0000000..f264609
--- /dev/null
@@ -0,0 +1,512 @@
+/* hexstrut, Copyright (c) 2016 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
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation.  No representations are made about the suitability of this
+ * software for any purpose.  It is provided "as is" without express or 
+ * implied warranty.
+ */
+
+#define DEFAULTS       "*delay:        30000       \n" \
+                       "*showFPS:      False       \n" \
+                       "*wireframe:    False       \n" \
+                       "*count:        20          \n" \
+                       "*suppressRotationAnimation: True\n" \
+
+# define refresh_hexstrut 0
+#undef countof
+#define countof(x) (sizeof((x))/sizeof((*x)))
+
+#include "xlockmore.h"
+#include "colors.h"
+#include "normals.h"
+#include "rotator.h"
+#include "gltrackball.h"
+#include <ctype.h>
+
+#ifdef USE_GL /* whole file */
+
+
+#define DEF_SPIN        "True"
+#define DEF_WANDER      "True"
+#define DEF_SPEED       "1.0"
+#define DEF_THICKNESS   "0.2"
+
+#define BELLRAND(n) ((frand((n)) + frand((n)) + frand((n))) / 3)
+
+typedef struct { double a, o; } LL;    /* latitude + longitude */
+
+typedef struct triangle triangle;
+struct triangle {
+  XYZ p[3];
+  triangle *next;
+  triangle *neighbors[6];
+  GLfloat orot, rot;
+  int delay, odelay;
+  int ccolor;
+};
+
+typedef struct {
+  GLXContext *glx_context;
+  rotator *rot;
+  trackball_state *trackball;
+  Bool button_down_p;
+
+  int count;
+  triangle *triangles;
+
+  int ncolors;
+  XColor *colors;
+
+} hexstrut_configuration;
+
+static hexstrut_configuration *bps = NULL;
+
+static Bool do_spin;
+static GLfloat speed;
+static Bool do_wander;
+static GLfloat thickness;
+
+static XrmOptionDescRec opts[] = {
+  { "-spin",   ".spin",   XrmoptionNoArg, "True" },
+  { "+spin",   ".spin",   XrmoptionNoArg, "False" },
+  { "-speed",  ".speed",  XrmoptionSepArg, 0 },
+  { "-wander", ".wander", XrmoptionNoArg, "True" },
+  { "+wander", ".wander", XrmoptionNoArg, "False" },
+  { "-thickness", ".thickness", XrmoptionSepArg, 0 },
+};
+
+static argtype vars[] = {
+  {&do_spin,   "spin",   "Spin",   DEF_SPIN,   t_Bool},
+  {&do_wander, "wander", "Wander", DEF_WANDER, t_Bool},
+  {&speed,     "speed",  "Speed",  DEF_SPEED,  t_Float},
+  {&thickness, "thickness", "Thickness", DEF_THICKNESS, t_Float},
+};
+
+ENTRYPOINT ModeSpecOpt hexstrut_opts = {countof(opts), opts, countof(vars), vars, NULL};
+
+
+
+/* Add t1 to the neighbor list of t0. */
+static void
+link_neighbor (triangle *t0, triangle *t1)
+{
+  int k;
+  if (t0 == t1)
+    return;
+  for (k = 0; k < countof(t0->neighbors); k++)
+    {
+      if (t0->neighbors[k] == t1 ||
+          t0->neighbors[k] == 0)
+        {
+          t0->neighbors[k] = t1;
+          return;
+        }
+    }
+  fprintf (stderr, "too many neighbors\n");
+  abort();
+}
+
+
+static void
+make_plane (ModeInfo *mi)
+{
+  hexstrut_configuration *bp = &bps[MI_SCREEN(mi)];
+  int n = MI_COUNT(mi) * 2;
+  GLfloat size = 2.0 / n;
+  int x, y;
+  GLfloat w = size;
+  GLfloat h = size * sqrt(3) / 2;
+  triangle **grid = (triangle **) calloc (n * n, sizeof(*grid));
+
+  for (y = 0; y < n; y++)
+    for (x = 0; x < n; x++)
+      {
+        triangle *t;
+
+        t = (triangle *) calloc (1, sizeof(*t));
+        t->p[0].x = (x - n/2) * w;
+        t->p[0].y = (y - n/2) * h;
+
+        if (y & 1)
+          t->p[0].x += w / 2;
+
+        t->p[1].x = t->p[0].x - w/2;
+        t->p[2].x = t->p[0].x + w/2;
+        t->p[1].y = t->p[0].y + h;
+        t->p[2].y = t->p[0].y + h;
+
+        if (x > 0)
+          {
+            triangle *t2 = grid[y * n + (x-1)];
+            link_neighbor (t, t2);
+            link_neighbor (t2, t);
+          }
+        if (y > 0)
+          {
+            triangle *t2 = grid[(y-1) * n + x];
+            link_neighbor (t, t2);
+            link_neighbor (t2, t);
+
+            if (x < n-1)
+              {
+                t2 = grid[(y-1) * n + (x+1)];
+                link_neighbor (t, t2);
+                link_neighbor (t2, t);
+              }
+          }
+
+        t->next = bp->triangles;
+        bp->triangles = t;
+        grid[y * n + x] = t;
+        bp->count++;
+      }
+
+  free (grid);
+}
+
+
+static void
+tick_triangles (ModeInfo *mi)
+{
+  hexstrut_configuration *bp = &bps[MI_SCREEN(mi)];
+  triangle *t;
+  GLfloat step = 0.01 + (0.04 * speed);
+
+  if (! (random() % 80))
+    {
+      int n = random() % bp->count;
+      int i;
+      for (i = 0, t = bp->triangles; t && i < n; t = t->next, i++)
+        ;
+      if (! t->rot)
+        {
+          t->rot += step * ((random() & 1) ? 1 : -1);
+          t->odelay = t->delay = 4;
+        }
+    }
+
+  for (t = bp->triangles; t; t = t->next)
+    {
+      /* If this triangle is rotating, continue until done. */
+      if (t->rot)
+        {
+          t->rot += step * (t->rot > 0 ? 1 : -1);
+
+          t->ccolor++;
+          if (t->ccolor > bp->ncolors)
+            t->ccolor = 0;
+
+          if (t->rot > 1 || t->rot < -1)
+            {
+              t->orot += (t->rot > 1 ? 1 : -1);
+              t->rot = 0;
+            }
+        }
+
+      /* If this triangle's propagation delay hasn't hit zero, decrement it.
+         When it does, start its neighbors rotating.
+       */
+      if (t->delay)
+        {
+          int i;
+          t->delay--;
+          if (t->delay == 0)
+            for (i = 0; i < countof(t->neighbors); i++)
+              {
+                if (t->neighbors[i] &&
+                    t->neighbors[i]->rot == 0)
+                  {
+                    t->neighbors[i]->rot += step * (t->rot > 0 ? 1 : -1);
+                    t->neighbors[i]->delay = 
+                      t->neighbors[i]->odelay = t->odelay;
+                  }
+              }
+        }
+    }
+}
+
+
+static void
+draw_triangles (ModeInfo *mi)
+{
+  hexstrut_configuration *bp = &bps[MI_SCREEN(mi)];
+  int wire = MI_IS_WIREFRAME(mi);
+  triangle *t;
+  GLfloat length = sqrt(3) / 3;
+  GLfloat t2 = length * thickness / 2;
+  GLfloat scale;
+
+  {
+    triangle *t = bp->triangles;
+    GLfloat X = t->p[0].x - t->p[1].x;
+    GLfloat Y = t->p[0].y - t->p[1].y;
+    GLfloat Z = t->p[0].z - t->p[1].z;
+    scale = sqrt(X*X + Y*Y + Z*Z);
+  }
+
+  glFrontFace (GL_CCW);
+
+  glBegin (wire ? GL_LINES : GL_QUADS);
+
+  glNormal3f (0, 0, 1);
+  for (t = bp->triangles; t; t = t->next)
+    {
+      int i;
+      XYZ c;
+      GLfloat color[4];
+
+      GLfloat angle = (M_PI * 2 / 3) * t->rot;
+      GLfloat cr = cos(angle), sr = sin(angle);
+
+      c.x = (t->p[0].x + t->p[1].x + t->p[2].x) / 3;
+      c.y = (t->p[0].y + t->p[1].y + t->p[2].y) / 3;
+      c.z = (t->p[0].z + t->p[1].z + t->p[2].z) / 3;
+
+      /* Actually we don't need normals at all, since no lighting.
+      do_normal (t->p[0].x, t->p[0].y, t->p[0].z,
+                 t->p[1].x, t->p[1].y, t->p[1].z,
+                 t->p[2].x, t->p[2].y, t->p[2].z);
+      */
+
+      color[0] = bp->colors[t->ccolor].red   / 65535.0;
+      color[1] = bp->colors[t->ccolor].green / 65535.0;
+      color[2] = bp->colors[t->ccolor].blue  / 65535.0;
+      color[3] = 1;
+
+      /* Brighter */
+      color[0] = color[0] * 0.75 + 0.25;
+      color[1] = color[1] * 0.75 + 0.25;
+      color[2] = color[2] * 0.75 + 0.25;
+
+      glColor4fv (color);
+      glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, color);
+
+      for (i = 0; i < 3; i++)
+        {
+          /* Orient to direction of corner. */
+          GLfloat x = t->p[i].x - c.x;
+          GLfloat y = t->p[i].y - c.y;
+          GLfloat z = t->p[i].z - c.z;
+
+          GLfloat smc = sr * y - cr * x;
+          GLfloat spc = cr * y + sr * x;
+
+          GLfloat st2 = t2 * scale / sqrt(x*x + y*y);
+          GLfloat slength = length * scale / sqrt(x*x + y*y + z*z);
+
+          GLfloat xt2 = spc * st2;
+          GLfloat yt2 = smc * st2;
+          GLfloat xlength = c.x - slength * smc;
+          GLfloat ylength = c.y + slength * spc;
+          GLfloat zlength = c.z + slength * z;
+
+          if (! wire)
+            glVertex3f (c.x - xt2, c.y - yt2, c.z);
+
+          glVertex3f (c.x + xt2, c.y + yt2, c.z);
+          if (wire)
+            glVertex3f (xlength + xt2, ylength + yt2, zlength);
+
+          if (! wire)
+            glVertex3f (xlength + xt2, ylength + yt2, zlength);
+
+          glVertex3f (xlength - xt2, ylength - yt2, zlength);
+
+          if (wire)
+            glVertex3f (c.x - xt2, c.y - yt2, c.z);
+
+          mi->polygon_count++;
+        }
+    }
+
+  glEnd();
+}
+
+
+/* Window management, etc
+ */
+ENTRYPOINT void
+reshape_hexstrut (ModeInfo *mi, int width, int height)
+{
+  GLfloat h = (GLfloat) height / (GLfloat) width;
+
+  glViewport (0, 0, (GLint) width, (GLint) height);
+
+  glMatrixMode(GL_PROJECTION);
+  glLoadIdentity();
+  gluPerspective (30.0, 1/h, 1.0, 100.0);
+
+  glMatrixMode(GL_MODELVIEW);
+  glLoadIdentity();
+  gluLookAt( 0.0, 0.0, 30.0,
+             0.0, 0.0, 0.0,
+             0.0, 1.0, 0.0);
+
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+  {
+    int o = (int) current_device_rotation();
+    if (o != 0 && o != 180 && o != -180)
+      glScalef (1/h, 1/h, 1/h);
+  }
+# endif
+
+  glClear(GL_COLOR_BUFFER_BIT);
+}
+
+
+ENTRYPOINT Bool
+hexstrut_handle_event (ModeInfo *mi, XEvent *event)
+{
+  hexstrut_configuration *bp = &bps[MI_SCREEN(mi)];
+
+  if (gltrackball_event_handler (event, bp->trackball,
+                                 MI_WIDTH (mi), MI_HEIGHT (mi),
+                                 &bp->button_down_p))
+    return True;
+  else if (event->xany.type == KeyPress)
+    {
+      KeySym keysym;
+      char c = 0;
+      XLookupString (&event->xkey, &c, 1, &keysym, 0);
+      if (c == ' ' || c == '\t')
+        {
+          bp->ncolors = 64;
+          make_smooth_colormap (0, 0, 0,
+                                bp->colors, &bp->ncolors,
+                                False, 0, False);
+          return True;
+        }
+    }
+
+  return False;
+}
+
+
+ENTRYPOINT void 
+init_hexstrut (ModeInfo *mi)
+{
+  hexstrut_configuration *bp;
+
+  if (!bps) {
+    bps = (hexstrut_configuration *)
+      calloc (MI_NUM_SCREENS(mi), sizeof (hexstrut_configuration));
+    if (!bps) {
+      fprintf(stderr, "%s: out of memory\n", progname);
+      exit(1);
+    }
+  }
+
+  bp = &bps[MI_SCREEN(mi)];
+
+  bp->glx_context = init_GL(mi);
+
+  reshape_hexstrut (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
+
+  {
+    double spin_speed   = 0.002;
+    double wander_speed = 0.003;
+    double spin_accel   = 1.0;
+
+    bp->rot = make_rotator (do_spin ? spin_speed : 0,
+                            do_spin ? spin_speed : 0,
+                            do_spin ? spin_speed : 0,
+                            spin_accel,
+                            do_wander ? wander_speed : 0,
+                            False);
+    bp->trackball = gltrackball_init (True);
+  }
+
+
+  /* Let's tilt the scene a little. */
+  gltrackball_start (bp->trackball, 500, 500, 1000, 1000);
+  gltrackball_track (bp->trackball,
+                     350 + (random() % 300),
+                     350 + (random() % 300),
+                     1000, 1000);
+
+
+  if (thickness < 0.05) thickness = 0.05;
+  if (thickness < 0.05) MI_IS_WIREFRAME(mi) = True;
+  if (thickness > 1.7) thickness = 1.7;
+  if (speed > 2) speed = 2;
+
+  bp->ncolors = 64;
+  bp->colors = (XColor *) calloc(bp->ncolors, sizeof(XColor));
+  make_smooth_colormap (0, 0, 0,
+                        bp->colors, &bp->ncolors,
+                        False, 0, False);
+
+  make_plane (mi);
+}
+
+
+ENTRYPOINT void
+draw_hexstrut (ModeInfo *mi)
+{
+  hexstrut_configuration *bp = &bps[MI_SCREEN(mi)];
+  Display *dpy = MI_DISPLAY(mi);
+  Window window = MI_WINDOW(mi);
+
+  if (!bp->glx_context)
+    return;
+
+  glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(bp->glx_context));
+
+  glShadeModel(GL_SMOOTH);
+
+  glDisable(GL_DEPTH_TEST);
+  glEnable(GL_NORMALIZE);
+  glDisable(GL_CULL_FACE);
+
+  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+  glPushMatrix ();
+
+  {
+    double x, y, z;
+    get_position (bp->rot, &x, &y, &z, !bp->button_down_p);
+    glTranslatef((x - 0.5) * 6,
+                 (y - 0.5) * 6,
+                 (z - 0.5) * 12);
+
+    gltrackball_rotate (bp->trackball);
+
+    get_rotation (bp->rot, &x, &y, &z, !bp->button_down_p);
+    glRotatef (z * 360, 0.0, 0.0, 1.0);
+  }
+
+  mi->polygon_count = 0;
+
+  glScalef (30, 30, 30);
+
+  if (! bp->button_down_p)
+    tick_triangles (mi);
+  draw_triangles (mi);
+
+  glPopMatrix ();
+
+  if (mi->fps_p) do_fps (mi);
+  glFinish();
+
+  glXSwapBuffers(dpy, window);
+}
+
+
+ENTRYPOINT void
+release_hexstrut (ModeInfo *mi)
+{
+  hexstrut_configuration *bp = &bps[MI_SCREEN(mi)];
+  while (bp->triangles)
+    {
+      triangle *t = bp->triangles->next;
+      free (bp->triangles);
+      bp->triangles = t;
+    }
+}
+
+XSCREENSAVER_MODULE ("Hexstrut", hexstrut)
+
+#endif /* USE_GL */
diff --git a/hacks/glx/hexstrut.man b/hacks/glx/hexstrut.man
new file mode 100644 (file)
index 0000000..19e49e0
--- /dev/null
@@ -0,0 +1,77 @@
+.TH XScreenSaver 1 "" "X Version 11"
+.SH NAME
+hexstrut - a grid of hexagons composed of rotating Y-shaped struts.
+.SH SYNOPSIS
+.B hexstrut
+[\-display \fIhost:display.screen\fP]
+[\-visual \fIvisual\fP]
+[\-window]
+[\-root]
+[\-delay \fInumber\fP]
+[\-speed \fInumber\fP]
+[\-count \fInumber\fP]
+[\-thickness \fInumber\fP]
+[\-no-wander]
+[\-no-spin]
+[\-wireframe]
+[\-fps]
+.SH DESCRIPTION
+A grid of hexagons composed of rotating Y-shaped struts.
+Waves of rotation and color changes randomly propagate across the plane.
+.SH OPTIONS
+.TP 8
+.B \-visual \fIvisual\fP
+Specify which visual to use.  Legal values are the name of a visual class,
+or the id number (decimal or hex) of a specific visual.
+.TP 8
+.B \-window
+Draw on a newly-created window.  This is the default.
+.TP 8
+.B \-root
+Draw on the root window.
+.TP 8
+.B \-delay \fInumber\fP
+Per-frame delay, in microseconds.  Default: 30000 (0.03 seconds).
+.TP 8
+.B \-speed \fInumber\fP
+Animation speed.  2.0 means twice as fast, 0.5 means half as fast.
+.TP 8
+.B \-count \fInumber\fP
+Approximate number of hexagons on the screen, horizontally.  Default: 20.
+.TP 8
+.B \-thickness \fInumber\fP
+Relative thickness of the struts.  0.01 - 1.7.  Default: 0.2.
+.TP 8
+.B \-wander | \-no-wander
+Whether the grid should wander around the screen.
+.TP 8
+.B \-spin | \-no-spin
+Whether the grid should spin.
+.TP 8
+.B \-wireframe | \-no-wireframe
+Render in wireframe instead of solid.
+.TP 8
+.B \-fps | \-no-fps
+Whether to show a frames-per-second display at the bottom of the screen.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1)
+.SH COPYRIGHT
+Copyright \(co 2016 by Jamie Zawinski.  Permission to use, copy, modify, 
+distribute, and sell this software and its documentation for any purpose is 
+hereby granted without fee, provided that the above copyright notice appear 
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation.  No representations are made about the 
+suitability of this software for any purpose.  It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+Jamie Zawinski.
index ea3de9dfb7df595d2629166c5d34d158128ce56e..85aea634cc5ba141682f5f048dc5293fa36b5d80 100644 (file)
@@ -508,10 +508,10 @@ make_squid (ModeInfo *mi, int which)
 static int
 cmp_squid (const void *aa, const void *bb)
 {
-  const squid *a = (squid *) aa;
-  const squid *b = (squid *) bb;
-  return ((int) (b->pos.y * 10000) -
-          (int) (a->pos.y * 10000));
+  squid * const *a = aa;
+  squid * const *b = bb;
+  return ((int) ((*b)->pos.y * 10000) -
+          (int) ((*a)->pos.y * 10000));
 }
 
 
index f3eadc5e78688b964fdf1c2deb813991d068c4cd..7e422ad6c0918d8452bfde98643cb85ffb9ca152 100644 (file)
@@ -339,6 +339,7 @@ load_texture (ModeInfo *mi, const char *filename)
     }
 
   image = xpm_file_to_ximage (dpy, visual, cmap, filename);
+  if (!image) return False;
 
   clear_gl_error();
   glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
index daedcec50086c06c2c525a57834c9a79517a0611..4f417c3991132b0dac4cde24743ac796314e4f4c 100755 (executable)
@@ -6,7 +6,7 @@ SRCS=$*
 
 TMP=molecules.h.$$
 rm -f $TMP
-trap "rm -f $TMP" 1 2 3 15 ERR EXIT
+trap "rm -f $TMP" 1 2 3 15 EXIT
 
 if [ -z "$UTILS_SRC" ]; then UTILS_SRC="../../utils"; fi
 
index d2ea5b402aed92a30f06fb294eba15212bfcbcf6..847b3b2926dd149b697e23c4ec16bf35306ccbcf 100644 (file)
  * implied warranty.
  */
 
-#define DEF_FONT "-*-helvetica-bold-r-normal-*-*-480-*-*-*-*-*-*"
+#if defined(HAVE_COCOA) || defined(HAVE_ANDROID)
+# define DEF_FONT "OCR A Std 48, Lucida Console 48, Monaco 48"
+#else
+# define DEF_FONT "-*-helvetica-bold-r-normal-*-*-480-*-*-*-*-*-*"
+#endif
+
 #define DEFAULTS  "*count:           7         \n" \
                   "*delay:           10000     \n" \
                   "*wireframe:       False     \n" \
@@ -48,7 +53,7 @@
 # define DEF_SPEED          "1.0"
 # define DEF_DURATION       "5"
 # define DEF_MIPMAP         "True"
-# define DEF_TITLES         "False"
+# define DEF_TITLES         "True"
 # define DEF_POLAROID       "True"
 # define DEF_CLIP           "True"
 # define DEF_SHADOWS        "True"
@@ -644,26 +649,44 @@ draw_image (ModeInfo *mi, int i, GLfloat t, GLfloat s, GLfloat z)
    */
   if (titles_p)
     {
-      int sw, sh, ascent, descent;
+      int sw = 0, sh = 0;
+      int ascent, descent;
+      GLfloat tw = w * 2;
+      GLfloat th = h1 - h;
       GLfloat scale = 1;
       const char *title = frame->title ? frame->title : "(untitled)";
       XCharStruct e;
 
-      /* #### Highly approximate, but doing real clipping is harder... */
-      int max = 35;
-      if (strlen(title) > max)
-        title += strlen(title) - max;
-
       texture_string_metrics (ss->texfont, title, &e, &ascent, &descent);
       sw = e.width;
-      sh = ascent + descent;
+      sh = ascent; /* + descent; */
 
       /* Scale the text to match the pixel size of the photo */
-      scale *= w / 300.0;
+      scale *= w / 150.0;
+
+# if defined(HAVE_COCOA)
+      scale /= 2;
+# endif
+
+# if defined(HAVE_MOBILE)
+      scale /= 2;
+# endif
+
+      /* Clip characters off the left end of the string until it fits. */
+      if (clip_p || polaroid_p)
+        while (sw * scale > tw && strlen (title) > 10)
+          {
+            title++;
+            texture_string_metrics (ss->texfont, title, &e, &ascent, &descent);
+            sw = e.width;
+          }
+
+      if (th <= 0)  /* Non-polaroid */
+        th = -sh * 1.2;
+
+      glTranslatef (-w, -h1, 0);
+      glTranslatef ((tw - sw*scale) / 2, (th - sh*scale) / 2, 0);
 
-      /* Move to below photo */
-      glTranslatef (0, -h - sh * (polaroid_p ? 2.2 : 0.5), 0);
-      glTranslatef (-sw*scale/2, sh*scale/2, z);
       glScalef (scale, scale, 1);
 
       if (wire || !polaroid_p)
@@ -672,14 +695,16 @@ draw_image (ModeInfo *mi, int i, GLfloat t, GLfloat s, GLfloat z)
         }
       else
         {
-          glColor3f (0, 0, 0);
+          glColor3f (0.5, 0.5, 0.5);
         }
 
       if (!wire)
         {
           glEnable (GL_TEXTURE_2D);
           glEnable (GL_BLEND);
+          glDisable (GL_DEPTH_TEST);
           print_texture_string (ss->texfont, title);
+          glEnable (GL_DEPTH_TEST);
         }
       else
         {
@@ -690,6 +715,7 @@ draw_image (ModeInfo *mi, int i, GLfloat t, GLfloat s, GLfloat z)
           glVertex3f (0,  sh, 0);
           glEnd();
         }
+
     }
 
   glPopMatrix();
index 277f9ddc7397754b8e474d4b994b3fbf062ea2d0..e93930854cecef5671b4fd250b820c86b4d1a693 100644 (file)
@@ -63,7 +63,7 @@ default; 2.0 means twice as fast.
 Per-frame delay, in microseconds.  Default: 10000 (0.01 seconds.).
 .TP 8
 .B \-titles \fB| \-no\-titles\fP
-Whether to display the file names of the images beneath them.  Default: no.
+Whether to display the file names of the images beneath them.  Default: yes.
 .TP 8
 .B \-polaroid \fB| \-no\-polaroid\fP
 Whether to simulate images taken by an instant camera.  Default: yes.
index d179de348b1f134d0f0311e8b42f74b286f663f4..a7699c917b640b2515fd71632831a5847ef0cecb 100644 (file)
@@ -502,15 +502,15 @@ static const struct {
   /* 76 */     {"5|2 5/2",     "Small Stellated Dodecahedron",
                                "Great Dodecahedron",
                                "Icosahedral (I[3])",
-                               "",
-                               "",
+                               "Kepler-Poinsot Solid",
+                               "Kepler-Poinsot Solid",
                                43, 20},
 
   /* 78 */     {"5/2|2 5",     "Great Dodecahedron",
                                "Small Stellated Dodecahedron",
                                "Icosahedral (I[3])",
-                               "",
-                               "",
+                               "Kepler-Poinsot Solid",
+                               "Kepler-Poinsot Solid",
                                44, 21},
 
   /* 80 */     {"2|5/2 5",     "Great Dodecadodecahedron",
@@ -588,7 +588,7 @@ static const struct {
                                "Medial Hexagonal Hexecontahedron",
                                "Icosahedral (I[4])",
                                "",
-                               "Kepler-Poinsot Solid",
+                               "",
                                58, 112},
                                                          /* (3/2 3 5) (I6b) */
 
@@ -632,15 +632,15 @@ static const struct {
   /* 112 */    {"3|2 5/2",     "Great Stellated Dodecahedron",
                                "Great Icosahedron",
                                "Icosahedral (I[7])",
-                               "",
-                               "",
+                               "Kepler-Poinsot Solid",
+                               "Kepler-Poinsot Solid",
                                68, 22},
 
   /* 114 */    {"5/2|2 3",     "Great Icosahedron",
                                "Great Stellated Dodecahedron",
                                "Icosahedral (I[7])",
-                               "",
-                               "",
+                               "Kepler-Poinsot Solid",
+                               "Kepler-Poinsot Solid",
                                69, 41},
 
   /* 116 */    {"2|5/2 3",     "Great Icosidodecahedron",
@@ -668,7 +668,7 @@ static const struct {
                                "Great Pentagonal Hexecontahedron",
                                "Icosahedral (I[7])",
                                "",
-                               "Kepler-Poinsot Solid",
+                               "",
                                73, 113},
                                                           /* (5/3 2 5) (I9) */
 
@@ -690,7 +690,7 @@ static const struct {
                                "Medial Inverted Pentagonal Hexecontahedron",
                                "Icosahedral (I[9])",
                                "",
-                               "Kepler-Poinsot Solid",
+                               "",
                                76, 114},
                                                       /* (5/3 5/2 3) (I10a) */
 
@@ -719,7 +719,7 @@ static const struct {
                                "Great Hexagonal Hexecontahedron",
                                "Icosahedral (I[10a])",
                                "",
-                               "Kepler-Poinsot Solid",
+                               "",
                                80, 115},
                                                         /* (5/4 3 5) (I10b) */
 
@@ -771,7 +771,7 @@ static const struct {
   /* 150 */    {"3/2 3|5/3",   "Great Icosihemidodecahedron",
                                "Great Icosihemidodecacron",
                                "Icosahedral (I[18b])",
-                               "Kepler-Poinsot Solid",
+                               "",
                                "",
                                85, 106},
                                                      /* (3/2 3/2 5/3) (I22) */
@@ -794,7 +794,7 @@ static const struct {
   /* 156 */    {"|3/2 5/3 2",  "Great Retrosnub Icosidodecahedron",
                                "Great Pentagrammic Hexecontahedron",
                                "Icosahedral (I[23])",
-                               "Kepler-Poinsot Solid",
+                               "",
                                "",
                                90, 117},
 
index 0a82167569be5a4ae38fa6fda50ffd4cd94b35f1..06301d171cd18aef142823a527815f1b0f7d1ce2 100644 (file)
@@ -230,11 +230,16 @@ static void Create_Texture(ModeInfo *mi, const char *filename)
   int format;
 
   if ( !strncmp(filename, "BUILTIN", 7))
-    image = Generate_Image(&width, &height, &format);
+    {
+    BUILTIN:
+      image = Generate_Image(&width, &height, &format);
+    }
   else
     {
       XImage *ximage = xpm_file_to_ximage (MI_DISPLAY (mi), MI_VISUAL (mi),
                                            MI_COLORMAP (mi), filename);
+      if (! ximage)
+        goto BUILTIN;
       image  = (GLubyte *) ximage->data;
       width  = ximage->width;
       height = ximage->height;
index 253cb8eb8d41e6fb60d9967bfd46d2096b549677..8256270b36a4af185c31c55b8b183c21cbefee38 100644 (file)
@@ -1,4 +1,4 @@
-/* sonar, Copyright (c) 1998-2012 Jamie Zawinski and Stephen Martin
+/* sonar, Copyright (c) 1998-2016 Jamie Zawinski and Stephen Martin
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -1050,7 +1050,7 @@ get_ping (sonar_sensor_data *ssd)
 {
   ping_data *pd = (ping_data *) ssd->closure;
   struct sockaddr from;
-  unsigned int fromlen;  /* Posix says socklen_t, but that's not portable */
+  socklen_t fromlen;
   int result;
   u_char packet[1024];
   struct timeval now;
diff --git a/hacks/glx/splodesic.c b/hacks/glx/splodesic.c
new file mode 100644 (file)
index 0000000..8bf2fc9
--- /dev/null
@@ -0,0 +1,640 @@
+/* splodesic, Copyright (c) 2016 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
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation.  No representations are made about the suitability of this
+ * software for any purpose.  It is provided "as is" without express or 
+ * implied warranty.
+ */
+
+#define DEFAULTS       "*delay:        30000       \n" \
+                       "*showFPS:      False       \n" \
+                       "*wireframe:    False       \n" \
+                       "*suppressRotationAnimation: True\n" \
+
+# define refresh_splodesic 0
+#undef countof
+#define countof(x) (sizeof((x))/sizeof((*x)))
+
+#include "xlockmore.h"
+#include "colors.h"
+#include "normals.h"
+#include "rotator.h"
+#include "gltrackball.h"
+#include <ctype.h>
+
+#ifdef USE_GL /* whole file */
+
+
+#define DEF_SPIN        "True"
+#define DEF_WANDER      "True"
+#define DEF_SPEED       "1.0"
+#define DEF_DEPTH       "4"
+
+#define BELLRAND(n) ((frand((n)) + frand((n)) + frand((n))) / 3)
+
+typedef struct { double a, o; } LL;    /* latitude + longitude */
+
+typedef struct triangle triangle;
+struct triangle {
+  XYZ p[3];
+  triangle *next;
+  triangle *neighbors[3];
+  GLfloat altitude;
+  GLfloat velocity;
+  GLfloat thrust;
+  int thrust_duration;
+  int refcount;
+};
+
+typedef struct {
+  GLXContext *glx_context;
+  rotator *rot;
+  trackball_state *trackball;
+  Bool button_down_p;
+
+  int count;
+  triangle *triangles;
+
+  int ncolors;
+  XColor *colors;
+  int ccolor;
+
+} splodesic_configuration;
+
+static splodesic_configuration *bps = NULL;
+
+static Bool do_spin;
+static GLfloat speed;
+static int depth_arg;
+static Bool do_wander;
+
+static XrmOptionDescRec opts[] = {
+  { "-spin",   ".spin",   XrmoptionNoArg, "True" },
+  { "+spin",   ".spin",   XrmoptionNoArg, "False" },
+  { "-speed",  ".speed",  XrmoptionSepArg, 0 },
+  { "-depth",  ".depth",  XrmoptionSepArg, 0 },
+  { "-wander", ".wander", XrmoptionNoArg, "True" },
+  { "+wander", ".wander", XrmoptionNoArg, "False" }
+};
+
+static argtype vars[] = {
+  {&do_spin,   "spin",   "Spin",   DEF_SPIN,   t_Bool},
+  {&do_wander, "wander", "Wander", DEF_WANDER, t_Bool},
+  {&speed,     "speed",  "Speed",  DEF_SPEED,  t_Float},
+  {&depth_arg, "depth",  "Depth",  DEF_DEPTH,  t_Int},
+};
+
+ENTRYPOINT ModeSpecOpt splodesic_opts = {countof(opts), opts, countof(vars), vars, NULL};
+
+
+/* Creates a triangle specified by 3 polar endpoints.
+ */
+static void
+make_triangle1 (ModeInfo *mi, LL v1, LL v2, LL v3)
+{
+  splodesic_configuration *bp = &bps[MI_SCREEN(mi)];
+  triangle *t = (triangle *) calloc (1, sizeof(*t));
+
+  t->p[0].x = cos (v1.a) * cos (v1.o);
+  t->p[0].y = cos (v1.a) * sin (v1.o);
+  t->p[0].z = sin (v1.a);
+
+  t->p[1].x = cos (v2.a) * cos (v2.o);
+  t->p[1].y = cos (v2.a) * sin (v2.o);
+  t->p[1].z = sin (v2.a);
+
+  t->p[2].x = cos (v3.a) * cos (v3.o);
+  t->p[2].y = cos (v3.a) * sin (v3.o);
+  t->p[2].z = sin (v3.a);
+
+  t->next = bp->triangles;
+  bp->triangles = t;
+  bp->count++;
+}
+
+
+/* Computes the midpoint of a line between two polar coords.
+ */
+static void
+midpoint2 (LL v1, LL v2, LL *vm_ret,
+           XYZ *p1_ret, XYZ *p2_ret, XYZ *pm_ret)
+{
+  XYZ p1, p2, pm;
+  LL vm;
+  GLfloat hyp;
+
+  p1.x = cos (v1.a) * cos (v1.o);
+  p1.y = cos (v1.a) * sin (v1.o);
+  p1.z = sin (v1.a);
+
+  p2.x = cos (v2.a) * cos (v2.o);
+  p2.y = cos (v2.a) * sin (v2.o);
+  p2.z = sin (v2.a);
+
+  pm.x = (p1.x + p2.x) / 2;
+  pm.y = (p1.y + p2.y) / 2;
+  pm.z = (p1.z + p2.z) / 2;
+
+  vm.o = atan2 (pm.y, pm.x);
+  hyp = sqrt (pm.x * pm.x + pm.y * pm.y);
+  vm.a = atan2 (pm.z, hyp);
+
+  *p1_ret = p1;
+  *p2_ret = p2;
+  *pm_ret = pm;
+  *vm_ret = vm;
+}
+
+
+/* Creates triangular geodesic facets to the given depth.
+ */
+static void
+make_triangle (ModeInfo *mi, LL v1, LL v2, LL v3, int depth)
+{
+  if (depth <= 0)
+    make_triangle1 (mi, v1, v2, v3);
+  else
+    {
+      LL v12, v23, v13;
+      XYZ p1, p2, p3, p12, p23, p13;
+
+      midpoint2 (v1, v2, &v12, &p1, &p2, &p12);
+      midpoint2 (v2, v3, &v23, &p2, &p3, &p23);
+      midpoint2 (v1, v3, &v13, &p1, &p3, &p13);
+      depth--;
+
+      make_triangle (mi, v1,  v12, v13, depth);
+      make_triangle (mi, v12, v2,  v23, depth);
+      make_triangle (mi, v13, v23, v3,  depth);
+      make_triangle (mi, v12, v23, v13, depth);
+    }
+}
+
+
+/* Creates triangles of a geodesic to the given depth (frequency).
+ */
+static void
+make_geodesic (ModeInfo *mi)
+{
+  int depth = depth_arg;
+  GLfloat th0 = atan (0.5);  /* lat division: 26.57 deg */
+  GLfloat s = M_PI / 5;             /* lon division: 72 deg    */
+  int i;
+
+  for (i = 0; i < 10; i++)
+    {
+      GLfloat th1 = s * i;
+      GLfloat th2 = s * (i+1);
+      GLfloat th3 = s * (i+2);
+      LL v1, v2, v3, vc;
+      v1.a = th0;    v1.o = th1;
+      v2.a = th0;    v2.o = th3;
+      v3.a = -th0;   v3.o = th2;
+      vc.a = M_PI/2; vc.o = th2;
+
+      if (i & 1)                       /* north */
+        {
+          make_triangle (mi, v1, v2, vc, depth);
+          make_triangle (mi, v2, v1, v3, depth);
+        }
+      else                             /* south */
+        {
+          v1.a = -v1.a;
+          v2.a = -v2.a;
+          v3.a = -v3.a;
+          vc.a = -vc.a;
+          make_triangle (mi, v2, v1, vc, depth);
+          make_triangle (mi, v1, v2, v3, depth);
+        }
+    }
+}
+
+
+/* Add t1 to the neighbor list of t0. */
+static void
+link_neighbor (int i, int j, triangle *t0, triangle *t1)
+{
+  int k;
+  if (t0 == t1)
+    return;
+  for (k = 0; k < countof(t0->neighbors); k++)
+    {
+      if (t0->neighbors[k] == t1 ||
+          t0->neighbors[k] == 0)
+        {
+          t0->neighbors[k] = t1;
+          return;
+        }
+    }
+  fprintf (stderr, "%d %d: too many neighbors\n", i, j);
+  abort();
+}
+
+
+static int
+feq (GLfloat a, GLfloat b)     /* Oh for fuck's sake */
+{
+  const GLfloat e = 0.00001;
+  GLfloat d = a - b;
+  return (d > -e && d < e);
+}
+
+
+/* Link each triangle to its three neighbors.
+ */
+static void
+link_neighbors (ModeInfo *mi)
+{
+  splodesic_configuration *bp = &bps[MI_SCREEN(mi)];
+  triangle *t0 = bp->triangles;
+  int i;
+
+  /* Triangles are neighbors if they share an edge (exactly 2 points).
+     (There must be a faster than N! way to do this...)
+   */
+  for (i = 0, t0 = bp->triangles; t0; t0 = t0->next, i++)
+    {
+      triangle *t1;
+      int j;
+
+      for (j = i+1, t1 = t0->next; t1; t1 = t1->next, j++)
+        {
+          int count = 0;
+          int ii, jj;
+          for (ii = 0; ii < 3; ii++)
+            for (jj = 0; jj < 3; jj++)
+              if (feq (t0->p[ii].x, t1->p[jj].x) &&
+                  feq (t0->p[ii].y, t1->p[jj].y) &&
+                  feq (t0->p[ii].z, t1->p[jj].z))
+                count++;
+          if (count >= 3)
+            {
+              fprintf (stderr, "%d %d: too many matches: %d\n", i, j, count);
+              abort();
+            }
+          if (count == 2)
+            {
+              link_neighbor (i, j, t0, t1);
+              link_neighbor (j, i, t1, t0);
+            }
+        }
+
+      if (! (t0->neighbors[0] && t0->neighbors[1] && t0->neighbors[2]))
+        {
+          fprintf (stderr, "%d: missing neighbors\n", i);
+          abort();
+        }
+
+      t0->altitude = 60;  /* Fall in from space */
+    }
+}
+
+
+/* Add thrust to the triangle, and propagate some of that to its neighbors.
+ */
+static void
+add_thrust (triangle *t, GLfloat thrust)
+{
+  GLfloat dampen = 0;
+  if (t->refcount)
+    return;
+  t->refcount++;
+  t->velocity += thrust;
+
+  /* Eyeballed this to look roughly the same at various depths. Eh. */
+  switch (depth_arg) {
+  case 0: dampen = 0.5;    break;
+  case 1: dampen = 0.7;    break;
+  case 2: dampen = 0.9;    break;
+  case 3: dampen = 0.98;   break;
+  case 4: dampen = 0.985;  break;
+  default: dampen = 0.993; break;
+  }
+
+  thrust *= dampen;
+  if (thrust > 0.1)
+    {
+      add_thrust (t->neighbors[0], thrust);
+      add_thrust (t->neighbors[1], thrust);
+      add_thrust (t->neighbors[2], thrust);
+    }
+}
+
+
+static void
+tick_triangles (ModeInfo *mi)
+{
+  splodesic_configuration *bp = &bps[MI_SCREEN(mi)];
+  GLfloat gravity = 0.1;
+  triangle *t;
+  int i;
+
+  /* Compute new velocities. */
+  for (i = 0, t = bp->triangles; t; t = t->next, i++)
+    {
+      if (t->thrust > 0)
+        {
+          add_thrust (t, t->thrust);
+          t->thrust_duration--;
+          if (t->thrust_duration <= 0)
+            {
+              t->thrust_duration = 0;
+              t->thrust = 0;
+            }
+        }
+    }
+
+  /* Apply new velocities. */
+  for (i = 0, t = bp->triangles; t; t = t->next, i++)
+    {
+      t->altitude += t->velocity;
+      t->velocity -= gravity;
+      if (t->altitude < 0)
+        {
+          t->velocity = 0;
+          t->altitude = 0;
+        }
+      t->refcount = 0;  /* Clear for next time */
+    }
+
+  /* Add eruptions. */
+  if (frand(1 / speed) < 0.2)
+    {
+      int n = random() % bp->count;
+      for (i = 0, t = bp->triangles; t; t = t->next, i++)
+        if (i == n)
+          break;
+      t->thrust += gravity * 1.5;
+      t->thrust_duration = 1 + BELLRAND(16);
+    }
+
+  bp->ccolor++;
+  if (bp->ccolor >= bp->ncolors)
+    bp->ccolor = 0;
+}
+
+
+static void
+draw_triangles (ModeInfo *mi)
+{
+  splodesic_configuration *bp = &bps[MI_SCREEN(mi)];
+  int wire = MI_IS_WIREFRAME(mi);
+  triangle *t;
+  GLfloat c[4];
+  int c0 = bp->ccolor;
+  int c1 = (c0 + bp->ncolors / 2) % bp->ncolors;
+
+  c[0] = bp->colors[c0].red    / 65536.0;
+  c[1] = bp->colors[c0].green  / 65536.0;
+  c[2] = bp->colors[c0].blue   / 65536.0;
+  c[3] = 1;
+
+  if (wire)
+    glColor4fv (c);
+  else
+    {
+      glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, c);
+
+      c[0] = bp->colors[c1].red    / 65536.0;
+      c[1] = bp->colors[c1].green  / 65536.0;
+      c[2] = bp->colors[c1].blue   / 65536.0;
+      c[3] = 1;
+      glMaterialfv (GL_BACK, GL_AMBIENT_AND_DIFFUSE, c);
+    }
+
+  glFrontFace (GL_CCW);
+  for (t = bp->triangles; t; t = t->next)
+    {
+      GLfloat a = t->altitude * 0.25;
+      XYZ c;
+      glPushMatrix();
+
+      c.x = t->p[0].x + t->p[1].x + t->p[2].x;
+      c.y = t->p[0].y + t->p[1].y + t->p[2].y;
+      c.z = t->p[0].z + t->p[1].z + t->p[2].z;
+      if (a > 0)
+        glTranslatef (a * c.x / 3, a * c.y / 3, a * c.z / 3);
+      glBegin (wire ? GL_LINE_LOOP : GL_TRIANGLES);
+      glNormal3f (c.x, c.y, c.z);
+      glVertex3f (t->p[0].x, t->p[0].y, t->p[0].z);
+      glVertex3f (t->p[1].x, t->p[1].y, t->p[1].z);
+      glVertex3f (t->p[2].x, t->p[2].y, t->p[2].z);
+      glEnd();
+      mi->polygon_count++;
+      glPopMatrix();
+    }
+}
+
+
+/* Window management, etc
+ */
+ENTRYPOINT void
+reshape_splodesic (ModeInfo *mi, int width, int height)
+{
+  GLfloat h = (GLfloat) height / (GLfloat) width;
+
+  glViewport (0, 0, (GLint) width, (GLint) height);
+
+  glMatrixMode(GL_PROJECTION);
+  glLoadIdentity();
+  gluPerspective (30.0, 1/h, 1.0, 100.0);
+
+  glMatrixMode(GL_MODELVIEW);
+  glLoadIdentity();
+  gluLookAt( 0.0, 0.0, 30.0,
+             0.0, 0.0, 0.0,
+             0.0, 1.0, 0.0);
+
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+  {
+    int o = (int) current_device_rotation();
+    if (o != 0 && o != 180 && o != -180)
+      glScalef (1/h, 1/h, 1/h);
+  }
+# endif
+
+  glClear(GL_COLOR_BUFFER_BIT);
+}
+
+
+ENTRYPOINT Bool
+splodesic_handle_event (ModeInfo *mi, XEvent *event)
+{
+  splodesic_configuration *bp = &bps[MI_SCREEN(mi)];
+
+  if (gltrackball_event_handler (event, bp->trackball,
+                                 MI_WIDTH (mi), MI_HEIGHT (mi),
+                                 &bp->button_down_p))
+    return True;
+  else if (event->xany.type == KeyPress)
+    {
+      KeySym keysym;
+      char c = 0;
+      XLookupString (&event->xkey, &c, 1, &keysym, 0);
+      if (c == ' ' || c == '\t')
+        {
+          bp->ncolors = 1024;
+          make_smooth_colormap (0, 0, 0,
+                                bp->colors, &bp->ncolors,
+                                False, 0, False);
+          return True;
+        }
+    }
+
+  return False;
+}
+
+
+ENTRYPOINT void 
+init_splodesic (ModeInfo *mi)
+{
+  splodesic_configuration *bp;
+  int wire = MI_IS_WIREFRAME(mi);
+
+  if (!bps) {
+    bps = (splodesic_configuration *)
+      calloc (MI_NUM_SCREENS(mi), sizeof (splodesic_configuration));
+    if (!bps) {
+      fprintf(stderr, "%s: out of memory\n", progname);
+      exit(1);
+    }
+  }
+
+  bp = &bps[MI_SCREEN(mi)];
+
+  bp->glx_context = init_GL(mi);
+
+  reshape_splodesic (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
+
+  if (!wire)
+    {
+      GLfloat pos[4] = {4.0, 1.4, 1.1, 0.0};
+      GLfloat amb[4] = {0.0, 0.0, 0.0, 1.0};
+      GLfloat dif[4] = {1.0, 1.0, 1.0, 1.0};
+      GLfloat spc[4] = {1.0, 0.2, 0.2, 1.0};
+      GLfloat cspec[4] = {1, 1, 1, 1};
+      static const GLfloat shiny = 10;
+      int lightmodel = 1;
+
+      glEnable(GL_LIGHTING);
+      glEnable(GL_LIGHT0);
+      glEnable(GL_DEPTH_TEST);
+      glEnable(GL_CULL_FACE);
+
+      glLightfv(GL_LIGHT0, GL_POSITION, pos);
+      glLightfv(GL_LIGHT0, GL_AMBIENT,  amb);
+      glLightfv(GL_LIGHT0, GL_DIFFUSE,  dif);
+      glLightfv(GL_LIGHT0, GL_SPECULAR, spc);
+      glLightModeliv (GL_LIGHT_MODEL_TWO_SIDE, &lightmodel);
+      glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, cspec);
+      glMateriali (GL_FRONT_AND_BACK, GL_SHININESS, shiny);
+    }
+
+  {
+    double spin_speed   = 0.5;
+    double wander_speed = 0.005;
+    double spin_accel   = 1.0;
+
+    bp->rot = make_rotator (do_spin ? spin_speed : 0,
+                            do_spin ? spin_speed : 0,
+                            do_spin ? spin_speed : 0,
+                            spin_accel,
+                            do_wander ? wander_speed : 0,
+                            True);
+    bp->trackball = gltrackball_init (True);
+  }
+
+  bp->ncolors = 1024;
+  bp->colors = (XColor *) calloc(bp->ncolors, sizeof(XColor));
+  make_smooth_colormap (0, 0, 0,
+                        bp->colors, &bp->ncolors,
+                        False, 0, False);
+
+# ifdef HAVE_MOBILE
+  depth_arg--;
+# endif
+
+  if (depth_arg < 0)  depth_arg = 0;
+  if (depth_arg > 10) depth_arg = 10;
+
+  make_geodesic (mi);
+  link_neighbors (mi);
+}
+
+
+ENTRYPOINT void
+draw_splodesic (ModeInfo *mi)
+{
+  splodesic_configuration *bp = &bps[MI_SCREEN(mi)];
+  Display *dpy = MI_DISPLAY(mi);
+  Window window = MI_WINDOW(mi);
+
+  if (!bp->glx_context)
+    return;
+
+  glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(bp->glx_context));
+
+  glShadeModel(GL_SMOOTH);
+
+  glEnable(GL_DEPTH_TEST);
+  glEnable(GL_NORMALIZE);
+  glDisable(GL_CULL_FACE);
+
+  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+  glPushMatrix ();
+
+  {
+    double x, y, z;
+    get_position (bp->rot, &x, &y, &z, !bp->button_down_p);
+    glTranslatef((x - 0.5) * 6,
+                 (y - 0.5) * 6,
+                 (z - 0.5) * 8);
+
+    gltrackball_rotate (bp->trackball);
+
+    get_rotation (bp->rot, &x, &y, &z, !bp->button_down_p);
+    glRotatef (x * 360, 1.0, 0.0, 0.0);
+    glRotatef (y * 360, 0.0, 1.0, 0.0);
+    glRotatef (z * 360, 0.0, 0.0, 1.0);
+  }
+
+  mi->polygon_count = 0;
+
+# ifdef HAVE_MOBILE
+  glScalef (3, 3, 3);
+#else
+  glScalef (4, 4, 4);
+# endif
+
+  if (! bp->button_down_p)
+    tick_triangles (mi);
+  draw_triangles (mi);
+
+  glPopMatrix ();
+
+  if (mi->fps_p) do_fps (mi);
+  glFinish();
+
+  glXSwapBuffers(dpy, window);
+}
+
+
+ENTRYPOINT void
+release_splodesic (ModeInfo *mi)
+{
+  splodesic_configuration *bp = &bps[MI_SCREEN(mi)];
+  while (bp->triangles)
+    {
+      triangle *t = bp->triangles->next;
+      free (bp->triangles);
+      bp->triangles = t;
+    }
+}
+
+XSCREENSAVER_MODULE ("Splodesic", splodesic)
+
+#endif /* USE_GL */
diff --git a/hacks/glx/splodesic.man b/hacks/glx/splodesic.man
new file mode 100644 (file)
index 0000000..bf31e1d
--- /dev/null
@@ -0,0 +1,69 @@
+.TH XScreenSaver 1 "" "X Version 11"
+.SH NAME
+splodesic - k
+A geodesic sphere experiences a series of eruptions.
+.SH SYNOPSIS
+.B splodesic
+[\-display \fIhost:display.screen\fP]
+[\-visual \fIvisual\fP]
+[\-window]
+[\-root]
+[\-no-wander]
+[\-no-spin]
+[\-fps]
+[\-delay \fInumber\fP]
+[\-speed \fInumber\fP]
+[\-depth \fInumber\fP]
+.SH DESCRIPTION
+A geodesic sphere experiences a series of eruptions.
+.SH OPTIONS
+.TP 8
+.B \-visual \fIvisual\fP
+Specify which visual to use.  Legal values are the name of a visual class,
+or the id number (decimal or hex) of a specific visual.
+.TP 8
+.B \-window
+Draw on a newly-created window.  This is the default.
+.TP 8
+.B \-root
+Draw on the root window.
+.TP 8
+.B \-wander | \-no-wander
+Whether the object should wander around the screen.
+.TP 8
+.B \-spin | \-no-spin
+Whether the object should spin.
+.TP 8
+.B \-fps | \-no-fps
+Whether to show a frames-per-second display at the bottom of the screen.
+.TP 8
+.B \-delay \fInumber\fP
+Per-frame delay, in microseconds.  Default: 30000 (0.03 seconds).
+.TP 8
+.B \-speed \fInumber\fP
+Frequency of eruptions.  2.0 means twice as often, 0.5 means half as often.
+.TP 8
+.B \-depth \fInumber\fP
+Depth (frequency) of the geodesic. 0 - 5. Default: 4.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1)
+.SH COPYRIGHT
+Copyright \(co 2016 by Jamie Zawinski.  Permission to use, copy, modify, 
+distribute, and sell this software and its documentation for any purpose is 
+hereby granted without fee, provided that the above copyright notice appear 
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation.  No representations are made about the 
+suitability of this software for any purpose.  It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+Jamie Zawinski.
index 0db66d9b7bbb60045a9224840fc74054c19f59ae..fc0a3f51d721aa9b844efeb2718bc4539bc0a7fe 100644 (file)
 "\\n" \
 "\\n" \
 "\\n" \
+"\\n" \
+"Episode VII\\n" \
+"THE FORCE AWAKENS\\n" \
+"Luke Skywalker has vanished.\\n" \
+"In his absence, the sinister\\n" \
+"FIRST ORDER has risen from\\n" \
+"the ashes of the Empire\\n" \
+"and will not rest until\\n" \
+"Skywalker, the last Jedi,\\n" \
+"has been destroyed.\\n" \
+"\\n" \
+"With the support of the\\n" \
+"REPUBLIC, General Leia Organa\\n" \
+"leads a brave RESISTANCE.\\n" \
+"She is desperate to find her\\n" \
+"brother Luke and gain his\\n" \
+"help in restoring peace and \\n" \
+"justice to the galaxy.\\n" \
+"\\n" \
+"Leia has sent her most daring\\n" \
+"pilot on a secret mission\\n" \
+"to Jakku, where an old ally\\n" \
+"has discovered a clue to\\n" \
+"Luke's whereabouts...\\n" \
+"\\n" \
+"\\n" \
+"\\n" \
+"\\n" \
+"\\n" \
+"\\n" \
+"\\n" \
+"\\n" \
+"\\n" \
+"\\n" \
+"\\n" \
+"\\n" \
+"\\n" \
+"\\n" \
+"\\n" \
+"\\n" \
+"\\n" \
+"\\n" \
+"\\n" \
+"\\n" \
+"\\n" \
+"\\n" \
+"\\n" \
+"\\n" \
+"\\n" \
+"\\n" \
+"\\n" \
 "\\n"
index e056f9226754e79bb486eb68d79239680bf39f54..818d3ab4f28f535ccbcc988924378f211a589f06 100644 (file)
@@ -301,6 +301,59 @@ captive Chancellor....
 
 
 
+
+
+
+
+
+
+
+
+Episode VII
+
+THE FORCE AWAKENS
+
+Luke Skywalker has vanished.
+In his absence, the sinister
+FIRST ORDER has risen from
+the ashes of the Empire
+and will not rest until
+Skywalker, the last Jedi,
+has been destroyed.
+
+With the support of the
+REPUBLIC, General Leia Organa
+leads a brave RESISTANCE.
+She is desperate to find her
+brother Luke and gain his
+help in restoring peace and
+justice to the galaxy.
+
+Leia has sent her most daring
+pilot on a secret mission
+to Jakku, where an old ally
+has discovered a clue to
+Luke's whereabouts...
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
 
 
 
index 7daa2d50d43746c62975001e3f4acbff086df094..0262f86161427c2d54459e16b133ebab486953a6 100644 (file)
@@ -928,7 +928,7 @@ char *
 texfont_unicode_character_name (texture_font_data *data, unsigned long uc)
 {
   Font fid = data->xftfont->xfont->fid;
-  return jwxyz_unicode_character_name (fid, uc);
+  return jwxyz_unicode_character_name (data->dpy, fid, uc);
 }
 #endif /* HAVE_JWXYZ */
 
index 882635000deee9be0c1b20f31589ec0f6fb2b0c4..53d8dd97b9d145be1cc6a167a461aeaf1b1a0935 100644 (file)
@@ -877,8 +877,8 @@ static void LoadTexture(ModeInfo * mi, char **fn, const char *filename, GLuint t
                        by = by * 2;
        }
 
-#ifndef HAVE_JWZGLES
        if (rescale) {
+#ifndef HAVE_JWZGLES
                tmpbuf = calloc(bx * by * 4, sizeof(unsigned char));
                if (gluScaleImage(GL_RGBA, teximage->width, teximage->height, GL_UNSIGNED_BYTE, teximage->data,
                                bx, by, GL_UNSIGNED_BYTE, tmpbuf))
@@ -888,9 +888,9 @@ static void LoadTexture(ModeInfo * mi, char **fn, const char *filename, GLuint t
                teximage->data = (char *) tmpbuf;
                teximage->width = bx;
                teximage->height= by;
+#endif /* !HAVE_JWZGLES */
        }
        /* end rescale code */
-#endif /* !HAVE_JWZGLES */
                
        if (anegative ) {
                for (ix = 0 ; ix < teximage->height * teximage->width; ix++)
index 024f95bc1277d5f8ca1410834fe9e150a8bd76b4..640ebf75d841575487d576d1568528054e0004e6 100644 (file)
@@ -1,5 +1,5 @@
 /* xpm-ximage.c --- converts XPM data to an XImage for use with OpenGL.
- * xscreensaver, Copyright (c) 1998-2013 Jamie Zawinski <jwz@jwz.org>
+ * xscreensaver, Copyright (c) 1998-2016 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
 
 #include "xpm-ximage.h"
 
+#ifdef HAVE_COCOA
+# include "grabscreen.h"  /* for osx_load_image_file() */
+#endif
+
 extern char *progname;
 
 
@@ -361,7 +365,7 @@ xpm_to_ximage_1 (Display *dpy, Visual *visual, Colormap cmap,
                  const char *filename, char **xpm_data)
 {
   int iw, ih, w8, x, y;
-  XImage *ximage;
+  XImage *ximage = 0;
   char *data;
   unsigned char *mask = 0;
   int depth = 32;
@@ -375,18 +379,58 @@ xpm_to_ximage_1 (Display *dpy, Visual *visual, Colormap cmap,
   unsigned long rmsk=0, gmsk=0, bmsk=0, amsk=0;
   unsigned long rsiz=0, gsiz=0, bsiz=0, asiz=0;
 
+# ifdef HAVE_COCOA
+  if (filename) {
+    XRectangle geom;
+    Screen *screen = DefaultScreenOfDisplay (dpy);
+    Window window = RootWindowOfScreen (screen);
+    XWindowAttributes xgwa;
+    XGetWindowAttributes (dpy, window, &xgwa);
+    Pixmap pixmap =
+      XCreatePixmap (dpy, window, xgwa.width, xgwa.height, xgwa.depth);
+
+    if (osx_load_image_file (screen, window, pixmap, filename, &geom)) {
+      ximage = XGetImage (dpy, pixmap, geom.x, geom.y, geom.width, geom.height,
+                          ~0L, ZPixmap);
+
+      /* Have to convert BGRA to ARGB */
+      if (ximage) {
+        int x, y;
+        for (y = 0; y < ximage->height; y++)
+          for (x = 0; x < ximage->width; x++) {
+            unsigned long p = XGetPixel (ximage, x, y);
+            unsigned long b = (p >> 24) & 0xFF;
+            unsigned long g = (p >> 16) & 0xFF;
+            unsigned long r = (p >>  8) & 0xFF;
+            unsigned long a = (p >>  0) & 0xFF;
+            p = (a << 24) | (r << 16) | (g << 8) | (b << 0);
+            XPutPixel (ximage, x, y, p);
+          }
+      }
+
+    }
+
+    XFreePixmap (dpy, pixmap);
+
+    if (! ximage)
+      fprintf (stderr, "%s: %s failed\n", progname, filename);
+    return ximage;
+  }
+# endif /* HAVE_COCOA */
+
   if (filename)
     {
       fprintf(stderr, 
-              "%s: no files: not compiled with XPM or Pixbuf support.\n", 
-              progname);
-      exit (1);
+              "%s: can't load %s: not compiled with XPM or Pixbuf support.\n", 
+              progname, filename);
+      return 0;
     }
 
   if (! xpm_data) abort();
   ximage = minixpm_to_ximage (dpy, visual, cmap, depth, background_color,
                               (const char * const *) xpm_data,
                               &iw, &ih, &pixels, &npixels, &mask);
+  if (!ximage) abort();
   if (pixels) free (pixels);
   
   bpl = ximage->bytes_per_line;
diff --git a/hacks/images/m6502/greynetic.asm b/hacks/images/m6502/greynetic.asm
new file mode 100644 (file)
index 0000000..1218d87
--- /dev/null
@@ -0,0 +1,96 @@
+;Port of Greynetic
+;Jeremy English 2013
+
+lda #$0
+sta $0
+lda #$2
+sta $1
+
+start:
+lda $1
+cmp #$6
+bne randOffset
+lda #$2
+sta $1
+
+randOffset:
+;move position by some random offset
+clc
+lda $fe
+adc $0
+sta $0
+lda $1
+adc #$0
+sta $1
+cmp #$06 ;Did we go out of range
+bne setRect ;Nope
+lda #$02 ;Start back at the top
+sta $1
+
+setRect:
+lda $fe
+and #$f
+tax
+inx ;at least 1
+stx $2 ;width
+stx $3 ;working copy
+lda $fe
+and #$f
+tax
+inx ;at least 1
+stx $4 ;height
+
+lda $fe
+sta $5 ;color
+
+ldy #0
+draw:
+lda $5
+sta ($0), y
+dec $3
+beq down
+
+lda $0
+clc
+adc #$1
+sta $0
+lda $1
+adc #$0
+sta $1
+cmp #$06 ;Did we go out of range
+beq done ;yes
+jmp draw
+
+down:
+
+;;Move back to the start of this row
+ldx $2 ;The width of the rectangle
+dex
+lda $0
+stx $0
+sec
+sbc $0
+sta $0
+lda $1
+sbc #$0
+sta $1
+
+;;Move down one row
+dec $4
+beq done ;;Are we done drawing?
+
+lda $2
+sta $3 ;reset the width counter
+
+lda $0
+clc
+adc #$20
+sta $0
+lda $1
+adc #$0
+sta $1
+cmp #$06 ;Did we go out of range
+beq done ;yes
+jmp draw
+done:
+jmp start
diff --git a/hacks/images/m6502/life.asm b/hacks/images/m6502/life.asm
new file mode 100644 (file)
index 0000000..6454812
--- /dev/null
@@ -0,0 +1,127 @@
+; Conway\'s Game of Life
+; http://rosettacode.org/wiki/Conway\'s_Game_of_Life
+; Submitted by Anonymous
+
+randfill:   stx $01          ;$200 for indirect
+            ldx #$02         ;addressing
+            stx $02
+randloop:   lda $fe          ;generate random
+            and #$01         ;pixels on the
+            sta ($01),Y      ;screen
+            jsr inc0103
+            cmp #$00
+            bne randloop
+            lda $02
+            cmp #$06
+            bne randloop
+clearmem:   lda #$df         ;set $07df-$0a20
+            sta $01          ;to $#00
+            lda #$07
+            sta $02
+clearbyte:  lda #$00
+            sta ($01),Y
+            jsr inc0103
+            cmp #$20
+            bne clearbyte
+            lda $02
+            cmp #$0a
+            bne clearbyte
+starttick:
+copyscreen: lda #$00         ;set up source
+            sta $01          ;pointer at
+            sta $03          ;$01/$02 and
+            lda #$02         ;dest pointer
+            sta $02          ;at $03/$04
+            lda #$08
+            sta $04
+            ldy #$00
+copybyte:   lda ($01),Y      ;copy pixel to
+            sta ($03),Y      ;back buffer
+            jsr inc0103      ;increment pointers
+            cmp #$00         ;check to see
+            bne copybyte     ;if we\'re at $600
+            lda $02          ;if so, we\'ve
+            cmp #$06         ;copied the
+            bne copybyte     ;entire screen
+conway:     lda #$df         ;apply conway rules
+            sta $01          ;reset the pointer
+            sta $03          ;to $#01df/$#07df
+            lda #$01         ;($200 - $21)
+            sta $02          ;($800 - $21)
+            lda #$07
+            sta $04
+onecell:    lda #$00         ;process one cell
+            ldy #$01         ;upper cell
+            clc
+            adc ($03),Y
+            ldy #$41         ;lower cell
+            clc
+            adc ($03),Y
+chkleft:    tax              ;check to see
+            lda $01          ;if we\'re at the
+            and #$1f         ;left edge
+            tay
+            txa
+            cpy #$1f
+            beq rightcells
+leftcells:  ldy #$00         ;upper-left cell
+            clc
+            adc ($03),Y
+            ldy #$20         ;left cell
+            clc
+            adc ($03),Y
+            ldy #$40         ;lower-left cell
+            clc
+            adc ($03),Y
+chkright:   tax              ;check to see
+            lda $01          ;if we\'re at the
+            and #$1f         ;right edge
+            tay
+            txa
+            cpy #$1e
+            beq evaluate
+rightcells: ldy #$02         ;upper-right cell
+            clc
+            adc ($03),Y
+            ldy #$22         ;right cell
+            clc
+            adc ($03),Y
+            ldy #$42         ;lower-right cell
+            clc
+            adc ($03),Y
+evaluate:   ldx #$01         ;evaluate total
+            ldy #$21         ;for current cell
+            cmp #$03         ;3 = alive
+            beq storex
+            ldx #$00
+            cmp #$02         ;2 = alive if
+            bne storex       ;c = alive
+            lda ($03),Y
+            and #$01
+            tax
+storex:     txa              ;store to screen
+            sta ($01),Y
+            jsr inc0103      ;move to next cell
+conwayloop: cmp #$e0         ;if not last cell,
+            bne onecell      ;process next cell
+            lda $02
+            cmp #$05
+            bne onecell
+            jmp starttick    ;run next tick
+inc0103:    lda $01          ;increment $01
+            cmp #$ff         ;and $03 as 16-bit
+            bne onlyinc01    ;pointers
+            inc $02
+            inc $04
+onlyinc01:  inc $01
+            lda $01
+            sta $03
+            rts
diff --git a/hacks/images/m6502/sflake.asm b/hacks/images/m6502/sflake.asm
new file mode 100644 (file)
index 0000000..cbb72e8
--- /dev/null
@@ -0,0 +1,320 @@
+;; Jeremy English 01-December-2008
+;; Snowflakes
+
+;; Main loop Count
+lda #7
+sta $f
+
+;; pattern number
+lda #0
+sta $10
+
+;;Cells
+lda #$00
+sta $4
+lda #$10
+sta $5
+
+;;Tmp
+lda #$00
+sta $6
+lda #$11
+sta $7
+
+;;Init Cells Buffer
+;;------------------------------------------------------------
+ldy #$ff
+initCells:
+lda #0
+sta ($4),y
+sta ($6),y
+dey
+bne initCells
+
+;;Set start position
+ldy #115
+lda #1
+sta ($4),y
+   
+;;Setup offset
+lda #15
+sta $d
+lda #16
+sta $e
+
+;;Start of main loop
+;;------------------------------------------------------------
+mainloop:
+
+;;init indent
+;;We want to indent every other line
+lda #0
+sta $a
+
+lda #0
+sta $9
+
+;; Display Cells
+;;------------------------------------------------------------
+;; 248 is the total number of cells
+ldy #248
+display:
+
+lda #0
+sta $8
+
+lda $a
+beq stop16
+lda #15
+sta $b
+lda #1
+sta $8
+jmp toggle
+stop16:
+lda #16
+sta $b
+toggle:
+lda $a
+eor #1
+sta $a
+
+;; Set the stop position
+ldx $b
+inner_display:
+dex
+txa
+pha
+
+dey
+tya
+pha
+lda ($4),y
+
+beq display_continue
+ldx $8
+ldy $9
+lda #1
+jsr paint
+ldx $8
+ldy $9
+inx
+jsr paint
+ldx $8
+ldy $9
+iny
+jsr paint
+ldx $8
+ldy $9
+inx
+iny
+jsr paint
+display_continue:
+inc $8
+inc $8
+
+;;Life Cycle
+;;------------------------------------------------------------
+pla
+tay
+pha ;;Store y on the stack
+
+tax
+dey
+lda ($4),y
+iny
+iny
+clc
+adc ($4),y
+sta $c
+
+txa
+sec
+sbc $d
+tay
+lda $c
+clc
+adc ($4),y
+sta $c
+
+txa
+sec
+sbc $e
+tay
+lda $c
+clc
+adc ($4),y
+sta $c
+
+txa
+clc
+adc $d
+tay
+lda $c
+clc
+adc ($4),y
+sta $c
+
+txa
+clc
+adc $e
+tay
+lda $c
+clc
+adc ($4),y
+sta $c
+
+pla
+tay ;;Pull Y off of the stack
+
+lda $c
+and #1
+beq dontset
+sta ($6),y
+dontset:
+   
+pla
+tax ;;Pull x off of the stack   
+beq exit_inner_display
+jmp inner_display
+exit_inner_display:
+inc $9
+inc $9
+tya
+beq display_exit
+jmp display
+display_exit:
+
+
+;;Copy Temporary Buffer
+;;------------------------------------------------------------
+ldy #248
+copybuf:
+dey
+lda ($6),y
+sta ($4),y
+tya
+bne copybuf
+
+dec $f
+lda $f
+beq reset_main
+jmp mainloop
+
+;;Reset main counter
+;;------------------------------------------------------------
+reset_main:
+lda #7
+sta $f
+
+lda #$ff ;;Delay Count
+sta $11
+delay:
+ldy #$a0
+inner_delay:
+nop
+dey
+bne inner_delay
+dec $11
+lda $11
+bne delay
+
+;; init buffer
+;; and clear screen
+clrscr:
+lda $fe
+and $f
+cmp #1
+beq clrscr ;We don't want a white background
+ldy #$00
+ldx #$0
+cs_loop: 
+sta $200,x
+sta $300,x
+sta $400,x
+sta $500,x
+pha
+lda #0
+sta ($6),y
+sta ($4),y
+pla
+inx
+dey
+bne cs_loop
+
+;; Setup new pattern
+;;------------------------------------------------------------
+inc $10
+lda $10
+and #3
+sta $10
+cmp #0
+beq pattern1
+cmp #1
+beq pattern2
+cmp #2
+beq pattern3
+cmp #3
+beq pattern4
+
+pattern1:
+ldy #114
+lda #1
+sta ($4),y
+ldy #115
+lda #1
+sta ($4),y
+ldy #116
+lda #1
+sta ($4),y
+jmp mainloop
+
+pattern2:
+ldy #113
+lda #1
+sta ($4),y
+ldy #118
+lda #1
+sta ($4),y
+jmp mainloop
+
+pattern3:
+ldy #115
+lda #1
+sta ($4),y
+jmp mainloop
+
+pattern4:
+ldy #102
+lda #1
+sta ($4),y
+ldy #128
+lda #1
+sta ($4),y
+jmp mainloop
+
+;;Paint subroutine
+;;------------------------------------------------------------
+paint:
+   pha
+   lda yl,y
+   sta $2
+   lda yh,y
+   sta $3
+   txa
+   tay
+   pla
+   sta ($2),y
+   rts
+
+       ;; Y cord MSB   
+yh:
+       dcb $02, $02, $02, $02, $02, $02, $02, $02
+       dcb $03, $03, $03, $03, $03, $03, $03, $03
+       dcb $04, $04, $04, $04, $04, $04, $04, $04
+       dcb $05, $05, $05, $05, $05, $05, $05, $05
+       ;; Y cord LSB
+yl:
+       dcb $00, $20, $40, $60, $80, $a0, $c0, $e0
+       dcb $00, $20, $40, $60, $80, $a0, $c0, $e0
+       dcb $00, $20, $40, $60, $80, $a0, $c0, $e0
+       dcb $00, $20, $40, $60, $80, $a0, $c0, $e0 
diff --git a/hacks/images/m6502/sierpinski.asm b/hacks/images/m6502/sierpinski.asm
new file mode 100644 (file)
index 0000000..2d21905
--- /dev/null
@@ -0,0 +1,24 @@
+; Sierpinski
+; Submitted by Anonymous
+
+start:
+  lda #$e1
+  sta $0
+  lda #$01
+  sta $1
+  ldy #$20
+
+write:
+  ldx #$00
+  eor ($0, x)
+  sta ($0),y
+
+  inc $0
+  bne write
+  inc $1
+  ldx $1
+  cpx #$06
+  bne write
+
+  rts
+
index 50cebfcc03e1bb434911721a501861c8e2d8a20d..30f338c98c1dffb8d47437971c9fc07fab1f6733 100755 (executable)
@@ -7,7 +7,7 @@ SRCS=$*
 TMP1=m6502.h.1.$$
 TMP2=m6502.h.2.$$
 rm -f $TMP1 $TMP2
-trap "rm -f $TMP1 $TMP2" 1 2 3 15 ERR EXIT
+trap "rm -f $TMP1 $TMP2" 1 2 3 15 EXIT
 
 if [ -z "$UTILS_SRC" ]; then UTILS_SRC="../utils"; fi
 
index 1238048976d0e3dd6c8eebb1fa36e52f464acdf9..a8469b0a58ac830d1ce1043233005a9c7bcaaf1e 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1999-2014 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1999-2016 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
@@ -78,7 +78,7 @@ typedef struct {
   int escstate;
   int csiparam[NPAR];
   int curparam;
-  int unicruds; char unicrud[7];
+  int unicruds; unsigned char unicrud[7];
 
   p_char **chars;
   p_cell *cells;
@@ -729,6 +729,56 @@ scroll (p_state *state)
 }
 
 
+static int
+process_unicrud (p_state *state, int c)
+{
+  if ((c & 0xE0) == 0xC0) {        /* 110xxxxx: 11 bits, 2 bytes */
+    state->unicruds = 1;
+    state->unicrud[0] = c;
+    state->escstate = 102;
+  } else if ((c & 0xF0) == 0xE0) { /* 1110xxxx: 16 bits, 3 bytes */
+    state->unicruds = 1;
+    state->unicrud[0] = c;
+    state->escstate = 103;
+  } else if ((c & 0xF8) == 0xF0) { /* 11110xxx: 21 bits, 4 bytes */
+    state->unicruds = 1;
+    state->unicrud[0] = c;
+    state->escstate = 104;
+  } else if ((c & 0xFC) == 0xF8) { /* 111110xx: 26 bits, 5 bytes */
+    state->unicruds = 1;
+    state->unicrud[0] = c;
+    state->escstate = 105;
+  } else if ((c & 0xFE) == 0xFC) { /* 1111110x: 31 bits, 6 bytes */
+    state->unicruds = 1;
+    state->unicrud[0] = c;
+    state->escstate = 106;
+  } else if (state->unicruds == 0) {
+    return c;
+  } else {
+    int total = state->escstate - 100;  /* see what I did there */
+    if (state->unicruds < total) {
+      /* Buffer more bytes of the UTF-8 sequence */
+      state->unicrud[state->unicruds++] = c;
+    }
+
+    if (state->unicruds >= total) {
+      /* Done! Convert it to Latin1 and print that. */
+      char *s;
+      state->unicrud[state->unicruds] = 0;
+      s = utf8_to_latin1 ((const char *) state->unicrud, False);
+      state->unicruds = 0;
+      state->escstate = 0;
+      if (s) {
+        c = (unsigned char) s[0];
+        free (s);
+        return c;
+      }
+    }
+  }
+  return 0;
+}
+
+
 static void
 print_char (p_state *state, int c)
 {
@@ -831,36 +881,10 @@ print_char (p_state *state, int c)
              break;
            default:
 
-              /* states 102-106 are for UTF-8 decoding */
-
-              if ((c & 0xE0) == 0xC0) {        /* 110xxxxx: 11 bits, 2 bytes */
-                state->unicruds = 1;
-                state->unicrud[0] = c;
-                state->escstate = 102;
-                break;
-              } else if ((c & 0xF0) == 0xE0) { /* 1110xxxx: 16 bits, 3 bytes */
-                state->unicruds = 1;
-                state->unicrud[0] = c;
-                state->escstate = 103;
-                break;
-              } else if ((c & 0xF8) == 0xF0) { /* 11110xxx: 21 bits, 4 bytes */
-                state->unicruds = 1;
-                state->unicrud[0] = c;
-                state->escstate = 104;
+            PRINT: /* Come from states 102-106 */
+              c = process_unicrud (state, c);
+              if (! c)
                 break;
-              } else if ((c & 0xFC) == 0xF8) { /* 111110xx: 26 bits, 5 bytes */
-                state->unicruds = 1;
-                state->unicrud[0] = c;
-                state->escstate = 105;
-                break;
-              } else if ((c & 0xFE) == 0xFC) { /* 1111110x: 31 bits, 6 bytes */
-                state->unicruds = 1;
-                state->unicrud[0] = c;
-                state->escstate = 106;
-                break;
-              }
-
-            PRINT:
 
               /* If the cursor is in column 39 and we print a character, then
                  that character shows up in column 39, and the cursor is no
@@ -1137,35 +1161,12 @@ print_char (p_state *state, int c)
          state->escstate = 0;
          break;
 
-        case 102:
+        case 102:      /* states 102-106 are for UTF-8 decoding */
         case 103:
         case 104:
         case 105:
         case 106:
-          {
-            int total = state->escstate - 100;  /* see what I did there */
-            if (state->unicruds < total) {
-              /* Buffer more bytes of the UTF-8 sequence */
-              state->unicrud[state->unicruds++] = c;
-            }
-
-            if (state->unicruds >= total) {
-              /* Done! Convert it to Latin1 and print that. */
-              char *s;
-              state->unicrud[state->unicruds] = 0;
-              s = utf8_to_latin1 ((const char *) state->unicrud, False);
-              state->unicruds = 0;
-              state->escstate = 0;
-              if (s) {
-                c = (unsigned char) s[0];
-                free (s);
-                goto PRINT;
-              } else {
-                c = 0;
-              }
-            }
-          }
-          break;
+          goto PRINT;
 
         default:
           abort();
@@ -1196,7 +1197,8 @@ print_char (p_state *state, int c)
        }
       else
        {
-          /* #### This should do UTF-8 decoding */
+          c = process_unicrud (state, c);
+          if (!c) return;
 
          cell->state = FLARE;
          cell->p_char = state->chars[c];
index e4cd8536c85cf3b4c740c6992961917acb62303a..f70511d8e4f6c97d2a1d4120fb80ae9cd9d7d883 100644 (file)
@@ -1,5 +1,5 @@
 /* rotzoomer - creates a collage of rotated and scaled portions of the screen
- * Copyright (C) 2001 Claudio Matsuoka <claudio@helllabs.org>
+ * Copyright (C) 2001-2016 Claudio Matsuoka <claudio@helllabs.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -10,7 +10,7 @@
  * implied warranty.
  */
 
-/* (circle-mode by jwz, 4-Jun-2014; not finished yet.) */
+/* Circle-mode by jwz, 2014, 2016. */
 
 /*
  * Options:
@@ -67,6 +67,7 @@ struct state {
   time_t start_time;
 
   async_load_state *img_loader;
+  Pixmap pm;
 
 #ifdef HAVE_XSHM_EXTENSION
   Bool use_shm;
@@ -88,8 +89,10 @@ rotzoom (struct state *st, struct zoom_area *za)
 
   for (y = za->y; y <= y2; y++) {
     for (x = za->x; x <= x2; x++) {
-      c = zoom * cos (M_PI * za->a1 / 8192);
-      s = zoom * sin (M_PI * za->a1 / 8192);
+      Bool copyp = True;
+      double a = M_PI * za->a1 / 8192;
+      c = zoom * cos (a);
+      s = zoom * sin (a);
       if (st->circle) {
         int cx = za->x + za->w / 2;
         int cy = za->y + za->h / 2;
@@ -98,30 +101,33 @@ rotzoom (struct state *st, struct zoom_area *za)
         int d2 = (dx*dx) + (dy*dy);
 
         if (d2 > w2) {
-          ox = x;
-          oy = y;
+          copyp = False;
         } else {
           double r = sqrt ((double) d2);
           double th = atan ((double)dy / (double) (dx == 0 ? 1 : dx));
-          th += M_PI * (za->a1 / 300.0);
-          ox = 10 + cx + (int) (r * cos(th));
-          oy = 10 + cy + (int) (r * sin(th));
+          copyp = 1;
+          if (dx < 0) th += M_PI;
+          th += M_PI * (za->a1 / 600.0);
+          ox = cx + (int) (r * cos(th));
+          oy = cy + (int) (r * sin(th));
         }
       } else {
         ox = (x * c + y * s) >> 13;
         oy = (-x * s + y * c) >> 13;
       }
 
-      while (ox < 0)
-        ox += st->width;
-      while (oy < 0)
-        oy += st->height;
-      while (ox >= st->width)
-        ox -= st->width;
-      while (oy >= st->height)
-        oy -= st->height;
-
-      XPutPixel (st->buffer_map, x, y, XGetPixel (st->orig_map, ox, oy));
+      if (copyp) {
+        while (ox < 0)
+          ox += st->width;
+        while (oy < 0)
+          oy += st->height;
+        while (ox >= st->width)
+          ox -= st->width;
+        while (oy >= st->height)
+          oy -= st->height;
+
+        XPutPixel (st->buffer_map, x, y, XGetPixel (st->orig_map, ox, oy));
+      }
     }
   }
 
@@ -134,6 +140,25 @@ rotzoom (struct state *st, struct zoom_area *za)
   za->ox = ox;                 /* Save state for next iteration */
   za->oy = oy;
 
+  if (st->circle && za->n <= 1)
+    {
+      /* Done rotating the circle: copy the bits from the working set back
+         into the origin, so that subsequent rotations pick up these changes.
+       */
+      int cx = za->x + za->w / 2;
+      int cy = za->y + za->h / 2;
+      int w2 = (za->w/2) * (za->w/2);
+      for (y = za->y; y < za->y + za->h; y++)
+        for (x = za->x; x < za->x + za->w; x++)
+          {
+            int dx = x - cx;
+            int dy = y - cy;
+            int d2 = (dx*dx) + (dy*dy);
+            if (d2 <= w2)
+              XPutPixel (st->orig_map, x, y, XGetPixel (st->buffer_map, x, y));
+          }
+    }
+
   za->count++;
 }
 
@@ -199,28 +224,27 @@ reset_zoom (struct state *st, struct zoom_area *za)
       za->w = st->height / 3;
     za->h = za->w;
 
-    za->ww = st->width - za->w;
+    za->ww = st->width  - za->w;
     za->hh = st->height - za->h;
 
     za->x = (za->ww ? random() % za->ww : 0);
     za->y = (za->hh ? random() % za->hh : 0);
-
     za->dx = 0;
     za->dy = 0;
-    za->inc1 = ((2 * (random() & 1)) - 1) * (random () % 30);
+    za->a1 = 0;
+    za->a2 = 0;
+    za->count = 0;
 
-    if (st->anim) {
-      za->n = 50 + random() % 1000;
-      za->a1 = 0;
-      za->a2 = 0;
-    } else {
-      za->n = 5 + random() % 10;
-      za->a1 = random ();
-      za->a2 = random ();
-    }
+    /* #### If we go clockwise, it doesn't start rotating from 0.
+       So only go counter-clockwise for now. Sigh. */
+    za->inc1 = (random () % 30);
+    za->inc2 = 0;
+    za->n = 50 + random() % 100;
 
-    za->inc1 = ((2 * (random() & 1)) - 1) * (random () % 30);
-    za->inc2 = ((2 * (random() & 1)) - 1) * (random () % 30);
+    if (!st->anim) {
+      za->count = random() % (za->n / 2);
+      za->a1 = random();
+    }
 
   } else {
     za->w = 50 + random() % 300;
@@ -317,11 +341,45 @@ DisplayImage (struct state *st, int x, int y, int w, int h)
 }
 
 
+static void
+set_mode(struct state *st)
+{
+  char *s = get_string_resource (st->dpy, "mode", "Mode");
+  if (!s || !*s || !strcasecmp (s, "random"))
+    {
+      switch (random() % 4) {
+      case 0: s = "stationary"; break;
+      case 1: s = "move"; break;
+      case 2: s = "sweep"; break;
+      case 3: s = "circle"; break;
+      default: abort();
+      }
+    }
+
+  st->move = False;
+  st->sweep = False;
+  st->circle = False;
+
+  if (!strcasecmp (s, "stationary"))
+    ;
+  else if (!strcasecmp (s, "move"))
+    st->move = True;
+  else if (!strcasecmp (s, "sweep"))
+    st->sweep = True;
+  else if (!strcasecmp (s, "circle"))
+    st->circle = True;
+  else
+    fprintf (stderr, "%s: bogus mode: \"%s\"\n", progname, s);
+}
+
+
 static void
 init_hack (struct state *st)
 {
   int i;
 
+  set_mode (st);
+
   st->start_time = time ((time_t *) 0);
   st->zoom_box = calloc (st->num_zoom, sizeof (struct zoom_area *));
   for (i = 0; i < st->num_zoom; i++) {
@@ -347,8 +405,10 @@ rotzoomer_draw (Display *disp, Window win, void *closure)
     {
       st->img_loader = load_image_async_simple (st->img_loader, 0, 0, 0, 0, 0);
       if (! st->img_loader) {  /* just finished */
-       st->orig_map = XGetImage (st->dpy, st->window, 0, 0, 
-                                  st->width, st->height, ~0L, ZPixmap);
+        if (! st->pm) abort();
+       st->orig_map = XGetImage (st->dpy, st->pm,
+                                  0, 0, st->width, st->height,
+                                  ~0L, ZPixmap);
         init_hack (st);
       }
       return st->delay;
@@ -358,8 +418,14 @@ rotzoomer_draw (Display *disp, Window win, void *closure)
       st->start_time + st->duration < time ((time_t *) 0)) {
     XWindowAttributes xgwa;
     XGetWindowAttributes(st->dpy, st->window, &xgwa);
+    /* On MacOS X11, XGetImage on a Window often gets an inexplicable BadMatch,
+       possibly due to the window manager having occluded something?  It seems
+       nondeterministic. Loading the image into a pixmap instead fixes it. */
+    if (st->pm) XFreePixmap (st->dpy, st->pm);
+    st->pm = XCreatePixmap (st->dpy, st->window,
+                            xgwa.width, xgwa.height, xgwa.depth);
     st->img_loader = load_image_async_simple (0, xgwa.screen, st->window,
-                                              st->window, 0, 0);
+                                              st->pm, 0, 0);
     st->start_time = time ((time_t *) 0);
     return st->delay;
   }
@@ -415,8 +481,11 @@ setup_X (struct state *st)
   if (use_subwindow_mode_p (xgwa.screen, st->window))  /* see grabscreen.c */
     gcflags |= GCSubwindowMode;
   st->gc = XCreateGC (st->dpy, st->window, gcflags, &gcv);
+  if (st->pm) XFreePixmap (st->dpy, st->pm);
+  st->pm = XCreatePixmap (st->dpy, st->window,
+                          xgwa.width, xgwa.height, xgwa.depth);
   st->img_loader = load_image_async_simple (0, xgwa.screen, st->window,
-                                            st->window, 0, 0);
+                                            st->pm, 0, 0);
 
   st->buffer_map = 0;
 
@@ -444,7 +513,6 @@ static void *
 rotzoomer_init (Display *dpy, Window window)
 {
   struct state *st = (struct state *) calloc (1, sizeof(*st));
-  char *s;
   st->dpy = dpy;
   st->window = window;
 #ifdef HAVE_XSHM_EXTENSION
@@ -452,17 +520,7 @@ rotzoomer_init (Display *dpy, Window window)
 #endif
   st->num_zoom = get_integer_resource (st->dpy, "numboxes", "Integer");
 
-  s = get_string_resource (dpy, "mode", "Mode");
-  if (!s || !*s || !strcasecmp (s, "stationary"))
-    ;
-  else if (!strcasecmp (s, "move"))
-    st->move = True;
-  else if (!strcasecmp (s, "sweep"))
-    st->sweep = True;
-  else if (!strcasecmp (s, "circle"))
-    st->circle = True;
-  else
-    fprintf (stderr, "%s: bogus mode: \"%s\"\n", progname, s);
+  set_mode(st);
 
   st->anim = get_boolean_resource (st->dpy, "anim", "Boolean");
   st->delay = get_integer_resource (st->dpy, "delay", "Integer");
@@ -512,6 +570,7 @@ static void
 rotzoomer_free (Display *dpy, Window window, void *closure)
 {
   struct state *st = (struct state *) closure;
+  if (st->pm) XFreePixmap (dpy, st->pm);
   free (st);
 }
 
@@ -526,7 +585,7 @@ static const char *rotzoomer_defaults[] = {
   "*useSHM: False",
 #endif
   "*anim: True",
-  "*mode: stationary",
+  "*mode: random",
   "*numboxes: 2",
   "*delay: 10000",
   "*duration: 120",
index 8b4212de132ccb9c5c2332524564c8312e3858ce..3494684e4129b668f4ae8485e0f9e46b8ab46a8d 100644 (file)
@@ -83,7 +83,6 @@
 
 #ifdef HAVE_ANDROID
  /* So that hacks' debug output shows up in logcat... */
- extern void Log(const char *fmt, ...);  /* jwxyz-android.c */
 # define fprintf(S, ...) Log(__VA_ARGS__)
 #endif
 
index 4c434d0dff834a0308a57c3411fbeee3b3163585..7d52a411156bda8047298f13ba6ea15d3acf6514 100644 (file)
@@ -62,7 +62,6 @@ struct state {
   Screen *screen;                 /* the screen to draw on */
   XImage *sourceImage;            /* image source of stuff to draw */
   XImage *workImage;              /* work area image, used when rendering */
-  XImage *backgroundImage;      /* image filled with background pixels */
 
   GC backgroundGC;              /* GC for the background color */
   GC foregroundGC;              /* GC for the foreground color */
@@ -79,6 +78,7 @@ struct state {
 
   time_t start_time;
   async_load_state *img_loader;
+  Pixmap pm;
 
   Bool useShm;         /* whether or not to use xshm */
 #ifdef HAVE_XSHM_EXTENSION
@@ -107,26 +107,16 @@ struct state {
 static void
 grabImage_start (struct state *st, XWindowAttributes *xwa)
 {
-    Pixmap p;
-    GC gc;
-    XGCValues gcv;
-    XFillRectangle (st->dpy, st->window, st->backgroundGC, 0, 0, 
-                   st->windowWidth, st->windowHeight);
-
-    p = XCreatePixmap (st->dpy, st->window,
-                       xwa->width, xwa->height, xwa->depth);
-    gc = XCreateGC (st->dpy, st->window, 0, &gcv);
-    XCopyArea (st->dpy, st->window, p, gc, 0, 0,
-               xwa->width, xwa->height, 0, 0);
-    st->backgroundImage = 
-       XGetImage (st->dpy, p, 0, 0, st->windowWidth, st->windowHeight,
-                  ~0L, ZPixmap);
-    XFreeGC (st->dpy, gc);
-    XFreePixmap (st->dpy, p);
+    /* On MacOS X11, XGetImage on a Window often gets an inexplicable BadMatch,
+       possibly due to the window manager having occluded something?  It seems
+       nondeterministic. Loading the image into a pixmap instead fixes it. */
+    if (st->pm) XFreePixmap (st->dpy, st->pm);
+    st->pm = XCreatePixmap (st->dpy, st->window,
+                            xwa->width, xwa->height, xwa->depth);
 
     st->start_time = time ((time_t *) 0);
     st->img_loader = load_image_async_simple (0, xwa->screen, st->window,
-                                              st->window, 0, 0);
+                                              st->pm, 0, 0);
 }
 
 static void
@@ -137,7 +127,8 @@ grabImage_done (struct state *st)
 
     st->start_time = time ((time_t *) 0);
     if (st->sourceImage) XDestroyImage (st->sourceImage);
-    st->sourceImage = XGetImage (st->dpy, st->window, 0, 0, st->windowWidth, st->windowHeight,
+    st->sourceImage = XGetImage (st->dpy, st->pm, 0, 0,
+                                 st->windowWidth, st->windowHeight,
                             ~0L, ZPixmap);
 
     if (st->workImage) XDestroyImage (st->workImage);
@@ -535,7 +526,8 @@ static void renderFrame (struct state *st)
 {
     int n;
 
-    memcpy (st->workImage->data, st->backgroundImage->data, 
+    /* This assumes black is zero. */
+    memset (st->workImage->data, 0, 
            st->workImage->bytes_per_line * st->workImage->height);
 
     sortTiles (st);
@@ -663,6 +655,7 @@ static void
 twang_free (Display *dpy, Window window, void *closure)
 {
   struct state *st = (struct state *) closure;
+  if (st->pm) XFreePixmap (dpy, st->pm);
   free (st);
 }
 
index 06993cf59434aa883b6dde94b6cf6c7cde9b50a3..2864acba769576bc784b71506c98749447157beb 100644 (file)
@@ -91,7 +91,6 @@ distdepend::
              -e 's@ $$(srcdir)/\(.*config.h\)@ \1@g' ;                     \
          echo ''                                                           \
        ) > /tmp/distdepend.$$$$ &&                                         \
-       mv Makefile.in Makefile.in.bak &&                                   \
        mv /tmp/distdepend.$$$$ Makefile.in
 
 TAGS: tags
index 420cd564a3ab432cfc7adbc6f324622fe8d5246e..3c85d253b579b88e37da88abfa047fc820b36283 100644 (file)
@@ -70,9 +70,10 @@ static double current_rotation = 0;
 extern void check_gl_error (const char *type);
 
 void
-do_logv(int prio, const char *fmt, va_list args)
+jwxyz_logv(Bool error, const char *fmt, va_list args)
 {
-  __android_log_vprint(prio, "xscreensaver", fmt, args);
+  __android_log_vprint(error ? ANDROID_LOG_ERROR : ANDROID_LOG_INFO,
+                       "xscreensaver", fmt, args);
 
   /* The idea here is that if the device/emulator dies shortly after a log
      message, then waiting here for a short while should increase the odds
@@ -88,14 +89,6 @@ do_logv(int prio, const char *fmt, va_list args)
 # endif
 }
 
-void Log(const char *fmt, ...)
-{
-  va_list args;
-  va_start (args, fmt);
-  Logv(fmt, args);
-  va_end (args);
-}
-
 /* Handle an abort on Android
    TODO: Test that Android handles aborts properly
  */
@@ -108,7 +101,7 @@ jwxyz_abort (const char *fmt, ...)
 
   va_list args;
   va_start (args, fmt);
-  do_logv(ANDROID_LOG_ERROR, fmt, args);
+  jwxyz_logv(True, fmt, args);
   va_end (args);
 
   char buf[10240];
@@ -303,16 +296,36 @@ doinit (jobject jwxyz_obj, struct running_hack *rh, JNIEnv *env,
 
 #undef DEBUG_FPS
 
+#ifdef DEBUG_FPS
+
+static double
+double_time (void)
+{
+  struct timeval now;
+# ifdef GETTIMEOFDAY_TWO_ARGS
+  struct timezone tzp;
+  gettimeofday(&now, &tzp);
+# else
+  gettimeofday(&now);
+# endif
+
+  return (now.tv_sec + ((double) now.tv_usec * 0.000001));
+}
+
+#endif
+
 // Animates a single frame of the current hack.
 //
-static void
+static jlong
 drawXScreenSaver (JNIEnv *env, struct running_hack *rh)
 {
-  double now = 0;
 # ifdef DEBUG_FPS
   double fps0=0, fps1=0, fps2=0, fps3=0, fps4=0;
+  fps0 = fps1 = fps2 = fps3 = fps4 = double_time();
 # endif
 
+  unsigned long delay = 0;
+
   if (setjmp (jmp_target)) goto END;  // Jump here from jwxyz_abort and return.
 
   /* There is some kind of weird redisplay race condition between Settings
@@ -323,25 +336,10 @@ drawXScreenSaver (JNIEnv *env, struct running_hack *rh)
   if (++rh->frame_count < 8)
     goto END;
 
-  /* Some of the screen hacks want to delay for long periods, and letting
-     the framework run the update function at 30 FPS when it really wanted
-     half a minute between frames would be bad.  So instead, we assume that
-     the framework's animation timer might fire whenever, but we only invoke
-     the screen hack's "draw frame" method when enough time has expired.
-  */
-  struct timeval tv;
-  gettimeofday (&tv, 0);
-  now = tv.tv_sec + (tv.tv_usec / 1000000.0);
-# ifdef DEBUG_FPS
-  fps0 = fps1 = fps2 = fps3 = fps4 = now;
-#endif
-  if (now < rh->next_frame_time) goto END;
-
   prepare_context(rh);
 
 # ifdef DEBUG_FPS
-  gettimeofday (&tv, 0);
-  fps1 = tv.tv_sec + (tv.tv_usec / 1000000.0);
+  fps1 = double_time();
 # endif
 
   // The init function might do graphics (e.g. XClearWindow) so it has
@@ -376,8 +374,7 @@ drawXScreenSaver (JNIEnv *env, struct running_hack *rh)
   }
 
 # ifdef DEBUG_FPS
-  gettimeofday (&tv, 0);
-  fps2 = tv.tv_sec + (tv.tv_usec / 1000000.0);
+  fps2 = double_time();
 # endif
 
   // Apparently events don't come in on the drawing thread, and JNI flips
@@ -385,29 +382,17 @@ drawXScreenSaver (JNIEnv *env, struct running_hack *rh)
   send_queued_events (rh);
 
 # ifdef DEBUG_FPS
-  gettimeofday (&tv, 0);
-  fps3 = tv.tv_sec + (tv.tv_usec / 1000000.0);
-# endif
-
-  unsigned long delay = rh->xsft->draw_cb(rh->dpy, rh->window, rh->closure);
-
-# ifdef __arm__
-  /* #### Until we work out why eglMakeCurrent is so slow on ARM. */
-  if (delay <= 40000) delay = 0;
+  fps3 = double_time();
 # endif
 
+  delay = rh->xsft->draw_cb(rh->dpy, rh->window, rh->closure);
 
 # ifdef DEBUG_FPS
-  gettimeofday (&tv, 0);
-  fps4 = tv.tv_sec + (tv.tv_usec / 1000000.0);
+  fps4 = double_time();
 # endif
   if (rh->fpst && rh->xsft->fps_cb)
     rh->xsft->fps_cb (rh->dpy, rh->window, rh->fpst, rh->closure);
 
-  gettimeofday (&tv, 0);
-  now = tv.tv_sec + (tv.tv_usec / 1000000.0);
-  rh->next_frame_time = now + (delay / 1000000.0);
-
  END: ;
 
 # ifdef DEBUG_FPS
@@ -416,8 +401,10 @@ drawXScreenSaver (JNIEnv *env, struct running_hack *rh)
       (int) ((fps2-fps1)*1000000),
       (int) ((fps3-fps2)*1000000),
       (int) ((fps4-fps3)*1000000),
-      (int) ( (now-fps4)*1000000));
+      (int) ((double_time()-fps4)*1000000));
 # endif
+
+  return delay;
 }
 
 
@@ -503,7 +490,7 @@ Java_org_jwz_xscreensaver_jwxyz_nativeInit (JNIEnv *env, jobject thiz,
 
   int chosen = 0;
   for (;;) {
-    if (!chosen == countof(function_table)) {
+    if (chosen == countof(function_table)) {
       Log ("Hack not found: %s", hack);
       abort();
     }
@@ -566,13 +553,14 @@ Java_org_jwz_xscreensaver_jwxyz_nativeResize (JNIEnv *env, jobject thiz,
 }
 
 
-JNIEXPORT void JNICALL
+JNIEXPORT jlong JNICALL
 Java_org_jwz_xscreensaver_jwxyz_nativeRender (JNIEnv *env, jobject thiz)
 {
   pthread_mutex_lock(&mutg);
   struct running_hack *rh = getRunningHack(env, thiz);
-  drawXScreenSaver(env, rh);
+  jlong result = drawXScreenSaver(env, rh);
   pthread_mutex_unlock(&mutg);
+  return result;
 }
 
 
@@ -909,6 +897,21 @@ ignore_rotation_p (Display *dpy)
 }
 
 
+static char *
+jstring_dup (JNIEnv *env, jstring str)
+{
+  Assert (str, "expected jstring, not null");
+  const char *cstr = (*env)->GetStringUTFChars (env, str, 0);
+  size_t len = (*env)->GetStringUTFLength (env, str) + 1;
+  char *result = malloc (len);
+  if (result) {
+    memcpy (result, cstr, len);
+  }
+  (*env)->ReleaseStringUTFChars (env, str, cstr);
+  return result;
+}
+
+
 char *
 get_string_resource (Display *dpy, char *name, char *class)
 {
@@ -929,11 +932,8 @@ get_string_resource (Display *dpy, char *name, char *class)
   (*env)->DeleteLocalRef (env, c);
   (*env)->DeleteLocalRef (env, jstr);
   char *ret = 0;
-  if (jvalue) {
-    const char *cvalue = (*env)->GetStringUTFChars (env, jvalue, 0);
-    ret = strdup (cvalue);
-    (*env)->ReleaseStringUTFChars (env, jvalue, cvalue);
-  }
+  if (jvalue)
+    ret = jstring_dup (env, jvalue);
 
   Log("pref %s = %s", name, (ret ? ret : "(null)"));
   return ret;
@@ -1007,13 +1007,9 @@ jwxyz_load_native_font (Display *dpy, const char *name,
     jobject desc = (*env)->GetObjectArrayElement (env, array, 4);
     if ((*env)->ExceptionOccurred(env)) abort();
 
-    const char *cname = (*env)->GetStringUTFChars (env, name, 0);
-    *native_name_ret = strdup (cname);
-    (*env)->ReleaseStringUTFChars (env, name, cname);
+    *native_name_ret = jstring_dup (env, name);
 
-    c = (*env)->GetObjectClass(env, font);
-    m = (*env)->GetMethodID (env, c, "longValue", "()J");
-    long font_id = (*env)->CallLongMethod (env, font, m);
+    jobject paint = (*env)->NewGlobalRef (env, font);
     if ((*env)->ExceptionOccurred(env)) abort();
 
     c = (*env)->GetObjectClass(env, size);
@@ -1024,7 +1020,7 @@ jwxyz_load_native_font (Display *dpy, const char *name,
     *ascent_ret  = (int) (*env)->CallFloatMethod (env, asc,  m);
     *descent_ret = (int) (*env)->CallFloatMethod (env, desc, m);
 
-    return (void *) font_id;
+    return (void *) paint;
   } else {
     return 0;
   }
@@ -1036,11 +1032,8 @@ jwxyz_release_native_font (Display *dpy, void *native_font)
 {
   Window window = RootWindow (dpy, 0);
   JNIEnv *env = window->window.rh->jni_env;
-  jobject obj = window->window.rh->jobject;
   if ((*env)->ExceptionOccurred(env)) abort();
-  jclass    c = (*env)->GetObjectClass (env, obj);
-  jmethodID m = (*env)->GetMethodID (env, c, "releaseFont", "(J)V");
-  (*env)->CallVoidMethod (env, obj, m, (jobject) native_font);
+  (*env)->DeleteGlobalRef (env, (jobject) native_font);
   if ((*env)->ExceptionOccurred(env)) abort();
 }
 
@@ -1096,12 +1089,12 @@ jwxyz_render_text (Display *dpy, void *native_font,
   jstring jstr  = (*env)->NewStringUTF (env, s2);
   jclass      c = (*env)->GetObjectClass (env, obj);
   jmethodID   m = (*env)->GetMethodID (env, c, "renderText",
-                            "(JLjava/lang/String;Z)Ljava/nio/ByteBuffer;");
+    "(Landroid/graphics/Paint;Ljava/lang/String;Z)Ljava/nio/ByteBuffer;");
   if ((*env)->ExceptionOccurred(env)) abort();
   jobject buf =
     (m
      ? (*env)->CallObjectMethod (env, obj, m,
-                                 (jlong) (long) native_font,
+                                 (jobject) native_font,
                                  jstr,
                                  (pixmap_ret ? JNI_TRUE : JNI_FALSE))
      : NULL);
@@ -1139,6 +1132,44 @@ jwxyz_render_text (Display *dpy, void *native_font,
 }
 
 
+char *
+jwxyz_unicode_character_name (Display *dpy, Font fid, unsigned long uc)
+{
+  JNIEnv *env = XRootWindow (dpy, 0)->window.rh->jni_env;
+  /* FindClass doesn't like to load classes if GetStaticMethodID fails. Huh? */
+  jclass
+    c = (*env)->FindClass (env, "java/lang/Character"),
+    c2 = (*env)->FindClass (env, "java/lang/NoSuchMethodError");
+
+  if ((*env)->ExceptionOccurred(env)) abort();
+  jmethodID m = (*env)->GetStaticMethodID (
+    env, c, "getName", "(I)Ljava/lang/String;");
+  jthrowable exc = (*env)->ExceptionOccurred(env);
+  if (exc) {
+    if ((*env)->IsAssignableFrom(env, (*env)->GetObjectClass(env, exc), c2)) {
+      (*env)->ExceptionClear (env);
+      Assert (!m, "jwxyz_unicode_character_name: m?");
+    } else {
+      abort();
+    }
+  }
+
+  char *ret = NULL;
+
+  if (m) {
+    jstring name = (*env)->CallStaticObjectMethod (env, c, m, (jint)uc);
+    if (name)
+     ret = jstring_dup (env, name);
+  }
+
+  if (!ret) {
+    asprintf(&ret, "U+%.4lX", uc);
+  }
+
+  return ret;
+}
+
+
 /* Called from utils/grabclient.c */
 char *
 jwxyz_load_random_image (Display *dpy,
index 949531f41cabe5e37d899c1c528d99924d3d8284..493f456a5c55ef5213a5e1aec1af4fdc68e151a4 100644 (file)
@@ -41,7 +41,6 @@ struct running_hack {
 
   unsigned long frame_count;
   Bool initted_p;
-  double next_frame_time;  // time_t in milliseconds of when to tick the frame
   struct event_queue *event_queue;
 };
 
@@ -60,10 +59,6 @@ struct jwxyz_Drawable {
   };
 };
 
-extern void do_logv(int prio, const char *fmt, va_list args);
-
-extern void Log(const char *format, ...); // TODO: GCC can verify printf strings.
-#define Logv(format, args) (do_logv(ANDROID_LOG_INFO, format, args))
 
 extern void prepare_context (struct running_hack *rh);
 
@@ -80,7 +75,7 @@ JNIEXPORT void JNICALL
 Java_org_jwz_xscreensaver_jwxyz_nativeResize (JNIEnv *, jobject thiz,
                                               jint w, jint h, jdouble rot);
 
-JNIEXPORT void JNICALL
+JNIEXPORT jlong JNICALL
 Java_org_jwz_xscreensaver_jwxyz_nativeRender (JNIEnv *, jobject thiz);
 
 JNIEXPORT void JNICALL
index 3b6bf4119f03ebfe297c7353d1e6e2bb360839a8..10da646f92a81e3b0b0856480b8a1a2b8c338242 100644 (file)
 
 /* OS X/iOS-specific JWXYZ implementation. */
 
+void
+jwxyz_logv (Bool error, const char *fmt, va_list args)
+{
+  vfprintf (stderr, fmt, args);
+  fputc ('\n', stderr);
+}
+
 /* Instead of calling abort(), throw a real exception, so that
    XScreenSaverView can catch it and display a dialog.
  */
index a168bda299a258883cd246752459ef9b9cdbdfcc..a40909948eda0067f5e912e572c02bec929eab0f 100644 (file)
 #define assert_window(dpy, w) \
   Assert (w == RootWindow (dpy, 0), "not a window")
 
+
+void
+Log (const char *fmt, ...)
+{
+  va_list args;
+  va_start (args, fmt);
+  Logv (fmt, args);
+  va_end (args);
+}
+
+
 int
 XDisplayWidth (Display *dpy, int screen)
 {
index 66944ed25a61aa870c1661d80c09ed395f8b67f2..2f15b1aa0199e050c6bce59b17d177561cc3ed5d 100644 (file)
 # include <CoreGraphics/CGGeometry.h>
 #else
 
-
-#ifdef HAVE_ANDROID
- extern void Log(const char *fmt, ...);
-#else
-static void
-Log (const char *fmt, ...)
-{
-  va_list args;
-  va_start (args, fmt);
-  vfprintf (stderr, fmt, args);
-  va_end (args);
-}
-#endif
-
 struct CGPoint {
     float x;
     float y;
@@ -1778,13 +1764,16 @@ XPutImage (Display *dpy, Drawable d, GC gc, XImage *ximage,
     glVertexPointer (2, GL_FLOAT, 0, vertices);
     glTexCoordPointer (2, GL_FLOAT, 0, tex_coords);
 
-    // Respect the alpha channel in the XImage
-    glEnable (GL_BLEND);
-    glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+    // Respect the alpha channel in the XImage if we're using alpha.
+    if (gc->gcv.alpha_allowed_p) {
+      glEnable (GL_BLEND);
+      glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+    }
 
     glDrawArrays (GL_TRIANGLE_FAN, 0, 4);
 
-    glDisable (GL_BLEND);
+    if (gc->gcv.alpha_allowed_p)
+      glDisable (GL_BLEND);
 
 //  clear_texture();
     glDisable (dpy->gl_texture_target);
@@ -2798,35 +2787,6 @@ XFreeStringList (char **list)
 }
 
 
-// Returns the verbose Unicode name of this character, like "agrave" or
-// "daggerdouble".  Used by fontglide debugMetrics.
-//
-char *
-jwxyz_unicode_character_name (Font fid, unsigned long uc)
-{
-  /* TODO Fonts
-  char *ret = 0;
-  CTFontRef ctfont =
-    CTFontCreateWithName ((CFStringRef) [fid->nsfont fontName],
-                          [fid->nsfont pointSize],
-                          NULL);
-  Assert (ctfont, @"no CTFontRef for UIFont");
-
-  CGGlyph cgglyph;
-  if (CTFontGetGlyphsForCharacters (ctfont, (UniChar *) &uc, &cgglyph, 1)) {
-    NSString *name = (NSString *)
-      CGFontCopyGlyphNameForGlyph (CTFontCopyGraphicsFont (ctfont, 0),
-                                   cgglyph);
-    ret = (name ? strdup ([name UTF8String]) : 0);
-  }
-
-  CFRelease (ctfont);
-  return ret;
-   */
-  return NULL;
-}
-
-
 // Given a UTF8 string, return an NSString.  Bogus UTF8 characters are ignored.
 // We have to do this because stringWithCString returns NULL if there are
 // any invalid characters at all.
index 335df69100b0c788a776e6336930a61a1b089201..6b87102652ca440097bc667f4e2ce93faffd0e3c 100644 (file)
@@ -20,6 +20,7 @@
 #define __JWXYZ_H__
 
 #include <stdlib.h> /* For abort(). */
+#include <stdarg.h>
 
 #if defined __FreeBSD__ || defined __MACH__ && defined __APPLE__
 # include <sys/cdefs.h>
@@ -460,7 +461,7 @@ extern int XUnloadFont (Display *, Font);
 extern int XTextExtents (XFontStruct *, const char *, int length,
                          int *dir_ret, int *ascent_ret, int *descent_ret,
                          XCharStruct *overall_ret);
-extern char * jwxyz_unicode_character_name (Font, unsigned long uc);
+extern char * jwxyz_unicode_character_name (Display *, Font, unsigned long uc);
 extern int XTextExtents16 (XFontStruct *, const XChar2b *, int length,
                            int *dir_ret, int *ascent_ret, int *descent_ret,
                            XCharStruct *overall_ret);
@@ -487,6 +488,17 @@ extern int XFreePixmap (Display *, Pixmap);
 
 extern char *XGetAtomName (Display *, Atom);
 
+// Log()/Logv(), for debugging JWXYZ. Screenhacks should still use
+// fprintf(stderr, ...).
+extern void Log(const char *format, ...)
+#if defined __GNUC__ || defined __clang__
+  __attribute__((format(printf, 1, 2)))
+#endif
+  ;
+
+extern void jwxyz_logv(Bool error, const char *fmt, va_list args);
+#define Logv(format, args) (jwxyz_logv(False, format, args))
+
 // Xt timers and fds
 extern XtAppContext XtDisplayToApplicationContext (Display *);
 typedef void (*XtTimerCallbackProc) (XtPointer closure, XtIntervalId *);
index bb189b0270e1c55f1e9cd48b1f4a7ce23f18abf2..23526cfc77a8ab12121d2dce0da2340b19200d64 100644 (file)
@@ -1941,7 +1941,7 @@ XQueryFont (Display *dpy, Font fid)
   Assert (sizeof (f->properties[0].card32) >= sizeof (char *),
           "atoms probably needs a real implementation");
   // If XInternAtom is ever implemented, use it here.
-  f->properties[0].card32 = (char *)fid->xa_font;
+  f->properties[0].card32 = (unsigned long)fid->xa_font;
 
   // copy XCharStruct array
   int size = (f->max_char_or_byte2 - f->min_char_or_byte2) + 1;
@@ -2255,7 +2255,7 @@ try_xlfd_font (Display *dpy, const char *name, float scale,
    // Default mask is for the built-in X11 font aliases.
    mask = NSFixedPitchFontMask | NSBoldFontMask | NSItalicFontMask;
   BOOL rand  = NO;
-  float size = 0;
+  float size = 12; /* In points (1/72 in.) */
   char *ps_name = 0;
 
   const char *s = (name ? name : "");
@@ -2312,24 +2312,45 @@ try_xlfd_font (Display *dpy, const char *name, float scale,
     xlfd_next (&s, &s2); // Set width name (ignore)
     xlfd_next (&s, &s2); // Add style name (ignore)
 
-    xlfd_next (&s, &s2); // Pixel size (ignore)
-
-    xlfd_next (&s, &s2); // Point size
+    L = xlfd_next (&s, &s2); // Pixel size (ignore)
     char *s3;
-    uintmax_t n = strtoumax(s, &s3, 10);
-    if (s2 == s3)
-      size = n / 10.0;
+    uintmax_t pxsize = strtoumax(s, &s3, 10);
+    if (UNSPEC || s2 != s3)
+      pxsize = UINTMAX_MAX; // i.e. it's invalid.
+
+    L = xlfd_next (&s, &s2); // Point size
+    uintmax_t ptsize = strtoumax(s, &s3, 10);
+    if (UNSPEC || s2 != s3)
+      ptsize = UINTMAX_MAX;
 
     xlfd_next (&s, &s2); // Resolution X (ignore)
     xlfd_next (&s, &s2); // Resolution Y (ignore)
 
-    xlfd_next (&s, &s2); // Spacing
+    L = xlfd_next (&s, &s2); // Spacing
     if (CMP ("p"))
       forbid |= NSFixedPitchFontMask;
     else if (CMP ("m") || CMP ("c"))
       require |= NSFixedPitchFontMask;
 
-    // Don't care about average_width or charset registry.
+    xlfd_next (&s, &s2); // Average width (ignore)
+
+    // -*-courier-bold-r-*-*-14-*-*-*-*-*-*-*         14 px
+    // -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*        14 pt
+    // -*-courier-bold-r-*-*-140-*                    14 pt, via wildcard
+    // -*-courier-bold-r-*-140-*                      14 pt, not handled
+    // -*-courier-bold-r-*-*-14-180-*-*-*-*-*-*       error
+
+    L = xlfd_next (&s, &s2); // Charset registry
+    if (ptsize != UINTMAX_MAX) {
+      // It was in the ptsize field, so that's definitely what it is.
+      size = ptsize / 10.0;
+    } else if (pxsize != UINTMAX_MAX) {
+      size = pxsize;
+      // If it's a fully qualified XLFD, then this really is the pxsize.
+      // Otherwise, this is probably point size with a multi-field wildcard.
+      if (L == 0)
+        size /= 10.0;
+    }
 
     mask = require | forbid;
   }
@@ -2523,7 +2544,7 @@ XCreateFontSet (Display *dpy, char *name,
                 char **def_string_return)
 {
   char *name2 = strdup (name);
-  char *s = strchr (name, ",");
+  char *s = strchr (name, ',');
   if (s) *s = 0;
   XFontSet set = 0;
   XFontStruct *f = XLoadQueryFont (dpy, name2);
@@ -2571,7 +2592,7 @@ XFreeStringList (char **list)
 // "daggerdouble".  Used by fontglide debugMetrics.
 //
 char *
-jwxyz_unicode_character_name (Font fid, unsigned long uc)
+jwxyz_unicode_character_name (Display *dpy, Font fid, unsigned long uc)
 {
   char *ret = 0;
   CTFontRef ctfont =
index 042d6a4d92a351ece23aa1dbfc8f44fd6f2f497d..912a4be31c770f237037c07ef6cc85dcfc95f89c 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 2012-2015 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 2012-2016 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
@@ -3339,8 +3339,8 @@ jwzgles_gluBuild2DMipmaps (GLenum target,
               *o++ = (istride == 4 ? *i : 0xFF); /* A */
             }
         }
-      // width  = w2;
-      // height = h2;
+      /* width  = w2; */
+      /* height = h2; */
       internalFormat = GL_RGBA;
       format = GL_RGBA;
     }
index cb8b2f7a48e410ce0e991ab998c7bfc0f27f7ade..c830df766a333add07816358da322d2dddaa487c 100644 (file)
@@ -1,4 +1,4 @@
-# Auto-generated: Tue May 24 11:02:33 PDT 2016
+# Auto-generated: Mon Oct 10 19:58:09 PDT 2016
 driver/demo-Gtk-conf.c
 driver/demo-Gtk.c
 driver/screensaver-properties.desktop.in
@@ -46,7 +46,9 @@ hacks/config/critical.xml
 hacks/config/crystal.xml
 hacks/config/cube21.xml
 hacks/config/cubenetic.xml
+hacks/config/cubestack.xml
 hacks/config/cubestorm.xml
+hacks/config/cubetwist.xml
 hacks/config/cubicgrid.xml
 hacks/config/cwaves.xml
 hacks/config/cynosure.xml
@@ -55,6 +57,7 @@ hacks/config/decayscreen.xml
 hacks/config/deco.xml
 hacks/config/deluxe.xml
 hacks/config/demon.xml
+hacks/config/discoball.xml
 hacks/config/discrete.xml
 hacks/config/distort.xml
 hacks/config/dnalogo.xml
@@ -106,6 +109,7 @@ hacks/config/halftone.xml
 hacks/config/halo.xml
 hacks/config/helix.xml
 hacks/config/hexadrop.xml
+hacks/config/hexstrut.xml
 hacks/config/hilbert.xml
 hacks/config/hopalong.xml
 hacks/config/hydrostat.xml
@@ -201,6 +205,7 @@ hacks/config/sphere.xml
 hacks/config/spheremonics.xml
 hacks/config/spiral.xml
 hacks/config/splitflap.xml
+hacks/config/splodesic.xml
 hacks/config/spotlight.xml
 hacks/config/sproingies.xml
 hacks/config/squiral.xml
index ea5f114470442dddc9ba1358a3ab2b8b93b12187..e4fc6ebc3691e24812e889a494e55e7962e8a106 100644 (file)
@@ -177,7 +177,6 @@ distdepend::
              -e 's@ $$(srcdir)/\(.*config.h\)@ \1@g' ;                     \
          echo ''                                                           \
        ) > /tmp/distdepend.$$$$ &&                                         \
-       mv Makefile.in Makefile.in.bak &&                                   \
        mv /tmp/distdepend.$$$$ Makefile.in
 
 TAGS: tags
index 6eec38430d320b26e5b6ea7618d4beed788de9b5..a1a360e476d8dbc23dc5b866250a325da96cc7fb 100644 (file)
@@ -44,7 +44,7 @@
 
        load_image_async CB
            load_random_image_cocoa
-               osx_grab_desktop_image (osxgrabscreen.m, MacOS version)
+               osx_grab_desktop_image (grabclient-osx.m, MacOS version)
                    copy_framebuffer_to_ximage
                    XPutImage
                draw_colorbars
@@ -62,7 +62,7 @@
 
        load_image_async CB
            load_random_image_cocoa
-               osx_grab_desktop_image (osxgrabscreen.m, iOS version)
+               osx_grab_desktop_image (grabclient-osx.m, iOS version)
                    CGWindowListCreateImage
                    jwxyz_draw_NSImage_or_CGImage
                draw_colorbars
@@ -702,7 +702,7 @@ xscreensaver_getimage_file_cb (XtPointer closure, int *source, XtInputId *id)
 # else   /* HAVE_COCOA && USE_IPHONE -- iOS */
 
 /* Callback for ios_load_random_image(), called after we have loaded an
-   image from the iOS device's Photo Library.  See iosgrabimage.m.
+   image from the iOS device's Photo Library.  See grabclient-ios.m.
  */
 static void
 ios_load_random_image_cb (void *uiimage, const char *filename, 
index 23f40aad9b98122db39454075c5eafffd79c4106..77fe3c96bd4c5d5130bc8e337aa6a88e31136b12 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1992-2013 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1992-2016 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
    The hacks themselves use utils/grabclient.c to invoke the
    "xscreensaver-getimage" program as a sub-process.
 
-   This code is linked only into "driver/xscreensaver-getimage".  On normal
-   X11 systems, "xscreensaver-getimage.c" invokes the code in this file.
+   On "real" X11 systems:
 
-   However, under X11 on MacOS, "xscreensaver-getimage" instead runs the
-   script "driver/xscreensaver-getimage-desktop", which invokes the MacOS-
-   specific program "/usr/sbin/screencapture" to get the desktop image.
+       "driver/xscreensaver-getimage" runs the code in this file to grab
+       the X11 root window image as a Pixmap.
 
-   However again, for the MacOS-native (Cocoa) build of the screen savers,
-   "utils/grabclient.c" instead links against "OSX/osxgrabscreen.m", which
-   grabs screen images directly without invoking a sub-process to do it.
+   On MacOS systems running X11, which nobody does any more:
+
+       "driver/xscreensaver-getimage" runs the Perl script
+       "driver/xscreensaver-getimage-desktop", which in turn runs the MacOS
+       program "/usr/sbin/screencapture" to get the Mac desktop image as a
+       PNG file.
+
+   On MacOS systems running the native Cocoa build, or on iOS or Android
+   systems:
+
+       "driver/xscreensaver-getimage" is not used.  Instead, each saver's
+       "utils/grabclient.c" links against "OSX/grabclient-osx.m",
+       "OSX/grabclient-ios.m" or "jwxyz/jwxyz-android.c" to grab
+       screenshots directly without invoking a sub-process to do it.
+
+   See the comment at the top of utils/grabclient.c for a more detailed
+   explanation.
  */
 
 #include "utils.h"
index 9aef5dff26af0a195b1df4c0466da214a518041a..c321487ed170bf6660632e81986edb342d09c746 100644 (file)
@@ -304,7 +304,7 @@ decode_entities (const char *html)
    in UTF8 encoding.  HTML tags are stripped, <BR> and <P> are converted
    to newlines, and some basic HTML entities are decoded.
  */
-char *
+static char *
 textclient_strip_html (const char *html)
 {
   int tag = 0;
@@ -549,7 +549,7 @@ strip_wiki (char *text)
    in UTF8 encoding.  Rougly, it uses the contents of the <description> field
    of each <item>, and decodes HTML within it.
  */
-char *
+static char *
 textclient_strip_rss (const char *rss)
 {
   char *ret = malloc (strlen(rss) * 4 + 1);  // room for UTF8
index f0d7fe898d65f82877ad862db9aeba4b7c4c0d2d..fe409287db6fbc0d015087505e9150b1937fa312 100644 (file)
@@ -104,6 +104,19 @@ subproc_cb (XtPointer closure, int *source, XtInputId *id)
       (c >= '0' && c <= '9') || \
       c == '.' || c == '_' || c == '-' || c == '+' || c == '/'))
 
+#ifdef HAVE_COCOA
+static char *
+escape_str (char *s, const char *src)
+{
+  while (*src) {
+    char c = *src++;
+    if (BACKSLASH(c)) *s++ = '\\';
+    *s++ = c;
+  }
+  return s;
+}
+#endif
+
 static void
 launch_text_generator (text_data *d)
 {
@@ -112,17 +125,17 @@ launch_text_generator (text_data *d)
   const char *oprogram = d->program;
   char *s;
 
+  size_t oprogram_size = strlen(oprogram);
+  size_t len;
+
 # ifdef HAVE_COCOA
   /* /bin/sh on OS X 10.10 wipes out the PATH. */
   const char *path = getenv("PATH");
-  char *cmd = s = malloc ((strlen(oprogram) + strlen(path)) * 2 + 100);
+  size_t cmd_capacity = (oprogram_size + strlen(path)) * 2 + 100;
+  char *cmd = s = malloc (cmd_capacity);
   strcpy (s, "export PATH=");
   s += strlen (s);
-  while (*path) {
-    char c = *path++;
-    if (BACKSLASH(c)) *s++ = '\\';
-    *s++ = c;
-  }
+  s = escape_str (s, path);
   strcpy (s, "; ");
   s += strlen (s);
 # else
@@ -139,20 +152,82 @@ launch_text_generator (text_data *d)
      "xscreensaver-text --cols %d", but that makes things blow up
      if someone ever uses a --program that includes a % anywhere.
    */
-  if (!strcmp (oprogram, "xscreensaver-text"))
+  len = 17; /* strlen("xscreensaver-text") */
+  if (oprogram_size >= len &&
+    !memcmp (oprogram, "xscreensaver-text", len) &&
+    (oprogram[len] == ' ' || !oprogram[len]))
     {
-      if (d->char_w)
+      /* strstr is sloppy here. Technically, we should be parsing the command
+         line to identify flags and their arguments. This will blow up if one
+         of those pesky end users could set .textLiteral to "--cols".
+       */
+      if (d->char_w && !strstr (oprogram, "--cols "))
         sprintf (s, " --cols %d", d->char_w);
-      if (d->max_lines)
+      if (d->max_lines && !strstr (oprogram, "--lines "))
         sprintf (s, " --lines %d", d->max_lines);
       s += strlen(s);
+
+# ifdef HAVE_COCOA
+      /* Also special-case "xscreensaver-text" to specify the text content on
+         the command line. defaults(1) on macOS doesn't know about the default
+         screenhack resources that don't make it into the
+         ~/Library/Preferences/ByHost/org.jwz.xscreensaver.*.plist.
+       */
+
+      char *text_mode_flag = " --date";
+      char *value_res = NULL;
+      char *text_mode = get_string_resource (d->dpy, "textMode", "String");
+
+      if (text_mode)
+        {
+          if (!strcmp (text_mode, "1") || !strcmp (text_mode, "literal"))
+            {
+              text_mode_flag = " --text";
+              value_res = "textLiteral";
+            }
+          else if (!strcmp (text_mode, "2") || !strcmp (text_mode, "file"))
+            {
+              text_mode_flag = " --file";
+              value_res = "textFile";
+            }
+          else if (!strcmp (text_mode, "3") || !strcmp (text_mode, "url"))
+            {
+              text_mode_flag = " --url";
+              value_res = "textURL";
+            }
+          else if (!strcmp (text_mode, "4") || !strcmp (text_mode, "program"))
+            {
+              text_mode_flag = " --program";
+              value_res = "textProgram";
+            }
+
+          free (text_mode);
+        }
+
+      strcpy (s, text_mode_flag);
+      s += strlen (s);
+
+      if (value_res)
+        {
+          size_t old_s = s - cmd;
+          char *value = get_string_resource (d->dpy, value_res, "");
+          if (!value)
+            value = strdup("");
+          cmd = realloc(cmd, cmd_capacity + strlen(value) * 2);
+          s = cmd + old_s;
+          *s = ' ';
+          ++s;
+          s = escape_str(s, value);
+          free(value);
+        }
+# endif /* HAVE_COCOA */
     }
 
   strcpy (s, " ) 2>&1");
 
 # ifdef DEBUG
-  fprintf (stderr, "%s: textclient: launch %s: %s\n", cmd
-           (d->pty_p ? "pty" : "pipe"), program);
+  fprintf (stderr, "%s: textclient: launch %s: %s\n", progname
+           (d->pty_p ? "pty" : "pipe"), cmd);
 # endif
 
 #ifdef HAVE_FORKPTY
@@ -167,6 +242,15 @@ launch_text_generator (text_data *d)
       ws.ws_ypixel = d->pix_h;
       
       d->pipe = 0;
+
+# ifdef HAVE_COCOA
+      if (getenv ("MallocScribble"))
+        /* This is here to stop me from wasting my time trying to answer
+           this question the next time I forget about it. */
+        fprintf (stderr, "%s: WARNING: forkpty hates 'Enable Guard Malloc'\n",
+                 progname);
+# endif
+
       if ((d->pid = forkpty(&fd, NULL, NULL, &ws)) < 0)
        {
           /* Unable to fork */
@@ -184,6 +268,15 @@ launch_text_generator (text_data *d)
           av[i++] = "-c";
           av[i++] = cmd;
           av[i] = 0;
+# ifdef DEBUG
+          {
+            int j;
+            fprintf (stderr, "%s: textclient: execvp:", progname);
+            for (j = 0; j < i; j++)
+              fprintf (stderr, " %s", av[j]);
+            fprintf (stderr, "\n");
+          }
+# endif
           execvp (av[0], av);
           sprintf (buf, "%.100s: %.100s", progname, oprogram);
          perror (buf);
@@ -327,6 +420,9 @@ textclient_reshape (text_data *d,
       ws.ws_ypixel = pix_h;
       ioctl (fileno (d->pipe), TIOCSWINSZ, &ws);
       kill (d->pid, SIGWINCH);
+#  ifdef DEBUG
+      fprintf (stderr, "%s: textclient: SIGWINCH\n", progname);
+#  endif
     }
 # endif /* HAVE_FORKPTY && TIOCSWINSZ */
 
@@ -337,6 +433,9 @@ textclient_reshape (text_data *d,
    */
   if (!strcmp (d->program, "xscreensaver-text"))
     {
+# ifdef DEBUG
+      fprintf (stderr, "%s: textclient: reshape relaunch\n", progname);
+# endif
       close_pipe (d);
       d->input_available_p = False;
       start_timer (d);
@@ -387,6 +486,10 @@ textclient_open (Display *dpy)
       {
         d->pty_p = 1;
         d->program = strdup (getenv ("SHELL"));
+#  ifdef DEBUG
+        fprintf (stderr, "%s: textclient: standalone: %s\n",
+                 progname, d->program);
+#  endif
       }
   }
 # endif
index 0d9aca3b88436c761758078690b4c356d9d110b1..0fe582dc0c3251945f4d2e7aa1a0ed90dcdd4ed9 100644 (file)
@@ -32,8 +32,6 @@ extern Bool textclient_putc (text_data *, XKeyEvent *);
 # if defined(USE_IPHONE) || defined(HAVE_ANDROID)
 extern char *textclient_mobile_date_string (void);
 extern char *textclient_mobile_url_string (Display *, const char *url);
-extern char *textclient_strip_html (const char *);
-extern char *textclient_strip_rss (const char *);
 # endif
 
 #endif /* __TEXTCLIENT_H__ */
index eeea0dc654436fd52732d1164ac9b63f12a44f84..27de26589f30e6bcbd30c1701ce3047f968a3d66 100644 (file)
@@ -1,2 +1,2 @@
 static const char screensaver_id[] =
-       "@(#)xscreensaver 5.35 (24-May-2016), by Jamie Zawinski (jwz@jwz.org)";
+       "@(#)xscreensaver 5.36 (10-Oct-2016), by Jamie Zawinski (jwz@jwz.org)";
index 6ea9687584e66d54122ab40729be96cab0830780..243875458fdebd8631b494d2ecbddf31ca05101e 100644 (file)
@@ -1,5 +1,5 @@
 %define        name xscreensaver
-%define        version 5.35
+%define        version 5.36
 
 Summary:       X screen saver and locker
 Name:          %{name}