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] * 6)]);
303 for (NSString *file in files) {
304 NSString *base([file stringByDeletingPathExtension]);
305 NSString *extension([file pathExtension]);
307 #define WBScaleImage(scale) \
309 [scaled addObject:[NSString stringWithFormat:@"%@~%@.%@", base, idiom, extension]]; \
310 [scaled addObject:file]; \
312 [scaled addObject:[NSString stringWithFormat:@"%@@%ux~%@.%@", base, scale, idiom, extension]]; \
313 [scaled addObject:[NSString stringWithFormat:@"%@@%ux.%@", base, scale, extension]]; \
317 WBScaleImage(Scale_);
319 for (unsigned scale(3); scale >= 1; --scale)
322 } else if ([base hasSuffix: @"@2x"] || [base hasSuffix:@"@3x"]) {
325 // XXX: this actually can't be used, as the person loading the file doesn't realize that the @2x changed
326 /*NSString *rest([base substringWithRange:NSMakeRange(0, [base length] - 3)]);
327 [scaled addObject:[NSString stringWithFormat:@"%@~%@.%@", rest, idiom, extension]];
328 [scaled addObject:[rest stringByAppendingPathExtension:extension]];*/
330 // XXX: this code isn't really complete
332 [scaled addObject:file];
334 if ([base hasSuffix:[NSString stringWithFormat:@"~%@", idiom]])
335 [scaled addObject:[[base substringWithRange:NSMakeRange(0, [base length] - 1 - [idiom length])] stringByAppendingPathExtension:extension]];
342 static NSString *$getTheme$(NSArray *files, NSArray *themes = Themes_) {
343 // XXX: this is not reasonable; OMG
346 @synchronized (Themed_) {
347 if (NSString *path = [Themed_ objectForKey:key])
348 return reinterpret_cast<id>(path) == [NSNull null] ? nil : path;
352 NSLog(@"WB:Debug: %@", [files description]);
356 for (NSString *theme in Themes_)
357 for (NSString *file in files) {
358 path = [NSString stringWithFormat:@"%@/%@", theme, file];
359 if ([Manager_ fileExistsAtPath:path]) {
360 if ([[Manager_ destinationOfSymbolicLinkAtPath:path error:NULL] isEqualToString:@"/"])
369 @synchronized (Themed_) {
370 [Themed_ setObject:(path == nil ? [NSNull null] : reinterpret_cast<id>(path)) forKey:key];
376 // $pathForFile$inBundle$() {{{
377 static void $pathForFile$inBundle$(NSMutableArray *names, NSString *file, NSString *identifier, NSString *folder) {
378 if (identifier != nil)
379 [names addObject:[NSString stringWithFormat:@"Bundles/%@/%@", identifier, file]];
381 [names addObject:[NSString stringWithFormat:@"Folders/%@/%@", folder, file]];
382 NSString *base([folder stringByDeletingPathExtension]);
383 if ([base hasSuffix:@"~iphone"])
384 [names addObject:[NSString stringWithFormat:@"Folders/%@.%@/%@", [base substringWithRange:NSMakeRange(0, [base length] - 7)], [folder pathExtension], file]];
385 if ([base hasSuffix:@"~ipad"])
386 [names addObject:[NSString stringWithFormat:@"Folders/%@.%@/%@", [base substringWithRange:NSMakeRange(0, [base length] - 5)], [folder pathExtension], file]];
389 #define remapResourceName(oldname, newname) \
390 else if ([file isEqualToString:(oldname)]) \
391 [names addObject:oldname ".png"];
393 bool summer(SpringBoard_ && SummerBoard_);
395 if (identifier == nil);
396 else if ([identifier isEqualToString:@"com.apple.uikit.Artwork"])
397 $pathForFile$inBundle$(names, file, @"com.apple.UIKit", @"UIKit.framework");
398 else if ([identifier isEqualToString:@"com.apple.uikit.LegacyArtwork"])
399 $pathForFile$inBundle$(names, file, @"com.apple.UIKit", @"UIKit.framework");
400 else if ([identifier isEqualToString:@"com.apple.UIKit"])
401 [names addObject:[NSString stringWithFormat:@"UIImages/%@", file]];
402 else if ([identifier isEqualToString:@"com.apple.chatkit"])
403 $pathForFile$inBundle$(names, file, @"com.apple.MobileSMS", @"MobileSMS.app");
404 else if ([identifier isEqualToString:@"com.apple.calculator"])
405 [names addObject:[NSString stringWithFormat:@"Files/Applications/Calculator.app/%@", file]];
406 else if ([identifier isEqualToString:@"com.apple.Maps"] && [file isEqualToString:@"Icon-57@2x.png"])
407 $pathForFile$inBundle$(names, @"icon.png", identifier, folder);
409 remapResourceName(@"FSO_BG.png", @"StatusBar")
410 remapResourceName(Four_ ? @"SBDockBG-old.png" : @"SBDockBG.png", @"Dock")
411 remapResourceName(@"SBWeatherCelsius.png", @"Icons/Weather")
414 static NSString *$pathForFile$inBundle$(NSString *file, NSString *identifier, NSURL *url, bool use) {
415 NSMutableArray *names = [NSMutableArray arrayWithCapacity:8];
416 $pathForFile$inBundle$(names, file, identifier, [url lastPathComponent]);
417 [names addObject:[NSString stringWithFormat:@"Fallback/%@", file]];
418 if (NSString *path = $getTheme$($useScale$(names, use)))
423 // XXX: this cannot be merged due to WBBundle
424 static NSString *$pathForFile$inBundle$(NSString *file, NSBundle *bundle, bool use) {
425 return $pathForFile$inBundle$(file, [bundle bundleIdentifier], [bundle bundleURL], use);
428 static NSString *$pathForFile$inBundle$(NSString *file, CFBundleRef bundle, bool use) {
429 NSString *identifier((NSString *) CFBundleGetIdentifier(bundle));
430 NSURL *url([(NSURL *) CFBundleCopyBundleURL(bundle) autorelease]);
431 return $pathForFile$inBundle$(file, identifier, url, use);
435 static NSString *$pathForIcon$(SBApplication *self, NSString *suffix = @"") {
436 NSString *identifier = [self bundleIdentifier];
437 NSString *path = [self path];
438 NSString *folder = [path lastPathComponent];
439 NSString *dname = [self displayName];
441 NSString *didentifier;
442 if ([self respondsToSelector:@selector(displayIdentifier)])
443 didentifier = [self displayIdentifier];
448 NSLog(@"WB:Debug: [SBApplication(%@:%@:%@:%@) pathForIcon]", identifier, folder, dname, didentifier);
450 NSMutableArray *names = [NSMutableArray arrayWithCapacity:8];
452 /* XXX: I might need to keep this for backwards compatibility
453 if (identifier != nil)
454 [names addObject:[NSString stringWithFormat:@"Bundles/%@/icon.png", identifier]];
456 [names addObject:[NSString stringWithFormat:@"Folders/%@/icon.png", folder]]; */
458 #define testForIcon(Name) \
459 if (NSString *name = Name) \
460 [names addObject:[NSString stringWithFormat:@"Icons%@/%@.png", suffix, name]];
462 if (didentifier != nil && ![didentifier isEqualToString:identifier])
463 testForIcon(didentifier);
465 testForIcon(identifier);
468 if ([identifier isEqualToString:@"com.apple.MobileSMS"])
471 if (didentifier != nil) {
472 testForIcon([English_ objectForKey:didentifier]);
474 NSArray *parts = [didentifier componentsSeparatedByString:@"-"];
475 if ([parts count] != 1)
476 if (NSDictionary *english = [[[NSDictionary alloc] initWithContentsOfFile:[path stringByAppendingString:@"/English.lproj/UIRoleDisplayNames.strings"]] autorelease])
477 testForIcon([english objectForKey:[parts lastObject]]);
480 if (NSString *path = $getTheme$(names))
486 // -[NSBundle wb$bundleWithFile] {{{
487 @interface NSBundle (WinterBoard)
488 + (NSBundle *) wb$bundleWithFile:(NSString *)path;
491 @implementation NSBundle (WinterBoard)
493 + (NSBundle *) _wb$bundleWithFile:(NSString *)path {
494 path = [path stringByDeletingLastPathComponent];
495 if (path == nil || [path length] == 0 || [path isEqualToString:@"/"])
499 @synchronized (Bundles_) {
500 bundle = [Bundles_ objectForKey:path];
503 if (reinterpret_cast<id>(bundle) == [NSNull null])
505 else if (bundle == nil) {
506 if ([Manager_ fileExistsAtPath:[path stringByAppendingPathComponent:@"Info.plist"]])
507 bundle = [NSBundle bundleWithPath:path];
509 bundle = [NSBundle _wb$bundleWithFile:path];
511 NSLog(@"WB:Debug:PathBundle(%@, %@)", path, bundle);
513 @synchronized (Bundles_) {
514 [Bundles_ setObject:(bundle == nil ? [NSNull null] : reinterpret_cast<id>(bundle)) forKey:path];
521 + (NSBundle *) wb$bundleWithFile:(NSString *)path {
522 if ([path hasPrefix:@"/Library/Themes"])
524 return [self _wb$bundleWithFile:path];
529 // -[NSString wb$themedPath] {{{
530 @interface NSString (WinterBoard)
531 - (NSString *) wb$themedPath;
534 @implementation NSString (WinterBoard)
536 - (NSString *) wb$themedPath {
538 NSLog(@"WB:Debug:Bypass(\"%@\")", self);
540 if (NSBundle *bundle = [NSBundle wb$bundleWithFile:self]) {
541 NSString *file([self stringByResolvingSymlinksInPath]);
542 NSString *prefix([[bundle bundlePath] stringByResolvingSymlinksInPath]);
543 if ([file hasPrefix:prefix]) {
544 NSUInteger length([prefix length]);
545 if (length != [file length])
546 if (NSString *path = $pathForFile$inBundle$([file substringFromIndex:(length + 1)], bundle, false))
557 void WBLogRect(const char *tag, struct CGRect rect) {
558 NSLog(@"%s:{%f,%f+%f,%f}", tag, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
561 void WBLogHierarchy(UIView *view, unsigned index = 0, unsigned indent = 0) {
562 CGRect frame([view frame]);
563 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]);
565 for (UIView *child in [view subviews])
566 WBLogHierarchy(child, index++, indent + 1);
569 UIImage *$cacheForImage$(UIImage *image) {
570 CGColorSpaceRef space(CGColorSpaceCreateDeviceRGB());
571 CGRect rect = {CGPointMake(1, 1), [image size]};
572 CGSize size = {rect.size.width + 2, rect.size.height + 2};
574 CGContextRef context(CGBitmapContextCreate(NULL, size.width, size.height, 8, 4 * size.width, space, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst));
575 CGColorSpaceRelease(space);
577 CGContextDrawImage(context, rect, [image CGImage]);
578 CGImageRef ref(CGBitmapContextCreateImage(context));
579 CGContextRelease(context);
581 UIImage *cache([UIImage imageWithCGImage:ref]);
587 /*MSHook(id, SBImageCache$initWithName$forImageWidth$imageHeight$initialCapacity$, SBImageCache *self, SEL sel, NSString *name, unsigned width, unsigned height, unsigned capacity) {
588 //if ([name isEqualToString:@"icons"]) return nil;
589 return _SBImageCache$initWithName$forImageWidth$imageHeight$initialCapacity$(self, sel, name, width, height, capacity);
592 MSHook(void, SBIconModel$cacheImageForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
593 NSString *key([icon displayIdentifier]);
595 if (UIImage *image = [icon icon]) {
596 CGSize size = [image size];
597 if (size.width != 59 || size.height != 60) {
598 UIImage *cache($cacheForImage$(image));
599 [Cache_ setObject:cache forKey:key];
604 _SBIconModel$cacheImageForIcon$(self, sel, icon);
607 MSHook(void, SBIconModel$cacheImagesForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
608 /* XXX: do I /really/ have to do this? figure out how to cache the small icon! */
609 _SBIconModel$cacheImagesForIcon$(self, sel, icon);
611 NSString *key([icon displayIdentifier]);
613 if (UIImage *image = [icon icon]) {
614 CGSize size = [image size];
615 if (size.width != 59 || size.height != 60) {
616 UIImage *cache($cacheForImage$(image));
617 [Cache_ setObject:cache forKey:key];
623 MSHook(UIImage *, SBIconModel$getCachedImagedForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
624 NSString *key([icon displayIdentifier]);
625 if (UIImage *image = [Cache_ objectForKey:key])
628 return _SBIconModel$getCachedImagedForIcon$(self, sel, icon);
631 MSHook(UIImage *, SBIconModel$getCachedImagedForIcon$smallIcon$, SBIconModel *self, SEL sel, SBIcon *icon, BOOL small) {
633 return _SBIconModel$getCachedImagedForIcon$smallIcon$(self, sel, icon, small);
634 NSString *key([icon displayIdentifier]);
635 if (UIImage *image = [Cache_ objectForKey:key])
638 return _SBIconModel$getCachedImagedForIcon$smallIcon$(self, sel, icon, small);
641 MSHook(id, SBSearchView$initWithFrame$, id /* XXX: SBSearchView */ self, SEL sel, struct CGRect frame) {
642 if ((self = _SBSearchView$initWithFrame$(self, sel, frame)) != nil) {
643 [self setBackgroundColor:[UIColor clearColor]];
644 for (UIView *child in [self subviews])
645 [child setBackgroundColor:[UIColor clearColor]];
649 MSHook(id, SBSearchTableViewCell$initWithStyle$reuseIdentifier$, SBSearchTableViewCell *self, SEL sel, int style, NSString *reuse) {
650 if ((self = _SBSearchTableViewCell$initWithStyle$reuseIdentifier$(self, sel, style, reuse)) != nil) {
651 [self setBackgroundColor:[UIColor clearColor]];
655 MSHook(void, SBSearchTableViewCell$drawRect$, SBSearchTableViewCell *self, SEL sel, struct CGRect rect, BOOL selected) {
656 _SBSearchTableViewCell$drawRect$(self, sel, rect, selected);
657 float inset([self edgeInset]);
658 [[UIColor clearColor] set];
659 UIRectFill(CGRectMake(0, 0, inset, rect.size.height));
660 UIRectFill(CGRectMake(rect.size.width - inset, 0, inset, rect.size.height));
663 MSHook(UIImage *, SBApplicationIcon$icon, SBApplicationIcon *self, SEL sel) {
664 if (![Info_ wb$boolForKey:@"ComposeStoreIcons"])
665 if (NSString *path = $pathForIcon$([self application]))
666 return [UIImage imageWithContentsOfFile:path];
667 return _SBApplicationIcon$icon(self, sel);
670 MSHook(UIImage *, SBApplicationIcon$generateIconImage$, SBApplicationIcon *self, SEL sel, int type) {
672 if (![Info_ wb$boolForKey:@"ComposeStoreIcons"]) {
673 if (IsWild_ && false) // XXX: delete this code, it should not be supported
674 if (NSString *path72 = $pathForIcon$([self application], @"-72"))
675 return [UIImage imageWithContentsOfFile:path72];
676 if (NSString *path = $pathForIcon$([self application]))
677 if (UIImage *image = [UIImage imageWithContentsOfFile:path]) {
679 if ([$SBIcon respondsToSelector:@selector(defaultIconImageSize)])
680 width = [$SBIcon defaultIconImageSize].width;
683 return width == 59 ? image : [image _imageScaledToProportion:(width / 59.0) interpolationQuality:5];
686 return _SBApplicationIcon$generateIconImage$(self, sel, type);
689 MSHook(UIImage *, SBWidgetApplicationIcon$icon, SBWidgetApplicationIcon *self, SEL sel) {
691 NSLog(@"WB:Debug:Widget(%@:%@)", [self displayIdentifier], [self displayName]);
692 if (NSString *path = $getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Icons/%@.png", [self displayName]]]))
693 return [UIImage imageWithContentsOfFile:path];
694 return _SBWidgetApplicationIcon$icon(self, sel);
697 MSHook(UIImage *, SBBookmarkIcon$icon, SBBookmarkIcon *self, SEL sel) {
699 NSLog(@"WB:Debug:Bookmark(%@:%@)", [self displayIdentifier], [self displayName]);
700 if (NSString *path = $getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Icons/%@.png", [self displayName]]]))
701 return [UIImage imageWithContentsOfFile:path];
702 return _SBBookmarkIcon$icon(self, sel);
705 MSHook(NSString *, SBApplication$pathForIcon, SBApplication *self, SEL sel) {
706 if (NSString *path = $pathForIcon$(self))
708 return _SBApplication$pathForIcon(self, sel);
711 static UIImage *CachedImageAtPath(NSString *path) {
712 path = [path stringByResolvingSymlinksInPath];
713 UIImage *image = [Images_ objectForKey:path];
715 return reinterpret_cast<id>(image) == [NSNull null] ? nil : image;
716 image = [[UIImage alloc] initWithContentsOfFile:path cache:true];
718 image = [image autorelease];
719 [Images_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:path];
723 MSHook(UIImage *, _UIApplicationImageWithName, NSString *name) {
724 NSBundle *bundle = [NSBundle mainBundle];
726 NSLog(@"WB:Debug: _UIApplicationImageWithName(\"%@\", %@)", name, bundle);
727 if (NSString *path = $pathForFile$inBundle$(name, bundle, false))
728 return CachedImageAtPath(path);
729 return __UIApplicationImageWithName(name);
732 #define WBDelegate(delegate) \
733 - (NSMethodSignature*) methodSignatureForSelector:(SEL)sel { \
735 NSLog(@"WB:MS:%s:(%s)", class_getName([self class]), sel_getName(sel)); \
736 if (NSMethodSignature *sig = [delegate methodSignatureForSelector:sel]) \
738 NSLog(@"WB:Error: [%s methodSignatureForSelector:(%s)]", class_getName([self class]), sel_getName(sel)); \
742 - (void) forwardInvocation:(NSInvocation*)inv { \
743 SEL sel = [inv selector]; \
744 if ([delegate respondsToSelector:sel]) \
745 [inv invokeWithTarget:delegate]; \
747 NSLog(@"WB:Error: [%s forwardInvocation:(%s)]", class_getName([self class]), sel_getName(sel)); \
750 // %hook CFBundleCopyResourceURL {{{
751 MSHook(CFURLRef, CFBundleCopyResourceURL, CFBundleRef bundle, CFStringRef resourceName, CFStringRef resourceType, CFStringRef subDirName) {
752 NSString *file((NSString *) resourceName);
753 if (resourceType != NULL)
754 file = [NSString stringWithFormat:@"%@.%@", file, resourceType];
755 if (subDirName != NULL)
756 file = [NSString stringWithFormat:@"%@/%@", subDirName, resourceType];
758 if (![file hasSuffix:@".png"]) {
760 NSLog(@"WB:Debug: CFBundleCopyResourceURL(<%@>, \"%@\", \"%@\", \"%@\")", CFBundleGetIdentifier(bundle), resourceName, resourceType, subDirName);
761 if (NSString *path = $pathForFile$inBundle$(file, bundle, false))
762 return (CFURLRef) [[NSURL alloc] initFileURLWithPath:path];
765 return _CFBundleCopyResourceURL(bundle, resourceName, resourceType, subDirName);
769 static void $drawLabel$(NSString *label, CGRect rect, NSString *style, NSString *custom) {
770 bool ellipsis(false);
771 CGFloat max = rect.size.width - 11, width;
773 width = [(ellipsis ? [label stringByAppendingString:@"..."] : label) sizeWithStyle:style forWidth:320].width;
776 size_t length([label length]);
777 CGFloat spacing((width - max) / (length - 1));
779 if (spacing > 1.25) {
781 label = [label substringToIndex:(length - 1)];
785 style = [style stringByAppendingString:[NSString stringWithFormat:@"letter-spacing: -%f; ", spacing]];
789 label = [label stringByAppendingString:@"..."];
792 style = [style stringByAppendingString:custom];
794 CGSize size = [label sizeWithStyle:style forWidth:rect.size.width];
795 [label drawAtPoint:CGPointMake((rect.size.width - size.width) / 2 + rect.origin.x, rect.origin.y) withStyle:style];
798 static struct WBStringDrawingState {
799 WBStringDrawingState *next_;
803 } *stringDrawingState_;
805 extern "C" CGColorSpaceRef CGContextGetFillColorSpace(CGContextRef);
806 extern "C" void CGContextGetFillColor(CGContextRef, CGFloat[]);
808 static NSString *WBColorMarkup(size_t number, const CGFloat *components) {
830 return [NSString stringWithFormat:@"color: rgba(%g, %g, %g, %g)", r * 255, g * 255, b * 255, a];
833 static NSString *WBColorMarkup() {
834 CGContextRef context(UIGraphicsGetCurrentContext());
835 //NSLog(@"XXX:1:%p", context);
839 CGColorSpaceRef space(CGContextGetFillColorSpace(context));
840 //NSLog(@"XXX:2:%p", space);
844 size_t number(CGColorSpaceGetNumberOfComponents(space));
845 //NSLog(@"XXX:3:%u", number);
849 CGFloat components[number + 1];
850 CGContextGetFillColor(context, components);
851 return WBColorMarkup(number, components);
854 static NSString *WBColorMarkup(UIColor *uicolor) {
857 CGColorRef cgcolor([uicolor CGColor]);
861 CGColorSpaceRef space(CGColorGetColorSpace(cgcolor));
862 //NSLog(@"XXX:2:%p", space);
866 size_t number(CGColorGetNumberOfComponents(cgcolor));
867 //NSLog(@"XXX:3:%u", number);
871 const CGFloat *components(CGColorGetComponents(cgcolor));
872 return WBColorMarkup(number, components);
875 extern "C" NSString *NSStringFromCGPoint(CGPoint rect);
877 MSInstanceMessage6(CGSize, NSString, drawAtPoint,forWidth,withFont,lineBreakMode,letterSpacing,includeEmoji, CGPoint, point, CGFloat, width, UIFont *, font, UILineBreakMode, mode, CGFloat, spacing, BOOL, emoji) {
878 //NSLog(@"XXX: @\"%@\" %@ %g \"%@\" %u %g %u", self, NSStringFromCGPoint(point), width, font, mode, spacing, emoji);
880 WBStringDrawingState *state(stringDrawingState_);
882 return MSOldCall(point, width, font, mode, spacing, emoji);
884 if (state->count_ != 0 && --state->count_ == 0)
885 stringDrawingState_ = state->next_;
886 if (state->info_ == nil)
887 return MSOldCall(point, width, font, mode, spacing, emoji);
889 NSString *info([Info_ objectForKey:state->info_]);
891 return MSOldCall(point, width, font, mode, spacing, emoji);
893 NSString *base(state->base_ ?: @"");
894 NSString *extra([NSString stringWithFormat:@"letter-spacing: %gpx", spacing]);
895 [self drawAtPoint:point withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info]];
899 extern "C" NSString *NSStringFromCGRect(CGRect rect);
901 MSInstanceMessageHook7(CGSize, NSString, _drawInRect,withFont,lineBreakMode,alignment,lineSpacing,includeEmoji,truncationRect, CGRect, rect, UIFont *, font, UILineBreakMode, mode, UITextAlignment, alignment, float, spacing, BOOL, emoji, CGRect, truncation) {
902 //NSLog(@"XXX: @\"%@\" %@ \"%@\" %u %u %g %u %@", self, NSStringFromCGRect(rect), font, mode, alignment, spacing, emoji, NSStringFromCGRect(truncation));
904 WBStringDrawingState *state(stringDrawingState_);
906 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
908 if (state->count_ != 0 && --state->count_ == 0)
909 stringDrawingState_ = state->next_;
910 if (state->info_ == nil)
911 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
913 NSString *info([Info_ objectForKey:state->info_]);
915 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
920 case UITextAlignmentLeft:
923 case UITextAlignmentCenter:
924 textAlign = @"center";
926 case UITextAlignmentRight:
927 textAlign = @"right";
931 NSString *base(state->base_ ?: @"");
932 NSString *extra([NSString stringWithFormat:@"text-align: %@", textAlign]);
935 $drawLabel$(self, rect, [NSString stringWithFormat:@"%@;%@;%@", [font markupDescription], WBColorMarkup(), base], info);
937 [self drawInRect:rect withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info]];
942 MSInstanceMessage2(void, NSString, drawInRect,withAttributes, CGRect, rect, NSDictionary *, attributes) {
943 //NSLog(@"XXX: *\"%@\" %@", self, attributes);
945 WBStringDrawingState *state(stringDrawingState_);
947 return MSOldCall(rect, attributes);
949 if (state->count_ != 0 && --state->count_ == 0)
950 stringDrawingState_ = state->next_;
951 if (state->info_ == nil)
952 return MSOldCall(rect, attributes);
954 NSString *info([Info_ objectForKey:state->info_]);
956 return MSOldCall(rect, attributes);
958 NSString *base(state->base_ ?: @"");
960 UIFont *font([attributes objectForKey:@"NSFont"]);
961 UIColor *color([attributes objectForKey:@"NSColor"]);
963 [self drawInRect:rect withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], WBColorMarkup(color), base, info]];
966 extern "C" NSString *NSStringFromCGSize(CGSize size);
968 MSInstanceMessage4(CGRect, NSString, boundingRectWithSize,options,attributes,context, CGSize, size, NSInteger, options, NSDictionary *, attributes, id, context) {
969 //NSLog(@"XXX: $\"%@\" %@ 0x%x %@ %@", self, NSStringFromCGSize(size), unsigned(options), attributes, context);
971 WBStringDrawingState *state(stringDrawingState_);
973 return MSOldCall(size, options, attributes, context);
975 if (state->count_ != 0 && --state->count_ == 0)
976 stringDrawingState_ = state->next_;
977 if (state->info_ == nil)
978 return MSOldCall(size, options, attributes, context);
980 NSString *info([Info_ objectForKey:state->info_]);
982 return MSOldCall(size, options, attributes, context);
984 NSString *base(state->base_ ?: @"");
986 UIFont *font([attributes objectForKey:@"NSFont"]);
987 UIColor *color([attributes objectForKey:@"NSColor"]);
989 return (CGRect) {{0, 0}, [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], WBColorMarkup(color), base, info] forWidth:size.width]};
992 MSInstanceMessage4(CGSize, NSString, sizeWithFont,forWidth,lineBreakMode,letterSpacing, UIFont *, font, CGFloat, width, UILineBreakMode, mode, CGFloat, spacing) {
993 //NSLog(@"XXX: #\"%@\" \"%@\" %g %u %g", self, font, width, mode, spacing);
995 WBStringDrawingState *state(stringDrawingState_);
997 return MSOldCall(font, width, mode, spacing);
999 if (state->count_ != 0 && --state->count_ == 0)
1000 stringDrawingState_ = state->next_;
1001 if (state->info_ == nil)
1002 return MSOldCall(font, width, mode, spacing);
1004 NSString *info([Info_ objectForKey:state->info_]);
1006 return MSOldCall(font, width, mode, spacing);
1008 NSString *base(state->base_ ?: @"");
1009 NSString *extra([NSString stringWithFormat:@"letter-spacing: %gpx", spacing]);
1010 return [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info] forWidth:width];
1013 MSInstanceMessage1(CGSize, NSString, sizeWithFont, UIFont *, font) {
1014 //NSLog(@"XXX: ?\"%@\"", self);
1016 WBStringDrawingState *state(stringDrawingState_);
1018 return MSOldCall(font);
1020 if (state->count_ != 0 && --state->count_ == 0)
1021 stringDrawingState_ = state->next_;
1022 if (state->info_ == nil)
1023 return MSOldCall(font);
1025 NSString *info([Info_ objectForKey:state->info_]);
1027 return MSOldCall(font);
1029 NSString *base(state->base_ ?: @"");
1030 return [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), base, info] forWidth:65535];
1033 MSClassMessageHook2(id, SBIconBadgeView, checkoutAccessoryImagesForIcon,location, id, icon, int, location) {
1034 WBStringDrawingState badgeState = {NULL, 0, @""
1037 stringDrawingState_ = &badgeState;
1039 id images(MSOldCall(icon, location));
1041 stringDrawingState_ = NULL;
1045 MSClassMessageHook2(UIImage *, SBIconAccessoryImage, checkoutAccessoryImageForIcon,location, id, icon, int, location) {
1046 if ([self _imageClassForIcon:icon location:location] != $SBIconBadgeImage)
1047 return MSOldCall(icon, location);
1049 WBStringDrawingState badgeState = {NULL, 0, @""
1052 stringDrawingState_ = &badgeState;
1054 UIImage *image(MSOldCall(icon, location));
1056 stringDrawingState_ = NULL;
1060 MSInstanceMessageHook1(UIImage *, SBIconBadgeFactory, checkoutBadgeImageForText, NSString *, text) {
1061 WBStringDrawingState badgeState = {NULL, 0, @""
1064 stringDrawingState_ = &badgeState;
1066 UIImage *image(MSOldCall(text));
1068 stringDrawingState_ = NULL;
1072 MSInstanceMessageHook1(UIImage *, SBCalendarApplicationIcon, generateIconImage, int, type) {
1073 WBStringDrawingState dayState = {NULL, 2, @""
1074 // XXX: this is only correct on an iPod dock
1075 "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px;"
1076 , @"CalendarIconDayStyle"};
1078 WBStringDrawingState skipState = {&dayState,
1079 unsigned(kCFCoreFoundationVersionNumber > 800 ? 16 : 7)
1082 WBStringDrawingState dateState = {&skipState, 2, @""
1083 , @"CalendarIconDateStyle"};
1085 stringDrawingState_ = &dateState;
1087 UIImage *image(MSOldCall(type));
1089 stringDrawingState_ = NULL;
1093 MSInstanceMessageHook1(UIImage *, UIStatusBarTimeItemView, contentsImageForStyle, int, style) {
1094 WBStringDrawingState timeState = {NULL, 0, @""
1097 stringDrawingState_ = &timeState;
1099 UIImage *image(MSOldCall(style));
1101 stringDrawingState_ = NULL;
1105 MSHook(void, SBCalendarIconContentsView$drawRect$, SBCalendarIconContentsView *self, SEL sel, CGRect rect) {
1106 NSBundle *bundle([NSBundle mainBundle]);
1108 CFLocaleRef locale(CFLocaleCopyCurrent());
1109 CFDateFormatterRef formatter(CFDateFormatterCreate(NULL, locale, kCFDateFormatterNoStyle, kCFDateFormatterNoStyle));
1112 CFDateRef now(CFDateCreate(NULL, CFAbsoluteTimeGetCurrent()));
1114 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NUMBER_FORMAT" value:@"d" table:@"SpringBoard"]);
1115 CFStringRef date(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
1116 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NAME_FORMAT" value:@"cccc" table:@"SpringBoard"]);
1117 CFStringRef day(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
1121 CFRelease(formatter);
1123 NSString *datestyle([@""
1124 "font-family: Helvetica; "
1125 "font-weight: bold; "
1128 "" stringByAppendingString:(IsWild_
1129 ? @"font-size: 54px; "
1130 : @"font-size: 39px; "
1133 NSString *daystyle([@""
1134 "font-family: Helvetica; "
1135 "font-weight: bold; "
1137 "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px; "
1138 "" stringByAppendingString:(IsWild_
1139 ? @"font-size: 11px; "
1140 : @"font-size: 9px; "
1143 if (NSString *style = [Info_ objectForKey:@"CalendarIconDateStyle"])
1144 datestyle = [datestyle stringByAppendingString:style];
1145 if (NSString *style = [Info_ objectForKey:@"CalendarIconDayStyle"])
1146 daystyle = [daystyle stringByAppendingString:style];
1148 CGFloat width([self bounds].size.width);
1150 CGSize datesize = [(NSString *)date sizeWithStyle:datestyle forWidth:(width + leeway)];
1151 CGSize daysize = [(NSString *)day sizeWithStyle:daystyle forWidth:(width + leeway)];
1153 unsigned base0(IsWild_ ? 89 : 70);
1154 if ($GSFontGetUseLegacyFontMetrics())
1156 unsigned base1(IsWild_ ? 18 : 16);
1163 [(NSString *)date drawAtPoint:CGPointMake(
1164 (width + 1 - datesize.width) / 2, (base0 - datesize.height) / 2
1165 ) withStyle:datestyle];
1167 [(NSString *)day drawAtPoint:CGPointMake(
1168 (width + 1 - daysize.width) / 2, (base1 - daysize.height) / 2
1169 ) withStyle:daystyle];
1175 // %hook -[{NavigationBar,Toolbar} setBarStyle:] {{{
1176 void $setBarStyle$_(NSString *name, int &style) {
1178 NSLog(@"WB:Debug:%@Style:%d", name, style);
1179 NSNumber *number = nil;
1181 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style-%d", name, style]];
1183 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style", name]];
1184 if (number != nil) {
1185 style = [number intValue];
1187 NSLog(@"WB:Debug:%@Style=%d", name, style);
1191 MSInstanceMessageHook1(void, UIToolbar, setBarStyle, int, style) {
1192 $setBarStyle$_(@"Toolbar", style);
1193 return MSOldCall(style);
1196 MSInstanceMessageHook1(void, UINavigationBar, setBarStyle, int, style) {
1197 $setBarStyle$_(@"NavigationBar", style);
1198 return MSOldCall(style);
1202 MSHook(void, SBButtonBar$didMoveToSuperview, UIView *self, SEL sel) {
1203 [[self superview] setBackgroundColor:[UIColor clearColor]];
1204 _SBButtonBar$didMoveToSuperview(self, sel);
1207 MSHook(void, SBStatusBarContentsView$didMoveToSuperview, UIView *self, SEL sel) {
1208 [[self superview] setBackgroundColor:[UIColor clearColor]];
1209 _SBStatusBarContentsView$didMoveToSuperview(self, sel);
1212 static NSArray *Wallpapers_;
1213 static bool Papered_;
1214 static bool Docked_;
1215 static bool SMSBackgrounded_;
1216 static NSString *WallpaperFile_;
1217 static UIImageView *WallpaperImage_;
1218 static UIWebDocumentView *WallpaperPage_;
1219 static NSURL *WallpaperURL_;
1221 #define _release(object) \
1222 do if (object != nil) { \
1227 static UIImage *$getImage$(NSString *path) {
1228 UIImage *image([UIImage imageWithContentsOfFile:path]);
1230 unsigned scale($getScale$(path));
1231 if (scale != 1 && [image respondsToSelector:@selector(setScale)])
1232 [image setScale:scale];
1237 template <typename Original_, typename Modified_>
1238 _finline UIImage *WBCacheImage(const Modified_ &modified, const Original_ &original, NSString *key) {
1239 UIImage *image([Images_ objectForKey:key]);
1241 return reinterpret_cast<id>(image) == [NSNull null] ? original() : image;
1242 if (NSString *path = modified())
1243 image = $getImage$(path);
1244 [Images_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:key];
1245 return image == nil ? original() : image;
1248 static UIImage *$getDefaultDesktopImage$() {
1249 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"LockBackground.png", @"LockBackground.jpg", nil])))
1250 return $getImage$(path);
1254 MSClassMessageHook0(UIImage *, UIImage, defaultDesktopImage) {
1255 return $getDefaultDesktopImage$() ?: MSOldCall();
1258 MSInstanceMessageHook0(UIImage *, SBSlidingAlertDisplay, _defaultDesktopImage) {
1259 return $getDefaultDesktopImage$() ?: MSOldCall();
1262 MSInstanceMessageHook0(void, SBWallpaperView, resetCurrentImageToWallpaper) {
1263 for (UIView *parent([self superview]); parent != nil; parent = [parent superview])
1264 if ([parent isKindOfClass:$SBSlidingAlertDisplay]) {
1265 if (UIImage *image = $getDefaultDesktopImage$()) {
1266 [self setImage:image];
1276 // %hook -[SBUIController init] {{{
1277 MSInstanceMessageHook0(id, SBUIController, init) {
1282 NSString *paper($getTheme$(Wallpapers_));
1284 paper = [paper stringByDeletingLastPathComponent];
1287 NSLog(@"WB:Debug:Info = %@", [Info_ description]);
1290 UIImageView *&_wallpaperView(MSHookIvar<UIImageView *>(self, "_wallpaperView"));
1291 if (&_wallpaperView != NULL) {
1292 [_wallpaperView removeFromSuperview];
1293 [_wallpaperView release];
1294 _wallpaperView = nil;
1298 UIView *&_contentLayer(MSHookIvar<UIView *>(self, "_contentLayer"));
1299 UIView *&_contentView(MSHookIvar<UIView *>(self, "_contentView"));
1302 if (&_contentLayer != NULL)
1303 player = &_contentLayer;
1304 else if (&_contentView != NULL)
1305 player = &_contentView;
1308 UIView *layer(player == NULL ? nil : *player);
1310 UIWindow *window([[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]);
1311 UIView *content([[[UIView alloc] initWithFrame:[window frame]] autorelease]);
1312 [window setContentView:content];
1314 UIWindow *&_window(MSHookIvar<UIWindow *>(self, "_window"));
1315 [window setBackgroundColor:[_window backgroundColor]];
1316 [_window setBackgroundColor:[UIColor clearColor]];
1318 [window setLevel:-1000];
1319 [window setHidden:NO];
1321 /*if (player != NULL)
1322 *player = content;*/
1324 [content setBackgroundColor:[layer backgroundColor]];
1325 [layer setBackgroundColor:[UIColor clearColor]];
1328 if (!SummerBoard_ || !IsWild_)
1331 CGRect bounds([content bounds]);
1332 bounds.origin.y = -30;
1333 indirect = [[[UIView alloc] initWithFrame:bounds] autorelease];
1334 [content addSubview:indirect];
1335 [indirect zoomToScale:2.4];
1338 _release(WallpaperFile_);
1339 _release(WallpaperImage_);
1340 _release(WallpaperPage_);
1341 _release(WallpaperURL_);
1344 NSArray *themes([NSArray arrayWithObject:paper]);
1346 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"], themes)) {
1350 static AVController *controller_(nil);
1351 if (controller_ == nil) {
1352 AVQueue *queue([AVQueue avQueue]);
1353 controller_ = [[AVController avControllerWithQueue:queue error:&error] retain];
1356 AVQueue *queue([controller_ queue]);
1358 UIView *video([[[UIView alloc] initWithFrame:[indirect bounds]] autorelease]);
1359 [controller_ setLayer:[video _layer]];
1361 AVItem *item([[[AVItem alloc] initWithPath:path error:&error] autorelease]);
1362 [queue appendItem:item error:&error];
1364 [controller_ play:&error];
1365 #elif UseMPMoviePlayerController
1366 NSURL *url([NSURL fileURLWithPath:path]);
1367 MPMoviePlayerController *controller = [[$MPMoviePlayerController alloc] initWithContentURL:url];
1368 controller.movieControlMode = MPMovieControlModeHidden;
1371 MPVideoView *video = [[[$MPVideoView alloc] initWithFrame:[indirect bounds]] autorelease];
1372 [video setMovieWithPath:path];
1373 [video setRepeatMode:1];
1374 [video setRepeatGap:-1];
1375 [video playFromBeginning];;
1378 [indirect addSubview:video];
1381 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"Wallpaper.png", @"Wallpaper.jpg", nil]), themes)) {
1382 if (UIImage *image = $getImage$(path)) {
1383 WallpaperFile_ = [path retain];
1384 WallpaperImage_ = [[UIImageView alloc] initWithImage:image];
1385 if (NSNumber *number = [Info_ objectForKey:@"WallpaperAlpha"])
1386 [WallpaperImage_ setAlpha:[number floatValue]];
1387 [indirect addSubview:WallpaperImage_];
1391 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.html"], themes)) {
1392 CGRect bounds = [indirect bounds];
1394 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1395 [view setAutoresizes:true];
1397 WallpaperPage_ = [view retain];
1398 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
1400 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1402 [view setBackgroundColor:[UIColor clearColor]];
1403 if ([view respondsToSelector:@selector(setDrawsBackground:)])
1404 [view setDrawsBackground:NO];
1405 [[view webView] setDrawsBackground:NO];
1407 [indirect addSubview:view];
1411 for (size_t i(0), e([Themes_ count]); i != e; ++i) {
1412 NSString *theme = [Themes_ objectAtIndex:(e - i - 1)];
1413 NSString *html = [theme stringByAppendingPathComponent:@"Widget.html"];
1414 if ([Manager_ fileExistsAtPath:html]) {
1415 CGRect bounds = [indirect bounds];
1417 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1418 [view setAutoresizes:true];
1420 NSURL *url = [NSURL fileURLWithPath:html];
1421 [view loadRequest:[NSURLRequest requestWithURL:url]];
1423 [view setBackgroundColor:[UIColor clearColor]];
1424 if ([view respondsToSelector:@selector(setDrawsBackground:)])
1425 [view setDrawsBackground:NO];
1426 [[view webView] setDrawsBackground:NO];
1428 [indirect addSubview:view];
1436 MSHook(void, SBAwayView$updateDesktopImage$, SBAwayView *self, SEL sel, UIImage *image) {
1437 NSString *path = $getTheme$([NSArray arrayWithObject:@"LockBackground.html"]);
1438 UIView *&_backgroundView(MSHookIvar<UIView *>(self, "_backgroundView"));
1440 if (path != nil && _backgroundView != nil)
1443 _SBAwayView$updateDesktopImage$(self, sel, image);
1446 CGRect bounds = [self bounds];
1448 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1449 [view setAutoresizes:true];
1451 if (WallpaperPage_ != nil)
1452 [WallpaperPage_ release];
1453 WallpaperPage_ = [view retain];
1455 if (WallpaperURL_ != nil)
1456 [WallpaperURL_ release];
1457 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
1459 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1461 [[view webView] setDrawsBackground:false];
1462 [view setBackgroundColor:[UIColor clearColor]];
1464 [self insertSubview:view aboveSubview:_backgroundView];
1466 if ($objc_setAssociatedObject != NULL)
1467 $objc_setAssociatedObject(self, @selector(wb$widgetView), view, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1471 MSHook(void, SBAwayView$_addSubview$positioned$relativeTo$, SBAwayView *self, SEL sel, UIView *view, int positioned, UIView *relative) {
1472 UIView *&_backgroundView(MSHookIvar<UIView *>(self, "_backgroundView"));
1473 UIView *&_chargingView(MSHookIvar<UIView *>(self, "_chargingView"));
1474 if (&_chargingView != NULL)
1475 if (positioned == -2 && (relative == _backgroundView && _chargingView == nil || relative == _chargingView))
1476 if ($objc_getAssociatedObject != NULL)
1477 if (UIView *widget = $objc_getAssociatedObject(self, @selector(wb$widgetView)))
1479 return _SBAwayView$_addSubview$positioned$relativeTo$(self, sel, view, positioned, relative);
1482 /*extern "C" CGColorRef CGGStateGetSystemColor(void *);
1483 extern "C" CGColorRef CGGStateGetFillColor(void *);
1484 extern "C" CGColorRef CGGStateGetStrokeColor(void *);
1485 extern "C" NSString *UIStyleStringFromColor(CGColorRef);*/
1487 /* WBTimeLabel {{{ */
1488 @interface WBTimeLabel : NSProxy {
1490 _transient SBStatusBarTimeView *view_;
1493 - (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view;
1497 @implementation WBTimeLabel
1504 - (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view {
1505 time_ = [time retain];
1510 - (NSString *) description {
1516 - (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(UILineBreakMode)mode {
1517 if (NSString *custom = [Info_ objectForKey:@"TimeStyle"]) {
1518 BOOL &_mode(MSHookIvar<BOOL>(view_, "_mode"));;
1520 [time_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1521 "font-family: Helvetica; "
1522 "font-weight: bold; "
1525 "%@", _mode ? @"white" : @"black", custom]];
1530 return [time_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1535 /* WBBadgeLabel {{{ */
1536 @interface WBBadgeLabel : NSProxy {
1540 - (id) initWithBadge:(NSString *)badge;
1541 - (NSString *) description;
1545 @implementation WBBadgeLabel
1552 - (id) initWithBadge:(NSString *)badge {
1553 badge_ = [badge retain];
1557 - (NSString *) description {
1558 return [badge_ description];
1563 - (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(UILineBreakMode)mode {
1564 if (NSString *custom = [Info_ objectForKey:@"BadgeStyle"]) {
1565 [badge_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1566 "font-family: Helvetica; "
1567 "font-weight: bold; "
1575 return [badge_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1582 MSInstanceMessageHook1(void, SBIcon, setIconImageAlpha, CGFloat, alpha) {
1583 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1584 alpha = [number floatValue];
1585 return MSOldCall(alpha);
1588 MSInstanceMessageHook1(void, SBIcon, setIconLabelAlpha, CGFloat, alpha) {
1589 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1590 alpha = [number floatValue];
1591 return MSOldCall(alpha);
1594 MSInstanceMessageHook0(id, SBIcon, initWithDefaultSize) {
1595 if ((self = MSOldCall()) != nil) {
1596 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"]) {
1597 // XXX: note: this is overridden above, which is silly
1598 float alpha([number floatValue]);
1599 if ([self respondsToSelector:@selector(setIconImageAlpha:)])
1600 [self setIconImageAlpha:alpha];
1601 if ([self respondsToSelector:@selector(setIconLabelAlpha:)])
1602 [self setIconLabelAlpha:alpha];
1603 if ([self respondsToSelector:@selector(setAlpha:)])
1604 [self setAlpha:alpha];
1609 MSInstanceMessageHook1(void, SBIcon, setAlpha, CGFloat, alpha) {
1610 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1611 alpha = [number floatValue];
1612 return MSOldCall(alpha);
1616 MSHook(id, SBIconBadge$initWithBadge$, SBIconBadge *self, SEL sel, NSString *badge) {
1617 if ((self = _SBIconBadge$initWithBadge$(self, sel, badge)) != nil) {
1618 id &_badge(MSHookIvar<id>(self, "_badge"));
1620 if (id label = [[WBBadgeLabel alloc] initWithBadge:[_badge autorelease]])
1625 void SBStatusBarController$setStatusBarMode(int &mode) {
1627 NSLog(@"WB:Debug:setStatusBarMode:%d", mode);
1628 if (mode < 100) // 104:hidden 105:glowing
1629 if (NSNumber *number = [Info_ objectForKey:@"StatusBarMode"])
1630 mode = [number intValue];
1633 /*MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, double duration, int animation) {
1634 NSLog(@"mode:%d orientation:%d duration:%f animation:%d", mode, orientation, duration, animation);
1635 SBStatusBarController$setStatusBarMode(mode);
1636 return _SBStatusBarController$setStatusBarMode$orientation$duration$animation$(self, sel, mode, orientation, duration, animation);
1639 MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, float duration, int fenceID, int animation) {
1640 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d", mode, orientation, duration, fenceID, animation);
1641 SBStatusBarController$setStatusBarMode(mode);
1642 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$(self, sel, mode, orientation, duration, fenceID, animation);
1645 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) {
1646 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d startTime:%f", mode, orientation, duration, fenceID, animation, startTime);
1647 SBStatusBarController$setStatusBarMode(mode);
1648 //NSLog(@"mode=%u", mode);
1649 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$startTime$(self, sel, mode, orientation, duration, fenceID, animation, startTime);
1652 /*MSHook(id, SBStatusBarContentsView$initWithStatusBar$mode$, SBStatusBarContentsView *self, SEL sel, id bar, int mode) {
1653 if (NSNumber *number = [Info_ objectForKey:@"StatusBarContentsMode"])
1654 mode = [number intValue];
1655 return _SBStatusBarContentsView$initWithStatusBar$mode$(self, sel, bar, mode);
1658 MSHook(NSString *, SBStatusBarOperatorNameView$operatorNameStyle, SBStatusBarOperatorNameView *self, SEL sel) {
1659 NSString *style(_SBStatusBarOperatorNameView$operatorNameStyle(self, sel));
1661 NSLog(@"operatorNameStyle= %@", style);
1662 if (NSString *custom = [Info_ objectForKey:@"OperatorNameStyle"])
1663 style = [NSString stringWithFormat:@"%@; %@", style, custom];
1667 MSHook(void, SBStatusBarOperatorNameView$setOperatorName$fullSize$, SBStatusBarOperatorNameView *self, SEL sel, NSString *name, BOOL full) {
1669 NSLog(@"setOperatorName:\"%@\" fullSize:%u", name, full);
1670 return _SBStatusBarOperatorNameView$setOperatorName$fullSize$(self, sel, name, NO);
1673 // XXX: replace this with [SBStatusBarTimeView tile]
1674 MSHook(void, SBStatusBarTimeView$drawRect$, SBStatusBarTimeView *self, SEL sel, CGRect rect) {
1675 id &_time(MSHookIvar<id>(self, "_time"));
1676 if (_time != nil && [_time class] != [WBTimeLabel class])
1677 object_setInstanceVariable(self, "_time", reinterpret_cast<void *>([[WBTimeLabel alloc] initWithTime:[_time autorelease] view:self]));
1678 return _SBStatusBarTimeView$drawRect$(self, sel, rect);
1681 @interface UIView (WinterBoard)
1682 - (bool) wb$isWBImageView;
1683 - (void) wb$logHierarchy;
1684 - (void) wb$setBackgroundColor:(UIColor *)color;
1687 @implementation UIView (WinterBoard)
1689 - (bool) wb$isWBImageView {
1693 - (void) wb$logHierarchy {
1694 WBLogHierarchy(self);
1697 - (void) wb$setBackgroundColor:(UIColor *)color {
1698 [self setBackgroundColor:color];
1699 for (UIView *child in [self subviews])
1700 [child wb$setBackgroundColor:color];
1705 @interface WBImageView : UIImageView {
1708 - (bool) wb$isWBImageView;
1709 - (void) wb$updateFrame;
1712 @implementation WBImageView
1714 - (bool) wb$isWBImageView {
1718 - (void) wb$updateFrame {
1719 CGRect frame([self frame]);
1722 for (UIView *view(self); ; ) {
1723 view = [view superview];
1726 frame.origin.y -= [view frame].origin.y;
1729 [self setFrame:frame];
1734 static void SBIconList$updateFrames$(SBIconList *self) {
1735 NSArray *subviews([self subviews]);
1736 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1737 if (view != nil && [view wb$isWBImageView])
1738 [view wb$updateFrame];
1741 MSHook(void, SBIconList$didMoveToSuperview, SBIconList *self, SEL sel) {
1742 SBIconList$updateFrames$(self);
1743 _SBIconList$didMoveToSuperview(self, sel);
1746 MSHook(void, SBIconList$setFrame$, SBIconList *self, SEL sel, CGRect frame) {
1747 SBIconList$updateFrames$(self);
1748 _SBIconList$setFrame$(self, sel, frame);
1751 static void $addPerPageView$(unsigned i, UIView *list) {
1752 NSString *path($getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Page%u.png", i]]));
1756 NSArray *subviews([list subviews]);
1758 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1759 if (view == nil || ![view wb$isWBImageView]) {
1760 view = [[[WBImageView alloc] init] autorelease];
1761 [list insertSubview:view atIndex:0];
1764 UIImage *image([UIImage imageWithContentsOfFile:path]);
1766 CGRect frame([view frame]);
1767 frame.size = [image size];
1768 [view setFrame:frame];
1770 [view setImage:image];
1771 [view wb$updateFrame];
1774 static void $addPerPageViews$(NSArray *lists) {
1775 for (unsigned i(0), e([lists count]); i != e; ++i)
1776 $addPerPageView$(i, [lists objectAtIndex:i]);
1779 MSInstanceMessageHook0(void, SBIconController, updateNumberOfRootIconLists) {
1780 NSArray *&_rootIconLists(MSHookIvar<NSArray *>(self, "_rootIconLists"));
1781 $addPerPageViews$(_rootIconLists);
1785 MSInstanceMessageHook0(void, SBIconContentView, layoutSubviews) {
1788 if (SBIconController *controller = [$SBIconController sharedInstance]) {
1789 UIView *&_dockContainerView(MSHookIvar<UIView *>(controller, "_dockContainerView"));
1790 if (&_dockContainerView != NULL)
1791 [[_dockContainerView superview] bringSubviewToFront:_dockContainerView];
1795 MSHook(void, SBIconController$noteNumberOfIconListsChanged, SBIconController *self, SEL sel) {
1796 SBIconModel *&_iconModel(MSHookIvar<SBIconModel *>(self, "_iconModel"));
1797 $addPerPageViews$([_iconModel iconLists]);
1798 return _SBIconController$noteNumberOfIconListsChanged(self, sel);
1801 MSHook(id, SBIconLabel$initWithSize$label$, SBIconLabel *self, SEL sel, CGSize size, NSString *label) {
1802 self = _SBIconLabel$initWithSize$label$(self, sel, size, label);
1804 [self setClipsToBounds:NO];
1808 MSHook(void, SBIconLabel$setInDock$, SBIconLabel *self, SEL sel, BOOL docked) {
1809 static bool gssc(false);
1811 BOOL (*GSSystemHasCapability)(CFStringRef) = reinterpret_cast<BOOL (*)(CFStringRef)>(dlsym(RTLD_DEFAULT, "GSSystemHasCapability"));
1812 Papered_ |= GSSystemHasCapability != NULL && GSSystemHasCapability(CFSTR("homescreen-wallpaper"));
1815 if ([Info_ objectForKey:@"UndockedIconLabels"] == nil)
1816 [Info_ setObject:[NSNumber numberWithBool:(
1818 [Info_ objectForKey:@"DockedIconLabelStyle"] != nil ||
1819 [Info_ objectForKey:@"UndockedIconLabelStyle"] != nil
1820 )] forKey:@"UndockedIconLabels"];
1823 id &_label(MSHookIvar<id>(self, "_label"));
1824 if (![Info_ wb$boolForKey:@"UndockedIconLabels"])
1827 if (_label != nil && [_label respondsToSelector:@selector(setInDock:)])
1828 [_label setInDock:docked];
1830 _SBIconLabel$setInDock$(self, sel, docked);
1831 [self setNeedsDisplay];
1834 MSHook(BOOL, SBDockIconListView$shouldShowNewDock, id self, SEL sel) {
1835 return SummerBoard_ && Docked_ ? NO : _SBDockIconListView$shouldShowNewDock(self, sel);
1838 MSHook(void, SBDockIconListView$setFrame$, id self, SEL sel, CGRect frame) {
1839 _SBDockIconListView$setFrame$(self, sel, frame);
1842 // %hook -[NSBundle localizedStringForKey:value:table:] {{{
1843 MSInstanceMessageHook3(NSString *, NSBundle, localizedStringForKey,value,table, NSString *, key, NSString *, value, NSString *, table) {
1844 NSString *identifier = [self bundleIdentifier];
1845 NSLocale *locale = [NSLocale currentLocale];
1846 NSString *language = [locale objectForKey:NSLocaleLanguageCode];
1848 NSLog(@"WB:Debug:[NSBundle(%@) localizedStringForKey:\"%@\" value:\"%@\" table:\"%@\"] (%@)", identifier, key, value, table, language);
1849 NSString *file = table == nil ? @"Localizable" : table;
1850 NSString *name = [NSString stringWithFormat:@"%@:%@", identifier, file];
1851 NSDictionary *strings;
1852 if ((strings = [Strings_ objectForKey:name]) != nil) {
1853 if (static_cast<id>(strings) != [NSNull null]) strings:
1854 if (NSString *value = [strings objectForKey:key])
1856 } else if (NSString *path = $pathForFile$inBundle$([NSString stringWithFormat:@"%@.lproj/%@.strings",
1859 if ((strings = [[NSDictionary alloc] initWithContentsOfFile:path]) != nil) {
1860 [Strings_ setObject:[strings autorelease] forKey:name];
1864 [Strings_ setObject:[NSNull null] forKey:name];
1865 return MSOldCall(key, value, table);
1868 // %hook -[WebCoreFrameBridge renderedSizeOfNode:constrainedToWidth:] {{{
1869 MSClassHook(WebCoreFrameBridge)
1871 MSInstanceMessageHook2(CGSize, WebCoreFrameBridge, renderedSizeOfNode,constrainedToWidth, id, node, float, width) {
1874 void **core(reinterpret_cast<void **>([node _node]));
1875 if (core == NULL || core[6] == NULL)
1877 return MSOldCall(node, width);
1881 MSInstanceMessage1(void, SBIconLabel, drawRect, CGRect, rect) {
1882 static Ivar drawMoreLegibly = object_getInstanceVariable(self, "_drawMoreLegibly", NULL);
1885 Ivar ivar = object_getInstanceVariable(self, "_inDock", reinterpret_cast<void **>(&docked));
1886 docked = (docked & (ivar_getOffset(ivar) == ivar_getOffset(drawMoreLegibly) ? 0x2 : 0x1)) != 0;
1888 NSString *label(MSHookIvar<NSString *>(self, "_label"));
1890 NSString *style = [NSString stringWithFormat:@""
1891 "font-family: Helvetica; "
1892 "font-weight: bold; "
1894 "", (docked || !SummerBoard_ ? @"white" : @"#b3b3b3"), (IsWild_
1895 ? @"font-size: 12px; "
1896 : @"font-size: 11px; "
1900 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px 1px 0px; "];
1902 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px -1px 0px; "];
1904 NSString *custom([Info_ objectForKey:(docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle")]);
1906 $drawLabel$(label, [self bounds], style, custom);
1909 MSInstanceMessage0(CGImageRef, SBIconLabel, buildLabelImage) {
1910 bool docked((MSHookIvar<unsigned>(self, "_inDock") & 0x2) != 0);
1912 WBStringDrawingState labelState = {NULL, 0, @""
1913 , docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle"};
1915 stringDrawingState_ = &labelState;
1918 CGImageRef image(MSOldCall());
1921 stringDrawingState_ = NULL;
1925 static bool wb$inDock(id parameters) {
1926 return [$objc_getAssociatedObject(parameters, @selector(wb$inDock)) boolValue];
1929 MSInstanceMessage0(NSUInteger, SBIconLabelImageParameters, hash) {
1930 return MSOldCall() + (wb$inDock(self) ? 0xdeadbeef : 0xd15ea5e);
1933 MSClassMessage2(id, SBIconView, _labelImageParametersForIcon,location, id, icon, int, location) {
1934 if (id parameters = MSOldCall(icon, location)) {
1935 $objc_setAssociatedObject(parameters, @selector(wb$inDock), [NSNumber numberWithBool:(location == 1)], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1940 MSInstanceMessage0(id, SBIconView, _labelImageParameters) {
1941 if (id parameters = MSOldCall()) {
1942 int &location(MSHookIvar<int>(self, "_iconLocation"));
1943 if (&location != NULL)
1944 $objc_setAssociatedObject(parameters, @selector(wb$inDock), [NSNumber numberWithBool:(location == 3)], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1949 MSClassMessage1(UIImage *, SBIconLabelImage, _drawLabelImageForParameters, id, parameters) {
1950 bool docked(wb$inDock(parameters));
1952 WBStringDrawingState labelState = {NULL, 0, @""
1953 , docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle"};
1955 stringDrawingState_ = &labelState;
1958 UIImage *image(MSOldCall(parameters));
1961 stringDrawingState_ = NULL;
1966 MSInstanceMessageHook2(id, CKBalloonView, initWithFrame,delegate, CGRect, frame, id, delegate) {
1967 if ((self = MSOldCall(frame, delegate)) != nil) {
1968 [self setBackgroundColor:[UIColor clearColor]];
1972 MSInstanceMessageHook0(BOOL, CKBalloonView, _canUseLayerBackedBalloon) {
1973 return SMSBackgrounded_ ? NO : MSOldCall();
1976 MSInstanceMessageHook0(void, CKTranscriptHeaderView, layoutSubviews) {
1977 [self wb$setBackgroundColor:[UIColor clearColor]];
1981 MSInstanceMessageHook1(void, CKMessageCell, addBalloonView, CKBalloonView *, balloon) {
1983 [balloon setBackgroundColor:[UIColor clearColor]];
1986 MSInstanceMessageHook1(void, CKTranscriptCell, setBackgroundColor, UIColor *, color) {
1987 MSOldCall([UIColor clearColor]);
1988 [[self contentView] wb$setBackgroundColor:[UIColor clearColor]];
1992 MSInstanceMessageHook2(id, CKTranscriptCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1993 if ((self = MSOldCall(style, reuse)) != nil) {
1994 [self setBackgroundColor:[UIColor clearColor]];
1995 [[self contentView] wb$setBackgroundColor:[UIColor clearColor]];
2000 MSInstanceMessageHook2(id, CKMessageCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
2001 if ((self = MSOldCall(style, reuse)) != nil) {
2002 [self setBackgroundColor:[UIColor clearColor]];
2003 [[self contentView] setBackgroundColor:[UIColor clearColor]];
2007 MSInstanceMessageHook2(id, CKTimestampView, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
2008 if ((self = MSOldCall(style, reuse)) != nil) {
2009 UILabel *&_label(MSHookIvar<UILabel *>(self, "_label"));
2010 [_label setBackgroundColor:[UIColor clearColor]];
2014 MSInstanceMessageHook1(void, CKTranscriptTableView, setSeparatorStyle, int, style) {
2015 MSOldCall(UITableViewCellSeparatorStyleNone);
2018 MSInstanceMessageHook2(id, CKTranscriptTableView, initWithFrame,style, CGRect, frame, int, style) {
2019 if ((self = MSOldCall(frame, style)) != nil) {
2020 [self setSeparatorStyle:UITableViewCellSeparatorStyleNone];
2024 MSInstanceMessageHook0(void, CKTranscriptController, loadView) {
2027 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"SMSBackground.png", @"SMSBackground.jpg", nil])))
2028 if (UIImage *image = $getImage$(path)) {
2029 SMSBackgrounded_ = true;
2031 UIView *&_transcriptTable(MSHookIvar<UIView *>(self, "_transcriptTable"));
2032 UIView *&_transcriptLayer(MSHookIvar<UIView *>(self, "_transcriptLayer"));
2034 if (&_transcriptTable != NULL)
2035 table = _transcriptTable;
2036 else if (&_transcriptLayer != NULL)
2037 table = _transcriptLayer;
2041 UIView *placard(table != nil ? [table superview] : MSHookIvar<UIView *>(self, "_backPlacard"));
2042 UIImageView *background([[[UIImageView alloc] initWithImage:image] autorelease]);
2045 [placard insertSubview:background atIndex:0];
2047 [table setBackgroundColor:[UIColor clearColor]];
2048 [placard insertSubview:background belowSubview:table];
2054 template <typename Original_>
2055 static UIImage *WBCacheImage(NSBundle *bundle, NSString *name, const Original_ &original, NSString *key) {
2058 NSUInteger period([name rangeOfString:@"."].location);
2059 NSUInteger length([name length]);
2060 if (period == NSNotFound || length < 4 || period > length - 4)
2061 name = [name stringByAppendingString:@".png"];
2063 return WBCacheImage(
2064 [=](){ return $pathForFile$inBundle$(name, bundle, true); },
2065 [bundle, &original, name](){
2066 UIImage *image(original());
2067 if (image != nil && UIDebug_) {
2068 NSString *path([@"/tmp/WBImages/" stringByAppendingString:[bundle bundleIdentifier]]);
2069 [Manager_ createDirectoryAtPath:path withIntermediateDirectories:YES attributes:@{NSFilePosixPermissions: @0777} error:NULL];
2070 path = [NSString stringWithFormat:@"%@/%@", path, name];
2071 if (![Manager_ fileExistsAtPath:path])
2072 [UIImagePNGRepresentation(image) writeToFile:path atomically:YES];
2078 // %hook _UIImageWithName() {{{
2079 MSHook(UIImage *, _UIImageWithName, NSString *name) {
2083 NSLog(@"WB:Debug: _UIImageWithName(\"%@\")", name);
2084 return WBCacheImage(_UIKitBundle(), name,
2085 [=](){ return __UIImageWithName(name); },
2086 [NSString stringWithFormat:@"I:%@", name]);
2089 // %hook _UIImageWithNameInDomain() {{{
2090 MSHook(UIImage *, _UIImageWithNameInDomain, NSString *name, NSString *domain) {
2092 NSLog(@"WB:Debug: _UIImageWithNameInDomain(\"%@\", \"%@\")", name, domain);
2093 return WBCacheImage(
2094 [=](){ return $getTheme$($useScale$([NSArray arrayWithObject:[NSString stringWithFormat:@"Domains/%@/%@", domain, name]])); },
2095 [=](){ return __UIImageWithNameInDomain(name, domain); },
2096 [NSString stringWithFormat:@"D:%zu:%@%@", size_t([domain length]), domain, name]);
2100 // UISharedArtwork (iOS 6) {{{
2101 MSInstanceMessageHook2(UISharedArtwork *, UISharedArtwork, initWithName,inBundle, NSString *, name, NSBundle *, bundle) {
2102 if ((self = MSOldCall(name, bundle)) != nil) {
2103 $objc_setAssociatedObject(self, @selector(wb$bundle), bundle, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
2107 MSInstanceMessageHook2(UIImage *, UISharedArtwork, imageNamed,device, NSString *, name, NSInteger, device) {
2108 NSBundle *bundle($objc_getAssociatedObject(self, @selector(wb$bundle)));
2110 NSLog(@"WB:Debug: -[UISharedArtwork(%@) imageNamed:@\"%@\" device:%li]", [bundle bundleIdentifier], name, (long) device);
2111 return WBCacheImage(bundle, name,
2112 [=](){ return MSOldCall(name, device); },
2113 [NSString stringWithFormat:@"M:%p:%@:%li", self, name, (long) device]);
2116 // _UIAssetManager (iOS 7) {{{
2117 MSInstanceMessageHook3(_UIAssetManager *, _UIAssetManager, initWithName,inBundle,idiom, NSString *, name, NSBundle *, bundle, NSInteger, idiom) {
2118 if ((self = MSOldCall(name, bundle, idiom)) != nil) {
2119 $objc_setAssociatedObject(self, @selector(wb$bundle), bundle, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
2123 MSInstanceMessageHook5(UIImage *, _UIAssetManager, imageNamed,scale,idiom,subtype,cachingOptions, NSString *, name, CGFloat, scale, NSInteger, idiom, NSUInteger, subtype, NSUInteger, caching) {
2124 NSBundle *bundle($objc_getAssociatedObject(self, @selector(wb$bundle)));
2126 NSLog(@"WB:Debug: -[_UIAssetManager(%@/%@) imageNamed:@\"%@\" scale:%g idiom:%li subtype:%lu cachingOptions:%lu]",
2127 [bundle bundleIdentifier], [self carFileName],
2128 name, scale, (long) idiom,
2129 (unsigned long) subtype,
2130 (unsigned long) caching
2133 if (bundle == _UIKitBundle()) {
2134 NSString *name([self carFileName]);
2136 else if ([name isEqualToString:@"UIKit_NewArtwork"])
2137 bundle = [WBBundle bundleWithIdentifier:@"com.apple.uikit.Artwork"];
2138 else if ([name isEqualToString:@"UIKit_OriginalArtwork"])
2139 bundle = [WBBundle bundleWithIdentifier:@"com.apple.uikit.LegacyArtwork"];
2142 return WBCacheImage(bundle, name,
2143 [=](){ return MSOldCall(name, scale, idiom, subtype, caching); },
2144 [NSString stringWithFormat:@"M:%p:%@:%g:%li:%lu", self, name, scale, (long) idiom, (unsigned long) subtype]);
2147 // _UIAssetManager (iOS 8) {{{
2148 struct SizeClassPair {
2153 MSInstanceMessageHook7(UIImage *, _UIAssetManager, imageNamed,scale,idiom,subtype,cachingOptions,sizeClassPair,attachCatalogImage, NSString *, name, CGFloat, scale, NSInteger, idiom, NSUInteger, subtype, NSUInteger, caching, SizeClassPair, size, BOOL, attach) {
2154 NSBundle *bundle([self bundle]);
2156 NSLog(@"WB:Debug: -[_UIAssetManager(%@/%@) imageNamed:@\"%@\" scale:%g idiom:%li subtype:%lu cachingOptions:%lu sizeClassPair:[%li %li] attachCatalogImage:%s]",
2157 [bundle bundleIdentifier], [self carFileName],
2158 name, scale, (long) idiom,
2159 (unsigned long) subtype,
2160 (unsigned long) caching,
2161 (long) size.first, (long) size.second,
2162 attach ? "YES" : "NO"
2164 return WBCacheImage(bundle, name,
2165 [=](){ return MSOldCall(name, scale, idiom, subtype, caching, size, attach); },
2166 [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']);
2170 // %hook GSFontCreateWithName() {{{
2171 MSHook(GSFontRef, GSFontCreateWithName, const char *name, GSFontSymbolicTraits traits, float size) {
2173 NSLog(@"WB:Debug: GSFontCreateWithName(\"%s\", %f)", name, size);
2174 if (NSString *font = [Info_ objectForKey:[NSString stringWithFormat:@"FontName-%s", name]])
2175 name = [font UTF8String];
2176 //if (NSString *scale = [Info_ objectForKey:[NSString stringWithFormat:@"FontScale-%s", name]])
2177 // size *= [scale floatValue];
2178 return _GSFontCreateWithName(name, traits, size);
2182 #define AudioToolbox "/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox"
2184 static bool GetFileNameForThisAction$(bool value, unsigned long a0, char *a1, unsigned long a2, bool &a3) {
2186 NSLog(@"WB:Debug:GetFileNameForThisAction(%lu, %s, %lu, %u) = %u", a0, value ? a1 : NULL, a2, a3, value);
2189 NSString *path = [NSString stringWithUTF8String:a1];
2190 if ([path hasPrefix:@"/System/Library/Audio/UISounds/"]) {
2191 NSString *file = [path substringFromIndex:31];
2192 for (NSString *theme in Themes_) {
2193 NSString *path([NSString stringWithFormat:@"%@/UISounds/%@", theme, file]);
2194 if ([Manager_ fileExistsAtPath:path]) {
2195 strcpy(a1, [path UTF8String]);
2204 MSHook(bool, _Z24GetFileNameForThisActionmPcRb, unsigned long a0, char *a1, bool &a3) {
2205 bool value(__Z24GetFileNameForThisActionmPcRb(a0, a1, a3));
2206 return GetFileNameForThisAction$(value, a0, a1, 0, a3);
2210 MSHook(bool, _Z24GetFileNameForThisActionjPcjRb, unsigned int a0, char *a1, unsigned int a2, bool &a3) {
2211 bool value(__Z24GetFileNameForThisActionjPcjRb(a0, a1, a2, a3));
2212 return GetFileNameForThisAction$(value, a0, a1, a2, a3);
2215 MSHook(bool, _Z24GetFileNameForThisActionmPcmRb, unsigned long a0, char *a1, unsigned long a2, bool &a3) {
2216 bool value(__Z24GetFileNameForThisActionmPcmRb(a0, a1, a2, a3));
2217 return GetFileNameForThisAction$(value, a0, a1, a2, a3);
2221 static void ChangeWallpaper(
2222 CFNotificationCenterRef center,
2226 CFDictionaryRef info
2229 NSLog(@"WB:Debug:ChangeWallpaper!");
2232 if (WallpaperFile_ != nil) {
2233 image = [[UIImage alloc] initWithContentsOfFile:WallpaperFile_];
2235 image = [image autorelease];
2238 if (WallpaperImage_ != nil)
2239 [WallpaperImage_ setImage:image];
2240 if (WallpaperPage_ != nil)
2241 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
2245 MSHook(NSArray *, CPBitmapCreateImagesFromPath, NSString *path, CFTypeRef *names, void *arg2, void *arg3) {
2246 NSArray *images(_CPBitmapCreateImagesFromPath(path, names, arg2, arg3));
2252 NSBundle *bundle([NSBundle wb$bundleWithFile:path]);
2256 NSString *file([path stringByResolvingSymlinksInPath]);
2257 NSString *prefix([[bundle bundlePath] stringByResolvingSymlinksInPath]);
2258 // XXX: why do I care about this?
2259 if (![file hasPrefix:prefix])
2262 NSMutableArray *copy([images mutableCopy]);
2266 NSDictionary *indexes;
2267 NSEnumerator *enumerator;
2269 if (CFGetTypeID((CFTypeRef) *names) == CFDictionaryGetTypeID()) {
2270 indexes = (NSDictionary *) *names;
2271 enumerator = [indexes keyEnumerator];
2274 enumerator = [(NSArray *) *names objectEnumerator];
2277 for (NSUInteger index(0); NSString *name = [enumerator nextObject]; ++index)
2278 if (NSString *themed = $pathForFile$inBundle$([name stringByAppendingString:@".png"], bundle, true)) {
2280 index = [[indexes objectForKey:name] intValue];
2281 if (UIImage *image = $getImage$(themed))
2282 [copy replaceObjectAtIndex:index withObject:(id)[image CGImage]];
2288 MSHook(void, BKSDisplayServicesSetSystemAppExitedImagePath, NSString *path) {
2289 if (NSString *themed = $getTheme$($useScale$([NSArray arrayWithObject:@"SystemAppExited.png"])))
2291 _BKSDisplayServicesSetSystemAppExitedImagePath(path);
2294 #define WBRename(name, sel, imp) \
2295 MSHookMessage($ ## name, @selector(sel), &$ ## name ## $ ## imp, &_ ## name ## $ ## imp)
2297 template <typename Type_>
2298 static void msset(Type_ &function, MSImageRef image, const char *name) {
2299 function = reinterpret_cast<Type_>(MSFindSymbol(image, name));
2302 #define WBHookSymbol(image, function) \
2303 msset(function, image, "_" #function)
2305 template <typename Type_>
2306 static void dlset(Type_ &function, const char *name) {
2307 function = reinterpret_cast<Type_>(dlsym(RTLD_DEFAULT, name));
2310 // %hook CGImageReadCreateWithFile() {{{
2311 MSHook(void *, CGImageReadCreateWithFile, NSString *path, int flag) {
2313 NSLog(@"WB:Debug: CGImageReadCreateWithFile(%@, %d)", path, flag);
2314 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2315 void *value(_CGImageReadCreateWithFile([path wb$themedPath], flag));
2320 MSHook(void *, CGImageSourceCreateWithFile, NSString *path, NSDictionary *options) {
2322 NSLog(@"WB:Debug: CGImageSourceCreateWithFile(%@, %@)", path, options);
2323 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2324 void *value(_CGImageSourceCreateWithFile([path wb$themedPath], options));
2329 MSHook(void *, CGImageSourceCreateWithURL, NSURL *url, NSDictionary *options) {
2331 NSLog(@"WB:Debug: CGImageSourceCreateWithURL(%@, %@)", url, options);
2332 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2333 if ([url isFileURL])
2334 url = [NSURL fileURLWithPath:[[url path] wb$themedPath]];
2335 void *value(_CGImageSourceCreateWithURL(url, options));
2341 static void NSString$drawAtPoint$withStyle$(NSString *self, SEL _cmd, CGPoint point, NSString *style) {
2342 WKSetCurrentGraphicsContext(UIGraphicsGetCurrentContext());
2343 if (style == nil || [style length] == 0)
2344 style = @"font-family: Helvetica; font-size: 12px";
2345 //NSLog(@"XXX:drawP(%@ | %@)", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "]);
2346 [[WBMarkup sharedMarkup] drawString:self atPoint:point withStyle:style];
2349 static void NSString$drawInRect$withStyle$(NSString *self, SEL _cmd, CGRect rect, NSString *style) {
2350 WKSetCurrentGraphicsContext(UIGraphicsGetCurrentContext());
2351 if (style == nil || [style length] == 0)
2352 style = @"font-family: Helvetica; font-size: 12px";
2353 //NSLog(@"XXX:drawR(%@ | %@)", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "]);
2354 return [[WBMarkup sharedMarkup] drawString:self inRect:rect withStyle:style];
2357 static CGSize NSString$sizeWithStyle$forWidth$(NSString *self, SEL _cmd, NSString *style, CGFloat width) {
2358 if (style == nil || [style length] == 0)
2359 style = @"font-family: Helvetica; font-size: 12px";
2360 CGSize size([[WBMarkup sharedMarkup] sizeOfString:self withStyle:style forWidth:width]);
2361 //NSLog(@"XXX:size(%@ | %@) = [%g %g]", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "], size.width, size.height);
2365 static void SBInitialize() {
2367 WBRename(SBApplication, pathForIcon, pathForIcon);
2368 WBRename(SBApplicationIcon, icon, icon);
2369 WBRename(SBApplicationIcon, generateIconImage:, generateIconImage$);
2372 WBRename(SBBookmarkIcon, icon, icon);
2373 WBRename(SBButtonBar, didMoveToSuperview, didMoveToSuperview);
2374 WBRename(SBCalendarIconContentsView, drawRect:, drawRect$);
2375 WBRename(SBIconBadge, initWithBadge:, initWithBadge$);
2376 WBRename(SBIconController, noteNumberOfIconListsChanged, noteNumberOfIconListsChanged);
2378 WBRename(SBWidgetApplicationIcon, icon, icon);
2380 WBRename(SBDockIconListView, setFrame:, setFrame$);
2381 MSHookMessage(object_getClass($SBDockIconListView), @selector(shouldShowNewDock), &$SBDockIconListView$shouldShowNewDock, &_SBDockIconListView$shouldShowNewDock);
2383 if (kCFCoreFoundationVersionNumber < 600 || SummerBoard_)
2384 WBRename(SBIconLabel, drawRect:, drawRect$);
2385 else if (kCFCoreFoundationVersionNumber < 700) {
2386 WBRename(SBIconLabel, buildLabelImage, buildLabelImage);
2388 WBRename(SBIconLabelImageParameters, hash, hash);
2389 WBRename($SBIconView, _labelImageParametersForIcon:location:, _labelImageParametersForIcon$location$);
2390 WBRename(SBIconView, _labelImageParameters, _labelImageParameters);
2391 WBRename($SBIconLabelImage, _drawLabelImageForParameters:, _drawLabelImageForParameters$);
2394 WBRename(SBIconLabel, initWithSize:label:, initWithSize$label$);
2395 WBRename(SBIconLabel, setInDock:, setInDock$);
2397 WBRename(SBIconList, didMoveToSuperview, didMoveToSuperview);
2398 WBRename(SBIconList, setFrame:, setFrame$);
2400 WBRename(SBIconModel, cacheImageForIcon:, cacheImageForIcon$);
2401 WBRename(SBIconModel, cacheImagesForIcon:, cacheImagesForIcon$);
2402 WBRename(SBIconModel, getCachedImagedForIcon:, getCachedImagedForIcon$);
2403 WBRename(SBIconModel, getCachedImagedForIcon:smallIcon:, getCachedImagedForIcon$smallIcon$);
2405 if (kCFCoreFoundationVersionNumber < 800) {
2406 WBRename(SBSearchView, initWithFrame:, initWithFrame$);
2407 WBRename(SBSearchTableViewCell, drawRect:, drawRect$);
2408 WBRename(SBSearchTableViewCell, initWithStyle:reuseIdentifier:, initWithStyle$reuseIdentifier$);
2411 //WBRename(SBImageCache, initWithName:forImageWidth:imageHeight:initialCapacity:, initWithName$forImageWidth$imageHeight$initialCapacity$);
2413 WBRename(SBAwayView, updateDesktopImage:, updateDesktopImage$);
2414 if (kCFCoreFoundationVersionNumber >= 700)
2415 WBRename(SBAwayView, _addSubview:positioned:relativeTo:, _addSubview$positioned$relativeTo$);
2417 WBRename(SBStatusBarContentsView, didMoveToSuperview, didMoveToSuperview);
2418 //WBRename(SBStatusBarContentsView, initWithStatusBar:mode:, initWithStatusBar$mode$);
2419 //WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:animation:, setStatusBarMode$orientation$duration$animation$);
2420 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:, setStatusBarMode$orientation$duration$fenceID$animation$);
2421 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:startTime:, setStatusBarMode$orientation$duration$fenceID$animation$startTime$);
2422 WBRename(SBStatusBarOperatorNameView, operatorNameStyle, operatorNameStyle);
2423 WBRename(SBStatusBarOperatorNameView, setOperatorName:fullSize:, setOperatorName$fullSize$);
2424 WBRename(SBStatusBarTimeView, drawRect:, drawRect$);
2427 English_ = [[NSDictionary alloc] initWithContentsOfFile:@"/System/Library/CoreServices/SpringBoard.app/English.lproj/LocalizedApplicationNames.strings"];
2429 if (kCFCoreFoundationVersionNumber >= 800) {
2430 WBRename(NSString, drawInRect:withAttributes:, drawInRect$withAttributes$);
2431 WBRename(NSString, boundingRectWithSize:options:attributes:context:, boundingRectWithSize$options$attributes$context$);
2435 /*MSHook(int, open, const char *path, int oflag, mode_t mode) {
2436 int fd(_open(path, oflag, mode));
2438 static bool no(false);
2442 if (strstr(path, "/icon") != NULL)
2443 *reinterpret_cast<void *volatile *>(NULL) = NULL;
2445 if (fd == -1 && errno == EFAULT)
2446 NSLog(@"open(%p, %#x, %#o) = %d\n", path, oflag, mode, fd);
2448 NSLog(@"open(\"%s\", %#x, %#o) = %d\n", path, oflag, mode, fd);
2455 $objc_setAssociatedObject = reinterpret_cast<void (*)(id, void *, id value, objc_AssociationPolicy)>(dlsym(RTLD_DEFAULT, "objc_setAssociatedObject"));
2456 $objc_getAssociatedObject = reinterpret_cast<id (*)(id, void *)>(dlsym(RTLD_DEFAULT, "objc_getAssociatedObject"));
2457 $objc_removeAssociatedObjects = reinterpret_cast<void (*)(id)>(dlsym(RTLD_DEFAULT, "objc_removeAssociatedObjects"));
2459 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2461 NSString *identifier([[NSBundle mainBundle] bundleIdentifier]);
2462 SpringBoard_ = [identifier isEqualToString:@"com.apple.springboard"];
2464 Manager_ = [[NSFileManager defaultManager] retain];
2465 Themes_ = [[NSMutableArray alloc] initWithCapacity:8];
2467 dlset(_GSFontGetUseLegacyFontMetrics, "GSFontGetUseLegacyFontMetrics");
2469 // Initialize IsWild_ {{{
2471 sysctlbyname("hw.machine", NULL, &size, NULL, 0);
2472 char *machine = new char[size];
2474 if (sysctlbyname("hw.machine", machine, &size, NULL, 0) == -1) {
2475 perror("sysctlbyname(\"hw.machine\", ?)");
2480 IsWild_ = machine != NULL && strncmp(machine, "iPad", 4) == 0;
2482 // Load Settings.plist {{{
2483 if (NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"/User/Library/Preferences/com.saurik.WinterBoard.plist"]]) {
2484 if (kCFCoreFoundationVersionNumber >= 1000)
2485 SummerBoard_ = false;
2486 else if (NSNumber *value = [settings objectForKey:@"SummerBoard"])
2487 SummerBoard_ = [value boolValue];
2489 SummerBoard_ = true;
2491 if (NSNumber *value = [settings objectForKey:@"Debug"])
2492 Debug_ = [value boolValue];
2493 if (NSNumber *value = [settings objectForKey:@"RecordUI"])
2494 UIDebug_ = [value boolValue];
2496 NSArray *themes([settings objectForKey:@"Themes"]);
2498 if (NSString *theme = [settings objectForKey:@"Theme"])
2499 themes = [NSArray arrayWithObject:[NSDictionary dictionaryWithObjectsAndKeys:
2501 [NSNumber numberWithBool:true], @"Active",
2505 for (NSDictionary *theme in themes) {
2506 NSNumber *active([theme objectForKey:@"Active"]);
2507 if (![active boolValue])
2510 NSString *name([theme objectForKey:@"Name"]);
2514 #define testForTheme(format...) \
2516 NSString *path = [NSString stringWithFormat:format]; \
2517 if ([Manager_ fileExistsAtPath:path]) { \
2518 [Themes_ addObject:path]; \
2523 testForTheme(@"/Library/Themes/%@.theme", name)
2524 testForTheme(@"/Library/Themes/%@", name)
2525 testForTheme(@"%@/Library/SummerBoard/Themes/%@", NSHomeDirectory(), name)
2530 // Merge Info.plist {{{
2531 Info_ = [[NSMutableDictionary dictionaryWithCapacity:16] retain];
2533 for (NSString *theme in Themes_)
2534 if (NSDictionary *info = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"%@/Info.plist", theme]])
2535 for (NSString *key in [info allKeys])
2536 if ([Info_ objectForKey:key] == nil)
2537 [Info_ setObject:[info objectForKey:key] forKey:key];
2541 if (MSImageRef image = MSGetImageByName("/System/Library/PrivateFrameworks/AppSupport.framework/AppSupport")) {
2542 NSArray *(*CPBitmapCreateImagesFromPath)(NSString *, CFTypeRef *, void *, void *);
2543 msset(CPBitmapCreateImagesFromPath, image, "_CPBitmapCreateImagesFromPath");
2544 MSHookFunction(CPBitmapCreateImagesFromPath, MSHake(CPBitmapCreateImagesFromPath));
2548 if (MSImageRef image = MSGetImageByName(AudioToolbox)) {
2549 bool (*_Z24GetFileNameForThisActionmPcRb)(unsigned long, char *, bool &);
2550 msset(_Z24GetFileNameForThisActionmPcRb, image, "__Z24GetFileNameForThisActionmPcRb");
2551 MSHookFunction(_Z24GetFileNameForThisActionmPcRb, &$_Z24GetFileNameForThisActionmPcRb, &__Z24GetFileNameForThisActionmPcRb);
2554 bool (*_Z24GetFileNameForThisActionjPcjRb)(unsigned int, char *, unsigned int, bool &);
2555 msset(_Z24GetFileNameForThisActionjPcjRb, image, "__Z24GetFileNameForThisActionjPcjRb");
2556 MSHookFunction(_Z24GetFileNameForThisActionjPcjRb, &$_Z24GetFileNameForThisActionjPcjRb, &__Z24GetFileNameForThisActionjPcjRb);
2558 bool (*_Z24GetFileNameForThisActionmPcmRb)(unsigned long, char *, unsigned long, bool &);
2559 msset(_Z24GetFileNameForThisActionmPcmRb, image, "__Z24GetFileNameForThisActionmPcmRb");
2560 MSHookFunction(_Z24GetFileNameForThisActionmPcmRb, &$_Z24GetFileNameForThisActionmPcmRb, &__Z24GetFileNameForThisActionmPcmRb);
2564 // BackBoardServices {{{
2565 if (MSImageRef image = MSGetImageByName("/System/Library/PrivateFrameworks/BackBoardServices.framework/BackBoardServices")) {
2566 void (*BKSDisplayServicesSetSystemAppExitedImagePath)(NSString *path);
2567 msset(BKSDisplayServicesSetSystemAppExitedImagePath, image, "_BKSDisplayServicesSetSystemAppExitedImagePath");
2568 MSHookFunction(BKSDisplayServicesSetSystemAppExitedImagePath, MSHake(BKSDisplayServicesSetSystemAppExitedImagePath));
2573 if (![identifier isEqualToString:@"com.apple.backupd"]) // XXX: rethink
2574 MSHookFunction(CFBundleCopyResourceURL, MSHake(CFBundleCopyResourceURL));
2577 // GraphicsServices {{{
2579 MSHookFunction(&GSFontCreateWithName, &$GSFontCreateWithName, &_GSFontCreateWithName);
2583 MSImageRef imageio = MSGetImageByName("/System/Library/Frameworks/ImageIO.framework/ImageIO");
2584 if (imageio == NULL)
2585 imageio = MSGetImageByName("/System/Library/PrivateFrameworks/ImageIO.framework/ImageIO");
2586 if (MSImageRef image = imageio) {
2587 void *(*CGImageReadCreateWithFile)(NSString *, int) = NULL;
2588 if (kCFCoreFoundationVersionNumber > 700) // XXX: iOS 6.x
2589 CGImageReadCreateWithFile = NULL;
2591 msset(CGImageReadCreateWithFile, image, "_CGImageReadCreateWithFile");
2592 MSHookFunction(CGImageReadCreateWithFile, MSHake(CGImageReadCreateWithFile));
2595 if (CGImageReadCreateWithFile == NULL) {
2596 void *(*CGImageSourceCreateWithFile)(NSString *, NSDictionary *);
2597 msset(CGImageSourceCreateWithFile, image, "_CGImageSourceCreateWithFile");
2598 MSHookFunction(CGImageSourceCreateWithFile, MSHake(CGImageSourceCreateWithFile));
2600 void *(*CGImageSourceCreateWithURL)(NSURL *, NSDictionary *);
2601 msset(CGImageSourceCreateWithURL, image, "_CGImageSourceCreateWithURL");
2602 MSHookFunction(CGImageSourceCreateWithURL, MSHake(CGImageSourceCreateWithURL));
2608 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];
2609 Papered_ = $getTheme$(Wallpapers_) != nil;
2610 Docked_ = $getTheme$([NSArray arrayWithObjects:@"Dock.png", nil]) != nil;
2612 CFNotificationCenterAddObserver(
2613 CFNotificationCenterGetDarwinNotifyCenter(),
2614 NULL, &ChangeWallpaper, (CFStringRef) @"com.saurik.winterboard.lockbackground", NULL, CFNotificationSuspensionBehaviorCoalesce
2617 if ($getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"]) != nil) {
2618 NSBundle *MediaPlayer([NSBundle bundleWithPath:@"/System/Library/Frameworks/MediaPlayer.framework"]);
2619 if (MediaPlayer != nil)
2622 $MPMoviePlayerController = objc_getClass("MPMoviePlayerController");
2623 $MPVideoView = objc_getClass("MPVideoView");
2630 if (MSImageRef image = MSGetImageByName("/System/Library/Frameworks/UIKit.framework/UIKit")) {
2632 class_addMethod($NSString, @selector(drawAtPoint:withStyle:), (IMP) &NSString$drawAtPoint$withStyle$, "v40@0:8{CGPoint=dd}16@32");
2633 class_addMethod($NSString, @selector(drawInRect:withStyle:), (IMP) &NSString$drawInRect$withStyle$, "v56@0:8{CGRect={CGSize=dd}{CGSize=dd}}16@48");
2634 class_addMethod($NSString, @selector(sizeWithStyle:forWidth:), (IMP) &NSString$sizeWithStyle$forWidth$, "{CGSize=dd}32@0:8@16d24");
2636 class_addMethod($NSString, @selector(drawAtPoint:withStyle:), (IMP) &NSString$drawAtPoint$withStyle$, "v20@0:4{CGPoint=ff}8@16");
2637 class_addMethod($NSString, @selector(drawInRect:withStyle:), (IMP) &NSString$drawInRect$withStyle$, "v28@0:4{CGRect={CGSize=ff}{CGSize=ff}}8@24");
2638 class_addMethod($NSString, @selector(sizeWithStyle:forWidth:), (IMP) &NSString$sizeWithStyle$forWidth$, "{CGSize=ff}16@0:4@8f12");
2641 WBHookSymbol(image, _UIKitBundle);
2643 if (kCFCoreFoundationVersionNumber < 700)
2644 MSHookFunction(_UIImageWithName, MSHake(_UIImageWithName));
2646 WBHookSymbol(image, _UIApplicationImageWithName);
2647 MSHookFunction(_UIApplicationImageWithName, MSHake(_UIApplicationImageWithName));
2649 WBHookSymbol(image, _UIImageWithNameInDomain);
2650 MSHookFunction(_UIImageWithNameInDomain, MSHake(_UIImageWithNameInDomain));
2652 SEL includeEmoji(@selector(_legacy_drawAtPoint:forWidth:withFont:lineBreakMode:letterSpacing:includeEmoji:));
2653 if (![@"" respondsToSelector:includeEmoji])
2654 includeEmoji = @selector(drawAtPoint:forWidth:withFont:lineBreakMode:letterSpacing:includeEmoji:);
2655 MSHookMessage($NSString, includeEmoji, MSHake(NSString$drawAtPoint$forWidth$withFont$lineBreakMode$letterSpacing$includeEmoji$));
2657 SEL letterSpacing(@selector(_legacy_sizeWithFont:forWidth:lineBreakMode:letterSpacing:));
2658 if (![@"" respondsToSelector:letterSpacing])
2659 letterSpacing = @selector(sizeWithFont:forWidth:lineBreakMode:letterSpacing:);
2660 MSHookMessage($NSString, letterSpacing, MSHake(NSString$sizeWithFont$forWidth$lineBreakMode$letterSpacing$));
2662 SEL sizeWithFont(@selector(_legacy_sizeWithFont:));
2663 if (![@"" respondsToSelector:sizeWithFont])
2664 sizeWithFont = @selector(sizeWithFont:);
2665 MSHookMessage($NSString, sizeWithFont, MSHake(NSString$sizeWithFont$));
2669 //MSHookFunction(reinterpret_cast<int (*)(const char *, int, mode_t)>(&open), MSHake(open));