1 /* WinterBoard - Theme Manager for the iPhone
2 * Copyright (C) 2008-2014 Jay Freeman (saurik)
5 /* GNU Lesser General Public License, Version 3 {{{ */
7 * WinterBoard is free software: you can redistribute it and/or modify it under
8 * the terms of the GNU Lesser General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
12 * WinterBoard is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 * License for more details.
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with WinterBoard. If not, see <http://www.gnu.org/licenses/>.
27 #define _trace() do { \
28 struct timeval _ctv; \
29 gettimeofday(&_ctv, NULL); \
34 NSLog(@"%lu.%.6u[%f]:WB:_trace()@%s:%u[%s]\n", \
35 _ctv.tv_sec, _ctv.tv_usec, \
36 (_ctv.tv_sec - _ltv.tv_sec) + (_ctv.tv_usec - _ltv.tv_usec) / 1000000.0, \
37 __FILE__, __LINE__, __FUNCTION__\
44 #import <CoreFoundation/CoreFoundation.h>
45 #import <Foundation/Foundation.h>
46 #import <CoreGraphics/CoreGraphics.h>
47 #import <ImageIO/CGImageSource.h>
49 #import <Celestial/AVController.h>
50 #import <Celestial/AVItem.h>
51 #import <Celestial/AVQueue.h>
53 #include <substrate.h>
55 #import <UIKit/UIKit.h>
57 #import <SpringBoard/SBApplication.h>
58 #import <SpringBoard/SBApplicationIcon.h>
59 #import <SpringBoard/SBAppWindow.h>
60 #import <SpringBoard/SBAwayView.h>
61 #import <SpringBoard/SBBookmarkIcon.h>
62 #import <SpringBoard/SBButtonBar.h>
63 #import <SpringBoard/SBCalendarIconContentsView.h>
64 #import <SpringBoard/SBIconController.h>
65 #import <SpringBoard/SBIconLabel.h>
66 #import <SpringBoard/SBIconList.h>
67 #import <SpringBoard/SBIconModel.h>
68 #import <SpringBoard/SBImageCache.h>
69 // XXX: #import <SpringBoard/SBSearchView.h>
70 #import <SpringBoard/SBSearchTableViewCell.h>
71 #import <SpringBoard/SBStatusBarContentsView.h>
72 #import <SpringBoard/SBStatusBarController.h>
73 #import <SpringBoard/SBStatusBarOperatorNameView.h>
74 #import <SpringBoard/SBStatusBarTimeView.h>
75 #import <SpringBoard/SBUIController.h>
76 #import <SpringBoard/SBWidgetApplicationIcon.h>
78 #import <MobileSMS/mSMSMessageTranscriptController.h>
80 #import <MediaPlayer/MPMoviePlayerController.h>
81 #import <MediaPlayer/MPVideoView.h>
82 #import <MediaPlayer/MPVideoView-PlaybackControl.h>
84 #import <CoreGraphics/CGGeometry.h>
86 #import <ChatKit/CKMessageCell.h>
88 #include <sys/sysctl.h>
92 static void (*$objc_setAssociatedObject)(id object, void *key, id value, objc_AssociationPolicy policy);
93 static id (*$objc_getAssociatedObject)(id object, void *key);
94 static void (*$objc_removeAssociatedObjects)(id object);
100 Class $MPMoviePlayerController;
103 MSClassHook(NSBundle)
104 MSClassHook(NSString)
106 MSClassHook(_UIAssetManager)
108 MSMetaClassHook(UIImage)
109 MSClassHook(UINavigationBar)
110 MSClassHook(UISharedArtwork)
111 MSClassHook(UIToolbar)
112 MSClassHook(UIStatusBarTimeItemView)
113 MSClassHook(UIWebDocumentView)
115 MSClassHook(CKBalloonView)
116 MSClassHook(CKMessageCell)
117 MSClassHook(CKTimestampView)
118 MSClassHook(CKTranscriptCell)
119 MSClassHook(CKTranscriptController)
120 MSClassHook(CKTranscriptHeaderView)
121 MSClassHook(CKTranscriptTableView)
123 MSClassHook(SBApplication)
124 MSClassHook(SBApplicationIcon)
125 MSClassHook(SBAwayView)
126 MSClassHook(SBBookmarkIcon)
127 MSClassHook(SBButtonBar)
128 MSClassHook(SBCalendarApplicationIcon)
129 MSClassHook(SBCalendarIconContentsView)
130 MSClassHook(SBDockIconListView)
132 MSClassHook(SBIconAccessoryImage)
133 MSMetaClassHook(SBIconAccessoryImage)
134 MSClassHook(SBIconBadge)
135 MSClassHook(SBIconBadgeFactory)
136 MSClassHook(SBIconBadgeImage)
137 MSClassHook(SBIconBadgeView)
138 MSMetaClassHook(SBIconBadgeView)
139 MSClassHook(SBIconContentView)
140 MSClassHook(SBIconController)
141 MSClassHook(SBIconLabel)
142 MSClassHook(SBIconLabelImage)
143 MSMetaClassHook(SBIconLabelImage)
144 MSClassHook(SBIconLabelImageParameters)
145 MSClassHook(SBIconList)
146 MSClassHook(SBIconModel)
147 MSClassHook(SBIconView)
148 MSMetaClassHook(SBIconView)
149 //MSClassHook(SBImageCache)
150 MSClassHook(SBSearchView)
151 MSClassHook(SBSearchTableViewCell)
152 MSClassHook(SBSlidingAlertDisplay)
153 MSClassHook(SBStatusBarContentsView)
154 MSClassHook(SBStatusBarController)
155 MSClassHook(SBStatusBarOperatorNameView)
156 MSClassHook(SBStatusBarTimeView)
157 MSClassHook(SBUIController)
158 MSClassHook(SBWallpaperView)
159 MSClassHook(SBWidgetApplicationIcon)
161 extern "C" void WKSetCurrentGraphicsContext(CGContextRef);
163 static struct MSFixClass { MSFixClass() {
164 $UIWebDocumentView = objc_getClass("UIWebBrowserView") ?: $UIWebDocumentView;
165 $SBIcon = objc_getClass("SBIconView") ?: $SBIcon;
167 if ($SBIconList == nil)
168 $SBIconList = objc_getClass("SBIconListView");
169 if ($CKTranscriptController == nil)
170 $CKTranscriptController = objc_getClass("mSMSMessageTranscriptController");
174 static bool Four_($SBDockIconListView != nil);
176 @interface NSObject (wb$SBIconAccessoryImage)
177 + (Class) _imageClassForIcon:(SBIcon *)icon location:(int)location;
180 @interface NSDictionary (WinterBoard)
181 - (UIColor *) wb$colorForKey:(NSString *)key;
182 - (BOOL) wb$boolForKey:(NSString *)key;
185 @implementation NSDictionary (WinterBoard)
187 - (UIColor *) wb$colorForKey:(NSString *)key {
188 NSString *value = [self objectForKey:key];
195 - (BOOL) wb$boolForKey:(NSString *)key {
196 if (NSString *value = [self objectForKey:key])
197 return [value boolValue];
203 @interface _UIAssetManager : NSObject
204 - (NSBundle *) bundle;
205 - (NSString *) carFileName;
208 static BOOL (*_GSFontGetUseLegacyFontMetrics)();
209 #define $GSFontGetUseLegacyFontMetrics() \
210 (_GSFontGetUseLegacyFontMetrics == NULL ? YES : _GSFontGetUseLegacyFontMetrics())
212 static bool Debug_ = false;
213 static bool UIDebug_ = false;
214 static bool Engineer_ = false;
215 static bool SummerBoard_ = false;
216 static bool SpringBoard_;
218 static UIImage *(*_UIApplicationImageWithName)(NSString *name);
219 static UIImage *(*_UIImageWithNameInDomain)(NSString *name, NSString *domain);
220 static NSBundle *(*_UIKitBundle)();
222 static NSMutableDictionary *Images_ = [[NSMutableDictionary alloc] initWithCapacity:64];
223 static NSMutableDictionary *Cache_ = [[NSMutableDictionary alloc] initWithCapacity:64];
224 static NSMutableDictionary *Strings_ = [[NSMutableDictionary alloc] initWithCapacity:0];
225 static NSMutableDictionary *Bundles_ = [[NSMutableDictionary alloc] initWithCapacity:2];
227 static NSFileManager *Manager_;
228 static NSMutableArray *Themes_;
230 static NSDictionary *English_;
231 static NSMutableDictionary *Info_;
233 // @interface WBBundle {{{
234 @interface WBBundle : NSBundle {
235 NSString *identifier_;
238 + (WBBundle *) bundleWithIdentifier:(NSString *)identifier;
242 @implementation WBBundle
245 [identifier_ release];
246 return [super dealloc];
249 + (WBBundle *) bundleWithIdentifier:(NSString *)identifier {
250 return [[[self alloc] initWithIdentifier:identifier] autorelease];
253 - (id) initWithIdentifier:(NSString *)identifier {
254 if ((self = [super init]) != nil) {
255 identifier_ = [identifier retain];
259 - (NSString *) bundleIdentifier {
267 static NSMutableDictionary *Themed_ = [[NSMutableDictionary alloc] initWithCapacity:128];
269 static unsigned Scale_ = 0;
271 static unsigned $getScale$(NSString *path) {
272 NSString *name(path);
274 #define StripName(strip) \
275 if ([name hasSuffix:@ strip]) \
276 name = [name substringWithRange:NSMakeRange(0, [name length] - sizeof(strip) - 1)];
280 StripName("~iphone");
283 if ([name hasSuffix:@"@3x"])
285 if ([name hasSuffix:@"@2x"])
290 static NSArray *$useScale$(NSArray *files, bool use = true) {
291 if (use && Scale_ == 0) {
292 UIScreen *screen([UIScreen mainScreen]);
293 if ([screen respondsToSelector:@selector(scale)])
294 Scale_ = [screen scale];
299 NSString *idiom(IsWild_ ? @"ipad" : @"iphone");
301 NSMutableArray *scaled([NSMutableArray arrayWithCapacity:([files count] * 4)]);
303 for (NSString *file in files) {
304 NSString *base([file stringByDeletingPathExtension]);
305 NSString *extension([file pathExtension]);
308 for (unsigned scale(2); scale <= Scale_; ++scale) {
309 [scaled addObject:[NSString stringWithFormat:@"%@@%ux~%@.%@", base, scale, idiom, extension]];
310 [scaled addObject:[NSString stringWithFormat:@"%@@%ux.%@", base, scale, extension]];
313 [scaled addObject:[NSString stringWithFormat:@"%@~%@.%@", base, idiom, extension]];
315 // if (!IsWild_) <- support old themes
316 [scaled addObject:file];
317 } else if ([base hasSuffix: @"@2x"] || [base hasSuffix:@"@3x"]) {
318 [scaled addObject:[NSString stringWithFormat:@"%@~%@.%@", base, idiom, extension]];
319 [scaled addObject:file];
321 // XXX: this actually can't be used, as the person loading the file doesn't realize that the @2x changed
322 /*NSString *rest([base substringWithRange:NSMakeRange(0, [base length] - 3)]);
323 [scaled addObject:[NSString stringWithFormat:@"%@~%@.%@", rest, idiom, extension]];
324 [scaled addObject:[rest stringByAppendingPathExtension:extension]];*/
326 // XXX: this code isn't really complete
328 [scaled addObject:file];
330 if ([base hasSuffix:[NSString stringWithFormat:@"~%@", idiom]])
331 [scaled addObject:[[base substringWithRange:NSMakeRange(0, [base length] - 1 - [idiom length])] stringByAppendingPathExtension:extension]];
338 static NSString *$getTheme$(NSArray *files, NSArray *themes = Themes_) {
339 // XXX: this is not reasonable; OMG
342 @synchronized (Themed_) {
343 if (NSString *path = [Themed_ objectForKey:key])
344 return reinterpret_cast<id>(path) == [NSNull null] ? nil : path;
348 NSLog(@"WB:Debug: %@", [files description]);
352 for (NSString *theme in Themes_)
353 for (NSString *file in files) {
354 path = [NSString stringWithFormat:@"%@/%@", theme, file];
355 if ([Manager_ fileExistsAtPath:path]) {
356 if ([[Manager_ destinationOfSymbolicLinkAtPath:path error:NULL] isEqualToString:@"/"])
365 @synchronized (Themed_) {
366 [Themed_ setObject:(path == nil ? [NSNull null] : reinterpret_cast<id>(path)) forKey:key];
372 // $pathForFile$inBundle$() {{{
373 static void $pathForFile$inBundle$(NSMutableArray *names, NSString *file, NSString *identifier, NSURL *url) {
374 if (identifier != nil)
375 [names addObject:[NSString stringWithFormat:@"Bundles/%@/%@", identifier, file]];
376 if (NSString *folder = [url lastPathComponent]) {
377 [names addObject:[NSString stringWithFormat:@"Folders/%@/%@", folder, file]];
378 NSString *base([folder stringByDeletingPathExtension]);
379 if ([base hasSuffix:@"~iphone"])
380 [names addObject:[NSString stringWithFormat:@"Folders/%@.%@/%@", [base substringWithRange:NSMakeRange(0, [base length] - 7)], [folder pathExtension], file]];
381 if ([base hasSuffix:@"~ipad"])
382 [names addObject:[NSString stringWithFormat:@"Folders/%@.%@/%@", [base substringWithRange:NSMakeRange(0, [base length] - 5)], [folder pathExtension], file]];
385 #define remapResourceName(oldname, newname) \
386 else if ([file isEqualToString:(oldname)]) \
387 [names addObject:[NSString stringWithFormat:@"%@.png", newname]]; \
389 bool summer(SpringBoard_ && SummerBoard_);
391 if (identifier == nil);
392 else if ([identifier isEqualToString:@"com.apple.uikit.Artwork"])
393 $pathForFile$inBundle$(names, file, @"com.apple.UIKit", nil);
394 else if ([identifier isEqualToString:@"com.apple.uikit.LegacyArtwork"])
395 $pathForFile$inBundle$(names, file, @"com.apple.UIKit", nil);
396 else if ([identifier isEqualToString:@"com.apple.UIKit"])
397 [names addObject:[NSString stringWithFormat:@"UIImages/%@", file]];
398 else if ([identifier isEqualToString:@"com.apple.chatkit"])
399 $pathForFile$inBundle$(names, file, @"com.apple.MobileSMS", nil);
400 else if ([identifier isEqualToString:@"com.apple.calculator"])
401 [names addObject:[NSString stringWithFormat:@"Files/Applications/Calculator.app/%@", file]];
402 else if ([identifier isEqualToString:@"com.apple.Maps"] && [file isEqualToString:@"Icon-57@2x.png"])
403 [names addObject:[NSString stringWithFormat:@"Bundles/com.apple.Maps/icon.png"]];
405 remapResourceName(@"FSO_BG.png", @"StatusBar")
406 remapResourceName(Four_ ? @"SBDockBG-old.png" : @"SBDockBG.png", @"Dock")
407 remapResourceName(@"SBWeatherCelsius.png", @"Icons/Weather")
410 static NSString *$pathForFile$inBundle$(NSString *file, NSString *identifier, NSURL *url, bool use) {
411 NSMutableArray *names = [NSMutableArray arrayWithCapacity:8];
412 $pathForFile$inBundle$(names, file, identifier, url);
413 [names addObject:[NSString stringWithFormat:@"Fallback/%@", file]];
414 if (NSString *path = $getTheme$($useScale$(names, use)))
419 // XXX: this cannot be merged due to WBBundle
420 static NSString *$pathForFile$inBundle$(NSString *file, NSBundle *bundle, bool use) {
421 return $pathForFile$inBundle$(file, [bundle bundleIdentifier], [bundle bundleURL], use);
424 static NSString *$pathForFile$inBundle$(NSString *file, CFBundleRef bundle, bool use) {
425 NSString *identifier((NSString *) CFBundleGetIdentifier(bundle));
426 NSURL *url([(NSURL *) CFBundleCopyBundleURL(bundle) autorelease]);
427 return $pathForFile$inBundle$(file, identifier, url, use);
431 static NSString *$pathForIcon$(SBApplication *self, NSString *suffix = @"") {
432 NSString *identifier = [self bundleIdentifier];
433 NSString *path = [self path];
434 NSString *folder = [path lastPathComponent];
435 NSString *dname = [self displayName];
436 NSString *didentifier = [self displayIdentifier];
439 NSLog(@"WB:Debug: [SBApplication(%@:%@:%@:%@) pathForIcon]", identifier, folder, dname, didentifier);
441 NSMutableArray *names = [NSMutableArray arrayWithCapacity:8];
443 /* XXX: I might need to keep this for backwards compatibility
444 if (identifier != nil)
445 [names addObject:[NSString stringWithFormat:@"Bundles/%@/icon.png", identifier]];
447 [names addObject:[NSString stringWithFormat:@"Folders/%@/icon.png", folder]]; */
449 #define testForIcon(Name) \
450 if (NSString *name = Name) \
451 [names addObject:[NSString stringWithFormat:@"Icons%@/%@.png", suffix, name]];
453 if (![didentifier isEqualToString:identifier])
454 testForIcon(didentifier);
456 testForIcon(identifier);
459 if ([identifier isEqualToString:@"com.apple.MobileSMS"])
462 if (didentifier != nil) {
463 testForIcon([English_ objectForKey:didentifier]);
465 NSArray *parts = [didentifier componentsSeparatedByString:@"-"];
466 if ([parts count] != 1)
467 if (NSDictionary *english = [[[NSDictionary alloc] initWithContentsOfFile:[path stringByAppendingString:@"/English.lproj/UIRoleDisplayNames.strings"]] autorelease])
468 testForIcon([english objectForKey:[parts lastObject]]);
471 if (NSString *path = $getTheme$(names))
477 // -[NSBundle wb$bundleWithFile] {{{
478 @interface NSBundle (WinterBoard)
479 + (NSBundle *) wb$bundleWithFile:(NSString *)path;
482 @implementation NSBundle (WinterBoard)
484 + (NSBundle *) wb$bundleWithFile:(NSString *)path {
485 path = [path stringByDeletingLastPathComponent];
486 if (path == nil || [path length] == 0 || [path isEqualToString:@"/"])
490 @synchronized (Bundles_) {
491 bundle = [Bundles_ objectForKey:path];
494 if (reinterpret_cast<id>(bundle) == [NSNull null])
496 else if (bundle == nil) {
497 if ([Manager_ fileExistsAtPath:[path stringByAppendingPathComponent:@"Info.plist"]])
498 bundle = [NSBundle bundleWithPath:path];
500 bundle = [NSBundle wb$bundleWithFile:path];
502 NSLog(@"WB:Debug:PathBundle(%@, %@)", path, bundle);
504 @synchronized (Bundles_) {
505 [Bundles_ setObject:(bundle == nil ? [NSNull null] : reinterpret_cast<id>(bundle)) forKey:path];
514 // -[NSString wb$themedPath] {{{
515 @interface NSString (WinterBoard)
516 - (NSString *) wb$themedPath;
519 @implementation NSString (WinterBoard)
521 - (NSString *) wb$themedPath {
522 if ([self hasPrefix:@"/Library/Themes/"])
526 NSLog(@"WB:Debug:Bypass(\"%@\")", self);
528 if (NSBundle *bundle = [NSBundle wb$bundleWithFile:self]) {
529 NSString *file([self stringByResolvingSymlinksInPath]);
530 NSString *prefix([[bundle bundlePath] stringByResolvingSymlinksInPath]);
531 if ([file hasPrefix:prefix]) {
532 NSUInteger length([prefix length]);
533 if (length != [file length])
534 if (NSString *path = $pathForFile$inBundle$([file substringFromIndex:(length + 1)], bundle, false))
545 void WBLogRect(const char *tag, struct CGRect rect) {
546 NSLog(@"%s:{%f,%f+%f,%f}", tag, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
549 void WBLogHierarchy(UIView *view, unsigned index = 0, unsigned indent = 0) {
550 CGRect frame([view frame]);
551 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]);
553 for (UIView *child in [view subviews])
554 WBLogHierarchy(child, index++, indent + 1);
557 UIImage *$cacheForImage$(UIImage *image) {
558 CGColorSpaceRef space(CGColorSpaceCreateDeviceRGB());
559 CGRect rect = {CGPointMake(1, 1), [image size]};
560 CGSize size = {rect.size.width + 2, rect.size.height + 2};
562 CGContextRef context(CGBitmapContextCreate(NULL, size.width, size.height, 8, 4 * size.width, space, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst));
563 CGColorSpaceRelease(space);
565 CGContextDrawImage(context, rect, [image CGImage]);
566 CGImageRef ref(CGBitmapContextCreateImage(context));
567 CGContextRelease(context);
569 UIImage *cache([UIImage imageWithCGImage:ref]);
575 /*MSHook(id, SBImageCache$initWithName$forImageWidth$imageHeight$initialCapacity$, SBImageCache *self, SEL sel, NSString *name, unsigned width, unsigned height, unsigned capacity) {
576 //if ([name isEqualToString:@"icons"]) return nil;
577 return _SBImageCache$initWithName$forImageWidth$imageHeight$initialCapacity$(self, sel, name, width, height, capacity);
580 MSHook(void, SBIconModel$cacheImageForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
581 NSString *key([icon displayIdentifier]);
583 if (UIImage *image = [icon icon]) {
584 CGSize size = [image size];
585 if (size.width != 59 || size.height != 60) {
586 UIImage *cache($cacheForImage$(image));
587 [Cache_ setObject:cache forKey:key];
592 _SBIconModel$cacheImageForIcon$(self, sel, icon);
595 MSHook(void, SBIconModel$cacheImagesForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
596 /* XXX: do I /really/ have to do this? figure out how to cache the small icon! */
597 _SBIconModel$cacheImagesForIcon$(self, sel, icon);
599 NSString *key([icon displayIdentifier]);
601 if (UIImage *image = [icon icon]) {
602 CGSize size = [image size];
603 if (size.width != 59 || size.height != 60) {
604 UIImage *cache($cacheForImage$(image));
605 [Cache_ setObject:cache forKey:key];
611 MSHook(UIImage *, SBIconModel$getCachedImagedForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
612 NSString *key([icon displayIdentifier]);
613 if (UIImage *image = [Cache_ objectForKey:key])
616 return _SBIconModel$getCachedImagedForIcon$(self, sel, icon);
619 MSHook(UIImage *, SBIconModel$getCachedImagedForIcon$smallIcon$, SBIconModel *self, SEL sel, SBIcon *icon, BOOL small) {
621 return _SBIconModel$getCachedImagedForIcon$smallIcon$(self, sel, icon, small);
622 NSString *key([icon displayIdentifier]);
623 if (UIImage *image = [Cache_ objectForKey:key])
626 return _SBIconModel$getCachedImagedForIcon$smallIcon$(self, sel, icon, small);
629 MSHook(id, SBSearchView$initWithFrame$, id /* XXX: SBSearchView */ self, SEL sel, struct CGRect frame) {
630 if ((self = _SBSearchView$initWithFrame$(self, sel, frame)) != nil) {
631 [self setBackgroundColor:[UIColor clearColor]];
632 for (UIView *child in [self subviews])
633 [child setBackgroundColor:[UIColor clearColor]];
637 MSHook(id, SBSearchTableViewCell$initWithStyle$reuseIdentifier$, SBSearchTableViewCell *self, SEL sel, int style, NSString *reuse) {
638 if ((self = _SBSearchTableViewCell$initWithStyle$reuseIdentifier$(self, sel, style, reuse)) != nil) {
639 [self setBackgroundColor:[UIColor clearColor]];
643 MSHook(void, SBSearchTableViewCell$drawRect$, SBSearchTableViewCell *self, SEL sel, struct CGRect rect, BOOL selected) {
644 _SBSearchTableViewCell$drawRect$(self, sel, rect, selected);
645 float inset([self edgeInset]);
646 [[UIColor clearColor] set];
647 UIRectFill(CGRectMake(0, 0, inset, rect.size.height));
648 UIRectFill(CGRectMake(rect.size.width - inset, 0, inset, rect.size.height));
651 MSHook(UIImage *, SBApplicationIcon$icon, SBApplicationIcon *self, SEL sel) {
652 if (![Info_ wb$boolForKey:@"ComposeStoreIcons"])
653 if (NSString *path = $pathForIcon$([self application]))
654 return [UIImage imageWithContentsOfFile:path];
655 return _SBApplicationIcon$icon(self, sel);
658 MSHook(UIImage *, SBApplicationIcon$generateIconImage$, SBApplicationIcon *self, SEL sel, int type) {
660 if (![Info_ wb$boolForKey:@"ComposeStoreIcons"]) {
661 if (IsWild_ && false) // XXX: delete this code, it should not be supported
662 if (NSString *path72 = $pathForIcon$([self application], @"-72"))
663 return [UIImage imageWithContentsOfFile:path72];
664 if (NSString *path = $pathForIcon$([self application]))
665 if (UIImage *image = [UIImage imageWithContentsOfFile:path]) {
667 if ([$SBIcon respondsToSelector:@selector(defaultIconImageSize)])
668 width = [$SBIcon defaultIconImageSize].width;
671 return width == 59 ? image : [image _imageScaledToProportion:(width / 59.0) interpolationQuality:5];
674 return _SBApplicationIcon$generateIconImage$(self, sel, type);
677 MSHook(UIImage *, SBWidgetApplicationIcon$icon, SBWidgetApplicationIcon *self, SEL sel) {
679 NSLog(@"WB:Debug:Widget(%@:%@)", [self displayIdentifier], [self displayName]);
680 if (NSString *path = $getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Icons/%@.png", [self displayName]]]))
681 return [UIImage imageWithContentsOfFile:path];
682 return _SBWidgetApplicationIcon$icon(self, sel);
685 MSHook(UIImage *, SBBookmarkIcon$icon, SBBookmarkIcon *self, SEL sel) {
687 NSLog(@"WB:Debug:Bookmark(%@:%@)", [self displayIdentifier], [self displayName]);
688 if (NSString *path = $getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Icons/%@.png", [self displayName]]]))
689 return [UIImage imageWithContentsOfFile:path];
690 return _SBBookmarkIcon$icon(self, sel);
693 MSHook(NSString *, SBApplication$pathForIcon, SBApplication *self, SEL sel) {
694 if (NSString *path = $pathForIcon$(self))
696 return _SBApplication$pathForIcon(self, sel);
699 static UIImage *CachedImageAtPath(NSString *path) {
700 path = [path stringByResolvingSymlinksInPath];
701 UIImage *image = [Images_ objectForKey:path];
703 return reinterpret_cast<id>(image) == [NSNull null] ? nil : image;
704 image = [[UIImage alloc] initWithContentsOfFile:path cache:true];
706 image = [image autorelease];
707 [Images_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:path];
711 MSHook(UIImage *, _UIApplicationImageWithName, NSString *name) {
712 NSBundle *bundle = [NSBundle mainBundle];
714 NSLog(@"WB:Debug: _UIApplicationImageWithName(\"%@\", %@)", name, bundle);
715 if (NSString *path = $pathForFile$inBundle$(name, bundle, false))
716 return CachedImageAtPath(path);
717 return __UIApplicationImageWithName(name);
720 #define WBDelegate(delegate) \
721 - (NSMethodSignature*) methodSignatureForSelector:(SEL)sel { \
723 NSLog(@"WB:MS:%s:(%s)", class_getName([self class]), sel_getName(sel)); \
724 if (NSMethodSignature *sig = [delegate methodSignatureForSelector:sel]) \
726 NSLog(@"WB:Error: [%s methodSignatureForSelector:(%s)]", class_getName([self class]), sel_getName(sel)); \
730 - (void) forwardInvocation:(NSInvocation*)inv { \
731 SEL sel = [inv selector]; \
732 if ([delegate respondsToSelector:sel]) \
733 [inv invokeWithTarget:delegate]; \
735 NSLog(@"WB:Error: [%s forwardInvocation:(%s)]", class_getName([self class]), sel_getName(sel)); \
738 // %hook CFBundleCopyResourceURL {{{
739 MSHook(CFURLRef, CFBundleCopyResourceURL, CFBundleRef bundle, CFStringRef resourceName, CFStringRef resourceType, CFStringRef subDirName) {
740 NSString *file((NSString *) resourceName);
741 if (resourceType != NULL)
742 file = [NSString stringWithFormat:@"%@.%@", file, resourceType];
743 if (subDirName != NULL)
744 file = [NSString stringWithFormat:@"%@/%@", subDirName, resourceType];
747 NSLog(@"WB:Debug: CFBundleCopyResourceURL(<%@>, \"%@\", \"%@\", \"%@\")", CFBundleGetIdentifier(bundle), resourceName, resourceType, subDirName);
748 if (NSString *path = $pathForFile$inBundle$(file, bundle, false))
749 return (CFURLRef) [[NSURL alloc] initFileURLWithPath:path];
750 return _CFBundleCopyResourceURL(bundle, resourceName, resourceType, subDirName);
754 static void $drawLabel$(NSString *label, CGRect rect, NSString *style, NSString *custom) {
755 bool ellipsis(false);
756 CGFloat max = rect.size.width - 11, width;
758 width = [(ellipsis ? [label stringByAppendingString:@"..."] : label) sizeWithStyle:style forWidth:320].width;
761 size_t length([label length]);
762 CGFloat spacing((width - max) / (length - 1));
764 if (spacing > 1.25) {
766 label = [label substringToIndex:(length - 1)];
770 style = [style stringByAppendingString:[NSString stringWithFormat:@"letter-spacing: -%f; ", spacing]];
774 label = [label stringByAppendingString:@"..."];
777 style = [style stringByAppendingString:custom];
779 CGSize size = [label sizeWithStyle:style forWidth:rect.size.width];
780 [label drawAtPoint:CGPointMake((rect.size.width - size.width) / 2 + rect.origin.x, rect.origin.y) withStyle:style];
783 static struct WBStringDrawingState {
784 WBStringDrawingState *next_;
788 } *stringDrawingState_;
790 extern "C" CGColorSpaceRef CGContextGetFillColorSpace(CGContextRef);
791 extern "C" void CGContextGetFillColor(CGContextRef, CGFloat[]);
793 static NSString *WBColorMarkup(size_t number, const CGFloat *components) {
815 return [NSString stringWithFormat:@"color: rgba(%g, %g, %g, %g)", r * 255, g * 255, b * 255, a];
818 static NSString *WBColorMarkup() {
819 CGContextRef context(UIGraphicsGetCurrentContext());
820 //NSLog(@"XXX:1:%p", context);
824 CGColorSpaceRef space(CGContextGetFillColorSpace(context));
825 //NSLog(@"XXX:2:%p", space);
829 size_t number(CGColorSpaceGetNumberOfComponents(space));
830 //NSLog(@"XXX:3:%u", number);
834 CGFloat components[number + 1];
835 CGContextGetFillColor(context, components);
836 return WBColorMarkup(number, components);
839 static NSString *WBColorMarkup(UIColor *uicolor) {
842 CGColorRef cgcolor([uicolor CGColor]);
846 CGColorSpaceRef space(CGColorGetColorSpace(cgcolor));
847 //NSLog(@"XXX:2:%p", space);
851 size_t number(CGColorGetNumberOfComponents(cgcolor));
852 //NSLog(@"XXX:3:%u", number);
856 const CGFloat *components(CGColorGetComponents(cgcolor));
857 return WBColorMarkup(number, components);
860 extern "C" NSString *NSStringFromCGPoint(CGPoint rect);
862 MSInstanceMessage6(CGSize, NSString, drawAtPoint,forWidth,withFont,lineBreakMode,letterSpacing,includeEmoji, CGPoint, point, CGFloat, width, UIFont *, font, UILineBreakMode, mode, CGFloat, spacing, BOOL, emoji) {
863 //NSLog(@"XXX: @\"%@\" %@ %g \"%@\" %u %g %u", self, NSStringFromCGPoint(point), width, font, mode, spacing, emoji);
865 WBStringDrawingState *state(stringDrawingState_);
867 return MSOldCall(point, width, font, mode, spacing, emoji);
869 if (state->count_ != 0 && --state->count_ == 0)
870 stringDrawingState_ = state->next_;
871 if (state->info_ == nil)
872 return MSOldCall(point, width, font, mode, spacing, emoji);
874 NSString *info([Info_ objectForKey:state->info_]);
876 return MSOldCall(point, width, font, mode, spacing, emoji);
878 NSString *base(state->base_ ?: @"");
879 NSString *extra([NSString stringWithFormat:@"letter-spacing: %gpx", spacing]);
880 [self drawAtPoint:point withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info]];
884 extern "C" NSString *NSStringFromCGRect(CGRect rect);
886 MSInstanceMessageHook7(CGSize, NSString, _drawInRect,withFont,lineBreakMode,alignment,lineSpacing,includeEmoji,truncationRect, CGRect, rect, UIFont *, font, UILineBreakMode, mode, UITextAlignment, alignment, float, spacing, BOOL, emoji, CGRect, truncation) {
887 //NSLog(@"XXX: @\"%@\" %@ \"%@\" %u %u %g %u %@", self, NSStringFromCGRect(rect), font, mode, alignment, spacing, emoji, NSStringFromCGRect(truncation));
889 WBStringDrawingState *state(stringDrawingState_);
891 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
893 if (state->count_ != 0 && --state->count_ == 0)
894 stringDrawingState_ = state->next_;
895 if (state->info_ == nil)
896 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
898 NSString *info([Info_ objectForKey:state->info_]);
900 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
905 case UITextAlignmentLeft:
908 case UITextAlignmentCenter:
909 textAlign = @"center";
911 case UITextAlignmentRight:
912 textAlign = @"right";
916 NSString *base(state->base_ ?: @"");
917 NSString *extra([NSString stringWithFormat:@"text-align: %@", textAlign]);
920 $drawLabel$(self, rect, [NSString stringWithFormat:@"%@;%@;%@", [font markupDescription], WBColorMarkup(), base], info);
922 [self drawInRect:rect withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info]];
927 MSInstanceMessage2(void, NSString, drawInRect,withAttributes, CGRect, rect, NSDictionary *, attributes) {
928 //NSLog(@"XXX: *\"%@\" %@", self, attributes);
930 WBStringDrawingState *state(stringDrawingState_);
932 return MSOldCall(rect, attributes);
934 if (state->count_ != 0 && --state->count_ == 0)
935 stringDrawingState_ = state->next_;
936 if (state->info_ == nil)
937 return MSOldCall(rect, attributes);
939 NSString *info([Info_ objectForKey:state->info_]);
941 return MSOldCall(rect, attributes);
943 NSString *base(state->base_ ?: @"");
945 UIFont *font([attributes objectForKey:@"NSFont"]);
946 UIColor *color([attributes objectForKey:@"NSColor"]);
948 [self drawInRect:rect withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], WBColorMarkup(color), base, info]];
951 extern "C" NSString *NSStringFromCGSize(CGSize size);
953 MSInstanceMessage4(CGRect, NSString, boundingRectWithSize,options,attributes,context, CGSize, size, NSInteger, options, NSDictionary *, attributes, id, context) {
954 //NSLog(@"XXX: $\"%@\" %@ 0x%x %@ %@", self, NSStringFromCGSize(size), unsigned(options), attributes, context);
956 WBStringDrawingState *state(stringDrawingState_);
958 return MSOldCall(size, options, attributes, context);
960 if (state->count_ != 0 && --state->count_ == 0)
961 stringDrawingState_ = state->next_;
962 if (state->info_ == nil)
963 return MSOldCall(size, options, attributes, context);
965 NSString *info([Info_ objectForKey:state->info_]);
967 return MSOldCall(size, options, attributes, context);
969 NSString *base(state->base_ ?: @"");
971 UIFont *font([attributes objectForKey:@"NSFont"]);
972 UIColor *color([attributes objectForKey:@"NSColor"]);
974 return (CGRect) {{0, 0}, [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], WBColorMarkup(color), base, info] forWidth:size.width]};
977 MSInstanceMessage4(CGSize, NSString, sizeWithFont,forWidth,lineBreakMode,letterSpacing, UIFont *, font, CGFloat, width, UILineBreakMode, mode, CGFloat, spacing) {
978 //NSLog(@"XXX: #\"%@\" \"%@\" %g %u %g", self, font, width, mode, spacing);
980 WBStringDrawingState *state(stringDrawingState_);
982 return MSOldCall(font, width, mode, spacing);
984 if (state->count_ != 0 && --state->count_ == 0)
985 stringDrawingState_ = state->next_;
986 if (state->info_ == nil)
987 return MSOldCall(font, width, mode, spacing);
989 NSString *info([Info_ objectForKey:state->info_]);
991 return MSOldCall(font, width, mode, spacing);
993 NSString *base(state->base_ ?: @"");
994 NSString *extra([NSString stringWithFormat:@"letter-spacing: %gpx", spacing]);
995 return [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info] forWidth:width];
998 MSInstanceMessage1(CGSize, NSString, sizeWithFont, UIFont *, font) {
999 //NSLog(@"XXX: ?\"%@\"", self);
1001 WBStringDrawingState *state(stringDrawingState_);
1003 return MSOldCall(font);
1005 if (state->count_ != 0 && --state->count_ == 0)
1006 stringDrawingState_ = state->next_;
1007 if (state->info_ == nil)
1008 return MSOldCall(font);
1010 NSString *info([Info_ objectForKey:state->info_]);
1012 return MSOldCall(font);
1014 NSString *base(state->base_ ?: @"");
1015 return [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), base, info] forWidth:65535];
1018 MSClassMessageHook2(id, SBIconBadgeView, checkoutAccessoryImagesForIcon,location, id, icon, int, location) {
1019 WBStringDrawingState badgeState = {NULL, 0, @""
1022 stringDrawingState_ = &badgeState;
1024 id images(MSOldCall(icon, location));
1026 stringDrawingState_ = NULL;
1030 MSClassMessageHook2(UIImage *, SBIconAccessoryImage, checkoutAccessoryImageForIcon,location, id, icon, int, location) {
1031 if ([self _imageClassForIcon:icon location:location] != $SBIconBadgeImage)
1032 return MSOldCall(icon, location);
1034 WBStringDrawingState badgeState = {NULL, 0, @""
1037 stringDrawingState_ = &badgeState;
1039 UIImage *image(MSOldCall(icon, location));
1041 stringDrawingState_ = NULL;
1045 MSInstanceMessageHook1(UIImage *, SBIconBadgeFactory, checkoutBadgeImageForText, NSString *, text) {
1046 WBStringDrawingState badgeState = {NULL, 0, @""
1049 stringDrawingState_ = &badgeState;
1051 UIImage *image(MSOldCall(text));
1053 stringDrawingState_ = NULL;
1057 MSInstanceMessageHook1(UIImage *, SBCalendarApplicationIcon, generateIconImage, int, type) {
1058 WBStringDrawingState dayState = {NULL, 2, @""
1059 // XXX: this is only correct on an iPod dock
1060 "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px;"
1061 , @"CalendarIconDayStyle"};
1063 WBStringDrawingState skipState = {&dayState,
1064 unsigned(kCFCoreFoundationVersionNumber > 800 ? 16 : 7)
1067 WBStringDrawingState dateState = {&skipState, 2, @""
1068 , @"CalendarIconDateStyle"};
1070 stringDrawingState_ = &dateState;
1072 UIImage *image(MSOldCall(type));
1074 stringDrawingState_ = NULL;
1078 MSInstanceMessageHook1(UIImage *, UIStatusBarTimeItemView, contentsImageForStyle, int, style) {
1079 WBStringDrawingState timeState = {NULL, 0, @""
1082 stringDrawingState_ = &timeState;
1084 UIImage *image(MSOldCall(style));
1086 stringDrawingState_ = NULL;
1090 MSHook(void, SBCalendarIconContentsView$drawRect$, SBCalendarIconContentsView *self, SEL sel, CGRect rect) {
1091 NSBundle *bundle([NSBundle mainBundle]);
1093 CFLocaleRef locale(CFLocaleCopyCurrent());
1094 CFDateFormatterRef formatter(CFDateFormatterCreate(NULL, locale, kCFDateFormatterNoStyle, kCFDateFormatterNoStyle));
1097 CFDateRef now(CFDateCreate(NULL, CFAbsoluteTimeGetCurrent()));
1099 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NUMBER_FORMAT" value:@"d" table:@"SpringBoard"]);
1100 CFStringRef date(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
1101 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NAME_FORMAT" value:@"cccc" table:@"SpringBoard"]);
1102 CFStringRef day(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
1106 CFRelease(formatter);
1108 NSString *datestyle([@""
1109 "font-family: Helvetica; "
1110 "font-weight: bold; "
1113 "" stringByAppendingString:(IsWild_
1114 ? @"font-size: 54px; "
1115 : @"font-size: 39px; "
1118 NSString *daystyle([@""
1119 "font-family: Helvetica; "
1120 "font-weight: bold; "
1122 "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px; "
1123 "" stringByAppendingString:(IsWild_
1124 ? @"font-size: 11px; "
1125 : @"font-size: 9px; "
1128 if (NSString *style = [Info_ objectForKey:@"CalendarIconDateStyle"])
1129 datestyle = [datestyle stringByAppendingString:style];
1130 if (NSString *style = [Info_ objectForKey:@"CalendarIconDayStyle"])
1131 daystyle = [daystyle stringByAppendingString:style];
1133 CGFloat width([self bounds].size.width);
1135 CGSize datesize = [(NSString *)date sizeWithStyle:datestyle forWidth:(width + leeway)];
1136 CGSize daysize = [(NSString *)day sizeWithStyle:daystyle forWidth:(width + leeway)];
1138 unsigned base0(IsWild_ ? 89 : 70);
1139 if ($GSFontGetUseLegacyFontMetrics())
1141 unsigned base1(IsWild_ ? 18 : 16);
1148 [(NSString *)date drawAtPoint:CGPointMake(
1149 (width + 1 - datesize.width) / 2, (base0 - datesize.height) / 2
1150 ) withStyle:datestyle];
1152 [(NSString *)day drawAtPoint:CGPointMake(
1153 (width + 1 - daysize.width) / 2, (base1 - daysize.height) / 2
1154 ) withStyle:daystyle];
1160 // %hook -[{NavigationBar,Toolbar} setBarStyle:] {{{
1161 void $setBarStyle$_(NSString *name, int &style) {
1163 NSLog(@"WB:Debug:%@Style:%d", name, style);
1164 NSNumber *number = nil;
1166 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style-%d", name, style]];
1168 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style", name]];
1169 if (number != nil) {
1170 style = [number intValue];
1172 NSLog(@"WB:Debug:%@Style=%d", name, style);
1176 MSInstanceMessageHook1(void, UIToolbar, setBarStyle, int, style) {
1177 $setBarStyle$_(@"Toolbar", style);
1178 return MSOldCall(style);
1181 MSInstanceMessageHook1(void, UINavigationBar, setBarStyle, int, style) {
1182 $setBarStyle$_(@"NavigationBar", style);
1183 return MSOldCall(style);
1187 MSHook(void, SBButtonBar$didMoveToSuperview, UIView *self, SEL sel) {
1188 [[self superview] setBackgroundColor:[UIColor clearColor]];
1189 _SBButtonBar$didMoveToSuperview(self, sel);
1192 MSHook(void, SBStatusBarContentsView$didMoveToSuperview, UIView *self, SEL sel) {
1193 [[self superview] setBackgroundColor:[UIColor clearColor]];
1194 _SBStatusBarContentsView$didMoveToSuperview(self, sel);
1197 static NSArray *Wallpapers_;
1198 static bool Papered_;
1199 static bool Docked_;
1200 static bool SMSBackgrounded_;
1201 static NSString *WallpaperFile_;
1202 static UIImageView *WallpaperImage_;
1203 static UIWebDocumentView *WallpaperPage_;
1204 static NSURL *WallpaperURL_;
1206 #define _release(object) \
1207 do if (object != nil) { \
1212 static UIImage *$getImage$(NSString *path) {
1213 UIImage *image([UIImage imageWithContentsOfFile:path]);
1215 unsigned scale($getScale$(path));
1216 if (scale != 1 && [image respondsToSelector:@selector(setScale)])
1217 [image setScale:scale];
1222 template <typename Original_, typename Modified_>
1223 _finline UIImage *WBCacheImage(const Original_ &original, const Modified_ &modified, NSString *key) {
1224 UIImage *image([Images_ objectForKey:key]);
1226 return reinterpret_cast<id>(image) == [NSNull null] ? original() : image;
1227 if (NSString *path = modified())
1228 image = $getImage$(path);
1229 [Images_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:key];
1230 return image == nil ? original() : image;
1233 static UIImage *$getDefaultDesktopImage$() {
1234 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"LockBackground.png", @"LockBackground.jpg", nil])))
1235 return $getImage$(path);
1239 MSClassMessageHook0(UIImage *, UIImage, defaultDesktopImage) {
1240 return $getDefaultDesktopImage$() ?: MSOldCall();
1243 MSInstanceMessageHook0(UIImage *, SBSlidingAlertDisplay, _defaultDesktopImage) {
1244 return $getDefaultDesktopImage$() ?: MSOldCall();
1247 MSInstanceMessageHook0(void, SBWallpaperView, resetCurrentImageToWallpaper) {
1248 for (UIView *parent([self superview]); parent != nil; parent = [parent superview])
1249 if ([parent isKindOfClass:$SBSlidingAlertDisplay]) {
1250 if (UIImage *image = $getDefaultDesktopImage$()) {
1251 [self setImage:image];
1261 // %hook -[SBUIController init] {{{
1262 MSInstanceMessageHook0(id, SBUIController, init) {
1267 NSString *paper($getTheme$(Wallpapers_));
1269 paper = [paper stringByDeletingLastPathComponent];
1273 sysctlbyname("hw.machine", NULL, &size, NULL, 0);
1274 char *machine = new char[size];
1276 if (sysctlbyname("hw.machine", machine, &size, NULL, 0) == -1) {
1277 perror("sysctlbyname(\"hw.machine\", ?)");
1282 IsWild_ = machine != NULL && strncmp(machine, "iPad", 4) == 0;
1286 NSLog(@"WB:Debug:Info = %@", [Info_ description]);
1289 UIImageView *&_wallpaperView(MSHookIvar<UIImageView *>(self, "_wallpaperView"));
1290 if (&_wallpaperView != NULL) {
1291 [_wallpaperView removeFromSuperview];
1292 [_wallpaperView release];
1293 _wallpaperView = nil;
1297 UIView *&_contentLayer(MSHookIvar<UIView *>(self, "_contentLayer"));
1298 UIView *&_contentView(MSHookIvar<UIView *>(self, "_contentView"));
1301 if (&_contentLayer != NULL)
1302 player = &_contentLayer;
1303 else if (&_contentView != NULL)
1304 player = &_contentView;
1307 UIView *layer(player == NULL ? nil : *player);
1309 UIWindow *window([[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]);
1310 UIView *content([[[UIView alloc] initWithFrame:[window frame]] autorelease]);
1311 [window setContentView:content];
1313 UIWindow *&_window(MSHookIvar<UIWindow *>(self, "_window"));
1314 [window setBackgroundColor:[_window backgroundColor]];
1315 [_window setBackgroundColor:[UIColor clearColor]];
1317 [window setLevel:-1000];
1318 [window setHidden:NO];
1320 /*if (player != NULL)
1321 *player = content;*/
1323 [content setBackgroundColor:[layer backgroundColor]];
1324 [layer setBackgroundColor:[UIColor clearColor]];
1327 if (!SummerBoard_ || !IsWild_)
1330 CGRect bounds([content bounds]);
1331 bounds.origin.y = -30;
1332 indirect = [[[UIView alloc] initWithFrame:bounds] autorelease];
1333 [content addSubview:indirect];
1334 [indirect zoomToScale:2.4];
1337 _release(WallpaperFile_);
1338 _release(WallpaperImage_);
1339 _release(WallpaperPage_);
1340 _release(WallpaperURL_);
1343 NSArray *themes([NSArray arrayWithObject:paper]);
1345 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"], themes)) {
1349 static AVController *controller_(nil);
1350 if (controller_ == nil) {
1351 AVQueue *queue([AVQueue avQueue]);
1352 controller_ = [[AVController avControllerWithQueue:queue error:&error] retain];
1355 AVQueue *queue([controller_ queue]);
1357 UIView *video([[[UIView alloc] initWithFrame:[indirect bounds]] autorelease]);
1358 [controller_ setLayer:[video _layer]];
1360 AVItem *item([[[AVItem alloc] initWithPath:path error:&error] autorelease]);
1361 [queue appendItem:item error:&error];
1363 [controller_ play:&error];
1364 #elif UseMPMoviePlayerController
1365 NSURL *url([NSURL fileURLWithPath:path]);
1366 MPMoviePlayerController *controller = [[$MPMoviePlayerController alloc] initWithContentURL:url];
1367 controller.movieControlMode = MPMovieControlModeHidden;
1370 MPVideoView *video = [[[$MPVideoView alloc] initWithFrame:[indirect bounds]] autorelease];
1371 [video setMovieWithPath:path];
1372 [video setRepeatMode:1];
1373 [video setRepeatGap:-1];
1374 [video playFromBeginning];;
1377 [indirect addSubview:video];
1380 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"Wallpaper.png", @"Wallpaper.jpg", nil]), themes)) {
1381 if (UIImage *image = $getImage$(path)) {
1382 WallpaperFile_ = [path retain];
1383 WallpaperImage_ = [[UIImageView alloc] initWithImage:image];
1384 if (NSNumber *number = [Info_ objectForKey:@"WallpaperAlpha"])
1385 [WallpaperImage_ setAlpha:[number floatValue]];
1386 [indirect addSubview:WallpaperImage_];
1390 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.html"], themes)) {
1391 CGRect bounds = [indirect bounds];
1393 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1394 [view setAutoresizes:true];
1396 WallpaperPage_ = [view retain];
1397 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
1399 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1401 [view setBackgroundColor:[UIColor clearColor]];
1402 if ([view respondsToSelector:@selector(setDrawsBackground:)])
1403 [view setDrawsBackground:NO];
1404 [[view webView] setDrawsBackground:NO];
1406 [indirect addSubview:view];
1410 for (size_t i(0), e([Themes_ count]); i != e; ++i) {
1411 NSString *theme = [Themes_ objectAtIndex:(e - i - 1)];
1412 NSString *html = [theme stringByAppendingPathComponent:@"Widget.html"];
1413 if ([Manager_ fileExistsAtPath:html]) {
1414 CGRect bounds = [indirect bounds];
1416 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1417 [view setAutoresizes:true];
1419 NSURL *url = [NSURL fileURLWithPath:html];
1420 [view loadRequest:[NSURLRequest requestWithURL:url]];
1422 [view setBackgroundColor:[UIColor clearColor]];
1423 if ([view respondsToSelector:@selector(setDrawsBackground:)])
1424 [view setDrawsBackground:NO];
1425 [[view webView] setDrawsBackground:NO];
1427 [indirect addSubview:view];
1435 MSHook(void, SBAwayView$updateDesktopImage$, SBAwayView *self, SEL sel, UIImage *image) {
1436 NSString *path = $getTheme$([NSArray arrayWithObject:@"LockBackground.html"]);
1437 UIView *&_backgroundView(MSHookIvar<UIView *>(self, "_backgroundView"));
1439 if (path != nil && _backgroundView != nil)
1442 _SBAwayView$updateDesktopImage$(self, sel, image);
1445 CGRect bounds = [self bounds];
1447 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1448 [view setAutoresizes:true];
1450 if (WallpaperPage_ != nil)
1451 [WallpaperPage_ release];
1452 WallpaperPage_ = [view retain];
1454 if (WallpaperURL_ != nil)
1455 [WallpaperURL_ release];
1456 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
1458 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1460 [[view webView] setDrawsBackground:false];
1461 [view setBackgroundColor:[UIColor clearColor]];
1463 [self insertSubview:view aboveSubview:_backgroundView];
1465 if ($objc_setAssociatedObject != NULL)
1466 $objc_setAssociatedObject(self, @selector(wb$widgetView), view, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1470 MSHook(void, SBAwayView$_addSubview$positioned$relativeTo$, SBAwayView *self, SEL sel, UIView *view, int positioned, UIView *relative) {
1471 UIView *&_backgroundView(MSHookIvar<UIView *>(self, "_backgroundView"));
1472 UIView *&_chargingView(MSHookIvar<UIView *>(self, "_chargingView"));
1473 if (&_chargingView != NULL)
1474 if (positioned == -2 && (relative == _backgroundView && _chargingView == nil || relative == _chargingView))
1475 if ($objc_getAssociatedObject != NULL)
1476 if (UIView *widget = $objc_getAssociatedObject(self, @selector(wb$widgetView)))
1478 return _SBAwayView$_addSubview$positioned$relativeTo$(self, sel, view, positioned, relative);
1481 /*extern "C" CGColorRef CGGStateGetSystemColor(void *);
1482 extern "C" CGColorRef CGGStateGetFillColor(void *);
1483 extern "C" CGColorRef CGGStateGetStrokeColor(void *);
1484 extern "C" NSString *UIStyleStringFromColor(CGColorRef);*/
1486 /* WBTimeLabel {{{ */
1487 @interface WBTimeLabel : NSProxy {
1489 _transient SBStatusBarTimeView *view_;
1492 - (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view;
1496 @implementation WBTimeLabel
1503 - (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view {
1504 time_ = [time retain];
1509 - (NSString *) description {
1515 - (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(UILineBreakMode)mode {
1516 if (NSString *custom = [Info_ objectForKey:@"TimeStyle"]) {
1517 BOOL &_mode(MSHookIvar<BOOL>(view_, "_mode"));;
1519 [time_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1520 "font-family: Helvetica; "
1521 "font-weight: bold; "
1524 "%@", _mode ? @"white" : @"black", custom]];
1529 return [time_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1534 /* WBBadgeLabel {{{ */
1535 @interface WBBadgeLabel : NSProxy {
1539 - (id) initWithBadge:(NSString *)badge;
1540 - (NSString *) description;
1544 @implementation WBBadgeLabel
1551 - (id) initWithBadge:(NSString *)badge {
1552 badge_ = [badge retain];
1556 - (NSString *) description {
1557 return [badge_ description];
1562 - (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(UILineBreakMode)mode {
1563 if (NSString *custom = [Info_ objectForKey:@"BadgeStyle"]) {
1564 [badge_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1565 "font-family: Helvetica; "
1566 "font-weight: bold; "
1574 return [badge_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1581 MSInstanceMessageHook1(void, SBIcon, setIconImageAlpha, CGFloat, alpha) {
1582 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1583 alpha = [number floatValue];
1584 return MSOldCall(alpha);
1587 MSInstanceMessageHook1(void, SBIcon, setIconLabelAlpha, CGFloat, alpha) {
1588 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1589 alpha = [number floatValue];
1590 return MSOldCall(alpha);
1593 MSInstanceMessageHook0(id, SBIcon, initWithDefaultSize) {
1594 if ((self = MSOldCall()) != nil) {
1595 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"]) {
1596 // XXX: note: this is overridden above, which is silly
1597 float alpha([number floatValue]);
1598 if ([self respondsToSelector:@selector(setIconImageAlpha:)])
1599 [self setIconImageAlpha:alpha];
1600 if ([self respondsToSelector:@selector(setIconLabelAlpha:)])
1601 [self setIconLabelAlpha:alpha];
1602 if ([self respondsToSelector:@selector(setAlpha:)])
1603 [self setAlpha:alpha];
1608 MSInstanceMessageHook1(void, SBIcon, setAlpha, CGFloat, alpha) {
1609 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1610 alpha = [number floatValue];
1611 return MSOldCall(alpha);
1615 MSHook(id, SBIconBadge$initWithBadge$, SBIconBadge *self, SEL sel, NSString *badge) {
1616 if ((self = _SBIconBadge$initWithBadge$(self, sel, badge)) != nil) {
1617 id &_badge(MSHookIvar<id>(self, "_badge"));
1619 if (id label = [[WBBadgeLabel alloc] initWithBadge:[_badge autorelease]])
1624 void SBStatusBarController$setStatusBarMode(int &mode) {
1626 NSLog(@"WB:Debug:setStatusBarMode:%d", mode);
1627 if (mode < 100) // 104:hidden 105:glowing
1628 if (NSNumber *number = [Info_ objectForKey:@"StatusBarMode"])
1629 mode = [number intValue];
1632 /*MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, double duration, int animation) {
1633 NSLog(@"mode:%d orientation:%d duration:%f animation:%d", mode, orientation, duration, animation);
1634 SBStatusBarController$setStatusBarMode(mode);
1635 return _SBStatusBarController$setStatusBarMode$orientation$duration$animation$(self, sel, mode, orientation, duration, animation);
1638 MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, float duration, int fenceID, int animation) {
1639 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d", mode, orientation, duration, fenceID, animation);
1640 SBStatusBarController$setStatusBarMode(mode);
1641 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$(self, sel, mode, orientation, duration, fenceID, animation);
1644 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) {
1645 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d startTime:%f", mode, orientation, duration, fenceID, animation, startTime);
1646 SBStatusBarController$setStatusBarMode(mode);
1647 //NSLog(@"mode=%u", mode);
1648 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$startTime$(self, sel, mode, orientation, duration, fenceID, animation, startTime);
1651 /*MSHook(id, SBStatusBarContentsView$initWithStatusBar$mode$, SBStatusBarContentsView *self, SEL sel, id bar, int mode) {
1652 if (NSNumber *number = [Info_ objectForKey:@"StatusBarContentsMode"])
1653 mode = [number intValue];
1654 return _SBStatusBarContentsView$initWithStatusBar$mode$(self, sel, bar, mode);
1657 MSHook(NSString *, SBStatusBarOperatorNameView$operatorNameStyle, SBStatusBarOperatorNameView *self, SEL sel) {
1658 NSString *style(_SBStatusBarOperatorNameView$operatorNameStyle(self, sel));
1660 NSLog(@"operatorNameStyle= %@", style);
1661 if (NSString *custom = [Info_ objectForKey:@"OperatorNameStyle"])
1662 style = [NSString stringWithFormat:@"%@; %@", style, custom];
1666 MSHook(void, SBStatusBarOperatorNameView$setOperatorName$fullSize$, SBStatusBarOperatorNameView *self, SEL sel, NSString *name, BOOL full) {
1668 NSLog(@"setOperatorName:\"%@\" fullSize:%u", name, full);
1669 return _SBStatusBarOperatorNameView$setOperatorName$fullSize$(self, sel, name, NO);
1672 // XXX: replace this with [SBStatusBarTimeView tile]
1673 MSHook(void, SBStatusBarTimeView$drawRect$, SBStatusBarTimeView *self, SEL sel, CGRect rect) {
1674 id &_time(MSHookIvar<id>(self, "_time"));
1675 if (_time != nil && [_time class] != [WBTimeLabel class])
1676 object_setInstanceVariable(self, "_time", reinterpret_cast<void *>([[WBTimeLabel alloc] initWithTime:[_time autorelease] view:self]));
1677 return _SBStatusBarTimeView$drawRect$(self, sel, rect);
1680 @interface UIView (WinterBoard)
1681 - (bool) wb$isWBImageView;
1682 - (void) wb$logHierarchy;
1683 - (void) wb$setBackgroundColor:(UIColor *)color;
1686 @implementation UIView (WinterBoard)
1688 - (bool) wb$isWBImageView {
1692 - (void) wb$logHierarchy {
1693 WBLogHierarchy(self);
1696 - (void) wb$setBackgroundColor:(UIColor *)color {
1697 [self setBackgroundColor:color];
1698 for (UIView *child in [self subviews])
1699 [child wb$setBackgroundColor:color];
1704 @interface WBImageView : UIImageView {
1707 - (bool) wb$isWBImageView;
1708 - (void) wb$updateFrame;
1711 @implementation WBImageView
1713 - (bool) wb$isWBImageView {
1717 - (void) wb$updateFrame {
1718 CGRect frame([self frame]);
1721 for (UIView *view(self); ; ) {
1722 view = [view superview];
1725 frame.origin.y -= [view frame].origin.y;
1728 [self setFrame:frame];
1733 static void SBIconList$updateFrames$(SBIconList *self) {
1734 NSArray *subviews([self subviews]);
1735 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1736 if (view != nil && [view wb$isWBImageView])
1737 [view wb$updateFrame];
1740 MSHook(void, SBIconList$didMoveToSuperview, SBIconList *self, SEL sel) {
1741 SBIconList$updateFrames$(self);
1742 _SBIconList$didMoveToSuperview(self, sel);
1745 MSHook(void, SBIconList$setFrame$, SBIconList *self, SEL sel, CGRect frame) {
1746 SBIconList$updateFrames$(self);
1747 _SBIconList$setFrame$(self, sel, frame);
1750 static void $addPerPageView$(unsigned i, UIView *list) {
1751 NSString *path($getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Page%u.png", i]]));
1755 NSArray *subviews([list subviews]);
1757 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1758 if (view == nil || ![view wb$isWBImageView]) {
1759 view = [[[WBImageView alloc] init] autorelease];
1760 [list insertSubview:view atIndex:0];
1763 UIImage *image([UIImage imageWithContentsOfFile:path]);
1765 CGRect frame([view frame]);
1766 frame.size = [image size];
1767 [view setFrame:frame];
1769 [view setImage:image];
1770 [view wb$updateFrame];
1773 static void $addPerPageViews$(NSArray *lists) {
1774 for (unsigned i(0), e([lists count]); i != e; ++i)
1775 $addPerPageView$(i, [lists objectAtIndex:i]);
1778 MSInstanceMessageHook0(void, SBIconController, updateNumberOfRootIconLists) {
1779 NSArray *&_rootIconLists(MSHookIvar<NSArray *>(self, "_rootIconLists"));
1780 $addPerPageViews$(_rootIconLists);
1784 MSInstanceMessageHook0(void, SBIconContentView, layoutSubviews) {
1787 if (SBIconController *controller = [$SBIconController sharedInstance]) {
1788 UIView *&_dockContainerView(MSHookIvar<UIView *>(controller, "_dockContainerView"));
1789 if (&_dockContainerView != NULL)
1790 [[_dockContainerView superview] bringSubviewToFront:_dockContainerView];
1794 MSHook(void, SBIconController$noteNumberOfIconListsChanged, SBIconController *self, SEL sel) {
1795 SBIconModel *&_iconModel(MSHookIvar<SBIconModel *>(self, "_iconModel"));
1796 $addPerPageViews$([_iconModel iconLists]);
1797 return _SBIconController$noteNumberOfIconListsChanged(self, sel);
1800 MSHook(id, SBIconLabel$initWithSize$label$, SBIconLabel *self, SEL sel, CGSize size, NSString *label) {
1801 self = _SBIconLabel$initWithSize$label$(self, sel, size, label);
1803 [self setClipsToBounds:NO];
1807 MSHook(void, SBIconLabel$setInDock$, SBIconLabel *self, SEL sel, BOOL docked) {
1808 static bool gssc(false);
1810 BOOL (*GSSystemHasCapability)(CFStringRef) = reinterpret_cast<BOOL (*)(CFStringRef)>(dlsym(RTLD_DEFAULT, "GSSystemHasCapability"));
1811 Papered_ |= GSSystemHasCapability != NULL && GSSystemHasCapability(CFSTR("homescreen-wallpaper"));
1814 if ([Info_ objectForKey:@"UndockedIconLabels"] == nil)
1815 [Info_ setObject:[NSNumber numberWithBool:(
1817 [Info_ objectForKey:@"DockedIconLabelStyle"] != nil ||
1818 [Info_ objectForKey:@"UndockedIconLabelStyle"] != nil
1819 )] forKey:@"UndockedIconLabels"];
1822 id &_label(MSHookIvar<id>(self, "_label"));
1823 if (![Info_ wb$boolForKey:@"UndockedIconLabels"])
1826 if (_label != nil && [_label respondsToSelector:@selector(setInDock:)])
1827 [_label setInDock:docked];
1829 _SBIconLabel$setInDock$(self, sel, docked);
1830 [self setNeedsDisplay];
1833 MSHook(BOOL, SBDockIconListView$shouldShowNewDock, id self, SEL sel) {
1834 return SummerBoard_ && Docked_ ? NO : _SBDockIconListView$shouldShowNewDock(self, sel);
1837 MSHook(void, SBDockIconListView$setFrame$, id self, SEL sel, CGRect frame) {
1838 _SBDockIconListView$setFrame$(self, sel, frame);
1841 // %hook -[NSBundle localizedStringForKey:value:table:] {{{
1842 MSInstanceMessageHook3(NSString *, NSBundle, localizedStringForKey,value,table, NSString *, key, NSString *, value, NSString *, table) {
1843 NSString *identifier = [self bundleIdentifier];
1844 NSLocale *locale = [NSLocale currentLocale];
1845 NSString *language = [locale objectForKey:NSLocaleLanguageCode];
1847 NSLog(@"WB:Debug:[NSBundle(%@) localizedStringForKey:\"%@\" value:\"%@\" table:\"%@\"] (%@)", identifier, key, value, table, language);
1848 NSString *file = table == nil ? @"Localizable" : table;
1849 NSString *name = [NSString stringWithFormat:@"%@:%@", identifier, file];
1850 NSDictionary *strings;
1851 if ((strings = [Strings_ objectForKey:name]) != nil) {
1852 if (static_cast<id>(strings) != [NSNull null]) strings:
1853 if (NSString *value = [strings objectForKey:key])
1855 } else if (NSString *path = $pathForFile$inBundle$([NSString stringWithFormat:@"%@.lproj/%@.strings",
1858 if ((strings = [[NSDictionary alloc] initWithContentsOfFile:path]) != nil) {
1859 [Strings_ setObject:[strings autorelease] forKey:name];
1863 [Strings_ setObject:[NSNull null] forKey:name];
1864 return MSOldCall(key, value, table);
1867 // %hook -[WebCoreFrameBridge renderedSizeOfNode:constrainedToWidth:] {{{
1868 MSClassHook(WebCoreFrameBridge)
1870 MSInstanceMessageHook2(CGSize, WebCoreFrameBridge, renderedSizeOfNode,constrainedToWidth, id, node, float, width) {
1873 void **core(reinterpret_cast<void **>([node _node]));
1874 if (core == NULL || core[6] == NULL)
1876 return MSOldCall(node, width);
1880 MSInstanceMessage1(void, SBIconLabel, drawRect, CGRect, rect) {
1881 static Ivar drawMoreLegibly = object_getInstanceVariable(self, "_drawMoreLegibly", NULL);
1884 Ivar ivar = object_getInstanceVariable(self, "_inDock", reinterpret_cast<void **>(&docked));
1885 docked = (docked & (ivar_getOffset(ivar) == ivar_getOffset(drawMoreLegibly) ? 0x2 : 0x1)) != 0;
1887 NSString *label(MSHookIvar<NSString *>(self, "_label"));
1889 NSString *style = [NSString stringWithFormat:@""
1890 "font-family: Helvetica; "
1891 "font-weight: bold; "
1893 "", (docked || !SummerBoard_ ? @"white" : @"#b3b3b3"), (IsWild_
1894 ? @"font-size: 12px; "
1895 : @"font-size: 11px; "
1899 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px 1px 0px; "];
1901 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px -1px 0px; "];
1903 NSString *custom([Info_ objectForKey:(docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle")]);
1905 $drawLabel$(label, [self bounds], style, custom);
1908 MSInstanceMessage0(CGImageRef, SBIconLabel, buildLabelImage) {
1909 bool docked((MSHookIvar<unsigned>(self, "_inDock") & 0x2) != 0);
1911 WBStringDrawingState labelState = {NULL, 0, @""
1912 , docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle"};
1914 stringDrawingState_ = &labelState;
1917 CGImageRef image(MSOldCall());
1920 stringDrawingState_ = NULL;
1924 static bool wb$inDock(id parameters) {
1925 return [$objc_getAssociatedObject(parameters, @selector(wb$inDock)) boolValue];
1928 MSInstanceMessage0(NSUInteger, SBIconLabelImageParameters, hash) {
1929 return MSOldCall() + (wb$inDock(self) ? 0xdeadbeef : 0xd15ea5e);
1932 MSClassMessage2(id, SBIconView, _labelImageParametersForIcon,location, id, icon, int, location) {
1933 if (id parameters = MSOldCall(icon, location)) {
1934 $objc_setAssociatedObject(parameters, @selector(wb$inDock), [NSNumber numberWithBool:(location == 1)], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1939 MSInstanceMessage0(id, SBIconView, _labelImageParameters) {
1940 if (id parameters = MSOldCall()) {
1941 int &location(MSHookIvar<int>(self, "_iconLocation"));
1942 if (&location != NULL)
1943 $objc_setAssociatedObject(parameters, @selector(wb$inDock), [NSNumber numberWithBool:(location == 3)], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1948 MSClassMessage1(UIImage *, SBIconLabelImage, _drawLabelImageForParameters, id, parameters) {
1949 bool docked(wb$inDock(parameters));
1951 WBStringDrawingState labelState = {NULL, 0, @""
1952 , docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle"};
1954 stringDrawingState_ = &labelState;
1957 UIImage *image(MSOldCall(parameters));
1960 stringDrawingState_ = NULL;
1965 MSInstanceMessageHook2(id, CKBalloonView, initWithFrame,delegate, CGRect, frame, id, delegate) {
1966 if ((self = MSOldCall(frame, delegate)) != nil) {
1967 [self setBackgroundColor:[UIColor clearColor]];
1971 MSInstanceMessageHook0(BOOL, CKBalloonView, _canUseLayerBackedBalloon) {
1972 return SMSBackgrounded_ ? NO : MSOldCall();
1975 MSInstanceMessageHook0(void, CKTranscriptHeaderView, layoutSubviews) {
1976 [self wb$setBackgroundColor:[UIColor clearColor]];
1980 MSInstanceMessageHook1(void, CKMessageCell, addBalloonView, CKBalloonView *, balloon) {
1982 [balloon setBackgroundColor:[UIColor clearColor]];
1985 MSInstanceMessageHook1(void, CKTranscriptCell, setBackgroundColor, UIColor *, color) {
1986 MSOldCall([UIColor clearColor]);
1987 [[self contentView] wb$setBackgroundColor:[UIColor clearColor]];
1991 MSInstanceMessageHook2(id, CKTranscriptCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1992 if ((self = MSOldCall(style, reuse)) != nil) {
1993 [self setBackgroundColor:[UIColor clearColor]];
1994 [[self contentView] wb$setBackgroundColor:[UIColor clearColor]];
1999 MSInstanceMessageHook2(id, CKMessageCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
2000 if ((self = MSOldCall(style, reuse)) != nil) {
2001 [self setBackgroundColor:[UIColor clearColor]];
2002 [[self contentView] setBackgroundColor:[UIColor clearColor]];
2006 MSInstanceMessageHook2(id, CKTimestampView, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
2007 if ((self = MSOldCall(style, reuse)) != nil) {
2008 UILabel *&_label(MSHookIvar<UILabel *>(self, "_label"));
2009 [_label setBackgroundColor:[UIColor clearColor]];
2013 MSInstanceMessageHook1(void, CKTranscriptTableView, setSeparatorStyle, int, style) {
2014 MSOldCall(UITableViewCellSeparatorStyleNone);
2017 MSInstanceMessageHook2(id, CKTranscriptTableView, initWithFrame,style, CGRect, frame, int, style) {
2018 if ((self = MSOldCall(frame, style)) != nil) {
2019 [self setSeparatorStyle:UITableViewCellSeparatorStyleNone];
2023 MSInstanceMessageHook0(void, CKTranscriptController, loadView) {
2026 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"SMSBackground.png", @"SMSBackground.jpg", nil])))
2027 if (UIImage *image = $getImage$(path)) {
2028 SMSBackgrounded_ = true;
2030 UIView *&_transcriptTable(MSHookIvar<UIView *>(self, "_transcriptTable"));
2031 UIView *&_transcriptLayer(MSHookIvar<UIView *>(self, "_transcriptLayer"));
2033 if (&_transcriptTable != NULL)
2034 table = _transcriptTable;
2035 else if (&_transcriptLayer != NULL)
2036 table = _transcriptLayer;
2040 UIView *placard(table != nil ? [table superview] : MSHookIvar<UIView *>(self, "_backPlacard"));
2041 UIImageView *background([[[UIImageView alloc] initWithImage:image] autorelease]);
2044 [placard insertSubview:background atIndex:0];
2046 [table setBackgroundColor:[UIColor clearColor]];
2047 [placard insertSubview:background belowSubview:table];
2053 template <typename Original_>
2054 static UIImage *WBCacheUIImage(NSBundle *bundle, const Original_ &original, NSString *name, NSString *key) {
2057 NSUInteger period([name rangeOfString:@"."].location);
2058 NSUInteger length([name length]);
2059 if (period == NSNotFound || length < 4 || period > length - 4)
2060 name = [name stringByAppendingString:@".png"];
2062 return WBCacheImage([bundle, &original, name](){
2063 UIImage *image(original());
2064 if (image != nil && UIDebug_) {
2065 NSString *path([@"/tmp/WBImages/" stringByAppendingString:[bundle bundleIdentifier]]);
2066 [Manager_ createDirectoryAtPath:path withIntermediateDirectories:YES attributes:@{NSFilePosixPermissions: @0777} error:NULL];
2067 path = [NSString stringWithFormat:@"%@/%@", path, name];
2068 if (![Manager_ fileExistsAtPath:path])
2069 [UIImagePNGRepresentation(image) writeToFile:path atomically:YES];
2071 }, [=](){ return $pathForFile$inBundle$(name, bundle, true); }, key);
2074 // %hook _UIImageWithName() {{{
2075 MSHook(UIImage *, _UIImageWithName, NSString *name) {
2079 NSLog(@"WB:Debug: _UIImageWithName(\"%@\")", name);
2080 return WBCacheUIImage(_UIKitBundle(),
2081 [=](){ return __UIImageWithName(name); },
2082 name, [NSString stringWithFormat:@"I:%@", name]);
2085 // %hook _UIImageWithNameInDomain() {{{
2086 MSHook(UIImage *, _UIImageWithNameInDomain, NSString *name, NSString *domain) {
2088 NSLog(@"WB:Debug: _UIImageWithNameInDomain(\"%@\", \"%@\")", name, domain);
2089 return WBCacheImage(
2090 [=](){ return __UIImageWithNameInDomain(name, domain); },
2091 [=](){ return $getTheme$($useScale$([NSArray arrayWithObject:[NSString stringWithFormat:@"Domains/%@/%@", domain, name]])); },
2092 [NSString stringWithFormat:@"D:%zu:%@%@", size_t([domain length]), domain, name]);
2096 // UISharedArtwork (iOS 6) {{{
2097 MSInstanceMessageHook2(UISharedArtwork *, UISharedArtwork, initWithName,inBundle, NSString *, name, NSBundle *, bundle) {
2098 if ((self = MSOldCall(name, bundle)) != nil) {
2099 $objc_setAssociatedObject(self, @selector(wb$bundle), bundle, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
2103 MSInstanceMessageHook2(UIImage *, UISharedArtwork, imageNamed,device, NSString *, name, NSInteger, device) {
2104 NSBundle *bundle($objc_getAssociatedObject(self, @selector(wb$bundle)));
2106 NSLog(@"WB:Debug: -[UISharedArtwork(%@) imageNamed:@\"%@\" device:%li]", [bundle bundleIdentifier], name, (long) device);
2107 return WBCacheUIImage(bundle,
2108 [=](){ return MSOldCall(name, device); },
2109 name, [NSString stringWithFormat:@"M:%p:%@:%li", self, name, (long) device]);
2112 // _UIAssetManager (iOS 7) {{{
2113 MSInstanceMessageHook3(_UIAssetManager *, _UIAssetManager, initWithName,inBundle,idiom, NSString *, name, NSBundle *, bundle, NSInteger, idiom) {
2114 if ((self = MSOldCall(name, bundle, idiom)) != nil) {
2115 $objc_setAssociatedObject(self, @selector(wb$bundle), bundle, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
2119 MSInstanceMessageHook5(UIImage *, _UIAssetManager, imageNamed,scale,idiom,subtype,cachingOptions, NSString *, name, CGFloat, scale, NSInteger, idiom, NSUInteger, subtype, NSUInteger, caching) {
2120 NSBundle *bundle($objc_getAssociatedObject(self, @selector(wb$bundle)));
2122 NSLog(@"WB:Debug: -[_UIAssetManager(%@/%@) imageNamed:@\"%@\" scale:%g idiom:%li subtype:%lu cachingOptions:%lu]",
2123 [bundle bundleIdentifier], [self carFileName],
2124 name, scale, (long) idiom,
2125 (unsigned long) subtype,
2126 (unsigned long) caching
2129 if (bundle == _UIKitBundle()) {
2130 NSString *name([self carFileName]);
2132 else if ([name isEqualToString:@"UIKit_NewArtwork"])
2133 bundle = [WBBundle bundleWithIdentifier:@"com.apple.uikit.Artwork"];
2134 else if ([name isEqualToString:@"UIKit_OriginalArtwork"])
2135 bundle = [WBBundle bundleWithIdentifier:@"com.apple.uikit.LegacyArtwork"];
2138 return WBCacheUIImage(bundle,
2139 [=](){ return MSOldCall(name, scale, idiom, subtype, caching); },
2140 name, [NSString stringWithFormat:@"M:%p:%@:%g:%li:%lu", self, name, scale, (long) idiom, (unsigned long) subtype]);
2143 // _UIAssetManager (iOS 8) {{{
2144 struct SizeClassPair {
2149 MSInstanceMessageHook7(UIImage *, _UIAssetManager, imageNamed,scale,idiom,subtype,cachingOptions,sizeClassPair,attachCatalogImage, NSString *, name, CGFloat, scale, NSInteger, idiom, NSUInteger, subtype, NSUInteger, caching, SizeClassPair, size, BOOL, attach) {
2150 NSBundle *bundle([self bundle]);
2152 NSLog(@"WB:Debug: -[_UIAssetManager(%@/%@) imageNamed:@\"%@\" scale:%g idiom:%li subtype:%lu cachingOptions:%lu sizeClassPair:[%li %li] attachCatalogImage:%s]",
2153 [bundle bundleIdentifier], [self carFileName],
2154 name, scale, (long) idiom,
2155 (unsigned long) subtype,
2156 (unsigned long) caching,
2157 (long) size.first, (long) size.second,
2158 attach ? "YES" : "NO"
2160 return WBCacheUIImage(bundle,
2161 [=](){ return MSOldCall(name, scale, idiom, subtype, caching, size, attach); },
2162 name, [NSString stringWithFormat:@"M:%p:%@:%g:%li:%lu:%li:%li:%c", self, name, scale, (long) idiom, (unsigned long) subtype, (long) size.first, (long) size.second, attach ? 'Y' : 'N']);
2166 // %hook GSFontCreateWithName() {{{
2167 MSHook(GSFontRef, GSFontCreateWithName, const char *name, GSFontSymbolicTraits traits, float size) {
2169 NSLog(@"WB:Debug: GSFontCreateWithName(\"%s\", %f)", name, size);
2170 if (NSString *font = [Info_ objectForKey:[NSString stringWithFormat:@"FontName-%s", name]])
2171 name = [font UTF8String];
2172 //if (NSString *scale = [Info_ objectForKey:[NSString stringWithFormat:@"FontScale-%s", name]])
2173 // size *= [scale floatValue];
2174 return _GSFontCreateWithName(name, traits, size);
2178 #define AudioToolbox "/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox"
2180 static bool GetFileNameForThisAction$(bool value, unsigned long a0, char *a1, unsigned long a2, bool &a3) {
2182 NSLog(@"WB:Debug:GetFileNameForThisAction(%lu, %s, %lu, %u) = %u", a0, value ? a1 : NULL, a2, a3, value);
2185 NSString *path = [NSString stringWithUTF8String:a1];
2186 if ([path hasPrefix:@"/System/Library/Audio/UISounds/"]) {
2187 NSString *file = [path substringFromIndex:31];
2188 for (NSString *theme in Themes_) {
2189 NSString *path([NSString stringWithFormat:@"%@/UISounds/%@", theme, file]);
2190 if ([Manager_ fileExistsAtPath:path]) {
2191 strcpy(a1, [path UTF8String]);
2200 MSHook(bool, _Z24GetFileNameForThisActionmPcRb, unsigned long a0, char *a1, bool &a3) {
2201 bool value(__Z24GetFileNameForThisActionmPcRb(a0, a1, a3));
2202 return GetFileNameForThisAction$(value, a0, a1, 0, a3);
2205 MSHook(bool, _Z24GetFileNameForThisActionmPcmRb, unsigned long a0, char *a1, unsigned long a2, bool &a3) {
2206 bool value(__Z24GetFileNameForThisActionmPcmRb(a0, a1, a2, a3));
2207 return GetFileNameForThisAction$(value, a0, a1, a2, a3);
2210 static void ChangeWallpaper(
2211 CFNotificationCenterRef center,
2215 CFDictionaryRef info
2218 NSLog(@"WB:Debug:ChangeWallpaper!");
2221 if (WallpaperFile_ != nil) {
2222 image = [[UIImage alloc] initWithContentsOfFile:WallpaperFile_];
2224 image = [image autorelease];
2227 if (WallpaperImage_ != nil)
2228 [WallpaperImage_ setImage:image];
2229 if (WallpaperPage_ != nil)
2230 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
2234 MSHook(NSArray *, CPBitmapCreateImagesFromPath, NSString *path, CFTypeRef *names, void *arg2, void *arg3) {
2235 NSArray *images(_CPBitmapCreateImagesFromPath(path, names, arg2, arg3));
2241 NSBundle *bundle([NSBundle wb$bundleWithFile:path]);
2245 NSString *file([path stringByResolvingSymlinksInPath]);
2246 NSString *prefix([[bundle bundlePath] stringByResolvingSymlinksInPath]);
2247 // XXX: why do I care about this?
2248 if (![file hasPrefix:prefix])
2251 NSMutableArray *copy([images mutableCopy]);
2255 NSDictionary *indexes;
2256 NSEnumerator *enumerator;
2258 if (CFGetTypeID((CFTypeRef) *names) == CFDictionaryGetTypeID()) {
2259 indexes = (NSDictionary *) *names;
2260 enumerator = [indexes keyEnumerator];
2263 enumerator = [(NSArray *) *names objectEnumerator];
2266 for (NSUInteger index(0); NSString *name = [enumerator nextObject]; ++index)
2267 if (NSString *themed = $pathForFile$inBundle$([name stringByAppendingString:@".png"], bundle, true)) {
2269 index = [[indexes objectForKey:name] intValue];
2270 UIImage *image($getImage$(themed));
2271 CGImageRef cg([image CGImage]);
2272 [copy replaceObjectAtIndex:index withObject:(id)cg];
2278 MSHook(void, BKSDisplayServicesSetSystemAppExitedImagePath, NSString *path) {
2279 if (NSString *themed = $getTheme$($useScale$([NSArray arrayWithObject:@"SystemAppExited.png"])))
2281 _BKSDisplayServicesSetSystemAppExitedImagePath(path);
2284 #define WBRename(name, sel, imp) \
2285 MSHookMessage($ ## name, @selector(sel), &$ ## name ## $ ## imp, &_ ## name ## $ ## imp)
2287 template <typename Type_>
2288 static void msset(Type_ &function, MSImageRef image, const char *name) {
2289 function = reinterpret_cast<Type_>(MSFindSymbol(image, name));
2292 #define WBHookSymbol(image, function) \
2293 msset(function, image, "_" #function)
2295 template <typename Type_>
2296 static void dlset(Type_ &function, const char *name) {
2297 function = reinterpret_cast<Type_>(dlsym(RTLD_DEFAULT, name));
2300 // %hook CGImageReadCreateWithFile() {{{
2301 MSHook(void *, CGImageReadCreateWithFile, NSString *path, int flag) {
2303 NSLog(@"WB:Debug: CGImageReadCreateWithFile(%@, %d)", path, flag);
2304 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2305 void *value(_CGImageReadCreateWithFile([path wb$themedPath], flag));
2310 MSHook(void *, CGImageSourceCreateWithFile, NSString *path, NSDictionary *options) {
2312 NSLog(@"WB:Debug: CGImageSourceCreateWithFile(%@, %@)", path, options);
2313 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2314 void *value(_CGImageSourceCreateWithFile([path wb$themedPath], options));
2319 MSHook(void *, CGImageSourceCreateWithURL, NSURL *url, NSDictionary *options) {
2321 NSLog(@"WB:Debug: CGImageSourceCreateWithURL(%@, %@)", url, options);
2322 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2323 if ([url isFileURL])
2324 url = [NSURL fileURLWithPath:[[url path] wb$themedPath]];
2325 void *value(_CGImageSourceCreateWithURL(url, options));
2331 static void NSString$drawAtPoint$withStyle$(NSString *self, SEL _cmd, CGPoint point, NSString *style) {
2332 WKSetCurrentGraphicsContext(UIGraphicsGetCurrentContext());
2333 if (style == nil || [style length] == 0)
2334 style = @"font-family: Helvetica; font-size: 12px";
2335 //NSLog(@"XXX:drawP(%@ | %@)", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "]);
2336 [[WBMarkup sharedMarkup] drawString:self atPoint:point withStyle:style];
2339 static void NSString$drawInRect$withStyle$(NSString *self, SEL _cmd, CGRect rect, NSString *style) {
2340 WKSetCurrentGraphicsContext(UIGraphicsGetCurrentContext());
2341 if (style == nil || [style length] == 0)
2342 style = @"font-family: Helvetica; font-size: 12px";
2343 //NSLog(@"XXX:drawR(%@ | %@)", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "]);
2344 return [[WBMarkup sharedMarkup] drawString:self inRect:rect withStyle:style];
2347 static CGSize NSString$sizeWithStyle$forWidth$(NSString *self, SEL _cmd, NSString *style, CGFloat width) {
2348 if (style == nil || [style length] == 0)
2349 style = @"font-family: Helvetica; font-size: 12px";
2350 CGSize size([[WBMarkup sharedMarkup] sizeOfString:self withStyle:style forWidth:width]);
2351 //NSLog(@"XXX:size(%@ | %@) = [%g %g]", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "], size.width, size.height);
2355 static void SBInitialize() {
2357 WBRename(SBApplication, pathForIcon, pathForIcon);
2358 WBRename(SBApplicationIcon, icon, icon);
2359 WBRename(SBApplicationIcon, generateIconImage:, generateIconImage$);
2362 WBRename(SBBookmarkIcon, icon, icon);
2363 WBRename(SBButtonBar, didMoveToSuperview, didMoveToSuperview);
2364 WBRename(SBCalendarIconContentsView, drawRect:, drawRect$);
2365 WBRename(SBIconBadge, initWithBadge:, initWithBadge$);
2366 WBRename(SBIconController, noteNumberOfIconListsChanged, noteNumberOfIconListsChanged);
2368 WBRename(SBWidgetApplicationIcon, icon, icon);
2370 WBRename(SBDockIconListView, setFrame:, setFrame$);
2371 MSHookMessage(object_getClass($SBDockIconListView), @selector(shouldShowNewDock), &$SBDockIconListView$shouldShowNewDock, &_SBDockIconListView$shouldShowNewDock);
2373 if (kCFCoreFoundationVersionNumber < 600 || SummerBoard_)
2374 WBRename(SBIconLabel, drawRect:, drawRect$);
2375 else if (kCFCoreFoundationVersionNumber < 700) {
2376 WBRename(SBIconLabel, buildLabelImage, buildLabelImage);
2378 WBRename(SBIconLabelImageParameters, hash, hash);
2379 WBRename($SBIconView, _labelImageParametersForIcon:location:, _labelImageParametersForIcon$location$);
2380 WBRename(SBIconView, _labelImageParameters, _labelImageParameters);
2381 WBRename($SBIconLabelImage, _drawLabelImageForParameters:, _drawLabelImageForParameters$);
2384 WBRename(SBIconLabel, initWithSize:label:, initWithSize$label$);
2385 WBRename(SBIconLabel, setInDock:, setInDock$);
2387 WBRename(SBIconList, didMoveToSuperview, didMoveToSuperview);
2388 WBRename(SBIconList, setFrame:, setFrame$);
2390 WBRename(SBIconModel, cacheImageForIcon:, cacheImageForIcon$);
2391 WBRename(SBIconModel, cacheImagesForIcon:, cacheImagesForIcon$);
2392 WBRename(SBIconModel, getCachedImagedForIcon:, getCachedImagedForIcon$);
2393 WBRename(SBIconModel, getCachedImagedForIcon:smallIcon:, getCachedImagedForIcon$smallIcon$);
2395 if (kCFCoreFoundationVersionNumber < 800) {
2396 WBRename(SBSearchView, initWithFrame:, initWithFrame$);
2397 WBRename(SBSearchTableViewCell, drawRect:, drawRect$);
2398 WBRename(SBSearchTableViewCell, initWithStyle:reuseIdentifier:, initWithStyle$reuseIdentifier$);
2401 //WBRename(SBImageCache, initWithName:forImageWidth:imageHeight:initialCapacity:, initWithName$forImageWidth$imageHeight$initialCapacity$);
2403 WBRename(SBAwayView, updateDesktopImage:, updateDesktopImage$);
2404 if (kCFCoreFoundationVersionNumber >= 700)
2405 WBRename(SBAwayView, _addSubview:positioned:relativeTo:, _addSubview$positioned$relativeTo$);
2407 WBRename(SBStatusBarContentsView, didMoveToSuperview, didMoveToSuperview);
2408 //WBRename(SBStatusBarContentsView, initWithStatusBar:mode:, initWithStatusBar$mode$);
2409 //WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:animation:, setStatusBarMode$orientation$duration$animation$);
2410 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:, setStatusBarMode$orientation$duration$fenceID$animation$);
2411 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:startTime:, setStatusBarMode$orientation$duration$fenceID$animation$startTime$);
2412 WBRename(SBStatusBarOperatorNameView, operatorNameStyle, operatorNameStyle);
2413 WBRename(SBStatusBarOperatorNameView, setOperatorName:fullSize:, setOperatorName$fullSize$);
2414 WBRename(SBStatusBarTimeView, drawRect:, drawRect$);
2417 English_ = [[NSDictionary alloc] initWithContentsOfFile:@"/System/Library/CoreServices/SpringBoard.app/English.lproj/LocalizedApplicationNames.strings"];
2419 if (kCFCoreFoundationVersionNumber >= 800) {
2420 WBRename(NSString, drawInRect:withAttributes:, drawInRect$withAttributes$);
2421 WBRename(NSString, boundingRectWithSize:options:attributes:context:, boundingRectWithSize$options$attributes$context$);
2425 /*MSHook(int, open, const char *path, int oflag, mode_t mode) {
2426 int fd(_open(path, oflag, mode));
2428 static bool no(false);
2432 if (strstr(path, "/icon") != NULL)
2433 *reinterpret_cast<void *volatile *>(NULL) = NULL;
2435 if (fd == -1 && errno == EFAULT)
2436 NSLog(@"open(%p, %#x, %#o) = %d\n", path, oflag, mode, fd);
2438 NSLog(@"open(\"%s\", %#x, %#o) = %d\n", path, oflag, mode, fd);
2445 $objc_setAssociatedObject = reinterpret_cast<void (*)(id, void *, id value, objc_AssociationPolicy)>(dlsym(RTLD_DEFAULT, "objc_setAssociatedObject"));
2446 $objc_getAssociatedObject = reinterpret_cast<id (*)(id, void *)>(dlsym(RTLD_DEFAULT, "objc_getAssociatedObject"));
2447 $objc_removeAssociatedObjects = reinterpret_cast<void (*)(id)>(dlsym(RTLD_DEFAULT, "objc_removeAssociatedObjects"));
2449 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2451 NSString *identifier([[NSBundle mainBundle] bundleIdentifier]);
2452 SpringBoard_ = [identifier isEqualToString:@"com.apple.springboard"];
2454 Manager_ = [[NSFileManager defaultManager] retain];
2455 Themes_ = [[NSMutableArray alloc] initWithCapacity:8];
2457 dlset(_GSFontGetUseLegacyFontMetrics, "GSFontGetUseLegacyFontMetrics");
2459 // Load Settings.plist {{{
2460 if (NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"/User/Library/Preferences/com.saurik.WinterBoard.plist"]]) {
2461 if (NSNumber *value = [settings objectForKey:@"SummerBoard"])
2462 SummerBoard_ = [value boolValue];
2464 SummerBoard_ = true;
2466 if (NSNumber *value = [settings objectForKey:@"Debug"])
2467 Debug_ = [value boolValue];
2468 if (NSNumber *value = [settings objectForKey:@"RecordUI"])
2469 UIDebug_ = [value boolValue];
2471 NSArray *themes([settings objectForKey:@"Themes"]);
2473 if (NSString *theme = [settings objectForKey:@"Theme"])
2474 themes = [NSArray arrayWithObject:[NSDictionary dictionaryWithObjectsAndKeys:
2476 [NSNumber numberWithBool:true], @"Active",
2480 for (NSDictionary *theme in themes) {
2481 NSNumber *active([theme objectForKey:@"Active"]);
2482 if (![active boolValue])
2485 NSString *name([theme objectForKey:@"Name"]);
2489 #define testForTheme(format...) \
2491 NSString *path = [NSString stringWithFormat:format]; \
2492 if ([Manager_ fileExistsAtPath:path]) { \
2493 [Themes_ addObject:path]; \
2498 testForTheme(@"/Library/Themes/%@.theme", name)
2499 testForTheme(@"/Library/Themes/%@", name)
2500 testForTheme(@"%@/Library/SummerBoard/Themes/%@", NSHomeDirectory(), name)
2505 // Merge Info.plist {{{
2506 Info_ = [[NSMutableDictionary dictionaryWithCapacity:16] retain];
2508 for (NSString *theme in Themes_)
2509 if (NSDictionary *info = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"%@/Info.plist", theme]])
2510 for (NSString *key in [info allKeys])
2511 if ([Info_ objectForKey:key] == nil)
2512 [Info_ setObject:[info objectForKey:key] forKey:key];
2516 if (MSImageRef image = MSGetImageByName("/System/Library/PrivateFrameworks/AppSupport.framework/AppSupport")) {
2517 NSArray *(*CPBitmapCreateImagesFromPath)(NSString *, CFTypeRef *, void *, void *);
2518 msset(CPBitmapCreateImagesFromPath, image, "_CPBitmapCreateImagesFromPath");
2519 MSHookFunction(CPBitmapCreateImagesFromPath, MSHake(CPBitmapCreateImagesFromPath));
2523 if (MSImageRef image = MSGetImageByName(AudioToolbox)) {
2524 bool (*_Z24GetFileNameForThisActionmPcRb)(unsigned long, char *, bool &);
2525 msset(_Z24GetFileNameForThisActionmPcRb, image, "__Z24GetFileNameForThisActionmPcRb");
2526 MSHookFunction(_Z24GetFileNameForThisActionmPcRb, &$_Z24GetFileNameForThisActionmPcRb, &__Z24GetFileNameForThisActionmPcRb);
2528 bool (*_Z24GetFileNameForThisActionmPcmRb)(unsigned long, char *, unsigned long, bool &);
2529 msset(_Z24GetFileNameForThisActionmPcmRb, image, "__Z24GetFileNameForThisActionmPcmRb");
2530 MSHookFunction(_Z24GetFileNameForThisActionmPcmRb, &$_Z24GetFileNameForThisActionmPcmRb, &__Z24GetFileNameForThisActionmPcmRb);
2533 // BackBoardServices {{{
2534 if (MSImageRef image = MSGetImageByName("/System/Library/PrivateFrameworks/BackBoardServices.framework/BackBoardServices")) {
2535 void (*BKSDisplayServicesSetSystemAppExitedImagePath)(NSString *path);
2536 msset(BKSDisplayServicesSetSystemAppExitedImagePath, image, "_BKSDisplayServicesSetSystemAppExitedImagePath");
2537 MSHookFunction(BKSDisplayServicesSetSystemAppExitedImagePath, MSHake(BKSDisplayServicesSetSystemAppExitedImagePath));
2542 MSHookFunction(CFBundleCopyResourceURL, MSHake(CFBundleCopyResourceURL));
2545 // GraphicsServices {{{
2547 MSHookFunction(&GSFontCreateWithName, &$GSFontCreateWithName, &_GSFontCreateWithName);
2551 MSImageRef imageio = MSGetImageByName("/System/Library/Frameworks/ImageIO.framework/ImageIO");
2552 if (imageio == NULL)
2553 imageio = MSGetImageByName("/System/Library/PrivateFrameworks/ImageIO.framework/ImageIO");
2554 if (MSImageRef image = imageio) {
2555 void *(*CGImageReadCreateWithFile)(NSString *, int) = NULL;
2556 if (kCFCoreFoundationVersionNumber > 700) // XXX: iOS 6.x
2557 CGImageReadCreateWithFile = NULL;
2559 msset(CGImageReadCreateWithFile, image, "_CGImageReadCreateWithFile");
2560 MSHookFunction(CGImageReadCreateWithFile, MSHake(CGImageReadCreateWithFile));
2563 if (CGImageReadCreateWithFile == NULL) {
2564 void *(*CGImageSourceCreateWithFile)(NSString *, NSDictionary *);
2565 msset(CGImageSourceCreateWithFile, image, "_CGImageSourceCreateWithFile");
2566 MSHookFunction(CGImageSourceCreateWithFile, MSHake(CGImageSourceCreateWithFile));
2568 void *(*CGImageSourceCreateWithURL)(NSURL *, NSDictionary *);
2569 msset(CGImageSourceCreateWithURL, image, "_CGImageSourceCreateWithURL");
2570 MSHookFunction(CGImageSourceCreateWithURL, MSHake(CGImageSourceCreateWithURL));
2576 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];
2577 Papered_ = $getTheme$(Wallpapers_) != nil;
2578 Docked_ = $getTheme$([NSArray arrayWithObjects:@"Dock.png", nil]) != nil;
2580 CFNotificationCenterAddObserver(
2581 CFNotificationCenterGetDarwinNotifyCenter(),
2582 NULL, &ChangeWallpaper, (CFStringRef) @"com.saurik.winterboard.lockbackground", NULL, CFNotificationSuspensionBehaviorCoalesce
2585 if ($getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"]) != nil) {
2586 NSBundle *MediaPlayer([NSBundle bundleWithPath:@"/System/Library/Frameworks/MediaPlayer.framework"]);
2587 if (MediaPlayer != nil)
2590 $MPMoviePlayerController = objc_getClass("MPMoviePlayerController");
2591 $MPVideoView = objc_getClass("MPVideoView");
2598 if (MSImageRef image = MSGetImageByName("/System/Library/Frameworks/UIKit.framework/UIKit")) {
2600 class_addMethod($NSString, @selector(drawAtPoint:withStyle:), (IMP) &NSString$drawAtPoint$withStyle$, "v40@0:8{CGPoint=dd}16@32");
2601 class_addMethod($NSString, @selector(drawInRect:withStyle:), (IMP) &NSString$drawInRect$withStyle$, "v56@0:8{CGRect={CGSize=dd}{CGSize=dd}}16@48");
2602 class_addMethod($NSString, @selector(sizeWithStyle:forWidth:), (IMP) &NSString$sizeWithStyle$forWidth$, "{CGSize=dd}32@0:8@16d24");
2604 class_addMethod($NSString, @selector(drawAtPoint:withStyle:), (IMP) &NSString$drawAtPoint$withStyle$, "v20@0:4{CGPoint=ff}8@16");
2605 class_addMethod($NSString, @selector(drawInRect:withStyle:), (IMP) &NSString$drawInRect$withStyle$, "v28@0:4{CGRect={CGSize=ff}{CGSize=ff}}8@24");
2606 class_addMethod($NSString, @selector(sizeWithStyle:forWidth:), (IMP) &NSString$sizeWithStyle$forWidth$, "{CGSize=ff}16@0:4@8f12");
2609 WBHookSymbol(image, _UIKitBundle);
2611 if (kCFCoreFoundationVersionNumber < 700)
2612 MSHookFunction(_UIImageWithName, MSHake(_UIImageWithName));
2614 WBHookSymbol(image, _UIApplicationImageWithName);
2615 MSHookFunction(_UIApplicationImageWithName, MSHake(_UIApplicationImageWithName));
2617 WBHookSymbol(image, _UIImageWithNameInDomain);
2618 MSHookFunction(_UIImageWithNameInDomain, MSHake(_UIImageWithNameInDomain));
2620 SEL includeEmoji(@selector(_legacy_drawAtPoint:forWidth:withFont:lineBreakMode:letterSpacing:includeEmoji:));
2621 if (![@"" respondsToSelector:includeEmoji])
2622 includeEmoji = @selector(drawAtPoint:forWidth:withFont:lineBreakMode:letterSpacing:includeEmoji:);
2623 MSHookMessage($NSString, includeEmoji, MSHake(NSString$drawAtPoint$forWidth$withFont$lineBreakMode$letterSpacing$includeEmoji$));
2625 SEL letterSpacing(@selector(_legacy_sizeWithFont:forWidth:lineBreakMode:letterSpacing:));
2626 if (![@"" respondsToSelector:letterSpacing])
2627 letterSpacing = @selector(sizeWithFont:forWidth:lineBreakMode:letterSpacing:);
2628 MSHookMessage($NSString, letterSpacing, MSHake(NSString$sizeWithFont$forWidth$lineBreakMode$letterSpacing$));
2630 SEL sizeWithFont(@selector(_legacy_sizeWithFont:));
2631 if (![@"" respondsToSelector:sizeWithFont])
2632 sizeWithFont = @selector(sizeWithFont:);
2633 MSHookMessage($NSString, sizeWithFont, MSHake(NSString$sizeWithFont$));
2637 //MSHookFunction(reinterpret_cast<int (*)(const char *, int, mode_t)>(&open), MSHake(open));