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/>.
27 #define _trace() do { \
28 struct timeval _ctv; \
29 gettimeofday(&_ctv, NULL); \
34 NSLog(@"%lu.%.6u[%f]:WB:_trace()@%s:%u[%s]\n", \
35 _ctv.tv_sec, _ctv.tv_usec, \
36 (_ctv.tv_sec - _ltv.tv_sec) + (_ctv.tv_usec - _ltv.tv_usec) / 1000000.0, \
37 __FILE__, __LINE__, __FUNCTION__\
44 #import <CoreFoundation/CoreFoundation.h>
45 #import <Foundation/Foundation.h>
46 #import <CoreGraphics/CoreGraphics.h>
47 #import <ImageIO/CGImageSource.h>
49 #import <Celestial/AVController.h>
50 #import <Celestial/AVItem.h>
51 #import <Celestial/AVQueue.h>
53 #include <substrate.h>
55 #import <UIKit/UIKit.h>
57 #import <SpringBoard/SBApplication.h>
58 #import <SpringBoard/SBApplicationIcon.h>
59 #import <SpringBoard/SBAppWindow.h>
60 #import <SpringBoard/SBAwayView.h>
61 #import <SpringBoard/SBBookmarkIcon.h>
62 #import <SpringBoard/SBButtonBar.h>
63 #import <SpringBoard/SBCalendarIconContentsView.h>
64 #import <SpringBoard/SBIconController.h>
65 #import <SpringBoard/SBIconLabel.h>
66 #import <SpringBoard/SBIconList.h>
67 #import <SpringBoard/SBIconModel.h>
68 #import <SpringBoard/SBImageCache.h>
69 // XXX: #import <SpringBoard/SBSearchView.h>
70 #import <SpringBoard/SBSearchTableViewCell.h>
71 #import <SpringBoard/SBStatusBarContentsView.h>
72 #import <SpringBoard/SBStatusBarController.h>
73 #import <SpringBoard/SBStatusBarOperatorNameView.h>
74 #import <SpringBoard/SBStatusBarTimeView.h>
75 #import <SpringBoard/SBUIController.h>
76 #import <SpringBoard/SBWidgetApplicationIcon.h>
78 #import <MobileSMS/mSMSMessageTranscriptController.h>
80 #import <MediaPlayer/MPMoviePlayerController.h>
81 #import <MediaPlayer/MPVideoView.h>
82 #import <MediaPlayer/MPVideoView-PlaybackControl.h>
84 #import <CoreGraphics/CGGeometry.h>
86 #import <ChatKit/CKMessageCell.h>
88 #include <sys/sysctl.h>
92 static void (*$objc_setAssociatedObject)(id object, void *key, id value, objc_AssociationPolicy policy);
93 static id (*$objc_getAssociatedObject)(id object, void *key);
94 static void (*$objc_removeAssociatedObjects)(id object);
100 Class $MPMoviePlayerController;
103 MSClassHook(NSBundle)
104 MSClassHook(NSString)
105 MSClassHook(NSAttributedString)
107 MSClassHook(_UIAssetManager)
109 MSMetaClassHook(UIImage)
110 MSClassHook(UINavigationBar)
111 MSClassHook(UISharedArtwork)
112 MSClassHook(UIToolbar)
113 MSClassHook(UIStatusBarTimeItemView)
114 MSClassHook(UIWebDocumentView)
116 MSClassHook(CKBalloonView)
117 MSClassHook(CKMessageCell)
118 MSClassHook(CKTimestampView)
119 MSClassHook(CKTranscriptCell)
120 MSClassHook(CKTranscriptController)
121 MSClassHook(CKTranscriptHeaderView)
122 MSClassHook(CKTranscriptTableView)
124 MSClassHook(SBApplication)
125 MSClassHook(SBApplicationIcon)
126 MSClassHook(SBAwayView)
127 MSClassHook(SBBookmarkIcon)
128 MSClassHook(SBButtonBar)
129 MSClassHook(SBCalendarApplicationIcon)
130 MSClassHook(SBCalendarIconContentsView)
131 MSClassHook(SBDockIconListView)
133 MSClassHook(SBIconAccessoryImage)
134 MSMetaClassHook(SBIconAccessoryImage)
135 MSClassHook(SBIconBadge)
136 MSClassHook(SBIconBadgeFactory)
137 MSClassHook(SBIconBadgeImage)
138 MSClassHook(SBIconBadgeView)
139 MSMetaClassHook(SBIconBadgeView)
140 MSClassHook(SBIconContentView)
141 MSClassHook(SBIconController)
142 MSClassHook(SBIconLabel)
143 MSClassHook(SBIconLabelImage)
144 MSMetaClassHook(SBIconLabelImage)
145 MSClassHook(SBIconLabelImageParameters)
146 MSClassHook(SBIconList)
147 MSClassHook(SBIconModel)
148 MSClassHook(SBIconView)
149 MSMetaClassHook(SBIconView)
150 //MSClassHook(SBImageCache)
151 MSClassHook(SBSearchView)
152 MSClassHook(SBSearchTableViewCell)
153 MSClassHook(SBSlidingAlertDisplay)
154 MSClassHook(SBStatusBarContentsView)
155 MSClassHook(SBStatusBarController)
156 MSClassHook(SBStatusBarOperatorNameView)
157 MSClassHook(SBStatusBarTimeView)
158 MSClassHook(SBUIController)
159 MSClassHook(SBWallpaperView)
160 MSClassHook(SBWidgetApplicationIcon)
162 extern "C" void WKSetCurrentGraphicsContext(CGContextRef);
164 static struct MSFixClass { MSFixClass() {
165 $UIWebDocumentView = objc_getClass("UIWebBrowserView") ?: $UIWebDocumentView;
166 $SBIcon = objc_getClass("SBIconView") ?: $SBIcon;
168 if ($SBIconList == nil)
169 $SBIconList = objc_getClass("SBIconListView");
170 if ($CKTranscriptController == nil)
171 $CKTranscriptController = objc_getClass("mSMSMessageTranscriptController");
175 static bool Four_($SBDockIconListView != nil);
177 @interface NSObject (wb$SBIconAccessoryImage)
178 + (Class) _imageClassForIcon:(SBIcon *)icon location:(int)location;
181 @interface NSDictionary (WinterBoard)
182 - (UIColor *) wb$colorForKey:(NSString *)key;
183 - (BOOL) wb$boolForKey:(NSString *)key;
186 @implementation NSDictionary (WinterBoard)
188 - (UIColor *) wb$colorForKey:(NSString *)key {
189 NSString *value = [self objectForKey:key];
196 - (BOOL) wb$boolForKey:(NSString *)key {
197 if (NSString *value = [self objectForKey:key])
198 return [value boolValue];
204 @interface _UIAssetManager : NSObject
205 - (NSBundle *) bundle;
206 - (NSString *) carFileName;
209 static BOOL (*_GSFontGetUseLegacyFontMetrics)();
210 #define $GSFontGetUseLegacyFontMetrics() \
211 (_GSFontGetUseLegacyFontMetrics == NULL ? YES : _GSFontGetUseLegacyFontMetrics())
213 static bool Debug_ = false;
214 static bool UIDebug_ = false;
215 static bool Engineer_ = false;
216 static bool SummerBoard_ = false;
217 static bool SpringBoard_;
219 static UIImage *(*_UIApplicationImageWithName)(NSString *name);
220 static UIImage *(*_UIImageWithNameInDomain)(NSString *name, NSString *domain);
221 static NSBundle *(*_UIKitBundle)();
223 static NSMutableDictionary *Images_ = [[NSMutableDictionary alloc] initWithCapacity:64];
224 static NSMutableDictionary *Cache_ = [[NSMutableDictionary alloc] initWithCapacity:64];
225 static NSMutableDictionary *Strings_ = [[NSMutableDictionary alloc] initWithCapacity:0];
226 static NSMutableDictionary *Bundles_ = [[NSMutableDictionary alloc] initWithCapacity:2];
228 static NSFileManager *Manager_;
229 static NSMutableArray *Themes_;
231 static NSDictionary *English_;
232 static NSMutableDictionary *Info_;
234 // @interface WBBundle {{{
235 @interface WBBundle : NSBundle {
236 NSString *identifier_;
239 + (WBBundle *) bundleWithIdentifier:(NSString *)identifier;
243 @implementation WBBundle
246 [identifier_ release];
247 return [super dealloc];
250 + (WBBundle *) bundleWithIdentifier:(NSString *)identifier {
251 return [[[self alloc] initWithIdentifier:identifier] autorelease];
254 - (id) initWithIdentifier:(NSString *)identifier {
255 if ((self = [super init]) != nil) {
256 identifier_ = [identifier retain];
260 - (NSString *) bundleIdentifier {
268 static NSMutableDictionary *Themed_ = [[NSMutableDictionary alloc] initWithCapacity:128];
270 static unsigned Scale_ = 0;
272 static unsigned $getScale$(NSString *path) {
273 NSString *name(path);
275 #define StripName(strip) \
276 if ([name hasSuffix:@ strip]) \
277 name = [name substringWithRange:NSMakeRange(0, [name length] - sizeof(strip) - 1)];
281 StripName("~iphone");
284 if ([name hasSuffix:@"@3x"])
286 if ([name hasSuffix:@"@2x"])
291 static NSArray *$useScale$(NSArray *files, bool use = true) {
292 if (use && Scale_ == 0) {
293 UIScreen *screen([UIScreen mainScreen]);
294 if ([screen respondsToSelector:@selector(scale)])
295 Scale_ = [screen scale];
300 NSString *idiom(IsWild_ ? @"ipad" : @"iphone");
302 NSMutableArray *scaled([NSMutableArray arrayWithCapacity:([files count] * 6)]);
304 for (NSString *file in files) {
305 NSString *base([file stringByDeletingPathExtension]);
306 NSString *extension([file pathExtension]);
308 #define WBScaleImage(scale) \
310 [scaled addObject:[NSString stringWithFormat:@"%@~%@.%@", base, idiom, extension]]; \
311 [scaled addObject:file]; \
313 [scaled addObject:[NSString stringWithFormat:@"%@@%ux~%@.%@", base, scale, idiom, extension]]; \
314 [scaled addObject:[NSString stringWithFormat:@"%@@%ux.%@", base, scale, extension]]; \
318 WBScaleImage(Scale_);
320 for (unsigned scale(3); scale >= 1; --scale)
323 } else if ([base hasSuffix: @"@2x"] || [base hasSuffix:@"@3x"]) {
326 // XXX: this actually can't be used, as the person loading the file doesn't realize that the @2x changed
327 /*NSString *rest([base substringWithRange:NSMakeRange(0, [base length] - 3)]);
328 [scaled addObject:[NSString stringWithFormat:@"%@~%@.%@", rest, idiom, extension]];
329 [scaled addObject:[rest stringByAppendingPathExtension:extension]];*/
331 // XXX: this code isn't really complete
333 [scaled addObject:file];
335 if ([base hasSuffix:[NSString stringWithFormat:@"~%@", idiom]])
336 [scaled addObject:[[base substringWithRange:NSMakeRange(0, [base length] - 1 - [idiom length])] stringByAppendingPathExtension:extension]];
343 static NSString *$getTheme$(NSArray *files, NSArray *themes = Themes_) {
344 // XXX: this is not reasonable; OMG
347 @synchronized (Themed_) {
348 if (NSString *path = [Themed_ objectForKey:key])
349 return reinterpret_cast<id>(path) == [NSNull null] ? nil : path;
353 NSLog(@"WB:Debug: %@", [files description]);
357 for (NSString *theme in Themes_)
358 for (NSString *file in files) {
359 path = [NSString stringWithFormat:@"%@/%@", theme, file];
360 if ([Manager_ fileExistsAtPath:path]) {
361 if ([[Manager_ destinationOfSymbolicLinkAtPath:path error:NULL] isEqualToString:@"/"])
370 @synchronized (Themed_) {
371 [Themed_ setObject:(path == nil ? [NSNull null] : reinterpret_cast<id>(path)) forKey:key];
377 // $pathForFile$inBundle$() {{{
378 static void $pathForFile$inBundle$(NSMutableArray *names, NSString *file, NSString *identifier, NSString *folder) {
379 if (identifier != nil)
380 [names addObject:[NSString stringWithFormat:@"Bundles/%@/%@", identifier, file]];
382 [names addObject:[NSString stringWithFormat:@"Folders/%@/%@", folder, file]];
383 NSString *base([folder stringByDeletingPathExtension]);
384 if ([base hasSuffix:@"~iphone"])
385 [names addObject:[NSString stringWithFormat:@"Folders/%@.%@/%@", [base substringWithRange:NSMakeRange(0, [base length] - 7)], [folder pathExtension], file]];
386 if ([base hasSuffix:@"~ipad"])
387 [names addObject:[NSString stringWithFormat:@"Folders/%@.%@/%@", [base substringWithRange:NSMakeRange(0, [base length] - 5)], [folder pathExtension], file]];
390 #define remapResourceName(oldname, newname) \
391 else if ([file isEqualToString:(oldname)]) \
392 [names addObject:oldname ".png"];
394 bool summer(SpringBoard_ && SummerBoard_);
396 if (identifier == nil);
397 else if ([identifier isEqualToString:@"com.apple.uikit.Artwork"])
398 $pathForFile$inBundle$(names, file, @"com.apple.UIKit", @"UIKit.framework");
399 else if ([identifier isEqualToString:@"com.apple.uikit.LegacyArtwork"])
400 $pathForFile$inBundle$(names, file, @"com.apple.UIKit", @"UIKit.framework");
401 else if ([identifier isEqualToString:@"com.apple.UIKit"])
402 [names addObject:[NSString stringWithFormat:@"UIImages/%@", file]];
403 else if ([identifier isEqualToString:@"com.apple.chatkit"])
404 $pathForFile$inBundle$(names, file, @"com.apple.MobileSMS", @"MobileSMS.app");
405 else if ([identifier isEqualToString:@"com.apple.calculator"])
406 [names addObject:[NSString stringWithFormat:@"Files/Applications/Calculator.app/%@", file]];
407 else if ([identifier isEqualToString:@"com.apple.Maps"] && [file isEqualToString:@"Icon-57@2x.png"])
408 $pathForFile$inBundle$(names, @"icon.png", identifier, folder);
410 remapResourceName(@"FSO_BG.png", @"StatusBar")
411 remapResourceName(Four_ ? @"SBDockBG-old.png" : @"SBDockBG.png", @"Dock")
412 remapResourceName(@"SBWeatherCelsius.png", @"Icons/Weather")
415 static NSString *$pathForFile$inBundle$(NSString *file, NSString *identifier, NSURL *url, bool use) {
416 NSMutableArray *names = [NSMutableArray arrayWithCapacity:8];
417 $pathForFile$inBundle$(names, file, identifier, [url lastPathComponent]);
418 [names addObject:[NSString stringWithFormat:@"Fallback/%@", file]];
419 if (NSString *path = $getTheme$($useScale$(names, use)))
424 // XXX: this cannot be merged due to WBBundle
425 static NSString *$pathForFile$inBundle$(NSString *file, NSBundle *bundle, bool use) {
426 return $pathForFile$inBundle$(file, [bundle bundleIdentifier], [bundle bundleURL], use);
429 static NSString *$pathForFile$inBundle$(NSString *file, CFBundleRef bundle, bool use) {
430 NSString *identifier((NSString *) CFBundleGetIdentifier(bundle));
431 NSURL *url([(NSURL *) CFBundleCopyBundleURL(bundle) autorelease]);
432 return $pathForFile$inBundle$(file, identifier, url, use);
436 static NSString *$pathForIcon$(SBApplication *self, NSString *suffix = @"") {
437 NSString *identifier = [self bundleIdentifier];
438 NSString *path = [self path];
439 NSString *folder = [path lastPathComponent];
440 NSString *dname = [self displayName];
442 NSString *didentifier;
443 if ([self respondsToSelector:@selector(displayIdentifier)])
444 didentifier = [self displayIdentifier];
449 NSLog(@"WB:Debug: [SBApplication(%@:%@:%@:%@) pathForIcon]", identifier, folder, dname, didentifier);
451 NSMutableArray *names = [NSMutableArray arrayWithCapacity:8];
453 /* XXX: I might need to keep this for backwards compatibility
454 if (identifier != nil)
455 [names addObject:[NSString stringWithFormat:@"Bundles/%@/icon.png", identifier]];
457 [names addObject:[NSString stringWithFormat:@"Folders/%@/icon.png", folder]]; */
459 #define testForIcon(Name) \
460 if (NSString *name = Name) \
461 [names addObject:[NSString stringWithFormat:@"Icons%@/%@.png", suffix, name]];
463 if (didentifier != nil && ![didentifier isEqualToString:identifier])
464 testForIcon(didentifier);
466 testForIcon(identifier);
469 if ([identifier isEqualToString:@"com.apple.MobileSMS"])
472 if (didentifier != nil) {
473 testForIcon([English_ objectForKey:didentifier]);
475 NSArray *parts = [didentifier componentsSeparatedByString:@"-"];
476 if ([parts count] != 1)
477 if (NSDictionary *english = [[[NSDictionary alloc] initWithContentsOfFile:[path stringByAppendingString:@"/English.lproj/UIRoleDisplayNames.strings"]] autorelease])
478 testForIcon([english objectForKey:[parts lastObject]]);
481 if (NSString *path = $getTheme$(names))
487 // -[NSBundle wb$bundleWithFile] {{{
488 @interface NSBundle (WinterBoard)
489 + (NSBundle *) wb$bundleWithFile:(NSString *)path;
492 @implementation NSBundle (WinterBoard)
494 + (NSBundle *) _wb$bundleWithFile:(NSString *)path {
495 path = [path stringByDeletingLastPathComponent];
496 if (path == nil || [path length] == 0 || [path isEqualToString:@"/"])
500 @synchronized (Bundles_) {
501 bundle = [Bundles_ objectForKey:path];
504 if (reinterpret_cast<id>(bundle) == [NSNull null])
506 else if (bundle == nil) {
507 if ([Manager_ fileExistsAtPath:[path stringByAppendingPathComponent:@"Info.plist"]])
508 bundle = [NSBundle bundleWithPath:path];
510 bundle = [NSBundle _wb$bundleWithFile:path];
512 NSLog(@"WB:Debug:PathBundle(%@, %@)", path, bundle);
514 @synchronized (Bundles_) {
515 [Bundles_ setObject:(bundle == nil ? [NSNull null] : reinterpret_cast<id>(bundle)) forKey:path];
522 + (NSBundle *) wb$bundleWithFile:(NSString *)path {
523 if ([path hasPrefix:@"/Library/Themes"])
525 return [self _wb$bundleWithFile:path];
530 // -[NSString wb$themedPath] {{{
531 @interface NSString (WinterBoard)
532 - (NSString *) wb$themedPath;
535 @implementation NSString (WinterBoard)
537 - (NSString *) wb$themedPath {
539 NSLog(@"WB:Debug:Bypass(\"%@\")", self);
541 if (NSBundle *bundle = [NSBundle wb$bundleWithFile:self]) {
542 NSString *file([self stringByResolvingSymlinksInPath]);
543 NSString *prefix([[bundle bundlePath] stringByResolvingSymlinksInPath]);
544 if ([file hasPrefix:prefix]) {
545 NSUInteger length([prefix length]);
546 if (length != [file length])
547 if (NSString *path = $pathForFile$inBundle$([file substringFromIndex:(length + 1)], bundle, false))
558 void WBLogRect(const char *tag, struct CGRect rect) {
559 NSLog(@"%s:{%f,%f+%f,%f}", tag, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
562 void WBLogHierarchy(UIView *view, unsigned index = 0, unsigned indent = 0) {
563 CGRect frame([view frame]);
564 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]);
566 for (UIView *child in [view subviews])
567 WBLogHierarchy(child, index++, indent + 1);
570 UIImage *$cacheForImage$(UIImage *image) {
571 CGColorSpaceRef space(CGColorSpaceCreateDeviceRGB());
572 CGRect rect = {CGPointMake(1, 1), [image size]};
573 CGSize size = {rect.size.width + 2, rect.size.height + 2};
575 CGContextRef context(CGBitmapContextCreate(NULL, size.width, size.height, 8, 4 * size.width, space, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst));
576 CGColorSpaceRelease(space);
578 CGContextDrawImage(context, rect, [image CGImage]);
579 CGImageRef ref(CGBitmapContextCreateImage(context));
580 CGContextRelease(context);
582 UIImage *cache([UIImage imageWithCGImage:ref]);
588 /*MSHook(id, SBImageCache$initWithName$forImageWidth$imageHeight$initialCapacity$, SBImageCache *self, SEL sel, NSString *name, unsigned width, unsigned height, unsigned capacity) {
589 //if ([name isEqualToString:@"icons"]) return nil;
590 return _SBImageCache$initWithName$forImageWidth$imageHeight$initialCapacity$(self, sel, name, width, height, capacity);
593 MSHook(void, SBIconModel$cacheImageForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
594 NSString *key([icon displayIdentifier]);
596 if (UIImage *image = [icon icon]) {
597 CGSize size = [image size];
598 if (size.width != 59 || size.height != 60) {
599 UIImage *cache($cacheForImage$(image));
600 [Cache_ setObject:cache forKey:key];
605 _SBIconModel$cacheImageForIcon$(self, sel, icon);
608 MSHook(void, SBIconModel$cacheImagesForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
609 /* XXX: do I /really/ have to do this? figure out how to cache the small icon! */
610 _SBIconModel$cacheImagesForIcon$(self, sel, icon);
612 NSString *key([icon displayIdentifier]);
614 if (UIImage *image = [icon icon]) {
615 CGSize size = [image size];
616 if (size.width != 59 || size.height != 60) {
617 UIImage *cache($cacheForImage$(image));
618 [Cache_ setObject:cache forKey:key];
624 MSHook(UIImage *, SBIconModel$getCachedImagedForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
625 NSString *key([icon displayIdentifier]);
626 if (UIImage *image = [Cache_ objectForKey:key])
629 return _SBIconModel$getCachedImagedForIcon$(self, sel, icon);
632 MSHook(UIImage *, SBIconModel$getCachedImagedForIcon$smallIcon$, SBIconModel *self, SEL sel, SBIcon *icon, BOOL small) {
634 return _SBIconModel$getCachedImagedForIcon$smallIcon$(self, sel, icon, small);
635 NSString *key([icon displayIdentifier]);
636 if (UIImage *image = [Cache_ objectForKey:key])
639 return _SBIconModel$getCachedImagedForIcon$smallIcon$(self, sel, icon, small);
642 MSHook(id, SBSearchView$initWithFrame$, id /* XXX: SBSearchView */ self, SEL sel, struct CGRect frame) {
643 if ((self = _SBSearchView$initWithFrame$(self, sel, frame)) != nil) {
644 [self setBackgroundColor:[UIColor clearColor]];
645 for (UIView *child in [self subviews])
646 [child setBackgroundColor:[UIColor clearColor]];
650 MSHook(id, SBSearchTableViewCell$initWithStyle$reuseIdentifier$, SBSearchTableViewCell *self, SEL sel, int style, NSString *reuse) {
651 if ((self = _SBSearchTableViewCell$initWithStyle$reuseIdentifier$(self, sel, style, reuse)) != nil) {
652 [self setBackgroundColor:[UIColor clearColor]];
656 MSHook(void, SBSearchTableViewCell$drawRect$, SBSearchTableViewCell *self, SEL sel, struct CGRect rect, BOOL selected) {
657 _SBSearchTableViewCell$drawRect$(self, sel, rect, selected);
658 float inset([self edgeInset]);
659 [[UIColor clearColor] set];
660 UIRectFill(CGRectMake(0, 0, inset, rect.size.height));
661 UIRectFill(CGRectMake(rect.size.width - inset, 0, inset, rect.size.height));
664 MSHook(UIImage *, SBApplicationIcon$icon, SBApplicationIcon *self, SEL sel) {
665 if (![Info_ wb$boolForKey:@"ComposeStoreIcons"])
666 if (NSString *path = $pathForIcon$([self application]))
667 return [UIImage imageWithContentsOfFile:path];
668 return _SBApplicationIcon$icon(self, sel);
671 MSHook(UIImage *, SBApplicationIcon$generateIconImage$, SBApplicationIcon *self, SEL sel, int type) {
673 if (![Info_ wb$boolForKey:@"ComposeStoreIcons"]) {
674 if (IsWild_ && false) // XXX: delete this code, it should not be supported
675 if (NSString *path72 = $pathForIcon$([self application], @"-72"))
676 return [UIImage imageWithContentsOfFile:path72];
677 if (NSString *path = $pathForIcon$([self application]))
678 if (UIImage *image = [UIImage imageWithContentsOfFile:path]) {
680 if ([$SBIcon respondsToSelector:@selector(defaultIconImageSize)])
681 width = [$SBIcon defaultIconImageSize].width;
684 return width == 59 ? image : [image _imageScaledToProportion:(width / 59.0) interpolationQuality:5];
687 return _SBApplicationIcon$generateIconImage$(self, sel, type);
690 MSHook(UIImage *, SBWidgetApplicationIcon$icon, SBWidgetApplicationIcon *self, SEL sel) {
692 NSLog(@"WB:Debug:Widget(%@:%@)", [self displayIdentifier], [self displayName]);
693 if (NSString *path = $getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Icons/%@.png", [self displayName]]]))
694 return [UIImage imageWithContentsOfFile:path];
695 return _SBWidgetApplicationIcon$icon(self, sel);
698 MSHook(UIImage *, SBBookmarkIcon$icon, SBBookmarkIcon *self, SEL sel) {
700 NSLog(@"WB:Debug:Bookmark(%@:%@)", [self displayIdentifier], [self displayName]);
701 if (NSString *path = $getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Icons/%@.png", [self displayName]]]))
702 return [UIImage imageWithContentsOfFile:path];
703 return _SBBookmarkIcon$icon(self, sel);
706 MSHook(NSString *, SBApplication$pathForIcon, SBApplication *self, SEL sel) {
707 if (NSString *path = $pathForIcon$(self))
709 return _SBApplication$pathForIcon(self, sel);
712 static UIImage *CachedImageAtPath(NSString *path) {
713 path = [path stringByResolvingSymlinksInPath];
714 UIImage *image = [Images_ objectForKey:path];
716 return reinterpret_cast<id>(image) == [NSNull null] ? nil : image;
717 image = [[UIImage alloc] initWithContentsOfFile:path cache:true];
719 image = [image autorelease];
720 [Images_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:path];
724 MSHook(UIImage *, _UIApplicationImageWithName, NSString *name) {
725 NSBundle *bundle = [NSBundle mainBundle];
727 NSLog(@"WB:Debug: _UIApplicationImageWithName(\"%@\", %@)", name, bundle);
728 if (NSString *path = $pathForFile$inBundle$(name, bundle, false))
729 return CachedImageAtPath(path);
730 return __UIApplicationImageWithName(name);
733 #define WBDelegate(delegate) \
734 - (NSMethodSignature*) methodSignatureForSelector:(SEL)sel { \
736 NSLog(@"WB:MS:%s:(%s)", class_getName([self class]), sel_getName(sel)); \
737 if (NSMethodSignature *sig = [delegate methodSignatureForSelector:sel]) \
739 NSLog(@"WB:Error: [%s methodSignatureForSelector:(%s)]", class_getName([self class]), sel_getName(sel)); \
743 - (void) forwardInvocation:(NSInvocation*)inv { \
744 SEL sel = [inv selector]; \
745 if ([delegate respondsToSelector:sel]) \
746 [inv invokeWithTarget:delegate]; \
748 NSLog(@"WB:Error: [%s forwardInvocation:(%s)]", class_getName([self class]), sel_getName(sel)); \
751 // %hook CFBundleCopyResourceURL {{{
752 MSHook(CFURLRef, CFBundleCopyResourceURL, CFBundleRef bundle, CFStringRef resourceName, CFStringRef resourceType, CFStringRef subDirName) {
753 NSString *file((NSString *) resourceName);
754 if (resourceType != NULL)
755 file = [NSString stringWithFormat:@"%@.%@", file, resourceType];
756 if (subDirName != NULL)
757 file = [NSString stringWithFormat:@"%@/%@", subDirName, resourceType];
759 if (![file hasSuffix:@".png"]) {
761 NSLog(@"WB:Debug: CFBundleCopyResourceURL(<%@>, \"%@\", \"%@\", \"%@\")", CFBundleGetIdentifier(bundle), resourceName, resourceType, subDirName);
762 if (NSString *path = $pathForFile$inBundle$(file, bundle, false))
763 return (CFURLRef) [[NSURL alloc] initFileURLWithPath:path];
766 return _CFBundleCopyResourceURL(bundle, resourceName, resourceType, subDirName);
770 static void $drawLabel$(NSString *label, CGRect rect, NSString *style, NSString *custom) {
771 bool ellipsis(false);
772 CGFloat max = rect.size.width - 11, width;
774 width = [(ellipsis ? [label stringByAppendingString:@"..."] : label) sizeWithStyle:style forWidth:320].width;
777 size_t length([label length]);
778 CGFloat spacing((width - max) / (length - 1));
780 if (spacing > 1.25) {
782 label = [label substringToIndex:(length - 1)];
786 style = [style stringByAppendingString:[NSString stringWithFormat:@"letter-spacing: -%f; ", spacing]];
790 label = [label stringByAppendingString:@"..."];
793 style = [style stringByAppendingString:custom];
795 CGSize size = [label sizeWithStyle:style forWidth:rect.size.width];
796 [label drawAtPoint:CGPointMake((rect.size.width - size.width) / 2 + rect.origin.x, rect.origin.y) withStyle:style];
799 static struct WBStringDrawingState {
800 WBStringDrawingState *next_;
804 } *stringDrawingState_;
806 extern "C" CGColorSpaceRef CGContextGetFillColorSpace(CGContextRef);
807 extern "C" void CGContextGetFillColor(CGContextRef, CGFloat[]);
809 static NSString *WBColorMarkup(size_t number, const CGFloat *components) {
831 return [NSString stringWithFormat:@"color: rgba(%g, %g, %g, %g)", r * 255, g * 255, b * 255, a];
834 static NSString *WBColorMarkup() {
835 CGContextRef context(UIGraphicsGetCurrentContext());
836 //NSLog(@"XXX:1:%p", context);
840 CGColorSpaceRef space(CGContextGetFillColorSpace(context));
841 //NSLog(@"XXX:2:%p", space);
845 size_t number(CGColorSpaceGetNumberOfComponents(space));
846 //NSLog(@"XXX:3:%u", number);
850 CGFloat components[number + 1];
851 CGContextGetFillColor(context, components);
852 return WBColorMarkup(number, components);
855 static NSString *WBColorMarkup(UIColor *uicolor) {
858 CGColorRef cgcolor([uicolor CGColor]);
862 CGColorSpaceRef space(CGColorGetColorSpace(cgcolor));
863 //NSLog(@"XXX:2:%p", space);
867 size_t number(CGColorGetNumberOfComponents(cgcolor));
868 //NSLog(@"XXX:3:%u", number);
872 const CGFloat *components(CGColorGetComponents(cgcolor));
873 return WBColorMarkup(number, components);
876 extern "C" NSString *NSStringFromCGPoint(CGPoint rect);
878 MSInstanceMessage6(CGSize, NSString, drawAtPoint,forWidth,withFont,lineBreakMode,letterSpacing,includeEmoji, CGPoint, point, CGFloat, width, UIFont *, font, UILineBreakMode, mode, CGFloat, spacing, BOOL, emoji) {
879 //NSLog(@"XXX: @\"%@\" %@ %g \"%@\" %u %g %u", self, NSStringFromCGPoint(point), width, font, mode, spacing, emoji);
881 WBStringDrawingState *state(stringDrawingState_);
883 return MSOldCall(point, width, font, mode, spacing, emoji);
885 if (state->count_ != 0 && --state->count_ == 0)
886 stringDrawingState_ = state->next_;
887 if (state->info_ == nil)
888 return MSOldCall(point, width, font, mode, spacing, emoji);
890 NSString *info([Info_ objectForKey:state->info_]);
892 return MSOldCall(point, width, font, mode, spacing, emoji);
894 NSString *base(state->base_ ?: @"");
895 NSString *extra([NSString stringWithFormat:@"letter-spacing: %gpx", spacing]);
896 [self drawAtPoint:point withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info]];
900 MSInstanceMessage1(void, NSAttributedString, drawAtPoint, CGPoint, point) {
901 //NSLog(@"XXX: @\"%@\" %@", self, NSStringFromCGPoint(point));
903 WBStringDrawingState *state(stringDrawingState_);
905 return MSOldCall(point);
907 if (state->count_ != 0 && --state->count_ == 0)
908 stringDrawingState_ = state->next_;
909 if (state->info_ == nil)
910 return MSOldCall(point);
912 NSString *info([Info_ objectForKey:state->info_]);
914 return MSOldCall(point);
916 NSDictionary *attributes([self attributesAtIndex:0 effectiveRange:NULL]);
918 UIFont *font([attributes objectForKey:@"NSFont"]);
920 NSString *base(state->base_ ?: @"");
921 [[self string] drawAtPoint:point withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), base, info]];
924 extern "C" NSString *NSStringFromCGRect(CGRect rect);
926 MSInstanceMessageHook7(CGSize, NSString, _drawInRect,withFont,lineBreakMode,alignment,lineSpacing,includeEmoji,truncationRect, CGRect, rect, UIFont *, font, UILineBreakMode, mode, UITextAlignment, alignment, float, spacing, BOOL, emoji, CGRect, truncation) {
927 //NSLog(@"XXX: @\"%@\" %@ \"%@\" %u %u %g %u %@", self, NSStringFromCGRect(rect), font, mode, alignment, spacing, emoji, NSStringFromCGRect(truncation));
929 WBStringDrawingState *state(stringDrawingState_);
931 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
933 if (state->count_ != 0 && --state->count_ == 0)
934 stringDrawingState_ = state->next_;
935 if (state->info_ == nil)
936 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
938 NSString *info([Info_ objectForKey:state->info_]);
940 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
945 case UITextAlignmentLeft:
948 case UITextAlignmentCenter:
949 textAlign = @"center";
951 case UITextAlignmentRight:
952 textAlign = @"right";
956 NSString *base(state->base_ ?: @"");
957 NSString *extra([NSString stringWithFormat:@"text-align: %@", textAlign]);
960 $drawLabel$(self, rect, [NSString stringWithFormat:@"%@;%@;%@", [font markupDescription], WBColorMarkup(), base], info);
962 [self drawInRect:rect withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info]];
967 MSInstanceMessage2(void, NSString, drawInRect,withAttributes, CGRect, rect, NSDictionary *, attributes) {
968 //NSLog(@"XXX: *\"%@\" %@", self, attributes);
970 WBStringDrawingState *state(stringDrawingState_);
972 return MSOldCall(rect, attributes);
974 if (state->count_ != 0 && --state->count_ == 0)
975 stringDrawingState_ = state->next_;
976 if (state->info_ == nil)
977 return MSOldCall(rect, attributes);
979 NSString *info([Info_ objectForKey:state->info_]);
981 return MSOldCall(rect, attributes);
983 NSString *base(state->base_ ?: @"");
985 UIFont *font([attributes objectForKey:@"NSFont"]);
986 UIColor *color([attributes objectForKey:@"NSColor"]);
988 [self drawInRect:rect withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], WBColorMarkup(color), base, info]];
991 extern "C" NSString *NSStringFromCGSize(CGSize size);
993 MSInstanceMessage4(CGRect, NSString, boundingRectWithSize,options,attributes,context, CGSize, size, NSInteger, options, NSDictionary *, attributes, id, context) {
994 //NSLog(@"XXX: $\"%@\" %@ 0x%x %@ %@", self, NSStringFromCGSize(size), unsigned(options), attributes, context);
996 WBStringDrawingState *state(stringDrawingState_);
998 return MSOldCall(size, options, attributes, context);
1000 if (state->count_ != 0 && --state->count_ == 0)
1001 stringDrawingState_ = state->next_;
1002 if (state->info_ == nil)
1003 return MSOldCall(size, options, attributes, context);
1005 NSString *info([Info_ objectForKey:state->info_]);
1007 return MSOldCall(size, options, attributes, context);
1009 NSString *base(state->base_ ?: @"");
1011 UIFont *font([attributes objectForKey:@"NSFont"]);
1012 UIColor *color([attributes objectForKey:@"NSColor"]);
1014 return (CGRect) {{0, 0}, [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], WBColorMarkup(color), base, info] forWidth:size.width]};
1017 MSInstanceMessage3(CGRect, NSAttributedString, boundingRectWithSize,options,context, CGSize, size, NSInteger, options, id, context) {
1018 //NSLog(@"XXX: $\"%@\" %@ 0x%x %@", self, NSStringFromCGSize(size), unsigned(options), context);
1020 WBStringDrawingState *state(stringDrawingState_);
1022 return MSOldCall(size, options, context);
1024 if (state->count_ != 0 && --state->count_ == 0)
1025 stringDrawingState_ = state->next_;
1026 if (state->info_ == nil)
1027 return MSOldCall(size, options, context);
1029 NSString *info([Info_ objectForKey:state->info_]);
1031 return MSOldCall(size, options, context);
1033 NSString *base(state->base_ ?: @"");
1035 NSDictionary *attributes([self attributesAtIndex:0 effectiveRange:NULL]);
1037 UIFont *font([attributes objectForKey:@"NSFont"]);
1038 UIColor *color([attributes objectForKey:@"NSColor"]);
1040 MSOldCall(size, options, context);
1041 return (CGRect) {{0, 0}, [[self string] sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], WBColorMarkup(color), base, info] forWidth:size.width]};
1044 MSInstanceMessage4(CGSize, NSString, sizeWithFont,forWidth,lineBreakMode,letterSpacing, UIFont *, font, CGFloat, width, UILineBreakMode, mode, CGFloat, spacing) {
1045 //NSLog(@"XXX: #\"%@\" \"%@\" %g %u %g", self, font, width, mode, spacing);
1047 WBStringDrawingState *state(stringDrawingState_);
1049 return MSOldCall(font, width, mode, spacing);
1051 if (state->count_ != 0 && --state->count_ == 0)
1052 stringDrawingState_ = state->next_;
1053 if (state->info_ == nil)
1054 return MSOldCall(font, width, mode, spacing);
1056 NSString *info([Info_ objectForKey:state->info_]);
1058 return MSOldCall(font, width, mode, spacing);
1060 NSString *base(state->base_ ?: @"");
1061 NSString *extra([NSString stringWithFormat:@"letter-spacing: %gpx", spacing]);
1062 return [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info] forWidth:width];
1065 MSInstanceMessage1(CGSize, NSString, sizeWithFont, UIFont *, font) {
1066 //NSLog(@"XXX: ?\"%@\"", self);
1068 WBStringDrawingState *state(stringDrawingState_);
1070 return MSOldCall(font);
1072 if (state->count_ != 0 && --state->count_ == 0)
1073 stringDrawingState_ = state->next_;
1074 if (state->info_ == nil)
1075 return MSOldCall(font);
1077 NSString *info([Info_ objectForKey:state->info_]);
1079 return MSOldCall(font);
1081 NSString *base(state->base_ ?: @"");
1082 return [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), base, info] forWidth:65535];
1085 MSClassMessageHook2(id, SBIconBadgeView, checkoutAccessoryImagesForIcon,location, id, icon, int, location) {
1086 WBStringDrawingState badgeState = {NULL, 0, @""
1089 stringDrawingState_ = &badgeState;
1091 id images(MSOldCall(icon, location));
1093 stringDrawingState_ = NULL;
1097 MSClassMessageHook2(UIImage *, SBIconAccessoryImage, checkoutAccessoryImageForIcon,location, id, icon, int, location) {
1098 if ([self _imageClassForIcon:icon location:location] != $SBIconBadgeImage)
1099 return MSOldCall(icon, location);
1101 WBStringDrawingState badgeState = {NULL, 0, @""
1104 stringDrawingState_ = &badgeState;
1106 UIImage *image(MSOldCall(icon, location));
1108 stringDrawingState_ = NULL;
1112 MSInstanceMessageHook1(UIImage *, SBIconBadgeFactory, checkoutBadgeImageForText, NSString *, text) {
1113 WBStringDrawingState badgeState = {NULL, 0, @""
1116 stringDrawingState_ = &badgeState;
1118 UIImage *image(MSOldCall(text));
1120 stringDrawingState_ = NULL;
1124 MSInstanceMessageHook1(UIImage *, SBCalendarApplicationIcon, generateIconImage, int, type) {
1125 WBStringDrawingState dayState = {NULL, unsigned(kCFCoreFoundationVersionNumber >= 1200 ? 3 : 2), @""
1126 // XXX: this is only correct on an iPod dock
1127 "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px;"
1128 , @"CalendarIconDayStyle"};
1131 if (kCFCoreFoundationVersionNumber < 800)
1133 else if (kCFCoreFoundationVersionNumber < 1200)
1138 WBStringDrawingState skipState = {&dayState, skips, nil, nil};
1140 WBStringDrawingState dateState = {&skipState, 2, @""
1141 , @"CalendarIconDateStyle"};
1143 stringDrawingState_ = &dateState;
1145 UIImage *image(MSOldCall(type));
1147 stringDrawingState_ = NULL;
1151 MSInstanceMessageHook1(UIImage *, UIStatusBarTimeItemView, contentsImageForStyle, int, style) {
1152 WBStringDrawingState timeState = {NULL, 0, @""
1155 stringDrawingState_ = &timeState;
1157 UIImage *image(MSOldCall(style));
1159 stringDrawingState_ = NULL;
1163 MSHook(void, SBCalendarIconContentsView$drawRect$, SBCalendarIconContentsView *self, SEL sel, CGRect rect) {
1164 NSBundle *bundle([NSBundle mainBundle]);
1166 CFLocaleRef locale(CFLocaleCopyCurrent());
1167 CFDateFormatterRef formatter(CFDateFormatterCreate(NULL, locale, kCFDateFormatterNoStyle, kCFDateFormatterNoStyle));
1170 CFDateRef now(CFDateCreate(NULL, CFAbsoluteTimeGetCurrent()));
1172 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NUMBER_FORMAT" value:@"d" table:@"SpringBoard"]);
1173 CFStringRef date(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
1174 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NAME_FORMAT" value:@"cccc" table:@"SpringBoard"]);
1175 CFStringRef day(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
1179 CFRelease(formatter);
1181 NSString *datestyle([@""
1182 "font-family: Helvetica; "
1183 "font-weight: bold; "
1186 "" stringByAppendingString:(IsWild_
1187 ? @"font-size: 54px; "
1188 : @"font-size: 39px; "
1191 NSString *daystyle([@""
1192 "font-family: Helvetica; "
1193 "font-weight: bold; "
1195 "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px; "
1196 "" stringByAppendingString:(IsWild_
1197 ? @"font-size: 11px; "
1198 : @"font-size: 9px; "
1201 if (NSString *style = [Info_ objectForKey:@"CalendarIconDateStyle"])
1202 datestyle = [datestyle stringByAppendingString:style];
1203 if (NSString *style = [Info_ objectForKey:@"CalendarIconDayStyle"])
1204 daystyle = [daystyle stringByAppendingString:style];
1206 CGFloat width([self bounds].size.width);
1208 CGSize datesize = [(NSString *)date sizeWithStyle:datestyle forWidth:(width + leeway)];
1209 CGSize daysize = [(NSString *)day sizeWithStyle:daystyle forWidth:(width + leeway)];
1211 unsigned base0(IsWild_ ? 89 : 70);
1212 if ($GSFontGetUseLegacyFontMetrics())
1214 unsigned base1(IsWild_ ? 18 : 16);
1221 [(NSString *)date drawAtPoint:CGPointMake(
1222 (width + 1 - datesize.width) / 2, (base0 - datesize.height) / 2
1223 ) withStyle:datestyle];
1225 [(NSString *)day drawAtPoint:CGPointMake(
1226 (width + 1 - daysize.width) / 2, (base1 - daysize.height) / 2
1227 ) withStyle:daystyle];
1233 // %hook -[{NavigationBar,Toolbar} setBarStyle:] {{{
1234 void $setBarStyle$_(NSString *name, int &style) {
1236 NSLog(@"WB:Debug:%@Style:%d", name, style);
1237 NSNumber *number = nil;
1239 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style-%d", name, style]];
1241 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style", name]];
1242 if (number != nil) {
1243 style = [number intValue];
1245 NSLog(@"WB:Debug:%@Style=%d", name, style);
1249 MSInstanceMessageHook1(void, UIToolbar, setBarStyle, int, style) {
1250 $setBarStyle$_(@"Toolbar", style);
1251 return MSOldCall(style);
1254 MSInstanceMessageHook1(void, UINavigationBar, setBarStyle, int, style) {
1255 $setBarStyle$_(@"NavigationBar", style);
1256 return MSOldCall(style);
1260 MSHook(void, SBButtonBar$didMoveToSuperview, UIView *self, SEL sel) {
1261 [[self superview] setBackgroundColor:[UIColor clearColor]];
1262 _SBButtonBar$didMoveToSuperview(self, sel);
1265 MSHook(void, SBStatusBarContentsView$didMoveToSuperview, UIView *self, SEL sel) {
1266 [[self superview] setBackgroundColor:[UIColor clearColor]];
1267 _SBStatusBarContentsView$didMoveToSuperview(self, sel);
1270 static NSArray *Wallpapers_;
1271 static bool Papered_;
1272 static bool Docked_;
1273 static bool SMSBackgrounded_;
1274 static NSString *WallpaperFile_;
1275 static UIImageView *WallpaperImage_;
1276 static UIWebDocumentView *WallpaperPage_;
1277 static NSURL *WallpaperURL_;
1279 #define _release(object) \
1280 do if (object != nil) { \
1285 static UIImage *$getImage$(NSString *path) {
1286 UIImage *image([UIImage imageWithContentsOfFile:path]);
1288 unsigned scale($getScale$(path));
1289 if (scale != 1 && [image respondsToSelector:@selector(setScale)])
1290 [image setScale:scale];
1295 template <typename Original_, typename Modified_>
1296 _finline UIImage *WBCacheImage(const Modified_ &modified, const Original_ &original, NSString *key) {
1297 UIImage *image([Images_ objectForKey:key]);
1299 return reinterpret_cast<id>(image) == [NSNull null] ? original() : image;
1300 if (NSString *path = modified())
1301 image = $getImage$(path);
1302 [Images_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:key];
1303 return image == nil ? original() : image;
1306 static UIImage *$getDefaultDesktopImage$() {
1307 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"LockBackground.png", @"LockBackground.jpg", nil])))
1308 return $getImage$(path);
1312 MSClassMessageHook0(UIImage *, UIImage, defaultDesktopImage) {
1313 return $getDefaultDesktopImage$() ?: MSOldCall();
1316 MSInstanceMessageHook0(UIImage *, SBSlidingAlertDisplay, _defaultDesktopImage) {
1317 return $getDefaultDesktopImage$() ?: MSOldCall();
1320 MSInstanceMessageHook0(void, SBWallpaperView, resetCurrentImageToWallpaper) {
1321 for (UIView *parent([self superview]); parent != nil; parent = [parent superview])
1322 if ([parent isKindOfClass:$SBSlidingAlertDisplay]) {
1323 if (UIImage *image = $getDefaultDesktopImage$()) {
1324 [self setImage:image];
1334 // %hook -[SBUIController init] {{{
1335 MSInstanceMessageHook0(id, SBUIController, init) {
1340 NSString *paper($getTheme$(Wallpapers_));
1342 paper = [paper stringByDeletingLastPathComponent];
1345 NSLog(@"WB:Debug:Info = %@", [Info_ description]);
1348 UIImageView *&_wallpaperView(MSHookIvar<UIImageView *>(self, "_wallpaperView"));
1349 if (&_wallpaperView != NULL) {
1350 [_wallpaperView removeFromSuperview];
1351 [_wallpaperView release];
1352 _wallpaperView = nil;
1356 UIView *&_contentLayer(MSHookIvar<UIView *>(self, "_contentLayer"));
1357 UIView *&_contentView(MSHookIvar<UIView *>(self, "_contentView"));
1360 if (&_contentLayer != NULL)
1361 player = &_contentLayer;
1362 else if (&_contentView != NULL)
1363 player = &_contentView;
1366 UIView *layer(player == NULL ? nil : *player);
1368 UIWindow *window([[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]);
1369 UIView *content([[[UIView alloc] initWithFrame:[window frame]] autorelease]);
1370 [window setContentView:content];
1372 UIWindow *&_window(MSHookIvar<UIWindow *>(self, "_window"));
1373 [window setBackgroundColor:[_window backgroundColor]];
1374 [_window setBackgroundColor:[UIColor clearColor]];
1376 [window setLevel:-1000];
1377 [window setHidden:NO];
1379 /*if (player != NULL)
1380 *player = content;*/
1382 [content setBackgroundColor:[layer backgroundColor]];
1383 [layer setBackgroundColor:[UIColor clearColor]];
1386 if (!SummerBoard_ || !IsWild_)
1389 CGRect bounds([content bounds]);
1390 bounds.origin.y = -30;
1391 indirect = [[[UIView alloc] initWithFrame:bounds] autorelease];
1392 [content addSubview:indirect];
1393 [indirect zoomToScale:2.4];
1396 _release(WallpaperFile_);
1397 _release(WallpaperImage_);
1398 _release(WallpaperPage_);
1399 _release(WallpaperURL_);
1402 NSArray *themes([NSArray arrayWithObject:paper]);
1404 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"], themes)) {
1408 static AVController *controller_(nil);
1409 if (controller_ == nil) {
1410 AVQueue *queue([AVQueue avQueue]);
1411 controller_ = [[AVController avControllerWithQueue:queue error:&error] retain];
1414 AVQueue *queue([controller_ queue]);
1416 UIView *video([[[UIView alloc] initWithFrame:[indirect bounds]] autorelease]);
1417 [controller_ setLayer:[video _layer]];
1419 AVItem *item([[[AVItem alloc] initWithPath:path error:&error] autorelease]);
1420 [queue appendItem:item error:&error];
1422 [controller_ play:&error];
1423 #elif UseMPMoviePlayerController
1424 NSURL *url([NSURL fileURLWithPath:path]);
1425 MPMoviePlayerController *controller = [[$MPMoviePlayerController alloc] initWithContentURL:url];
1426 controller.movieControlMode = MPMovieControlModeHidden;
1429 MPVideoView *video = [[[$MPVideoView alloc] initWithFrame:[indirect bounds]] autorelease];
1430 [video setMovieWithPath:path];
1431 [video setRepeatMode:1];
1432 [video setRepeatGap:-1];
1433 [video playFromBeginning];;
1436 [indirect addSubview:video];
1439 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"Wallpaper.png", @"Wallpaper.jpg", nil]), themes)) {
1440 if (UIImage *image = $getImage$(path)) {
1441 WallpaperFile_ = [path retain];
1442 WallpaperImage_ = [[UIImageView alloc] initWithImage:image];
1443 if (NSNumber *number = [Info_ objectForKey:@"WallpaperAlpha"])
1444 [WallpaperImage_ setAlpha:[number floatValue]];
1445 [indirect addSubview:WallpaperImage_];
1449 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.html"], themes)) {
1450 CGRect bounds = [indirect bounds];
1452 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1453 [view setAutoresizes:true];
1455 WallpaperPage_ = [view retain];
1456 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
1458 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1460 [view setBackgroundColor:[UIColor clearColor]];
1461 if ([view respondsToSelector:@selector(setDrawsBackground:)])
1462 [view setDrawsBackground:NO];
1463 [[view webView] setDrawsBackground:NO];
1465 [indirect addSubview:view];
1469 for (size_t i(0), e([Themes_ count]); i != e; ++i) {
1470 NSString *theme = [Themes_ objectAtIndex:(e - i - 1)];
1471 NSString *html = [theme stringByAppendingPathComponent:@"Widget.html"];
1472 if ([Manager_ fileExistsAtPath:html]) {
1473 CGRect bounds = [indirect bounds];
1475 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1476 [view setAutoresizes:true];
1478 NSURL *url = [NSURL fileURLWithPath:html];
1479 [view loadRequest:[NSURLRequest requestWithURL:url]];
1481 [view setBackgroundColor:[UIColor clearColor]];
1482 if ([view respondsToSelector:@selector(setDrawsBackground:)])
1483 [view setDrawsBackground:NO];
1484 [[view webView] setDrawsBackground:NO];
1486 [indirect addSubview:view];
1494 MSHook(void, SBAwayView$updateDesktopImage$, SBAwayView *self, SEL sel, UIImage *image) {
1495 NSString *path = $getTheme$([NSArray arrayWithObject:@"LockBackground.html"]);
1496 UIView *&_backgroundView(MSHookIvar<UIView *>(self, "_backgroundView"));
1498 if (path != nil && _backgroundView != nil)
1501 _SBAwayView$updateDesktopImage$(self, sel, image);
1504 CGRect bounds = [self bounds];
1506 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1507 [view setAutoresizes:true];
1509 if (WallpaperPage_ != nil)
1510 [WallpaperPage_ release];
1511 WallpaperPage_ = [view retain];
1513 if (WallpaperURL_ != nil)
1514 [WallpaperURL_ release];
1515 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
1517 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1519 [[view webView] setDrawsBackground:false];
1520 [view setBackgroundColor:[UIColor clearColor]];
1522 [self insertSubview:view aboveSubview:_backgroundView];
1524 if ($objc_setAssociatedObject != NULL)
1525 $objc_setAssociatedObject(self, @selector(wb$widgetView), view, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1529 MSHook(void, SBAwayView$_addSubview$positioned$relativeTo$, SBAwayView *self, SEL sel, UIView *view, int positioned, UIView *relative) {
1530 UIView *&_backgroundView(MSHookIvar<UIView *>(self, "_backgroundView"));
1531 UIView *&_chargingView(MSHookIvar<UIView *>(self, "_chargingView"));
1532 if (&_chargingView != NULL)
1533 if (positioned == -2 && (relative == _backgroundView && _chargingView == nil || relative == _chargingView))
1534 if ($objc_getAssociatedObject != NULL)
1535 if (UIView *widget = $objc_getAssociatedObject(self, @selector(wb$widgetView)))
1537 return _SBAwayView$_addSubview$positioned$relativeTo$(self, sel, view, positioned, relative);
1540 /*extern "C" CGColorRef CGGStateGetSystemColor(void *);
1541 extern "C" CGColorRef CGGStateGetFillColor(void *);
1542 extern "C" CGColorRef CGGStateGetStrokeColor(void *);
1543 extern "C" NSString *UIStyleStringFromColor(CGColorRef);*/
1545 /* WBTimeLabel {{{ */
1546 @interface WBTimeLabel : NSProxy {
1548 _transient SBStatusBarTimeView *view_;
1551 - (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view;
1555 @implementation WBTimeLabel
1562 - (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view {
1563 time_ = [time retain];
1568 - (NSString *) description {
1574 - (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(UILineBreakMode)mode {
1575 if (NSString *custom = [Info_ objectForKey:@"TimeStyle"]) {
1576 BOOL &_mode(MSHookIvar<BOOL>(view_, "_mode"));;
1578 [time_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1579 "font-family: Helvetica; "
1580 "font-weight: bold; "
1583 "%@", _mode ? @"white" : @"black", custom]];
1588 return [time_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1593 /* WBBadgeLabel {{{ */
1594 @interface WBBadgeLabel : NSProxy {
1598 - (id) initWithBadge:(NSString *)badge;
1599 - (NSString *) description;
1603 @implementation WBBadgeLabel
1610 - (id) initWithBadge:(NSString *)badge {
1611 badge_ = [badge retain];
1615 - (NSString *) description {
1616 return [badge_ description];
1621 - (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(UILineBreakMode)mode {
1622 if (NSString *custom = [Info_ objectForKey:@"BadgeStyle"]) {
1623 [badge_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1624 "font-family: Helvetica; "
1625 "font-weight: bold; "
1633 return [badge_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1640 MSInstanceMessageHook1(void, SBIcon, setIconImageAlpha, CGFloat, alpha) {
1641 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1642 alpha = [number floatValue];
1643 return MSOldCall(alpha);
1646 MSInstanceMessageHook1(void, SBIcon, setIconLabelAlpha, CGFloat, alpha) {
1647 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1648 alpha = [number floatValue];
1649 return MSOldCall(alpha);
1652 MSInstanceMessageHook0(id, SBIcon, initWithDefaultSize) {
1653 if ((self = MSOldCall()) != nil) {
1654 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"]) {
1655 // XXX: note: this is overridden above, which is silly
1656 float alpha([number floatValue]);
1657 if ([self respondsToSelector:@selector(setIconImageAlpha:)])
1658 [self setIconImageAlpha:alpha];
1659 if ([self respondsToSelector:@selector(setIconLabelAlpha:)])
1660 [self setIconLabelAlpha:alpha];
1661 if ([self respondsToSelector:@selector(setAlpha:)])
1662 [self setAlpha:alpha];
1667 MSInstanceMessageHook1(void, SBIcon, setAlpha, CGFloat, alpha) {
1668 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1669 alpha = [number floatValue];
1670 return MSOldCall(alpha);
1674 MSHook(id, SBIconBadge$initWithBadge$, SBIconBadge *self, SEL sel, NSString *badge) {
1675 if ((self = _SBIconBadge$initWithBadge$(self, sel, badge)) != nil) {
1676 id &_badge(MSHookIvar<id>(self, "_badge"));
1678 if (id label = [[WBBadgeLabel alloc] initWithBadge:[_badge autorelease]])
1683 void SBStatusBarController$setStatusBarMode(int &mode) {
1685 NSLog(@"WB:Debug:setStatusBarMode:%d", mode);
1686 if (mode < 100) // 104:hidden 105:glowing
1687 if (NSNumber *number = [Info_ objectForKey:@"StatusBarMode"])
1688 mode = [number intValue];
1691 /*MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, double duration, int animation) {
1692 NSLog(@"mode:%d orientation:%d duration:%f animation:%d", mode, orientation, duration, animation);
1693 SBStatusBarController$setStatusBarMode(mode);
1694 return _SBStatusBarController$setStatusBarMode$orientation$duration$animation$(self, sel, mode, orientation, duration, animation);
1697 MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, float duration, int fenceID, int animation) {
1698 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d", mode, orientation, duration, fenceID, animation);
1699 SBStatusBarController$setStatusBarMode(mode);
1700 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$(self, sel, mode, orientation, duration, fenceID, animation);
1703 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) {
1704 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d startTime:%f", mode, orientation, duration, fenceID, animation, startTime);
1705 SBStatusBarController$setStatusBarMode(mode);
1706 //NSLog(@"mode=%u", mode);
1707 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$startTime$(self, sel, mode, orientation, duration, fenceID, animation, startTime);
1710 /*MSHook(id, SBStatusBarContentsView$initWithStatusBar$mode$, SBStatusBarContentsView *self, SEL sel, id bar, int mode) {
1711 if (NSNumber *number = [Info_ objectForKey:@"StatusBarContentsMode"])
1712 mode = [number intValue];
1713 return _SBStatusBarContentsView$initWithStatusBar$mode$(self, sel, bar, mode);
1716 MSHook(NSString *, SBStatusBarOperatorNameView$operatorNameStyle, SBStatusBarOperatorNameView *self, SEL sel) {
1717 NSString *style(_SBStatusBarOperatorNameView$operatorNameStyle(self, sel));
1719 NSLog(@"operatorNameStyle= %@", style);
1720 if (NSString *custom = [Info_ objectForKey:@"OperatorNameStyle"])
1721 style = [NSString stringWithFormat:@"%@; %@", style, custom];
1725 MSHook(void, SBStatusBarOperatorNameView$setOperatorName$fullSize$, SBStatusBarOperatorNameView *self, SEL sel, NSString *name, BOOL full) {
1727 NSLog(@"setOperatorName:\"%@\" fullSize:%u", name, full);
1728 return _SBStatusBarOperatorNameView$setOperatorName$fullSize$(self, sel, name, NO);
1731 // XXX: replace this with [SBStatusBarTimeView tile]
1732 MSHook(void, SBStatusBarTimeView$drawRect$, SBStatusBarTimeView *self, SEL sel, CGRect rect) {
1733 id &_time(MSHookIvar<id>(self, "_time"));
1734 if (_time != nil && [_time class] != [WBTimeLabel class])
1735 object_setInstanceVariable(self, "_time", reinterpret_cast<void *>([[WBTimeLabel alloc] initWithTime:[_time autorelease] view:self]));
1736 return _SBStatusBarTimeView$drawRect$(self, sel, rect);
1739 @interface UIView (WinterBoard)
1740 - (bool) wb$isWBImageView;
1741 - (void) wb$logHierarchy;
1742 - (void) wb$setBackgroundColor:(UIColor *)color;
1745 @implementation UIView (WinterBoard)
1747 - (bool) wb$isWBImageView {
1751 - (void) wb$logHierarchy {
1752 WBLogHierarchy(self);
1755 - (void) wb$setBackgroundColor:(UIColor *)color {
1756 [self setBackgroundColor:color];
1757 for (UIView *child in [self subviews])
1758 [child wb$setBackgroundColor:color];
1763 @interface WBImageView : UIImageView {
1766 - (bool) wb$isWBImageView;
1767 - (void) wb$updateFrame;
1770 @implementation WBImageView
1772 - (bool) wb$isWBImageView {
1776 - (void) wb$updateFrame {
1777 CGRect frame([self frame]);
1780 for (UIView *view(self); ; ) {
1781 view = [view superview];
1784 frame.origin.y -= [view frame].origin.y;
1787 [self setFrame:frame];
1792 static void SBIconList$updateFrames$(SBIconList *self) {
1793 NSArray *subviews([self subviews]);
1794 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1795 if (view != nil && [view wb$isWBImageView])
1796 [view wb$updateFrame];
1799 MSHook(void, SBIconList$didMoveToSuperview, SBIconList *self, SEL sel) {
1800 SBIconList$updateFrames$(self);
1801 _SBIconList$didMoveToSuperview(self, sel);
1804 MSHook(void, SBIconList$setFrame$, SBIconList *self, SEL sel, CGRect frame) {
1805 SBIconList$updateFrames$(self);
1806 _SBIconList$setFrame$(self, sel, frame);
1809 static void $addPerPageView$(unsigned i, UIView *list) {
1810 NSString *path($getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Page%u.png", i]]));
1814 NSArray *subviews([list subviews]);
1816 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1817 if (view == nil || ![view wb$isWBImageView]) {
1818 view = [[[WBImageView alloc] init] autorelease];
1819 [list insertSubview:view atIndex:0];
1822 UIImage *image([UIImage imageWithContentsOfFile:path]);
1824 CGRect frame([view frame]);
1825 frame.size = [image size];
1826 [view setFrame:frame];
1828 [view setImage:image];
1829 [view wb$updateFrame];
1832 static void $addPerPageViews$(NSArray *lists) {
1833 for (unsigned i(0), e([lists count]); i != e; ++i)
1834 $addPerPageView$(i, [lists objectAtIndex:i]);
1837 MSInstanceMessageHook0(void, SBIconController, updateNumberOfRootIconLists) {
1838 NSArray *&_rootIconLists(MSHookIvar<NSArray *>(self, "_rootIconLists"));
1839 $addPerPageViews$(_rootIconLists);
1843 MSInstanceMessageHook0(void, SBIconContentView, layoutSubviews) {
1846 if (SBIconController *controller = [$SBIconController sharedInstance]) {
1847 UIView *&_dockContainerView(MSHookIvar<UIView *>(controller, "_dockContainerView"));
1848 if (&_dockContainerView != NULL)
1849 [[_dockContainerView superview] bringSubviewToFront:_dockContainerView];
1853 MSHook(void, SBIconController$noteNumberOfIconListsChanged, SBIconController *self, SEL sel) {
1854 SBIconModel *&_iconModel(MSHookIvar<SBIconModel *>(self, "_iconModel"));
1855 $addPerPageViews$([_iconModel iconLists]);
1856 return _SBIconController$noteNumberOfIconListsChanged(self, sel);
1859 MSHook(id, SBIconLabel$initWithSize$label$, SBIconLabel *self, SEL sel, CGSize size, NSString *label) {
1860 self = _SBIconLabel$initWithSize$label$(self, sel, size, label);
1862 [self setClipsToBounds:NO];
1866 MSHook(void, SBIconLabel$setInDock$, SBIconLabel *self, SEL sel, BOOL docked) {
1867 static bool gssc(false);
1869 BOOL (*GSSystemHasCapability)(CFStringRef) = reinterpret_cast<BOOL (*)(CFStringRef)>(dlsym(RTLD_DEFAULT, "GSSystemHasCapability"));
1870 Papered_ |= GSSystemHasCapability != NULL && GSSystemHasCapability(CFSTR("homescreen-wallpaper"));
1873 if ([Info_ objectForKey:@"UndockedIconLabels"] == nil)
1874 [Info_ setObject:[NSNumber numberWithBool:(
1876 [Info_ objectForKey:@"DockedIconLabelStyle"] != nil ||
1877 [Info_ objectForKey:@"UndockedIconLabelStyle"] != nil
1878 )] forKey:@"UndockedIconLabels"];
1881 id &_label(MSHookIvar<id>(self, "_label"));
1882 if (![Info_ wb$boolForKey:@"UndockedIconLabels"])
1885 if (_label != nil && [_label respondsToSelector:@selector(setInDock:)])
1886 [_label setInDock:docked];
1888 _SBIconLabel$setInDock$(self, sel, docked);
1889 [self setNeedsDisplay];
1892 MSHook(BOOL, SBDockIconListView$shouldShowNewDock, id self, SEL sel) {
1893 return SummerBoard_ && Docked_ ? NO : _SBDockIconListView$shouldShowNewDock(self, sel);
1896 MSHook(void, SBDockIconListView$setFrame$, id self, SEL sel, CGRect frame) {
1897 _SBDockIconListView$setFrame$(self, sel, frame);
1900 // %hook -[NSBundle localizedStringForKey:value:table:] {{{
1901 MSInstanceMessageHook3(NSString *, NSBundle, localizedStringForKey,value,table, NSString *, key, NSString *, value, NSString *, table) {
1902 NSString *identifier = [self bundleIdentifier];
1903 NSLocale *locale = [NSLocale currentLocale];
1904 NSString *language = [locale objectForKey:NSLocaleLanguageCode];
1906 NSLog(@"WB:Debug:[NSBundle(%@) localizedStringForKey:\"%@\" value:\"%@\" table:\"%@\"] (%@)", identifier, key, value, table, language);
1907 NSString *file = table == nil ? @"Localizable" : table;
1908 NSString *name = [NSString stringWithFormat:@"%@:%@", identifier, file];
1909 NSDictionary *strings;
1910 if ((strings = [Strings_ objectForKey:name]) != nil) {
1911 if (static_cast<id>(strings) != [NSNull null]) strings:
1912 if (NSString *value = [strings objectForKey:key])
1914 } else if (NSString *path = $pathForFile$inBundle$([NSString stringWithFormat:@"%@.lproj/%@.strings",
1917 if ((strings = [[NSDictionary alloc] initWithContentsOfFile:path]) != nil) {
1918 [Strings_ setObject:[strings autorelease] forKey:name];
1922 [Strings_ setObject:[NSNull null] forKey:name];
1923 return MSOldCall(key, value, table);
1926 // %hook -[WebCoreFrameBridge renderedSizeOfNode:constrainedToWidth:] {{{
1927 MSClassHook(WebCoreFrameBridge)
1929 MSInstanceMessageHook2(CGSize, WebCoreFrameBridge, renderedSizeOfNode,constrainedToWidth, id, node, float, width) {
1932 void **core(reinterpret_cast<void **>([node _node]));
1933 if (core == NULL || core[6] == NULL)
1935 return MSOldCall(node, width);
1939 MSInstanceMessage1(void, SBIconLabel, drawRect, CGRect, rect) {
1940 static Ivar drawMoreLegibly = object_getInstanceVariable(self, "_drawMoreLegibly", NULL);
1943 Ivar ivar = object_getInstanceVariable(self, "_inDock", reinterpret_cast<void **>(&docked));
1944 docked = (docked & (ivar_getOffset(ivar) == ivar_getOffset(drawMoreLegibly) ? 0x2 : 0x1)) != 0;
1946 NSString *label(MSHookIvar<NSString *>(self, "_label"));
1948 NSString *style = [NSString stringWithFormat:@""
1949 "font-family: Helvetica; "
1950 "font-weight: bold; "
1952 "", (docked || !SummerBoard_ ? @"white" : @"#b3b3b3"), (IsWild_
1953 ? @"font-size: 12px; "
1954 : @"font-size: 11px; "
1958 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px 1px 0px; "];
1960 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px -1px 0px; "];
1962 NSString *custom([Info_ objectForKey:(docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle")]);
1964 $drawLabel$(label, [self bounds], style, custom);
1967 MSInstanceMessage0(CGImageRef, SBIconLabel, buildLabelImage) {
1968 bool docked((MSHookIvar<unsigned>(self, "_inDock") & 0x2) != 0);
1970 WBStringDrawingState labelState = {NULL, 0, @""
1971 , docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle"};
1973 stringDrawingState_ = &labelState;
1976 CGImageRef image(MSOldCall());
1979 stringDrawingState_ = NULL;
1983 static bool wb$inDock(id parameters) {
1984 return [$objc_getAssociatedObject(parameters, @selector(wb$inDock)) boolValue];
1987 MSInstanceMessage0(NSUInteger, SBIconLabelImageParameters, hash) {
1988 return MSOldCall() + (wb$inDock(self) ? 0xdeadbeef : 0xd15ea5e);
1991 MSClassMessage2(id, SBIconView, _labelImageParametersForIcon,location, id, icon, int, location) {
1992 if (id parameters = MSOldCall(icon, location)) {
1993 $objc_setAssociatedObject(parameters, @selector(wb$inDock), [NSNumber numberWithBool:(location == 1)], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1998 MSInstanceMessage0(id, SBIconView, _labelImageParameters) {
1999 if (id parameters = MSOldCall()) {
2000 int &location(MSHookIvar<int>(self, "_iconLocation"));
2001 if (&location != NULL)
2002 $objc_setAssociatedObject(parameters, @selector(wb$inDock), [NSNumber numberWithBool:(location == 3)], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
2007 MSClassMessage1(UIImage *, SBIconLabelImage, _drawLabelImageForParameters, id, parameters) {
2008 bool docked(wb$inDock(parameters));
2010 WBStringDrawingState labelState = {NULL, 0, @""
2011 , docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle"};
2013 stringDrawingState_ = &labelState;
2016 UIImage *image(MSOldCall(parameters));
2019 stringDrawingState_ = NULL;
2024 MSInstanceMessageHook2(id, CKBalloonView, initWithFrame,delegate, CGRect, frame, id, delegate) {
2025 if ((self = MSOldCall(frame, delegate)) != nil) {
2026 [self setBackgroundColor:[UIColor clearColor]];
2030 MSInstanceMessageHook0(BOOL, CKBalloonView, _canUseLayerBackedBalloon) {
2031 return SMSBackgrounded_ ? NO : MSOldCall();
2034 MSInstanceMessageHook0(void, CKTranscriptHeaderView, layoutSubviews) {
2035 [self wb$setBackgroundColor:[UIColor clearColor]];
2039 MSInstanceMessageHook1(void, CKMessageCell, addBalloonView, CKBalloonView *, balloon) {
2041 [balloon setBackgroundColor:[UIColor clearColor]];
2044 MSInstanceMessageHook1(void, CKTranscriptCell, setBackgroundColor, UIColor *, color) {
2045 MSOldCall([UIColor clearColor]);
2046 [[self contentView] wb$setBackgroundColor:[UIColor clearColor]];
2050 MSInstanceMessageHook2(id, CKTranscriptCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
2051 if ((self = MSOldCall(style, reuse)) != nil) {
2052 [self setBackgroundColor:[UIColor clearColor]];
2053 [[self contentView] wb$setBackgroundColor:[UIColor clearColor]];
2058 MSInstanceMessageHook2(id, CKMessageCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
2059 if ((self = MSOldCall(style, reuse)) != nil) {
2060 [self setBackgroundColor:[UIColor clearColor]];
2061 [[self contentView] setBackgroundColor:[UIColor clearColor]];
2065 MSInstanceMessageHook2(id, CKTimestampView, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
2066 if ((self = MSOldCall(style, reuse)) != nil) {
2067 UILabel *&_label(MSHookIvar<UILabel *>(self, "_label"));
2068 [_label setBackgroundColor:[UIColor clearColor]];
2072 MSInstanceMessageHook1(void, CKTranscriptTableView, setSeparatorStyle, int, style) {
2073 MSOldCall(UITableViewCellSeparatorStyleNone);
2076 MSInstanceMessageHook2(id, CKTranscriptTableView, initWithFrame,style, CGRect, frame, int, style) {
2077 if ((self = MSOldCall(frame, style)) != nil) {
2078 [self setSeparatorStyle:UITableViewCellSeparatorStyleNone];
2082 MSInstanceMessageHook0(void, CKTranscriptController, loadView) {
2085 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"SMSBackground.png", @"SMSBackground.jpg", nil])))
2086 if (UIImage *image = $getImage$(path)) {
2087 SMSBackgrounded_ = true;
2089 UIView *&_transcriptTable(MSHookIvar<UIView *>(self, "_transcriptTable"));
2090 UIView *&_transcriptLayer(MSHookIvar<UIView *>(self, "_transcriptLayer"));
2092 if (&_transcriptTable != NULL)
2093 table = _transcriptTable;
2094 else if (&_transcriptLayer != NULL)
2095 table = _transcriptLayer;
2099 UIView *placard(table != nil ? [table superview] : MSHookIvar<UIView *>(self, "_backPlacard"));
2100 UIImageView *background([[[UIImageView alloc] initWithImage:image] autorelease]);
2103 [placard insertSubview:background atIndex:0];
2105 [table setBackgroundColor:[UIColor clearColor]];
2106 [placard insertSubview:background belowSubview:table];
2112 template <typename Original_>
2113 static UIImage *WBCacheImage(NSBundle *bundle, NSString *name, const Original_ &original, NSString *key) {
2116 NSUInteger period([name rangeOfString:@"."].location);
2117 NSUInteger length([name length]);
2118 if (period == NSNotFound || length < 4 || period > length - 4)
2119 name = [name stringByAppendingString:@".png"];
2121 return WBCacheImage(
2122 [=](){ return $pathForFile$inBundle$(name, bundle, true); },
2123 [bundle, &original, name](){
2124 UIImage *image(original());
2125 if (image != nil && UIDebug_) {
2126 NSString *path([@"/tmp/WBImages/" stringByAppendingString:[bundle bundleIdentifier]]);
2127 [Manager_ createDirectoryAtPath:path withIntermediateDirectories:YES attributes:@{NSFilePosixPermissions: @0777} error:NULL];
2128 path = [NSString stringWithFormat:@"%@/%@", path, name];
2129 if (![Manager_ fileExistsAtPath:path])
2130 [UIImagePNGRepresentation(image) writeToFile:path atomically:YES];
2136 // %hook _UIImageWithName() {{{
2137 MSHook(UIImage *, _UIImageWithName, NSString *name) {
2141 NSLog(@"WB:Debug: _UIImageWithName(\"%@\")", name);
2142 return WBCacheImage(_UIKitBundle(), name,
2143 [=](){ return __UIImageWithName(name); },
2144 [NSString stringWithFormat:@"I:%@", name]);
2147 // %hook _UIImageWithNameInDomain() {{{
2148 MSHook(UIImage *, _UIImageWithNameInDomain, NSString *name, NSString *domain) {
2150 NSLog(@"WB:Debug: _UIImageWithNameInDomain(\"%@\", \"%@\")", name, domain);
2151 return WBCacheImage(
2152 [=](){ return $getTheme$($useScale$([NSArray arrayWithObject:[NSString stringWithFormat:@"Domains/%@/%@", domain, name]])); },
2153 [=](){ return __UIImageWithNameInDomain(name, domain); },
2154 [NSString stringWithFormat:@"D:%zu:%@%@", size_t([domain length]), domain, name]);
2158 // UISharedArtwork (iOS 6) {{{
2159 MSInstanceMessageHook2(UISharedArtwork *, UISharedArtwork, initWithName,inBundle, NSString *, name, NSBundle *, bundle) {
2160 if ((self = MSOldCall(name, bundle)) != nil) {
2161 $objc_setAssociatedObject(self, @selector(wb$bundle), bundle, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
2165 MSInstanceMessageHook2(UIImage *, UISharedArtwork, imageNamed,device, NSString *, name, NSInteger, device) {
2166 NSBundle *bundle($objc_getAssociatedObject(self, @selector(wb$bundle)));
2168 NSLog(@"WB:Debug: -[UISharedArtwork(%@) imageNamed:@\"%@\" device:%li]", [bundle bundleIdentifier], name, (long) device);
2169 return WBCacheImage(bundle, name,
2170 [=](){ return MSOldCall(name, device); },
2171 [NSString stringWithFormat:@"M:%p:%@:%li", self, name, (long) device]);
2174 // _UIAssetManager (iOS 7) {{{
2175 MSInstanceMessageHook3(_UIAssetManager *, _UIAssetManager, initWithName,inBundle,idiom, NSString *, name, NSBundle *, bundle, NSInteger, idiom) {
2176 if ((self = MSOldCall(name, bundle, idiom)) != nil) {
2177 $objc_setAssociatedObject(self, @selector(wb$bundle), bundle, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
2181 MSInstanceMessageHook5(UIImage *, _UIAssetManager, imageNamed,scale,idiom,subtype,cachingOptions, NSString *, name, CGFloat, scale, NSInteger, idiom, NSUInteger, subtype, NSUInteger, caching) {
2182 NSBundle *bundle($objc_getAssociatedObject(self, @selector(wb$bundle)));
2184 NSLog(@"WB:Debug: -[_UIAssetManager(%@/%@) imageNamed:@\"%@\" scale:%g idiom:%li subtype:%lu cachingOptions:%lu]",
2185 [bundle bundleIdentifier], [self carFileName],
2186 name, scale, (long) idiom,
2187 (unsigned long) subtype,
2188 (unsigned long) caching
2191 if (bundle == _UIKitBundle()) {
2192 NSString *name([self carFileName]);
2194 else if ([name isEqualToString:@"UIKit_NewArtwork"])
2195 bundle = [WBBundle bundleWithIdentifier:@"com.apple.uikit.Artwork"];
2196 else if ([name isEqualToString:@"UIKit_OriginalArtwork"])
2197 bundle = [WBBundle bundleWithIdentifier:@"com.apple.uikit.LegacyArtwork"];
2200 return WBCacheImage(bundle, name,
2201 [=](){ return MSOldCall(name, scale, idiom, subtype, caching); },
2202 [NSString stringWithFormat:@"M:%p:%@:%g:%li:%lu", self, name, scale, (long) idiom, (unsigned long) subtype]);
2205 // _UIAssetManager (iOS 8) {{{
2206 struct SizeClassPair {
2211 MSInstanceMessageHook7(UIImage *, _UIAssetManager, imageNamed,scale,idiom,subtype,cachingOptions,sizeClassPair,attachCatalogImage, NSString *, name, CGFloat, scale, NSInteger, idiom, NSUInteger, subtype, NSUInteger, caching, SizeClassPair, size, BOOL, attach) {
2212 NSBundle *bundle([self bundle]);
2214 NSLog(@"WB:Debug: -[_UIAssetManager(%@/%@) imageNamed:@\"%@\" scale:%g idiom:%li subtype:%lu cachingOptions:%lu sizeClassPair:[%li %li] attachCatalogImage:%s]",
2215 [bundle bundleIdentifier], [self carFileName],
2216 name, scale, (long) idiom,
2217 (unsigned long) subtype,
2218 (unsigned long) caching,
2219 (long) size.first, (long) size.second,
2220 attach ? "YES" : "NO"
2222 return WBCacheImage(bundle, name,
2223 [=](){ return MSOldCall(name, scale, idiom, subtype, caching, size, attach); },
2224 [NSString stringWithFormat:@"M:%p:%@:%g:%li:%lu:%li:%li:%c", self, name, scale, (long) idiom, (unsigned long) subtype, (long) size.first, (long) size.second, attach ? 'Y' : 'N']);
2228 // %hook GSFontCreateWithName() {{{
2229 MSHook(GSFontRef, GSFontCreateWithName, const char *name, GSFontSymbolicTraits traits, float size) {
2231 NSLog(@"WB:Debug: GSFontCreateWithName(\"%s\", %f)", name, size);
2232 if (NSString *font = [Info_ objectForKey:[NSString stringWithFormat:@"FontName-%s", name]])
2233 name = [font UTF8String];
2234 //if (NSString *scale = [Info_ objectForKey:[NSString stringWithFormat:@"FontScale-%s", name]])
2235 // size *= [scale floatValue];
2236 return _GSFontCreateWithName(name, traits, size);
2240 #define AudioToolbox "/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox"
2242 static bool GetFileNameForThisAction$(bool value, unsigned long a0, char *a1, unsigned long a2, bool &a3) {
2244 NSLog(@"WB:Debug:GetFileNameForThisAction(%lu, %s, %lu, %u) = %u", a0, value ? a1 : NULL, a2, a3, value);
2247 NSString *path = [NSString stringWithUTF8String:a1];
2248 if ([path hasPrefix:@"/System/Library/Audio/UISounds/"]) {
2249 NSString *file = [path substringFromIndex:31];
2250 for (NSString *theme in Themes_) {
2251 NSString *path([NSString stringWithFormat:@"%@/UISounds/%@", theme, file]);
2252 if ([Manager_ fileExistsAtPath:path]) {
2253 strcpy(a1, [path UTF8String]);
2262 MSHook(bool, _Z24GetFileNameForThisActionmPcRb, unsigned long a0, char *a1, bool &a3) {
2263 bool value(__Z24GetFileNameForThisActionmPcRb(a0, a1, a3));
2264 return GetFileNameForThisAction$(value, a0, a1, 0, a3);
2268 MSHook(bool, _Z24GetFileNameForThisActionjPcjRb, unsigned int a0, char *a1, unsigned int a2, bool &a3) {
2269 bool value(__Z24GetFileNameForThisActionjPcjRb(a0, a1, a2, a3));
2270 return GetFileNameForThisAction$(value, a0, a1, a2, a3);
2273 MSHook(bool, _Z24GetFileNameForThisActionmPcmRb, unsigned long a0, char *a1, unsigned long a2, bool &a3) {
2274 bool value(__Z24GetFileNameForThisActionmPcmRb(a0, a1, a2, a3));
2275 return GetFileNameForThisAction$(value, a0, a1, a2, a3);
2279 static void ChangeWallpaper(
2280 CFNotificationCenterRef center,
2284 CFDictionaryRef info
2287 NSLog(@"WB:Debug:ChangeWallpaper!");
2290 if (WallpaperFile_ != nil) {
2291 image = [[UIImage alloc] initWithContentsOfFile:WallpaperFile_];
2293 image = [image autorelease];
2296 if (WallpaperImage_ != nil)
2297 [WallpaperImage_ setImage:image];
2298 if (WallpaperPage_ != nil)
2299 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
2303 MSHook(NSArray *, CPBitmapCreateImagesFromPath, NSString *path, CFTypeRef *names, void *arg2, void *arg3) {
2304 NSArray *images(_CPBitmapCreateImagesFromPath(path, names, arg2, arg3));
2307 if (names == NULL || *names == nil)
2310 NSBundle *bundle([NSBundle wb$bundleWithFile:path]);
2314 NSString *file([path stringByResolvingSymlinksInPath]);
2315 NSString *prefix([[bundle bundlePath] stringByResolvingSymlinksInPath]);
2316 // XXX: why do I care about this?
2317 if (![file hasPrefix:prefix])
2320 NSMutableArray *copy([images mutableCopy]);
2324 NSDictionary *indexes;
2325 NSEnumerator *enumerator;
2327 if (CFGetTypeID((CFTypeRef) *names) == CFDictionaryGetTypeID()) {
2328 indexes = (NSDictionary *) *names;
2329 enumerator = [indexes keyEnumerator];
2332 enumerator = [(NSArray *) *names objectEnumerator];
2335 for (NSUInteger index(0); NSString *name = [enumerator nextObject]; ++index)
2336 if (NSString *themed = $pathForFile$inBundle$([name stringByAppendingString:@".png"], bundle, true)) {
2338 index = [[indexes objectForKey:name] intValue];
2339 if (UIImage *image = $getImage$(themed))
2340 [copy replaceObjectAtIndex:index withObject:(id)[image CGImage]];
2346 MSHook(void, BKSDisplayServicesSetSystemAppExitedImagePath, NSString *path) {
2347 if (NSString *themed = $getTheme$($useScale$([NSArray arrayWithObject:@"SystemAppExited.png"])))
2349 _BKSDisplayServicesSetSystemAppExitedImagePath(path);
2352 #define WBRename(name, sel, imp) \
2353 MSHookMessage($ ## name, @selector(sel), &$ ## name ## $ ## imp, &_ ## name ## $ ## imp)
2355 template <typename Type_>
2356 static void msset(Type_ &function, MSImageRef image, const char *name) {
2357 function = reinterpret_cast<Type_>(MSFindSymbol(image, name));
2360 #define WBHookSymbol(image, function) \
2361 msset(function, image, "_" #function)
2363 template <typename Type_>
2364 static void dlset(Type_ &function, const char *name) {
2365 function = reinterpret_cast<Type_>(dlsym(RTLD_DEFAULT, name));
2368 // %hook CGImageReadCreateWithFile() {{{
2369 MSHook(void *, CGImageReadCreateWithFile, NSString *path, int flag) {
2371 NSLog(@"WB:Debug: CGImageReadCreateWithFile(%@, %d)", path, flag);
2372 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2373 void *value(_CGImageReadCreateWithFile([path wb$themedPath], flag));
2378 MSHook(void *, CGImageSourceCreateWithFile, NSString *path, NSDictionary *options) {
2380 NSLog(@"WB:Debug: CGImageSourceCreateWithFile(%@, %@)", path, options);
2381 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2382 void *value(_CGImageSourceCreateWithFile([path wb$themedPath], options));
2387 MSHook(void *, CGImageSourceCreateWithURL, NSURL *url, NSDictionary *options) {
2389 NSLog(@"WB:Debug: CGImageSourceCreateWithURL(%@, %@)", url, options);
2390 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2391 if ([url isFileURL])
2392 url = [NSURL fileURLWithPath:[[url path] wb$themedPath]];
2393 void *value(_CGImageSourceCreateWithURL(url, options));
2399 static void NSString$drawAtPoint$withStyle$(NSString *self, SEL _cmd, CGPoint point, NSString *style) {
2400 WKSetCurrentGraphicsContext(UIGraphicsGetCurrentContext());
2401 if (style == nil || [style length] == 0)
2402 style = @"font-family: Helvetica; font-size: 12px";
2403 //NSLog(@"XXX:drawP(%@ | %@)", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "]);
2404 [[WBMarkup sharedMarkup] drawString:self atPoint:point withStyle:style];
2407 static void NSString$drawInRect$withStyle$(NSString *self, SEL _cmd, CGRect rect, NSString *style) {
2408 WKSetCurrentGraphicsContext(UIGraphicsGetCurrentContext());
2409 if (style == nil || [style length] == 0)
2410 style = @"font-family: Helvetica; font-size: 12px";
2411 //NSLog(@"XXX:drawR(%@ | %@)", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "]);
2412 return [[WBMarkup sharedMarkup] drawString:self inRect:rect withStyle:style];
2415 static CGSize NSString$sizeWithStyle$forWidth$(NSString *self, SEL _cmd, NSString *style, CGFloat width) {
2416 if (style == nil || [style length] == 0)
2417 style = @"font-family: Helvetica; font-size: 12px";
2418 CGSize size([[WBMarkup sharedMarkup] sizeOfString:self withStyle:style forWidth:width]);
2419 //NSLog(@"XXX:size(%@ | %@) = [%g %g]", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "], size.width, size.height);
2423 static void SBInitialize() {
2425 WBRename(SBApplication, pathForIcon, pathForIcon);
2426 WBRename(SBApplicationIcon, icon, icon);
2427 WBRename(SBApplicationIcon, generateIconImage:, generateIconImage$);
2430 WBRename(SBBookmarkIcon, icon, icon);
2431 WBRename(SBButtonBar, didMoveToSuperview, didMoveToSuperview);
2432 WBRename(SBCalendarIconContentsView, drawRect:, drawRect$);
2433 WBRename(SBIconBadge, initWithBadge:, initWithBadge$);
2434 WBRename(SBIconController, noteNumberOfIconListsChanged, noteNumberOfIconListsChanged);
2436 WBRename(SBWidgetApplicationIcon, icon, icon);
2438 WBRename(SBDockIconListView, setFrame:, setFrame$);
2439 MSHookMessage(object_getClass($SBDockIconListView), @selector(shouldShowNewDock), &$SBDockIconListView$shouldShowNewDock, &_SBDockIconListView$shouldShowNewDock);
2441 if (kCFCoreFoundationVersionNumber < 600 || SummerBoard_)
2442 WBRename(SBIconLabel, drawRect:, drawRect$);
2443 else if (kCFCoreFoundationVersionNumber < 700) {
2444 WBRename(SBIconLabel, buildLabelImage, buildLabelImage);
2446 WBRename(SBIconLabelImageParameters, hash, hash);
2447 WBRename($SBIconView, _labelImageParametersForIcon:location:, _labelImageParametersForIcon$location$);
2448 WBRename(SBIconView, _labelImageParameters, _labelImageParameters);
2449 WBRename($SBIconLabelImage, _drawLabelImageForParameters:, _drawLabelImageForParameters$);
2452 WBRename(SBIconLabel, initWithSize:label:, initWithSize$label$);
2453 WBRename(SBIconLabel, setInDock:, setInDock$);
2455 WBRename(SBIconList, didMoveToSuperview, didMoveToSuperview);
2456 WBRename(SBIconList, setFrame:, setFrame$);
2458 WBRename(SBIconModel, cacheImageForIcon:, cacheImageForIcon$);
2459 WBRename(SBIconModel, cacheImagesForIcon:, cacheImagesForIcon$);
2460 WBRename(SBIconModel, getCachedImagedForIcon:, getCachedImagedForIcon$);
2461 WBRename(SBIconModel, getCachedImagedForIcon:smallIcon:, getCachedImagedForIcon$smallIcon$);
2463 if (kCFCoreFoundationVersionNumber < 800) {
2464 WBRename(SBSearchView, initWithFrame:, initWithFrame$);
2465 WBRename(SBSearchTableViewCell, drawRect:, drawRect$);
2466 WBRename(SBSearchTableViewCell, initWithStyle:reuseIdentifier:, initWithStyle$reuseIdentifier$);
2469 //WBRename(SBImageCache, initWithName:forImageWidth:imageHeight:initialCapacity:, initWithName$forImageWidth$imageHeight$initialCapacity$);
2471 WBRename(SBAwayView, updateDesktopImage:, updateDesktopImage$);
2472 if (kCFCoreFoundationVersionNumber >= 700)
2473 WBRename(SBAwayView, _addSubview:positioned:relativeTo:, _addSubview$positioned$relativeTo$);
2475 WBRename(SBStatusBarContentsView, didMoveToSuperview, didMoveToSuperview);
2476 //WBRename(SBStatusBarContentsView, initWithStatusBar:mode:, initWithStatusBar$mode$);
2477 //WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:animation:, setStatusBarMode$orientation$duration$animation$);
2478 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:, setStatusBarMode$orientation$duration$fenceID$animation$);
2479 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:startTime:, setStatusBarMode$orientation$duration$fenceID$animation$startTime$);
2480 WBRename(SBStatusBarOperatorNameView, operatorNameStyle, operatorNameStyle);
2481 WBRename(SBStatusBarOperatorNameView, setOperatorName:fullSize:, setOperatorName$fullSize$);
2482 WBRename(SBStatusBarTimeView, drawRect:, drawRect$);
2485 English_ = [[NSDictionary alloc] initWithContentsOfFile:@"/System/Library/CoreServices/SpringBoard.app/English.lproj/LocalizedApplicationNames.strings"];
2487 if (kCFCoreFoundationVersionNumber >= 800) {
2488 WBRename(NSString, drawInRect:withAttributes:, drawInRect$withAttributes$);
2489 WBRename(NSString, boundingRectWithSize:options:attributes:context:, boundingRectWithSize$options$attributes$context$);
2493 /*MSHook(int, open, const char *path, int oflag, mode_t mode) {
2494 int fd(_open(path, oflag, mode));
2496 static bool no(false);
2500 if (strstr(path, "/icon") != NULL)
2501 *reinterpret_cast<void *volatile *>(NULL) = NULL;
2503 if (fd == -1 && errno == EFAULT)
2504 NSLog(@"open(%p, %#x, %#o) = %d\n", path, oflag, mode, fd);
2506 NSLog(@"open(\"%s\", %#x, %#o) = %d\n", path, oflag, mode, fd);
2513 $objc_setAssociatedObject = reinterpret_cast<void (*)(id, void *, id value, objc_AssociationPolicy)>(dlsym(RTLD_DEFAULT, "objc_setAssociatedObject"));
2514 $objc_getAssociatedObject = reinterpret_cast<id (*)(id, void *)>(dlsym(RTLD_DEFAULT, "objc_getAssociatedObject"));
2515 $objc_removeAssociatedObjects = reinterpret_cast<void (*)(id)>(dlsym(RTLD_DEFAULT, "objc_removeAssociatedObjects"));
2517 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2519 NSString *identifier([[NSBundle mainBundle] bundleIdentifier]);
2520 SpringBoard_ = [identifier isEqualToString:@"com.apple.springboard"];
2522 Manager_ = [[NSFileManager defaultManager] retain];
2523 Themes_ = [[NSMutableArray alloc] initWithCapacity:8];
2525 dlset(_GSFontGetUseLegacyFontMetrics, "GSFontGetUseLegacyFontMetrics");
2527 // Initialize IsWild_ {{{
2529 sysctlbyname("hw.machine", NULL, &size, NULL, 0);
2530 char *machine = new char[size];
2532 if (sysctlbyname("hw.machine", machine, &size, NULL, 0) == -1) {
2533 perror("sysctlbyname(\"hw.machine\", ?)");
2538 IsWild_ = machine != NULL && strncmp(machine, "iPad", 4) == 0;
2540 // Load Settings.plist {{{
2541 if (NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"/User/Library/Preferences/com.saurik.WinterBoard.plist"]]) {
2542 if (kCFCoreFoundationVersionNumber >= 1000)
2543 SummerBoard_ = false;
2544 else if (NSNumber *value = [settings objectForKey:@"SummerBoard"])
2545 SummerBoard_ = [value boolValue];
2547 SummerBoard_ = true;
2549 if (NSNumber *value = [settings objectForKey:@"Debug"])
2550 Debug_ = [value boolValue];
2551 if (NSNumber *value = [settings objectForKey:@"RecordUI"])
2552 UIDebug_ = [value boolValue];
2554 NSArray *themes([settings objectForKey:@"Themes"]);
2556 if (NSString *theme = [settings objectForKey:@"Theme"])
2557 themes = [NSArray arrayWithObject:[NSDictionary dictionaryWithObjectsAndKeys:
2559 [NSNumber numberWithBool:true], @"Active",
2563 for (NSDictionary *theme in themes) {
2564 NSNumber *active([theme objectForKey:@"Active"]);
2565 if (![active boolValue])
2568 NSString *name([theme objectForKey:@"Name"]);
2572 #define testForTheme(format...) \
2574 NSString *path = [NSString stringWithFormat:format]; \
2575 if ([Manager_ fileExistsAtPath:path]) { \
2576 [Themes_ addObject:path]; \
2581 testForTheme(@"/Library/Themes/%@.theme", name)
2582 testForTheme(@"/Library/Themes/%@", name)
2583 testForTheme(@"%@/Library/SummerBoard/Themes/%@", NSHomeDirectory(), name)
2588 // Merge Info.plist {{{
2589 Info_ = [[NSMutableDictionary dictionaryWithCapacity:16] retain];
2591 for (NSString *theme in Themes_)
2592 if (NSDictionary *info = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"%@/Info.plist", theme]])
2593 for (NSString *key in [info allKeys])
2594 if ([Info_ objectForKey:key] == nil)
2595 [Info_ setObject:[info objectForKey:key] forKey:key];
2599 if (MSImageRef image = MSGetImageByName("/System/Library/PrivateFrameworks/AppSupport.framework/AppSupport")) {
2600 NSArray *(*CPBitmapCreateImagesFromPath)(NSString *, CFTypeRef *, void *, void *);
2601 msset(CPBitmapCreateImagesFromPath, image, "_CPBitmapCreateImagesFromPath");
2602 MSHookFunction(CPBitmapCreateImagesFromPath, MSHake(CPBitmapCreateImagesFromPath));
2606 if (MSImageRef image = MSGetImageByName(AudioToolbox)) {
2607 bool (*_Z24GetFileNameForThisActionmPcRb)(unsigned long, char *, bool &);
2608 msset(_Z24GetFileNameForThisActionmPcRb, image, "__Z24GetFileNameForThisActionmPcRb");
2609 MSHookFunction(_Z24GetFileNameForThisActionmPcRb, &$_Z24GetFileNameForThisActionmPcRb, &__Z24GetFileNameForThisActionmPcRb);
2612 bool (*_Z24GetFileNameForThisActionjPcjRb)(unsigned int, char *, unsigned int, bool &);
2613 msset(_Z24GetFileNameForThisActionjPcjRb, image, "__Z24GetFileNameForThisActionjPcjRb");
2614 MSHookFunction(_Z24GetFileNameForThisActionjPcjRb, &$_Z24GetFileNameForThisActionjPcjRb, &__Z24GetFileNameForThisActionjPcjRb);
2616 bool (*_Z24GetFileNameForThisActionmPcmRb)(unsigned long, char *, unsigned long, bool &);
2617 msset(_Z24GetFileNameForThisActionmPcmRb, image, "__Z24GetFileNameForThisActionmPcmRb");
2618 MSHookFunction(_Z24GetFileNameForThisActionmPcmRb, &$_Z24GetFileNameForThisActionmPcmRb, &__Z24GetFileNameForThisActionmPcmRb);
2622 // BackBoardServices {{{
2623 if (MSImageRef image = MSGetImageByName("/System/Library/PrivateFrameworks/BackBoardServices.framework/BackBoardServices")) {
2624 void (*BKSDisplayServicesSetSystemAppExitedImagePath)(NSString *path);
2625 msset(BKSDisplayServicesSetSystemAppExitedImagePath, image, "_BKSDisplayServicesSetSystemAppExitedImagePath");
2626 MSHookFunction(BKSDisplayServicesSetSystemAppExitedImagePath, MSHake(BKSDisplayServicesSetSystemAppExitedImagePath));
2631 if (![identifier isEqualToString:@"com.apple.backupd"]) // XXX: rethink
2632 MSHookFunction(CFBundleCopyResourceURL, MSHake(CFBundleCopyResourceURL));
2635 // GraphicsServices {{{
2637 MSHookFunction(&GSFontCreateWithName, &$GSFontCreateWithName, &_GSFontCreateWithName);
2641 MSImageRef imageio = MSGetImageByName("/System/Library/Frameworks/ImageIO.framework/ImageIO");
2642 if (imageio == NULL)
2643 imageio = MSGetImageByName("/System/Library/PrivateFrameworks/ImageIO.framework/ImageIO");
2644 if (MSImageRef image = imageio) {
2645 void *(*CGImageReadCreateWithFile)(NSString *, int) = NULL;
2646 if (kCFCoreFoundationVersionNumber > 700) // XXX: iOS 6.x
2647 CGImageReadCreateWithFile = NULL;
2649 msset(CGImageReadCreateWithFile, image, "_CGImageReadCreateWithFile");
2650 MSHookFunction(CGImageReadCreateWithFile, MSHake(CGImageReadCreateWithFile));
2653 if (CGImageReadCreateWithFile == NULL) {
2654 void *(*CGImageSourceCreateWithFile)(NSString *, NSDictionary *);
2655 msset(CGImageSourceCreateWithFile, image, "_CGImageSourceCreateWithFile");
2656 MSHookFunction(CGImageSourceCreateWithFile, MSHake(CGImageSourceCreateWithFile));
2658 void *(*CGImageSourceCreateWithURL)(NSURL *, NSDictionary *);
2659 msset(CGImageSourceCreateWithURL, image, "_CGImageSourceCreateWithURL");
2660 MSHookFunction(CGImageSourceCreateWithURL, MSHake(CGImageSourceCreateWithURL));
2666 Wallpapers_ = [[NSArray arrayWithObjects:@"Wallpaper.mp4", @"Wallpaper@3x.png", @"Wallpaper@3x.jpg", @"Wallpaper@2x.png", @"Wallpaper@2x.jpg", @"Wallpaper.png", @"Wallpaper.jpg", @"Wallpaper.html", nil] retain];
2667 Papered_ = $getTheme$(Wallpapers_) != nil;
2668 Docked_ = $getTheme$([NSArray arrayWithObjects:@"Dock.png", nil]) != nil;
2670 CFNotificationCenterAddObserver(
2671 CFNotificationCenterGetDarwinNotifyCenter(),
2672 NULL, &ChangeWallpaper, (CFStringRef) @"com.saurik.winterboard.lockbackground", NULL, CFNotificationSuspensionBehaviorCoalesce
2675 if ($getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"]) != nil) {
2676 NSBundle *MediaPlayer([NSBundle bundleWithPath:@"/System/Library/Frameworks/MediaPlayer.framework"]);
2677 if (MediaPlayer != nil)
2680 $MPMoviePlayerController = objc_getClass("MPMoviePlayerController");
2681 $MPVideoView = objc_getClass("MPVideoView");
2688 if (MSImageRef image = MSGetImageByName("/System/Library/Frameworks/UIKit.framework/UIKit")) {
2690 class_addMethod($NSString, @selector(drawAtPoint:withStyle:), (IMP) &NSString$drawAtPoint$withStyle$, "v40@0:8{CGPoint=dd}16@32");
2691 class_addMethod($NSString, @selector(drawInRect:withStyle:), (IMP) &NSString$drawInRect$withStyle$, "v56@0:8{CGRect={CGSize=dd}{CGSize=dd}}16@48");
2692 class_addMethod($NSString, @selector(sizeWithStyle:forWidth:), (IMP) &NSString$sizeWithStyle$forWidth$, "{CGSize=dd}32@0:8@16d24");
2694 class_addMethod($NSString, @selector(drawAtPoint:withStyle:), (IMP) &NSString$drawAtPoint$withStyle$, "v20@0:4{CGPoint=ff}8@16");
2695 class_addMethod($NSString, @selector(drawInRect:withStyle:), (IMP) &NSString$drawInRect$withStyle$, "v28@0:4{CGRect={CGSize=ff}{CGSize=ff}}8@24");
2696 class_addMethod($NSString, @selector(sizeWithStyle:forWidth:), (IMP) &NSString$sizeWithStyle$forWidth$, "{CGSize=ff}16@0:4@8f12");
2699 WBHookSymbol(image, _UIKitBundle);
2701 if (kCFCoreFoundationVersionNumber < 700)
2702 MSHookFunction(_UIImageWithName, MSHake(_UIImageWithName));
2704 WBHookSymbol(image, _UIApplicationImageWithName);
2705 MSHookFunction(_UIApplicationImageWithName, MSHake(_UIApplicationImageWithName));
2707 WBHookSymbol(image, _UIImageWithNameInDomain);
2708 MSHookFunction(_UIImageWithNameInDomain, MSHake(_UIImageWithNameInDomain));
2710 SEL includeEmoji(@selector(_legacy_drawAtPoint:forWidth:withFont:lineBreakMode:letterSpacing:includeEmoji:));
2711 if (![@"" respondsToSelector:includeEmoji])
2712 includeEmoji = @selector(drawAtPoint:forWidth:withFont:lineBreakMode:letterSpacing:includeEmoji:);
2713 MSHookMessage($NSString, includeEmoji, MSHake(NSString$drawAtPoint$forWidth$withFont$lineBreakMode$letterSpacing$includeEmoji$));
2715 SEL letterSpacing(@selector(_legacy_sizeWithFont:forWidth:lineBreakMode:letterSpacing:));
2716 if (![@"" respondsToSelector:letterSpacing])
2717 letterSpacing = @selector(sizeWithFont:forWidth:lineBreakMode:letterSpacing:);
2718 MSHookMessage($NSString, letterSpacing, MSHake(NSString$sizeWithFont$forWidth$lineBreakMode$letterSpacing$));
2720 SEL sizeWithFont(@selector(_legacy_sizeWithFont:));
2721 if (![@"" respondsToSelector:sizeWithFont])
2722 sizeWithFont = @selector(sizeWithFont:);
2723 MSHookMessage($NSString, sizeWithFont, MSHake(NSString$sizeWithFont$));
2725 MSHookMessage($NSAttributedString, @selector(drawAtPoint:), MSHake(NSAttributedString$drawAtPoint$));
2726 MSHookMessage($NSAttributedString, @selector(boundingRectWithSize:options:context:), MSHake(NSAttributedString$boundingRectWithSize$options$context$));
2730 //MSHookFunction(reinterpret_cast<int (*)(const char *, int, mode_t)>(&open), MSHake(open));