1 /* WinterBoard - Theme Manager for the iPhone
2 * Copyright (C) 2008-2011 Jay Freeman (saurik)
6 * Redistribution and use in source and binary
7 * forms, with or without modification, are permitted
8 * provided that the following conditions are met:
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
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.
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.
43 #define _trace() do { \
44 struct timeval _ctv; \
45 gettimeofday(&_ctv, NULL); \
50 NSLog(@"%lu.%.6u[%f]:WB:_trace()@%s:%u[%s]\n", \
51 _ctv.tv_sec, _ctv.tv_usec, \
52 (_ctv.tv_sec - _ltv.tv_sec) + (_ctv.tv_usec - _ltv.tv_usec) / 1000000.0, \
53 __FILE__, __LINE__, __FUNCTION__\
60 #import <CoreFoundation/CoreFoundation.h>
61 #import <Foundation/Foundation.h>
62 #import <CoreGraphics/CoreGraphics.h>
63 #import <ImageIO/CGImageSource.h>
65 #import <Celestial/AVController.h>
66 #import <Celestial/AVItem.h>
67 #import <Celestial/AVQueue.h>
69 #include <substrate.h>
71 #import <UIKit/UIKit.h>
73 #import <SpringBoard/SBApplication.h>
74 #import <SpringBoard/SBApplicationIcon.h>
75 #import <SpringBoard/SBAppWindow.h>
76 #import <SpringBoard/SBAwayView.h>
77 #import <SpringBoard/SBBookmarkIcon.h>
78 #import <SpringBoard/SBButtonBar.h>
79 #import <SpringBoard/SBCalendarIconContentsView.h>
80 #import <SpringBoard/SBIconController.h>
81 #import <SpringBoard/SBIconLabel.h>
82 #import <SpringBoard/SBIconList.h>
83 #import <SpringBoard/SBIconModel.h>
84 #import <SpringBoard/SBImageCache.h>
85 // XXX: #import <SpringBoard/SBSearchView.h>
86 #import <SpringBoard/SBSearchTableViewCell.h>
87 #import <SpringBoard/SBStatusBarContentsView.h>
88 #import <SpringBoard/SBStatusBarController.h>
89 #import <SpringBoard/SBStatusBarOperatorNameView.h>
90 #import <SpringBoard/SBStatusBarTimeView.h>
91 #import <SpringBoard/SBUIController.h>
92 #import <SpringBoard/SBWidgetApplicationIcon.h>
94 #import <MobileSMS/mSMSMessageTranscriptController.h>
96 #import <MediaPlayer/MPMoviePlayerController.h>
97 #import <MediaPlayer/MPVideoView.h>
98 #import <MediaPlayer/MPVideoView-PlaybackControl.h>
100 #import <CoreGraphics/CGGeometry.h>
102 #import <ChatKit/CKMessageCell.h>
104 #include <sys/sysctl.h>
106 #include "WBMarkup.h"
108 extern "C" void __clear_cache (char *beg, char *end);
110 @protocol WinterBoard
114 Class $MPMoviePlayerController;
117 MSClassHook(NSBundle)
118 MSClassHook(NSString)
121 MSMetaClassHook(UIImage)
122 MSClassHook(UINavigationBar)
123 MSClassHook(UIToolbar)
125 MSClassHook(CKBalloonView)
126 MSClassHook(CKMessageCell)
127 MSClassHook(CKTimestampView)
128 MSClassHook(CKTranscriptCell)
129 MSClassHook(CKTranscriptController)
130 MSClassHook(CKTranscriptHeaderView)
131 MSClassHook(CKTranscriptTableView)
133 MSClassHook(SBApplication)
134 MSClassHook(SBApplicationIcon)
135 MSClassHook(SBAwayView)
136 MSClassHook(SBBookmarkIcon)
137 MSClassHook(SBButtonBar)
138 MSClassHook(SBCalendarApplicationIcon)
139 MSClassHook(SBCalendarIconContentsView)
140 MSClassHook(SBDockIconListView)
142 MSClassHook(SBIconBadge)
143 MSClassHook(SBIconBadgeFactory)
144 MSClassHook(SBIconController)
145 MSClassHook(SBIconLabel)
146 MSClassHook(SBIconList)
147 MSClassHook(SBIconModel)
148 //MSClassHook(SBImageCache)
149 MSClassHook(SBSearchView)
150 MSClassHook(SBSearchTableViewCell)
151 MSClassHook(SBSlidingAlertDisplay)
152 MSClassHook(SBStatusBarContentsView)
153 MSClassHook(SBStatusBarController)
154 MSClassHook(SBStatusBarOperatorNameView)
155 MSClassHook(SBStatusBarTimeView)
156 MSClassHook(SBUIController)
157 MSClassHook(SBWallpaperView)
158 MSClassHook(SBWidgetApplicationIcon)
160 extern "C" void WKSetCurrentGraphicsContext(CGContextRef);
162 __attribute__((__constructor__))
163 static void MSFixClass() {
165 $SBIcon = objc_getClass("SBIconView");
166 if ($CKTranscriptController == nil)
167 $CKTranscriptController = objc_getClass("mSMSMessageTranscriptController");
171 static bool Four_($SBDockIconListView != nil);
173 @interface NSDictionary (WinterBoard)
174 - (UIColor *) wb$colorForKey:(NSString *)key;
175 - (BOOL) wb$boolForKey:(NSString *)key;
178 @implementation NSDictionary (WinterBoard)
180 - (UIColor *) wb$colorForKey:(NSString *)key {
181 NSString *value = [self objectForKey:key];
188 - (BOOL) wb$boolForKey:(NSString *)key {
189 if (NSString *value = [self objectForKey:key])
190 return [value boolValue];
196 static BOOL (*_GSFontGetUseLegacyFontMetrics)();
197 #define $GSFontGetUseLegacyFontMetrics() \
198 (_GSFontGetUseLegacyFontMetrics == NULL ? YES : _GSFontGetUseLegacyFontMetrics())
200 static bool Debug_ = false;
201 static bool UIDebug_ = false;
202 static bool Engineer_ = false;
203 static bool SummerBoard_ = true;
204 static bool SpringBoard_;
206 static UIImage *(*_UIApplicationImageWithName)(NSString *name);
207 static UIImage *(*_UIImageWithNameInDomain)(NSString *name, NSString *domain);
208 static NSBundle *(*_UIKitBundle)();
209 static bool (*_UIPackedImageTableGetIdentifierForName)(NSString *, int *);
210 static int (*_UISharedImageNameGetIdentifier)(NSString *);
212 static NSMutableDictionary *UIImages_ = [[NSMutableDictionary alloc] initWithCapacity:32];
213 static NSMutableDictionary *PathImages_ = [[NSMutableDictionary alloc] initWithCapacity:16];
214 static NSMutableDictionary *Cache_ = [[NSMutableDictionary alloc] initWithCapacity:64];
215 static NSMutableDictionary *Strings_ = [[NSMutableDictionary alloc] initWithCapacity:0];
216 static NSMutableDictionary *Bundles_ = [[NSMutableDictionary alloc] initWithCapacity:2];
218 static NSFileManager *Manager_;
219 static NSMutableArray *Themes_;
221 static NSDictionary *English_;
222 static NSMutableDictionary *Info_;
225 static NSMutableDictionary *Themed_ = [[NSMutableDictionary alloc] initWithCapacity:128];
227 static unsigned Scale_ = 0;
229 static unsigned $getScale$(NSString *path) {
230 NSString *name(path);
232 #define StripName(strip) \
233 if ([name hasSuffix:@ strip]) \
234 name = [name substringWithRange:NSMakeRange(0, [name length] - sizeof(strip) - 1)];
238 StripName("~iphone");
241 return [name hasSuffix:@"@2x"] ? 2 : 1;
244 static NSArray *$useScale$(NSArray *files, bool use = true) {
245 if (use && Scale_ == 0) {
246 UIScreen *screen([UIScreen mainScreen]);
247 if ([screen respondsToSelector:@selector(scale)])
248 Scale_ = [screen scale];
256 NSString *idiom(IsWild_ ? @"ipad" : @"iphone");
258 NSMutableArray *scaled([NSMutableArray arrayWithCapacity:([files count] * 4)]);
260 for (NSString *file in files) {
261 NSString *base([file stringByDeletingPathExtension]);
262 NSString *extension([file pathExtension]);
266 [scaled addObject:[NSString stringWithFormat:@"%@@2x~%@.%@", base, idiom, extension]];
268 [scaled addObject:[NSString stringWithFormat:@"%@@2x.%@", base, extension]];
271 [scaled addObject:[NSString stringWithFormat:@"%@~%@.%@", base, idiom, extension]];
273 // if (!IsWild_) <- support old themes
274 [scaled addObject:file];
275 } else if ([base hasSuffix: @"@2x"]) {
276 [scaled addObject:[NSString stringWithFormat:@"%@~iphone.%@", base, extension]];
277 [scaled addObject:file];
279 // XXX: this actually can't be used, as the person loading the file doesn't realize that the @2x changed
280 /*NSString *rest([base substringWithRange:NSMakeRange(0, [base length] - 3)]);
281 [scaled addObject:[NSString stringWithFormat:@"%@~iphone.%@", rest, extension]];
282 [scaled addObject:[rest stringByAppendingPathExtension:extension]];*/
284 // XXX: this code isn't really complete
286 [scaled addObject:file];
288 if ([base hasSuffix:@"~iphone"])
289 [scaled addObject:[[base substringWithRange:NSMakeRange(0, [base length] - 7)] stringByAppendingPathExtension:extension]];
296 static NSString *$getTheme$(NSArray *files, NSArray *themes = Themes_) {
297 // XXX: this is not reasonable; OMG
300 @synchronized (Themed_) {
301 if (NSString *path = [Themed_ objectForKey:key])
302 return reinterpret_cast<id>(path) == [NSNull null] ? nil : path;
306 NSLog(@"WB:Debug: %@", [files description]);
310 for (NSString *theme in Themes_)
311 for (NSString *file in files) {
312 path = [NSString stringWithFormat:@"%@/%@", theme, file];
313 if ([Manager_ fileExistsAtPath:path])
320 @synchronized (Themed_) {
321 [Themed_ setObject:(path == nil ? [NSNull null] : reinterpret_cast<id>(path)) forKey:key];
327 // $pathForFile$inBundle$() {{{
328 static NSString *$pathForFile$inBundle$(NSString *file, NSBundle *bundle, bool ui) {
329 NSString *identifier = [bundle bundleIdentifier];
330 NSMutableArray *names = [NSMutableArray arrayWithCapacity:8];
332 if (identifier != nil)
333 [names addObject:[NSString stringWithFormat:@"Bundles/%@/%@", identifier, file]];
334 if (NSString *folder = [[bundle bundlePath] lastPathComponent]) {
335 [names addObject:[NSString stringWithFormat:@"Folders/%@/%@", folder, file]];
336 NSString *base([folder stringByDeletingPathExtension]);
337 if ([base hasSuffix:@"~iphone"])
338 [names addObject:[NSString stringWithFormat:@"Folders/%@.%@/%@", [base substringWithRange:NSMakeRange(0, [base length] - 7)], [folder pathExtension], file]];
341 [names addObject:[NSString stringWithFormat:@"UIImages/%@", file]];
343 #define remapResourceName(oldname, newname) \
344 else if ([file isEqualToString:(oldname)]) \
345 [names addObject:[NSString stringWithFormat:@"%@.png", newname]]; \
347 bool summer(SpringBoard_ && SummerBoard_);
349 if (identifier == nil);
350 else if ([identifier isEqualToString:@"com.apple.chatkit"])
351 [names addObject:[NSString stringWithFormat:@"Bundles/com.apple.MobileSMS/%@", file]];
352 else if ([identifier isEqualToString:@"com.apple.calculator"])
353 [names addObject:[NSString stringWithFormat:@"Files/Applications/Calculator.app/%@", file]];
355 remapResourceName(@"FSO_BG.png", @"StatusBar")
356 remapResourceName(Four_ ? @"SBDockBG-old.png" : @"SBDockBG.png", @"Dock")
357 remapResourceName(@"SBWeatherCelsius.png", @"Icons/Weather")
359 [names addObject:[NSString stringWithFormat:@"Fallback/%@", file]];
361 if (NSString *path = $getTheme$($useScale$(names, ui)))
368 static NSString *$pathForIcon$(SBApplication *self, NSString *suffix = @"") {
369 NSString *identifier = [self bundleIdentifier];
370 NSString *path = [self path];
371 NSString *folder = [path lastPathComponent];
372 NSString *dname = [self displayName];
373 NSString *didentifier = [self displayIdentifier];
376 NSLog(@"WB:Debug: [SBApplication(%@:%@:%@:%@) pathForIcon]", identifier, folder, dname, didentifier);
378 NSMutableArray *names = [NSMutableArray arrayWithCapacity:8];
380 /* XXX: I might need to keep this for backwards compatibility
381 if (identifier != nil)
382 [names addObject:[NSString stringWithFormat:@"Bundles/%@/icon.png", identifier]];
384 [names addObject:[NSString stringWithFormat:@"Folders/%@/icon.png", folder]]; */
386 #define testForIcon(Name) \
387 if (NSString *name = Name) \
388 [names addObject:[NSString stringWithFormat:@"Icons%@/%@.png", suffix, name]];
390 if (![didentifier isEqualToString:identifier])
391 testForIcon(didentifier);
393 testForIcon(identifier);
396 if ([identifier isEqualToString:@"com.apple.MobileSMS"])
399 if (didentifier != nil) {
400 testForIcon([English_ objectForKey:didentifier]);
402 NSArray *parts = [didentifier componentsSeparatedByString:@"-"];
403 if ([parts count] != 1)
404 if (NSDictionary *english = [[[NSDictionary alloc] initWithContentsOfFile:[path stringByAppendingString:@"/English.lproj/UIRoleDisplayNames.strings"]] autorelease])
405 testForIcon([english objectForKey:[parts lastObject]]);
408 if (NSString *path = $getTheme$(names))
414 // -[NSBundle wb$bundleWithFile] {{{
415 @interface NSBundle (WinterBoard)
416 + (NSBundle *) wb$bundleWithFile:(NSString *)path;
419 @implementation NSBundle (WinterBoard)
421 + (NSBundle *) wb$bundleWithFile:(NSString *)path {
422 path = [path stringByDeletingLastPathComponent];
423 if (path == nil || [path length] == 0 || [path isEqualToString:@"/"])
426 NSBundle *bundle([Bundles_ objectForKey:path]);
427 if (reinterpret_cast<id>(bundle) == [NSNull null])
429 else if (bundle == nil) {
430 if ([Manager_ fileExistsAtPath:[path stringByAppendingPathComponent:@"Info.plist"]])
431 bundle = [NSBundle bundleWithPath:path];
433 bundle = [NSBundle wb$bundleWithFile:path];
435 NSLog(@"WB:Debug:PathBundle(%@, %@)", path, bundle);
436 [Bundles_ setObject:(bundle == nil ? [NSNull null] : reinterpret_cast<id>(bundle)) forKey:path];
444 // -[NSString wb$themedPath] {{{
445 @interface NSString (WinterBoard)
446 - (NSString *) wb$themedPath;
449 @implementation NSString (WinterBoard)
451 - (NSString *) wb$themedPath {
452 if ([self hasPrefix:@"/Library/Themes/"])
456 NSLog(@"WB:Debug:Bypass(\"%@\")", self);
458 if (NSBundle *bundle = [NSBundle wb$bundleWithFile:self]) {
459 NSString *file([self stringByResolvingSymlinksInPath]);
460 NSString *prefix([[bundle bundlePath] stringByResolvingSymlinksInPath]);
461 if ([file hasPrefix:prefix]) {
462 NSUInteger length([prefix length]);
463 if (length != [file length])
464 if (NSString *path = $pathForFile$inBundle$([file substringFromIndex:(length + 1)], bundle, false))
475 void WBLogRect(const char *tag, struct CGRect rect) {
476 NSLog(@"%s:{%f,%f+%f,%f}", tag, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
479 void WBLogHierarchy(UIView *view, unsigned index = 0, unsigned indent = 0) {
480 CGRect frame([view frame]);
481 NSLog(@"%*s|%2d:%p:%s : {%f,%f+%f,%f} (%@)", indent * 3, "", index, view, class_getName([view class]), frame.origin.x, frame.origin.y, frame.size.width, frame.size.height, [view backgroundColor]);
483 for (UIView *child in [view subviews])
484 WBLogHierarchy(child, index++, indent + 1);
487 UIImage *$cacheForImage$(UIImage *image) {
488 CGColorSpaceRef space(CGColorSpaceCreateDeviceRGB());
489 CGRect rect = {CGPointMake(1, 1), [image size]};
490 CGSize size = {rect.size.width + 2, rect.size.height + 2};
492 CGContextRef context(CGBitmapContextCreate(NULL, size.width, size.height, 8, 4 * size.width, space, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst));
493 CGColorSpaceRelease(space);
495 CGContextDrawImage(context, rect, [image CGImage]);
496 CGImageRef ref(CGBitmapContextCreateImage(context));
497 CGContextRelease(context);
499 UIImage *cache([UIImage imageWithCGImage:ref]);
505 /*MSHook(id, SBImageCache$initWithName$forImageWidth$imageHeight$initialCapacity$, SBImageCache *self, SEL sel, NSString *name, unsigned width, unsigned height, unsigned capacity) {
506 //if ([name isEqualToString:@"icons"]) return nil;
507 return _SBImageCache$initWithName$forImageWidth$imageHeight$initialCapacity$(self, sel, name, width, height, capacity);
510 MSHook(void, SBIconModel$cacheImageForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
511 NSString *key([icon displayIdentifier]);
513 if (UIImage *image = [icon icon]) {
514 CGSize size = [image size];
515 if (size.width != 59 || size.height != 60) {
516 UIImage *cache($cacheForImage$(image));
517 [Cache_ setObject:cache forKey:key];
522 _SBIconModel$cacheImageForIcon$(self, sel, icon);
525 MSHook(void, SBIconModel$cacheImagesForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
526 /* XXX: do I /really/ have to do this? figure out how to cache the small icon! */
527 _SBIconModel$cacheImagesForIcon$(self, sel, icon);
529 NSString *key([icon displayIdentifier]);
531 if (UIImage *image = [icon icon]) {
532 CGSize size = [image size];
533 if (size.width != 59 || size.height != 60) {
534 UIImage *cache($cacheForImage$(image));
535 [Cache_ setObject:cache forKey:key];
541 MSHook(UIImage *, SBIconModel$getCachedImagedForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
542 NSString *key([icon displayIdentifier]);
543 if (UIImage *image = [Cache_ objectForKey:key])
546 return _SBIconModel$getCachedImagedForIcon$(self, sel, icon);
549 MSHook(UIImage *, SBIconModel$getCachedImagedForIcon$smallIcon$, SBIconModel *self, SEL sel, SBIcon *icon, BOOL small) {
551 return _SBIconModel$getCachedImagedForIcon$smallIcon$(self, sel, icon, small);
552 NSString *key([icon displayIdentifier]);
553 if (UIImage *image = [Cache_ objectForKey:key])
556 return _SBIconModel$getCachedImagedForIcon$smallIcon$(self, sel, icon, small);
559 MSHook(id, SBSearchView$initWithFrame$, id /* XXX: SBSearchView */ self, SEL sel, struct CGRect frame) {
560 if ((self = _SBSearchView$initWithFrame$(self, sel, frame)) != nil) {
561 [self setBackgroundColor:[UIColor clearColor]];
562 for (UIView *child in [self subviews])
563 [child setBackgroundColor:[UIColor clearColor]];
567 MSHook(id, SBSearchTableViewCell$initWithStyle$reuseIdentifier$, SBSearchTableViewCell *self, SEL sel, int style, NSString *reuse) {
568 if ((self = _SBSearchTableViewCell$initWithStyle$reuseIdentifier$(self, sel, style, reuse)) != nil) {
569 [self setBackgroundColor:[UIColor clearColor]];
573 MSHook(void, SBSearchTableViewCell$drawRect$, SBSearchTableViewCell *self, SEL sel, struct CGRect rect, BOOL selected) {
574 _SBSearchTableViewCell$drawRect$(self, sel, rect, selected);
575 float inset([self edgeInset]);
576 [[UIColor clearColor] set];
577 UIRectFill(CGRectMake(0, 0, inset, rect.size.height));
578 UIRectFill(CGRectMake(rect.size.width - inset, 0, inset, rect.size.height));
581 MSHook(UIImage *, SBApplicationIcon$icon, SBApplicationIcon *self, SEL sel) {
582 if (![Info_ wb$boolForKey:@"ComposeStoreIcons"])
583 if (NSString *path = $pathForIcon$([self application]))
584 return [UIImage imageWithContentsOfFile:path];
585 return _SBApplicationIcon$icon(self, sel);
588 MSHook(UIImage *, SBApplicationIcon$generateIconImage$, SBApplicationIcon *self, SEL sel, int type) {
590 if (![Info_ wb$boolForKey:@"ComposeStoreIcons"]) {
591 if (IsWild_ && false) // XXX: delete this code, it should not be supported
592 if (NSString *path72 = $pathForIcon$([self application], @"-72"))
593 return [UIImage imageWithContentsOfFile:path72];
594 if (NSString *path = $pathForIcon$([self application]))
595 if (UIImage *image = [UIImage imageWithContentsOfFile:path]) {
597 if ([$SBIcon respondsToSelector:@selector(defaultIconImageSize)])
598 width = [$SBIcon defaultIconImageSize].width;
601 return width == 59 ? image : [image _imageScaledToProportion:(width / 59.0) interpolationQuality:5];
604 return _SBApplicationIcon$generateIconImage$(self, sel, type);
607 MSHook(UIImage *, SBWidgetApplicationIcon$icon, SBWidgetApplicationIcon *self, SEL sel) {
609 NSLog(@"WB:Debug:Widget(%@:%@)", [self displayIdentifier], [self displayName]);
610 if (NSString *path = $getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Icons/%@.png", [self displayName]]]))
611 return [UIImage imageWithContentsOfFile:path];
612 return _SBWidgetApplicationIcon$icon(self, sel);
615 MSHook(UIImage *, SBBookmarkIcon$icon, SBBookmarkIcon *self, SEL sel) {
617 NSLog(@"WB:Debug:Bookmark(%@:%@)", [self displayIdentifier], [self displayName]);
618 if (NSString *path = $getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Icons/%@.png", [self displayName]]]))
619 return [UIImage imageWithContentsOfFile:path];
620 return _SBBookmarkIcon$icon(self, sel);
623 MSHook(NSString *, SBApplication$pathForIcon, SBApplication *self, SEL sel) {
624 if (NSString *path = $pathForIcon$(self))
626 return _SBApplication$pathForIcon(self, sel);
629 static UIImage *CachedImageAtPath(NSString *path) {
630 path = [path stringByResolvingSymlinksInPath];
631 UIImage *image = [PathImages_ objectForKey:path];
633 return reinterpret_cast<id>(image) == [NSNull null] ? nil : image;
634 image = [[UIImage alloc] initWithContentsOfFile:path cache:true];
636 image = [image autorelease];
637 [PathImages_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:path];
641 MSHook(UIImage *, _UIApplicationImageWithName, NSString *name) {
642 NSBundle *bundle = [NSBundle mainBundle];
644 NSLog(@"WB:Debug: _UIApplicationImageWithName(\"%@\", %@)", name, bundle);
645 if (NSString *path = $pathForFile$inBundle$(name, bundle, false))
646 return CachedImageAtPath(path);
647 return __UIApplicationImageWithName(name);
650 #define WBDelegate(delegate) \
651 - (NSMethodSignature*) methodSignatureForSelector:(SEL)sel { \
653 NSLog(@"WB:MS:%s:(%s)", class_getName([self class]), sel_getName(sel)); \
654 if (NSMethodSignature *sig = [delegate methodSignatureForSelector:sel]) \
656 NSLog(@"WB:Error: [%s methodSignatureForSelector:(%s)]", class_getName([self class]), sel_getName(sel)); \
660 - (void) forwardInvocation:(NSInvocation*)inv { \
661 SEL sel = [inv selector]; \
662 if ([delegate respondsToSelector:sel]) \
663 [inv invokeWithTarget:delegate]; \
665 NSLog(@"WB:Error: [%s forwardInvocation:(%s)]", class_getName([self class]), sel_getName(sel)); \
668 // %hook -[NSBundle pathForResource:ofType:] {{{
669 MSInstanceMessageHook2(NSString *, NSBundle, pathForResource,ofType, NSString *, resource, NSString *, type) {
670 NSString *file = type == nil ? resource : [NSString stringWithFormat:@"%@.%@", resource, type];
672 NSLog(@"WB:Debug: [NSBundle(%@) pathForResource:\"%@\"]", [self bundleIdentifier], file);
673 if (NSString *path = $pathForFile$inBundle$(file, self, false))
675 return MSOldCall(resource, type);
679 static void $drawLabel$(NSString *label, CGRect rect, NSString *style, NSString *custom) {
680 bool ellipsis(false);
681 float max = rect.size.width - 11, width;
683 width = [(ellipsis ? [label stringByAppendingString:@"..."] : label) sizeWithStyle:style forWidth:320].width;
686 size_t length([label length]);
687 float spacing((width - max) / (length - 1));
689 if (spacing > 1.25) {
691 label = [label substringToIndex:(length - 1)];
695 style = [style stringByAppendingString:[NSString stringWithFormat:@"letter-spacing: -%f; ", spacing]];
699 label = [label stringByAppendingString:@"..."];
702 style = [style stringByAppendingString:custom];
704 CGSize size = [label sizeWithStyle:style forWidth:rect.size.width];
705 [label drawAtPoint:CGPointMake((rect.size.width - size.width) / 2 + rect.origin.x, rect.origin.y) withStyle:style];
708 static struct WBStringDrawingState {
709 WBStringDrawingState *next_;
713 } *stringDrawingState_;
715 MSInstanceMessageHook6(CGSize, NSString, drawAtPoint,forWidth,withFont,lineBreakMode,letterSpacing,includeEmoji, CGPoint, point, float, width, UIFont *, font, UILineBreakMode, mode, float, spacing, BOOL, emoji) {
716 WBStringDrawingState *state(stringDrawingState_);
718 return MSOldCall(point, width, font, mode, spacing, emoji);
720 if (--state->count_ == 0)
721 stringDrawingState_ = state->next_;
722 if (state->info_ == nil)
723 return MSOldCall(point, width, font, mode, spacing, emoji);
725 NSString *info([Info_ objectForKey:state->info_]);
727 return MSOldCall(point, width, font, mode, spacing, emoji);
729 NSString *base(state->base_ ?: @"");
730 NSString *extra([NSString stringWithFormat:@"letter-spacing: %gpx", spacing]);
731 [self drawAtPoint:point withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], extra, base, info]];
735 MSInstanceMessageHook7(CGSize, NSString, _drawInRect,withFont,lineBreakMode,alignment,lineSpacing,includeEmoji,truncationRect, CGRect, rect, UIFont *, font, UILineBreakMode, mode, UITextAlignment, alignment, float, spacing, BOOL, emoji, CGRect, truncation) {
736 WBStringDrawingState *state(stringDrawingState_);
738 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
740 if (--state->count_ == 0)
741 stringDrawingState_ = state->next_;
742 if (state->info_ == nil)
743 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
745 NSString *info([Info_ objectForKey:state->info_]);
747 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
752 case UITextAlignmentLeft:
755 case UITextAlignmentCenter:
756 textAlign = @"center";
758 case UITextAlignmentRight:
759 textAlign = @"right";
763 NSString *base(state->base_ ?: @"");
764 NSString *extra([NSString stringWithFormat:@"text-align: %@", textAlign]);
767 $drawLabel$(self, rect, [NSString stringWithFormat:@"%@;%@", [font markupDescription], base], info);
769 [self drawInRect:rect withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], extra, base, info]];
774 MSInstanceMessageHook4(CGSize, NSString, sizeWithFont,forWidth,lineBreakMode,letterSpacing, UIFont *, font, float, width, UILineBreakMode, mode, float, spacing) {
775 WBStringDrawingState *state(stringDrawingState_);
777 return MSOldCall(font, width, mode, spacing);
779 if (--state->count_ == 0)
780 stringDrawingState_ = state->next_;
781 if (state->info_ == nil)
782 return MSOldCall(font, width, mode, spacing);
784 NSString *info([Info_ objectForKey:state->info_]);
786 return MSOldCall(font, width, mode, spacing);
788 NSString *base(state->base_ ?: @"");
789 NSString *extra([NSString stringWithFormat:@"letter-spacing: %gpx", spacing]);
790 return [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], extra, base, info] forWidth:width];
793 MSInstanceMessageHook1(CGSize, NSString, sizeWithFont, UIFont *, font) {
794 WBStringDrawingState *state(stringDrawingState_);
796 return MSOldCall(font);
798 if (--state->count_ == 0)
799 stringDrawingState_ = state->next_;
800 if (state->info_ == nil)
801 return MSOldCall(font);
803 NSString *info([Info_ objectForKey:state->info_]);
805 return MSOldCall(font);
807 NSString *base(state->base_ ?: @"");
808 return [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@", [font markupDescription], base, info] forWidth:65535];
811 MSInstanceMessageHook1(UIImage *, SBIconBadgeFactory, checkoutBadgeImageForText, NSString *, text) {
812 WBStringDrawingState badgeState = {NULL, 1, @""
816 stringDrawingState_ = &badgeState;
818 UIImage *image(MSOldCall(text));
820 stringDrawingState_ = NULL;
824 MSInstanceMessageHook1(UIImage *, SBCalendarApplicationIcon, generateIconImage, int, type) {
825 WBStringDrawingState dayState = {NULL, 2, @""
827 // XXX: this is only correct on an iPod dock
828 "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px;"
829 , @"CalendarIconDayStyle"};
831 WBStringDrawingState sizeState = {&dayState, 7, nil, nil};
833 WBStringDrawingState dateState = {&sizeState, 2, @""
835 , @"CalendarIconDateStyle"};
837 stringDrawingState_ = &dateState;
839 UIImage *image(MSOldCall(type));
841 stringDrawingState_ = NULL;
845 MSHook(void, SBCalendarIconContentsView$drawRect$, SBCalendarIconContentsView *self, SEL sel, CGRect rect) {
846 NSBundle *bundle([NSBundle mainBundle]);
848 CFLocaleRef locale(CFLocaleCopyCurrent());
849 CFDateFormatterRef formatter(CFDateFormatterCreate(NULL, locale, kCFDateFormatterNoStyle, kCFDateFormatterNoStyle));
852 CFDateRef now(CFDateCreate(NULL, CFAbsoluteTimeGetCurrent()));
854 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NUMBER_FORMAT" value:@"d" table:@"SpringBoard"]);
855 CFStringRef date(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
856 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NAME_FORMAT" value:@"cccc" table:@"SpringBoard"]);
857 CFStringRef day(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
861 CFRelease(formatter);
863 NSString *datestyle([@""
864 "font-family: Helvetica; "
865 "font-weight: bold; "
868 "" stringByAppendingString:(IsWild_
869 ? @"font-size: 54px; "
870 : @"font-size: 39px; "
873 NSString *daystyle([@""
874 "font-family: Helvetica; "
875 "font-weight: bold; "
877 "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px; "
878 "" stringByAppendingString:(IsWild_
879 ? @"font-size: 11px; "
880 : @"font-size: 9px; "
883 if (NSString *style = [Info_ objectForKey:@"CalendarIconDateStyle"])
884 datestyle = [datestyle stringByAppendingString:style];
885 if (NSString *style = [Info_ objectForKey:@"CalendarIconDayStyle"])
886 daystyle = [daystyle stringByAppendingString:style];
888 float width([self bounds].size.width);
890 CGSize datesize = [(NSString *)date sizeWithStyle:datestyle forWidth:(width + leeway)];
891 CGSize daysize = [(NSString *)day sizeWithStyle:daystyle forWidth:(width + leeway)];
893 unsigned base0(IsWild_ ? 89 : 70);
894 if ($GSFontGetUseLegacyFontMetrics())
896 unsigned base1(IsWild_ ? 18 : 16);
903 [(NSString *)date drawAtPoint:CGPointMake(
904 (width + 1 - datesize.width) / 2, (base0 - datesize.height) / 2
905 ) withStyle:datestyle];
907 [(NSString *)day drawAtPoint:CGPointMake(
908 (width + 1 - daysize.width) / 2, (base1 - daysize.height) / 2
909 ) withStyle:daystyle];
915 // %hook -[{NavigationBar,Toolbar} setBarStyle:] {{{
916 void $setBarStyle$_(NSString *name, int &style) {
918 NSLog(@"WB:Debug:%@Style:%d", name, style);
919 NSNumber *number = nil;
921 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style-%d", name, style]];
923 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style", name]];
925 style = [number intValue];
927 NSLog(@"WB:Debug:%@Style=%d", name, style);
931 MSInstanceMessageHook1(void, UIToolbar, setBarStyle, int, style) {
932 $setBarStyle$_(@"Toolbar", style);
933 return MSOldCall(style);
936 MSInstanceMessageHook1(void, UINavigationBar, setBarStyle, int, style) {
937 $setBarStyle$_(@"NavigationBar", style);
938 return MSOldCall(style);
942 MSHook(void, SBButtonBar$didMoveToSuperview, UIView *self, SEL sel) {
943 [[self superview] setBackgroundColor:[UIColor clearColor]];
944 _SBButtonBar$didMoveToSuperview(self, sel);
947 MSHook(void, SBStatusBarContentsView$didMoveToSuperview, UIView *self, SEL sel) {
948 [[self superview] setBackgroundColor:[UIColor clearColor]];
949 _SBStatusBarContentsView$didMoveToSuperview(self, sel);
952 static NSArray *Wallpapers_;
953 static bool Papered_;
955 static bool SMSBackgrounded_;
956 static NSString *WallpaperFile_;
957 static UIImageView *WallpaperImage_;
958 static UIWebDocumentView *WallpaperPage_;
959 static NSURL *WallpaperURL_;
961 #define _release(object) \
962 do if (object != nil) { \
967 static UIImage *$getImage$(NSString *path) {
968 UIImage *image([UIImage imageWithContentsOfFile:path]);
970 unsigned scale($getScale$(path));
971 if (scale != 1 && [image respondsToSelector:@selector(setScale)])
972 [image setScale:scale];
977 static UIImage *$getDefaultDesktopImage$() {
978 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"LockBackground.png", @"LockBackground.jpg", nil])))
979 return $getImage$(path);
983 MSClassMessageHook0(UIImage *, UIImage, defaultDesktopImage) {
984 return $getDefaultDesktopImage$() ?: MSOldCall();
987 MSInstanceMessageHook0(UIImage *, SBSlidingAlertDisplay, _defaultDesktopImage) {
988 return $getDefaultDesktopImage$() ?: MSOldCall();
991 MSInstanceMessageHook0(void, SBWallpaperView, resetCurrentImageToWallpaper) {
992 for (UIView *parent([self superview]); parent != nil; parent = [parent superview])
993 if ([parent isKindOfClass:$SBSlidingAlertDisplay]) {
994 if (UIImage *image = $getDefaultDesktopImage$()) {
995 [self setImage:image];
1005 // %hook -[SBUIController init] {{{
1006 MSInstanceMessageHook0(id, SBUIController, init) {
1011 NSString *paper($getTheme$(Wallpapers_));
1013 paper = [paper stringByDeletingLastPathComponent];
1017 sysctlbyname("hw.machine", NULL, &size, NULL, 0);
1018 char *machine = new char[size];
1020 if (sysctlbyname("hw.machine", machine, &size, NULL, 0) == -1) {
1021 perror("sysctlbyname(\"hw.machine\", ?)");
1026 IsWild_ = machine != NULL && strncmp(machine, "iPad", 4) == 0;
1030 NSLog(@"WB:Debug:Info = %@", [Info_ description]);
1033 UIImageView *&_wallpaperView(MSHookIvar<UIImageView *>(self, "_wallpaperView"));
1034 if (&_wallpaperView != NULL) {
1035 [_wallpaperView removeFromSuperview];
1036 [_wallpaperView release];
1037 _wallpaperView = nil;
1041 UIView *&_contentLayer(MSHookIvar<UIView *>(self, "_contentLayer"));
1042 UIView *&_contentView(MSHookIvar<UIView *>(self, "_contentView"));
1045 if (&_contentLayer != NULL)
1046 player = &_contentLayer;
1047 else if (&_contentView != NULL)
1048 player = &_contentView;
1051 UIView *layer(player == NULL ? nil : *player);
1053 UIWindow *window([[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]);
1054 UIView *content([[[UIView alloc] initWithFrame:[window frame]] autorelease]);
1055 [window setContentView:content];
1057 UIWindow *&_window(MSHookIvar<UIWindow *>(self, "_window"));
1058 [window setBackgroundColor:[_window backgroundColor]];
1059 [_window setBackgroundColor:[UIColor clearColor]];
1061 [window setLevel:-1000];
1062 [window setHidden:NO];
1064 /*if (player != NULL)
1065 *player = content;*/
1067 [content setBackgroundColor:[layer backgroundColor]];
1068 [layer setBackgroundColor:[UIColor clearColor]];
1071 if (!SummerBoard_ || !IsWild_)
1074 CGRect bounds([content bounds]);
1075 bounds.origin.y = -30;
1076 indirect = [[[UIView alloc] initWithFrame:bounds] autorelease];
1077 [content addSubview:indirect];
1078 [indirect zoomToScale:2.4];
1081 _release(WallpaperFile_);
1082 _release(WallpaperImage_);
1083 _release(WallpaperPage_);
1084 _release(WallpaperURL_);
1087 NSArray *themes([NSArray arrayWithObject:paper]);
1089 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"], themes)) {
1093 static AVController *controller_(nil);
1094 if (controller_ == nil) {
1095 AVQueue *queue([AVQueue avQueue]);
1096 controller_ = [[AVController avControllerWithQueue:queue error:&error] retain];
1099 AVQueue *queue([controller_ queue]);
1101 UIView *video([[[UIView alloc] initWithFrame:[indirect bounds]] autorelease]);
1102 [controller_ setLayer:[video _layer]];
1104 AVItem *item([[[AVItem alloc] initWithPath:path error:&error] autorelease]);
1105 [queue appendItem:item error:&error];
1107 [controller_ play:&error];
1108 #elif UseMPMoviePlayerController
1109 NSURL *url([NSURL fileURLWithPath:path]);
1110 MPMoviePlayerController *controller = [[$MPMoviePlayerController alloc] initWithContentURL:url];
1111 controller.movieControlMode = MPMovieControlModeHidden;
1114 MPVideoView *video = [[[$MPVideoView alloc] initWithFrame:[indirect bounds]] autorelease];
1115 [video setMovieWithPath:path];
1116 [video setRepeatMode:1];
1117 [video setRepeatGap:-1];
1118 [video playFromBeginning];;
1121 [indirect addSubview:video];
1124 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"Wallpaper.png", @"Wallpaper.jpg", nil]), themes)) {
1125 if (UIImage *image = $getImage$(path)) {
1126 WallpaperFile_ = [path retain];
1127 WallpaperImage_ = [[UIImageView alloc] initWithImage:image];
1128 if (NSNumber *number = [Info_ objectForKey:@"WallpaperAlpha"])
1129 [WallpaperImage_ setAlpha:[number floatValue]];
1130 [indirect addSubview:WallpaperImage_];
1134 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.html"], themes)) {
1135 CGRect bounds = [indirect bounds];
1137 UIWebDocumentView *view([[[UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1138 [view setAutoresizes:true];
1140 WallpaperPage_ = [view retain];
1141 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
1143 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1145 [view setBackgroundColor:[UIColor clearColor]];
1146 if ([view respondsToSelector:@selector(setDrawsBackground:)])
1147 [view setDrawsBackground:NO];
1148 [[view webView] setDrawsBackground:NO];
1150 [indirect addSubview:view];
1154 for (size_t i(0), e([Themes_ count]); i != e; ++i) {
1155 NSString *theme = [Themes_ objectAtIndex:(e - i - 1)];
1156 NSString *html = [theme stringByAppendingPathComponent:@"Widget.html"];
1157 if ([Manager_ fileExistsAtPath:html]) {
1158 CGRect bounds = [indirect bounds];
1160 UIWebDocumentView *view([[[UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1161 [view setAutoresizes:true];
1163 NSURL *url = [NSURL fileURLWithPath:html];
1164 [view loadRequest:[NSURLRequest requestWithURL:url]];
1166 [view setBackgroundColor:[UIColor clearColor]];
1167 if ([view respondsToSelector:@selector(setDrawsBackground:)])
1168 [view setDrawsBackground:NO];
1169 [[view webView] setDrawsBackground:NO];
1171 [indirect addSubview:view];
1179 MSHook(void, SBAwayView$updateDesktopImage$, SBAwayView *self, SEL sel, UIImage *image) {
1180 NSString *path = $getTheme$([NSArray arrayWithObject:@"LockBackground.html"]);
1181 UIView *&_backgroundView(MSHookIvar<UIView *>(self, "_backgroundView"));
1183 if (path != nil && _backgroundView != nil)
1186 _SBAwayView$updateDesktopImage$(self, sel, image);
1189 CGRect bounds = [self bounds];
1191 UIWebDocumentView *view([[[UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1192 [view setAutoresizes:true];
1194 if (WallpaperPage_ != nil)
1195 [WallpaperPage_ release];
1196 WallpaperPage_ = [view retain];
1198 if (WallpaperURL_ != nil)
1199 [WallpaperURL_ release];
1200 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
1202 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1204 [[view webView] setDrawsBackground:false];
1205 [view setBackgroundColor:[UIColor clearColor]];
1207 [self insertSubview:view aboveSubview:_backgroundView];
1211 /*extern "C" CGColorRef CGGStateGetSystemColor(void *);
1212 extern "C" CGColorRef CGGStateGetFillColor(void *);
1213 extern "C" CGColorRef CGGStateGetStrokeColor(void *);
1214 extern "C" NSString *UIStyleStringFromColor(CGColorRef);*/
1216 /* WBTimeLabel {{{ */
1217 @interface WBTimeLabel : NSProxy {
1219 _transient SBStatusBarTimeView *view_;
1222 - (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view;
1226 @implementation WBTimeLabel
1233 - (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view {
1234 time_ = [time retain];
1239 - (NSString *) description {
1245 - (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(UILineBreakMode)mode {
1246 if (NSString *custom = [Info_ objectForKey:@"TimeStyle"]) {
1247 BOOL &_mode(MSHookIvar<BOOL>(view_, "_mode"));;
1249 [time_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1250 "font-family: Helvetica; "
1251 "font-weight: bold; "
1254 "%@", _mode ? @"white" : @"black", custom]];
1259 return [time_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1264 /* WBBadgeLabel {{{ */
1265 @interface WBBadgeLabel : NSProxy {
1269 - (id) initWithBadge:(NSString *)badge;
1270 - (NSString *) description;
1274 @implementation WBBadgeLabel
1281 - (id) initWithBadge:(NSString *)badge {
1282 badge_ = [badge retain];
1286 - (NSString *) description {
1287 return [badge_ description];
1292 - (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(UILineBreakMode)mode {
1293 if (NSString *custom = [Info_ objectForKey:@"BadgeStyle"]) {
1294 [badge_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1295 "font-family: Helvetica; "
1296 "font-weight: bold; "
1304 return [badge_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1311 MSInstanceMessageHook1(void, SBIcon, setIconImageAlpha, float, alpha) {
1312 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1313 alpha = [number floatValue];
1314 return MSOldCall(alpha);
1317 MSInstanceMessageHook1(void, SBIcon, setIconLabelAlpha, float, alpha) {
1318 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1319 alpha = [number floatValue];
1320 return MSOldCall(alpha);
1323 MSInstanceMessageHook0(id, SBIcon, initWithDefaultSize) {
1324 if ((self = MSOldCall()) != nil) {
1325 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"]) {
1326 // XXX: note: this is overridden above, which is silly
1327 float alpha([number floatValue]);
1328 [self setIconImageAlpha:alpha];
1329 [self setIconLabelAlpha:alpha];
1334 MSInstanceMessageHook1(void, SBIcon, setAlpha, float, alpha) {
1335 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1336 alpha = [number floatValue];
1337 return MSOldCall(alpha);
1341 MSHook(id, SBIconBadge$initWithBadge$, SBIconBadge *self, SEL sel, NSString *badge) {
1342 if ((self = _SBIconBadge$initWithBadge$(self, sel, badge)) != nil) {
1343 id &_badge(MSHookIvar<id>(self, "_badge"));
1345 if (id label = [[WBBadgeLabel alloc] initWithBadge:[_badge autorelease]])
1350 void SBStatusBarController$setStatusBarMode(int &mode) {
1352 NSLog(@"WB:Debug:setStatusBarMode:%d", mode);
1353 if (mode < 100) // 104:hidden 105:glowing
1354 if (NSNumber *number = [Info_ objectForKey:@"StatusBarMode"])
1355 mode = [number intValue];
1358 /*MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, double duration, int animation) {
1359 NSLog(@"mode:%d orientation:%d duration:%f animation:%d", mode, orientation, duration, animation);
1360 SBStatusBarController$setStatusBarMode(mode);
1361 return _SBStatusBarController$setStatusBarMode$orientation$duration$animation$(self, sel, mode, orientation, duration, animation);
1364 MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, float duration, int fenceID, int animation) {
1365 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d", mode, orientation, duration, fenceID, animation);
1366 SBStatusBarController$setStatusBarMode(mode);
1367 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$(self, sel, mode, orientation, duration, fenceID, animation);
1370 MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$startTime$, SBStatusBarController *self, SEL sel, int mode, int orientation, double duration, int fenceID, int animation, double startTime) {
1371 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d startTime:%f", mode, orientation, duration, fenceID, animation, startTime);
1372 SBStatusBarController$setStatusBarMode(mode);
1373 //NSLog(@"mode=%u", mode);
1374 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$startTime$(self, sel, mode, orientation, duration, fenceID, animation, startTime);
1377 /*MSHook(id, SBStatusBarContentsView$initWithStatusBar$mode$, SBStatusBarContentsView *self, SEL sel, id bar, int mode) {
1378 if (NSNumber *number = [Info_ objectForKey:@"StatusBarContentsMode"])
1379 mode = [number intValue];
1380 return _SBStatusBarContentsView$initWithStatusBar$mode$(self, sel, bar, mode);
1383 MSHook(NSString *, SBStatusBarOperatorNameView$operatorNameStyle, SBStatusBarOperatorNameView *self, SEL sel) {
1384 NSString *style(_SBStatusBarOperatorNameView$operatorNameStyle(self, sel));
1386 NSLog(@"operatorNameStyle= %@", style);
1387 if (NSString *custom = [Info_ objectForKey:@"OperatorNameStyle"])
1388 style = [NSString stringWithFormat:@"%@; %@", style, custom];
1392 MSHook(void, SBStatusBarOperatorNameView$setOperatorName$fullSize$, SBStatusBarOperatorNameView *self, SEL sel, NSString *name, BOOL full) {
1394 NSLog(@"setOperatorName:\"%@\" fullSize:%u", name, full);
1395 return _SBStatusBarOperatorNameView$setOperatorName$fullSize$(self, sel, name, NO);
1398 // XXX: replace this with [SBStatusBarTimeView tile]
1399 MSHook(void, SBStatusBarTimeView$drawRect$, SBStatusBarTimeView *self, SEL sel, CGRect rect) {
1400 id &_time(MSHookIvar<id>(self, "_time"));
1401 if (_time != nil && [_time class] != [WBTimeLabel class])
1402 object_setInstanceVariable(self, "_time", reinterpret_cast<void *>([[WBTimeLabel alloc] initWithTime:[_time autorelease] view:self]));
1403 return _SBStatusBarTimeView$drawRect$(self, sel, rect);
1406 @interface UIView (WinterBoard)
1407 - (bool) wb$isWBImageView;
1408 - (void) wb$logHierarchy;
1409 - (void) wb$setBackgroundColor:(UIColor *)color;
1412 @implementation UIView (WinterBoard)
1414 - (bool) wb$isWBImageView {
1418 - (void) wb$logHierarchy {
1419 WBLogHierarchy(self);
1422 - (void) wb$setBackgroundColor:(UIColor *)color {
1423 [self setBackgroundColor:color];
1424 for (UIView *child in [self subviews])
1425 [child wb$setBackgroundColor:color];
1430 @interface WBImageView : UIImageView {
1433 - (bool) wb$isWBImageView;
1434 - (void) wb$updateFrame;
1437 @implementation WBImageView
1439 - (bool) wb$isWBImageView {
1443 - (void) wb$updateFrame {
1444 CGRect frame([self frame]);
1447 for (UIView *view(self); ; ) {
1448 view = [view superview];
1451 frame.origin.y -= [view frame].origin.y;
1454 [self setFrame:frame];
1459 MSHook(void, SBIconList$setFrame$, SBIconList *self, SEL sel, CGRect frame) {
1460 NSArray *subviews([self subviews]);
1461 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1462 if (view != nil && [view wb$isWBImageView])
1463 [view wb$updateFrame];
1464 _SBIconList$setFrame$(self, sel, frame);
1467 MSHook(void, SBIconController$noteNumberOfIconListsChanged, SBIconController *self, SEL sel) {
1468 SBIconModel *&_iconModel(MSHookIvar<SBIconModel *>(self, "_iconModel"));
1469 NSArray *lists([_iconModel iconLists]);
1471 for (unsigned i(0), e([lists count]); i != e; ++i)
1472 if (NSString *path = $getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Page%u.png", i]])) {
1473 SBIconList *list([lists objectAtIndex:i]);
1474 NSArray *subviews([list subviews]);
1476 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1477 if (view == nil || ![view wb$isWBImageView]) {
1478 view = [[[WBImageView alloc] init] autorelease];
1479 [list insertSubview:view atIndex:0];
1482 UIImage *image([UIImage imageWithContentsOfFile:path]);
1484 CGRect frame([view frame]);
1485 frame.size = [image size];
1486 [view setFrame:frame];
1488 [view setImage:image];
1489 [view wb$updateFrame];
1492 return _SBIconController$noteNumberOfIconListsChanged(self, sel);
1495 MSHook(id, SBIconLabel$initWithSize$label$, SBIconLabel *self, SEL sel, CGSize size, NSString *label) {
1496 self = _SBIconLabel$initWithSize$label$(self, sel, size, label);
1498 [self setClipsToBounds:NO];
1502 MSHook(void, SBIconLabel$setInDock$, SBIconLabel *self, SEL sel, BOOL docked) {
1503 static bool gssc(false);
1505 BOOL (*GSSystemHasCapability)(CFStringRef) = reinterpret_cast<BOOL (*)(CFStringRef)>(dlsym(RTLD_DEFAULT, "GSSystemHasCapability"));
1506 Papered_ |= GSSystemHasCapability != NULL && GSSystemHasCapability(CFSTR("homescreen-wallpaper"));
1509 if ([Info_ objectForKey:@"UndockedIconLabels"] == nil)
1510 [Info_ setObject:[NSNumber numberWithBool:(
1512 [Info_ objectForKey:@"DockedIconLabelStyle"] != nil ||
1513 [Info_ objectForKey:@"UndockedIconLabelStyle"] != nil
1514 )] forKey:@"UndockedIconLabels"];
1517 id &_label(MSHookIvar<id>(self, "_label"));
1518 if (![Info_ wb$boolForKey:@"UndockedIconLabels"])
1521 if (_label != nil && [_label respondsToSelector:@selector(setInDock:)])
1522 [_label setInDock:docked];
1524 _SBIconLabel$setInDock$(self, sel, docked);
1525 [self setNeedsDisplay];
1528 MSHook(BOOL, SBDockIconListView$shouldShowNewDock, id self, SEL sel) {
1529 return SummerBoard_ && Docked_ ? NO : _SBDockIconListView$shouldShowNewDock(self, sel);
1532 MSHook(void, SBDockIconListView$setFrame$, id self, SEL sel, CGRect frame) {
1533 _SBDockIconListView$setFrame$(self, sel, frame);
1536 // %hook -[NSBundle localizedStringForKey:value:table:] {{{
1537 MSInstanceMessageHook3(NSString *, NSBundle, localizedStringForKey,value,table, NSString *, key, NSString *, value, NSString *, table) {
1538 NSString *identifier = [self bundleIdentifier];
1539 NSLocale *locale = [NSLocale currentLocale];
1540 NSString *language = [locale objectForKey:NSLocaleLanguageCode];
1542 NSLog(@"WB:Debug:[NSBundle(%@) localizedStringForKey:\"%@\" value:\"%@\" table:\"%@\"] (%@)", identifier, key, value, table, language);
1543 NSString *file = table == nil ? @"Localizable" : table;
1544 NSString *name = [NSString stringWithFormat:@"%@:%@", identifier, file];
1545 NSDictionary *strings;
1546 if ((strings = [Strings_ objectForKey:name]) != nil) {
1547 if (static_cast<id>(strings) != [NSNull null]) strings:
1548 if (NSString *value = [strings objectForKey:key])
1550 } else if (NSString *path = $pathForFile$inBundle$([NSString stringWithFormat:@"%@.lproj/%@.strings",
1553 if ((strings = [[NSDictionary alloc] initWithContentsOfFile:path]) != nil) {
1554 [Strings_ setObject:[strings autorelease] forKey:name];
1558 [Strings_ setObject:[NSNull null] forKey:name];
1559 return MSOldCall(key, value, table);
1562 // %hook -[WebCoreFrameBridge renderedSizeOfNode:constrainedToWidth:] {{{
1563 MSClassHook(WebCoreFrameBridge)
1565 MSInstanceMessageHook2(CGSize, WebCoreFrameBridge, renderedSizeOfNode,constrainedToWidth, id, node, float, width) {
1568 void **core(reinterpret_cast<void **>([node _node]));
1569 if (core == NULL || core[6] == NULL)
1571 return MSOldCall(node, width);
1575 MSInstanceMessage1(void, SBIconLabel, drawRect, CGRect, rect) {
1576 static Ivar drawMoreLegibly = object_getInstanceVariable(self, "_drawMoreLegibly", NULL);
1579 Ivar ivar = object_getInstanceVariable(self, "_inDock", reinterpret_cast<void **>(&docked));
1580 docked = (docked & (ivar_getOffset(ivar) == ivar_getOffset(drawMoreLegibly) ? 0x2 : 0x1)) != 0;
1582 NSString *label(MSHookIvar<NSString *>(self, "_label"));
1584 NSString *style = [NSString stringWithFormat:@""
1585 "font-family: Helvetica; "
1586 "font-weight: bold; "
1588 "", (docked || !SummerBoard_ ? @"white" : @"#b3b3b3"), (IsWild_
1589 ? @"font-size: 12px; "
1590 : @"font-size: 11px; "
1594 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px 1px 0px; "];
1596 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px -1px 0px; "];
1598 NSString *custom([Info_ objectForKey:(docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle")]);
1600 $drawLabel$(label, [self bounds], style, custom);
1603 MSInstanceMessage0(CGImageRef, SBIconLabel, buildLabelImage) {
1604 bool docked((MSHookIvar<unsigned>(self, "_inDock") & 0x2) != 0);
1606 WBStringDrawingState labelState = {NULL, 0, [NSString stringWithFormat:@""
1609 (docked || !SummerBoard_ ? @"white" : @"#b3b3b3")
1610 ], docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle"};
1612 stringDrawingState_ = &labelState;
1614 CGImageRef image(MSOldCall());
1616 stringDrawingState_ = NULL;
1621 MSInstanceMessageHook2(id, CKBalloonView, initWithFrame,delegate, CGRect, frame, id, delegate) {
1622 if ((self = MSOldCall(frame, delegate)) != nil) {
1623 [self setBackgroundColor:[UIColor clearColor]];
1627 MSInstanceMessageHook0(BOOL, CKBalloonView, _canUseLayerBackedBalloon) {
1628 return SMSBackgrounded_ ? NO : MSOldCall();
1631 MSInstanceMessageHook0(void, CKTranscriptHeaderView, layoutSubviews) {
1632 [self wb$setBackgroundColor:[UIColor clearColor]];
1636 MSInstanceMessageHook1(void, CKMessageCell, addBalloonView, CKBalloonView *, balloon) {
1638 [balloon setBackgroundColor:[UIColor clearColor]];
1641 MSInstanceMessageHook1(void, CKTranscriptCell, setBackgroundColor, UIColor *, color) {
1642 MSOldCall([UIColor clearColor]);
1643 [[self contentView] wb$setBackgroundColor:[UIColor clearColor]];
1647 MSInstanceMessageHook2(id, CKTranscriptCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1648 if ((self = MSOldCall(style, reuse)) != nil) {
1649 [self setBackgroundColor:[UIColor clearColor]];
1650 [[self contentView] wb$setBackgroundColor:[UIColor clearColor]];
1655 MSInstanceMessageHook2(id, CKMessageCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1656 if ((self = MSOldCall(style, reuse)) != nil) {
1657 [self setBackgroundColor:[UIColor clearColor]];
1658 [[self contentView] setBackgroundColor:[UIColor clearColor]];
1662 MSInstanceMessageHook2(id, CKTimestampView, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1663 if ((self = MSOldCall(style, reuse)) != nil) {
1664 UILabel *&_label(MSHookIvar<UILabel *>(self, "_label"));
1665 [_label setBackgroundColor:[UIColor clearColor]];
1669 MSInstanceMessageHook1(void, CKTranscriptTableView, setSeparatorStyle, int, style) {
1670 MSOldCall(UITableViewCellSeparatorStyleNone);
1673 MSInstanceMessageHook2(id, CKTranscriptTableView, initWithFrame,style, CGRect, frame, int, style) {
1674 if ((self = MSOldCall(frame, style)) != nil) {
1675 [self setSeparatorStyle:UITableViewCellSeparatorStyleNone];
1679 MSInstanceMessageHook0(void, CKTranscriptController, loadView) {
1682 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"SMSBackground.png", @"SMSBackground.jpg", nil])))
1683 if (UIImage *image = $getImage$(path)) {
1684 SMSBackgrounded_ = true;
1686 UIView *&_transcriptTable(MSHookIvar<UIView *>(self, "_transcriptTable"));
1687 UIView *&_transcriptLayer(MSHookIvar<UIView *>(self, "_transcriptLayer"));
1689 if (&_transcriptTable != NULL)
1690 table = _transcriptTable;
1691 else if (&_transcriptLayer != NULL)
1692 table = _transcriptLayer;
1696 UIView *placard(table != nil ? [table superview] : MSHookIvar<UIView *>(self, "_backPlacard"));
1697 UIImageView *background([[[UIImageView alloc] initWithImage:image] autorelease]);
1700 [placard insertSubview:background atIndex:0];
1702 [table setBackgroundColor:[UIColor clearColor]];
1703 [placard insertSubview:background belowSubview:table];
1709 // %hook _UIImageWithName() {{{
1710 MSHook(UIImage *, _UIImageWithName, NSString *name) {
1712 NSLog(@"WB:Debug: _UIImageWithName(\"%@\")", name);
1719 if (_UIPackedImageTableGetIdentifierForName != NULL)
1720 packed = _UIPackedImageTableGetIdentifierForName(name, &identifier);
1721 else if (_UISharedImageNameGetIdentifier != NULL) {
1722 identifier = _UISharedImageNameGetIdentifier(name);
1723 packed = identifier != -1;
1730 NSLog(@"WB:Debug: _UISharedImageNameGetIdentifier(\"%@\") = %d", name, identifier);
1733 return __UIImageWithName(name);
1735 NSNumber *key([NSNumber numberWithInt:identifier]);
1736 UIImage *image([UIImages_ objectForKey:key]);
1738 return reinterpret_cast<id>(image) == [NSNull null] ? __UIImageWithName(name) : image;
1739 if (NSString *path = $pathForFile$inBundle$(name, _UIKitBundle(), true))
1740 image = $getImage$(path);
1741 [UIImages_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:key];
1745 image = __UIImageWithName(name);
1748 NSString *path([@"/tmp/UIImages/" stringByAppendingString:name]);
1749 if (![Manager_ fileExistsAtPath:path])
1750 [UIImagePNGRepresentation(image) writeToFile:path atomically:YES];
1757 // %hook _UIImageWithNameInDomain() {{{
1758 MSHook(UIImage *, _UIImageWithNameInDomain, NSString *name, NSString *domain) {
1759 NSString *key([NSString stringWithFormat:@"D:%zu%@%@", [domain length], domain, name]);
1760 UIImage *image([PathImages_ objectForKey:key]);
1762 return reinterpret_cast<id>(image) == [NSNull null] ? __UIImageWithNameInDomain(name, domain) : image;
1764 NSLog(@"WB:Debug: UIImageWithNameInDomain(\"%@\", \"%@\")", name, domain);
1765 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObject:[NSString stringWithFormat:@"Domains/%@/%@", domain, name]])))
1766 image = $getImage$(path);
1767 [PathImages_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:key];
1768 return image == nil ? __UIImageWithNameInDomain(name, domain) : image;
1772 // %hook GSFontCreateWithName() {{{
1773 MSHook(GSFontRef, GSFontCreateWithName, const char *name, GSFontSymbolicTraits traits, float size) {
1775 NSLog(@"WB:Debug: GSFontCreateWithName(\"%s\", %f)", name, size);
1776 if (NSString *font = [Info_ objectForKey:[NSString stringWithFormat:@"FontName-%s", name]])
1777 name = [font UTF8String];
1778 //if (NSString *scale = [Info_ objectForKey:[NSString stringWithFormat:@"FontScale-%s", name]])
1779 // size *= [scale floatValue];
1780 return _GSFontCreateWithName(name, traits, size);
1784 #define AudioToolbox "/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox"
1785 #define UIKit "/System/Library/Frameworks/UIKit.framework/UIKit"
1787 bool (*_Z24GetFileNameForThisActionmPcRb)(unsigned long a0, char *a1, bool &a2);
1789 MSHook(bool, _Z24GetFileNameForThisActionmPcRb, unsigned long a0, char *a1, bool &a2) {
1791 NSLog(@"WB:Debug:GetFileNameForThisAction(%u, %p, %u)", a0, a1, a2);
1792 bool value = __Z24GetFileNameForThisActionmPcRb(a0, a1, a2);
1794 NSLog(@"WB:Debug:GetFileNameForThisAction(%u, %s, %u) = %u", a0, value ? a1 : NULL, a2, value);
1797 NSString *path = [NSString stringWithUTF8String:a1];
1798 if ([path hasPrefix:@"/System/Library/Audio/UISounds/"]) {
1799 NSString *file = [path substringFromIndex:31];
1800 for (NSString *theme in Themes_) {
1801 NSString *path([NSString stringWithFormat:@"%@/UISounds/%@", theme, file]);
1802 if ([Manager_ fileExistsAtPath:path]) {
1803 strcpy(a1, [path UTF8String]);
1812 static void ChangeWallpaper(
1813 CFNotificationCenterRef center,
1817 CFDictionaryRef info
1820 NSLog(@"WB:Debug:ChangeWallpaper!");
1823 if (WallpaperFile_ != nil) {
1824 image = [[UIImage alloc] initWithContentsOfFile:WallpaperFile_];
1826 image = [image autorelease];
1829 if (WallpaperImage_ != nil)
1830 [WallpaperImage_ setImage:image];
1831 if (WallpaperPage_ != nil)
1832 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1836 #define WBRename(name, sel, imp) \
1837 _ ## name ## $ ## imp = MSHookMessage($ ## name, @selector(sel), &$ ## name ## $ ## imp)
1839 template <typename Type_>
1840 static void msset(Type_ &function, MSImageRef image, const char *name) {
1841 function = reinterpret_cast<Type_>(MSFindSymbol(image, name));
1844 template <typename Type_>
1845 static void nlset(Type_ &function, struct nlist *nl, size_t index) {
1846 struct nlist &name(nl[index]);
1847 uintptr_t value(name.n_value);
1848 if ((name.n_desc & N_ARM_THUMB_DEF) != 0)
1849 value |= 0x00000001;
1850 function = reinterpret_cast<Type_>(value);
1853 template <typename Type_>
1854 static void dlset(Type_ &function, const char *name) {
1855 function = reinterpret_cast<Type_>(dlsym(RTLD_DEFAULT, name));
1858 // %hook CGImageReadCreateWithFile() {{{
1859 MSHook(void *, CGImageReadCreateWithFile, NSString *path, int flag) {
1861 NSLog(@"WB:Debug: CGImageReadCreateWithFile(%@, %d)", path, flag);
1862 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
1863 void *value(_CGImageReadCreateWithFile([path wb$themedPath], flag));
1869 static void NSString$drawAtPoint$withStyle$(NSString *self, SEL _cmd, CGPoint point, NSString *style) {
1870 WKSetCurrentGraphicsContext(UIGraphicsGetCurrentContext());
1871 if (style == nil || [style length] == 0)
1872 style = @"font-family: Helvetica; font-size: 12px";
1873 return [[WBMarkup sharedMarkup] drawString:self atPoint:point withStyle:style];
1876 static void NSString$drawInRect$withStyle$(NSString *self, SEL _cmd, CGRect rect, NSString *style) {
1877 WKSetCurrentGraphicsContext(UIGraphicsGetCurrentContext());
1878 if (style == nil || [style length] == 0)
1879 style = @"font-family: Helvetica; font-size: 12px";
1880 return [[WBMarkup sharedMarkup] drawString:self inRect:rect withStyle:style];
1883 static CGSize NSString$sizeWithStyle$forWidth$(NSString *self, SEL _cmd, NSString *style, float width) {
1884 if (style == nil || [style length] == 0)
1885 style = @"font-family: Helvetica; font-size: 12px";
1886 return [[WBMarkup sharedMarkup] sizeOfString:self withStyle:style forWidth:width];
1889 static void SBInitialize() {
1890 class_addMethod($NSString, @selector(drawAtPoint:withStyle:), (IMP) &NSString$drawAtPoint$withStyle$, "v20@0:4{CGPoint=ff}8@16");
1891 class_addMethod($NSString, @selector(drawInRect:withStyle:), (IMP) &NSString$drawInRect$withStyle$, "v28@0:4{CGRect={CGSize=ff}{CGSize=ff}}8@24");
1892 class_addMethod($NSString, @selector(sizeWithStyle:forWidth:), (IMP) &NSString$sizeWithStyle$forWidth$, "{CGSize=ff}16@0:4@8f12");
1895 WBRename(SBApplication, pathForIcon, pathForIcon);
1896 WBRename(SBApplicationIcon, icon, icon);
1897 WBRename(SBApplicationIcon, generateIconImage:, generateIconImage$);
1900 WBRename(SBBookmarkIcon, icon, icon);
1901 WBRename(SBButtonBar, didMoveToSuperview, didMoveToSuperview);
1902 WBRename(SBCalendarIconContentsView, drawRect:, drawRect$);
1903 WBRename(SBIconBadge, initWithBadge:, initWithBadge$);
1904 WBRename(SBIconController, noteNumberOfIconListsChanged, noteNumberOfIconListsChanged);
1906 WBRename(SBWidgetApplicationIcon, icon, icon);
1908 WBRename(SBDockIconListView, setFrame:, setFrame$);
1909 MSHookMessage(object_getClass($SBDockIconListView), @selector(shouldShowNewDock), &$SBDockIconListView$shouldShowNewDock, &_SBDockIconListView$shouldShowNewDock);
1911 if (kCFCoreFoundationVersionNumber < 600)
1912 WBRename(SBIconLabel, drawRect:, drawRect$);
1914 WBRename(SBIconLabel, buildLabelImage, buildLabelImage);
1916 WBRename(SBIconLabel, initWithSize:label:, initWithSize$label$);
1917 WBRename(SBIconLabel, setInDock:, setInDock$);
1919 WBRename(SBIconList, setFrame:, setFrame$);
1921 WBRename(SBIconModel, cacheImageForIcon:, cacheImageForIcon$);
1922 WBRename(SBIconModel, cacheImagesForIcon:, cacheImagesForIcon$);
1923 WBRename(SBIconModel, getCachedImagedForIcon:, getCachedImagedForIcon$);
1924 WBRename(SBIconModel, getCachedImagedForIcon:smallIcon:, getCachedImagedForIcon$smallIcon$);
1926 WBRename(SBSearchView, initWithFrame:, initWithFrame$);
1927 WBRename(SBSearchTableViewCell, drawRect:, drawRect$);
1928 WBRename(SBSearchTableViewCell, initWithStyle:reuseIdentifier:, initWithStyle$reuseIdentifier$);
1930 //WBRename(SBImageCache, initWithName:forImageWidth:imageHeight:initialCapacity:, initWithName$forImageWidth$imageHeight$initialCapacity$);
1932 WBRename(SBAwayView, updateDesktopImage:, updateDesktopImage$);
1933 WBRename(SBStatusBarContentsView, didMoveToSuperview, didMoveToSuperview);
1934 //WBRename(SBStatusBarContentsView, initWithStatusBar:mode:, initWithStatusBar$mode$);
1935 //WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:animation:, setStatusBarMode$orientation$duration$animation$);
1936 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:, setStatusBarMode$orientation$duration$fenceID$animation$);
1937 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:startTime:, setStatusBarMode$orientation$duration$fenceID$animation$startTime$);
1938 WBRename(SBStatusBarOperatorNameView, operatorNameStyle, operatorNameStyle);
1939 WBRename(SBStatusBarOperatorNameView, setOperatorName:fullSize:, setOperatorName$fullSize$);
1940 WBRename(SBStatusBarTimeView, drawRect:, drawRect$);
1943 English_ = [[NSDictionary alloc] initWithContentsOfFile:@"/System/Library/CoreServices/SpringBoard.app/English.lproj/LocalizedApplicationNames.strings"];
1947 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
1949 NSString *identifier([[NSBundle mainBundle] bundleIdentifier]);
1950 SpringBoard_ = [identifier isEqualToString:@"com.apple.springboard"];
1952 Manager_ = [[NSFileManager defaultManager] retain];
1953 Themes_ = [[NSMutableArray alloc] initWithCapacity:8];
1955 dlset(_GSFontGetUseLegacyFontMetrics, "GSFontGetUseLegacyFontMetrics");
1957 // Load Settings.plist {{{
1958 if (NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"/User/Library/Preferences/com.saurik.WinterBoard.plist"]]) {
1959 if (NSNumber *value = [settings objectForKey:@"SummerBoard"])
1960 SummerBoard_ = [value boolValue];
1961 if (NSNumber *value = [settings objectForKey:@"Debug"])
1962 Debug_ = [value boolValue];
1963 if (NSNumber *value = [settings objectForKey:@"RecordUI"])
1964 UIDebug_ = [value boolValue];
1966 NSArray *themes([settings objectForKey:@"Themes"]);
1968 if (NSString *theme = [settings objectForKey:@"Theme"])
1969 themes = [NSArray arrayWithObject:[NSDictionary dictionaryWithObjectsAndKeys:
1971 [NSNumber numberWithBool:true], @"Active",
1975 for (NSDictionary *theme in themes) {
1976 NSNumber *active([theme objectForKey:@"Active"]);
1977 if (![active boolValue])
1980 NSString *name([theme objectForKey:@"Name"]);
1984 NSString *theme(nil);
1986 #define testForTheme(format...) \
1987 if (theme == nil) { \
1988 NSString *path = [NSString stringWithFormat:format]; \
1989 if ([Manager_ fileExistsAtPath:path]) { \
1990 [Themes_ addObject:path]; \
1995 testForTheme(@"/Library/Themes/%@.theme", name)
1996 testForTheme(@"/Library/Themes/%@", name)
1997 testForTheme(@"%@/Library/SummerBoard/Themes/%@", NSHomeDirectory(), name)
2002 // Merge Info.plist {{{
2003 Info_ = [[NSMutableDictionary dictionaryWithCapacity:16] retain];
2005 for (NSString *theme in Themes_)
2006 if (NSDictionary *info = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"%@/Info.plist", theme]])
2007 for (NSString *key in [info allKeys])
2008 if ([Info_ objectForKey:key] == nil)
2009 [Info_ setObject:[info objectForKey:key] forKey:key];
2013 if (MSImageRef image = MSGetImageByName(AudioToolbox)) {
2014 msset(_Z24GetFileNameForThisActionmPcRb, image, "__Z24GetFileNameForThisActionmPcRb");
2015 MSHookFunction(_Z24GetFileNameForThisActionmPcRb, &$_Z24GetFileNameForThisActionmPcRb, &__Z24GetFileNameForThisActionmPcRb);
2018 // GraphicsServices {{{
2020 MSHookFunction(&GSFontCreateWithName, &$GSFontCreateWithName, &_GSFontCreateWithName);
2024 if (MSImageRef image = MSGetImageByName("/System/Library/Frameworks/ImageIO.framework/ImageIO")) {
2025 void *(*CGImageReadCreateWithFile)(NSString *, int);
2026 msset(CGImageReadCreateWithFile, image, "_CGImageReadCreateWithFile");
2027 MSHookFunction(CGImageReadCreateWithFile, MSHake(CGImageReadCreateWithFile));
2032 Wallpapers_ = [[NSArray arrayWithObjects:@"Wallpaper.mp4", @"Wallpaper@2x.png", @"Wallpaper@2x.jpg", @"Wallpaper.png", @"Wallpaper.jpg", @"Wallpaper.html", nil] retain];
2033 Papered_ = $getTheme$(Wallpapers_) != nil;
2034 Docked_ = $getTheme$([NSArray arrayWithObjects:@"Dock.png", nil]) != nil;
2036 CFNotificationCenterAddObserver(
2037 CFNotificationCenterGetDarwinNotifyCenter(),
2038 NULL, &ChangeWallpaper, (CFStringRef) @"com.saurik.winterboard.lockbackground", NULL, 0
2041 if ($getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"]) != nil) {
2042 NSBundle *MediaPlayer([NSBundle bundleWithPath:@"/System/Library/Frameworks/MediaPlayer.framework"]);
2043 if (MediaPlayer != nil)
2046 $MPMoviePlayerController = objc_getClass("MPMoviePlayerController");
2047 $MPVideoView = objc_getClass("MPVideoView");
2054 if ([NSBundle bundleWithIdentifier:@"com.apple.UIKit"] != nil) {
2056 memset(nl, 0, sizeof(nl));
2057 nl[0].n_un.n_name = (char *) "__UIApplicationImageWithName";
2058 nl[1].n_un.n_name = (char *) "__UIImageWithNameInDomain";
2059 nl[2].n_un.n_name = (char *) "__UIKitBundle";
2060 nl[3].n_un.n_name = (char *) "__UIPackedImageTableGetIdentifierForName";
2061 nl[4].n_un.n_name = (char *) "__UISharedImageNameGetIdentifier";
2064 nlset(_UIApplicationImageWithName, nl, 0);
2065 nlset(_UIImageWithNameInDomain, nl, 1);
2066 nlset(_UIKitBundle, nl, 2);
2067 nlset(_UIPackedImageTableGetIdentifierForName, nl, 3);
2068 nlset(_UISharedImageNameGetIdentifier, nl, 4);
2070 MSHookFunction(_UIApplicationImageWithName, &$_UIApplicationImageWithName, &__UIApplicationImageWithName);
2071 MSHookFunction(_UIImageWithName, &$_UIImageWithName, &__UIImageWithName);
2072 MSHookFunction(_UIImageWithNameInDomain, &$_UIImageWithNameInDomain, &__UIImageWithNameInDomain);
2076 if (UIDebug_ && ![Manager_ fileExistsAtPath:@"/tmp/UIImages"]) {
2077 NSError *error(nil);
2078 if (![Manager_ createDirectoryAtPath:@"/tmp/UIImages" withIntermediateDirectories:NO attributes:[NSDictionary dictionaryWithObjectsAndKeys:
2079 [NSNumber numberWithShort:0777], NSFilePosixPermissions,
2081 NSLog(@"WB:Error: cannot create /tmp/UIImages (%@)", error);