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)
107 MSMetaClassHook(UIImage)
108 MSClassHook(UINavigationBar)
109 MSClassHook(UISharedArtwork)
110 MSClassHook(UIToolbar)
111 MSClassHook(UIStatusBarTimeItemView)
112 MSClassHook(UIWebDocumentView)
114 MSClassHook(CKBalloonView)
115 MSClassHook(CKMessageCell)
116 MSClassHook(CKTimestampView)
117 MSClassHook(CKTranscriptCell)
118 MSClassHook(CKTranscriptController)
119 MSClassHook(CKTranscriptHeaderView)
120 MSClassHook(CKTranscriptTableView)
122 MSClassHook(SBApplication)
123 MSClassHook(SBApplicationIcon)
124 MSClassHook(SBAwayView)
125 MSClassHook(SBBookmarkIcon)
126 MSClassHook(SBButtonBar)
127 MSClassHook(SBCalendarApplicationIcon)
128 MSClassHook(SBCalendarIconContentsView)
129 MSClassHook(SBDockIconListView)
131 MSClassHook(SBIconAccessoryImage)
132 MSMetaClassHook(SBIconAccessoryImage)
133 MSClassHook(SBIconBadge)
134 MSClassHook(SBIconBadgeFactory)
135 MSClassHook(SBIconBadgeImage)
136 MSClassHook(SBIconBadgeView)
137 MSMetaClassHook(SBIconBadgeView)
138 MSClassHook(SBIconContentView)
139 MSClassHook(SBIconController)
140 MSClassHook(SBIconLabel)
141 MSClassHook(SBIconLabelImage)
142 MSMetaClassHook(SBIconLabelImage)
143 MSClassHook(SBIconLabelImageParameters)
144 MSClassHook(SBIconList)
145 MSClassHook(SBIconModel)
146 MSClassHook(SBIconView)
147 MSMetaClassHook(SBIconView)
148 //MSClassHook(SBImageCache)
149 MSClassHook(SBSearchView)
150 MSClassHook(SBSearchTableViewCell)
151 MSClassHook(SBSlidingAlertDisplay)
152 MSClassHook(SBStatusBarContentsView)
153 MSClassHook(SBStatusBarController)
154 MSClassHook(SBStatusBarOperatorNameView)
155 MSClassHook(SBStatusBarTimeView)
156 MSClassHook(SBUIController)
157 MSClassHook(SBWallpaperView)
158 MSClassHook(SBWidgetApplicationIcon)
160 extern "C" void WKSetCurrentGraphicsContext(CGContextRef);
162 static struct MSFixClass { MSFixClass() {
163 $UIWebDocumentView = objc_getClass("UIWebBrowserView") ?: $UIWebDocumentView;
164 $SBIcon = objc_getClass("SBIconView") ?: $SBIcon;
166 if ($SBIconList == nil)
167 $SBIconList = objc_getClass("SBIconListView");
168 if ($CKTranscriptController == nil)
169 $CKTranscriptController = objc_getClass("mSMSMessageTranscriptController");
173 static bool Four_($SBDockIconListView != nil);
175 @interface NSObject (wb$SBIconAccessoryImage)
176 + (Class) _imageClassForIcon:(SBIcon *)icon location:(int)location;
179 @interface NSDictionary (WinterBoard)
180 - (UIColor *) wb$colorForKey:(NSString *)key;
181 - (BOOL) wb$boolForKey:(NSString *)key;
184 @implementation NSDictionary (WinterBoard)
186 - (UIColor *) wb$colorForKey:(NSString *)key {
187 NSString *value = [self objectForKey:key];
194 - (BOOL) wb$boolForKey:(NSString *)key {
195 if (NSString *value = [self objectForKey:key])
196 return [value boolValue];
202 static BOOL (*_GSFontGetUseLegacyFontMetrics)();
203 #define $GSFontGetUseLegacyFontMetrics() \
204 (_GSFontGetUseLegacyFontMetrics == NULL ? YES : _GSFontGetUseLegacyFontMetrics())
206 static bool Debug_ = false;
207 static bool UIDebug_ = false;
208 static bool Engineer_ = false;
209 static bool SummerBoard_ = false;
210 static bool SpringBoard_;
212 static UIImage *(*_UIApplicationImageWithName)(NSString *name);
213 static UIImage *(*_UIImageWithNameInDomain)(NSString *name, NSString *domain);
214 static UIImage *(*_UIImageWithNameUsingCurrentIdiom)(NSString *name);
215 static UIImage *(*_UIImageWithDeviceSpecificName)(NSString *name);
216 static NSBundle *(*_UIKitBundle)();
217 static bool (*_UIPackedImageTableGetIdentifierForName)(NSString *, int *);
218 static int (*_UISharedImageNameGetIdentifier)(NSString *);
220 static NSMutableDictionary *Images_ = [[NSMutableDictionary alloc] initWithCapacity:64];
221 static NSMutableDictionary *Cache_ = [[NSMutableDictionary alloc] initWithCapacity:64];
222 static NSMutableDictionary *Strings_ = [[NSMutableDictionary alloc] initWithCapacity:0];
223 static NSMutableDictionary *Bundles_ = [[NSMutableDictionary alloc] initWithCapacity:2];
225 static NSFileManager *Manager_;
226 static NSMutableArray *Themes_;
228 static NSDictionary *English_;
229 static NSMutableDictionary *Info_;
232 static NSMutableDictionary *Themed_ = [[NSMutableDictionary alloc] initWithCapacity:128];
234 static unsigned Scale_ = 0;
236 static unsigned $getScale$(NSString *path) {
237 NSString *name(path);
239 #define StripName(strip) \
240 if ([name hasSuffix:@ strip]) \
241 name = [name substringWithRange:NSMakeRange(0, [name length] - sizeof(strip) - 1)];
245 StripName("~iphone");
248 return [name hasSuffix:@"@2x"] ? 2 : 1;
251 static NSArray *$useScale$(NSArray *files, bool use = true) {
252 if (use && Scale_ == 0) {
253 UIScreen *screen([UIScreen mainScreen]);
254 if ([screen respondsToSelector:@selector(scale)])
255 Scale_ = [screen scale];
260 NSString *idiom(IsWild_ ? @"ipad" : @"iphone");
262 NSMutableArray *scaled([NSMutableArray arrayWithCapacity:([files count] * 4)]);
264 for (NSString *file in files) {
265 NSString *base([file stringByDeletingPathExtension]);
266 NSString *extension([file pathExtension]);
270 [scaled addObject:[NSString stringWithFormat:@"%@@2x~%@.%@", base, idiom, extension]];
271 [scaled addObject:[NSString stringWithFormat:@"%@@2x.%@", base, extension]];
274 [scaled addObject:[NSString stringWithFormat:@"%@~%@.%@", base, idiom, extension]];
276 // if (!IsWild_) <- support old themes
277 [scaled addObject:file];
278 } else if ([base hasSuffix: @"@2x"]) {
279 [scaled addObject:[NSString stringWithFormat:@"%@~%@.%@", base, idiom, extension]];
280 [scaled addObject:file];
282 // XXX: this actually can't be used, as the person loading the file doesn't realize that the @2x changed
283 /*NSString *rest([base substringWithRange:NSMakeRange(0, [base length] - 3)]);
284 [scaled addObject:[NSString stringWithFormat:@"%@~%@.%@", rest, idiom, extension]];
285 [scaled addObject:[rest stringByAppendingPathExtension:extension]];*/
287 // XXX: this code isn't really complete
289 [scaled addObject:file];
291 if ([base hasSuffix:[NSString stringWithFormat:@"~%@", idiom]])
292 [scaled addObject:[[base substringWithRange:NSMakeRange(0, [base length] - 1 - [idiom length])] stringByAppendingPathExtension:extension]];
299 static NSString *$getTheme$(NSArray *files, NSArray *themes = Themes_) {
300 // XXX: this is not reasonable; OMG
303 @synchronized (Themed_) {
304 if (NSString *path = [Themed_ objectForKey:key])
305 return reinterpret_cast<id>(path) == [NSNull null] ? nil : path;
309 NSLog(@"WB:Debug: %@", [files description]);
313 for (NSString *theme in Themes_)
314 for (NSString *file in files) {
315 path = [NSString stringWithFormat:@"%@/%@", theme, file];
316 if ([Manager_ fileExistsAtPath:path]) {
317 if ([[Manager_ destinationOfSymbolicLinkAtPath:path error:NULL] isEqualToString:@"/"])
326 @synchronized (Themed_) {
327 [Themed_ setObject:(path == nil ? [NSNull null] : reinterpret_cast<id>(path)) forKey:key];
333 // $pathForFile$inBundle$() {{{
334 static NSString *$pathForFile$inBundle$(NSString *file, NSBundle *bundle, bool ui, bool use) {
335 NSString *identifier = [bundle bundleIdentifier];
336 NSMutableArray *names = [NSMutableArray arrayWithCapacity:8];
338 if (identifier != nil)
339 [names addObject:[NSString stringWithFormat:@"Bundles/%@/%@", identifier, file]];
340 if (NSString *folder = [[bundle bundlePath] lastPathComponent]) {
341 [names addObject:[NSString stringWithFormat:@"Folders/%@/%@", folder, file]];
342 NSString *base([folder stringByDeletingPathExtension]);
343 if ([base hasSuffix:@"~iphone"])
344 [names addObject:[NSString stringWithFormat:@"Folders/%@.%@/%@", [base substringWithRange:NSMakeRange(0, [base length] - 7)], [folder pathExtension], file]];
345 if ([base hasSuffix:@"~ipad"])
346 [names addObject:[NSString stringWithFormat:@"Folders/%@.%@/%@", [base substringWithRange:NSMakeRange(0, [base length] - 5)], [folder pathExtension], file]];
349 [names addObject:[NSString stringWithFormat:@"UIImages/%@", file]];
351 #define remapResourceName(oldname, newname) \
352 else if ([file isEqualToString:(oldname)]) \
353 [names addObject:[NSString stringWithFormat:@"%@.png", newname]]; \
355 bool summer(SpringBoard_ && SummerBoard_);
357 if (identifier == nil);
358 else if ([identifier isEqualToString:@"com.apple.chatkit"])
359 [names addObject:[NSString stringWithFormat:@"Bundles/com.apple.MobileSMS/%@", file]];
360 else if ([identifier isEqualToString:@"com.apple.calculator"])
361 [names addObject:[NSString stringWithFormat:@"Files/Applications/Calculator.app/%@", file]];
362 else if ([identifier isEqualToString:@"com.apple.Maps"] && [file isEqualToString:@"Icon-57@2x.png"])
363 [names addObject:[NSString stringWithFormat:@"Bundles/com.apple.Maps/icon.png"]];
365 remapResourceName(@"FSO_BG.png", @"StatusBar")
366 remapResourceName(Four_ ? @"SBDockBG-old.png" : @"SBDockBG.png", @"Dock")
367 remapResourceName(@"SBWeatherCelsius.png", @"Icons/Weather")
369 [names addObject:[NSString stringWithFormat:@"Fallback/%@", file]];
371 if (NSString *path = $getTheme$($useScale$(names, use)))
378 static NSString *$pathForIcon$(SBApplication *self, NSString *suffix = @"") {
379 NSString *identifier = [self bundleIdentifier];
380 NSString *path = [self path];
381 NSString *folder = [path lastPathComponent];
382 NSString *dname = [self displayName];
383 NSString *didentifier = [self displayIdentifier];
386 NSLog(@"WB:Debug: [SBApplication(%@:%@:%@:%@) pathForIcon]", identifier, folder, dname, didentifier);
388 NSMutableArray *names = [NSMutableArray arrayWithCapacity:8];
390 /* XXX: I might need to keep this for backwards compatibility
391 if (identifier != nil)
392 [names addObject:[NSString stringWithFormat:@"Bundles/%@/icon.png", identifier]];
394 [names addObject:[NSString stringWithFormat:@"Folders/%@/icon.png", folder]]; */
396 #define testForIcon(Name) \
397 if (NSString *name = Name) \
398 [names addObject:[NSString stringWithFormat:@"Icons%@/%@.png", suffix, name]];
400 if (![didentifier isEqualToString:identifier])
401 testForIcon(didentifier);
403 testForIcon(identifier);
406 if ([identifier isEqualToString:@"com.apple.MobileSMS"])
409 if (didentifier != nil) {
410 testForIcon([English_ objectForKey:didentifier]);
412 NSArray *parts = [didentifier componentsSeparatedByString:@"-"];
413 if ([parts count] != 1)
414 if (NSDictionary *english = [[[NSDictionary alloc] initWithContentsOfFile:[path stringByAppendingString:@"/English.lproj/UIRoleDisplayNames.strings"]] autorelease])
415 testForIcon([english objectForKey:[parts lastObject]]);
418 if (NSString *path = $getTheme$(names))
424 // -[NSBundle wb$bundleWithFile] {{{
425 @interface NSBundle (WinterBoard)
426 + (NSBundle *) wb$bundleWithFile:(NSString *)path;
429 @implementation NSBundle (WinterBoard)
431 + (NSBundle *) wb$bundleWithFile:(NSString *)path {
432 path = [path stringByDeletingLastPathComponent];
433 if (path == nil || [path length] == 0 || [path isEqualToString:@"/"])
436 NSBundle *bundle([Bundles_ objectForKey:path]);
437 if (reinterpret_cast<id>(bundle) == [NSNull null])
439 else if (bundle == nil) {
440 if ([Manager_ fileExistsAtPath:[path stringByAppendingPathComponent:@"Info.plist"]])
441 bundle = [NSBundle bundleWithPath:path];
443 bundle = [NSBundle wb$bundleWithFile:path];
445 NSLog(@"WB:Debug:PathBundle(%@, %@)", path, bundle);
446 [Bundles_ setObject:(bundle == nil ? [NSNull null] : reinterpret_cast<id>(bundle)) forKey:path];
454 // -[NSString wb$themedPath] {{{
455 @interface NSString (WinterBoard)
456 - (NSString *) wb$themedPath;
459 @implementation NSString (WinterBoard)
461 - (NSString *) wb$themedPath {
462 if ([self hasPrefix:@"/Library/Themes/"])
466 NSLog(@"WB:Debug:Bypass(\"%@\")", self);
468 if (NSBundle *bundle = [NSBundle wb$bundleWithFile:self]) {
469 NSString *file([self stringByResolvingSymlinksInPath]);
470 NSString *prefix([[bundle bundlePath] stringByResolvingSymlinksInPath]);
471 if ([file hasPrefix:prefix]) {
472 NSUInteger length([prefix length]);
473 if (length != [file length])
474 if (NSString *path = $pathForFile$inBundle$([file substringFromIndex:(length + 1)], bundle, false, false))
485 void WBLogRect(const char *tag, struct CGRect rect) {
486 NSLog(@"%s:{%f,%f+%f,%f}", tag, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
489 void WBLogHierarchy(UIView *view, unsigned index = 0, unsigned indent = 0) {
490 CGRect frame([view frame]);
491 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]);
493 for (UIView *child in [view subviews])
494 WBLogHierarchy(child, index++, indent + 1);
497 UIImage *$cacheForImage$(UIImage *image) {
498 CGColorSpaceRef space(CGColorSpaceCreateDeviceRGB());
499 CGRect rect = {CGPointMake(1, 1), [image size]};
500 CGSize size = {rect.size.width + 2, rect.size.height + 2};
502 CGContextRef context(CGBitmapContextCreate(NULL, size.width, size.height, 8, 4 * size.width, space, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst));
503 CGColorSpaceRelease(space);
505 CGContextDrawImage(context, rect, [image CGImage]);
506 CGImageRef ref(CGBitmapContextCreateImage(context));
507 CGContextRelease(context);
509 UIImage *cache([UIImage imageWithCGImage:ref]);
515 /*MSHook(id, SBImageCache$initWithName$forImageWidth$imageHeight$initialCapacity$, SBImageCache *self, SEL sel, NSString *name, unsigned width, unsigned height, unsigned capacity) {
516 //if ([name isEqualToString:@"icons"]) return nil;
517 return _SBImageCache$initWithName$forImageWidth$imageHeight$initialCapacity$(self, sel, name, width, height, capacity);
520 MSHook(void, SBIconModel$cacheImageForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
521 NSString *key([icon displayIdentifier]);
523 if (UIImage *image = [icon icon]) {
524 CGSize size = [image size];
525 if (size.width != 59 || size.height != 60) {
526 UIImage *cache($cacheForImage$(image));
527 [Cache_ setObject:cache forKey:key];
532 _SBIconModel$cacheImageForIcon$(self, sel, icon);
535 MSHook(void, SBIconModel$cacheImagesForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
536 /* XXX: do I /really/ have to do this? figure out how to cache the small icon! */
537 _SBIconModel$cacheImagesForIcon$(self, sel, icon);
539 NSString *key([icon displayIdentifier]);
541 if (UIImage *image = [icon icon]) {
542 CGSize size = [image size];
543 if (size.width != 59 || size.height != 60) {
544 UIImage *cache($cacheForImage$(image));
545 [Cache_ setObject:cache forKey:key];
551 MSHook(UIImage *, SBIconModel$getCachedImagedForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
552 NSString *key([icon displayIdentifier]);
553 if (UIImage *image = [Cache_ objectForKey:key])
556 return _SBIconModel$getCachedImagedForIcon$(self, sel, icon);
559 MSHook(UIImage *, SBIconModel$getCachedImagedForIcon$smallIcon$, SBIconModel *self, SEL sel, SBIcon *icon, BOOL small) {
561 return _SBIconModel$getCachedImagedForIcon$smallIcon$(self, sel, icon, small);
562 NSString *key([icon displayIdentifier]);
563 if (UIImage *image = [Cache_ objectForKey:key])
566 return _SBIconModel$getCachedImagedForIcon$smallIcon$(self, sel, icon, small);
569 MSHook(id, SBSearchView$initWithFrame$, id /* XXX: SBSearchView */ self, SEL sel, struct CGRect frame) {
570 if ((self = _SBSearchView$initWithFrame$(self, sel, frame)) != nil) {
571 [self setBackgroundColor:[UIColor clearColor]];
572 for (UIView *child in [self subviews])
573 [child setBackgroundColor:[UIColor clearColor]];
577 MSHook(id, SBSearchTableViewCell$initWithStyle$reuseIdentifier$, SBSearchTableViewCell *self, SEL sel, int style, NSString *reuse) {
578 if ((self = _SBSearchTableViewCell$initWithStyle$reuseIdentifier$(self, sel, style, reuse)) != nil) {
579 [self setBackgroundColor:[UIColor clearColor]];
583 MSHook(void, SBSearchTableViewCell$drawRect$, SBSearchTableViewCell *self, SEL sel, struct CGRect rect, BOOL selected) {
584 _SBSearchTableViewCell$drawRect$(self, sel, rect, selected);
585 float inset([self edgeInset]);
586 [[UIColor clearColor] set];
587 UIRectFill(CGRectMake(0, 0, inset, rect.size.height));
588 UIRectFill(CGRectMake(rect.size.width - inset, 0, inset, rect.size.height));
591 MSHook(UIImage *, SBApplicationIcon$icon, SBApplicationIcon *self, SEL sel) {
592 if (![Info_ wb$boolForKey:@"ComposeStoreIcons"])
593 if (NSString *path = $pathForIcon$([self application]))
594 return [UIImage imageWithContentsOfFile:path];
595 return _SBApplicationIcon$icon(self, sel);
598 MSHook(UIImage *, SBApplicationIcon$generateIconImage$, SBApplicationIcon *self, SEL sel, int type) {
600 if (![Info_ wb$boolForKey:@"ComposeStoreIcons"]) {
601 if (IsWild_ && false) // XXX: delete this code, it should not be supported
602 if (NSString *path72 = $pathForIcon$([self application], @"-72"))
603 return [UIImage imageWithContentsOfFile:path72];
604 if (NSString *path = $pathForIcon$([self application]))
605 if (UIImage *image = [UIImage imageWithContentsOfFile:path]) {
607 if ([$SBIcon respondsToSelector:@selector(defaultIconImageSize)])
608 width = [$SBIcon defaultIconImageSize].width;
611 return width == 59 ? image : [image _imageScaledToProportion:(width / 59.0) interpolationQuality:5];
614 return _SBApplicationIcon$generateIconImage$(self, sel, type);
617 MSHook(UIImage *, SBWidgetApplicationIcon$icon, SBWidgetApplicationIcon *self, SEL sel) {
619 NSLog(@"WB:Debug:Widget(%@:%@)", [self displayIdentifier], [self displayName]);
620 if (NSString *path = $getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Icons/%@.png", [self displayName]]]))
621 return [UIImage imageWithContentsOfFile:path];
622 return _SBWidgetApplicationIcon$icon(self, sel);
625 MSHook(UIImage *, SBBookmarkIcon$icon, SBBookmarkIcon *self, SEL sel) {
627 NSLog(@"WB:Debug:Bookmark(%@:%@)", [self displayIdentifier], [self displayName]);
628 if (NSString *path = $getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Icons/%@.png", [self displayName]]]))
629 return [UIImage imageWithContentsOfFile:path];
630 return _SBBookmarkIcon$icon(self, sel);
633 MSHook(NSString *, SBApplication$pathForIcon, SBApplication *self, SEL sel) {
634 if (NSString *path = $pathForIcon$(self))
636 return _SBApplication$pathForIcon(self, sel);
639 static UIImage *CachedImageAtPath(NSString *path) {
640 path = [path stringByResolvingSymlinksInPath];
641 UIImage *image = [Images_ objectForKey:path];
643 return reinterpret_cast<id>(image) == [NSNull null] ? nil : image;
644 image = [[UIImage alloc] initWithContentsOfFile:path cache:true];
646 image = [image autorelease];
647 [Images_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:path];
651 MSHook(UIImage *, _UIApplicationImageWithName, NSString *name) {
652 NSBundle *bundle = [NSBundle mainBundle];
654 NSLog(@"WB:Debug: _UIApplicationImageWithName(\"%@\", %@)", name, bundle);
655 if (NSString *path = $pathForFile$inBundle$(name, bundle, false, false))
656 return CachedImageAtPath(path);
657 return __UIApplicationImageWithName(name);
660 #define WBDelegate(delegate) \
661 - (NSMethodSignature*) methodSignatureForSelector:(SEL)sel { \
663 NSLog(@"WB:MS:%s:(%s)", class_getName([self class]), sel_getName(sel)); \
664 if (NSMethodSignature *sig = [delegate methodSignatureForSelector:sel]) \
666 NSLog(@"WB:Error: [%s methodSignatureForSelector:(%s)]", class_getName([self class]), sel_getName(sel)); \
670 - (void) forwardInvocation:(NSInvocation*)inv { \
671 SEL sel = [inv selector]; \
672 if ([delegate respondsToSelector:sel]) \
673 [inv invokeWithTarget:delegate]; \
675 NSLog(@"WB:Error: [%s forwardInvocation:(%s)]", class_getName([self class]), sel_getName(sel)); \
678 // %hook -[NSBundle pathForResource:ofType:] {{{
679 MSInstanceMessageHook2(NSString *, NSBundle, pathForResource,ofType, NSString *, resource, NSString *, type) {
680 NSString *file = type == nil ? resource : [NSString stringWithFormat:@"%@.%@", resource, type];
681 if ([file isEqualToString:@"Info.plist"])
682 return MSOldCall(resource, type);
684 NSLog(@"WB:Debug: [NSBundle(%@) pathForResource:\"%@\"]", [self bundleIdentifier], file);
685 if (NSString *path = $pathForFile$inBundle$(file, self, false, false))
687 return MSOldCall(resource, type);
691 static void $drawLabel$(NSString *label, CGRect rect, NSString *style, NSString *custom) {
692 bool ellipsis(false);
693 CGFloat max = rect.size.width - 11, width;
695 width = [(ellipsis ? [label stringByAppendingString:@"..."] : label) sizeWithStyle:style forWidth:320].width;
698 size_t length([label length]);
699 CGFloat spacing((width - max) / (length - 1));
701 if (spacing > 1.25) {
703 label = [label substringToIndex:(length - 1)];
707 style = [style stringByAppendingString:[NSString stringWithFormat:@"letter-spacing: -%f; ", spacing]];
711 label = [label stringByAppendingString:@"..."];
714 style = [style stringByAppendingString:custom];
716 CGSize size = [label sizeWithStyle:style forWidth:rect.size.width];
717 [label drawAtPoint:CGPointMake((rect.size.width - size.width) / 2 + rect.origin.x, rect.origin.y) withStyle:style];
720 static struct WBStringDrawingState {
721 WBStringDrawingState *next_;
725 } *stringDrawingState_;
727 extern "C" CGColorSpaceRef CGContextGetFillColorSpace(CGContextRef);
728 extern "C" void CGContextGetFillColor(CGContextRef, CGFloat[]);
730 static NSString *WBColorMarkup(size_t number, const CGFloat *components) {
752 return [NSString stringWithFormat:@"color: rgba(%g, %g, %g, %g)", r * 255, g * 255, b * 255, a];
755 static NSString *WBColorMarkup() {
756 CGContextRef context(UIGraphicsGetCurrentContext());
757 //NSLog(@"XXX:1:%p", context);
761 CGColorSpaceRef space(CGContextGetFillColorSpace(context));
762 //NSLog(@"XXX:2:%p", space);
766 size_t number(CGColorSpaceGetNumberOfComponents(space));
767 //NSLog(@"XXX:3:%u", number);
771 CGFloat components[number + 1];
772 CGContextGetFillColor(context, components);
773 return WBColorMarkup(number, components);
776 static NSString *WBColorMarkup(UIColor *uicolor) {
779 CGColorRef cgcolor([uicolor CGColor]);
783 CGColorSpaceRef space(CGColorGetColorSpace(cgcolor));
784 //NSLog(@"XXX:2:%p", space);
788 size_t number(CGColorGetNumberOfComponents(cgcolor));
789 //NSLog(@"XXX:3:%u", number);
793 const CGFloat *components(CGColorGetComponents(cgcolor));
794 return WBColorMarkup(number, components);
797 extern "C" NSString *NSStringFromCGPoint(CGPoint rect);
799 MSInstanceMessage6(CGSize, NSString, drawAtPoint,forWidth,withFont,lineBreakMode,letterSpacing,includeEmoji, CGPoint, point, CGFloat, width, UIFont *, font, UILineBreakMode, mode, CGFloat, spacing, BOOL, emoji) {
800 //NSLog(@"XXX: @\"%@\" %@ %g \"%@\" %u %g %u", self, NSStringFromCGPoint(point), width, font, mode, spacing, emoji);
802 WBStringDrawingState *state(stringDrawingState_);
804 return MSOldCall(point, width, font, mode, spacing, emoji);
806 if (state->count_ != 0 && --state->count_ == 0)
807 stringDrawingState_ = state->next_;
808 if (state->info_ == nil)
809 return MSOldCall(point, width, font, mode, spacing, emoji);
811 NSString *info([Info_ objectForKey:state->info_]);
813 return MSOldCall(point, width, font, mode, spacing, emoji);
815 NSString *base(state->base_ ?: @"");
816 NSString *extra([NSString stringWithFormat:@"letter-spacing: %gpx", spacing]);
817 [self drawAtPoint:point withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info]];
821 extern "C" NSString *NSStringFromCGRect(CGRect rect);
823 MSInstanceMessageHook7(CGSize, NSString, _drawInRect,withFont,lineBreakMode,alignment,lineSpacing,includeEmoji,truncationRect, CGRect, rect, UIFont *, font, UILineBreakMode, mode, UITextAlignment, alignment, float, spacing, BOOL, emoji, CGRect, truncation) {
824 //NSLog(@"XXX: @\"%@\" %@ \"%@\" %u %u %g %u %@", self, NSStringFromCGRect(rect), font, mode, alignment, spacing, emoji, NSStringFromCGRect(truncation));
826 WBStringDrawingState *state(stringDrawingState_);
828 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
830 if (state->count_ != 0 && --state->count_ == 0)
831 stringDrawingState_ = state->next_;
832 if (state->info_ == nil)
833 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
835 NSString *info([Info_ objectForKey:state->info_]);
837 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
842 case UITextAlignmentLeft:
845 case UITextAlignmentCenter:
846 textAlign = @"center";
848 case UITextAlignmentRight:
849 textAlign = @"right";
853 NSString *base(state->base_ ?: @"");
854 NSString *extra([NSString stringWithFormat:@"text-align: %@", textAlign]);
857 $drawLabel$(self, rect, [NSString stringWithFormat:@"%@;%@;%@", [font markupDescription], WBColorMarkup(), base], info);
859 [self drawInRect:rect withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info]];
864 MSInstanceMessage2(void, NSString, drawInRect,withAttributes, CGRect, rect, NSDictionary *, attributes) {
865 //NSLog(@"XXX: *\"%@\" %@", self, attributes);
867 WBStringDrawingState *state(stringDrawingState_);
869 return MSOldCall(rect, attributes);
871 if (state->count_ != 0 && --state->count_ == 0)
872 stringDrawingState_ = state->next_;
873 if (state->info_ == nil)
874 return MSOldCall(rect, attributes);
876 NSString *info([Info_ objectForKey:state->info_]);
878 return MSOldCall(rect, attributes);
880 NSString *base(state->base_ ?: @"");
882 UIFont *font([attributes objectForKey:@"NSFont"]);
883 UIColor *color([attributes objectForKey:@"NSColor"]);
885 [self drawInRect:rect withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], WBColorMarkup(color), base, info]];
888 extern "C" NSString *NSStringFromCGSize(CGSize size);
890 MSInstanceMessage4(CGRect, NSString, boundingRectWithSize,options,attributes,context, CGSize, size, NSInteger, options, NSDictionary *, attributes, id, context) {
891 //NSLog(@"XXX: $\"%@\" %@ 0x%x %@ %@", self, NSStringFromCGSize(size), unsigned(options), attributes, context);
893 WBStringDrawingState *state(stringDrawingState_);
895 return MSOldCall(size, options, attributes, context);
897 if (state->count_ != 0 && --state->count_ == 0)
898 stringDrawingState_ = state->next_;
899 if (state->info_ == nil)
900 return MSOldCall(size, options, attributes, context);
902 NSString *info([Info_ objectForKey:state->info_]);
904 return MSOldCall(size, options, attributes, context);
906 NSString *base(state->base_ ?: @"");
908 UIFont *font([attributes objectForKey:@"NSFont"]);
909 UIColor *color([attributes objectForKey:@"NSColor"]);
911 return (CGRect) {{0, 0}, [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], WBColorMarkup(color), base, info] forWidth:size.width]};
914 MSInstanceMessage4(CGSize, NSString, sizeWithFont,forWidth,lineBreakMode,letterSpacing, UIFont *, font, CGFloat, width, UILineBreakMode, mode, CGFloat, spacing) {
915 //NSLog(@"XXX: #\"%@\" \"%@\" %g %u %g", self, font, width, mode, spacing);
917 WBStringDrawingState *state(stringDrawingState_);
919 return MSOldCall(font, width, mode, spacing);
921 if (state->count_ != 0 && --state->count_ == 0)
922 stringDrawingState_ = state->next_;
923 if (state->info_ == nil)
924 return MSOldCall(font, width, mode, spacing);
926 NSString *info([Info_ objectForKey:state->info_]);
928 return MSOldCall(font, width, mode, spacing);
930 NSString *base(state->base_ ?: @"");
931 NSString *extra([NSString stringWithFormat:@"letter-spacing: %gpx", spacing]);
932 return [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info] forWidth:width];
935 MSInstanceMessage1(CGSize, NSString, sizeWithFont, UIFont *, font) {
936 //NSLog(@"XXX: ?\"%@\"", self);
938 WBStringDrawingState *state(stringDrawingState_);
940 return MSOldCall(font);
942 if (state->count_ != 0 && --state->count_ == 0)
943 stringDrawingState_ = state->next_;
944 if (state->info_ == nil)
945 return MSOldCall(font);
947 NSString *info([Info_ objectForKey:state->info_]);
949 return MSOldCall(font);
951 NSString *base(state->base_ ?: @"");
952 return [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), base, info] forWidth:65535];
955 MSClassMessageHook2(id, SBIconBadgeView, checkoutAccessoryImagesForIcon,location, id, icon, int, location) {
956 WBStringDrawingState badgeState = {NULL, 0, @""
959 stringDrawingState_ = &badgeState;
961 id images(MSOldCall(icon, location));
963 stringDrawingState_ = NULL;
967 MSClassMessageHook2(UIImage *, SBIconAccessoryImage, checkoutAccessoryImageForIcon,location, id, icon, int, location) {
968 if ([self _imageClassForIcon:icon location:location] != $SBIconBadgeImage)
969 return MSOldCall(icon, location);
971 WBStringDrawingState badgeState = {NULL, 0, @""
974 stringDrawingState_ = &badgeState;
976 UIImage *image(MSOldCall(icon, location));
978 stringDrawingState_ = NULL;
982 MSInstanceMessageHook1(UIImage *, SBIconBadgeFactory, checkoutBadgeImageForText, NSString *, text) {
983 WBStringDrawingState badgeState = {NULL, 0, @""
986 stringDrawingState_ = &badgeState;
988 UIImage *image(MSOldCall(text));
990 stringDrawingState_ = NULL;
994 MSInstanceMessageHook1(UIImage *, SBCalendarApplicationIcon, generateIconImage, int, type) {
995 WBStringDrawingState dayState = {NULL, 2, @""
996 // XXX: this is only correct on an iPod dock
997 "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px;"
998 , @"CalendarIconDayStyle"};
1000 WBStringDrawingState wtfState = {&dayState, 1, nil, nil};
1002 WBStringDrawingState sizeState = {
1003 kCFCoreFoundationVersionNumber > 800 ? &wtfState : &dayState
1006 WBStringDrawingState dateState = {&sizeState, 2, @""
1007 , @"CalendarIconDateStyle"};
1009 stringDrawingState_ = &dateState;
1011 UIImage *image(MSOldCall(type));
1013 stringDrawingState_ = NULL;
1017 MSInstanceMessageHook1(UIImage *, UIStatusBarTimeItemView, contentsImageForStyle, int, style) {
1018 WBStringDrawingState timeState = {NULL, 0, @""
1021 stringDrawingState_ = &timeState;
1023 UIImage *image(MSOldCall(style));
1025 stringDrawingState_ = NULL;
1029 MSHook(void, SBCalendarIconContentsView$drawRect$, SBCalendarIconContentsView *self, SEL sel, CGRect rect) {
1030 NSBundle *bundle([NSBundle mainBundle]);
1032 CFLocaleRef locale(CFLocaleCopyCurrent());
1033 CFDateFormatterRef formatter(CFDateFormatterCreate(NULL, locale, kCFDateFormatterNoStyle, kCFDateFormatterNoStyle));
1036 CFDateRef now(CFDateCreate(NULL, CFAbsoluteTimeGetCurrent()));
1038 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NUMBER_FORMAT" value:@"d" table:@"SpringBoard"]);
1039 CFStringRef date(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
1040 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NAME_FORMAT" value:@"cccc" table:@"SpringBoard"]);
1041 CFStringRef day(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
1045 CFRelease(formatter);
1047 NSString *datestyle([@""
1048 "font-family: Helvetica; "
1049 "font-weight: bold; "
1052 "" stringByAppendingString:(IsWild_
1053 ? @"font-size: 54px; "
1054 : @"font-size: 39px; "
1057 NSString *daystyle([@""
1058 "font-family: Helvetica; "
1059 "font-weight: bold; "
1061 "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px; "
1062 "" stringByAppendingString:(IsWild_
1063 ? @"font-size: 11px; "
1064 : @"font-size: 9px; "
1067 if (NSString *style = [Info_ objectForKey:@"CalendarIconDateStyle"])
1068 datestyle = [datestyle stringByAppendingString:style];
1069 if (NSString *style = [Info_ objectForKey:@"CalendarIconDayStyle"])
1070 daystyle = [daystyle stringByAppendingString:style];
1072 CGFloat width([self bounds].size.width);
1074 CGSize datesize = [(NSString *)date sizeWithStyle:datestyle forWidth:(width + leeway)];
1075 CGSize daysize = [(NSString *)day sizeWithStyle:daystyle forWidth:(width + leeway)];
1077 unsigned base0(IsWild_ ? 89 : 70);
1078 if ($GSFontGetUseLegacyFontMetrics())
1080 unsigned base1(IsWild_ ? 18 : 16);
1087 [(NSString *)date drawAtPoint:CGPointMake(
1088 (width + 1 - datesize.width) / 2, (base0 - datesize.height) / 2
1089 ) withStyle:datestyle];
1091 [(NSString *)day drawAtPoint:CGPointMake(
1092 (width + 1 - daysize.width) / 2, (base1 - daysize.height) / 2
1093 ) withStyle:daystyle];
1099 // %hook -[{NavigationBar,Toolbar} setBarStyle:] {{{
1100 void $setBarStyle$_(NSString *name, int &style) {
1102 NSLog(@"WB:Debug:%@Style:%d", name, style);
1103 NSNumber *number = nil;
1105 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style-%d", name, style]];
1107 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style", name]];
1108 if (number != nil) {
1109 style = [number intValue];
1111 NSLog(@"WB:Debug:%@Style=%d", name, style);
1115 MSInstanceMessageHook1(void, UIToolbar, setBarStyle, int, style) {
1116 $setBarStyle$_(@"Toolbar", style);
1117 return MSOldCall(style);
1120 MSInstanceMessageHook1(void, UINavigationBar, setBarStyle, int, style) {
1121 $setBarStyle$_(@"NavigationBar", style);
1122 return MSOldCall(style);
1126 MSHook(void, SBButtonBar$didMoveToSuperview, UIView *self, SEL sel) {
1127 [[self superview] setBackgroundColor:[UIColor clearColor]];
1128 _SBButtonBar$didMoveToSuperview(self, sel);
1131 MSHook(void, SBStatusBarContentsView$didMoveToSuperview, UIView *self, SEL sel) {
1132 [[self superview] setBackgroundColor:[UIColor clearColor]];
1133 _SBStatusBarContentsView$didMoveToSuperview(self, sel);
1136 static NSArray *Wallpapers_;
1137 static bool Papered_;
1138 static bool Docked_;
1139 static bool SMSBackgrounded_;
1140 static NSString *WallpaperFile_;
1141 static UIImageView *WallpaperImage_;
1142 static UIWebDocumentView *WallpaperPage_;
1143 static NSURL *WallpaperURL_;
1145 #define _release(object) \
1146 do if (object != nil) { \
1151 static UIImage *$getImage$(NSString *path) {
1152 UIImage *image([UIImage imageWithContentsOfFile:path]);
1154 unsigned scale($getScale$(path));
1155 if (scale != 1 && [image respondsToSelector:@selector(setScale)])
1156 [image setScale:scale];
1161 template <typename Original_, typename Modified_>
1162 _finline UIImage *WBCacheImage(const Original_ &original, const Modified_ &modified, NSString *key) {
1163 UIImage *image([Images_ objectForKey:key]);
1165 return reinterpret_cast<id>(image) == [NSNull null] ? original() : image;
1166 if (NSString *path = modified())
1167 image = $getImage$(path);
1168 [Images_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:key];
1169 return image == nil ? original() : image;
1172 static UIImage *$getDefaultDesktopImage$() {
1173 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"LockBackground.png", @"LockBackground.jpg", nil])))
1174 return $getImage$(path);
1178 MSClassMessageHook0(UIImage *, UIImage, defaultDesktopImage) {
1179 return $getDefaultDesktopImage$() ?: MSOldCall();
1182 MSInstanceMessageHook0(UIImage *, SBSlidingAlertDisplay, _defaultDesktopImage) {
1183 return $getDefaultDesktopImage$() ?: MSOldCall();
1186 MSInstanceMessageHook0(void, SBWallpaperView, resetCurrentImageToWallpaper) {
1187 for (UIView *parent([self superview]); parent != nil; parent = [parent superview])
1188 if ([parent isKindOfClass:$SBSlidingAlertDisplay]) {
1189 if (UIImage *image = $getDefaultDesktopImage$()) {
1190 [self setImage:image];
1200 // %hook -[SBUIController init] {{{
1201 MSInstanceMessageHook0(id, SBUIController, init) {
1206 NSString *paper($getTheme$(Wallpapers_));
1208 paper = [paper stringByDeletingLastPathComponent];
1212 sysctlbyname("hw.machine", NULL, &size, NULL, 0);
1213 char *machine = new char[size];
1215 if (sysctlbyname("hw.machine", machine, &size, NULL, 0) == -1) {
1216 perror("sysctlbyname(\"hw.machine\", ?)");
1221 IsWild_ = machine != NULL && strncmp(machine, "iPad", 4) == 0;
1225 NSLog(@"WB:Debug:Info = %@", [Info_ description]);
1228 UIImageView *&_wallpaperView(MSHookIvar<UIImageView *>(self, "_wallpaperView"));
1229 if (&_wallpaperView != NULL) {
1230 [_wallpaperView removeFromSuperview];
1231 [_wallpaperView release];
1232 _wallpaperView = nil;
1236 UIView *&_contentLayer(MSHookIvar<UIView *>(self, "_contentLayer"));
1237 UIView *&_contentView(MSHookIvar<UIView *>(self, "_contentView"));
1240 if (&_contentLayer != NULL)
1241 player = &_contentLayer;
1242 else if (&_contentView != NULL)
1243 player = &_contentView;
1246 UIView *layer(player == NULL ? nil : *player);
1248 UIWindow *window([[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]);
1249 UIView *content([[[UIView alloc] initWithFrame:[window frame]] autorelease]);
1250 [window setContentView:content];
1252 UIWindow *&_window(MSHookIvar<UIWindow *>(self, "_window"));
1253 [window setBackgroundColor:[_window backgroundColor]];
1254 [_window setBackgroundColor:[UIColor clearColor]];
1256 [window setLevel:-1000];
1257 [window setHidden:NO];
1259 /*if (player != NULL)
1260 *player = content;*/
1262 [content setBackgroundColor:[layer backgroundColor]];
1263 [layer setBackgroundColor:[UIColor clearColor]];
1266 if (!SummerBoard_ || !IsWild_)
1269 CGRect bounds([content bounds]);
1270 bounds.origin.y = -30;
1271 indirect = [[[UIView alloc] initWithFrame:bounds] autorelease];
1272 [content addSubview:indirect];
1273 [indirect zoomToScale:2.4];
1276 _release(WallpaperFile_);
1277 _release(WallpaperImage_);
1278 _release(WallpaperPage_);
1279 _release(WallpaperURL_);
1282 NSArray *themes([NSArray arrayWithObject:paper]);
1284 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"], themes)) {
1288 static AVController *controller_(nil);
1289 if (controller_ == nil) {
1290 AVQueue *queue([AVQueue avQueue]);
1291 controller_ = [[AVController avControllerWithQueue:queue error:&error] retain];
1294 AVQueue *queue([controller_ queue]);
1296 UIView *video([[[UIView alloc] initWithFrame:[indirect bounds]] autorelease]);
1297 [controller_ setLayer:[video _layer]];
1299 AVItem *item([[[AVItem alloc] initWithPath:path error:&error] autorelease]);
1300 [queue appendItem:item error:&error];
1302 [controller_ play:&error];
1303 #elif UseMPMoviePlayerController
1304 NSURL *url([NSURL fileURLWithPath:path]);
1305 MPMoviePlayerController *controller = [[$MPMoviePlayerController alloc] initWithContentURL:url];
1306 controller.movieControlMode = MPMovieControlModeHidden;
1309 MPVideoView *video = [[[$MPVideoView alloc] initWithFrame:[indirect bounds]] autorelease];
1310 [video setMovieWithPath:path];
1311 [video setRepeatMode:1];
1312 [video setRepeatGap:-1];
1313 [video playFromBeginning];;
1316 [indirect addSubview:video];
1319 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"Wallpaper.png", @"Wallpaper.jpg", nil]), themes)) {
1320 if (UIImage *image = $getImage$(path)) {
1321 WallpaperFile_ = [path retain];
1322 WallpaperImage_ = [[UIImageView alloc] initWithImage:image];
1323 if (NSNumber *number = [Info_ objectForKey:@"WallpaperAlpha"])
1324 [WallpaperImage_ setAlpha:[number floatValue]];
1325 [indirect addSubview:WallpaperImage_];
1329 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.html"], themes)) {
1330 CGRect bounds = [indirect bounds];
1332 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1333 [view setAutoresizes:true];
1335 WallpaperPage_ = [view retain];
1336 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
1338 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1340 [view setBackgroundColor:[UIColor clearColor]];
1341 if ([view respondsToSelector:@selector(setDrawsBackground:)])
1342 [view setDrawsBackground:NO];
1343 [[view webView] setDrawsBackground:NO];
1345 [indirect addSubview:view];
1349 for (size_t i(0), e([Themes_ count]); i != e; ++i) {
1350 NSString *theme = [Themes_ objectAtIndex:(e - i - 1)];
1351 NSString *html = [theme stringByAppendingPathComponent:@"Widget.html"];
1352 if ([Manager_ fileExistsAtPath:html]) {
1353 CGRect bounds = [indirect bounds];
1355 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1356 [view setAutoresizes:true];
1358 NSURL *url = [NSURL fileURLWithPath:html];
1359 [view loadRequest:[NSURLRequest requestWithURL:url]];
1361 [view setBackgroundColor:[UIColor clearColor]];
1362 if ([view respondsToSelector:@selector(setDrawsBackground:)])
1363 [view setDrawsBackground:NO];
1364 [[view webView] setDrawsBackground:NO];
1366 [indirect addSubview:view];
1374 MSHook(void, SBAwayView$updateDesktopImage$, SBAwayView *self, SEL sel, UIImage *image) {
1375 NSString *path = $getTheme$([NSArray arrayWithObject:@"LockBackground.html"]);
1376 UIView *&_backgroundView(MSHookIvar<UIView *>(self, "_backgroundView"));
1378 if (path != nil && _backgroundView != nil)
1381 _SBAwayView$updateDesktopImage$(self, sel, image);
1384 CGRect bounds = [self bounds];
1386 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1387 [view setAutoresizes:true];
1389 if (WallpaperPage_ != nil)
1390 [WallpaperPage_ release];
1391 WallpaperPage_ = [view retain];
1393 if (WallpaperURL_ != nil)
1394 [WallpaperURL_ release];
1395 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
1397 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1399 [[view webView] setDrawsBackground:false];
1400 [view setBackgroundColor:[UIColor clearColor]];
1402 [self insertSubview:view aboveSubview:_backgroundView];
1404 if ($objc_setAssociatedObject != NULL)
1405 $objc_setAssociatedObject(self, @selector(wb$widgetView), view, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1409 MSHook(void, SBAwayView$_addSubview$positioned$relativeTo$, SBAwayView *self, SEL sel, UIView *view, int positioned, UIView *relative) {
1410 UIView *&_backgroundView(MSHookIvar<UIView *>(self, "_backgroundView"));
1411 UIView *&_chargingView(MSHookIvar<UIView *>(self, "_chargingView"));
1412 if (&_chargingView != NULL)
1413 if (positioned == -2 && (relative == _backgroundView && _chargingView == nil || relative == _chargingView))
1414 if ($objc_getAssociatedObject != NULL)
1415 if (UIView *widget = $objc_getAssociatedObject(self, @selector(wb$widgetView)))
1417 return _SBAwayView$_addSubview$positioned$relativeTo$(self, sel, view, positioned, relative);
1420 /*extern "C" CGColorRef CGGStateGetSystemColor(void *);
1421 extern "C" CGColorRef CGGStateGetFillColor(void *);
1422 extern "C" CGColorRef CGGStateGetStrokeColor(void *);
1423 extern "C" NSString *UIStyleStringFromColor(CGColorRef);*/
1425 /* WBTimeLabel {{{ */
1426 @interface WBTimeLabel : NSProxy {
1428 _transient SBStatusBarTimeView *view_;
1431 - (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view;
1435 @implementation WBTimeLabel
1442 - (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view {
1443 time_ = [time retain];
1448 - (NSString *) description {
1454 - (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(UILineBreakMode)mode {
1455 if (NSString *custom = [Info_ objectForKey:@"TimeStyle"]) {
1456 BOOL &_mode(MSHookIvar<BOOL>(view_, "_mode"));;
1458 [time_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1459 "font-family: Helvetica; "
1460 "font-weight: bold; "
1463 "%@", _mode ? @"white" : @"black", custom]];
1468 return [time_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1473 /* WBBadgeLabel {{{ */
1474 @interface WBBadgeLabel : NSProxy {
1478 - (id) initWithBadge:(NSString *)badge;
1479 - (NSString *) description;
1483 @implementation WBBadgeLabel
1490 - (id) initWithBadge:(NSString *)badge {
1491 badge_ = [badge retain];
1495 - (NSString *) description {
1496 return [badge_ description];
1501 - (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(UILineBreakMode)mode {
1502 if (NSString *custom = [Info_ objectForKey:@"BadgeStyle"]) {
1503 [badge_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1504 "font-family: Helvetica; "
1505 "font-weight: bold; "
1513 return [badge_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1520 MSInstanceMessageHook1(void, SBIcon, setIconImageAlpha, CGFloat, alpha) {
1521 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1522 alpha = [number floatValue];
1523 return MSOldCall(alpha);
1526 MSInstanceMessageHook1(void, SBIcon, setIconLabelAlpha, CGFloat, alpha) {
1527 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1528 alpha = [number floatValue];
1529 return MSOldCall(alpha);
1532 MSInstanceMessageHook0(id, SBIcon, initWithDefaultSize) {
1533 if ((self = MSOldCall()) != nil) {
1534 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"]) {
1535 // XXX: note: this is overridden above, which is silly
1536 float alpha([number floatValue]);
1537 if ([self respondsToSelector:@selector(setIconImageAlpha:)])
1538 [self setIconImageAlpha:alpha];
1539 if ([self respondsToSelector:@selector(setIconLabelAlpha:)])
1540 [self setIconLabelAlpha:alpha];
1541 if ([self respondsToSelector:@selector(setAlpha:)])
1542 [self setAlpha:alpha];
1547 MSInstanceMessageHook1(void, SBIcon, setAlpha, CGFloat, alpha) {
1548 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1549 alpha = [number floatValue];
1550 return MSOldCall(alpha);
1554 MSHook(id, SBIconBadge$initWithBadge$, SBIconBadge *self, SEL sel, NSString *badge) {
1555 if ((self = _SBIconBadge$initWithBadge$(self, sel, badge)) != nil) {
1556 id &_badge(MSHookIvar<id>(self, "_badge"));
1558 if (id label = [[WBBadgeLabel alloc] initWithBadge:[_badge autorelease]])
1563 void SBStatusBarController$setStatusBarMode(int &mode) {
1565 NSLog(@"WB:Debug:setStatusBarMode:%d", mode);
1566 if (mode < 100) // 104:hidden 105:glowing
1567 if (NSNumber *number = [Info_ objectForKey:@"StatusBarMode"])
1568 mode = [number intValue];
1571 /*MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, double duration, int animation) {
1572 NSLog(@"mode:%d orientation:%d duration:%f animation:%d", mode, orientation, duration, animation);
1573 SBStatusBarController$setStatusBarMode(mode);
1574 return _SBStatusBarController$setStatusBarMode$orientation$duration$animation$(self, sel, mode, orientation, duration, animation);
1577 MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, float duration, int fenceID, int animation) {
1578 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d", mode, orientation, duration, fenceID, animation);
1579 SBStatusBarController$setStatusBarMode(mode);
1580 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$(self, sel, mode, orientation, duration, fenceID, animation);
1583 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) {
1584 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d startTime:%f", mode, orientation, duration, fenceID, animation, startTime);
1585 SBStatusBarController$setStatusBarMode(mode);
1586 //NSLog(@"mode=%u", mode);
1587 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$startTime$(self, sel, mode, orientation, duration, fenceID, animation, startTime);
1590 /*MSHook(id, SBStatusBarContentsView$initWithStatusBar$mode$, SBStatusBarContentsView *self, SEL sel, id bar, int mode) {
1591 if (NSNumber *number = [Info_ objectForKey:@"StatusBarContentsMode"])
1592 mode = [number intValue];
1593 return _SBStatusBarContentsView$initWithStatusBar$mode$(self, sel, bar, mode);
1596 MSHook(NSString *, SBStatusBarOperatorNameView$operatorNameStyle, SBStatusBarOperatorNameView *self, SEL sel) {
1597 NSString *style(_SBStatusBarOperatorNameView$operatorNameStyle(self, sel));
1599 NSLog(@"operatorNameStyle= %@", style);
1600 if (NSString *custom = [Info_ objectForKey:@"OperatorNameStyle"])
1601 style = [NSString stringWithFormat:@"%@; %@", style, custom];
1605 MSHook(void, SBStatusBarOperatorNameView$setOperatorName$fullSize$, SBStatusBarOperatorNameView *self, SEL sel, NSString *name, BOOL full) {
1607 NSLog(@"setOperatorName:\"%@\" fullSize:%u", name, full);
1608 return _SBStatusBarOperatorNameView$setOperatorName$fullSize$(self, sel, name, NO);
1611 // XXX: replace this with [SBStatusBarTimeView tile]
1612 MSHook(void, SBStatusBarTimeView$drawRect$, SBStatusBarTimeView *self, SEL sel, CGRect rect) {
1613 id &_time(MSHookIvar<id>(self, "_time"));
1614 if (_time != nil && [_time class] != [WBTimeLabel class])
1615 object_setInstanceVariable(self, "_time", reinterpret_cast<void *>([[WBTimeLabel alloc] initWithTime:[_time autorelease] view:self]));
1616 return _SBStatusBarTimeView$drawRect$(self, sel, rect);
1619 @interface UIView (WinterBoard)
1620 - (bool) wb$isWBImageView;
1621 - (void) wb$logHierarchy;
1622 - (void) wb$setBackgroundColor:(UIColor *)color;
1625 @implementation UIView (WinterBoard)
1627 - (bool) wb$isWBImageView {
1631 - (void) wb$logHierarchy {
1632 WBLogHierarchy(self);
1635 - (void) wb$setBackgroundColor:(UIColor *)color {
1636 [self setBackgroundColor:color];
1637 for (UIView *child in [self subviews])
1638 [child wb$setBackgroundColor:color];
1643 @interface WBImageView : UIImageView {
1646 - (bool) wb$isWBImageView;
1647 - (void) wb$updateFrame;
1650 @implementation WBImageView
1652 - (bool) wb$isWBImageView {
1656 - (void) wb$updateFrame {
1657 CGRect frame([self frame]);
1660 for (UIView *view(self); ; ) {
1661 view = [view superview];
1664 frame.origin.y -= [view frame].origin.y;
1667 [self setFrame:frame];
1672 static void SBIconList$updateFrames$(SBIconList *self) {
1673 NSArray *subviews([self subviews]);
1674 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1675 if (view != nil && [view wb$isWBImageView])
1676 [view wb$updateFrame];
1679 MSHook(void, SBIconList$didMoveToSuperview, SBIconList *self, SEL sel) {
1680 SBIconList$updateFrames$(self);
1681 _SBIconList$didMoveToSuperview(self, sel);
1684 MSHook(void, SBIconList$setFrame$, SBIconList *self, SEL sel, CGRect frame) {
1685 SBIconList$updateFrames$(self);
1686 _SBIconList$setFrame$(self, sel, frame);
1689 static void $addPerPageView$(unsigned i, UIView *list) {
1690 NSString *path($getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Page%u.png", i]]));
1694 NSArray *subviews([list subviews]);
1696 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1697 if (view == nil || ![view wb$isWBImageView]) {
1698 view = [[[WBImageView alloc] init] autorelease];
1699 [list insertSubview:view atIndex:0];
1702 UIImage *image([UIImage imageWithContentsOfFile:path]);
1704 CGRect frame([view frame]);
1705 frame.size = [image size];
1706 [view setFrame:frame];
1708 [view setImage:image];
1709 [view wb$updateFrame];
1712 static void $addPerPageViews$(NSArray *lists) {
1713 for (unsigned i(0), e([lists count]); i != e; ++i)
1714 $addPerPageView$(i, [lists objectAtIndex:i]);
1717 MSInstanceMessageHook0(void, SBIconController, updateNumberOfRootIconLists) {
1718 NSArray *&_rootIconLists(MSHookIvar<NSArray *>(self, "_rootIconLists"));
1719 $addPerPageViews$(_rootIconLists);
1723 MSInstanceMessageHook0(void, SBIconContentView, layoutSubviews) {
1726 if (SBIconController *controller = [$SBIconController sharedInstance]) {
1727 UIView *&_dockContainerView(MSHookIvar<UIView *>(controller, "_dockContainerView"));
1728 if (&_dockContainerView != NULL)
1729 [[_dockContainerView superview] bringSubviewToFront:_dockContainerView];
1733 MSHook(void, SBIconController$noteNumberOfIconListsChanged, SBIconController *self, SEL sel) {
1734 SBIconModel *&_iconModel(MSHookIvar<SBIconModel *>(self, "_iconModel"));
1735 $addPerPageViews$([_iconModel iconLists]);
1736 return _SBIconController$noteNumberOfIconListsChanged(self, sel);
1739 MSHook(id, SBIconLabel$initWithSize$label$, SBIconLabel *self, SEL sel, CGSize size, NSString *label) {
1740 self = _SBIconLabel$initWithSize$label$(self, sel, size, label);
1742 [self setClipsToBounds:NO];
1746 MSHook(void, SBIconLabel$setInDock$, SBIconLabel *self, SEL sel, BOOL docked) {
1747 static bool gssc(false);
1749 BOOL (*GSSystemHasCapability)(CFStringRef) = reinterpret_cast<BOOL (*)(CFStringRef)>(dlsym(RTLD_DEFAULT, "GSSystemHasCapability"));
1750 Papered_ |= GSSystemHasCapability != NULL && GSSystemHasCapability(CFSTR("homescreen-wallpaper"));
1753 if ([Info_ objectForKey:@"UndockedIconLabels"] == nil)
1754 [Info_ setObject:[NSNumber numberWithBool:(
1756 [Info_ objectForKey:@"DockedIconLabelStyle"] != nil ||
1757 [Info_ objectForKey:@"UndockedIconLabelStyle"] != nil
1758 )] forKey:@"UndockedIconLabels"];
1761 id &_label(MSHookIvar<id>(self, "_label"));
1762 if (![Info_ wb$boolForKey:@"UndockedIconLabels"])
1765 if (_label != nil && [_label respondsToSelector:@selector(setInDock:)])
1766 [_label setInDock:docked];
1768 _SBIconLabel$setInDock$(self, sel, docked);
1769 [self setNeedsDisplay];
1772 MSHook(BOOL, SBDockIconListView$shouldShowNewDock, id self, SEL sel) {
1773 return SummerBoard_ && Docked_ ? NO : _SBDockIconListView$shouldShowNewDock(self, sel);
1776 MSHook(void, SBDockIconListView$setFrame$, id self, SEL sel, CGRect frame) {
1777 _SBDockIconListView$setFrame$(self, sel, frame);
1780 // %hook -[NSBundle localizedStringForKey:value:table:] {{{
1781 MSInstanceMessageHook3(NSString *, NSBundle, localizedStringForKey,value,table, NSString *, key, NSString *, value, NSString *, table) {
1782 NSString *identifier = [self bundleIdentifier];
1783 NSLocale *locale = [NSLocale currentLocale];
1784 NSString *language = [locale objectForKey:NSLocaleLanguageCode];
1786 NSLog(@"WB:Debug:[NSBundle(%@) localizedStringForKey:\"%@\" value:\"%@\" table:\"%@\"] (%@)", identifier, key, value, table, language);
1787 NSString *file = table == nil ? @"Localizable" : table;
1788 NSString *name = [NSString stringWithFormat:@"%@:%@", identifier, file];
1789 NSDictionary *strings;
1790 if ((strings = [Strings_ objectForKey:name]) != nil) {
1791 if (static_cast<id>(strings) != [NSNull null]) strings:
1792 if (NSString *value = [strings objectForKey:key])
1794 } else if (NSString *path = $pathForFile$inBundle$([NSString stringWithFormat:@"%@.lproj/%@.strings",
1796 ], self, false, false)) {
1797 if ((strings = [[NSDictionary alloc] initWithContentsOfFile:path]) != nil) {
1798 [Strings_ setObject:[strings autorelease] forKey:name];
1802 [Strings_ setObject:[NSNull null] forKey:name];
1803 return MSOldCall(key, value, table);
1806 // %hook -[WebCoreFrameBridge renderedSizeOfNode:constrainedToWidth:] {{{
1807 MSClassHook(WebCoreFrameBridge)
1809 MSInstanceMessageHook2(CGSize, WebCoreFrameBridge, renderedSizeOfNode,constrainedToWidth, id, node, float, width) {
1812 void **core(reinterpret_cast<void **>([node _node]));
1813 if (core == NULL || core[6] == NULL)
1815 return MSOldCall(node, width);
1819 MSInstanceMessage1(void, SBIconLabel, drawRect, CGRect, rect) {
1820 static Ivar drawMoreLegibly = object_getInstanceVariable(self, "_drawMoreLegibly", NULL);
1823 Ivar ivar = object_getInstanceVariable(self, "_inDock", reinterpret_cast<void **>(&docked));
1824 docked = (docked & (ivar_getOffset(ivar) == ivar_getOffset(drawMoreLegibly) ? 0x2 : 0x1)) != 0;
1826 NSString *label(MSHookIvar<NSString *>(self, "_label"));
1828 NSString *style = [NSString stringWithFormat:@""
1829 "font-family: Helvetica; "
1830 "font-weight: bold; "
1832 "", (docked || !SummerBoard_ ? @"white" : @"#b3b3b3"), (IsWild_
1833 ? @"font-size: 12px; "
1834 : @"font-size: 11px; "
1838 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px 1px 0px; "];
1840 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px -1px 0px; "];
1842 NSString *custom([Info_ objectForKey:(docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle")]);
1844 $drawLabel$(label, [self bounds], style, custom);
1847 MSInstanceMessage0(CGImageRef, SBIconLabel, buildLabelImage) {
1848 bool docked((MSHookIvar<unsigned>(self, "_inDock") & 0x2) != 0);
1850 WBStringDrawingState labelState = {NULL, 0, @""
1851 , docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle"};
1853 stringDrawingState_ = &labelState;
1856 CGImageRef image(MSOldCall());
1859 stringDrawingState_ = NULL;
1863 static bool wb$inDock(id parameters) {
1864 return [$objc_getAssociatedObject(parameters, @selector(wb$inDock)) boolValue];
1867 MSInstanceMessage0(NSUInteger, SBIconLabelImageParameters, hash) {
1868 return MSOldCall() + (wb$inDock(self) ? 0xdeadbeef : 0xd15ea5e);
1871 MSClassMessage2(id, SBIconView, _labelImageParametersForIcon,location, id, icon, int, location) {
1872 if (id parameters = MSOldCall(icon, location)) {
1873 $objc_setAssociatedObject(parameters, @selector(wb$inDock), [NSNumber numberWithBool:(location == 1)], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1878 MSInstanceMessage0(id, SBIconView, _labelImageParameters) {
1879 if (id parameters = MSOldCall()) {
1880 int &location(MSHookIvar<int>(self, "_iconLocation"));
1881 if (&location != NULL)
1882 $objc_setAssociatedObject(parameters, @selector(wb$inDock), [NSNumber numberWithBool:(location == 3)], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1887 MSClassMessage1(UIImage *, SBIconLabelImage, _drawLabelImageForParameters, id, parameters) {
1888 bool docked(wb$inDock(parameters));
1890 WBStringDrawingState labelState = {NULL, 0, @""
1891 , docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle"};
1893 stringDrawingState_ = &labelState;
1896 UIImage *image(MSOldCall(parameters));
1899 stringDrawingState_ = NULL;
1904 MSInstanceMessageHook2(id, CKBalloonView, initWithFrame,delegate, CGRect, frame, id, delegate) {
1905 if ((self = MSOldCall(frame, delegate)) != nil) {
1906 [self setBackgroundColor:[UIColor clearColor]];
1910 MSInstanceMessageHook0(BOOL, CKBalloonView, _canUseLayerBackedBalloon) {
1911 return SMSBackgrounded_ ? NO : MSOldCall();
1914 MSInstanceMessageHook0(void, CKTranscriptHeaderView, layoutSubviews) {
1915 [self wb$setBackgroundColor:[UIColor clearColor]];
1919 MSInstanceMessageHook1(void, CKMessageCell, addBalloonView, CKBalloonView *, balloon) {
1921 [balloon setBackgroundColor:[UIColor clearColor]];
1924 MSInstanceMessageHook1(void, CKTranscriptCell, setBackgroundColor, UIColor *, color) {
1925 MSOldCall([UIColor clearColor]);
1926 [[self contentView] wb$setBackgroundColor:[UIColor clearColor]];
1930 MSInstanceMessageHook2(id, CKTranscriptCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1931 if ((self = MSOldCall(style, reuse)) != nil) {
1932 [self setBackgroundColor:[UIColor clearColor]];
1933 [[self contentView] wb$setBackgroundColor:[UIColor clearColor]];
1938 MSInstanceMessageHook2(id, CKMessageCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1939 if ((self = MSOldCall(style, reuse)) != nil) {
1940 [self setBackgroundColor:[UIColor clearColor]];
1941 [[self contentView] setBackgroundColor:[UIColor clearColor]];
1945 MSInstanceMessageHook2(id, CKTimestampView, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1946 if ((self = MSOldCall(style, reuse)) != nil) {
1947 UILabel *&_label(MSHookIvar<UILabel *>(self, "_label"));
1948 [_label setBackgroundColor:[UIColor clearColor]];
1952 MSInstanceMessageHook1(void, CKTranscriptTableView, setSeparatorStyle, int, style) {
1953 MSOldCall(UITableViewCellSeparatorStyleNone);
1956 MSInstanceMessageHook2(id, CKTranscriptTableView, initWithFrame,style, CGRect, frame, int, style) {
1957 if ((self = MSOldCall(frame, style)) != nil) {
1958 [self setSeparatorStyle:UITableViewCellSeparatorStyleNone];
1962 MSInstanceMessageHook0(void, CKTranscriptController, loadView) {
1965 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"SMSBackground.png", @"SMSBackground.jpg", nil])))
1966 if (UIImage *image = $getImage$(path)) {
1967 SMSBackgrounded_ = true;
1969 UIView *&_transcriptTable(MSHookIvar<UIView *>(self, "_transcriptTable"));
1970 UIView *&_transcriptLayer(MSHookIvar<UIView *>(self, "_transcriptLayer"));
1972 if (&_transcriptTable != NULL)
1973 table = _transcriptTable;
1974 else if (&_transcriptLayer != NULL)
1975 table = _transcriptLayer;
1979 UIView *placard(table != nil ? [table superview] : MSHookIvar<UIView *>(self, "_backPlacard"));
1980 UIImageView *background([[[UIImageView alloc] initWithImage:image] autorelease]);
1983 [placard insertSubview:background atIndex:0];
1985 [table setBackgroundColor:[UIColor clearColor]];
1986 [placard insertSubview:background belowSubview:table];
1992 template <typename Original_>
1993 static UIImage *WBCacheUIImage(const Original_ &original, NSString *name, NSString *key) {
1994 if ([name rangeOfString:@"."].location == NSNotFound)
1995 name = [name stringByAppendingString:@".png"];
1996 UIImage *image(WBCacheImage(original, [=](){ return $pathForFile$inBundle$(name, _UIKitBundle(), true, true); }, key));
1997 if (image != nil && UIDebug_) {
1998 NSString *path([@"/tmp/UIImages/" stringByAppendingString:name]);
1999 if (![Manager_ fileExistsAtPath:path])
2000 [UIImagePNGRepresentation(image) writeToFile:path atomically:YES];
2004 // %hook _UIImageWithName() {{{
2005 MSHook(UIImage *, _UIImageWithName, NSString *name) {
2009 NSLog(@"WB:Debug: _UIImageWithName(\"%@\")", name);
2010 return WBCacheUIImage(
2011 [=](){ return __UIImageWithName(name); },
2012 name, [NSString stringWithFormat:@"I:%@", name]);
2015 // %hook _UIImageWithNameInDomain() {{{
2016 MSHook(UIImage *, _UIImageWithNameInDomain, NSString *name, NSString *domain) {
2018 NSLog(@"WB:Debug: _UIImageWithNameInDomain(\"%@\", \"%@\")", name, domain);
2019 return WBCacheImage(
2020 [=](){ return __UIImageWithNameInDomain(name, domain); },
2021 [=](){ return $getTheme$($useScale$([NSArray arrayWithObject:[NSString stringWithFormat:@"Domains/%@/%@", domain, name]])); },
2022 [NSString stringWithFormat:@"D:%zu:%@%@", size_t([domain length]), domain, name]);
2025 // %hook _UIImageWithDeviceUsingCurrentIdiom() {{{
2026 MSHook(UIImage *, _UIImageWithNameUsingCurrentIdiom, NSString *name) {
2028 NSLog(@"WB:Debug: _UIImageWithNameUsingCurrentIdiom(\"%@\")", name);
2029 return WBCacheUIImage(
2030 [=](){ return __UIImageWithNameUsingCurrentIdiom(name); },
2031 name, [NSString stringWithFormat:@"I:%@", name]);
2034 // %hook _UIImageWithDeviceSpecificName() {{{
2035 MSHook(UIImage *, _UIImageWithDeviceSpecificName, NSString *name) {
2037 NSLog(@"WB:Debug: _UIImageWithDeviceSpecificName(\"%@\")", name);
2038 return WBCacheUIImage(
2039 [=](){ return __UIImageWithDeviceSpecificName(name); },
2040 name, [NSString stringWithFormat:@"S:%@", name]);
2044 // %hook GSFontCreateWithName() {{{
2045 MSHook(GSFontRef, GSFontCreateWithName, const char *name, GSFontSymbolicTraits traits, float size) {
2047 NSLog(@"WB:Debug: GSFontCreateWithName(\"%s\", %f)", name, size);
2048 if (NSString *font = [Info_ objectForKey:[NSString stringWithFormat:@"FontName-%s", name]])
2049 name = [font UTF8String];
2050 //if (NSString *scale = [Info_ objectForKey:[NSString stringWithFormat:@"FontScale-%s", name]])
2051 // size *= [scale floatValue];
2052 return _GSFontCreateWithName(name, traits, size);
2056 #define AudioToolbox "/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox"
2058 static bool GetFileNameForThisAction$(bool value, unsigned long a0, char *a1, unsigned long a2, bool &a3) {
2060 NSLog(@"WB:Debug:GetFileNameForThisAction(%lu, %s, %lu, %u) = %u", a0, value ? a1 : NULL, a2, a3, value);
2063 NSString *path = [NSString stringWithUTF8String:a1];
2064 if ([path hasPrefix:@"/System/Library/Audio/UISounds/"]) {
2065 NSString *file = [path substringFromIndex:31];
2066 for (NSString *theme in Themes_) {
2067 NSString *path([NSString stringWithFormat:@"%@/UISounds/%@", theme, file]);
2068 if ([Manager_ fileExistsAtPath:path]) {
2069 strcpy(a1, [path UTF8String]);
2078 MSHook(bool, _Z24GetFileNameForThisActionmPcRb, unsigned long a0, char *a1, bool &a3) {
2079 bool value(__Z24GetFileNameForThisActionmPcRb(a0, a1, a3));
2080 return GetFileNameForThisAction$(value, a0, a1, 0, a3);
2083 MSHook(bool, _Z24GetFileNameForThisActionmPcmRb, unsigned long a0, char *a1, unsigned long a2, bool &a3) {
2084 bool value(__Z24GetFileNameForThisActionmPcmRb(a0, a1, a2, a3));
2085 return GetFileNameForThisAction$(value, a0, a1, a2, a3);
2088 static void ChangeWallpaper(
2089 CFNotificationCenterRef center,
2093 CFDictionaryRef info
2096 NSLog(@"WB:Debug:ChangeWallpaper!");
2099 if (WallpaperFile_ != nil) {
2100 image = [[UIImage alloc] initWithContentsOfFile:WallpaperFile_];
2102 image = [image autorelease];
2105 if (WallpaperImage_ != nil)
2106 [WallpaperImage_ setImage:image];
2107 if (WallpaperPage_ != nil)
2108 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
2112 MSHook(NSArray *, CPBitmapCreateImagesFromPath, NSString *path, NSDictionary **names, void *arg2, void *arg3) {
2113 NSArray *images(_CPBitmapCreateImagesFromPath(path, names, arg2, arg3));
2114 if (images != NULL && *names != nil && CFGetTypeID((CFTypeRef) *names) == CFDictionaryGetTypeID()) {
2115 if (NSBundle *bundle = [NSBundle wb$bundleWithFile:path]) {
2116 NSMutableArray *copy([images mutableCopy]);
2120 NSString *file([path stringByResolvingSymlinksInPath]);
2121 NSString *prefix([[bundle bundlePath] stringByResolvingSymlinksInPath]);
2122 if ([file hasPrefix:prefix]) {
2123 NSUInteger length([prefix length]);
2124 if (length != [file length]) {
2125 NSEnumerator *enumerator([*names keyEnumerator]);
2126 while (NSString *name = [enumerator nextObject]) {
2127 NSString *png([name stringByAppendingString:@".png"]);
2128 if (NSString *themed = $pathForFile$inBundle$(png, bundle, false, true)) {
2129 NSUInteger index([[*names objectForKey:name] intValue]);
2130 UIImage *image($getImage$(themed));
2131 CGImageRef cg([image CGImage]);
2132 [copy replaceObjectAtIndex:index withObject:(id)cg];
2141 MSHook(void, BKSDisplayServicesSetSystemAppExitedImagePath, NSString *path) {
2142 if (NSString *themed = $getTheme$($useScale$([NSArray arrayWithObject:@"SystemAppExited.png"])))
2144 _BKSDisplayServicesSetSystemAppExitedImagePath(path);
2147 #define WBRename(name, sel, imp) \
2148 MSHookMessage($ ## name, @selector(sel), &$ ## name ## $ ## imp, &_ ## name ## $ ## imp)
2150 template <typename Type_>
2151 static void msset(Type_ &function, MSImageRef image, const char *name) {
2152 function = reinterpret_cast<Type_>(MSFindSymbol(image, name));
2155 #define WBHookSymbol(image, function) \
2156 msset(function, image, "_" #function)
2158 template <typename Type_>
2159 static void dlset(Type_ &function, const char *name) {
2160 function = reinterpret_cast<Type_>(dlsym(RTLD_DEFAULT, name));
2163 // %hook CGImageReadCreateWithFile() {{{
2164 MSHook(void *, CGImageReadCreateWithFile, NSString *path, int flag) {
2166 NSLog(@"WB:Debug: CGImageReadCreateWithFile(%@, %d)", path, flag);
2167 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2168 void *value(_CGImageReadCreateWithFile([path wb$themedPath], flag));
2173 MSHook(void *, CGImageSourceCreateWithFile, NSString *path, NSDictionary *options) {
2175 NSLog(@"WB:Debug: CGImageSourceCreateWithFile(%@, %@)", path, options);
2176 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2177 void *value(_CGImageSourceCreateWithFile([path wb$themedPath], options));
2182 MSHook(void *, CGImageSourceCreateWithURL, NSURL *url, NSDictionary *options) {
2184 NSLog(@"WB:Debug: CGImageSourceCreateWithURL(%@, %@)", url, options);
2185 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2186 if ([url isFileURL])
2187 url = [NSURL fileURLWithPath:[[url path] wb$themedPath]];
2188 void *value(_CGImageSourceCreateWithURL(url, options));
2194 static void NSString$drawAtPoint$withStyle$(NSString *self, SEL _cmd, CGPoint point, NSString *style) {
2195 WKSetCurrentGraphicsContext(UIGraphicsGetCurrentContext());
2196 if (style == nil || [style length] == 0)
2197 style = @"font-family: Helvetica; font-size: 12px";
2198 //NSLog(@"XXX:drawP(%@ | %@)", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "]);
2199 [[WBMarkup sharedMarkup] drawString:self atPoint:point withStyle:style];
2202 static void NSString$drawInRect$withStyle$(NSString *self, SEL _cmd, CGRect rect, NSString *style) {
2203 WKSetCurrentGraphicsContext(UIGraphicsGetCurrentContext());
2204 if (style == nil || [style length] == 0)
2205 style = @"font-family: Helvetica; font-size: 12px";
2206 //NSLog(@"XXX:drawR(%@ | %@)", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "]);
2207 return [[WBMarkup sharedMarkup] drawString:self inRect:rect withStyle:style];
2210 static CGSize NSString$sizeWithStyle$forWidth$(NSString *self, SEL _cmd, NSString *style, CGFloat width) {
2211 if (style == nil || [style length] == 0)
2212 style = @"font-family: Helvetica; font-size: 12px";
2213 CGSize size([[WBMarkup sharedMarkup] sizeOfString:self withStyle:style forWidth:width]);
2214 //NSLog(@"XXX:size(%@ | %@) = [%g %g]", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "], size.width, size.height);
2218 static void SBInitialize() {
2220 WBRename(SBApplication, pathForIcon, pathForIcon);
2221 WBRename(SBApplicationIcon, icon, icon);
2222 WBRename(SBApplicationIcon, generateIconImage:, generateIconImage$);
2225 WBRename(SBBookmarkIcon, icon, icon);
2226 WBRename(SBButtonBar, didMoveToSuperview, didMoveToSuperview);
2227 WBRename(SBCalendarIconContentsView, drawRect:, drawRect$);
2228 WBRename(SBIconBadge, initWithBadge:, initWithBadge$);
2229 WBRename(SBIconController, noteNumberOfIconListsChanged, noteNumberOfIconListsChanged);
2231 WBRename(SBWidgetApplicationIcon, icon, icon);
2233 WBRename(SBDockIconListView, setFrame:, setFrame$);
2234 MSHookMessage(object_getClass($SBDockIconListView), @selector(shouldShowNewDock), &$SBDockIconListView$shouldShowNewDock, &_SBDockIconListView$shouldShowNewDock);
2236 if (kCFCoreFoundationVersionNumber < 600 || SummerBoard_)
2237 WBRename(SBIconLabel, drawRect:, drawRect$);
2238 else if (kCFCoreFoundationVersionNumber < 700) {
2239 WBRename(SBIconLabel, buildLabelImage, buildLabelImage);
2241 WBRename(SBIconLabelImageParameters, hash, hash);
2242 WBRename($SBIconView, _labelImageParametersForIcon:location:, _labelImageParametersForIcon$location$);
2243 WBRename(SBIconView, _labelImageParameters, _labelImageParameters);
2244 WBRename($SBIconLabelImage, _drawLabelImageForParameters:, _drawLabelImageForParameters$);
2247 WBRename(SBIconLabel, initWithSize:label:, initWithSize$label$);
2248 WBRename(SBIconLabel, setInDock:, setInDock$);
2250 WBRename(SBIconList, didMoveToSuperview, didMoveToSuperview);
2251 WBRename(SBIconList, setFrame:, setFrame$);
2253 WBRename(SBIconModel, cacheImageForIcon:, cacheImageForIcon$);
2254 WBRename(SBIconModel, cacheImagesForIcon:, cacheImagesForIcon$);
2255 WBRename(SBIconModel, getCachedImagedForIcon:, getCachedImagedForIcon$);
2256 WBRename(SBIconModel, getCachedImagedForIcon:smallIcon:, getCachedImagedForIcon$smallIcon$);
2258 if (kCFCoreFoundationVersionNumber < 800) {
2259 WBRename(SBSearchView, initWithFrame:, initWithFrame$);
2260 WBRename(SBSearchTableViewCell, drawRect:, drawRect$);
2261 WBRename(SBSearchTableViewCell, initWithStyle:reuseIdentifier:, initWithStyle$reuseIdentifier$);
2264 //WBRename(SBImageCache, initWithName:forImageWidth:imageHeight:initialCapacity:, initWithName$forImageWidth$imageHeight$initialCapacity$);
2266 WBRename(SBAwayView, updateDesktopImage:, updateDesktopImage$);
2267 if (kCFCoreFoundationVersionNumber >= 700)
2268 WBRename(SBAwayView, _addSubview:positioned:relativeTo:, _addSubview$positioned$relativeTo$);
2270 WBRename(SBStatusBarContentsView, didMoveToSuperview, didMoveToSuperview);
2271 //WBRename(SBStatusBarContentsView, initWithStatusBar:mode:, initWithStatusBar$mode$);
2272 //WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:animation:, setStatusBarMode$orientation$duration$animation$);
2273 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:, setStatusBarMode$orientation$duration$fenceID$animation$);
2274 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:startTime:, setStatusBarMode$orientation$duration$fenceID$animation$startTime$);
2275 WBRename(SBStatusBarOperatorNameView, operatorNameStyle, operatorNameStyle);
2276 WBRename(SBStatusBarOperatorNameView, setOperatorName:fullSize:, setOperatorName$fullSize$);
2277 WBRename(SBStatusBarTimeView, drawRect:, drawRect$);
2280 English_ = [[NSDictionary alloc] initWithContentsOfFile:@"/System/Library/CoreServices/SpringBoard.app/English.lproj/LocalizedApplicationNames.strings"];
2282 if (kCFCoreFoundationVersionNumber >= 800) {
2283 WBRename(NSString, drawInRect:withAttributes:, drawInRect$withAttributes$);
2284 WBRename(NSString, boundingRectWithSize:options:attributes:context:, boundingRectWithSize$options$attributes$context$);
2288 /*MSHook(int, open, const char *path, int oflag, mode_t mode) {
2289 int fd(_open(path, oflag, mode));
2291 static bool no(false);
2295 if (strstr(path, "/icon") != NULL)
2296 MSHookProcess(-1, "");
2298 if (fd == -1 && errno == EFAULT)
2299 NSLog(@"open(%p, %#x, %#o) = %d\n", path, oflag, mode, fd);
2301 NSLog(@"open(\"%s\", %#x, %#o) = %d\n", path, oflag, mode, fd);
2308 $objc_setAssociatedObject = reinterpret_cast<void (*)(id, void *, id value, objc_AssociationPolicy)>(dlsym(RTLD_DEFAULT, "objc_setAssociatedObject"));
2309 $objc_getAssociatedObject = reinterpret_cast<id (*)(id, void *)>(dlsym(RTLD_DEFAULT, "objc_getAssociatedObject"));
2310 $objc_removeAssociatedObjects = reinterpret_cast<void (*)(id)>(dlsym(RTLD_DEFAULT, "objc_removeAssociatedObjects"));
2312 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2314 NSString *identifier([[NSBundle mainBundle] bundleIdentifier]);
2315 SpringBoard_ = [identifier isEqualToString:@"com.apple.springboard"];
2317 Manager_ = [[NSFileManager defaultManager] retain];
2318 Themes_ = [[NSMutableArray alloc] initWithCapacity:8];
2320 dlset(_GSFontGetUseLegacyFontMetrics, "GSFontGetUseLegacyFontMetrics");
2322 // Load Settings.plist {{{
2323 if (NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"/User/Library/Preferences/com.saurik.WinterBoard.plist"]]) {
2324 if (NSNumber *value = [settings objectForKey:@"SummerBoard"])
2325 SummerBoard_ = [value boolValue];
2327 SummerBoard_ = true;
2329 if (NSNumber *value = [settings objectForKey:@"Debug"])
2330 Debug_ = [value boolValue];
2331 if (NSNumber *value = [settings objectForKey:@"RecordUI"])
2332 UIDebug_ = [value boolValue];
2334 NSArray *themes([settings objectForKey:@"Themes"]);
2336 if (NSString *theme = [settings objectForKey:@"Theme"])
2337 themes = [NSArray arrayWithObject:[NSDictionary dictionaryWithObjectsAndKeys:
2339 [NSNumber numberWithBool:true], @"Active",
2343 for (NSDictionary *theme in themes) {
2344 NSNumber *active([theme objectForKey:@"Active"]);
2345 if (![active boolValue])
2348 NSString *name([theme objectForKey:@"Name"]);
2352 #define testForTheme(format...) \
2354 NSString *path = [NSString stringWithFormat:format]; \
2355 if ([Manager_ fileExistsAtPath:path]) { \
2356 [Themes_ addObject:path]; \
2361 testForTheme(@"/Library/Themes/%@.theme", name)
2362 testForTheme(@"/Library/Themes/%@", name)
2363 testForTheme(@"%@/Library/SummerBoard/Themes/%@", NSHomeDirectory(), name)
2368 // Merge Info.plist {{{
2369 Info_ = [[NSMutableDictionary dictionaryWithCapacity:16] retain];
2371 for (NSString *theme in Themes_)
2372 if (NSDictionary *info = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"%@/Info.plist", theme]])
2373 for (NSString *key in [info allKeys])
2374 if ([Info_ objectForKey:key] == nil)
2375 [Info_ setObject:[info objectForKey:key] forKey:key];
2379 if (MSImageRef image = MSGetImageByName("/System/Library/PrivateFrameworks/AppSupport.framework/AppSupport")) {
2380 NSArray *(*CPBitmapCreateImagesFromPath)(NSString *, NSDictionary **, void *, void *);
2381 msset(CPBitmapCreateImagesFromPath, image, "_CPBitmapCreateImagesFromPath");
2382 MSHookFunction(CPBitmapCreateImagesFromPath, MSHake(CPBitmapCreateImagesFromPath));
2386 if (MSImageRef image = MSGetImageByName(AudioToolbox)) {
2387 bool (*_Z24GetFileNameForThisActionmPcRb)(unsigned long, char *, bool &);
2388 msset(_Z24GetFileNameForThisActionmPcRb, image, "__Z24GetFileNameForThisActionmPcRb");
2389 MSHookFunction(_Z24GetFileNameForThisActionmPcRb, &$_Z24GetFileNameForThisActionmPcRb, &__Z24GetFileNameForThisActionmPcRb);
2391 bool (*_Z24GetFileNameForThisActionmPcmRb)(unsigned long, char *, unsigned long, bool &);
2392 msset(_Z24GetFileNameForThisActionmPcmRb, image, "__Z24GetFileNameForThisActionmPcmRb");
2393 MSHookFunction(_Z24GetFileNameForThisActionmPcmRb, &$_Z24GetFileNameForThisActionmPcmRb, &__Z24GetFileNameForThisActionmPcmRb);
2396 // BackBoardServices {{{
2397 if (MSImageRef image = MSGetImageByName("/System/Library/PrivateFrameworks/BackBoardServices.framework/BackBoardServices")) {
2398 void (*BKSDisplayServicesSetSystemAppExitedImagePath)(NSString *path);
2399 msset(BKSDisplayServicesSetSystemAppExitedImagePath, image, "_BKSDisplayServicesSetSystemAppExitedImagePath");
2400 MSHookFunction(BKSDisplayServicesSetSystemAppExitedImagePath, MSHake(BKSDisplayServicesSetSystemAppExitedImagePath));
2403 // GraphicsServices {{{
2405 MSHookFunction(&GSFontCreateWithName, &$GSFontCreateWithName, &_GSFontCreateWithName);
2409 MSImageRef imageio = MSGetImageByName("/System/Library/Frameworks/ImageIO.framework/ImageIO");
2410 if (imageio == NULL)
2411 imageio = MSGetImageByName("/System/Library/PrivateFrameworks/ImageIO.framework/ImageIO");
2412 if (MSImageRef image = imageio) {
2413 void *(*CGImageReadCreateWithFile)(NSString *, int) = NULL;
2414 if (kCFCoreFoundationVersionNumber > 700) // XXX: iOS 6.x
2415 CGImageReadCreateWithFile = NULL;
2417 msset(CGImageReadCreateWithFile, image, "_CGImageReadCreateWithFile");
2418 MSHookFunction(CGImageReadCreateWithFile, MSHake(CGImageReadCreateWithFile));
2421 if (CGImageReadCreateWithFile == NULL) {
2422 void *(*CGImageSourceCreateWithFile)(NSString *, NSDictionary *);
2423 msset(CGImageSourceCreateWithFile, image, "_CGImageSourceCreateWithFile");
2424 MSHookFunction(CGImageSourceCreateWithFile, MSHake(CGImageSourceCreateWithFile));
2426 void *(*CGImageSourceCreateWithURL)(NSURL *, NSDictionary *);
2427 msset(CGImageSourceCreateWithURL, image, "_CGImageSourceCreateWithURL");
2428 MSHookFunction(CGImageSourceCreateWithURL, MSHake(CGImageSourceCreateWithURL));
2434 Wallpapers_ = [[NSArray arrayWithObjects:@"Wallpaper.mp4", @"Wallpaper@2x.png", @"Wallpaper@2x.jpg", @"Wallpaper.png", @"Wallpaper.jpg", @"Wallpaper.html", nil] retain];
2435 Papered_ = $getTheme$(Wallpapers_) != nil;
2436 Docked_ = $getTheme$([NSArray arrayWithObjects:@"Dock.png", nil]) != nil;
2438 CFNotificationCenterAddObserver(
2439 CFNotificationCenterGetDarwinNotifyCenter(),
2440 NULL, &ChangeWallpaper, (CFStringRef) @"com.saurik.winterboard.lockbackground", NULL, CFNotificationSuspensionBehaviorCoalesce
2443 if ($getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"]) != nil) {
2444 NSBundle *MediaPlayer([NSBundle bundleWithPath:@"/System/Library/Frameworks/MediaPlayer.framework"]);
2445 if (MediaPlayer != nil)
2448 $MPMoviePlayerController = objc_getClass("MPMoviePlayerController");
2449 $MPVideoView = objc_getClass("MPVideoView");
2456 if (MSImageRef image = MSGetImageByName("/System/Library/Frameworks/UIKit.framework/UIKit")) {
2458 class_addMethod($NSString, @selector(drawAtPoint:withStyle:), (IMP) &NSString$drawAtPoint$withStyle$, "v40@0:8{CGPoint=dd}16@32");
2459 class_addMethod($NSString, @selector(drawInRect:withStyle:), (IMP) &NSString$drawInRect$withStyle$, "v56@0:8{CGRect={CGSize=dd}{CGSize=dd}}16@48");
2460 class_addMethod($NSString, @selector(sizeWithStyle:forWidth:), (IMP) &NSString$sizeWithStyle$forWidth$, "{CGSize=dd}32@0:8@16d24");
2462 class_addMethod($NSString, @selector(drawAtPoint:withStyle:), (IMP) &NSString$drawAtPoint$withStyle$, "v20@0:4{CGPoint=ff}8@16");
2463 class_addMethod($NSString, @selector(drawInRect:withStyle:), (IMP) &NSString$drawInRect$withStyle$, "v28@0:4{CGRect={CGSize=ff}{CGSize=ff}}8@24");
2464 class_addMethod($NSString, @selector(sizeWithStyle:forWidth:), (IMP) &NSString$sizeWithStyle$forWidth$, "{CGSize=ff}16@0:4@8f12");
2467 WBHookSymbol(image, _UIKitBundle);
2468 WBHookSymbol(image, _UIPackedImageTableGetIdentifierForName);
2469 WBHookSymbol(image, _UISharedImageNameGetIdentifier);
2471 MSHookFunction(_UIImageWithName, MSHake(_UIImageWithName));
2473 WBHookSymbol(image, _UIApplicationImageWithName);
2474 MSHookFunction(_UIApplicationImageWithName, MSHake(_UIApplicationImageWithName));
2476 WBHookSymbol(image, _UIImageWithNameInDomain);
2477 MSHookFunction(_UIImageWithNameInDomain, MSHake(_UIImageWithNameInDomain));
2479 WBHookSymbol(image, _UIImageWithNameUsingCurrentIdiom);
2480 MSHookFunction(_UIImageWithNameUsingCurrentIdiom, MSHake(_UIImageWithNameUsingCurrentIdiom));
2482 WBHookSymbol(image, _UIImageWithDeviceSpecificName);
2483 MSHookFunction(_UIImageWithDeviceSpecificName, MSHake(_UIImageWithDeviceSpecificName));
2485 SEL includeEmoji(@selector(_legacy_drawAtPoint:forWidth:withFont:lineBreakMode:letterSpacing:includeEmoji:));
2486 if (![@"" respondsToSelector:includeEmoji])
2487 includeEmoji = @selector(drawAtPoint:forWidth:withFont:lineBreakMode:letterSpacing:includeEmoji:);
2488 MSHookMessage($NSString, includeEmoji, MSHake(NSString$drawAtPoint$forWidth$withFont$lineBreakMode$letterSpacing$includeEmoji$));
2490 SEL letterSpacing(@selector(_legacy_sizeWithFont:forWidth:lineBreakMode:letterSpacing:));
2491 if (![@"" respondsToSelector:letterSpacing])
2492 letterSpacing = @selector(sizeWithFont:forWidth:lineBreakMode:letterSpacing:);
2493 MSHookMessage($NSString, letterSpacing, MSHake(NSString$sizeWithFont$forWidth$lineBreakMode$letterSpacing$));
2495 SEL sizeWithFont(@selector(_legacy_sizeWithFont:));
2496 if (![@"" respondsToSelector:sizeWithFont])
2497 sizeWithFont = @selector(sizeWithFont:);
2498 MSHookMessage($NSString, sizeWithFont, MSHake(NSString$sizeWithFont$));
2502 //MSHookFunction(reinterpret_cast<int (*)(const char *, int, mode_t)>(&open), MSHake(open));
2504 if (UIDebug_ && ![Manager_ fileExistsAtPath:@"/tmp/UIImages"]) {
2505 NSError *error(nil);
2506 if (![Manager_ createDirectoryAtPath:@"/tmp/UIImages" withIntermediateDirectories:NO attributes:[NSDictionary dictionaryWithObjectsAndKeys:
2507 [NSNumber numberWithShort:0777], NSFilePosixPermissions,
2509 NSLog(@"WB:Error: cannot create /tmp/UIImages (%@)", error);