]> git.saurik.com Git - winterboard.git/blob - WinterBoard.mm
131624c3b5ca02cf6c1887a0c2921d578e038d52
[winterboard.git] / WinterBoard.mm
1 /* WinterBoard - Theme Manager for the iPhone
2 * Copyright (C) 2008 Jay Freeman (saurik)
3 */
4
5 /*
6 * Redistribution and use in source and binary
7 * forms, with or without modification, are permitted
8 * provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the
11 * above copyright notice, this list of conditions
12 * and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the
14 * above copyright notice, this list of conditions
15 * and the following disclaimer in the documentation
16 * and/or other materials provided with the
17 * distribution.
18 * 3. The name of the author may not be used to endorse
19 * or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS''
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
24 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
27 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
33 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
35 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 */
37
38 #include <objc/runtime.h>
39 #include <objc/message.h>
40
41 #import <Foundation/Foundation.h>
42
43 #import <UIKit/UIColor.h>
44 #import <UIKit/UIImage.h>
45 #import <UIKit/UIImageView.h>
46 #import <UIKit/UIView-Hierarchy.h>
47
48 #import <SpringBoard/SBApplication.h>
49 #import <SpringBoard/SBAppWindow.h>
50 #import <SpringBoard/SBContentLayer.h>
51 #import <SpringBoard/SBUIController.h>
52
53 #import <CoreGraphics/CGGeometry.h>
54
55 /* WinterBoard Backend {{{ */
56 #define WBPrefix "wb_"
57
58 void WBInject(const char *classname, const char *oldname, IMP newimp, const char *type) {
59 Class _class = objc_getClass(classname);
60 if (_class == nil)
61 return;
62 if (!class_addMethod(_class, sel_registerName(oldname), newimp, type))
63 NSLog(@"WB: failed to inject [%s %s]", classname, oldname);
64 }
65
66 void WBRename(const char *classname, const char *oldname, IMP newimp) {
67 Class _class = objc_getClass(classname);
68 if (_class == nil)
69 return;
70 size_t namelen = strlen(oldname);
71 char newname[sizeof(WBPrefix) + namelen];
72 memcpy(newname, WBPrefix, sizeof(WBPrefix) - 1);
73 memcpy(newname + sizeof(WBPrefix) - 1, oldname, namelen + 1);
74 Method method = class_getInstanceMethod(_class, sel_getUid(oldname));
75 if (method == nil)
76 return;
77 const char *type = method_getTypeEncoding(method);
78 if (!class_addMethod(_class, sel_registerName(newname), method_getImplementation(method), type))
79 NSLog(@"WB: failed to rename [%s %s]", classname, oldname);
80 unsigned int count;
81 Method *methods = class_copyMethodList(_class, &count);
82 for (unsigned int index(0); index != count; ++index)
83 if (methods[index] == method)
84 goto found;
85 if (newimp != NULL)
86 if (!class_addMethod(_class, sel_getUid(oldname), newimp, type))
87 NSLog(@"WB: failed to rename [%s %s]", classname, oldname);
88 goto done;
89 found:
90 if (newimp != NULL)
91 method_setImplementation(method, newimp);
92 done:
93 free(methods);
94 }
95
96 static NSString *Dylib_ = @"/System/Library/PrivateFrameworks/WinterBoard.framework/WinterBoard.dylib";
97 /* }}} */
98
99 @protocol WinterBoard
100 - (NSString *) wb_pathForIcon;
101 - (NSString *) wb_pathForResource:(NSString *)resource ofType:(NSString *)type;
102 - (id) wb_initWithSize:(CGSize)size;
103 - (void) wb_setBackgroundColor:(id)color;
104 @end
105
106 NSString *Themes_ = @"/System/Library/Themes";
107 NSString *theme_ = @"Litho";
108
109 NSString *SBApplication$pathForIcon(SBApplication<WinterBoard> *self, SEL sel) {
110 NSFileManager *manager([NSFileManager defaultManager]);
111 NSString *path;
112 path = [NSString stringWithFormat:@"%@/%@/Icons/%@.png", Themes_, theme_, [self displayName]];
113 if ([manager fileExistsAtPath:path])
114 return path;
115 path = [NSString stringWithFormat:@"%@/%@/Icons/%@.png", Themes_, theme_, [self bundleIdentifier]];
116 if ([manager fileExistsAtPath:path])
117 return path;
118 return [self wb_pathForIcon];
119 }
120
121 NSString *NSBundle$pathForResource$ofType$(NSBundle<WinterBoard> *self, SEL sel, NSString *resource, NSString *type) {
122 if ([resource isEqualToString:@"SBDockBG"] && [type isEqualToString:@"png"]) {
123 NSFileManager *manager([NSFileManager defaultManager]);
124 NSString *path = [NSString stringWithFormat:@"%@/%@/Dock.png", Themes_, theme_];
125 if ([manager fileExistsAtPath:path])
126 return path;
127 }
128
129 return [self wb_pathForResource:resource ofType:type];
130 }
131
132 void SBAppWindow$setBackgroundColor$(SBAppWindow<WinterBoard> *self, SEL sel, id color) {
133 [self wb_setBackgroundColor:[UIColor clearColor]];
134 }
135
136 id SBContentLayer$initWithSize$(SBContentLayer<WinterBoard> *self, SEL sel, CGSize size) {
137 self = [self wb_initWithSize:size];
138 if (self == nil)
139 return nil;
140
141 NSFileManager *manager([NSFileManager defaultManager]);
142 NSString *path = [NSString stringWithFormat:@"%@/%@/Wallpaper.png", Themes_, theme_];
143 if ([manager fileExistsAtPath:path])
144 if (UIImage *image = [[UIImage alloc] initWithContentsOfFile:path]) {
145 /*window_ = [[UIWindow alloc] initWithContentRect:CGRectMake(0, 0, 320, 480)];
146 [window_ setHidden:NO];*/
147 UIImageView *view = [[[UIImageView alloc] initWithImage:image] autorelease];
148 //[view setFrame:CGRectMake(0, -10, 320, 480)];
149 [self addSubview:view];
150 }
151
152 return self;
153 }
154
155 extern "C" void WBInitialize() {
156 /* WinterBoard FrontEnd {{{ */
157 if (NSClassFromString(@"SpringBoard") == nil)
158 return;
159 NSLog(@"WB: installing WinterBoard...");
160
161 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
162
163 char *dil = getenv("DYLD_INSERT_LIBRARIES");
164 if (dil == NULL)
165 NSLog(@"WB: DYLD_INSERT_LIBRARIES is unset?");
166 else {
167 NSArray *dylibs = [[NSString stringWithUTF8String:dil] componentsSeparatedByString:@":"];
168 int index = [dylibs indexOfObject:Dylib_];
169 if (index == INT_MAX)
170 NSLog(@"WB: dylib not in DYLD_INSERT_LIBRARIES?");
171 else if ([dylibs count] == 1)
172 unsetenv("DYLD_INSERT_LIBRARIES");
173 else {
174 NSMutableArray *value = [[NSMutableArray alloc] init];
175 [value setArray:dylibs];
176 [value removeObjectAtIndex:index];
177 setenv("DYLD_INSERT_LIBRARIES", [[value componentsJoinedByString:@":"] UTF8String], !0);
178 }
179 }
180 /* }}} */
181
182 WBRename("SBApplication", "pathForIcon", (IMP) &SBApplication$pathForIcon);
183 WBRename("NSBundle", "pathForResource:ofType:", (IMP) &NSBundle$pathForResource$ofType$);
184 WBRename("SBAppWindow", "setBackgroundColor:", (IMP) &SBAppWindow$setBackgroundColor$);
185 WBRename("SBContentLayer", "initWithSize:", (IMP) &SBContentLayer$initWithSize$);
186
187 [pool release];
188 }