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 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 #define remapResourceName(oldname, newname) \
347 else if ([file isEqualToString:(oldname)]) \
348 [names addObject:[NSString stringWithFormat:@"%@.png", newname]]; \
350 bool summer(SpringBoard_ && SummerBoard_);
352 if (identifier == nil);
353 else if ([identifier isEqualToString:@"com.apple.UIKit"])
354 [names addObject:[NSString stringWithFormat:@"UIImages/%@", file]];
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 use) {
375 return $pathForFile$inBundle$(file, [bundle bundleIdentifier], [[bundle bundlePath] lastPathComponent], 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:@"/"])
438 @synchronized (Bundles_) {
439 bundle = [Bundles_ objectForKey:path];
442 if (reinterpret_cast<id>(bundle) == [NSNull null])
444 else if (bundle == nil) {
445 if ([Manager_ fileExistsAtPath:[path stringByAppendingPathComponent:@"Info.plist"]])
446 bundle = [NSBundle bundleWithPath:path];
448 bundle = [NSBundle wb$bundleWithFile:path];
450 NSLog(@"WB:Debug:PathBundle(%@, %@)", path, bundle);
452 @synchronized (Bundles_) {
453 [Bundles_ setObject:(bundle == nil ? [NSNull null] : reinterpret_cast<id>(bundle)) forKey:path];
462 // -[NSString wb$themedPath] {{{
463 @interface NSString (WinterBoard)
464 - (NSString *) wb$themedPath;
467 @implementation NSString (WinterBoard)
469 - (NSString *) wb$themedPath {
470 if ([self hasPrefix:@"/Library/Themes/"])
474 NSLog(@"WB:Debug:Bypass(\"%@\")", self);
476 if (NSBundle *bundle = [NSBundle wb$bundleWithFile:self]) {
477 NSString *file([self stringByResolvingSymlinksInPath]);
478 NSString *prefix([[bundle bundlePath] stringByResolvingSymlinksInPath]);
479 if ([file hasPrefix:prefix]) {
480 NSUInteger length([prefix length]);
481 if (length != [file length])
482 if (NSString *path = $pathForFile$inBundle$([file substringFromIndex:(length + 1)], bundle, false))
493 void WBLogRect(const char *tag, struct CGRect rect) {
494 NSLog(@"%s:{%f,%f+%f,%f}", tag, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
497 void WBLogHierarchy(UIView *view, unsigned index = 0, unsigned indent = 0) {
498 CGRect frame([view frame]);
499 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]);
501 for (UIView *child in [view subviews])
502 WBLogHierarchy(child, index++, indent + 1);
505 UIImage *$cacheForImage$(UIImage *image) {
506 CGColorSpaceRef space(CGColorSpaceCreateDeviceRGB());
507 CGRect rect = {CGPointMake(1, 1), [image size]};
508 CGSize size = {rect.size.width + 2, rect.size.height + 2};
510 CGContextRef context(CGBitmapContextCreate(NULL, size.width, size.height, 8, 4 * size.width, space, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst));
511 CGColorSpaceRelease(space);
513 CGContextDrawImage(context, rect, [image CGImage]);
514 CGImageRef ref(CGBitmapContextCreateImage(context));
515 CGContextRelease(context);
517 UIImage *cache([UIImage imageWithCGImage:ref]);
523 /*MSHook(id, SBImageCache$initWithName$forImageWidth$imageHeight$initialCapacity$, SBImageCache *self, SEL sel, NSString *name, unsigned width, unsigned height, unsigned capacity) {
524 //if ([name isEqualToString:@"icons"]) return nil;
525 return _SBImageCache$initWithName$forImageWidth$imageHeight$initialCapacity$(self, sel, name, width, height, capacity);
528 MSHook(void, SBIconModel$cacheImageForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
529 NSString *key([icon displayIdentifier]);
531 if (UIImage *image = [icon icon]) {
532 CGSize size = [image size];
533 if (size.width != 59 || size.height != 60) {
534 UIImage *cache($cacheForImage$(image));
535 [Cache_ setObject:cache forKey:key];
540 _SBIconModel$cacheImageForIcon$(self, sel, icon);
543 MSHook(void, SBIconModel$cacheImagesForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
544 /* XXX: do I /really/ have to do this? figure out how to cache the small icon! */
545 _SBIconModel$cacheImagesForIcon$(self, sel, icon);
547 NSString *key([icon displayIdentifier]);
549 if (UIImage *image = [icon icon]) {
550 CGSize size = [image size];
551 if (size.width != 59 || size.height != 60) {
552 UIImage *cache($cacheForImage$(image));
553 [Cache_ setObject:cache forKey:key];
559 MSHook(UIImage *, SBIconModel$getCachedImagedForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
560 NSString *key([icon displayIdentifier]);
561 if (UIImage *image = [Cache_ objectForKey:key])
564 return _SBIconModel$getCachedImagedForIcon$(self, sel, icon);
567 MSHook(UIImage *, SBIconModel$getCachedImagedForIcon$smallIcon$, SBIconModel *self, SEL sel, SBIcon *icon, BOOL small) {
569 return _SBIconModel$getCachedImagedForIcon$smallIcon$(self, sel, icon, small);
570 NSString *key([icon displayIdentifier]);
571 if (UIImage *image = [Cache_ objectForKey:key])
574 return _SBIconModel$getCachedImagedForIcon$smallIcon$(self, sel, icon, small);
577 MSHook(id, SBSearchView$initWithFrame$, id /* XXX: SBSearchView */ self, SEL sel, struct CGRect frame) {
578 if ((self = _SBSearchView$initWithFrame$(self, sel, frame)) != nil) {
579 [self setBackgroundColor:[UIColor clearColor]];
580 for (UIView *child in [self subviews])
581 [child setBackgroundColor:[UIColor clearColor]];
585 MSHook(id, SBSearchTableViewCell$initWithStyle$reuseIdentifier$, SBSearchTableViewCell *self, SEL sel, int style, NSString *reuse) {
586 if ((self = _SBSearchTableViewCell$initWithStyle$reuseIdentifier$(self, sel, style, reuse)) != nil) {
587 [self setBackgroundColor:[UIColor clearColor]];
591 MSHook(void, SBSearchTableViewCell$drawRect$, SBSearchTableViewCell *self, SEL sel, struct CGRect rect, BOOL selected) {
592 _SBSearchTableViewCell$drawRect$(self, sel, rect, selected);
593 float inset([self edgeInset]);
594 [[UIColor clearColor] set];
595 UIRectFill(CGRectMake(0, 0, inset, rect.size.height));
596 UIRectFill(CGRectMake(rect.size.width - inset, 0, inset, rect.size.height));
599 MSHook(UIImage *, SBApplicationIcon$icon, SBApplicationIcon *self, SEL sel) {
600 if (![Info_ wb$boolForKey:@"ComposeStoreIcons"])
601 if (NSString *path = $pathForIcon$([self application]))
602 return [UIImage imageWithContentsOfFile:path];
603 return _SBApplicationIcon$icon(self, sel);
606 MSHook(UIImage *, SBApplicationIcon$generateIconImage$, SBApplicationIcon *self, SEL sel, int type) {
608 if (![Info_ wb$boolForKey:@"ComposeStoreIcons"]) {
609 if (IsWild_ && false) // XXX: delete this code, it should not be supported
610 if (NSString *path72 = $pathForIcon$([self application], @"-72"))
611 return [UIImage imageWithContentsOfFile:path72];
612 if (NSString *path = $pathForIcon$([self application]))
613 if (UIImage *image = [UIImage imageWithContentsOfFile:path]) {
615 if ([$SBIcon respondsToSelector:@selector(defaultIconImageSize)])
616 width = [$SBIcon defaultIconImageSize].width;
619 return width == 59 ? image : [image _imageScaledToProportion:(width / 59.0) interpolationQuality:5];
622 return _SBApplicationIcon$generateIconImage$(self, sel, type);
625 MSHook(UIImage *, SBWidgetApplicationIcon$icon, SBWidgetApplicationIcon *self, SEL sel) {
627 NSLog(@"WB:Debug:Widget(%@:%@)", [self displayIdentifier], [self displayName]);
628 if (NSString *path = $getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Icons/%@.png", [self displayName]]]))
629 return [UIImage imageWithContentsOfFile:path];
630 return _SBWidgetApplicationIcon$icon(self, sel);
633 MSHook(UIImage *, SBBookmarkIcon$icon, SBBookmarkIcon *self, SEL sel) {
635 NSLog(@"WB:Debug:Bookmark(%@:%@)", [self displayIdentifier], [self displayName]);
636 if (NSString *path = $getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Icons/%@.png", [self displayName]]]))
637 return [UIImage imageWithContentsOfFile:path];
638 return _SBBookmarkIcon$icon(self, sel);
641 MSHook(NSString *, SBApplication$pathForIcon, SBApplication *self, SEL sel) {
642 if (NSString *path = $pathForIcon$(self))
644 return _SBApplication$pathForIcon(self, sel);
647 static UIImage *CachedImageAtPath(NSString *path) {
648 path = [path stringByResolvingSymlinksInPath];
649 UIImage *image = [Images_ objectForKey:path];
651 return reinterpret_cast<id>(image) == [NSNull null] ? nil : image;
652 image = [[UIImage alloc] initWithContentsOfFile:path cache:true];
654 image = [image autorelease];
655 [Images_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:path];
659 MSHook(UIImage *, _UIApplicationImageWithName, NSString *name) {
660 NSBundle *bundle = [NSBundle mainBundle];
662 NSLog(@"WB:Debug: _UIApplicationImageWithName(\"%@\", %@)", name, bundle);
663 if (NSString *path = $pathForFile$inBundle$(name, bundle, false))
664 return CachedImageAtPath(path);
665 return __UIApplicationImageWithName(name);
668 #define WBDelegate(delegate) \
669 - (NSMethodSignature*) methodSignatureForSelector:(SEL)sel { \
671 NSLog(@"WB:MS:%s:(%s)", class_getName([self class]), sel_getName(sel)); \
672 if (NSMethodSignature *sig = [delegate methodSignatureForSelector:sel]) \
674 NSLog(@"WB:Error: [%s methodSignatureForSelector:(%s)]", class_getName([self class]), sel_getName(sel)); \
678 - (void) forwardInvocation:(NSInvocation*)inv { \
679 SEL sel = [inv selector]; \
680 if ([delegate respondsToSelector:sel]) \
681 [inv invokeWithTarget:delegate]; \
683 NSLog(@"WB:Error: [%s forwardInvocation:(%s)]", class_getName([self class]), sel_getName(sel)); \
686 // %hook -[NSBundle pathForResource:ofType:] {{{
687 MSInstanceMessageHook2(NSString *, NSBundle, pathForResource,ofType, NSString *, resource, NSString *, type) {
688 NSString *file = type == nil ? resource : [NSString stringWithFormat:@"%@.%@", resource, type];
689 if ([file isEqualToString:@"Info.plist"])
690 return MSOldCall(resource, type);
692 NSLog(@"WB:Debug: [NSBundle(%@) pathForResource:\"%@\"]", [self bundleIdentifier], file);
693 if (NSString *path = $pathForFile$inBundle$(file, self, false))
695 return MSOldCall(resource, type);
699 static void $drawLabel$(NSString *label, CGRect rect, NSString *style, NSString *custom) {
700 bool ellipsis(false);
701 CGFloat max = rect.size.width - 11, width;
703 width = [(ellipsis ? [label stringByAppendingString:@"..."] : label) sizeWithStyle:style forWidth:320].width;
706 size_t length([label length]);
707 CGFloat spacing((width - max) / (length - 1));
709 if (spacing > 1.25) {
711 label = [label substringToIndex:(length - 1)];
715 style = [style stringByAppendingString:[NSString stringWithFormat:@"letter-spacing: -%f; ", spacing]];
719 label = [label stringByAppendingString:@"..."];
722 style = [style stringByAppendingString:custom];
724 CGSize size = [label sizeWithStyle:style forWidth:rect.size.width];
725 [label drawAtPoint:CGPointMake((rect.size.width - size.width) / 2 + rect.origin.x, rect.origin.y) withStyle:style];
728 static struct WBStringDrawingState {
729 WBStringDrawingState *next_;
733 } *stringDrawingState_;
735 extern "C" CGColorSpaceRef CGContextGetFillColorSpace(CGContextRef);
736 extern "C" void CGContextGetFillColor(CGContextRef, CGFloat[]);
738 static NSString *WBColorMarkup(size_t number, const CGFloat *components) {
760 return [NSString stringWithFormat:@"color: rgba(%g, %g, %g, %g)", r * 255, g * 255, b * 255, a];
763 static NSString *WBColorMarkup() {
764 CGContextRef context(UIGraphicsGetCurrentContext());
765 //NSLog(@"XXX:1:%p", context);
769 CGColorSpaceRef space(CGContextGetFillColorSpace(context));
770 //NSLog(@"XXX:2:%p", space);
774 size_t number(CGColorSpaceGetNumberOfComponents(space));
775 //NSLog(@"XXX:3:%u", number);
779 CGFloat components[number + 1];
780 CGContextGetFillColor(context, components);
781 return WBColorMarkup(number, components);
784 static NSString *WBColorMarkup(UIColor *uicolor) {
787 CGColorRef cgcolor([uicolor CGColor]);
791 CGColorSpaceRef space(CGColorGetColorSpace(cgcolor));
792 //NSLog(@"XXX:2:%p", space);
796 size_t number(CGColorGetNumberOfComponents(cgcolor));
797 //NSLog(@"XXX:3:%u", number);
801 const CGFloat *components(CGColorGetComponents(cgcolor));
802 return WBColorMarkup(number, components);
805 extern "C" NSString *NSStringFromCGPoint(CGPoint rect);
807 MSInstanceMessage6(CGSize, NSString, drawAtPoint,forWidth,withFont,lineBreakMode,letterSpacing,includeEmoji, CGPoint, point, CGFloat, width, UIFont *, font, UILineBreakMode, mode, CGFloat, spacing, BOOL, emoji) {
808 //NSLog(@"XXX: @\"%@\" %@ %g \"%@\" %u %g %u", self, NSStringFromCGPoint(point), width, font, mode, spacing, emoji);
810 WBStringDrawingState *state(stringDrawingState_);
812 return MSOldCall(point, width, font, mode, spacing, emoji);
814 if (state->count_ != 0 && --state->count_ == 0)
815 stringDrawingState_ = state->next_;
816 if (state->info_ == nil)
817 return MSOldCall(point, width, font, mode, spacing, emoji);
819 NSString *info([Info_ objectForKey:state->info_]);
821 return MSOldCall(point, width, font, mode, spacing, emoji);
823 NSString *base(state->base_ ?: @"");
824 NSString *extra([NSString stringWithFormat:@"letter-spacing: %gpx", spacing]);
825 [self drawAtPoint:point withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info]];
829 extern "C" NSString *NSStringFromCGRect(CGRect rect);
831 MSInstanceMessageHook7(CGSize, NSString, _drawInRect,withFont,lineBreakMode,alignment,lineSpacing,includeEmoji,truncationRect, CGRect, rect, UIFont *, font, UILineBreakMode, mode, UITextAlignment, alignment, float, spacing, BOOL, emoji, CGRect, truncation) {
832 //NSLog(@"XXX: @\"%@\" %@ \"%@\" %u %u %g %u %@", self, NSStringFromCGRect(rect), font, mode, alignment, spacing, emoji, NSStringFromCGRect(truncation));
834 WBStringDrawingState *state(stringDrawingState_);
836 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
838 if (state->count_ != 0 && --state->count_ == 0)
839 stringDrawingState_ = state->next_;
840 if (state->info_ == nil)
841 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
843 NSString *info([Info_ objectForKey:state->info_]);
845 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
850 case UITextAlignmentLeft:
853 case UITextAlignmentCenter:
854 textAlign = @"center";
856 case UITextAlignmentRight:
857 textAlign = @"right";
861 NSString *base(state->base_ ?: @"");
862 NSString *extra([NSString stringWithFormat:@"text-align: %@", textAlign]);
865 $drawLabel$(self, rect, [NSString stringWithFormat:@"%@;%@;%@", [font markupDescription], WBColorMarkup(), base], info);
867 [self drawInRect:rect withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info]];
872 MSInstanceMessage2(void, NSString, drawInRect,withAttributes, CGRect, rect, NSDictionary *, attributes) {
873 //NSLog(@"XXX: *\"%@\" %@", self, attributes);
875 WBStringDrawingState *state(stringDrawingState_);
877 return MSOldCall(rect, attributes);
879 if (state->count_ != 0 && --state->count_ == 0)
880 stringDrawingState_ = state->next_;
881 if (state->info_ == nil)
882 return MSOldCall(rect, attributes);
884 NSString *info([Info_ objectForKey:state->info_]);
886 return MSOldCall(rect, attributes);
888 NSString *base(state->base_ ?: @"");
890 UIFont *font([attributes objectForKey:@"NSFont"]);
891 UIColor *color([attributes objectForKey:@"NSColor"]);
893 [self drawInRect:rect withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], WBColorMarkup(color), base, info]];
896 extern "C" NSString *NSStringFromCGSize(CGSize size);
898 MSInstanceMessage4(CGRect, NSString, boundingRectWithSize,options,attributes,context, CGSize, size, NSInteger, options, NSDictionary *, attributes, id, context) {
899 //NSLog(@"XXX: $\"%@\" %@ 0x%x %@ %@", self, NSStringFromCGSize(size), unsigned(options), attributes, context);
901 WBStringDrawingState *state(stringDrawingState_);
903 return MSOldCall(size, options, attributes, context);
905 if (state->count_ != 0 && --state->count_ == 0)
906 stringDrawingState_ = state->next_;
907 if (state->info_ == nil)
908 return MSOldCall(size, options, attributes, context);
910 NSString *info([Info_ objectForKey:state->info_]);
912 return MSOldCall(size, options, attributes, context);
914 NSString *base(state->base_ ?: @"");
916 UIFont *font([attributes objectForKey:@"NSFont"]);
917 UIColor *color([attributes objectForKey:@"NSColor"]);
919 return (CGRect) {{0, 0}, [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], WBColorMarkup(color), base, info] forWidth:size.width]};
922 MSInstanceMessage4(CGSize, NSString, sizeWithFont,forWidth,lineBreakMode,letterSpacing, UIFont *, font, CGFloat, width, UILineBreakMode, mode, CGFloat, spacing) {
923 //NSLog(@"XXX: #\"%@\" \"%@\" %g %u %g", self, font, width, mode, spacing);
925 WBStringDrawingState *state(stringDrawingState_);
927 return MSOldCall(font, width, mode, spacing);
929 if (state->count_ != 0 && --state->count_ == 0)
930 stringDrawingState_ = state->next_;
931 if (state->info_ == nil)
932 return MSOldCall(font, width, mode, spacing);
934 NSString *info([Info_ objectForKey:state->info_]);
936 return MSOldCall(font, width, mode, spacing);
938 NSString *base(state->base_ ?: @"");
939 NSString *extra([NSString stringWithFormat:@"letter-spacing: %gpx", spacing]);
940 return [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info] forWidth:width];
943 MSInstanceMessage1(CGSize, NSString, sizeWithFont, UIFont *, font) {
944 //NSLog(@"XXX: ?\"%@\"", self);
946 WBStringDrawingState *state(stringDrawingState_);
948 return MSOldCall(font);
950 if (state->count_ != 0 && --state->count_ == 0)
951 stringDrawingState_ = state->next_;
952 if (state->info_ == nil)
953 return MSOldCall(font);
955 NSString *info([Info_ objectForKey:state->info_]);
957 return MSOldCall(font);
959 NSString *base(state->base_ ?: @"");
960 return [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), base, info] forWidth:65535];
963 MSClassMessageHook2(id, SBIconBadgeView, checkoutAccessoryImagesForIcon,location, id, icon, int, location) {
964 WBStringDrawingState badgeState = {NULL, 0, @""
967 stringDrawingState_ = &badgeState;
969 id images(MSOldCall(icon, location));
971 stringDrawingState_ = NULL;
975 MSClassMessageHook2(UIImage *, SBIconAccessoryImage, checkoutAccessoryImageForIcon,location, id, icon, int, location) {
976 if ([self _imageClassForIcon:icon location:location] != $SBIconBadgeImage)
977 return MSOldCall(icon, location);
979 WBStringDrawingState badgeState = {NULL, 0, @""
982 stringDrawingState_ = &badgeState;
984 UIImage *image(MSOldCall(icon, location));
986 stringDrawingState_ = NULL;
990 MSInstanceMessageHook1(UIImage *, SBIconBadgeFactory, checkoutBadgeImageForText, NSString *, text) {
991 WBStringDrawingState badgeState = {NULL, 0, @""
994 stringDrawingState_ = &badgeState;
996 UIImage *image(MSOldCall(text));
998 stringDrawingState_ = NULL;
1002 MSInstanceMessageHook1(UIImage *, SBCalendarApplicationIcon, generateIconImage, int, type) {
1003 WBStringDrawingState dayState = {NULL, 2, @""
1004 // XXX: this is only correct on an iPod dock
1005 "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px;"
1006 , @"CalendarIconDayStyle"};
1008 WBStringDrawingState skipState = {&dayState,
1009 unsigned(kCFCoreFoundationVersionNumber > 800 ? 16 : 7)
1012 WBStringDrawingState dateState = {&skipState, 2, @""
1013 , @"CalendarIconDateStyle"};
1015 stringDrawingState_ = &dateState;
1017 UIImage *image(MSOldCall(type));
1019 stringDrawingState_ = NULL;
1023 MSInstanceMessageHook1(UIImage *, UIStatusBarTimeItemView, contentsImageForStyle, int, style) {
1024 WBStringDrawingState timeState = {NULL, 0, @""
1027 stringDrawingState_ = &timeState;
1029 UIImage *image(MSOldCall(style));
1031 stringDrawingState_ = NULL;
1035 MSHook(void, SBCalendarIconContentsView$drawRect$, SBCalendarIconContentsView *self, SEL sel, CGRect rect) {
1036 NSBundle *bundle([NSBundle mainBundle]);
1038 CFLocaleRef locale(CFLocaleCopyCurrent());
1039 CFDateFormatterRef formatter(CFDateFormatterCreate(NULL, locale, kCFDateFormatterNoStyle, kCFDateFormatterNoStyle));
1042 CFDateRef now(CFDateCreate(NULL, CFAbsoluteTimeGetCurrent()));
1044 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NUMBER_FORMAT" value:@"d" table:@"SpringBoard"]);
1045 CFStringRef date(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
1046 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NAME_FORMAT" value:@"cccc" table:@"SpringBoard"]);
1047 CFStringRef day(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
1051 CFRelease(formatter);
1053 NSString *datestyle([@""
1054 "font-family: Helvetica; "
1055 "font-weight: bold; "
1058 "" stringByAppendingString:(IsWild_
1059 ? @"font-size: 54px; "
1060 : @"font-size: 39px; "
1063 NSString *daystyle([@""
1064 "font-family: Helvetica; "
1065 "font-weight: bold; "
1067 "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px; "
1068 "" stringByAppendingString:(IsWild_
1069 ? @"font-size: 11px; "
1070 : @"font-size: 9px; "
1073 if (NSString *style = [Info_ objectForKey:@"CalendarIconDateStyle"])
1074 datestyle = [datestyle stringByAppendingString:style];
1075 if (NSString *style = [Info_ objectForKey:@"CalendarIconDayStyle"])
1076 daystyle = [daystyle stringByAppendingString:style];
1078 CGFloat width([self bounds].size.width);
1080 CGSize datesize = [(NSString *)date sizeWithStyle:datestyle forWidth:(width + leeway)];
1081 CGSize daysize = [(NSString *)day sizeWithStyle:daystyle forWidth:(width + leeway)];
1083 unsigned base0(IsWild_ ? 89 : 70);
1084 if ($GSFontGetUseLegacyFontMetrics())
1086 unsigned base1(IsWild_ ? 18 : 16);
1093 [(NSString *)date drawAtPoint:CGPointMake(
1094 (width + 1 - datesize.width) / 2, (base0 - datesize.height) / 2
1095 ) withStyle:datestyle];
1097 [(NSString *)day drawAtPoint:CGPointMake(
1098 (width + 1 - daysize.width) / 2, (base1 - daysize.height) / 2
1099 ) withStyle:daystyle];
1105 // %hook -[{NavigationBar,Toolbar} setBarStyle:] {{{
1106 void $setBarStyle$_(NSString *name, int &style) {
1108 NSLog(@"WB:Debug:%@Style:%d", name, style);
1109 NSNumber *number = nil;
1111 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style-%d", name, style]];
1113 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style", name]];
1114 if (number != nil) {
1115 style = [number intValue];
1117 NSLog(@"WB:Debug:%@Style=%d", name, style);
1121 MSInstanceMessageHook1(void, UIToolbar, setBarStyle, int, style) {
1122 $setBarStyle$_(@"Toolbar", style);
1123 return MSOldCall(style);
1126 MSInstanceMessageHook1(void, UINavigationBar, setBarStyle, int, style) {
1127 $setBarStyle$_(@"NavigationBar", style);
1128 return MSOldCall(style);
1132 MSHook(void, SBButtonBar$didMoveToSuperview, UIView *self, SEL sel) {
1133 [[self superview] setBackgroundColor:[UIColor clearColor]];
1134 _SBButtonBar$didMoveToSuperview(self, sel);
1137 MSHook(void, SBStatusBarContentsView$didMoveToSuperview, UIView *self, SEL sel) {
1138 [[self superview] setBackgroundColor:[UIColor clearColor]];
1139 _SBStatusBarContentsView$didMoveToSuperview(self, sel);
1142 static NSArray *Wallpapers_;
1143 static bool Papered_;
1144 static bool Docked_;
1145 static bool SMSBackgrounded_;
1146 static NSString *WallpaperFile_;
1147 static UIImageView *WallpaperImage_;
1148 static UIWebDocumentView *WallpaperPage_;
1149 static NSURL *WallpaperURL_;
1151 #define _release(object) \
1152 do if (object != nil) { \
1157 static UIImage *$getImage$(NSString *path) {
1158 UIImage *image([UIImage imageWithContentsOfFile:path]);
1160 unsigned scale($getScale$(path));
1161 if (scale != 1 && [image respondsToSelector:@selector(setScale)])
1162 [image setScale:scale];
1167 template <typename Original_, typename Modified_>
1168 _finline UIImage *WBCacheImage(const Original_ &original, const Modified_ &modified, NSString *key) {
1169 UIImage *image([Images_ objectForKey:key]);
1171 return reinterpret_cast<id>(image) == [NSNull null] ? original() : image;
1172 if (NSString *path = modified())
1173 image = $getImage$(path);
1174 [Images_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:key];
1175 return image == nil ? original() : image;
1178 static UIImage *$getDefaultDesktopImage$() {
1179 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"LockBackground.png", @"LockBackground.jpg", nil])))
1180 return $getImage$(path);
1184 MSClassMessageHook0(UIImage *, UIImage, defaultDesktopImage) {
1185 return $getDefaultDesktopImage$() ?: MSOldCall();
1188 MSInstanceMessageHook0(UIImage *, SBSlidingAlertDisplay, _defaultDesktopImage) {
1189 return $getDefaultDesktopImage$() ?: MSOldCall();
1192 MSInstanceMessageHook0(void, SBWallpaperView, resetCurrentImageToWallpaper) {
1193 for (UIView *parent([self superview]); parent != nil; parent = [parent superview])
1194 if ([parent isKindOfClass:$SBSlidingAlertDisplay]) {
1195 if (UIImage *image = $getDefaultDesktopImage$()) {
1196 [self setImage:image];
1206 // %hook -[SBUIController init] {{{
1207 MSInstanceMessageHook0(id, SBUIController, init) {
1212 NSString *paper($getTheme$(Wallpapers_));
1214 paper = [paper stringByDeletingLastPathComponent];
1218 sysctlbyname("hw.machine", NULL, &size, NULL, 0);
1219 char *machine = new char[size];
1221 if (sysctlbyname("hw.machine", machine, &size, NULL, 0) == -1) {
1222 perror("sysctlbyname(\"hw.machine\", ?)");
1227 IsWild_ = machine != NULL && strncmp(machine, "iPad", 4) == 0;
1231 NSLog(@"WB:Debug:Info = %@", [Info_ description]);
1234 UIImageView *&_wallpaperView(MSHookIvar<UIImageView *>(self, "_wallpaperView"));
1235 if (&_wallpaperView != NULL) {
1236 [_wallpaperView removeFromSuperview];
1237 [_wallpaperView release];
1238 _wallpaperView = nil;
1242 UIView *&_contentLayer(MSHookIvar<UIView *>(self, "_contentLayer"));
1243 UIView *&_contentView(MSHookIvar<UIView *>(self, "_contentView"));
1246 if (&_contentLayer != NULL)
1247 player = &_contentLayer;
1248 else if (&_contentView != NULL)
1249 player = &_contentView;
1252 UIView *layer(player == NULL ? nil : *player);
1254 UIWindow *window([[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]);
1255 UIView *content([[[UIView alloc] initWithFrame:[window frame]] autorelease]);
1256 [window setContentView:content];
1258 UIWindow *&_window(MSHookIvar<UIWindow *>(self, "_window"));
1259 [window setBackgroundColor:[_window backgroundColor]];
1260 [_window setBackgroundColor:[UIColor clearColor]];
1262 [window setLevel:-1000];
1263 [window setHidden:NO];
1265 /*if (player != NULL)
1266 *player = content;*/
1268 [content setBackgroundColor:[layer backgroundColor]];
1269 [layer setBackgroundColor:[UIColor clearColor]];
1272 if (!SummerBoard_ || !IsWild_)
1275 CGRect bounds([content bounds]);
1276 bounds.origin.y = -30;
1277 indirect = [[[UIView alloc] initWithFrame:bounds] autorelease];
1278 [content addSubview:indirect];
1279 [indirect zoomToScale:2.4];
1282 _release(WallpaperFile_);
1283 _release(WallpaperImage_);
1284 _release(WallpaperPage_);
1285 _release(WallpaperURL_);
1288 NSArray *themes([NSArray arrayWithObject:paper]);
1290 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"], themes)) {
1294 static AVController *controller_(nil);
1295 if (controller_ == nil) {
1296 AVQueue *queue([AVQueue avQueue]);
1297 controller_ = [[AVController avControllerWithQueue:queue error:&error] retain];
1300 AVQueue *queue([controller_ queue]);
1302 UIView *video([[[UIView alloc] initWithFrame:[indirect bounds]] autorelease]);
1303 [controller_ setLayer:[video _layer]];
1305 AVItem *item([[[AVItem alloc] initWithPath:path error:&error] autorelease]);
1306 [queue appendItem:item error:&error];
1308 [controller_ play:&error];
1309 #elif UseMPMoviePlayerController
1310 NSURL *url([NSURL fileURLWithPath:path]);
1311 MPMoviePlayerController *controller = [[$MPMoviePlayerController alloc] initWithContentURL:url];
1312 controller.movieControlMode = MPMovieControlModeHidden;
1315 MPVideoView *video = [[[$MPVideoView alloc] initWithFrame:[indirect bounds]] autorelease];
1316 [video setMovieWithPath:path];
1317 [video setRepeatMode:1];
1318 [video setRepeatGap:-1];
1319 [video playFromBeginning];;
1322 [indirect addSubview:video];
1325 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"Wallpaper.png", @"Wallpaper.jpg", nil]), themes)) {
1326 if (UIImage *image = $getImage$(path)) {
1327 WallpaperFile_ = [path retain];
1328 WallpaperImage_ = [[UIImageView alloc] initWithImage:image];
1329 if (NSNumber *number = [Info_ objectForKey:@"WallpaperAlpha"])
1330 [WallpaperImage_ setAlpha:[number floatValue]];
1331 [indirect addSubview:WallpaperImage_];
1335 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.html"], themes)) {
1336 CGRect bounds = [indirect bounds];
1338 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1339 [view setAutoresizes:true];
1341 WallpaperPage_ = [view retain];
1342 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
1344 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1346 [view setBackgroundColor:[UIColor clearColor]];
1347 if ([view respondsToSelector:@selector(setDrawsBackground:)])
1348 [view setDrawsBackground:NO];
1349 [[view webView] setDrawsBackground:NO];
1351 [indirect addSubview:view];
1355 for (size_t i(0), e([Themes_ count]); i != e; ++i) {
1356 NSString *theme = [Themes_ objectAtIndex:(e - i - 1)];
1357 NSString *html = [theme stringByAppendingPathComponent:@"Widget.html"];
1358 if ([Manager_ fileExistsAtPath:html]) {
1359 CGRect bounds = [indirect bounds];
1361 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1362 [view setAutoresizes:true];
1364 NSURL *url = [NSURL fileURLWithPath:html];
1365 [view loadRequest:[NSURLRequest requestWithURL:url]];
1367 [view setBackgroundColor:[UIColor clearColor]];
1368 if ([view respondsToSelector:@selector(setDrawsBackground:)])
1369 [view setDrawsBackground:NO];
1370 [[view webView] setDrawsBackground:NO];
1372 [indirect addSubview:view];
1380 MSHook(void, SBAwayView$updateDesktopImage$, SBAwayView *self, SEL sel, UIImage *image) {
1381 NSString *path = $getTheme$([NSArray arrayWithObject:@"LockBackground.html"]);
1382 UIView *&_backgroundView(MSHookIvar<UIView *>(self, "_backgroundView"));
1384 if (path != nil && _backgroundView != nil)
1387 _SBAwayView$updateDesktopImage$(self, sel, image);
1390 CGRect bounds = [self bounds];
1392 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1393 [view setAutoresizes:true];
1395 if (WallpaperPage_ != nil)
1396 [WallpaperPage_ release];
1397 WallpaperPage_ = [view retain];
1399 if (WallpaperURL_ != nil)
1400 [WallpaperURL_ release];
1401 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
1403 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1405 [[view webView] setDrawsBackground:false];
1406 [view setBackgroundColor:[UIColor clearColor]];
1408 [self insertSubview:view aboveSubview:_backgroundView];
1410 if ($objc_setAssociatedObject != NULL)
1411 $objc_setAssociatedObject(self, @selector(wb$widgetView), view, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1415 MSHook(void, SBAwayView$_addSubview$positioned$relativeTo$, SBAwayView *self, SEL sel, UIView *view, int positioned, UIView *relative) {
1416 UIView *&_backgroundView(MSHookIvar<UIView *>(self, "_backgroundView"));
1417 UIView *&_chargingView(MSHookIvar<UIView *>(self, "_chargingView"));
1418 if (&_chargingView != NULL)
1419 if (positioned == -2 && (relative == _backgroundView && _chargingView == nil || relative == _chargingView))
1420 if ($objc_getAssociatedObject != NULL)
1421 if (UIView *widget = $objc_getAssociatedObject(self, @selector(wb$widgetView)))
1423 return _SBAwayView$_addSubview$positioned$relativeTo$(self, sel, view, positioned, relative);
1426 /*extern "C" CGColorRef CGGStateGetSystemColor(void *);
1427 extern "C" CGColorRef CGGStateGetFillColor(void *);
1428 extern "C" CGColorRef CGGStateGetStrokeColor(void *);
1429 extern "C" NSString *UIStyleStringFromColor(CGColorRef);*/
1431 /* WBTimeLabel {{{ */
1432 @interface WBTimeLabel : NSProxy {
1434 _transient SBStatusBarTimeView *view_;
1437 - (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view;
1441 @implementation WBTimeLabel
1448 - (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view {
1449 time_ = [time retain];
1454 - (NSString *) description {
1460 - (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(UILineBreakMode)mode {
1461 if (NSString *custom = [Info_ objectForKey:@"TimeStyle"]) {
1462 BOOL &_mode(MSHookIvar<BOOL>(view_, "_mode"));;
1464 [time_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1465 "font-family: Helvetica; "
1466 "font-weight: bold; "
1469 "%@", _mode ? @"white" : @"black", custom]];
1474 return [time_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1479 /* WBBadgeLabel {{{ */
1480 @interface WBBadgeLabel : NSProxy {
1484 - (id) initWithBadge:(NSString *)badge;
1485 - (NSString *) description;
1489 @implementation WBBadgeLabel
1496 - (id) initWithBadge:(NSString *)badge {
1497 badge_ = [badge retain];
1501 - (NSString *) description {
1502 return [badge_ description];
1507 - (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(UILineBreakMode)mode {
1508 if (NSString *custom = [Info_ objectForKey:@"BadgeStyle"]) {
1509 [badge_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1510 "font-family: Helvetica; "
1511 "font-weight: bold; "
1519 return [badge_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1526 MSInstanceMessageHook1(void, SBIcon, setIconImageAlpha, CGFloat, alpha) {
1527 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1528 alpha = [number floatValue];
1529 return MSOldCall(alpha);
1532 MSInstanceMessageHook1(void, SBIcon, setIconLabelAlpha, CGFloat, alpha) {
1533 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1534 alpha = [number floatValue];
1535 return MSOldCall(alpha);
1538 MSInstanceMessageHook0(id, SBIcon, initWithDefaultSize) {
1539 if ((self = MSOldCall()) != nil) {
1540 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"]) {
1541 // XXX: note: this is overridden above, which is silly
1542 float alpha([number floatValue]);
1543 if ([self respondsToSelector:@selector(setIconImageAlpha:)])
1544 [self setIconImageAlpha:alpha];
1545 if ([self respondsToSelector:@selector(setIconLabelAlpha:)])
1546 [self setIconLabelAlpha:alpha];
1547 if ([self respondsToSelector:@selector(setAlpha:)])
1548 [self setAlpha:alpha];
1553 MSInstanceMessageHook1(void, SBIcon, setAlpha, CGFloat, alpha) {
1554 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1555 alpha = [number floatValue];
1556 return MSOldCall(alpha);
1560 MSHook(id, SBIconBadge$initWithBadge$, SBIconBadge *self, SEL sel, NSString *badge) {
1561 if ((self = _SBIconBadge$initWithBadge$(self, sel, badge)) != nil) {
1562 id &_badge(MSHookIvar<id>(self, "_badge"));
1564 if (id label = [[WBBadgeLabel alloc] initWithBadge:[_badge autorelease]])
1569 void SBStatusBarController$setStatusBarMode(int &mode) {
1571 NSLog(@"WB:Debug:setStatusBarMode:%d", mode);
1572 if (mode < 100) // 104:hidden 105:glowing
1573 if (NSNumber *number = [Info_ objectForKey:@"StatusBarMode"])
1574 mode = [number intValue];
1577 /*MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, double duration, int animation) {
1578 NSLog(@"mode:%d orientation:%d duration:%f animation:%d", mode, orientation, duration, animation);
1579 SBStatusBarController$setStatusBarMode(mode);
1580 return _SBStatusBarController$setStatusBarMode$orientation$duration$animation$(self, sel, mode, orientation, duration, animation);
1583 MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, float duration, int fenceID, int animation) {
1584 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d", mode, orientation, duration, fenceID, animation);
1585 SBStatusBarController$setStatusBarMode(mode);
1586 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$(self, sel, mode, orientation, duration, fenceID, animation);
1589 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) {
1590 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d startTime:%f", mode, orientation, duration, fenceID, animation, startTime);
1591 SBStatusBarController$setStatusBarMode(mode);
1592 //NSLog(@"mode=%u", mode);
1593 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$startTime$(self, sel, mode, orientation, duration, fenceID, animation, startTime);
1596 /*MSHook(id, SBStatusBarContentsView$initWithStatusBar$mode$, SBStatusBarContentsView *self, SEL sel, id bar, int mode) {
1597 if (NSNumber *number = [Info_ objectForKey:@"StatusBarContentsMode"])
1598 mode = [number intValue];
1599 return _SBStatusBarContentsView$initWithStatusBar$mode$(self, sel, bar, mode);
1602 MSHook(NSString *, SBStatusBarOperatorNameView$operatorNameStyle, SBStatusBarOperatorNameView *self, SEL sel) {
1603 NSString *style(_SBStatusBarOperatorNameView$operatorNameStyle(self, sel));
1605 NSLog(@"operatorNameStyle= %@", style);
1606 if (NSString *custom = [Info_ objectForKey:@"OperatorNameStyle"])
1607 style = [NSString stringWithFormat:@"%@; %@", style, custom];
1611 MSHook(void, SBStatusBarOperatorNameView$setOperatorName$fullSize$, SBStatusBarOperatorNameView *self, SEL sel, NSString *name, BOOL full) {
1613 NSLog(@"setOperatorName:\"%@\" fullSize:%u", name, full);
1614 return _SBStatusBarOperatorNameView$setOperatorName$fullSize$(self, sel, name, NO);
1617 // XXX: replace this with [SBStatusBarTimeView tile]
1618 MSHook(void, SBStatusBarTimeView$drawRect$, SBStatusBarTimeView *self, SEL sel, CGRect rect) {
1619 id &_time(MSHookIvar<id>(self, "_time"));
1620 if (_time != nil && [_time class] != [WBTimeLabel class])
1621 object_setInstanceVariable(self, "_time", reinterpret_cast<void *>([[WBTimeLabel alloc] initWithTime:[_time autorelease] view:self]));
1622 return _SBStatusBarTimeView$drawRect$(self, sel, rect);
1625 @interface UIView (WinterBoard)
1626 - (bool) wb$isWBImageView;
1627 - (void) wb$logHierarchy;
1628 - (void) wb$setBackgroundColor:(UIColor *)color;
1631 @implementation UIView (WinterBoard)
1633 - (bool) wb$isWBImageView {
1637 - (void) wb$logHierarchy {
1638 WBLogHierarchy(self);
1641 - (void) wb$setBackgroundColor:(UIColor *)color {
1642 [self setBackgroundColor:color];
1643 for (UIView *child in [self subviews])
1644 [child wb$setBackgroundColor:color];
1649 @interface WBImageView : UIImageView {
1652 - (bool) wb$isWBImageView;
1653 - (void) wb$updateFrame;
1656 @implementation WBImageView
1658 - (bool) wb$isWBImageView {
1662 - (void) wb$updateFrame {
1663 CGRect frame([self frame]);
1666 for (UIView *view(self); ; ) {
1667 view = [view superview];
1670 frame.origin.y -= [view frame].origin.y;
1673 [self setFrame:frame];
1678 static void SBIconList$updateFrames$(SBIconList *self) {
1679 NSArray *subviews([self subviews]);
1680 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1681 if (view != nil && [view wb$isWBImageView])
1682 [view wb$updateFrame];
1685 MSHook(void, SBIconList$didMoveToSuperview, SBIconList *self, SEL sel) {
1686 SBIconList$updateFrames$(self);
1687 _SBIconList$didMoveToSuperview(self, sel);
1690 MSHook(void, SBIconList$setFrame$, SBIconList *self, SEL sel, CGRect frame) {
1691 SBIconList$updateFrames$(self);
1692 _SBIconList$setFrame$(self, sel, frame);
1695 static void $addPerPageView$(unsigned i, UIView *list) {
1696 NSString *path($getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Page%u.png", i]]));
1700 NSArray *subviews([list subviews]);
1702 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1703 if (view == nil || ![view wb$isWBImageView]) {
1704 view = [[[WBImageView alloc] init] autorelease];
1705 [list insertSubview:view atIndex:0];
1708 UIImage *image([UIImage imageWithContentsOfFile:path]);
1710 CGRect frame([view frame]);
1711 frame.size = [image size];
1712 [view setFrame:frame];
1714 [view setImage:image];
1715 [view wb$updateFrame];
1718 static void $addPerPageViews$(NSArray *lists) {
1719 for (unsigned i(0), e([lists count]); i != e; ++i)
1720 $addPerPageView$(i, [lists objectAtIndex:i]);
1723 MSInstanceMessageHook0(void, SBIconController, updateNumberOfRootIconLists) {
1724 NSArray *&_rootIconLists(MSHookIvar<NSArray *>(self, "_rootIconLists"));
1725 $addPerPageViews$(_rootIconLists);
1729 MSInstanceMessageHook0(void, SBIconContentView, layoutSubviews) {
1732 if (SBIconController *controller = [$SBIconController sharedInstance]) {
1733 UIView *&_dockContainerView(MSHookIvar<UIView *>(controller, "_dockContainerView"));
1734 if (&_dockContainerView != NULL)
1735 [[_dockContainerView superview] bringSubviewToFront:_dockContainerView];
1739 MSHook(void, SBIconController$noteNumberOfIconListsChanged, SBIconController *self, SEL sel) {
1740 SBIconModel *&_iconModel(MSHookIvar<SBIconModel *>(self, "_iconModel"));
1741 $addPerPageViews$([_iconModel iconLists]);
1742 return _SBIconController$noteNumberOfIconListsChanged(self, sel);
1745 MSHook(id, SBIconLabel$initWithSize$label$, SBIconLabel *self, SEL sel, CGSize size, NSString *label) {
1746 self = _SBIconLabel$initWithSize$label$(self, sel, size, label);
1748 [self setClipsToBounds:NO];
1752 MSHook(void, SBIconLabel$setInDock$, SBIconLabel *self, SEL sel, BOOL docked) {
1753 static bool gssc(false);
1755 BOOL (*GSSystemHasCapability)(CFStringRef) = reinterpret_cast<BOOL (*)(CFStringRef)>(dlsym(RTLD_DEFAULT, "GSSystemHasCapability"));
1756 Papered_ |= GSSystemHasCapability != NULL && GSSystemHasCapability(CFSTR("homescreen-wallpaper"));
1759 if ([Info_ objectForKey:@"UndockedIconLabels"] == nil)
1760 [Info_ setObject:[NSNumber numberWithBool:(
1762 [Info_ objectForKey:@"DockedIconLabelStyle"] != nil ||
1763 [Info_ objectForKey:@"UndockedIconLabelStyle"] != nil
1764 )] forKey:@"UndockedIconLabels"];
1767 id &_label(MSHookIvar<id>(self, "_label"));
1768 if (![Info_ wb$boolForKey:@"UndockedIconLabels"])
1771 if (_label != nil && [_label respondsToSelector:@selector(setInDock:)])
1772 [_label setInDock:docked];
1774 _SBIconLabel$setInDock$(self, sel, docked);
1775 [self setNeedsDisplay];
1778 MSHook(BOOL, SBDockIconListView$shouldShowNewDock, id self, SEL sel) {
1779 return SummerBoard_ && Docked_ ? NO : _SBDockIconListView$shouldShowNewDock(self, sel);
1782 MSHook(void, SBDockIconListView$setFrame$, id self, SEL sel, CGRect frame) {
1783 _SBDockIconListView$setFrame$(self, sel, frame);
1786 // %hook -[NSBundle localizedStringForKey:value:table:] {{{
1787 MSInstanceMessageHook3(NSString *, NSBundle, localizedStringForKey,value,table, NSString *, key, NSString *, value, NSString *, table) {
1788 NSString *identifier = [self bundleIdentifier];
1789 NSLocale *locale = [NSLocale currentLocale];
1790 NSString *language = [locale objectForKey:NSLocaleLanguageCode];
1792 NSLog(@"WB:Debug:[NSBundle(%@) localizedStringForKey:\"%@\" value:\"%@\" table:\"%@\"] (%@)", identifier, key, value, table, language);
1793 NSString *file = table == nil ? @"Localizable" : table;
1794 NSString *name = [NSString stringWithFormat:@"%@:%@", identifier, file];
1795 NSDictionary *strings;
1796 if ((strings = [Strings_ objectForKey:name]) != nil) {
1797 if (static_cast<id>(strings) != [NSNull null]) strings:
1798 if (NSString *value = [strings objectForKey:key])
1800 } else if (NSString *path = $pathForFile$inBundle$([NSString stringWithFormat:@"%@.lproj/%@.strings",
1803 if ((strings = [[NSDictionary alloc] initWithContentsOfFile:path]) != nil) {
1804 [Strings_ setObject:[strings autorelease] forKey:name];
1808 [Strings_ setObject:[NSNull null] forKey:name];
1809 return MSOldCall(key, value, table);
1812 // %hook -[WebCoreFrameBridge renderedSizeOfNode:constrainedToWidth:] {{{
1813 MSClassHook(WebCoreFrameBridge)
1815 MSInstanceMessageHook2(CGSize, WebCoreFrameBridge, renderedSizeOfNode,constrainedToWidth, id, node, float, width) {
1818 void **core(reinterpret_cast<void **>([node _node]));
1819 if (core == NULL || core[6] == NULL)
1821 return MSOldCall(node, width);
1825 MSInstanceMessage1(void, SBIconLabel, drawRect, CGRect, rect) {
1826 static Ivar drawMoreLegibly = object_getInstanceVariable(self, "_drawMoreLegibly", NULL);
1829 Ivar ivar = object_getInstanceVariable(self, "_inDock", reinterpret_cast<void **>(&docked));
1830 docked = (docked & (ivar_getOffset(ivar) == ivar_getOffset(drawMoreLegibly) ? 0x2 : 0x1)) != 0;
1832 NSString *label(MSHookIvar<NSString *>(self, "_label"));
1834 NSString *style = [NSString stringWithFormat:@""
1835 "font-family: Helvetica; "
1836 "font-weight: bold; "
1838 "", (docked || !SummerBoard_ ? @"white" : @"#b3b3b3"), (IsWild_
1839 ? @"font-size: 12px; "
1840 : @"font-size: 11px; "
1844 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px 1px 0px; "];
1846 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px -1px 0px; "];
1848 NSString *custom([Info_ objectForKey:(docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle")]);
1850 $drawLabel$(label, [self bounds], style, custom);
1853 MSInstanceMessage0(CGImageRef, SBIconLabel, buildLabelImage) {
1854 bool docked((MSHookIvar<unsigned>(self, "_inDock") & 0x2) != 0);
1856 WBStringDrawingState labelState = {NULL, 0, @""
1857 , docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle"};
1859 stringDrawingState_ = &labelState;
1862 CGImageRef image(MSOldCall());
1865 stringDrawingState_ = NULL;
1869 static bool wb$inDock(id parameters) {
1870 return [$objc_getAssociatedObject(parameters, @selector(wb$inDock)) boolValue];
1873 MSInstanceMessage0(NSUInteger, SBIconLabelImageParameters, hash) {
1874 return MSOldCall() + (wb$inDock(self) ? 0xdeadbeef : 0xd15ea5e);
1877 MSClassMessage2(id, SBIconView, _labelImageParametersForIcon,location, id, icon, int, location) {
1878 if (id parameters = MSOldCall(icon, location)) {
1879 $objc_setAssociatedObject(parameters, @selector(wb$inDock), [NSNumber numberWithBool:(location == 1)], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1884 MSInstanceMessage0(id, SBIconView, _labelImageParameters) {
1885 if (id parameters = MSOldCall()) {
1886 int &location(MSHookIvar<int>(self, "_iconLocation"));
1887 if (&location != NULL)
1888 $objc_setAssociatedObject(parameters, @selector(wb$inDock), [NSNumber numberWithBool:(location == 3)], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1893 MSClassMessage1(UIImage *, SBIconLabelImage, _drawLabelImageForParameters, id, parameters) {
1894 bool docked(wb$inDock(parameters));
1896 WBStringDrawingState labelState = {NULL, 0, @""
1897 , docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle"};
1899 stringDrawingState_ = &labelState;
1902 UIImage *image(MSOldCall(parameters));
1905 stringDrawingState_ = NULL;
1910 MSInstanceMessageHook2(id, CKBalloonView, initWithFrame,delegate, CGRect, frame, id, delegate) {
1911 if ((self = MSOldCall(frame, delegate)) != nil) {
1912 [self setBackgroundColor:[UIColor clearColor]];
1916 MSInstanceMessageHook0(BOOL, CKBalloonView, _canUseLayerBackedBalloon) {
1917 return SMSBackgrounded_ ? NO : MSOldCall();
1920 MSInstanceMessageHook0(void, CKTranscriptHeaderView, layoutSubviews) {
1921 [self wb$setBackgroundColor:[UIColor clearColor]];
1925 MSInstanceMessageHook1(void, CKMessageCell, addBalloonView, CKBalloonView *, balloon) {
1927 [balloon setBackgroundColor:[UIColor clearColor]];
1930 MSInstanceMessageHook1(void, CKTranscriptCell, setBackgroundColor, UIColor *, color) {
1931 MSOldCall([UIColor clearColor]);
1932 [[self contentView] wb$setBackgroundColor:[UIColor clearColor]];
1936 MSInstanceMessageHook2(id, CKTranscriptCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1937 if ((self = MSOldCall(style, reuse)) != nil) {
1938 [self setBackgroundColor:[UIColor clearColor]];
1939 [[self contentView] wb$setBackgroundColor:[UIColor clearColor]];
1944 MSInstanceMessageHook2(id, CKMessageCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1945 if ((self = MSOldCall(style, reuse)) != nil) {
1946 [self setBackgroundColor:[UIColor clearColor]];
1947 [[self contentView] setBackgroundColor:[UIColor clearColor]];
1951 MSInstanceMessageHook2(id, CKTimestampView, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1952 if ((self = MSOldCall(style, reuse)) != nil) {
1953 UILabel *&_label(MSHookIvar<UILabel *>(self, "_label"));
1954 [_label setBackgroundColor:[UIColor clearColor]];
1958 MSInstanceMessageHook1(void, CKTranscriptTableView, setSeparatorStyle, int, style) {
1959 MSOldCall(UITableViewCellSeparatorStyleNone);
1962 MSInstanceMessageHook2(id, CKTranscriptTableView, initWithFrame,style, CGRect, frame, int, style) {
1963 if ((self = MSOldCall(frame, style)) != nil) {
1964 [self setSeparatorStyle:UITableViewCellSeparatorStyleNone];
1968 MSInstanceMessageHook0(void, CKTranscriptController, loadView) {
1971 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"SMSBackground.png", @"SMSBackground.jpg", nil])))
1972 if (UIImage *image = $getImage$(path)) {
1973 SMSBackgrounded_ = true;
1975 UIView *&_transcriptTable(MSHookIvar<UIView *>(self, "_transcriptTable"));
1976 UIView *&_transcriptLayer(MSHookIvar<UIView *>(self, "_transcriptLayer"));
1978 if (&_transcriptTable != NULL)
1979 table = _transcriptTable;
1980 else if (&_transcriptLayer != NULL)
1981 table = _transcriptLayer;
1985 UIView *placard(table != nil ? [table superview] : MSHookIvar<UIView *>(self, "_backPlacard"));
1986 UIImageView *background([[[UIImageView alloc] initWithImage:image] autorelease]);
1989 [placard insertSubview:background atIndex:0];
1991 [table setBackgroundColor:[UIColor clearColor]];
1992 [placard insertSubview:background belowSubview:table];
1998 template <typename Original_>
1999 static UIImage *WBCacheUIImage(const Original_ &original, NSString *name, NSString *key) {
2000 if ([name rangeOfString:@"."].location == NSNotFound)
2001 name = [name stringByAppendingString:@".png"];
2002 UIImage *image(WBCacheImage(original, [=](){ return $pathForFile$inBundle$(name, _UIKitBundle(), true); }, key));
2003 if (image != nil && UIDebug_) {
2004 NSString *path(@"/tmp/UIImages");
2005 [Manager_ createDirectoryAtPath:path withIntermediateDirectories:YES attributes:@{NSFilePosixPermissions: @0777} error:NULL];
2006 path = [NSString stringWithFormat:@"%@/%@", path, name];
2007 if (![Manager_ fileExistsAtPath:path])
2008 [UIImagePNGRepresentation(image) writeToFile:path atomically:YES];
2012 // %hook _UIImageWithName() {{{
2013 MSHook(UIImage *, _UIImageWithName, NSString *name) {
2017 NSLog(@"WB:Debug: _UIImageWithName(\"%@\")", name);
2018 return WBCacheUIImage(
2019 [=](){ return __UIImageWithName(name); },
2020 name, [NSString stringWithFormat:@"I:%@", name]);
2023 // %hook _UIImageWithNameInDomain() {{{
2024 MSHook(UIImage *, _UIImageWithNameInDomain, NSString *name, NSString *domain) {
2026 NSLog(@"WB:Debug: _UIImageWithNameInDomain(\"%@\", \"%@\")", name, domain);
2027 return WBCacheImage(
2028 [=](){ return __UIImageWithNameInDomain(name, domain); },
2029 [=](){ return $getTheme$($useScale$([NSArray arrayWithObject:[NSString stringWithFormat:@"Domains/%@/%@", domain, name]])); },
2030 [NSString stringWithFormat:@"D:%zu:%@%@", size_t([domain length]), domain, name]);
2033 // %hook _UIImageWithDeviceUsingCurrentIdiom() {{{
2034 MSHook(UIImage *, _UIImageWithNameUsingCurrentIdiom, NSString *name) {
2036 NSLog(@"WB:Debug: _UIImageWithNameUsingCurrentIdiom(\"%@\")", name);
2037 return WBCacheUIImage(
2038 [=](){ return __UIImageWithNameUsingCurrentIdiom(name); },
2039 name, [NSString stringWithFormat:@"I:%@", name]);
2042 // %hook _UIImageWithDeviceSpecificName() {{{
2043 MSHook(UIImage *, _UIImageWithDeviceSpecificName, NSString *name) {
2045 NSLog(@"WB:Debug: _UIImageWithDeviceSpecificName(\"%@\")", name);
2046 return WBCacheUIImage(
2047 [=](){ return __UIImageWithDeviceSpecificName(name); },
2048 name, [NSString stringWithFormat:@"S:%@", name]);
2052 // %hook GSFontCreateWithName() {{{
2053 MSHook(GSFontRef, GSFontCreateWithName, const char *name, GSFontSymbolicTraits traits, float size) {
2055 NSLog(@"WB:Debug: GSFontCreateWithName(\"%s\", %f)", name, size);
2056 if (NSString *font = [Info_ objectForKey:[NSString stringWithFormat:@"FontName-%s", name]])
2057 name = [font UTF8String];
2058 //if (NSString *scale = [Info_ objectForKey:[NSString stringWithFormat:@"FontScale-%s", name]])
2059 // size *= [scale floatValue];
2060 return _GSFontCreateWithName(name, traits, size);
2064 #define AudioToolbox "/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox"
2066 static bool GetFileNameForThisAction$(bool value, unsigned long a0, char *a1, unsigned long a2, bool &a3) {
2068 NSLog(@"WB:Debug:GetFileNameForThisAction(%lu, %s, %lu, %u) = %u", a0, value ? a1 : NULL, a2, a3, value);
2071 NSString *path = [NSString stringWithUTF8String:a1];
2072 if ([path hasPrefix:@"/System/Library/Audio/UISounds/"]) {
2073 NSString *file = [path substringFromIndex:31];
2074 for (NSString *theme in Themes_) {
2075 NSString *path([NSString stringWithFormat:@"%@/UISounds/%@", theme, file]);
2076 if ([Manager_ fileExistsAtPath:path]) {
2077 strcpy(a1, [path UTF8String]);
2086 MSHook(bool, _Z24GetFileNameForThisActionmPcRb, unsigned long a0, char *a1, bool &a3) {
2087 bool value(__Z24GetFileNameForThisActionmPcRb(a0, a1, a3));
2088 return GetFileNameForThisAction$(value, a0, a1, 0, a3);
2091 MSHook(bool, _Z24GetFileNameForThisActionmPcmRb, unsigned long a0, char *a1, unsigned long a2, bool &a3) {
2092 bool value(__Z24GetFileNameForThisActionmPcmRb(a0, a1, a2, a3));
2093 return GetFileNameForThisAction$(value, a0, a1, a2, a3);
2096 static void ChangeWallpaper(
2097 CFNotificationCenterRef center,
2101 CFDictionaryRef info
2104 NSLog(@"WB:Debug:ChangeWallpaper!");
2107 if (WallpaperFile_ != nil) {
2108 image = [[UIImage alloc] initWithContentsOfFile:WallpaperFile_];
2110 image = [image autorelease];
2113 if (WallpaperImage_ != nil)
2114 [WallpaperImage_ setImage:image];
2115 if (WallpaperPage_ != nil)
2116 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
2120 MSHook(NSArray *, CPBitmapCreateImagesFromPath, NSString *path, NSDictionary **names, void *arg2, void *arg3) {
2121 NSArray *images(_CPBitmapCreateImagesFromPath(path, names, arg2, arg3));
2122 if (images != NULL && *names != nil && CFGetTypeID((CFTypeRef) *names) == CFDictionaryGetTypeID()) {
2123 if (NSBundle *bundle = [NSBundle wb$bundleWithFile:path]) {
2124 NSMutableArray *copy([images mutableCopy]);
2128 NSString *file([path stringByResolvingSymlinksInPath]);
2129 NSString *prefix([[bundle bundlePath] stringByResolvingSymlinksInPath]);
2130 if ([file hasPrefix:prefix]) {
2131 NSUInteger length([prefix length]);
2132 if (length != [file length]) {
2133 NSEnumerator *enumerator([*names keyEnumerator]);
2134 while (NSString *name = [enumerator nextObject]) {
2135 NSString *png([name stringByAppendingString:@".png"]);
2136 if (NSString *themed = $pathForFile$inBundle$(png, bundle, true)) {
2137 NSUInteger index([[*names objectForKey:name] intValue]);
2138 UIImage *image($getImage$(themed));
2139 CGImageRef cg([image CGImage]);
2140 [copy replaceObjectAtIndex:index withObject:(id)cg];
2149 MSHook(void, BKSDisplayServicesSetSystemAppExitedImagePath, NSString *path) {
2150 if (NSString *themed = $getTheme$($useScale$([NSArray arrayWithObject:@"SystemAppExited.png"])))
2152 _BKSDisplayServicesSetSystemAppExitedImagePath(path);
2155 #define WBRename(name, sel, imp) \
2156 MSHookMessage($ ## name, @selector(sel), &$ ## name ## $ ## imp, &_ ## name ## $ ## imp)
2158 template <typename Type_>
2159 static void msset(Type_ &function, MSImageRef image, const char *name) {
2160 function = reinterpret_cast<Type_>(MSFindSymbol(image, name));
2163 #define WBHookSymbol(image, function) \
2164 msset(function, image, "_" #function)
2166 template <typename Type_>
2167 static void dlset(Type_ &function, const char *name) {
2168 function = reinterpret_cast<Type_>(dlsym(RTLD_DEFAULT, name));
2171 // %hook CGImageReadCreateWithFile() {{{
2172 MSHook(void *, CGImageReadCreateWithFile, NSString *path, int flag) {
2174 NSLog(@"WB:Debug: CGImageReadCreateWithFile(%@, %d)", path, flag);
2175 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2176 void *value(_CGImageReadCreateWithFile([path wb$themedPath], flag));
2181 MSHook(void *, CGImageSourceCreateWithFile, NSString *path, NSDictionary *options) {
2183 NSLog(@"WB:Debug: CGImageSourceCreateWithFile(%@, %@)", path, options);
2184 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2185 void *value(_CGImageSourceCreateWithFile([path wb$themedPath], options));
2190 MSHook(void *, CGImageSourceCreateWithURL, NSURL *url, NSDictionary *options) {
2192 NSLog(@"WB:Debug: CGImageSourceCreateWithURL(%@, %@)", url, options);
2193 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2194 if ([url isFileURL])
2195 url = [NSURL fileURLWithPath:[[url path] wb$themedPath]];
2196 void *value(_CGImageSourceCreateWithURL(url, options));
2202 static void NSString$drawAtPoint$withStyle$(NSString *self, SEL _cmd, CGPoint point, NSString *style) {
2203 WKSetCurrentGraphicsContext(UIGraphicsGetCurrentContext());
2204 if (style == nil || [style length] == 0)
2205 style = @"font-family: Helvetica; font-size: 12px";
2206 //NSLog(@"XXX:drawP(%@ | %@)", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "]);
2207 [[WBMarkup sharedMarkup] drawString:self atPoint:point withStyle:style];
2210 static void NSString$drawInRect$withStyle$(NSString *self, SEL _cmd, CGRect rect, NSString *style) {
2211 WKSetCurrentGraphicsContext(UIGraphicsGetCurrentContext());
2212 if (style == nil || [style length] == 0)
2213 style = @"font-family: Helvetica; font-size: 12px";
2214 //NSLog(@"XXX:drawR(%@ | %@)", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "]);
2215 return [[WBMarkup sharedMarkup] drawString:self inRect:rect withStyle:style];
2218 static CGSize NSString$sizeWithStyle$forWidth$(NSString *self, SEL _cmd, NSString *style, CGFloat width) {
2219 if (style == nil || [style length] == 0)
2220 style = @"font-family: Helvetica; font-size: 12px";
2221 CGSize size([[WBMarkup sharedMarkup] sizeOfString:self withStyle:style forWidth:width]);
2222 //NSLog(@"XXX:size(%@ | %@) = [%g %g]", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "], size.width, size.height);
2226 static void SBInitialize() {
2228 WBRename(SBApplication, pathForIcon, pathForIcon);
2229 WBRename(SBApplicationIcon, icon, icon);
2230 WBRename(SBApplicationIcon, generateIconImage:, generateIconImage$);
2233 WBRename(SBBookmarkIcon, icon, icon);
2234 WBRename(SBButtonBar, didMoveToSuperview, didMoveToSuperview);
2235 WBRename(SBCalendarIconContentsView, drawRect:, drawRect$);
2236 WBRename(SBIconBadge, initWithBadge:, initWithBadge$);
2237 WBRename(SBIconController, noteNumberOfIconListsChanged, noteNumberOfIconListsChanged);
2239 WBRename(SBWidgetApplicationIcon, icon, icon);
2241 WBRename(SBDockIconListView, setFrame:, setFrame$);
2242 MSHookMessage(object_getClass($SBDockIconListView), @selector(shouldShowNewDock), &$SBDockIconListView$shouldShowNewDock, &_SBDockIconListView$shouldShowNewDock);
2244 if (kCFCoreFoundationVersionNumber < 600 || SummerBoard_)
2245 WBRename(SBIconLabel, drawRect:, drawRect$);
2246 else if (kCFCoreFoundationVersionNumber < 700) {
2247 WBRename(SBIconLabel, buildLabelImage, buildLabelImage);
2249 WBRename(SBIconLabelImageParameters, hash, hash);
2250 WBRename($SBIconView, _labelImageParametersForIcon:location:, _labelImageParametersForIcon$location$);
2251 WBRename(SBIconView, _labelImageParameters, _labelImageParameters);
2252 WBRename($SBIconLabelImage, _drawLabelImageForParameters:, _drawLabelImageForParameters$);
2255 WBRename(SBIconLabel, initWithSize:label:, initWithSize$label$);
2256 WBRename(SBIconLabel, setInDock:, setInDock$);
2258 WBRename(SBIconList, didMoveToSuperview, didMoveToSuperview);
2259 WBRename(SBIconList, setFrame:, setFrame$);
2261 WBRename(SBIconModel, cacheImageForIcon:, cacheImageForIcon$);
2262 WBRename(SBIconModel, cacheImagesForIcon:, cacheImagesForIcon$);
2263 WBRename(SBIconModel, getCachedImagedForIcon:, getCachedImagedForIcon$);
2264 WBRename(SBIconModel, getCachedImagedForIcon:smallIcon:, getCachedImagedForIcon$smallIcon$);
2266 if (kCFCoreFoundationVersionNumber < 800) {
2267 WBRename(SBSearchView, initWithFrame:, initWithFrame$);
2268 WBRename(SBSearchTableViewCell, drawRect:, drawRect$);
2269 WBRename(SBSearchTableViewCell, initWithStyle:reuseIdentifier:, initWithStyle$reuseIdentifier$);
2272 //WBRename(SBImageCache, initWithName:forImageWidth:imageHeight:initialCapacity:, initWithName$forImageWidth$imageHeight$initialCapacity$);
2274 WBRename(SBAwayView, updateDesktopImage:, updateDesktopImage$);
2275 if (kCFCoreFoundationVersionNumber >= 700)
2276 WBRename(SBAwayView, _addSubview:positioned:relativeTo:, _addSubview$positioned$relativeTo$);
2278 WBRename(SBStatusBarContentsView, didMoveToSuperview, didMoveToSuperview);
2279 //WBRename(SBStatusBarContentsView, initWithStatusBar:mode:, initWithStatusBar$mode$);
2280 //WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:animation:, setStatusBarMode$orientation$duration$animation$);
2281 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:, setStatusBarMode$orientation$duration$fenceID$animation$);
2282 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:startTime:, setStatusBarMode$orientation$duration$fenceID$animation$startTime$);
2283 WBRename(SBStatusBarOperatorNameView, operatorNameStyle, operatorNameStyle);
2284 WBRename(SBStatusBarOperatorNameView, setOperatorName:fullSize:, setOperatorName$fullSize$);
2285 WBRename(SBStatusBarTimeView, drawRect:, drawRect$);
2288 English_ = [[NSDictionary alloc] initWithContentsOfFile:@"/System/Library/CoreServices/SpringBoard.app/English.lproj/LocalizedApplicationNames.strings"];
2290 if (kCFCoreFoundationVersionNumber >= 800) {
2291 WBRename(NSString, drawInRect:withAttributes:, drawInRect$withAttributes$);
2292 WBRename(NSString, boundingRectWithSize:options:attributes:context:, boundingRectWithSize$options$attributes$context$);
2296 /*MSHook(int, open, const char *path, int oflag, mode_t mode) {
2297 int fd(_open(path, oflag, mode));
2299 static bool no(false);
2303 if (strstr(path, "/icon") != NULL)
2304 MSHookProcess(-1, "");
2306 if (fd == -1 && errno == EFAULT)
2307 NSLog(@"open(%p, %#x, %#o) = %d\n", path, oflag, mode, fd);
2309 NSLog(@"open(\"%s\", %#x, %#o) = %d\n", path, oflag, mode, fd);
2316 $objc_setAssociatedObject = reinterpret_cast<void (*)(id, void *, id value, objc_AssociationPolicy)>(dlsym(RTLD_DEFAULT, "objc_setAssociatedObject"));
2317 $objc_getAssociatedObject = reinterpret_cast<id (*)(id, void *)>(dlsym(RTLD_DEFAULT, "objc_getAssociatedObject"));
2318 $objc_removeAssociatedObjects = reinterpret_cast<void (*)(id)>(dlsym(RTLD_DEFAULT, "objc_removeAssociatedObjects"));
2320 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2322 NSString *identifier([[NSBundle mainBundle] bundleIdentifier]);
2323 SpringBoard_ = [identifier isEqualToString:@"com.apple.springboard"];
2325 Manager_ = [[NSFileManager defaultManager] retain];
2326 Themes_ = [[NSMutableArray alloc] initWithCapacity:8];
2328 dlset(_GSFontGetUseLegacyFontMetrics, "GSFontGetUseLegacyFontMetrics");
2330 // Load Settings.plist {{{
2331 if (NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"/User/Library/Preferences/com.saurik.WinterBoard.plist"]]) {
2332 if (NSNumber *value = [settings objectForKey:@"SummerBoard"])
2333 SummerBoard_ = [value boolValue];
2335 SummerBoard_ = true;
2337 if (NSNumber *value = [settings objectForKey:@"Debug"])
2338 Debug_ = [value boolValue];
2339 if (NSNumber *value = [settings objectForKey:@"RecordUI"])
2340 UIDebug_ = [value boolValue];
2342 NSArray *themes([settings objectForKey:@"Themes"]);
2344 if (NSString *theme = [settings objectForKey:@"Theme"])
2345 themes = [NSArray arrayWithObject:[NSDictionary dictionaryWithObjectsAndKeys:
2347 [NSNumber numberWithBool:true], @"Active",
2351 for (NSDictionary *theme in themes) {
2352 NSNumber *active([theme objectForKey:@"Active"]);
2353 if (![active boolValue])
2356 NSString *name([theme objectForKey:@"Name"]);
2360 #define testForTheme(format...) \
2362 NSString *path = [NSString stringWithFormat:format]; \
2363 if ([Manager_ fileExistsAtPath:path]) { \
2364 [Themes_ addObject:path]; \
2369 testForTheme(@"/Library/Themes/%@.theme", name)
2370 testForTheme(@"/Library/Themes/%@", name)
2371 testForTheme(@"%@/Library/SummerBoard/Themes/%@", NSHomeDirectory(), name)
2376 // Merge Info.plist {{{
2377 Info_ = [[NSMutableDictionary dictionaryWithCapacity:16] retain];
2379 for (NSString *theme in Themes_)
2380 if (NSDictionary *info = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"%@/Info.plist", theme]])
2381 for (NSString *key in [info allKeys])
2382 if ([Info_ objectForKey:key] == nil)
2383 [Info_ setObject:[info objectForKey:key] forKey:key];
2387 if (MSImageRef image = MSGetImageByName("/System/Library/PrivateFrameworks/AppSupport.framework/AppSupport")) {
2388 NSArray *(*CPBitmapCreateImagesFromPath)(NSString *, NSDictionary **, void *, void *);
2389 msset(CPBitmapCreateImagesFromPath, image, "_CPBitmapCreateImagesFromPath");
2390 MSHookFunction(CPBitmapCreateImagesFromPath, MSHake(CPBitmapCreateImagesFromPath));
2394 if (MSImageRef image = MSGetImageByName(AudioToolbox)) {
2395 bool (*_Z24GetFileNameForThisActionmPcRb)(unsigned long, char *, bool &);
2396 msset(_Z24GetFileNameForThisActionmPcRb, image, "__Z24GetFileNameForThisActionmPcRb");
2397 MSHookFunction(_Z24GetFileNameForThisActionmPcRb, &$_Z24GetFileNameForThisActionmPcRb, &__Z24GetFileNameForThisActionmPcRb);
2399 bool (*_Z24GetFileNameForThisActionmPcmRb)(unsigned long, char *, unsigned long, bool &);
2400 msset(_Z24GetFileNameForThisActionmPcmRb, image, "__Z24GetFileNameForThisActionmPcmRb");
2401 MSHookFunction(_Z24GetFileNameForThisActionmPcmRb, &$_Z24GetFileNameForThisActionmPcmRb, &__Z24GetFileNameForThisActionmPcmRb);
2404 // BackBoardServices {{{
2405 if (MSImageRef image = MSGetImageByName("/System/Library/PrivateFrameworks/BackBoardServices.framework/BackBoardServices")) {
2406 void (*BKSDisplayServicesSetSystemAppExitedImagePath)(NSString *path);
2407 msset(BKSDisplayServicesSetSystemAppExitedImagePath, image, "_BKSDisplayServicesSetSystemAppExitedImagePath");
2408 MSHookFunction(BKSDisplayServicesSetSystemAppExitedImagePath, MSHake(BKSDisplayServicesSetSystemAppExitedImagePath));
2411 // GraphicsServices {{{
2413 MSHookFunction(&GSFontCreateWithName, &$GSFontCreateWithName, &_GSFontCreateWithName);
2417 MSImageRef imageio = MSGetImageByName("/System/Library/Frameworks/ImageIO.framework/ImageIO");
2418 if (imageio == NULL)
2419 imageio = MSGetImageByName("/System/Library/PrivateFrameworks/ImageIO.framework/ImageIO");
2420 if (MSImageRef image = imageio) {
2421 void *(*CGImageReadCreateWithFile)(NSString *, int) = NULL;
2422 if (kCFCoreFoundationVersionNumber > 700) // XXX: iOS 6.x
2423 CGImageReadCreateWithFile = NULL;
2425 msset(CGImageReadCreateWithFile, image, "_CGImageReadCreateWithFile");
2426 MSHookFunction(CGImageReadCreateWithFile, MSHake(CGImageReadCreateWithFile));
2429 if (CGImageReadCreateWithFile == NULL) {
2430 void *(*CGImageSourceCreateWithFile)(NSString *, NSDictionary *);
2431 msset(CGImageSourceCreateWithFile, image, "_CGImageSourceCreateWithFile");
2432 MSHookFunction(CGImageSourceCreateWithFile, MSHake(CGImageSourceCreateWithFile));
2434 void *(*CGImageSourceCreateWithURL)(NSURL *, NSDictionary *);
2435 msset(CGImageSourceCreateWithURL, image, "_CGImageSourceCreateWithURL");
2436 MSHookFunction(CGImageSourceCreateWithURL, MSHake(CGImageSourceCreateWithURL));
2442 Wallpapers_ = [[NSArray arrayWithObjects:@"Wallpaper.mp4", @"Wallpaper@2x.png", @"Wallpaper@2x.jpg", @"Wallpaper.png", @"Wallpaper.jpg", @"Wallpaper.html", nil] retain];
2443 Papered_ = $getTheme$(Wallpapers_) != nil;
2444 Docked_ = $getTheme$([NSArray arrayWithObjects:@"Dock.png", nil]) != nil;
2446 CFNotificationCenterAddObserver(
2447 CFNotificationCenterGetDarwinNotifyCenter(),
2448 NULL, &ChangeWallpaper, (CFStringRef) @"com.saurik.winterboard.lockbackground", NULL, CFNotificationSuspensionBehaviorCoalesce
2451 if ($getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"]) != nil) {
2452 NSBundle *MediaPlayer([NSBundle bundleWithPath:@"/System/Library/Frameworks/MediaPlayer.framework"]);
2453 if (MediaPlayer != nil)
2456 $MPMoviePlayerController = objc_getClass("MPMoviePlayerController");
2457 $MPVideoView = objc_getClass("MPVideoView");
2464 if (MSImageRef image = MSGetImageByName("/System/Library/Frameworks/UIKit.framework/UIKit")) {
2466 class_addMethod($NSString, @selector(drawAtPoint:withStyle:), (IMP) &NSString$drawAtPoint$withStyle$, "v40@0:8{CGPoint=dd}16@32");
2467 class_addMethod($NSString, @selector(drawInRect:withStyle:), (IMP) &NSString$drawInRect$withStyle$, "v56@0:8{CGRect={CGSize=dd}{CGSize=dd}}16@48");
2468 class_addMethod($NSString, @selector(sizeWithStyle:forWidth:), (IMP) &NSString$sizeWithStyle$forWidth$, "{CGSize=dd}32@0:8@16d24");
2470 class_addMethod($NSString, @selector(drawAtPoint:withStyle:), (IMP) &NSString$drawAtPoint$withStyle$, "v20@0:4{CGPoint=ff}8@16");
2471 class_addMethod($NSString, @selector(drawInRect:withStyle:), (IMP) &NSString$drawInRect$withStyle$, "v28@0:4{CGRect={CGSize=ff}{CGSize=ff}}8@24");
2472 class_addMethod($NSString, @selector(sizeWithStyle:forWidth:), (IMP) &NSString$sizeWithStyle$forWidth$, "{CGSize=ff}16@0:4@8f12");
2475 WBHookSymbol(image, _UIKitBundle);
2477 MSHookFunction(_UIImageWithName, MSHake(_UIImageWithName));
2479 WBHookSymbol(image, _UIApplicationImageWithName);
2480 MSHookFunction(_UIApplicationImageWithName, MSHake(_UIApplicationImageWithName));
2482 WBHookSymbol(image, _UIImageWithNameInDomain);
2483 MSHookFunction(_UIImageWithNameInDomain, MSHake(_UIImageWithNameInDomain));
2485 WBHookSymbol(image, _UIImageWithNameUsingCurrentIdiom);
2486 MSHookFunction(_UIImageWithNameUsingCurrentIdiom, MSHake(_UIImageWithNameUsingCurrentIdiom));
2488 WBHookSymbol(image, _UIImageWithDeviceSpecificName);
2489 MSHookFunction(_UIImageWithDeviceSpecificName, MSHake(_UIImageWithDeviceSpecificName));
2491 SEL includeEmoji(@selector(_legacy_drawAtPoint:forWidth:withFont:lineBreakMode:letterSpacing:includeEmoji:));
2492 if (![@"" respondsToSelector:includeEmoji])
2493 includeEmoji = @selector(drawAtPoint:forWidth:withFont:lineBreakMode:letterSpacing:includeEmoji:);
2494 MSHookMessage($NSString, includeEmoji, MSHake(NSString$drawAtPoint$forWidth$withFont$lineBreakMode$letterSpacing$includeEmoji$));
2496 SEL letterSpacing(@selector(_legacy_sizeWithFont:forWidth:lineBreakMode:letterSpacing:));
2497 if (![@"" respondsToSelector:letterSpacing])
2498 letterSpacing = @selector(sizeWithFont:forWidth:lineBreakMode:letterSpacing:);
2499 MSHookMessage($NSString, letterSpacing, MSHake(NSString$sizeWithFont$forWidth$lineBreakMode$letterSpacing$));
2501 SEL sizeWithFont(@selector(_legacy_sizeWithFont:));
2502 if (![@"" respondsToSelector:sizeWithFont])
2503 sizeWithFont = @selector(sizeWithFont:);
2504 MSHookMessage($NSString, sizeWithFont, MSHake(NSString$sizeWithFont$));
2508 //MSHookFunction(reinterpret_cast<int (*)(const char *, int, mode_t)>(&open), MSHake(open));