X-Git-Url: https://git.saurik.com/winterboard.git/blobdiff_plain/e10298ee3369f38ace9f5daef6bf70b2bbd05127..8e699a8292b89f59ae0d4effd986307e16f2379c:/Library.mm diff --git a/Library.mm b/Library.mm index c251280..48eca47 100644 --- a/Library.mm +++ b/Library.mm @@ -118,11 +118,13 @@ MSClassHook(NSBundle) MSClassHook(NSString) MSClassHook(UIImage) +MSMetaClassHook(UIImage) MSClassHook(UINavigationBar) MSClassHook(UIToolbar) MSClassHook(CKMessageCell) MSClassHook(CKTimestampView) +MSClassHook(CKTranscriptCell) MSClassHook(CKTranscriptController) MSClassHook(CKTranscriptTableView) @@ -131,10 +133,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 +146,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 +196,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_; @@ -230,11 +239,8 @@ static unsigned $getScale$(NSString *path) { return [name hasSuffix:@"@2x"] ? 2 : 1; } -static NSString *$getTheme$(NSArray *files, bool rescale = false) { - if (NSString *path = [Themed_ objectForKey:files]) - return reinterpret_cast(path) == [NSNull null] ? nil : path; - - if (rescale && Scale_ == 0) { +static NSArray *$useScale$(NSArray *files, bool use = true) { + if (Scale_ == 0) { UIScreen *screen([UIScreen mainScreen]); if ([screen respondsToSelector:@selector(scale)]) Scale_ = [screen scale]; @@ -242,6 +248,52 @@ static NSString *$getTheme$(NSArray *files, bool rescale = false) { Scale_ = 1; } + if (Scale_ == 1) + return files; + + NSString *idiom(IsWild_ ? @"ipad" : @"iphone"); + + NSMutableArray *scaled([NSMutableArray arrayWithCapacity:([files count] * 4)]); + + for (NSString *file in files) { + 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; +} + +static NSString *$getTheme$(NSArray *files, NSArray *themes = Themes_) { + if (NSString *path = [Themed_ objectForKey:files]) + return reinterpret_cast(path) == [NSNull null] ? nil : path; + if (Debug_) NSLog(@"WB:Debug: %@", [files description]); @@ -249,12 +301,6 @@ static NSString *$getTheme$(NSArray *files, bool rescale = false) { for (NSString *theme in Themes_) for (NSString *file in files) { - if (rescale && /*$getScale$(file) == 1 &&*/ Scale_ == 2) { - path = [NSString stringWithFormat:@"%@/%@@2x.%@", theme, [file stringByDeletingPathExtension], [file pathExtension]]; - if ([Manager_ fileExistsAtPath:path]) - goto set; - } - path = [NSString stringWithFormat:@"%@/%@", theme, file]; if ([Manager_ fileExistsAtPath:path]) goto set; @@ -295,7 +341,7 @@ static NSString *$pathForFile$inBundle$(NSString *file, NSBundle *bundle, bool u remapResourceName(Four_ ? @"SBDockBG-old.png" : @"SBDockBG.png", @"Dock") remapResourceName(@"SBWeatherCelsius.png", @"Icons/Weather") - if (NSString *path = $getTheme$(names, ui)) + if (NSString *path = $getTheme$($useScale$(names, ui))) return path; return nil; @@ -613,6 +659,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]); @@ -720,14 +863,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_; @@ -752,13 +887,43 @@ 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(); if (self == nil) return nil; - NSString *paper($getTheme$(Wallpapers_, true)); + NSString *paper($getTheme$(Wallpapers_)); + if (paper != nil) + paper = [paper stringByDeletingLastPathComponent]; { size_t size; @@ -840,8 +1005,10 @@ MSInstanceMessageHook0(id, SBUIController, init) { _release(WallpaperPage_); _release(WallpaperURL_); - if (NSString *path = paper) { - if ([path hasSuffix:@".mp4"]) { + if (paper != nil) { + NSArray *themes([NSArray arrayWithObject:paper]); + + if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"], themes)) { #if UseAVController NSError *error; @@ -876,7 +1043,7 @@ MSInstanceMessageHook0(id, SBUIController, init) { [indirect addSubview:video]; } - if ([path hasSuffix:@".png"] || [path hasSuffix:@".jpg"]) { + if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"Wallpaper.png", @"Wallpaper.jpg", nil]), themes)) { if (UIImage *image = $getImage$(path)) { WallpaperFile_ = [path retain]; WallpaperImage_ = [[UIImageView alloc] initWithImage:image]; @@ -886,7 +1053,7 @@ MSInstanceMessageHook0(id, SBUIController, init) { } } - if ([path hasSuffix:@".html"]) { + if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.html"], themes)) { CGRect bounds = [indirect bounds]; UIWebDocumentView *view([[[UIWebDocumentView alloc] initWithFrame:bounds] autorelease]); @@ -1251,9 +1418,12 @@ MSHook(void, SBIconLabel$setInDock$, SBIconLabel *self, SEL sel, BOOL docked) { 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) { @@ -1329,7 +1499,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; @@ -1362,8 +1532,20 @@ MSInstanceMessageHook1(void, CKMessageCell, addBalloonView, CKBalloonView *, bal [balloon setBackgroundColor:[UIColor clearColor]]; } +MSInstanceMessageHook1(void, CKTranscriptCell, setBackgroundColor, UIColor *, color) { + MSOldCall([UIColor clearColor]); +} + +MSInstanceMessageHook2(id, CKTranscriptCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) { + if ((self = MSOldCall(style, reuse)) != nil) { + [self setBackgroundColor:[UIColor clearColor]]; + [[self contentView] 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; } @@ -1388,10 +1570,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; @@ -1448,7 +1628,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; } } // }}} @@ -1460,7 +1651,7 @@ MSHook(UIImage *, _UIImageWithNameInDomain, NSString *name, NSString *domain) { return reinterpret_cast(image) == [NSNull null] ? __UIImageWithNameInDomain(name, domain) : image; if (Debug_) NSLog(@"WB:Debug: UIImageWithNameInDomain(\"%@\", \"%@\")", name, domain); - if (NSString *path = $getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Domains/%@/%@", domain, name]], true)) + if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObject:[NSString stringWithFormat:@"Domains/%@/%@", domain, name]]))) image = $getImage$(path); [PathImages_ setObject:(image == nil ? [NSNull null] : reinterpret_cast(image)) forKey:key]; return image == nil ? __UIImageWithNameInDomain(name, domain) : image; @@ -1564,8 +1755,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) @@ -1583,8 +1772,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); @@ -1649,6 +1836,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) @@ -1716,7 +1905,7 @@ MSInitialize { // }}} // SpringBoard {{{ if (SpringBoard_) { - Wallpapers_ = [[NSArray arrayWithObjects:@"Wallpaper.mp4", @"Wallpaper.png", @"Wallpaper.jpg", @"Wallpaper.html", nil] retain]; + Wallpapers_ = [[NSArray arrayWithObjects:@"Wallpaper.mp4", @"Wallpaper@2x.png", @"Wallpaper@2x.jpg", @"Wallpaper.png", @"Wallpaper.jpg", @"Wallpaper.html", nil] retain]; Docked_ = $getTheme$([NSArray arrayWithObjects:@"Dock.png", nil]); CFNotificationCenterAddObserver( @@ -1759,5 +1948,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]; }