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 skipState = {&dayState,
1001 unsigned(kCFCoreFoundationVersionNumber > 800 ? 16 : 7)
1004 WBStringDrawingState dateState = {&skipState, 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 if (kCFCoreFoundationVersionNumber >= 800) {
2281 WBRename(NSString, drawInRect:withAttributes:, drawInRect$withAttributes$);
2282 WBRename(NSString, boundingRectWithSize:options:attributes:context:, boundingRectWithSize$options$attributes$context$);
2286 /*MSHook(int, open, const char *path, int oflag, mode_t mode) {
2287 int fd(_open(path, oflag, mode));
2289 static bool no(false);
2293 if (strstr(path, "/icon") != NULL)
2294 MSHookProcess(-1, "");
2296 if (fd == -1 && errno == EFAULT)
2297 NSLog(@"open(%p, %#x, %#o) = %d\n", path, oflag, mode, fd);
2299 NSLog(@"open(\"%s\", %#x, %#o) = %d\n", path, oflag, mode, fd);
2306 $objc_setAssociatedObject = reinterpret_cast<void (*)(id, void *, id value, objc_AssociationPolicy)>(dlsym(RTLD_DEFAULT, "objc_setAssociatedObject"));
2307 $objc_getAssociatedObject = reinterpret_cast<id (*)(id, void *)>(dlsym(RTLD_DEFAULT, "objc_getAssociatedObject"));
2308 $objc_removeAssociatedObjects = reinterpret_cast<void (*)(id)>(dlsym(RTLD_DEFAULT, "objc_removeAssociatedObjects"));
2310 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2312 NSString *identifier([[NSBundle mainBundle] bundleIdentifier]);
2313 SpringBoard_ = [identifier isEqualToString:@"com.apple.springboard"];
2315 Manager_ = [[NSFileManager defaultManager] retain];
2316 Themes_ = [[NSMutableArray alloc] initWithCapacity:8];
2318 dlset(_GSFontGetUseLegacyFontMetrics, "GSFontGetUseLegacyFontMetrics");
2320 // Load Settings.plist {{{
2321 if (NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"/User/Library/Preferences/com.saurik.WinterBoard.plist"]]) {
2322 if (NSNumber *value = [settings objectForKey:@"SummerBoard"])
2323 SummerBoard_ = [value boolValue];
2325 SummerBoard_ = true;
2327 if (NSNumber *value = [settings objectForKey:@"Debug"])
2328 Debug_ = [value boolValue];
2329 if (NSNumber *value = [settings objectForKey:@"RecordUI"])
2330 UIDebug_ = [value boolValue];
2332 NSArray *themes([settings objectForKey:@"Themes"]);
2334 if (NSString *theme = [settings objectForKey:@"Theme"])
2335 themes = [NSArray arrayWithObject:[NSDictionary dictionaryWithObjectsAndKeys:
2337 [NSNumber numberWithBool:true], @"Active",
2341 for (NSDictionary *theme in themes) {
2342 NSNumber *active([theme objectForKey:@"Active"]);
2343 if (![active boolValue])
2346 NSString *name([theme objectForKey:@"Name"]);
2350 #define testForTheme(format...) \
2352 NSString *path = [NSString stringWithFormat:format]; \
2353 if ([Manager_ fileExistsAtPath:path]) { \
2354 [Themes_ addObject:path]; \
2359 testForTheme(@"/Library/Themes/%@.theme", name)
2360 testForTheme(@"/Library/Themes/%@", name)
2361 testForTheme(@"%@/Library/SummerBoard/Themes/%@", NSHomeDirectory(), name)
2366 // Merge Info.plist {{{
2367 Info_ = [[NSMutableDictionary dictionaryWithCapacity:16] retain];
2369 for (NSString *theme in Themes_)
2370 if (NSDictionary *info = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"%@/Info.plist", theme]])
2371 for (NSString *key in [info allKeys])
2372 if ([Info_ objectForKey:key] == nil)
2373 [Info_ setObject:[info objectForKey:key] forKey:key];
2377 if (MSImageRef image = MSGetImageByName("/System/Library/PrivateFrameworks/AppSupport.framework/AppSupport")) {
2378 NSArray *(*CPBitmapCreateImagesFromPath)(NSString *, NSDictionary **, void *, void *);
2379 msset(CPBitmapCreateImagesFromPath, image, "_CPBitmapCreateImagesFromPath");
2380 MSHookFunction(CPBitmapCreateImagesFromPath, MSHake(CPBitmapCreateImagesFromPath));
2384 if (MSImageRef image = MSGetImageByName(AudioToolbox)) {
2385 bool (*_Z24GetFileNameForThisActionmPcRb)(unsigned long, char *, bool &);
2386 msset(_Z24GetFileNameForThisActionmPcRb, image, "__Z24GetFileNameForThisActionmPcRb");
2387 MSHookFunction(_Z24GetFileNameForThisActionmPcRb, &$_Z24GetFileNameForThisActionmPcRb, &__Z24GetFileNameForThisActionmPcRb);
2389 bool (*_Z24GetFileNameForThisActionmPcmRb)(unsigned long, char *, unsigned long, bool &);
2390 msset(_Z24GetFileNameForThisActionmPcmRb, image, "__Z24GetFileNameForThisActionmPcmRb");
2391 MSHookFunction(_Z24GetFileNameForThisActionmPcmRb, &$_Z24GetFileNameForThisActionmPcmRb, &__Z24GetFileNameForThisActionmPcmRb);
2394 // BackBoardServices {{{
2395 if (MSImageRef image = MSGetImageByName("/System/Library/PrivateFrameworks/BackBoardServices.framework/BackBoardServices")) {
2396 void (*BKSDisplayServicesSetSystemAppExitedImagePath)(NSString *path);
2397 msset(BKSDisplayServicesSetSystemAppExitedImagePath, image, "_BKSDisplayServicesSetSystemAppExitedImagePath");
2398 MSHookFunction(BKSDisplayServicesSetSystemAppExitedImagePath, MSHake(BKSDisplayServicesSetSystemAppExitedImagePath));
2401 // GraphicsServices {{{
2403 MSHookFunction(&GSFontCreateWithName, &$GSFontCreateWithName, &_GSFontCreateWithName);
2407 MSImageRef imageio = MSGetImageByName("/System/Library/Frameworks/ImageIO.framework/ImageIO");
2408 if (imageio == NULL)
2409 imageio = MSGetImageByName("/System/Library/PrivateFrameworks/ImageIO.framework/ImageIO");
2410 if (MSImageRef image = imageio) {
2411 void *(*CGImageReadCreateWithFile)(NSString *, int) = NULL;
2412 if (kCFCoreFoundationVersionNumber > 700) // XXX: iOS 6.x
2413 CGImageReadCreateWithFile = NULL;
2415 msset(CGImageReadCreateWithFile, image, "_CGImageReadCreateWithFile");
2416 MSHookFunction(CGImageReadCreateWithFile, MSHake(CGImageReadCreateWithFile));
2419 if (CGImageReadCreateWithFile == NULL) {
2420 void *(*CGImageSourceCreateWithFile)(NSString *, NSDictionary *);
2421 msset(CGImageSourceCreateWithFile, image, "_CGImageSourceCreateWithFile");
2422 MSHookFunction(CGImageSourceCreateWithFile, MSHake(CGImageSourceCreateWithFile));
2424 void *(*CGImageSourceCreateWithURL)(NSURL *, NSDictionary *);
2425 msset(CGImageSourceCreateWithURL, image, "_CGImageSourceCreateWithURL");
2426 MSHookFunction(CGImageSourceCreateWithURL, MSHake(CGImageSourceCreateWithURL));
2432 Wallpapers_ = [[NSArray arrayWithObjects:@"Wallpaper.mp4", @"Wallpaper@2x.png", @"Wallpaper@2x.jpg", @"Wallpaper.png", @"Wallpaper.jpg", @"Wallpaper.html", nil] retain];
2433 Papered_ = $getTheme$(Wallpapers_) != nil;
2434 Docked_ = $getTheme$([NSArray arrayWithObjects:@"Dock.png", nil]) != nil;
2436 CFNotificationCenterAddObserver(
2437 CFNotificationCenterGetDarwinNotifyCenter(),
2438 NULL, &ChangeWallpaper, (CFStringRef) @"com.saurik.winterboard.lockbackground", NULL, CFNotificationSuspensionBehaviorCoalesce
2441 if ($getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"]) != nil) {
2442 NSBundle *MediaPlayer([NSBundle bundleWithPath:@"/System/Library/Frameworks/MediaPlayer.framework"]);
2443 if (MediaPlayer != nil)
2446 $MPMoviePlayerController = objc_getClass("MPMoviePlayerController");
2447 $MPVideoView = objc_getClass("MPVideoView");
2454 if (MSImageRef image = MSGetImageByName("/System/Library/Frameworks/UIKit.framework/UIKit")) {
2456 class_addMethod($NSString, @selector(drawAtPoint:withStyle:), (IMP) &NSString$drawAtPoint$withStyle$, "v40@0:8{CGPoint=dd}16@32");
2457 class_addMethod($NSString, @selector(drawInRect:withStyle:), (IMP) &NSString$drawInRect$withStyle$, "v56@0:8{CGRect={CGSize=dd}{CGSize=dd}}16@48");
2458 class_addMethod($NSString, @selector(sizeWithStyle:forWidth:), (IMP) &NSString$sizeWithStyle$forWidth$, "{CGSize=dd}32@0:8@16d24");
2460 class_addMethod($NSString, @selector(drawAtPoint:withStyle:), (IMP) &NSString$drawAtPoint$withStyle$, "v20@0:4{CGPoint=ff}8@16");
2461 class_addMethod($NSString, @selector(drawInRect:withStyle:), (IMP) &NSString$drawInRect$withStyle$, "v28@0:4{CGRect={CGSize=ff}{CGSize=ff}}8@24");
2462 class_addMethod($NSString, @selector(sizeWithStyle:forWidth:), (IMP) &NSString$sizeWithStyle$forWidth$, "{CGSize=ff}16@0:4@8f12");
2465 WBHookSymbol(image, _UIKitBundle);
2466 WBHookSymbol(image, _UIPackedImageTableGetIdentifierForName);
2467 WBHookSymbol(image, _UISharedImageNameGetIdentifier);
2469 MSHookFunction(_UIImageWithName, MSHake(_UIImageWithName));
2471 WBHookSymbol(image, _UIApplicationImageWithName);
2472 MSHookFunction(_UIApplicationImageWithName, MSHake(_UIApplicationImageWithName));
2474 WBHookSymbol(image, _UIImageWithNameInDomain);
2475 MSHookFunction(_UIImageWithNameInDomain, MSHake(_UIImageWithNameInDomain));
2477 WBHookSymbol(image, _UIImageWithNameUsingCurrentIdiom);
2478 MSHookFunction(_UIImageWithNameUsingCurrentIdiom, MSHake(_UIImageWithNameUsingCurrentIdiom));
2480 WBHookSymbol(image, _UIImageWithDeviceSpecificName);
2481 MSHookFunction(_UIImageWithDeviceSpecificName, MSHake(_UIImageWithDeviceSpecificName));
2483 SEL includeEmoji(@selector(_legacy_drawAtPoint:forWidth:withFont:lineBreakMode:letterSpacing:includeEmoji:));
2484 if (![@"" respondsToSelector:includeEmoji])
2485 includeEmoji = @selector(drawAtPoint:forWidth:withFont:lineBreakMode:letterSpacing:includeEmoji:);
2486 MSHookMessage($NSString, includeEmoji, MSHake(NSString$drawAtPoint$forWidth$withFont$lineBreakMode$letterSpacing$includeEmoji$));
2488 SEL letterSpacing(@selector(_legacy_sizeWithFont:forWidth:lineBreakMode:letterSpacing:));
2489 if (![@"" respondsToSelector:letterSpacing])
2490 letterSpacing = @selector(sizeWithFont:forWidth:lineBreakMode:letterSpacing:);
2491 MSHookMessage($NSString, letterSpacing, MSHake(NSString$sizeWithFont$forWidth$lineBreakMode$letterSpacing$));
2493 SEL sizeWithFont(@selector(_legacy_sizeWithFont:));
2494 if (![@"" respondsToSelector:sizeWithFont])
2495 sizeWithFont = @selector(sizeWithFont:);
2496 MSHookMessage($NSString, sizeWithFont, MSHake(NSString$sizeWithFont$));
2500 //MSHookFunction(reinterpret_cast<int (*)(const char *, int, mode_t)>(&open), MSHake(open));
2502 if (UIDebug_ && ![Manager_ fileExistsAtPath:@"/tmp/UIImages"]) {
2503 NSError *error(nil);
2504 if (![Manager_ createDirectoryAtPath:@"/tmp/UIImages" withIntermediateDirectories:NO attributes:[NSDictionary dictionaryWithObjectsAndKeys:
2505 [NSNumber numberWithShort:0777], NSFilePosixPermissions,
2507 NSLog(@"WB:Error: cannot create /tmp/UIImages (%@)", error);