Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
267 lines (208 sloc) 6.75 KB
//
// Tweak.xmi
// Ignition
//
// Created by Adam Bell on 2014-11-28.
// Copyright (c) 2014 Adam Bell. All rights reserved.
//
#import <xctheos.h>
CONFIG(generator=MobileSubstrate);
#import <UIKit/UIKit.h>
#import "substrate.h"
#import "PrivateHeaders.h"
#include "ViewControllerFixes.xm"
#include "AppFixes.xm"
// Temporary for now, flipswitch or preferences bundle toggle would make sense in the future.
#define UIInterfaceIdiomCarPlay 0x3 // Or external display?
GROUP(CARPLAY_HAX);
HOOK(UIScreen)
- (BOOL)_isCarScreen
{
return YES;
}
- (UIScreen *)_carScreen
{
return [UIScreen mainScreen];
}
// Loads of places check for this to be 0x3 (which I'm assuming is an external display or carplay).
- (NSUInteger)_userInterfaceIdiom
{
return UIInterfaceIdiomCarPlay;
}
- (void)_setUserInterfaceIdiom:(NSUInteger)idiom
{
ORIG(UIInterfaceIdiomCarPlay);
}
- (CGRect)bounds
{
#ifdef __LOGOS_H
CGRect screenBounds = ORIG();
#else
CGRect screenBounds = CGRectZero;
#endif
BOOL shouldFlipWidth = screenBounds.size.height > screenBounds.size.width;
if (shouldFlipWidth) {
screenBounds = CGRectMake(screenBounds.origin.x, screenBounds.origin.y, screenBounds.size.height, screenBounds.size.width);
}
if ([[UIApplication sharedApplication].delegate isKindOfClass:GET_CLASS(MAAppDelegate)] ||
[[UIApplication sharedApplication].delegate isKindOfClass:GET_CLASS(SMSApplication)] ||
[[UIApplication sharedApplication].delegate isKindOfClass:GET_CLASS(MobilePhoneApplication)]) {
return CGRectMake(STATUSBAR_WIDTH, 0.0, screenBounds.size.width - STATUSBAR_WIDTH, screenBounds.size.height);
}
#ifdef __LOGOS_H
return ORIG_T();
#else
return CGRectZero;
#endif
}
- (CGRect)applicationFrame
{
if ([[UIApplication sharedApplication].delegate isKindOfClass:GET_CLASS(MAAppDelegate)] ||
[[UIApplication sharedApplication].delegate isKindOfClass:GET_CLASS(SMSApplication)] ||
[[UIApplication sharedApplication].delegate isKindOfClass:GET_CLASS(MobilePhoneApplication)]) {
return [UIScreen mainScreen].bounds;
}
#ifdef __LOGOS_H
return ORIG_T();
#else
return CGRectZero;
#endif
}
END()
HOOK(UIWindow)
- (void)setFrame:(CGRect)frame
{
if ([[UIApplication sharedApplication].delegate isKindOfClass:GET_CLASS(MAAppDelegate)] ||
[[UIApplication sharedApplication].delegate isKindOfClass:GET_CLASS(SMSApplication)] ||
[[UIApplication sharedApplication].delegate isKindOfClass:GET_CLASS(MobilePhoneApplication)]) {
ORIG([UIScreen mainScreen].bounds);
} else {
ORIG();
}
}
END()
HOOK(UIDevice)
- (NSUInteger)orientation
{
return UIDeviceOrientationLandscapeLeft;
}
- (void)_setUserInterfaceIdiom:(NSUInteger)idiom
{
ORIG(UIInterfaceIdiomCarPlay);
}
- (void)_setActiveUserInterfaceIdiom:(NSUInteger)idiom
{
ORIG(UIInterfaceIdiomCarPlay);
}
- (NSUInteger)_userInterfaceIdiom
{
return UIInterfaceIdiomCarPlay;
}
END()
// Don't need this anymore!
HOOK(UIStatusBarWindow)
- (id)initWithFrame:(CGRect)frame
{
id orig = ORIG();
[self setAlpha:0.0];
return orig;
}
- (void)setAlpha:(CGFloat)alpha
{
ORIG(0.0);
}
END()
HOOK(FBSDisplay)
- (BOOL)isCarDisplay
{
return YES;
}
// lulz
- (BOOL)isAirPlayDisplay
{
return NO;
}
END()
HOOK(SpringBoard)
// Activates CarPlay when SpringBoard launches (only for debugging purposes atm).
- (void)applicationDidFinishLaunching:(UIApplication *)application
{
ORIG();
[[GET_CLASS(SBStarkScreenManager) sharedInstance] screenManager:[GET_CLASS(SBStarkScreenManager) sharedInstance] didTriggerConnectionHandlerEvent: nil forScreen: [UIScreen mainScreen]];
// Creates a proper frame to display any carplay UI, because when projected onto an external screen the UI is forced into portrait. :/
if (CGRectIsEmpty(carplay_frame)) {
CGRect screenFrame = [[UIScreen mainScreen] bounds];
BOOL shouldFlipHeight = screenFrame.size.width > screenFrame.size.height;
if (shouldFlipHeight) {
screenFrame = CGRectMake(STATUSBAR_WIDTH, screenFrame.origin.y, screenFrame.size.height, screenFrame.size.width);
}
carplay_frame = screenFrame;
carplay_frame.size.height -= [GET_CLASS(SBCarWindowLayoutStrategy) edgeInsetsForStatusBar].top;
}
// Also hide "SpringBoard's" icon grid, so it doesn't conflict with the Stark one.
for (UIWindow *window in [UIApplication sharedApplication].windows) {
if ([window isKindOfClass:GET_CLASS(SBAppWindow)]) {
window.hidden = YES;
}
}
}
END()
HOOK(LSApplicationProxy)
- (NSDictionary *)entitlements
{
// Only include @"com.apple.developer.playable-content" : @YES if the app actually supports it, it's meant for music apps and overrides the primary window.
static NSArray *allowedApplicationIdentifiers = @[
@"ca.adambell.IgnitionLauncher",
@"com.steventroughtonsmith.speed2",
@"com.apple.Preferences",
@"com.google.Maps",
@"com.waze.iphone",
@"com.soundcloud.TouchApp",
@"com.facebook.Messenger",
];
NSDictionary *entitlements = ORIG();
if ([allowedApplicationIdentifiers containsObject:self.applicationIdentifier]) {
NSMutableDictionary *newEntitlements = [entitlements mutableCopy];
newEntitlements[@"SBStarkCapable"] = @YES;
entitlements = [newEntitlements copy];
}
return entitlements;
}
END()
HOOK(SBCarWindowLayoutStrategy)
// Flip CarPlay statusbar frame inset such that it's on the left and not the top (since when projected onto an external screen everything is portrait).
+ (UIEdgeInsets)edgeInsetsForStatusBar
{
#ifdef __LOGOS_H
UIEdgeInsets insets = ORIG_T();
#else
UIEdgeInsets insets = UIEdgeInsetsZero;
#endif
insets.top = insets.left;
insets.left = 0.0;
return insets;
}
END()
END_GROUP()
// Force libMobileGestalt to allow CarPlay capabilities.
CFBooleanRef (*orig_MGGetBoolAnswer)(CFStringRef);
CFBooleanRef fixed_MGGetBoolAnswer(CFStringRef string)
{
if (CFEqual(string, CFSTR("StarkCapability"))) {
return kCFBooleanTrue;
}
return orig_MGGetBoolAnswer(string);
}
CTOR({
if (!CARPLAY_ACTIVE) {
return;
}
MSHookFunction(((void *)MSFindSymbol(NULL, "_MGGetBoolAnswer")), (void *)fixed_MGGetBoolAnswer, (void **)&orig_MGGetBoolAnswer);
if ([[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.springboard"]) {
// Need to load up the Siri UI first to apply fixes.
dlopen("/System/Library/SpringBoardPlugins/Assistant.uibundle/Assistant", RTLD_NOW);
}
INIT(CARPLAY_HAX);
INIT(VIEWCONTROLLER_FIXES);
INIT(APP_FIXES);
})
You can’t perform that action at this time.