X-Git-Url: https://git.saurik.com/winterboard.git/blobdiff_plain/26c43b47c1020faa78c7ce6559c9d1f8319b7007..900dc9a5d6341928f9190bb8840fdf61df65b59b:/Application.mm diff --git a/Application.mm b/Application.mm index a7c72ad..2b5bfb3 100644 --- a/Application.mm +++ b/Application.mm @@ -1,114 +1,183 @@ /* WinterBoard - Theme Manager for the iPhone - * Copyright (C) 2008 Jay Freeman (saurik) + * Copyright (C) 2008-2014 Jay Freeman (saurik) */ +/* GNU Lesser General Public License, Version 3 {{{ */ /* - * Redistribution and use in source and binary - * forms, with or without modification, are permitted - * provided that the following conditions are met: + * WinterBoard is free software: you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. * - * 1. Redistributions of source code must retain the - * above copyright notice, this list of conditions - * and the following disclaimer. - * 2. Redistributions in binary form must reproduce the - * above copyright notice, this list of conditions - * and the following disclaimer in the documentation - * and/or other materials provided with the - * distribution. - * 3. The name of the author may not be used to endorse - * or promote products derived from this software - * without specific prior written permission. + * WinterBoard is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ + * You should have received a copy of the GNU Lesser General Public License + * along with WinterBoard. If not, see . +**/ +/* }}} */ #import #import #import -#define _trace() NSLog(@"_trace(%u)", __LINE__); +#include -@interface WBApplication : UIApplication < - UITableViewDataSource, - UITableViewDelegate -> { - UIWindow *window_; - UITableView *themesTable_; - NSMutableArray *themesArray_; -} +#import +#import +#import +#import + +#include +#include +static NSBundle *wbSettingsBundle; +static Class $WBSettingsController; + +@interface UIApplication (Private) +- (void) terminateWithSuccess; @end -@implementation WBApplication +@interface UIDevice (Private) +- (BOOL) isWildcat; +@end -- (void) dealloc { - [window_ release]; - [themesTable_ release]; - [themesArray_ release]; - [super dealloc]; +@interface PSRootController (Compatibility) +- (id) _popController; // < 3.2 +- (id) contentView; // < 3.2 +- (id) lastController; // < 3.2 +- (id) topViewController; // >= 3.2 +@end + +@interface PSListController (Compatibility) +- (void) viewWillBecomeVisible:(void *)specifier; // < 3.2 +- (void) viewWillAppear:(BOOL)a; // >= 3.2 +- (void) setSpecifier:(PSSpecifier *)spec; // >= 3.2 +@end + +@interface WBRootController : PSRootController { + PSListController *_rootListController; } -- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { - UITableViewCell *cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero] autorelease]; - cell.text = [themesArray_ objectAtIndex:[indexPath row]]; - return cell; +@property (readonly) PSListController *rootListController; + +- (void) setupRootListForSize:(CGSize)size; +- (id) topViewController; +@end + +@implementation WBRootController + +@synthesize rootListController = _rootListController; + +// < 3.2 +- (void) setupRootListForSize:(CGSize)size { + PSSpecifier *spec([[PSSpecifier alloc] init]); + [spec setTarget:self]; + spec.name = @"WinterBoard"; + + _rootListController = [[$WBSettingsController alloc] initForContentSize:size]; + _rootListController.rootController = self; + _rootListController.parentController = self; + [_rootListController viewWillBecomeVisible:spec]; + + [spec release]; + + [self pushController:_rootListController]; } -- (NSInteger) tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section { - return [themesArray_ count]; +// >= 3.2 +- (void) loadView { + [super loadView]; + [self pushViewController:[self rootListController] animated:NO]; } -- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - NSString *theme = [themesArray_ objectAtIndex:[indexPath row]]; +- (PSListController *) rootListController { + if(!_rootListController) { + PSSpecifier *spec([[PSSpecifier alloc] init]); + [spec setTarget:self]; + spec.name = @"WinterBoard"; + _rootListController = [[$WBSettingsController alloc] initForContentSize:CGSizeZero]; + _rootListController.rootController = self; + _rootListController.parentController = self; + [_rootListController setSpecifier:spec]; + [spec release]; + } + return _rootListController; +} - [[NSDictionary dictionaryWithObjectsAndKeys: - theme, @"Theme", - nil] writeToFile:[NSString stringWithFormat:@"%@/Library/Preferences/com.saurik.WinterBoard.plist", - NSHomeDirectory() - ] atomically:YES]; +- (id) contentView { + if ([[PSRootController class] instancesRespondToSelector:@selector(contentView)]) { + return [super contentView]; + } else { + return [super view]; + } +} - if (fork() == 0) { - execlp("killall", "killall", "SpringBoard", NULL); - exit(0); +- (id) topViewController { + if ([[PSRootController class] instancesRespondToSelector:@selector(topViewController)]) { + return [super topViewController]; + } else { + return [super lastController]; } } -- (void) applicationDidFinishLaunching:(id)unused { - window_ = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].applicationFrame]; - [window_ makeKeyAndVisible]; +- (void) _popController { + // Pop the last controller = exit the application. + // The only time the last controller should pop is when the user taps Respring/Cancel. + // Which only gets displayed if the user has made changes. + if ([self topViewController] == _rootListController) + [[UIApplication sharedApplication] terminateWithSuccess]; + [super _popController]; +} + +@end + +@interface WBApplication : UIApplication { + WBRootController *_rootController; +} - themesArray_ = [[NSMutableArray arrayWithCapacity:32] retain]; - NSFileManager *manager = [NSFileManager defaultManager]; +@end - [themesArray_ addObjectsFromArray:[manager contentsOfDirectoryAtPath:@"/Library/Themes" error:NULL]]; - [themesArray_ addObjectsFromArray:[manager contentsOfDirectoryAtPath:[NSString stringWithFormat:@"%@/Library/SummerBoard/Themes", NSHomeDirectory()] error:NULL]]; +@implementation WBApplication - themesTable_ = [[UITableView alloc] initWithFrame:window_.bounds]; - [window_ addSubview:themesTable_]; +- (void) dealloc { + [_rootController release]; + [super dealloc]; +} - [themesTable_ setDataSource:self]; - [themesTable_ setDelegate:self]; +- (void) applicationWillTerminate:(UIApplication *)application { + [_rootController.rootListController suspend]; +} - [themesTable_ setSeparatorStyle:UITableViewCellSeparatorStyleSingleLine]; +- (void) applicationDidFinishLaunching:(id)unused { + wbSettingsBundle = [NSBundle bundleWithPath:@"/System/Library/PreferenceBundles/WinterBoardSettings.bundle"]; + [wbSettingsBundle load]; + $WBSettingsController = [wbSettingsBundle principalClass]; + + CGRect applicationFrame(([UIDevice instancesRespondToSelector:@selector(isWildcat)] + && [[UIDevice currentDevice] isWildcat]) || objc_getClass("UIStatusBar") != nil + ? [UIScreen mainScreen].bounds + : [UIScreen mainScreen].applicationFrame); + UIWindow *window([[UIWindow alloc] initWithFrame:applicationFrame]); + _rootController = [[WBRootController alloc] initWithTitle:@"WinterBoard" identifier:[[NSBundle mainBundle] bundleIdentifier]]; + [window addSubview:[_rootController contentView]]; + [window makeKeyAndVisible]; } @end +MSHook(int32_t, NSVersionOfLinkTimeLibrary, const char *name) { + if (strcmp(name, "UIKit") == 0) + return 0x6400000; + return _NSVersionOfLinkTimeLibrary(name); +} + int main(int argc, char *argv[]) { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSAutoreleasePool *pool( [[NSAutoreleasePool alloc] init]); + + MSHookFunction(NSVersionOfLinkTimeLibrary, MSHake(NSVersionOfLinkTimeLibrary)); int value = UIApplicationMain(argc, argv, @"WBApplication", @"WBApplication");