X-Git-Url: https://git.saurik.com/winterboard.git/blobdiff_plain/b461e3ec585f8899d86e38674566930a7445414e..116c57045f5c204b82defc34b6b52b32c57dbcf1:/Library.mm diff --git a/Library.mm b/Library.mm index fe01279..673f847 100644 --- a/Library.mm +++ b/Library.mm @@ -118,12 +118,15 @@ MSClassHook(NSBundle) MSClassHook(NSString) MSClassHook(UIImage) +MSMetaClassHook(UIImage) MSClassHook(UINavigationBar) MSClassHook(UIToolbar) MSClassHook(CKMessageCell) MSClassHook(CKTimestampView) +MSClassHook(CKTranscriptCell) MSClassHook(CKTranscriptController) +MSClassHook(CKTranscriptHeaderView) MSClassHook(CKTranscriptTableView) MSClassHook(SBApplication) @@ -131,10 +134,12 @@ MSClassHook(SBApplicationIcon) MSClassHook(SBAwayView) MSClassHook(SBBookmarkIcon) MSClassHook(SBButtonBar) +MSClassHook(SBCalendarApplicationIcon) MSClassHook(SBCalendarIconContentsView) MSClassHook(SBDockIconListView) MSClassHook(SBIcon) MSClassHook(SBIconBadge) +MSClassHook(SBIconBadgeFactory) MSClassHook(SBIconController) MSClassHook(SBIconLabel) MSClassHook(SBIconList) @@ -142,13 +147,17 @@ MSClassHook(SBIconModel) //MSClassHook(SBImageCache) MSClassHook(SBSearchView) MSClassHook(SBSearchTableViewCell) +MSClassHook(SBSlidingAlertDisplay) MSClassHook(SBStatusBarContentsView) MSClassHook(SBStatusBarController) MSClassHook(SBStatusBarOperatorNameView) MSClassHook(SBStatusBarTimeView) MSClassHook(SBUIController) +MSClassHook(SBWallpaperView) MSClassHook(SBWidgetApplicationIcon) +extern "C" void WKSetCurrentGraphicsContext(CGContextRef); + __attribute__((__constructor__)) static void MSFixClass() { if ($SBIcon == nil) @@ -188,6 +197,7 @@ static BOOL (*_GSFontGetUseLegacyFontMetrics)(); (_GSFontGetUseLegacyFontMetrics == NULL ? YES : _GSFontGetUseLegacyFontMetrics()) static bool Debug_ = false; +static bool UIDebug_ = false; static bool Engineer_ = false; static bool SummerBoard_ = true; static bool SpringBoard_; @@ -231,9 +241,6 @@ static unsigned $getScale$(NSString *path) { } static NSArray *$useScale$(NSArray *files, bool use = true) { - if (!use) - return files; - if (Scale_ == 0) { UIScreen *screen([UIScreen mainScreen]); if ([screen respondsToSelector:@selector(scale)]) @@ -245,11 +252,40 @@ static NSArray *$useScale$(NSArray *files, bool use = true) { if (Scale_ == 1) return files; - NSMutableArray *scaled([NSMutableArray arrayWithCapacity:([files count] * 2)]); + NSString *idiom(IsWild_ ? @"ipad" : @"iphone"); + + NSMutableArray *scaled([NSMutableArray arrayWithCapacity:([files count] * 4)]); for (NSString *file in files) { - [scaled addObject:[NSString stringWithFormat:@"%@@2x.%@", [file stringByDeletingPathExtension], [file pathExtension]]]; - [scaled addObject:file]; + NSString *base([file stringByDeletingPathExtension]); + NSString *extension([file pathExtension]); + + if (use) { + if (Scale_ == 2) { + [scaled addObject:[NSString stringWithFormat:@"%@@2x~%@.%@", base, idiom, extension]]; + if (!IsWild_) + [scaled addObject:[NSString stringWithFormat:@"%@@2x.%@", base, extension]]; + } + + [scaled addObject:[NSString stringWithFormat:@"%@~%@.%@", base, idiom, extension]]; + + // if (!IsWild_) <- support old themes + [scaled addObject:file]; + } else if ([base hasSuffix: @"@2x"]) { + [scaled addObject:[NSString stringWithFormat:@"%@~iphone.%@", base, extension]]; + [scaled addObject:file]; + + NSString *rest([base substringWithRange:NSMakeRange(0, [base length] - 3)]); + [scaled addObject:[NSString stringWithFormat:@"%@~iphone.%@", rest, extension]]; + [scaled addObject:[rest stringByAppendingPathExtension:extension]]; + } else { + // XXX: this code isn't really complete + + [scaled addObject:file]; + + if ([base hasSuffix:@"~iphone"]) + [scaled addObject:[[base substringWithRange:NSMakeRange(0, [base length] - 7)] stringByAppendingPathExtension:extension]]; + } } return scaled; @@ -624,6 +660,103 @@ MSInstanceMessageHook2(NSString *, NSBundle, pathForResource,ofType, NSString *, } // }}} +static struct WBStringDrawingState { + WBStringDrawingState *next_; + unsigned count_; + NSString *base_; + NSString *info_; +} *stringDrawingState_; + +MSInstanceMessageHook4(CGSize, NSString, drawAtPoint,forWidth,withFont,lineBreakMode, CGPoint, point, float, width, UIFont *, font, int, mode) { + WBStringDrawingState *state(stringDrawingState_); + if (state == NULL) + return MSOldCall(point, width, font, mode); + + if (--state->count_ == 0) + stringDrawingState_ = state->next_; + if (state->info_ == nil) + return MSOldCall(point, width, font, mode); + + NSString *info([Info_ objectForKey:state->info_]); + if (info == nil) + return MSOldCall(point, width, font, mode); + + NSString *base(state->base_ ?: @""); + [self drawAtPoint:point withStyle:[NSString stringWithFormat:@"%@;%@;%@", [font markupDescription], base, info]]; + return CGSizeZero; +} + +MSInstanceMessageHook2(CGSize, NSString, drawAtPoint,withFont, CGPoint, point, UIFont *, font) { + WBStringDrawingState *state(stringDrawingState_); + if (state == NULL) + return MSOldCall(point, font); + + if (--state->count_ == 0) + stringDrawingState_ = state->next_; + if (state->info_ == nil) + return MSOldCall(point, font); + + NSString *info([Info_ objectForKey:state->info_]); + if (info == nil) + return MSOldCall(point, font); + + NSString *base(state->base_ ?: @""); + [self drawAtPoint:point withStyle:[NSString stringWithFormat:@"%@;%@;%@", [font markupDescription], base, info]]; + return CGSizeZero; +} + +MSInstanceMessageHook1(CGSize, NSString, sizeWithFont, UIFont *, font) { + WBStringDrawingState *state(stringDrawingState_); + if (state == NULL) + return MSOldCall(font); + + if (--state->count_ == 0) + stringDrawingState_ = state->next_; + if (state->info_ == nil) + return MSOldCall(font); + + NSString *info([Info_ objectForKey:state->info_]); + if (info == nil) + return MSOldCall(font); + + NSString *base(state->base_ ?: @""); + return [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@", [font markupDescription], base, info] forWidth:65535]; +} + +MSInstanceMessageHook1(UIImage *, SBIconBadgeFactory, checkoutBadgeImageForText, NSString *, text) { + WBStringDrawingState badgeState = {NULL, 1, @"" + "color: white;" + , @"BadgeStyle"}; + + stringDrawingState_ = &badgeState; + + UIImage *image(MSOldCall(text)); + + stringDrawingState_ = NULL; + return image; +} + +MSInstanceMessageHook1(UIImage *, SBCalendarApplicationIcon, generateIconImage, int, type) { + WBStringDrawingState dayState = {NULL, 2, @"" + "color: white;" + // XXX: this is only correct on an iPod dock + "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px;" + , @"CalendarIconDayStyle"}; + + WBStringDrawingState sizeState = {&dayState, 7, nil, nil}; + + WBStringDrawingState dateState = {&sizeState, 2, @"" + "color: #333333;" + , @"CalendarIconDateStyle"}; + + stringDrawingState_ = &dateState; + + UIImage *image(MSOldCall(type)); + + stringDrawingState_ = NULL; + return image; +} + MSHook(void, SBCalendarIconContentsView$drawRect$, SBCalendarIconContentsView *self, SEL sel, CGRect rect) { NSBundle *bundle([NSBundle mainBundle]); @@ -731,14 +864,6 @@ MSHook(void, SBStatusBarContentsView$didMoveToSuperview, UIView *self, SEL sel) _SBStatusBarContentsView$didMoveToSuperview(self, sel); } -MSHook(UIImage *, UIImage$defaultDesktopImage, UIImage *self, SEL sel) { - if (Debug_) - NSLog(@"WB:Debug:DefaultDesktopImage"); - if (NSString *path = $getTheme$([NSArray arrayWithObjects:@"LockBackground.png", @"LockBackground.jpg", nil])) - return [UIImage imageWithContentsOfFile:path]; - return _UIImage$defaultDesktopImage(self, sel); -} - static NSArray *Wallpapers_; static bool Papered_; static bool Docked_; @@ -763,6 +888,34 @@ static UIImage *$getImage$(NSString *path) { return image; } +static UIImage *$getDefaultDesktopImage$() { + if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"LockBackground.png", @"LockBackground.jpg", nil]))) + return $getImage$(path); + return nil; +} + +MSClassMessageHook0(UIImage *, UIImage, defaultDesktopImage) { + return $getDefaultDesktopImage$() ?: MSOldCall(); +} + +MSInstanceMessageHook0(UIImage *, SBSlidingAlertDisplay, _defaultDesktopImage) { + return $getDefaultDesktopImage$() ?: MSOldCall(); +} + +MSInstanceMessageHook0(void, SBWallpaperView, resetCurrentImageToWallpaper) { + for (UIView *parent([self superview]); parent != nil; parent = [parent superview]) + if ([parent isKindOfClass:$SBSlidingAlertDisplay]) { + if (UIImage *image = $getDefaultDesktopImage$()) { + [self setImage:image]; + return; + } + + break; + } + + MSOldCall(); +} + // %hook -[SBUIController init] {{{ MSInstanceMessageHook0(id, SBUIController, init) { self = MSOldCall(); @@ -787,15 +940,6 @@ MSInstanceMessageHook0(id, SBUIController, init) { IsWild_ = machine != NULL && strncmp(machine, "iPad", 4) == 0; } - BOOL (*GSSystemHasCapability)(CFStringRef) = reinterpret_cast(dlsym(RTLD_DEFAULT, "GSSystemHasCapability")); - - if ([Info_ objectForKey:@"UndockedIconLabels"] == nil) - [Info_ setObject:[NSNumber numberWithBool:( - !(paper != nil || GSSystemHasCapability != NULL && GSSystemHasCapability(CFSTR("homescreen-wallpaper"))) || - [Info_ objectForKey:@"DockedIconLabelStyle"] != nil || - [Info_ objectForKey:@"UndockedIconLabelStyle"] != nil - )] forKey:@"UndockedIconLabels"]; - if (Debug_) NSLog(@"WB:Debug:Info = %@", [Info_ description]); @@ -1176,6 +1320,7 @@ MSHook(void, SBStatusBarTimeView$drawRect$, SBStatusBarTimeView *self, SEL sel, @interface UIView (WinterBoard) - (bool) wb$isWBImageView; - (void) wb$logHierarchy; +- (void) wb$setBackgroundColor:(UIColor *)color; @end @implementation UIView (WinterBoard) @@ -1188,6 +1333,12 @@ MSHook(void, SBStatusBarTimeView$drawRect$, SBStatusBarTimeView *self, SEL sel, WBLogHierarchy(self); } +- (void) wb$setBackgroundColor:(UIColor *)color { + [self setBackgroundColor:color]; + for (UIView *child in [self subviews]) + [child wb$setBackgroundColor:color]; +} + @end @interface WBImageView : UIImageView { @@ -1263,12 +1414,29 @@ MSHook(id, SBIconLabel$initWithSize$label$, SBIconLabel *self, SEL sel, CGSize s } MSHook(void, SBIconLabel$setInDock$, SBIconLabel *self, SEL sel, BOOL docked) { + static bool gssc(false); + if (!gssc) { + BOOL (*GSSystemHasCapability)(CFStringRef) = reinterpret_cast(dlsym(RTLD_DEFAULT, "GSSystemHasCapability")); + Papered_ |= GSSystemHasCapability != NULL && GSSystemHasCapability(CFSTR("homescreen-wallpaper")); + gssc = true; + + if ([Info_ objectForKey:@"UndockedIconLabels"] == nil) + [Info_ setObject:[NSNumber numberWithBool:( + !Papered_ || + [Info_ objectForKey:@"DockedIconLabelStyle"] != nil || + [Info_ objectForKey:@"UndockedIconLabelStyle"] != nil + )] forKey:@"UndockedIconLabels"]; + } + id &_label(MSHookIvar(self, "_label")); if (![Info_ wb$boolForKey:@"UndockedIconLabels"]) docked = true; + if (_label != nil && [_label respondsToSelector:@selector(setInDock:)]) [_label setInDock:docked]; - return _SBIconLabel$setInDock$(self, sel, docked); + + _SBIconLabel$setInDock$(self, sel, docked); + [self setNeedsDisplay]; } MSHook(BOOL, SBDockIconListView$shouldShowNewDock, id self, SEL sel) { @@ -1344,7 +1512,7 @@ MSInstanceMessageHook1(void, SBIconLabel, drawRect, CGRect, rect) { style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px -1px 0px; "]; bool ellipsis(false); - float max = 75, width; + float max = [self frame].size.width - 11, width; width: width = [(ellipsis ? [label stringByAppendingString:@"..."] : label) sizeWithStyle:style forWidth:320].width; @@ -1372,13 +1540,31 @@ MSInstanceMessageHook1(void, SBIconLabel, drawRect, CGRect, rect) { } // ChatKit {{{ +MSInstanceMessageHook0(void, CKTranscriptHeaderView, layoutSubviews) { + [self wb$setBackgroundColor:[UIColor clearColor]]; + return MSOldCall(); +} + MSInstanceMessageHook1(void, CKMessageCell, addBalloonView, CKBalloonView *, balloon) { MSOldCall(balloon); [balloon setBackgroundColor:[UIColor clearColor]]; } +MSInstanceMessageHook1(void, CKTranscriptCell, setBackgroundColor, UIColor *, color) { + MSOldCall([UIColor clearColor]); + [[self contentView] wb$setBackgroundColor:[UIColor clearColor]]; +} + +MSInstanceMessageHook2(id, CKTranscriptCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) { + if ((self = MSOldCall(style, reuse)) != nil) { + [self setBackgroundColor:[UIColor clearColor]]; + [[self contentView] wb$setBackgroundColor:[UIColor clearColor]]; + } return self; +} + MSInstanceMessageHook2(id, CKMessageCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) { if ((self = MSOldCall(style, reuse)) != nil) { + [self setBackgroundColor:[UIColor clearColor]]; [[self contentView] setBackgroundColor:[UIColor clearColor]]; } return self; } @@ -1403,10 +1589,8 @@ MSInstanceMessageHook2(id, CKTranscriptTableView, initWithFrame,style, CGRect, f MSInstanceMessageHook0(void, CKTranscriptController, loadView) { MSOldCall(); - if (NSString *path = $getTheme$([NSArray arrayWithObjects:@"SMSBackground.png", @"SMSBackground.jpg", nil])) - if (UIImage *image = [[UIImage alloc] initWithContentsOfFile:path]) { - [image autorelease]; - + if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"SMSBackground.png", @"SMSBackground.jpg", nil]))) + if (UIImage *image = $getImage$(path)) { UIView *&_transcriptTable(MSHookIvar(self, "_transcriptTable")); UIView *&_transcriptLayer(MSHookIvar(self, "_transcriptLayer")); UIView *table; @@ -1463,7 +1647,18 @@ MSHook(UIImage *, _UIImageWithName, NSString *name) { if (NSString *path = $pathForFile$inBundle$(name, _UIKitBundle(), true)) image = $getImage$(path); [UIImages_ setObject:(image == nil ? [NSNull null] : reinterpret_cast(image)) forKey:key]; - return image == nil ? __UIImageWithName(name) : image; + if (image != nil) + return image; + + image = __UIImageWithName(name); + + if (UIDebug_) { + NSString *path([@"/tmp/UIImages/" stringByAppendingString:name]); + if (![Manager_ fileExistsAtPath:path]) + [UIImagePNGRepresentation(image) writeToFile:path atomically:YES]; + } + + return image; } } // }}} @@ -1579,8 +1774,6 @@ MSHook(void *, CGImageReadCreateWithFile, NSString *path, int flag) { } // }}} -extern "C" void WKSetCurrentGraphicsContext(CGContextRef); - static void NSString$drawAtPoint$withStyle$(NSString *self, SEL _cmd, CGPoint point, NSString *style) { WKSetCurrentGraphicsContext(UIGraphicsGetCurrentContext()); if (style == nil || [style length] == 0) @@ -1598,8 +1791,6 @@ static void SBInitialize() { class_addMethod($NSString, @selector(drawAtPoint:withStyle:), (IMP) &NSString$drawAtPoint$withStyle$, "v20@0:4{CGPoint=ff}8@16"); class_addMethod($NSString, @selector(sizeWithStyle:forWidth:), (IMP) &NSString$sizeWithStyle$forWidth$, "{CGSize=ff}16@0:4@8f12"); - _UIImage$defaultDesktopImage = MSHookMessage(object_getClass($UIImage), @selector(defaultDesktopImage), &$UIImage$defaultDesktopImage); - if (SummerBoard_) { WBRename(SBApplication, pathForIcon, pathForIcon); WBRename(SBApplicationIcon, icon, icon); @@ -1664,6 +1855,8 @@ MSInitialize { SummerBoard_ = [value boolValue]; if (NSNumber *value = [settings objectForKey:@"Debug"]) Debug_ = [value boolValue]; + if (NSNumber *value = [settings objectForKey:@"RecordUI"]) + UIDebug_ = [value boolValue]; NSArray *themes([settings objectForKey:@"Themes"]); if (themes == nil) @@ -1732,6 +1925,7 @@ MSInitialize { // SpringBoard {{{ if (SpringBoard_) { Wallpapers_ = [[NSArray arrayWithObjects:@"Wallpaper.mp4", @"Wallpaper@2x.png", @"Wallpaper@2x.jpg", @"Wallpaper.png", @"Wallpaper.jpg", @"Wallpaper.html", nil] retain]; + Papered_ = $getTheme$(Wallpapers_) != nil; Docked_ = $getTheme$([NSArray arrayWithObjects:@"Dock.png", nil]); CFNotificationCenterAddObserver( @@ -1774,5 +1968,13 @@ MSInitialize { } // }}} + if (UIDebug_ && ![Manager_ fileExistsAtPath:@"/tmp/UIImages"]) { + NSError *error(nil); + if (![Manager_ createDirectoryAtPath:@"/tmp/UIImages" withIntermediateDirectories:NO attributes:[NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithShort:0777], NSFilePosixPermissions, + nil] error:&error]) + NSLog(@"WB:Error: cannot create /tmp/UIImages (%@)", error); + } + [pool release]; }