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, NSString *folder) {
374 if (identifier != nil)
375 [names addObject:[NSString stringWithFormat:@"Bundles/%@/%@", identifier, file]];
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:oldname ".png"];
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", @"UIKit.framework");
394 else if ([identifier isEqualToString:@"com.apple.uikit.LegacyArtwork"])
395 $pathForFile$inBundle$(names, file, @"com.apple.UIKit", @"UIKit.framework");
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", @"MobileSMS.app");
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 $pathForFile$inBundle$(names, @"icon.png", identifier, folder);
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 lastPathComponent]);
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];
437 NSString *didentifier;
438 if ([self respondsToSelector:@selector(displayIdentifier)])
439 didentifier = [self displayIdentifier];
444 NSLog(@"WB:Debug: [SBApplication(%@:%@:%@:%@) pathForIcon]", identifier, folder, dname, didentifier);
446 NSMutableArray *names = [NSMutableArray arrayWithCapacity:8];
448 /* XXX: I might need to keep this for backwards compatibility
449 if (identifier != nil)
450 [names addObject:[NSString stringWithFormat:@"Bundles/%@/icon.png", identifier]];
452 [names addObject:[NSString stringWithFormat:@"Folders/%@/icon.png", folder]]; */
454 #define testForIcon(Name) \
455 if (NSString *name = Name) \
456 [names addObject:[NSString stringWithFormat:@"Icons%@/%@.png", suffix, name]];
458 if (didentifier != nil && ![didentifier isEqualToString:identifier])
459 testForIcon(didentifier);
461 testForIcon(identifier);
464 if ([identifier isEqualToString:@"com.apple.MobileSMS"])
467 if (didentifier != nil) {
468 testForIcon([English_ objectForKey:didentifier]);
470 NSArray *parts = [didentifier componentsSeparatedByString:@"-"];
471 if ([parts count] != 1)
472 if (NSDictionary *english = [[[NSDictionary alloc] initWithContentsOfFile:[path stringByAppendingString:@"/English.lproj/UIRoleDisplayNames.strings"]] autorelease])
473 testForIcon([english objectForKey:[parts lastObject]]);
476 if (NSString *path = $getTheme$(names))
482 // -[NSBundle wb$bundleWithFile] {{{
483 @interface NSBundle (WinterBoard)
484 + (NSBundle *) wb$bundleWithFile:(NSString *)path;
487 @implementation NSBundle (WinterBoard)
489 + (NSBundle *) wb$bundleWithFile:(NSString *)path {
490 path = [path stringByDeletingLastPathComponent];
491 if (path == nil || [path length] == 0 || [path isEqualToString:@"/"])
495 @synchronized (Bundles_) {
496 bundle = [Bundles_ objectForKey:path];
499 if (reinterpret_cast<id>(bundle) == [NSNull null])
501 else if (bundle == nil) {
502 if ([Manager_ fileExistsAtPath:[path stringByAppendingPathComponent:@"Info.plist"]])
503 bundle = [NSBundle bundleWithPath:path];
505 bundle = [NSBundle wb$bundleWithFile:path];
507 NSLog(@"WB:Debug:PathBundle(%@, %@)", path, bundle);
509 @synchronized (Bundles_) {
510 [Bundles_ setObject:(bundle == nil ? [NSNull null] : reinterpret_cast<id>(bundle)) forKey:path];
519 // -[NSString wb$themedPath] {{{
520 @interface NSString (WinterBoard)
521 - (NSString *) wb$themedPath;
524 @implementation NSString (WinterBoard)
526 - (NSString *) wb$themedPath {
527 if ([self hasPrefix:@"/Library/Themes/"])
531 NSLog(@"WB:Debug:Bypass(\"%@\")", self);
533 if (NSBundle *bundle = [NSBundle wb$bundleWithFile:self]) {
534 NSString *file([self stringByResolvingSymlinksInPath]);
535 NSString *prefix([[bundle bundlePath] stringByResolvingSymlinksInPath]);
536 if ([file hasPrefix:prefix]) {
537 NSUInteger length([prefix length]);
538 if (length != [file length])
539 if (NSString *path = $pathForFile$inBundle$([file substringFromIndex:(length + 1)], bundle, false))
550 void WBLogRect(const char *tag, struct CGRect rect) {
551 NSLog(@"%s:{%f,%f+%f,%f}", tag, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
554 void WBLogHierarchy(UIView *view, unsigned index = 0, unsigned indent = 0) {
555 CGRect frame([view frame]);
556 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]);
558 for (UIView *child in [view subviews])
559 WBLogHierarchy(child, index++, indent + 1);
562 UIImage *$cacheForImage$(UIImage *image) {
563 CGColorSpaceRef space(CGColorSpaceCreateDeviceRGB());
564 CGRect rect = {CGPointMake(1, 1), [image size]};
565 CGSize size = {rect.size.width + 2, rect.size.height + 2};
567 CGContextRef context(CGBitmapContextCreate(NULL, size.width, size.height, 8, 4 * size.width, space, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst));
568 CGColorSpaceRelease(space);
570 CGContextDrawImage(context, rect, [image CGImage]);
571 CGImageRef ref(CGBitmapContextCreateImage(context));
572 CGContextRelease(context);
574 UIImage *cache([UIImage imageWithCGImage:ref]);
580 /*MSHook(id, SBImageCache$initWithName$forImageWidth$imageHeight$initialCapacity$, SBImageCache *self, SEL sel, NSString *name, unsigned width, unsigned height, unsigned capacity) {
581 //if ([name isEqualToString:@"icons"]) return nil;
582 return _SBImageCache$initWithName$forImageWidth$imageHeight$initialCapacity$(self, sel, name, width, height, capacity);
585 MSHook(void, SBIconModel$cacheImageForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
586 NSString *key([icon displayIdentifier]);
588 if (UIImage *image = [icon icon]) {
589 CGSize size = [image size];
590 if (size.width != 59 || size.height != 60) {
591 UIImage *cache($cacheForImage$(image));
592 [Cache_ setObject:cache forKey:key];
597 _SBIconModel$cacheImageForIcon$(self, sel, icon);
600 MSHook(void, SBIconModel$cacheImagesForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
601 /* XXX: do I /really/ have to do this? figure out how to cache the small icon! */
602 _SBIconModel$cacheImagesForIcon$(self, sel, icon);
604 NSString *key([icon displayIdentifier]);
606 if (UIImage *image = [icon icon]) {
607 CGSize size = [image size];
608 if (size.width != 59 || size.height != 60) {
609 UIImage *cache($cacheForImage$(image));
610 [Cache_ setObject:cache forKey:key];
616 MSHook(UIImage *, SBIconModel$getCachedImagedForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
617 NSString *key([icon displayIdentifier]);
618 if (UIImage *image = [Cache_ objectForKey:key])
621 return _SBIconModel$getCachedImagedForIcon$(self, sel, icon);
624 MSHook(UIImage *, SBIconModel$getCachedImagedForIcon$smallIcon$, SBIconModel *self, SEL sel, SBIcon *icon, BOOL small) {
626 return _SBIconModel$getCachedImagedForIcon$smallIcon$(self, sel, icon, small);
627 NSString *key([icon displayIdentifier]);
628 if (UIImage *image = [Cache_ objectForKey:key])
631 return _SBIconModel$getCachedImagedForIcon$smallIcon$(self, sel, icon, small);
634 MSHook(id, SBSearchView$initWithFrame$, id /* XXX: SBSearchView */ self, SEL sel, struct CGRect frame) {
635 if ((self = _SBSearchView$initWithFrame$(self, sel, frame)) != nil) {
636 [self setBackgroundColor:[UIColor clearColor]];
637 for (UIView *child in [self subviews])
638 [child setBackgroundColor:[UIColor clearColor]];
642 MSHook(id, SBSearchTableViewCell$initWithStyle$reuseIdentifier$, SBSearchTableViewCell *self, SEL sel, int style, NSString *reuse) {
643 if ((self = _SBSearchTableViewCell$initWithStyle$reuseIdentifier$(self, sel, style, reuse)) != nil) {
644 [self setBackgroundColor:[UIColor clearColor]];
648 MSHook(void, SBSearchTableViewCell$drawRect$, SBSearchTableViewCell *self, SEL sel, struct CGRect rect, BOOL selected) {
649 _SBSearchTableViewCell$drawRect$(self, sel, rect, selected);
650 float inset([self edgeInset]);
651 [[UIColor clearColor] set];
652 UIRectFill(CGRectMake(0, 0, inset, rect.size.height));
653 UIRectFill(CGRectMake(rect.size.width - inset, 0, inset, rect.size.height));
656 MSHook(UIImage *, SBApplicationIcon$icon, SBApplicationIcon *self, SEL sel) {
657 if (![Info_ wb$boolForKey:@"ComposeStoreIcons"])
658 if (NSString *path = $pathForIcon$([self application]))
659 return [UIImage imageWithContentsOfFile:path];
660 return _SBApplicationIcon$icon(self, sel);
663 MSHook(UIImage *, SBApplicationIcon$generateIconImage$, SBApplicationIcon *self, SEL sel, int type) {
665 if (![Info_ wb$boolForKey:@"ComposeStoreIcons"]) {
666 if (IsWild_ && false) // XXX: delete this code, it should not be supported
667 if (NSString *path72 = $pathForIcon$([self application], @"-72"))
668 return [UIImage imageWithContentsOfFile:path72];
669 if (NSString *path = $pathForIcon$([self application]))
670 if (UIImage *image = [UIImage imageWithContentsOfFile:path]) {
672 if ([$SBIcon respondsToSelector:@selector(defaultIconImageSize)])
673 width = [$SBIcon defaultIconImageSize].width;
676 return width == 59 ? image : [image _imageScaledToProportion:(width / 59.0) interpolationQuality:5];
679 return _SBApplicationIcon$generateIconImage$(self, sel, type);
682 MSHook(UIImage *, SBWidgetApplicationIcon$icon, SBWidgetApplicationIcon *self, SEL sel) {
684 NSLog(@"WB:Debug:Widget(%@:%@)", [self displayIdentifier], [self displayName]);
685 if (NSString *path = $getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Icons/%@.png", [self displayName]]]))
686 return [UIImage imageWithContentsOfFile:path];
687 return _SBWidgetApplicationIcon$icon(self, sel);
690 MSHook(UIImage *, SBBookmarkIcon$icon, SBBookmarkIcon *self, SEL sel) {
692 NSLog(@"WB:Debug:Bookmark(%@:%@)", [self displayIdentifier], [self displayName]);
693 if (NSString *path = $getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Icons/%@.png", [self displayName]]]))
694 return [UIImage imageWithContentsOfFile:path];
695 return _SBBookmarkIcon$icon(self, sel);
698 MSHook(NSString *, SBApplication$pathForIcon, SBApplication *self, SEL sel) {
699 if (NSString *path = $pathForIcon$(self))
701 return _SBApplication$pathForIcon(self, sel);
704 static UIImage *CachedImageAtPath(NSString *path) {
705 path = [path stringByResolvingSymlinksInPath];
706 UIImage *image = [Images_ objectForKey:path];
708 return reinterpret_cast<id>(image) == [NSNull null] ? nil : image;
709 image = [[UIImage alloc] initWithContentsOfFile:path cache:true];
711 image = [image autorelease];
712 [Images_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:path];
716 MSHook(UIImage *, _UIApplicationImageWithName, NSString *name) {
717 NSBundle *bundle = [NSBundle mainBundle];
719 NSLog(@"WB:Debug: _UIApplicationImageWithName(\"%@\", %@)", name, bundle);
720 if (NSString *path = $pathForFile$inBundle$(name, bundle, false))
721 return CachedImageAtPath(path);
722 return __UIApplicationImageWithName(name);
725 #define WBDelegate(delegate) \
726 - (NSMethodSignature*) methodSignatureForSelector:(SEL)sel { \
728 NSLog(@"WB:MS:%s:(%s)", class_getName([self class]), sel_getName(sel)); \
729 if (NSMethodSignature *sig = [delegate methodSignatureForSelector:sel]) \
731 NSLog(@"WB:Error: [%s methodSignatureForSelector:(%s)]", class_getName([self class]), sel_getName(sel)); \
735 - (void) forwardInvocation:(NSInvocation*)inv { \
736 SEL sel = [inv selector]; \
737 if ([delegate respondsToSelector:sel]) \
738 [inv invokeWithTarget:delegate]; \
740 NSLog(@"WB:Error: [%s forwardInvocation:(%s)]", class_getName([self class]), sel_getName(sel)); \
743 // %hook CFBundleCopyResourceURL {{{
744 MSHook(CFURLRef, CFBundleCopyResourceURL, CFBundleRef bundle, CFStringRef resourceName, CFStringRef resourceType, CFStringRef subDirName) {
745 NSString *file((NSString *) resourceName);
746 if (resourceType != NULL)
747 file = [NSString stringWithFormat:@"%@.%@", file, resourceType];
748 if (subDirName != NULL)
749 file = [NSString stringWithFormat:@"%@/%@", subDirName, resourceType];
751 if (![file hasSuffix:@".png"]) {
753 NSLog(@"WB:Debug: CFBundleCopyResourceURL(<%@>, \"%@\", \"%@\", \"%@\")", CFBundleGetIdentifier(bundle), resourceName, resourceType, subDirName);
754 if (NSString *path = $pathForFile$inBundle$(file, bundle, false))
755 return (CFURLRef) [[NSURL alloc] initFileURLWithPath:path];
758 return _CFBundleCopyResourceURL(bundle, resourceName, resourceType, subDirName);
762 static void $drawLabel$(NSString *label, CGRect rect, NSString *style, NSString *custom) {
763 bool ellipsis(false);
764 CGFloat max = rect.size.width - 11, width;
766 width = [(ellipsis ? [label stringByAppendingString:@"..."] : label) sizeWithStyle:style forWidth:320].width;
769 size_t length([label length]);
770 CGFloat spacing((width - max) / (length - 1));
772 if (spacing > 1.25) {
774 label = [label substringToIndex:(length - 1)];
778 style = [style stringByAppendingString:[NSString stringWithFormat:@"letter-spacing: -%f; ", spacing]];
782 label = [label stringByAppendingString:@"..."];
785 style = [style stringByAppendingString:custom];
787 CGSize size = [label sizeWithStyle:style forWidth:rect.size.width];
788 [label drawAtPoint:CGPointMake((rect.size.width - size.width) / 2 + rect.origin.x, rect.origin.y) withStyle:style];
791 static struct WBStringDrawingState {
792 WBStringDrawingState *next_;
796 } *stringDrawingState_;
798 extern "C" CGColorSpaceRef CGContextGetFillColorSpace(CGContextRef);
799 extern "C" void CGContextGetFillColor(CGContextRef, CGFloat[]);
801 static NSString *WBColorMarkup(size_t number, const CGFloat *components) {
823 return [NSString stringWithFormat:@"color: rgba(%g, %g, %g, %g)", r * 255, g * 255, b * 255, a];
826 static NSString *WBColorMarkup() {
827 CGContextRef context(UIGraphicsGetCurrentContext());
828 //NSLog(@"XXX:1:%p", context);
832 CGColorSpaceRef space(CGContextGetFillColorSpace(context));
833 //NSLog(@"XXX:2:%p", space);
837 size_t number(CGColorSpaceGetNumberOfComponents(space));
838 //NSLog(@"XXX:3:%u", number);
842 CGFloat components[number + 1];
843 CGContextGetFillColor(context, components);
844 return WBColorMarkup(number, components);
847 static NSString *WBColorMarkup(UIColor *uicolor) {
850 CGColorRef cgcolor([uicolor CGColor]);
854 CGColorSpaceRef space(CGColorGetColorSpace(cgcolor));
855 //NSLog(@"XXX:2:%p", space);
859 size_t number(CGColorGetNumberOfComponents(cgcolor));
860 //NSLog(@"XXX:3:%u", number);
864 const CGFloat *components(CGColorGetComponents(cgcolor));
865 return WBColorMarkup(number, components);
868 extern "C" NSString *NSStringFromCGPoint(CGPoint rect);
870 MSInstanceMessage6(CGSize, NSString, drawAtPoint,forWidth,withFont,lineBreakMode,letterSpacing,includeEmoji, CGPoint, point, CGFloat, width, UIFont *, font, UILineBreakMode, mode, CGFloat, spacing, BOOL, emoji) {
871 //NSLog(@"XXX: @\"%@\" %@ %g \"%@\" %u %g %u", self, NSStringFromCGPoint(point), width, font, mode, spacing, emoji);
873 WBStringDrawingState *state(stringDrawingState_);
875 return MSOldCall(point, width, font, mode, spacing, emoji);
877 if (state->count_ != 0 && --state->count_ == 0)
878 stringDrawingState_ = state->next_;
879 if (state->info_ == nil)
880 return MSOldCall(point, width, font, mode, spacing, emoji);
882 NSString *info([Info_ objectForKey:state->info_]);
884 return MSOldCall(point, width, font, mode, spacing, emoji);
886 NSString *base(state->base_ ?: @"");
887 NSString *extra([NSString stringWithFormat:@"letter-spacing: %gpx", spacing]);
888 [self drawAtPoint:point withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info]];
892 extern "C" NSString *NSStringFromCGRect(CGRect rect);
894 MSInstanceMessageHook7(CGSize, NSString, _drawInRect,withFont,lineBreakMode,alignment,lineSpacing,includeEmoji,truncationRect, CGRect, rect, UIFont *, font, UILineBreakMode, mode, UITextAlignment, alignment, float, spacing, BOOL, emoji, CGRect, truncation) {
895 //NSLog(@"XXX: @\"%@\" %@ \"%@\" %u %u %g %u %@", self, NSStringFromCGRect(rect), font, mode, alignment, spacing, emoji, NSStringFromCGRect(truncation));
897 WBStringDrawingState *state(stringDrawingState_);
899 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
901 if (state->count_ != 0 && --state->count_ == 0)
902 stringDrawingState_ = state->next_;
903 if (state->info_ == nil)
904 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
906 NSString *info([Info_ objectForKey:state->info_]);
908 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
913 case UITextAlignmentLeft:
916 case UITextAlignmentCenter:
917 textAlign = @"center";
919 case UITextAlignmentRight:
920 textAlign = @"right";
924 NSString *base(state->base_ ?: @"");
925 NSString *extra([NSString stringWithFormat:@"text-align: %@", textAlign]);
928 $drawLabel$(self, rect, [NSString stringWithFormat:@"%@;%@;%@", [font markupDescription], WBColorMarkup(), base], info);
930 [self drawInRect:rect withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info]];
935 MSInstanceMessage2(void, NSString, drawInRect,withAttributes, CGRect, rect, NSDictionary *, attributes) {
936 //NSLog(@"XXX: *\"%@\" %@", self, attributes);
938 WBStringDrawingState *state(stringDrawingState_);
940 return MSOldCall(rect, attributes);
942 if (state->count_ != 0 && --state->count_ == 0)
943 stringDrawingState_ = state->next_;
944 if (state->info_ == nil)
945 return MSOldCall(rect, attributes);
947 NSString *info([Info_ objectForKey:state->info_]);
949 return MSOldCall(rect, attributes);
951 NSString *base(state->base_ ?: @"");
953 UIFont *font([attributes objectForKey:@"NSFont"]);
954 UIColor *color([attributes objectForKey:@"NSColor"]);
956 [self drawInRect:rect withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], WBColorMarkup(color), base, info]];
959 extern "C" NSString *NSStringFromCGSize(CGSize size);
961 MSInstanceMessage4(CGRect, NSString, boundingRectWithSize,options,attributes,context, CGSize, size, NSInteger, options, NSDictionary *, attributes, id, context) {
962 //NSLog(@"XXX: $\"%@\" %@ 0x%x %@ %@", self, NSStringFromCGSize(size), unsigned(options), attributes, context);
964 WBStringDrawingState *state(stringDrawingState_);
966 return MSOldCall(size, options, attributes, context);
968 if (state->count_ != 0 && --state->count_ == 0)
969 stringDrawingState_ = state->next_;
970 if (state->info_ == nil)
971 return MSOldCall(size, options, attributes, context);
973 NSString *info([Info_ objectForKey:state->info_]);
975 return MSOldCall(size, options, attributes, context);
977 NSString *base(state->base_ ?: @"");
979 UIFont *font([attributes objectForKey:@"NSFont"]);
980 UIColor *color([attributes objectForKey:@"NSColor"]);
982 return (CGRect) {{0, 0}, [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], WBColorMarkup(color), base, info] forWidth:size.width]};
985 MSInstanceMessage4(CGSize, NSString, sizeWithFont,forWidth,lineBreakMode,letterSpacing, UIFont *, font, CGFloat, width, UILineBreakMode, mode, CGFloat, spacing) {
986 //NSLog(@"XXX: #\"%@\" \"%@\" %g %u %g", self, font, width, mode, spacing);
988 WBStringDrawingState *state(stringDrawingState_);
990 return MSOldCall(font, width, mode, spacing);
992 if (state->count_ != 0 && --state->count_ == 0)
993 stringDrawingState_ = state->next_;
994 if (state->info_ == nil)
995 return MSOldCall(font, width, mode, spacing);
997 NSString *info([Info_ objectForKey:state->info_]);
999 return MSOldCall(font, width, mode, spacing);
1001 NSString *base(state->base_ ?: @"");
1002 NSString *extra([NSString stringWithFormat:@"letter-spacing: %gpx", spacing]);
1003 return [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info] forWidth:width];
1006 MSInstanceMessage1(CGSize, NSString, sizeWithFont, UIFont *, font) {
1007 //NSLog(@"XXX: ?\"%@\"", self);
1009 WBStringDrawingState *state(stringDrawingState_);
1011 return MSOldCall(font);
1013 if (state->count_ != 0 && --state->count_ == 0)
1014 stringDrawingState_ = state->next_;
1015 if (state->info_ == nil)
1016 return MSOldCall(font);
1018 NSString *info([Info_ objectForKey:state->info_]);
1020 return MSOldCall(font);
1022 NSString *base(state->base_ ?: @"");
1023 return [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), base, info] forWidth:65535];
1026 MSClassMessageHook2(id, SBIconBadgeView, checkoutAccessoryImagesForIcon,location, id, icon, int, location) {
1027 WBStringDrawingState badgeState = {NULL, 0, @""
1030 stringDrawingState_ = &badgeState;
1032 id images(MSOldCall(icon, location));
1034 stringDrawingState_ = NULL;
1038 MSClassMessageHook2(UIImage *, SBIconAccessoryImage, checkoutAccessoryImageForIcon,location, id, icon, int, location) {
1039 if ([self _imageClassForIcon:icon location:location] != $SBIconBadgeImage)
1040 return MSOldCall(icon, location);
1042 WBStringDrawingState badgeState = {NULL, 0, @""
1045 stringDrawingState_ = &badgeState;
1047 UIImage *image(MSOldCall(icon, location));
1049 stringDrawingState_ = NULL;
1053 MSInstanceMessageHook1(UIImage *, SBIconBadgeFactory, checkoutBadgeImageForText, NSString *, text) {
1054 WBStringDrawingState badgeState = {NULL, 0, @""
1057 stringDrawingState_ = &badgeState;
1059 UIImage *image(MSOldCall(text));
1061 stringDrawingState_ = NULL;
1065 MSInstanceMessageHook1(UIImage *, SBCalendarApplicationIcon, generateIconImage, int, type) {
1066 WBStringDrawingState dayState = {NULL, 2, @""
1067 // XXX: this is only correct on an iPod dock
1068 "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px;"
1069 , @"CalendarIconDayStyle"};
1071 WBStringDrawingState skipState = {&dayState,
1072 unsigned(kCFCoreFoundationVersionNumber > 800 ? 16 : 7)
1075 WBStringDrawingState dateState = {&skipState, 2, @""
1076 , @"CalendarIconDateStyle"};
1078 stringDrawingState_ = &dateState;
1080 UIImage *image(MSOldCall(type));
1082 stringDrawingState_ = NULL;
1086 MSInstanceMessageHook1(UIImage *, UIStatusBarTimeItemView, contentsImageForStyle, int, style) {
1087 WBStringDrawingState timeState = {NULL, 0, @""
1090 stringDrawingState_ = &timeState;
1092 UIImage *image(MSOldCall(style));
1094 stringDrawingState_ = NULL;
1098 MSHook(void, SBCalendarIconContentsView$drawRect$, SBCalendarIconContentsView *self, SEL sel, CGRect rect) {
1099 NSBundle *bundle([NSBundle mainBundle]);
1101 CFLocaleRef locale(CFLocaleCopyCurrent());
1102 CFDateFormatterRef formatter(CFDateFormatterCreate(NULL, locale, kCFDateFormatterNoStyle, kCFDateFormatterNoStyle));
1105 CFDateRef now(CFDateCreate(NULL, CFAbsoluteTimeGetCurrent()));
1107 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NUMBER_FORMAT" value:@"d" table:@"SpringBoard"]);
1108 CFStringRef date(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
1109 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NAME_FORMAT" value:@"cccc" table:@"SpringBoard"]);
1110 CFStringRef day(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
1114 CFRelease(formatter);
1116 NSString *datestyle([@""
1117 "font-family: Helvetica; "
1118 "font-weight: bold; "
1121 "" stringByAppendingString:(IsWild_
1122 ? @"font-size: 54px; "
1123 : @"font-size: 39px; "
1126 NSString *daystyle([@""
1127 "font-family: Helvetica; "
1128 "font-weight: bold; "
1130 "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px; "
1131 "" stringByAppendingString:(IsWild_
1132 ? @"font-size: 11px; "
1133 : @"font-size: 9px; "
1136 if (NSString *style = [Info_ objectForKey:@"CalendarIconDateStyle"])
1137 datestyle = [datestyle stringByAppendingString:style];
1138 if (NSString *style = [Info_ objectForKey:@"CalendarIconDayStyle"])
1139 daystyle = [daystyle stringByAppendingString:style];
1141 CGFloat width([self bounds].size.width);
1143 CGSize datesize = [(NSString *)date sizeWithStyle:datestyle forWidth:(width + leeway)];
1144 CGSize daysize = [(NSString *)day sizeWithStyle:daystyle forWidth:(width + leeway)];
1146 unsigned base0(IsWild_ ? 89 : 70);
1147 if ($GSFontGetUseLegacyFontMetrics())
1149 unsigned base1(IsWild_ ? 18 : 16);
1156 [(NSString *)date drawAtPoint:CGPointMake(
1157 (width + 1 - datesize.width) / 2, (base0 - datesize.height) / 2
1158 ) withStyle:datestyle];
1160 [(NSString *)day drawAtPoint:CGPointMake(
1161 (width + 1 - daysize.width) / 2, (base1 - daysize.height) / 2
1162 ) withStyle:daystyle];
1168 // %hook -[{NavigationBar,Toolbar} setBarStyle:] {{{
1169 void $setBarStyle$_(NSString *name, int &style) {
1171 NSLog(@"WB:Debug:%@Style:%d", name, style);
1172 NSNumber *number = nil;
1174 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style-%d", name, style]];
1176 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style", name]];
1177 if (number != nil) {
1178 style = [number intValue];
1180 NSLog(@"WB:Debug:%@Style=%d", name, style);
1184 MSInstanceMessageHook1(void, UIToolbar, setBarStyle, int, style) {
1185 $setBarStyle$_(@"Toolbar", style);
1186 return MSOldCall(style);
1189 MSInstanceMessageHook1(void, UINavigationBar, setBarStyle, int, style) {
1190 $setBarStyle$_(@"NavigationBar", style);
1191 return MSOldCall(style);
1195 MSHook(void, SBButtonBar$didMoveToSuperview, UIView *self, SEL sel) {
1196 [[self superview] setBackgroundColor:[UIColor clearColor]];
1197 _SBButtonBar$didMoveToSuperview(self, sel);
1200 MSHook(void, SBStatusBarContentsView$didMoveToSuperview, UIView *self, SEL sel) {
1201 [[self superview] setBackgroundColor:[UIColor clearColor]];
1202 _SBStatusBarContentsView$didMoveToSuperview(self, sel);
1205 static NSArray *Wallpapers_;
1206 static bool Papered_;
1207 static bool Docked_;
1208 static bool SMSBackgrounded_;
1209 static NSString *WallpaperFile_;
1210 static UIImageView *WallpaperImage_;
1211 static UIWebDocumentView *WallpaperPage_;
1212 static NSURL *WallpaperURL_;
1214 #define _release(object) \
1215 do if (object != nil) { \
1220 static UIImage *$getImage$(NSString *path) {
1221 UIImage *image([UIImage imageWithContentsOfFile:path]);
1223 unsigned scale($getScale$(path));
1224 if (scale != 1 && [image respondsToSelector:@selector(setScale)])
1225 [image setScale:scale];
1230 template <typename Original_, typename Modified_>
1231 _finline UIImage *WBCacheImage(const Modified_ &modified, const Original_ &original, NSString *key) {
1232 UIImage *image([Images_ objectForKey:key]);
1234 return reinterpret_cast<id>(image) == [NSNull null] ? original() : image;
1235 if (NSString *path = modified())
1236 image = $getImage$(path);
1237 [Images_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:key];
1238 return image == nil ? original() : image;
1241 static UIImage *$getDefaultDesktopImage$() {
1242 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"LockBackground.png", @"LockBackground.jpg", nil])))
1243 return $getImage$(path);
1247 MSClassMessageHook0(UIImage *, UIImage, defaultDesktopImage) {
1248 return $getDefaultDesktopImage$() ?: MSOldCall();
1251 MSInstanceMessageHook0(UIImage *, SBSlidingAlertDisplay, _defaultDesktopImage) {
1252 return $getDefaultDesktopImage$() ?: MSOldCall();
1255 MSInstanceMessageHook0(void, SBWallpaperView, resetCurrentImageToWallpaper) {
1256 for (UIView *parent([self superview]); parent != nil; parent = [parent superview])
1257 if ([parent isKindOfClass:$SBSlidingAlertDisplay]) {
1258 if (UIImage *image = $getDefaultDesktopImage$()) {
1259 [self setImage:image];
1269 // %hook -[SBUIController init] {{{
1270 MSInstanceMessageHook0(id, SBUIController, init) {
1275 NSString *paper($getTheme$(Wallpapers_));
1277 paper = [paper stringByDeletingLastPathComponent];
1280 NSLog(@"WB:Debug:Info = %@", [Info_ description]);
1283 UIImageView *&_wallpaperView(MSHookIvar<UIImageView *>(self, "_wallpaperView"));
1284 if (&_wallpaperView != NULL) {
1285 [_wallpaperView removeFromSuperview];
1286 [_wallpaperView release];
1287 _wallpaperView = nil;
1291 UIView *&_contentLayer(MSHookIvar<UIView *>(self, "_contentLayer"));
1292 UIView *&_contentView(MSHookIvar<UIView *>(self, "_contentView"));
1295 if (&_contentLayer != NULL)
1296 player = &_contentLayer;
1297 else if (&_contentView != NULL)
1298 player = &_contentView;
1301 UIView *layer(player == NULL ? nil : *player);
1303 UIWindow *window([[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]);
1304 UIView *content([[[UIView alloc] initWithFrame:[window frame]] autorelease]);
1305 [window setContentView:content];
1307 UIWindow *&_window(MSHookIvar<UIWindow *>(self, "_window"));
1308 [window setBackgroundColor:[_window backgroundColor]];
1309 [_window setBackgroundColor:[UIColor clearColor]];
1311 [window setLevel:-1000];
1312 [window setHidden:NO];
1314 /*if (player != NULL)
1315 *player = content;*/
1317 [content setBackgroundColor:[layer backgroundColor]];
1318 [layer setBackgroundColor:[UIColor clearColor]];
1321 if (!SummerBoard_ || !IsWild_)
1324 CGRect bounds([content bounds]);
1325 bounds.origin.y = -30;
1326 indirect = [[[UIView alloc] initWithFrame:bounds] autorelease];
1327 [content addSubview:indirect];
1328 [indirect zoomToScale:2.4];
1331 _release(WallpaperFile_);
1332 _release(WallpaperImage_);
1333 _release(WallpaperPage_);
1334 _release(WallpaperURL_);
1337 NSArray *themes([NSArray arrayWithObject:paper]);
1339 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"], themes)) {
1343 static AVController *controller_(nil);
1344 if (controller_ == nil) {
1345 AVQueue *queue([AVQueue avQueue]);
1346 controller_ = [[AVController avControllerWithQueue:queue error:&error] retain];
1349 AVQueue *queue([controller_ queue]);
1351 UIView *video([[[UIView alloc] initWithFrame:[indirect bounds]] autorelease]);
1352 [controller_ setLayer:[video _layer]];
1354 AVItem *item([[[AVItem alloc] initWithPath:path error:&error] autorelease]);
1355 [queue appendItem:item error:&error];
1357 [controller_ play:&error];
1358 #elif UseMPMoviePlayerController
1359 NSURL *url([NSURL fileURLWithPath:path]);
1360 MPMoviePlayerController *controller = [[$MPMoviePlayerController alloc] initWithContentURL:url];
1361 controller.movieControlMode = MPMovieControlModeHidden;
1364 MPVideoView *video = [[[$MPVideoView alloc] initWithFrame:[indirect bounds]] autorelease];
1365 [video setMovieWithPath:path];
1366 [video setRepeatMode:1];
1367 [video setRepeatGap:-1];
1368 [video playFromBeginning];;
1371 [indirect addSubview:video];
1374 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"Wallpaper.png", @"Wallpaper.jpg", nil]), themes)) {
1375 if (UIImage *image = $getImage$(path)) {
1376 WallpaperFile_ = [path retain];
1377 WallpaperImage_ = [[UIImageView alloc] initWithImage:image];
1378 if (NSNumber *number = [Info_ objectForKey:@"WallpaperAlpha"])
1379 [WallpaperImage_ setAlpha:[number floatValue]];
1380 [indirect addSubview:WallpaperImage_];
1384 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.html"], themes)) {
1385 CGRect bounds = [indirect bounds];
1387 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1388 [view setAutoresizes:true];
1390 WallpaperPage_ = [view retain];
1391 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
1393 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1395 [view setBackgroundColor:[UIColor clearColor]];
1396 if ([view respondsToSelector:@selector(setDrawsBackground:)])
1397 [view setDrawsBackground:NO];
1398 [[view webView] setDrawsBackground:NO];
1400 [indirect addSubview:view];
1404 for (size_t i(0), e([Themes_ count]); i != e; ++i) {
1405 NSString *theme = [Themes_ objectAtIndex:(e - i - 1)];
1406 NSString *html = [theme stringByAppendingPathComponent:@"Widget.html"];
1407 if ([Manager_ fileExistsAtPath:html]) {
1408 CGRect bounds = [indirect bounds];
1410 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1411 [view setAutoresizes:true];
1413 NSURL *url = [NSURL fileURLWithPath:html];
1414 [view loadRequest:[NSURLRequest requestWithURL:url]];
1416 [view setBackgroundColor:[UIColor clearColor]];
1417 if ([view respondsToSelector:@selector(setDrawsBackground:)])
1418 [view setDrawsBackground:NO];
1419 [[view webView] setDrawsBackground:NO];
1421 [indirect addSubview:view];
1429 MSHook(void, SBAwayView$updateDesktopImage$, SBAwayView *self, SEL sel, UIImage *image) {
1430 NSString *path = $getTheme$([NSArray arrayWithObject:@"LockBackground.html"]);
1431 UIView *&_backgroundView(MSHookIvar<UIView *>(self, "_backgroundView"));
1433 if (path != nil && _backgroundView != nil)
1436 _SBAwayView$updateDesktopImage$(self, sel, image);
1439 CGRect bounds = [self bounds];
1441 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1442 [view setAutoresizes:true];
1444 if (WallpaperPage_ != nil)
1445 [WallpaperPage_ release];
1446 WallpaperPage_ = [view retain];
1448 if (WallpaperURL_ != nil)
1449 [WallpaperURL_ release];
1450 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
1452 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1454 [[view webView] setDrawsBackground:false];
1455 [view setBackgroundColor:[UIColor clearColor]];
1457 [self insertSubview:view aboveSubview:_backgroundView];
1459 if ($objc_setAssociatedObject != NULL)
1460 $objc_setAssociatedObject(self, @selector(wb$widgetView), view, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1464 MSHook(void, SBAwayView$_addSubview$positioned$relativeTo$, SBAwayView *self, SEL sel, UIView *view, int positioned, UIView *relative) {
1465 UIView *&_backgroundView(MSHookIvar<UIView *>(self, "_backgroundView"));
1466 UIView *&_chargingView(MSHookIvar<UIView *>(self, "_chargingView"));
1467 if (&_chargingView != NULL)
1468 if (positioned == -2 && (relative == _backgroundView && _chargingView == nil || relative == _chargingView))
1469 if ($objc_getAssociatedObject != NULL)
1470 if (UIView *widget = $objc_getAssociatedObject(self, @selector(wb$widgetView)))
1472 return _SBAwayView$_addSubview$positioned$relativeTo$(self, sel, view, positioned, relative);
1475 /*extern "C" CGColorRef CGGStateGetSystemColor(void *);
1476 extern "C" CGColorRef CGGStateGetFillColor(void *);
1477 extern "C" CGColorRef CGGStateGetStrokeColor(void *);
1478 extern "C" NSString *UIStyleStringFromColor(CGColorRef);*/
1480 /* WBTimeLabel {{{ */
1481 @interface WBTimeLabel : NSProxy {
1483 _transient SBStatusBarTimeView *view_;
1486 - (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view;
1490 @implementation WBTimeLabel
1497 - (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view {
1498 time_ = [time retain];
1503 - (NSString *) description {
1509 - (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(UILineBreakMode)mode {
1510 if (NSString *custom = [Info_ objectForKey:@"TimeStyle"]) {
1511 BOOL &_mode(MSHookIvar<BOOL>(view_, "_mode"));;
1513 [time_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1514 "font-family: Helvetica; "
1515 "font-weight: bold; "
1518 "%@", _mode ? @"white" : @"black", custom]];
1523 return [time_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1528 /* WBBadgeLabel {{{ */
1529 @interface WBBadgeLabel : NSProxy {
1533 - (id) initWithBadge:(NSString *)badge;
1534 - (NSString *) description;
1538 @implementation WBBadgeLabel
1545 - (id) initWithBadge:(NSString *)badge {
1546 badge_ = [badge retain];
1550 - (NSString *) description {
1551 return [badge_ description];
1556 - (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(UILineBreakMode)mode {
1557 if (NSString *custom = [Info_ objectForKey:@"BadgeStyle"]) {
1558 [badge_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1559 "font-family: Helvetica; "
1560 "font-weight: bold; "
1568 return [badge_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1575 MSInstanceMessageHook1(void, SBIcon, setIconImageAlpha, CGFloat, alpha) {
1576 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1577 alpha = [number floatValue];
1578 return MSOldCall(alpha);
1581 MSInstanceMessageHook1(void, SBIcon, setIconLabelAlpha, CGFloat, alpha) {
1582 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1583 alpha = [number floatValue];
1584 return MSOldCall(alpha);
1587 MSInstanceMessageHook0(id, SBIcon, initWithDefaultSize) {
1588 if ((self = MSOldCall()) != nil) {
1589 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"]) {
1590 // XXX: note: this is overridden above, which is silly
1591 float alpha([number floatValue]);
1592 if ([self respondsToSelector:@selector(setIconImageAlpha:)])
1593 [self setIconImageAlpha:alpha];
1594 if ([self respondsToSelector:@selector(setIconLabelAlpha:)])
1595 [self setIconLabelAlpha:alpha];
1596 if ([self respondsToSelector:@selector(setAlpha:)])
1597 [self setAlpha:alpha];
1602 MSInstanceMessageHook1(void, SBIcon, setAlpha, CGFloat, alpha) {
1603 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1604 alpha = [number floatValue];
1605 return MSOldCall(alpha);
1609 MSHook(id, SBIconBadge$initWithBadge$, SBIconBadge *self, SEL sel, NSString *badge) {
1610 if ((self = _SBIconBadge$initWithBadge$(self, sel, badge)) != nil) {
1611 id &_badge(MSHookIvar<id>(self, "_badge"));
1613 if (id label = [[WBBadgeLabel alloc] initWithBadge:[_badge autorelease]])
1618 void SBStatusBarController$setStatusBarMode(int &mode) {
1620 NSLog(@"WB:Debug:setStatusBarMode:%d", mode);
1621 if (mode < 100) // 104:hidden 105:glowing
1622 if (NSNumber *number = [Info_ objectForKey:@"StatusBarMode"])
1623 mode = [number intValue];
1626 /*MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, double duration, int animation) {
1627 NSLog(@"mode:%d orientation:%d duration:%f animation:%d", mode, orientation, duration, animation);
1628 SBStatusBarController$setStatusBarMode(mode);
1629 return _SBStatusBarController$setStatusBarMode$orientation$duration$animation$(self, sel, mode, orientation, duration, animation);
1632 MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, float duration, int fenceID, int animation) {
1633 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d", mode, orientation, duration, fenceID, animation);
1634 SBStatusBarController$setStatusBarMode(mode);
1635 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$(self, sel, mode, orientation, duration, fenceID, animation);
1638 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) {
1639 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d startTime:%f", mode, orientation, duration, fenceID, animation, startTime);
1640 SBStatusBarController$setStatusBarMode(mode);
1641 //NSLog(@"mode=%u", mode);
1642 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$startTime$(self, sel, mode, orientation, duration, fenceID, animation, startTime);
1645 /*MSHook(id, SBStatusBarContentsView$initWithStatusBar$mode$, SBStatusBarContentsView *self, SEL sel, id bar, int mode) {
1646 if (NSNumber *number = [Info_ objectForKey:@"StatusBarContentsMode"])
1647 mode = [number intValue];
1648 return _SBStatusBarContentsView$initWithStatusBar$mode$(self, sel, bar, mode);
1651 MSHook(NSString *, SBStatusBarOperatorNameView$operatorNameStyle, SBStatusBarOperatorNameView *self, SEL sel) {
1652 NSString *style(_SBStatusBarOperatorNameView$operatorNameStyle(self, sel));
1654 NSLog(@"operatorNameStyle= %@", style);
1655 if (NSString *custom = [Info_ objectForKey:@"OperatorNameStyle"])
1656 style = [NSString stringWithFormat:@"%@; %@", style, custom];
1660 MSHook(void, SBStatusBarOperatorNameView$setOperatorName$fullSize$, SBStatusBarOperatorNameView *self, SEL sel, NSString *name, BOOL full) {
1662 NSLog(@"setOperatorName:\"%@\" fullSize:%u", name, full);
1663 return _SBStatusBarOperatorNameView$setOperatorName$fullSize$(self, sel, name, NO);
1666 // XXX: replace this with [SBStatusBarTimeView tile]
1667 MSHook(void, SBStatusBarTimeView$drawRect$, SBStatusBarTimeView *self, SEL sel, CGRect rect) {
1668 id &_time(MSHookIvar<id>(self, "_time"));
1669 if (_time != nil && [_time class] != [WBTimeLabel class])
1670 object_setInstanceVariable(self, "_time", reinterpret_cast<void *>([[WBTimeLabel alloc] initWithTime:[_time autorelease] view:self]));
1671 return _SBStatusBarTimeView$drawRect$(self, sel, rect);
1674 @interface UIView (WinterBoard)
1675 - (bool) wb$isWBImageView;
1676 - (void) wb$logHierarchy;
1677 - (void) wb$setBackgroundColor:(UIColor *)color;
1680 @implementation UIView (WinterBoard)
1682 - (bool) wb$isWBImageView {
1686 - (void) wb$logHierarchy {
1687 WBLogHierarchy(self);
1690 - (void) wb$setBackgroundColor:(UIColor *)color {
1691 [self setBackgroundColor:color];
1692 for (UIView *child in [self subviews])
1693 [child wb$setBackgroundColor:color];
1698 @interface WBImageView : UIImageView {
1701 - (bool) wb$isWBImageView;
1702 - (void) wb$updateFrame;
1705 @implementation WBImageView
1707 - (bool) wb$isWBImageView {
1711 - (void) wb$updateFrame {
1712 CGRect frame([self frame]);
1715 for (UIView *view(self); ; ) {
1716 view = [view superview];
1719 frame.origin.y -= [view frame].origin.y;
1722 [self setFrame:frame];
1727 static void SBIconList$updateFrames$(SBIconList *self) {
1728 NSArray *subviews([self subviews]);
1729 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1730 if (view != nil && [view wb$isWBImageView])
1731 [view wb$updateFrame];
1734 MSHook(void, SBIconList$didMoveToSuperview, SBIconList *self, SEL sel) {
1735 SBIconList$updateFrames$(self);
1736 _SBIconList$didMoveToSuperview(self, sel);
1739 MSHook(void, SBIconList$setFrame$, SBIconList *self, SEL sel, CGRect frame) {
1740 SBIconList$updateFrames$(self);
1741 _SBIconList$setFrame$(self, sel, frame);
1744 static void $addPerPageView$(unsigned i, UIView *list) {
1745 NSString *path($getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Page%u.png", i]]));
1749 NSArray *subviews([list subviews]);
1751 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1752 if (view == nil || ![view wb$isWBImageView]) {
1753 view = [[[WBImageView alloc] init] autorelease];
1754 [list insertSubview:view atIndex:0];
1757 UIImage *image([UIImage imageWithContentsOfFile:path]);
1759 CGRect frame([view frame]);
1760 frame.size = [image size];
1761 [view setFrame:frame];
1763 [view setImage:image];
1764 [view wb$updateFrame];
1767 static void $addPerPageViews$(NSArray *lists) {
1768 for (unsigned i(0), e([lists count]); i != e; ++i)
1769 $addPerPageView$(i, [lists objectAtIndex:i]);
1772 MSInstanceMessageHook0(void, SBIconController, updateNumberOfRootIconLists) {
1773 NSArray *&_rootIconLists(MSHookIvar<NSArray *>(self, "_rootIconLists"));
1774 $addPerPageViews$(_rootIconLists);
1778 MSInstanceMessageHook0(void, SBIconContentView, layoutSubviews) {
1781 if (SBIconController *controller = [$SBIconController sharedInstance]) {
1782 UIView *&_dockContainerView(MSHookIvar<UIView *>(controller, "_dockContainerView"));
1783 if (&_dockContainerView != NULL)
1784 [[_dockContainerView superview] bringSubviewToFront:_dockContainerView];
1788 MSHook(void, SBIconController$noteNumberOfIconListsChanged, SBIconController *self, SEL sel) {
1789 SBIconModel *&_iconModel(MSHookIvar<SBIconModel *>(self, "_iconModel"));
1790 $addPerPageViews$([_iconModel iconLists]);
1791 return _SBIconController$noteNumberOfIconListsChanged(self, sel);
1794 MSHook(id, SBIconLabel$initWithSize$label$, SBIconLabel *self, SEL sel, CGSize size, NSString *label) {
1795 self = _SBIconLabel$initWithSize$label$(self, sel, size, label);
1797 [self setClipsToBounds:NO];
1801 MSHook(void, SBIconLabel$setInDock$, SBIconLabel *self, SEL sel, BOOL docked) {
1802 static bool gssc(false);
1804 BOOL (*GSSystemHasCapability)(CFStringRef) = reinterpret_cast<BOOL (*)(CFStringRef)>(dlsym(RTLD_DEFAULT, "GSSystemHasCapability"));
1805 Papered_ |= GSSystemHasCapability != NULL && GSSystemHasCapability(CFSTR("homescreen-wallpaper"));
1808 if ([Info_ objectForKey:@"UndockedIconLabels"] == nil)
1809 [Info_ setObject:[NSNumber numberWithBool:(
1811 [Info_ objectForKey:@"DockedIconLabelStyle"] != nil ||
1812 [Info_ objectForKey:@"UndockedIconLabelStyle"] != nil
1813 )] forKey:@"UndockedIconLabels"];
1816 id &_label(MSHookIvar<id>(self, "_label"));
1817 if (![Info_ wb$boolForKey:@"UndockedIconLabels"])
1820 if (_label != nil && [_label respondsToSelector:@selector(setInDock:)])
1821 [_label setInDock:docked];
1823 _SBIconLabel$setInDock$(self, sel, docked);
1824 [self setNeedsDisplay];
1827 MSHook(BOOL, SBDockIconListView$shouldShowNewDock, id self, SEL sel) {
1828 return SummerBoard_ && Docked_ ? NO : _SBDockIconListView$shouldShowNewDock(self, sel);
1831 MSHook(void, SBDockIconListView$setFrame$, id self, SEL sel, CGRect frame) {
1832 _SBDockIconListView$setFrame$(self, sel, frame);
1835 // %hook -[NSBundle localizedStringForKey:value:table:] {{{
1836 MSInstanceMessageHook3(NSString *, NSBundle, localizedStringForKey,value,table, NSString *, key, NSString *, value, NSString *, table) {
1837 NSString *identifier = [self bundleIdentifier];
1838 NSLocale *locale = [NSLocale currentLocale];
1839 NSString *language = [locale objectForKey:NSLocaleLanguageCode];
1841 NSLog(@"WB:Debug:[NSBundle(%@) localizedStringForKey:\"%@\" value:\"%@\" table:\"%@\"] (%@)", identifier, key, value, table, language);
1842 NSString *file = table == nil ? @"Localizable" : table;
1843 NSString *name = [NSString stringWithFormat:@"%@:%@", identifier, file];
1844 NSDictionary *strings;
1845 if ((strings = [Strings_ objectForKey:name]) != nil) {
1846 if (static_cast<id>(strings) != [NSNull null]) strings:
1847 if (NSString *value = [strings objectForKey:key])
1849 } else if (NSString *path = $pathForFile$inBundle$([NSString stringWithFormat:@"%@.lproj/%@.strings",
1852 if ((strings = [[NSDictionary alloc] initWithContentsOfFile:path]) != nil) {
1853 [Strings_ setObject:[strings autorelease] forKey:name];
1857 [Strings_ setObject:[NSNull null] forKey:name];
1858 return MSOldCall(key, value, table);
1861 // %hook -[WebCoreFrameBridge renderedSizeOfNode:constrainedToWidth:] {{{
1862 MSClassHook(WebCoreFrameBridge)
1864 MSInstanceMessageHook2(CGSize, WebCoreFrameBridge, renderedSizeOfNode,constrainedToWidth, id, node, float, width) {
1867 void **core(reinterpret_cast<void **>([node _node]));
1868 if (core == NULL || core[6] == NULL)
1870 return MSOldCall(node, width);
1874 MSInstanceMessage1(void, SBIconLabel, drawRect, CGRect, rect) {
1875 static Ivar drawMoreLegibly = object_getInstanceVariable(self, "_drawMoreLegibly", NULL);
1878 Ivar ivar = object_getInstanceVariable(self, "_inDock", reinterpret_cast<void **>(&docked));
1879 docked = (docked & (ivar_getOffset(ivar) == ivar_getOffset(drawMoreLegibly) ? 0x2 : 0x1)) != 0;
1881 NSString *label(MSHookIvar<NSString *>(self, "_label"));
1883 NSString *style = [NSString stringWithFormat:@""
1884 "font-family: Helvetica; "
1885 "font-weight: bold; "
1887 "", (docked || !SummerBoard_ ? @"white" : @"#b3b3b3"), (IsWild_
1888 ? @"font-size: 12px; "
1889 : @"font-size: 11px; "
1893 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px 1px 0px; "];
1895 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px -1px 0px; "];
1897 NSString *custom([Info_ objectForKey:(docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle")]);
1899 $drawLabel$(label, [self bounds], style, custom);
1902 MSInstanceMessage0(CGImageRef, SBIconLabel, buildLabelImage) {
1903 bool docked((MSHookIvar<unsigned>(self, "_inDock") & 0x2) != 0);
1905 WBStringDrawingState labelState = {NULL, 0, @""
1906 , docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle"};
1908 stringDrawingState_ = &labelState;
1911 CGImageRef image(MSOldCall());
1914 stringDrawingState_ = NULL;
1918 static bool wb$inDock(id parameters) {
1919 return [$objc_getAssociatedObject(parameters, @selector(wb$inDock)) boolValue];
1922 MSInstanceMessage0(NSUInteger, SBIconLabelImageParameters, hash) {
1923 return MSOldCall() + (wb$inDock(self) ? 0xdeadbeef : 0xd15ea5e);
1926 MSClassMessage2(id, SBIconView, _labelImageParametersForIcon,location, id, icon, int, location) {
1927 if (id parameters = MSOldCall(icon, location)) {
1928 $objc_setAssociatedObject(parameters, @selector(wb$inDock), [NSNumber numberWithBool:(location == 1)], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1933 MSInstanceMessage0(id, SBIconView, _labelImageParameters) {
1934 if (id parameters = MSOldCall()) {
1935 int &location(MSHookIvar<int>(self, "_iconLocation"));
1936 if (&location != NULL)
1937 $objc_setAssociatedObject(parameters, @selector(wb$inDock), [NSNumber numberWithBool:(location == 3)], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1942 MSClassMessage1(UIImage *, SBIconLabelImage, _drawLabelImageForParameters, id, parameters) {
1943 bool docked(wb$inDock(parameters));
1945 WBStringDrawingState labelState = {NULL, 0, @""
1946 , docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle"};
1948 stringDrawingState_ = &labelState;
1951 UIImage *image(MSOldCall(parameters));
1954 stringDrawingState_ = NULL;
1959 MSInstanceMessageHook2(id, CKBalloonView, initWithFrame,delegate, CGRect, frame, id, delegate) {
1960 if ((self = MSOldCall(frame, delegate)) != nil) {
1961 [self setBackgroundColor:[UIColor clearColor]];
1965 MSInstanceMessageHook0(BOOL, CKBalloonView, _canUseLayerBackedBalloon) {
1966 return SMSBackgrounded_ ? NO : MSOldCall();
1969 MSInstanceMessageHook0(void, CKTranscriptHeaderView, layoutSubviews) {
1970 [self wb$setBackgroundColor:[UIColor clearColor]];
1974 MSInstanceMessageHook1(void, CKMessageCell, addBalloonView, CKBalloonView *, balloon) {
1976 [balloon setBackgroundColor:[UIColor clearColor]];
1979 MSInstanceMessageHook1(void, CKTranscriptCell, setBackgroundColor, UIColor *, color) {
1980 MSOldCall([UIColor clearColor]);
1981 [[self contentView] wb$setBackgroundColor:[UIColor clearColor]];
1985 MSInstanceMessageHook2(id, CKTranscriptCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1986 if ((self = MSOldCall(style, reuse)) != nil) {
1987 [self setBackgroundColor:[UIColor clearColor]];
1988 [[self contentView] wb$setBackgroundColor:[UIColor clearColor]];
1993 MSInstanceMessageHook2(id, CKMessageCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1994 if ((self = MSOldCall(style, reuse)) != nil) {
1995 [self setBackgroundColor:[UIColor clearColor]];
1996 [[self contentView] setBackgroundColor:[UIColor clearColor]];
2000 MSInstanceMessageHook2(id, CKTimestampView, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
2001 if ((self = MSOldCall(style, reuse)) != nil) {
2002 UILabel *&_label(MSHookIvar<UILabel *>(self, "_label"));
2003 [_label setBackgroundColor:[UIColor clearColor]];
2007 MSInstanceMessageHook1(void, CKTranscriptTableView, setSeparatorStyle, int, style) {
2008 MSOldCall(UITableViewCellSeparatorStyleNone);
2011 MSInstanceMessageHook2(id, CKTranscriptTableView, initWithFrame,style, CGRect, frame, int, style) {
2012 if ((self = MSOldCall(frame, style)) != nil) {
2013 [self setSeparatorStyle:UITableViewCellSeparatorStyleNone];
2017 MSInstanceMessageHook0(void, CKTranscriptController, loadView) {
2020 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"SMSBackground.png", @"SMSBackground.jpg", nil])))
2021 if (UIImage *image = $getImage$(path)) {
2022 SMSBackgrounded_ = true;
2024 UIView *&_transcriptTable(MSHookIvar<UIView *>(self, "_transcriptTable"));
2025 UIView *&_transcriptLayer(MSHookIvar<UIView *>(self, "_transcriptLayer"));
2027 if (&_transcriptTable != NULL)
2028 table = _transcriptTable;
2029 else if (&_transcriptLayer != NULL)
2030 table = _transcriptLayer;
2034 UIView *placard(table != nil ? [table superview] : MSHookIvar<UIView *>(self, "_backPlacard"));
2035 UIImageView *background([[[UIImageView alloc] initWithImage:image] autorelease]);
2038 [placard insertSubview:background atIndex:0];
2040 [table setBackgroundColor:[UIColor clearColor]];
2041 [placard insertSubview:background belowSubview:table];
2047 template <typename Original_>
2048 static UIImage *WBCacheImage(NSBundle *bundle, NSString *name, const Original_ &original, NSString *key) {
2051 NSUInteger period([name rangeOfString:@"."].location);
2052 NSUInteger length([name length]);
2053 if (period == NSNotFound || length < 4 || period > length - 4)
2054 name = [name stringByAppendingString:@".png"];
2056 return WBCacheImage(
2057 [=](){ return $pathForFile$inBundle$(name, bundle, true); },
2058 [bundle, &original, name](){
2059 UIImage *image(original());
2060 if (image != nil && UIDebug_) {
2061 NSString *path([@"/tmp/WBImages/" stringByAppendingString:[bundle bundleIdentifier]]);
2062 [Manager_ createDirectoryAtPath:path withIntermediateDirectories:YES attributes:@{NSFilePosixPermissions: @0777} error:NULL];
2063 path = [NSString stringWithFormat:@"%@/%@", path, name];
2064 if (![Manager_ fileExistsAtPath:path])
2065 [UIImagePNGRepresentation(image) writeToFile:path atomically:YES];
2071 // %hook _UIImageWithName() {{{
2072 MSHook(UIImage *, _UIImageWithName, NSString *name) {
2076 NSLog(@"WB:Debug: _UIImageWithName(\"%@\")", name);
2077 return WBCacheImage(_UIKitBundle(), name,
2078 [=](){ return __UIImageWithName(name); },
2079 [NSString stringWithFormat:@"I:%@", name]);
2082 // %hook _UIImageWithNameInDomain() {{{
2083 MSHook(UIImage *, _UIImageWithNameInDomain, NSString *name, NSString *domain) {
2085 NSLog(@"WB:Debug: _UIImageWithNameInDomain(\"%@\", \"%@\")", name, domain);
2086 return WBCacheImage(
2087 [=](){ return $getTheme$($useScale$([NSArray arrayWithObject:[NSString stringWithFormat:@"Domains/%@/%@", domain, name]])); },
2088 [=](){ return __UIImageWithNameInDomain(name, domain); },
2089 [NSString stringWithFormat:@"D:%zu:%@%@", size_t([domain length]), domain, name]);
2093 // UISharedArtwork (iOS 6) {{{
2094 MSInstanceMessageHook2(UISharedArtwork *, UISharedArtwork, initWithName,inBundle, NSString *, name, NSBundle *, bundle) {
2095 if ((self = MSOldCall(name, bundle)) != nil) {
2096 $objc_setAssociatedObject(self, @selector(wb$bundle), bundle, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
2100 MSInstanceMessageHook2(UIImage *, UISharedArtwork, imageNamed,device, NSString *, name, NSInteger, device) {
2101 NSBundle *bundle($objc_getAssociatedObject(self, @selector(wb$bundle)));
2103 NSLog(@"WB:Debug: -[UISharedArtwork(%@) imageNamed:@\"%@\" device:%li]", [bundle bundleIdentifier], name, (long) device);
2104 return WBCacheImage(bundle, name,
2105 [=](){ return MSOldCall(name, device); },
2106 [NSString stringWithFormat:@"M:%p:%@:%li", self, name, (long) device]);
2109 // _UIAssetManager (iOS 7) {{{
2110 MSInstanceMessageHook3(_UIAssetManager *, _UIAssetManager, initWithName,inBundle,idiom, NSString *, name, NSBundle *, bundle, NSInteger, idiom) {
2111 if ((self = MSOldCall(name, bundle, idiom)) != nil) {
2112 $objc_setAssociatedObject(self, @selector(wb$bundle), bundle, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
2116 MSInstanceMessageHook5(UIImage *, _UIAssetManager, imageNamed,scale,idiom,subtype,cachingOptions, NSString *, name, CGFloat, scale, NSInteger, idiom, NSUInteger, subtype, NSUInteger, caching) {
2117 NSBundle *bundle($objc_getAssociatedObject(self, @selector(wb$bundle)));
2119 NSLog(@"WB:Debug: -[_UIAssetManager(%@/%@) imageNamed:@\"%@\" scale:%g idiom:%li subtype:%lu cachingOptions:%lu]",
2120 [bundle bundleIdentifier], [self carFileName],
2121 name, scale, (long) idiom,
2122 (unsigned long) subtype,
2123 (unsigned long) caching
2126 if (bundle == _UIKitBundle()) {
2127 NSString *name([self carFileName]);
2129 else if ([name isEqualToString:@"UIKit_NewArtwork"])
2130 bundle = [WBBundle bundleWithIdentifier:@"com.apple.uikit.Artwork"];
2131 else if ([name isEqualToString:@"UIKit_OriginalArtwork"])
2132 bundle = [WBBundle bundleWithIdentifier:@"com.apple.uikit.LegacyArtwork"];
2135 return WBCacheImage(bundle, name,
2136 [=](){ return MSOldCall(name, scale, idiom, subtype, caching); },
2137 [NSString stringWithFormat:@"M:%p:%@:%g:%li:%lu", self, name, scale, (long) idiom, (unsigned long) subtype]);
2140 // _UIAssetManager (iOS 8) {{{
2141 struct SizeClassPair {
2146 MSInstanceMessageHook7(UIImage *, _UIAssetManager, imageNamed,scale,idiom,subtype,cachingOptions,sizeClassPair,attachCatalogImage, NSString *, name, CGFloat, scale, NSInteger, idiom, NSUInteger, subtype, NSUInteger, caching, SizeClassPair, size, BOOL, attach) {
2147 NSBundle *bundle([self bundle]);
2149 NSLog(@"WB:Debug: -[_UIAssetManager(%@/%@) imageNamed:@\"%@\" scale:%g idiom:%li subtype:%lu cachingOptions:%lu sizeClassPair:[%li %li] attachCatalogImage:%s]",
2150 [bundle bundleIdentifier], [self carFileName],
2151 name, scale, (long) idiom,
2152 (unsigned long) subtype,
2153 (unsigned long) caching,
2154 (long) size.first, (long) size.second,
2155 attach ? "YES" : "NO"
2157 return WBCacheImage(bundle, name,
2158 [=](){ return MSOldCall(name, scale, idiom, subtype, caching, size, attach); },
2159 [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']);
2163 // %hook GSFontCreateWithName() {{{
2164 MSHook(GSFontRef, GSFontCreateWithName, const char *name, GSFontSymbolicTraits traits, float size) {
2166 NSLog(@"WB:Debug: GSFontCreateWithName(\"%s\", %f)", name, size);
2167 if (NSString *font = [Info_ objectForKey:[NSString stringWithFormat:@"FontName-%s", name]])
2168 name = [font UTF8String];
2169 //if (NSString *scale = [Info_ objectForKey:[NSString stringWithFormat:@"FontScale-%s", name]])
2170 // size *= [scale floatValue];
2171 return _GSFontCreateWithName(name, traits, size);
2175 #define AudioToolbox "/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox"
2177 static bool GetFileNameForThisAction$(bool value, unsigned long a0, char *a1, unsigned long a2, bool &a3) {
2179 NSLog(@"WB:Debug:GetFileNameForThisAction(%lu, %s, %lu, %u) = %u", a0, value ? a1 : NULL, a2, a3, value);
2182 NSString *path = [NSString stringWithUTF8String:a1];
2183 if ([path hasPrefix:@"/System/Library/Audio/UISounds/"]) {
2184 NSString *file = [path substringFromIndex:31];
2185 for (NSString *theme in Themes_) {
2186 NSString *path([NSString stringWithFormat:@"%@/UISounds/%@", theme, file]);
2187 if ([Manager_ fileExistsAtPath:path]) {
2188 strcpy(a1, [path UTF8String]);
2197 MSHook(bool, _Z24GetFileNameForThisActionmPcRb, unsigned long a0, char *a1, bool &a3) {
2198 bool value(__Z24GetFileNameForThisActionmPcRb(a0, a1, a3));
2199 return GetFileNameForThisAction$(value, a0, a1, 0, a3);
2203 MSHook(bool, _Z24GetFileNameForThisActionjPcjRb, unsigned int a0, char *a1, unsigned int a2, bool &a3) {
2204 bool value(__Z24GetFileNameForThisActionjPcjRb(a0, a1, a2, a3));
2205 return GetFileNameForThisAction$(value, a0, a1, a2, a3);
2208 MSHook(bool, _Z24GetFileNameForThisActionmPcmRb, unsigned long a0, char *a1, unsigned long a2, bool &a3) {
2209 bool value(__Z24GetFileNameForThisActionmPcmRb(a0, a1, a2, a3));
2210 return GetFileNameForThisAction$(value, a0, a1, a2, a3);
2214 static void ChangeWallpaper(
2215 CFNotificationCenterRef center,
2219 CFDictionaryRef info
2222 NSLog(@"WB:Debug:ChangeWallpaper!");
2225 if (WallpaperFile_ != nil) {
2226 image = [[UIImage alloc] initWithContentsOfFile:WallpaperFile_];
2228 image = [image autorelease];
2231 if (WallpaperImage_ != nil)
2232 [WallpaperImage_ setImage:image];
2233 if (WallpaperPage_ != nil)
2234 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
2238 MSHook(NSArray *, CPBitmapCreateImagesFromPath, NSString *path, CFTypeRef *names, void *arg2, void *arg3) {
2239 NSArray *images(_CPBitmapCreateImagesFromPath(path, names, arg2, arg3));
2245 NSBundle *bundle([NSBundle wb$bundleWithFile:path]);
2249 NSString *file([path stringByResolvingSymlinksInPath]);
2250 NSString *prefix([[bundle bundlePath] stringByResolvingSymlinksInPath]);
2251 // XXX: why do I care about this?
2252 if (![file hasPrefix:prefix])
2255 NSMutableArray *copy([images mutableCopy]);
2259 NSDictionary *indexes;
2260 NSEnumerator *enumerator;
2262 if (CFGetTypeID((CFTypeRef) *names) == CFDictionaryGetTypeID()) {
2263 indexes = (NSDictionary *) *names;
2264 enumerator = [indexes keyEnumerator];
2267 enumerator = [(NSArray *) *names objectEnumerator];
2270 for (NSUInteger index(0); NSString *name = [enumerator nextObject]; ++index)
2271 if (NSString *themed = $pathForFile$inBundle$([name stringByAppendingString:@".png"], bundle, true)) {
2273 index = [[indexes objectForKey:name] intValue];
2274 if (UIImage *image = $getImage$(themed))
2275 [copy replaceObjectAtIndex:index withObject:(id)[image CGImage]];
2281 MSHook(void, BKSDisplayServicesSetSystemAppExitedImagePath, NSString *path) {
2282 if (NSString *themed = $getTheme$($useScale$([NSArray arrayWithObject:@"SystemAppExited.png"])))
2284 _BKSDisplayServicesSetSystemAppExitedImagePath(path);
2287 #define WBRename(name, sel, imp) \
2288 MSHookMessage($ ## name, @selector(sel), &$ ## name ## $ ## imp, &_ ## name ## $ ## imp)
2290 template <typename Type_>
2291 static void msset(Type_ &function, MSImageRef image, const char *name) {
2292 function = reinterpret_cast<Type_>(MSFindSymbol(image, name));
2295 #define WBHookSymbol(image, function) \
2296 msset(function, image, "_" #function)
2298 template <typename Type_>
2299 static void dlset(Type_ &function, const char *name) {
2300 function = reinterpret_cast<Type_>(dlsym(RTLD_DEFAULT, name));
2303 // %hook CGImageReadCreateWithFile() {{{
2304 MSHook(void *, CGImageReadCreateWithFile, NSString *path, int flag) {
2306 NSLog(@"WB:Debug: CGImageReadCreateWithFile(%@, %d)", path, flag);
2307 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2308 void *value(_CGImageReadCreateWithFile([path wb$themedPath], flag));
2313 MSHook(void *, CGImageSourceCreateWithFile, NSString *path, NSDictionary *options) {
2315 NSLog(@"WB:Debug: CGImageSourceCreateWithFile(%@, %@)", path, options);
2316 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2317 void *value(_CGImageSourceCreateWithFile([path wb$themedPath], options));
2322 MSHook(void *, CGImageSourceCreateWithURL, NSURL *url, NSDictionary *options) {
2324 NSLog(@"WB:Debug: CGImageSourceCreateWithURL(%@, %@)", url, options);
2325 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2326 if ([url isFileURL])
2327 url = [NSURL fileURLWithPath:[[url path] wb$themedPath]];
2328 void *value(_CGImageSourceCreateWithURL(url, options));
2334 static void NSString$drawAtPoint$withStyle$(NSString *self, SEL _cmd, CGPoint point, NSString *style) {
2335 WKSetCurrentGraphicsContext(UIGraphicsGetCurrentContext());
2336 if (style == nil || [style length] == 0)
2337 style = @"font-family: Helvetica; font-size: 12px";
2338 //NSLog(@"XXX:drawP(%@ | %@)", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "]);
2339 [[WBMarkup sharedMarkup] drawString:self atPoint:point withStyle:style];
2342 static void NSString$drawInRect$withStyle$(NSString *self, SEL _cmd, CGRect rect, NSString *style) {
2343 WKSetCurrentGraphicsContext(UIGraphicsGetCurrentContext());
2344 if (style == nil || [style length] == 0)
2345 style = @"font-family: Helvetica; font-size: 12px";
2346 //NSLog(@"XXX:drawR(%@ | %@)", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "]);
2347 return [[WBMarkup sharedMarkup] drawString:self inRect:rect withStyle:style];
2350 static CGSize NSString$sizeWithStyle$forWidth$(NSString *self, SEL _cmd, NSString *style, CGFloat width) {
2351 if (style == nil || [style length] == 0)
2352 style = @"font-family: Helvetica; font-size: 12px";
2353 CGSize size([[WBMarkup sharedMarkup] sizeOfString:self withStyle:style forWidth:width]);
2354 //NSLog(@"XXX:size(%@ | %@) = [%g %g]", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "], size.width, size.height);
2358 static void SBInitialize() {
2360 WBRename(SBApplication, pathForIcon, pathForIcon);
2361 WBRename(SBApplicationIcon, icon, icon);
2362 WBRename(SBApplicationIcon, generateIconImage:, generateIconImage$);
2365 WBRename(SBBookmarkIcon, icon, icon);
2366 WBRename(SBButtonBar, didMoveToSuperview, didMoveToSuperview);
2367 WBRename(SBCalendarIconContentsView, drawRect:, drawRect$);
2368 WBRename(SBIconBadge, initWithBadge:, initWithBadge$);
2369 WBRename(SBIconController, noteNumberOfIconListsChanged, noteNumberOfIconListsChanged);
2371 WBRename(SBWidgetApplicationIcon, icon, icon);
2373 WBRename(SBDockIconListView, setFrame:, setFrame$);
2374 MSHookMessage(object_getClass($SBDockIconListView), @selector(shouldShowNewDock), &$SBDockIconListView$shouldShowNewDock, &_SBDockIconListView$shouldShowNewDock);
2376 if (kCFCoreFoundationVersionNumber < 600 || SummerBoard_)
2377 WBRename(SBIconLabel, drawRect:, drawRect$);
2378 else if (kCFCoreFoundationVersionNumber < 700) {
2379 WBRename(SBIconLabel, buildLabelImage, buildLabelImage);
2381 WBRename(SBIconLabelImageParameters, hash, hash);
2382 WBRename($SBIconView, _labelImageParametersForIcon:location:, _labelImageParametersForIcon$location$);
2383 WBRename(SBIconView, _labelImageParameters, _labelImageParameters);
2384 WBRename($SBIconLabelImage, _drawLabelImageForParameters:, _drawLabelImageForParameters$);
2387 WBRename(SBIconLabel, initWithSize:label:, initWithSize$label$);
2388 WBRename(SBIconLabel, setInDock:, setInDock$);
2390 WBRename(SBIconList, didMoveToSuperview, didMoveToSuperview);
2391 WBRename(SBIconList, setFrame:, setFrame$);
2393 WBRename(SBIconModel, cacheImageForIcon:, cacheImageForIcon$);
2394 WBRename(SBIconModel, cacheImagesForIcon:, cacheImagesForIcon$);
2395 WBRename(SBIconModel, getCachedImagedForIcon:, getCachedImagedForIcon$);
2396 WBRename(SBIconModel, getCachedImagedForIcon:smallIcon:, getCachedImagedForIcon$smallIcon$);
2398 if (kCFCoreFoundationVersionNumber < 800) {
2399 WBRename(SBSearchView, initWithFrame:, initWithFrame$);
2400 WBRename(SBSearchTableViewCell, drawRect:, drawRect$);
2401 WBRename(SBSearchTableViewCell, initWithStyle:reuseIdentifier:, initWithStyle$reuseIdentifier$);
2404 //WBRename(SBImageCache, initWithName:forImageWidth:imageHeight:initialCapacity:, initWithName$forImageWidth$imageHeight$initialCapacity$);
2406 WBRename(SBAwayView, updateDesktopImage:, updateDesktopImage$);
2407 if (kCFCoreFoundationVersionNumber >= 700)
2408 WBRename(SBAwayView, _addSubview:positioned:relativeTo:, _addSubview$positioned$relativeTo$);
2410 WBRename(SBStatusBarContentsView, didMoveToSuperview, didMoveToSuperview);
2411 //WBRename(SBStatusBarContentsView, initWithStatusBar:mode:, initWithStatusBar$mode$);
2412 //WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:animation:, setStatusBarMode$orientation$duration$animation$);
2413 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:, setStatusBarMode$orientation$duration$fenceID$animation$);
2414 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:startTime:, setStatusBarMode$orientation$duration$fenceID$animation$startTime$);
2415 WBRename(SBStatusBarOperatorNameView, operatorNameStyle, operatorNameStyle);
2416 WBRename(SBStatusBarOperatorNameView, setOperatorName:fullSize:, setOperatorName$fullSize$);
2417 WBRename(SBStatusBarTimeView, drawRect:, drawRect$);
2420 English_ = [[NSDictionary alloc] initWithContentsOfFile:@"/System/Library/CoreServices/SpringBoard.app/English.lproj/LocalizedApplicationNames.strings"];
2422 if (kCFCoreFoundationVersionNumber >= 800) {
2423 WBRename(NSString, drawInRect:withAttributes:, drawInRect$withAttributes$);
2424 WBRename(NSString, boundingRectWithSize:options:attributes:context:, boundingRectWithSize$options$attributes$context$);
2428 /*MSHook(int, open, const char *path, int oflag, mode_t mode) {
2429 int fd(_open(path, oflag, mode));
2431 static bool no(false);
2435 if (strstr(path, "/icon") != NULL)
2436 *reinterpret_cast<void *volatile *>(NULL) = NULL;
2438 if (fd == -1 && errno == EFAULT)
2439 NSLog(@"open(%p, %#x, %#o) = %d\n", path, oflag, mode, fd);
2441 NSLog(@"open(\"%s\", %#x, %#o) = %d\n", path, oflag, mode, fd);
2448 $objc_setAssociatedObject = reinterpret_cast<void (*)(id, void *, id value, objc_AssociationPolicy)>(dlsym(RTLD_DEFAULT, "objc_setAssociatedObject"));
2449 $objc_getAssociatedObject = reinterpret_cast<id (*)(id, void *)>(dlsym(RTLD_DEFAULT, "objc_getAssociatedObject"));
2450 $objc_removeAssociatedObjects = reinterpret_cast<void (*)(id)>(dlsym(RTLD_DEFAULT, "objc_removeAssociatedObjects"));
2452 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2454 NSString *identifier([[NSBundle mainBundle] bundleIdentifier]);
2455 SpringBoard_ = [identifier isEqualToString:@"com.apple.springboard"];
2457 Manager_ = [[NSFileManager defaultManager] retain];
2458 Themes_ = [[NSMutableArray alloc] initWithCapacity:8];
2460 dlset(_GSFontGetUseLegacyFontMetrics, "GSFontGetUseLegacyFontMetrics");
2462 // Initialize IsWild_ {{{
2464 sysctlbyname("hw.machine", NULL, &size, NULL, 0);
2465 char *machine = new char[size];
2467 if (sysctlbyname("hw.machine", machine, &size, NULL, 0) == -1) {
2468 perror("sysctlbyname(\"hw.machine\", ?)");
2473 IsWild_ = machine != NULL && strncmp(machine, "iPad", 4) == 0;
2475 // Load Settings.plist {{{
2476 if (NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"/User/Library/Preferences/com.saurik.WinterBoard.plist"]]) {
2477 if (kCFCoreFoundationVersionNumber >= 1000)
2478 SummerBoard_ = false;
2479 else if (NSNumber *value = [settings objectForKey:@"SummerBoard"])
2480 SummerBoard_ = [value boolValue];
2482 SummerBoard_ = true;
2484 if (NSNumber *value = [settings objectForKey:@"Debug"])
2485 Debug_ = [value boolValue];
2486 if (NSNumber *value = [settings objectForKey:@"RecordUI"])
2487 UIDebug_ = [value boolValue];
2489 NSArray *themes([settings objectForKey:@"Themes"]);
2491 if (NSString *theme = [settings objectForKey:@"Theme"])
2492 themes = [NSArray arrayWithObject:[NSDictionary dictionaryWithObjectsAndKeys:
2494 [NSNumber numberWithBool:true], @"Active",
2498 for (NSDictionary *theme in themes) {
2499 NSNumber *active([theme objectForKey:@"Active"]);
2500 if (![active boolValue])
2503 NSString *name([theme objectForKey:@"Name"]);
2507 #define testForTheme(format...) \
2509 NSString *path = [NSString stringWithFormat:format]; \
2510 if ([Manager_ fileExistsAtPath:path]) { \
2511 [Themes_ addObject:path]; \
2516 testForTheme(@"/Library/Themes/%@.theme", name)
2517 testForTheme(@"/Library/Themes/%@", name)
2518 testForTheme(@"%@/Library/SummerBoard/Themes/%@", NSHomeDirectory(), name)
2523 // Merge Info.plist {{{
2524 Info_ = [[NSMutableDictionary dictionaryWithCapacity:16] retain];
2526 for (NSString *theme in Themes_)
2527 if (NSDictionary *info = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"%@/Info.plist", theme]])
2528 for (NSString *key in [info allKeys])
2529 if ([Info_ objectForKey:key] == nil)
2530 [Info_ setObject:[info objectForKey:key] forKey:key];
2534 if (MSImageRef image = MSGetImageByName("/System/Library/PrivateFrameworks/AppSupport.framework/AppSupport")) {
2535 NSArray *(*CPBitmapCreateImagesFromPath)(NSString *, CFTypeRef *, void *, void *);
2536 msset(CPBitmapCreateImagesFromPath, image, "_CPBitmapCreateImagesFromPath");
2537 MSHookFunction(CPBitmapCreateImagesFromPath, MSHake(CPBitmapCreateImagesFromPath));
2541 if (MSImageRef image = MSGetImageByName(AudioToolbox)) {
2542 bool (*_Z24GetFileNameForThisActionmPcRb)(unsigned long, char *, bool &);
2543 msset(_Z24GetFileNameForThisActionmPcRb, image, "__Z24GetFileNameForThisActionmPcRb");
2544 MSHookFunction(_Z24GetFileNameForThisActionmPcRb, &$_Z24GetFileNameForThisActionmPcRb, &__Z24GetFileNameForThisActionmPcRb);
2547 bool (*_Z24GetFileNameForThisActionjPcjRb)(unsigned int, char *, unsigned int, bool &);
2548 msset(_Z24GetFileNameForThisActionjPcjRb, image, "__Z24GetFileNameForThisActionjPcjRb");
2549 MSHookFunction(_Z24GetFileNameForThisActionjPcjRb, &$_Z24GetFileNameForThisActionjPcjRb, &__Z24GetFileNameForThisActionjPcjRb);
2551 bool (*_Z24GetFileNameForThisActionmPcmRb)(unsigned long, char *, unsigned long, bool &);
2552 msset(_Z24GetFileNameForThisActionmPcmRb, image, "__Z24GetFileNameForThisActionmPcmRb");
2553 MSHookFunction(_Z24GetFileNameForThisActionmPcmRb, &$_Z24GetFileNameForThisActionmPcmRb, &__Z24GetFileNameForThisActionmPcmRb);
2557 // BackBoardServices {{{
2558 if (MSImageRef image = MSGetImageByName("/System/Library/PrivateFrameworks/BackBoardServices.framework/BackBoardServices")) {
2559 void (*BKSDisplayServicesSetSystemAppExitedImagePath)(NSString *path);
2560 msset(BKSDisplayServicesSetSystemAppExitedImagePath, image, "_BKSDisplayServicesSetSystemAppExitedImagePath");
2561 MSHookFunction(BKSDisplayServicesSetSystemAppExitedImagePath, MSHake(BKSDisplayServicesSetSystemAppExitedImagePath));
2566 MSHookFunction(CFBundleCopyResourceURL, MSHake(CFBundleCopyResourceURL));
2569 // GraphicsServices {{{
2571 MSHookFunction(&GSFontCreateWithName, &$GSFontCreateWithName, &_GSFontCreateWithName);
2575 MSImageRef imageio = MSGetImageByName("/System/Library/Frameworks/ImageIO.framework/ImageIO");
2576 if (imageio == NULL)
2577 imageio = MSGetImageByName("/System/Library/PrivateFrameworks/ImageIO.framework/ImageIO");
2578 if (MSImageRef image = imageio) {
2579 void *(*CGImageReadCreateWithFile)(NSString *, int) = NULL;
2580 if (kCFCoreFoundationVersionNumber > 700) // XXX: iOS 6.x
2581 CGImageReadCreateWithFile = NULL;
2583 msset(CGImageReadCreateWithFile, image, "_CGImageReadCreateWithFile");
2584 MSHookFunction(CGImageReadCreateWithFile, MSHake(CGImageReadCreateWithFile));
2587 if (CGImageReadCreateWithFile == NULL) {
2588 void *(*CGImageSourceCreateWithFile)(NSString *, NSDictionary *);
2589 msset(CGImageSourceCreateWithFile, image, "_CGImageSourceCreateWithFile");
2590 MSHookFunction(CGImageSourceCreateWithFile, MSHake(CGImageSourceCreateWithFile));
2592 void *(*CGImageSourceCreateWithURL)(NSURL *, NSDictionary *);
2593 msset(CGImageSourceCreateWithURL, image, "_CGImageSourceCreateWithURL");
2594 MSHookFunction(CGImageSourceCreateWithURL, MSHake(CGImageSourceCreateWithURL));
2600 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];
2601 Papered_ = $getTheme$(Wallpapers_) != nil;
2602 Docked_ = $getTheme$([NSArray arrayWithObjects:@"Dock.png", nil]) != nil;
2604 CFNotificationCenterAddObserver(
2605 CFNotificationCenterGetDarwinNotifyCenter(),
2606 NULL, &ChangeWallpaper, (CFStringRef) @"com.saurik.winterboard.lockbackground", NULL, CFNotificationSuspensionBehaviorCoalesce
2609 if ($getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"]) != nil) {
2610 NSBundle *MediaPlayer([NSBundle bundleWithPath:@"/System/Library/Frameworks/MediaPlayer.framework"]);
2611 if (MediaPlayer != nil)
2614 $MPMoviePlayerController = objc_getClass("MPMoviePlayerController");
2615 $MPVideoView = objc_getClass("MPVideoView");
2622 if (MSImageRef image = MSGetImageByName("/System/Library/Frameworks/UIKit.framework/UIKit")) {
2624 class_addMethod($NSString, @selector(drawAtPoint:withStyle:), (IMP) &NSString$drawAtPoint$withStyle$, "v40@0:8{CGPoint=dd}16@32");
2625 class_addMethod($NSString, @selector(drawInRect:withStyle:), (IMP) &NSString$drawInRect$withStyle$, "v56@0:8{CGRect={CGSize=dd}{CGSize=dd}}16@48");
2626 class_addMethod($NSString, @selector(sizeWithStyle:forWidth:), (IMP) &NSString$sizeWithStyle$forWidth$, "{CGSize=dd}32@0:8@16d24");
2628 class_addMethod($NSString, @selector(drawAtPoint:withStyle:), (IMP) &NSString$drawAtPoint$withStyle$, "v20@0:4{CGPoint=ff}8@16");
2629 class_addMethod($NSString, @selector(drawInRect:withStyle:), (IMP) &NSString$drawInRect$withStyle$, "v28@0:4{CGRect={CGSize=ff}{CGSize=ff}}8@24");
2630 class_addMethod($NSString, @selector(sizeWithStyle:forWidth:), (IMP) &NSString$sizeWithStyle$forWidth$, "{CGSize=ff}16@0:4@8f12");
2633 WBHookSymbol(image, _UIKitBundle);
2635 if (kCFCoreFoundationVersionNumber < 700)
2636 MSHookFunction(_UIImageWithName, MSHake(_UIImageWithName));
2638 WBHookSymbol(image, _UIApplicationImageWithName);
2639 MSHookFunction(_UIApplicationImageWithName, MSHake(_UIApplicationImageWithName));
2641 WBHookSymbol(image, _UIImageWithNameInDomain);
2642 MSHookFunction(_UIImageWithNameInDomain, MSHake(_UIImageWithNameInDomain));
2644 SEL includeEmoji(@selector(_legacy_drawAtPoint:forWidth:withFont:lineBreakMode:letterSpacing:includeEmoji:));
2645 if (![@"" respondsToSelector:includeEmoji])
2646 includeEmoji = @selector(drawAtPoint:forWidth:withFont:lineBreakMode:letterSpacing:includeEmoji:);
2647 MSHookMessage($NSString, includeEmoji, MSHake(NSString$drawAtPoint$forWidth$withFont$lineBreakMode$letterSpacing$includeEmoji$));
2649 SEL letterSpacing(@selector(_legacy_sizeWithFont:forWidth:lineBreakMode:letterSpacing:));
2650 if (![@"" respondsToSelector:letterSpacing])
2651 letterSpacing = @selector(sizeWithFont:forWidth:lineBreakMode:letterSpacing:);
2652 MSHookMessage($NSString, letterSpacing, MSHake(NSString$sizeWithFont$forWidth$lineBreakMode$letterSpacing$));
2654 SEL sizeWithFont(@selector(_legacy_sizeWithFont:));
2655 if (![@"" respondsToSelector:sizeWithFont])
2656 sizeWithFont = @selector(sizeWithFont:);
2657 MSHookMessage($NSString, sizeWithFont, MSHake(NSString$sizeWithFont$));
2661 //MSHookFunction(reinterpret_cast<int (*)(const char *, int, mode_t)>(&open), MSHake(open));