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)();
218 static NSMutableDictionary *Images_ = [[NSMutableDictionary alloc] initWithCapacity:64];
219 static NSMutableDictionary *Cache_ = [[NSMutableDictionary alloc] initWithCapacity:64];
220 static NSMutableDictionary *Strings_ = [[NSMutableDictionary alloc] initWithCapacity:0];
221 static NSMutableDictionary *Bundles_ = [[NSMutableDictionary alloc] initWithCapacity:2];
223 static NSFileManager *Manager_;
224 static NSMutableArray *Themes_;
226 static NSDictionary *English_;
227 static NSMutableDictionary *Info_;
230 static NSMutableDictionary *Themed_ = [[NSMutableDictionary alloc] initWithCapacity:128];
232 static unsigned Scale_ = 0;
234 static unsigned $getScale$(NSString *path) {
235 NSString *name(path);
237 #define StripName(strip) \
238 if ([name hasSuffix:@ strip]) \
239 name = [name substringWithRange:NSMakeRange(0, [name length] - sizeof(strip) - 1)];
243 StripName("~iphone");
246 return [name hasSuffix:@"@2x"] ? 2 : 1;
249 static NSArray *$useScale$(NSArray *files, bool use = true) {
250 if (use && Scale_ == 0) {
251 UIScreen *screen([UIScreen mainScreen]);
252 if ([screen respondsToSelector:@selector(scale)])
253 Scale_ = [screen scale];
258 NSString *idiom(IsWild_ ? @"ipad" : @"iphone");
260 NSMutableArray *scaled([NSMutableArray arrayWithCapacity:([files count] * 4)]);
262 for (NSString *file in files) {
263 NSString *base([file stringByDeletingPathExtension]);
264 NSString *extension([file pathExtension]);
268 [scaled addObject:[NSString stringWithFormat:@"%@@2x~%@.%@", base, idiom, extension]];
269 [scaled addObject:[NSString stringWithFormat:@"%@@2x.%@", base, extension]];
272 [scaled addObject:[NSString stringWithFormat:@"%@~%@.%@", base, idiom, extension]];
274 // if (!IsWild_) <- support old themes
275 [scaled addObject:file];
276 } else if ([base hasSuffix: @"@2x"]) {
277 [scaled addObject:[NSString stringWithFormat:@"%@~%@.%@", base, idiom, extension]];
278 [scaled addObject:file];
280 // XXX: this actually can't be used, as the person loading the file doesn't realize that the @2x changed
281 /*NSString *rest([base substringWithRange:NSMakeRange(0, [base length] - 3)]);
282 [scaled addObject:[NSString stringWithFormat:@"%@~%@.%@", rest, idiom, extension]];
283 [scaled addObject:[rest stringByAppendingPathExtension:extension]];*/
285 // XXX: this code isn't really complete
287 [scaled addObject:file];
289 if ([base hasSuffix:[NSString stringWithFormat:@"~%@", idiom]])
290 [scaled addObject:[[base substringWithRange:NSMakeRange(0, [base length] - 1 - [idiom length])] stringByAppendingPathExtension:extension]];
297 static NSString *$getTheme$(NSArray *files, NSArray *themes = Themes_) {
298 // XXX: this is not reasonable; OMG
301 @synchronized (Themed_) {
302 if (NSString *path = [Themed_ objectForKey:key])
303 return reinterpret_cast<id>(path) == [NSNull null] ? nil : path;
307 NSLog(@"WB:Debug: %@", [files description]);
311 for (NSString *theme in Themes_)
312 for (NSString *file in files) {
313 path = [NSString stringWithFormat:@"%@/%@", theme, file];
314 if ([Manager_ fileExistsAtPath:path]) {
315 if ([[Manager_ destinationOfSymbolicLinkAtPath:path error:NULL] isEqualToString:@"/"])
324 @synchronized (Themed_) {
325 [Themed_ setObject:(path == nil ? [NSNull null] : reinterpret_cast<id>(path)) forKey:key];
331 // $pathForFile$inBundle$() {{{
332 static NSString *$pathForFile$inBundle$(NSString *file, NSString *identifier, NSString *folder, bool ui, bool use) {
333 NSMutableArray *names = [NSMutableArray arrayWithCapacity:8];
335 if (identifier != nil)
336 [names addObject:[NSString stringWithFormat:@"Bundles/%@/%@", identifier, file]];
338 [names addObject:[NSString stringWithFormat:@"Folders/%@/%@", folder, file]];
339 NSString *base([folder stringByDeletingPathExtension]);
340 if ([base hasSuffix:@"~iphone"])
341 [names addObject:[NSString stringWithFormat:@"Folders/%@.%@/%@", [base substringWithRange:NSMakeRange(0, [base length] - 7)], [folder pathExtension], file]];
342 if ([base hasSuffix:@"~ipad"])
343 [names addObject:[NSString stringWithFormat:@"Folders/%@.%@/%@", [base substringWithRange:NSMakeRange(0, [base length] - 5)], [folder pathExtension], file]];
346 [names addObject:[NSString stringWithFormat:@"UIImages/%@", file]];
348 #define remapResourceName(oldname, newname) \
349 else if ([file isEqualToString:(oldname)]) \
350 [names addObject:[NSString stringWithFormat:@"%@.png", newname]]; \
352 bool summer(SpringBoard_ && SummerBoard_);
354 if (identifier == nil);
355 else if ([identifier isEqualToString:@"com.apple.chatkit"])
356 [names addObject:[NSString stringWithFormat:@"Bundles/com.apple.MobileSMS/%@", file]];
357 else if ([identifier isEqualToString:@"com.apple.calculator"])
358 [names addObject:[NSString stringWithFormat:@"Files/Applications/Calculator.app/%@", file]];
359 else if ([identifier isEqualToString:@"com.apple.Maps"] && [file isEqualToString:@"Icon-57@2x.png"])
360 [names addObject:[NSString stringWithFormat:@"Bundles/com.apple.Maps/icon.png"]];
362 remapResourceName(@"FSO_BG.png", @"StatusBar")
363 remapResourceName(Four_ ? @"SBDockBG-old.png" : @"SBDockBG.png", @"Dock")
364 remapResourceName(@"SBWeatherCelsius.png", @"Icons/Weather")
366 [names addObject:[NSString stringWithFormat:@"Fallback/%@", file]];
368 if (NSString *path = $getTheme$($useScale$(names, use)))
374 static NSString *$pathForFile$inBundle$(NSString *file, NSBundle *bundle, bool ui, bool use) {
375 return $pathForFile$inBundle$(file, [bundle bundleIdentifier], [[bundle bundlePath] lastPathComponent], ui, use);
379 static NSString *$pathForIcon$(SBApplication *self, NSString *suffix = @"") {
380 NSString *identifier = [self bundleIdentifier];
381 NSString *path = [self path];
382 NSString *folder = [path lastPathComponent];
383 NSString *dname = [self displayName];
384 NSString *didentifier = [self displayIdentifier];
387 NSLog(@"WB:Debug: [SBApplication(%@:%@:%@:%@) pathForIcon]", identifier, folder, dname, didentifier);
389 NSMutableArray *names = [NSMutableArray arrayWithCapacity:8];
391 /* XXX: I might need to keep this for backwards compatibility
392 if (identifier != nil)
393 [names addObject:[NSString stringWithFormat:@"Bundles/%@/icon.png", identifier]];
395 [names addObject:[NSString stringWithFormat:@"Folders/%@/icon.png", folder]]; */
397 #define testForIcon(Name) \
398 if (NSString *name = Name) \
399 [names addObject:[NSString stringWithFormat:@"Icons%@/%@.png", suffix, name]];
401 if (![didentifier isEqualToString:identifier])
402 testForIcon(didentifier);
404 testForIcon(identifier);
407 if ([identifier isEqualToString:@"com.apple.MobileSMS"])
410 if (didentifier != nil) {
411 testForIcon([English_ objectForKey:didentifier]);
413 NSArray *parts = [didentifier componentsSeparatedByString:@"-"];
414 if ([parts count] != 1)
415 if (NSDictionary *english = [[[NSDictionary alloc] initWithContentsOfFile:[path stringByAppendingString:@"/English.lproj/UIRoleDisplayNames.strings"]] autorelease])
416 testForIcon([english objectForKey:[parts lastObject]]);
419 if (NSString *path = $getTheme$(names))
425 // -[NSBundle wb$bundleWithFile] {{{
426 @interface NSBundle (WinterBoard)
427 + (NSBundle *) wb$bundleWithFile:(NSString *)path;
430 @implementation NSBundle (WinterBoard)
432 + (NSBundle *) wb$bundleWithFile:(NSString *)path {
433 path = [path stringByDeletingLastPathComponent];
434 if (path == nil || [path length] == 0 || [path isEqualToString:@"/"])
437 NSBundle *bundle([Bundles_ objectForKey:path]);
438 if (reinterpret_cast<id>(bundle) == [NSNull null])
440 else if (bundle == nil) {
441 if ([Manager_ fileExistsAtPath:[path stringByAppendingPathComponent:@"Info.plist"]])
442 bundle = [NSBundle bundleWithPath:path];
444 bundle = [NSBundle wb$bundleWithFile:path];
446 NSLog(@"WB:Debug:PathBundle(%@, %@)", path, bundle);
447 [Bundles_ setObject:(bundle == nil ? [NSNull null] : reinterpret_cast<id>(bundle)) forKey:path];
455 // -[NSString wb$themedPath] {{{
456 @interface NSString (WinterBoard)
457 - (NSString *) wb$themedPath;
460 @implementation NSString (WinterBoard)
462 - (NSString *) wb$themedPath {
463 if ([self hasPrefix:@"/Library/Themes/"])
467 NSLog(@"WB:Debug:Bypass(\"%@\")", self);
469 if (NSBundle *bundle = [NSBundle wb$bundleWithFile:self]) {
470 NSString *file([self stringByResolvingSymlinksInPath]);
471 NSString *prefix([[bundle bundlePath] stringByResolvingSymlinksInPath]);
472 if ([file hasPrefix:prefix]) {
473 NSUInteger length([prefix length]);
474 if (length != [file length])
475 if (NSString *path = $pathForFile$inBundle$([file substringFromIndex:(length + 1)], bundle, false, false))
486 void WBLogRect(const char *tag, struct CGRect rect) {
487 NSLog(@"%s:{%f,%f+%f,%f}", tag, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
490 void WBLogHierarchy(UIView *view, unsigned index = 0, unsigned indent = 0) {
491 CGRect frame([view frame]);
492 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]);
494 for (UIView *child in [view subviews])
495 WBLogHierarchy(child, index++, indent + 1);
498 UIImage *$cacheForImage$(UIImage *image) {
499 CGColorSpaceRef space(CGColorSpaceCreateDeviceRGB());
500 CGRect rect = {CGPointMake(1, 1), [image size]};
501 CGSize size = {rect.size.width + 2, rect.size.height + 2};
503 CGContextRef context(CGBitmapContextCreate(NULL, size.width, size.height, 8, 4 * size.width, space, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst));
504 CGColorSpaceRelease(space);
506 CGContextDrawImage(context, rect, [image CGImage]);
507 CGImageRef ref(CGBitmapContextCreateImage(context));
508 CGContextRelease(context);
510 UIImage *cache([UIImage imageWithCGImage:ref]);
516 /*MSHook(id, SBImageCache$initWithName$forImageWidth$imageHeight$initialCapacity$, SBImageCache *self, SEL sel, NSString *name, unsigned width, unsigned height, unsigned capacity) {
517 //if ([name isEqualToString:@"icons"]) return nil;
518 return _SBImageCache$initWithName$forImageWidth$imageHeight$initialCapacity$(self, sel, name, width, height, capacity);
521 MSHook(void, SBIconModel$cacheImageForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
522 NSString *key([icon displayIdentifier]);
524 if (UIImage *image = [icon icon]) {
525 CGSize size = [image size];
526 if (size.width != 59 || size.height != 60) {
527 UIImage *cache($cacheForImage$(image));
528 [Cache_ setObject:cache forKey:key];
533 _SBIconModel$cacheImageForIcon$(self, sel, icon);
536 MSHook(void, SBIconModel$cacheImagesForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
537 /* XXX: do I /really/ have to do this? figure out how to cache the small icon! */
538 _SBIconModel$cacheImagesForIcon$(self, sel, icon);
540 NSString *key([icon displayIdentifier]);
542 if (UIImage *image = [icon icon]) {
543 CGSize size = [image size];
544 if (size.width != 59 || size.height != 60) {
545 UIImage *cache($cacheForImage$(image));
546 [Cache_ setObject:cache forKey:key];
552 MSHook(UIImage *, SBIconModel$getCachedImagedForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
553 NSString *key([icon displayIdentifier]);
554 if (UIImage *image = [Cache_ objectForKey:key])
557 return _SBIconModel$getCachedImagedForIcon$(self, sel, icon);
560 MSHook(UIImage *, SBIconModel$getCachedImagedForIcon$smallIcon$, SBIconModel *self, SEL sel, SBIcon *icon, BOOL small) {
562 return _SBIconModel$getCachedImagedForIcon$smallIcon$(self, sel, icon, small);
563 NSString *key([icon displayIdentifier]);
564 if (UIImage *image = [Cache_ objectForKey:key])
567 return _SBIconModel$getCachedImagedForIcon$smallIcon$(self, sel, icon, small);
570 MSHook(id, SBSearchView$initWithFrame$, id /* XXX: SBSearchView */ self, SEL sel, struct CGRect frame) {
571 if ((self = _SBSearchView$initWithFrame$(self, sel, frame)) != nil) {
572 [self setBackgroundColor:[UIColor clearColor]];
573 for (UIView *child in [self subviews])
574 [child setBackgroundColor:[UIColor clearColor]];
578 MSHook(id, SBSearchTableViewCell$initWithStyle$reuseIdentifier$, SBSearchTableViewCell *self, SEL sel, int style, NSString *reuse) {
579 if ((self = _SBSearchTableViewCell$initWithStyle$reuseIdentifier$(self, sel, style, reuse)) != nil) {
580 [self setBackgroundColor:[UIColor clearColor]];
584 MSHook(void, SBSearchTableViewCell$drawRect$, SBSearchTableViewCell *self, SEL sel, struct CGRect rect, BOOL selected) {
585 _SBSearchTableViewCell$drawRect$(self, sel, rect, selected);
586 float inset([self edgeInset]);
587 [[UIColor clearColor] set];
588 UIRectFill(CGRectMake(0, 0, inset, rect.size.height));
589 UIRectFill(CGRectMake(rect.size.width - inset, 0, inset, rect.size.height));
592 MSHook(UIImage *, SBApplicationIcon$icon, SBApplicationIcon *self, SEL sel) {
593 if (![Info_ wb$boolForKey:@"ComposeStoreIcons"])
594 if (NSString *path = $pathForIcon$([self application]))
595 return [UIImage imageWithContentsOfFile:path];
596 return _SBApplicationIcon$icon(self, sel);
599 MSHook(UIImage *, SBApplicationIcon$generateIconImage$, SBApplicationIcon *self, SEL sel, int type) {
601 if (![Info_ wb$boolForKey:@"ComposeStoreIcons"]) {
602 if (IsWild_ && false) // XXX: delete this code, it should not be supported
603 if (NSString *path72 = $pathForIcon$([self application], @"-72"))
604 return [UIImage imageWithContentsOfFile:path72];
605 if (NSString *path = $pathForIcon$([self application]))
606 if (UIImage *image = [UIImage imageWithContentsOfFile:path]) {
608 if ([$SBIcon respondsToSelector:@selector(defaultIconImageSize)])
609 width = [$SBIcon defaultIconImageSize].width;
612 return width == 59 ? image : [image _imageScaledToProportion:(width / 59.0) interpolationQuality:5];
615 return _SBApplicationIcon$generateIconImage$(self, sel, type);
618 MSHook(UIImage *, SBWidgetApplicationIcon$icon, SBWidgetApplicationIcon *self, SEL sel) {
620 NSLog(@"WB:Debug:Widget(%@:%@)", [self displayIdentifier], [self displayName]);
621 if (NSString *path = $getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Icons/%@.png", [self displayName]]]))
622 return [UIImage imageWithContentsOfFile:path];
623 return _SBWidgetApplicationIcon$icon(self, sel);
626 MSHook(UIImage *, SBBookmarkIcon$icon, SBBookmarkIcon *self, SEL sel) {
628 NSLog(@"WB:Debug:Bookmark(%@:%@)", [self displayIdentifier], [self displayName]);
629 if (NSString *path = $getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Icons/%@.png", [self displayName]]]))
630 return [UIImage imageWithContentsOfFile:path];
631 return _SBBookmarkIcon$icon(self, sel);
634 MSHook(NSString *, SBApplication$pathForIcon, SBApplication *self, SEL sel) {
635 if (NSString *path = $pathForIcon$(self))
637 return _SBApplication$pathForIcon(self, sel);
640 static UIImage *CachedImageAtPath(NSString *path) {
641 path = [path stringByResolvingSymlinksInPath];
642 UIImage *image = [Images_ objectForKey:path];
644 return reinterpret_cast<id>(image) == [NSNull null] ? nil : image;
645 image = [[UIImage alloc] initWithContentsOfFile:path cache:true];
647 image = [image autorelease];
648 [Images_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:path];
652 MSHook(UIImage *, _UIApplicationImageWithName, NSString *name) {
653 NSBundle *bundle = [NSBundle mainBundle];
655 NSLog(@"WB:Debug: _UIApplicationImageWithName(\"%@\", %@)", name, bundle);
656 if (NSString *path = $pathForFile$inBundle$(name, bundle, false, false))
657 return CachedImageAtPath(path);
658 return __UIApplicationImageWithName(name);
661 #define WBDelegate(delegate) \
662 - (NSMethodSignature*) methodSignatureForSelector:(SEL)sel { \
664 NSLog(@"WB:MS:%s:(%s)", class_getName([self class]), sel_getName(sel)); \
665 if (NSMethodSignature *sig = [delegate methodSignatureForSelector:sel]) \
667 NSLog(@"WB:Error: [%s methodSignatureForSelector:(%s)]", class_getName([self class]), sel_getName(sel)); \
671 - (void) forwardInvocation:(NSInvocation*)inv { \
672 SEL sel = [inv selector]; \
673 if ([delegate respondsToSelector:sel]) \
674 [inv invokeWithTarget:delegate]; \
676 NSLog(@"WB:Error: [%s forwardInvocation:(%s)]", class_getName([self class]), sel_getName(sel)); \
679 // %hook -[NSBundle pathForResource:ofType:] {{{
680 MSInstanceMessageHook2(NSString *, NSBundle, pathForResource,ofType, NSString *, resource, NSString *, type) {
681 NSString *file = type == nil ? resource : [NSString stringWithFormat:@"%@.%@", resource, type];
682 if ([file isEqualToString:@"Info.plist"])
683 return MSOldCall(resource, type);
685 NSLog(@"WB:Debug: [NSBundle(%@) pathForResource:\"%@\"]", [self bundleIdentifier], file);
686 if (NSString *path = $pathForFile$inBundle$(file, self, false, false))
688 return MSOldCall(resource, type);
692 static void $drawLabel$(NSString *label, CGRect rect, NSString *style, NSString *custom) {
693 bool ellipsis(false);
694 CGFloat max = rect.size.width - 11, width;
696 width = [(ellipsis ? [label stringByAppendingString:@"..."] : label) sizeWithStyle:style forWidth:320].width;
699 size_t length([label length]);
700 CGFloat spacing((width - max) / (length - 1));
702 if (spacing > 1.25) {
704 label = [label substringToIndex:(length - 1)];
708 style = [style stringByAppendingString:[NSString stringWithFormat:@"letter-spacing: -%f; ", spacing]];
712 label = [label stringByAppendingString:@"..."];
715 style = [style stringByAppendingString:custom];
717 CGSize size = [label sizeWithStyle:style forWidth:rect.size.width];
718 [label drawAtPoint:CGPointMake((rect.size.width - size.width) / 2 + rect.origin.x, rect.origin.y) withStyle:style];
721 static struct WBStringDrawingState {
722 WBStringDrawingState *next_;
726 } *stringDrawingState_;
728 extern "C" CGColorSpaceRef CGContextGetFillColorSpace(CGContextRef);
729 extern "C" void CGContextGetFillColor(CGContextRef, CGFloat[]);
731 static NSString *WBColorMarkup(size_t number, const CGFloat *components) {
753 return [NSString stringWithFormat:@"color: rgba(%g, %g, %g, %g)", r * 255, g * 255, b * 255, a];
756 static NSString *WBColorMarkup() {
757 CGContextRef context(UIGraphicsGetCurrentContext());
758 //NSLog(@"XXX:1:%p", context);
762 CGColorSpaceRef space(CGContextGetFillColorSpace(context));
763 //NSLog(@"XXX:2:%p", space);
767 size_t number(CGColorSpaceGetNumberOfComponents(space));
768 //NSLog(@"XXX:3:%u", number);
772 CGFloat components[number + 1];
773 CGContextGetFillColor(context, components);
774 return WBColorMarkup(number, components);
777 static NSString *WBColorMarkup(UIColor *uicolor) {
780 CGColorRef cgcolor([uicolor CGColor]);
784 CGColorSpaceRef space(CGColorGetColorSpace(cgcolor));
785 //NSLog(@"XXX:2:%p", space);
789 size_t number(CGColorGetNumberOfComponents(cgcolor));
790 //NSLog(@"XXX:3:%u", number);
794 const CGFloat *components(CGColorGetComponents(cgcolor));
795 return WBColorMarkup(number, components);
798 extern "C" NSString *NSStringFromCGPoint(CGPoint rect);
800 MSInstanceMessage6(CGSize, NSString, drawAtPoint,forWidth,withFont,lineBreakMode,letterSpacing,includeEmoji, CGPoint, point, CGFloat, width, UIFont *, font, UILineBreakMode, mode, CGFloat, spacing, BOOL, emoji) {
801 //NSLog(@"XXX: @\"%@\" %@ %g \"%@\" %u %g %u", self, NSStringFromCGPoint(point), width, font, mode, spacing, emoji);
803 WBStringDrawingState *state(stringDrawingState_);
805 return MSOldCall(point, width, font, mode, spacing, emoji);
807 if (state->count_ != 0 && --state->count_ == 0)
808 stringDrawingState_ = state->next_;
809 if (state->info_ == nil)
810 return MSOldCall(point, width, font, mode, spacing, emoji);
812 NSString *info([Info_ objectForKey:state->info_]);
814 return MSOldCall(point, width, font, mode, spacing, emoji);
816 NSString *base(state->base_ ?: @"");
817 NSString *extra([NSString stringWithFormat:@"letter-spacing: %gpx", spacing]);
818 [self drawAtPoint:point withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info]];
822 extern "C" NSString *NSStringFromCGRect(CGRect rect);
824 MSInstanceMessageHook7(CGSize, NSString, _drawInRect,withFont,lineBreakMode,alignment,lineSpacing,includeEmoji,truncationRect, CGRect, rect, UIFont *, font, UILineBreakMode, mode, UITextAlignment, alignment, float, spacing, BOOL, emoji, CGRect, truncation) {
825 //NSLog(@"XXX: @\"%@\" %@ \"%@\" %u %u %g %u %@", self, NSStringFromCGRect(rect), font, mode, alignment, spacing, emoji, NSStringFromCGRect(truncation));
827 WBStringDrawingState *state(stringDrawingState_);
829 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
831 if (state->count_ != 0 && --state->count_ == 0)
832 stringDrawingState_ = state->next_;
833 if (state->info_ == nil)
834 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
836 NSString *info([Info_ objectForKey:state->info_]);
838 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
843 case UITextAlignmentLeft:
846 case UITextAlignmentCenter:
847 textAlign = @"center";
849 case UITextAlignmentRight:
850 textAlign = @"right";
854 NSString *base(state->base_ ?: @"");
855 NSString *extra([NSString stringWithFormat:@"text-align: %@", textAlign]);
858 $drawLabel$(self, rect, [NSString stringWithFormat:@"%@;%@;%@", [font markupDescription], WBColorMarkup(), base], info);
860 [self drawInRect:rect withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info]];
865 MSInstanceMessage2(void, NSString, drawInRect,withAttributes, CGRect, rect, NSDictionary *, attributes) {
866 //NSLog(@"XXX: *\"%@\" %@", self, attributes);
868 WBStringDrawingState *state(stringDrawingState_);
870 return MSOldCall(rect, attributes);
872 if (state->count_ != 0 && --state->count_ == 0)
873 stringDrawingState_ = state->next_;
874 if (state->info_ == nil)
875 return MSOldCall(rect, attributes);
877 NSString *info([Info_ objectForKey:state->info_]);
879 return MSOldCall(rect, attributes);
881 NSString *base(state->base_ ?: @"");
883 UIFont *font([attributes objectForKey:@"NSFont"]);
884 UIColor *color([attributes objectForKey:@"NSColor"]);
886 [self drawInRect:rect withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], WBColorMarkup(color), base, info]];
889 extern "C" NSString *NSStringFromCGSize(CGSize size);
891 MSInstanceMessage4(CGRect, NSString, boundingRectWithSize,options,attributes,context, CGSize, size, NSInteger, options, NSDictionary *, attributes, id, context) {
892 //NSLog(@"XXX: $\"%@\" %@ 0x%x %@ %@", self, NSStringFromCGSize(size), unsigned(options), attributes, context);
894 WBStringDrawingState *state(stringDrawingState_);
896 return MSOldCall(size, options, attributes, context);
898 if (state->count_ != 0 && --state->count_ == 0)
899 stringDrawingState_ = state->next_;
900 if (state->info_ == nil)
901 return MSOldCall(size, options, attributes, context);
903 NSString *info([Info_ objectForKey:state->info_]);
905 return MSOldCall(size, options, attributes, context);
907 NSString *base(state->base_ ?: @"");
909 UIFont *font([attributes objectForKey:@"NSFont"]);
910 UIColor *color([attributes objectForKey:@"NSColor"]);
912 return (CGRect) {{0, 0}, [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], WBColorMarkup(color), base, info] forWidth:size.width]};
915 MSInstanceMessage4(CGSize, NSString, sizeWithFont,forWidth,lineBreakMode,letterSpacing, UIFont *, font, CGFloat, width, UILineBreakMode, mode, CGFloat, spacing) {
916 //NSLog(@"XXX: #\"%@\" \"%@\" %g %u %g", self, font, width, mode, spacing);
918 WBStringDrawingState *state(stringDrawingState_);
920 return MSOldCall(font, width, mode, spacing);
922 if (state->count_ != 0 && --state->count_ == 0)
923 stringDrawingState_ = state->next_;
924 if (state->info_ == nil)
925 return MSOldCall(font, width, mode, spacing);
927 NSString *info([Info_ objectForKey:state->info_]);
929 return MSOldCall(font, width, mode, spacing);
931 NSString *base(state->base_ ?: @"");
932 NSString *extra([NSString stringWithFormat:@"letter-spacing: %gpx", spacing]);
933 return [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info] forWidth:width];
936 MSInstanceMessage1(CGSize, NSString, sizeWithFont, UIFont *, font) {
937 //NSLog(@"XXX: ?\"%@\"", self);
939 WBStringDrawingState *state(stringDrawingState_);
941 return MSOldCall(font);
943 if (state->count_ != 0 && --state->count_ == 0)
944 stringDrawingState_ = state->next_;
945 if (state->info_ == nil)
946 return MSOldCall(font);
948 NSString *info([Info_ objectForKey:state->info_]);
950 return MSOldCall(font);
952 NSString *base(state->base_ ?: @"");
953 return [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), base, info] forWidth:65535];
956 MSClassMessageHook2(id, SBIconBadgeView, checkoutAccessoryImagesForIcon,location, id, icon, int, location) {
957 WBStringDrawingState badgeState = {NULL, 0, @""
960 stringDrawingState_ = &badgeState;
962 id images(MSOldCall(icon, location));
964 stringDrawingState_ = NULL;
968 MSClassMessageHook2(UIImage *, SBIconAccessoryImage, checkoutAccessoryImageForIcon,location, id, icon, int, location) {
969 if ([self _imageClassForIcon:icon location:location] != $SBIconBadgeImage)
970 return MSOldCall(icon, location);
972 WBStringDrawingState badgeState = {NULL, 0, @""
975 stringDrawingState_ = &badgeState;
977 UIImage *image(MSOldCall(icon, location));
979 stringDrawingState_ = NULL;
983 MSInstanceMessageHook1(UIImage *, SBIconBadgeFactory, checkoutBadgeImageForText, NSString *, text) {
984 WBStringDrawingState badgeState = {NULL, 0, @""
987 stringDrawingState_ = &badgeState;
989 UIImage *image(MSOldCall(text));
991 stringDrawingState_ = NULL;
995 MSInstanceMessageHook1(UIImage *, SBCalendarApplicationIcon, generateIconImage, int, type) {
996 WBStringDrawingState dayState = {NULL, 2, @""
997 // XXX: this is only correct on an iPod dock
998 "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px;"
999 , @"CalendarIconDayStyle"};
1001 WBStringDrawingState skipState = {&dayState,
1002 unsigned(kCFCoreFoundationVersionNumber > 800 ? 16 : 7)
1005 WBStringDrawingState dateState = {&skipState, 2, @""
1006 , @"CalendarIconDateStyle"};
1008 stringDrawingState_ = &dateState;
1010 UIImage *image(MSOldCall(type));
1012 stringDrawingState_ = NULL;
1016 MSInstanceMessageHook1(UIImage *, UIStatusBarTimeItemView, contentsImageForStyle, int, style) {
1017 WBStringDrawingState timeState = {NULL, 0, @""
1020 stringDrawingState_ = &timeState;
1022 UIImage *image(MSOldCall(style));
1024 stringDrawingState_ = NULL;
1028 MSHook(void, SBCalendarIconContentsView$drawRect$, SBCalendarIconContentsView *self, SEL sel, CGRect rect) {
1029 NSBundle *bundle([NSBundle mainBundle]);
1031 CFLocaleRef locale(CFLocaleCopyCurrent());
1032 CFDateFormatterRef formatter(CFDateFormatterCreate(NULL, locale, kCFDateFormatterNoStyle, kCFDateFormatterNoStyle));
1035 CFDateRef now(CFDateCreate(NULL, CFAbsoluteTimeGetCurrent()));
1037 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NUMBER_FORMAT" value:@"d" table:@"SpringBoard"]);
1038 CFStringRef date(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
1039 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NAME_FORMAT" value:@"cccc" table:@"SpringBoard"]);
1040 CFStringRef day(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
1044 CFRelease(formatter);
1046 NSString *datestyle([@""
1047 "font-family: Helvetica; "
1048 "font-weight: bold; "
1051 "" stringByAppendingString:(IsWild_
1052 ? @"font-size: 54px; "
1053 : @"font-size: 39px; "
1056 NSString *daystyle([@""
1057 "font-family: Helvetica; "
1058 "font-weight: bold; "
1060 "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px; "
1061 "" stringByAppendingString:(IsWild_
1062 ? @"font-size: 11px; "
1063 : @"font-size: 9px; "
1066 if (NSString *style = [Info_ objectForKey:@"CalendarIconDateStyle"])
1067 datestyle = [datestyle stringByAppendingString:style];
1068 if (NSString *style = [Info_ objectForKey:@"CalendarIconDayStyle"])
1069 daystyle = [daystyle stringByAppendingString:style];
1071 CGFloat width([self bounds].size.width);
1073 CGSize datesize = [(NSString *)date sizeWithStyle:datestyle forWidth:(width + leeway)];
1074 CGSize daysize = [(NSString *)day sizeWithStyle:daystyle forWidth:(width + leeway)];
1076 unsigned base0(IsWild_ ? 89 : 70);
1077 if ($GSFontGetUseLegacyFontMetrics())
1079 unsigned base1(IsWild_ ? 18 : 16);
1086 [(NSString *)date drawAtPoint:CGPointMake(
1087 (width + 1 - datesize.width) / 2, (base0 - datesize.height) / 2
1088 ) withStyle:datestyle];
1090 [(NSString *)day drawAtPoint:CGPointMake(
1091 (width + 1 - daysize.width) / 2, (base1 - daysize.height) / 2
1092 ) withStyle:daystyle];
1098 // %hook -[{NavigationBar,Toolbar} setBarStyle:] {{{
1099 void $setBarStyle$_(NSString *name, int &style) {
1101 NSLog(@"WB:Debug:%@Style:%d", name, style);
1102 NSNumber *number = nil;
1104 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style-%d", name, style]];
1106 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style", name]];
1107 if (number != nil) {
1108 style = [number intValue];
1110 NSLog(@"WB:Debug:%@Style=%d", name, style);
1114 MSInstanceMessageHook1(void, UIToolbar, setBarStyle, int, style) {
1115 $setBarStyle$_(@"Toolbar", style);
1116 return MSOldCall(style);
1119 MSInstanceMessageHook1(void, UINavigationBar, setBarStyle, int, style) {
1120 $setBarStyle$_(@"NavigationBar", style);
1121 return MSOldCall(style);
1125 MSHook(void, SBButtonBar$didMoveToSuperview, UIView *self, SEL sel) {
1126 [[self superview] setBackgroundColor:[UIColor clearColor]];
1127 _SBButtonBar$didMoveToSuperview(self, sel);
1130 MSHook(void, SBStatusBarContentsView$didMoveToSuperview, UIView *self, SEL sel) {
1131 [[self superview] setBackgroundColor:[UIColor clearColor]];
1132 _SBStatusBarContentsView$didMoveToSuperview(self, sel);
1135 static NSArray *Wallpapers_;
1136 static bool Papered_;
1137 static bool Docked_;
1138 static bool SMSBackgrounded_;
1139 static NSString *WallpaperFile_;
1140 static UIImageView *WallpaperImage_;
1141 static UIWebDocumentView *WallpaperPage_;
1142 static NSURL *WallpaperURL_;
1144 #define _release(object) \
1145 do if (object != nil) { \
1150 static UIImage *$getImage$(NSString *path) {
1151 UIImage *image([UIImage imageWithContentsOfFile:path]);
1153 unsigned scale($getScale$(path));
1154 if (scale != 1 && [image respondsToSelector:@selector(setScale)])
1155 [image setScale:scale];
1160 template <typename Original_, typename Modified_>
1161 _finline UIImage *WBCacheImage(const Original_ &original, const Modified_ &modified, NSString *key) {
1162 UIImage *image([Images_ objectForKey:key]);
1164 return reinterpret_cast<id>(image) == [NSNull null] ? original() : image;
1165 if (NSString *path = modified())
1166 image = $getImage$(path);
1167 [Images_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:key];
1168 return image == nil ? original() : image;
1171 static UIImage *$getDefaultDesktopImage$() {
1172 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"LockBackground.png", @"LockBackground.jpg", nil])))
1173 return $getImage$(path);
1177 MSClassMessageHook0(UIImage *, UIImage, defaultDesktopImage) {
1178 return $getDefaultDesktopImage$() ?: MSOldCall();
1181 MSInstanceMessageHook0(UIImage *, SBSlidingAlertDisplay, _defaultDesktopImage) {
1182 return $getDefaultDesktopImage$() ?: MSOldCall();
1185 MSInstanceMessageHook0(void, SBWallpaperView, resetCurrentImageToWallpaper) {
1186 for (UIView *parent([self superview]); parent != nil; parent = [parent superview])
1187 if ([parent isKindOfClass:$SBSlidingAlertDisplay]) {
1188 if (UIImage *image = $getDefaultDesktopImage$()) {
1189 [self setImage:image];
1199 // %hook -[SBUIController init] {{{
1200 MSInstanceMessageHook0(id, SBUIController, init) {
1205 NSString *paper($getTheme$(Wallpapers_));
1207 paper = [paper stringByDeletingLastPathComponent];
1211 sysctlbyname("hw.machine", NULL, &size, NULL, 0);
1212 char *machine = new char[size];
1214 if (sysctlbyname("hw.machine", machine, &size, NULL, 0) == -1) {
1215 perror("sysctlbyname(\"hw.machine\", ?)");
1220 IsWild_ = machine != NULL && strncmp(machine, "iPad", 4) == 0;
1224 NSLog(@"WB:Debug:Info = %@", [Info_ description]);
1227 UIImageView *&_wallpaperView(MSHookIvar<UIImageView *>(self, "_wallpaperView"));
1228 if (&_wallpaperView != NULL) {
1229 [_wallpaperView removeFromSuperview];
1230 [_wallpaperView release];
1231 _wallpaperView = nil;
1235 UIView *&_contentLayer(MSHookIvar<UIView *>(self, "_contentLayer"));
1236 UIView *&_contentView(MSHookIvar<UIView *>(self, "_contentView"));
1239 if (&_contentLayer != NULL)
1240 player = &_contentLayer;
1241 else if (&_contentView != NULL)
1242 player = &_contentView;
1245 UIView *layer(player == NULL ? nil : *player);
1247 UIWindow *window([[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]);
1248 UIView *content([[[UIView alloc] initWithFrame:[window frame]] autorelease]);
1249 [window setContentView:content];
1251 UIWindow *&_window(MSHookIvar<UIWindow *>(self, "_window"));
1252 [window setBackgroundColor:[_window backgroundColor]];
1253 [_window setBackgroundColor:[UIColor clearColor]];
1255 [window setLevel:-1000];
1256 [window setHidden:NO];
1258 /*if (player != NULL)
1259 *player = content;*/
1261 [content setBackgroundColor:[layer backgroundColor]];
1262 [layer setBackgroundColor:[UIColor clearColor]];
1265 if (!SummerBoard_ || !IsWild_)
1268 CGRect bounds([content bounds]);
1269 bounds.origin.y = -30;
1270 indirect = [[[UIView alloc] initWithFrame:bounds] autorelease];
1271 [content addSubview:indirect];
1272 [indirect zoomToScale:2.4];
1275 _release(WallpaperFile_);
1276 _release(WallpaperImage_);
1277 _release(WallpaperPage_);
1278 _release(WallpaperURL_);
1281 NSArray *themes([NSArray arrayWithObject:paper]);
1283 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"], themes)) {
1287 static AVController *controller_(nil);
1288 if (controller_ == nil) {
1289 AVQueue *queue([AVQueue avQueue]);
1290 controller_ = [[AVController avControllerWithQueue:queue error:&error] retain];
1293 AVQueue *queue([controller_ queue]);
1295 UIView *video([[[UIView alloc] initWithFrame:[indirect bounds]] autorelease]);
1296 [controller_ setLayer:[video _layer]];
1298 AVItem *item([[[AVItem alloc] initWithPath:path error:&error] autorelease]);
1299 [queue appendItem:item error:&error];
1301 [controller_ play:&error];
1302 #elif UseMPMoviePlayerController
1303 NSURL *url([NSURL fileURLWithPath:path]);
1304 MPMoviePlayerController *controller = [[$MPMoviePlayerController alloc] initWithContentURL:url];
1305 controller.movieControlMode = MPMovieControlModeHidden;
1308 MPVideoView *video = [[[$MPVideoView alloc] initWithFrame:[indirect bounds]] autorelease];
1309 [video setMovieWithPath:path];
1310 [video setRepeatMode:1];
1311 [video setRepeatGap:-1];
1312 [video playFromBeginning];;
1315 [indirect addSubview:video];
1318 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"Wallpaper.png", @"Wallpaper.jpg", nil]), themes)) {
1319 if (UIImage *image = $getImage$(path)) {
1320 WallpaperFile_ = [path retain];
1321 WallpaperImage_ = [[UIImageView alloc] initWithImage:image];
1322 if (NSNumber *number = [Info_ objectForKey:@"WallpaperAlpha"])
1323 [WallpaperImage_ setAlpha:[number floatValue]];
1324 [indirect addSubview:WallpaperImage_];
1328 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.html"], themes)) {
1329 CGRect bounds = [indirect bounds];
1331 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1332 [view setAutoresizes:true];
1334 WallpaperPage_ = [view retain];
1335 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
1337 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1339 [view setBackgroundColor:[UIColor clearColor]];
1340 if ([view respondsToSelector:@selector(setDrawsBackground:)])
1341 [view setDrawsBackground:NO];
1342 [[view webView] setDrawsBackground:NO];
1344 [indirect addSubview:view];
1348 for (size_t i(0), e([Themes_ count]); i != e; ++i) {
1349 NSString *theme = [Themes_ objectAtIndex:(e - i - 1)];
1350 NSString *html = [theme stringByAppendingPathComponent:@"Widget.html"];
1351 if ([Manager_ fileExistsAtPath:html]) {
1352 CGRect bounds = [indirect bounds];
1354 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1355 [view setAutoresizes:true];
1357 NSURL *url = [NSURL fileURLWithPath:html];
1358 [view loadRequest:[NSURLRequest requestWithURL:url]];
1360 [view setBackgroundColor:[UIColor clearColor]];
1361 if ([view respondsToSelector:@selector(setDrawsBackground:)])
1362 [view setDrawsBackground:NO];
1363 [[view webView] setDrawsBackground:NO];
1365 [indirect addSubview:view];
1373 MSHook(void, SBAwayView$updateDesktopImage$, SBAwayView *self, SEL sel, UIImage *image) {
1374 NSString *path = $getTheme$([NSArray arrayWithObject:@"LockBackground.html"]);
1375 UIView *&_backgroundView(MSHookIvar<UIView *>(self, "_backgroundView"));
1377 if (path != nil && _backgroundView != nil)
1380 _SBAwayView$updateDesktopImage$(self, sel, image);
1383 CGRect bounds = [self bounds];
1385 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1386 [view setAutoresizes:true];
1388 if (WallpaperPage_ != nil)
1389 [WallpaperPage_ release];
1390 WallpaperPage_ = [view retain];
1392 if (WallpaperURL_ != nil)
1393 [WallpaperURL_ release];
1394 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
1396 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1398 [[view webView] setDrawsBackground:false];
1399 [view setBackgroundColor:[UIColor clearColor]];
1401 [self insertSubview:view aboveSubview:_backgroundView];
1403 if ($objc_setAssociatedObject != NULL)
1404 $objc_setAssociatedObject(self, @selector(wb$widgetView), view, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1408 MSHook(void, SBAwayView$_addSubview$positioned$relativeTo$, SBAwayView *self, SEL sel, UIView *view, int positioned, UIView *relative) {
1409 UIView *&_backgroundView(MSHookIvar<UIView *>(self, "_backgroundView"));
1410 UIView *&_chargingView(MSHookIvar<UIView *>(self, "_chargingView"));
1411 if (&_chargingView != NULL)
1412 if (positioned == -2 && (relative == _backgroundView && _chargingView == nil || relative == _chargingView))
1413 if ($objc_getAssociatedObject != NULL)
1414 if (UIView *widget = $objc_getAssociatedObject(self, @selector(wb$widgetView)))
1416 return _SBAwayView$_addSubview$positioned$relativeTo$(self, sel, view, positioned, relative);
1419 /*extern "C" CGColorRef CGGStateGetSystemColor(void *);
1420 extern "C" CGColorRef CGGStateGetFillColor(void *);
1421 extern "C" CGColorRef CGGStateGetStrokeColor(void *);
1422 extern "C" NSString *UIStyleStringFromColor(CGColorRef);*/
1424 /* WBTimeLabel {{{ */
1425 @interface WBTimeLabel : NSProxy {
1427 _transient SBStatusBarTimeView *view_;
1430 - (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view;
1434 @implementation WBTimeLabel
1441 - (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view {
1442 time_ = [time retain];
1447 - (NSString *) description {
1453 - (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(UILineBreakMode)mode {
1454 if (NSString *custom = [Info_ objectForKey:@"TimeStyle"]) {
1455 BOOL &_mode(MSHookIvar<BOOL>(view_, "_mode"));;
1457 [time_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1458 "font-family: Helvetica; "
1459 "font-weight: bold; "
1462 "%@", _mode ? @"white" : @"black", custom]];
1467 return [time_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1472 /* WBBadgeLabel {{{ */
1473 @interface WBBadgeLabel : NSProxy {
1477 - (id) initWithBadge:(NSString *)badge;
1478 - (NSString *) description;
1482 @implementation WBBadgeLabel
1489 - (id) initWithBadge:(NSString *)badge {
1490 badge_ = [badge retain];
1494 - (NSString *) description {
1495 return [badge_ description];
1500 - (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(UILineBreakMode)mode {
1501 if (NSString *custom = [Info_ objectForKey:@"BadgeStyle"]) {
1502 [badge_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1503 "font-family: Helvetica; "
1504 "font-weight: bold; "
1512 return [badge_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1519 MSInstanceMessageHook1(void, SBIcon, setIconImageAlpha, CGFloat, alpha) {
1520 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1521 alpha = [number floatValue];
1522 return MSOldCall(alpha);
1525 MSInstanceMessageHook1(void, SBIcon, setIconLabelAlpha, CGFloat, alpha) {
1526 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1527 alpha = [number floatValue];
1528 return MSOldCall(alpha);
1531 MSInstanceMessageHook0(id, SBIcon, initWithDefaultSize) {
1532 if ((self = MSOldCall()) != nil) {
1533 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"]) {
1534 // XXX: note: this is overridden above, which is silly
1535 float alpha([number floatValue]);
1536 if ([self respondsToSelector:@selector(setIconImageAlpha:)])
1537 [self setIconImageAlpha:alpha];
1538 if ([self respondsToSelector:@selector(setIconLabelAlpha:)])
1539 [self setIconLabelAlpha:alpha];
1540 if ([self respondsToSelector:@selector(setAlpha:)])
1541 [self setAlpha:alpha];
1546 MSInstanceMessageHook1(void, SBIcon, setAlpha, CGFloat, alpha) {
1547 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1548 alpha = [number floatValue];
1549 return MSOldCall(alpha);
1553 MSHook(id, SBIconBadge$initWithBadge$, SBIconBadge *self, SEL sel, NSString *badge) {
1554 if ((self = _SBIconBadge$initWithBadge$(self, sel, badge)) != nil) {
1555 id &_badge(MSHookIvar<id>(self, "_badge"));
1557 if (id label = [[WBBadgeLabel alloc] initWithBadge:[_badge autorelease]])
1562 void SBStatusBarController$setStatusBarMode(int &mode) {
1564 NSLog(@"WB:Debug:setStatusBarMode:%d", mode);
1565 if (mode < 100) // 104:hidden 105:glowing
1566 if (NSNumber *number = [Info_ objectForKey:@"StatusBarMode"])
1567 mode = [number intValue];
1570 /*MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, double duration, int animation) {
1571 NSLog(@"mode:%d orientation:%d duration:%f animation:%d", mode, orientation, duration, animation);
1572 SBStatusBarController$setStatusBarMode(mode);
1573 return _SBStatusBarController$setStatusBarMode$orientation$duration$animation$(self, sel, mode, orientation, duration, animation);
1576 MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, float duration, int fenceID, int animation) {
1577 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d", mode, orientation, duration, fenceID, animation);
1578 SBStatusBarController$setStatusBarMode(mode);
1579 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$(self, sel, mode, orientation, duration, fenceID, animation);
1582 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) {
1583 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d startTime:%f", mode, orientation, duration, fenceID, animation, startTime);
1584 SBStatusBarController$setStatusBarMode(mode);
1585 //NSLog(@"mode=%u", mode);
1586 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$startTime$(self, sel, mode, orientation, duration, fenceID, animation, startTime);
1589 /*MSHook(id, SBStatusBarContentsView$initWithStatusBar$mode$, SBStatusBarContentsView *self, SEL sel, id bar, int mode) {
1590 if (NSNumber *number = [Info_ objectForKey:@"StatusBarContentsMode"])
1591 mode = [number intValue];
1592 return _SBStatusBarContentsView$initWithStatusBar$mode$(self, sel, bar, mode);
1595 MSHook(NSString *, SBStatusBarOperatorNameView$operatorNameStyle, SBStatusBarOperatorNameView *self, SEL sel) {
1596 NSString *style(_SBStatusBarOperatorNameView$operatorNameStyle(self, sel));
1598 NSLog(@"operatorNameStyle= %@", style);
1599 if (NSString *custom = [Info_ objectForKey:@"OperatorNameStyle"])
1600 style = [NSString stringWithFormat:@"%@; %@", style, custom];
1604 MSHook(void, SBStatusBarOperatorNameView$setOperatorName$fullSize$, SBStatusBarOperatorNameView *self, SEL sel, NSString *name, BOOL full) {
1606 NSLog(@"setOperatorName:\"%@\" fullSize:%u", name, full);
1607 return _SBStatusBarOperatorNameView$setOperatorName$fullSize$(self, sel, name, NO);
1610 // XXX: replace this with [SBStatusBarTimeView tile]
1611 MSHook(void, SBStatusBarTimeView$drawRect$, SBStatusBarTimeView *self, SEL sel, CGRect rect) {
1612 id &_time(MSHookIvar<id>(self, "_time"));
1613 if (_time != nil && [_time class] != [WBTimeLabel class])
1614 object_setInstanceVariable(self, "_time", reinterpret_cast<void *>([[WBTimeLabel alloc] initWithTime:[_time autorelease] view:self]));
1615 return _SBStatusBarTimeView$drawRect$(self, sel, rect);
1618 @interface UIView (WinterBoard)
1619 - (bool) wb$isWBImageView;
1620 - (void) wb$logHierarchy;
1621 - (void) wb$setBackgroundColor:(UIColor *)color;
1624 @implementation UIView (WinterBoard)
1626 - (bool) wb$isWBImageView {
1630 - (void) wb$logHierarchy {
1631 WBLogHierarchy(self);
1634 - (void) wb$setBackgroundColor:(UIColor *)color {
1635 [self setBackgroundColor:color];
1636 for (UIView *child in [self subviews])
1637 [child wb$setBackgroundColor:color];
1642 @interface WBImageView : UIImageView {
1645 - (bool) wb$isWBImageView;
1646 - (void) wb$updateFrame;
1649 @implementation WBImageView
1651 - (bool) wb$isWBImageView {
1655 - (void) wb$updateFrame {
1656 CGRect frame([self frame]);
1659 for (UIView *view(self); ; ) {
1660 view = [view superview];
1663 frame.origin.y -= [view frame].origin.y;
1666 [self setFrame:frame];
1671 static void SBIconList$updateFrames$(SBIconList *self) {
1672 NSArray *subviews([self subviews]);
1673 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1674 if (view != nil && [view wb$isWBImageView])
1675 [view wb$updateFrame];
1678 MSHook(void, SBIconList$didMoveToSuperview, SBIconList *self, SEL sel) {
1679 SBIconList$updateFrames$(self);
1680 _SBIconList$didMoveToSuperview(self, sel);
1683 MSHook(void, SBIconList$setFrame$, SBIconList *self, SEL sel, CGRect frame) {
1684 SBIconList$updateFrames$(self);
1685 _SBIconList$setFrame$(self, sel, frame);
1688 static void $addPerPageView$(unsigned i, UIView *list) {
1689 NSString *path($getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Page%u.png", i]]));
1693 NSArray *subviews([list subviews]);
1695 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1696 if (view == nil || ![view wb$isWBImageView]) {
1697 view = [[[WBImageView alloc] init] autorelease];
1698 [list insertSubview:view atIndex:0];
1701 UIImage *image([UIImage imageWithContentsOfFile:path]);
1703 CGRect frame([view frame]);
1704 frame.size = [image size];
1705 [view setFrame:frame];
1707 [view setImage:image];
1708 [view wb$updateFrame];
1711 static void $addPerPageViews$(NSArray *lists) {
1712 for (unsigned i(0), e([lists count]); i != e; ++i)
1713 $addPerPageView$(i, [lists objectAtIndex:i]);
1716 MSInstanceMessageHook0(void, SBIconController, updateNumberOfRootIconLists) {
1717 NSArray *&_rootIconLists(MSHookIvar<NSArray *>(self, "_rootIconLists"));
1718 $addPerPageViews$(_rootIconLists);
1722 MSInstanceMessageHook0(void, SBIconContentView, layoutSubviews) {
1725 if (SBIconController *controller = [$SBIconController sharedInstance]) {
1726 UIView *&_dockContainerView(MSHookIvar<UIView *>(controller, "_dockContainerView"));
1727 if (&_dockContainerView != NULL)
1728 [[_dockContainerView superview] bringSubviewToFront:_dockContainerView];
1732 MSHook(void, SBIconController$noteNumberOfIconListsChanged, SBIconController *self, SEL sel) {
1733 SBIconModel *&_iconModel(MSHookIvar<SBIconModel *>(self, "_iconModel"));
1734 $addPerPageViews$([_iconModel iconLists]);
1735 return _SBIconController$noteNumberOfIconListsChanged(self, sel);
1738 MSHook(id, SBIconLabel$initWithSize$label$, SBIconLabel *self, SEL sel, CGSize size, NSString *label) {
1739 self = _SBIconLabel$initWithSize$label$(self, sel, size, label);
1741 [self setClipsToBounds:NO];
1745 MSHook(void, SBIconLabel$setInDock$, SBIconLabel *self, SEL sel, BOOL docked) {
1746 static bool gssc(false);
1748 BOOL (*GSSystemHasCapability)(CFStringRef) = reinterpret_cast<BOOL (*)(CFStringRef)>(dlsym(RTLD_DEFAULT, "GSSystemHasCapability"));
1749 Papered_ |= GSSystemHasCapability != NULL && GSSystemHasCapability(CFSTR("homescreen-wallpaper"));
1752 if ([Info_ objectForKey:@"UndockedIconLabels"] == nil)
1753 [Info_ setObject:[NSNumber numberWithBool:(
1755 [Info_ objectForKey:@"DockedIconLabelStyle"] != nil ||
1756 [Info_ objectForKey:@"UndockedIconLabelStyle"] != nil
1757 )] forKey:@"UndockedIconLabels"];
1760 id &_label(MSHookIvar<id>(self, "_label"));
1761 if (![Info_ wb$boolForKey:@"UndockedIconLabels"])
1764 if (_label != nil && [_label respondsToSelector:@selector(setInDock:)])
1765 [_label setInDock:docked];
1767 _SBIconLabel$setInDock$(self, sel, docked);
1768 [self setNeedsDisplay];
1771 MSHook(BOOL, SBDockIconListView$shouldShowNewDock, id self, SEL sel) {
1772 return SummerBoard_ && Docked_ ? NO : _SBDockIconListView$shouldShowNewDock(self, sel);
1775 MSHook(void, SBDockIconListView$setFrame$, id self, SEL sel, CGRect frame) {
1776 _SBDockIconListView$setFrame$(self, sel, frame);
1779 // %hook -[NSBundle localizedStringForKey:value:table:] {{{
1780 MSInstanceMessageHook3(NSString *, NSBundle, localizedStringForKey,value,table, NSString *, key, NSString *, value, NSString *, table) {
1781 NSString *identifier = [self bundleIdentifier];
1782 NSLocale *locale = [NSLocale currentLocale];
1783 NSString *language = [locale objectForKey:NSLocaleLanguageCode];
1785 NSLog(@"WB:Debug:[NSBundle(%@) localizedStringForKey:\"%@\" value:\"%@\" table:\"%@\"] (%@)", identifier, key, value, table, language);
1786 NSString *file = table == nil ? @"Localizable" : table;
1787 NSString *name = [NSString stringWithFormat:@"%@:%@", identifier, file];
1788 NSDictionary *strings;
1789 if ((strings = [Strings_ objectForKey:name]) != nil) {
1790 if (static_cast<id>(strings) != [NSNull null]) strings:
1791 if (NSString *value = [strings objectForKey:key])
1793 } else if (NSString *path = $pathForFile$inBundle$([NSString stringWithFormat:@"%@.lproj/%@.strings",
1795 ], self, false, false)) {
1796 if ((strings = [[NSDictionary alloc] initWithContentsOfFile:path]) != nil) {
1797 [Strings_ setObject:[strings autorelease] forKey:name];
1801 [Strings_ setObject:[NSNull null] forKey:name];
1802 return MSOldCall(key, value, table);
1805 // %hook -[WebCoreFrameBridge renderedSizeOfNode:constrainedToWidth:] {{{
1806 MSClassHook(WebCoreFrameBridge)
1808 MSInstanceMessageHook2(CGSize, WebCoreFrameBridge, renderedSizeOfNode,constrainedToWidth, id, node, float, width) {
1811 void **core(reinterpret_cast<void **>([node _node]));
1812 if (core == NULL || core[6] == NULL)
1814 return MSOldCall(node, width);
1818 MSInstanceMessage1(void, SBIconLabel, drawRect, CGRect, rect) {
1819 static Ivar drawMoreLegibly = object_getInstanceVariable(self, "_drawMoreLegibly", NULL);
1822 Ivar ivar = object_getInstanceVariable(self, "_inDock", reinterpret_cast<void **>(&docked));
1823 docked = (docked & (ivar_getOffset(ivar) == ivar_getOffset(drawMoreLegibly) ? 0x2 : 0x1)) != 0;
1825 NSString *label(MSHookIvar<NSString *>(self, "_label"));
1827 NSString *style = [NSString stringWithFormat:@""
1828 "font-family: Helvetica; "
1829 "font-weight: bold; "
1831 "", (docked || !SummerBoard_ ? @"white" : @"#b3b3b3"), (IsWild_
1832 ? @"font-size: 12px; "
1833 : @"font-size: 11px; "
1837 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px 1px 0px; "];
1839 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px -1px 0px; "];
1841 NSString *custom([Info_ objectForKey:(docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle")]);
1843 $drawLabel$(label, [self bounds], style, custom);
1846 MSInstanceMessage0(CGImageRef, SBIconLabel, buildLabelImage) {
1847 bool docked((MSHookIvar<unsigned>(self, "_inDock") & 0x2) != 0);
1849 WBStringDrawingState labelState = {NULL, 0, @""
1850 , docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle"};
1852 stringDrawingState_ = &labelState;
1855 CGImageRef image(MSOldCall());
1858 stringDrawingState_ = NULL;
1862 static bool wb$inDock(id parameters) {
1863 return [$objc_getAssociatedObject(parameters, @selector(wb$inDock)) boolValue];
1866 MSInstanceMessage0(NSUInteger, SBIconLabelImageParameters, hash) {
1867 return MSOldCall() + (wb$inDock(self) ? 0xdeadbeef : 0xd15ea5e);
1870 MSClassMessage2(id, SBIconView, _labelImageParametersForIcon,location, id, icon, int, location) {
1871 if (id parameters = MSOldCall(icon, location)) {
1872 $objc_setAssociatedObject(parameters, @selector(wb$inDock), [NSNumber numberWithBool:(location == 1)], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1877 MSInstanceMessage0(id, SBIconView, _labelImageParameters) {
1878 if (id parameters = MSOldCall()) {
1879 int &location(MSHookIvar<int>(self, "_iconLocation"));
1880 if (&location != NULL)
1881 $objc_setAssociatedObject(parameters, @selector(wb$inDock), [NSNumber numberWithBool:(location == 3)], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1886 MSClassMessage1(UIImage *, SBIconLabelImage, _drawLabelImageForParameters, id, parameters) {
1887 bool docked(wb$inDock(parameters));
1889 WBStringDrawingState labelState = {NULL, 0, @""
1890 , docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle"};
1892 stringDrawingState_ = &labelState;
1895 UIImage *image(MSOldCall(parameters));
1898 stringDrawingState_ = NULL;
1903 MSInstanceMessageHook2(id, CKBalloonView, initWithFrame,delegate, CGRect, frame, id, delegate) {
1904 if ((self = MSOldCall(frame, delegate)) != nil) {
1905 [self setBackgroundColor:[UIColor clearColor]];
1909 MSInstanceMessageHook0(BOOL, CKBalloonView, _canUseLayerBackedBalloon) {
1910 return SMSBackgrounded_ ? NO : MSOldCall();
1913 MSInstanceMessageHook0(void, CKTranscriptHeaderView, layoutSubviews) {
1914 [self wb$setBackgroundColor:[UIColor clearColor]];
1918 MSInstanceMessageHook1(void, CKMessageCell, addBalloonView, CKBalloonView *, balloon) {
1920 [balloon setBackgroundColor:[UIColor clearColor]];
1923 MSInstanceMessageHook1(void, CKTranscriptCell, setBackgroundColor, UIColor *, color) {
1924 MSOldCall([UIColor clearColor]);
1925 [[self contentView] wb$setBackgroundColor:[UIColor clearColor]];
1929 MSInstanceMessageHook2(id, CKTranscriptCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1930 if ((self = MSOldCall(style, reuse)) != nil) {
1931 [self setBackgroundColor:[UIColor clearColor]];
1932 [[self contentView] wb$setBackgroundColor:[UIColor clearColor]];
1937 MSInstanceMessageHook2(id, CKMessageCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1938 if ((self = MSOldCall(style, reuse)) != nil) {
1939 [self setBackgroundColor:[UIColor clearColor]];
1940 [[self contentView] setBackgroundColor:[UIColor clearColor]];
1944 MSInstanceMessageHook2(id, CKTimestampView, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1945 if ((self = MSOldCall(style, reuse)) != nil) {
1946 UILabel *&_label(MSHookIvar<UILabel *>(self, "_label"));
1947 [_label setBackgroundColor:[UIColor clearColor]];
1951 MSInstanceMessageHook1(void, CKTranscriptTableView, setSeparatorStyle, int, style) {
1952 MSOldCall(UITableViewCellSeparatorStyleNone);
1955 MSInstanceMessageHook2(id, CKTranscriptTableView, initWithFrame,style, CGRect, frame, int, style) {
1956 if ((self = MSOldCall(frame, style)) != nil) {
1957 [self setSeparatorStyle:UITableViewCellSeparatorStyleNone];
1961 MSInstanceMessageHook0(void, CKTranscriptController, loadView) {
1964 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"SMSBackground.png", @"SMSBackground.jpg", nil])))
1965 if (UIImage *image = $getImage$(path)) {
1966 SMSBackgrounded_ = true;
1968 UIView *&_transcriptTable(MSHookIvar<UIView *>(self, "_transcriptTable"));
1969 UIView *&_transcriptLayer(MSHookIvar<UIView *>(self, "_transcriptLayer"));
1971 if (&_transcriptTable != NULL)
1972 table = _transcriptTable;
1973 else if (&_transcriptLayer != NULL)
1974 table = _transcriptLayer;
1978 UIView *placard(table != nil ? [table superview] : MSHookIvar<UIView *>(self, "_backPlacard"));
1979 UIImageView *background([[[UIImageView alloc] initWithImage:image] autorelease]);
1982 [placard insertSubview:background atIndex:0];
1984 [table setBackgroundColor:[UIColor clearColor]];
1985 [placard insertSubview:background belowSubview:table];
1991 template <typename Original_>
1992 static UIImage *WBCacheUIImage(const Original_ &original, NSString *name, NSString *key) {
1993 if ([name rangeOfString:@"."].location == NSNotFound)
1994 name = [name stringByAppendingString:@".png"];
1995 UIImage *image(WBCacheImage(original, [=](){ return $pathForFile$inBundle$(name, _UIKitBundle(), true, true); }, key));
1996 if (image != nil && UIDebug_) {
1997 NSString *path([@"/tmp/UIImages/" stringByAppendingString:name]);
1998 if (![Manager_ fileExistsAtPath:path])
1999 [UIImagePNGRepresentation(image) writeToFile:path atomically:YES];
2003 // %hook _UIImageWithName() {{{
2004 MSHook(UIImage *, _UIImageWithName, NSString *name) {
2008 NSLog(@"WB:Debug: _UIImageWithName(\"%@\")", name);
2009 return WBCacheUIImage(
2010 [=](){ return __UIImageWithName(name); },
2011 name, [NSString stringWithFormat:@"I:%@", name]);
2014 // %hook _UIImageWithNameInDomain() {{{
2015 MSHook(UIImage *, _UIImageWithNameInDomain, NSString *name, NSString *domain) {
2017 NSLog(@"WB:Debug: _UIImageWithNameInDomain(\"%@\", \"%@\")", name, domain);
2018 return WBCacheImage(
2019 [=](){ return __UIImageWithNameInDomain(name, domain); },
2020 [=](){ return $getTheme$($useScale$([NSArray arrayWithObject:[NSString stringWithFormat:@"Domains/%@/%@", domain, name]])); },
2021 [NSString stringWithFormat:@"D:%zu:%@%@", size_t([domain length]), domain, name]);
2024 // %hook _UIImageWithDeviceUsingCurrentIdiom() {{{
2025 MSHook(UIImage *, _UIImageWithNameUsingCurrentIdiom, NSString *name) {
2027 NSLog(@"WB:Debug: _UIImageWithNameUsingCurrentIdiom(\"%@\")", name);
2028 return WBCacheUIImage(
2029 [=](){ return __UIImageWithNameUsingCurrentIdiom(name); },
2030 name, [NSString stringWithFormat:@"I:%@", name]);
2033 // %hook _UIImageWithDeviceSpecificName() {{{
2034 MSHook(UIImage *, _UIImageWithDeviceSpecificName, NSString *name) {
2036 NSLog(@"WB:Debug: _UIImageWithDeviceSpecificName(\"%@\")", name);
2037 return WBCacheUIImage(
2038 [=](){ return __UIImageWithDeviceSpecificName(name); },
2039 name, [NSString stringWithFormat:@"S:%@", name]);
2043 // %hook GSFontCreateWithName() {{{
2044 MSHook(GSFontRef, GSFontCreateWithName, const char *name, GSFontSymbolicTraits traits, float size) {
2046 NSLog(@"WB:Debug: GSFontCreateWithName(\"%s\", %f)", name, size);
2047 if (NSString *font = [Info_ objectForKey:[NSString stringWithFormat:@"FontName-%s", name]])
2048 name = [font UTF8String];
2049 //if (NSString *scale = [Info_ objectForKey:[NSString stringWithFormat:@"FontScale-%s", name]])
2050 // size *= [scale floatValue];
2051 return _GSFontCreateWithName(name, traits, size);
2055 #define AudioToolbox "/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox"
2057 static bool GetFileNameForThisAction$(bool value, unsigned long a0, char *a1, unsigned long a2, bool &a3) {
2059 NSLog(@"WB:Debug:GetFileNameForThisAction(%lu, %s, %lu, %u) = %u", a0, value ? a1 : NULL, a2, a3, value);
2062 NSString *path = [NSString stringWithUTF8String:a1];
2063 if ([path hasPrefix:@"/System/Library/Audio/UISounds/"]) {
2064 NSString *file = [path substringFromIndex:31];
2065 for (NSString *theme in Themes_) {
2066 NSString *path([NSString stringWithFormat:@"%@/UISounds/%@", theme, file]);
2067 if ([Manager_ fileExistsAtPath:path]) {
2068 strcpy(a1, [path UTF8String]);
2077 MSHook(bool, _Z24GetFileNameForThisActionmPcRb, unsigned long a0, char *a1, bool &a3) {
2078 bool value(__Z24GetFileNameForThisActionmPcRb(a0, a1, a3));
2079 return GetFileNameForThisAction$(value, a0, a1, 0, a3);
2082 MSHook(bool, _Z24GetFileNameForThisActionmPcmRb, unsigned long a0, char *a1, unsigned long a2, bool &a3) {
2083 bool value(__Z24GetFileNameForThisActionmPcmRb(a0, a1, a2, a3));
2084 return GetFileNameForThisAction$(value, a0, a1, a2, a3);
2087 static void ChangeWallpaper(
2088 CFNotificationCenterRef center,
2092 CFDictionaryRef info
2095 NSLog(@"WB:Debug:ChangeWallpaper!");
2098 if (WallpaperFile_ != nil) {
2099 image = [[UIImage alloc] initWithContentsOfFile:WallpaperFile_];
2101 image = [image autorelease];
2104 if (WallpaperImage_ != nil)
2105 [WallpaperImage_ setImage:image];
2106 if (WallpaperPage_ != nil)
2107 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
2111 MSHook(NSArray *, CPBitmapCreateImagesFromPath, NSString *path, NSDictionary **names, void *arg2, void *arg3) {
2112 NSArray *images(_CPBitmapCreateImagesFromPath(path, names, arg2, arg3));
2113 if (images != NULL && *names != nil && CFGetTypeID((CFTypeRef) *names) == CFDictionaryGetTypeID()) {
2114 if (NSBundle *bundle = [NSBundle wb$bundleWithFile:path]) {
2115 NSMutableArray *copy([images mutableCopy]);
2119 NSString *file([path stringByResolvingSymlinksInPath]);
2120 NSString *prefix([[bundle bundlePath] stringByResolvingSymlinksInPath]);
2121 if ([file hasPrefix:prefix]) {
2122 NSUInteger length([prefix length]);
2123 if (length != [file length]) {
2124 NSEnumerator *enumerator([*names keyEnumerator]);
2125 while (NSString *name = [enumerator nextObject]) {
2126 NSString *png([name stringByAppendingString:@".png"]);
2127 if (NSString *themed = $pathForFile$inBundle$(png, bundle, false, true)) {
2128 NSUInteger index([[*names objectForKey:name] intValue]);
2129 UIImage *image($getImage$(themed));
2130 CGImageRef cg([image CGImage]);
2131 [copy replaceObjectAtIndex:index withObject:(id)cg];
2140 MSHook(void, BKSDisplayServicesSetSystemAppExitedImagePath, NSString *path) {
2141 if (NSString *themed = $getTheme$($useScale$([NSArray arrayWithObject:@"SystemAppExited.png"])))
2143 _BKSDisplayServicesSetSystemAppExitedImagePath(path);
2146 #define WBRename(name, sel, imp) \
2147 MSHookMessage($ ## name, @selector(sel), &$ ## name ## $ ## imp, &_ ## name ## $ ## imp)
2149 template <typename Type_>
2150 static void msset(Type_ &function, MSImageRef image, const char *name) {
2151 function = reinterpret_cast<Type_>(MSFindSymbol(image, name));
2154 #define WBHookSymbol(image, function) \
2155 msset(function, image, "_" #function)
2157 template <typename Type_>
2158 static void dlset(Type_ &function, const char *name) {
2159 function = reinterpret_cast<Type_>(dlsym(RTLD_DEFAULT, name));
2162 // %hook CGImageReadCreateWithFile() {{{
2163 MSHook(void *, CGImageReadCreateWithFile, NSString *path, int flag) {
2165 NSLog(@"WB:Debug: CGImageReadCreateWithFile(%@, %d)", path, flag);
2166 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2167 void *value(_CGImageReadCreateWithFile([path wb$themedPath], flag));
2172 MSHook(void *, CGImageSourceCreateWithFile, NSString *path, NSDictionary *options) {
2174 NSLog(@"WB:Debug: CGImageSourceCreateWithFile(%@, %@)", path, options);
2175 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2176 void *value(_CGImageSourceCreateWithFile([path wb$themedPath], options));
2181 MSHook(void *, CGImageSourceCreateWithURL, NSURL *url, NSDictionary *options) {
2183 NSLog(@"WB:Debug: CGImageSourceCreateWithURL(%@, %@)", url, options);
2184 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2185 if ([url isFileURL])
2186 url = [NSURL fileURLWithPath:[[url path] wb$themedPath]];
2187 void *value(_CGImageSourceCreateWithURL(url, options));
2193 static void NSString$drawAtPoint$withStyle$(NSString *self, SEL _cmd, CGPoint point, NSString *style) {
2194 WKSetCurrentGraphicsContext(UIGraphicsGetCurrentContext());
2195 if (style == nil || [style length] == 0)
2196 style = @"font-family: Helvetica; font-size: 12px";
2197 //NSLog(@"XXX:drawP(%@ | %@)", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "]);
2198 [[WBMarkup sharedMarkup] drawString:self atPoint:point withStyle:style];
2201 static void NSString$drawInRect$withStyle$(NSString *self, SEL _cmd, CGRect rect, NSString *style) {
2202 WKSetCurrentGraphicsContext(UIGraphicsGetCurrentContext());
2203 if (style == nil || [style length] == 0)
2204 style = @"font-family: Helvetica; font-size: 12px";
2205 //NSLog(@"XXX:drawR(%@ | %@)", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "]);
2206 return [[WBMarkup sharedMarkup] drawString:self inRect:rect withStyle:style];
2209 static CGSize NSString$sizeWithStyle$forWidth$(NSString *self, SEL _cmd, NSString *style, CGFloat width) {
2210 if (style == nil || [style length] == 0)
2211 style = @"font-family: Helvetica; font-size: 12px";
2212 CGSize size([[WBMarkup sharedMarkup] sizeOfString:self withStyle:style forWidth:width]);
2213 //NSLog(@"XXX:size(%@ | %@) = [%g %g]", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "], size.width, size.height);
2217 static void SBInitialize() {
2219 WBRename(SBApplication, pathForIcon, pathForIcon);
2220 WBRename(SBApplicationIcon, icon, icon);
2221 WBRename(SBApplicationIcon, generateIconImage:, generateIconImage$);
2224 WBRename(SBBookmarkIcon, icon, icon);
2225 WBRename(SBButtonBar, didMoveToSuperview, didMoveToSuperview);
2226 WBRename(SBCalendarIconContentsView, drawRect:, drawRect$);
2227 WBRename(SBIconBadge, initWithBadge:, initWithBadge$);
2228 WBRename(SBIconController, noteNumberOfIconListsChanged, noteNumberOfIconListsChanged);
2230 WBRename(SBWidgetApplicationIcon, icon, icon);
2232 WBRename(SBDockIconListView, setFrame:, setFrame$);
2233 MSHookMessage(object_getClass($SBDockIconListView), @selector(shouldShowNewDock), &$SBDockIconListView$shouldShowNewDock, &_SBDockIconListView$shouldShowNewDock);
2235 if (kCFCoreFoundationVersionNumber < 600 || SummerBoard_)
2236 WBRename(SBIconLabel, drawRect:, drawRect$);
2237 else if (kCFCoreFoundationVersionNumber < 700) {
2238 WBRename(SBIconLabel, buildLabelImage, buildLabelImage);
2240 WBRename(SBIconLabelImageParameters, hash, hash);
2241 WBRename($SBIconView, _labelImageParametersForIcon:location:, _labelImageParametersForIcon$location$);
2242 WBRename(SBIconView, _labelImageParameters, _labelImageParameters);
2243 WBRename($SBIconLabelImage, _drawLabelImageForParameters:, _drawLabelImageForParameters$);
2246 WBRename(SBIconLabel, initWithSize:label:, initWithSize$label$);
2247 WBRename(SBIconLabel, setInDock:, setInDock$);
2249 WBRename(SBIconList, didMoveToSuperview, didMoveToSuperview);
2250 WBRename(SBIconList, setFrame:, setFrame$);
2252 WBRename(SBIconModel, cacheImageForIcon:, cacheImageForIcon$);
2253 WBRename(SBIconModel, cacheImagesForIcon:, cacheImagesForIcon$);
2254 WBRename(SBIconModel, getCachedImagedForIcon:, getCachedImagedForIcon$);
2255 WBRename(SBIconModel, getCachedImagedForIcon:smallIcon:, getCachedImagedForIcon$smallIcon$);
2257 if (kCFCoreFoundationVersionNumber < 800) {
2258 WBRename(SBSearchView, initWithFrame:, initWithFrame$);
2259 WBRename(SBSearchTableViewCell, drawRect:, drawRect$);
2260 WBRename(SBSearchTableViewCell, initWithStyle:reuseIdentifier:, initWithStyle$reuseIdentifier$);
2263 //WBRename(SBImageCache, initWithName:forImageWidth:imageHeight:initialCapacity:, initWithName$forImageWidth$imageHeight$initialCapacity$);
2265 WBRename(SBAwayView, updateDesktopImage:, updateDesktopImage$);
2266 if (kCFCoreFoundationVersionNumber >= 700)
2267 WBRename(SBAwayView, _addSubview:positioned:relativeTo:, _addSubview$positioned$relativeTo$);
2269 WBRename(SBStatusBarContentsView, didMoveToSuperview, didMoveToSuperview);
2270 //WBRename(SBStatusBarContentsView, initWithStatusBar:mode:, initWithStatusBar$mode$);
2271 //WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:animation:, setStatusBarMode$orientation$duration$animation$);
2272 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:, setStatusBarMode$orientation$duration$fenceID$animation$);
2273 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:startTime:, setStatusBarMode$orientation$duration$fenceID$animation$startTime$);
2274 WBRename(SBStatusBarOperatorNameView, operatorNameStyle, operatorNameStyle);
2275 WBRename(SBStatusBarOperatorNameView, setOperatorName:fullSize:, setOperatorName$fullSize$);
2276 WBRename(SBStatusBarTimeView, drawRect:, drawRect$);
2279 English_ = [[NSDictionary alloc] initWithContentsOfFile:@"/System/Library/CoreServices/SpringBoard.app/English.lproj/LocalizedApplicationNames.strings"];
2281 if (kCFCoreFoundationVersionNumber >= 800) {
2282 WBRename(NSString, drawInRect:withAttributes:, drawInRect$withAttributes$);
2283 WBRename(NSString, boundingRectWithSize:options:attributes:context:, boundingRectWithSize$options$attributes$context$);
2287 /*MSHook(int, open, const char *path, int oflag, mode_t mode) {
2288 int fd(_open(path, oflag, mode));
2290 static bool no(false);
2294 if (strstr(path, "/icon") != NULL)
2295 MSHookProcess(-1, "");
2297 if (fd == -1 && errno == EFAULT)
2298 NSLog(@"open(%p, %#x, %#o) = %d\n", path, oflag, mode, fd);
2300 NSLog(@"open(\"%s\", %#x, %#o) = %d\n", path, oflag, mode, fd);
2307 $objc_setAssociatedObject = reinterpret_cast<void (*)(id, void *, id value, objc_AssociationPolicy)>(dlsym(RTLD_DEFAULT, "objc_setAssociatedObject"));
2308 $objc_getAssociatedObject = reinterpret_cast<id (*)(id, void *)>(dlsym(RTLD_DEFAULT, "objc_getAssociatedObject"));
2309 $objc_removeAssociatedObjects = reinterpret_cast<void (*)(id)>(dlsym(RTLD_DEFAULT, "objc_removeAssociatedObjects"));
2311 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2313 NSString *identifier([[NSBundle mainBundle] bundleIdentifier]);
2314 SpringBoard_ = [identifier isEqualToString:@"com.apple.springboard"];
2316 Manager_ = [[NSFileManager defaultManager] retain];
2317 Themes_ = [[NSMutableArray alloc] initWithCapacity:8];
2319 dlset(_GSFontGetUseLegacyFontMetrics, "GSFontGetUseLegacyFontMetrics");
2321 // Load Settings.plist {{{
2322 if (NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"/User/Library/Preferences/com.saurik.WinterBoard.plist"]]) {
2323 if (NSNumber *value = [settings objectForKey:@"SummerBoard"])
2324 SummerBoard_ = [value boolValue];
2326 SummerBoard_ = true;
2328 if (NSNumber *value = [settings objectForKey:@"Debug"])
2329 Debug_ = [value boolValue];
2330 if (NSNumber *value = [settings objectForKey:@"RecordUI"])
2331 UIDebug_ = [value boolValue];
2333 NSArray *themes([settings objectForKey:@"Themes"]);
2335 if (NSString *theme = [settings objectForKey:@"Theme"])
2336 themes = [NSArray arrayWithObject:[NSDictionary dictionaryWithObjectsAndKeys:
2338 [NSNumber numberWithBool:true], @"Active",
2342 for (NSDictionary *theme in themes) {
2343 NSNumber *active([theme objectForKey:@"Active"]);
2344 if (![active boolValue])
2347 NSString *name([theme objectForKey:@"Name"]);
2351 #define testForTheme(format...) \
2353 NSString *path = [NSString stringWithFormat:format]; \
2354 if ([Manager_ fileExistsAtPath:path]) { \
2355 [Themes_ addObject:path]; \
2360 testForTheme(@"/Library/Themes/%@.theme", name)
2361 testForTheme(@"/Library/Themes/%@", name)
2362 testForTheme(@"%@/Library/SummerBoard/Themes/%@", NSHomeDirectory(), name)
2367 // Merge Info.plist {{{
2368 Info_ = [[NSMutableDictionary dictionaryWithCapacity:16] retain];
2370 for (NSString *theme in Themes_)
2371 if (NSDictionary *info = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"%@/Info.plist", theme]])
2372 for (NSString *key in [info allKeys])
2373 if ([Info_ objectForKey:key] == nil)
2374 [Info_ setObject:[info objectForKey:key] forKey:key];
2378 if (MSImageRef image = MSGetImageByName("/System/Library/PrivateFrameworks/AppSupport.framework/AppSupport")) {
2379 NSArray *(*CPBitmapCreateImagesFromPath)(NSString *, NSDictionary **, void *, void *);
2380 msset(CPBitmapCreateImagesFromPath, image, "_CPBitmapCreateImagesFromPath");
2381 MSHookFunction(CPBitmapCreateImagesFromPath, MSHake(CPBitmapCreateImagesFromPath));
2385 if (MSImageRef image = MSGetImageByName(AudioToolbox)) {
2386 bool (*_Z24GetFileNameForThisActionmPcRb)(unsigned long, char *, bool &);
2387 msset(_Z24GetFileNameForThisActionmPcRb, image, "__Z24GetFileNameForThisActionmPcRb");
2388 MSHookFunction(_Z24GetFileNameForThisActionmPcRb, &$_Z24GetFileNameForThisActionmPcRb, &__Z24GetFileNameForThisActionmPcRb);
2390 bool (*_Z24GetFileNameForThisActionmPcmRb)(unsigned long, char *, unsigned long, bool &);
2391 msset(_Z24GetFileNameForThisActionmPcmRb, image, "__Z24GetFileNameForThisActionmPcmRb");
2392 MSHookFunction(_Z24GetFileNameForThisActionmPcmRb, &$_Z24GetFileNameForThisActionmPcmRb, &__Z24GetFileNameForThisActionmPcmRb);
2395 // BackBoardServices {{{
2396 if (MSImageRef image = MSGetImageByName("/System/Library/PrivateFrameworks/BackBoardServices.framework/BackBoardServices")) {
2397 void (*BKSDisplayServicesSetSystemAppExitedImagePath)(NSString *path);
2398 msset(BKSDisplayServicesSetSystemAppExitedImagePath, image, "_BKSDisplayServicesSetSystemAppExitedImagePath");
2399 MSHookFunction(BKSDisplayServicesSetSystemAppExitedImagePath, MSHake(BKSDisplayServicesSetSystemAppExitedImagePath));
2402 // GraphicsServices {{{
2404 MSHookFunction(&GSFontCreateWithName, &$GSFontCreateWithName, &_GSFontCreateWithName);
2408 MSImageRef imageio = MSGetImageByName("/System/Library/Frameworks/ImageIO.framework/ImageIO");
2409 if (imageio == NULL)
2410 imageio = MSGetImageByName("/System/Library/PrivateFrameworks/ImageIO.framework/ImageIO");
2411 if (MSImageRef image = imageio) {
2412 void *(*CGImageReadCreateWithFile)(NSString *, int) = NULL;
2413 if (kCFCoreFoundationVersionNumber > 700) // XXX: iOS 6.x
2414 CGImageReadCreateWithFile = NULL;
2416 msset(CGImageReadCreateWithFile, image, "_CGImageReadCreateWithFile");
2417 MSHookFunction(CGImageReadCreateWithFile, MSHake(CGImageReadCreateWithFile));
2420 if (CGImageReadCreateWithFile == NULL) {
2421 void *(*CGImageSourceCreateWithFile)(NSString *, NSDictionary *);
2422 msset(CGImageSourceCreateWithFile, image, "_CGImageSourceCreateWithFile");
2423 MSHookFunction(CGImageSourceCreateWithFile, MSHake(CGImageSourceCreateWithFile));
2425 void *(*CGImageSourceCreateWithURL)(NSURL *, NSDictionary *);
2426 msset(CGImageSourceCreateWithURL, image, "_CGImageSourceCreateWithURL");
2427 MSHookFunction(CGImageSourceCreateWithURL, MSHake(CGImageSourceCreateWithURL));
2433 Wallpapers_ = [[NSArray arrayWithObjects:@"Wallpaper.mp4", @"Wallpaper@2x.png", @"Wallpaper@2x.jpg", @"Wallpaper.png", @"Wallpaper.jpg", @"Wallpaper.html", nil] retain];
2434 Papered_ = $getTheme$(Wallpapers_) != nil;
2435 Docked_ = $getTheme$([NSArray arrayWithObjects:@"Dock.png", nil]) != nil;
2437 CFNotificationCenterAddObserver(
2438 CFNotificationCenterGetDarwinNotifyCenter(),
2439 NULL, &ChangeWallpaper, (CFStringRef) @"com.saurik.winterboard.lockbackground", NULL, CFNotificationSuspensionBehaviorCoalesce
2442 if ($getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"]) != nil) {
2443 NSBundle *MediaPlayer([NSBundle bundleWithPath:@"/System/Library/Frameworks/MediaPlayer.framework"]);
2444 if (MediaPlayer != nil)
2447 $MPMoviePlayerController = objc_getClass("MPMoviePlayerController");
2448 $MPVideoView = objc_getClass("MPVideoView");
2455 if (MSImageRef image = MSGetImageByName("/System/Library/Frameworks/UIKit.framework/UIKit")) {
2457 class_addMethod($NSString, @selector(drawAtPoint:withStyle:), (IMP) &NSString$drawAtPoint$withStyle$, "v40@0:8{CGPoint=dd}16@32");
2458 class_addMethod($NSString, @selector(drawInRect:withStyle:), (IMP) &NSString$drawInRect$withStyle$, "v56@0:8{CGRect={CGSize=dd}{CGSize=dd}}16@48");
2459 class_addMethod($NSString, @selector(sizeWithStyle:forWidth:), (IMP) &NSString$sizeWithStyle$forWidth$, "{CGSize=dd}32@0:8@16d24");
2461 class_addMethod($NSString, @selector(drawAtPoint:withStyle:), (IMP) &NSString$drawAtPoint$withStyle$, "v20@0:4{CGPoint=ff}8@16");
2462 class_addMethod($NSString, @selector(drawInRect:withStyle:), (IMP) &NSString$drawInRect$withStyle$, "v28@0:4{CGRect={CGSize=ff}{CGSize=ff}}8@24");
2463 class_addMethod($NSString, @selector(sizeWithStyle:forWidth:), (IMP) &NSString$sizeWithStyle$forWidth$, "{CGSize=ff}16@0:4@8f12");
2466 WBHookSymbol(image, _UIKitBundle);
2468 MSHookFunction(_UIImageWithName, MSHake(_UIImageWithName));
2470 WBHookSymbol(image, _UIApplicationImageWithName);
2471 MSHookFunction(_UIApplicationImageWithName, MSHake(_UIApplicationImageWithName));
2473 WBHookSymbol(image, _UIImageWithNameInDomain);
2474 MSHookFunction(_UIImageWithNameInDomain, MSHake(_UIImageWithNameInDomain));
2476 WBHookSymbol(image, _UIImageWithNameUsingCurrentIdiom);
2477 MSHookFunction(_UIImageWithNameUsingCurrentIdiom, MSHake(_UIImageWithNameUsingCurrentIdiom));
2479 WBHookSymbol(image, _UIImageWithDeviceSpecificName);
2480 MSHookFunction(_UIImageWithDeviceSpecificName, MSHake(_UIImageWithDeviceSpecificName));
2482 SEL includeEmoji(@selector(_legacy_drawAtPoint:forWidth:withFont:lineBreakMode:letterSpacing:includeEmoji:));
2483 if (![@"" respondsToSelector:includeEmoji])
2484 includeEmoji = @selector(drawAtPoint:forWidth:withFont:lineBreakMode:letterSpacing:includeEmoji:);
2485 MSHookMessage($NSString, includeEmoji, MSHake(NSString$drawAtPoint$forWidth$withFont$lineBreakMode$letterSpacing$includeEmoji$));
2487 SEL letterSpacing(@selector(_legacy_sizeWithFont:forWidth:lineBreakMode:letterSpacing:));
2488 if (![@"" respondsToSelector:letterSpacing])
2489 letterSpacing = @selector(sizeWithFont:forWidth:lineBreakMode:letterSpacing:);
2490 MSHookMessage($NSString, letterSpacing, MSHake(NSString$sizeWithFont$forWidth$lineBreakMode$letterSpacing$));
2492 SEL sizeWithFont(@selector(_legacy_sizeWithFont:));
2493 if (![@"" respondsToSelector:sizeWithFont])
2494 sizeWithFont = @selector(sizeWithFont:);
2495 MSHookMessage($NSString, sizeWithFont, MSHake(NSString$sizeWithFont$));
2499 //MSHookFunction(reinterpret_cast<int (*)(const char *, int, mode_t)>(&open), MSHake(open));
2501 if (UIDebug_ && ![Manager_ fileExistsAtPath:@"/tmp/UIImages"]) {
2502 NSError *error(nil);
2503 if (![Manager_ createDirectoryAtPath:@"/tmp/UIImages" withIntermediateDirectories:NO attributes:[NSDictionary dictionaryWithObjectsAndKeys:
2504 [NSNumber numberWithShort:0777], NSFilePosixPermissions,
2506 NSLog(@"WB:Error: cannot create /tmp/UIImages (%@)", error);