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];
682 NSLog(@"WB:Debug: [NSBundle(%@) pathForResource:\"%@\"]", [self bundleIdentifier], file);
683 if (NSString *path = $pathForFile$inBundle$(file, self, false, false))
685 return MSOldCall(resource, type);
689 static void $drawLabel$(NSString *label, CGRect rect, NSString *style, NSString *custom) {
690 bool ellipsis(false);
691 CGFloat max = rect.size.width - 11, width;
693 width = [(ellipsis ? [label stringByAppendingString:@"..."] : label) sizeWithStyle:style forWidth:320].width;
696 size_t length([label length]);
697 CGFloat spacing((width - max) / (length - 1));
699 if (spacing > 1.25) {
701 label = [label substringToIndex:(length - 1)];
705 style = [style stringByAppendingString:[NSString stringWithFormat:@"letter-spacing: -%f; ", spacing]];
709 label = [label stringByAppendingString:@"..."];
712 style = [style stringByAppendingString:custom];
714 CGSize size = [label sizeWithStyle:style forWidth:rect.size.width];
715 [label drawAtPoint:CGPointMake((rect.size.width - size.width) / 2 + rect.origin.x, rect.origin.y) withStyle:style];
718 static struct WBStringDrawingState {
719 WBStringDrawingState *next_;
723 } *stringDrawingState_;
725 extern "C" CGColorSpaceRef CGContextGetFillColorSpace(CGContextRef);
726 extern "C" void CGContextGetFillColor(CGContextRef, CGFloat[]);
728 static NSString *WBColorMarkup(size_t number, const CGFloat *components) {
750 return [NSString stringWithFormat:@"color: rgba(%g, %g, %g, %g)", r * 255, g * 255, b * 255, a];
753 static NSString *WBColorMarkup() {
754 CGContextRef context(UIGraphicsGetCurrentContext());
755 //NSLog(@"XXX:1:%p", context);
759 CGColorSpaceRef space(CGContextGetFillColorSpace(context));
760 //NSLog(@"XXX:2:%p", space);
764 size_t number(CGColorSpaceGetNumberOfComponents(space));
765 //NSLog(@"XXX:3:%u", number);
769 CGFloat components[number + 1];
770 CGContextGetFillColor(context, components);
771 return WBColorMarkup(number, components);
774 static NSString *WBColorMarkup(UIColor *uicolor) {
777 CGColorRef cgcolor([uicolor CGColor]);
781 CGColorSpaceRef space(CGColorGetColorSpace(cgcolor));
782 //NSLog(@"XXX:2:%p", space);
786 size_t number(CGColorGetNumberOfComponents(cgcolor));
787 //NSLog(@"XXX:3:%u", number);
791 const CGFloat *components(CGColorGetComponents(cgcolor));
792 return WBColorMarkup(number, components);
795 extern "C" NSString *NSStringFromCGPoint(CGPoint rect);
797 MSInstanceMessage6(CGSize, NSString, drawAtPoint,forWidth,withFont,lineBreakMode,letterSpacing,includeEmoji, CGPoint, point, CGFloat, width, UIFont *, font, UILineBreakMode, mode, CGFloat, spacing, BOOL, emoji) {
798 //NSLog(@"XXX: @\"%@\" %@ %g \"%@\" %u %g %u", self, NSStringFromCGPoint(point), width, font, mode, spacing, emoji);
800 WBStringDrawingState *state(stringDrawingState_);
802 return MSOldCall(point, width, font, mode, spacing, emoji);
804 if (state->count_ != 0 && --state->count_ == 0)
805 stringDrawingState_ = state->next_;
806 if (state->info_ == nil)
807 return MSOldCall(point, width, font, mode, spacing, emoji);
809 NSString *info([Info_ objectForKey:state->info_]);
811 return MSOldCall(point, width, font, mode, spacing, emoji);
813 NSString *base(state->base_ ?: @"");
814 NSString *extra([NSString stringWithFormat:@"letter-spacing: %gpx", spacing]);
815 [self drawAtPoint:point withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info]];
819 extern "C" NSString *NSStringFromCGRect(CGRect rect);
821 MSInstanceMessageHook7(CGSize, NSString, _drawInRect,withFont,lineBreakMode,alignment,lineSpacing,includeEmoji,truncationRect, CGRect, rect, UIFont *, font, UILineBreakMode, mode, UITextAlignment, alignment, float, spacing, BOOL, emoji, CGRect, truncation) {
822 //NSLog(@"XXX: @\"%@\" %@ \"%@\" %u %u %g %u %@", self, NSStringFromCGRect(rect), font, mode, alignment, spacing, emoji, NSStringFromCGRect(truncation));
824 WBStringDrawingState *state(stringDrawingState_);
826 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
828 if (state->count_ != 0 && --state->count_ == 0)
829 stringDrawingState_ = state->next_;
830 if (state->info_ == nil)
831 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
833 NSString *info([Info_ objectForKey:state->info_]);
835 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
840 case UITextAlignmentLeft:
843 case UITextAlignmentCenter:
844 textAlign = @"center";
846 case UITextAlignmentRight:
847 textAlign = @"right";
851 NSString *base(state->base_ ?: @"");
852 NSString *extra([NSString stringWithFormat:@"text-align: %@", textAlign]);
855 $drawLabel$(self, rect, [NSString stringWithFormat:@"%@;%@;%@", [font markupDescription], WBColorMarkup(), base], info);
857 [self drawInRect:rect withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info]];
862 MSInstanceMessage2(void, NSString, drawInRect,withAttributes, CGRect, rect, NSDictionary *, attributes) {
863 NSLog(@"XXX: *\"%@\" %@", self, attributes);
865 WBStringDrawingState *state(stringDrawingState_);
867 return MSOldCall(rect, attributes);
869 if (state->count_ != 0 && --state->count_ == 0)
870 stringDrawingState_ = state->next_;
871 if (state->info_ == nil)
872 return MSOldCall(rect, attributes);
874 NSString *info([Info_ objectForKey:state->info_]);
876 return MSOldCall(rect, attributes);
878 NSString *base(state->base_ ?: @"");
880 UIFont *font([attributes objectForKey:@"NSFont"]);
881 UIColor *color([attributes objectForKey:@"NSColor"]);
883 [self drawInRect:rect withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], WBColorMarkup(color), base, info]];
886 extern "C" NSString *NSStringFromCGSize(CGSize size);
888 MSInstanceMessage4(CGRect, NSString, boundingRectWithSize,options,attributes,context, CGSize, size, NSInteger, options, NSDictionary *, attributes, id, context) {
889 NSLog(@"XXX: $\"%@\" %@ 0x%x %@ %@", self, NSStringFromCGSize(size), unsigned(options), attributes, context);
891 WBStringDrawingState *state(stringDrawingState_);
893 return MSOldCall(size, options, attributes, context);
895 if (state->count_ != 0 && --state->count_ == 0)
896 stringDrawingState_ = state->next_;
897 if (state->info_ == nil)
898 return MSOldCall(size, options, attributes, context);
900 NSString *info([Info_ objectForKey:state->info_]);
902 return MSOldCall(size, options, attributes, context);
904 NSString *base(state->base_ ?: @"");
906 UIFont *font([attributes objectForKey:@"NSFont"]);
907 UIColor *color([attributes objectForKey:@"NSColor"]);
909 return (CGRect) {{0, 0}, [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], WBColorMarkup(color), base, info] forWidth:size.width]};
912 MSInstanceMessage4(CGSize, NSString, sizeWithFont,forWidth,lineBreakMode,letterSpacing, UIFont *, font, CGFloat, width, UILineBreakMode, mode, CGFloat, spacing) {
913 //NSLog(@"XXX: #\"%@\" \"%@\" %g %u %g", self, font, width, mode, spacing);
915 WBStringDrawingState *state(stringDrawingState_);
917 return MSOldCall(font, width, mode, spacing);
919 if (state->count_ != 0 && --state->count_ == 0)
920 stringDrawingState_ = state->next_;
921 if (state->info_ == nil)
922 return MSOldCall(font, width, mode, spacing);
924 NSString *info([Info_ objectForKey:state->info_]);
926 return MSOldCall(font, width, mode, spacing);
928 NSString *base(state->base_ ?: @"");
929 NSString *extra([NSString stringWithFormat:@"letter-spacing: %gpx", spacing]);
930 return [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info] forWidth:width];
933 MSInstanceMessage1(CGSize, NSString, sizeWithFont, UIFont *, font) {
934 //NSLog(@"XXX: ?\"%@\"", self);
936 WBStringDrawingState *state(stringDrawingState_);
938 return MSOldCall(font);
940 if (state->count_ != 0 && --state->count_ == 0)
941 stringDrawingState_ = state->next_;
942 if (state->info_ == nil)
943 return MSOldCall(font);
945 NSString *info([Info_ objectForKey:state->info_]);
947 return MSOldCall(font);
949 NSString *base(state->base_ ?: @"");
950 return [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), base, info] forWidth:65535];
953 MSClassMessageHook2(id, SBIconBadgeView, checkoutAccessoryImagesForIcon,location, id, icon, int, location) {
954 WBStringDrawingState badgeState = {NULL, 0, @""
957 stringDrawingState_ = &badgeState;
959 id images(MSOldCall(icon, location));
961 stringDrawingState_ = NULL;
965 MSClassMessageHook2(UIImage *, SBIconAccessoryImage, checkoutAccessoryImageForIcon,location, id, icon, int, location) {
966 if ([self _imageClassForIcon:icon location:location] != $SBIconBadgeImage)
967 return MSOldCall(icon, location);
969 WBStringDrawingState badgeState = {NULL, 0, @""
972 stringDrawingState_ = &badgeState;
974 UIImage *image(MSOldCall(icon, location));
976 stringDrawingState_ = NULL;
980 MSInstanceMessageHook1(UIImage *, SBIconBadgeFactory, checkoutBadgeImageForText, NSString *, text) {
981 WBStringDrawingState badgeState = {NULL, 0, @""
984 stringDrawingState_ = &badgeState;
986 UIImage *image(MSOldCall(text));
988 stringDrawingState_ = NULL;
992 MSInstanceMessageHook1(UIImage *, SBCalendarApplicationIcon, generateIconImage, int, type) {
993 WBStringDrawingState dayState = {NULL, 2, @""
994 // XXX: this is only correct on an iPod dock
995 "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px;"
996 , @"CalendarIconDayStyle"};
998 WBStringDrawingState wtfState = {&dayState, 1, nil, nil};
1000 WBStringDrawingState sizeState = {
1001 kCFCoreFoundationVersionNumber > 800 ? &wtfState : &dayState
1004 WBStringDrawingState dateState = {&sizeState, 2, @""
1005 , @"CalendarIconDateStyle"};
1007 stringDrawingState_ = &dateState;
1009 UIImage *image(MSOldCall(type));
1011 stringDrawingState_ = NULL;
1015 MSInstanceMessageHook1(UIImage *, UIStatusBarTimeItemView, contentsImageForStyle, int, style) {
1016 WBStringDrawingState timeState = {NULL, 0, @""
1019 stringDrawingState_ = &timeState;
1021 UIImage *image(MSOldCall(style));
1023 stringDrawingState_ = NULL;
1027 MSHook(void, SBCalendarIconContentsView$drawRect$, SBCalendarIconContentsView *self, SEL sel, CGRect rect) {
1028 NSBundle *bundle([NSBundle mainBundle]);
1030 CFLocaleRef locale(CFLocaleCopyCurrent());
1031 CFDateFormatterRef formatter(CFDateFormatterCreate(NULL, locale, kCFDateFormatterNoStyle, kCFDateFormatterNoStyle));
1034 CFDateRef now(CFDateCreate(NULL, CFAbsoluteTimeGetCurrent()));
1036 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NUMBER_FORMAT" value:@"d" table:@"SpringBoard"]);
1037 CFStringRef date(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
1038 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NAME_FORMAT" value:@"cccc" table:@"SpringBoard"]);
1039 CFStringRef day(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
1043 CFRelease(formatter);
1045 NSString *datestyle([@""
1046 "font-family: Helvetica; "
1047 "font-weight: bold; "
1050 "" stringByAppendingString:(IsWild_
1051 ? @"font-size: 54px; "
1052 : @"font-size: 39px; "
1055 NSString *daystyle([@""
1056 "font-family: Helvetica; "
1057 "font-weight: bold; "
1059 "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px; "
1060 "" stringByAppendingString:(IsWild_
1061 ? @"font-size: 11px; "
1062 : @"font-size: 9px; "
1065 if (NSString *style = [Info_ objectForKey:@"CalendarIconDateStyle"])
1066 datestyle = [datestyle stringByAppendingString:style];
1067 if (NSString *style = [Info_ objectForKey:@"CalendarIconDayStyle"])
1068 daystyle = [daystyle stringByAppendingString:style];
1070 CGFloat width([self bounds].size.width);
1072 CGSize datesize = [(NSString *)date sizeWithStyle:datestyle forWidth:(width + leeway)];
1073 CGSize daysize = [(NSString *)day sizeWithStyle:daystyle forWidth:(width + leeway)];
1075 unsigned base0(IsWild_ ? 89 : 70);
1076 if ($GSFontGetUseLegacyFontMetrics())
1078 unsigned base1(IsWild_ ? 18 : 16);
1085 [(NSString *)date drawAtPoint:CGPointMake(
1086 (width + 1 - datesize.width) / 2, (base0 - datesize.height) / 2
1087 ) withStyle:datestyle];
1089 [(NSString *)day drawAtPoint:CGPointMake(
1090 (width + 1 - daysize.width) / 2, (base1 - daysize.height) / 2
1091 ) withStyle:daystyle];
1097 // %hook -[{NavigationBar,Toolbar} setBarStyle:] {{{
1098 void $setBarStyle$_(NSString *name, int &style) {
1100 NSLog(@"WB:Debug:%@Style:%d", name, style);
1101 NSNumber *number = nil;
1103 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style-%d", name, style]];
1105 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style", name]];
1106 if (number != nil) {
1107 style = [number intValue];
1109 NSLog(@"WB:Debug:%@Style=%d", name, style);
1113 MSInstanceMessageHook1(void, UIToolbar, setBarStyle, int, style) {
1114 $setBarStyle$_(@"Toolbar", style);
1115 return MSOldCall(style);
1118 MSInstanceMessageHook1(void, UINavigationBar, setBarStyle, int, style) {
1119 $setBarStyle$_(@"NavigationBar", style);
1120 return MSOldCall(style);
1124 MSHook(void, SBButtonBar$didMoveToSuperview, UIView *self, SEL sel) {
1125 [[self superview] setBackgroundColor:[UIColor clearColor]];
1126 _SBButtonBar$didMoveToSuperview(self, sel);
1129 MSHook(void, SBStatusBarContentsView$didMoveToSuperview, UIView *self, SEL sel) {
1130 [[self superview] setBackgroundColor:[UIColor clearColor]];
1131 _SBStatusBarContentsView$didMoveToSuperview(self, sel);
1134 static NSArray *Wallpapers_;
1135 static bool Papered_;
1136 static bool Docked_;
1137 static bool SMSBackgrounded_;
1138 static NSString *WallpaperFile_;
1139 static UIImageView *WallpaperImage_;
1140 static UIWebDocumentView *WallpaperPage_;
1141 static NSURL *WallpaperURL_;
1143 #define _release(object) \
1144 do if (object != nil) { \
1149 static UIImage *$getImage$(NSString *path) {
1150 UIImage *image([UIImage imageWithContentsOfFile:path]);
1152 unsigned scale($getScale$(path));
1153 if (scale != 1 && [image respondsToSelector:@selector(setScale)])
1154 [image setScale:scale];
1159 template <typename Original_, typename Modified_>
1160 _finline UIImage *WBCacheImage(const Original_ &original, const Modified_ &modified, NSString *key) {
1161 UIImage *image([Images_ objectForKey:key]);
1163 return reinterpret_cast<id>(image) == [NSNull null] ? original() : image;
1164 if (NSString *path = modified())
1165 image = $getImage$(path);
1166 [Images_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:key];
1167 return image == nil ? original() : image;
1170 static UIImage *$getDefaultDesktopImage$() {
1171 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"LockBackground.png", @"LockBackground.jpg", nil])))
1172 return $getImage$(path);
1176 MSClassMessageHook0(UIImage *, UIImage, defaultDesktopImage) {
1177 return $getDefaultDesktopImage$() ?: MSOldCall();
1180 MSInstanceMessageHook0(UIImage *, SBSlidingAlertDisplay, _defaultDesktopImage) {
1181 return $getDefaultDesktopImage$() ?: MSOldCall();
1184 MSInstanceMessageHook0(void, SBWallpaperView, resetCurrentImageToWallpaper) {
1185 for (UIView *parent([self superview]); parent != nil; parent = [parent superview])
1186 if ([parent isKindOfClass:$SBSlidingAlertDisplay]) {
1187 if (UIImage *image = $getDefaultDesktopImage$()) {
1188 [self setImage:image];
1198 // %hook -[SBUIController init] {{{
1199 MSInstanceMessageHook0(id, SBUIController, init) {
1204 NSString *paper($getTheme$(Wallpapers_));
1206 paper = [paper stringByDeletingLastPathComponent];
1210 sysctlbyname("hw.machine", NULL, &size, NULL, 0);
1211 char *machine = new char[size];
1213 if (sysctlbyname("hw.machine", machine, &size, NULL, 0) == -1) {
1214 perror("sysctlbyname(\"hw.machine\", ?)");
1219 IsWild_ = machine != NULL && strncmp(machine, "iPad", 4) == 0;
1223 NSLog(@"WB:Debug:Info = %@", [Info_ description]);
1226 UIImageView *&_wallpaperView(MSHookIvar<UIImageView *>(self, "_wallpaperView"));
1227 if (&_wallpaperView != NULL) {
1228 [_wallpaperView removeFromSuperview];
1229 [_wallpaperView release];
1230 _wallpaperView = nil;
1234 UIView *&_contentLayer(MSHookIvar<UIView *>(self, "_contentLayer"));
1235 UIView *&_contentView(MSHookIvar<UIView *>(self, "_contentView"));
1238 if (&_contentLayer != NULL)
1239 player = &_contentLayer;
1240 else if (&_contentView != NULL)
1241 player = &_contentView;
1244 UIView *layer(player == NULL ? nil : *player);
1246 UIWindow *window([[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]);
1247 UIView *content([[[UIView alloc] initWithFrame:[window frame]] autorelease]);
1248 [window setContentView:content];
1250 UIWindow *&_window(MSHookIvar<UIWindow *>(self, "_window"));
1251 [window setBackgroundColor:[_window backgroundColor]];
1252 [_window setBackgroundColor:[UIColor clearColor]];
1254 [window setLevel:-1000];
1255 [window setHidden:NO];
1257 /*if (player != NULL)
1258 *player = content;*/
1260 [content setBackgroundColor:[layer backgroundColor]];
1261 [layer setBackgroundColor:[UIColor clearColor]];
1264 if (!SummerBoard_ || !IsWild_)
1267 CGRect bounds([content bounds]);
1268 bounds.origin.y = -30;
1269 indirect = [[[UIView alloc] initWithFrame:bounds] autorelease];
1270 [content addSubview:indirect];
1271 [indirect zoomToScale:2.4];
1274 _release(WallpaperFile_);
1275 _release(WallpaperImage_);
1276 _release(WallpaperPage_);
1277 _release(WallpaperURL_);
1280 NSArray *themes([NSArray arrayWithObject:paper]);
1282 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"], themes)) {
1286 static AVController *controller_(nil);
1287 if (controller_ == nil) {
1288 AVQueue *queue([AVQueue avQueue]);
1289 controller_ = [[AVController avControllerWithQueue:queue error:&error] retain];
1292 AVQueue *queue([controller_ queue]);
1294 UIView *video([[[UIView alloc] initWithFrame:[indirect bounds]] autorelease]);
1295 [controller_ setLayer:[video _layer]];
1297 AVItem *item([[[AVItem alloc] initWithPath:path error:&error] autorelease]);
1298 [queue appendItem:item error:&error];
1300 [controller_ play:&error];
1301 #elif UseMPMoviePlayerController
1302 NSURL *url([NSURL fileURLWithPath:path]);
1303 MPMoviePlayerController *controller = [[$MPMoviePlayerController alloc] initWithContentURL:url];
1304 controller.movieControlMode = MPMovieControlModeHidden;
1307 MPVideoView *video = [[[$MPVideoView alloc] initWithFrame:[indirect bounds]] autorelease];
1308 [video setMovieWithPath:path];
1309 [video setRepeatMode:1];
1310 [video setRepeatGap:-1];
1311 [video playFromBeginning];;
1314 [indirect addSubview:video];
1317 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"Wallpaper.png", @"Wallpaper.jpg", nil]), themes)) {
1318 if (UIImage *image = $getImage$(path)) {
1319 WallpaperFile_ = [path retain];
1320 WallpaperImage_ = [[UIImageView alloc] initWithImage:image];
1321 if (NSNumber *number = [Info_ objectForKey:@"WallpaperAlpha"])
1322 [WallpaperImage_ setAlpha:[number floatValue]];
1323 [indirect addSubview:WallpaperImage_];
1327 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.html"], themes)) {
1328 CGRect bounds = [indirect bounds];
1330 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1331 [view setAutoresizes:true];
1333 WallpaperPage_ = [view retain];
1334 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
1336 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1338 [view setBackgroundColor:[UIColor clearColor]];
1339 if ([view respondsToSelector:@selector(setDrawsBackground:)])
1340 [view setDrawsBackground:NO];
1341 [[view webView] setDrawsBackground:NO];
1343 [indirect addSubview:view];
1347 for (size_t i(0), e([Themes_ count]); i != e; ++i) {
1348 NSString *theme = [Themes_ objectAtIndex:(e - i - 1)];
1349 NSString *html = [theme stringByAppendingPathComponent:@"Widget.html"];
1350 if ([Manager_ fileExistsAtPath:html]) {
1351 CGRect bounds = [indirect bounds];
1353 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1354 [view setAutoresizes:true];
1356 NSURL *url = [NSURL fileURLWithPath:html];
1357 [view loadRequest:[NSURLRequest requestWithURL:url]];
1359 [view setBackgroundColor:[UIColor clearColor]];
1360 if ([view respondsToSelector:@selector(setDrawsBackground:)])
1361 [view setDrawsBackground:NO];
1362 [[view webView] setDrawsBackground:NO];
1364 [indirect addSubview:view];
1372 MSHook(void, SBAwayView$updateDesktopImage$, SBAwayView *self, SEL sel, UIImage *image) {
1373 NSString *path = $getTheme$([NSArray arrayWithObject:@"LockBackground.html"]);
1374 UIView *&_backgroundView(MSHookIvar<UIView *>(self, "_backgroundView"));
1376 if (path != nil && _backgroundView != nil)
1379 _SBAwayView$updateDesktopImage$(self, sel, image);
1382 CGRect bounds = [self bounds];
1384 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1385 [view setAutoresizes:true];
1387 if (WallpaperPage_ != nil)
1388 [WallpaperPage_ release];
1389 WallpaperPage_ = [view retain];
1391 if (WallpaperURL_ != nil)
1392 [WallpaperURL_ release];
1393 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
1395 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1397 [[view webView] setDrawsBackground:false];
1398 [view setBackgroundColor:[UIColor clearColor]];
1400 [self insertSubview:view aboveSubview:_backgroundView];
1402 if ($objc_setAssociatedObject != NULL)
1403 $objc_setAssociatedObject(self, @selector(wb$widgetView), view, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1407 MSHook(void, SBAwayView$_addSubview$positioned$relativeTo$, SBAwayView *self, SEL sel, UIView *view, int positioned, UIView *relative) {
1408 UIView *&_backgroundView(MSHookIvar<UIView *>(self, "_backgroundView"));
1409 UIView *&_chargingView(MSHookIvar<UIView *>(self, "_chargingView"));
1410 if (&_chargingView != NULL)
1411 if (positioned == -2 && (relative == _backgroundView && _chargingView == nil || relative == _chargingView))
1412 if ($objc_getAssociatedObject != NULL)
1413 if (UIView *widget = $objc_getAssociatedObject(self, @selector(wb$widgetView)))
1415 return _SBAwayView$_addSubview$positioned$relativeTo$(self, sel, view, positioned, relative);
1418 /*extern "C" CGColorRef CGGStateGetSystemColor(void *);
1419 extern "C" CGColorRef CGGStateGetFillColor(void *);
1420 extern "C" CGColorRef CGGStateGetStrokeColor(void *);
1421 extern "C" NSString *UIStyleStringFromColor(CGColorRef);*/
1423 /* WBTimeLabel {{{ */
1424 @interface WBTimeLabel : NSProxy {
1426 _transient SBStatusBarTimeView *view_;
1429 - (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view;
1433 @implementation WBTimeLabel
1440 - (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view {
1441 time_ = [time retain];
1446 - (NSString *) description {
1452 - (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(UILineBreakMode)mode {
1453 if (NSString *custom = [Info_ objectForKey:@"TimeStyle"]) {
1454 BOOL &_mode(MSHookIvar<BOOL>(view_, "_mode"));;
1456 [time_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1457 "font-family: Helvetica; "
1458 "font-weight: bold; "
1461 "%@", _mode ? @"white" : @"black", custom]];
1466 return [time_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1471 /* WBBadgeLabel {{{ */
1472 @interface WBBadgeLabel : NSProxy {
1476 - (id) initWithBadge:(NSString *)badge;
1477 - (NSString *) description;
1481 @implementation WBBadgeLabel
1488 - (id) initWithBadge:(NSString *)badge {
1489 badge_ = [badge retain];
1493 - (NSString *) description {
1494 return [badge_ description];
1499 - (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(UILineBreakMode)mode {
1500 if (NSString *custom = [Info_ objectForKey:@"BadgeStyle"]) {
1501 [badge_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1502 "font-family: Helvetica; "
1503 "font-weight: bold; "
1511 return [badge_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1518 MSInstanceMessageHook1(void, SBIcon, setIconImageAlpha, CGFloat, alpha) {
1519 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1520 alpha = [number floatValue];
1521 return MSOldCall(alpha);
1524 MSInstanceMessageHook1(void, SBIcon, setIconLabelAlpha, CGFloat, alpha) {
1525 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1526 alpha = [number floatValue];
1527 return MSOldCall(alpha);
1530 MSInstanceMessageHook0(id, SBIcon, initWithDefaultSize) {
1531 if ((self = MSOldCall()) != nil) {
1532 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"]) {
1533 // XXX: note: this is overridden above, which is silly
1534 float alpha([number floatValue]);
1535 if ([self respondsToSelector:@selector(setIconImageAlpha:)])
1536 [self setIconImageAlpha:alpha];
1537 if ([self respondsToSelector:@selector(setIconLabelAlpha:)])
1538 [self setIconLabelAlpha:alpha];
1539 if ([self respondsToSelector:@selector(setAlpha:)])
1540 [self setAlpha:alpha];
1545 MSInstanceMessageHook1(void, SBIcon, setAlpha, CGFloat, alpha) {
1546 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1547 alpha = [number floatValue];
1548 return MSOldCall(alpha);
1552 MSHook(id, SBIconBadge$initWithBadge$, SBIconBadge *self, SEL sel, NSString *badge) {
1553 if ((self = _SBIconBadge$initWithBadge$(self, sel, badge)) != nil) {
1554 id &_badge(MSHookIvar<id>(self, "_badge"));
1556 if (id label = [[WBBadgeLabel alloc] initWithBadge:[_badge autorelease]])
1561 void SBStatusBarController$setStatusBarMode(int &mode) {
1563 NSLog(@"WB:Debug:setStatusBarMode:%d", mode);
1564 if (mode < 100) // 104:hidden 105:glowing
1565 if (NSNumber *number = [Info_ objectForKey:@"StatusBarMode"])
1566 mode = [number intValue];
1569 /*MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, double duration, int animation) {
1570 NSLog(@"mode:%d orientation:%d duration:%f animation:%d", mode, orientation, duration, animation);
1571 SBStatusBarController$setStatusBarMode(mode);
1572 return _SBStatusBarController$setStatusBarMode$orientation$duration$animation$(self, sel, mode, orientation, duration, animation);
1575 MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, float duration, int fenceID, int animation) {
1576 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d", mode, orientation, duration, fenceID, animation);
1577 SBStatusBarController$setStatusBarMode(mode);
1578 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$(self, sel, mode, orientation, duration, fenceID, animation);
1581 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) {
1582 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d startTime:%f", mode, orientation, duration, fenceID, animation, startTime);
1583 SBStatusBarController$setStatusBarMode(mode);
1584 //NSLog(@"mode=%u", mode);
1585 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$startTime$(self, sel, mode, orientation, duration, fenceID, animation, startTime);
1588 /*MSHook(id, SBStatusBarContentsView$initWithStatusBar$mode$, SBStatusBarContentsView *self, SEL sel, id bar, int mode) {
1589 if (NSNumber *number = [Info_ objectForKey:@"StatusBarContentsMode"])
1590 mode = [number intValue];
1591 return _SBStatusBarContentsView$initWithStatusBar$mode$(self, sel, bar, mode);
1594 MSHook(NSString *, SBStatusBarOperatorNameView$operatorNameStyle, SBStatusBarOperatorNameView *self, SEL sel) {
1595 NSString *style(_SBStatusBarOperatorNameView$operatorNameStyle(self, sel));
1597 NSLog(@"operatorNameStyle= %@", style);
1598 if (NSString *custom = [Info_ objectForKey:@"OperatorNameStyle"])
1599 style = [NSString stringWithFormat:@"%@; %@", style, custom];
1603 MSHook(void, SBStatusBarOperatorNameView$setOperatorName$fullSize$, SBStatusBarOperatorNameView *self, SEL sel, NSString *name, BOOL full) {
1605 NSLog(@"setOperatorName:\"%@\" fullSize:%u", name, full);
1606 return _SBStatusBarOperatorNameView$setOperatorName$fullSize$(self, sel, name, NO);
1609 // XXX: replace this with [SBStatusBarTimeView tile]
1610 MSHook(void, SBStatusBarTimeView$drawRect$, SBStatusBarTimeView *self, SEL sel, CGRect rect) {
1611 id &_time(MSHookIvar<id>(self, "_time"));
1612 if (_time != nil && [_time class] != [WBTimeLabel class])
1613 object_setInstanceVariable(self, "_time", reinterpret_cast<void *>([[WBTimeLabel alloc] initWithTime:[_time autorelease] view:self]));
1614 return _SBStatusBarTimeView$drawRect$(self, sel, rect);
1617 @interface UIView (WinterBoard)
1618 - (bool) wb$isWBImageView;
1619 - (void) wb$logHierarchy;
1620 - (void) wb$setBackgroundColor:(UIColor *)color;
1623 @implementation UIView (WinterBoard)
1625 - (bool) wb$isWBImageView {
1629 - (void) wb$logHierarchy {
1630 WBLogHierarchy(self);
1633 - (void) wb$setBackgroundColor:(UIColor *)color {
1634 [self setBackgroundColor:color];
1635 for (UIView *child in [self subviews])
1636 [child wb$setBackgroundColor:color];
1641 @interface WBImageView : UIImageView {
1644 - (bool) wb$isWBImageView;
1645 - (void) wb$updateFrame;
1648 @implementation WBImageView
1650 - (bool) wb$isWBImageView {
1654 - (void) wb$updateFrame {
1655 CGRect frame([self frame]);
1658 for (UIView *view(self); ; ) {
1659 view = [view superview];
1662 frame.origin.y -= [view frame].origin.y;
1665 [self setFrame:frame];
1670 static void SBIconList$updateFrames$(SBIconList *self) {
1671 NSArray *subviews([self subviews]);
1672 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1673 if (view != nil && [view wb$isWBImageView])
1674 [view wb$updateFrame];
1677 MSHook(void, SBIconList$didMoveToSuperview, SBIconList *self, SEL sel) {
1678 SBIconList$updateFrames$(self);
1679 _SBIconList$didMoveToSuperview(self, sel);
1682 MSHook(void, SBIconList$setFrame$, SBIconList *self, SEL sel, CGRect frame) {
1683 SBIconList$updateFrames$(self);
1684 _SBIconList$setFrame$(self, sel, frame);
1687 static void $addPerPageView$(unsigned i, UIView *list) {
1688 NSString *path($getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Page%u.png", i]]));
1692 NSArray *subviews([list subviews]);
1694 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1695 if (view == nil || ![view wb$isWBImageView]) {
1696 view = [[[WBImageView alloc] init] autorelease];
1697 [list insertSubview:view atIndex:0];
1700 UIImage *image([UIImage imageWithContentsOfFile:path]);
1702 CGRect frame([view frame]);
1703 frame.size = [image size];
1704 [view setFrame:frame];
1706 [view setImage:image];
1707 [view wb$updateFrame];
1710 static void $addPerPageViews$(NSArray *lists) {
1711 for (unsigned i(0), e([lists count]); i != e; ++i)
1712 $addPerPageView$(i, [lists objectAtIndex:i]);
1715 MSInstanceMessageHook0(void, SBIconController, updateNumberOfRootIconLists) {
1716 NSArray *&_rootIconLists(MSHookIvar<NSArray *>(self, "_rootIconLists"));
1717 $addPerPageViews$(_rootIconLists);
1721 MSInstanceMessageHook0(void, SBIconContentView, layoutSubviews) {
1724 if (SBIconController *controller = [$SBIconController sharedInstance]) {
1725 UIView *&_dockContainerView(MSHookIvar<UIView *>(controller, "_dockContainerView"));
1726 if (&_dockContainerView != NULL)
1727 [[_dockContainerView superview] bringSubviewToFront:_dockContainerView];
1731 MSHook(void, SBIconController$noteNumberOfIconListsChanged, SBIconController *self, SEL sel) {
1732 SBIconModel *&_iconModel(MSHookIvar<SBIconModel *>(self, "_iconModel"));
1733 $addPerPageViews$([_iconModel iconLists]);
1734 return _SBIconController$noteNumberOfIconListsChanged(self, sel);
1737 MSHook(id, SBIconLabel$initWithSize$label$, SBIconLabel *self, SEL sel, CGSize size, NSString *label) {
1738 self = _SBIconLabel$initWithSize$label$(self, sel, size, label);
1740 [self setClipsToBounds:NO];
1744 MSHook(void, SBIconLabel$setInDock$, SBIconLabel *self, SEL sel, BOOL docked) {
1745 static bool gssc(false);
1747 BOOL (*GSSystemHasCapability)(CFStringRef) = reinterpret_cast<BOOL (*)(CFStringRef)>(dlsym(RTLD_DEFAULT, "GSSystemHasCapability"));
1748 Papered_ |= GSSystemHasCapability != NULL && GSSystemHasCapability(CFSTR("homescreen-wallpaper"));
1751 if ([Info_ objectForKey:@"UndockedIconLabels"] == nil)
1752 [Info_ setObject:[NSNumber numberWithBool:(
1754 [Info_ objectForKey:@"DockedIconLabelStyle"] != nil ||
1755 [Info_ objectForKey:@"UndockedIconLabelStyle"] != nil
1756 )] forKey:@"UndockedIconLabels"];
1759 id &_label(MSHookIvar<id>(self, "_label"));
1760 if (![Info_ wb$boolForKey:@"UndockedIconLabels"])
1763 if (_label != nil && [_label respondsToSelector:@selector(setInDock:)])
1764 [_label setInDock:docked];
1766 _SBIconLabel$setInDock$(self, sel, docked);
1767 [self setNeedsDisplay];
1770 MSHook(BOOL, SBDockIconListView$shouldShowNewDock, id self, SEL sel) {
1771 return SummerBoard_ && Docked_ ? NO : _SBDockIconListView$shouldShowNewDock(self, sel);
1774 MSHook(void, SBDockIconListView$setFrame$, id self, SEL sel, CGRect frame) {
1775 _SBDockIconListView$setFrame$(self, sel, frame);
1778 // %hook -[NSBundle localizedStringForKey:value:table:] {{{
1779 MSInstanceMessageHook3(NSString *, NSBundle, localizedStringForKey,value,table, NSString *, key, NSString *, value, NSString *, table) {
1780 NSString *identifier = [self bundleIdentifier];
1781 NSLocale *locale = [NSLocale currentLocale];
1782 NSString *language = [locale objectForKey:NSLocaleLanguageCode];
1784 NSLog(@"WB:Debug:[NSBundle(%@) localizedStringForKey:\"%@\" value:\"%@\" table:\"%@\"] (%@)", identifier, key, value, table, language);
1785 NSString *file = table == nil ? @"Localizable" : table;
1786 NSString *name = [NSString stringWithFormat:@"%@:%@", identifier, file];
1787 NSDictionary *strings;
1788 if ((strings = [Strings_ objectForKey:name]) != nil) {
1789 if (static_cast<id>(strings) != [NSNull null]) strings:
1790 if (NSString *value = [strings objectForKey:key])
1792 } else if (NSString *path = $pathForFile$inBundle$([NSString stringWithFormat:@"%@.lproj/%@.strings",
1794 ], self, false, false)) {
1795 if ((strings = [[NSDictionary alloc] initWithContentsOfFile:path]) != nil) {
1796 [Strings_ setObject:[strings autorelease] forKey:name];
1800 [Strings_ setObject:[NSNull null] forKey:name];
1801 return MSOldCall(key, value, table);
1804 // %hook -[WebCoreFrameBridge renderedSizeOfNode:constrainedToWidth:] {{{
1805 MSClassHook(WebCoreFrameBridge)
1807 MSInstanceMessageHook2(CGSize, WebCoreFrameBridge, renderedSizeOfNode,constrainedToWidth, id, node, float, width) {
1810 void **core(reinterpret_cast<void **>([node _node]));
1811 if (core == NULL || core[6] == NULL)
1813 return MSOldCall(node, width);
1817 MSInstanceMessage1(void, SBIconLabel, drawRect, CGRect, rect) {
1818 static Ivar drawMoreLegibly = object_getInstanceVariable(self, "_drawMoreLegibly", NULL);
1821 Ivar ivar = object_getInstanceVariable(self, "_inDock", reinterpret_cast<void **>(&docked));
1822 docked = (docked & (ivar_getOffset(ivar) == ivar_getOffset(drawMoreLegibly) ? 0x2 : 0x1)) != 0;
1824 NSString *label(MSHookIvar<NSString *>(self, "_label"));
1826 NSString *style = [NSString stringWithFormat:@""
1827 "font-family: Helvetica; "
1828 "font-weight: bold; "
1830 "", (docked || !SummerBoard_ ? @"white" : @"#b3b3b3"), (IsWild_
1831 ? @"font-size: 12px; "
1832 : @"font-size: 11px; "
1836 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px 1px 0px; "];
1838 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px -1px 0px; "];
1840 NSString *custom([Info_ objectForKey:(docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle")]);
1842 $drawLabel$(label, [self bounds], style, custom);
1845 MSInstanceMessage0(CGImageRef, SBIconLabel, buildLabelImage) {
1846 bool docked((MSHookIvar<unsigned>(self, "_inDock") & 0x2) != 0);
1848 WBStringDrawingState labelState = {NULL, 0, @""
1849 , docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle"};
1851 stringDrawingState_ = &labelState;
1854 CGImageRef image(MSOldCall());
1857 stringDrawingState_ = NULL;
1861 static bool wb$inDock(id parameters) {
1862 return [$objc_getAssociatedObject(parameters, @selector(wb$inDock)) boolValue];
1865 MSInstanceMessage0(NSUInteger, SBIconLabelImageParameters, hash) {
1866 return MSOldCall() + (wb$inDock(self) ? 0xdeadbeef : 0xd15ea5e);
1869 MSClassMessage2(id, SBIconView, _labelImageParametersForIcon,location, id, icon, int, location) {
1870 if (id parameters = MSOldCall(icon, location)) {
1871 $objc_setAssociatedObject(parameters, @selector(wb$inDock), [NSNumber numberWithBool:(location == 1)], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1876 MSInstanceMessage0(id, SBIconView, _labelImageParameters) {
1877 if (id parameters = MSOldCall()) {
1878 int &location(MSHookIvar<int>(self, "_iconLocation"));
1879 if (&location != NULL)
1880 $objc_setAssociatedObject(parameters, @selector(wb$inDock), [NSNumber numberWithBool:(location == 3)], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1885 MSClassMessage1(UIImage *, SBIconLabelImage, _drawLabelImageForParameters, id, parameters) {
1886 bool docked(wb$inDock(parameters));
1888 WBStringDrawingState labelState = {NULL, 0, @""
1889 , docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle"};
1891 stringDrawingState_ = &labelState;
1894 UIImage *image(MSOldCall(parameters));
1897 stringDrawingState_ = NULL;
1902 MSInstanceMessageHook2(id, CKBalloonView, initWithFrame,delegate, CGRect, frame, id, delegate) {
1903 if ((self = MSOldCall(frame, delegate)) != nil) {
1904 [self setBackgroundColor:[UIColor clearColor]];
1908 MSInstanceMessageHook0(BOOL, CKBalloonView, _canUseLayerBackedBalloon) {
1909 return SMSBackgrounded_ ? NO : MSOldCall();
1912 MSInstanceMessageHook0(void, CKTranscriptHeaderView, layoutSubviews) {
1913 [self wb$setBackgroundColor:[UIColor clearColor]];
1917 MSInstanceMessageHook1(void, CKMessageCell, addBalloonView, CKBalloonView *, balloon) {
1919 [balloon setBackgroundColor:[UIColor clearColor]];
1922 MSInstanceMessageHook1(void, CKTranscriptCell, setBackgroundColor, UIColor *, color) {
1923 MSOldCall([UIColor clearColor]);
1924 [[self contentView] wb$setBackgroundColor:[UIColor clearColor]];
1928 MSInstanceMessageHook2(id, CKTranscriptCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1929 if ((self = MSOldCall(style, reuse)) != nil) {
1930 [self setBackgroundColor:[UIColor clearColor]];
1931 [[self contentView] wb$setBackgroundColor:[UIColor clearColor]];
1936 MSInstanceMessageHook2(id, CKMessageCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1937 if ((self = MSOldCall(style, reuse)) != nil) {
1938 [self setBackgroundColor:[UIColor clearColor]];
1939 [[self contentView] setBackgroundColor:[UIColor clearColor]];
1943 MSInstanceMessageHook2(id, CKTimestampView, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1944 if ((self = MSOldCall(style, reuse)) != nil) {
1945 UILabel *&_label(MSHookIvar<UILabel *>(self, "_label"));
1946 [_label setBackgroundColor:[UIColor clearColor]];
1950 MSInstanceMessageHook1(void, CKTranscriptTableView, setSeparatorStyle, int, style) {
1951 MSOldCall(UITableViewCellSeparatorStyleNone);
1954 MSInstanceMessageHook2(id, CKTranscriptTableView, initWithFrame,style, CGRect, frame, int, style) {
1955 if ((self = MSOldCall(frame, style)) != nil) {
1956 [self setSeparatorStyle:UITableViewCellSeparatorStyleNone];
1960 MSInstanceMessageHook0(void, CKTranscriptController, loadView) {
1963 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"SMSBackground.png", @"SMSBackground.jpg", nil])))
1964 if (UIImage *image = $getImage$(path)) {
1965 SMSBackgrounded_ = true;
1967 UIView *&_transcriptTable(MSHookIvar<UIView *>(self, "_transcriptTable"));
1968 UIView *&_transcriptLayer(MSHookIvar<UIView *>(self, "_transcriptLayer"));
1970 if (&_transcriptTable != NULL)
1971 table = _transcriptTable;
1972 else if (&_transcriptLayer != NULL)
1973 table = _transcriptLayer;
1977 UIView *placard(table != nil ? [table superview] : MSHookIvar<UIView *>(self, "_backPlacard"));
1978 UIImageView *background([[[UIImageView alloc] initWithImage:image] autorelease]);
1981 [placard insertSubview:background atIndex:0];
1983 [table setBackgroundColor:[UIColor clearColor]];
1984 [placard insertSubview:background belowSubview:table];
1990 template <typename Original_>
1991 static UIImage *WBCacheUIImage(const Original_ &original, NSString *name, NSString *key) {
1992 if ([name rangeOfString:@"."].location == NSNotFound)
1993 name = [name stringByAppendingString:@".png"];
1994 UIImage *image(WBCacheImage(original, [=](){ return $pathForFile$inBundle$(name, _UIKitBundle(), true, true); }, key));
1995 if (image != nil && UIDebug_) {
1996 NSString *path([@"/tmp/UIImages/" stringByAppendingString:name]);
1997 if (![Manager_ fileExistsAtPath:path])
1998 [UIImagePNGRepresentation(image) writeToFile:path atomically:YES];
2002 // %hook _UIImageWithName() {{{
2003 MSHook(UIImage *, _UIImageWithName, NSString *name) {
2007 NSLog(@"WB:Debug: _UIImageWithName(\"%@\")", name);
2008 return WBCacheUIImage(
2009 [=](){ return __UIImageWithName(name); },
2010 name, [NSString stringWithFormat:@"I:%@", name]);
2013 // %hook _UIImageWithNameInDomain() {{{
2014 MSHook(UIImage *, _UIImageWithNameInDomain, NSString *name, NSString *domain) {
2016 NSLog(@"WB:Debug: _UIImageWithNameInDomain(\"%@\", \"%@\")", name, domain);
2017 return WBCacheImage(
2018 [=](){ return __UIImageWithNameInDomain(name, domain); },
2019 [=](){ return $getTheme$($useScale$([NSArray arrayWithObject:[NSString stringWithFormat:@"Domains/%@/%@", domain, name]])); },
2020 [NSString stringWithFormat:@"D:%zu:%@%@", size_t([domain length]), domain, name]);
2023 // %hook _UIImageWithDeviceUsingCurrentIdiom() {{{
2024 MSHook(UIImage *, _UIImageWithNameUsingCurrentIdiom, NSString *name) {
2026 NSLog(@"WB:Debug: _UIImageWithNameUsingCurrentIdiom(\"%@\")", name);
2027 return WBCacheUIImage(
2028 [=](){ return __UIImageWithNameUsingCurrentIdiom(name); },
2029 name, [NSString stringWithFormat:@"I:%@", name]);
2032 // %hook _UIImageWithDeviceSpecificName() {{{
2033 MSHook(UIImage *, _UIImageWithDeviceSpecificName, NSString *name) {
2035 NSLog(@"WB:Debug: _UIImageWithDeviceSpecificName(\"%@\")", name);
2036 return WBCacheUIImage(
2037 [=](){ return __UIImageWithDeviceSpecificName(name); },
2038 name, [NSString stringWithFormat:@"S:%@", name]);
2042 // %hook GSFontCreateWithName() {{{
2043 MSHook(GSFontRef, GSFontCreateWithName, const char *name, GSFontSymbolicTraits traits, float size) {
2045 NSLog(@"WB:Debug: GSFontCreateWithName(\"%s\", %f)", name, size);
2046 if (NSString *font = [Info_ objectForKey:[NSString stringWithFormat:@"FontName-%s", name]])
2047 name = [font UTF8String];
2048 //if (NSString *scale = [Info_ objectForKey:[NSString stringWithFormat:@"FontScale-%s", name]])
2049 // size *= [scale floatValue];
2050 return _GSFontCreateWithName(name, traits, size);
2054 #define AudioToolbox "/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox"
2056 static bool GetFileNameForThisAction$(bool value, unsigned long a0, char *a1, unsigned long a2, bool &a3) {
2058 NSLog(@"WB:Debug:GetFileNameForThisAction(%lu, %s, %lu, %u) = %u", a0, value ? a1 : NULL, a2, a3, value);
2061 NSString *path = [NSString stringWithUTF8String:a1];
2062 if ([path hasPrefix:@"/System/Library/Audio/UISounds/"]) {
2063 NSString *file = [path substringFromIndex:31];
2064 for (NSString *theme in Themes_) {
2065 NSString *path([NSString stringWithFormat:@"%@/UISounds/%@", theme, file]);
2066 if ([Manager_ fileExistsAtPath:path]) {
2067 strcpy(a1, [path UTF8String]);
2076 MSHook(bool, _Z24GetFileNameForThisActionmPcRb, unsigned long a0, char *a1, bool &a3) {
2077 bool value(__Z24GetFileNameForThisActionmPcRb(a0, a1, a3));
2078 return GetFileNameForThisAction$(value, a0, a1, 0, a3);
2081 MSHook(bool, _Z24GetFileNameForThisActionmPcmRb, unsigned long a0, char *a1, unsigned long a2, bool &a3) {
2082 bool value(__Z24GetFileNameForThisActionmPcmRb(a0, a1, a2, a3));
2083 return GetFileNameForThisAction$(value, a0, a1, a2, a3);
2086 static void ChangeWallpaper(
2087 CFNotificationCenterRef center,
2091 CFDictionaryRef info
2094 NSLog(@"WB:Debug:ChangeWallpaper!");
2097 if (WallpaperFile_ != nil) {
2098 image = [[UIImage alloc] initWithContentsOfFile:WallpaperFile_];
2100 image = [image autorelease];
2103 if (WallpaperImage_ != nil)
2104 [WallpaperImage_ setImage:image];
2105 if (WallpaperPage_ != nil)
2106 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
2110 MSHook(NSArray *, CPBitmapCreateImagesFromPath, NSString *path, NSDictionary **names, void *arg2, void *arg3) {
2111 NSArray *images(_CPBitmapCreateImagesFromPath(path, names, arg2, arg3));
2112 if (images != NULL && *names != nil && CFGetTypeID((CFTypeRef) *names) == CFDictionaryGetTypeID()) {
2113 if (NSBundle *bundle = [NSBundle wb$bundleWithFile:path]) {
2114 NSMutableArray *copy([images mutableCopy]);
2118 NSString *file([path stringByResolvingSymlinksInPath]);
2119 NSString *prefix([[bundle bundlePath] stringByResolvingSymlinksInPath]);
2120 if ([file hasPrefix:prefix]) {
2121 NSUInteger length([prefix length]);
2122 if (length != [file length]) {
2123 NSEnumerator *enumerator([*names keyEnumerator]);
2124 while (NSString *name = [enumerator nextObject]) {
2125 NSString *png([name stringByAppendingString:@".png"]);
2126 if (NSString *themed = $pathForFile$inBundle$(png, bundle, false, true)) {
2127 NSUInteger index([[*names objectForKey:name] intValue]);
2128 UIImage *image($getImage$(themed));
2129 CGImageRef cg([image CGImage]);
2130 [copy replaceObjectAtIndex:index withObject:(id)cg];
2139 MSHook(void, BKSDisplayServicesSetSystemAppExitedImagePath, NSString *path) {
2140 if (NSString *themed = $getTheme$($useScale$([NSArray arrayWithObject:@"SystemAppExited.png"])))
2142 _BKSDisplayServicesSetSystemAppExitedImagePath(path);
2145 #define WBRename(name, sel, imp) \
2146 MSHookMessage($ ## name, @selector(sel), &$ ## name ## $ ## imp, &_ ## name ## $ ## imp)
2148 template <typename Type_>
2149 static void msset(Type_ &function, MSImageRef image, const char *name) {
2150 function = reinterpret_cast<Type_>(MSFindSymbol(image, name));
2153 #define WBHookSymbol(image, function) \
2154 msset(function, image, "_" #function)
2156 template <typename Type_>
2157 static void dlset(Type_ &function, const char *name) {
2158 function = reinterpret_cast<Type_>(dlsym(RTLD_DEFAULT, name));
2161 // %hook CGImageReadCreateWithFile() {{{
2162 MSHook(void *, CGImageReadCreateWithFile, NSString *path, int flag) {
2164 NSLog(@"WB:Debug: CGImageReadCreateWithFile(%@, %d)", path, flag);
2165 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2166 void *value(_CGImageReadCreateWithFile([path wb$themedPath], flag));
2171 MSHook(void *, CGImageSourceCreateWithFile, NSString *path, NSDictionary *options) {
2173 NSLog(@"WB:Debug: CGImageSourceCreateWithFile(%@, %@)", path, options);
2174 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2175 void *value(_CGImageSourceCreateWithFile([path wb$themedPath], options));
2180 MSHook(void *, CGImageSourceCreateWithURL, NSURL *url, NSDictionary *options) {
2182 NSLog(@"WB:Debug: CGImageSourceCreateWithURL(%@, %@)", url, options);
2183 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2184 if ([url isFileURL])
2185 url = [NSURL fileURLWithPath:[[url path] wb$themedPath]];
2186 void *value(_CGImageSourceCreateWithURL(url, options));
2192 static void NSString$drawAtPoint$withStyle$(NSString *self, SEL _cmd, CGPoint point, NSString *style) {
2193 WKSetCurrentGraphicsContext(UIGraphicsGetCurrentContext());
2194 if (style == nil || [style length] == 0)
2195 style = @"font-family: Helvetica; font-size: 12px";
2196 //NSLog(@"XXX:drawP(%@ | %@)", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "]);
2197 [[WBMarkup sharedMarkup] drawString:self atPoint:point withStyle:style];
2200 static void NSString$drawInRect$withStyle$(NSString *self, SEL _cmd, CGRect rect, NSString *style) {
2201 WKSetCurrentGraphicsContext(UIGraphicsGetCurrentContext());
2202 if (style == nil || [style length] == 0)
2203 style = @"font-family: Helvetica; font-size: 12px";
2204 //NSLog(@"XXX:drawR(%@ | %@)", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "]);
2205 return [[WBMarkup sharedMarkup] drawString:self inRect:rect withStyle:style];
2208 static CGSize NSString$sizeWithStyle$forWidth$(NSString *self, SEL _cmd, NSString *style, CGFloat width) {
2209 if (style == nil || [style length] == 0)
2210 style = @"font-family: Helvetica; font-size: 12px";
2211 CGSize size([[WBMarkup sharedMarkup] sizeOfString:self withStyle:style forWidth:width]);
2212 //NSLog(@"XXX:size(%@ | %@) = [%g %g]", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "], size.width, size.height);
2216 static void SBInitialize() {
2218 WBRename(SBApplication, pathForIcon, pathForIcon);
2219 WBRename(SBApplicationIcon, icon, icon);
2220 WBRename(SBApplicationIcon, generateIconImage:, generateIconImage$);
2223 WBRename(SBBookmarkIcon, icon, icon);
2224 WBRename(SBButtonBar, didMoveToSuperview, didMoveToSuperview);
2225 WBRename(SBCalendarIconContentsView, drawRect:, drawRect$);
2226 WBRename(SBIconBadge, initWithBadge:, initWithBadge$);
2227 WBRename(SBIconController, noteNumberOfIconListsChanged, noteNumberOfIconListsChanged);
2229 WBRename(SBWidgetApplicationIcon, icon, icon);
2231 WBRename(SBDockIconListView, setFrame:, setFrame$);
2232 MSHookMessage(object_getClass($SBDockIconListView), @selector(shouldShowNewDock), &$SBDockIconListView$shouldShowNewDock, &_SBDockIconListView$shouldShowNewDock);
2234 if (kCFCoreFoundationVersionNumber < 600 || SummerBoard_)
2235 WBRename(SBIconLabel, drawRect:, drawRect$);
2236 else if (kCFCoreFoundationVersionNumber < 700) {
2237 WBRename(SBIconLabel, buildLabelImage, buildLabelImage);
2239 WBRename(SBIconLabelImageParameters, hash, hash);
2240 WBRename($SBIconView, _labelImageParametersForIcon:location:, _labelImageParametersForIcon$location$);
2241 WBRename(SBIconView, _labelImageParameters, _labelImageParameters);
2242 WBRename($SBIconLabelImage, _drawLabelImageForParameters:, _drawLabelImageForParameters$);
2245 WBRename(SBIconLabel, initWithSize:label:, initWithSize$label$);
2246 WBRename(SBIconLabel, setInDock:, setInDock$);
2248 WBRename(SBIconList, didMoveToSuperview, didMoveToSuperview);
2249 WBRename(SBIconList, setFrame:, setFrame$);
2251 WBRename(SBIconModel, cacheImageForIcon:, cacheImageForIcon$);
2252 WBRename(SBIconModel, cacheImagesForIcon:, cacheImagesForIcon$);
2253 WBRename(SBIconModel, getCachedImagedForIcon:, getCachedImagedForIcon$);
2254 WBRename(SBIconModel, getCachedImagedForIcon:smallIcon:, getCachedImagedForIcon$smallIcon$);
2256 if (kCFCoreFoundationVersionNumber < 800) {
2257 WBRename(SBSearchView, initWithFrame:, initWithFrame$);
2258 WBRename(SBSearchTableViewCell, drawRect:, drawRect$);
2259 WBRename(SBSearchTableViewCell, initWithStyle:reuseIdentifier:, initWithStyle$reuseIdentifier$);
2262 //WBRename(SBImageCache, initWithName:forImageWidth:imageHeight:initialCapacity:, initWithName$forImageWidth$imageHeight$initialCapacity$);
2264 WBRename(SBAwayView, updateDesktopImage:, updateDesktopImage$);
2265 if (kCFCoreFoundationVersionNumber >= 700)
2266 WBRename(SBAwayView, _addSubview:positioned:relativeTo:, _addSubview$positioned$relativeTo$);
2268 WBRename(SBStatusBarContentsView, didMoveToSuperview, didMoveToSuperview);
2269 //WBRename(SBStatusBarContentsView, initWithStatusBar:mode:, initWithStatusBar$mode$);
2270 //WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:animation:, setStatusBarMode$orientation$duration$animation$);
2271 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:, setStatusBarMode$orientation$duration$fenceID$animation$);
2272 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:startTime:, setStatusBarMode$orientation$duration$fenceID$animation$startTime$);
2273 WBRename(SBStatusBarOperatorNameView, operatorNameStyle, operatorNameStyle);
2274 WBRename(SBStatusBarOperatorNameView, setOperatorName:fullSize:, setOperatorName$fullSize$);
2275 WBRename(SBStatusBarTimeView, drawRect:, drawRect$);
2278 English_ = [[NSDictionary alloc] initWithContentsOfFile:@"/System/Library/CoreServices/SpringBoard.app/English.lproj/LocalizedApplicationNames.strings"];
2280 WBRename(NSString, drawInRect:withAttributes:, drawInRect$withAttributes$);
2281 WBRename(NSString, boundingRectWithSize:options:attributes:context:, boundingRectWithSize$options$attributes$context$);
2284 /*MSHook(int, open, const char *path, int oflag, mode_t mode) {
2285 int fd(_open(path, oflag, mode));
2287 static bool no(false);
2291 if (strstr(path, "/icon") != NULL)
2292 MSHookProcess(-1, "");
2294 if (fd == -1 && errno == EFAULT)
2295 NSLog(@"open(%p, %#x, %#o) = %d\n", path, oflag, mode, fd);
2297 NSLog(@"open(\"%s\", %#x, %#o) = %d\n", path, oflag, mode, fd);
2304 $objc_setAssociatedObject = reinterpret_cast<void (*)(id, void *, id value, objc_AssociationPolicy)>(dlsym(RTLD_DEFAULT, "objc_setAssociatedObject"));
2305 $objc_getAssociatedObject = reinterpret_cast<id (*)(id, void *)>(dlsym(RTLD_DEFAULT, "objc_getAssociatedObject"));
2306 $objc_removeAssociatedObjects = reinterpret_cast<void (*)(id)>(dlsym(RTLD_DEFAULT, "objc_removeAssociatedObjects"));
2308 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2310 NSString *identifier([[NSBundle mainBundle] bundleIdentifier]);
2311 SpringBoard_ = [identifier isEqualToString:@"com.apple.springboard"];
2313 Manager_ = [[NSFileManager defaultManager] retain];
2314 Themes_ = [[NSMutableArray alloc] initWithCapacity:8];
2316 dlset(_GSFontGetUseLegacyFontMetrics, "GSFontGetUseLegacyFontMetrics");
2318 // Load Settings.plist {{{
2319 if (NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"/User/Library/Preferences/com.saurik.WinterBoard.plist"]]) {
2320 if (NSNumber *value = [settings objectForKey:@"SummerBoard"])
2321 SummerBoard_ = [value boolValue];
2323 SummerBoard_ = true;
2325 if (NSNumber *value = [settings objectForKey:@"Debug"])
2326 Debug_ = [value boolValue];
2327 if (NSNumber *value = [settings objectForKey:@"RecordUI"])
2328 UIDebug_ = [value boolValue];
2330 NSArray *themes([settings objectForKey:@"Themes"]);
2332 if (NSString *theme = [settings objectForKey:@"Theme"])
2333 themes = [NSArray arrayWithObject:[NSDictionary dictionaryWithObjectsAndKeys:
2335 [NSNumber numberWithBool:true], @"Active",
2339 for (NSDictionary *theme in themes) {
2340 NSNumber *active([theme objectForKey:@"Active"]);
2341 if (![active boolValue])
2344 NSString *name([theme objectForKey:@"Name"]);
2348 #define testForTheme(format...) \
2350 NSString *path = [NSString stringWithFormat:format]; \
2351 if ([Manager_ fileExistsAtPath:path]) { \
2352 [Themes_ addObject:path]; \
2357 testForTheme(@"/Library/Themes/%@.theme", name)
2358 testForTheme(@"/Library/Themes/%@", name)
2359 testForTheme(@"%@/Library/SummerBoard/Themes/%@", NSHomeDirectory(), name)
2364 // Merge Info.plist {{{
2365 Info_ = [[NSMutableDictionary dictionaryWithCapacity:16] retain];
2367 for (NSString *theme in Themes_)
2368 if (NSDictionary *info = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"%@/Info.plist", theme]])
2369 for (NSString *key in [info allKeys])
2370 if ([Info_ objectForKey:key] == nil)
2371 [Info_ setObject:[info objectForKey:key] forKey:key];
2375 if (MSImageRef image = MSGetImageByName("/System/Library/PrivateFrameworks/AppSupport.framework/AppSupport")) {
2376 NSArray *(*CPBitmapCreateImagesFromPath)(NSString *, NSDictionary **, void *, void *);
2377 msset(CPBitmapCreateImagesFromPath, image, "_CPBitmapCreateImagesFromPath");
2378 MSHookFunction(CPBitmapCreateImagesFromPath, MSHake(CPBitmapCreateImagesFromPath));
2382 if (MSImageRef image = MSGetImageByName(AudioToolbox)) {
2383 bool (*_Z24GetFileNameForThisActionmPcRb)(unsigned long, char *, bool &);
2384 msset(_Z24GetFileNameForThisActionmPcRb, image, "__Z24GetFileNameForThisActionmPcRb");
2385 MSHookFunction(_Z24GetFileNameForThisActionmPcRb, &$_Z24GetFileNameForThisActionmPcRb, &__Z24GetFileNameForThisActionmPcRb);
2387 bool (*_Z24GetFileNameForThisActionmPcmRb)(unsigned long, char *, unsigned long, bool &);
2388 msset(_Z24GetFileNameForThisActionmPcmRb, image, "__Z24GetFileNameForThisActionmPcmRb");
2389 MSHookFunction(_Z24GetFileNameForThisActionmPcmRb, &$_Z24GetFileNameForThisActionmPcmRb, &__Z24GetFileNameForThisActionmPcmRb);
2392 // BackBoardServices {{{
2393 if (MSImageRef image = MSGetImageByName("/System/Library/PrivateFrameworks/BackBoardServices.framework/BackBoardServices")) {
2394 void (*BKSDisplayServicesSetSystemAppExitedImagePath)(NSString *path);
2395 msset(BKSDisplayServicesSetSystemAppExitedImagePath, image, "_BKSDisplayServicesSetSystemAppExitedImagePath");
2396 MSHookFunction(BKSDisplayServicesSetSystemAppExitedImagePath, MSHake(BKSDisplayServicesSetSystemAppExitedImagePath));
2399 // GraphicsServices {{{
2401 MSHookFunction(&GSFontCreateWithName, &$GSFontCreateWithName, &_GSFontCreateWithName);
2405 MSImageRef imageio = MSGetImageByName("/System/Library/Frameworks/ImageIO.framework/ImageIO");
2406 if (imageio == NULL)
2407 imageio = MSGetImageByName("/System/Library/PrivateFrameworks/ImageIO.framework/ImageIO");
2408 if (MSImageRef image = imageio) {
2409 void *(*CGImageReadCreateWithFile)(NSString *, int) = NULL;
2410 if (kCFCoreFoundationVersionNumber > 700) // XXX: iOS 6.x
2411 CGImageReadCreateWithFile = NULL;
2413 msset(CGImageReadCreateWithFile, image, "_CGImageReadCreateWithFile");
2414 MSHookFunction(CGImageReadCreateWithFile, MSHake(CGImageReadCreateWithFile));
2417 if (CGImageReadCreateWithFile == NULL) {
2418 void *(*CGImageSourceCreateWithFile)(NSString *, NSDictionary *);
2419 msset(CGImageSourceCreateWithFile, image, "_CGImageSourceCreateWithFile");
2420 MSHookFunction(CGImageSourceCreateWithFile, MSHake(CGImageSourceCreateWithFile));
2422 void *(*CGImageSourceCreateWithURL)(NSURL *, NSDictionary *);
2423 msset(CGImageSourceCreateWithURL, image, "_CGImageSourceCreateWithURL");
2424 MSHookFunction(CGImageSourceCreateWithURL, MSHake(CGImageSourceCreateWithURL));
2430 Wallpapers_ = [[NSArray arrayWithObjects:@"Wallpaper.mp4", @"Wallpaper@2x.png", @"Wallpaper@2x.jpg", @"Wallpaper.png", @"Wallpaper.jpg", @"Wallpaper.html", nil] retain];
2431 Papered_ = $getTheme$(Wallpapers_) != nil;
2432 Docked_ = $getTheme$([NSArray arrayWithObjects:@"Dock.png", nil]) != nil;
2434 CFNotificationCenterAddObserver(
2435 CFNotificationCenterGetDarwinNotifyCenter(),
2436 NULL, &ChangeWallpaper, (CFStringRef) @"com.saurik.winterboard.lockbackground", NULL, CFNotificationSuspensionBehaviorCoalesce
2439 if ($getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"]) != nil) {
2440 NSBundle *MediaPlayer([NSBundle bundleWithPath:@"/System/Library/Frameworks/MediaPlayer.framework"]);
2441 if (MediaPlayer != nil)
2444 $MPMoviePlayerController = objc_getClass("MPMoviePlayerController");
2445 $MPVideoView = objc_getClass("MPVideoView");
2452 if (MSImageRef image = MSGetImageByName("/System/Library/Frameworks/UIKit.framework/UIKit")) {
2454 class_addMethod($NSString, @selector(drawAtPoint:withStyle:), (IMP) &NSString$drawAtPoint$withStyle$, "v40@0:8{CGPoint=dd}16@32");
2455 class_addMethod($NSString, @selector(drawInRect:withStyle:), (IMP) &NSString$drawInRect$withStyle$, "v56@0:8{CGRect={CGSize=dd}{CGSize=dd}}16@48");
2456 class_addMethod($NSString, @selector(sizeWithStyle:forWidth:), (IMP) &NSString$sizeWithStyle$forWidth$, "{CGSize=dd}32@0:8@16d24");
2458 class_addMethod($NSString, @selector(drawAtPoint:withStyle:), (IMP) &NSString$drawAtPoint$withStyle$, "v20@0:4{CGPoint=ff}8@16");
2459 class_addMethod($NSString, @selector(drawInRect:withStyle:), (IMP) &NSString$drawInRect$withStyle$, "v28@0:4{CGRect={CGSize=ff}{CGSize=ff}}8@24");
2460 class_addMethod($NSString, @selector(sizeWithStyle:forWidth:), (IMP) &NSString$sizeWithStyle$forWidth$, "{CGSize=ff}16@0:4@8f12");
2463 WBHookSymbol(image, _UIKitBundle);
2464 WBHookSymbol(image, _UIPackedImageTableGetIdentifierForName);
2465 WBHookSymbol(image, _UISharedImageNameGetIdentifier);
2467 MSHookFunction(_UIImageWithName, MSHake(_UIImageWithName));
2469 WBHookSymbol(image, _UIApplicationImageWithName);
2470 MSHookFunction(_UIApplicationImageWithName, MSHake(_UIApplicationImageWithName));
2472 WBHookSymbol(image, _UIImageWithNameInDomain);
2473 MSHookFunction(_UIImageWithNameInDomain, MSHake(_UIImageWithNameInDomain));
2475 WBHookSymbol(image, _UIImageWithNameUsingCurrentIdiom);
2476 MSHookFunction(_UIImageWithNameUsingCurrentIdiom, MSHake(_UIImageWithNameUsingCurrentIdiom));
2478 WBHookSymbol(image, _UIImageWithDeviceSpecificName);
2479 MSHookFunction(_UIImageWithDeviceSpecificName, MSHake(_UIImageWithDeviceSpecificName));
2481 SEL includeEmoji(@selector(_legacy_drawAtPoint:forWidth:withFont:lineBreakMode:letterSpacing:includeEmoji:));
2482 if (![@"" respondsToSelector:includeEmoji])
2483 includeEmoji = @selector(drawAtPoint:forWidth:withFont:lineBreakMode:letterSpacing:includeEmoji:);
2484 MSHookMessage($NSString, includeEmoji, MSHake(NSString$drawAtPoint$forWidth$withFont$lineBreakMode$letterSpacing$includeEmoji$));
2486 SEL letterSpacing(@selector(_legacy_sizeWithFont:forWidth:lineBreakMode:letterSpacing:));
2487 if (![@"" respondsToSelector:letterSpacing])
2488 letterSpacing = @selector(sizeWithFont:forWidth:lineBreakMode:letterSpacing:);
2489 MSHookMessage($NSString, letterSpacing, MSHake(NSString$sizeWithFont$forWidth$lineBreakMode$letterSpacing$));
2491 SEL sizeWithFont(@selector(_legacy_sizeWithFont:));
2492 if (![@"" respondsToSelector:sizeWithFont])
2493 sizeWithFont = @selector(sizeWithFont:);
2494 MSHookMessage($NSString, sizeWithFont, MSHake(NSString$sizeWithFont$));
2498 //MSHookFunction(reinterpret_cast<int (*)(const char *, int, mode_t)>(&open), MSHake(open));
2500 if (UIDebug_ && ![Manager_ fileExistsAtPath:@"/tmp/UIImages"]) {
2501 NSError *error(nil);
2502 if (![Manager_ createDirectoryAtPath:@"/tmp/UIImages" withIntermediateDirectories:NO attributes:[NSDictionary dictionaryWithObjectsAndKeys:
2503 [NSNumber numberWithShort:0777], NSFilePosixPermissions,
2505 NSLog(@"WB:Error: cannot create /tmp/UIImages (%@)", error);