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 return (CGRect) {{0, 0}, [[self string] sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], WBColorMarkup(color), base, info] forWidth:size.width]};
1043 MSInstanceMessage4(CGSize, NSString, sizeWithFont,forWidth,lineBreakMode,letterSpacing, UIFont *, font, CGFloat, width, UILineBreakMode, mode, CGFloat, spacing) {
1044 //NSLog(@"XXX: #\"%@\" \"%@\" %g %u %g", self, font, width, mode, spacing);
1046 WBStringDrawingState *state(stringDrawingState_);
1048 return MSOldCall(font, width, mode, spacing);
1050 if (state->count_ != 0 && --state->count_ == 0)
1051 stringDrawingState_ = state->next_;
1052 if (state->info_ == nil)
1053 return MSOldCall(font, width, mode, spacing);
1055 NSString *info([Info_ objectForKey:state->info_]);
1057 return MSOldCall(font, width, mode, spacing);
1059 NSString *base(state->base_ ?: @"");
1060 NSString *extra([NSString stringWithFormat:@"letter-spacing: %gpx", spacing]);
1061 return [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info] forWidth:width];
1064 MSInstanceMessage1(CGSize, NSString, sizeWithFont, UIFont *, font) {
1065 //NSLog(@"XXX: ?\"%@\"", self);
1067 WBStringDrawingState *state(stringDrawingState_);
1069 return MSOldCall(font);
1071 if (state->count_ != 0 && --state->count_ == 0)
1072 stringDrawingState_ = state->next_;
1073 if (state->info_ == nil)
1074 return MSOldCall(font);
1076 NSString *info([Info_ objectForKey:state->info_]);
1078 return MSOldCall(font);
1080 NSString *base(state->base_ ?: @"");
1081 return [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), base, info] forWidth:65535];
1084 MSClassMessageHook2(id, SBIconBadgeView, checkoutAccessoryImagesForIcon,location, id, icon, int, location) {
1085 WBStringDrawingState badgeState = {NULL, 0, @""
1088 stringDrawingState_ = &badgeState;
1090 id images(MSOldCall(icon, location));
1092 stringDrawingState_ = NULL;
1096 MSClassMessageHook2(UIImage *, SBIconAccessoryImage, checkoutAccessoryImageForIcon,location, id, icon, int, location) {
1097 if ([self _imageClassForIcon:icon location:location] != $SBIconBadgeImage)
1098 return MSOldCall(icon, location);
1100 WBStringDrawingState badgeState = {NULL, 0, @""
1103 stringDrawingState_ = &badgeState;
1105 UIImage *image(MSOldCall(icon, location));
1107 stringDrawingState_ = NULL;
1111 MSInstanceMessageHook1(UIImage *, SBIconBadgeFactory, checkoutBadgeImageForText, NSString *, text) {
1112 WBStringDrawingState badgeState = {NULL, 0, @""
1115 stringDrawingState_ = &badgeState;
1117 UIImage *image(MSOldCall(text));
1119 stringDrawingState_ = NULL;
1123 MSInstanceMessageHook1(UIImage *, SBCalendarApplicationIcon, generateIconImage, int, type) {
1124 WBStringDrawingState dayState = {NULL, unsigned(kCFCoreFoundationVersionNumber >= 1200 ? 1 : 2), @""
1125 // XXX: this is only correct on an iPod dock
1126 "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px;"
1127 , @"CalendarIconDayStyle"};
1130 if (kCFCoreFoundationVersionNumber < 800)
1132 else if (kCFCoreFoundationVersionNumber < 1200)
1137 WBStringDrawingState skipState = {&dayState, skips, nil, nil};
1139 WBStringDrawingState dateState = {&skipState, 2, @""
1140 , @"CalendarIconDateStyle"};
1142 stringDrawingState_ = &dateState;
1144 UIImage *image(MSOldCall(type));
1146 stringDrawingState_ = NULL;
1150 MSInstanceMessageHook1(UIImage *, UIStatusBarTimeItemView, contentsImageForStyle, int, style) {
1151 WBStringDrawingState timeState = {NULL, 0, @""
1154 stringDrawingState_ = &timeState;
1156 UIImage *image(MSOldCall(style));
1158 stringDrawingState_ = NULL;
1162 MSHook(void, SBCalendarIconContentsView$drawRect$, SBCalendarIconContentsView *self, SEL sel, CGRect rect) {
1163 NSBundle *bundle([NSBundle mainBundle]);
1165 CFLocaleRef locale(CFLocaleCopyCurrent());
1166 CFDateFormatterRef formatter(CFDateFormatterCreate(NULL, locale, kCFDateFormatterNoStyle, kCFDateFormatterNoStyle));
1169 CFDateRef now(CFDateCreate(NULL, CFAbsoluteTimeGetCurrent()));
1171 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NUMBER_FORMAT" value:@"d" table:@"SpringBoard"]);
1172 CFStringRef date(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
1173 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NAME_FORMAT" value:@"cccc" table:@"SpringBoard"]);
1174 CFStringRef day(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
1178 CFRelease(formatter);
1180 NSString *datestyle([@""
1181 "font-family: Helvetica; "
1182 "font-weight: bold; "
1185 "" stringByAppendingString:(IsWild_
1186 ? @"font-size: 54px; "
1187 : @"font-size: 39px; "
1190 NSString *daystyle([@""
1191 "font-family: Helvetica; "
1192 "font-weight: bold; "
1194 "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px; "
1195 "" stringByAppendingString:(IsWild_
1196 ? @"font-size: 11px; "
1197 : @"font-size: 9px; "
1200 if (NSString *style = [Info_ objectForKey:@"CalendarIconDateStyle"])
1201 datestyle = [datestyle stringByAppendingString:style];
1202 if (NSString *style = [Info_ objectForKey:@"CalendarIconDayStyle"])
1203 daystyle = [daystyle stringByAppendingString:style];
1205 CGFloat width([self bounds].size.width);
1207 CGSize datesize = [(NSString *)date sizeWithStyle:datestyle forWidth:(width + leeway)];
1208 CGSize daysize = [(NSString *)day sizeWithStyle:daystyle forWidth:(width + leeway)];
1210 unsigned base0(IsWild_ ? 89 : 70);
1211 if ($GSFontGetUseLegacyFontMetrics())
1213 unsigned base1(IsWild_ ? 18 : 16);
1220 [(NSString *)date drawAtPoint:CGPointMake(
1221 (width + 1 - datesize.width) / 2, (base0 - datesize.height) / 2
1222 ) withStyle:datestyle];
1224 [(NSString *)day drawAtPoint:CGPointMake(
1225 (width + 1 - daysize.width) / 2, (base1 - daysize.height) / 2
1226 ) withStyle:daystyle];
1232 // %hook -[{NavigationBar,Toolbar} setBarStyle:] {{{
1233 void $setBarStyle$_(NSString *name, int &style) {
1235 NSLog(@"WB:Debug:%@Style:%d", name, style);
1236 NSNumber *number = nil;
1238 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style-%d", name, style]];
1240 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style", name]];
1241 if (number != nil) {
1242 style = [number intValue];
1244 NSLog(@"WB:Debug:%@Style=%d", name, style);
1248 MSInstanceMessageHook1(void, UIToolbar, setBarStyle, int, style) {
1249 $setBarStyle$_(@"Toolbar", style);
1250 return MSOldCall(style);
1253 MSInstanceMessageHook1(void, UINavigationBar, setBarStyle, int, style) {
1254 $setBarStyle$_(@"NavigationBar", style);
1255 return MSOldCall(style);
1259 MSHook(void, SBButtonBar$didMoveToSuperview, UIView *self, SEL sel) {
1260 [[self superview] setBackgroundColor:[UIColor clearColor]];
1261 _SBButtonBar$didMoveToSuperview(self, sel);
1264 MSHook(void, SBStatusBarContentsView$didMoveToSuperview, UIView *self, SEL sel) {
1265 [[self superview] setBackgroundColor:[UIColor clearColor]];
1266 _SBStatusBarContentsView$didMoveToSuperview(self, sel);
1269 static NSArray *Wallpapers_;
1270 static bool Papered_;
1271 static bool Docked_;
1272 static bool SMSBackgrounded_;
1273 static NSString *WallpaperFile_;
1274 static UIImageView *WallpaperImage_;
1275 static UIWebDocumentView *WallpaperPage_;
1276 static NSURL *WallpaperURL_;
1278 #define _release(object) \
1279 do if (object != nil) { \
1284 static UIImage *$getImage$(NSString *path) {
1285 UIImage *image([UIImage imageWithContentsOfFile:path]);
1287 unsigned scale($getScale$(path));
1288 if (scale != 1 && [image respondsToSelector:@selector(setScale)])
1289 [image setScale:scale];
1294 template <typename Original_, typename Modified_>
1295 _finline UIImage *WBCacheImage(const Modified_ &modified, const Original_ &original, NSString *key) {
1296 UIImage *image([Images_ objectForKey:key]);
1298 return reinterpret_cast<id>(image) == [NSNull null] ? original() : image;
1299 if (NSString *path = modified())
1300 image = $getImage$(path);
1301 [Images_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:key];
1302 return image == nil ? original() : image;
1305 static UIImage *$getDefaultDesktopImage$() {
1306 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"LockBackground.png", @"LockBackground.jpg", nil])))
1307 return $getImage$(path);
1311 MSClassMessageHook0(UIImage *, UIImage, defaultDesktopImage) {
1312 return $getDefaultDesktopImage$() ?: MSOldCall();
1315 MSInstanceMessageHook0(UIImage *, SBSlidingAlertDisplay, _defaultDesktopImage) {
1316 return $getDefaultDesktopImage$() ?: MSOldCall();
1319 MSInstanceMessageHook0(void, SBWallpaperView, resetCurrentImageToWallpaper) {
1320 for (UIView *parent([self superview]); parent != nil; parent = [parent superview])
1321 if ([parent isKindOfClass:$SBSlidingAlertDisplay]) {
1322 if (UIImage *image = $getDefaultDesktopImage$()) {
1323 [self setImage:image];
1333 // %hook -[SBUIController init] {{{
1334 MSInstanceMessageHook0(id, SBUIController, init) {
1339 NSString *paper($getTheme$(Wallpapers_));
1341 paper = [paper stringByDeletingLastPathComponent];
1344 NSLog(@"WB:Debug:Info = %@", [Info_ description]);
1347 UIImageView *&_wallpaperView(MSHookIvar<UIImageView *>(self, "_wallpaperView"));
1348 if (&_wallpaperView != NULL) {
1349 [_wallpaperView removeFromSuperview];
1350 [_wallpaperView release];
1351 _wallpaperView = nil;
1355 UIView *&_contentLayer(MSHookIvar<UIView *>(self, "_contentLayer"));
1356 UIView *&_contentView(MSHookIvar<UIView *>(self, "_contentView"));
1359 if (&_contentLayer != NULL)
1360 player = &_contentLayer;
1361 else if (&_contentView != NULL)
1362 player = &_contentView;
1365 UIView *layer(player == NULL ? nil : *player);
1367 UIWindow *window([[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]);
1368 UIView *content([[[UIView alloc] initWithFrame:[window frame]] autorelease]);
1369 [window setContentView:content];
1371 UIWindow *&_window(MSHookIvar<UIWindow *>(self, "_window"));
1372 [window setBackgroundColor:[_window backgroundColor]];
1373 [_window setBackgroundColor:[UIColor clearColor]];
1375 [window setLevel:-1000];
1376 [window setHidden:NO];
1378 /*if (player != NULL)
1379 *player = content;*/
1381 [content setBackgroundColor:[layer backgroundColor]];
1382 [layer setBackgroundColor:[UIColor clearColor]];
1385 if (!SummerBoard_ || !IsWild_)
1388 CGRect bounds([content bounds]);
1389 bounds.origin.y = -30;
1390 indirect = [[[UIView alloc] initWithFrame:bounds] autorelease];
1391 [content addSubview:indirect];
1392 [indirect zoomToScale:2.4];
1395 _release(WallpaperFile_);
1396 _release(WallpaperImage_);
1397 _release(WallpaperPage_);
1398 _release(WallpaperURL_);
1401 NSArray *themes([NSArray arrayWithObject:paper]);
1403 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"], themes)) {
1407 static AVController *controller_(nil);
1408 if (controller_ == nil) {
1409 AVQueue *queue([AVQueue avQueue]);
1410 controller_ = [[AVController avControllerWithQueue:queue error:&error] retain];
1413 AVQueue *queue([controller_ queue]);
1415 UIView *video([[[UIView alloc] initWithFrame:[indirect bounds]] autorelease]);
1416 [controller_ setLayer:[video _layer]];
1418 AVItem *item([[[AVItem alloc] initWithPath:path error:&error] autorelease]);
1419 [queue appendItem:item error:&error];
1421 [controller_ play:&error];
1422 #elif UseMPMoviePlayerController
1423 NSURL *url([NSURL fileURLWithPath:path]);
1424 MPMoviePlayerController *controller = [[$MPMoviePlayerController alloc] initWithContentURL:url];
1425 controller.movieControlMode = MPMovieControlModeHidden;
1428 MPVideoView *video = [[[$MPVideoView alloc] initWithFrame:[indirect bounds]] autorelease];
1429 [video setMovieWithPath:path];
1430 [video setRepeatMode:1];
1431 [video setRepeatGap:-1];
1432 [video playFromBeginning];;
1435 [indirect addSubview:video];
1438 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"Wallpaper.png", @"Wallpaper.jpg", nil]), themes)) {
1439 if (UIImage *image = $getImage$(path)) {
1440 WallpaperFile_ = [path retain];
1441 WallpaperImage_ = [[UIImageView alloc] initWithImage:image];
1442 if (NSNumber *number = [Info_ objectForKey:@"WallpaperAlpha"])
1443 [WallpaperImage_ setAlpha:[number floatValue]];
1444 [indirect addSubview:WallpaperImage_];
1448 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.html"], themes)) {
1449 CGRect bounds = [indirect bounds];
1451 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1452 [view setAutoresizes:true];
1454 WallpaperPage_ = [view retain];
1455 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
1457 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1459 [view setBackgroundColor:[UIColor clearColor]];
1460 if ([view respondsToSelector:@selector(setDrawsBackground:)])
1461 [view setDrawsBackground:NO];
1462 [[view webView] setDrawsBackground:NO];
1464 [indirect addSubview:view];
1468 for (size_t i(0), e([Themes_ count]); i != e; ++i) {
1469 NSString *theme = [Themes_ objectAtIndex:(e - i - 1)];
1470 NSString *html = [theme stringByAppendingPathComponent:@"Widget.html"];
1471 if ([Manager_ fileExistsAtPath:html]) {
1472 CGRect bounds = [indirect bounds];
1474 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1475 [view setAutoresizes:true];
1477 NSURL *url = [NSURL fileURLWithPath:html];
1478 [view loadRequest:[NSURLRequest requestWithURL:url]];
1480 [view setBackgroundColor:[UIColor clearColor]];
1481 if ([view respondsToSelector:@selector(setDrawsBackground:)])
1482 [view setDrawsBackground:NO];
1483 [[view webView] setDrawsBackground:NO];
1485 [indirect addSubview:view];
1493 MSHook(void, SBAwayView$updateDesktopImage$, SBAwayView *self, SEL sel, UIImage *image) {
1494 NSString *path = $getTheme$([NSArray arrayWithObject:@"LockBackground.html"]);
1495 UIView *&_backgroundView(MSHookIvar<UIView *>(self, "_backgroundView"));
1497 if (path != nil && _backgroundView != nil)
1500 _SBAwayView$updateDesktopImage$(self, sel, image);
1503 CGRect bounds = [self bounds];
1505 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1506 [view setAutoresizes:true];
1508 if (WallpaperPage_ != nil)
1509 [WallpaperPage_ release];
1510 WallpaperPage_ = [view retain];
1512 if (WallpaperURL_ != nil)
1513 [WallpaperURL_ release];
1514 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
1516 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1518 [[view webView] setDrawsBackground:false];
1519 [view setBackgroundColor:[UIColor clearColor]];
1521 [self insertSubview:view aboveSubview:_backgroundView];
1523 if ($objc_setAssociatedObject != NULL)
1524 $objc_setAssociatedObject(self, @selector(wb$widgetView), view, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1528 MSHook(void, SBAwayView$_addSubview$positioned$relativeTo$, SBAwayView *self, SEL sel, UIView *view, int positioned, UIView *relative) {
1529 UIView *&_backgroundView(MSHookIvar<UIView *>(self, "_backgroundView"));
1530 UIView *&_chargingView(MSHookIvar<UIView *>(self, "_chargingView"));
1531 if (&_chargingView != NULL)
1532 if (positioned == -2 && (relative == _backgroundView && _chargingView == nil || relative == _chargingView))
1533 if ($objc_getAssociatedObject != NULL)
1534 if (UIView *widget = $objc_getAssociatedObject(self, @selector(wb$widgetView)))
1536 return _SBAwayView$_addSubview$positioned$relativeTo$(self, sel, view, positioned, relative);
1539 /*extern "C" CGColorRef CGGStateGetSystemColor(void *);
1540 extern "C" CGColorRef CGGStateGetFillColor(void *);
1541 extern "C" CGColorRef CGGStateGetStrokeColor(void *);
1542 extern "C" NSString *UIStyleStringFromColor(CGColorRef);*/
1544 /* WBTimeLabel {{{ */
1545 @interface WBTimeLabel : NSProxy {
1547 _transient SBStatusBarTimeView *view_;
1550 - (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view;
1554 @implementation WBTimeLabel
1561 - (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view {
1562 time_ = [time retain];
1567 - (NSString *) description {
1573 - (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(UILineBreakMode)mode {
1574 if (NSString *custom = [Info_ objectForKey:@"TimeStyle"]) {
1575 BOOL &_mode(MSHookIvar<BOOL>(view_, "_mode"));;
1577 [time_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1578 "font-family: Helvetica; "
1579 "font-weight: bold; "
1582 "%@", _mode ? @"white" : @"black", custom]];
1587 return [time_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1592 /* WBBadgeLabel {{{ */
1593 @interface WBBadgeLabel : NSProxy {
1597 - (id) initWithBadge:(NSString *)badge;
1598 - (NSString *) description;
1602 @implementation WBBadgeLabel
1609 - (id) initWithBadge:(NSString *)badge {
1610 badge_ = [badge retain];
1614 - (NSString *) description {
1615 return [badge_ description];
1620 - (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(UILineBreakMode)mode {
1621 if (NSString *custom = [Info_ objectForKey:@"BadgeStyle"]) {
1622 [badge_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1623 "font-family: Helvetica; "
1624 "font-weight: bold; "
1632 return [badge_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1639 MSInstanceMessageHook1(void, SBIcon, setIconImageAlpha, CGFloat, alpha) {
1640 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1641 alpha = [number floatValue];
1642 return MSOldCall(alpha);
1645 MSInstanceMessageHook1(void, SBIcon, setIconLabelAlpha, CGFloat, alpha) {
1646 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1647 alpha = [number floatValue];
1648 return MSOldCall(alpha);
1651 MSInstanceMessageHook0(id, SBIcon, initWithDefaultSize) {
1652 if ((self = MSOldCall()) != nil) {
1653 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"]) {
1654 // XXX: note: this is overridden above, which is silly
1655 float alpha([number floatValue]);
1656 if ([self respondsToSelector:@selector(setIconImageAlpha:)])
1657 [self setIconImageAlpha:alpha];
1658 if ([self respondsToSelector:@selector(setIconLabelAlpha:)])
1659 [self setIconLabelAlpha:alpha];
1660 if ([self respondsToSelector:@selector(setAlpha:)])
1661 [self setAlpha:alpha];
1666 MSInstanceMessageHook1(void, SBIcon, setAlpha, CGFloat, alpha) {
1667 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1668 alpha = [number floatValue];
1669 return MSOldCall(alpha);
1673 MSHook(id, SBIconBadge$initWithBadge$, SBIconBadge *self, SEL sel, NSString *badge) {
1674 if ((self = _SBIconBadge$initWithBadge$(self, sel, badge)) != nil) {
1675 id &_badge(MSHookIvar<id>(self, "_badge"));
1677 if (id label = [[WBBadgeLabel alloc] initWithBadge:[_badge autorelease]])
1682 void SBStatusBarController$setStatusBarMode(int &mode) {
1684 NSLog(@"WB:Debug:setStatusBarMode:%d", mode);
1685 if (mode < 100) // 104:hidden 105:glowing
1686 if (NSNumber *number = [Info_ objectForKey:@"StatusBarMode"])
1687 mode = [number intValue];
1690 /*MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, double duration, int animation) {
1691 NSLog(@"mode:%d orientation:%d duration:%f animation:%d", mode, orientation, duration, animation);
1692 SBStatusBarController$setStatusBarMode(mode);
1693 return _SBStatusBarController$setStatusBarMode$orientation$duration$animation$(self, sel, mode, orientation, duration, animation);
1696 MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, float duration, int fenceID, int animation) {
1697 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d", mode, orientation, duration, fenceID, animation);
1698 SBStatusBarController$setStatusBarMode(mode);
1699 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$(self, sel, mode, orientation, duration, fenceID, animation);
1702 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) {
1703 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d startTime:%f", mode, orientation, duration, fenceID, animation, startTime);
1704 SBStatusBarController$setStatusBarMode(mode);
1705 //NSLog(@"mode=%u", mode);
1706 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$startTime$(self, sel, mode, orientation, duration, fenceID, animation, startTime);
1709 /*MSHook(id, SBStatusBarContentsView$initWithStatusBar$mode$, SBStatusBarContentsView *self, SEL sel, id bar, int mode) {
1710 if (NSNumber *number = [Info_ objectForKey:@"StatusBarContentsMode"])
1711 mode = [number intValue];
1712 return _SBStatusBarContentsView$initWithStatusBar$mode$(self, sel, bar, mode);
1715 MSHook(NSString *, SBStatusBarOperatorNameView$operatorNameStyle, SBStatusBarOperatorNameView *self, SEL sel) {
1716 NSString *style(_SBStatusBarOperatorNameView$operatorNameStyle(self, sel));
1718 NSLog(@"operatorNameStyle= %@", style);
1719 if (NSString *custom = [Info_ objectForKey:@"OperatorNameStyle"])
1720 style = [NSString stringWithFormat:@"%@; %@", style, custom];
1724 MSHook(void, SBStatusBarOperatorNameView$setOperatorName$fullSize$, SBStatusBarOperatorNameView *self, SEL sel, NSString *name, BOOL full) {
1726 NSLog(@"setOperatorName:\"%@\" fullSize:%u", name, full);
1727 return _SBStatusBarOperatorNameView$setOperatorName$fullSize$(self, sel, name, NO);
1730 // XXX: replace this with [SBStatusBarTimeView tile]
1731 MSHook(void, SBStatusBarTimeView$drawRect$, SBStatusBarTimeView *self, SEL sel, CGRect rect) {
1732 id &_time(MSHookIvar<id>(self, "_time"));
1733 if (_time != nil && [_time class] != [WBTimeLabel class])
1734 object_setInstanceVariable(self, "_time", reinterpret_cast<void *>([[WBTimeLabel alloc] initWithTime:[_time autorelease] view:self]));
1735 return _SBStatusBarTimeView$drawRect$(self, sel, rect);
1738 @interface UIView (WinterBoard)
1739 - (bool) wb$isWBImageView;
1740 - (void) wb$logHierarchy;
1741 - (void) wb$setBackgroundColor:(UIColor *)color;
1744 @implementation UIView (WinterBoard)
1746 - (bool) wb$isWBImageView {
1750 - (void) wb$logHierarchy {
1751 WBLogHierarchy(self);
1754 - (void) wb$setBackgroundColor:(UIColor *)color {
1755 [self setBackgroundColor:color];
1756 for (UIView *child in [self subviews])
1757 [child wb$setBackgroundColor:color];
1762 @interface WBImageView : UIImageView {
1765 - (bool) wb$isWBImageView;
1766 - (void) wb$updateFrame;
1769 @implementation WBImageView
1771 - (bool) wb$isWBImageView {
1775 - (void) wb$updateFrame {
1776 CGRect frame([self frame]);
1779 for (UIView *view(self); ; ) {
1780 view = [view superview];
1783 frame.origin.y -= [view frame].origin.y;
1786 [self setFrame:frame];
1791 static void SBIconList$updateFrames$(SBIconList *self) {
1792 NSArray *subviews([self subviews]);
1793 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1794 if (view != nil && [view wb$isWBImageView])
1795 [view wb$updateFrame];
1798 MSHook(void, SBIconList$didMoveToSuperview, SBIconList *self, SEL sel) {
1799 SBIconList$updateFrames$(self);
1800 _SBIconList$didMoveToSuperview(self, sel);
1803 MSHook(void, SBIconList$setFrame$, SBIconList *self, SEL sel, CGRect frame) {
1804 SBIconList$updateFrames$(self);
1805 _SBIconList$setFrame$(self, sel, frame);
1808 static void $addPerPageView$(unsigned i, UIView *list) {
1809 NSString *path($getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Page%u.png", i]]));
1813 NSArray *subviews([list subviews]);
1815 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1816 if (view == nil || ![view wb$isWBImageView]) {
1817 view = [[[WBImageView alloc] init] autorelease];
1818 [list insertSubview:view atIndex:0];
1821 UIImage *image([UIImage imageWithContentsOfFile:path]);
1823 CGRect frame([view frame]);
1824 frame.size = [image size];
1825 [view setFrame:frame];
1827 [view setImage:image];
1828 [view wb$updateFrame];
1831 static void $addPerPageViews$(NSArray *lists) {
1832 for (unsigned i(0), e([lists count]); i != e; ++i)
1833 $addPerPageView$(i, [lists objectAtIndex:i]);
1836 MSInstanceMessageHook0(void, SBIconController, updateNumberOfRootIconLists) {
1837 NSArray *&_rootIconLists(MSHookIvar<NSArray *>(self, "_rootIconLists"));
1838 $addPerPageViews$(_rootIconLists);
1842 MSInstanceMessageHook0(void, SBIconContentView, layoutSubviews) {
1845 if (SBIconController *controller = [$SBIconController sharedInstance]) {
1846 UIView *&_dockContainerView(MSHookIvar<UIView *>(controller, "_dockContainerView"));
1847 if (&_dockContainerView != NULL)
1848 [[_dockContainerView superview] bringSubviewToFront:_dockContainerView];
1852 MSHook(void, SBIconController$noteNumberOfIconListsChanged, SBIconController *self, SEL sel) {
1853 SBIconModel *&_iconModel(MSHookIvar<SBIconModel *>(self, "_iconModel"));
1854 $addPerPageViews$([_iconModel iconLists]);
1855 return _SBIconController$noteNumberOfIconListsChanged(self, sel);
1858 MSHook(id, SBIconLabel$initWithSize$label$, SBIconLabel *self, SEL sel, CGSize size, NSString *label) {
1859 self = _SBIconLabel$initWithSize$label$(self, sel, size, label);
1861 [self setClipsToBounds:NO];
1865 MSHook(void, SBIconLabel$setInDock$, SBIconLabel *self, SEL sel, BOOL docked) {
1866 static bool gssc(false);
1868 BOOL (*GSSystemHasCapability)(CFStringRef) = reinterpret_cast<BOOL (*)(CFStringRef)>(dlsym(RTLD_DEFAULT, "GSSystemHasCapability"));
1869 Papered_ |= GSSystemHasCapability != NULL && GSSystemHasCapability(CFSTR("homescreen-wallpaper"));
1872 if ([Info_ objectForKey:@"UndockedIconLabels"] == nil)
1873 [Info_ setObject:[NSNumber numberWithBool:(
1875 [Info_ objectForKey:@"DockedIconLabelStyle"] != nil ||
1876 [Info_ objectForKey:@"UndockedIconLabelStyle"] != nil
1877 )] forKey:@"UndockedIconLabels"];
1880 id &_label(MSHookIvar<id>(self, "_label"));
1881 if (![Info_ wb$boolForKey:@"UndockedIconLabels"])
1884 if (_label != nil && [_label respondsToSelector:@selector(setInDock:)])
1885 [_label setInDock:docked];
1887 _SBIconLabel$setInDock$(self, sel, docked);
1888 [self setNeedsDisplay];
1891 MSHook(BOOL, SBDockIconListView$shouldShowNewDock, id self, SEL sel) {
1892 return SummerBoard_ && Docked_ ? NO : _SBDockIconListView$shouldShowNewDock(self, sel);
1895 MSHook(void, SBDockIconListView$setFrame$, id self, SEL sel, CGRect frame) {
1896 _SBDockIconListView$setFrame$(self, sel, frame);
1899 // %hook -[NSBundle localizedStringForKey:value:table:] {{{
1900 MSInstanceMessageHook3(NSString *, NSBundle, localizedStringForKey,value,table, NSString *, key, NSString *, value, NSString *, table) {
1901 NSString *identifier = [self bundleIdentifier];
1902 NSLocale *locale = [NSLocale currentLocale];
1903 NSString *language = [locale objectForKey:NSLocaleLanguageCode];
1905 NSLog(@"WB:Debug:[NSBundle(%@) localizedStringForKey:\"%@\" value:\"%@\" table:\"%@\"] (%@)", identifier, key, value, table, language);
1906 NSString *file = table == nil ? @"Localizable" : table;
1907 NSString *name = [NSString stringWithFormat:@"%@:%@", identifier, file];
1908 NSDictionary *strings;
1909 if ((strings = [Strings_ objectForKey:name]) != nil) {
1910 if (static_cast<id>(strings) != [NSNull null]) strings:
1911 if (NSString *value = [strings objectForKey:key])
1913 } else if (NSString *path = $pathForFile$inBundle$([NSString stringWithFormat:@"%@.lproj/%@.strings",
1916 if ((strings = [[NSDictionary alloc] initWithContentsOfFile:path]) != nil) {
1917 [Strings_ setObject:[strings autorelease] forKey:name];
1921 [Strings_ setObject:[NSNull null] forKey:name];
1922 return MSOldCall(key, value, table);
1925 // %hook -[WebCoreFrameBridge renderedSizeOfNode:constrainedToWidth:] {{{
1926 MSClassHook(WebCoreFrameBridge)
1928 MSInstanceMessageHook2(CGSize, WebCoreFrameBridge, renderedSizeOfNode,constrainedToWidth, id, node, float, width) {
1931 void **core(reinterpret_cast<void **>([node _node]));
1932 if (core == NULL || core[6] == NULL)
1934 return MSOldCall(node, width);
1938 MSInstanceMessage1(void, SBIconLabel, drawRect, CGRect, rect) {
1939 static Ivar drawMoreLegibly = object_getInstanceVariable(self, "_drawMoreLegibly", NULL);
1942 Ivar ivar = object_getInstanceVariable(self, "_inDock", reinterpret_cast<void **>(&docked));
1943 docked = (docked & (ivar_getOffset(ivar) == ivar_getOffset(drawMoreLegibly) ? 0x2 : 0x1)) != 0;
1945 NSString *label(MSHookIvar<NSString *>(self, "_label"));
1947 NSString *style = [NSString stringWithFormat:@""
1948 "font-family: Helvetica; "
1949 "font-weight: bold; "
1951 "", (docked || !SummerBoard_ ? @"white" : @"#b3b3b3"), (IsWild_
1952 ? @"font-size: 12px; "
1953 : @"font-size: 11px; "
1957 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px 1px 0px; "];
1959 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px -1px 0px; "];
1961 NSString *custom([Info_ objectForKey:(docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle")]);
1963 $drawLabel$(label, [self bounds], style, custom);
1966 MSInstanceMessage0(CGImageRef, SBIconLabel, buildLabelImage) {
1967 bool docked((MSHookIvar<unsigned>(self, "_inDock") & 0x2) != 0);
1969 WBStringDrawingState labelState = {NULL, 0, @""
1970 , docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle"};
1972 stringDrawingState_ = &labelState;
1975 CGImageRef image(MSOldCall());
1978 stringDrawingState_ = NULL;
1982 static bool wb$inDock(id parameters) {
1983 return [$objc_getAssociatedObject(parameters, @selector(wb$inDock)) boolValue];
1986 MSInstanceMessage0(NSUInteger, SBIconLabelImageParameters, hash) {
1987 return MSOldCall() + (wb$inDock(self) ? 0xdeadbeef : 0xd15ea5e);
1990 MSClassMessage2(id, SBIconView, _labelImageParametersForIcon,location, id, icon, int, location) {
1991 if (id parameters = MSOldCall(icon, location)) {
1992 $objc_setAssociatedObject(parameters, @selector(wb$inDock), [NSNumber numberWithBool:(location == 1)], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1997 MSInstanceMessage0(id, SBIconView, _labelImageParameters) {
1998 if (id parameters = MSOldCall()) {
1999 int &location(MSHookIvar<int>(self, "_iconLocation"));
2000 if (&location != NULL)
2001 $objc_setAssociatedObject(parameters, @selector(wb$inDock), [NSNumber numberWithBool:(location == 3)], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
2006 MSClassMessage1(UIImage *, SBIconLabelImage, _drawLabelImageForParameters, id, parameters) {
2007 bool docked(wb$inDock(parameters));
2009 WBStringDrawingState labelState = {NULL, 0, @""
2010 , docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle"};
2012 stringDrawingState_ = &labelState;
2015 UIImage *image(MSOldCall(parameters));
2018 stringDrawingState_ = NULL;
2023 MSInstanceMessageHook2(id, CKBalloonView, initWithFrame,delegate, CGRect, frame, id, delegate) {
2024 if ((self = MSOldCall(frame, delegate)) != nil) {
2025 [self setBackgroundColor:[UIColor clearColor]];
2029 MSInstanceMessageHook0(BOOL, CKBalloonView, _canUseLayerBackedBalloon) {
2030 return SMSBackgrounded_ ? NO : MSOldCall();
2033 MSInstanceMessageHook0(void, CKTranscriptHeaderView, layoutSubviews) {
2034 [self wb$setBackgroundColor:[UIColor clearColor]];
2038 MSInstanceMessageHook1(void, CKMessageCell, addBalloonView, CKBalloonView *, balloon) {
2040 [balloon setBackgroundColor:[UIColor clearColor]];
2043 MSInstanceMessageHook1(void, CKTranscriptCell, setBackgroundColor, UIColor *, color) {
2044 MSOldCall([UIColor clearColor]);
2045 [[self contentView] wb$setBackgroundColor:[UIColor clearColor]];
2049 MSInstanceMessageHook2(id, CKTranscriptCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
2050 if ((self = MSOldCall(style, reuse)) != nil) {
2051 [self setBackgroundColor:[UIColor clearColor]];
2052 [[self contentView] wb$setBackgroundColor:[UIColor clearColor]];
2057 MSInstanceMessageHook2(id, CKMessageCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
2058 if ((self = MSOldCall(style, reuse)) != nil) {
2059 [self setBackgroundColor:[UIColor clearColor]];
2060 [[self contentView] setBackgroundColor:[UIColor clearColor]];
2064 MSInstanceMessageHook2(id, CKTimestampView, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
2065 if ((self = MSOldCall(style, reuse)) != nil) {
2066 UILabel *&_label(MSHookIvar<UILabel *>(self, "_label"));
2067 [_label setBackgroundColor:[UIColor clearColor]];
2071 MSInstanceMessageHook1(void, CKTranscriptTableView, setSeparatorStyle, int, style) {
2072 MSOldCall(UITableViewCellSeparatorStyleNone);
2075 MSInstanceMessageHook2(id, CKTranscriptTableView, initWithFrame,style, CGRect, frame, int, style) {
2076 if ((self = MSOldCall(frame, style)) != nil) {
2077 [self setSeparatorStyle:UITableViewCellSeparatorStyleNone];
2081 MSInstanceMessageHook0(void, CKTranscriptController, loadView) {
2084 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"SMSBackground.png", @"SMSBackground.jpg", nil])))
2085 if (UIImage *image = $getImage$(path)) {
2086 SMSBackgrounded_ = true;
2088 UIView *&_transcriptTable(MSHookIvar<UIView *>(self, "_transcriptTable"));
2089 UIView *&_transcriptLayer(MSHookIvar<UIView *>(self, "_transcriptLayer"));
2091 if (&_transcriptTable != NULL)
2092 table = _transcriptTable;
2093 else if (&_transcriptLayer != NULL)
2094 table = _transcriptLayer;
2098 UIView *placard(table != nil ? [table superview] : MSHookIvar<UIView *>(self, "_backPlacard"));
2099 UIImageView *background([[[UIImageView alloc] initWithImage:image] autorelease]);
2102 [placard insertSubview:background atIndex:0];
2104 [table setBackgroundColor:[UIColor clearColor]];
2105 [placard insertSubview:background belowSubview:table];
2111 template <typename Original_>
2112 static UIImage *WBCacheImage(NSBundle *bundle, NSString *name, const Original_ &original, NSString *key) {
2115 NSUInteger period([name rangeOfString:@"."].location);
2116 NSUInteger length([name length]);
2117 if (period == NSNotFound || length < 4 || period > length - 4)
2118 name = [name stringByAppendingString:@".png"];
2120 return WBCacheImage(
2121 [=](){ return $pathForFile$inBundle$(name, bundle, true); },
2122 [bundle, &original, name](){
2123 UIImage *image(original());
2124 if (image != nil && UIDebug_) {
2125 NSString *path([@"/tmp/WBImages/" stringByAppendingString:[bundle bundleIdentifier]]);
2126 [Manager_ createDirectoryAtPath:path withIntermediateDirectories:YES attributes:@{NSFilePosixPermissions: @0777} error:NULL];
2127 path = [NSString stringWithFormat:@"%@/%@", path, name];
2128 if (![Manager_ fileExistsAtPath:path])
2129 [UIImagePNGRepresentation(image) writeToFile:path atomically:YES];
2135 // %hook _UIImageWithName() {{{
2136 MSHook(UIImage *, _UIImageWithName, NSString *name) {
2140 NSLog(@"WB:Debug: _UIImageWithName(\"%@\")", name);
2141 return WBCacheImage(_UIKitBundle(), name,
2142 [=](){ return __UIImageWithName(name); },
2143 [NSString stringWithFormat:@"I:%@", name]);
2146 // %hook _UIImageWithNameInDomain() {{{
2147 MSHook(UIImage *, _UIImageWithNameInDomain, NSString *name, NSString *domain) {
2149 NSLog(@"WB:Debug: _UIImageWithNameInDomain(\"%@\", \"%@\")", name, domain);
2150 return WBCacheImage(
2151 [=](){ return $getTheme$($useScale$([NSArray arrayWithObject:[NSString stringWithFormat:@"Domains/%@/%@", domain, name]])); },
2152 [=](){ return __UIImageWithNameInDomain(name, domain); },
2153 [NSString stringWithFormat:@"D:%zu:%@%@", size_t([domain length]), domain, name]);
2157 // UISharedArtwork (iOS 6) {{{
2158 MSInstanceMessageHook2(UISharedArtwork *, UISharedArtwork, initWithName,inBundle, NSString *, name, NSBundle *, bundle) {
2159 if ((self = MSOldCall(name, bundle)) != nil) {
2160 $objc_setAssociatedObject(self, @selector(wb$bundle), bundle, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
2164 MSInstanceMessageHook2(UIImage *, UISharedArtwork, imageNamed,device, NSString *, name, NSInteger, device) {
2165 NSBundle *bundle($objc_getAssociatedObject(self, @selector(wb$bundle)));
2167 NSLog(@"WB:Debug: -[UISharedArtwork(%@) imageNamed:@\"%@\" device:%li]", [bundle bundleIdentifier], name, (long) device);
2168 return WBCacheImage(bundle, name,
2169 [=](){ return MSOldCall(name, device); },
2170 [NSString stringWithFormat:@"M:%p:%@:%li", self, name, (long) device]);
2173 // _UIAssetManager (iOS 7) {{{
2174 MSInstanceMessageHook3(_UIAssetManager *, _UIAssetManager, initWithName,inBundle,idiom, NSString *, name, NSBundle *, bundle, NSInteger, idiom) {
2175 if ((self = MSOldCall(name, bundle, idiom)) != nil) {
2176 $objc_setAssociatedObject(self, @selector(wb$bundle), bundle, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
2180 MSInstanceMessageHook5(UIImage *, _UIAssetManager, imageNamed,scale,idiom,subtype,cachingOptions, NSString *, name, CGFloat, scale, NSInteger, idiom, NSUInteger, subtype, NSUInteger, caching) {
2181 NSBundle *bundle($objc_getAssociatedObject(self, @selector(wb$bundle)));
2183 NSLog(@"WB:Debug: -[_UIAssetManager(%@/%@) imageNamed:@\"%@\" scale:%g idiom:%li subtype:%lu cachingOptions:%lu]",
2184 [bundle bundleIdentifier], [self carFileName],
2185 name, scale, (long) idiom,
2186 (unsigned long) subtype,
2187 (unsigned long) caching
2190 if (bundle == _UIKitBundle()) {
2191 NSString *name([self carFileName]);
2193 else if ([name isEqualToString:@"UIKit_NewArtwork"])
2194 bundle = [WBBundle bundleWithIdentifier:@"com.apple.uikit.Artwork"];
2195 else if ([name isEqualToString:@"UIKit_OriginalArtwork"])
2196 bundle = [WBBundle bundleWithIdentifier:@"com.apple.uikit.LegacyArtwork"];
2199 return WBCacheImage(bundle, name,
2200 [=](){ return MSOldCall(name, scale, idiom, subtype, caching); },
2201 [NSString stringWithFormat:@"M:%p:%@:%g:%li:%lu", self, name, scale, (long) idiom, (unsigned long) subtype]);
2204 // _UIAssetManager (iOS 8) {{{
2205 struct SizeClassPair {
2210 MSInstanceMessageHook7(UIImage *, _UIAssetManager, imageNamed,scale,idiom,subtype,cachingOptions,sizeClassPair,attachCatalogImage, NSString *, name, CGFloat, scale, NSInteger, idiom, NSUInteger, subtype, NSUInteger, caching, SizeClassPair, size, BOOL, attach) {
2211 NSBundle *bundle([self bundle]);
2213 NSLog(@"WB:Debug: -[_UIAssetManager(%@/%@) imageNamed:@\"%@\" scale:%g idiom:%li subtype:%lu cachingOptions:%lu sizeClassPair:[%li %li] attachCatalogImage:%s]",
2214 [bundle bundleIdentifier], [self carFileName],
2215 name, scale, (long) idiom,
2216 (unsigned long) subtype,
2217 (unsigned long) caching,
2218 (long) size.first, (long) size.second,
2219 attach ? "YES" : "NO"
2221 return WBCacheImage(bundle, name,
2222 [=](){ return MSOldCall(name, scale, idiom, subtype, caching, size, attach); },
2223 [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']);
2227 // %hook GSFontCreateWithName() {{{
2228 MSHook(GSFontRef, GSFontCreateWithName, const char *name, GSFontSymbolicTraits traits, float size) {
2230 NSLog(@"WB:Debug: GSFontCreateWithName(\"%s\", %f)", name, size);
2231 if (NSString *font = [Info_ objectForKey:[NSString stringWithFormat:@"FontName-%s", name]])
2232 name = [font UTF8String];
2233 //if (NSString *scale = [Info_ objectForKey:[NSString stringWithFormat:@"FontScale-%s", name]])
2234 // size *= [scale floatValue];
2235 return _GSFontCreateWithName(name, traits, size);
2239 #define AudioToolbox "/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox"
2241 static bool GetFileNameForThisAction$(bool value, unsigned long a0, char *a1, unsigned long a2, bool &a3) {
2243 NSLog(@"WB:Debug:GetFileNameForThisAction(%lu, %s, %lu, %u) = %u", a0, value ? a1 : NULL, a2, a3, value);
2246 NSString *path = [NSString stringWithUTF8String:a1];
2247 if ([path hasPrefix:@"/System/Library/Audio/UISounds/"]) {
2248 NSString *file = [path substringFromIndex:31];
2249 for (NSString *theme in Themes_) {
2250 NSString *path([NSString stringWithFormat:@"%@/UISounds/%@", theme, file]);
2251 if ([Manager_ fileExistsAtPath:path]) {
2252 strcpy(a1, [path UTF8String]);
2261 MSHook(bool, _Z24GetFileNameForThisActionmPcRb, unsigned long a0, char *a1, bool &a3) {
2262 bool value(__Z24GetFileNameForThisActionmPcRb(a0, a1, a3));
2263 return GetFileNameForThisAction$(value, a0, a1, 0, a3);
2267 MSHook(bool, _Z24GetFileNameForThisActionjPcjRb, unsigned int a0, char *a1, unsigned int a2, bool &a3) {
2268 bool value(__Z24GetFileNameForThisActionjPcjRb(a0, a1, a2, a3));
2269 return GetFileNameForThisAction$(value, a0, a1, a2, a3);
2272 MSHook(bool, _Z24GetFileNameForThisActionmPcmRb, unsigned long a0, char *a1, unsigned long a2, bool &a3) {
2273 bool value(__Z24GetFileNameForThisActionmPcmRb(a0, a1, a2, a3));
2274 return GetFileNameForThisAction$(value, a0, a1, a2, a3);
2278 static void ChangeWallpaper(
2279 CFNotificationCenterRef center,
2283 CFDictionaryRef info
2286 NSLog(@"WB:Debug:ChangeWallpaper!");
2289 if (WallpaperFile_ != nil) {
2290 image = [[UIImage alloc] initWithContentsOfFile:WallpaperFile_];
2292 image = [image autorelease];
2295 if (WallpaperImage_ != nil)
2296 [WallpaperImage_ setImage:image];
2297 if (WallpaperPage_ != nil)
2298 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
2302 MSHook(NSArray *, CPBitmapCreateImagesFromPath, NSString *path, CFTypeRef *names, void *arg2, void *arg3) {
2303 NSArray *images(_CPBitmapCreateImagesFromPath(path, names, arg2, arg3));
2309 NSBundle *bundle([NSBundle wb$bundleWithFile:path]);
2313 NSString *file([path stringByResolvingSymlinksInPath]);
2314 NSString *prefix([[bundle bundlePath] stringByResolvingSymlinksInPath]);
2315 // XXX: why do I care about this?
2316 if (![file hasPrefix:prefix])
2319 NSMutableArray *copy([images mutableCopy]);
2323 NSDictionary *indexes;
2324 NSEnumerator *enumerator;
2326 if (CFGetTypeID((CFTypeRef) *names) == CFDictionaryGetTypeID()) {
2327 indexes = (NSDictionary *) *names;
2328 enumerator = [indexes keyEnumerator];
2331 enumerator = [(NSArray *) *names objectEnumerator];
2334 for (NSUInteger index(0); NSString *name = [enumerator nextObject]; ++index)
2335 if (NSString *themed = $pathForFile$inBundle$([name stringByAppendingString:@".png"], bundle, true)) {
2337 index = [[indexes objectForKey:name] intValue];
2338 if (UIImage *image = $getImage$(themed))
2339 [copy replaceObjectAtIndex:index withObject:(id)[image CGImage]];
2345 MSHook(void, BKSDisplayServicesSetSystemAppExitedImagePath, NSString *path) {
2346 if (NSString *themed = $getTheme$($useScale$([NSArray arrayWithObject:@"SystemAppExited.png"])))
2348 _BKSDisplayServicesSetSystemAppExitedImagePath(path);
2351 #define WBRename(name, sel, imp) \
2352 MSHookMessage($ ## name, @selector(sel), &$ ## name ## $ ## imp, &_ ## name ## $ ## imp)
2354 template <typename Type_>
2355 static void msset(Type_ &function, MSImageRef image, const char *name) {
2356 function = reinterpret_cast<Type_>(MSFindSymbol(image, name));
2359 #define WBHookSymbol(image, function) \
2360 msset(function, image, "_" #function)
2362 template <typename Type_>
2363 static void dlset(Type_ &function, const char *name) {
2364 function = reinterpret_cast<Type_>(dlsym(RTLD_DEFAULT, name));
2367 // %hook CGImageReadCreateWithFile() {{{
2368 MSHook(void *, CGImageReadCreateWithFile, NSString *path, int flag) {
2370 NSLog(@"WB:Debug: CGImageReadCreateWithFile(%@, %d)", path, flag);
2371 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2372 void *value(_CGImageReadCreateWithFile([path wb$themedPath], flag));
2377 MSHook(void *, CGImageSourceCreateWithFile, NSString *path, NSDictionary *options) {
2379 NSLog(@"WB:Debug: CGImageSourceCreateWithFile(%@, %@)", path, options);
2380 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2381 void *value(_CGImageSourceCreateWithFile([path wb$themedPath], options));
2386 MSHook(void *, CGImageSourceCreateWithURL, NSURL *url, NSDictionary *options) {
2388 NSLog(@"WB:Debug: CGImageSourceCreateWithURL(%@, %@)", url, options);
2389 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2390 if ([url isFileURL])
2391 url = [NSURL fileURLWithPath:[[url path] wb$themedPath]];
2392 void *value(_CGImageSourceCreateWithURL(url, options));
2398 static void NSString$drawAtPoint$withStyle$(NSString *self, SEL _cmd, CGPoint point, NSString *style) {
2399 WKSetCurrentGraphicsContext(UIGraphicsGetCurrentContext());
2400 if (style == nil || [style length] == 0)
2401 style = @"font-family: Helvetica; font-size: 12px";
2402 //NSLog(@"XXX:drawP(%@ | %@)", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "]);
2403 [[WBMarkup sharedMarkup] drawString:self atPoint:point withStyle:style];
2406 static void NSString$drawInRect$withStyle$(NSString *self, SEL _cmd, CGRect rect, NSString *style) {
2407 WKSetCurrentGraphicsContext(UIGraphicsGetCurrentContext());
2408 if (style == nil || [style length] == 0)
2409 style = @"font-family: Helvetica; font-size: 12px";
2410 //NSLog(@"XXX:drawR(%@ | %@)", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "]);
2411 return [[WBMarkup sharedMarkup] drawString:self inRect:rect withStyle:style];
2414 static CGSize NSString$sizeWithStyle$forWidth$(NSString *self, SEL _cmd, NSString *style, CGFloat width) {
2415 if (style == nil || [style length] == 0)
2416 style = @"font-family: Helvetica; font-size: 12px";
2417 CGSize size([[WBMarkup sharedMarkup] sizeOfString:self withStyle:style forWidth:width]);
2418 //NSLog(@"XXX:size(%@ | %@) = [%g %g]", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "], size.width, size.height);
2422 static void SBInitialize() {
2424 WBRename(SBApplication, pathForIcon, pathForIcon);
2425 WBRename(SBApplicationIcon, icon, icon);
2426 WBRename(SBApplicationIcon, generateIconImage:, generateIconImage$);
2429 WBRename(SBBookmarkIcon, icon, icon);
2430 WBRename(SBButtonBar, didMoveToSuperview, didMoveToSuperview);
2431 WBRename(SBCalendarIconContentsView, drawRect:, drawRect$);
2432 WBRename(SBIconBadge, initWithBadge:, initWithBadge$);
2433 WBRename(SBIconController, noteNumberOfIconListsChanged, noteNumberOfIconListsChanged);
2435 WBRename(SBWidgetApplicationIcon, icon, icon);
2437 WBRename(SBDockIconListView, setFrame:, setFrame$);
2438 MSHookMessage(object_getClass($SBDockIconListView), @selector(shouldShowNewDock), &$SBDockIconListView$shouldShowNewDock, &_SBDockIconListView$shouldShowNewDock);
2440 if (kCFCoreFoundationVersionNumber < 600 || SummerBoard_)
2441 WBRename(SBIconLabel, drawRect:, drawRect$);
2442 else if (kCFCoreFoundationVersionNumber < 700) {
2443 WBRename(SBIconLabel, buildLabelImage, buildLabelImage);
2445 WBRename(SBIconLabelImageParameters, hash, hash);
2446 WBRename($SBIconView, _labelImageParametersForIcon:location:, _labelImageParametersForIcon$location$);
2447 WBRename(SBIconView, _labelImageParameters, _labelImageParameters);
2448 WBRename($SBIconLabelImage, _drawLabelImageForParameters:, _drawLabelImageForParameters$);
2451 WBRename(SBIconLabel, initWithSize:label:, initWithSize$label$);
2452 WBRename(SBIconLabel, setInDock:, setInDock$);
2454 WBRename(SBIconList, didMoveToSuperview, didMoveToSuperview);
2455 WBRename(SBIconList, setFrame:, setFrame$);
2457 WBRename(SBIconModel, cacheImageForIcon:, cacheImageForIcon$);
2458 WBRename(SBIconModel, cacheImagesForIcon:, cacheImagesForIcon$);
2459 WBRename(SBIconModel, getCachedImagedForIcon:, getCachedImagedForIcon$);
2460 WBRename(SBIconModel, getCachedImagedForIcon:smallIcon:, getCachedImagedForIcon$smallIcon$);
2462 if (kCFCoreFoundationVersionNumber < 800) {
2463 WBRename(SBSearchView, initWithFrame:, initWithFrame$);
2464 WBRename(SBSearchTableViewCell, drawRect:, drawRect$);
2465 WBRename(SBSearchTableViewCell, initWithStyle:reuseIdentifier:, initWithStyle$reuseIdentifier$);
2468 //WBRename(SBImageCache, initWithName:forImageWidth:imageHeight:initialCapacity:, initWithName$forImageWidth$imageHeight$initialCapacity$);
2470 WBRename(SBAwayView, updateDesktopImage:, updateDesktopImage$);
2471 if (kCFCoreFoundationVersionNumber >= 700)
2472 WBRename(SBAwayView, _addSubview:positioned:relativeTo:, _addSubview$positioned$relativeTo$);
2474 WBRename(SBStatusBarContentsView, didMoveToSuperview, didMoveToSuperview);
2475 //WBRename(SBStatusBarContentsView, initWithStatusBar:mode:, initWithStatusBar$mode$);
2476 //WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:animation:, setStatusBarMode$orientation$duration$animation$);
2477 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:, setStatusBarMode$orientation$duration$fenceID$animation$);
2478 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:startTime:, setStatusBarMode$orientation$duration$fenceID$animation$startTime$);
2479 WBRename(SBStatusBarOperatorNameView, operatorNameStyle, operatorNameStyle);
2480 WBRename(SBStatusBarOperatorNameView, setOperatorName:fullSize:, setOperatorName$fullSize$);
2481 WBRename(SBStatusBarTimeView, drawRect:, drawRect$);
2484 English_ = [[NSDictionary alloc] initWithContentsOfFile:@"/System/Library/CoreServices/SpringBoard.app/English.lproj/LocalizedApplicationNames.strings"];
2486 if (kCFCoreFoundationVersionNumber >= 800) {
2487 WBRename(NSString, drawInRect:withAttributes:, drawInRect$withAttributes$);
2488 WBRename(NSString, boundingRectWithSize:options:attributes:context:, boundingRectWithSize$options$attributes$context$);
2492 /*MSHook(int, open, const char *path, int oflag, mode_t mode) {
2493 int fd(_open(path, oflag, mode));
2495 static bool no(false);
2499 if (strstr(path, "/icon") != NULL)
2500 *reinterpret_cast<void *volatile *>(NULL) = NULL;
2502 if (fd == -1 && errno == EFAULT)
2503 NSLog(@"open(%p, %#x, %#o) = %d\n", path, oflag, mode, fd);
2505 NSLog(@"open(\"%s\", %#x, %#o) = %d\n", path, oflag, mode, fd);
2512 $objc_setAssociatedObject = reinterpret_cast<void (*)(id, void *, id value, objc_AssociationPolicy)>(dlsym(RTLD_DEFAULT, "objc_setAssociatedObject"));
2513 $objc_getAssociatedObject = reinterpret_cast<id (*)(id, void *)>(dlsym(RTLD_DEFAULT, "objc_getAssociatedObject"));
2514 $objc_removeAssociatedObjects = reinterpret_cast<void (*)(id)>(dlsym(RTLD_DEFAULT, "objc_removeAssociatedObjects"));
2516 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2518 NSString *identifier([[NSBundle mainBundle] bundleIdentifier]);
2519 SpringBoard_ = [identifier isEqualToString:@"com.apple.springboard"];
2521 Manager_ = [[NSFileManager defaultManager] retain];
2522 Themes_ = [[NSMutableArray alloc] initWithCapacity:8];
2524 dlset(_GSFontGetUseLegacyFontMetrics, "GSFontGetUseLegacyFontMetrics");
2526 // Initialize IsWild_ {{{
2528 sysctlbyname("hw.machine", NULL, &size, NULL, 0);
2529 char *machine = new char[size];
2531 if (sysctlbyname("hw.machine", machine, &size, NULL, 0) == -1) {
2532 perror("sysctlbyname(\"hw.machine\", ?)");
2537 IsWild_ = machine != NULL && strncmp(machine, "iPad", 4) == 0;
2539 // Load Settings.plist {{{
2540 if (NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"/User/Library/Preferences/com.saurik.WinterBoard.plist"]]) {
2541 if (kCFCoreFoundationVersionNumber >= 1000)
2542 SummerBoard_ = false;
2543 else if (NSNumber *value = [settings objectForKey:@"SummerBoard"])
2544 SummerBoard_ = [value boolValue];
2546 SummerBoard_ = true;
2548 if (NSNumber *value = [settings objectForKey:@"Debug"])
2549 Debug_ = [value boolValue];
2550 if (NSNumber *value = [settings objectForKey:@"RecordUI"])
2551 UIDebug_ = [value boolValue];
2553 NSArray *themes([settings objectForKey:@"Themes"]);
2555 if (NSString *theme = [settings objectForKey:@"Theme"])
2556 themes = [NSArray arrayWithObject:[NSDictionary dictionaryWithObjectsAndKeys:
2558 [NSNumber numberWithBool:true], @"Active",
2562 for (NSDictionary *theme in themes) {
2563 NSNumber *active([theme objectForKey:@"Active"]);
2564 if (![active boolValue])
2567 NSString *name([theme objectForKey:@"Name"]);
2571 #define testForTheme(format...) \
2573 NSString *path = [NSString stringWithFormat:format]; \
2574 if ([Manager_ fileExistsAtPath:path]) { \
2575 [Themes_ addObject:path]; \
2580 testForTheme(@"/Library/Themes/%@.theme", name)
2581 testForTheme(@"/Library/Themes/%@", name)
2582 testForTheme(@"%@/Library/SummerBoard/Themes/%@", NSHomeDirectory(), name)
2587 // Merge Info.plist {{{
2588 Info_ = [[NSMutableDictionary dictionaryWithCapacity:16] retain];
2590 for (NSString *theme in Themes_)
2591 if (NSDictionary *info = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"%@/Info.plist", theme]])
2592 for (NSString *key in [info allKeys])
2593 if ([Info_ objectForKey:key] == nil)
2594 [Info_ setObject:[info objectForKey:key] forKey:key];
2598 if (MSImageRef image = MSGetImageByName("/System/Library/PrivateFrameworks/AppSupport.framework/AppSupport")) {
2599 NSArray *(*CPBitmapCreateImagesFromPath)(NSString *, CFTypeRef *, void *, void *);
2600 msset(CPBitmapCreateImagesFromPath, image, "_CPBitmapCreateImagesFromPath");
2601 MSHookFunction(CPBitmapCreateImagesFromPath, MSHake(CPBitmapCreateImagesFromPath));
2605 if (MSImageRef image = MSGetImageByName(AudioToolbox)) {
2606 bool (*_Z24GetFileNameForThisActionmPcRb)(unsigned long, char *, bool &);
2607 msset(_Z24GetFileNameForThisActionmPcRb, image, "__Z24GetFileNameForThisActionmPcRb");
2608 MSHookFunction(_Z24GetFileNameForThisActionmPcRb, &$_Z24GetFileNameForThisActionmPcRb, &__Z24GetFileNameForThisActionmPcRb);
2611 bool (*_Z24GetFileNameForThisActionjPcjRb)(unsigned int, char *, unsigned int, bool &);
2612 msset(_Z24GetFileNameForThisActionjPcjRb, image, "__Z24GetFileNameForThisActionjPcjRb");
2613 MSHookFunction(_Z24GetFileNameForThisActionjPcjRb, &$_Z24GetFileNameForThisActionjPcjRb, &__Z24GetFileNameForThisActionjPcjRb);
2615 bool (*_Z24GetFileNameForThisActionmPcmRb)(unsigned long, char *, unsigned long, bool &);
2616 msset(_Z24GetFileNameForThisActionmPcmRb, image, "__Z24GetFileNameForThisActionmPcmRb");
2617 MSHookFunction(_Z24GetFileNameForThisActionmPcmRb, &$_Z24GetFileNameForThisActionmPcmRb, &__Z24GetFileNameForThisActionmPcmRb);
2621 // BackBoardServices {{{
2622 if (MSImageRef image = MSGetImageByName("/System/Library/PrivateFrameworks/BackBoardServices.framework/BackBoardServices")) {
2623 void (*BKSDisplayServicesSetSystemAppExitedImagePath)(NSString *path);
2624 msset(BKSDisplayServicesSetSystemAppExitedImagePath, image, "_BKSDisplayServicesSetSystemAppExitedImagePath");
2625 MSHookFunction(BKSDisplayServicesSetSystemAppExitedImagePath, MSHake(BKSDisplayServicesSetSystemAppExitedImagePath));
2630 if (![identifier isEqualToString:@"com.apple.backupd"]) // XXX: rethink
2631 MSHookFunction(CFBundleCopyResourceURL, MSHake(CFBundleCopyResourceURL));
2634 // GraphicsServices {{{
2636 MSHookFunction(&GSFontCreateWithName, &$GSFontCreateWithName, &_GSFontCreateWithName);
2640 MSImageRef imageio = MSGetImageByName("/System/Library/Frameworks/ImageIO.framework/ImageIO");
2641 if (imageio == NULL)
2642 imageio = MSGetImageByName("/System/Library/PrivateFrameworks/ImageIO.framework/ImageIO");
2643 if (MSImageRef image = imageio) {
2644 void *(*CGImageReadCreateWithFile)(NSString *, int) = NULL;
2645 if (kCFCoreFoundationVersionNumber > 700) // XXX: iOS 6.x
2646 CGImageReadCreateWithFile = NULL;
2648 msset(CGImageReadCreateWithFile, image, "_CGImageReadCreateWithFile");
2649 MSHookFunction(CGImageReadCreateWithFile, MSHake(CGImageReadCreateWithFile));
2652 if (CGImageReadCreateWithFile == NULL) {
2653 void *(*CGImageSourceCreateWithFile)(NSString *, NSDictionary *);
2654 msset(CGImageSourceCreateWithFile, image, "_CGImageSourceCreateWithFile");
2655 MSHookFunction(CGImageSourceCreateWithFile, MSHake(CGImageSourceCreateWithFile));
2657 void *(*CGImageSourceCreateWithURL)(NSURL *, NSDictionary *);
2658 msset(CGImageSourceCreateWithURL, image, "_CGImageSourceCreateWithURL");
2659 MSHookFunction(CGImageSourceCreateWithURL, MSHake(CGImageSourceCreateWithURL));
2665 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];
2666 Papered_ = $getTheme$(Wallpapers_) != nil;
2667 Docked_ = $getTheme$([NSArray arrayWithObjects:@"Dock.png", nil]) != nil;
2669 CFNotificationCenterAddObserver(
2670 CFNotificationCenterGetDarwinNotifyCenter(),
2671 NULL, &ChangeWallpaper, (CFStringRef) @"com.saurik.winterboard.lockbackground", NULL, CFNotificationSuspensionBehaviorCoalesce
2674 if ($getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"]) != nil) {
2675 NSBundle *MediaPlayer([NSBundle bundleWithPath:@"/System/Library/Frameworks/MediaPlayer.framework"]);
2676 if (MediaPlayer != nil)
2679 $MPMoviePlayerController = objc_getClass("MPMoviePlayerController");
2680 $MPVideoView = objc_getClass("MPVideoView");
2687 if (MSImageRef image = MSGetImageByName("/System/Library/Frameworks/UIKit.framework/UIKit")) {
2689 class_addMethod($NSString, @selector(drawAtPoint:withStyle:), (IMP) &NSString$drawAtPoint$withStyle$, "v40@0:8{CGPoint=dd}16@32");
2690 class_addMethod($NSString, @selector(drawInRect:withStyle:), (IMP) &NSString$drawInRect$withStyle$, "v56@0:8{CGRect={CGSize=dd}{CGSize=dd}}16@48");
2691 class_addMethod($NSString, @selector(sizeWithStyle:forWidth:), (IMP) &NSString$sizeWithStyle$forWidth$, "{CGSize=dd}32@0:8@16d24");
2693 class_addMethod($NSString, @selector(drawAtPoint:withStyle:), (IMP) &NSString$drawAtPoint$withStyle$, "v20@0:4{CGPoint=ff}8@16");
2694 class_addMethod($NSString, @selector(drawInRect:withStyle:), (IMP) &NSString$drawInRect$withStyle$, "v28@0:4{CGRect={CGSize=ff}{CGSize=ff}}8@24");
2695 class_addMethod($NSString, @selector(sizeWithStyle:forWidth:), (IMP) &NSString$sizeWithStyle$forWidth$, "{CGSize=ff}16@0:4@8f12");
2698 WBHookSymbol(image, _UIKitBundle);
2700 if (kCFCoreFoundationVersionNumber < 700)
2701 MSHookFunction(_UIImageWithName, MSHake(_UIImageWithName));
2703 WBHookSymbol(image, _UIApplicationImageWithName);
2704 MSHookFunction(_UIApplicationImageWithName, MSHake(_UIApplicationImageWithName));
2706 WBHookSymbol(image, _UIImageWithNameInDomain);
2707 MSHookFunction(_UIImageWithNameInDomain, MSHake(_UIImageWithNameInDomain));
2709 SEL includeEmoji(@selector(_legacy_drawAtPoint:forWidth:withFont:lineBreakMode:letterSpacing:includeEmoji:));
2710 if (![@"" respondsToSelector:includeEmoji])
2711 includeEmoji = @selector(drawAtPoint:forWidth:withFont:lineBreakMode:letterSpacing:includeEmoji:);
2712 MSHookMessage($NSString, includeEmoji, MSHake(NSString$drawAtPoint$forWidth$withFont$lineBreakMode$letterSpacing$includeEmoji$));
2714 SEL letterSpacing(@selector(_legacy_sizeWithFont:forWidth:lineBreakMode:letterSpacing:));
2715 if (![@"" respondsToSelector:letterSpacing])
2716 letterSpacing = @selector(sizeWithFont:forWidth:lineBreakMode:letterSpacing:);
2717 MSHookMessage($NSString, letterSpacing, MSHake(NSString$sizeWithFont$forWidth$lineBreakMode$letterSpacing$));
2719 SEL sizeWithFont(@selector(_legacy_sizeWithFont:));
2720 if (![@"" respondsToSelector:sizeWithFont])
2721 sizeWithFont = @selector(sizeWithFont:);
2722 MSHookMessage($NSString, sizeWithFont, MSHake(NSString$sizeWithFont$));
2724 MSHookMessage($NSAttributedString, @selector(drawAtPoint:), MSHake(NSAttributedString$drawAtPoint$));
2725 MSHookMessage($NSAttributedString, @selector(boundingRectWithSize:options:context:), MSHake(NSAttributedString$boundingRectWithSize$options$context$));
2729 //MSHookFunction(reinterpret_cast<int (*)(const char *, int, mode_t)>(&open), MSHake(open));