1 /* WinterBoard - Theme Manager for the iPhone
2 * Copyright (C) 2008-2011 Jay Freeman (saurik)
6 * Redistribution and use in source and binary
7 * forms, with or without modification, are permitted
8 * provided that the following conditions are met:
10 * 1. Redistributions of source code must retain the
11 * above copyright notice, this list of conditions
12 * and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the
14 * above copyright notice, this list of conditions
15 * and the following disclaimer in the documentation
16 * and/or other materials provided with the
18 * 3. The name of the author may not be used to endorse
19 * or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS''
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
24 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
27 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
33 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
35 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43 #define _trace() do { \
44 struct timeval _ctv; \
45 gettimeofday(&_ctv, NULL); \
50 NSLog(@"%lu.%.6u[%f]:_trace()@%s:%u[%s]\n", \
51 _ctv.tv_sec, _ctv.tv_usec, \
52 (_ctv.tv_sec - _ltv.tv_sec) + (_ctv.tv_usec - _ltv.tv_usec) / 1000000.0, \
53 __FILE__, __LINE__, __FUNCTION__\
60 #import <CoreFoundation/CoreFoundation.h>
61 #import <Foundation/Foundation.h>
62 #import <CoreGraphics/CoreGraphics.h>
63 #import <ImageIO/CGImageSource.h>
65 #import <Celestial/AVController.h>
66 #import <Celestial/AVItem.h>
67 #import <Celestial/AVQueue.h>
69 #include <substrate.h>
71 #import <UIKit/UIKit.h>
73 #import <SpringBoard/SBApplication.h>
74 #import <SpringBoard/SBApplicationIcon.h>
75 #import <SpringBoard/SBAppWindow.h>
76 #import <SpringBoard/SBAwayView.h>
77 #import <SpringBoard/SBBookmarkIcon.h>
78 #import <SpringBoard/SBButtonBar.h>
79 #import <SpringBoard/SBCalendarIconContentsView.h>
80 #import <SpringBoard/SBIconController.h>
81 #import <SpringBoard/SBIconLabel.h>
82 #import <SpringBoard/SBIconList.h>
83 #import <SpringBoard/SBIconModel.h>
84 #import <SpringBoard/SBImageCache.h>
85 // XXX: #import <SpringBoard/SBSearchView.h>
86 #import <SpringBoard/SBSearchTableViewCell.h>
87 #import <SpringBoard/SBStatusBarContentsView.h>
88 #import <SpringBoard/SBStatusBarController.h>
89 #import <SpringBoard/SBStatusBarOperatorNameView.h>
90 #import <SpringBoard/SBStatusBarTimeView.h>
91 #import <SpringBoard/SBUIController.h>
92 #import <SpringBoard/SBWidgetApplicationIcon.h>
94 #import <MobileSMS/mSMSMessageTranscriptController.h>
96 #import <MediaPlayer/MPMoviePlayerController.h>
97 #import <MediaPlayer/MPVideoView.h>
98 #import <MediaPlayer/MPVideoView-PlaybackControl.h>
100 #import <CoreGraphics/CGGeometry.h>
102 #import <ChatKit/CKMessageCell.h>
104 #include <sys/sysctl.h>
106 #include "WBMarkup.h"
108 extern "C" void __clear_cache (char *beg, char *end);
110 @protocol WinterBoard
114 Class $MPMoviePlayerController;
117 MSClassHook(NSBundle)
118 MSClassHook(NSString)
121 MSMetaClassHook(UIImage)
122 MSClassHook(UINavigationBar)
123 MSClassHook(UIToolbar)
125 MSClassHook(CKMessageCell)
126 MSClassHook(CKTimestampView)
127 MSClassHook(CKTranscriptCell)
128 MSClassHook(CKTranscriptController)
129 MSClassHook(CKTranscriptTableView)
131 MSClassHook(SBApplication)
132 MSClassHook(SBApplicationIcon)
133 MSClassHook(SBAwayView)
134 MSClassHook(SBBookmarkIcon)
135 MSClassHook(SBButtonBar)
136 MSClassHook(SBCalendarApplicationIcon)
137 MSClassHook(SBCalendarIconContentsView)
138 MSClassHook(SBDockIconListView)
140 MSClassHook(SBIconBadge)
141 MSClassHook(SBIconBadgeFactory)
142 MSClassHook(SBIconController)
143 MSClassHook(SBIconLabel)
144 MSClassHook(SBIconList)
145 MSClassHook(SBIconModel)
146 //MSClassHook(SBImageCache)
147 MSClassHook(SBSearchView)
148 MSClassHook(SBSearchTableViewCell)
149 MSClassHook(SBSlidingAlertDisplay)
150 MSClassHook(SBStatusBarContentsView)
151 MSClassHook(SBStatusBarController)
152 MSClassHook(SBStatusBarOperatorNameView)
153 MSClassHook(SBStatusBarTimeView)
154 MSClassHook(SBUIController)
155 MSClassHook(SBWallpaperView)
156 MSClassHook(SBWidgetApplicationIcon)
158 extern "C" void WKSetCurrentGraphicsContext(CGContextRef);
160 __attribute__((__constructor__))
161 static void MSFixClass() {
163 $SBIcon = objc_getClass("SBIconView");
164 if ($CKTranscriptController == nil)
165 $CKTranscriptController = objc_getClass("mSMSMessageTranscriptController");
169 static bool Four_($SBDockIconListView != nil);
171 @interface NSDictionary (WinterBoard)
172 - (UIColor *) wb$colorForKey:(NSString *)key;
173 - (BOOL) wb$boolForKey:(NSString *)key;
176 @implementation NSDictionary (WinterBoard)
178 - (UIColor *) wb$colorForKey:(NSString *)key {
179 NSString *value = [self objectForKey:key];
186 - (BOOL) wb$boolForKey:(NSString *)key {
187 if (NSString *value = [self objectForKey:key])
188 return [value boolValue];
194 static BOOL (*_GSFontGetUseLegacyFontMetrics)();
195 #define $GSFontGetUseLegacyFontMetrics() \
196 (_GSFontGetUseLegacyFontMetrics == NULL ? YES : _GSFontGetUseLegacyFontMetrics())
198 static bool Debug_ = false;
199 static bool UIDebug_ = false;
200 static bool Engineer_ = false;
201 static bool SummerBoard_ = true;
202 static bool SpringBoard_;
204 static UIImage *(*_UIApplicationImageWithName)(NSString *name);
205 static UIImage *(*_UIImageWithNameInDomain)(NSString *name, NSString *domain);
206 static NSBundle *(*_UIKitBundle)();
207 static bool (*_UIPackedImageTableGetIdentifierForName)(NSString *, int *);
208 static int (*_UISharedImageNameGetIdentifier)(NSString *);
210 static NSMutableDictionary *UIImages_ = [[NSMutableDictionary alloc] initWithCapacity:32];
211 static NSMutableDictionary *PathImages_ = [[NSMutableDictionary alloc] initWithCapacity:16];
212 static NSMutableDictionary *Cache_ = [[NSMutableDictionary alloc] initWithCapacity:64];
213 static NSMutableDictionary *Strings_ = [[NSMutableDictionary alloc] initWithCapacity:0];
214 static NSMutableDictionary *Bundles_ = [[NSMutableDictionary alloc] initWithCapacity:2];
216 static NSFileManager *Manager_;
217 static NSMutableArray *Themes_;
219 static NSDictionary *English_;
220 static NSMutableDictionary *Info_;
223 static NSMutableDictionary *Themed_ = [[NSMutableDictionary alloc] initWithCapacity:128];
225 static unsigned Scale_ = 0;
227 static unsigned $getScale$(NSString *path) {
228 NSString *name(path);
230 #define StripName(strip) \
231 if ([name hasSuffix:@ strip]) \
232 name = [name substringWithRange:NSMakeRange(0, [name length] - sizeof(strip) - 1)];
236 StripName("~iphone");
239 return [name hasSuffix:@"@2x"] ? 2 : 1;
242 static NSArray *$useScale$(NSArray *files, bool use = true) {
244 UIScreen *screen([UIScreen mainScreen]);
245 if ([screen respondsToSelector:@selector(scale)])
246 Scale_ = [screen scale];
254 NSString *idiom(IsWild_ ? @"ipad" : @"iphone");
256 NSMutableArray *scaled([NSMutableArray arrayWithCapacity:([files count] * 4)]);
258 for (NSString *file in files) {
259 NSString *base([file stringByDeletingPathExtension]);
260 NSString *extension([file pathExtension]);
264 [scaled addObject:[NSString stringWithFormat:@"%@@2x~%@.%@", base, idiom, extension]];
266 [scaled addObject:[NSString stringWithFormat:@"%@@2x.%@", base, extension]];
269 [scaled addObject:[NSString stringWithFormat:@"%@~%@.%@", base, idiom, extension]];
271 // if (!IsWild_) <- support old themes
272 [scaled addObject:file];
273 } else if ([base hasSuffix: @"@2x"]) {
274 [scaled addObject:[NSString stringWithFormat:@"%@~iphone.%@", base, extension]];
275 [scaled addObject:file];
277 NSString *rest([base substringWithRange:NSMakeRange(0, [base length] - 3)]);
278 [scaled addObject:[NSString stringWithFormat:@"%@~iphone.%@", rest, extension]];
279 [scaled addObject:[rest stringByAppendingPathExtension:extension]];
281 // XXX: this code isn't really complete
283 [scaled addObject:file];
285 if ([base hasSuffix:@"~iphone"])
286 [scaled addObject:[[base substringWithRange:NSMakeRange(0, [base length] - 7)] stringByAppendingPathExtension:extension]];
293 static NSString *$getTheme$(NSArray *files, NSArray *themes = Themes_) {
294 if (NSString *path = [Themed_ objectForKey:files])
295 return reinterpret_cast<id>(path) == [NSNull null] ? nil : path;
298 NSLog(@"WB:Debug: %@", [files description]);
302 for (NSString *theme in Themes_)
303 for (NSString *file in files) {
304 path = [NSString stringWithFormat:@"%@/%@", theme, file];
305 if ([Manager_ fileExistsAtPath:path])
312 [Themed_ setObject:(path == nil ? [NSNull null] : reinterpret_cast<id>(path)) forKey:files];
316 // $pathForFile$inBundle$() {{{
317 static NSString *$pathForFile$inBundle$(NSString *file, NSBundle *bundle, bool ui) {
318 NSString *identifier = [bundle bundleIdentifier];
319 NSMutableArray *names = [NSMutableArray arrayWithCapacity:8];
321 if (identifier != nil)
322 [names addObject:[NSString stringWithFormat:@"Bundles/%@/%@", identifier, file]];
323 if (NSString *folder = [[bundle bundlePath] lastPathComponent])
324 [names addObject:[NSString stringWithFormat:@"Folders/%@/%@", folder, file]];
326 [names addObject:[NSString stringWithFormat:@"UIImages/%@", file]];
328 #define remapResourceName(oldname, newname) \
329 else if ([file isEqualToString:(oldname)]) \
330 [names addObject:[NSString stringWithFormat:@"%@.png", newname]]; \
332 bool summer(SpringBoard_ && SummerBoard_);
334 if (identifier == nil);
335 else if ([identifier isEqualToString:@"com.apple.chatkit"])
336 [names addObject:[NSString stringWithFormat:@"Bundles/com.apple.MobileSMS/%@", file]];
337 else if ([identifier isEqualToString:@"com.apple.calculator"])
338 [names addObject:[NSString stringWithFormat:@"Files/Applications/Calculator.app/%@", file]];
340 remapResourceName(@"FSO_BG.png", @"StatusBar")
341 remapResourceName(Four_ ? @"SBDockBG-old.png" : @"SBDockBG.png", @"Dock")
342 remapResourceName(@"SBWeatherCelsius.png", @"Icons/Weather")
344 if (NSString *path = $getTheme$($useScale$(names, ui)))
351 static NSString *$pathForIcon$(SBApplication *self, NSString *suffix = @"") {
352 NSString *identifier = [self bundleIdentifier];
353 NSString *path = [self path];
354 NSString *folder = [path lastPathComponent];
355 NSString *dname = [self displayName];
356 NSString *didentifier = [self displayIdentifier];
359 NSLog(@"WB:Debug: [SBApplication(%@:%@:%@:%@) pathForIcon]", identifier, folder, dname, didentifier);
361 NSMutableArray *names = [NSMutableArray arrayWithCapacity:8];
363 /* XXX: I might need to keep this for backwards compatibility
364 if (identifier != nil)
365 [names addObject:[NSString stringWithFormat:@"Bundles/%@/icon.png", identifier]];
367 [names addObject:[NSString stringWithFormat:@"Folders/%@/icon.png", folder]]; */
369 #define testForIcon(Name) \
370 if (NSString *name = Name) \
371 [names addObject:[NSString stringWithFormat:@"Icons%@/%@.png", suffix, name]];
373 if (![didentifier isEqualToString:identifier])
374 testForIcon(didentifier);
376 testForIcon(identifier);
379 if ([identifier isEqualToString:@"com.apple.MobileSMS"])
382 if (didentifier != nil) {
383 testForIcon([English_ objectForKey:didentifier]);
385 NSArray *parts = [didentifier componentsSeparatedByString:@"-"];
386 if ([parts count] != 1)
387 if (NSDictionary *english = [[[NSDictionary alloc] initWithContentsOfFile:[path stringByAppendingString:@"/English.lproj/UIRoleDisplayNames.strings"]] autorelease])
388 testForIcon([english objectForKey:[parts lastObject]]);
391 if (NSString *path = $getTheme$(names))
397 // -[NSBundle wb$bundleWithFile] {{{
398 @interface NSBundle (WinterBoard)
399 + (NSBundle *) wb$bundleWithFile:(NSString *)path;
402 @implementation NSBundle (WinterBoard)
404 + (NSBundle *) wb$bundleWithFile:(NSString *)path {
405 path = [path stringByDeletingLastPathComponent];
406 if (path == nil || [path length] == 0 || [path isEqualToString:@"/"])
409 NSBundle *bundle([Bundles_ objectForKey:path]);
410 if (reinterpret_cast<id>(bundle) == [NSNull null])
412 else if (bundle == nil) {
413 if ([Manager_ fileExistsAtPath:[path stringByAppendingPathComponent:@"Info.plist"]])
414 bundle = [NSBundle bundleWithPath:path];
416 bundle = [NSBundle wb$bundleWithFile:path];
418 NSLog(@"WB:Debug:PathBundle(%@, %@)", path, bundle);
419 [Bundles_ setObject:(bundle == nil ? [NSNull null] : reinterpret_cast<id>(bundle)) forKey:path];
427 // -[NSString wb$themedPath] {{{
428 @interface NSString (WinterBoard)
429 - (NSString *) wb$themedPath;
432 @implementation NSString (WinterBoard)
434 - (NSString *) wb$themedPath {
435 if ([self hasPrefix:@"/Library/Themes/"])
439 NSLog(@"WB:Debug:Bypass(\"%@\")", self);
441 if (NSBundle *bundle = [NSBundle wb$bundleWithFile:self]) {
442 NSString *file([self stringByResolvingSymlinksInPath]);
443 NSString *prefix([[bundle bundlePath] stringByResolvingSymlinksInPath]);
444 if ([file hasPrefix:prefix]) {
445 NSUInteger length([prefix length]);
446 if (length != [file length])
447 if (NSString *path = $pathForFile$inBundle$([file substringFromIndex:(length + 1)], bundle, false))
458 void WBLogRect(const char *tag, struct CGRect rect) {
459 NSLog(@"%s:{%f,%f+%f,%f}", tag, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
462 void WBLogHierarchy(UIView *view, unsigned index = 0, unsigned indent = 0) {
463 CGRect frame([view frame]);
464 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]);
466 for (UIView *child in [view subviews])
467 WBLogHierarchy(child, index++, indent + 1);
470 UIImage *$cacheForImage$(UIImage *image) {
471 CGColorSpaceRef space(CGColorSpaceCreateDeviceRGB());
472 CGRect rect = {CGPointMake(1, 1), [image size]};
473 CGSize size = {rect.size.width + 2, rect.size.height + 2};
475 CGContextRef context(CGBitmapContextCreate(NULL, size.width, size.height, 8, 4 * size.width, space, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst));
476 CGColorSpaceRelease(space);
478 CGContextDrawImage(context, rect, [image CGImage]);
479 CGImageRef ref(CGBitmapContextCreateImage(context));
480 CGContextRelease(context);
482 UIImage *cache([UIImage imageWithCGImage:ref]);
488 /*MSHook(id, SBImageCache$initWithName$forImageWidth$imageHeight$initialCapacity$, SBImageCache *self, SEL sel, NSString *name, unsigned width, unsigned height, unsigned capacity) {
489 //if ([name isEqualToString:@"icons"]) return nil;
490 return _SBImageCache$initWithName$forImageWidth$imageHeight$initialCapacity$(self, sel, name, width, height, capacity);
493 MSHook(void, SBIconModel$cacheImageForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
494 NSString *key([icon displayIdentifier]);
496 if (UIImage *image = [icon icon]) {
497 CGSize size = [image size];
498 if (size.width != 59 || size.height != 60) {
499 UIImage *cache($cacheForImage$(image));
500 [Cache_ setObject:cache forKey:key];
505 _SBIconModel$cacheImageForIcon$(self, sel, icon);
508 MSHook(void, SBIconModel$cacheImagesForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
509 /* XXX: do I /really/ have to do this? figure out how to cache the small icon! */
510 _SBIconModel$cacheImagesForIcon$(self, sel, icon);
512 NSString *key([icon displayIdentifier]);
514 if (UIImage *image = [icon icon]) {
515 CGSize size = [image size];
516 if (size.width != 59 || size.height != 60) {
517 UIImage *cache($cacheForImage$(image));
518 [Cache_ setObject:cache forKey:key];
524 MSHook(UIImage *, SBIconModel$getCachedImagedForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
525 NSString *key([icon displayIdentifier]);
526 if (UIImage *image = [Cache_ objectForKey:key])
529 return _SBIconModel$getCachedImagedForIcon$(self, sel, icon);
532 MSHook(UIImage *, SBIconModel$getCachedImagedForIcon$smallIcon$, SBIconModel *self, SEL sel, SBIcon *icon, BOOL small) {
534 return _SBIconModel$getCachedImagedForIcon$smallIcon$(self, sel, icon, small);
535 NSString *key([icon displayIdentifier]);
536 if (UIImage *image = [Cache_ objectForKey:key])
539 return _SBIconModel$getCachedImagedForIcon$smallIcon$(self, sel, icon, small);
542 MSHook(id, SBSearchView$initWithFrame$, id /* XXX: SBSearchView */ self, SEL sel, struct CGRect frame) {
543 if ((self = _SBSearchView$initWithFrame$(self, sel, frame)) != nil) {
544 [self setBackgroundColor:[UIColor clearColor]];
545 for (UIView *child in [self subviews])
546 [child setBackgroundColor:[UIColor clearColor]];
550 MSHook(id, SBSearchTableViewCell$initWithStyle$reuseIdentifier$, SBSearchTableViewCell *self, SEL sel, int style, NSString *reuse) {
551 if ((self = _SBSearchTableViewCell$initWithStyle$reuseIdentifier$(self, sel, style, reuse)) != nil) {
552 [self setBackgroundColor:[UIColor clearColor]];
556 MSHook(void, SBSearchTableViewCell$drawRect$, SBSearchTableViewCell *self, SEL sel, struct CGRect rect, BOOL selected) {
557 _SBSearchTableViewCell$drawRect$(self, sel, rect, selected);
558 float inset([self edgeInset]);
559 [[UIColor clearColor] set];
560 UIRectFill(CGRectMake(0, 0, inset, rect.size.height));
561 UIRectFill(CGRectMake(rect.size.width - inset, 0, inset, rect.size.height));
564 MSHook(UIImage *, SBApplicationIcon$icon, SBApplicationIcon *self, SEL sel) {
565 if (![Info_ wb$boolForKey:@"ComposeStoreIcons"])
566 if (NSString *path = $pathForIcon$([self application]))
567 return [UIImage imageWithContentsOfFile:path];
568 return _SBApplicationIcon$icon(self, sel);
571 MSHook(UIImage *, SBApplicationIcon$generateIconImage$, SBApplicationIcon *self, SEL sel, int type) {
573 if (![Info_ wb$boolForKey:@"ComposeStoreIcons"]) {
574 if (IsWild_ && false) // XXX: delete this code, it should not be supported
575 if (NSString *path72 = $pathForIcon$([self application], @"-72"))
576 return [UIImage imageWithContentsOfFile:path72];
577 if (NSString *path = $pathForIcon$([self application]))
578 if (UIImage *image = [UIImage imageWithContentsOfFile:path]) {
580 if ([$SBIcon respondsToSelector:@selector(defaultIconImageSize)])
581 width = [$SBIcon defaultIconImageSize].width;
584 return width == 59 ? image : [image _imageScaledToProportion:(width / 59.0) interpolationQuality:5];
587 return _SBApplicationIcon$generateIconImage$(self, sel, type);
590 MSHook(UIImage *, SBWidgetApplicationIcon$icon, SBWidgetApplicationIcon *self, SEL sel) {
592 NSLog(@"WB:Debug:Widget(%@:%@)", [self displayIdentifier], [self displayName]);
593 if (NSString *path = $getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Icons/%@.png", [self displayName]]]))
594 return [UIImage imageWithContentsOfFile:path];
595 return _SBWidgetApplicationIcon$icon(self, sel);
598 MSHook(UIImage *, SBBookmarkIcon$icon, SBBookmarkIcon *self, SEL sel) {
600 NSLog(@"WB:Debug:Bookmark(%@:%@)", [self displayIdentifier], [self displayName]);
601 if (NSString *path = $getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Icons/%@.png", [self displayName]]]))
602 return [UIImage imageWithContentsOfFile:path];
603 return _SBBookmarkIcon$icon(self, sel);
606 MSHook(NSString *, SBApplication$pathForIcon, SBApplication *self, SEL sel) {
607 if (NSString *path = $pathForIcon$(self))
609 return _SBApplication$pathForIcon(self, sel);
612 static UIImage *CachedImageAtPath(NSString *path) {
613 path = [path stringByResolvingSymlinksInPath];
614 UIImage *image = [PathImages_ objectForKey:path];
616 return reinterpret_cast<id>(image) == [NSNull null] ? nil : image;
617 image = [[UIImage alloc] initWithContentsOfFile:path cache:true];
619 image = [image autorelease];
620 [PathImages_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:path];
624 MSHook(UIImage *, _UIApplicationImageWithName, NSString *name) {
625 NSBundle *bundle = [NSBundle mainBundle];
627 NSLog(@"WB:Debug: _UIApplicationImageWithName(\"%@\", %@)", name, bundle);
628 if (NSString *path = $pathForFile$inBundle$(name, bundle, false))
629 return CachedImageAtPath(path);
630 return __UIApplicationImageWithName(name);
633 #define WBDelegate(delegate) \
634 - (NSMethodSignature*) methodSignatureForSelector:(SEL)sel { \
636 NSLog(@"WB:MS:%s:(%s)", class_getName([self class]), sel_getName(sel)); \
637 if (NSMethodSignature *sig = [delegate methodSignatureForSelector:sel]) \
639 NSLog(@"WB:Error: [%s methodSignatureForSelector:(%s)]", class_getName([self class]), sel_getName(sel)); \
643 - (void) forwardInvocation:(NSInvocation*)inv { \
644 SEL sel = [inv selector]; \
645 if ([delegate respondsToSelector:sel]) \
646 [inv invokeWithTarget:delegate]; \
648 NSLog(@"WB:Error: [%s forwardInvocation:(%s)]", class_getName([self class]), sel_getName(sel)); \
651 // %hook -[NSBundle pathForResource:ofType:] {{{
652 MSInstanceMessageHook2(NSString *, NSBundle, pathForResource,ofType, NSString *, resource, NSString *, type) {
653 NSString *file = type == nil ? resource : [NSString stringWithFormat:@"%@.%@", resource, type];
655 NSLog(@"WB:Debug: [NSBundle(%@) pathForResource:\"%@\"]", [self bundleIdentifier], file);
656 if (NSString *path = $pathForFile$inBundle$(file, self, false))
658 return MSOldCall(resource, type);
662 static struct WBStringDrawingState {
663 WBStringDrawingState *next_;
666 } *stringDrawingState_;
668 MSInstanceMessageHook4(CGSize, NSString, drawAtPoint,forWidth,withFont,lineBreakMode, CGPoint, point, float, width, UIFont *, font, int, mode) {
669 if (stringDrawingState_ == NULL || stringDrawingState_->info_ == nil)
670 return MSOldCall(point, width, font, mode);
672 NSString *info([Info_ objectForKey:stringDrawingState_->info_]);
674 return MSOldCall(point, width, font, mode);
676 NSString *base(stringDrawingState_->base_ ?: @"");
677 stringDrawingState_ = stringDrawingState_->next_;
679 [self drawAtPoint:point withStyle:[NSString stringWithFormat:@"%@;%@;%@", [font markupDescription], base, info]];
683 MSInstanceMessageHook2(CGSize, NSString, drawAtPoint,withFont, CGPoint, point, UIFont *, font) {
684 if (stringDrawingState_ == NULL || stringDrawingState_->info_ == nil)
685 return MSOldCall(point, font);
687 NSString *info([Info_ objectForKey:stringDrawingState_->info_]);
689 return MSOldCall(point, font);
691 NSString *base(stringDrawingState_->base_ ?: @"");
692 stringDrawingState_ = stringDrawingState_->next_;
694 [self drawAtPoint:point withStyle:[NSString stringWithFormat:@"%@;%@;%@", [font markupDescription], base, info]];
698 MSInstanceMessageHook1(UIImage *, SBIconBadgeFactory, checkoutBadgeImageForText, NSString *, text) {
699 WBStringDrawingState badgeState = {NULL, @""
703 stringDrawingState_ = &badgeState;
705 UIImage *image(MSOldCall(text));
707 stringDrawingState_ = NULL;
711 MSInstanceMessageHook1(UIImage *, SBCalendarApplicationIcon, generateIconImage, int, type) {
712 WBStringDrawingState dayState = {NULL, @""
714 // XXX: this is only correct on an iPod dock
715 "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px;"
716 , @"CalendarIconDayStyle"};
718 WBStringDrawingState dateState = {&dayState, @""
720 , @"CalendarIconDateStyle"};
722 stringDrawingState_ = &dateState;
724 UIImage *image(MSOldCall(type));
726 stringDrawingState_ = NULL;
730 MSHook(void, SBCalendarIconContentsView$drawRect$, SBCalendarIconContentsView *self, SEL sel, CGRect rect) {
731 NSBundle *bundle([NSBundle mainBundle]);
733 CFLocaleRef locale(CFLocaleCopyCurrent());
734 CFDateFormatterRef formatter(CFDateFormatterCreate(NULL, locale, kCFDateFormatterNoStyle, kCFDateFormatterNoStyle));
737 CFDateRef now(CFDateCreate(NULL, CFAbsoluteTimeGetCurrent()));
739 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NUMBER_FORMAT" value:@"d" table:@"SpringBoard"]);
740 CFStringRef date(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
741 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NAME_FORMAT" value:@"cccc" table:@"SpringBoard"]);
742 CFStringRef day(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
746 CFRelease(formatter);
748 NSString *datestyle([@""
749 "font-family: Helvetica; "
750 "font-weight: bold; "
753 "" stringByAppendingString:(IsWild_
754 ? @"font-size: 54px; "
755 : @"font-size: 39px; "
758 NSString *daystyle([@""
759 "font-family: Helvetica; "
760 "font-weight: bold; "
762 "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px; "
763 "" stringByAppendingString:(IsWild_
764 ? @"font-size: 11px; "
765 : @"font-size: 9px; "
768 if (NSString *style = [Info_ objectForKey:@"CalendarIconDateStyle"])
769 datestyle = [datestyle stringByAppendingString:style];
770 if (NSString *style = [Info_ objectForKey:@"CalendarIconDayStyle"])
771 daystyle = [daystyle stringByAppendingString:style];
773 float width([self bounds].size.width);
775 CGSize datesize = [(NSString *)date sizeWithStyle:datestyle forWidth:(width + leeway)];
776 CGSize daysize = [(NSString *)day sizeWithStyle:daystyle forWidth:(width + leeway)];
778 unsigned base0(IsWild_ ? 89 : 70);
779 if ($GSFontGetUseLegacyFontMetrics())
781 unsigned base1(IsWild_ ? 18 : 16);
788 [(NSString *)date drawAtPoint:CGPointMake(
789 (width + 1 - datesize.width) / 2, (base0 - datesize.height) / 2
790 ) withStyle:datestyle];
792 [(NSString *)day drawAtPoint:CGPointMake(
793 (width + 1 - daysize.width) / 2, (base1 - daysize.height) / 2
794 ) withStyle:daystyle];
800 // %hook -[{NavigationBar,Toolbar} setBarStyle:] {{{
801 void $setBarStyle$_(NSString *name, int &style) {
803 NSLog(@"WB:Debug:%@Style:%d", name, style);
804 NSNumber *number = nil;
806 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style-%d", name, style]];
808 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style", name]];
810 style = [number intValue];
812 NSLog(@"WB:Debug:%@Style=%d", name, style);
816 MSInstanceMessageHook1(void, UIToolbar, setBarStyle, int, style) {
817 $setBarStyle$_(@"Toolbar", style);
818 return MSOldCall(style);
821 MSInstanceMessageHook1(void, UINavigationBar, setBarStyle, int, style) {
822 $setBarStyle$_(@"NavigationBar", style);
823 return MSOldCall(style);
827 MSHook(void, SBButtonBar$didMoveToSuperview, UIView *self, SEL sel) {
828 [[self superview] setBackgroundColor:[UIColor clearColor]];
829 _SBButtonBar$didMoveToSuperview(self, sel);
832 MSHook(void, SBStatusBarContentsView$didMoveToSuperview, UIView *self, SEL sel) {
833 [[self superview] setBackgroundColor:[UIColor clearColor]];
834 _SBStatusBarContentsView$didMoveToSuperview(self, sel);
837 static NSArray *Wallpapers_;
838 static bool Papered_;
840 static NSString *WallpaperFile_;
841 static UIImageView *WallpaperImage_;
842 static UIWebDocumentView *WallpaperPage_;
843 static NSURL *WallpaperURL_;
845 #define _release(object) \
846 do if (object != nil) { \
851 static UIImage *$getImage$(NSString *path) {
852 UIImage *image([UIImage imageWithContentsOfFile:path]);
854 unsigned scale($getScale$(path));
855 if (scale != 1 && [image respondsToSelector:@selector(setScale)])
856 [image setScale:scale];
861 static UIImage *$getDefaultDesktopImage$() {
862 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"LockBackground.png", @"LockBackground.jpg", nil])))
863 return $getImage$(path);
867 MSClassMessageHook0(UIImage *, UIImage, defaultDesktopImage) {
868 return $getDefaultDesktopImage$() ?: MSOldCall();
871 MSInstanceMessageHook0(UIImage *, SBSlidingAlertDisplay, _defaultDesktopImage) {
872 return $getDefaultDesktopImage$() ?: MSOldCall();
875 MSInstanceMessageHook0(void, SBWallpaperView, resetCurrentImageToWallpaper) {
876 for (UIView *parent([self superview]); parent != nil; parent = [parent superview])
877 if ([parent isKindOfClass:$SBSlidingAlertDisplay]) {
878 if (UIImage *image = $getDefaultDesktopImage$()) {
879 [self setImage:image];
889 // %hook -[SBUIController init] {{{
890 MSInstanceMessageHook0(id, SBUIController, init) {
895 NSString *paper($getTheme$(Wallpapers_));
897 paper = [paper stringByDeletingLastPathComponent];
901 sysctlbyname("hw.machine", NULL, &size, NULL, 0);
902 char *machine = new char[size];
904 if (sysctlbyname("hw.machine", machine, &size, NULL, 0) == -1) {
905 perror("sysctlbyname(\"hw.machine\", ?)");
910 IsWild_ = machine != NULL && strncmp(machine, "iPad", 4) == 0;
913 BOOL (*GSSystemHasCapability)(CFStringRef) = reinterpret_cast<BOOL (*)(CFStringRef)>(dlsym(RTLD_DEFAULT, "GSSystemHasCapability"));
915 if ([Info_ objectForKey:@"UndockedIconLabels"] == nil)
916 [Info_ setObject:[NSNumber numberWithBool:(
917 !(paper != nil || GSSystemHasCapability != NULL && GSSystemHasCapability(CFSTR("homescreen-wallpaper"))) ||
918 [Info_ objectForKey:@"DockedIconLabelStyle"] != nil ||
919 [Info_ objectForKey:@"UndockedIconLabelStyle"] != nil
920 )] forKey:@"UndockedIconLabels"];
923 NSLog(@"WB:Debug:Info = %@", [Info_ description]);
926 UIImageView *&_wallpaperView(MSHookIvar<UIImageView *>(self, "_wallpaperView"));
927 if (&_wallpaperView != NULL) {
928 [_wallpaperView removeFromSuperview];
929 [_wallpaperView release];
930 _wallpaperView = nil;
934 UIView *&_contentLayer(MSHookIvar<UIView *>(self, "_contentLayer"));
935 UIView *&_contentView(MSHookIvar<UIView *>(self, "_contentView"));
938 if (&_contentLayer != NULL)
939 player = &_contentLayer;
940 else if (&_contentView != NULL)
941 player = &_contentView;
944 UIView *layer(player == NULL ? nil : *player);
946 UIWindow *window([[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]);
947 UIView *content([[[UIView alloc] initWithFrame:[window frame]] autorelease]);
948 [window setContentView:content];
950 UIWindow *&_window(MSHookIvar<UIWindow *>(self, "_window"));
951 [window setBackgroundColor:[_window backgroundColor]];
952 [_window setBackgroundColor:[UIColor clearColor]];
954 [window setLevel:-1000];
955 [window setHidden:NO];
957 /*if (player != NULL)
960 [content setBackgroundColor:[layer backgroundColor]];
961 [layer setBackgroundColor:[UIColor clearColor]];
964 if (!SummerBoard_ || !IsWild_)
967 CGRect bounds([content bounds]);
968 bounds.origin.y = -30;
969 indirect = [[[UIView alloc] initWithFrame:bounds] autorelease];
970 [content addSubview:indirect];
971 [indirect zoomToScale:2.4];
974 _release(WallpaperFile_);
975 _release(WallpaperImage_);
976 _release(WallpaperPage_);
977 _release(WallpaperURL_);
980 NSArray *themes([NSArray arrayWithObject:paper]);
982 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"], themes)) {
986 static AVController *controller_(nil);
987 if (controller_ == nil) {
988 AVQueue *queue([AVQueue avQueue]);
989 controller_ = [[AVController avControllerWithQueue:queue error:&error] retain];
992 AVQueue *queue([controller_ queue]);
994 UIView *video([[[UIView alloc] initWithFrame:[indirect bounds]] autorelease]);
995 [controller_ setLayer:[video _layer]];
997 AVItem *item([[[AVItem alloc] initWithPath:path error:&error] autorelease]);
998 [queue appendItem:item error:&error];
1000 [controller_ play:&error];
1001 #elif UseMPMoviePlayerController
1002 NSURL *url([NSURL fileURLWithPath:path]);
1003 MPMoviePlayerController *controller = [[$MPMoviePlayerController alloc] initWithContentURL:url];
1004 controller.movieControlMode = MPMovieControlModeHidden;
1007 MPVideoView *video = [[[$MPVideoView alloc] initWithFrame:[indirect bounds]] autorelease];
1008 [video setMovieWithPath:path];
1009 [video setRepeatMode:1];
1010 [video setRepeatGap:-1];
1011 [video playFromBeginning];;
1014 [indirect addSubview:video];
1017 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"Wallpaper.png", @"Wallpaper.jpg", nil]), themes)) {
1018 if (UIImage *image = $getImage$(path)) {
1019 WallpaperFile_ = [path retain];
1020 WallpaperImage_ = [[UIImageView alloc] initWithImage:image];
1021 if (NSNumber *number = [Info_ objectForKey:@"WallpaperAlpha"])
1022 [WallpaperImage_ setAlpha:[number floatValue]];
1023 [indirect addSubview:WallpaperImage_];
1027 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.html"], themes)) {
1028 CGRect bounds = [indirect bounds];
1030 UIWebDocumentView *view([[[UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1031 [view setAutoresizes:true];
1033 WallpaperPage_ = [view retain];
1034 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
1036 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1038 [view setBackgroundColor:[UIColor clearColor]];
1039 if ([view respondsToSelector:@selector(setDrawsBackground:)])
1040 [view setDrawsBackground:NO];
1041 [[view webView] setDrawsBackground:NO];
1043 [indirect addSubview:view];
1047 for (size_t i(0), e([Themes_ count]); i != e; ++i) {
1048 NSString *theme = [Themes_ objectAtIndex:(e - i - 1)];
1049 NSString *html = [theme stringByAppendingPathComponent:@"Widget.html"];
1050 if ([Manager_ fileExistsAtPath:html]) {
1051 CGRect bounds = [indirect bounds];
1053 UIWebDocumentView *view([[[UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1054 [view setAutoresizes:true];
1056 NSURL *url = [NSURL fileURLWithPath:html];
1057 [view loadRequest:[NSURLRequest requestWithURL:url]];
1059 [view setBackgroundColor:[UIColor clearColor]];
1060 if ([view respondsToSelector:@selector(setDrawsBackground:)])
1061 [view setDrawsBackground:NO];
1062 [[view webView] setDrawsBackground:NO];
1064 [indirect addSubview:view];
1072 MSHook(void, SBAwayView$updateDesktopImage$, SBAwayView *self, SEL sel, UIImage *image) {
1073 NSString *path = $getTheme$([NSArray arrayWithObject:@"LockBackground.html"]);
1074 UIView *&_backgroundView(MSHookIvar<UIView *>(self, "_backgroundView"));
1076 if (path != nil && _backgroundView != nil)
1079 _SBAwayView$updateDesktopImage$(self, sel, image);
1082 CGRect bounds = [self bounds];
1084 UIWebDocumentView *view([[[UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1085 [view setAutoresizes:true];
1087 if (WallpaperPage_ != nil)
1088 [WallpaperPage_ release];
1089 WallpaperPage_ = [view retain];
1091 if (WallpaperURL_ != nil)
1092 [WallpaperURL_ release];
1093 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
1095 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1097 [[view webView] setDrawsBackground:false];
1098 [view setBackgroundColor:[UIColor clearColor]];
1100 [self insertSubview:view aboveSubview:_backgroundView];
1104 /*extern "C" CGColorRef CGGStateGetSystemColor(void *);
1105 extern "C" CGColorRef CGGStateGetFillColor(void *);
1106 extern "C" CGColorRef CGGStateGetStrokeColor(void *);
1107 extern "C" NSString *UIStyleStringFromColor(CGColorRef);*/
1109 /* WBTimeLabel {{{ */
1110 @interface WBTimeLabel : NSProxy {
1112 _transient SBStatusBarTimeView *view_;
1115 - (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view;
1119 @implementation WBTimeLabel
1126 - (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view {
1127 time_ = [time retain];
1132 - (NSString *) description {
1138 - (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(int)mode {
1139 if (NSString *custom = [Info_ objectForKey:@"TimeStyle"]) {
1140 BOOL &_mode(MSHookIvar<BOOL>(view_, "_mode"));;
1142 [time_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1143 "font-family: Helvetica; "
1144 "font-weight: bold; "
1147 "%@", _mode ? @"white" : @"black", custom]];
1152 return [time_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1157 /* WBBadgeLabel {{{ */
1158 @interface WBBadgeLabel : NSProxy {
1162 - (id) initWithBadge:(NSString *)badge;
1163 - (NSString *) description;
1167 @implementation WBBadgeLabel
1174 - (id) initWithBadge:(NSString *)badge {
1175 badge_ = [badge retain];
1179 - (NSString *) description {
1180 return [badge_ description];
1185 - (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(int)mode {
1186 if (NSString *custom = [Info_ objectForKey:@"BadgeStyle"]) {
1187 [badge_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1188 "font-family: Helvetica; "
1189 "font-weight: bold; "
1197 return [badge_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1204 MSInstanceMessageHook1(void, SBIcon, setIconImageAlpha, float, alpha) {
1205 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1206 alpha = [number floatValue];
1207 return MSOldCall(alpha);
1210 MSInstanceMessageHook1(void, SBIcon, setIconLabelAlpha, float, alpha) {
1211 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1212 alpha = [number floatValue];
1213 return MSOldCall(alpha);
1216 MSInstanceMessageHook0(id, SBIcon, initWithDefaultSize) {
1217 if ((self = MSOldCall()) != nil) {
1218 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"]) {
1219 // XXX: note: this is overridden above, which is silly
1220 float alpha([number floatValue]);
1221 [self setIconImageAlpha:alpha];
1222 [self setIconLabelAlpha:alpha];
1227 MSInstanceMessageHook1(void, SBIcon, setAlpha, float, alpha) {
1228 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1229 alpha = [number floatValue];
1230 return MSOldCall(alpha);
1234 MSHook(id, SBIconBadge$initWithBadge$, SBIconBadge *self, SEL sel, NSString *badge) {
1235 if ((self = _SBIconBadge$initWithBadge$(self, sel, badge)) != nil) {
1236 id &_badge(MSHookIvar<id>(self, "_badge"));
1238 if (id label = [[WBBadgeLabel alloc] initWithBadge:[_badge autorelease]])
1243 void SBStatusBarController$setStatusBarMode(int &mode) {
1245 NSLog(@"WB:Debug:setStatusBarMode:%d", mode);
1246 if (mode < 100) // 104:hidden 105:glowing
1247 if (NSNumber *number = [Info_ objectForKey:@"StatusBarMode"])
1248 mode = [number intValue];
1251 /*MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, double duration, int animation) {
1252 NSLog(@"mode:%d orientation:%d duration:%f animation:%d", mode, orientation, duration, animation);
1253 SBStatusBarController$setStatusBarMode(mode);
1254 return _SBStatusBarController$setStatusBarMode$orientation$duration$animation$(self, sel, mode, orientation, duration, animation);
1257 MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, float duration, int fenceID, int animation) {
1258 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d", mode, orientation, duration, fenceID, animation);
1259 SBStatusBarController$setStatusBarMode(mode);
1260 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$(self, sel, mode, orientation, duration, fenceID, animation);
1263 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) {
1264 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d startTime:%f", mode, orientation, duration, fenceID, animation, startTime);
1265 SBStatusBarController$setStatusBarMode(mode);
1266 //NSLog(@"mode=%u", mode);
1267 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$startTime$(self, sel, mode, orientation, duration, fenceID, animation, startTime);
1270 /*MSHook(id, SBStatusBarContentsView$initWithStatusBar$mode$, SBStatusBarContentsView *self, SEL sel, id bar, int mode) {
1271 if (NSNumber *number = [Info_ objectForKey:@"StatusBarContentsMode"])
1272 mode = [number intValue];
1273 return _SBStatusBarContentsView$initWithStatusBar$mode$(self, sel, bar, mode);
1276 MSHook(NSString *, SBStatusBarOperatorNameView$operatorNameStyle, SBStatusBarOperatorNameView *self, SEL sel) {
1277 NSString *style(_SBStatusBarOperatorNameView$operatorNameStyle(self, sel));
1279 NSLog(@"operatorNameStyle= %@", style);
1280 if (NSString *custom = [Info_ objectForKey:@"OperatorNameStyle"])
1281 style = [NSString stringWithFormat:@"%@; %@", style, custom];
1285 MSHook(void, SBStatusBarOperatorNameView$setOperatorName$fullSize$, SBStatusBarOperatorNameView *self, SEL sel, NSString *name, BOOL full) {
1287 NSLog(@"setOperatorName:\"%@\" fullSize:%u", name, full);
1288 return _SBStatusBarOperatorNameView$setOperatorName$fullSize$(self, sel, name, NO);
1291 // XXX: replace this with [SBStatusBarTimeView tile]
1292 MSHook(void, SBStatusBarTimeView$drawRect$, SBStatusBarTimeView *self, SEL sel, CGRect rect) {
1293 id &_time(MSHookIvar<id>(self, "_time"));
1294 if (_time != nil && [_time class] != [WBTimeLabel class])
1295 object_setInstanceVariable(self, "_time", reinterpret_cast<void *>([[WBTimeLabel alloc] initWithTime:[_time autorelease] view:self]));
1296 return _SBStatusBarTimeView$drawRect$(self, sel, rect);
1299 @interface UIView (WinterBoard)
1300 - (bool) wb$isWBImageView;
1301 - (void) wb$logHierarchy;
1304 @implementation UIView (WinterBoard)
1306 - (bool) wb$isWBImageView {
1310 - (void) wb$logHierarchy {
1311 WBLogHierarchy(self);
1316 @interface WBImageView : UIImageView {
1319 - (bool) wb$isWBImageView;
1320 - (void) wb$updateFrame;
1323 @implementation WBImageView
1325 - (bool) wb$isWBImageView {
1329 - (void) wb$updateFrame {
1330 CGRect frame([self frame]);
1333 for (UIView *view(self); ; ) {
1334 view = [view superview];
1337 frame.origin.y -= [view frame].origin.y;
1340 [self setFrame:frame];
1345 MSHook(void, SBIconList$setFrame$, SBIconList *self, SEL sel, CGRect frame) {
1346 NSArray *subviews([self subviews]);
1347 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1348 if (view != nil && [view wb$isWBImageView])
1349 [view wb$updateFrame];
1350 _SBIconList$setFrame$(self, sel, frame);
1353 MSHook(void, SBIconController$noteNumberOfIconListsChanged, SBIconController *self, SEL sel) {
1354 SBIconModel *&_iconModel(MSHookIvar<SBIconModel *>(self, "_iconModel"));
1355 NSArray *lists([_iconModel iconLists]);
1357 for (unsigned i(0), e([lists count]); i != e; ++i)
1358 if (NSString *path = $getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Page%u.png", i]])) {
1359 SBIconList *list([lists objectAtIndex:i]);
1360 NSArray *subviews([list subviews]);
1362 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1363 if (view == nil || ![view wb$isWBImageView]) {
1364 view = [[[WBImageView alloc] init] autorelease];
1365 [list insertSubview:view atIndex:0];
1368 UIImage *image([UIImage imageWithContentsOfFile:path]);
1370 CGRect frame([view frame]);
1371 frame.size = [image size];
1372 [view setFrame:frame];
1374 [view setImage:image];
1375 [view wb$updateFrame];
1378 return _SBIconController$noteNumberOfIconListsChanged(self, sel);
1381 MSHook(id, SBIconLabel$initWithSize$label$, SBIconLabel *self, SEL sel, CGSize size, NSString *label) {
1382 self = _SBIconLabel$initWithSize$label$(self, sel, size, label);
1384 [self setClipsToBounds:NO];
1388 MSHook(void, SBIconLabel$setInDock$, SBIconLabel *self, SEL sel, BOOL docked) {
1389 id &_label(MSHookIvar<id>(self, "_label"));
1390 if (![Info_ wb$boolForKey:@"UndockedIconLabels"])
1392 if (_label != nil && [_label respondsToSelector:@selector(setInDock:)])
1393 [_label setInDock:docked];
1394 return _SBIconLabel$setInDock$(self, sel, docked);
1397 MSHook(BOOL, SBDockIconListView$shouldShowNewDock, id self, SEL sel) {
1398 return SummerBoard_ && Docked_ ? NO : _SBDockIconListView$shouldShowNewDock(self, sel);
1401 MSHook(void, SBDockIconListView$setFrame$, id self, SEL sel, CGRect frame) {
1402 _SBDockIconListView$setFrame$(self, sel, frame);
1405 // %hook -[NSBundle localizedStringForKey:value:table:] {{{
1406 MSInstanceMessageHook3(NSString *, NSBundle, localizedStringForKey,value,table, NSString *, key, NSString *, value, NSString *, table) {
1407 NSString *identifier = [self bundleIdentifier];
1408 NSLocale *locale = [NSLocale currentLocale];
1409 NSString *language = [locale objectForKey:NSLocaleLanguageCode];
1411 NSLog(@"WB:Debug:[NSBundle(%@) localizedStringForKey:\"%@\" value:\"%@\" table:\"%@\"] (%@)", identifier, key, value, table, language);
1412 NSString *file = table == nil ? @"Localizable" : table;
1413 NSString *name = [NSString stringWithFormat:@"%@:%@", identifier, file];
1414 NSDictionary *strings;
1415 if ((strings = [Strings_ objectForKey:name]) != nil) {
1416 if (static_cast<id>(strings) != [NSNull null]) strings:
1417 if (NSString *value = [strings objectForKey:key])
1419 } else if (NSString *path = $pathForFile$inBundle$([NSString stringWithFormat:@"%@.lproj/%@.strings",
1422 if ((strings = [[NSDictionary alloc] initWithContentsOfFile:path]) != nil) {
1423 [Strings_ setObject:[strings autorelease] forKey:name];
1427 [Strings_ setObject:[NSNull null] forKey:name];
1428 return MSOldCall(key, value, table);
1431 // %hook -[WebCoreFrameBridge renderedSizeOfNode:constrainedToWidth:] {{{
1432 MSClassHook(WebCoreFrameBridge)
1434 MSInstanceMessageHook2(CGSize, WebCoreFrameBridge, renderedSizeOfNode,constrainedToWidth, id, node, float, width) {
1437 void **core(reinterpret_cast<void **>([node _node]));
1438 if (core == NULL || core[6] == NULL)
1440 return MSOldCall(node, width);
1444 MSInstanceMessageHook1(void, SBIconLabel, drawRect, CGRect, rect) {
1445 CGRect bounds = [self bounds];
1447 static Ivar drawMoreLegibly = object_getInstanceVariable(self, "_drawMoreLegibly", NULL);
1450 Ivar ivar = object_getInstanceVariable(self, "_inDock", reinterpret_cast<void **>(&docked));
1451 docked = (docked & (ivar_getOffset(ivar) == ivar_getOffset(drawMoreLegibly) ? 0x2 : 0x1)) != 0;
1453 NSString *label(MSHookIvar<NSString *>(self, "_label"));
1455 NSString *style = [NSString stringWithFormat:@""
1456 "font-family: Helvetica; "
1457 "font-weight: bold; "
1459 "", (docked || !SummerBoard_ ? @"white" : @"#b3b3b3"), (IsWild_
1460 ? @"font-size: 12px; "
1461 : @"font-size: 11px; "
1465 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px 1px 0px; "];
1467 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px -1px 0px; "];
1469 bool ellipsis(false);
1470 float max = [self frame].size.width - 11, width;
1472 width = [(ellipsis ? [label stringByAppendingString:@"..."] : label) sizeWithStyle:style forWidth:320].width;
1475 size_t length([label length]);
1476 float spacing((width - max) / (length - 1));
1478 if (spacing > 1.25) {
1480 label = [label substringToIndex:(length - 1)];
1484 style = [style stringByAppendingString:[NSString stringWithFormat:@"letter-spacing: -%f; ", spacing]];
1488 label = [label stringByAppendingString:@"..."];
1490 if (NSString *custom = [Info_ objectForKey:(docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle")])
1491 style = [style stringByAppendingString:custom];
1493 CGSize size = [label sizeWithStyle:style forWidth:bounds.size.width];
1494 [label drawAtPoint:CGPointMake((bounds.size.width - size.width) / 2, 0) withStyle:style];
1498 MSInstanceMessageHook1(void, CKMessageCell, addBalloonView, CKBalloonView *, balloon) {
1500 [balloon setBackgroundColor:[UIColor clearColor]];
1503 MSInstanceMessageHook1(void, CKTranscriptCell, setBackgroundColor, UIColor *, color) {
1504 MSOldCall([UIColor clearColor]);
1507 MSInstanceMessageHook2(id, CKTranscriptCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1508 if ((self = MSOldCall(style, reuse)) != nil) {
1509 [self setBackgroundColor:[UIColor clearColor]];
1510 [[self contentView] setBackgroundColor:[UIColor clearColor]];
1514 MSInstanceMessageHook2(id, CKMessageCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1515 if ((self = MSOldCall(style, reuse)) != nil) {
1516 [self setBackgroundColor:[UIColor clearColor]];
1517 [[self contentView] setBackgroundColor:[UIColor clearColor]];
1521 MSInstanceMessageHook2(id, CKTimestampView, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1522 if ((self = MSOldCall(style, reuse)) != nil) {
1523 UILabel *&_label(MSHookIvar<UILabel *>(self, "_label"));
1524 [_label setBackgroundColor:[UIColor clearColor]];
1528 MSInstanceMessageHook1(void, CKTranscriptTableView, setSeparatorStyle, int, style) {
1529 MSOldCall(UITableViewCellSeparatorStyleNone);
1532 MSInstanceMessageHook2(id, CKTranscriptTableView, initWithFrame,style, CGRect, frame, int, style) {
1533 if ((self = MSOldCall(frame, style)) != nil) {
1534 [self setSeparatorStyle:UITableViewCellSeparatorStyleNone];
1538 MSInstanceMessageHook0(void, CKTranscriptController, loadView) {
1541 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"SMSBackground.png", @"SMSBackground.jpg", nil])))
1542 if (UIImage *image = $getImage$(path)) {
1543 UIView *&_transcriptTable(MSHookIvar<UIView *>(self, "_transcriptTable"));
1544 UIView *&_transcriptLayer(MSHookIvar<UIView *>(self, "_transcriptLayer"));
1546 if (&_transcriptTable != NULL)
1547 table = _transcriptTable;
1548 else if (&_transcriptLayer != NULL)
1549 table = _transcriptLayer;
1553 UIView *placard(table != nil ? [table superview] : MSHookIvar<UIView *>(self, "_backPlacard"));
1554 UIImageView *background([[[UIImageView alloc] initWithImage:image] autorelease]);
1557 [placard insertSubview:background atIndex:0];
1559 [table setBackgroundColor:[UIColor clearColor]];
1560 [placard insertSubview:background belowSubview:table];
1566 // %hook _UIImageWithName() {{{
1567 MSHook(UIImage *, _UIImageWithName, NSString *name) {
1569 NSLog(@"WB:Debug: _UIImageWithName(\"%@\")", name);
1576 if (_UIPackedImageTableGetIdentifierForName != NULL)
1577 packed = _UIPackedImageTableGetIdentifierForName(name, &identifier);
1578 else if (_UISharedImageNameGetIdentifier != NULL) {
1579 identifier = _UISharedImageNameGetIdentifier(name);
1580 packed = identifier != -1;
1587 NSLog(@"WB:Debug: _UISharedImageNameGetIdentifier(\"%@\") = %d", name, identifier);
1590 return __UIImageWithName(name);
1592 NSNumber *key([NSNumber numberWithInt:identifier]);
1593 UIImage *image([UIImages_ objectForKey:key]);
1595 return reinterpret_cast<id>(image) == [NSNull null] ? __UIImageWithName(name) : image;
1596 if (NSString *path = $pathForFile$inBundle$(name, _UIKitBundle(), true))
1597 image = $getImage$(path);
1598 [UIImages_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:key];
1602 image = __UIImageWithName(name);
1605 NSString *path([@"/tmp/UIImages/" stringByAppendingString:name]);
1606 if (![Manager_ fileExistsAtPath:path])
1607 [UIImagePNGRepresentation(image) writeToFile:path atomically:YES];
1614 // %hook _UIImageWithNameInDomain() {{{
1615 MSHook(UIImage *, _UIImageWithNameInDomain, NSString *name, NSString *domain) {
1616 NSString *key([NSString stringWithFormat:@"D:%zu%@%@", [domain length], domain, name]);
1617 UIImage *image([PathImages_ objectForKey:key]);
1619 return reinterpret_cast<id>(image) == [NSNull null] ? __UIImageWithNameInDomain(name, domain) : image;
1621 NSLog(@"WB:Debug: UIImageWithNameInDomain(\"%@\", \"%@\")", name, domain);
1622 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObject:[NSString stringWithFormat:@"Domains/%@/%@", domain, name]])))
1623 image = $getImage$(path);
1624 [PathImages_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:key];
1625 return image == nil ? __UIImageWithNameInDomain(name, domain) : image;
1629 // %hook GSFontCreateWithName() {{{
1630 MSHook(GSFontRef, GSFontCreateWithName, const char *name, GSFontSymbolicTraits traits, float size) {
1632 NSLog(@"WB:Debug: GSFontCreateWithName(\"%s\", %f)", name, size);
1633 if (NSString *font = [Info_ objectForKey:[NSString stringWithFormat:@"FontName-%s", name]])
1634 name = [font UTF8String];
1635 //if (NSString *scale = [Info_ objectForKey:[NSString stringWithFormat:@"FontScale-%s", name]])
1636 // size *= [scale floatValue];
1637 return _GSFontCreateWithName(name, traits, size);
1641 #define AudioToolbox "/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox"
1642 #define UIKit "/System/Library/Frameworks/UIKit.framework/UIKit"
1644 bool (*_Z24GetFileNameForThisActionmPcRb)(unsigned long a0, char *a1, bool &a2);
1646 MSHook(bool, _Z24GetFileNameForThisActionmPcRb, unsigned long a0, char *a1, bool &a2) {
1648 NSLog(@"WB:Debug:GetFileNameForThisAction(%u, %p, %u)", a0, a1, a2);
1649 bool value = __Z24GetFileNameForThisActionmPcRb(a0, a1, a2);
1651 NSLog(@"WB:Debug:GetFileNameForThisAction(%u, %s, %u) = %u", a0, value ? a1 : NULL, a2, value);
1654 NSString *path = [NSString stringWithUTF8String:a1];
1655 if ([path hasPrefix:@"/System/Library/Audio/UISounds/"]) {
1656 NSString *file = [path substringFromIndex:31];
1657 for (NSString *theme in Themes_) {
1658 NSString *path([NSString stringWithFormat:@"%@/UISounds/%@", theme, file]);
1659 if ([Manager_ fileExistsAtPath:path]) {
1660 strcpy(a1, [path UTF8String]);
1669 static void ChangeWallpaper(
1670 CFNotificationCenterRef center,
1674 CFDictionaryRef info
1677 NSLog(@"WB:Debug:ChangeWallpaper!");
1680 if (WallpaperFile_ != nil) {
1681 image = [[UIImage alloc] initWithContentsOfFile:WallpaperFile_];
1683 image = [image autorelease];
1686 if (WallpaperImage_ != nil)
1687 [WallpaperImage_ setImage:image];
1688 if (WallpaperPage_ != nil)
1689 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1693 #define WBRename(name, sel, imp) \
1694 _ ## name ## $ ## imp = MSHookMessage($ ## name, @selector(sel), &$ ## name ## $ ## imp)
1696 template <typename Type_>
1697 static void msset(Type_ &function, MSImageRef image, const char *name) {
1698 function = reinterpret_cast<Type_>(MSFindSymbol(image, name));
1701 template <typename Type_>
1702 static void nlset(Type_ &function, struct nlist *nl, size_t index) {
1703 struct nlist &name(nl[index]);
1704 uintptr_t value(name.n_value);
1705 if ((name.n_desc & N_ARM_THUMB_DEF) != 0)
1706 value |= 0x00000001;
1707 function = reinterpret_cast<Type_>(value);
1710 template <typename Type_>
1711 static void dlset(Type_ &function, const char *name) {
1712 function = reinterpret_cast<Type_>(dlsym(RTLD_DEFAULT, name));
1715 // %hook CGImageReadCreateWithFile() {{{
1716 MSHook(void *, CGImageReadCreateWithFile, NSString *path, int flag) {
1718 NSLog(@"WB:Debug: CGImageReadCreateWithFile(%@, %d)", path, flag);
1719 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
1720 void *value(_CGImageReadCreateWithFile([path wb$themedPath], flag));
1726 static void NSString$drawAtPoint$withStyle$(NSString *self, SEL _cmd, CGPoint point, NSString *style) {
1727 WKSetCurrentGraphicsContext(UIGraphicsGetCurrentContext());
1728 if (style == nil || [style length] == 0)
1729 style = @"font-family: Helvetica; font-size: 12px";
1730 return [[WBMarkup sharedMarkup] drawString:self atPoint:point withStyle:style];
1733 static CGSize NSString$sizeWithStyle$forWidth$(NSString *self, SEL _cmd, NSString *style, float width) {
1734 if (style == nil || [style length] == 0)
1735 style = @"font-family: Helvetica; font-size: 12px";
1736 return [[WBMarkup sharedMarkup] sizeOfString:self withStyle:style forWidth:width];
1739 static void SBInitialize() {
1740 class_addMethod($NSString, @selector(drawAtPoint:withStyle:), (IMP) &NSString$drawAtPoint$withStyle$, "v20@0:4{CGPoint=ff}8@16");
1741 class_addMethod($NSString, @selector(sizeWithStyle:forWidth:), (IMP) &NSString$sizeWithStyle$forWidth$, "{CGSize=ff}16@0:4@8f12");
1744 WBRename(SBApplication, pathForIcon, pathForIcon);
1745 WBRename(SBApplicationIcon, icon, icon);
1746 WBRename(SBApplicationIcon, generateIconImage:, generateIconImage$);
1749 WBRename(SBBookmarkIcon, icon, icon);
1750 WBRename(SBButtonBar, didMoveToSuperview, didMoveToSuperview);
1751 WBRename(SBCalendarIconContentsView, drawRect:, drawRect$);
1752 WBRename(SBIconBadge, initWithBadge:, initWithBadge$);
1753 WBRename(SBIconController, noteNumberOfIconListsChanged, noteNumberOfIconListsChanged);
1755 WBRename(SBWidgetApplicationIcon, icon, icon);
1757 WBRename(SBDockIconListView, setFrame:, setFrame$);
1758 MSHookMessage(object_getClass($SBDockIconListView), @selector(shouldShowNewDock), &$SBDockIconListView$shouldShowNewDock, &_SBDockIconListView$shouldShowNewDock);
1760 WBRename(SBIconLabel, initWithSize:label:, initWithSize$label$);
1761 WBRename(SBIconLabel, setInDock:, setInDock$);
1763 WBRename(SBIconList, setFrame:, setFrame$);
1765 WBRename(SBIconModel, cacheImageForIcon:, cacheImageForIcon$);
1766 WBRename(SBIconModel, cacheImagesForIcon:, cacheImagesForIcon$);
1767 WBRename(SBIconModel, getCachedImagedForIcon:, getCachedImagedForIcon$);
1768 WBRename(SBIconModel, getCachedImagedForIcon:smallIcon:, getCachedImagedForIcon$smallIcon$);
1770 WBRename(SBSearchView, initWithFrame:, initWithFrame$);
1771 WBRename(SBSearchTableViewCell, drawRect:, drawRect$);
1772 WBRename(SBSearchTableViewCell, initWithStyle:reuseIdentifier:, initWithStyle$reuseIdentifier$);
1774 //WBRename(SBImageCache, initWithName:forImageWidth:imageHeight:initialCapacity:, initWithName$forImageWidth$imageHeight$initialCapacity$);
1776 WBRename(SBAwayView, updateDesktopImage:, updateDesktopImage$);
1777 WBRename(SBStatusBarContentsView, didMoveToSuperview, didMoveToSuperview);
1778 //WBRename(SBStatusBarContentsView, initWithStatusBar:mode:, initWithStatusBar$mode$);
1779 //WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:animation:, setStatusBarMode$orientation$duration$animation$);
1780 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:, setStatusBarMode$orientation$duration$fenceID$animation$);
1781 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:startTime:, setStatusBarMode$orientation$duration$fenceID$animation$startTime$);
1782 WBRename(SBStatusBarOperatorNameView, operatorNameStyle, operatorNameStyle);
1783 WBRename(SBStatusBarOperatorNameView, setOperatorName:fullSize:, setOperatorName$fullSize$);
1784 WBRename(SBStatusBarTimeView, drawRect:, drawRect$);
1787 English_ = [[NSDictionary alloc] initWithContentsOfFile:@"/System/Library/CoreServices/SpringBoard.app/English.lproj/LocalizedApplicationNames.strings"];
1791 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
1793 NSString *identifier([[NSBundle mainBundle] bundleIdentifier]);
1794 SpringBoard_ = [identifier isEqualToString:@"com.apple.springboard"];
1796 Manager_ = [[NSFileManager defaultManager] retain];
1797 Themes_ = [[NSMutableArray alloc] initWithCapacity:8];
1799 dlset(_GSFontGetUseLegacyFontMetrics, "GSFontGetUseLegacyFontMetrics");
1801 // Load Settings.plist {{{
1802 if (NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"/User/Library/Preferences/com.saurik.WinterBoard.plist"]]) {
1803 if (NSNumber *value = [settings objectForKey:@"SummerBoard"])
1804 SummerBoard_ = [value boolValue];
1805 if (NSNumber *value = [settings objectForKey:@"Debug"])
1806 Debug_ = [value boolValue];
1808 NSArray *themes([settings objectForKey:@"Themes"]);
1810 if (NSString *theme = [settings objectForKey:@"Theme"])
1811 themes = [NSArray arrayWithObject:[NSDictionary dictionaryWithObjectsAndKeys:
1813 [NSNumber numberWithBool:true], @"Active",
1817 for (NSDictionary *theme in themes) {
1818 NSNumber *active([theme objectForKey:@"Active"]);
1819 if (![active boolValue])
1822 NSString *name([theme objectForKey:@"Name"]);
1826 NSString *theme(nil);
1828 #define testForTheme(format...) \
1829 if (theme == nil) { \
1830 NSString *path = [NSString stringWithFormat:format]; \
1831 if ([Manager_ fileExistsAtPath:path]) { \
1832 [Themes_ addObject:path]; \
1837 testForTheme(@"/Library/Themes/%@.theme", name)
1838 testForTheme(@"/Library/Themes/%@", name)
1839 testForTheme(@"%@/Library/SummerBoard/Themes/%@", NSHomeDirectory(), name)
1844 // Merge Info.plist {{{
1845 Info_ = [[NSMutableDictionary dictionaryWithCapacity:16] retain];
1847 for (NSString *theme in Themes_)
1848 if (NSDictionary *info = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"%@/Info.plist", theme]])
1849 for (NSString *key in [info allKeys])
1850 if ([Info_ objectForKey:key] == nil)
1851 [Info_ setObject:[info objectForKey:key] forKey:key];
1855 if (MSImageRef image = MSGetImageByName(AudioToolbox)) {
1856 msset(_Z24GetFileNameForThisActionmPcRb, image, "__Z24GetFileNameForThisActionmPcRb");
1857 MSHookFunction(_Z24GetFileNameForThisActionmPcRb, &$_Z24GetFileNameForThisActionmPcRb, &__Z24GetFileNameForThisActionmPcRb);
1860 // GraphicsServices {{{
1862 MSHookFunction(&GSFontCreateWithName, &$GSFontCreateWithName, &_GSFontCreateWithName);
1866 if (MSImageRef image = MSGetImageByName("/System/Library/Frameworks/ImageIO.framework/ImageIO")) {
1867 void *(*CGImageReadCreateWithFile)(NSString *, int);
1868 msset(CGImageReadCreateWithFile, image, "_CGImageReadCreateWithFile");
1869 MSHookFunction(CGImageReadCreateWithFile, MSHake(CGImageReadCreateWithFile));
1874 Wallpapers_ = [[NSArray arrayWithObjects:@"Wallpaper.mp4", @"Wallpaper@2x.png", @"Wallpaper@2x.jpg", @"Wallpaper.png", @"Wallpaper.jpg", @"Wallpaper.html", nil] retain];
1875 Docked_ = $getTheme$([NSArray arrayWithObjects:@"Dock.png", nil]);
1877 CFNotificationCenterAddObserver(
1878 CFNotificationCenterGetDarwinNotifyCenter(),
1879 NULL, &ChangeWallpaper, (CFStringRef) @"com.saurik.winterboard.lockbackground", NULL, 0
1882 if ($getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"]) != nil) {
1883 NSBundle *MediaPlayer([NSBundle bundleWithPath:@"/System/Library/Frameworks/MediaPlayer.framework"]);
1884 if (MediaPlayer != nil)
1887 $MPMoviePlayerController = objc_getClass("MPMoviePlayerController");
1888 $MPVideoView = objc_getClass("MPVideoView");
1895 if ([NSBundle bundleWithIdentifier:@"com.apple.UIKit"] != nil) {
1897 memset(nl, 0, sizeof(nl));
1898 nl[0].n_un.n_name = (char *) "__UIApplicationImageWithName";
1899 nl[1].n_un.n_name = (char *) "__UIImageWithNameInDomain";
1900 nl[2].n_un.n_name = (char *) "__UIKitBundle";
1901 nl[3].n_un.n_name = (char *) "__UIPackedImageTableGetIdentifierForName";
1902 nl[4].n_un.n_name = (char *) "__UISharedImageNameGetIdentifier";
1905 nlset(_UIApplicationImageWithName, nl, 0);
1906 nlset(_UIImageWithNameInDomain, nl, 1);
1907 nlset(_UIKitBundle, nl, 2);
1908 nlset(_UIPackedImageTableGetIdentifierForName, nl, 3);
1909 nlset(_UISharedImageNameGetIdentifier, nl, 4);
1911 MSHookFunction(_UIApplicationImageWithName, &$_UIApplicationImageWithName, &__UIApplicationImageWithName);
1912 MSHookFunction(_UIImageWithName, &$_UIImageWithName, &__UIImageWithName);
1913 MSHookFunction(_UIImageWithNameInDomain, &$_UIImageWithNameInDomain, &__UIImageWithNameInDomain);
1917 if (Debug_ && [Manager_ fileExistsAtPath:@"/tmp/UIImages"])