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)
106 MSClassHook(_UIAssetManager)
108 MSMetaClassHook(UIImage)
109 MSClassHook(UINavigationBar)
110 MSClassHook(UISharedArtwork)
111 MSClassHook(UIToolbar)
112 MSClassHook(UIStatusBarTimeItemView)
113 MSClassHook(UIWebDocumentView)
115 MSClassHook(CKBalloonView)
116 MSClassHook(CKMessageCell)
117 MSClassHook(CKTimestampView)
118 MSClassHook(CKTranscriptCell)
119 MSClassHook(CKTranscriptController)
120 MSClassHook(CKTranscriptHeaderView)
121 MSClassHook(CKTranscriptTableView)
123 MSClassHook(SBApplication)
124 MSClassHook(SBApplicationIcon)
125 MSClassHook(SBAwayView)
126 MSClassHook(SBBookmarkIcon)
127 MSClassHook(SBButtonBar)
128 MSClassHook(SBCalendarApplicationIcon)
129 MSClassHook(SBCalendarIconContentsView)
130 MSClassHook(SBDockIconListView)
132 MSClassHook(SBIconAccessoryImage)
133 MSMetaClassHook(SBIconAccessoryImage)
134 MSClassHook(SBIconBadge)
135 MSClassHook(SBIconBadgeFactory)
136 MSClassHook(SBIconBadgeImage)
137 MSClassHook(SBIconBadgeView)
138 MSMetaClassHook(SBIconBadgeView)
139 MSClassHook(SBIconContentView)
140 MSClassHook(SBIconController)
141 MSClassHook(SBIconLabel)
142 MSClassHook(SBIconLabelImage)
143 MSMetaClassHook(SBIconLabelImage)
144 MSClassHook(SBIconLabelImageParameters)
145 MSClassHook(SBIconList)
146 MSClassHook(SBIconModel)
147 MSClassHook(SBIconView)
148 MSMetaClassHook(SBIconView)
149 //MSClassHook(SBImageCache)
150 MSClassHook(SBSearchView)
151 MSClassHook(SBSearchTableViewCell)
152 MSClassHook(SBSlidingAlertDisplay)
153 MSClassHook(SBStatusBarContentsView)
154 MSClassHook(SBStatusBarController)
155 MSClassHook(SBStatusBarOperatorNameView)
156 MSClassHook(SBStatusBarTimeView)
157 MSClassHook(SBUIController)
158 MSClassHook(SBWallpaperView)
159 MSClassHook(SBWidgetApplicationIcon)
161 extern "C" void WKSetCurrentGraphicsContext(CGContextRef);
163 static struct MSFixClass { MSFixClass() {
164 $UIWebDocumentView = objc_getClass("UIWebBrowserView") ?: $UIWebDocumentView;
165 $SBIcon = objc_getClass("SBIconView") ?: $SBIcon;
167 if ($SBIconList == nil)
168 $SBIconList = objc_getClass("SBIconListView");
169 if ($CKTranscriptController == nil)
170 $CKTranscriptController = objc_getClass("mSMSMessageTranscriptController");
174 static bool Four_($SBDockIconListView != nil);
176 @interface NSObject (wb$SBIconAccessoryImage)
177 + (Class) _imageClassForIcon:(SBIcon *)icon location:(int)location;
180 @interface NSDictionary (WinterBoard)
181 - (UIColor *) wb$colorForKey:(NSString *)key;
182 - (BOOL) wb$boolForKey:(NSString *)key;
185 @implementation NSDictionary (WinterBoard)
187 - (UIColor *) wb$colorForKey:(NSString *)key {
188 NSString *value = [self objectForKey:key];
195 - (BOOL) wb$boolForKey:(NSString *)key {
196 if (NSString *value = [self objectForKey:key])
197 return [value boolValue];
203 @interface _UIAssetManager : NSObject
204 - (NSBundle *) bundle;
205 - (NSString *) carFileName;
208 static BOOL (*_GSFontGetUseLegacyFontMetrics)();
209 #define $GSFontGetUseLegacyFontMetrics() \
210 (_GSFontGetUseLegacyFontMetrics == NULL ? YES : _GSFontGetUseLegacyFontMetrics())
212 static bool Debug_ = false;
213 static bool UIDebug_ = false;
214 static bool Engineer_ = false;
215 static bool SummerBoard_ = false;
216 static bool SpringBoard_;
218 static UIImage *(*_UIApplicationImageWithName)(NSString *name);
219 static UIImage *(*_UIImageWithNameInDomain)(NSString *name, NSString *domain);
220 static NSBundle *(*_UIKitBundle)();
222 static NSMutableDictionary *Images_ = [[NSMutableDictionary alloc] initWithCapacity:64];
223 static NSMutableDictionary *Cache_ = [[NSMutableDictionary alloc] initWithCapacity:64];
224 static NSMutableDictionary *Strings_ = [[NSMutableDictionary alloc] initWithCapacity:0];
225 static NSMutableDictionary *Bundles_ = [[NSMutableDictionary alloc] initWithCapacity:2];
227 static NSFileManager *Manager_;
228 static NSMutableArray *Themes_;
230 static NSDictionary *English_;
231 static NSMutableDictionary *Info_;
233 // @interface WBBundle {{{
234 @interface WBBundle : NSBundle {
235 NSString *identifier_;
238 + (WBBundle *) bundleWithIdentifier:(NSString *)identifier;
242 @implementation WBBundle
245 [identifier_ release];
246 return [super dealloc];
249 + (WBBundle *) bundleWithIdentifier:(NSString *)identifier {
250 return [[[self alloc] initWithIdentifier:identifier] autorelease];
253 - (id) initWithIdentifier:(NSString *)identifier {
254 if ((self = [super init]) != nil) {
255 identifier_ = [identifier retain];
259 - (NSString *) bundleIdentifier {
267 static NSMutableDictionary *Themed_ = [[NSMutableDictionary alloc] initWithCapacity:128];
269 static unsigned Scale_ = 0;
271 static unsigned $getScale$(NSString *path) {
272 NSString *name(path);
274 #define StripName(strip) \
275 if ([name hasSuffix:@ strip]) \
276 name = [name substringWithRange:NSMakeRange(0, [name length] - sizeof(strip) - 1)];
280 StripName("~iphone");
283 if ([name hasSuffix:@"@3x"])
285 if ([name hasSuffix:@"@2x"])
290 static NSArray *$useScale$(NSArray *files, bool use = true) {
291 if (use && Scale_ == 0) {
292 UIScreen *screen([UIScreen mainScreen]);
293 if ([screen respondsToSelector:@selector(scale)])
294 Scale_ = [screen scale];
299 NSString *idiom(IsWild_ ? @"ipad" : @"iphone");
301 NSMutableArray *scaled([NSMutableArray arrayWithCapacity:([files count] * 4)]);
303 for (NSString *file in files) {
304 NSString *base([file stringByDeletingPathExtension]);
305 NSString *extension([file pathExtension]);
308 for (unsigned scale(2); scale <= Scale_; ++scale) {
309 [scaled addObject:[NSString stringWithFormat:@"%@@%ux~%@.%@", base, scale, idiom, extension]];
310 [scaled addObject:[NSString stringWithFormat:@"%@@%ux.%@", base, scale, extension]];
313 [scaled addObject:[NSString stringWithFormat:@"%@~%@.%@", base, idiom, extension]];
315 // if (!IsWild_) <- support old themes
316 [scaled addObject:file];
317 } else if ([base hasSuffix: @"@2x"] || [base hasSuffix:@"@3x"]) {
318 [scaled addObject:[NSString stringWithFormat:@"%@~%@.%@", base, idiom, extension]];
319 [scaled addObject:file];
321 // XXX: this actually can't be used, as the person loading the file doesn't realize that the @2x changed
322 /*NSString *rest([base substringWithRange:NSMakeRange(0, [base length] - 3)]);
323 [scaled addObject:[NSString stringWithFormat:@"%@~%@.%@", rest, idiom, extension]];
324 [scaled addObject:[rest stringByAppendingPathExtension:extension]];*/
326 // XXX: this code isn't really complete
328 [scaled addObject:file];
330 if ([base hasSuffix:[NSString stringWithFormat:@"~%@", idiom]])
331 [scaled addObject:[[base substringWithRange:NSMakeRange(0, [base length] - 1 - [idiom length])] stringByAppendingPathExtension:extension]];
338 static NSString *$getTheme$(NSArray *files, NSArray *themes = Themes_) {
339 // XXX: this is not reasonable; OMG
342 @synchronized (Themed_) {
343 if (NSString *path = [Themed_ objectForKey:key])
344 return reinterpret_cast<id>(path) == [NSNull null] ? nil : path;
348 NSLog(@"WB:Debug: %@", [files description]);
352 for (NSString *theme in Themes_)
353 for (NSString *file in files) {
354 path = [NSString stringWithFormat:@"%@/%@", theme, file];
355 if ([Manager_ fileExistsAtPath:path]) {
356 if ([[Manager_ destinationOfSymbolicLinkAtPath:path error:NULL] isEqualToString:@"/"])
365 @synchronized (Themed_) {
366 [Themed_ setObject:(path == nil ? [NSNull null] : reinterpret_cast<id>(path)) forKey:key];
372 // $pathForFile$inBundle$() {{{
373 static void $pathForFile$inBundle$(NSMutableArray *names, NSString *file, NSBundle *bundle) {
374 NSString *identifier = [bundle bundleIdentifier];
376 if (identifier != nil)
377 [names addObject:[NSString stringWithFormat:@"Bundles/%@/%@", identifier, file]];
378 if (NSString *folder = [[bundle bundlePath] lastPathComponent]) {
379 [names addObject:[NSString stringWithFormat:@"Folders/%@/%@", folder, file]];
380 NSString *base([folder stringByDeletingPathExtension]);
381 if ([base hasSuffix:@"~iphone"])
382 [names addObject:[NSString stringWithFormat:@"Folders/%@.%@/%@", [base substringWithRange:NSMakeRange(0, [base length] - 7)], [folder pathExtension], file]];
383 if ([base hasSuffix:@"~ipad"])
384 [names addObject:[NSString stringWithFormat:@"Folders/%@.%@/%@", [base substringWithRange:NSMakeRange(0, [base length] - 5)], [folder pathExtension], file]];
387 #define remapResourceName(oldname, newname) \
388 else if ([file isEqualToString:(oldname)]) \
389 [names addObject:[NSString stringWithFormat:@"%@.png", newname]]; \
391 bool summer(SpringBoard_ && SummerBoard_);
393 if (identifier == nil);
394 else if ([identifier isEqualToString:@"com.apple.uikit.Artwork"])
395 $pathForFile$inBundle$(names, file, [WBBundle bundleWithIdentifier:@"com.apple.UIKit"]);
396 else if ([identifier isEqualToString:@"com.apple.uikit.LegacyArtwork"])
397 $pathForFile$inBundle$(names, file, [WBBundle bundleWithIdentifier:@"com.apple.UIKit"]);
398 else if ([identifier isEqualToString:@"com.apple.UIKit"])
399 [names addObject:[NSString stringWithFormat:@"UIImages/%@", file]];
400 else if ([identifier isEqualToString:@"com.apple.chatkit"])
401 $pathForFile$inBundle$(names, file, [WBBundle bundleWithIdentifier:@"com.apple.MobileSMS"]);
402 else if ([identifier isEqualToString:@"com.apple.calculator"])
403 [names addObject:[NSString stringWithFormat:@"Files/Applications/Calculator.app/%@", file]];
404 else if ([identifier isEqualToString:@"com.apple.Maps"] && [file isEqualToString:@"Icon-57@2x.png"])
405 [names addObject:[NSString stringWithFormat:@"Bundles/com.apple.Maps/icon.png"]];
407 remapResourceName(@"FSO_BG.png", @"StatusBar")
408 remapResourceName(Four_ ? @"SBDockBG-old.png" : @"SBDockBG.png", @"Dock")
409 remapResourceName(@"SBWeatherCelsius.png", @"Icons/Weather")
412 static NSString *$pathForFile$inBundle$(NSString *file, NSBundle *bundle, bool use) {
413 NSMutableArray *names = [NSMutableArray arrayWithCapacity:8];
414 $pathForFile$inBundle$(names, file, bundle);
415 [names addObject:[NSString stringWithFormat:@"Fallback/%@", file]];
416 if (NSString *path = $getTheme$($useScale$(names, use)))
422 static NSString *$pathForIcon$(SBApplication *self, NSString *suffix = @"") {
423 NSString *identifier = [self bundleIdentifier];
424 NSString *path = [self path];
425 NSString *folder = [path lastPathComponent];
426 NSString *dname = [self displayName];
427 NSString *didentifier = [self displayIdentifier];
430 NSLog(@"WB:Debug: [SBApplication(%@:%@:%@:%@) pathForIcon]", identifier, folder, dname, didentifier);
432 NSMutableArray *names = [NSMutableArray arrayWithCapacity:8];
434 /* XXX: I might need to keep this for backwards compatibility
435 if (identifier != nil)
436 [names addObject:[NSString stringWithFormat:@"Bundles/%@/icon.png", identifier]];
438 [names addObject:[NSString stringWithFormat:@"Folders/%@/icon.png", folder]]; */
440 #define testForIcon(Name) \
441 if (NSString *name = Name) \
442 [names addObject:[NSString stringWithFormat:@"Icons%@/%@.png", suffix, name]];
444 if (![didentifier isEqualToString:identifier])
445 testForIcon(didentifier);
447 testForIcon(identifier);
450 if ([identifier isEqualToString:@"com.apple.MobileSMS"])
453 if (didentifier != nil) {
454 testForIcon([English_ objectForKey:didentifier]);
456 NSArray *parts = [didentifier componentsSeparatedByString:@"-"];
457 if ([parts count] != 1)
458 if (NSDictionary *english = [[[NSDictionary alloc] initWithContentsOfFile:[path stringByAppendingString:@"/English.lproj/UIRoleDisplayNames.strings"]] autorelease])
459 testForIcon([english objectForKey:[parts lastObject]]);
462 if (NSString *path = $getTheme$(names))
468 // -[NSBundle wb$bundleWithFile] {{{
469 @interface NSBundle (WinterBoard)
470 + (NSBundle *) wb$bundleWithFile:(NSString *)path;
473 @implementation NSBundle (WinterBoard)
475 + (NSBundle *) wb$bundleWithFile:(NSString *)path {
476 path = [path stringByDeletingLastPathComponent];
477 if (path == nil || [path length] == 0 || [path isEqualToString:@"/"])
481 @synchronized (Bundles_) {
482 bundle = [Bundles_ objectForKey:path];
485 if (reinterpret_cast<id>(bundle) == [NSNull null])
487 else if (bundle == nil) {
488 if ([Manager_ fileExistsAtPath:[path stringByAppendingPathComponent:@"Info.plist"]])
489 bundle = [NSBundle bundleWithPath:path];
491 bundle = [NSBundle wb$bundleWithFile:path];
493 NSLog(@"WB:Debug:PathBundle(%@, %@)", path, bundle);
495 @synchronized (Bundles_) {
496 [Bundles_ setObject:(bundle == nil ? [NSNull null] : reinterpret_cast<id>(bundle)) forKey:path];
505 // -[NSString wb$themedPath] {{{
506 @interface NSString (WinterBoard)
507 - (NSString *) wb$themedPath;
510 @implementation NSString (WinterBoard)
512 - (NSString *) wb$themedPath {
513 if ([self hasPrefix:@"/Library/Themes/"])
517 NSLog(@"WB:Debug:Bypass(\"%@\")", self);
519 if (NSBundle *bundle = [NSBundle wb$bundleWithFile:self]) {
520 NSString *file([self stringByResolvingSymlinksInPath]);
521 NSString *prefix([[bundle bundlePath] stringByResolvingSymlinksInPath]);
522 if ([file hasPrefix:prefix]) {
523 NSUInteger length([prefix length]);
524 if (length != [file length])
525 if (NSString *path = $pathForFile$inBundle$([file substringFromIndex:(length + 1)], bundle, false))
536 void WBLogRect(const char *tag, struct CGRect rect) {
537 NSLog(@"%s:{%f,%f+%f,%f}", tag, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
540 void WBLogHierarchy(UIView *view, unsigned index = 0, unsigned indent = 0) {
541 CGRect frame([view frame]);
542 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]);
544 for (UIView *child in [view subviews])
545 WBLogHierarchy(child, index++, indent + 1);
548 UIImage *$cacheForImage$(UIImage *image) {
549 CGColorSpaceRef space(CGColorSpaceCreateDeviceRGB());
550 CGRect rect = {CGPointMake(1, 1), [image size]};
551 CGSize size = {rect.size.width + 2, rect.size.height + 2};
553 CGContextRef context(CGBitmapContextCreate(NULL, size.width, size.height, 8, 4 * size.width, space, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst));
554 CGColorSpaceRelease(space);
556 CGContextDrawImage(context, rect, [image CGImage]);
557 CGImageRef ref(CGBitmapContextCreateImage(context));
558 CGContextRelease(context);
560 UIImage *cache([UIImage imageWithCGImage:ref]);
566 /*MSHook(id, SBImageCache$initWithName$forImageWidth$imageHeight$initialCapacity$, SBImageCache *self, SEL sel, NSString *name, unsigned width, unsigned height, unsigned capacity) {
567 //if ([name isEqualToString:@"icons"]) return nil;
568 return _SBImageCache$initWithName$forImageWidth$imageHeight$initialCapacity$(self, sel, name, width, height, capacity);
571 MSHook(void, SBIconModel$cacheImageForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
572 NSString *key([icon displayIdentifier]);
574 if (UIImage *image = [icon icon]) {
575 CGSize size = [image size];
576 if (size.width != 59 || size.height != 60) {
577 UIImage *cache($cacheForImage$(image));
578 [Cache_ setObject:cache forKey:key];
583 _SBIconModel$cacheImageForIcon$(self, sel, icon);
586 MSHook(void, SBIconModel$cacheImagesForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
587 /* XXX: do I /really/ have to do this? figure out how to cache the small icon! */
588 _SBIconModel$cacheImagesForIcon$(self, sel, icon);
590 NSString *key([icon displayIdentifier]);
592 if (UIImage *image = [icon icon]) {
593 CGSize size = [image size];
594 if (size.width != 59 || size.height != 60) {
595 UIImage *cache($cacheForImage$(image));
596 [Cache_ setObject:cache forKey:key];
602 MSHook(UIImage *, SBIconModel$getCachedImagedForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
603 NSString *key([icon displayIdentifier]);
604 if (UIImage *image = [Cache_ objectForKey:key])
607 return _SBIconModel$getCachedImagedForIcon$(self, sel, icon);
610 MSHook(UIImage *, SBIconModel$getCachedImagedForIcon$smallIcon$, SBIconModel *self, SEL sel, SBIcon *icon, BOOL small) {
612 return _SBIconModel$getCachedImagedForIcon$smallIcon$(self, sel, icon, small);
613 NSString *key([icon displayIdentifier]);
614 if (UIImage *image = [Cache_ objectForKey:key])
617 return _SBIconModel$getCachedImagedForIcon$smallIcon$(self, sel, icon, small);
620 MSHook(id, SBSearchView$initWithFrame$, id /* XXX: SBSearchView */ self, SEL sel, struct CGRect frame) {
621 if ((self = _SBSearchView$initWithFrame$(self, sel, frame)) != nil) {
622 [self setBackgroundColor:[UIColor clearColor]];
623 for (UIView *child in [self subviews])
624 [child setBackgroundColor:[UIColor clearColor]];
628 MSHook(id, SBSearchTableViewCell$initWithStyle$reuseIdentifier$, SBSearchTableViewCell *self, SEL sel, int style, NSString *reuse) {
629 if ((self = _SBSearchTableViewCell$initWithStyle$reuseIdentifier$(self, sel, style, reuse)) != nil) {
630 [self setBackgroundColor:[UIColor clearColor]];
634 MSHook(void, SBSearchTableViewCell$drawRect$, SBSearchTableViewCell *self, SEL sel, struct CGRect rect, BOOL selected) {
635 _SBSearchTableViewCell$drawRect$(self, sel, rect, selected);
636 float inset([self edgeInset]);
637 [[UIColor clearColor] set];
638 UIRectFill(CGRectMake(0, 0, inset, rect.size.height));
639 UIRectFill(CGRectMake(rect.size.width - inset, 0, inset, rect.size.height));
642 MSHook(UIImage *, SBApplicationIcon$icon, SBApplicationIcon *self, SEL sel) {
643 if (![Info_ wb$boolForKey:@"ComposeStoreIcons"])
644 if (NSString *path = $pathForIcon$([self application]))
645 return [UIImage imageWithContentsOfFile:path];
646 return _SBApplicationIcon$icon(self, sel);
649 MSHook(UIImage *, SBApplicationIcon$generateIconImage$, SBApplicationIcon *self, SEL sel, int type) {
651 if (![Info_ wb$boolForKey:@"ComposeStoreIcons"]) {
652 if (IsWild_ && false) // XXX: delete this code, it should not be supported
653 if (NSString *path72 = $pathForIcon$([self application], @"-72"))
654 return [UIImage imageWithContentsOfFile:path72];
655 if (NSString *path = $pathForIcon$([self application]))
656 if (UIImage *image = [UIImage imageWithContentsOfFile:path]) {
658 if ([$SBIcon respondsToSelector:@selector(defaultIconImageSize)])
659 width = [$SBIcon defaultIconImageSize].width;
662 return width == 59 ? image : [image _imageScaledToProportion:(width / 59.0) interpolationQuality:5];
665 return _SBApplicationIcon$generateIconImage$(self, sel, type);
668 MSHook(UIImage *, SBWidgetApplicationIcon$icon, SBWidgetApplicationIcon *self, SEL sel) {
670 NSLog(@"WB:Debug:Widget(%@:%@)", [self displayIdentifier], [self displayName]);
671 if (NSString *path = $getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Icons/%@.png", [self displayName]]]))
672 return [UIImage imageWithContentsOfFile:path];
673 return _SBWidgetApplicationIcon$icon(self, sel);
676 MSHook(UIImage *, SBBookmarkIcon$icon, SBBookmarkIcon *self, SEL sel) {
678 NSLog(@"WB:Debug:Bookmark(%@:%@)", [self displayIdentifier], [self displayName]);
679 if (NSString *path = $getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Icons/%@.png", [self displayName]]]))
680 return [UIImage imageWithContentsOfFile:path];
681 return _SBBookmarkIcon$icon(self, sel);
684 MSHook(NSString *, SBApplication$pathForIcon, SBApplication *self, SEL sel) {
685 if (NSString *path = $pathForIcon$(self))
687 return _SBApplication$pathForIcon(self, sel);
690 static UIImage *CachedImageAtPath(NSString *path) {
691 path = [path stringByResolvingSymlinksInPath];
692 UIImage *image = [Images_ objectForKey:path];
694 return reinterpret_cast<id>(image) == [NSNull null] ? nil : image;
695 image = [[UIImage alloc] initWithContentsOfFile:path cache:true];
697 image = [image autorelease];
698 [Images_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:path];
702 MSHook(UIImage *, _UIApplicationImageWithName, NSString *name) {
703 NSBundle *bundle = [NSBundle mainBundle];
705 NSLog(@"WB:Debug: _UIApplicationImageWithName(\"%@\", %@)", name, bundle);
706 if (NSString *path = $pathForFile$inBundle$(name, bundle, false))
707 return CachedImageAtPath(path);
708 return __UIApplicationImageWithName(name);
711 #define WBDelegate(delegate) \
712 - (NSMethodSignature*) methodSignatureForSelector:(SEL)sel { \
714 NSLog(@"WB:MS:%s:(%s)", class_getName([self class]), sel_getName(sel)); \
715 if (NSMethodSignature *sig = [delegate methodSignatureForSelector:sel]) \
717 NSLog(@"WB:Error: [%s methodSignatureForSelector:(%s)]", class_getName([self class]), sel_getName(sel)); \
721 - (void) forwardInvocation:(NSInvocation*)inv { \
722 SEL sel = [inv selector]; \
723 if ([delegate respondsToSelector:sel]) \
724 [inv invokeWithTarget:delegate]; \
726 NSLog(@"WB:Error: [%s forwardInvocation:(%s)]", class_getName([self class]), sel_getName(sel)); \
729 // %hook -[NSBundle pathForResource:ofType:] {{{
730 MSInstanceMessageHook2(NSString *, NSBundle, pathForResource,ofType, NSString *, resource, NSString *, type) {
731 NSString *file = type == nil ? resource : [NSString stringWithFormat:@"%@.%@", resource, type];
732 if ([file isEqualToString:@"Info.plist"])
733 return MSOldCall(resource, type);
735 NSLog(@"WB:Debug: [NSBundle(%@) pathForResource:\"%@\"]", [self bundleIdentifier], file);
736 if (NSString *path = $pathForFile$inBundle$(file, self, false))
738 return MSOldCall(resource, type);
742 static void $drawLabel$(NSString *label, CGRect rect, NSString *style, NSString *custom) {
743 bool ellipsis(false);
744 CGFloat max = rect.size.width - 11, width;
746 width = [(ellipsis ? [label stringByAppendingString:@"..."] : label) sizeWithStyle:style forWidth:320].width;
749 size_t length([label length]);
750 CGFloat spacing((width - max) / (length - 1));
752 if (spacing > 1.25) {
754 label = [label substringToIndex:(length - 1)];
758 style = [style stringByAppendingString:[NSString stringWithFormat:@"letter-spacing: -%f; ", spacing]];
762 label = [label stringByAppendingString:@"..."];
765 style = [style stringByAppendingString:custom];
767 CGSize size = [label sizeWithStyle:style forWidth:rect.size.width];
768 [label drawAtPoint:CGPointMake((rect.size.width - size.width) / 2 + rect.origin.x, rect.origin.y) withStyle:style];
771 static struct WBStringDrawingState {
772 WBStringDrawingState *next_;
776 } *stringDrawingState_;
778 extern "C" CGColorSpaceRef CGContextGetFillColorSpace(CGContextRef);
779 extern "C" void CGContextGetFillColor(CGContextRef, CGFloat[]);
781 static NSString *WBColorMarkup(size_t number, const CGFloat *components) {
803 return [NSString stringWithFormat:@"color: rgba(%g, %g, %g, %g)", r * 255, g * 255, b * 255, a];
806 static NSString *WBColorMarkup() {
807 CGContextRef context(UIGraphicsGetCurrentContext());
808 //NSLog(@"XXX:1:%p", context);
812 CGColorSpaceRef space(CGContextGetFillColorSpace(context));
813 //NSLog(@"XXX:2:%p", space);
817 size_t number(CGColorSpaceGetNumberOfComponents(space));
818 //NSLog(@"XXX:3:%u", number);
822 CGFloat components[number + 1];
823 CGContextGetFillColor(context, components);
824 return WBColorMarkup(number, components);
827 static NSString *WBColorMarkup(UIColor *uicolor) {
830 CGColorRef cgcolor([uicolor CGColor]);
834 CGColorSpaceRef space(CGColorGetColorSpace(cgcolor));
835 //NSLog(@"XXX:2:%p", space);
839 size_t number(CGColorGetNumberOfComponents(cgcolor));
840 //NSLog(@"XXX:3:%u", number);
844 const CGFloat *components(CGColorGetComponents(cgcolor));
845 return WBColorMarkup(number, components);
848 extern "C" NSString *NSStringFromCGPoint(CGPoint rect);
850 MSInstanceMessage6(CGSize, NSString, drawAtPoint,forWidth,withFont,lineBreakMode,letterSpacing,includeEmoji, CGPoint, point, CGFloat, width, UIFont *, font, UILineBreakMode, mode, CGFloat, spacing, BOOL, emoji) {
851 //NSLog(@"XXX: @\"%@\" %@ %g \"%@\" %u %g %u", self, NSStringFromCGPoint(point), width, font, mode, spacing, emoji);
853 WBStringDrawingState *state(stringDrawingState_);
855 return MSOldCall(point, width, font, mode, spacing, emoji);
857 if (state->count_ != 0 && --state->count_ == 0)
858 stringDrawingState_ = state->next_;
859 if (state->info_ == nil)
860 return MSOldCall(point, width, font, mode, spacing, emoji);
862 NSString *info([Info_ objectForKey:state->info_]);
864 return MSOldCall(point, width, font, mode, spacing, emoji);
866 NSString *base(state->base_ ?: @"");
867 NSString *extra([NSString stringWithFormat:@"letter-spacing: %gpx", spacing]);
868 [self drawAtPoint:point withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info]];
872 extern "C" NSString *NSStringFromCGRect(CGRect rect);
874 MSInstanceMessageHook7(CGSize, NSString, _drawInRect,withFont,lineBreakMode,alignment,lineSpacing,includeEmoji,truncationRect, CGRect, rect, UIFont *, font, UILineBreakMode, mode, UITextAlignment, alignment, float, spacing, BOOL, emoji, CGRect, truncation) {
875 //NSLog(@"XXX: @\"%@\" %@ \"%@\" %u %u %g %u %@", self, NSStringFromCGRect(rect), font, mode, alignment, spacing, emoji, NSStringFromCGRect(truncation));
877 WBStringDrawingState *state(stringDrawingState_);
879 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
881 if (state->count_ != 0 && --state->count_ == 0)
882 stringDrawingState_ = state->next_;
883 if (state->info_ == nil)
884 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
886 NSString *info([Info_ objectForKey:state->info_]);
888 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
893 case UITextAlignmentLeft:
896 case UITextAlignmentCenter:
897 textAlign = @"center";
899 case UITextAlignmentRight:
900 textAlign = @"right";
904 NSString *base(state->base_ ?: @"");
905 NSString *extra([NSString stringWithFormat:@"text-align: %@", textAlign]);
908 $drawLabel$(self, rect, [NSString stringWithFormat:@"%@;%@;%@", [font markupDescription], WBColorMarkup(), base], info);
910 [self drawInRect:rect withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info]];
915 MSInstanceMessage2(void, NSString, drawInRect,withAttributes, CGRect, rect, NSDictionary *, attributes) {
916 //NSLog(@"XXX: *\"%@\" %@", self, attributes);
918 WBStringDrawingState *state(stringDrawingState_);
920 return MSOldCall(rect, attributes);
922 if (state->count_ != 0 && --state->count_ == 0)
923 stringDrawingState_ = state->next_;
924 if (state->info_ == nil)
925 return MSOldCall(rect, attributes);
927 NSString *info([Info_ objectForKey:state->info_]);
929 return MSOldCall(rect, attributes);
931 NSString *base(state->base_ ?: @"");
933 UIFont *font([attributes objectForKey:@"NSFont"]);
934 UIColor *color([attributes objectForKey:@"NSColor"]);
936 [self drawInRect:rect withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], WBColorMarkup(color), base, info]];
939 extern "C" NSString *NSStringFromCGSize(CGSize size);
941 MSInstanceMessage4(CGRect, NSString, boundingRectWithSize,options,attributes,context, CGSize, size, NSInteger, options, NSDictionary *, attributes, id, context) {
942 //NSLog(@"XXX: $\"%@\" %@ 0x%x %@ %@", self, NSStringFromCGSize(size), unsigned(options), attributes, context);
944 WBStringDrawingState *state(stringDrawingState_);
946 return MSOldCall(size, options, attributes, context);
948 if (state->count_ != 0 && --state->count_ == 0)
949 stringDrawingState_ = state->next_;
950 if (state->info_ == nil)
951 return MSOldCall(size, options, attributes, context);
953 NSString *info([Info_ objectForKey:state->info_]);
955 return MSOldCall(size, options, attributes, context);
957 NSString *base(state->base_ ?: @"");
959 UIFont *font([attributes objectForKey:@"NSFont"]);
960 UIColor *color([attributes objectForKey:@"NSColor"]);
962 return (CGRect) {{0, 0}, [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], WBColorMarkup(color), base, info] forWidth:size.width]};
965 MSInstanceMessage4(CGSize, NSString, sizeWithFont,forWidth,lineBreakMode,letterSpacing, UIFont *, font, CGFloat, width, UILineBreakMode, mode, CGFloat, spacing) {
966 //NSLog(@"XXX: #\"%@\" \"%@\" %g %u %g", self, font, width, mode, spacing);
968 WBStringDrawingState *state(stringDrawingState_);
970 return MSOldCall(font, width, mode, spacing);
972 if (state->count_ != 0 && --state->count_ == 0)
973 stringDrawingState_ = state->next_;
974 if (state->info_ == nil)
975 return MSOldCall(font, width, mode, spacing);
977 NSString *info([Info_ objectForKey:state->info_]);
979 return MSOldCall(font, width, mode, spacing);
981 NSString *base(state->base_ ?: @"");
982 NSString *extra([NSString stringWithFormat:@"letter-spacing: %gpx", spacing]);
983 return [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info] forWidth:width];
986 MSInstanceMessage1(CGSize, NSString, sizeWithFont, UIFont *, font) {
987 //NSLog(@"XXX: ?\"%@\"", self);
989 WBStringDrawingState *state(stringDrawingState_);
991 return MSOldCall(font);
993 if (state->count_ != 0 && --state->count_ == 0)
994 stringDrawingState_ = state->next_;
995 if (state->info_ == nil)
996 return MSOldCall(font);
998 NSString *info([Info_ objectForKey:state->info_]);
1000 return MSOldCall(font);
1002 NSString *base(state->base_ ?: @"");
1003 return [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), base, info] forWidth:65535];
1006 MSClassMessageHook2(id, SBIconBadgeView, checkoutAccessoryImagesForIcon,location, id, icon, int, location) {
1007 WBStringDrawingState badgeState = {NULL, 0, @""
1010 stringDrawingState_ = &badgeState;
1012 id images(MSOldCall(icon, location));
1014 stringDrawingState_ = NULL;
1018 MSClassMessageHook2(UIImage *, SBIconAccessoryImage, checkoutAccessoryImageForIcon,location, id, icon, int, location) {
1019 if ([self _imageClassForIcon:icon location:location] != $SBIconBadgeImage)
1020 return MSOldCall(icon, location);
1022 WBStringDrawingState badgeState = {NULL, 0, @""
1025 stringDrawingState_ = &badgeState;
1027 UIImage *image(MSOldCall(icon, location));
1029 stringDrawingState_ = NULL;
1033 MSInstanceMessageHook1(UIImage *, SBIconBadgeFactory, checkoutBadgeImageForText, NSString *, text) {
1034 WBStringDrawingState badgeState = {NULL, 0, @""
1037 stringDrawingState_ = &badgeState;
1039 UIImage *image(MSOldCall(text));
1041 stringDrawingState_ = NULL;
1045 MSInstanceMessageHook1(UIImage *, SBCalendarApplicationIcon, generateIconImage, int, type) {
1046 WBStringDrawingState dayState = {NULL, 2, @""
1047 // XXX: this is only correct on an iPod dock
1048 "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px;"
1049 , @"CalendarIconDayStyle"};
1051 WBStringDrawingState skipState = {&dayState,
1052 unsigned(kCFCoreFoundationVersionNumber > 800 ? 16 : 7)
1055 WBStringDrawingState dateState = {&skipState, 2, @""
1056 , @"CalendarIconDateStyle"};
1058 stringDrawingState_ = &dateState;
1060 UIImage *image(MSOldCall(type));
1062 stringDrawingState_ = NULL;
1066 MSInstanceMessageHook1(UIImage *, UIStatusBarTimeItemView, contentsImageForStyle, int, style) {
1067 WBStringDrawingState timeState = {NULL, 0, @""
1070 stringDrawingState_ = &timeState;
1072 UIImage *image(MSOldCall(style));
1074 stringDrawingState_ = NULL;
1078 MSHook(void, SBCalendarIconContentsView$drawRect$, SBCalendarIconContentsView *self, SEL sel, CGRect rect) {
1079 NSBundle *bundle([NSBundle mainBundle]);
1081 CFLocaleRef locale(CFLocaleCopyCurrent());
1082 CFDateFormatterRef formatter(CFDateFormatterCreate(NULL, locale, kCFDateFormatterNoStyle, kCFDateFormatterNoStyle));
1085 CFDateRef now(CFDateCreate(NULL, CFAbsoluteTimeGetCurrent()));
1087 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NUMBER_FORMAT" value:@"d" table:@"SpringBoard"]);
1088 CFStringRef date(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
1089 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NAME_FORMAT" value:@"cccc" table:@"SpringBoard"]);
1090 CFStringRef day(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
1094 CFRelease(formatter);
1096 NSString *datestyle([@""
1097 "font-family: Helvetica; "
1098 "font-weight: bold; "
1101 "" stringByAppendingString:(IsWild_
1102 ? @"font-size: 54px; "
1103 : @"font-size: 39px; "
1106 NSString *daystyle([@""
1107 "font-family: Helvetica; "
1108 "font-weight: bold; "
1110 "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px; "
1111 "" stringByAppendingString:(IsWild_
1112 ? @"font-size: 11px; "
1113 : @"font-size: 9px; "
1116 if (NSString *style = [Info_ objectForKey:@"CalendarIconDateStyle"])
1117 datestyle = [datestyle stringByAppendingString:style];
1118 if (NSString *style = [Info_ objectForKey:@"CalendarIconDayStyle"])
1119 daystyle = [daystyle stringByAppendingString:style];
1121 CGFloat width([self bounds].size.width);
1123 CGSize datesize = [(NSString *)date sizeWithStyle:datestyle forWidth:(width + leeway)];
1124 CGSize daysize = [(NSString *)day sizeWithStyle:daystyle forWidth:(width + leeway)];
1126 unsigned base0(IsWild_ ? 89 : 70);
1127 if ($GSFontGetUseLegacyFontMetrics())
1129 unsigned base1(IsWild_ ? 18 : 16);
1136 [(NSString *)date drawAtPoint:CGPointMake(
1137 (width + 1 - datesize.width) / 2, (base0 - datesize.height) / 2
1138 ) withStyle:datestyle];
1140 [(NSString *)day drawAtPoint:CGPointMake(
1141 (width + 1 - daysize.width) / 2, (base1 - daysize.height) / 2
1142 ) withStyle:daystyle];
1148 // %hook -[{NavigationBar,Toolbar} setBarStyle:] {{{
1149 void $setBarStyle$_(NSString *name, int &style) {
1151 NSLog(@"WB:Debug:%@Style:%d", name, style);
1152 NSNumber *number = nil;
1154 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style-%d", name, style]];
1156 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style", name]];
1157 if (number != nil) {
1158 style = [number intValue];
1160 NSLog(@"WB:Debug:%@Style=%d", name, style);
1164 MSInstanceMessageHook1(void, UIToolbar, setBarStyle, int, style) {
1165 $setBarStyle$_(@"Toolbar", style);
1166 return MSOldCall(style);
1169 MSInstanceMessageHook1(void, UINavigationBar, setBarStyle, int, style) {
1170 $setBarStyle$_(@"NavigationBar", style);
1171 return MSOldCall(style);
1175 MSHook(void, SBButtonBar$didMoveToSuperview, UIView *self, SEL sel) {
1176 [[self superview] setBackgroundColor:[UIColor clearColor]];
1177 _SBButtonBar$didMoveToSuperview(self, sel);
1180 MSHook(void, SBStatusBarContentsView$didMoveToSuperview, UIView *self, SEL sel) {
1181 [[self superview] setBackgroundColor:[UIColor clearColor]];
1182 _SBStatusBarContentsView$didMoveToSuperview(self, sel);
1185 static NSArray *Wallpapers_;
1186 static bool Papered_;
1187 static bool Docked_;
1188 static bool SMSBackgrounded_;
1189 static NSString *WallpaperFile_;
1190 static UIImageView *WallpaperImage_;
1191 static UIWebDocumentView *WallpaperPage_;
1192 static NSURL *WallpaperURL_;
1194 #define _release(object) \
1195 do if (object != nil) { \
1200 static UIImage *$getImage$(NSString *path) {
1201 UIImage *image([UIImage imageWithContentsOfFile:path]);
1203 unsigned scale($getScale$(path));
1204 if (scale != 1 && [image respondsToSelector:@selector(setScale)])
1205 [image setScale:scale];
1210 template <typename Original_, typename Modified_>
1211 _finline UIImage *WBCacheImage(const Original_ &original, const Modified_ &modified, NSString *key) {
1212 UIImage *image([Images_ objectForKey:key]);
1214 return reinterpret_cast<id>(image) == [NSNull null] ? original() : image;
1215 if (NSString *path = modified())
1216 image = $getImage$(path);
1217 [Images_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:key];
1218 return image == nil ? original() : image;
1221 static UIImage *$getDefaultDesktopImage$() {
1222 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"LockBackground.png", @"LockBackground.jpg", nil])))
1223 return $getImage$(path);
1227 MSClassMessageHook0(UIImage *, UIImage, defaultDesktopImage) {
1228 return $getDefaultDesktopImage$() ?: MSOldCall();
1231 MSInstanceMessageHook0(UIImage *, SBSlidingAlertDisplay, _defaultDesktopImage) {
1232 return $getDefaultDesktopImage$() ?: MSOldCall();
1235 MSInstanceMessageHook0(void, SBWallpaperView, resetCurrentImageToWallpaper) {
1236 for (UIView *parent([self superview]); parent != nil; parent = [parent superview])
1237 if ([parent isKindOfClass:$SBSlidingAlertDisplay]) {
1238 if (UIImage *image = $getDefaultDesktopImage$()) {
1239 [self setImage:image];
1249 // %hook -[SBUIController init] {{{
1250 MSInstanceMessageHook0(id, SBUIController, init) {
1255 NSString *paper($getTheme$(Wallpapers_));
1257 paper = [paper stringByDeletingLastPathComponent];
1261 sysctlbyname("hw.machine", NULL, &size, NULL, 0);
1262 char *machine = new char[size];
1264 if (sysctlbyname("hw.machine", machine, &size, NULL, 0) == -1) {
1265 perror("sysctlbyname(\"hw.machine\", ?)");
1270 IsWild_ = machine != NULL && strncmp(machine, "iPad", 4) == 0;
1274 NSLog(@"WB:Debug:Info = %@", [Info_ description]);
1277 UIImageView *&_wallpaperView(MSHookIvar<UIImageView *>(self, "_wallpaperView"));
1278 if (&_wallpaperView != NULL) {
1279 [_wallpaperView removeFromSuperview];
1280 [_wallpaperView release];
1281 _wallpaperView = nil;
1285 UIView *&_contentLayer(MSHookIvar<UIView *>(self, "_contentLayer"));
1286 UIView *&_contentView(MSHookIvar<UIView *>(self, "_contentView"));
1289 if (&_contentLayer != NULL)
1290 player = &_contentLayer;
1291 else if (&_contentView != NULL)
1292 player = &_contentView;
1295 UIView *layer(player == NULL ? nil : *player);
1297 UIWindow *window([[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]);
1298 UIView *content([[[UIView alloc] initWithFrame:[window frame]] autorelease]);
1299 [window setContentView:content];
1301 UIWindow *&_window(MSHookIvar<UIWindow *>(self, "_window"));
1302 [window setBackgroundColor:[_window backgroundColor]];
1303 [_window setBackgroundColor:[UIColor clearColor]];
1305 [window setLevel:-1000];
1306 [window setHidden:NO];
1308 /*if (player != NULL)
1309 *player = content;*/
1311 [content setBackgroundColor:[layer backgroundColor]];
1312 [layer setBackgroundColor:[UIColor clearColor]];
1315 if (!SummerBoard_ || !IsWild_)
1318 CGRect bounds([content bounds]);
1319 bounds.origin.y = -30;
1320 indirect = [[[UIView alloc] initWithFrame:bounds] autorelease];
1321 [content addSubview:indirect];
1322 [indirect zoomToScale:2.4];
1325 _release(WallpaperFile_);
1326 _release(WallpaperImage_);
1327 _release(WallpaperPage_);
1328 _release(WallpaperURL_);
1331 NSArray *themes([NSArray arrayWithObject:paper]);
1333 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"], themes)) {
1337 static AVController *controller_(nil);
1338 if (controller_ == nil) {
1339 AVQueue *queue([AVQueue avQueue]);
1340 controller_ = [[AVController avControllerWithQueue:queue error:&error] retain];
1343 AVQueue *queue([controller_ queue]);
1345 UIView *video([[[UIView alloc] initWithFrame:[indirect bounds]] autorelease]);
1346 [controller_ setLayer:[video _layer]];
1348 AVItem *item([[[AVItem alloc] initWithPath:path error:&error] autorelease]);
1349 [queue appendItem:item error:&error];
1351 [controller_ play:&error];
1352 #elif UseMPMoviePlayerController
1353 NSURL *url([NSURL fileURLWithPath:path]);
1354 MPMoviePlayerController *controller = [[$MPMoviePlayerController alloc] initWithContentURL:url];
1355 controller.movieControlMode = MPMovieControlModeHidden;
1358 MPVideoView *video = [[[$MPVideoView alloc] initWithFrame:[indirect bounds]] autorelease];
1359 [video setMovieWithPath:path];
1360 [video setRepeatMode:1];
1361 [video setRepeatGap:-1];
1362 [video playFromBeginning];;
1365 [indirect addSubview:video];
1368 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"Wallpaper.png", @"Wallpaper.jpg", nil]), themes)) {
1369 if (UIImage *image = $getImage$(path)) {
1370 WallpaperFile_ = [path retain];
1371 WallpaperImage_ = [[UIImageView alloc] initWithImage:image];
1372 if (NSNumber *number = [Info_ objectForKey:@"WallpaperAlpha"])
1373 [WallpaperImage_ setAlpha:[number floatValue]];
1374 [indirect addSubview:WallpaperImage_];
1378 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.html"], themes)) {
1379 CGRect bounds = [indirect bounds];
1381 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1382 [view setAutoresizes:true];
1384 WallpaperPage_ = [view retain];
1385 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
1387 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1389 [view setBackgroundColor:[UIColor clearColor]];
1390 if ([view respondsToSelector:@selector(setDrawsBackground:)])
1391 [view setDrawsBackground:NO];
1392 [[view webView] setDrawsBackground:NO];
1394 [indirect addSubview:view];
1398 for (size_t i(0), e([Themes_ count]); i != e; ++i) {
1399 NSString *theme = [Themes_ objectAtIndex:(e - i - 1)];
1400 NSString *html = [theme stringByAppendingPathComponent:@"Widget.html"];
1401 if ([Manager_ fileExistsAtPath:html]) {
1402 CGRect bounds = [indirect bounds];
1404 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1405 [view setAutoresizes:true];
1407 NSURL *url = [NSURL fileURLWithPath:html];
1408 [view loadRequest:[NSURLRequest requestWithURL:url]];
1410 [view setBackgroundColor:[UIColor clearColor]];
1411 if ([view respondsToSelector:@selector(setDrawsBackground:)])
1412 [view setDrawsBackground:NO];
1413 [[view webView] setDrawsBackground:NO];
1415 [indirect addSubview:view];
1423 MSHook(void, SBAwayView$updateDesktopImage$, SBAwayView *self, SEL sel, UIImage *image) {
1424 NSString *path = $getTheme$([NSArray arrayWithObject:@"LockBackground.html"]);
1425 UIView *&_backgroundView(MSHookIvar<UIView *>(self, "_backgroundView"));
1427 if (path != nil && _backgroundView != nil)
1430 _SBAwayView$updateDesktopImage$(self, sel, image);
1433 CGRect bounds = [self bounds];
1435 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1436 [view setAutoresizes:true];
1438 if (WallpaperPage_ != nil)
1439 [WallpaperPage_ release];
1440 WallpaperPage_ = [view retain];
1442 if (WallpaperURL_ != nil)
1443 [WallpaperURL_ release];
1444 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
1446 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1448 [[view webView] setDrawsBackground:false];
1449 [view setBackgroundColor:[UIColor clearColor]];
1451 [self insertSubview:view aboveSubview:_backgroundView];
1453 if ($objc_setAssociatedObject != NULL)
1454 $objc_setAssociatedObject(self, @selector(wb$widgetView), view, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1458 MSHook(void, SBAwayView$_addSubview$positioned$relativeTo$, SBAwayView *self, SEL sel, UIView *view, int positioned, UIView *relative) {
1459 UIView *&_backgroundView(MSHookIvar<UIView *>(self, "_backgroundView"));
1460 UIView *&_chargingView(MSHookIvar<UIView *>(self, "_chargingView"));
1461 if (&_chargingView != NULL)
1462 if (positioned == -2 && (relative == _backgroundView && _chargingView == nil || relative == _chargingView))
1463 if ($objc_getAssociatedObject != NULL)
1464 if (UIView *widget = $objc_getAssociatedObject(self, @selector(wb$widgetView)))
1466 return _SBAwayView$_addSubview$positioned$relativeTo$(self, sel, view, positioned, relative);
1469 /*extern "C" CGColorRef CGGStateGetSystemColor(void *);
1470 extern "C" CGColorRef CGGStateGetFillColor(void *);
1471 extern "C" CGColorRef CGGStateGetStrokeColor(void *);
1472 extern "C" NSString *UIStyleStringFromColor(CGColorRef);*/
1474 /* WBTimeLabel {{{ */
1475 @interface WBTimeLabel : NSProxy {
1477 _transient SBStatusBarTimeView *view_;
1480 - (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view;
1484 @implementation WBTimeLabel
1491 - (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view {
1492 time_ = [time retain];
1497 - (NSString *) description {
1503 - (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(UILineBreakMode)mode {
1504 if (NSString *custom = [Info_ objectForKey:@"TimeStyle"]) {
1505 BOOL &_mode(MSHookIvar<BOOL>(view_, "_mode"));;
1507 [time_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1508 "font-family: Helvetica; "
1509 "font-weight: bold; "
1512 "%@", _mode ? @"white" : @"black", custom]];
1517 return [time_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1522 /* WBBadgeLabel {{{ */
1523 @interface WBBadgeLabel : NSProxy {
1527 - (id) initWithBadge:(NSString *)badge;
1528 - (NSString *) description;
1532 @implementation WBBadgeLabel
1539 - (id) initWithBadge:(NSString *)badge {
1540 badge_ = [badge retain];
1544 - (NSString *) description {
1545 return [badge_ description];
1550 - (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(UILineBreakMode)mode {
1551 if (NSString *custom = [Info_ objectForKey:@"BadgeStyle"]) {
1552 [badge_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1553 "font-family: Helvetica; "
1554 "font-weight: bold; "
1562 return [badge_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1569 MSInstanceMessageHook1(void, SBIcon, setIconImageAlpha, CGFloat, alpha) {
1570 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1571 alpha = [number floatValue];
1572 return MSOldCall(alpha);
1575 MSInstanceMessageHook1(void, SBIcon, setIconLabelAlpha, CGFloat, alpha) {
1576 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1577 alpha = [number floatValue];
1578 return MSOldCall(alpha);
1581 MSInstanceMessageHook0(id, SBIcon, initWithDefaultSize) {
1582 if ((self = MSOldCall()) != nil) {
1583 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"]) {
1584 // XXX: note: this is overridden above, which is silly
1585 float alpha([number floatValue]);
1586 if ([self respondsToSelector:@selector(setIconImageAlpha:)])
1587 [self setIconImageAlpha:alpha];
1588 if ([self respondsToSelector:@selector(setIconLabelAlpha:)])
1589 [self setIconLabelAlpha:alpha];
1590 if ([self respondsToSelector:@selector(setAlpha:)])
1591 [self setAlpha:alpha];
1596 MSInstanceMessageHook1(void, SBIcon, setAlpha, CGFloat, alpha) {
1597 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1598 alpha = [number floatValue];
1599 return MSOldCall(alpha);
1603 MSHook(id, SBIconBadge$initWithBadge$, SBIconBadge *self, SEL sel, NSString *badge) {
1604 if ((self = _SBIconBadge$initWithBadge$(self, sel, badge)) != nil) {
1605 id &_badge(MSHookIvar<id>(self, "_badge"));
1607 if (id label = [[WBBadgeLabel alloc] initWithBadge:[_badge autorelease]])
1612 void SBStatusBarController$setStatusBarMode(int &mode) {
1614 NSLog(@"WB:Debug:setStatusBarMode:%d", mode);
1615 if (mode < 100) // 104:hidden 105:glowing
1616 if (NSNumber *number = [Info_ objectForKey:@"StatusBarMode"])
1617 mode = [number intValue];
1620 /*MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, double duration, int animation) {
1621 NSLog(@"mode:%d orientation:%d duration:%f animation:%d", mode, orientation, duration, animation);
1622 SBStatusBarController$setStatusBarMode(mode);
1623 return _SBStatusBarController$setStatusBarMode$orientation$duration$animation$(self, sel, mode, orientation, duration, animation);
1626 MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, float duration, int fenceID, int animation) {
1627 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d", mode, orientation, duration, fenceID, animation);
1628 SBStatusBarController$setStatusBarMode(mode);
1629 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$(self, sel, mode, orientation, duration, fenceID, animation);
1632 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) {
1633 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d startTime:%f", mode, orientation, duration, fenceID, animation, startTime);
1634 SBStatusBarController$setStatusBarMode(mode);
1635 //NSLog(@"mode=%u", mode);
1636 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$startTime$(self, sel, mode, orientation, duration, fenceID, animation, startTime);
1639 /*MSHook(id, SBStatusBarContentsView$initWithStatusBar$mode$, SBStatusBarContentsView *self, SEL sel, id bar, int mode) {
1640 if (NSNumber *number = [Info_ objectForKey:@"StatusBarContentsMode"])
1641 mode = [number intValue];
1642 return _SBStatusBarContentsView$initWithStatusBar$mode$(self, sel, bar, mode);
1645 MSHook(NSString *, SBStatusBarOperatorNameView$operatorNameStyle, SBStatusBarOperatorNameView *self, SEL sel) {
1646 NSString *style(_SBStatusBarOperatorNameView$operatorNameStyle(self, sel));
1648 NSLog(@"operatorNameStyle= %@", style);
1649 if (NSString *custom = [Info_ objectForKey:@"OperatorNameStyle"])
1650 style = [NSString stringWithFormat:@"%@; %@", style, custom];
1654 MSHook(void, SBStatusBarOperatorNameView$setOperatorName$fullSize$, SBStatusBarOperatorNameView *self, SEL sel, NSString *name, BOOL full) {
1656 NSLog(@"setOperatorName:\"%@\" fullSize:%u", name, full);
1657 return _SBStatusBarOperatorNameView$setOperatorName$fullSize$(self, sel, name, NO);
1660 // XXX: replace this with [SBStatusBarTimeView tile]
1661 MSHook(void, SBStatusBarTimeView$drawRect$, SBStatusBarTimeView *self, SEL sel, CGRect rect) {
1662 id &_time(MSHookIvar<id>(self, "_time"));
1663 if (_time != nil && [_time class] != [WBTimeLabel class])
1664 object_setInstanceVariable(self, "_time", reinterpret_cast<void *>([[WBTimeLabel alloc] initWithTime:[_time autorelease] view:self]));
1665 return _SBStatusBarTimeView$drawRect$(self, sel, rect);
1668 @interface UIView (WinterBoard)
1669 - (bool) wb$isWBImageView;
1670 - (void) wb$logHierarchy;
1671 - (void) wb$setBackgroundColor:(UIColor *)color;
1674 @implementation UIView (WinterBoard)
1676 - (bool) wb$isWBImageView {
1680 - (void) wb$logHierarchy {
1681 WBLogHierarchy(self);
1684 - (void) wb$setBackgroundColor:(UIColor *)color {
1685 [self setBackgroundColor:color];
1686 for (UIView *child in [self subviews])
1687 [child wb$setBackgroundColor:color];
1692 @interface WBImageView : UIImageView {
1695 - (bool) wb$isWBImageView;
1696 - (void) wb$updateFrame;
1699 @implementation WBImageView
1701 - (bool) wb$isWBImageView {
1705 - (void) wb$updateFrame {
1706 CGRect frame([self frame]);
1709 for (UIView *view(self); ; ) {
1710 view = [view superview];
1713 frame.origin.y -= [view frame].origin.y;
1716 [self setFrame:frame];
1721 static void SBIconList$updateFrames$(SBIconList *self) {
1722 NSArray *subviews([self subviews]);
1723 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1724 if (view != nil && [view wb$isWBImageView])
1725 [view wb$updateFrame];
1728 MSHook(void, SBIconList$didMoveToSuperview, SBIconList *self, SEL sel) {
1729 SBIconList$updateFrames$(self);
1730 _SBIconList$didMoveToSuperview(self, sel);
1733 MSHook(void, SBIconList$setFrame$, SBIconList *self, SEL sel, CGRect frame) {
1734 SBIconList$updateFrames$(self);
1735 _SBIconList$setFrame$(self, sel, frame);
1738 static void $addPerPageView$(unsigned i, UIView *list) {
1739 NSString *path($getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Page%u.png", i]]));
1743 NSArray *subviews([list subviews]);
1745 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1746 if (view == nil || ![view wb$isWBImageView]) {
1747 view = [[[WBImageView alloc] init] autorelease];
1748 [list insertSubview:view atIndex:0];
1751 UIImage *image([UIImage imageWithContentsOfFile:path]);
1753 CGRect frame([view frame]);
1754 frame.size = [image size];
1755 [view setFrame:frame];
1757 [view setImage:image];
1758 [view wb$updateFrame];
1761 static void $addPerPageViews$(NSArray *lists) {
1762 for (unsigned i(0), e([lists count]); i != e; ++i)
1763 $addPerPageView$(i, [lists objectAtIndex:i]);
1766 MSInstanceMessageHook0(void, SBIconController, updateNumberOfRootIconLists) {
1767 NSArray *&_rootIconLists(MSHookIvar<NSArray *>(self, "_rootIconLists"));
1768 $addPerPageViews$(_rootIconLists);
1772 MSInstanceMessageHook0(void, SBIconContentView, layoutSubviews) {
1775 if (SBIconController *controller = [$SBIconController sharedInstance]) {
1776 UIView *&_dockContainerView(MSHookIvar<UIView *>(controller, "_dockContainerView"));
1777 if (&_dockContainerView != NULL)
1778 [[_dockContainerView superview] bringSubviewToFront:_dockContainerView];
1782 MSHook(void, SBIconController$noteNumberOfIconListsChanged, SBIconController *self, SEL sel) {
1783 SBIconModel *&_iconModel(MSHookIvar<SBIconModel *>(self, "_iconModel"));
1784 $addPerPageViews$([_iconModel iconLists]);
1785 return _SBIconController$noteNumberOfIconListsChanged(self, sel);
1788 MSHook(id, SBIconLabel$initWithSize$label$, SBIconLabel *self, SEL sel, CGSize size, NSString *label) {
1789 self = _SBIconLabel$initWithSize$label$(self, sel, size, label);
1791 [self setClipsToBounds:NO];
1795 MSHook(void, SBIconLabel$setInDock$, SBIconLabel *self, SEL sel, BOOL docked) {
1796 static bool gssc(false);
1798 BOOL (*GSSystemHasCapability)(CFStringRef) = reinterpret_cast<BOOL (*)(CFStringRef)>(dlsym(RTLD_DEFAULT, "GSSystemHasCapability"));
1799 Papered_ |= GSSystemHasCapability != NULL && GSSystemHasCapability(CFSTR("homescreen-wallpaper"));
1802 if ([Info_ objectForKey:@"UndockedIconLabels"] == nil)
1803 [Info_ setObject:[NSNumber numberWithBool:(
1805 [Info_ objectForKey:@"DockedIconLabelStyle"] != nil ||
1806 [Info_ objectForKey:@"UndockedIconLabelStyle"] != nil
1807 )] forKey:@"UndockedIconLabels"];
1810 id &_label(MSHookIvar<id>(self, "_label"));
1811 if (![Info_ wb$boolForKey:@"UndockedIconLabels"])
1814 if (_label != nil && [_label respondsToSelector:@selector(setInDock:)])
1815 [_label setInDock:docked];
1817 _SBIconLabel$setInDock$(self, sel, docked);
1818 [self setNeedsDisplay];
1821 MSHook(BOOL, SBDockIconListView$shouldShowNewDock, id self, SEL sel) {
1822 return SummerBoard_ && Docked_ ? NO : _SBDockIconListView$shouldShowNewDock(self, sel);
1825 MSHook(void, SBDockIconListView$setFrame$, id self, SEL sel, CGRect frame) {
1826 _SBDockIconListView$setFrame$(self, sel, frame);
1829 // %hook -[NSBundle localizedStringForKey:value:table:] {{{
1830 MSInstanceMessageHook3(NSString *, NSBundle, localizedStringForKey,value,table, NSString *, key, NSString *, value, NSString *, table) {
1831 NSString *identifier = [self bundleIdentifier];
1832 NSLocale *locale = [NSLocale currentLocale];
1833 NSString *language = [locale objectForKey:NSLocaleLanguageCode];
1835 NSLog(@"WB:Debug:[NSBundle(%@) localizedStringForKey:\"%@\" value:\"%@\" table:\"%@\"] (%@)", identifier, key, value, table, language);
1836 NSString *file = table == nil ? @"Localizable" : table;
1837 NSString *name = [NSString stringWithFormat:@"%@:%@", identifier, file];
1838 NSDictionary *strings;
1839 if ((strings = [Strings_ objectForKey:name]) != nil) {
1840 if (static_cast<id>(strings) != [NSNull null]) strings:
1841 if (NSString *value = [strings objectForKey:key])
1843 } else if (NSString *path = $pathForFile$inBundle$([NSString stringWithFormat:@"%@.lproj/%@.strings",
1846 if ((strings = [[NSDictionary alloc] initWithContentsOfFile:path]) != nil) {
1847 [Strings_ setObject:[strings autorelease] forKey:name];
1851 [Strings_ setObject:[NSNull null] forKey:name];
1852 return MSOldCall(key, value, table);
1855 // %hook -[WebCoreFrameBridge renderedSizeOfNode:constrainedToWidth:] {{{
1856 MSClassHook(WebCoreFrameBridge)
1858 MSInstanceMessageHook2(CGSize, WebCoreFrameBridge, renderedSizeOfNode,constrainedToWidth, id, node, float, width) {
1861 void **core(reinterpret_cast<void **>([node _node]));
1862 if (core == NULL || core[6] == NULL)
1864 return MSOldCall(node, width);
1868 MSInstanceMessage1(void, SBIconLabel, drawRect, CGRect, rect) {
1869 static Ivar drawMoreLegibly = object_getInstanceVariable(self, "_drawMoreLegibly", NULL);
1872 Ivar ivar = object_getInstanceVariable(self, "_inDock", reinterpret_cast<void **>(&docked));
1873 docked = (docked & (ivar_getOffset(ivar) == ivar_getOffset(drawMoreLegibly) ? 0x2 : 0x1)) != 0;
1875 NSString *label(MSHookIvar<NSString *>(self, "_label"));
1877 NSString *style = [NSString stringWithFormat:@""
1878 "font-family: Helvetica; "
1879 "font-weight: bold; "
1881 "", (docked || !SummerBoard_ ? @"white" : @"#b3b3b3"), (IsWild_
1882 ? @"font-size: 12px; "
1883 : @"font-size: 11px; "
1887 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px 1px 0px; "];
1889 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px -1px 0px; "];
1891 NSString *custom([Info_ objectForKey:(docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle")]);
1893 $drawLabel$(label, [self bounds], style, custom);
1896 MSInstanceMessage0(CGImageRef, SBIconLabel, buildLabelImage) {
1897 bool docked((MSHookIvar<unsigned>(self, "_inDock") & 0x2) != 0);
1899 WBStringDrawingState labelState = {NULL, 0, @""
1900 , docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle"};
1902 stringDrawingState_ = &labelState;
1905 CGImageRef image(MSOldCall());
1908 stringDrawingState_ = NULL;
1912 static bool wb$inDock(id parameters) {
1913 return [$objc_getAssociatedObject(parameters, @selector(wb$inDock)) boolValue];
1916 MSInstanceMessage0(NSUInteger, SBIconLabelImageParameters, hash) {
1917 return MSOldCall() + (wb$inDock(self) ? 0xdeadbeef : 0xd15ea5e);
1920 MSClassMessage2(id, SBIconView, _labelImageParametersForIcon,location, id, icon, int, location) {
1921 if (id parameters = MSOldCall(icon, location)) {
1922 $objc_setAssociatedObject(parameters, @selector(wb$inDock), [NSNumber numberWithBool:(location == 1)], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1927 MSInstanceMessage0(id, SBIconView, _labelImageParameters) {
1928 if (id parameters = MSOldCall()) {
1929 int &location(MSHookIvar<int>(self, "_iconLocation"));
1930 if (&location != NULL)
1931 $objc_setAssociatedObject(parameters, @selector(wb$inDock), [NSNumber numberWithBool:(location == 3)], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1936 MSClassMessage1(UIImage *, SBIconLabelImage, _drawLabelImageForParameters, id, parameters) {
1937 bool docked(wb$inDock(parameters));
1939 WBStringDrawingState labelState = {NULL, 0, @""
1940 , docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle"};
1942 stringDrawingState_ = &labelState;
1945 UIImage *image(MSOldCall(parameters));
1948 stringDrawingState_ = NULL;
1953 MSInstanceMessageHook2(id, CKBalloonView, initWithFrame,delegate, CGRect, frame, id, delegate) {
1954 if ((self = MSOldCall(frame, delegate)) != nil) {
1955 [self setBackgroundColor:[UIColor clearColor]];
1959 MSInstanceMessageHook0(BOOL, CKBalloonView, _canUseLayerBackedBalloon) {
1960 return SMSBackgrounded_ ? NO : MSOldCall();
1963 MSInstanceMessageHook0(void, CKTranscriptHeaderView, layoutSubviews) {
1964 [self wb$setBackgroundColor:[UIColor clearColor]];
1968 MSInstanceMessageHook1(void, CKMessageCell, addBalloonView, CKBalloonView *, balloon) {
1970 [balloon setBackgroundColor:[UIColor clearColor]];
1973 MSInstanceMessageHook1(void, CKTranscriptCell, setBackgroundColor, UIColor *, color) {
1974 MSOldCall([UIColor clearColor]);
1975 [[self contentView] wb$setBackgroundColor:[UIColor clearColor]];
1979 MSInstanceMessageHook2(id, CKTranscriptCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1980 if ((self = MSOldCall(style, reuse)) != nil) {
1981 [self setBackgroundColor:[UIColor clearColor]];
1982 [[self contentView] wb$setBackgroundColor:[UIColor clearColor]];
1987 MSInstanceMessageHook2(id, CKMessageCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1988 if ((self = MSOldCall(style, reuse)) != nil) {
1989 [self setBackgroundColor:[UIColor clearColor]];
1990 [[self contentView] setBackgroundColor:[UIColor clearColor]];
1994 MSInstanceMessageHook2(id, CKTimestampView, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1995 if ((self = MSOldCall(style, reuse)) != nil) {
1996 UILabel *&_label(MSHookIvar<UILabel *>(self, "_label"));
1997 [_label setBackgroundColor:[UIColor clearColor]];
2001 MSInstanceMessageHook1(void, CKTranscriptTableView, setSeparatorStyle, int, style) {
2002 MSOldCall(UITableViewCellSeparatorStyleNone);
2005 MSInstanceMessageHook2(id, CKTranscriptTableView, initWithFrame,style, CGRect, frame, int, style) {
2006 if ((self = MSOldCall(frame, style)) != nil) {
2007 [self setSeparatorStyle:UITableViewCellSeparatorStyleNone];
2011 MSInstanceMessageHook0(void, CKTranscriptController, loadView) {
2014 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"SMSBackground.png", @"SMSBackground.jpg", nil])))
2015 if (UIImage *image = $getImage$(path)) {
2016 SMSBackgrounded_ = true;
2018 UIView *&_transcriptTable(MSHookIvar<UIView *>(self, "_transcriptTable"));
2019 UIView *&_transcriptLayer(MSHookIvar<UIView *>(self, "_transcriptLayer"));
2021 if (&_transcriptTable != NULL)
2022 table = _transcriptTable;
2023 else if (&_transcriptLayer != NULL)
2024 table = _transcriptLayer;
2028 UIView *placard(table != nil ? [table superview] : MSHookIvar<UIView *>(self, "_backPlacard"));
2029 UIImageView *background([[[UIImageView alloc] initWithImage:image] autorelease]);
2032 [placard insertSubview:background atIndex:0];
2034 [table setBackgroundColor:[UIColor clearColor]];
2035 [placard insertSubview:background belowSubview:table];
2041 template <typename Original_>
2042 static UIImage *WBCacheUIImage(NSBundle *bundle, const Original_ &original, NSString *name, NSString *key) {
2045 NSUInteger period([name rangeOfString:@"."].location);
2046 NSUInteger length([name length]);
2047 if (period == NSNotFound || length < 4 || period > length - 4)
2048 name = [name stringByAppendingString:@".png"];
2050 return WBCacheImage([bundle, &original, name](){
2051 UIImage *image(original());
2052 if (image != nil && UIDebug_) {
2053 NSString *path([@"/tmp/WBImages/" stringByAppendingString:[bundle bundleIdentifier]]);
2054 [Manager_ createDirectoryAtPath:path withIntermediateDirectories:YES attributes:@{NSFilePosixPermissions: @0777} error:NULL];
2055 path = [NSString stringWithFormat:@"%@/%@", path, name];
2056 if (![Manager_ fileExistsAtPath:path])
2057 [UIImagePNGRepresentation(image) writeToFile:path atomically:YES];
2059 }, [=](){ return $pathForFile$inBundle$(name, bundle, true); }, key);
2062 // %hook _UIImageWithName() {{{
2063 MSHook(UIImage *, _UIImageWithName, NSString *name) {
2067 NSLog(@"WB:Debug: _UIImageWithName(\"%@\")", name);
2068 return WBCacheUIImage(_UIKitBundle(),
2069 [=](){ return __UIImageWithName(name); },
2070 name, [NSString stringWithFormat:@"I:%@", name]);
2073 // %hook _UIImageWithNameInDomain() {{{
2074 MSHook(UIImage *, _UIImageWithNameInDomain, NSString *name, NSString *domain) {
2076 NSLog(@"WB:Debug: _UIImageWithNameInDomain(\"%@\", \"%@\")", name, domain);
2077 return WBCacheImage(
2078 [=](){ return __UIImageWithNameInDomain(name, domain); },
2079 [=](){ return $getTheme$($useScale$([NSArray arrayWithObject:[NSString stringWithFormat:@"Domains/%@/%@", domain, name]])); },
2080 [NSString stringWithFormat:@"D:%zu:%@%@", size_t([domain length]), domain, name]);
2084 // UISharedArtwork (iOS 6) {{{
2085 MSInstanceMessageHook2(UISharedArtwork *, UISharedArtwork, initWithName,inBundle, NSString *, name, NSBundle *, bundle) {
2086 if ((self = MSOldCall(name, bundle)) != nil) {
2087 $objc_setAssociatedObject(self, @selector(wb$bundle), bundle, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
2091 MSInstanceMessageHook2(UIImage *, UISharedArtwork, imageNamed,device, NSString *, name, NSInteger, device) {
2092 NSBundle *bundle($objc_getAssociatedObject(self, @selector(wb$bundle)));
2094 NSLog(@"WB:Debug: -[UISharedArtwork(%@) imageNamed:@\"%@\" device:%li]", [bundle bundleIdentifier], name, (long) device);
2095 return WBCacheUIImage(bundle,
2096 [=](){ return MSOldCall(name, device); },
2097 name, [NSString stringWithFormat:@"M:%p:%@:%li", self, name, (long) device]);
2100 // _UIAssetManager (iOS 7) {{{
2101 MSInstanceMessageHook3(_UIAssetManager *, _UIAssetManager, initWithName,inBundle,idiom, NSString *, name, NSBundle *, bundle, NSInteger, idiom) {
2102 if ((self = MSOldCall(name, bundle, idiom)) != nil) {
2103 $objc_setAssociatedObject(self, @selector(wb$bundle), bundle, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
2107 MSInstanceMessageHook5(UIImage *, _UIAssetManager, imageNamed,scale,idiom,subtype,cachingOptions, NSString *, name, CGFloat, scale, NSInteger, idiom, NSUInteger, subtype, NSUInteger, caching) {
2108 NSBundle *bundle($objc_getAssociatedObject(self, @selector(wb$bundle)));
2110 NSLog(@"WB:Debug: -[_UIAssetManager(%@/%@) imageNamed:@\"%@\" scale:%g idiom:%li subtype:%lu cachingOptions:%lu]",
2111 [bundle bundleIdentifier], [self carFileName],
2112 name, scale, (long) idiom,
2113 (unsigned long) subtype,
2114 (unsigned long) caching
2117 if (bundle == _UIKitBundle()) {
2118 NSString *name([self carFileName]);
2120 else if ([name isEqualToString:@"UIKit_NewArtwork"])
2121 bundle = [WBBundle bundleWithIdentifier:@"com.apple.uikit.Artwork"];
2122 else if ([name isEqualToString:@"UIKit_OriginalArtwork"])
2123 bundle = [WBBundle bundleWithIdentifier:@"com.apple.uikit.LegacyArtwork"];
2126 return WBCacheUIImage(bundle,
2127 [=](){ return MSOldCall(name, scale, idiom, subtype, caching); },
2128 name, [NSString stringWithFormat:@"M:%p:%@:%g:%li:%lu", self, name, scale, (long) idiom, (unsigned long) subtype]);
2131 // _UIAssetManager (iOS 8) {{{
2132 struct SizeClassPair {
2137 MSInstanceMessageHook7(UIImage *, _UIAssetManager, imageNamed,scale,idiom,subtype,cachingOptions,sizeClassPair,attachCatalogImage, NSString *, name, CGFloat, scale, NSInteger, idiom, NSUInteger, subtype, NSUInteger, caching, SizeClassPair, size, BOOL, attach) {
2138 NSBundle *bundle([self bundle]);
2140 NSLog(@"WB:Debug: -[_UIAssetManager(%@/%@) imageNamed:@\"%@\" scale:%g idiom:%li subtype:%lu cachingOptions:%lu sizeClassPair:[%li %li] attachCatalogImage:%s]",
2141 [bundle bundleIdentifier], [self carFileName],
2142 name, scale, (long) idiom,
2143 (unsigned long) subtype,
2144 (unsigned long) caching,
2145 (long) size.first, (long) size.second,
2146 attach ? "YES" : "NO"
2148 return WBCacheUIImage(bundle,
2149 [=](){ return MSOldCall(name, scale, idiom, subtype, caching, size, attach); },
2150 name, [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']);
2154 // %hook GSFontCreateWithName() {{{
2155 MSHook(GSFontRef, GSFontCreateWithName, const char *name, GSFontSymbolicTraits traits, float size) {
2157 NSLog(@"WB:Debug: GSFontCreateWithName(\"%s\", %f)", name, size);
2158 if (NSString *font = [Info_ objectForKey:[NSString stringWithFormat:@"FontName-%s", name]])
2159 name = [font UTF8String];
2160 //if (NSString *scale = [Info_ objectForKey:[NSString stringWithFormat:@"FontScale-%s", name]])
2161 // size *= [scale floatValue];
2162 return _GSFontCreateWithName(name, traits, size);
2166 #define AudioToolbox "/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox"
2168 static bool GetFileNameForThisAction$(bool value, unsigned long a0, char *a1, unsigned long a2, bool &a3) {
2170 NSLog(@"WB:Debug:GetFileNameForThisAction(%lu, %s, %lu, %u) = %u", a0, value ? a1 : NULL, a2, a3, value);
2173 NSString *path = [NSString stringWithUTF8String:a1];
2174 if ([path hasPrefix:@"/System/Library/Audio/UISounds/"]) {
2175 NSString *file = [path substringFromIndex:31];
2176 for (NSString *theme in Themes_) {
2177 NSString *path([NSString stringWithFormat:@"%@/UISounds/%@", theme, file]);
2178 if ([Manager_ fileExistsAtPath:path]) {
2179 strcpy(a1, [path UTF8String]);
2188 MSHook(bool, _Z24GetFileNameForThisActionmPcRb, unsigned long a0, char *a1, bool &a3) {
2189 bool value(__Z24GetFileNameForThisActionmPcRb(a0, a1, a3));
2190 return GetFileNameForThisAction$(value, a0, a1, 0, a3);
2193 MSHook(bool, _Z24GetFileNameForThisActionmPcmRb, unsigned long a0, char *a1, unsigned long a2, bool &a3) {
2194 bool value(__Z24GetFileNameForThisActionmPcmRb(a0, a1, a2, a3));
2195 return GetFileNameForThisAction$(value, a0, a1, a2, a3);
2198 static void ChangeWallpaper(
2199 CFNotificationCenterRef center,
2203 CFDictionaryRef info
2206 NSLog(@"WB:Debug:ChangeWallpaper!");
2209 if (WallpaperFile_ != nil) {
2210 image = [[UIImage alloc] initWithContentsOfFile:WallpaperFile_];
2212 image = [image autorelease];
2215 if (WallpaperImage_ != nil)
2216 [WallpaperImage_ setImage:image];
2217 if (WallpaperPage_ != nil)
2218 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
2222 MSHook(NSArray *, CPBitmapCreateImagesFromPath, NSString *path, NSDictionary **names, void *arg2, void *arg3) {
2223 NSArray *images(_CPBitmapCreateImagesFromPath(path, names, arg2, arg3));
2224 if (images != NULL && *names != nil && CFGetTypeID((CFTypeRef) *names) == CFDictionaryGetTypeID()) {
2225 if (NSBundle *bundle = [NSBundle wb$bundleWithFile:path]) {
2226 NSMutableArray *copy([images mutableCopy]);
2230 NSString *file([path stringByResolvingSymlinksInPath]);
2231 NSString *prefix([[bundle bundlePath] stringByResolvingSymlinksInPath]);
2232 if ([file hasPrefix:prefix]) {
2233 NSUInteger length([prefix length]);
2234 if (length != [file length]) {
2235 NSEnumerator *enumerator([*names keyEnumerator]);
2236 while (NSString *name = [enumerator nextObject]) {
2237 NSString *png([name stringByAppendingString:@".png"]);
2238 if (NSString *themed = $pathForFile$inBundle$(png, bundle, true)) {
2239 NSUInteger index([[*names objectForKey:name] intValue]);
2240 UIImage *image($getImage$(themed));
2241 CGImageRef cg([image CGImage]);
2242 [copy replaceObjectAtIndex:index withObject:(id)cg];
2251 MSHook(void, BKSDisplayServicesSetSystemAppExitedImagePath, NSString *path) {
2252 if (NSString *themed = $getTheme$($useScale$([NSArray arrayWithObject:@"SystemAppExited.png"])))
2254 _BKSDisplayServicesSetSystemAppExitedImagePath(path);
2257 #define WBRename(name, sel, imp) \
2258 MSHookMessage($ ## name, @selector(sel), &$ ## name ## $ ## imp, &_ ## name ## $ ## imp)
2260 template <typename Type_>
2261 static void msset(Type_ &function, MSImageRef image, const char *name) {
2262 function = reinterpret_cast<Type_>(MSFindSymbol(image, name));
2265 #define WBHookSymbol(image, function) \
2266 msset(function, image, "_" #function)
2268 template <typename Type_>
2269 static void dlset(Type_ &function, const char *name) {
2270 function = reinterpret_cast<Type_>(dlsym(RTLD_DEFAULT, name));
2273 // %hook CGImageReadCreateWithFile() {{{
2274 MSHook(void *, CGImageReadCreateWithFile, NSString *path, int flag) {
2276 NSLog(@"WB:Debug: CGImageReadCreateWithFile(%@, %d)", path, flag);
2277 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2278 void *value(_CGImageReadCreateWithFile([path wb$themedPath], flag));
2283 MSHook(void *, CGImageSourceCreateWithFile, NSString *path, NSDictionary *options) {
2285 NSLog(@"WB:Debug: CGImageSourceCreateWithFile(%@, %@)", path, options);
2286 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2287 void *value(_CGImageSourceCreateWithFile([path wb$themedPath], options));
2292 MSHook(void *, CGImageSourceCreateWithURL, NSURL *url, NSDictionary *options) {
2294 NSLog(@"WB:Debug: CGImageSourceCreateWithURL(%@, %@)", url, options);
2295 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2296 if ([url isFileURL])
2297 url = [NSURL fileURLWithPath:[[url path] wb$themedPath]];
2298 void *value(_CGImageSourceCreateWithURL(url, options));
2304 static void NSString$drawAtPoint$withStyle$(NSString *self, SEL _cmd, CGPoint point, NSString *style) {
2305 WKSetCurrentGraphicsContext(UIGraphicsGetCurrentContext());
2306 if (style == nil || [style length] == 0)
2307 style = @"font-family: Helvetica; font-size: 12px";
2308 //NSLog(@"XXX:drawP(%@ | %@)", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "]);
2309 [[WBMarkup sharedMarkup] drawString:self atPoint:point withStyle:style];
2312 static void NSString$drawInRect$withStyle$(NSString *self, SEL _cmd, CGRect rect, NSString *style) {
2313 WKSetCurrentGraphicsContext(UIGraphicsGetCurrentContext());
2314 if (style == nil || [style length] == 0)
2315 style = @"font-family: Helvetica; font-size: 12px";
2316 //NSLog(@"XXX:drawR(%@ | %@)", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "]);
2317 return [[WBMarkup sharedMarkup] drawString:self inRect:rect withStyle:style];
2320 static CGSize NSString$sizeWithStyle$forWidth$(NSString *self, SEL _cmd, NSString *style, CGFloat width) {
2321 if (style == nil || [style length] == 0)
2322 style = @"font-family: Helvetica; font-size: 12px";
2323 CGSize size([[WBMarkup sharedMarkup] sizeOfString:self withStyle:style forWidth:width]);
2324 //NSLog(@"XXX:size(%@ | %@) = [%g %g]", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "], size.width, size.height);
2328 static void SBInitialize() {
2330 WBRename(SBApplication, pathForIcon, pathForIcon);
2331 WBRename(SBApplicationIcon, icon, icon);
2332 WBRename(SBApplicationIcon, generateIconImage:, generateIconImage$);
2335 WBRename(SBBookmarkIcon, icon, icon);
2336 WBRename(SBButtonBar, didMoveToSuperview, didMoveToSuperview);
2337 WBRename(SBCalendarIconContentsView, drawRect:, drawRect$);
2338 WBRename(SBIconBadge, initWithBadge:, initWithBadge$);
2339 WBRename(SBIconController, noteNumberOfIconListsChanged, noteNumberOfIconListsChanged);
2341 WBRename(SBWidgetApplicationIcon, icon, icon);
2343 WBRename(SBDockIconListView, setFrame:, setFrame$);
2344 MSHookMessage(object_getClass($SBDockIconListView), @selector(shouldShowNewDock), &$SBDockIconListView$shouldShowNewDock, &_SBDockIconListView$shouldShowNewDock);
2346 if (kCFCoreFoundationVersionNumber < 600 || SummerBoard_)
2347 WBRename(SBIconLabel, drawRect:, drawRect$);
2348 else if (kCFCoreFoundationVersionNumber < 700) {
2349 WBRename(SBIconLabel, buildLabelImage, buildLabelImage);
2351 WBRename(SBIconLabelImageParameters, hash, hash);
2352 WBRename($SBIconView, _labelImageParametersForIcon:location:, _labelImageParametersForIcon$location$);
2353 WBRename(SBIconView, _labelImageParameters, _labelImageParameters);
2354 WBRename($SBIconLabelImage, _drawLabelImageForParameters:, _drawLabelImageForParameters$);
2357 WBRename(SBIconLabel, initWithSize:label:, initWithSize$label$);
2358 WBRename(SBIconLabel, setInDock:, setInDock$);
2360 WBRename(SBIconList, didMoveToSuperview, didMoveToSuperview);
2361 WBRename(SBIconList, setFrame:, setFrame$);
2363 WBRename(SBIconModel, cacheImageForIcon:, cacheImageForIcon$);
2364 WBRename(SBIconModel, cacheImagesForIcon:, cacheImagesForIcon$);
2365 WBRename(SBIconModel, getCachedImagedForIcon:, getCachedImagedForIcon$);
2366 WBRename(SBIconModel, getCachedImagedForIcon:smallIcon:, getCachedImagedForIcon$smallIcon$);
2368 if (kCFCoreFoundationVersionNumber < 800) {
2369 WBRename(SBSearchView, initWithFrame:, initWithFrame$);
2370 WBRename(SBSearchTableViewCell, drawRect:, drawRect$);
2371 WBRename(SBSearchTableViewCell, initWithStyle:reuseIdentifier:, initWithStyle$reuseIdentifier$);
2374 //WBRename(SBImageCache, initWithName:forImageWidth:imageHeight:initialCapacity:, initWithName$forImageWidth$imageHeight$initialCapacity$);
2376 WBRename(SBAwayView, updateDesktopImage:, updateDesktopImage$);
2377 if (kCFCoreFoundationVersionNumber >= 700)
2378 WBRename(SBAwayView, _addSubview:positioned:relativeTo:, _addSubview$positioned$relativeTo$);
2380 WBRename(SBStatusBarContentsView, didMoveToSuperview, didMoveToSuperview);
2381 //WBRename(SBStatusBarContentsView, initWithStatusBar:mode:, initWithStatusBar$mode$);
2382 //WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:animation:, setStatusBarMode$orientation$duration$animation$);
2383 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:, setStatusBarMode$orientation$duration$fenceID$animation$);
2384 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:startTime:, setStatusBarMode$orientation$duration$fenceID$animation$startTime$);
2385 WBRename(SBStatusBarOperatorNameView, operatorNameStyle, operatorNameStyle);
2386 WBRename(SBStatusBarOperatorNameView, setOperatorName:fullSize:, setOperatorName$fullSize$);
2387 WBRename(SBStatusBarTimeView, drawRect:, drawRect$);
2390 English_ = [[NSDictionary alloc] initWithContentsOfFile:@"/System/Library/CoreServices/SpringBoard.app/English.lproj/LocalizedApplicationNames.strings"];
2392 if (kCFCoreFoundationVersionNumber >= 800) {
2393 WBRename(NSString, drawInRect:withAttributes:, drawInRect$withAttributes$);
2394 WBRename(NSString, boundingRectWithSize:options:attributes:context:, boundingRectWithSize$options$attributes$context$);
2398 /*MSHook(int, open, const char *path, int oflag, mode_t mode) {
2399 int fd(_open(path, oflag, mode));
2401 static bool no(false);
2405 if (strstr(path, "/icon") != NULL)
2406 MSHookProcess(-1, "");
2408 if (fd == -1 && errno == EFAULT)
2409 NSLog(@"open(%p, %#x, %#o) = %d\n", path, oflag, mode, fd);
2411 NSLog(@"open(\"%s\", %#x, %#o) = %d\n", path, oflag, mode, fd);
2418 $objc_setAssociatedObject = reinterpret_cast<void (*)(id, void *, id value, objc_AssociationPolicy)>(dlsym(RTLD_DEFAULT, "objc_setAssociatedObject"));
2419 $objc_getAssociatedObject = reinterpret_cast<id (*)(id, void *)>(dlsym(RTLD_DEFAULT, "objc_getAssociatedObject"));
2420 $objc_removeAssociatedObjects = reinterpret_cast<void (*)(id)>(dlsym(RTLD_DEFAULT, "objc_removeAssociatedObjects"));
2422 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2424 NSString *identifier([[NSBundle mainBundle] bundleIdentifier]);
2425 SpringBoard_ = [identifier isEqualToString:@"com.apple.springboard"];
2427 Manager_ = [[NSFileManager defaultManager] retain];
2428 Themes_ = [[NSMutableArray alloc] initWithCapacity:8];
2430 dlset(_GSFontGetUseLegacyFontMetrics, "GSFontGetUseLegacyFontMetrics");
2432 // Load Settings.plist {{{
2433 if (NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"/User/Library/Preferences/com.saurik.WinterBoard.plist"]]) {
2434 if (NSNumber *value = [settings objectForKey:@"SummerBoard"])
2435 SummerBoard_ = [value boolValue];
2437 SummerBoard_ = true;
2439 if (NSNumber *value = [settings objectForKey:@"Debug"])
2440 Debug_ = [value boolValue];
2441 if (NSNumber *value = [settings objectForKey:@"RecordUI"])
2442 UIDebug_ = [value boolValue];
2444 NSArray *themes([settings objectForKey:@"Themes"]);
2446 if (NSString *theme = [settings objectForKey:@"Theme"])
2447 themes = [NSArray arrayWithObject:[NSDictionary dictionaryWithObjectsAndKeys:
2449 [NSNumber numberWithBool:true], @"Active",
2453 for (NSDictionary *theme in themes) {
2454 NSNumber *active([theme objectForKey:@"Active"]);
2455 if (![active boolValue])
2458 NSString *name([theme objectForKey:@"Name"]);
2462 #define testForTheme(format...) \
2464 NSString *path = [NSString stringWithFormat:format]; \
2465 if ([Manager_ fileExistsAtPath:path]) { \
2466 [Themes_ addObject:path]; \
2471 testForTheme(@"/Library/Themes/%@.theme", name)
2472 testForTheme(@"/Library/Themes/%@", name)
2473 testForTheme(@"%@/Library/SummerBoard/Themes/%@", NSHomeDirectory(), name)
2478 // Merge Info.plist {{{
2479 Info_ = [[NSMutableDictionary dictionaryWithCapacity:16] retain];
2481 for (NSString *theme in Themes_)
2482 if (NSDictionary *info = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"%@/Info.plist", theme]])
2483 for (NSString *key in [info allKeys])
2484 if ([Info_ objectForKey:key] == nil)
2485 [Info_ setObject:[info objectForKey:key] forKey:key];
2489 if (MSImageRef image = MSGetImageByName("/System/Library/PrivateFrameworks/AppSupport.framework/AppSupport")) {
2490 NSArray *(*CPBitmapCreateImagesFromPath)(NSString *, NSDictionary **, void *, void *);
2491 msset(CPBitmapCreateImagesFromPath, image, "_CPBitmapCreateImagesFromPath");
2492 MSHookFunction(CPBitmapCreateImagesFromPath, MSHake(CPBitmapCreateImagesFromPath));
2496 if (MSImageRef image = MSGetImageByName(AudioToolbox)) {
2497 bool (*_Z24GetFileNameForThisActionmPcRb)(unsigned long, char *, bool &);
2498 msset(_Z24GetFileNameForThisActionmPcRb, image, "__Z24GetFileNameForThisActionmPcRb");
2499 MSHookFunction(_Z24GetFileNameForThisActionmPcRb, &$_Z24GetFileNameForThisActionmPcRb, &__Z24GetFileNameForThisActionmPcRb);
2501 bool (*_Z24GetFileNameForThisActionmPcmRb)(unsigned long, char *, unsigned long, bool &);
2502 msset(_Z24GetFileNameForThisActionmPcmRb, image, "__Z24GetFileNameForThisActionmPcmRb");
2503 MSHookFunction(_Z24GetFileNameForThisActionmPcmRb, &$_Z24GetFileNameForThisActionmPcmRb, &__Z24GetFileNameForThisActionmPcmRb);
2506 // BackBoardServices {{{
2507 if (MSImageRef image = MSGetImageByName("/System/Library/PrivateFrameworks/BackBoardServices.framework/BackBoardServices")) {
2508 void (*BKSDisplayServicesSetSystemAppExitedImagePath)(NSString *path);
2509 msset(BKSDisplayServicesSetSystemAppExitedImagePath, image, "_BKSDisplayServicesSetSystemAppExitedImagePath");
2510 MSHookFunction(BKSDisplayServicesSetSystemAppExitedImagePath, MSHake(BKSDisplayServicesSetSystemAppExitedImagePath));
2513 // GraphicsServices {{{
2515 MSHookFunction(&GSFontCreateWithName, &$GSFontCreateWithName, &_GSFontCreateWithName);
2519 MSImageRef imageio = MSGetImageByName("/System/Library/Frameworks/ImageIO.framework/ImageIO");
2520 if (imageio == NULL)
2521 imageio = MSGetImageByName("/System/Library/PrivateFrameworks/ImageIO.framework/ImageIO");
2522 if (MSImageRef image = imageio) {
2523 void *(*CGImageReadCreateWithFile)(NSString *, int) = NULL;
2524 if (kCFCoreFoundationVersionNumber > 700) // XXX: iOS 6.x
2525 CGImageReadCreateWithFile = NULL;
2527 msset(CGImageReadCreateWithFile, image, "_CGImageReadCreateWithFile");
2528 MSHookFunction(CGImageReadCreateWithFile, MSHake(CGImageReadCreateWithFile));
2531 if (CGImageReadCreateWithFile == NULL) {
2532 void *(*CGImageSourceCreateWithFile)(NSString *, NSDictionary *);
2533 msset(CGImageSourceCreateWithFile, image, "_CGImageSourceCreateWithFile");
2534 MSHookFunction(CGImageSourceCreateWithFile, MSHake(CGImageSourceCreateWithFile));
2536 void *(*CGImageSourceCreateWithURL)(NSURL *, NSDictionary *);
2537 msset(CGImageSourceCreateWithURL, image, "_CGImageSourceCreateWithURL");
2538 MSHookFunction(CGImageSourceCreateWithURL, MSHake(CGImageSourceCreateWithURL));
2544 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];
2545 Papered_ = $getTheme$(Wallpapers_) != nil;
2546 Docked_ = $getTheme$([NSArray arrayWithObjects:@"Dock.png", nil]) != nil;
2548 CFNotificationCenterAddObserver(
2549 CFNotificationCenterGetDarwinNotifyCenter(),
2550 NULL, &ChangeWallpaper, (CFStringRef) @"com.saurik.winterboard.lockbackground", NULL, CFNotificationSuspensionBehaviorCoalesce
2553 if ($getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"]) != nil) {
2554 NSBundle *MediaPlayer([NSBundle bundleWithPath:@"/System/Library/Frameworks/MediaPlayer.framework"]);
2555 if (MediaPlayer != nil)
2558 $MPMoviePlayerController = objc_getClass("MPMoviePlayerController");
2559 $MPVideoView = objc_getClass("MPVideoView");
2566 if (MSImageRef image = MSGetImageByName("/System/Library/Frameworks/UIKit.framework/UIKit")) {
2568 class_addMethod($NSString, @selector(drawAtPoint:withStyle:), (IMP) &NSString$drawAtPoint$withStyle$, "v40@0:8{CGPoint=dd}16@32");
2569 class_addMethod($NSString, @selector(drawInRect:withStyle:), (IMP) &NSString$drawInRect$withStyle$, "v56@0:8{CGRect={CGSize=dd}{CGSize=dd}}16@48");
2570 class_addMethod($NSString, @selector(sizeWithStyle:forWidth:), (IMP) &NSString$sizeWithStyle$forWidth$, "{CGSize=dd}32@0:8@16d24");
2572 class_addMethod($NSString, @selector(drawAtPoint:withStyle:), (IMP) &NSString$drawAtPoint$withStyle$, "v20@0:4{CGPoint=ff}8@16");
2573 class_addMethod($NSString, @selector(drawInRect:withStyle:), (IMP) &NSString$drawInRect$withStyle$, "v28@0:4{CGRect={CGSize=ff}{CGSize=ff}}8@24");
2574 class_addMethod($NSString, @selector(sizeWithStyle:forWidth:), (IMP) &NSString$sizeWithStyle$forWidth$, "{CGSize=ff}16@0:4@8f12");
2577 WBHookSymbol(image, _UIKitBundle);
2579 if (kCFCoreFoundationVersionNumber < 700)
2580 MSHookFunction(_UIImageWithName, MSHake(_UIImageWithName));
2582 WBHookSymbol(image, _UIApplicationImageWithName);
2583 MSHookFunction(_UIApplicationImageWithName, MSHake(_UIApplicationImageWithName));
2585 WBHookSymbol(image, _UIImageWithNameInDomain);
2586 MSHookFunction(_UIImageWithNameInDomain, MSHake(_UIImageWithNameInDomain));
2588 SEL includeEmoji(@selector(_legacy_drawAtPoint:forWidth:withFont:lineBreakMode:letterSpacing:includeEmoji:));
2589 if (![@"" respondsToSelector:includeEmoji])
2590 includeEmoji = @selector(drawAtPoint:forWidth:withFont:lineBreakMode:letterSpacing:includeEmoji:);
2591 MSHookMessage($NSString, includeEmoji, MSHake(NSString$drawAtPoint$forWidth$withFont$lineBreakMode$letterSpacing$includeEmoji$));
2593 SEL letterSpacing(@selector(_legacy_sizeWithFont:forWidth:lineBreakMode:letterSpacing:));
2594 if (![@"" respondsToSelector:letterSpacing])
2595 letterSpacing = @selector(sizeWithFont:forWidth:lineBreakMode:letterSpacing:);
2596 MSHookMessage($NSString, letterSpacing, MSHake(NSString$sizeWithFont$forWidth$lineBreakMode$letterSpacing$));
2598 SEL sizeWithFont(@selector(_legacy_sizeWithFont:));
2599 if (![@"" respondsToSelector:sizeWithFont])
2600 sizeWithFont = @selector(sizeWithFont:);
2601 MSHookMessage($NSString, sizeWithFont, MSHake(NSString$sizeWithFont$));
2605 //MSHookFunction(reinterpret_cast<int (*)(const char *, int, mode_t)>(&open), MSHake(open));