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 MSClassHook(UINavigationBar)
122 MSClassHook(UIToolbar)
124 MSClassHook(CKMessageCell)
125 MSClassHook(CKTimestampView)
126 MSClassHook(CKTranscriptCell)
127 MSClassHook(CKTranscriptController)
128 MSClassHook(CKTranscriptTableView)
130 MSClassHook(SBApplication)
131 MSClassHook(SBApplicationIcon)
132 MSClassHook(SBAwayView)
133 MSClassHook(SBBookmarkIcon)
134 MSClassHook(SBButtonBar)
135 MSClassHook(SBCalendarApplicationIcon)
136 MSClassHook(SBCalendarIconContentsView)
137 MSClassHook(SBDockIconListView)
139 MSClassHook(SBIconBadge)
140 MSClassHook(SBIconBadgeFactory)
141 MSClassHook(SBIconController)
142 MSClassHook(SBIconLabel)
143 MSClassHook(SBIconList)
144 MSClassHook(SBIconModel)
145 //MSClassHook(SBImageCache)
146 MSClassHook(SBSearchView)
147 MSClassHook(SBSearchTableViewCell)
148 MSClassHook(SBStatusBarContentsView)
149 MSClassHook(SBStatusBarController)
150 MSClassHook(SBStatusBarOperatorNameView)
151 MSClassHook(SBStatusBarTimeView)
152 MSClassHook(SBUIController)
153 MSClassHook(SBWidgetApplicationIcon)
155 extern "C" void WKSetCurrentGraphicsContext(CGContextRef);
157 __attribute__((__constructor__))
158 static void MSFixClass() {
160 $SBIcon = objc_getClass("SBIconView");
161 if ($CKTranscriptController == nil)
162 $CKTranscriptController = objc_getClass("mSMSMessageTranscriptController");
166 static bool Four_($SBDockIconListView != nil);
168 @interface NSDictionary (WinterBoard)
169 - (UIColor *) wb$colorForKey:(NSString *)key;
170 - (BOOL) wb$boolForKey:(NSString *)key;
173 @implementation NSDictionary (WinterBoard)
175 - (UIColor *) wb$colorForKey:(NSString *)key {
176 NSString *value = [self objectForKey:key];
183 - (BOOL) wb$boolForKey:(NSString *)key {
184 if (NSString *value = [self objectForKey:key])
185 return [value boolValue];
191 static BOOL (*_GSFontGetUseLegacyFontMetrics)();
192 #define $GSFontGetUseLegacyFontMetrics() \
193 (_GSFontGetUseLegacyFontMetrics == NULL ? YES : _GSFontGetUseLegacyFontMetrics())
195 static bool Debug_ = false;
196 static bool UIDebug_ = false;
197 static bool Engineer_ = false;
198 static bool SummerBoard_ = true;
199 static bool SpringBoard_;
201 static UIImage *(*_UIApplicationImageWithName)(NSString *name);
202 static UIImage *(*_UIImageWithNameInDomain)(NSString *name, NSString *domain);
203 static NSBundle *(*_UIKitBundle)();
204 static bool (*_UIPackedImageTableGetIdentifierForName)(NSString *, int *);
205 static int (*_UISharedImageNameGetIdentifier)(NSString *);
207 static NSMutableDictionary *UIImages_ = [[NSMutableDictionary alloc] initWithCapacity:32];
208 static NSMutableDictionary *PathImages_ = [[NSMutableDictionary alloc] initWithCapacity:16];
209 static NSMutableDictionary *Cache_ = [[NSMutableDictionary alloc] initWithCapacity:64];
210 static NSMutableDictionary *Strings_ = [[NSMutableDictionary alloc] initWithCapacity:0];
211 static NSMutableDictionary *Bundles_ = [[NSMutableDictionary alloc] initWithCapacity:2];
213 static NSFileManager *Manager_;
214 static NSMutableArray *Themes_;
216 static NSDictionary *English_;
217 static NSMutableDictionary *Info_;
220 static NSMutableDictionary *Themed_ = [[NSMutableDictionary alloc] initWithCapacity:128];
222 static unsigned Scale_ = 0;
224 static unsigned $getScale$(NSString *path) {
225 NSString *name(path);
227 #define StripName(strip) \
228 if ([name hasSuffix:@ strip]) \
229 name = [name substringWithRange:NSMakeRange(0, [name length] - sizeof(strip) - 1)];
233 StripName("~iphone");
236 return [name hasSuffix:@"@2x"] ? 2 : 1;
239 static NSArray *$useScale$(NSArray *files, bool use = true) {
241 UIScreen *screen([UIScreen mainScreen]);
242 if ([screen respondsToSelector:@selector(scale)])
243 Scale_ = [screen scale];
251 NSString *idiom(IsWild_ ? @"ipad" : @"iphone");
253 NSMutableArray *scaled([NSMutableArray arrayWithCapacity:([files count] * 4)]);
255 for (NSString *file in files) {
256 NSString *base([file stringByDeletingPathExtension]);
257 NSString *extension([file pathExtension]);
261 [scaled addObject:[NSString stringWithFormat:@"%@@2x~%@.%@", base, idiom, extension]];
263 [scaled addObject:[NSString stringWithFormat:@"%@@2x.%@", base, extension]];
266 [scaled addObject:[NSString stringWithFormat:@"%@~%@.%@", base, idiom, extension]];
268 // if (!IsWild_) <- support old themes
269 [scaled addObject:file];
270 } else if ([base hasSuffix: @"@2x"]) {
271 [scaled addObject:[NSString stringWithFormat:@"%@~iphone.%@", base, extension]];
272 [scaled addObject:file];
274 NSString *rest([base substringWithRange:NSMakeRange(0, [base length] - 3)]);
275 [scaled addObject:[NSString stringWithFormat:@"%@~iphone.%@", rest, extension]];
276 [scaled addObject:[rest stringByAppendingPathExtension:extension]];
278 // XXX: this code isn't really complete
280 [scaled addObject:file];
282 if ([base hasSuffix:@"~iphone"])
283 [scaled addObject:[[base substringWithRange:NSMakeRange(0, [base length] - 7)] stringByAppendingPathExtension:extension]];
290 static NSString *$getTheme$(NSArray *files, NSArray *themes = Themes_) {
291 if (NSString *path = [Themed_ objectForKey:files])
292 return reinterpret_cast<id>(path) == [NSNull null] ? nil : path;
295 NSLog(@"WB:Debug: %@", [files description]);
299 for (NSString *theme in Themes_)
300 for (NSString *file in files) {
301 path = [NSString stringWithFormat:@"%@/%@", theme, file];
302 if ([Manager_ fileExistsAtPath:path])
309 [Themed_ setObject:(path == nil ? [NSNull null] : reinterpret_cast<id>(path)) forKey:files];
313 // $pathForFile$inBundle$() {{{
314 static NSString *$pathForFile$inBundle$(NSString *file, NSBundle *bundle, bool ui) {
315 NSString *identifier = [bundle bundleIdentifier];
316 NSMutableArray *names = [NSMutableArray arrayWithCapacity:8];
318 if (identifier != nil)
319 [names addObject:[NSString stringWithFormat:@"Bundles/%@/%@", identifier, file]];
320 if (NSString *folder = [[bundle bundlePath] lastPathComponent])
321 [names addObject:[NSString stringWithFormat:@"Folders/%@/%@", folder, file]];
323 [names addObject:[NSString stringWithFormat:@"UIImages/%@", file]];
325 #define remapResourceName(oldname, newname) \
326 else if ([file isEqualToString:(oldname)]) \
327 [names addObject:[NSString stringWithFormat:@"%@.png", newname]]; \
329 bool summer(SpringBoard_ && SummerBoard_);
331 if (identifier == nil);
332 else if ([identifier isEqualToString:@"com.apple.chatkit"])
333 [names addObject:[NSString stringWithFormat:@"Bundles/com.apple.MobileSMS/%@", file]];
334 else if ([identifier isEqualToString:@"com.apple.calculator"])
335 [names addObject:[NSString stringWithFormat:@"Files/Applications/Calculator.app/%@", file]];
337 remapResourceName(@"FSO_BG.png", @"StatusBar")
338 remapResourceName(Four_ ? @"SBDockBG-old.png" : @"SBDockBG.png", @"Dock")
339 remapResourceName(@"SBWeatherCelsius.png", @"Icons/Weather")
341 if (NSString *path = $getTheme$($useScale$(names, ui)))
348 static NSString *$pathForIcon$(SBApplication *self, NSString *suffix = @"") {
349 NSString *identifier = [self bundleIdentifier];
350 NSString *path = [self path];
351 NSString *folder = [path lastPathComponent];
352 NSString *dname = [self displayName];
353 NSString *didentifier = [self displayIdentifier];
356 NSLog(@"WB:Debug: [SBApplication(%@:%@:%@:%@) pathForIcon]", identifier, folder, dname, didentifier);
358 NSMutableArray *names = [NSMutableArray arrayWithCapacity:8];
360 /* XXX: I might need to keep this for backwards compatibility
361 if (identifier != nil)
362 [names addObject:[NSString stringWithFormat:@"Bundles/%@/icon.png", identifier]];
364 [names addObject:[NSString stringWithFormat:@"Folders/%@/icon.png", folder]]; */
366 #define testForIcon(Name) \
367 if (NSString *name = Name) \
368 [names addObject:[NSString stringWithFormat:@"Icons%@/%@.png", suffix, name]];
370 if (![didentifier isEqualToString:identifier])
371 testForIcon(didentifier);
373 testForIcon(identifier);
376 if ([identifier isEqualToString:@"com.apple.MobileSMS"])
379 if (didentifier != nil) {
380 testForIcon([English_ objectForKey:didentifier]);
382 NSArray *parts = [didentifier componentsSeparatedByString:@"-"];
383 if ([parts count] != 1)
384 if (NSDictionary *english = [[[NSDictionary alloc] initWithContentsOfFile:[path stringByAppendingString:@"/English.lproj/UIRoleDisplayNames.strings"]] autorelease])
385 testForIcon([english objectForKey:[parts lastObject]]);
388 if (NSString *path = $getTheme$(names))
394 // -[NSBundle wb$bundleWithFile] {{{
395 @interface NSBundle (WinterBoard)
396 + (NSBundle *) wb$bundleWithFile:(NSString *)path;
399 @implementation NSBundle (WinterBoard)
401 + (NSBundle *) wb$bundleWithFile:(NSString *)path {
402 path = [path stringByDeletingLastPathComponent];
403 if (path == nil || [path length] == 0 || [path isEqualToString:@"/"])
406 NSBundle *bundle([Bundles_ objectForKey:path]);
407 if (reinterpret_cast<id>(bundle) == [NSNull null])
409 else if (bundle == nil) {
410 if ([Manager_ fileExistsAtPath:[path stringByAppendingPathComponent:@"Info.plist"]])
411 bundle = [NSBundle bundleWithPath:path];
413 bundle = [NSBundle wb$bundleWithFile:path];
415 NSLog(@"WB:Debug:PathBundle(%@, %@)", path, bundle);
416 [Bundles_ setObject:(bundle == nil ? [NSNull null] : reinterpret_cast<id>(bundle)) forKey:path];
424 // -[NSString wb$themedPath] {{{
425 @interface NSString (WinterBoard)
426 - (NSString *) wb$themedPath;
429 @implementation NSString (WinterBoard)
431 - (NSString *) wb$themedPath {
432 if ([self hasPrefix:@"/Library/Themes/"])
436 NSLog(@"WB:Debug:Bypass(\"%@\")", self);
438 if (NSBundle *bundle = [NSBundle wb$bundleWithFile:self]) {
439 NSString *file([self stringByResolvingSymlinksInPath]);
440 NSString *prefix([[bundle bundlePath] stringByResolvingSymlinksInPath]);
441 if ([file hasPrefix:prefix]) {
442 NSUInteger length([prefix length]);
443 if (length != [file length])
444 if (NSString *path = $pathForFile$inBundle$([file substringFromIndex:(length + 1)], bundle, false))
455 void WBLogRect(const char *tag, struct CGRect rect) {
456 NSLog(@"%s:{%f,%f+%f,%f}", tag, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
459 void WBLogHierarchy(UIView *view, unsigned index = 0, unsigned indent = 0) {
460 CGRect frame([view frame]);
461 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]);
463 for (UIView *child in [view subviews])
464 WBLogHierarchy(child, index++, indent + 1);
467 UIImage *$cacheForImage$(UIImage *image) {
468 CGColorSpaceRef space(CGColorSpaceCreateDeviceRGB());
469 CGRect rect = {CGPointMake(1, 1), [image size]};
470 CGSize size = {rect.size.width + 2, rect.size.height + 2};
472 CGContextRef context(CGBitmapContextCreate(NULL, size.width, size.height, 8, 4 * size.width, space, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst));
473 CGColorSpaceRelease(space);
475 CGContextDrawImage(context, rect, [image CGImage]);
476 CGImageRef ref(CGBitmapContextCreateImage(context));
477 CGContextRelease(context);
479 UIImage *cache([UIImage imageWithCGImage:ref]);
485 /*MSHook(id, SBImageCache$initWithName$forImageWidth$imageHeight$initialCapacity$, SBImageCache *self, SEL sel, NSString *name, unsigned width, unsigned height, unsigned capacity) {
486 //if ([name isEqualToString:@"icons"]) return nil;
487 return _SBImageCache$initWithName$forImageWidth$imageHeight$initialCapacity$(self, sel, name, width, height, capacity);
490 MSHook(void, SBIconModel$cacheImageForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
491 NSString *key([icon displayIdentifier]);
493 if (UIImage *image = [icon icon]) {
494 CGSize size = [image size];
495 if (size.width != 59 || size.height != 60) {
496 UIImage *cache($cacheForImage$(image));
497 [Cache_ setObject:cache forKey:key];
502 _SBIconModel$cacheImageForIcon$(self, sel, icon);
505 MSHook(void, SBIconModel$cacheImagesForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
506 /* XXX: do I /really/ have to do this? figure out how to cache the small icon! */
507 _SBIconModel$cacheImagesForIcon$(self, sel, icon);
509 NSString *key([icon displayIdentifier]);
511 if (UIImage *image = [icon icon]) {
512 CGSize size = [image size];
513 if (size.width != 59 || size.height != 60) {
514 UIImage *cache($cacheForImage$(image));
515 [Cache_ setObject:cache forKey:key];
521 MSHook(UIImage *, SBIconModel$getCachedImagedForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
522 NSString *key([icon displayIdentifier]);
523 if (UIImage *image = [Cache_ objectForKey:key])
526 return _SBIconModel$getCachedImagedForIcon$(self, sel, icon);
529 MSHook(UIImage *, SBIconModel$getCachedImagedForIcon$smallIcon$, SBIconModel *self, SEL sel, SBIcon *icon, BOOL small) {
531 return _SBIconModel$getCachedImagedForIcon$smallIcon$(self, sel, icon, small);
532 NSString *key([icon displayIdentifier]);
533 if (UIImage *image = [Cache_ objectForKey:key])
536 return _SBIconModel$getCachedImagedForIcon$smallIcon$(self, sel, icon, small);
539 MSHook(id, SBSearchView$initWithFrame$, id /* XXX: SBSearchView */ self, SEL sel, struct CGRect frame) {
540 if ((self = _SBSearchView$initWithFrame$(self, sel, frame)) != nil) {
541 [self setBackgroundColor:[UIColor clearColor]];
542 for (UIView *child in [self subviews])
543 [child setBackgroundColor:[UIColor clearColor]];
547 MSHook(id, SBSearchTableViewCell$initWithStyle$reuseIdentifier$, SBSearchTableViewCell *self, SEL sel, int style, NSString *reuse) {
548 if ((self = _SBSearchTableViewCell$initWithStyle$reuseIdentifier$(self, sel, style, reuse)) != nil) {
549 [self setBackgroundColor:[UIColor clearColor]];
553 MSHook(void, SBSearchTableViewCell$drawRect$, SBSearchTableViewCell *self, SEL sel, struct CGRect rect, BOOL selected) {
554 _SBSearchTableViewCell$drawRect$(self, sel, rect, selected);
555 float inset([self edgeInset]);
556 [[UIColor clearColor] set];
557 UIRectFill(CGRectMake(0, 0, inset, rect.size.height));
558 UIRectFill(CGRectMake(rect.size.width - inset, 0, inset, rect.size.height));
561 MSHook(UIImage *, SBApplicationIcon$icon, SBApplicationIcon *self, SEL sel) {
562 if (![Info_ wb$boolForKey:@"ComposeStoreIcons"])
563 if (NSString *path = $pathForIcon$([self application]))
564 return [UIImage imageWithContentsOfFile:path];
565 return _SBApplicationIcon$icon(self, sel);
568 MSHook(UIImage *, SBApplicationIcon$generateIconImage$, SBApplicationIcon *self, SEL sel, int type) {
570 if (![Info_ wb$boolForKey:@"ComposeStoreIcons"]) {
571 if (IsWild_ && false) // XXX: delete this code, it should not be supported
572 if (NSString *path72 = $pathForIcon$([self application], @"-72"))
573 return [UIImage imageWithContentsOfFile:path72];
574 if (NSString *path = $pathForIcon$([self application]))
575 if (UIImage *image = [UIImage imageWithContentsOfFile:path]) {
577 if ([$SBIcon respondsToSelector:@selector(defaultIconImageSize)])
578 width = [$SBIcon defaultIconImageSize].width;
581 return width == 59 ? image : [image _imageScaledToProportion:(width / 59.0) interpolationQuality:5];
584 return _SBApplicationIcon$generateIconImage$(self, sel, type);
587 MSHook(UIImage *, SBWidgetApplicationIcon$icon, SBWidgetApplicationIcon *self, SEL sel) {
589 NSLog(@"WB:Debug:Widget(%@:%@)", [self displayIdentifier], [self displayName]);
590 if (NSString *path = $getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Icons/%@.png", [self displayName]]]))
591 return [UIImage imageWithContentsOfFile:path];
592 return _SBWidgetApplicationIcon$icon(self, sel);
595 MSHook(UIImage *, SBBookmarkIcon$icon, SBBookmarkIcon *self, SEL sel) {
597 NSLog(@"WB:Debug:Bookmark(%@:%@)", [self displayIdentifier], [self displayName]);
598 if (NSString *path = $getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Icons/%@.png", [self displayName]]]))
599 return [UIImage imageWithContentsOfFile:path];
600 return _SBBookmarkIcon$icon(self, sel);
603 MSHook(NSString *, SBApplication$pathForIcon, SBApplication *self, SEL sel) {
604 if (NSString *path = $pathForIcon$(self))
606 return _SBApplication$pathForIcon(self, sel);
609 static UIImage *CachedImageAtPath(NSString *path) {
610 path = [path stringByResolvingSymlinksInPath];
611 UIImage *image = [PathImages_ objectForKey:path];
613 return reinterpret_cast<id>(image) == [NSNull null] ? nil : image;
614 image = [[UIImage alloc] initWithContentsOfFile:path cache:true];
616 image = [image autorelease];
617 [PathImages_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:path];
621 MSHook(UIImage *, _UIApplicationImageWithName, NSString *name) {
622 NSBundle *bundle = [NSBundle mainBundle];
624 NSLog(@"WB:Debug: _UIApplicationImageWithName(\"%@\", %@)", name, bundle);
625 if (NSString *path = $pathForFile$inBundle$(name, bundle, false))
626 return CachedImageAtPath(path);
627 return __UIApplicationImageWithName(name);
630 #define WBDelegate(delegate) \
631 - (NSMethodSignature*) methodSignatureForSelector:(SEL)sel { \
633 NSLog(@"WB:MS:%s:(%s)", class_getName([self class]), sel_getName(sel)); \
634 if (NSMethodSignature *sig = [delegate methodSignatureForSelector:sel]) \
636 NSLog(@"WB:Error: [%s methodSignatureForSelector:(%s)]", class_getName([self class]), sel_getName(sel)); \
640 - (void) forwardInvocation:(NSInvocation*)inv { \
641 SEL sel = [inv selector]; \
642 if ([delegate respondsToSelector:sel]) \
643 [inv invokeWithTarget:delegate]; \
645 NSLog(@"WB:Error: [%s forwardInvocation:(%s)]", class_getName([self class]), sel_getName(sel)); \
648 // %hook -[NSBundle pathForResource:ofType:] {{{
649 MSInstanceMessageHook2(NSString *, NSBundle, pathForResource,ofType, NSString *, resource, NSString *, type) {
650 NSString *file = type == nil ? resource : [NSString stringWithFormat:@"%@.%@", resource, type];
652 NSLog(@"WB:Debug: [NSBundle(%@) pathForResource:\"%@\"]", [self bundleIdentifier], file);
653 if (NSString *path = $pathForFile$inBundle$(file, self, false))
655 return MSOldCall(resource, type);
659 static struct WBStringDrawingState {
660 WBStringDrawingState *next_;
663 } *stringDrawingState_;
665 MSInstanceMessageHook4(CGSize, NSString, drawAtPoint,forWidth,withFont,lineBreakMode, CGPoint, point, float, width, UIFont *, font, int, mode) {
666 if (stringDrawingState_ == NULL || stringDrawingState_->info_ == nil)
667 return MSOldCall(point, width, font, mode);
669 NSString *info([Info_ objectForKey:stringDrawingState_->info_]);
671 return MSOldCall(point, width, font, mode);
673 NSString *base(stringDrawingState_->base_ ?: @"");
674 stringDrawingState_ = stringDrawingState_->next_;
676 [self drawAtPoint:point withStyle:[NSString stringWithFormat:@"%@;%@;%@", [font markupDescription], base, info]];
680 MSInstanceMessageHook2(CGSize, NSString, drawAtPoint,withFont, CGPoint, point, UIFont *, font) {
681 if (stringDrawingState_ == NULL || stringDrawingState_->info_ == nil)
682 return MSOldCall(point, font);
684 NSString *info([Info_ objectForKey:stringDrawingState_->info_]);
686 return MSOldCall(point, font);
688 NSString *base(stringDrawingState_->base_ ?: @"");
689 stringDrawingState_ = stringDrawingState_->next_;
691 [self drawAtPoint:point withStyle:[NSString stringWithFormat:@"%@;%@;%@", [font markupDescription], base, info]];
695 MSInstanceMessageHook1(UIImage *, SBIconBadgeFactory, checkoutBadgeImageForText, NSString *, text) {
696 WBStringDrawingState badgeState = {NULL, @""
700 stringDrawingState_ = &badgeState;
702 UIImage *image(MSOldCall(text));
704 stringDrawingState_ = NULL;
708 MSInstanceMessageHook1(UIImage *, SBCalendarApplicationIcon, generateIconImage, int, type) {
709 WBStringDrawingState dayState = {NULL, @""
711 // XXX: this is only correct on an iPod dock
712 "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px;"
713 , @"CalendarIconDayStyle"};
715 WBStringDrawingState dateState = {&dayState, @""
717 , @"CalendarIconDateStyle"};
719 stringDrawingState_ = &dateState;
721 UIImage *image(MSOldCall(type));
723 stringDrawingState_ = NULL;
727 MSHook(void, SBCalendarIconContentsView$drawRect$, SBCalendarIconContentsView *self, SEL sel, CGRect rect) {
728 NSBundle *bundle([NSBundle mainBundle]);
730 CFLocaleRef locale(CFLocaleCopyCurrent());
731 CFDateFormatterRef formatter(CFDateFormatterCreate(NULL, locale, kCFDateFormatterNoStyle, kCFDateFormatterNoStyle));
734 CFDateRef now(CFDateCreate(NULL, CFAbsoluteTimeGetCurrent()));
736 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NUMBER_FORMAT" value:@"d" table:@"SpringBoard"]);
737 CFStringRef date(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
738 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NAME_FORMAT" value:@"cccc" table:@"SpringBoard"]);
739 CFStringRef day(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
743 CFRelease(formatter);
745 NSString *datestyle([@""
746 "font-family: Helvetica; "
747 "font-weight: bold; "
750 "" stringByAppendingString:(IsWild_
751 ? @"font-size: 54px; "
752 : @"font-size: 39px; "
755 NSString *daystyle([@""
756 "font-family: Helvetica; "
757 "font-weight: bold; "
759 "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px; "
760 "" stringByAppendingString:(IsWild_
761 ? @"font-size: 11px; "
762 : @"font-size: 9px; "
765 if (NSString *style = [Info_ objectForKey:@"CalendarIconDateStyle"])
766 datestyle = [datestyle stringByAppendingString:style];
767 if (NSString *style = [Info_ objectForKey:@"CalendarIconDayStyle"])
768 daystyle = [daystyle stringByAppendingString:style];
770 float width([self bounds].size.width);
772 CGSize datesize = [(NSString *)date sizeWithStyle:datestyle forWidth:(width + leeway)];
773 CGSize daysize = [(NSString *)day sizeWithStyle:daystyle forWidth:(width + leeway)];
775 unsigned base0(IsWild_ ? 89 : 70);
776 if ($GSFontGetUseLegacyFontMetrics())
778 unsigned base1(IsWild_ ? 18 : 16);
785 [(NSString *)date drawAtPoint:CGPointMake(
786 (width + 1 - datesize.width) / 2, (base0 - datesize.height) / 2
787 ) withStyle:datestyle];
789 [(NSString *)day drawAtPoint:CGPointMake(
790 (width + 1 - daysize.width) / 2, (base1 - daysize.height) / 2
791 ) withStyle:daystyle];
797 // %hook -[{NavigationBar,Toolbar} setBarStyle:] {{{
798 void $setBarStyle$_(NSString *name, int &style) {
800 NSLog(@"WB:Debug:%@Style:%d", name, style);
801 NSNumber *number = nil;
803 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style-%d", name, style]];
805 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style", name]];
807 style = [number intValue];
809 NSLog(@"WB:Debug:%@Style=%d", name, style);
813 MSInstanceMessageHook1(void, UIToolbar, setBarStyle, int, style) {
814 $setBarStyle$_(@"Toolbar", style);
815 return MSOldCall(style);
818 MSInstanceMessageHook1(void, UINavigationBar, setBarStyle, int, style) {
819 $setBarStyle$_(@"NavigationBar", style);
820 return MSOldCall(style);
824 MSHook(void, SBButtonBar$didMoveToSuperview, UIView *self, SEL sel) {
825 [[self superview] setBackgroundColor:[UIColor clearColor]];
826 _SBButtonBar$didMoveToSuperview(self, sel);
829 MSHook(void, SBStatusBarContentsView$didMoveToSuperview, UIView *self, SEL sel) {
830 [[self superview] setBackgroundColor:[UIColor clearColor]];
831 _SBStatusBarContentsView$didMoveToSuperview(self, sel);
834 MSHook(UIImage *, UIImage$defaultDesktopImage, UIImage *self, SEL sel) {
836 NSLog(@"WB:Debug:DefaultDesktopImage");
837 if (NSString *path = $getTheme$([NSArray arrayWithObjects:@"LockBackground.png", @"LockBackground.jpg", nil]))
838 return [UIImage imageWithContentsOfFile:path];
839 return _UIImage$defaultDesktopImage(self, sel);
842 static NSArray *Wallpapers_;
843 static bool Papered_;
845 static NSString *WallpaperFile_;
846 static UIImageView *WallpaperImage_;
847 static UIWebDocumentView *WallpaperPage_;
848 static NSURL *WallpaperURL_;
850 #define _release(object) \
851 do if (object != nil) { \
856 static UIImage *$getImage$(NSString *path) {
857 UIImage *image([UIImage imageWithContentsOfFile:path]);
859 unsigned scale($getScale$(path));
860 if (scale != 1 && [image respondsToSelector:@selector(setScale)])
861 [image setScale:scale];
866 // %hook -[SBUIController init] {{{
867 MSInstanceMessageHook0(id, SBUIController, init) {
872 NSString *paper($getTheme$(Wallpapers_));
874 paper = [paper stringByDeletingLastPathComponent];
878 sysctlbyname("hw.machine", NULL, &size, NULL, 0);
879 char *machine = new char[size];
881 if (sysctlbyname("hw.machine", machine, &size, NULL, 0) == -1) {
882 perror("sysctlbyname(\"hw.machine\", ?)");
887 IsWild_ = machine != NULL && strncmp(machine, "iPad", 4) == 0;
890 BOOL (*GSSystemHasCapability)(CFStringRef) = reinterpret_cast<BOOL (*)(CFStringRef)>(dlsym(RTLD_DEFAULT, "GSSystemHasCapability"));
892 if ([Info_ objectForKey:@"UndockedIconLabels"] == nil)
893 [Info_ setObject:[NSNumber numberWithBool:(
894 !(paper != nil || GSSystemHasCapability != NULL && GSSystemHasCapability(CFSTR("homescreen-wallpaper"))) ||
895 [Info_ objectForKey:@"DockedIconLabelStyle"] != nil ||
896 [Info_ objectForKey:@"UndockedIconLabelStyle"] != nil
897 )] forKey:@"UndockedIconLabels"];
900 NSLog(@"WB:Debug:Info = %@", [Info_ description]);
903 UIImageView *&_wallpaperView(MSHookIvar<UIImageView *>(self, "_wallpaperView"));
904 if (&_wallpaperView != NULL) {
905 [_wallpaperView removeFromSuperview];
906 [_wallpaperView release];
907 _wallpaperView = nil;
911 UIView *&_contentLayer(MSHookIvar<UIView *>(self, "_contentLayer"));
912 UIView *&_contentView(MSHookIvar<UIView *>(self, "_contentView"));
915 if (&_contentLayer != NULL)
916 player = &_contentLayer;
917 else if (&_contentView != NULL)
918 player = &_contentView;
921 UIView *layer(player == NULL ? nil : *player);
923 UIWindow *window([[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]);
924 UIView *content([[[UIView alloc] initWithFrame:[window frame]] autorelease]);
925 [window setContentView:content];
927 UIWindow *&_window(MSHookIvar<UIWindow *>(self, "_window"));
928 [window setBackgroundColor:[_window backgroundColor]];
929 [_window setBackgroundColor:[UIColor clearColor]];
931 [window setLevel:-1000];
932 [window setHidden:NO];
934 /*if (player != NULL)
937 [content setBackgroundColor:[layer backgroundColor]];
938 [layer setBackgroundColor:[UIColor clearColor]];
941 if (!SummerBoard_ || !IsWild_)
944 CGRect bounds([content bounds]);
945 bounds.origin.y = -30;
946 indirect = [[[UIView alloc] initWithFrame:bounds] autorelease];
947 [content addSubview:indirect];
948 [indirect zoomToScale:2.4];
951 _release(WallpaperFile_);
952 _release(WallpaperImage_);
953 _release(WallpaperPage_);
954 _release(WallpaperURL_);
957 NSArray *themes([NSArray arrayWithObject:paper]);
959 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"], themes)) {
963 static AVController *controller_(nil);
964 if (controller_ == nil) {
965 AVQueue *queue([AVQueue avQueue]);
966 controller_ = [[AVController avControllerWithQueue:queue error:&error] retain];
969 AVQueue *queue([controller_ queue]);
971 UIView *video([[[UIView alloc] initWithFrame:[indirect bounds]] autorelease]);
972 [controller_ setLayer:[video _layer]];
974 AVItem *item([[[AVItem alloc] initWithPath:path error:&error] autorelease]);
975 [queue appendItem:item error:&error];
977 [controller_ play:&error];
978 #elif UseMPMoviePlayerController
979 NSURL *url([NSURL fileURLWithPath:path]);
980 MPMoviePlayerController *controller = [[$MPMoviePlayerController alloc] initWithContentURL:url];
981 controller.movieControlMode = MPMovieControlModeHidden;
984 MPVideoView *video = [[[$MPVideoView alloc] initWithFrame:[indirect bounds]] autorelease];
985 [video setMovieWithPath:path];
986 [video setRepeatMode:1];
987 [video setRepeatGap:-1];
988 [video playFromBeginning];;
991 [indirect addSubview:video];
994 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"Wallpaper.png", @"Wallpaper.jpg", nil]), themes)) {
995 if (UIImage *image = $getImage$(path)) {
996 WallpaperFile_ = [path retain];
997 WallpaperImage_ = [[UIImageView alloc] initWithImage:image];
998 if (NSNumber *number = [Info_ objectForKey:@"WallpaperAlpha"])
999 [WallpaperImage_ setAlpha:[number floatValue]];
1000 [indirect addSubview:WallpaperImage_];
1004 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.html"], themes)) {
1005 CGRect bounds = [indirect bounds];
1007 UIWebDocumentView *view([[[UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1008 [view setAutoresizes:true];
1010 WallpaperPage_ = [view retain];
1011 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
1013 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1015 [view setBackgroundColor:[UIColor clearColor]];
1016 if ([view respondsToSelector:@selector(setDrawsBackground:)])
1017 [view setDrawsBackground:NO];
1018 [[view webView] setDrawsBackground:NO];
1020 [indirect addSubview:view];
1024 for (size_t i(0), e([Themes_ count]); i != e; ++i) {
1025 NSString *theme = [Themes_ objectAtIndex:(e - i - 1)];
1026 NSString *html = [theme stringByAppendingPathComponent:@"Widget.html"];
1027 if ([Manager_ fileExistsAtPath:html]) {
1028 CGRect bounds = [indirect bounds];
1030 UIWebDocumentView *view([[[UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1031 [view setAutoresizes:true];
1033 NSURL *url = [NSURL fileURLWithPath:html];
1034 [view loadRequest:[NSURLRequest requestWithURL:url]];
1036 [view setBackgroundColor:[UIColor clearColor]];
1037 if ([view respondsToSelector:@selector(setDrawsBackground:)])
1038 [view setDrawsBackground:NO];
1039 [[view webView] setDrawsBackground:NO];
1041 [indirect addSubview:view];
1049 MSHook(void, SBAwayView$updateDesktopImage$, SBAwayView *self, SEL sel, UIImage *image) {
1050 NSString *path = $getTheme$([NSArray arrayWithObject:@"LockBackground.html"]);
1051 UIView *&_backgroundView(MSHookIvar<UIView *>(self, "_backgroundView"));
1053 if (path != nil && _backgroundView != nil)
1056 _SBAwayView$updateDesktopImage$(self, sel, image);
1059 CGRect bounds = [self bounds];
1061 UIWebDocumentView *view([[[UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1062 [view setAutoresizes:true];
1064 if (WallpaperPage_ != nil)
1065 [WallpaperPage_ release];
1066 WallpaperPage_ = [view retain];
1068 if (WallpaperURL_ != nil)
1069 [WallpaperURL_ release];
1070 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
1072 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1074 [[view webView] setDrawsBackground:false];
1075 [view setBackgroundColor:[UIColor clearColor]];
1077 [self insertSubview:view aboveSubview:_backgroundView];
1081 /*extern "C" CGColorRef CGGStateGetSystemColor(void *);
1082 extern "C" CGColorRef CGGStateGetFillColor(void *);
1083 extern "C" CGColorRef CGGStateGetStrokeColor(void *);
1084 extern "C" NSString *UIStyleStringFromColor(CGColorRef);*/
1086 /* WBTimeLabel {{{ */
1087 @interface WBTimeLabel : NSProxy {
1089 _transient SBStatusBarTimeView *view_;
1092 - (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view;
1096 @implementation WBTimeLabel
1103 - (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view {
1104 time_ = [time retain];
1109 - (NSString *) description {
1115 - (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(int)mode {
1116 if (NSString *custom = [Info_ objectForKey:@"TimeStyle"]) {
1117 BOOL &_mode(MSHookIvar<BOOL>(view_, "_mode"));;
1119 [time_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1120 "font-family: Helvetica; "
1121 "font-weight: bold; "
1124 "%@", _mode ? @"white" : @"black", custom]];
1129 return [time_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1134 /* WBBadgeLabel {{{ */
1135 @interface WBBadgeLabel : NSProxy {
1139 - (id) initWithBadge:(NSString *)badge;
1140 - (NSString *) description;
1144 @implementation WBBadgeLabel
1151 - (id) initWithBadge:(NSString *)badge {
1152 badge_ = [badge retain];
1156 - (NSString *) description {
1157 return [badge_ description];
1162 - (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(int)mode {
1163 if (NSString *custom = [Info_ objectForKey:@"BadgeStyle"]) {
1164 [badge_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1165 "font-family: Helvetica; "
1166 "font-weight: bold; "
1174 return [badge_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1181 MSInstanceMessageHook1(void, SBIcon, setIconImageAlpha, float, alpha) {
1182 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1183 alpha = [number floatValue];
1184 return MSOldCall(alpha);
1187 MSInstanceMessageHook1(void, SBIcon, setIconLabelAlpha, float, alpha) {
1188 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1189 alpha = [number floatValue];
1190 return MSOldCall(alpha);
1193 MSInstanceMessageHook0(id, SBIcon, initWithDefaultSize) {
1194 if ((self = MSOldCall()) != nil) {
1195 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"]) {
1196 // XXX: note: this is overridden above, which is silly
1197 float alpha([number floatValue]);
1198 [self setIconImageAlpha:alpha];
1199 [self setIconLabelAlpha:alpha];
1204 MSInstanceMessageHook1(void, SBIcon, setAlpha, float, alpha) {
1205 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1206 alpha = [number floatValue];
1207 return MSOldCall(alpha);
1211 MSHook(id, SBIconBadge$initWithBadge$, SBIconBadge *self, SEL sel, NSString *badge) {
1212 if ((self = _SBIconBadge$initWithBadge$(self, sel, badge)) != nil) {
1213 id &_badge(MSHookIvar<id>(self, "_badge"));
1215 if (id label = [[WBBadgeLabel alloc] initWithBadge:[_badge autorelease]])
1220 void SBStatusBarController$setStatusBarMode(int &mode) {
1222 NSLog(@"WB:Debug:setStatusBarMode:%d", mode);
1223 if (mode < 100) // 104:hidden 105:glowing
1224 if (NSNumber *number = [Info_ objectForKey:@"StatusBarMode"])
1225 mode = [number intValue];
1228 /*MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, double duration, int animation) {
1229 NSLog(@"mode:%d orientation:%d duration:%f animation:%d", mode, orientation, duration, animation);
1230 SBStatusBarController$setStatusBarMode(mode);
1231 return _SBStatusBarController$setStatusBarMode$orientation$duration$animation$(self, sel, mode, orientation, duration, animation);
1234 MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, float duration, int fenceID, int animation) {
1235 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d", mode, orientation, duration, fenceID, animation);
1236 SBStatusBarController$setStatusBarMode(mode);
1237 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$(self, sel, mode, orientation, duration, fenceID, animation);
1240 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) {
1241 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d startTime:%f", mode, orientation, duration, fenceID, animation, startTime);
1242 SBStatusBarController$setStatusBarMode(mode);
1243 //NSLog(@"mode=%u", mode);
1244 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$startTime$(self, sel, mode, orientation, duration, fenceID, animation, startTime);
1247 /*MSHook(id, SBStatusBarContentsView$initWithStatusBar$mode$, SBStatusBarContentsView *self, SEL sel, id bar, int mode) {
1248 if (NSNumber *number = [Info_ objectForKey:@"StatusBarContentsMode"])
1249 mode = [number intValue];
1250 return _SBStatusBarContentsView$initWithStatusBar$mode$(self, sel, bar, mode);
1253 MSHook(NSString *, SBStatusBarOperatorNameView$operatorNameStyle, SBStatusBarOperatorNameView *self, SEL sel) {
1254 NSString *style(_SBStatusBarOperatorNameView$operatorNameStyle(self, sel));
1256 NSLog(@"operatorNameStyle= %@", style);
1257 if (NSString *custom = [Info_ objectForKey:@"OperatorNameStyle"])
1258 style = [NSString stringWithFormat:@"%@; %@", style, custom];
1262 MSHook(void, SBStatusBarOperatorNameView$setOperatorName$fullSize$, SBStatusBarOperatorNameView *self, SEL sel, NSString *name, BOOL full) {
1264 NSLog(@"setOperatorName:\"%@\" fullSize:%u", name, full);
1265 return _SBStatusBarOperatorNameView$setOperatorName$fullSize$(self, sel, name, NO);
1268 // XXX: replace this with [SBStatusBarTimeView tile]
1269 MSHook(void, SBStatusBarTimeView$drawRect$, SBStatusBarTimeView *self, SEL sel, CGRect rect) {
1270 id &_time(MSHookIvar<id>(self, "_time"));
1271 if (_time != nil && [_time class] != [WBTimeLabel class])
1272 object_setInstanceVariable(self, "_time", reinterpret_cast<void *>([[WBTimeLabel alloc] initWithTime:[_time autorelease] view:self]));
1273 return _SBStatusBarTimeView$drawRect$(self, sel, rect);
1276 @interface UIView (WinterBoard)
1277 - (bool) wb$isWBImageView;
1278 - (void) wb$logHierarchy;
1281 @implementation UIView (WinterBoard)
1283 - (bool) wb$isWBImageView {
1287 - (void) wb$logHierarchy {
1288 WBLogHierarchy(self);
1293 @interface WBImageView : UIImageView {
1296 - (bool) wb$isWBImageView;
1297 - (void) wb$updateFrame;
1300 @implementation WBImageView
1302 - (bool) wb$isWBImageView {
1306 - (void) wb$updateFrame {
1307 CGRect frame([self frame]);
1310 for (UIView *view(self); ; ) {
1311 view = [view superview];
1314 frame.origin.y -= [view frame].origin.y;
1317 [self setFrame:frame];
1322 MSHook(void, SBIconList$setFrame$, SBIconList *self, SEL sel, CGRect frame) {
1323 NSArray *subviews([self subviews]);
1324 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1325 if (view != nil && [view wb$isWBImageView])
1326 [view wb$updateFrame];
1327 _SBIconList$setFrame$(self, sel, frame);
1330 MSHook(void, SBIconController$noteNumberOfIconListsChanged, SBIconController *self, SEL sel) {
1331 SBIconModel *&_iconModel(MSHookIvar<SBIconModel *>(self, "_iconModel"));
1332 NSArray *lists([_iconModel iconLists]);
1334 for (unsigned i(0), e([lists count]); i != e; ++i)
1335 if (NSString *path = $getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Page%u.png", i]])) {
1336 SBIconList *list([lists objectAtIndex:i]);
1337 NSArray *subviews([list subviews]);
1339 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1340 if (view == nil || ![view wb$isWBImageView]) {
1341 view = [[[WBImageView alloc] init] autorelease];
1342 [list insertSubview:view atIndex:0];
1345 UIImage *image([UIImage imageWithContentsOfFile:path]);
1347 CGRect frame([view frame]);
1348 frame.size = [image size];
1349 [view setFrame:frame];
1351 [view setImage:image];
1352 [view wb$updateFrame];
1355 return _SBIconController$noteNumberOfIconListsChanged(self, sel);
1358 MSHook(id, SBIconLabel$initWithSize$label$, SBIconLabel *self, SEL sel, CGSize size, NSString *label) {
1359 self = _SBIconLabel$initWithSize$label$(self, sel, size, label);
1361 [self setClipsToBounds:NO];
1365 MSHook(void, SBIconLabel$setInDock$, SBIconLabel *self, SEL sel, BOOL docked) {
1366 id &_label(MSHookIvar<id>(self, "_label"));
1367 if (![Info_ wb$boolForKey:@"UndockedIconLabels"])
1369 if (_label != nil && [_label respondsToSelector:@selector(setInDock:)])
1370 [_label setInDock:docked];
1371 return _SBIconLabel$setInDock$(self, sel, docked);
1374 MSHook(BOOL, SBDockIconListView$shouldShowNewDock, id self, SEL sel) {
1375 return SummerBoard_ && Docked_ ? NO : _SBDockIconListView$shouldShowNewDock(self, sel);
1378 MSHook(void, SBDockIconListView$setFrame$, id self, SEL sel, CGRect frame) {
1379 _SBDockIconListView$setFrame$(self, sel, frame);
1382 // %hook -[NSBundle localizedStringForKey:value:table:] {{{
1383 MSInstanceMessageHook3(NSString *, NSBundle, localizedStringForKey,value,table, NSString *, key, NSString *, value, NSString *, table) {
1384 NSString *identifier = [self bundleIdentifier];
1385 NSLocale *locale = [NSLocale currentLocale];
1386 NSString *language = [locale objectForKey:NSLocaleLanguageCode];
1388 NSLog(@"WB:Debug:[NSBundle(%@) localizedStringForKey:\"%@\" value:\"%@\" table:\"%@\"] (%@)", identifier, key, value, table, language);
1389 NSString *file = table == nil ? @"Localizable" : table;
1390 NSString *name = [NSString stringWithFormat:@"%@:%@", identifier, file];
1391 NSDictionary *strings;
1392 if ((strings = [Strings_ objectForKey:name]) != nil) {
1393 if (static_cast<id>(strings) != [NSNull null]) strings:
1394 if (NSString *value = [strings objectForKey:key])
1396 } else if (NSString *path = $pathForFile$inBundle$([NSString stringWithFormat:@"%@.lproj/%@.strings",
1399 if ((strings = [[NSDictionary alloc] initWithContentsOfFile:path]) != nil) {
1400 [Strings_ setObject:[strings autorelease] forKey:name];
1404 [Strings_ setObject:[NSNull null] forKey:name];
1405 return MSOldCall(key, value, table);
1408 // %hook -[WebCoreFrameBridge renderedSizeOfNode:constrainedToWidth:] {{{
1409 MSClassHook(WebCoreFrameBridge)
1411 MSInstanceMessageHook2(CGSize, WebCoreFrameBridge, renderedSizeOfNode,constrainedToWidth, id, node, float, width) {
1414 void **core(reinterpret_cast<void **>([node _node]));
1415 if (core == NULL || core[6] == NULL)
1417 return MSOldCall(node, width);
1421 MSInstanceMessageHook1(void, SBIconLabel, drawRect, CGRect, rect) {
1422 CGRect bounds = [self bounds];
1424 static Ivar drawMoreLegibly = object_getInstanceVariable(self, "_drawMoreLegibly", NULL);
1427 Ivar ivar = object_getInstanceVariable(self, "_inDock", reinterpret_cast<void **>(&docked));
1428 docked = (docked & (ivar_getOffset(ivar) == ivar_getOffset(drawMoreLegibly) ? 0x2 : 0x1)) != 0;
1430 NSString *label(MSHookIvar<NSString *>(self, "_label"));
1432 NSString *style = [NSString stringWithFormat:@""
1433 "font-family: Helvetica; "
1434 "font-weight: bold; "
1436 "", (docked || !SummerBoard_ ? @"white" : @"#b3b3b3"), (IsWild_
1437 ? @"font-size: 12px; "
1438 : @"font-size: 11px; "
1442 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px 1px 0px; "];
1444 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px -1px 0px; "];
1446 bool ellipsis(false);
1447 float max = [self frame].size.width - 11, width;
1449 width = [(ellipsis ? [label stringByAppendingString:@"..."] : label) sizeWithStyle:style forWidth:320].width;
1452 size_t length([label length]);
1453 float spacing((width - max) / (length - 1));
1455 if (spacing > 1.25) {
1457 label = [label substringToIndex:(length - 1)];
1461 style = [style stringByAppendingString:[NSString stringWithFormat:@"letter-spacing: -%f; ", spacing]];
1465 label = [label stringByAppendingString:@"..."];
1467 if (NSString *custom = [Info_ objectForKey:(docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle")])
1468 style = [style stringByAppendingString:custom];
1470 CGSize size = [label sizeWithStyle:style forWidth:bounds.size.width];
1471 [label drawAtPoint:CGPointMake((bounds.size.width - size.width) / 2, 0) withStyle:style];
1475 MSInstanceMessageHook1(void, CKMessageCell, addBalloonView, CKBalloonView *, balloon) {
1477 [balloon setBackgroundColor:[UIColor clearColor]];
1480 MSInstanceMessageHook1(void, CKTranscriptCell, setBackgroundColor, UIColor *, color) {
1481 MSOldCall([UIColor clearColor]);
1484 MSInstanceMessageHook2(id, CKTranscriptCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1485 if ((self = MSOldCall(style, reuse)) != nil) {
1486 [self setBackgroundColor:[UIColor clearColor]];
1487 [[self contentView] setBackgroundColor:[UIColor clearColor]];
1491 MSInstanceMessageHook2(id, CKMessageCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1492 if ((self = MSOldCall(style, reuse)) != nil) {
1493 [self setBackgroundColor:[UIColor clearColor]];
1494 [[self contentView] setBackgroundColor:[UIColor clearColor]];
1498 MSInstanceMessageHook2(id, CKTimestampView, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1499 if ((self = MSOldCall(style, reuse)) != nil) {
1500 UILabel *&_label(MSHookIvar<UILabel *>(self, "_label"));
1501 [_label setBackgroundColor:[UIColor clearColor]];
1505 MSInstanceMessageHook1(void, CKTranscriptTableView, setSeparatorStyle, int, style) {
1506 MSOldCall(UITableViewCellSeparatorStyleNone);
1509 MSInstanceMessageHook2(id, CKTranscriptTableView, initWithFrame,style, CGRect, frame, int, style) {
1510 if ((self = MSOldCall(frame, style)) != nil) {
1511 [self setSeparatorStyle:UITableViewCellSeparatorStyleNone];
1515 MSInstanceMessageHook0(void, CKTranscriptController, loadView) {
1518 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"SMSBackground.png", @"SMSBackground.jpg", nil])))
1519 if (UIImage *image = $getImage$(path)) {
1520 UIView *&_transcriptTable(MSHookIvar<UIView *>(self, "_transcriptTable"));
1521 UIView *&_transcriptLayer(MSHookIvar<UIView *>(self, "_transcriptLayer"));
1523 if (&_transcriptTable != NULL)
1524 table = _transcriptTable;
1525 else if (&_transcriptLayer != NULL)
1526 table = _transcriptLayer;
1530 UIView *placard(table != nil ? [table superview] : MSHookIvar<UIView *>(self, "_backPlacard"));
1531 UIImageView *background([[[UIImageView alloc] initWithImage:image] autorelease]);
1534 [placard insertSubview:background atIndex:0];
1536 [table setBackgroundColor:[UIColor clearColor]];
1537 [placard insertSubview:background belowSubview:table];
1543 // %hook _UIImageWithName() {{{
1544 MSHook(UIImage *, _UIImageWithName, NSString *name) {
1546 NSLog(@"WB:Debug: _UIImageWithName(\"%@\")", name);
1553 if (_UIPackedImageTableGetIdentifierForName != NULL)
1554 packed = _UIPackedImageTableGetIdentifierForName(name, &identifier);
1555 else if (_UISharedImageNameGetIdentifier != NULL) {
1556 identifier = _UISharedImageNameGetIdentifier(name);
1557 packed = identifier != -1;
1564 NSLog(@"WB:Debug: _UISharedImageNameGetIdentifier(\"%@\") = %d", name, identifier);
1567 return __UIImageWithName(name);
1569 NSNumber *key([NSNumber numberWithInt:identifier]);
1570 UIImage *image([UIImages_ objectForKey:key]);
1572 return reinterpret_cast<id>(image) == [NSNull null] ? __UIImageWithName(name) : image;
1573 if (NSString *path = $pathForFile$inBundle$(name, _UIKitBundle(), true))
1574 image = $getImage$(path);
1575 [UIImages_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:key];
1579 image = __UIImageWithName(name);
1582 NSString *path([@"/tmp/UIImages/" stringByAppendingString:name]);
1583 if (![Manager_ fileExistsAtPath:path])
1584 [UIImagePNGRepresentation(image) writeToFile:path atomically:YES];
1591 // %hook _UIImageWithNameInDomain() {{{
1592 MSHook(UIImage *, _UIImageWithNameInDomain, NSString *name, NSString *domain) {
1593 NSString *key([NSString stringWithFormat:@"D:%zu%@%@", [domain length], domain, name]);
1594 UIImage *image([PathImages_ objectForKey:key]);
1596 return reinterpret_cast<id>(image) == [NSNull null] ? __UIImageWithNameInDomain(name, domain) : image;
1598 NSLog(@"WB:Debug: UIImageWithNameInDomain(\"%@\", \"%@\")", name, domain);
1599 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObject:[NSString stringWithFormat:@"Domains/%@/%@", domain, name]])))
1600 image = $getImage$(path);
1601 [PathImages_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:key];
1602 return image == nil ? __UIImageWithNameInDomain(name, domain) : image;
1606 // %hook GSFontCreateWithName() {{{
1607 MSHook(GSFontRef, GSFontCreateWithName, const char *name, GSFontSymbolicTraits traits, float size) {
1609 NSLog(@"WB:Debug: GSFontCreateWithName(\"%s\", %f)", name, size);
1610 if (NSString *font = [Info_ objectForKey:[NSString stringWithFormat:@"FontName-%s", name]])
1611 name = [font UTF8String];
1612 //if (NSString *scale = [Info_ objectForKey:[NSString stringWithFormat:@"FontScale-%s", name]])
1613 // size *= [scale floatValue];
1614 return _GSFontCreateWithName(name, traits, size);
1618 #define AudioToolbox "/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox"
1619 #define UIKit "/System/Library/Frameworks/UIKit.framework/UIKit"
1621 bool (*_Z24GetFileNameForThisActionmPcRb)(unsigned long a0, char *a1, bool &a2);
1623 MSHook(bool, _Z24GetFileNameForThisActionmPcRb, unsigned long a0, char *a1, bool &a2) {
1625 NSLog(@"WB:Debug:GetFileNameForThisAction(%u, %p, %u)", a0, a1, a2);
1626 bool value = __Z24GetFileNameForThisActionmPcRb(a0, a1, a2);
1628 NSLog(@"WB:Debug:GetFileNameForThisAction(%u, %s, %u) = %u", a0, value ? a1 : NULL, a2, value);
1631 NSString *path = [NSString stringWithUTF8String:a1];
1632 if ([path hasPrefix:@"/System/Library/Audio/UISounds/"]) {
1633 NSString *file = [path substringFromIndex:31];
1634 for (NSString *theme in Themes_) {
1635 NSString *path([NSString stringWithFormat:@"%@/UISounds/%@", theme, file]);
1636 if ([Manager_ fileExistsAtPath:path]) {
1637 strcpy(a1, [path UTF8String]);
1646 static void ChangeWallpaper(
1647 CFNotificationCenterRef center,
1651 CFDictionaryRef info
1654 NSLog(@"WB:Debug:ChangeWallpaper!");
1657 if (WallpaperFile_ != nil) {
1658 image = [[UIImage alloc] initWithContentsOfFile:WallpaperFile_];
1660 image = [image autorelease];
1663 if (WallpaperImage_ != nil)
1664 [WallpaperImage_ setImage:image];
1665 if (WallpaperPage_ != nil)
1666 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1670 #define WBRename(name, sel, imp) \
1671 _ ## name ## $ ## imp = MSHookMessage($ ## name, @selector(sel), &$ ## name ## $ ## imp)
1673 template <typename Type_>
1674 static void msset(Type_ &function, MSImageRef image, const char *name) {
1675 function = reinterpret_cast<Type_>(MSFindSymbol(image, name));
1678 template <typename Type_>
1679 static void nlset(Type_ &function, struct nlist *nl, size_t index) {
1680 struct nlist &name(nl[index]);
1681 uintptr_t value(name.n_value);
1682 if ((name.n_desc & N_ARM_THUMB_DEF) != 0)
1683 value |= 0x00000001;
1684 function = reinterpret_cast<Type_>(value);
1687 template <typename Type_>
1688 static void dlset(Type_ &function, const char *name) {
1689 function = reinterpret_cast<Type_>(dlsym(RTLD_DEFAULT, name));
1692 // %hook CGImageReadCreateWithFile() {{{
1693 MSHook(void *, CGImageReadCreateWithFile, NSString *path, int flag) {
1695 NSLog(@"WB:Debug: CGImageReadCreateWithFile(%@, %d)", path, flag);
1696 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
1697 void *value(_CGImageReadCreateWithFile([path wb$themedPath], flag));
1703 static void NSString$drawAtPoint$withStyle$(NSString *self, SEL _cmd, CGPoint point, NSString *style) {
1704 WKSetCurrentGraphicsContext(UIGraphicsGetCurrentContext());
1705 if (style == nil || [style length] == 0)
1706 style = @"font-family: Helvetica; font-size: 12px";
1707 return [[WBMarkup sharedMarkup] drawString:self atPoint:point withStyle:style];
1710 static CGSize NSString$sizeWithStyle$forWidth$(NSString *self, SEL _cmd, NSString *style, float width) {
1711 if (style == nil || [style length] == 0)
1712 style = @"font-family: Helvetica; font-size: 12px";
1713 return [[WBMarkup sharedMarkup] sizeOfString:self withStyle:style forWidth:width];
1716 static void SBInitialize() {
1717 class_addMethod($NSString, @selector(drawAtPoint:withStyle:), (IMP) &NSString$drawAtPoint$withStyle$, "v20@0:4{CGPoint=ff}8@16");
1718 class_addMethod($NSString, @selector(sizeWithStyle:forWidth:), (IMP) &NSString$sizeWithStyle$forWidth$, "{CGSize=ff}16@0:4@8f12");
1720 _UIImage$defaultDesktopImage = MSHookMessage(object_getClass($UIImage), @selector(defaultDesktopImage), &$UIImage$defaultDesktopImage);
1723 WBRename(SBApplication, pathForIcon, pathForIcon);
1724 WBRename(SBApplicationIcon, icon, icon);
1725 WBRename(SBApplicationIcon, generateIconImage:, generateIconImage$);
1728 WBRename(SBBookmarkIcon, icon, icon);
1729 WBRename(SBButtonBar, didMoveToSuperview, didMoveToSuperview);
1730 WBRename(SBCalendarIconContentsView, drawRect:, drawRect$);
1731 WBRename(SBIconBadge, initWithBadge:, initWithBadge$);
1732 WBRename(SBIconController, noteNumberOfIconListsChanged, noteNumberOfIconListsChanged);
1734 WBRename(SBWidgetApplicationIcon, icon, icon);
1736 WBRename(SBDockIconListView, setFrame:, setFrame$);
1737 MSHookMessage(object_getClass($SBDockIconListView), @selector(shouldShowNewDock), &$SBDockIconListView$shouldShowNewDock, &_SBDockIconListView$shouldShowNewDock);
1739 WBRename(SBIconLabel, initWithSize:label:, initWithSize$label$);
1740 WBRename(SBIconLabel, setInDock:, setInDock$);
1742 WBRename(SBIconList, setFrame:, setFrame$);
1744 WBRename(SBIconModel, cacheImageForIcon:, cacheImageForIcon$);
1745 WBRename(SBIconModel, cacheImagesForIcon:, cacheImagesForIcon$);
1746 WBRename(SBIconModel, getCachedImagedForIcon:, getCachedImagedForIcon$);
1747 WBRename(SBIconModel, getCachedImagedForIcon:smallIcon:, getCachedImagedForIcon$smallIcon$);
1749 WBRename(SBSearchView, initWithFrame:, initWithFrame$);
1750 WBRename(SBSearchTableViewCell, drawRect:, drawRect$);
1751 WBRename(SBSearchTableViewCell, initWithStyle:reuseIdentifier:, initWithStyle$reuseIdentifier$);
1753 //WBRename(SBImageCache, initWithName:forImageWidth:imageHeight:initialCapacity:, initWithName$forImageWidth$imageHeight$initialCapacity$);
1755 WBRename(SBAwayView, updateDesktopImage:, updateDesktopImage$);
1756 WBRename(SBStatusBarContentsView, didMoveToSuperview, didMoveToSuperview);
1757 //WBRename(SBStatusBarContentsView, initWithStatusBar:mode:, initWithStatusBar$mode$);
1758 //WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:animation:, setStatusBarMode$orientation$duration$animation$);
1759 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:, setStatusBarMode$orientation$duration$fenceID$animation$);
1760 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:startTime:, setStatusBarMode$orientation$duration$fenceID$animation$startTime$);
1761 WBRename(SBStatusBarOperatorNameView, operatorNameStyle, operatorNameStyle);
1762 WBRename(SBStatusBarOperatorNameView, setOperatorName:fullSize:, setOperatorName$fullSize$);
1763 WBRename(SBStatusBarTimeView, drawRect:, drawRect$);
1766 English_ = [[NSDictionary alloc] initWithContentsOfFile:@"/System/Library/CoreServices/SpringBoard.app/English.lproj/LocalizedApplicationNames.strings"];
1770 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
1772 NSString *identifier([[NSBundle mainBundle] bundleIdentifier]);
1773 SpringBoard_ = [identifier isEqualToString:@"com.apple.springboard"];
1775 Manager_ = [[NSFileManager defaultManager] retain];
1776 Themes_ = [[NSMutableArray alloc] initWithCapacity:8];
1778 dlset(_GSFontGetUseLegacyFontMetrics, "GSFontGetUseLegacyFontMetrics");
1780 // Load Settings.plist {{{
1781 if (NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"/User/Library/Preferences/com.saurik.WinterBoard.plist"]]) {
1782 if (NSNumber *value = [settings objectForKey:@"SummerBoard"])
1783 SummerBoard_ = [value boolValue];
1784 if (NSNumber *value = [settings objectForKey:@"Debug"])
1785 Debug_ = [value boolValue];
1787 NSArray *themes([settings objectForKey:@"Themes"]);
1789 if (NSString *theme = [settings objectForKey:@"Theme"])
1790 themes = [NSArray arrayWithObject:[NSDictionary dictionaryWithObjectsAndKeys:
1792 [NSNumber numberWithBool:true], @"Active",
1796 for (NSDictionary *theme in themes) {
1797 NSNumber *active([theme objectForKey:@"Active"]);
1798 if (![active boolValue])
1801 NSString *name([theme objectForKey:@"Name"]);
1805 NSString *theme(nil);
1807 #define testForTheme(format...) \
1808 if (theme == nil) { \
1809 NSString *path = [NSString stringWithFormat:format]; \
1810 if ([Manager_ fileExistsAtPath:path]) { \
1811 [Themes_ addObject:path]; \
1816 testForTheme(@"/Library/Themes/%@.theme", name)
1817 testForTheme(@"/Library/Themes/%@", name)
1818 testForTheme(@"%@/Library/SummerBoard/Themes/%@", NSHomeDirectory(), name)
1823 // Merge Info.plist {{{
1824 Info_ = [[NSMutableDictionary dictionaryWithCapacity:16] retain];
1826 for (NSString *theme in Themes_)
1827 if (NSDictionary *info = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"%@/Info.plist", theme]])
1828 for (NSString *key in [info allKeys])
1829 if ([Info_ objectForKey:key] == nil)
1830 [Info_ setObject:[info objectForKey:key] forKey:key];
1834 if (MSImageRef image = MSGetImageByName(AudioToolbox)) {
1835 msset(_Z24GetFileNameForThisActionmPcRb, image, "__Z24GetFileNameForThisActionmPcRb");
1836 MSHookFunction(_Z24GetFileNameForThisActionmPcRb, &$_Z24GetFileNameForThisActionmPcRb, &__Z24GetFileNameForThisActionmPcRb);
1839 // GraphicsServices {{{
1841 MSHookFunction(&GSFontCreateWithName, &$GSFontCreateWithName, &_GSFontCreateWithName);
1845 if (MSImageRef image = MSGetImageByName("/System/Library/Frameworks/ImageIO.framework/ImageIO")) {
1846 void *(*CGImageReadCreateWithFile)(NSString *, int);
1847 msset(CGImageReadCreateWithFile, image, "_CGImageReadCreateWithFile");
1848 MSHookFunction(CGImageReadCreateWithFile, MSHake(CGImageReadCreateWithFile));
1853 Wallpapers_ = [[NSArray arrayWithObjects:@"Wallpaper.mp4", @"Wallpaper@2x.png", @"Wallpaper@2x.jpg", @"Wallpaper.png", @"Wallpaper.jpg", @"Wallpaper.html", nil] retain];
1854 Docked_ = $getTheme$([NSArray arrayWithObjects:@"Dock.png", nil]);
1856 CFNotificationCenterAddObserver(
1857 CFNotificationCenterGetDarwinNotifyCenter(),
1858 NULL, &ChangeWallpaper, (CFStringRef) @"com.saurik.winterboard.lockbackground", NULL, 0
1861 if ($getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"]) != nil) {
1862 NSBundle *MediaPlayer([NSBundle bundleWithPath:@"/System/Library/Frameworks/MediaPlayer.framework"]);
1863 if (MediaPlayer != nil)
1866 $MPMoviePlayerController = objc_getClass("MPMoviePlayerController");
1867 $MPVideoView = objc_getClass("MPVideoView");
1874 if ([NSBundle bundleWithIdentifier:@"com.apple.UIKit"] != nil) {
1876 memset(nl, 0, sizeof(nl));
1877 nl[0].n_un.n_name = (char *) "__UIApplicationImageWithName";
1878 nl[1].n_un.n_name = (char *) "__UIImageWithNameInDomain";
1879 nl[2].n_un.n_name = (char *) "__UIKitBundle";
1880 nl[3].n_un.n_name = (char *) "__UIPackedImageTableGetIdentifierForName";
1881 nl[4].n_un.n_name = (char *) "__UISharedImageNameGetIdentifier";
1884 nlset(_UIApplicationImageWithName, nl, 0);
1885 nlset(_UIImageWithNameInDomain, nl, 1);
1886 nlset(_UIKitBundle, nl, 2);
1887 nlset(_UIPackedImageTableGetIdentifierForName, nl, 3);
1888 nlset(_UISharedImageNameGetIdentifier, nl, 4);
1890 MSHookFunction(_UIApplicationImageWithName, &$_UIApplicationImageWithName, &__UIApplicationImageWithName);
1891 MSHookFunction(_UIImageWithName, &$_UIImageWithName, &__UIImageWithName);
1892 MSHookFunction(_UIImageWithNameInDomain, &$_UIImageWithNameInDomain, &__UIImageWithNameInDomain);
1896 if (Debug_ && [Manager_ fileExistsAtPath:@"/tmp/UIImages"])