]> git.saurik.com Git - winterboard.git/blame - Application.mm
In the last couple decades I learned BSD is wrong.
[winterboard.git] / Application.mm
CommitLineData
62b2dbad 1/* WinterBoard - Theme Manager for the iPhone
900dc9a5 2 * Copyright (C) 2008-2014 Jay Freeman (saurik)
62b2dbad
JF
3*/
4
900dc9a5 5/* GNU Lesser General Public License, Version 3 {{{ */
62b2dbad 6/*
900dc9a5
JF
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.
62b2dbad 11 *
900dc9a5
JF
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.
62b2dbad 16 *
900dc9a5
JF
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/>.
19**/
20/* }}} */
62b2dbad
JF
21
22#import <Foundation/Foundation.h>
23#import <CoreGraphics/CGGeometry.h>
24#import <UIKit/UIKit.h>
25
77d89d52
JF
26#include <objc/objc-runtime.h>
27
224d48e3
JF
28#import <Preferences/PSRootController.h>
29#import <Preferences/PSViewController.h>
b44f5c22 30#import <Preferences/PSListController.h>
224d48e3 31#import <Preferences/PSSpecifier.h>
d5fb6e01 32
f9511b59
JF
33#include <substrate.h>
34#include <mach-o/dyld.h>
35
b44f5c22
DH
36static NSBundle *wbSettingsBundle;
37static Class $WBSettingsController;
38
224d48e3
JF
39@interface UIApplication (Private)
40- (void) terminateWithSuccess;
41@end
d5fb6e01 42
b44f5c22
DH
43@interface UIDevice (Private)
44- (BOOL) isWildcat;
45@end
46
47@interface PSRootController (Compatibility)
48- (id) _popController; // < 3.2
49- (id) contentView; // < 3.2
50- (id) lastController; // < 3.2
51- (id) topViewController; // >= 3.2
52@end
53
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
58@end
59
224d48e3 60@interface WBRootController : PSRootController {
b44f5c22 61 PSListController *_rootListController;
d5fb6e01
JF
62}
63
b44f5c22 64@property (readonly) PSListController *rootListController;
d5fb6e01 65
224d48e3 66- (void) setupRootListForSize:(CGSize)size;
b44f5c22 67- (id) topViewController;
d5fb6e01 68@end
62b2dbad 69
224d48e3 70@implementation WBRootController
62b2dbad 71
b44f5c22 72@synthesize rootListController = _rootListController;
62b2dbad 73
b44f5c22 74// < 3.2
224d48e3 75- (void) setupRootListForSize:(CGSize)size {
b44f5c22 76 PSSpecifier *spec([[PSSpecifier alloc] init]);
224d48e3
JF
77 [spec setTarget:self];
78 spec.name = @"WinterBoard";
62b2dbad 79
b44f5c22
DH
80 _rootListController = [[$WBSettingsController alloc] initForContentSize:size];
81 _rootListController.rootController = self;
82 _rootListController.parentController = self;
83 [_rootListController viewWillBecomeVisible:spec];
d5fb6e01 84
224d48e3 85 [spec release];
62b2dbad 86
b44f5c22 87 [self pushController:_rootListController];
d5fb6e01
JF
88}
89
b44f5c22
DH
90// >= 3.2
91- (void) loadView {
92 [super loadView];
93 [self pushViewController:[self rootListController] animated:NO];
94}
95
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];
105 [spec release];
106 }
107 return _rootListController;
108}
109
110- (id) contentView {
111 if ([[PSRootController class] instancesRespondToSelector:@selector(contentView)]) {
112 return [super contentView];
113 } else {
114 return [super view];
115 }
116}
117
118- (id) topViewController {
119 if ([[PSRootController class] instancesRespondToSelector:@selector(topViewController)]) {
120 return [super topViewController];
121 } else {
122 return [super lastController];
123 }
124}
125
1d3b613f 126- (void) _popController {
224d48e3
JF
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.
b44f5c22 130 if ([self topViewController] == _rootListController)
224d48e3 131 [[UIApplication sharedApplication] terminateWithSuccess];
1d3b613f 132 [super _popController];
62b2dbad 133}
b44f5c22 134
224d48e3 135@end
62b2dbad 136
224d48e3
JF
137@interface WBApplication : UIApplication {
138 WBRootController *_rootController;
d5fb6e01 139}
62b2dbad 140
224d48e3
JF
141@end
142
143@implementation WBApplication
144
145- (void) dealloc {
146 [_rootController release];
147 [super dealloc];
d5fb6e01 148}
62b2dbad 149
224d48e3 150- (void) applicationWillTerminate:(UIApplication *)application {
b44f5c22 151 [_rootController.rootListController suspend];
62b2dbad
JF
152}
153
154- (void) applicationDidFinishLaunching:(id)unused {
b44f5c22
DH
155 wbSettingsBundle = [NSBundle bundleWithPath:@"/System/Library/PreferenceBundles/WinterBoardSettings.bundle"];
156 [wbSettingsBundle load];
157 $WBSettingsController = [wbSettingsBundle principalClass];
158
159 CGRect applicationFrame(([UIDevice instancesRespondToSelector:@selector(isWildcat)]
77d89d52 160 && [[UIDevice currentDevice] isWildcat]) || objc_getClass("UIStatusBar") != nil
b44f5c22
DH
161 ? [UIScreen mainScreen].bounds
162 : [UIScreen mainScreen].applicationFrame);
163 UIWindow *window([[UIWindow alloc] initWithFrame:applicationFrame]);
224d48e3 164 _rootController = [[WBRootController alloc] initWithTitle:@"WinterBoard" identifier:[[NSBundle mainBundle] bundleIdentifier]];
b44f5c22 165 [window addSubview:[_rootController contentView]];
224d48e3 166 [window makeKeyAndVisible];
62b2dbad
JF
167}
168
169@end
170
f9511b59
JF
171MSHook(int32_t, NSVersionOfLinkTimeLibrary, const char *name) {
172 if (strcmp(name, "UIKit") == 0)
173 return 0x6400000;
174 return _NSVersionOfLinkTimeLibrary(name);
175}
176
62b2dbad 177int main(int argc, char *argv[]) {
b44f5c22 178 NSAutoreleasePool *pool( [[NSAutoreleasePool alloc] init]);
62b2dbad 179
f9511b59
JF
180 MSHookFunction(NSVersionOfLinkTimeLibrary, MSHake(NSVersionOfLinkTimeLibrary));
181
62b2dbad
JF
182 int value = UIApplicationMain(argc, argv, @"WBApplication", @"WBApplication");
183
184 [pool release];
185 return value;
186}