1 /* WinterBoard - Theme Manager for the iPhone
2 * Copyright (C) 2008-2014 Jay Freeman (saurik)
5 /* GNU Lesser General Public License, Version 3 {{{ */
7 * WinterBoard is free software: you can redistribute it and/or modify it under
8 * the terms of the GNU Lesser General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
12 * WinterBoard is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 * License for more details.
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with WinterBoard. If not, see <http://www.gnu.org/licenses/>.
22 #import <Foundation/Foundation.h>
23 #import <CoreGraphics/CGGeometry.h>
24 #import <UIKit/UIKit.h>
26 #include <objc/objc-runtime.h>
28 #import <Preferences/PSRootController.h>
29 #import <Preferences/PSViewController.h>
30 #import <Preferences/PSListController.h>
31 #import <Preferences/PSSpecifier.h>
33 #include <substrate.h>
34 #include <mach-o/dyld.h>
36 static NSBundle *wbSettingsBundle;
37 static Class $WBSettingsController;
39 @interface UIApplication (Private)
40 - (void) terminateWithSuccess;
43 @interface UIDevice (Private)
47 @interface PSRootController (Compatibility)
48 - (id) _popController; // < 3.2
49 - (id) contentView; // < 3.2
50 - (id) lastController; // < 3.2
51 - (id) topViewController; // >= 3.2
54 @interface PSListController (Compatibility)
55 - (void) viewWillBecomeVisible:(void *)specifier; // < 3.2
56 - (void) viewWillAppear:(BOOL)a; // >= 3.2
57 - (void) setSpecifier:(PSSpecifier *)spec; // >= 3.2
60 @interface WBRootController : PSRootController {
61 PSListController *_rootListController;
64 @property (readonly) PSListController *rootListController;
66 - (void) setupRootListForSize:(CGSize)size;
67 - (id) topViewController;
70 @implementation WBRootController
72 @synthesize rootListController = _rootListController;
75 - (void) setupRootListForSize:(CGSize)size {
76 PSSpecifier *spec([[PSSpecifier alloc] init]);
77 [spec setTarget:self];
78 spec.name = @"WinterBoard";
80 _rootListController = [[$WBSettingsController alloc] initForContentSize:size];
81 _rootListController.rootController = self;
82 _rootListController.parentController = self;
83 [_rootListController viewWillBecomeVisible:spec];
87 [self pushController:_rootListController];
93 [self pushViewController:[self rootListController] animated:NO];
96 - (PSListController *) rootListController {
97 if(!_rootListController) {
98 PSSpecifier *spec([[PSSpecifier alloc] init]);
99 [spec setTarget:self];
100 spec.name = @"WinterBoard";
101 _rootListController = [[$WBSettingsController alloc] initForContentSize:CGSizeZero];
102 _rootListController.rootController = self;
103 _rootListController.parentController = self;
104 [_rootListController setSpecifier:spec];
107 return _rootListController;
111 if ([[PSRootController class] instancesRespondToSelector:@selector(contentView)]) {
112 return [super contentView];
118 - (id) topViewController {
119 if ([[PSRootController class] instancesRespondToSelector:@selector(topViewController)]) {
120 return [super topViewController];
122 return [super lastController];
126 - (void) _popController {
127 // Pop the last controller = exit the application.
128 // The only time the last controller should pop is when the user taps Respring/Cancel.
129 // Which only gets displayed if the user has made changes.
130 if ([self topViewController] == _rootListController)
131 [[UIApplication sharedApplication] terminateWithSuccess];
132 [super _popController];
137 @interface WBApplication : UIApplication {
138 WBRootController *_rootController;
143 @implementation WBApplication
146 [_rootController release];
150 - (void) applicationWillTerminate:(UIApplication *)application {
151 [_rootController.rootListController suspend];
154 - (void) applicationDidFinishLaunching:(id)unused {
155 wbSettingsBundle = [NSBundle bundleWithPath:@"/System/Library/PreferenceBundles/WinterBoardSettings.bundle"];
156 [wbSettingsBundle load];
157 $WBSettingsController = [wbSettingsBundle principalClass];
159 CGRect applicationFrame(([UIDevice instancesRespondToSelector:@selector(isWildcat)]
160 && [[UIDevice currentDevice] isWildcat]) || objc_getClass("UIStatusBar") != nil
161 ? [UIScreen mainScreen].bounds
162 : [UIScreen mainScreen].applicationFrame);
163 UIWindow *window([[UIWindow alloc] initWithFrame:applicationFrame]);
164 _rootController = [[WBRootController alloc] initWithTitle:@"WinterBoard" identifier:[[NSBundle mainBundle] bundleIdentifier]];
165 [window addSubview:[_rootController contentView]];
166 [window makeKeyAndVisible];
171 MSHook(int32_t, NSVersionOfLinkTimeLibrary, const char *name) {
172 if (strcmp(name, "UIKit") == 0)
174 return _NSVersionOfLinkTimeLibrary(name);
177 int main(int argc, char *argv[]) {
178 NSAutoreleasePool *pool( [[NSAutoreleasePool alloc] init]);
180 MSHookFunction(NSVersionOfLinkTimeLibrary, MSHake(NSVersionOfLinkTimeLibrary));
182 int value = UIApplicationMain(argc, argv, @"WBApplication", @"WBApplication");