From: Zygo Blaxell Date: Sun, 16 Nov 2014 06:50:59 +0000 (-0500) Subject: From http://www.jwz.org/xscreensaver/xscreensaver-5.31.tar.gz X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?p=xscreensaver;a=commitdiff_plain;h=d5186197bc394e10a4402f7f6d23fbb14103bc50 From jwz.org/xscreensaver/xscreensaver-5.31.tar.gz -rw-r--r-- 1 zblaxell zblaxell 10569562 Nov 15 18:51 xscreensaver-5.31.tar.gz 1b023a3b01f1f23aa136d13c37f79c0c01c3f1e6 xscreensaver-5.31.tar.gz --- diff --git a/Makefile.in b/Makefile.in index 1d29b54b..4be400df 100644 --- a/Makefile.in +++ b/Makefile.in @@ -7,8 +7,7 @@ VPATH = @srcdir@ SHELL = /bin/sh SUBDIRS = utils driver hacks hacks/glx po -#SUBDIRS = utils driver hacks hacks/glx -SUBDIRS2 = $(SUBDIRS) OSX +SUBDIRS2 = $(SUBDIRS) OSX android TARFILES = README README.hacking README.VMS INSTALL \ configure configure.in Makefile.in config.h.in \ config.h-vms install-sh setup.com config.guess aclocal.m4 \ @@ -326,10 +325,10 @@ www:: fi ; \ fi ; \ \ - git commit -a -m "$$VERS" . ; \ - git tag -a "v$$VERS" -m "$$VERS" . ; \ + git tag -a "v$$VERS" -m "$$VERS" ; \ + git commit -m "$$VERS" . ; \ \ - ( cd $$DEST ; git pull . ) ; \ + ( cd $$DEST ; git pull ) ; \ \ cp -p $$NAME $$DNAME ; \ cp -p $$NAME2 $$DNAME2 ; \ @@ -372,8 +371,8 @@ www:: exit 1 ; \ fi ; \ \ - git commit -m "$$VERS" . ; \ git tag -a "v$$VERS" -m "$$VERS" ; \ + git commit -m "$$VERS" . ; \ git push ; \ diff --git a/OSX/Makefile b/OSX/Makefile index 54670234..bfbf61f2 100644 --- a/OSX/Makefile +++ b/OSX/Makefile @@ -259,13 +259,13 @@ dmg:: for r in $$retired ; do \ if [ "$$ff" = "$$r" ]; then ok=no ; fi ; \ done ; \ - DSTNAME="" ; \ if [ "$$f2" = "XScreenSaverUpdater.app" ]; then \ - DSTNAME=".$$f2" ; \ - fi ; \ - if [ "$$ok" = yes ]; then \ - echo + cp -pR "$$f" "$$DST/$$DSTNAME" ; \ - cp -pR "$$f" "$$DST/$$DSTNAME" ; \ + DST_HACK="XScreenSaver.updater" ; \ + echo + tar ... "$$DST/$$DST_HACK" ; \ + ( cd $$SRC ; tar -czf - "$$f2" ) > "$$DST/$$DST_HACK" ; \ + elif [ "$$ok" = yes ]; then \ + echo + cp -pR "$$f" "$$DST/" ; \ + cp -pR "$$f" "$$DST/" ; \ else \ echo skipping "$$f" ; \ fi ; \ diff --git a/OSX/README b/OSX/README index d1eb2259..6a158c75 100644 --- a/OSX/README +++ b/OSX/README @@ -6,9 +6,9 @@ To build it, just type "make", or use the included XCode project. The executables will show up in the "build/Release/" and/or "build/Debug/" directories. -To build these programs, XCode 2.4 or later is required. -To run them, MacOS 10.4.0 or later is required. - +If you build using anything later than Xcode 5.0.2, the resultant savers +will require MacOS 10.7 or later. To support 10.4 through 10.6, you must +use Xcode 5.0.2 or earlier. This is how you add a new screen saver to the Xcode project. It's a ridiculously long list of steps! @@ -32,9 +32,8 @@ ridiculously long list of steps! 16: Put a 200x150 screen shot in ~/www/xscreensaver/screenshots/ 17: ln -s ../../src/xscreensaver/OSX/build/Debug/NEW.saver \ ~/Library/Screen\ Savers/ - 18: Build "XScreenSaver-iOS" once. then: - cd ~/src/xscreensaver/OSX ; make ios-function-table.m - and build it again. - 19: git add xscreensaver.xcodeproj/xcuserdata/*/xcschemes/*.xcscheme - 20: Don't forget to create a man page from the XML with xml2man.pl, + 18: git add xscreensaver.xcodeproj/xcuserdata/*/xcschemes/*.xcscheme + 19: Don't forget to create a man page from the XML with xml2man.pl, and update Makefile.in. + 20: Make a video: -record-animation 3600 -delay 1 -geom 1920x1080+128+64 + ./upload-video.pl NAME diff --git a/OSX/SaverListController.h b/OSX/SaverListController.h index fef8a78e..9b461335 100644 --- a/OSX/SaverListController.h +++ b/OSX/SaverListController.h @@ -1,4 +1,4 @@ -/* xscreensaver, Copyright (c) 2012 Jamie Zawinski +/* xscreensaver, Copyright (c) 2012-2014 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 @@ -15,12 +15,13 @@ #import -@interface SaverListController : UITableViewController { +@interface SaverListController : UITableViewController { int active_section_count; NSMutableArray *list_by_letter[26]; // 27 to get "#" after "Z". NSMutableArray *letter_sections; NSMutableArray *section_titles; + NSArray *names; NSDictionary *descriptions; int tap_count; @@ -29,7 +30,6 @@ } - (id)initWithNames:(NSArray *)names descriptions:(NSDictionary *)descs; -- (void) reload:(NSArray *)names descriptions:(NSDictionary *)descs; - (void) scrollTo:(NSString *)name; @end diff --git a/OSX/SaverListController.m b/OSX/SaverListController.m index 15b3089d..904f570a 100644 --- a/OSX/SaverListController.m +++ b/OSX/SaverListController.m @@ -58,9 +58,9 @@ UIImage *img = [UIImage imageWithContentsOfFile: [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent: - @"iSaverRunner29t.png"]]; + @"iSaverRunner57t.png"]]; UIButton *button = [[UIButton alloc] init]; - [button setFrame: CGRectMake(0, 0, img.size.width, img.size.height)]; + [button setFrame: CGRectMake(0, 0, img.size.width/2, img.size.height/2)]; [button setBackgroundImage:img forState:UIControlStateNormal]; [button addTarget:self action:@selector(titleTapped:) @@ -89,8 +89,8 @@ CGRect win = [self view].frame; if (win.size.width > 320) { // iPad - [label1 setTextAlignment: UITextAlignmentLeft]; - [label2 setTextAlignment: UITextAlignmentRight]; + [label1 setTextAlignment: NSTextAlignmentLeft]; + [label2 setTextAlignment: NSTextAlignmentRight]; label2.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin; r3.size.width = win.size.width; r1 = r3; @@ -100,8 +100,8 @@ } else { // iPhone r3.size.width = 320; // force it to be flush-left - [label1 setTextAlignment: UITextAlignmentLeft]; - [label2 setTextAlignment: UITextAlignmentLeft]; + [label1 setTextAlignment: NSTextAlignmentLeft]; + [label2 setTextAlignment: NSTextAlignmentLeft]; r1.origin.y = -1; // make it fit in landscape r2.origin.y = r1.origin.y + r1.size.height - 2; r3.size.height = r1.size.height + r2.size.height; @@ -114,15 +114,33 @@ [v addSubview:label1]; [v addSubview:label2]; + // Default opacity looks bad. + [v setBackgroundColor:[[v backgroundColor] colorWithAlphaComponent:1]]; + self.navigationItem.titleView = v; + + win.origin.x = 0; + win.origin.y = 0; + win.size.height = 44; // #### This cannot possibly be right. + UISearchBar *search = [[UISearchBar alloc] initWithFrame:win]; + search.delegate = self; + search.placeholder = @"Search..."; + self.tableView.tableHeaderView = search; + + // Dismiss the search field's keyboard as soon as we scroll. +# ifdef __IPHONE_7_0 + if ([self.tableView respondsToSelector:@selector(keyboardDismissMode)]) + [self.tableView setKeyboardDismissMode: + UIScrollViewKeyboardDismissModeOnDrag]; +# endif } -- (id)initWithNames:(NSArray *)names descriptions:(NSDictionary *)descs; +- (id)initWithNames:(NSArray *)_names descriptions:(NSDictionary *)_descs; { self = [self init]; if (! self) return 0; - [self reload:names descriptions:descs]; + [self reload:_names descriptions:_descs search:nil]; [self makeTitleBar]; return self; } @@ -133,6 +151,8 @@ int n = countof(list_by_letter); NSMutableArray *a = [NSMutableArray arrayWithCapacity: n]; for (int i = 0; i < n; i++) { + if ([list_by_letter[i] count] == 0) // Omit empty letter sections. + continue; char s[2]; s[0] = (i == 'Z'-'A'+1 ? '#' : i+'A'); s[1] = 0; @@ -143,11 +163,25 @@ } -- (void) reload:(NSArray *)names descriptions:(NSDictionary *)descs +/* Called when text is typed into the top search bar. + */ +- (void)searchBar:(UISearchBar *)bar textDidChange:(NSString *)txt { - if (descriptions) - [descriptions release]; - descriptions = [descs retain]; + [self reload:names descriptions:descriptions search:txt]; +} + + +- (void) reload:(NSArray *)_names descriptions:(NSDictionary *)_descs + search:search +{ + if (names != _names) { + if (names) [names release]; + names = [_names retain]; + } + if (_descs != descriptions) { + if (descriptions) [descriptions release]; + descriptions = [_descs retain]; + } int n = countof(list_by_letter); for (int i = 0; i < n; i++) { @@ -155,6 +189,25 @@ } for (NSString *name in names) { + + // If we're searching, omit any items that don't have a match in the + // title or description. + // + BOOL matchp = (!search || [search length] == 0); + if (! matchp) { + matchp = ([name rangeOfString:search + options:NSCaseInsensitiveSearch].location + != NSNotFound); + } + if (! matchp) { + NSString *desc = [descriptions objectForKey:name]; + matchp = ([desc rangeOfString:search + options:NSCaseInsensitiveSearch].location + != NSNotFound); + } + if (! matchp) + continue; + int index = ([name cStringUsingEncoding: NSASCIIStringEncoding])[0]; if (index >= 'a' && index <= 'z') index -= 'a'-'A'; @@ -217,25 +270,23 @@ - (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)ip { - NSString *id = + NSString *title = [[letter_sections objectAtIndex: [ip indexAtPosition: 0]] objectAtIndex: [ip indexAtPosition: 1]]; - NSString *desc = [descriptions objectForKey:id]; + NSString *desc = [descriptions objectForKey:title]; - UITableViewCell *cell = [tv dequeueReusableCellWithIdentifier: id]; - if (!cell) { + NSString *id = @"Cell"; + UITableViewCell *cell = [tv dequeueReusableCellWithIdentifier:id]; + if (!cell) cell = [[[UITableViewCell alloc] - initWithStyle: (desc - ? UITableViewCellStyleSubtitle - : UITableViewCellStyleDefault) + initWithStyle: UITableViewCellStyleSubtitle reuseIdentifier: id] autorelease]; - cell.textLabel.text = id; - cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton; - if (desc) - cell.detailTextLabel.text = desc; - } + cell.textLabel.text = title; + cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton; + cell.detailTextLabel.text = desc; + return cell; } @@ -249,6 +300,10 @@ SaverRunner *s = (SaverRunner *) [[UIApplication sharedApplication] delegate]; if (! s) return; + + // Dismiss the search field's keyboard before launching a saver. + [self.tableView.tableHeaderView resignFirstResponder]; + NSAssert ([s isKindOfClass:[SaverRunner class]], @"not a SaverRunner"); [s loadSaver: cell.textLabel.text]; } @@ -291,12 +346,6 @@ } -- (BOOL)shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation)o -{ - return YES; -} - - /* We need this to respond to "shake" gestures */ - (BOOL)canBecomeFirstResponder diff --git a/OSX/SaverRunner.h b/OSX/SaverRunner.h index c58e2b33..35d22354 100644 --- a/OSX/SaverRunner.h +++ b/OSX/SaverRunner.h @@ -1,4 +1,4 @@ -/* xscreensaver, Copyright (c) 2006-2013 Jamie Zawinski +/* xscreensaver, Copyright (c) 2006-2014 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 @@ -48,13 +48,17 @@ # else // USE_IPHONE - ScreenSaverView *saverView; - UIView *backgroundView; - UINavigationController *rootViewController; + UINavigationController *rotating_nav; // Hierarchy 1 (UI) IBOutlet UIWindow *window; + IBOutlet UIView *view; + + UINavigationController *nonrotating_nav; // Hierarchy 2 (savers) + UIWindow *saverWindow; + UIView *backgroundView; + ScreenSaverView *saverView; + EAGLContext *eagl_ctx; GLuint gl_framebuffer, gl_renderbuffer; - IBOutlet UIView *view; UIImage *saved_screenshot; UIView *aboutBox; NSTimer *splashTimer; diff --git a/OSX/SaverRunner.m b/OSX/SaverRunner.m index e2cd11c5..80031e77 100644 --- a/OSX/SaverRunner.m +++ b/OSX/SaverRunner.m @@ -1,4 +1,4 @@ -/* xscreensaver, Copyright (c) 2006-2013 Jamie Zawinski +/* xscreensaver, Copyright (c) 2006-2014 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 @@ -38,13 +38,40 @@ #ifdef USE_IPHONE @interface RotateyViewController : UINavigationController +{ + BOOL allowRotation; +} @end @implementation RotateyViewController + +/* This subclass exists so that we can ask that the SaverListController and + preferences panels be auto-rotated by the system. Note that the + XScreenSaverView is not auto-rotated because it is on a different UIWindow. + */ + +- (id)initWithRotation:(BOOL)rotatep +{ + self = [super init]; + allowRotation = rotatep; + return self; +} + - (BOOL)shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation)o { - return YES; + return allowRotation; /* Deprecated in iOS 6 */ } + +- (BOOL)shouldAutorotate /* Added in iOS 6 */ +{ + return allowRotation; +} + +- (NSUInteger)supportedInterfaceOrientations /* Added in iOS 6 */ +{ + return UIInterfaceOrientationMaskAll; +} + @end #endif // USE_IPHONE @@ -354,7 +381,7 @@ relabel_menus (NSObject *v, NSString *old_str, NSString *new_str) [prefs setObject:saver forKey:@"selectedSaverName"]; [prefs synchronize]; - [rootViewController pushViewController: [saverView configureView] + [rotating_nav pushViewController: [saverView configureView] animated:YES]; } @@ -431,15 +458,6 @@ relabel_menus (NSObject *v, NSString *old_str, NSString *new_str) saverName = name; - if (! backgroundView) { - // This view is the parent of the XScreenSaverView, and exists only - // so that there is a black background behind it. Without this, when - // rotation is in progress, the scrolling-list window's corners show - // through in the corners. - backgroundView = [[[NSView class] alloc] initWithFrame:[window frame]]; - [backgroundView setBackgroundColor:[NSColor blackColor]]; - } - if (saverView) { if ([saverView isAnimating]) [saverView stopAnimation]; @@ -449,8 +467,27 @@ relabel_menus (NSObject *v, NSString *old_str, NSString *new_str) [saverView release]; } - NSSize size = [window frame].size; - saverView = [self makeSaverView:name withSize: size]; + /* We can't just use [window bounds] because that is the *rotated* rectangle + and we need the *unrotated* rectangle, so that the view is always created + in portrait orientation. Without that, the initial rotation event that + takes us from unknown->landscape will be out of step with reality. + */ + UIScreen *screen = [UIScreen mainScreen]; +# ifndef __IPHONE_8_0 // iOS 7 SDK + NSSize size = [screen bounds].size; + int ss = [screen scale]; +# else // iOS 8 SDK + NSSize size = ([screen respondsToSelector:@selector(nativeBounds)] + ? [screen nativeBounds].size // iOS 8 + : [screen bounds].size); // iOS 7 + int ss = ([screen respondsToSelector:@selector(nativeScale)] + ? [screen nativeScale] // iOS 8 + : [screen scale]); // iOS 7 +# endif // iOS 8 SDK + + size.width /= ss; + size.height /= ss; + saverView = [self makeSaverView:name withSize:size]; if (! saverView) { [[[UIAlertView alloc] initWithTitle: name @@ -462,20 +499,41 @@ relabel_menus (NSObject *v, NSString *old_str, NSString *new_str) return; } - [saverView setFrame: [window frame]]; [[NSNotificationCenter defaultCenter] addObserver:saverView selector:@selector(didRotate:) name:UIDeviceOrientationDidChangeNotification object:nil]; LAUNCH: + if (launch) { [self saveScreenshot]; - [window addSubview: backgroundView]; + NSRect f = [saverWindow bounds]; + [backgroundView setFrame:f]; + [saverView setFrame:f]; + [saverWindow addSubview: backgroundView]; [backgroundView addSubview: saverView]; - [saverView becomeFirstResponder]; + [saverView setBackgroundColor:[NSColor blackColor]]; + + /* WTF! Without creating and keying this window, we get no events + delivered on the saverView/saverWindow! Bad craziness. + */ + { + UIWindow *dummy = [[UIWindow alloc] initWithFrame:CGRectMake(0,0,0,0)]; + [dummy setRootViewController: nonrotating_nav]; // Must be this one. + [dummy setHidden:NO]; // required + [dummy setHidden:YES]; + [dummy release]; + } + + [saverWindow setHidden:NO]; + [saverWindow makeKeyAndVisible]; [saverView startAnimation]; [self aboutPanel:nil]; + + // Doing this makes savers cut back to the list instead of fading, + // even though [XScreenSaverView stopAndClose] does setHidden:NO first. + // [window setHidden:YES]; } # endif // USE_IPHONE } @@ -521,16 +579,37 @@ relabel_menus (NSObject *v, NSString *old_str, NSString *new_str) CGFloat pt2 = 14; UIFont *font1 = [UIFont boldSystemFontOfSize: pt1]; UIFont *font2 = [UIFont italicSystemFontOfSize:pt2]; + +# ifdef __IPHONE_7_0 + CGSize s = CGSizeMake(frame.size.width, frame.size.height); + CGSize tsize1 = [[[NSAttributedString alloc] + initWithString: name + attributes:@{ NSFontAttributeName: font1 }] + boundingRectWithSize: s + options: NSStringDrawingUsesLineFragmentOrigin + context: nil].size; + CGSize tsize2 = [[[NSAttributedString alloc] + initWithString: name + attributes:@{ NSFontAttributeName: font2 }] + boundingRectWithSize: s + options: NSStringDrawingUsesLineFragmentOrigin + context: nil].size; +# else // iOS 6 or Cocoa CGSize tsize1 = [name sizeWithFont:font1 constrainedToSize:CGSizeMake(frame.size.width, frame.size.height)]; CGSize tsize2 = [year sizeWithFont:font2 constrainedToSize:CGSizeMake(frame.size.width, frame.size.height)]; +#endif + CGSize tsize = CGSizeMake (tsize1.width > tsize2.width ? tsize1.width : tsize2.width, tsize1.height + tsize2.height); + tsize.width = ceilf(tsize.width); + tsize.height = ceilf(tsize.height); + // Don't know how to find inner margin of UITextView. CGFloat margin = 10; tsize.width += margin * 4; @@ -541,10 +620,7 @@ relabel_menus (NSObject *v, NSString *old_str, NSString *new_str) frame = CGRectMake (0, 0, tsize.width, tsize.height); - UIInterfaceOrientation orient = - // Why are both of these wrong when starting up rotated?? - [[UIDevice currentDevice] orientation]; - // [rootViewController interfaceOrientation]; + UIInterfaceOrientation orient = [rotating_nav interfaceOrientation]; /* Get the text oriented properly, and move it to the bottom of the screen, since many savers have action in the middle. @@ -604,7 +680,7 @@ relabel_menus (NSObject *v, NSString *old_str, NSString *new_str) textview = [[UITextView alloc] initWithFrame:frame]; textview.font = (j == 0 ? font1 : font2); textview.text = (j == 0 ? name : year); - textview.textAlignment = UITextAlignmentCenter; + textview.textAlignment = NSTextAlignmentCenter; textview.showsHorizontalScrollIndicator = NO; textview.showsVerticalScrollIndicator = NO; textview.scrollEnabled = NO; @@ -881,14 +957,23 @@ relabel_menus (NSObject *v, NSString *old_str, NSString *new_str) } // Delete everything after the first blank line. + // r = [desc rangeOfString:@"\n\n" options:0]; if (r.length > 0) desc = [desc substringToIndex: r.location]; - // Truncate really long ones. - int max = 140; - if ([desc length] > max) - desc = [desc substringToIndex: max]; + // Unwrap lines and compress whitespace. + { + NSString *result = @""; + for (NSString *s in [desc componentsSeparatedByCharactersInSet: + [NSCharacterSet whitespaceAndNewlineCharacterSet]]) { + if ([result length] == 0) + result = s; + else if ([s length] > 0) + result = [NSString stringWithFormat: @"%@ %@", result, s]; + desc = result; + } + } if (year) desc = [year stringByAppendingString: @@ -1112,23 +1197,63 @@ FAIL: # undef ya_rand_init ya_rand_init (0); // Now's a good time. - rootViewController = [[[RotateyViewController alloc] init] retain]; - [window setRootViewController: rootViewController]; + rotating_nav = [[[RotateyViewController alloc] initWithRotation:YES] + retain]; + [window setRootViewController: rotating_nav]; + [window setAutoresizesSubviews:YES]; + [window setAutoresizingMask: + (UIViewAutoresizingFlexibleWidth | + UIViewAutoresizingFlexibleHeight)]; + + nonrotating_nav = [[[RotateyViewController alloc] initWithRotation:NO] + retain]; + [nonrotating_nav setNavigationBarHidden:YES animated:NO]; + + /* We run the saver on a different UIWindow than the one the + SaverListController and preferences panels run on, because that's + the only way to make rotation work right. We want the system to + handle rotation of the UI stuff, but we want it to keep its hands + off of rotation of the savers. As of iOS 8, this seems to be the + only way to accomplish that. + + Also, we need to create saverWindow with a portrait rectangle, always. + Note that [UIScreen bounds] returns rotated and scaled values. + */ + UIScreen *screen = [UIScreen mainScreen]; +# ifndef __IPHONE_8_0 // iOS 7 SDK + NSRect frame = [screen bounds]; + int ss = [screen scale]; +# else // iOS 8 SDK + NSRect frame = ([screen respondsToSelector:@selector(nativeBounds)] + ? [screen nativeBounds] // iOS 8 + : [screen bounds]); // iOS 7 + int ss = ([screen respondsToSelector:@selector(nativeScale)] + ? [screen nativeScale] // iOS 8 + : [screen scale]); // iOS 7 +# endif // iOS 8 SDK + frame.size.width /= ss; + frame.size.height /= ss; + saverWindow = [[UIWindow alloc] initWithFrame:frame]; + [saverWindow setRootViewController: nonrotating_nav]; + [saverWindow setHidden:YES]; + + /* This view is the parent of the XScreenSaverView, and exists only + so that there is a black background behind it. Without this, when + rotation is in progress, the scrolling-list window's corners show + through in the corners. + */ + backgroundView = [[[NSView class] alloc] initWithFrame:[saverWindow frame]]; + [backgroundView setBackgroundColor:[NSColor blackColor]]; SaverListController *menu = [[SaverListController alloc] initWithNames:saverNames descriptions:[self makeDescTable]]; - [rootViewController pushViewController:menu animated:YES]; + [rotating_nav pushViewController:menu animated:YES]; [menu becomeFirstResponder]; - [window makeKeyAndVisible]; - [window setAutoresizesSubviews:YES]; - [window setAutoresizingMask: - (UIViewAutoresizingFlexibleWidth | - UIViewAutoresizingFlexibleHeight)]; - application.applicationSupportsShakeToEdit = YES; + # endif // USE_IPHONE NSString *forced = 0; @@ -1183,6 +1308,12 @@ FAIL: # endif [self selectedSaverDidChange:nil]; +// [NSTimer scheduledTimerWithTimeInterval: 0 +// target:self +// selector:@selector(selectedSaverDidChange:) +// userInfo:nil +// repeats:NO]; + # ifndef USE_IPHONE diff --git a/OSX/SaverRunner.plist b/OSX/SaverRunner.plist index 083a4e40..9cd51e50 100644 --- a/OSX/SaverRunner.plist +++ b/OSX/SaverRunner.plist @@ -7,7 +7,7 @@ CFBundleExecutable ${EXECUTABLE_NAME} CFBundleGetInfoString - 5.30 + 5.31 CFBundleIconFile SaverRunner CFBundleIdentifier @@ -15,21 +15,21 @@ CFBundleInfoDictionaryVersion 6.0 CFBundleLongVersionString - 5.30 + 5.31 CFBundleName ${PRODUCT_NAME} CFBundlePackageType APPL CFBundleShortVersionString - 5.30 + 5.31 CFBundleSignature ???? CFBundleVersion - 5.30 + 5.31 LSMinimumSystemVersion ${MACOSX_DEPLOYMENT_TARGET} NSHumanReadableCopyright - 5.30 + 5.31 NSMainNibFile SaverRunner NSPrincipalClass diff --git a/OSX/Updater.plist b/OSX/Updater.plist index b06d1725..cc937af9 100644 --- a/OSX/Updater.plist +++ b/OSX/Updater.plist @@ -7,7 +7,7 @@ CFBundleExecutable ${EXECUTABLE_NAME} CFBundleGetInfoString - 5.30 + 5.31 CFBundleIconFile SaverRunner CFBundleIdentifier @@ -15,7 +15,7 @@ CFBundleInfoDictionaryVersion 6.0 CFBundleLongVersionString - 5.30 + 5.31 CFBundleName ${PRODUCT_NAME} CFBundleDisplayName @@ -23,17 +23,17 @@ CFBundlePackageType APPL CFBundleShortVersionString - 5.30 + 5.31 CFBundleSignature ???? CFBundleVersion - 5.30 + 5.31 LSMinimumSystemVersion ${MACOSX_DEPLOYMENT_TARGET} LSUIElement NSHumanReadableCopyright - 5.30 + 5.31 NSMainNibFile Updater NSPrincipalClass diff --git a/OSX/XScreenSaver.plist b/OSX/XScreenSaver.plist index 77009ea1..93d7dca4 100644 --- a/OSX/XScreenSaver.plist +++ b/OSX/XScreenSaver.plist @@ -15,11 +15,11 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 5.30 + 5.31 CFBundleSignature ???? CFBundleVersion - 5.30 + 5.31 LSMinimumSystemVersion 10.4 NSMainNibFile diff --git a/OSX/XScreenSaverConfigSheet.m b/OSX/XScreenSaverConfigSheet.m index 1e58dc26..6dceacf7 100644 --- a/OSX/XScreenSaverConfigSheet.m +++ b/OSX/XScreenSaverConfigSheet.m @@ -1,4 +1,4 @@ -/* xscreensaver, Copyright (c) 2006-2013 Jamie Zawinski +/* xscreensaver, Copyright (c) 2006-2014 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 @@ -228,10 +228,13 @@ typedef enum { SimpleXMLCommentKind, webView = [[UIWebView alloc] init]; webView.delegate = self; webView.dataDetectorTypes = UIDataDetectorTypeNone; - self. autoresizingMask = (UIViewAutoresizingFlexibleWidth | - UIViewAutoresizingFlexibleHeight); - webView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | - UIViewAutoresizingFlexibleHeight); + self. autoresizingMask = UIViewAutoresizingNone; // we do it manually + webView.autoresizingMask = UIViewAutoresizingNone; + webView.scrollView.scrollEnabled = NO; + webView.scrollView.bounces = NO; + webView.opaque = NO; + [webView setBackgroundColor:[UIColor clearColor]]; + [self addSubview: webView]; [self setHTML: h]; return self; @@ -270,6 +273,7 @@ typedef enum { SimpleXMLCommentKind, " font-family: \"%@\";" " font-size: %.4fpx;" // Must be "px", not "pt"! " line-height: %.4fpx;" // And no spaces before it. + " -webkit-text-size-adjust: none;" "}" "\n//-->\n" "" @@ -282,6 +286,7 @@ typedef enum { SimpleXMLCommentKind, [font pointSize], [font lineHeight], h]; + [webView stopLoading]; [webView loadHTMLString:h2 baseURL:[NSURL URLWithString:@""]]; } @@ -290,6 +295,8 @@ static char *anchorize (const char *url); - (void) setText: (NSString *)t { + t = [t stringByTrimmingCharactersInSet:[NSCharacterSet + whitespaceCharacterSet]]; t = [t stringByReplacingOccurrencesOfString:@"&" withString:@"&"]; t = [t stringByReplacingOccurrencesOfString:@"<" withString:@"<"]; t = [t stringByReplacingOccurrencesOfString:@">" withString:@">"]; @@ -313,6 +320,12 @@ static char *anchorize (const char *url); } h = [NSString stringWithFormat: @"%@ %@", h, s]; } + + h = [h stringByReplacingOccurrencesOfString:@"

" withString:@"

"]; + h = [h stringByReplacingOccurrencesOfString:@"

" withString:@"

"]; + h = [h stringByTrimmingCharactersInSet:[NSCharacterSet + whitespaceAndNewlineCharacterSet]]; + [self setHTML: h]; } @@ -336,8 +349,6 @@ static char *anchorize (const char *url); r.origin.x = 0; r.origin.y = 0; [webView setFrame: r]; - [self setHTML: html]; - [webView reload]; } @@ -345,6 +356,7 @@ static char *anchorize (const char *url); { NSString *result = @""; + // Add newlines. str = [str stringByReplacingOccurrencesOfString:@"

" withString:@"

" options:NSCaseInsensitiveSearch @@ -354,12 +366,25 @@ static char *anchorize (const char *url); options:NSCaseInsensitiveSearch range:NSMakeRange(0, [str length])]; + // Remove HREFs. for (NSString *s in [str componentsSeparatedByString: @"<"]) { NSRange r = [s rangeOfString:@">"]; if (r.length > 0) s = [s substringFromIndex: r.location + r.length]; result = [result stringByAppendingString: s]; } + + // Compress internal horizontal whitespace. + str = result; + result = @""; + for (NSString *s in [str componentsSeparatedByCharactersInSet: + [NSCharacterSet whitespaceCharacterSet]]) { + if ([result length] == 0) + result = s; + else if ([s length] > 0) + result = [NSString stringWithFormat: @"%@ %@", result, s]; + } + return result; } @@ -370,8 +395,15 @@ static char *anchorize (const char *url); /* It would be sensible to just ask the UIWebView how tall the page is, instead of hoping that NSString and UIWebView measure fonts and do - wrapping in exactly the same way, but I can't make that work. - Maybe because it loads async? + wrapping in exactly the same way, but since UIWebView is asynchronous, + we'd have to wait for the document to load first, e.g.: + + - Start the document loading; + - return a default height to use for the UITableViewCell; + - wait for the webViewDidFinishLoad delegate method to fire; + - then force the UITableView to reload, to pick up the new height. + + But I couldn't make that work. */ # if 0 r.size.height = [[webView @@ -385,11 +417,6 @@ static char *anchorize (const char *url); s = [text sizeWithFont: font constrainedToSize: s lineBreakMode:NSLineBreakByWordWrapping]; - - // GAAAH. Add one more line, or the UIWebView is still scrollable! - // The text is sized right, but it lets you scroll it up anyway. - s.height += [font pointSize]; - r.size.height = s.height; # endif @@ -1329,6 +1356,8 @@ hreffify (NSText *nstext) [self placeChild:lab on:parent]; # else // USE_IPHONE [lab setTextAlignment: NSTextAlignmentRight]; + // Sometimes rotation screws up truncation. + [lab setLineBreakMode:NSLineBreakByClipping]; [self placeChild:lab on:parent right:(label ? YES : NO)]; # endif // USE_IPHONE @@ -1363,6 +1392,10 @@ hreffify (NSText *nstext) // Make right label be same height as slider. rect.size.height = [slider frame].size.height; [lab setFrame:rect]; +# ifdef USE_IPHONE + // Sometimes rotation screws up truncation. + [lab setLineBreakMode:NSLineBreakByClipping]; +# endif [self placeChild:lab on:parent right:YES]; [lab release]; } @@ -1677,7 +1710,7 @@ set_menu_item_object (NSMenuItem *item, NSObject *obj) // Store the items for this picker in the picker_values array. // This is so fucking stupid. - int menu_number = [pref_keys count] - 1; + unsigned long menu_number = [pref_keys count] - 1; if (! picker_values) picker_values = [[NSMutableArray arrayWithCapacity:menu_number] retain]; while ([picker_values count] <= menu_number) @@ -2488,7 +2521,25 @@ last_child (NSView *parent) # else // USE_IPHONE - // Controls is an array of arrays of the controls, divided into sections. + /* Controls is an array of arrays of the controls, divided into sections. + Each hgroup / vgroup gets a nested array, too, e.g.: + + [ [ [

diff --git a/hacks/config/abstractile.xml b/hacks/config/abstractile.xml index 2181862e..0ff0c6c7 100644 --- a/hacks/config/abstractile.xml +++ b/hacks/config/abstractile.xml @@ -4,6 +4,8 @@ +