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]);
309 [scaled addObject:[NSString stringWithFormat:@"%@@%ux~%@.%@", base, Scale_, idiom, extension]];
310 [scaled addObject:[NSString stringWithFormat:@"%@@%ux.%@", base, Scale_, extension]];
313 for (unsigned scale(3); scale >= 2; --scale)
314 if (scale != Scale_) {
315 [scaled addObject:[NSString stringWithFormat:@"%@@%ux~%@.%@", base, scale, idiom, extension]];
316 [scaled addObject:[NSString stringWithFormat:@"%@@%ux.%@", base, scale, extension]];
319 [scaled addObject:[NSString stringWithFormat:@"%@~%@.%@", base, idiom, extension]];
321 // if (!IsWild_) <- support old themes
322 [scaled addObject:file];
323 } else if ([base hasSuffix: @"@2x"] || [base hasSuffix:@"@3x"]) {
324 [scaled addObject:[NSString stringWithFormat:@"%@~%@.%@", base, idiom, extension]];
325 [scaled addObject:file];
327 // XXX: this actually can't be used, as the person loading the file doesn't realize that the @2x changed
328 /*NSString *rest([base substringWithRange:NSMakeRange(0, [base length] - 3)]);
329 [scaled addObject:[NSString stringWithFormat:@"%@~%@.%@", rest, idiom, extension]];
330 [scaled addObject:[rest stringByAppendingPathExtension:extension]];*/
332 // XXX: this code isn't really complete
334 [scaled addObject:file];
336 if ([base hasSuffix:[NSString stringWithFormat:@"~%@", idiom]])
337 [scaled addObject:[[base substringWithRange:NSMakeRange(0, [base length] - 1 - [idiom length])] stringByAppendingPathExtension:extension]];
344 static NSString *$getTheme$(NSArray *files, NSArray *themes = Themes_) {
345 // XXX: this is not reasonable; OMG
348 @synchronized (Themed_) {
349 if (NSString *path = [Themed_ objectForKey:key])
350 return reinterpret_cast<id>(path) == [NSNull null] ? nil : path;
354 NSLog(@"WB:Debug: %@", [files description]);
358 for (NSString *theme in Themes_)
359 for (NSString *file in files) {
360 path = [NSString stringWithFormat:@"%@/%@", theme, file];
361 if ([Manager_ fileExistsAtPath:path]) {
362 if ([[Manager_ destinationOfSymbolicLinkAtPath:path error:NULL] isEqualToString:@"/"])
371 @synchronized (Themed_) {
372 [Themed_ setObject:(path == nil ? [NSNull null] : reinterpret_cast<id>(path)) forKey:key];
378 // $pathForFile$inBundle$() {{{
379 static void $pathForFile$inBundle$(NSMutableArray *names, NSString *file, NSString *identifier, NSString *folder) {
380 if (identifier != nil)
381 [names addObject:[NSString stringWithFormat:@"Bundles/%@/%@", identifier, file]];
383 [names addObject:[NSString stringWithFormat:@"Folders/%@/%@", folder, file]];
384 NSString *base([folder stringByDeletingPathExtension]);
385 if ([base hasSuffix:@"~iphone"])
386 [names addObject:[NSString stringWithFormat:@"Folders/%@.%@/%@", [base substringWithRange:NSMakeRange(0, [base length] - 7)], [folder pathExtension], file]];
387 if ([base hasSuffix:@"~ipad"])
388 [names addObject:[NSString stringWithFormat:@"Folders/%@.%@/%@", [base substringWithRange:NSMakeRange(0, [base length] - 5)], [folder pathExtension], file]];
391 #define remapResourceName(oldname, newname) \
392 else if ([file isEqualToString:(oldname)]) \
393 [names addObject:oldname ".png"];
395 bool summer(SpringBoard_ && SummerBoard_);
397 if (identifier == nil);
398 else if ([identifier isEqualToString:@"com.apple.uikit.Artwork"])
399 $pathForFile$inBundle$(names, file, @"com.apple.UIKit", @"UIKit.framework");
400 else if ([identifier isEqualToString:@"com.apple.uikit.LegacyArtwork"])
401 $pathForFile$inBundle$(names, file, @"com.apple.UIKit", @"UIKit.framework");
402 else if ([identifier isEqualToString:@"com.apple.UIKit"])
403 [names addObject:[NSString stringWithFormat:@"UIImages/%@", file]];
404 else if ([identifier isEqualToString:@"com.apple.chatkit"])
405 $pathForFile$inBundle$(names, file, @"com.apple.MobileSMS", @"MobileSMS.app");
406 else if ([identifier isEqualToString:@"com.apple.calculator"])
407 [names addObject:[NSString stringWithFormat:@"Files/Applications/Calculator.app/%@", file]];
408 else if ([identifier isEqualToString:@"com.apple.Maps"] && [file isEqualToString:@"Icon-57@2x.png"])
409 $pathForFile$inBundle$(names, @"icon.png", identifier, folder);
411 remapResourceName(@"FSO_BG.png", @"StatusBar")
412 remapResourceName(Four_ ? @"SBDockBG-old.png" : @"SBDockBG.png", @"Dock")
413 remapResourceName(@"SBWeatherCelsius.png", @"Icons/Weather")
416 static NSString *$pathForFile$inBundle$(NSString *file, NSString *identifier, NSURL *url, bool use) {
417 NSMutableArray *names = [NSMutableArray arrayWithCapacity:8];
418 $pathForFile$inBundle$(names, file, identifier, [url lastPathComponent]);
419 [names addObject:[NSString stringWithFormat:@"Fallback/%@", file]];
420 if (NSString *path = $getTheme$($useScale$(names, use)))
425 // XXX: this cannot be merged due to WBBundle
426 static NSString *$pathForFile$inBundle$(NSString *file, NSBundle *bundle, bool use) {
427 return $pathForFile$inBundle$(file, [bundle bundleIdentifier], [bundle bundleURL], use);
430 static NSString *$pathForFile$inBundle$(NSString *file, CFBundleRef bundle, bool use) {
431 NSString *identifier((NSString *) CFBundleGetIdentifier(bundle));
432 NSURL *url([(NSURL *) CFBundleCopyBundleURL(bundle) autorelease]);
433 return $pathForFile$inBundle$(file, identifier, url, use);
437 static NSString *$pathForIcon$(SBApplication *self, NSString *suffix = @"") {
438 NSString *identifier = [self bundleIdentifier];
439 NSString *path = [self path];
440 NSString *folder = [path lastPathComponent];
441 NSString *dname = [self displayName];
443 NSString *didentifier;
444 if ([self respondsToSelector:@selector(displayIdentifier)])
445 didentifier = [self displayIdentifier];
450 NSLog(@"WB:Debug: [SBApplication(%@:%@:%@:%@) pathForIcon]", identifier, folder, dname, didentifier);
452 NSMutableArray *names = [NSMutableArray arrayWithCapacity:8];
454 /* XXX: I might need to keep this for backwards compatibility
455 if (identifier != nil)
456 [names addObject:[NSString stringWithFormat:@"Bundles/%@/icon.png", identifier]];
458 [names addObject:[NSString stringWithFormat:@"Folders/%@/icon.png", folder]]; */
460 #define testForIcon(Name) \
461 if (NSString *name = Name) \
462 [names addObject:[NSString stringWithFormat:@"Icons%@/%@.png", suffix, name]];
464 if (didentifier != nil && ![didentifier isEqualToString:identifier])
465 testForIcon(didentifier);
467 testForIcon(identifier);
470 if ([identifier isEqualToString:@"com.apple.MobileSMS"])
473 if (didentifier != nil) {
474 testForIcon([English_ objectForKey:didentifier]);
476 NSArray *parts = [didentifier componentsSeparatedByString:@"-"];
477 if ([parts count] != 1)
478 if (NSDictionary *english = [[[NSDictionary alloc] initWithContentsOfFile:[path stringByAppendingString:@"/English.lproj/UIRoleDisplayNames.strings"]] autorelease])
479 testForIcon([english objectForKey:[parts lastObject]]);
482 if (NSString *path = $getTheme$(names))
488 // -[NSBundle wb$bundleWithFile] {{{
489 @interface NSBundle (WinterBoard)
490 + (NSBundle *) wb$bundleWithFile:(NSString *)path;
493 @implementation NSBundle (WinterBoard)
495 + (NSBundle *) _wb$bundleWithFile:(NSString *)path {
496 path = [path stringByDeletingLastPathComponent];
497 if (path == nil || [path length] == 0 || [path isEqualToString:@"/"])
501 @synchronized (Bundles_) {
502 bundle = [Bundles_ objectForKey:path];
505 if (reinterpret_cast<id>(bundle) == [NSNull null])
507 else if (bundle == nil) {
508 if ([Manager_ fileExistsAtPath:[path stringByAppendingPathComponent:@"Info.plist"]])
509 bundle = [NSBundle bundleWithPath:path];
511 bundle = [NSBundle _wb$bundleWithFile:path];
513 NSLog(@"WB:Debug:PathBundle(%@, %@)", path, bundle);
515 @synchronized (Bundles_) {
516 [Bundles_ setObject:(bundle == nil ? [NSNull null] : reinterpret_cast<id>(bundle)) forKey:path];
523 + (NSBundle *) wb$bundleWithFile:(NSString *)path {
524 if ([path hasPrefix:@"/Library/Themes"])
526 return [self _wb$bundleWithFile:path];
531 // -[NSString wb$themedPath] {{{
532 @interface NSString (WinterBoard)
533 - (NSString *) wb$themedPath;
536 @implementation NSString (WinterBoard)
538 - (NSString *) wb$themedPath {
540 NSLog(@"WB:Debug:Bypass(\"%@\")", self);
542 if (NSBundle *bundle = [NSBundle wb$bundleWithFile:self]) {
543 NSString *file([self stringByResolvingSymlinksInPath]);
544 NSString *prefix([[bundle bundlePath] stringByResolvingSymlinksInPath]);
545 if ([file hasPrefix:prefix]) {
546 NSUInteger length([prefix length]);
547 if (length != [file length])
548 if (NSString *path = $pathForFile$inBundle$([file substringFromIndex:(length + 1)], bundle, false))
559 void WBLogRect(const char *tag, struct CGRect rect) {
560 NSLog(@"%s:{%f,%f+%f,%f}", tag, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
563 void WBLogHierarchy(UIView *view, unsigned index = 0, unsigned indent = 0) {
564 CGRect frame([view frame]);
565 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]);
567 for (UIView *child in [view subviews])
568 WBLogHierarchy(child, index++, indent + 1);
571 UIImage *$cacheForImage$(UIImage *image) {
572 CGColorSpaceRef space(CGColorSpaceCreateDeviceRGB());
573 CGRect rect = {CGPointMake(1, 1), [image size]};
574 CGSize size = {rect.size.width + 2, rect.size.height + 2};
576 CGContextRef context(CGBitmapContextCreate(NULL, size.width, size.height, 8, 4 * size.width, space, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst));
577 CGColorSpaceRelease(space);
579 CGContextDrawImage(context, rect, [image CGImage]);
580 CGImageRef ref(CGBitmapContextCreateImage(context));
581 CGContextRelease(context);
583 UIImage *cache([UIImage imageWithCGImage:ref]);
589 /*MSHook(id, SBImageCache$initWithName$forImageWidth$imageHeight$initialCapacity$, SBImageCache *self, SEL sel, NSString *name, unsigned width, unsigned height, unsigned capacity) {
590 //if ([name isEqualToString:@"icons"]) return nil;
591 return _SBImageCache$initWithName$forImageWidth$imageHeight$initialCapacity$(self, sel, name, width, height, capacity);
594 MSHook(void, SBIconModel$cacheImageForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
595 NSString *key([icon displayIdentifier]);
597 if (UIImage *image = [icon icon]) {
598 CGSize size = [image size];
599 if (size.width != 59 || size.height != 60) {
600 UIImage *cache($cacheForImage$(image));
601 [Cache_ setObject:cache forKey:key];
606 _SBIconModel$cacheImageForIcon$(self, sel, icon);
609 MSHook(void, SBIconModel$cacheImagesForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
610 /* XXX: do I /really/ have to do this? figure out how to cache the small icon! */
611 _SBIconModel$cacheImagesForIcon$(self, sel, icon);
613 NSString *key([icon displayIdentifier]);
615 if (UIImage *image = [icon icon]) {
616 CGSize size = [image size];
617 if (size.width != 59 || size.height != 60) {
618 UIImage *cache($cacheForImage$(image));
619 [Cache_ setObject:cache forKey:key];
625 MSHook(UIImage *, SBIconModel$getCachedImagedForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
626 NSString *key([icon displayIdentifier]);
627 if (UIImage *image = [Cache_ objectForKey:key])
630 return _SBIconModel$getCachedImagedForIcon$(self, sel, icon);
633 MSHook(UIImage *, SBIconModel$getCachedImagedForIcon$smallIcon$, SBIconModel *self, SEL sel, SBIcon *icon, BOOL small) {
635 return _SBIconModel$getCachedImagedForIcon$smallIcon$(self, sel, icon, small);
636 NSString *key([icon displayIdentifier]);
637 if (UIImage *image = [Cache_ objectForKey:key])
640 return _SBIconModel$getCachedImagedForIcon$smallIcon$(self, sel, icon, small);
643 MSHook(id, SBSearchView$initWithFrame$, id /* XXX: SBSearchView */ self, SEL sel, struct CGRect frame) {
644 if ((self = _SBSearchView$initWithFrame$(self, sel, frame)) != nil) {
645 [self setBackgroundColor:[UIColor clearColor]];
646 for (UIView *child in [self subviews])
647 [child setBackgroundColor:[UIColor clearColor]];
651 MSHook(id, SBSearchTableViewCell$initWithStyle$reuseIdentifier$, SBSearchTableViewCell *self, SEL sel, int style, NSString *reuse) {
652 if ((self = _SBSearchTableViewCell$initWithStyle$reuseIdentifier$(self, sel, style, reuse)) != nil) {
653 [self setBackgroundColor:[UIColor clearColor]];
657 MSHook(void, SBSearchTableViewCell$drawRect$, SBSearchTableViewCell *self, SEL sel, struct CGRect rect, BOOL selected) {
658 _SBSearchTableViewCell$drawRect$(self, sel, rect, selected);
659 float inset([self edgeInset]);
660 [[UIColor clearColor] set];
661 UIRectFill(CGRectMake(0, 0, inset, rect.size.height));
662 UIRectFill(CGRectMake(rect.size.width - inset, 0, inset, rect.size.height));
665 MSHook(UIImage *, SBApplicationIcon$icon, SBApplicationIcon *self, SEL sel) {
666 if (![Info_ wb$boolForKey:@"ComposeStoreIcons"])
667 if (NSString *path = $pathForIcon$([self application]))
668 return [UIImage imageWithContentsOfFile:path];
669 return _SBApplicationIcon$icon(self, sel);
672 MSHook(UIImage *, SBApplicationIcon$generateIconImage$, SBApplicationIcon *self, SEL sel, int type) {
674 if (![Info_ wb$boolForKey:@"ComposeStoreIcons"]) {
675 if (IsWild_ && false) // XXX: delete this code, it should not be supported
676 if (NSString *path72 = $pathForIcon$([self application], @"-72"))
677 return [UIImage imageWithContentsOfFile:path72];
678 if (NSString *path = $pathForIcon$([self application]))
679 if (UIImage *image = [UIImage imageWithContentsOfFile:path]) {
681 if ([$SBIcon respondsToSelector:@selector(defaultIconImageSize)])
682 width = [$SBIcon defaultIconImageSize].width;
685 return width == 59 ? image : [image _imageScaledToProportion:(width / 59.0) interpolationQuality:5];
688 return _SBApplicationIcon$generateIconImage$(self, sel, type);
691 MSHook(UIImage *, SBWidgetApplicationIcon$icon, SBWidgetApplicationIcon *self, SEL sel) {
693 NSLog(@"WB:Debug:Widget(%@:%@)", [self displayIdentifier], [self displayName]);
694 if (NSString *path = $getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Icons/%@.png", [self displayName]]]))
695 return [UIImage imageWithContentsOfFile:path];
696 return _SBWidgetApplicationIcon$icon(self, sel);
699 MSHook(UIImage *, SBBookmarkIcon$icon, SBBookmarkIcon *self, SEL sel) {
701 NSLog(@"WB:Debug:Bookmark(%@:%@)", [self displayIdentifier], [self displayName]);
702 if (NSString *path = $getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Icons/%@.png", [self displayName]]]))
703 return [UIImage imageWithContentsOfFile:path];
704 return _SBBookmarkIcon$icon(self, sel);
707 MSHook(NSString *, SBApplication$pathForIcon, SBApplication *self, SEL sel) {
708 if (NSString *path = $pathForIcon$(self))
710 return _SBApplication$pathForIcon(self, sel);
713 static UIImage *CachedImageAtPath(NSString *path) {
714 path = [path stringByResolvingSymlinksInPath];
715 UIImage *image = [Images_ objectForKey:path];
717 return reinterpret_cast<id>(image) == [NSNull null] ? nil : image;
718 image = [[UIImage alloc] initWithContentsOfFile:path cache:true];
720 image = [image autorelease];
721 [Images_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:path];
725 MSHook(UIImage *, _UIApplicationImageWithName, NSString *name) {
726 NSBundle *bundle = [NSBundle mainBundle];
728 NSLog(@"WB:Debug: _UIApplicationImageWithName(\"%@\", %@)", name, bundle);
729 if (NSString *path = $pathForFile$inBundle$(name, bundle, false))
730 return CachedImageAtPath(path);
731 return __UIApplicationImageWithName(name);
734 #define WBDelegate(delegate) \
735 - (NSMethodSignature*) methodSignatureForSelector:(SEL)sel { \
737 NSLog(@"WB:MS:%s:(%s)", class_getName([self class]), sel_getName(sel)); \
738 if (NSMethodSignature *sig = [delegate methodSignatureForSelector:sel]) \
740 NSLog(@"WB:Error: [%s methodSignatureForSelector:(%s)]", class_getName([self class]), sel_getName(sel)); \
744 - (void) forwardInvocation:(NSInvocation*)inv { \
745 SEL sel = [inv selector]; \
746 if ([delegate respondsToSelector:sel]) \
747 [inv invokeWithTarget:delegate]; \
749 NSLog(@"WB:Error: [%s forwardInvocation:(%s)]", class_getName([self class]), sel_getName(sel)); \
752 // %hook CFBundleCopyResourceURL {{{
753 MSHook(CFURLRef, CFBundleCopyResourceURL, CFBundleRef bundle, CFStringRef resourceName, CFStringRef resourceType, CFStringRef subDirName) {
754 NSString *file((NSString *) resourceName);
755 if (resourceType != NULL)
756 file = [NSString stringWithFormat:@"%@.%@", file, resourceType];
757 if (subDirName != NULL)
758 file = [NSString stringWithFormat:@"%@/%@", subDirName, resourceType];
760 if (![file hasSuffix:@".png"]) {
762 NSLog(@"WB:Debug: CFBundleCopyResourceURL(<%@>, \"%@\", \"%@\", \"%@\")", CFBundleGetIdentifier(bundle), resourceName, resourceType, subDirName);
763 if (NSString *path = $pathForFile$inBundle$(file, bundle, false))
764 return (CFURLRef) [[NSURL alloc] initFileURLWithPath:path];
767 return _CFBundleCopyResourceURL(bundle, resourceName, resourceType, subDirName);
771 static void $drawLabel$(NSString *label, CGRect rect, NSString *style, NSString *custom) {
772 bool ellipsis(false);
773 CGFloat max = rect.size.width - 11, width;
775 width = [(ellipsis ? [label stringByAppendingString:@"..."] : label) sizeWithStyle:style forWidth:320].width;
778 size_t length([label length]);
779 CGFloat spacing((width - max) / (length - 1));
781 if (spacing > 1.25) {
783 label = [label substringToIndex:(length - 1)];
787 style = [style stringByAppendingString:[NSString stringWithFormat:@"letter-spacing: -%f; ", spacing]];
791 label = [label stringByAppendingString:@"..."];
794 style = [style stringByAppendingString:custom];
796 CGSize size = [label sizeWithStyle:style forWidth:rect.size.width];
797 [label drawAtPoint:CGPointMake((rect.size.width - size.width) / 2 + rect.origin.x, rect.origin.y) withStyle:style];
800 static struct WBStringDrawingState {
801 WBStringDrawingState *next_;
805 } *stringDrawingState_;
807 extern "C" CGColorSpaceRef CGContextGetFillColorSpace(CGContextRef);
808 extern "C" void CGContextGetFillColor(CGContextRef, CGFloat[]);
810 static NSString *WBColorMarkup(size_t number, const CGFloat *components) {
832 return [NSString stringWithFormat:@"color: rgba(%g, %g, %g, %g)", r * 255, g * 255, b * 255, a];
835 static NSString *WBColorMarkup() {
836 CGContextRef context(UIGraphicsGetCurrentContext());
837 //NSLog(@"XXX:1:%p", context);
841 CGColorSpaceRef space(CGContextGetFillColorSpace(context));
842 //NSLog(@"XXX:2:%p", space);
846 size_t number(CGColorSpaceGetNumberOfComponents(space));
847 //NSLog(@"XXX:3:%u", number);
851 CGFloat components[number + 1];
852 CGContextGetFillColor(context, components);
853 return WBColorMarkup(number, components);
856 static NSString *WBColorMarkup(UIColor *uicolor) {
859 CGColorRef cgcolor([uicolor CGColor]);
863 CGColorSpaceRef space(CGColorGetColorSpace(cgcolor));
864 //NSLog(@"XXX:2:%p", space);
868 size_t number(CGColorGetNumberOfComponents(cgcolor));
869 //NSLog(@"XXX:3:%u", number);
873 const CGFloat *components(CGColorGetComponents(cgcolor));
874 return WBColorMarkup(number, components);
877 extern "C" NSString *NSStringFromCGPoint(CGPoint rect);
879 MSInstanceMessage6(CGSize, NSString, drawAtPoint,forWidth,withFont,lineBreakMode,letterSpacing,includeEmoji, CGPoint, point, CGFloat, width, UIFont *, font, UILineBreakMode, mode, CGFloat, spacing, BOOL, emoji) {
880 //NSLog(@"XXX: @\"%@\" %@ %g \"%@\" %u %g %u", self, NSStringFromCGPoint(point), width, font, mode, spacing, emoji);
882 WBStringDrawingState *state(stringDrawingState_);
884 return MSOldCall(point, width, font, mode, spacing, emoji);
886 if (state->count_ != 0 && --state->count_ == 0)
887 stringDrawingState_ = state->next_;
888 if (state->info_ == nil)
889 return MSOldCall(point, width, font, mode, spacing, emoji);
891 NSString *info([Info_ objectForKey:state->info_]);
893 return MSOldCall(point, width, font, mode, spacing, emoji);
895 NSString *base(state->base_ ?: @"");
896 NSString *extra([NSString stringWithFormat:@"letter-spacing: %gpx", spacing]);
897 [self drawAtPoint:point withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info]];
901 extern "C" NSString *NSStringFromCGRect(CGRect rect);
903 MSInstanceMessageHook7(CGSize, NSString, _drawInRect,withFont,lineBreakMode,alignment,lineSpacing,includeEmoji,truncationRect, CGRect, rect, UIFont *, font, UILineBreakMode, mode, UITextAlignment, alignment, float, spacing, BOOL, emoji, CGRect, truncation) {
904 //NSLog(@"XXX: @\"%@\" %@ \"%@\" %u %u %g %u %@", self, NSStringFromCGRect(rect), font, mode, alignment, spacing, emoji, NSStringFromCGRect(truncation));
906 WBStringDrawingState *state(stringDrawingState_);
908 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
910 if (state->count_ != 0 && --state->count_ == 0)
911 stringDrawingState_ = state->next_;
912 if (state->info_ == nil)
913 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
915 NSString *info([Info_ objectForKey:state->info_]);
917 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
922 case UITextAlignmentLeft:
925 case UITextAlignmentCenter:
926 textAlign = @"center";
928 case UITextAlignmentRight:
929 textAlign = @"right";
933 NSString *base(state->base_ ?: @"");
934 NSString *extra([NSString stringWithFormat:@"text-align: %@", textAlign]);
937 $drawLabel$(self, rect, [NSString stringWithFormat:@"%@;%@;%@", [font markupDescription], WBColorMarkup(), base], info);
939 [self drawInRect:rect withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info]];
944 MSInstanceMessage2(void, NSString, drawInRect,withAttributes, CGRect, rect, NSDictionary *, attributes) {
945 //NSLog(@"XXX: *\"%@\" %@", self, attributes);
947 WBStringDrawingState *state(stringDrawingState_);
949 return MSOldCall(rect, attributes);
951 if (state->count_ != 0 && --state->count_ == 0)
952 stringDrawingState_ = state->next_;
953 if (state->info_ == nil)
954 return MSOldCall(rect, attributes);
956 NSString *info([Info_ objectForKey:state->info_]);
958 return MSOldCall(rect, attributes);
960 NSString *base(state->base_ ?: @"");
962 UIFont *font([attributes objectForKey:@"NSFont"]);
963 UIColor *color([attributes objectForKey:@"NSColor"]);
965 [self drawInRect:rect withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], WBColorMarkup(color), base, info]];
968 extern "C" NSString *NSStringFromCGSize(CGSize size);
970 MSInstanceMessage4(CGRect, NSString, boundingRectWithSize,options,attributes,context, CGSize, size, NSInteger, options, NSDictionary *, attributes, id, context) {
971 //NSLog(@"XXX: $\"%@\" %@ 0x%x %@ %@", self, NSStringFromCGSize(size), unsigned(options), attributes, context);
973 WBStringDrawingState *state(stringDrawingState_);
975 return MSOldCall(size, options, attributes, context);
977 if (state->count_ != 0 && --state->count_ == 0)
978 stringDrawingState_ = state->next_;
979 if (state->info_ == nil)
980 return MSOldCall(size, options, attributes, context);
982 NSString *info([Info_ objectForKey:state->info_]);
984 return MSOldCall(size, options, attributes, context);
986 NSString *base(state->base_ ?: @"");
988 UIFont *font([attributes objectForKey:@"NSFont"]);
989 UIColor *color([attributes objectForKey:@"NSColor"]);
991 return (CGRect) {{0, 0}, [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], WBColorMarkup(color), base, info] forWidth:size.width]};
994 MSInstanceMessage4(CGSize, NSString, sizeWithFont,forWidth,lineBreakMode,letterSpacing, UIFont *, font, CGFloat, width, UILineBreakMode, mode, CGFloat, spacing) {
995 //NSLog(@"XXX: #\"%@\" \"%@\" %g %u %g", self, font, width, mode, spacing);
997 WBStringDrawingState *state(stringDrawingState_);
999 return MSOldCall(font, width, mode, spacing);
1001 if (state->count_ != 0 && --state->count_ == 0)
1002 stringDrawingState_ = state->next_;
1003 if (state->info_ == nil)
1004 return MSOldCall(font, width, mode, spacing);
1006 NSString *info([Info_ objectForKey:state->info_]);
1008 return MSOldCall(font, width, mode, spacing);
1010 NSString *base(state->base_ ?: @"");
1011 NSString *extra([NSString stringWithFormat:@"letter-spacing: %gpx", spacing]);
1012 return [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info] forWidth:width];
1015 MSInstanceMessage1(CGSize, NSString, sizeWithFont, UIFont *, font) {
1016 //NSLog(@"XXX: ?\"%@\"", self);
1018 WBStringDrawingState *state(stringDrawingState_);
1020 return MSOldCall(font);
1022 if (state->count_ != 0 && --state->count_ == 0)
1023 stringDrawingState_ = state->next_;
1024 if (state->info_ == nil)
1025 return MSOldCall(font);
1027 NSString *info([Info_ objectForKey:state->info_]);
1029 return MSOldCall(font);
1031 NSString *base(state->base_ ?: @"");
1032 return [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), base, info] forWidth:65535];
1035 MSClassMessageHook2(id, SBIconBadgeView, checkoutAccessoryImagesForIcon,location, id, icon, int, location) {
1036 WBStringDrawingState badgeState = {NULL, 0, @""
1039 stringDrawingState_ = &badgeState;
1041 id images(MSOldCall(icon, location));
1043 stringDrawingState_ = NULL;
1047 MSClassMessageHook2(UIImage *, SBIconAccessoryImage, checkoutAccessoryImageForIcon,location, id, icon, int, location) {
1048 if ([self _imageClassForIcon:icon location:location] != $SBIconBadgeImage)
1049 return MSOldCall(icon, location);
1051 WBStringDrawingState badgeState = {NULL, 0, @""
1054 stringDrawingState_ = &badgeState;
1056 UIImage *image(MSOldCall(icon, location));
1058 stringDrawingState_ = NULL;
1062 MSInstanceMessageHook1(UIImage *, SBIconBadgeFactory, checkoutBadgeImageForText, NSString *, text) {
1063 WBStringDrawingState badgeState = {NULL, 0, @""
1066 stringDrawingState_ = &badgeState;
1068 UIImage *image(MSOldCall(text));
1070 stringDrawingState_ = NULL;
1074 MSInstanceMessageHook1(UIImage *, SBCalendarApplicationIcon, generateIconImage, int, type) {
1075 WBStringDrawingState dayState = {NULL, 2, @""
1076 // XXX: this is only correct on an iPod dock
1077 "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px;"
1078 , @"CalendarIconDayStyle"};
1080 WBStringDrawingState skipState = {&dayState,
1081 unsigned(kCFCoreFoundationVersionNumber > 800 ? 16 : 7)
1084 WBStringDrawingState dateState = {&skipState, 2, @""
1085 , @"CalendarIconDateStyle"};
1087 stringDrawingState_ = &dateState;
1089 UIImage *image(MSOldCall(type));
1091 stringDrawingState_ = NULL;
1095 MSInstanceMessageHook1(UIImage *, UIStatusBarTimeItemView, contentsImageForStyle, int, style) {
1096 WBStringDrawingState timeState = {NULL, 0, @""
1099 stringDrawingState_ = &timeState;
1101 UIImage *image(MSOldCall(style));
1103 stringDrawingState_ = NULL;
1107 MSHook(void, SBCalendarIconContentsView$drawRect$, SBCalendarIconContentsView *self, SEL sel, CGRect rect) {
1108 NSBundle *bundle([NSBundle mainBundle]);
1110 CFLocaleRef locale(CFLocaleCopyCurrent());
1111 CFDateFormatterRef formatter(CFDateFormatterCreate(NULL, locale, kCFDateFormatterNoStyle, kCFDateFormatterNoStyle));
1114 CFDateRef now(CFDateCreate(NULL, CFAbsoluteTimeGetCurrent()));
1116 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NUMBER_FORMAT" value:@"d" table:@"SpringBoard"]);
1117 CFStringRef date(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
1118 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NAME_FORMAT" value:@"cccc" table:@"SpringBoard"]);
1119 CFStringRef day(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
1123 CFRelease(formatter);
1125 NSString *datestyle([@""
1126 "font-family: Helvetica; "
1127 "font-weight: bold; "
1130 "" stringByAppendingString:(IsWild_
1131 ? @"font-size: 54px; "
1132 : @"font-size: 39px; "
1135 NSString *daystyle([@""
1136 "font-family: Helvetica; "
1137 "font-weight: bold; "
1139 "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px; "
1140 "" stringByAppendingString:(IsWild_
1141 ? @"font-size: 11px; "
1142 : @"font-size: 9px; "
1145 if (NSString *style = [Info_ objectForKey:@"CalendarIconDateStyle"])
1146 datestyle = [datestyle stringByAppendingString:style];
1147 if (NSString *style = [Info_ objectForKey:@"CalendarIconDayStyle"])
1148 daystyle = [daystyle stringByAppendingString:style];
1150 CGFloat width([self bounds].size.width);
1152 CGSize datesize = [(NSString *)date sizeWithStyle:datestyle forWidth:(width + leeway)];
1153 CGSize daysize = [(NSString *)day sizeWithStyle:daystyle forWidth:(width + leeway)];
1155 unsigned base0(IsWild_ ? 89 : 70);
1156 if ($GSFontGetUseLegacyFontMetrics())
1158 unsigned base1(IsWild_ ? 18 : 16);
1165 [(NSString *)date drawAtPoint:CGPointMake(
1166 (width + 1 - datesize.width) / 2, (base0 - datesize.height) / 2
1167 ) withStyle:datestyle];
1169 [(NSString *)day drawAtPoint:CGPointMake(
1170 (width + 1 - daysize.width) / 2, (base1 - daysize.height) / 2
1171 ) withStyle:daystyle];
1177 // %hook -[{NavigationBar,Toolbar} setBarStyle:] {{{
1178 void $setBarStyle$_(NSString *name, int &style) {
1180 NSLog(@"WB:Debug:%@Style:%d", name, style);
1181 NSNumber *number = nil;
1183 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style-%d", name, style]];
1185 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style", name]];
1186 if (number != nil) {
1187 style = [number intValue];
1189 NSLog(@"WB:Debug:%@Style=%d", name, style);
1193 MSInstanceMessageHook1(void, UIToolbar, setBarStyle, int, style) {
1194 $setBarStyle$_(@"Toolbar", style);
1195 return MSOldCall(style);
1198 MSInstanceMessageHook1(void, UINavigationBar, setBarStyle, int, style) {
1199 $setBarStyle$_(@"NavigationBar", style);
1200 return MSOldCall(style);
1204 MSHook(void, SBButtonBar$didMoveToSuperview, UIView *self, SEL sel) {
1205 [[self superview] setBackgroundColor:[UIColor clearColor]];
1206 _SBButtonBar$didMoveToSuperview(self, sel);
1209 MSHook(void, SBStatusBarContentsView$didMoveToSuperview, UIView *self, SEL sel) {
1210 [[self superview] setBackgroundColor:[UIColor clearColor]];
1211 _SBStatusBarContentsView$didMoveToSuperview(self, sel);
1214 static NSArray *Wallpapers_;
1215 static bool Papered_;
1216 static bool Docked_;
1217 static bool SMSBackgrounded_;
1218 static NSString *WallpaperFile_;
1219 static UIImageView *WallpaperImage_;
1220 static UIWebDocumentView *WallpaperPage_;
1221 static NSURL *WallpaperURL_;
1223 #define _release(object) \
1224 do if (object != nil) { \
1229 static UIImage *$getImage$(NSString *path) {
1230 UIImage *image([UIImage imageWithContentsOfFile:path]);
1232 unsigned scale($getScale$(path));
1233 if (scale != 1 && [image respondsToSelector:@selector(setScale)])
1234 [image setScale:scale];
1239 template <typename Original_, typename Modified_>
1240 _finline UIImage *WBCacheImage(const Modified_ &modified, const Original_ &original, NSString *key) {
1241 UIImage *image([Images_ objectForKey:key]);
1243 return reinterpret_cast<id>(image) == [NSNull null] ? original() : image;
1244 if (NSString *path = modified())
1245 image = $getImage$(path);
1246 [Images_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:key];
1247 return image == nil ? original() : image;
1250 static UIImage *$getDefaultDesktopImage$() {
1251 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"LockBackground.png", @"LockBackground.jpg", nil])))
1252 return $getImage$(path);
1256 MSClassMessageHook0(UIImage *, UIImage, defaultDesktopImage) {
1257 return $getDefaultDesktopImage$() ?: MSOldCall();
1260 MSInstanceMessageHook0(UIImage *, SBSlidingAlertDisplay, _defaultDesktopImage) {
1261 return $getDefaultDesktopImage$() ?: MSOldCall();
1264 MSInstanceMessageHook0(void, SBWallpaperView, resetCurrentImageToWallpaper) {
1265 for (UIView *parent([self superview]); parent != nil; parent = [parent superview])
1266 if ([parent isKindOfClass:$SBSlidingAlertDisplay]) {
1267 if (UIImage *image = $getDefaultDesktopImage$()) {
1268 [self setImage:image];
1278 // %hook -[SBUIController init] {{{
1279 MSInstanceMessageHook0(id, SBUIController, init) {
1284 NSString *paper($getTheme$(Wallpapers_));
1286 paper = [paper stringByDeletingLastPathComponent];
1289 NSLog(@"WB:Debug:Info = %@", [Info_ description]);
1292 UIImageView *&_wallpaperView(MSHookIvar<UIImageView *>(self, "_wallpaperView"));
1293 if (&_wallpaperView != NULL) {
1294 [_wallpaperView removeFromSuperview];
1295 [_wallpaperView release];
1296 _wallpaperView = nil;
1300 UIView *&_contentLayer(MSHookIvar<UIView *>(self, "_contentLayer"));
1301 UIView *&_contentView(MSHookIvar<UIView *>(self, "_contentView"));
1304 if (&_contentLayer != NULL)
1305 player = &_contentLayer;
1306 else if (&_contentView != NULL)
1307 player = &_contentView;
1310 UIView *layer(player == NULL ? nil : *player);
1312 UIWindow *window([[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]);
1313 UIView *content([[[UIView alloc] initWithFrame:[window frame]] autorelease]);
1314 [window setContentView:content];
1316 UIWindow *&_window(MSHookIvar<UIWindow *>(self, "_window"));
1317 [window setBackgroundColor:[_window backgroundColor]];
1318 [_window setBackgroundColor:[UIColor clearColor]];
1320 [window setLevel:-1000];
1321 [window setHidden:NO];
1323 /*if (player != NULL)
1324 *player = content;*/
1326 [content setBackgroundColor:[layer backgroundColor]];
1327 [layer setBackgroundColor:[UIColor clearColor]];
1330 if (!SummerBoard_ || !IsWild_)
1333 CGRect bounds([content bounds]);
1334 bounds.origin.y = -30;
1335 indirect = [[[UIView alloc] initWithFrame:bounds] autorelease];
1336 [content addSubview:indirect];
1337 [indirect zoomToScale:2.4];
1340 _release(WallpaperFile_);
1341 _release(WallpaperImage_);
1342 _release(WallpaperPage_);
1343 _release(WallpaperURL_);
1346 NSArray *themes([NSArray arrayWithObject:paper]);
1348 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"], themes)) {
1352 static AVController *controller_(nil);
1353 if (controller_ == nil) {
1354 AVQueue *queue([AVQueue avQueue]);
1355 controller_ = [[AVController avControllerWithQueue:queue error:&error] retain];
1358 AVQueue *queue([controller_ queue]);
1360 UIView *video([[[UIView alloc] initWithFrame:[indirect bounds]] autorelease]);
1361 [controller_ setLayer:[video _layer]];
1363 AVItem *item([[[AVItem alloc] initWithPath:path error:&error] autorelease]);
1364 [queue appendItem:item error:&error];
1366 [controller_ play:&error];
1367 #elif UseMPMoviePlayerController
1368 NSURL *url([NSURL fileURLWithPath:path]);
1369 MPMoviePlayerController *controller = [[$MPMoviePlayerController alloc] initWithContentURL:url];
1370 controller.movieControlMode = MPMovieControlModeHidden;
1373 MPVideoView *video = [[[$MPVideoView alloc] initWithFrame:[indirect bounds]] autorelease];
1374 [video setMovieWithPath:path];
1375 [video setRepeatMode:1];
1376 [video setRepeatGap:-1];
1377 [video playFromBeginning];;
1380 [indirect addSubview:video];
1383 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"Wallpaper.png", @"Wallpaper.jpg", nil]), themes)) {
1384 if (UIImage *image = $getImage$(path)) {
1385 WallpaperFile_ = [path retain];
1386 WallpaperImage_ = [[UIImageView alloc] initWithImage:image];
1387 if (NSNumber *number = [Info_ objectForKey:@"WallpaperAlpha"])
1388 [WallpaperImage_ setAlpha:[number floatValue]];
1389 [indirect addSubview:WallpaperImage_];
1393 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.html"], themes)) {
1394 CGRect bounds = [indirect bounds];
1396 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1397 [view setAutoresizes:true];
1399 WallpaperPage_ = [view retain];
1400 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
1402 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1404 [view setBackgroundColor:[UIColor clearColor]];
1405 if ([view respondsToSelector:@selector(setDrawsBackground:)])
1406 [view setDrawsBackground:NO];
1407 [[view webView] setDrawsBackground:NO];
1409 [indirect addSubview:view];
1413 for (size_t i(0), e([Themes_ count]); i != e; ++i) {
1414 NSString *theme = [Themes_ objectAtIndex:(e - i - 1)];
1415 NSString *html = [theme stringByAppendingPathComponent:@"Widget.html"];
1416 if ([Manager_ fileExistsAtPath:html]) {
1417 CGRect bounds = [indirect bounds];
1419 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1420 [view setAutoresizes:true];
1422 NSURL *url = [NSURL fileURLWithPath:html];
1423 [view loadRequest:[NSURLRequest requestWithURL:url]];
1425 [view setBackgroundColor:[UIColor clearColor]];
1426 if ([view respondsToSelector:@selector(setDrawsBackground:)])
1427 [view setDrawsBackground:NO];
1428 [[view webView] setDrawsBackground:NO];
1430 [indirect addSubview:view];
1438 MSHook(void, SBAwayView$updateDesktopImage$, SBAwayView *self, SEL sel, UIImage *image) {
1439 NSString *path = $getTheme$([NSArray arrayWithObject:@"LockBackground.html"]);
1440 UIView *&_backgroundView(MSHookIvar<UIView *>(self, "_backgroundView"));
1442 if (path != nil && _backgroundView != nil)
1445 _SBAwayView$updateDesktopImage$(self, sel, image);
1448 CGRect bounds = [self bounds];
1450 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1451 [view setAutoresizes:true];
1453 if (WallpaperPage_ != nil)
1454 [WallpaperPage_ release];
1455 WallpaperPage_ = [view retain];
1457 if (WallpaperURL_ != nil)
1458 [WallpaperURL_ release];
1459 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
1461 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1463 [[view webView] setDrawsBackground:false];
1464 [view setBackgroundColor:[UIColor clearColor]];
1466 [self insertSubview:view aboveSubview:_backgroundView];
1468 if ($objc_setAssociatedObject != NULL)
1469 $objc_setAssociatedObject(self, @selector(wb$widgetView), view, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1473 MSHook(void, SBAwayView$_addSubview$positioned$relativeTo$, SBAwayView *self, SEL sel, UIView *view, int positioned, UIView *relative) {
1474 UIView *&_backgroundView(MSHookIvar<UIView *>(self, "_backgroundView"));
1475 UIView *&_chargingView(MSHookIvar<UIView *>(self, "_chargingView"));
1476 if (&_chargingView != NULL)
1477 if (positioned == -2 && (relative == _backgroundView && _chargingView == nil || relative == _chargingView))
1478 if ($objc_getAssociatedObject != NULL)
1479 if (UIView *widget = $objc_getAssociatedObject(self, @selector(wb$widgetView)))
1481 return _SBAwayView$_addSubview$positioned$relativeTo$(self, sel, view, positioned, relative);
1484 /*extern "C" CGColorRef CGGStateGetSystemColor(void *);
1485 extern "C" CGColorRef CGGStateGetFillColor(void *);
1486 extern "C" CGColorRef CGGStateGetStrokeColor(void *);
1487 extern "C" NSString *UIStyleStringFromColor(CGColorRef);*/
1489 /* WBTimeLabel {{{ */
1490 @interface WBTimeLabel : NSProxy {
1492 _transient SBStatusBarTimeView *view_;
1495 - (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view;
1499 @implementation WBTimeLabel
1506 - (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view {
1507 time_ = [time retain];
1512 - (NSString *) description {
1518 - (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(UILineBreakMode)mode {
1519 if (NSString *custom = [Info_ objectForKey:@"TimeStyle"]) {
1520 BOOL &_mode(MSHookIvar<BOOL>(view_, "_mode"));;
1522 [time_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1523 "font-family: Helvetica; "
1524 "font-weight: bold; "
1527 "%@", _mode ? @"white" : @"black", custom]];
1532 return [time_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1537 /* WBBadgeLabel {{{ */
1538 @interface WBBadgeLabel : NSProxy {
1542 - (id) initWithBadge:(NSString *)badge;
1543 - (NSString *) description;
1547 @implementation WBBadgeLabel
1554 - (id) initWithBadge:(NSString *)badge {
1555 badge_ = [badge retain];
1559 - (NSString *) description {
1560 return [badge_ description];
1565 - (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(UILineBreakMode)mode {
1566 if (NSString *custom = [Info_ objectForKey:@"BadgeStyle"]) {
1567 [badge_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1568 "font-family: Helvetica; "
1569 "font-weight: bold; "
1577 return [badge_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1584 MSInstanceMessageHook1(void, SBIcon, setIconImageAlpha, CGFloat, alpha) {
1585 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1586 alpha = [number floatValue];
1587 return MSOldCall(alpha);
1590 MSInstanceMessageHook1(void, SBIcon, setIconLabelAlpha, CGFloat, alpha) {
1591 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1592 alpha = [number floatValue];
1593 return MSOldCall(alpha);
1596 MSInstanceMessageHook0(id, SBIcon, initWithDefaultSize) {
1597 if ((self = MSOldCall()) != nil) {
1598 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"]) {
1599 // XXX: note: this is overridden above, which is silly
1600 float alpha([number floatValue]);
1601 if ([self respondsToSelector:@selector(setIconImageAlpha:)])
1602 [self setIconImageAlpha:alpha];
1603 if ([self respondsToSelector:@selector(setIconLabelAlpha:)])
1604 [self setIconLabelAlpha:alpha];
1605 if ([self respondsToSelector:@selector(setAlpha:)])
1606 [self setAlpha:alpha];
1611 MSInstanceMessageHook1(void, SBIcon, setAlpha, CGFloat, alpha) {
1612 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1613 alpha = [number floatValue];
1614 return MSOldCall(alpha);
1618 MSHook(id, SBIconBadge$initWithBadge$, SBIconBadge *self, SEL sel, NSString *badge) {
1619 if ((self = _SBIconBadge$initWithBadge$(self, sel, badge)) != nil) {
1620 id &_badge(MSHookIvar<id>(self, "_badge"));
1622 if (id label = [[WBBadgeLabel alloc] initWithBadge:[_badge autorelease]])
1627 void SBStatusBarController$setStatusBarMode(int &mode) {
1629 NSLog(@"WB:Debug:setStatusBarMode:%d", mode);
1630 if (mode < 100) // 104:hidden 105:glowing
1631 if (NSNumber *number = [Info_ objectForKey:@"StatusBarMode"])
1632 mode = [number intValue];
1635 /*MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, double duration, int animation) {
1636 NSLog(@"mode:%d orientation:%d duration:%f animation:%d", mode, orientation, duration, animation);
1637 SBStatusBarController$setStatusBarMode(mode);
1638 return _SBStatusBarController$setStatusBarMode$orientation$duration$animation$(self, sel, mode, orientation, duration, animation);
1641 MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, float duration, int fenceID, int animation) {
1642 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d", mode, orientation, duration, fenceID, animation);
1643 SBStatusBarController$setStatusBarMode(mode);
1644 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$(self, sel, mode, orientation, duration, fenceID, animation);
1647 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) {
1648 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d startTime:%f", mode, orientation, duration, fenceID, animation, startTime);
1649 SBStatusBarController$setStatusBarMode(mode);
1650 //NSLog(@"mode=%u", mode);
1651 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$startTime$(self, sel, mode, orientation, duration, fenceID, animation, startTime);
1654 /*MSHook(id, SBStatusBarContentsView$initWithStatusBar$mode$, SBStatusBarContentsView *self, SEL sel, id bar, int mode) {
1655 if (NSNumber *number = [Info_ objectForKey:@"StatusBarContentsMode"])
1656 mode = [number intValue];
1657 return _SBStatusBarContentsView$initWithStatusBar$mode$(self, sel, bar, mode);
1660 MSHook(NSString *, SBStatusBarOperatorNameView$operatorNameStyle, SBStatusBarOperatorNameView *self, SEL sel) {
1661 NSString *style(_SBStatusBarOperatorNameView$operatorNameStyle(self, sel));
1663 NSLog(@"operatorNameStyle= %@", style);
1664 if (NSString *custom = [Info_ objectForKey:@"OperatorNameStyle"])
1665 style = [NSString stringWithFormat:@"%@; %@", style, custom];
1669 MSHook(void, SBStatusBarOperatorNameView$setOperatorName$fullSize$, SBStatusBarOperatorNameView *self, SEL sel, NSString *name, BOOL full) {
1671 NSLog(@"setOperatorName:\"%@\" fullSize:%u", name, full);
1672 return _SBStatusBarOperatorNameView$setOperatorName$fullSize$(self, sel, name, NO);
1675 // XXX: replace this with [SBStatusBarTimeView tile]
1676 MSHook(void, SBStatusBarTimeView$drawRect$, SBStatusBarTimeView *self, SEL sel, CGRect rect) {
1677 id &_time(MSHookIvar<id>(self, "_time"));
1678 if (_time != nil && [_time class] != [WBTimeLabel class])
1679 object_setInstanceVariable(self, "_time", reinterpret_cast<void *>([[WBTimeLabel alloc] initWithTime:[_time autorelease] view:self]));
1680 return _SBStatusBarTimeView$drawRect$(self, sel, rect);
1683 @interface UIView (WinterBoard)
1684 - (bool) wb$isWBImageView;
1685 - (void) wb$logHierarchy;
1686 - (void) wb$setBackgroundColor:(UIColor *)color;
1689 @implementation UIView (WinterBoard)
1691 - (bool) wb$isWBImageView {
1695 - (void) wb$logHierarchy {
1696 WBLogHierarchy(self);
1699 - (void) wb$setBackgroundColor:(UIColor *)color {
1700 [self setBackgroundColor:color];
1701 for (UIView *child in [self subviews])
1702 [child wb$setBackgroundColor:color];
1707 @interface WBImageView : UIImageView {
1710 - (bool) wb$isWBImageView;
1711 - (void) wb$updateFrame;
1714 @implementation WBImageView
1716 - (bool) wb$isWBImageView {
1720 - (void) wb$updateFrame {
1721 CGRect frame([self frame]);
1724 for (UIView *view(self); ; ) {
1725 view = [view superview];
1728 frame.origin.y -= [view frame].origin.y;
1731 [self setFrame:frame];
1736 static void SBIconList$updateFrames$(SBIconList *self) {
1737 NSArray *subviews([self subviews]);
1738 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1739 if (view != nil && [view wb$isWBImageView])
1740 [view wb$updateFrame];
1743 MSHook(void, SBIconList$didMoveToSuperview, SBIconList *self, SEL sel) {
1744 SBIconList$updateFrames$(self);
1745 _SBIconList$didMoveToSuperview(self, sel);
1748 MSHook(void, SBIconList$setFrame$, SBIconList *self, SEL sel, CGRect frame) {
1749 SBIconList$updateFrames$(self);
1750 _SBIconList$setFrame$(self, sel, frame);
1753 static void $addPerPageView$(unsigned i, UIView *list) {
1754 NSString *path($getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Page%u.png", i]]));
1758 NSArray *subviews([list subviews]);
1760 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1761 if (view == nil || ![view wb$isWBImageView]) {
1762 view = [[[WBImageView alloc] init] autorelease];
1763 [list insertSubview:view atIndex:0];
1766 UIImage *image([UIImage imageWithContentsOfFile:path]);
1768 CGRect frame([view frame]);
1769 frame.size = [image size];
1770 [view setFrame:frame];
1772 [view setImage:image];
1773 [view wb$updateFrame];
1776 static void $addPerPageViews$(NSArray *lists) {
1777 for (unsigned i(0), e([lists count]); i != e; ++i)
1778 $addPerPageView$(i, [lists objectAtIndex:i]);
1781 MSInstanceMessageHook0(void, SBIconController, updateNumberOfRootIconLists) {
1782 NSArray *&_rootIconLists(MSHookIvar<NSArray *>(self, "_rootIconLists"));
1783 $addPerPageViews$(_rootIconLists);
1787 MSInstanceMessageHook0(void, SBIconContentView, layoutSubviews) {
1790 if (SBIconController *controller = [$SBIconController sharedInstance]) {
1791 UIView *&_dockContainerView(MSHookIvar<UIView *>(controller, "_dockContainerView"));
1792 if (&_dockContainerView != NULL)
1793 [[_dockContainerView superview] bringSubviewToFront:_dockContainerView];
1797 MSHook(void, SBIconController$noteNumberOfIconListsChanged, SBIconController *self, SEL sel) {
1798 SBIconModel *&_iconModel(MSHookIvar<SBIconModel *>(self, "_iconModel"));
1799 $addPerPageViews$([_iconModel iconLists]);
1800 return _SBIconController$noteNumberOfIconListsChanged(self, sel);
1803 MSHook(id, SBIconLabel$initWithSize$label$, SBIconLabel *self, SEL sel, CGSize size, NSString *label) {
1804 self = _SBIconLabel$initWithSize$label$(self, sel, size, label);
1806 [self setClipsToBounds:NO];
1810 MSHook(void, SBIconLabel$setInDock$, SBIconLabel *self, SEL sel, BOOL docked) {
1811 static bool gssc(false);
1813 BOOL (*GSSystemHasCapability)(CFStringRef) = reinterpret_cast<BOOL (*)(CFStringRef)>(dlsym(RTLD_DEFAULT, "GSSystemHasCapability"));
1814 Papered_ |= GSSystemHasCapability != NULL && GSSystemHasCapability(CFSTR("homescreen-wallpaper"));
1817 if ([Info_ objectForKey:@"UndockedIconLabels"] == nil)
1818 [Info_ setObject:[NSNumber numberWithBool:(
1820 [Info_ objectForKey:@"DockedIconLabelStyle"] != nil ||
1821 [Info_ objectForKey:@"UndockedIconLabelStyle"] != nil
1822 )] forKey:@"UndockedIconLabels"];
1825 id &_label(MSHookIvar<id>(self, "_label"));
1826 if (![Info_ wb$boolForKey:@"UndockedIconLabels"])
1829 if (_label != nil && [_label respondsToSelector:@selector(setInDock:)])
1830 [_label setInDock:docked];
1832 _SBIconLabel$setInDock$(self, sel, docked);
1833 [self setNeedsDisplay];
1836 MSHook(BOOL, SBDockIconListView$shouldShowNewDock, id self, SEL sel) {
1837 return SummerBoard_ && Docked_ ? NO : _SBDockIconListView$shouldShowNewDock(self, sel);
1840 MSHook(void, SBDockIconListView$setFrame$, id self, SEL sel, CGRect frame) {
1841 _SBDockIconListView$setFrame$(self, sel, frame);
1844 // %hook -[NSBundle localizedStringForKey:value:table:] {{{
1845 MSInstanceMessageHook3(NSString *, NSBundle, localizedStringForKey,value,table, NSString *, key, NSString *, value, NSString *, table) {
1846 NSString *identifier = [self bundleIdentifier];
1847 NSLocale *locale = [NSLocale currentLocale];
1848 NSString *language = [locale objectForKey:NSLocaleLanguageCode];
1850 NSLog(@"WB:Debug:[NSBundle(%@) localizedStringForKey:\"%@\" value:\"%@\" table:\"%@\"] (%@)", identifier, key, value, table, language);
1851 NSString *file = table == nil ? @"Localizable" : table;
1852 NSString *name = [NSString stringWithFormat:@"%@:%@", identifier, file];
1853 NSDictionary *strings;
1854 if ((strings = [Strings_ objectForKey:name]) != nil) {
1855 if (static_cast<id>(strings) != [NSNull null]) strings:
1856 if (NSString *value = [strings objectForKey:key])
1858 } else if (NSString *path = $pathForFile$inBundle$([NSString stringWithFormat:@"%@.lproj/%@.strings",
1861 if ((strings = [[NSDictionary alloc] initWithContentsOfFile:path]) != nil) {
1862 [Strings_ setObject:[strings autorelease] forKey:name];
1866 [Strings_ setObject:[NSNull null] forKey:name];
1867 return MSOldCall(key, value, table);
1870 // %hook -[WebCoreFrameBridge renderedSizeOfNode:constrainedToWidth:] {{{
1871 MSClassHook(WebCoreFrameBridge)
1873 MSInstanceMessageHook2(CGSize, WebCoreFrameBridge, renderedSizeOfNode,constrainedToWidth, id, node, float, width) {
1876 void **core(reinterpret_cast<void **>([node _node]));
1877 if (core == NULL || core[6] == NULL)
1879 return MSOldCall(node, width);
1883 MSInstanceMessage1(void, SBIconLabel, drawRect, CGRect, rect) {
1884 static Ivar drawMoreLegibly = object_getInstanceVariable(self, "_drawMoreLegibly", NULL);
1887 Ivar ivar = object_getInstanceVariable(self, "_inDock", reinterpret_cast<void **>(&docked));
1888 docked = (docked & (ivar_getOffset(ivar) == ivar_getOffset(drawMoreLegibly) ? 0x2 : 0x1)) != 0;
1890 NSString *label(MSHookIvar<NSString *>(self, "_label"));
1892 NSString *style = [NSString stringWithFormat:@""
1893 "font-family: Helvetica; "
1894 "font-weight: bold; "
1896 "", (docked || !SummerBoard_ ? @"white" : @"#b3b3b3"), (IsWild_
1897 ? @"font-size: 12px; "
1898 : @"font-size: 11px; "
1902 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px 1px 0px; "];
1904 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px -1px 0px; "];
1906 NSString *custom([Info_ objectForKey:(docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle")]);
1908 $drawLabel$(label, [self bounds], style, custom);
1911 MSInstanceMessage0(CGImageRef, SBIconLabel, buildLabelImage) {
1912 bool docked((MSHookIvar<unsigned>(self, "_inDock") & 0x2) != 0);
1914 WBStringDrawingState labelState = {NULL, 0, @""
1915 , docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle"};
1917 stringDrawingState_ = &labelState;
1920 CGImageRef image(MSOldCall());
1923 stringDrawingState_ = NULL;
1927 static bool wb$inDock(id parameters) {
1928 return [$objc_getAssociatedObject(parameters, @selector(wb$inDock)) boolValue];
1931 MSInstanceMessage0(NSUInteger, SBIconLabelImageParameters, hash) {
1932 return MSOldCall() + (wb$inDock(self) ? 0xdeadbeef : 0xd15ea5e);
1935 MSClassMessage2(id, SBIconView, _labelImageParametersForIcon,location, id, icon, int, location) {
1936 if (id parameters = MSOldCall(icon, location)) {
1937 $objc_setAssociatedObject(parameters, @selector(wb$inDock), [NSNumber numberWithBool:(location == 1)], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1942 MSInstanceMessage0(id, SBIconView, _labelImageParameters) {
1943 if (id parameters = MSOldCall()) {
1944 int &location(MSHookIvar<int>(self, "_iconLocation"));
1945 if (&location != NULL)
1946 $objc_setAssociatedObject(parameters, @selector(wb$inDock), [NSNumber numberWithBool:(location == 3)], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1951 MSClassMessage1(UIImage *, SBIconLabelImage, _drawLabelImageForParameters, id, parameters) {
1952 bool docked(wb$inDock(parameters));
1954 WBStringDrawingState labelState = {NULL, 0, @""
1955 , docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle"};
1957 stringDrawingState_ = &labelState;
1960 UIImage *image(MSOldCall(parameters));
1963 stringDrawingState_ = NULL;
1968 MSInstanceMessageHook2(id, CKBalloonView, initWithFrame,delegate, CGRect, frame, id, delegate) {
1969 if ((self = MSOldCall(frame, delegate)) != nil) {
1970 [self setBackgroundColor:[UIColor clearColor]];
1974 MSInstanceMessageHook0(BOOL, CKBalloonView, _canUseLayerBackedBalloon) {
1975 return SMSBackgrounded_ ? NO : MSOldCall();
1978 MSInstanceMessageHook0(void, CKTranscriptHeaderView, layoutSubviews) {
1979 [self wb$setBackgroundColor:[UIColor clearColor]];
1983 MSInstanceMessageHook1(void, CKMessageCell, addBalloonView, CKBalloonView *, balloon) {
1985 [balloon setBackgroundColor:[UIColor clearColor]];
1988 MSInstanceMessageHook1(void, CKTranscriptCell, setBackgroundColor, UIColor *, color) {
1989 MSOldCall([UIColor clearColor]);
1990 [[self contentView] wb$setBackgroundColor:[UIColor clearColor]];
1994 MSInstanceMessageHook2(id, CKTranscriptCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1995 if ((self = MSOldCall(style, reuse)) != nil) {
1996 [self setBackgroundColor:[UIColor clearColor]];
1997 [[self contentView] wb$setBackgroundColor:[UIColor clearColor]];
2002 MSInstanceMessageHook2(id, CKMessageCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
2003 if ((self = MSOldCall(style, reuse)) != nil) {
2004 [self setBackgroundColor:[UIColor clearColor]];
2005 [[self contentView] setBackgroundColor:[UIColor clearColor]];
2009 MSInstanceMessageHook2(id, CKTimestampView, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
2010 if ((self = MSOldCall(style, reuse)) != nil) {
2011 UILabel *&_label(MSHookIvar<UILabel *>(self, "_label"));
2012 [_label setBackgroundColor:[UIColor clearColor]];
2016 MSInstanceMessageHook1(void, CKTranscriptTableView, setSeparatorStyle, int, style) {
2017 MSOldCall(UITableViewCellSeparatorStyleNone);
2020 MSInstanceMessageHook2(id, CKTranscriptTableView, initWithFrame,style, CGRect, frame, int, style) {
2021 if ((self = MSOldCall(frame, style)) != nil) {
2022 [self setSeparatorStyle:UITableViewCellSeparatorStyleNone];
2026 MSInstanceMessageHook0(void, CKTranscriptController, loadView) {
2029 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"SMSBackground.png", @"SMSBackground.jpg", nil])))
2030 if (UIImage *image = $getImage$(path)) {
2031 SMSBackgrounded_ = true;
2033 UIView *&_transcriptTable(MSHookIvar<UIView *>(self, "_transcriptTable"));
2034 UIView *&_transcriptLayer(MSHookIvar<UIView *>(self, "_transcriptLayer"));
2036 if (&_transcriptTable != NULL)
2037 table = _transcriptTable;
2038 else if (&_transcriptLayer != NULL)
2039 table = _transcriptLayer;
2043 UIView *placard(table != nil ? [table superview] : MSHookIvar<UIView *>(self, "_backPlacard"));
2044 UIImageView *background([[[UIImageView alloc] initWithImage:image] autorelease]);
2047 [placard insertSubview:background atIndex:0];
2049 [table setBackgroundColor:[UIColor clearColor]];
2050 [placard insertSubview:background belowSubview:table];
2056 template <typename Original_>
2057 static UIImage *WBCacheImage(NSBundle *bundle, NSString *name, const Original_ &original, NSString *key) {
2060 NSUInteger period([name rangeOfString:@"."].location);
2061 NSUInteger length([name length]);
2062 if (period == NSNotFound || length < 4 || period > length - 4)
2063 name = [name stringByAppendingString:@".png"];
2065 return WBCacheImage(
2066 [=](){ return $pathForFile$inBundle$(name, bundle, true); },
2067 [bundle, &original, name](){
2068 UIImage *image(original());
2069 if (image != nil && UIDebug_) {
2070 NSString *path([@"/tmp/WBImages/" stringByAppendingString:[bundle bundleIdentifier]]);
2071 [Manager_ createDirectoryAtPath:path withIntermediateDirectories:YES attributes:@{NSFilePosixPermissions: @0777} error:NULL];
2072 path = [NSString stringWithFormat:@"%@/%@", path, name];
2073 if (![Manager_ fileExistsAtPath:path])
2074 [UIImagePNGRepresentation(image) writeToFile:path atomically:YES];
2080 // %hook _UIImageWithName() {{{
2081 MSHook(UIImage *, _UIImageWithName, NSString *name) {
2085 NSLog(@"WB:Debug: _UIImageWithName(\"%@\")", name);
2086 return WBCacheImage(_UIKitBundle(), name,
2087 [=](){ return __UIImageWithName(name); },
2088 [NSString stringWithFormat:@"I:%@", name]);
2091 // %hook _UIImageWithNameInDomain() {{{
2092 MSHook(UIImage *, _UIImageWithNameInDomain, NSString *name, NSString *domain) {
2094 NSLog(@"WB:Debug: _UIImageWithNameInDomain(\"%@\", \"%@\")", name, domain);
2095 return WBCacheImage(
2096 [=](){ return $getTheme$($useScale$([NSArray arrayWithObject:[NSString stringWithFormat:@"Domains/%@/%@", domain, name]])); },
2097 [=](){ return __UIImageWithNameInDomain(name, domain); },
2098 [NSString stringWithFormat:@"D:%zu:%@%@", size_t([domain length]), domain, name]);
2102 // UISharedArtwork (iOS 6) {{{
2103 MSInstanceMessageHook2(UISharedArtwork *, UISharedArtwork, initWithName,inBundle, NSString *, name, NSBundle *, bundle) {
2104 if ((self = MSOldCall(name, bundle)) != nil) {
2105 $objc_setAssociatedObject(self, @selector(wb$bundle), bundle, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
2109 MSInstanceMessageHook2(UIImage *, UISharedArtwork, imageNamed,device, NSString *, name, NSInteger, device) {
2110 NSBundle *bundle($objc_getAssociatedObject(self, @selector(wb$bundle)));
2112 NSLog(@"WB:Debug: -[UISharedArtwork(%@) imageNamed:@\"%@\" device:%li]", [bundle bundleIdentifier], name, (long) device);
2113 return WBCacheImage(bundle, name,
2114 [=](){ return MSOldCall(name, device); },
2115 [NSString stringWithFormat:@"M:%p:%@:%li", self, name, (long) device]);
2118 // _UIAssetManager (iOS 7) {{{
2119 MSInstanceMessageHook3(_UIAssetManager *, _UIAssetManager, initWithName,inBundle,idiom, NSString *, name, NSBundle *, bundle, NSInteger, idiom) {
2120 if ((self = MSOldCall(name, bundle, idiom)) != nil) {
2121 $objc_setAssociatedObject(self, @selector(wb$bundle), bundle, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
2125 MSInstanceMessageHook5(UIImage *, _UIAssetManager, imageNamed,scale,idiom,subtype,cachingOptions, NSString *, name, CGFloat, scale, NSInteger, idiom, NSUInteger, subtype, NSUInteger, caching) {
2126 NSBundle *bundle($objc_getAssociatedObject(self, @selector(wb$bundle)));
2128 NSLog(@"WB:Debug: -[_UIAssetManager(%@/%@) imageNamed:@\"%@\" scale:%g idiom:%li subtype:%lu cachingOptions:%lu]",
2129 [bundle bundleIdentifier], [self carFileName],
2130 name, scale, (long) idiom,
2131 (unsigned long) subtype,
2132 (unsigned long) caching
2135 if (bundle == _UIKitBundle()) {
2136 NSString *name([self carFileName]);
2138 else if ([name isEqualToString:@"UIKit_NewArtwork"])
2139 bundle = [WBBundle bundleWithIdentifier:@"com.apple.uikit.Artwork"];
2140 else if ([name isEqualToString:@"UIKit_OriginalArtwork"])
2141 bundle = [WBBundle bundleWithIdentifier:@"com.apple.uikit.LegacyArtwork"];
2144 return WBCacheImage(bundle, name,
2145 [=](){ return MSOldCall(name, scale, idiom, subtype, caching); },
2146 [NSString stringWithFormat:@"M:%p:%@:%g:%li:%lu", self, name, scale, (long) idiom, (unsigned long) subtype]);
2149 // _UIAssetManager (iOS 8) {{{
2150 struct SizeClassPair {
2155 MSInstanceMessageHook7(UIImage *, _UIAssetManager, imageNamed,scale,idiom,subtype,cachingOptions,sizeClassPair,attachCatalogImage, NSString *, name, CGFloat, scale, NSInteger, idiom, NSUInteger, subtype, NSUInteger, caching, SizeClassPair, size, BOOL, attach) {
2156 NSBundle *bundle([self bundle]);
2158 NSLog(@"WB:Debug: -[_UIAssetManager(%@/%@) imageNamed:@\"%@\" scale:%g idiom:%li subtype:%lu cachingOptions:%lu sizeClassPair:[%li %li] attachCatalogImage:%s]",
2159 [bundle bundleIdentifier], [self carFileName],
2160 name, scale, (long) idiom,
2161 (unsigned long) subtype,
2162 (unsigned long) caching,
2163 (long) size.first, (long) size.second,
2164 attach ? "YES" : "NO"
2166 return WBCacheImage(bundle, name,
2167 [=](){ return MSOldCall(name, scale, idiom, subtype, caching, size, attach); },
2168 [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']);
2172 // %hook GSFontCreateWithName() {{{
2173 MSHook(GSFontRef, GSFontCreateWithName, const char *name, GSFontSymbolicTraits traits, float size) {
2175 NSLog(@"WB:Debug: GSFontCreateWithName(\"%s\", %f)", name, size);
2176 if (NSString *font = [Info_ objectForKey:[NSString stringWithFormat:@"FontName-%s", name]])
2177 name = [font UTF8String];
2178 //if (NSString *scale = [Info_ objectForKey:[NSString stringWithFormat:@"FontScale-%s", name]])
2179 // size *= [scale floatValue];
2180 return _GSFontCreateWithName(name, traits, size);
2184 #define AudioToolbox "/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox"
2186 static bool GetFileNameForThisAction$(bool value, unsigned long a0, char *a1, unsigned long a2, bool &a3) {
2188 NSLog(@"WB:Debug:GetFileNameForThisAction(%lu, %s, %lu, %u) = %u", a0, value ? a1 : NULL, a2, a3, value);
2191 NSString *path = [NSString stringWithUTF8String:a1];
2192 if ([path hasPrefix:@"/System/Library/Audio/UISounds/"]) {
2193 NSString *file = [path substringFromIndex:31];
2194 for (NSString *theme in Themes_) {
2195 NSString *path([NSString stringWithFormat:@"%@/UISounds/%@", theme, file]);
2196 if ([Manager_ fileExistsAtPath:path]) {
2197 strcpy(a1, [path UTF8String]);
2206 MSHook(bool, _Z24GetFileNameForThisActionmPcRb, unsigned long a0, char *a1, bool &a3) {
2207 bool value(__Z24GetFileNameForThisActionmPcRb(a0, a1, a3));
2208 return GetFileNameForThisAction$(value, a0, a1, 0, a3);
2212 MSHook(bool, _Z24GetFileNameForThisActionjPcjRb, unsigned int a0, char *a1, unsigned int a2, bool &a3) {
2213 bool value(__Z24GetFileNameForThisActionjPcjRb(a0, a1, a2, a3));
2214 return GetFileNameForThisAction$(value, a0, a1, a2, a3);
2217 MSHook(bool, _Z24GetFileNameForThisActionmPcmRb, unsigned long a0, char *a1, unsigned long a2, bool &a3) {
2218 bool value(__Z24GetFileNameForThisActionmPcmRb(a0, a1, a2, a3));
2219 return GetFileNameForThisAction$(value, a0, a1, a2, a3);
2223 static void ChangeWallpaper(
2224 CFNotificationCenterRef center,
2228 CFDictionaryRef info
2231 NSLog(@"WB:Debug:ChangeWallpaper!");
2234 if (WallpaperFile_ != nil) {
2235 image = [[UIImage alloc] initWithContentsOfFile:WallpaperFile_];
2237 image = [image autorelease];
2240 if (WallpaperImage_ != nil)
2241 [WallpaperImage_ setImage:image];
2242 if (WallpaperPage_ != nil)
2243 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
2247 MSHook(NSArray *, CPBitmapCreateImagesFromPath, NSString *path, CFTypeRef *names, void *arg2, void *arg3) {
2248 NSArray *images(_CPBitmapCreateImagesFromPath(path, names, arg2, arg3));
2254 NSBundle *bundle([NSBundle wb$bundleWithFile:path]);
2258 NSString *file([path stringByResolvingSymlinksInPath]);
2259 NSString *prefix([[bundle bundlePath] stringByResolvingSymlinksInPath]);
2260 // XXX: why do I care about this?
2261 if (![file hasPrefix:prefix])
2264 NSMutableArray *copy([images mutableCopy]);
2268 NSDictionary *indexes;
2269 NSEnumerator *enumerator;
2271 if (CFGetTypeID((CFTypeRef) *names) == CFDictionaryGetTypeID()) {
2272 indexes = (NSDictionary *) *names;
2273 enumerator = [indexes keyEnumerator];
2276 enumerator = [(NSArray *) *names objectEnumerator];
2279 for (NSUInteger index(0); NSString *name = [enumerator nextObject]; ++index)
2280 if (NSString *themed = $pathForFile$inBundle$([name stringByAppendingString:@".png"], bundle, true)) {
2282 index = [[indexes objectForKey:name] intValue];
2283 if (UIImage *image = $getImage$(themed))
2284 [copy replaceObjectAtIndex:index withObject:(id)[image CGImage]];
2290 MSHook(void, BKSDisplayServicesSetSystemAppExitedImagePath, NSString *path) {
2291 if (NSString *themed = $getTheme$($useScale$([NSArray arrayWithObject:@"SystemAppExited.png"])))
2293 _BKSDisplayServicesSetSystemAppExitedImagePath(path);
2296 #define WBRename(name, sel, imp) \
2297 MSHookMessage($ ## name, @selector(sel), &$ ## name ## $ ## imp, &_ ## name ## $ ## imp)
2299 template <typename Type_>
2300 static void msset(Type_ &function, MSImageRef image, const char *name) {
2301 function = reinterpret_cast<Type_>(MSFindSymbol(image, name));
2304 #define WBHookSymbol(image, function) \
2305 msset(function, image, "_" #function)
2307 template <typename Type_>
2308 static void dlset(Type_ &function, const char *name) {
2309 function = reinterpret_cast<Type_>(dlsym(RTLD_DEFAULT, name));
2312 // %hook CGImageReadCreateWithFile() {{{
2313 MSHook(void *, CGImageReadCreateWithFile, NSString *path, int flag) {
2315 NSLog(@"WB:Debug: CGImageReadCreateWithFile(%@, %d)", path, flag);
2316 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2317 void *value(_CGImageReadCreateWithFile([path wb$themedPath], flag));
2322 MSHook(void *, CGImageSourceCreateWithFile, NSString *path, NSDictionary *options) {
2324 NSLog(@"WB:Debug: CGImageSourceCreateWithFile(%@, %@)", path, options);
2325 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2326 void *value(_CGImageSourceCreateWithFile([path wb$themedPath], options));
2331 MSHook(void *, CGImageSourceCreateWithURL, NSURL *url, NSDictionary *options) {
2333 NSLog(@"WB:Debug: CGImageSourceCreateWithURL(%@, %@)", url, options);
2334 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2335 if ([url isFileURL])
2336 url = [NSURL fileURLWithPath:[[url path] wb$themedPath]];
2337 void *value(_CGImageSourceCreateWithURL(url, options));
2343 static void NSString$drawAtPoint$withStyle$(NSString *self, SEL _cmd, CGPoint point, NSString *style) {
2344 WKSetCurrentGraphicsContext(UIGraphicsGetCurrentContext());
2345 if (style == nil || [style length] == 0)
2346 style = @"font-family: Helvetica; font-size: 12px";
2347 //NSLog(@"XXX:drawP(%@ | %@)", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "]);
2348 [[WBMarkup sharedMarkup] drawString:self atPoint:point withStyle:style];
2351 static void NSString$drawInRect$withStyle$(NSString *self, SEL _cmd, CGRect rect, NSString *style) {
2352 WKSetCurrentGraphicsContext(UIGraphicsGetCurrentContext());
2353 if (style == nil || [style length] == 0)
2354 style = @"font-family: Helvetica; font-size: 12px";
2355 //NSLog(@"XXX:drawR(%@ | %@)", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "]);
2356 return [[WBMarkup sharedMarkup] drawString:self inRect:rect withStyle:style];
2359 static CGSize NSString$sizeWithStyle$forWidth$(NSString *self, SEL _cmd, NSString *style, CGFloat width) {
2360 if (style == nil || [style length] == 0)
2361 style = @"font-family: Helvetica; font-size: 12px";
2362 CGSize size([[WBMarkup sharedMarkup] sizeOfString:self withStyle:style forWidth:width]);
2363 //NSLog(@"XXX:size(%@ | %@) = [%g %g]", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "], size.width, size.height);
2367 static void SBInitialize() {
2369 WBRename(SBApplication, pathForIcon, pathForIcon);
2370 WBRename(SBApplicationIcon, icon, icon);
2371 WBRename(SBApplicationIcon, generateIconImage:, generateIconImage$);
2374 WBRename(SBBookmarkIcon, icon, icon);
2375 WBRename(SBButtonBar, didMoveToSuperview, didMoveToSuperview);
2376 WBRename(SBCalendarIconContentsView, drawRect:, drawRect$);
2377 WBRename(SBIconBadge, initWithBadge:, initWithBadge$);
2378 WBRename(SBIconController, noteNumberOfIconListsChanged, noteNumberOfIconListsChanged);
2380 WBRename(SBWidgetApplicationIcon, icon, icon);
2382 WBRename(SBDockIconListView, setFrame:, setFrame$);
2383 MSHookMessage(object_getClass($SBDockIconListView), @selector(shouldShowNewDock), &$SBDockIconListView$shouldShowNewDock, &_SBDockIconListView$shouldShowNewDock);
2385 if (kCFCoreFoundationVersionNumber < 600 || SummerBoard_)
2386 WBRename(SBIconLabel, drawRect:, drawRect$);
2387 else if (kCFCoreFoundationVersionNumber < 700) {
2388 WBRename(SBIconLabel, buildLabelImage, buildLabelImage);
2390 WBRename(SBIconLabelImageParameters, hash, hash);
2391 WBRename($SBIconView, _labelImageParametersForIcon:location:, _labelImageParametersForIcon$location$);
2392 WBRename(SBIconView, _labelImageParameters, _labelImageParameters);
2393 WBRename($SBIconLabelImage, _drawLabelImageForParameters:, _drawLabelImageForParameters$);
2396 WBRename(SBIconLabel, initWithSize:label:, initWithSize$label$);
2397 WBRename(SBIconLabel, setInDock:, setInDock$);
2399 WBRename(SBIconList, didMoveToSuperview, didMoveToSuperview);
2400 WBRename(SBIconList, setFrame:, setFrame$);
2402 WBRename(SBIconModel, cacheImageForIcon:, cacheImageForIcon$);
2403 WBRename(SBIconModel, cacheImagesForIcon:, cacheImagesForIcon$);
2404 WBRename(SBIconModel, getCachedImagedForIcon:, getCachedImagedForIcon$);
2405 WBRename(SBIconModel, getCachedImagedForIcon:smallIcon:, getCachedImagedForIcon$smallIcon$);
2407 if (kCFCoreFoundationVersionNumber < 800) {
2408 WBRename(SBSearchView, initWithFrame:, initWithFrame$);
2409 WBRename(SBSearchTableViewCell, drawRect:, drawRect$);
2410 WBRename(SBSearchTableViewCell, initWithStyle:reuseIdentifier:, initWithStyle$reuseIdentifier$);
2413 //WBRename(SBImageCache, initWithName:forImageWidth:imageHeight:initialCapacity:, initWithName$forImageWidth$imageHeight$initialCapacity$);
2415 WBRename(SBAwayView, updateDesktopImage:, updateDesktopImage$);
2416 if (kCFCoreFoundationVersionNumber >= 700)
2417 WBRename(SBAwayView, _addSubview:positioned:relativeTo:, _addSubview$positioned$relativeTo$);
2419 WBRename(SBStatusBarContentsView, didMoveToSuperview, didMoveToSuperview);
2420 //WBRename(SBStatusBarContentsView, initWithStatusBar:mode:, initWithStatusBar$mode$);
2421 //WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:animation:, setStatusBarMode$orientation$duration$animation$);
2422 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:, setStatusBarMode$orientation$duration$fenceID$animation$);
2423 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:startTime:, setStatusBarMode$orientation$duration$fenceID$animation$startTime$);
2424 WBRename(SBStatusBarOperatorNameView, operatorNameStyle, operatorNameStyle);
2425 WBRename(SBStatusBarOperatorNameView, setOperatorName:fullSize:, setOperatorName$fullSize$);
2426 WBRename(SBStatusBarTimeView, drawRect:, drawRect$);
2429 English_ = [[NSDictionary alloc] initWithContentsOfFile:@"/System/Library/CoreServices/SpringBoard.app/English.lproj/LocalizedApplicationNames.strings"];
2431 if (kCFCoreFoundationVersionNumber >= 800) {
2432 WBRename(NSString, drawInRect:withAttributes:, drawInRect$withAttributes$);
2433 WBRename(NSString, boundingRectWithSize:options:attributes:context:, boundingRectWithSize$options$attributes$context$);
2437 /*MSHook(int, open, const char *path, int oflag, mode_t mode) {
2438 int fd(_open(path, oflag, mode));
2440 static bool no(false);
2444 if (strstr(path, "/icon") != NULL)
2445 *reinterpret_cast<void *volatile *>(NULL) = NULL;
2447 if (fd == -1 && errno == EFAULT)
2448 NSLog(@"open(%p, %#x, %#o) = %d\n", path, oflag, mode, fd);
2450 NSLog(@"open(\"%s\", %#x, %#o) = %d\n", path, oflag, mode, fd);
2457 $objc_setAssociatedObject = reinterpret_cast<void (*)(id, void *, id value, objc_AssociationPolicy)>(dlsym(RTLD_DEFAULT, "objc_setAssociatedObject"));
2458 $objc_getAssociatedObject = reinterpret_cast<id (*)(id, void *)>(dlsym(RTLD_DEFAULT, "objc_getAssociatedObject"));
2459 $objc_removeAssociatedObjects = reinterpret_cast<void (*)(id)>(dlsym(RTLD_DEFAULT, "objc_removeAssociatedObjects"));
2461 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2463 NSString *identifier([[NSBundle mainBundle] bundleIdentifier]);
2464 SpringBoard_ = [identifier isEqualToString:@"com.apple.springboard"];
2466 Manager_ = [[NSFileManager defaultManager] retain];
2467 Themes_ = [[NSMutableArray alloc] initWithCapacity:8];
2469 dlset(_GSFontGetUseLegacyFontMetrics, "GSFontGetUseLegacyFontMetrics");
2471 // Initialize IsWild_ {{{
2473 sysctlbyname("hw.machine", NULL, &size, NULL, 0);
2474 char *machine = new char[size];
2476 if (sysctlbyname("hw.machine", machine, &size, NULL, 0) == -1) {
2477 perror("sysctlbyname(\"hw.machine\", ?)");
2482 IsWild_ = machine != NULL && strncmp(machine, "iPad", 4) == 0;
2484 // Load Settings.plist {{{
2485 if (NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"/User/Library/Preferences/com.saurik.WinterBoard.plist"]]) {
2486 if (kCFCoreFoundationVersionNumber >= 1000)
2487 SummerBoard_ = false;
2488 else if (NSNumber *value = [settings objectForKey:@"SummerBoard"])
2489 SummerBoard_ = [value boolValue];
2491 SummerBoard_ = true;
2493 if (NSNumber *value = [settings objectForKey:@"Debug"])
2494 Debug_ = [value boolValue];
2495 if (NSNumber *value = [settings objectForKey:@"RecordUI"])
2496 UIDebug_ = [value boolValue];
2498 NSArray *themes([settings objectForKey:@"Themes"]);
2500 if (NSString *theme = [settings objectForKey:@"Theme"])
2501 themes = [NSArray arrayWithObject:[NSDictionary dictionaryWithObjectsAndKeys:
2503 [NSNumber numberWithBool:true], @"Active",
2507 for (NSDictionary *theme in themes) {
2508 NSNumber *active([theme objectForKey:@"Active"]);
2509 if (![active boolValue])
2512 NSString *name([theme objectForKey:@"Name"]);
2516 #define testForTheme(format...) \
2518 NSString *path = [NSString stringWithFormat:format]; \
2519 if ([Manager_ fileExistsAtPath:path]) { \
2520 [Themes_ addObject:path]; \
2525 testForTheme(@"/Library/Themes/%@.theme", name)
2526 testForTheme(@"/Library/Themes/%@", name)
2527 testForTheme(@"%@/Library/SummerBoard/Themes/%@", NSHomeDirectory(), name)
2532 // Merge Info.plist {{{
2533 Info_ = [[NSMutableDictionary dictionaryWithCapacity:16] retain];
2535 for (NSString *theme in Themes_)
2536 if (NSDictionary *info = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"%@/Info.plist", theme]])
2537 for (NSString *key in [info allKeys])
2538 if ([Info_ objectForKey:key] == nil)
2539 [Info_ setObject:[info objectForKey:key] forKey:key];
2543 if (MSImageRef image = MSGetImageByName("/System/Library/PrivateFrameworks/AppSupport.framework/AppSupport")) {
2544 NSArray *(*CPBitmapCreateImagesFromPath)(NSString *, CFTypeRef *, void *, void *);
2545 msset(CPBitmapCreateImagesFromPath, image, "_CPBitmapCreateImagesFromPath");
2546 MSHookFunction(CPBitmapCreateImagesFromPath, MSHake(CPBitmapCreateImagesFromPath));
2550 if (MSImageRef image = MSGetImageByName(AudioToolbox)) {
2551 bool (*_Z24GetFileNameForThisActionmPcRb)(unsigned long, char *, bool &);
2552 msset(_Z24GetFileNameForThisActionmPcRb, image, "__Z24GetFileNameForThisActionmPcRb");
2553 MSHookFunction(_Z24GetFileNameForThisActionmPcRb, &$_Z24GetFileNameForThisActionmPcRb, &__Z24GetFileNameForThisActionmPcRb);
2556 bool (*_Z24GetFileNameForThisActionjPcjRb)(unsigned int, char *, unsigned int, bool &);
2557 msset(_Z24GetFileNameForThisActionjPcjRb, image, "__Z24GetFileNameForThisActionjPcjRb");
2558 MSHookFunction(_Z24GetFileNameForThisActionjPcjRb, &$_Z24GetFileNameForThisActionjPcjRb, &__Z24GetFileNameForThisActionjPcjRb);
2560 bool (*_Z24GetFileNameForThisActionmPcmRb)(unsigned long, char *, unsigned long, bool &);
2561 msset(_Z24GetFileNameForThisActionmPcmRb, image, "__Z24GetFileNameForThisActionmPcmRb");
2562 MSHookFunction(_Z24GetFileNameForThisActionmPcmRb, &$_Z24GetFileNameForThisActionmPcmRb, &__Z24GetFileNameForThisActionmPcmRb);
2566 // BackBoardServices {{{
2567 if (MSImageRef image = MSGetImageByName("/System/Library/PrivateFrameworks/BackBoardServices.framework/BackBoardServices")) {
2568 void (*BKSDisplayServicesSetSystemAppExitedImagePath)(NSString *path);
2569 msset(BKSDisplayServicesSetSystemAppExitedImagePath, image, "_BKSDisplayServicesSetSystemAppExitedImagePath");
2570 MSHookFunction(BKSDisplayServicesSetSystemAppExitedImagePath, MSHake(BKSDisplayServicesSetSystemAppExitedImagePath));
2575 MSHookFunction(CFBundleCopyResourceURL, MSHake(CFBundleCopyResourceURL));
2578 // GraphicsServices {{{
2580 MSHookFunction(&GSFontCreateWithName, &$GSFontCreateWithName, &_GSFontCreateWithName);
2584 MSImageRef imageio = MSGetImageByName("/System/Library/Frameworks/ImageIO.framework/ImageIO");
2585 if (imageio == NULL)
2586 imageio = MSGetImageByName("/System/Library/PrivateFrameworks/ImageIO.framework/ImageIO");
2587 if (MSImageRef image = imageio) {
2588 void *(*CGImageReadCreateWithFile)(NSString *, int) = NULL;
2589 if (kCFCoreFoundationVersionNumber > 700) // XXX: iOS 6.x
2590 CGImageReadCreateWithFile = NULL;
2592 msset(CGImageReadCreateWithFile, image, "_CGImageReadCreateWithFile");
2593 MSHookFunction(CGImageReadCreateWithFile, MSHake(CGImageReadCreateWithFile));
2596 if (CGImageReadCreateWithFile == NULL) {
2597 void *(*CGImageSourceCreateWithFile)(NSString *, NSDictionary *);
2598 msset(CGImageSourceCreateWithFile, image, "_CGImageSourceCreateWithFile");
2599 MSHookFunction(CGImageSourceCreateWithFile, MSHake(CGImageSourceCreateWithFile));
2601 void *(*CGImageSourceCreateWithURL)(NSURL *, NSDictionary *);
2602 msset(CGImageSourceCreateWithURL, image, "_CGImageSourceCreateWithURL");
2603 MSHookFunction(CGImageSourceCreateWithURL, MSHake(CGImageSourceCreateWithURL));
2609 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];
2610 Papered_ = $getTheme$(Wallpapers_) != nil;
2611 Docked_ = $getTheme$([NSArray arrayWithObjects:@"Dock.png", nil]) != nil;
2613 CFNotificationCenterAddObserver(
2614 CFNotificationCenterGetDarwinNotifyCenter(),
2615 NULL, &ChangeWallpaper, (CFStringRef) @"com.saurik.winterboard.lockbackground", NULL, CFNotificationSuspensionBehaviorCoalesce
2618 if ($getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"]) != nil) {
2619 NSBundle *MediaPlayer([NSBundle bundleWithPath:@"/System/Library/Frameworks/MediaPlayer.framework"]);
2620 if (MediaPlayer != nil)
2623 $MPMoviePlayerController = objc_getClass("MPMoviePlayerController");
2624 $MPVideoView = objc_getClass("MPVideoView");
2631 if (MSImageRef image = MSGetImageByName("/System/Library/Frameworks/UIKit.framework/UIKit")) {
2633 class_addMethod($NSString, @selector(drawAtPoint:withStyle:), (IMP) &NSString$drawAtPoint$withStyle$, "v40@0:8{CGPoint=dd}16@32");
2634 class_addMethod($NSString, @selector(drawInRect:withStyle:), (IMP) &NSString$drawInRect$withStyle$, "v56@0:8{CGRect={CGSize=dd}{CGSize=dd}}16@48");
2635 class_addMethod($NSString, @selector(sizeWithStyle:forWidth:), (IMP) &NSString$sizeWithStyle$forWidth$, "{CGSize=dd}32@0:8@16d24");
2637 class_addMethod($NSString, @selector(drawAtPoint:withStyle:), (IMP) &NSString$drawAtPoint$withStyle$, "v20@0:4{CGPoint=ff}8@16");
2638 class_addMethod($NSString, @selector(drawInRect:withStyle:), (IMP) &NSString$drawInRect$withStyle$, "v28@0:4{CGRect={CGSize=ff}{CGSize=ff}}8@24");
2639 class_addMethod($NSString, @selector(sizeWithStyle:forWidth:), (IMP) &NSString$sizeWithStyle$forWidth$, "{CGSize=ff}16@0:4@8f12");
2642 WBHookSymbol(image, _UIKitBundle);
2644 if (kCFCoreFoundationVersionNumber < 700)
2645 MSHookFunction(_UIImageWithName, MSHake(_UIImageWithName));
2647 WBHookSymbol(image, _UIApplicationImageWithName);
2648 MSHookFunction(_UIApplicationImageWithName, MSHake(_UIApplicationImageWithName));
2650 WBHookSymbol(image, _UIImageWithNameInDomain);
2651 MSHookFunction(_UIImageWithNameInDomain, MSHake(_UIImageWithNameInDomain));
2653 SEL includeEmoji(@selector(_legacy_drawAtPoint:forWidth:withFont:lineBreakMode:letterSpacing:includeEmoji:));
2654 if (![@"" respondsToSelector:includeEmoji])
2655 includeEmoji = @selector(drawAtPoint:forWidth:withFont:lineBreakMode:letterSpacing:includeEmoji:);
2656 MSHookMessage($NSString, includeEmoji, MSHake(NSString$drawAtPoint$forWidth$withFont$lineBreakMode$letterSpacing$includeEmoji$));
2658 SEL letterSpacing(@selector(_legacy_sizeWithFont:forWidth:lineBreakMode:letterSpacing:));
2659 if (![@"" respondsToSelector:letterSpacing])
2660 letterSpacing = @selector(sizeWithFont:forWidth:lineBreakMode:letterSpacing:);
2661 MSHookMessage($NSString, letterSpacing, MSHake(NSString$sizeWithFont$forWidth$lineBreakMode$letterSpacing$));
2663 SEL sizeWithFont(@selector(_legacy_sizeWithFont:));
2664 if (![@"" respondsToSelector:sizeWithFont])
2665 sizeWithFont = @selector(sizeWithFont:);
2666 MSHookMessage($NSString, sizeWithFont, MSHake(NSString$sizeWithFont$));
2670 //MSHookFunction(reinterpret_cast<int (*)(const char *, int, mode_t)>(&open), MSHake(open));