diff --git a/JavaApp/src/main/java/net/kdt/pojavlaunch/Tools.java b/JavaApp/src/main/java/net/kdt/pojavlaunch/Tools.java index 12eb1a3e..e3965723 100644 --- a/JavaApp/src/main/java/net/kdt/pojavlaunch/Tools.java +++ b/JavaApp/src/main/java/net/kdt/pojavlaunch/Tools.java @@ -158,6 +158,7 @@ public final class Tools gameDir.mkdirs(); Map varArgMap = new ArrayMap(); + varArgMap.put("auth_session", profile.accessToken); // For legacy versions of MC varArgMap.put("auth_access_token", profile.accessToken); varArgMap.put("auth_player_name", username); varArgMap.put("auth_uuid", profile.profileId); diff --git a/Makefile b/Makefile index 3f85c51d..3586c8d2 100644 --- a/Makefile +++ b/Makefile @@ -90,7 +90,7 @@ PACKAGING = \ cp $(SOURCEDIR)/DEBIAN/postinst DEBIAN/postinst; \ ldid -S$(SOURCEDIR)/entitlements.xml Applications/PojavLauncher.app; \ cd $(OUTPUTDIR); \ - fakeroot dpkg-deb -b $(OUTPUTDIR)/net.kdt.pojavlauncher.$(1)_$(VERSION)_iphoneos-arm; \ + fakeroot dpkg-deb -Zxz -b $(OUTPUTDIR)/net.kdt.pojavlauncher.$(1)_$(VERSION)_iphoneos-arm; \ mkdir -p $(OUTPUTDIR)/net.kdt.pojavlauncher.$(1)-rootless_$(VERSION)_iphoneos-arm64; \ cd $(OUTPUTDIR)/net.kdt.pojavlauncher.$(1)-rootless_$(VERSION)_iphoneos-arm64; \ mkdir -p {DEBIAN,$(IOS15PREF)/{Applications,usr/share/pojavlauncher/{accounts,instances/default,Library/{Application\ Support,Caches}}}}; \ @@ -107,7 +107,7 @@ PACKAGING = \ cp $(SOURCEDIR)/DEBIAN/postinst DEBIAN/postinst; \ ldid -S$(SOURCEDIR)/entitlements.xml $(IOS15PREF)/Applications/PojavLauncher.app; \ cd $(OUTPUTDIR); \ - fakeroot dpkg-deb -b $(OUTPUTDIR)/net.kdt.pojavlauncher.$(1)-rootless_$(VERSION)_iphoneos-arm64 + fakeroot dpkg-deb -Zxz -b $(OUTPUTDIR)/net.kdt.pojavlauncher.$(1)-rootless_$(VERSION)_iphoneos-arm64 # Function to check directories DIRCHECK = \ diff --git a/Natives/AboutLauncherViewController.m b/Natives/AboutLauncherViewController.m index b3066cff..5f9d9204 100644 --- a/Natives/AboutLauncherViewController.m +++ b/Natives/AboutLauncherViewController.m @@ -26,7 +26,7 @@ - (void)viewDidLoad { [super viewDidLoad]; - + setViewBackgroundColor(self.view); [self setTitle:@"About PojavLauncher"]; CGRect screenBounds = [[UIScreen mainScreen] bounds]; @@ -40,13 +40,6 @@ [self.view addSubview:scrollView]; scrollView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; - // Update color mode once - if(@available(iOS 13.0, *)) { - [self traitCollectionDidChange:nil]; - } else { - self.view.backgroundColor = [UIColor whiteColor]; - } - // TODO: Move this into utils? struct utsname systemInfo; uname(&systemInfo); @@ -125,14 +118,4 @@ [self.navigationController pushViewController:vc animated:YES]; } --(void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection { - if(@available(iOS 13.0, *)) { - if (UITraitCollection.currentTraitCollection.userInterfaceStyle == UIUserInterfaceStyleDark) { - self.view.backgroundColor = [UIColor blackColor]; - } else { - self.view.backgroundColor = [UIColor whiteColor]; - } - } -} - @end diff --git a/Natives/AccountListViewController.h b/Natives/AccountListViewController.h index 7ab063c2..4d1f418a 100644 --- a/Natives/AccountListViewController.h +++ b/Natives/AccountListViewController.h @@ -1,6 +1,7 @@ #import -@interface AccountListViewController : UITableViewController +@interface AccountListViewController: UITableViewController + @property (nonatomic, copy) void (^whenDelete)(NSString* name); @property(nonatomic, copy) void (^whenItemSelected)(NSString* name); diff --git a/Natives/AccountListViewController.m b/Natives/AccountListViewController.m index d8247888..6b444dfb 100644 --- a/Natives/AccountListViewController.m +++ b/Natives/AccountListViewController.m @@ -58,8 +58,10 @@ } NSDictionary *selected = self.accountList[indexPath.row]; + // By default, display the saved username cell.textLabel.text = selected[@"username"]; if ([selected[@"username"] hasPrefix:@"Demo."]) { + // Remove the prefix "Demo." cell.textLabel.text = [selected[@"username"] substringFromIndex:5]; cell.detailTextLabel.text = NSLocalizedString(@"login.option.demo", nil); } else if (selected[@"xboxGamertag"] == nil) { @@ -85,7 +87,7 @@ if (editingStyle == UITableViewCellEditingStyleDelete) { // TODO: invalidate token - NSString *str = [self.accountList objectAtIndex:indexPath.row][@"username"]; + NSString *str = self.accountList[indexPath.row][@"username"]; NSFileManager *fm = [NSFileManager defaultManager]; NSString *path = [NSString stringWithFormat:@"%s/accounts/%@.json", getenv("POJAV_HOME"), str]; if (self.whenDelete != nil) { @@ -97,4 +99,9 @@ } } +#pragma mark - UIPopoverPresentationControllerDelegate +- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller traitCollection:(UITraitCollection *)traitCollection { + return UIModalPresentationNone; +} + @end diff --git a/Natives/CMakeLists.txt b/Natives/CMakeLists.txt index 89b1b8b3..1de7337a 100644 --- a/Natives/CMakeLists.txt +++ b/Natives/CMakeLists.txt @@ -59,6 +59,7 @@ add_executable(PojavLauncher external/AFNetworking/UIKit+AFNetworking/AFNetworkActivityIndicatorManager.m external/AFNetworking/UIKit+AFNetworking/AFAutoPurgingImageCache.m external/AFNetworking/UIKit+AFNetworking/AFImageDownloader.m + external/AFNetworking/UIKit+AFNetworking/UIButton+AFNetworking.m external/AFNetworking/UIKit+AFNetworking/UIImageView+AFNetworking.m main.m @@ -87,8 +88,10 @@ add_executable(PojavLauncher JavaGUIViewController.m KeyboardInput.m LauncherFAQViewController.m + LauncherMenuViewController.m LauncherPreferences.m LauncherPreferencesViewController.m + LauncherSplitViewController.m LauncherViewController.m LoginViewController.m MinecraftResourceUtils.m diff --git a/Natives/CustomControlsViewController.m b/Natives/CustomControlsViewController.m index 6a5d7f6d..32a8becd 100644 --- a/Natives/CustomControlsViewController.m +++ b/Natives/CustomControlsViewController.m @@ -86,19 +86,13 @@ NSMutableArray *keyCodeMap, *keyValueMap; - (void)viewDidLoad { [super viewDidLoad]; + self.view.backgroundColor = [UIColor colorWithWhite:0.2 alpha:0.5]; + viewController = self; isControlModifiable = YES; - [self.navigationController setNavigationBarHidden:YES animated:YES]; [self setNeedsUpdateOfScreenEdgesDeferringSystemGestures]; [self setNeedsUpdateOfHomeIndicatorAutoHidden]; - // Update color mode once - if(@available(iOS 13.0, *)) { - [self traitCollectionDidChange:nil]; - } else { - self.view.backgroundColor = [UIColor whiteColor]; - } - CGRect screenBounds = [[UIScreen mainScreen] bounds]; UIEdgeInsets insets = UIApplication.sharedApplication.windows.firstObject.safeAreaInsets; @@ -203,8 +197,7 @@ NSMutableArray *keyCodeMap, *keyValueMap; } - (void)actionMenuExit { - [self.navigationController setNavigationBarHidden:NO animated:YES]; - [self.navigationController popViewControllerAnimated:YES]; + [self dismissViewControllerAnimated:YES completion:nil]; } - (void)actionMenuSave { @@ -437,16 +430,6 @@ NSMutableArray *keyCodeMap, *keyValueMap; } } --(void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection { - if(@available(iOS 13.0, *)) { - if (UITraitCollection.currentTraitCollection.userInterfaceStyle == UIUserInterfaceStyleDark) { - self.view.backgroundColor = [UIColor blackColor]; - } else { - self.view.backgroundColor = [UIColor whiteColor]; - } - } -} - #pragma mark - UIPopoverPresentationControllerDelegate - (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller traitCollection:(UITraitCollection *)traitCollection { return UIModalPresentationNone; diff --git a/Natives/JavaGUIViewController.m b/Natives/JavaGUIViewController.m index 883a9dfe..6e113a4f 100644 --- a/Natives/JavaGUIViewController.m +++ b/Natives/JavaGUIViewController.m @@ -69,7 +69,8 @@ const void * _CGDataProviderGetBytePointerCallbackAWT(void *info) { - (void)viewDidLoad { [super viewDidLoad]; - + viewController = self; + self.view.backgroundColor = UIColor.blackColor; [self.navigationController setNavigationBarHidden:YES animated:NO]; [self setNeedsUpdateOfScreenEdgesDeferringSystemGestures]; [self setNeedsUpdateOfHomeIndicatorAutoHidden]; @@ -95,13 +96,6 @@ const void * _CGDataProviderGetBytePointerCallbackAWT(void *info) { [self.view addSubview:scrollView]; - // Update color mode once - if(@available(iOS 13.0, *)) { - [self traitCollectionDidChange:nil]; - } else { - self.view.backgroundColor = [UIColor whiteColor]; - } - UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(surfaceOnClick:)]; tapGesture.delegate = self; @@ -164,14 +158,4 @@ const void * _CGDataProviderGetBytePointerCallbackAWT(void *info) { return NO; } --(void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection { - if(@available(iOS 13.0, *)) { - if (UITraitCollection.currentTraitCollection.userInterfaceStyle == UIUserInterfaceStyleDark) { - self.view.backgroundColor = [UIColor blackColor]; - } else { - self.view.backgroundColor = [UIColor whiteColor]; - } - } -} - @end diff --git a/Natives/JavaLauncher.m b/Natives/JavaLauncher.m index 8f382ea1..c1bb0cfd 100644 --- a/Natives/JavaLauncher.m +++ b/Natives/JavaLauncher.m @@ -58,6 +58,9 @@ void init_loadCustomEnv() { // Override OpenGL version to 4.1 for Zink setenv("MESA_GL_VERSION_OVERRIDE", "4.1", 1); + // Runs JVM in a separate thread + setenv("HACK_IGNORE_START_ON_FIRST_THREAD", "1", 1); + /* Load custom env */ FILE *envFile = fopen([NSString stringWithFormat:@"%s/custom_env.txt", getenv("POJAV_HOME")].UTF8String, "r"); @@ -103,22 +106,24 @@ void init_loadCustomJvmFlags() { } NSString* environmentFailsafes(int minVersion) { + NSString *jvmPath = getenv("POJAV_DETECTEDJB") ? @"/usr/lib/jvm" : [NSString stringWithFormat:@"%s/jvm", getenv("BUNDLE_PATH")]; NSString *javaHome = nil; - if (getenv("POJAV_DETECTEDJB")) { - BOOL foundJava8 = [fm fileExistsAtPath:JRE8_HOME_JB]; - if (!foundJava8) { - regLog("[JavaLauncher] Java 8 wasn't found on your device. Install Java 8 for more compatibility and the mod installer."); - } - if (foundJava8 && minVersion <= 8) { - javaHome = JRE8_HOME_JB; - } else if ([fm fileExistsAtPath:JRE16_HOME_JB] && minVersion <= 16) { - javaHome = JRE16_HOME_JB; - } else if ([fm fileExistsAtPath:JRE17_HOME_JB] && minVersion <= 17) { - javaHome = JRE17_HOME_JB; - } - } else if (minVersion <= 8) { - javaHome = [NSString stringWithFormat:@"%s/jre", getenv("POJAV_HOME")]; + NSString *jre8Path = [NSString stringWithFormat:@"%@/java-8-openjdk", jvmPath]; + NSString *jre16Path = [NSString stringWithFormat:@"%@/java-16-openjdk", jvmPath]; + NSString *jre17Path = [NSString stringWithFormat:@"%@/java-17-openjdk", jvmPath]; + + BOOL foundJava8 = [fm fileExistsAtPath:jre8Path]; + if (!foundJava8) { + regLog("[JavaLauncher] Java 8 wasn't found on your device. Install Java 8 for more compatibility and the mod installer."); + } + + if (foundJava8 && minVersion <= 8) { + javaHome = jre8Path; + } else if ([fm fileExistsAtPath:jre16Path] && minVersion <= 16) { + javaHome = jre16Path; + } else if ([fm fileExistsAtPath:jre17Path] && minVersion <= 17) { + javaHome = jre17Path; } if (javaHome == nil) { @@ -163,92 +168,6 @@ int launchJVM(NSString *username, id launchTarget, int width, int height, int mi javaHome = javaHome_pre.UTF8String; setenv("JAVA_HOME", javaHome, 1); - if (!getenv("POJAV_DETECTEDJB")) { - char src[2048], dst[2048]; - - // Symlink frameworks -> dylibs on jailed environment - mkdir(javaHome, 755); - - // Symlink the skeleton part of JRE - sprintf((char *)src, "%s/jre/man", getenv("BUNDLE_PATH")); - sprintf((char *)dst, "%s/man", javaHome); - symlink(src, dst); - - sprintf((char *)src, "%s/jre/lib", getenv("BUNDLE_PATH")); - sprintf((char *)dst, "%s/lib", javaHome); - mkdir(dst, 755); - - DIR *d; - struct dirent *dir; - d = opendir(src); - assert(d); - int i = 0; - while ((dir = readdir(d)) != NULL) { - // Skip "." and ".." - if (i < 2) { - i++; - continue; - } else if (!strncmp(dir->d_name, "jli", 3)) { - sprintf((char *)dst, "%s/lib/jli", javaHome); - mkdir(dst, 755); - - // libjli.dylib - sprintf((char *)src, "%s/Frameworks/libjli.dylib.framework/libjli.dylib", getenv("BUNDLE_PATH")); - sprintf((char *)dst, "%s/lib/jli/libjli.dylib", javaHome); - symlink(src, dst); - } else if (!strncmp(dir->d_name, "server", 6)) { - sprintf((char *)dst, "%s/lib/server", javaHome); - mkdir(dst, 755); - - // libjsig.dylib - sprintf((char *)src, "%s/Frameworks/libjsig.dylib.framework/libjsig.dylib", getenv("BUNDLE_PATH")); - sprintf((char *)dst, "%s/lib/server/libjsig.dylib", javaHome); - symlink(src, dst); - - // libjvm.dylib - sprintf((char *)src, "%s/Frameworks/libjvm.dylib.framework/libjvm.dylib", getenv("BUNDLE_PATH")); - sprintf((char *)dst, "%s/lib/server/libjvm.dylib", javaHome); - symlink(src, dst); - - // Xusage.txt - sprintf((char *)src, "%s/jre/lib/server/Xusage.txt", getenv("BUNDLE_PATH")); - sprintf((char *)dst, "%s/lib/server/Xusage.txt", javaHome); - symlink(src, dst); - } else { - sprintf((char *)src, "%s/jre/lib/%s", getenv("BUNDLE_PATH"), dir->d_name); - sprintf((char *)dst, "%s/lib/%s", javaHome, dir->d_name); - symlink(src, dst); - } - } - closedir(d); - - // Symlink dylibs - sprintf((char *)src, "%s/Frameworks", getenv("BUNDLE_PATH")); - d = opendir(src); - assert(d); - i = 0; - while ((dir = readdir(d)) != NULL) { - // Skip "." and ".." - if (i < 2) { - i++; - continue; - } else if (!strncmp(dir->d_name, "lib", 3) && strlen(dir->d_name) > 12) { - char *dylibName = strdup(dir->d_name); - dylibName[strlen(dylibName) - 10] = '\0'; - sprintf((char *)src, "%s/Frameworks/%s/%s", getenv("BUNDLE_PATH"), dir->d_name, dylibName); - if (!strncmp(dir->d_name, "libjvm.dylib", 12)) { - sprintf((char *)dst, "%s/lib/server/%s", javaHome, dylibName); - } else { - sprintf((char *)dst, "%s/lib/%s", javaHome, dylibName); - } - symlink(src, dst); - dylibName[strlen(dylibName) - 11] = '.'; - free(dylibName); - } - } - closedir(d); - } - renderer_pre = getPreference(@"renderer"); renderer = renderer_pre.UTF8String; if (renderer_pre.length == 0) { diff --git a/Natives/LauncherFAQViewController.m b/Natives/LauncherFAQViewController.m index 6717c4e0..7b64adb8 100644 --- a/Natives/LauncherFAQViewController.m +++ b/Natives/LauncherFAQViewController.m @@ -12,7 +12,7 @@ CGFloat faqcurrY = 4.0; - (void)viewDidLoad { [super viewDidLoad]; - + setViewBackgroundColor(self.view); [self setTitle:@"Launcher FAQ"]; CGRect screenBounds = [[UIScreen mainScreen] bounds]; @@ -25,12 +25,6 @@ CGFloat faqcurrY = 4.0; [self.view addSubview:scrollView]; scrollView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; - // Update color mode once - if(@available(iOS 13.0, *)) { - [self traitCollectionDidChange:nil]; - } else { - self.view.backgroundColor = [UIColor whiteColor]; - } NSString *snapheadingtext = @"Vanilla versions after 21w08b"; faqcurrY = 4.0; @@ -67,14 +61,4 @@ CGFloat faqcurrY = 4.0; return label; } --(void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection { - if(@available(iOS 13.0, *)) { - if (UITraitCollection.currentTraitCollection.userInterfaceStyle == UIUserInterfaceStyleDark) { - self.view.backgroundColor = [UIColor blackColor]; - } else { - self.view.backgroundColor = [UIColor whiteColor]; - } - } -} - @end diff --git a/Natives/LauncherMenuViewController.h b/Natives/LauncherMenuViewController.h new file mode 100644 index 00000000..ff66f69a --- /dev/null +++ b/Natives/LauncherMenuViewController.h @@ -0,0 +1,7 @@ +#import + +@interface LauncherMenuViewController : UITableViewController + +@property NSString* listPath; + +@end diff --git a/Natives/LauncherMenuViewController.m b/Natives/LauncherMenuViewController.m new file mode 100644 index 00000000..0a3c15f9 --- /dev/null +++ b/Natives/LauncherMenuViewController.m @@ -0,0 +1,138 @@ +#import "authenticator/BaseAuthenticator.h" +#import "AccountListViewController.h" +#import "LauncherMenuViewController.h" +#import "LauncherPreferencesViewController.h" +#import "LauncherViewController.h" +#import "UIButton+AFNetworking.h" +#import "UIImageView+AFNetworking.h" + +@interface LauncherMenuViewController () { +} + +@property NSArray *options; +@end + +@implementation LauncherMenuViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + + // View controllers are put into an array to keep its state + self.options = @[ + [[LauncherViewController alloc] init], + [[LauncherPreferencesViewController alloc] init] + ]; + self.options[0].title = @"PojavLauncher"; + self.options[1].title = @"Preferences"; + //@[@"News", @"Development Console", @"Crash logs"]; + self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; + + UIButton *titleButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [titleButton addTarget:self action:@selector(selectAccount:) forControlEvents:UIControlEventTouchUpInside]; + titleButton.frame = self.navigationController.navigationBar.frame; + titleButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft; + if (@available(iOS 14.0, tvOS 14.0, *)) { + // On iOS 14+, a special button is displayed to toggle the visibility of the master view controller. + // It creates a bit more offset while in the process of swipe/animation. Therefore the left inset + // has to be increased a bit for this button. + titleButton.contentEdgeInsets = UIEdgeInsetsMake(4, 4, 4, 8); + } else { + titleButton.contentEdgeInsets = UIEdgeInsetsMake(4, 0, 4, 8); + } + titleButton.titleEdgeInsets = UIEdgeInsetsMake(0, 4, 0, -4); + titleButton.imageView.contentMode = UIViewContentModeScaleAspectFit; + titleButton.titleLabel.lineBreakMode = NSLineBreakByWordWrapping; + self.navigationItem.titleView = titleButton; + + [self updateAccountInfo]; + [self tableView:self.tableView didSelectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; +} + +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + + // workaround while investigating for issue + if (self.splitViewController.viewControllers.count < 2) return; + + // Restore the selected row when the view appears again + int index = [self.options indexOfObject:[self.splitViewController.viewControllers[1] viewControllers][0]]; + NSIndexPath *indexPath = [NSIndexPath indexPathForRow:index inSection:0]; + [self.tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone]; +} + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section +{ + return self.options.count; +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath +{ + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"]; + if (cell == nil) { + cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"]; + } + + cell.textLabel.text = [self.options[indexPath.row] title]; + return cell; +} + +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath +{ + UIViewController *selected = self.options[indexPath.row]; + [self.splitViewController.viewControllers[1] setViewControllers:@[selected] animated:NO]; //YES? + + if (@available(iOS 14.0, tvOS 14.0, *)) { + // It is unnecessary to put the toggle button as it is automated on iOS 14+ + } else { + selected.navigationItem.leftBarButtonItem = self.splitViewController.displayModeButtonItem; + selected.navigationItem.leftItemsSupplementBackButton = true; + } + + // This button is placed temporarily while migrating to the new UI + self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"❌" style:UIBarButtonItemStyleDone target:self.splitViewController action:@selector(dismissViewController)]; +} + +- (void)selectAccount:(UIButton *)sender { + AccountListViewController *vc = [[AccountListViewController alloc] init]; + vc.whenItemSelected = ^void(NSString* name) { + // TODO: perform token refreshing + [BaseAuthenticator loadSavedName:name]; + [self updateAccountInfo]; + }; + vc.modalPresentationStyle = UIModalPresentationPopover; + vc.preferredContentSize = CGSizeMake(350, 250); + + UIPopoverPresentationController *popoverController = vc.popoverPresentationController; + popoverController.sourceView = sender; + popoverController.sourceRect = sender.bounds; + popoverController.permittedArrowDirections = UIPopoverArrowDirectionAny; + popoverController.delegate = vc; + [self presentViewController:vc animated:YES completion:nil]; +} + +- (void)updateAccountInfo { + NSDictionary *selected = BaseAuthenticator.current.authData; + BOOL isDemo = [selected[@"username"] hasPrefix:@"Demo."]; + NSMutableAttributedString *title = [[NSMutableAttributedString alloc] initWithString:[selected[@"username"] substringFromIndex:(isDemo?5:0)]]; + id subtitle; + if (isDemo) { + // Remove the prefix "Demo." + subtitle = NSLocalizedString(@"login.option.demo", nil); + } else if (selected[@"xboxGamertag"] == nil) { + subtitle = NSLocalizedString(@"login.option.local", nil); + } else { + // Display the Xbox gamertag for online accounts + subtitle = selected[@"xboxGamertag"]; + } + subtitle = [[NSAttributedString alloc] initWithString:subtitle attributes:@{NSFontAttributeName: [UIFont systemFontOfSize:12]}]; + [title appendAttributedString:[[NSAttributedString alloc] initWithString:@"\n" attributes:nil]]; + [title appendAttributedString:subtitle]; + [(UIButton *)self.navigationItem.titleView setAttributedTitle:title forState:UIControlStateNormal]; + + NSURL *url = [NSURL URLWithString:[selected[@"profilePicURL"] stringByReplacingOccurrencesOfString:@"\\/" withString:@"/"]]; + UIImage *placeholder = [UIImage imageNamed:@"default_account_pfp"]; + [(UIButton *)self.navigationItem.titleView setImageForState:UIControlStateNormal withURL:url placeholderImage:placeholder]; + [((UIButton *)self.navigationItem.titleView).imageView setImageWithURL:url placeholderImage:placeholder]; +} + +@end diff --git a/Natives/LauncherPreferences.h b/Natives/LauncherPreferences.h index 5675ab1e..c135bd7f 100644 --- a/Natives/LauncherPreferences.h +++ b/Natives/LauncherPreferences.h @@ -7,6 +7,7 @@ void loadPreferences(); id getPreference(NSString* key); NSMutableDictionary* getDictionary(NSString *type); +int getJavaVersion(NSString* java); int getSelectedJavaVersion(); void setDefaultValueForPref(NSMutableDictionary *dict, NSString* key, id value); void setPreference(NSString* key, id value); diff --git a/Natives/LauncherPreferences.m b/Natives/LauncherPreferences.m index f090c7c6..da9a38d4 100644 --- a/Natives/LauncherPreferences.m +++ b/Natives/LauncherPreferences.m @@ -46,21 +46,21 @@ NSMutableDictionary *getDictionary(NSString *type) { return nil; } -int getSelectedJavaVersion() { - NSString *java = [getPreference(@"java_home") lastPathComponent]; +int getJavaVersion(NSString* java) { if (java.length == 0) { return 0; } else if ([java hasPrefix:@"java-"] && [java hasSuffix:@"-openjdk"]) { return [java substringWithRange:NSMakeRange(5, java.length - 13)].intValue; - } else if ([java isEqualToString:@"jre"]) { - // TODO for jailbroken: jre8 and jre17 - return 8; } else { NSLog(@"FIXME: What is the Java version of %@?", java); return 0; } } +int getSelectedJavaVersion() { + return getJavaVersion([getPreference(@"java_home") lastPathComponent]); +} + void setDefaultValueForPref(NSMutableDictionary *dict, NSString* key, id value) { if (!dict[key]) { dict[key] = value; diff --git a/Natives/LauncherPreferencesViewController.m b/Natives/LauncherPreferencesViewController.m index a5d76b9c..781b8a06 100644 --- a/Natives/LauncherPreferencesViewController.m +++ b/Natives/LauncherPreferencesViewController.m @@ -84,7 +84,7 @@ UITextField *gdirTextField; UITextField *activeField; NSArray* rendererList; NSMutableArray* gdirList; -NSMutableArray* jhomeList; +NSArray* jhomeList; UIPickerView* rendPickerView; UIPickerView* gdirPickerView; UIPickerView* jhomePickerView; @@ -95,15 +95,12 @@ UIScrollView *scrollView; NSDictionary *rendererDict; -NSString *JRE8_HOME_SB; - int tempIndex; - (void)viewDidLoad { [super viewDidLoad]; - - [self setTitle:@"Preferences"]; + setViewBackgroundColor(self.view); CGRect screenBounds = [[UIScreen mainScreen] bounds]; CGFloat screenScale = [[UIScreen mainScreen] scale]; @@ -111,14 +108,7 @@ int tempIndex; int width = (int) roundf(screenBounds.size.width); int height = (int) roundf(screenBounds.size.height) - self.navigationController.navigationBar.frame.size.height; CGFloat currY = 8.0; -/* - javaDict = @{ - @"/usr/lib/jvm/java-8-openjdk": @"Java 8", - @"/usr/lib/jvm/java-16-openjdk": @"Java 16", - @"/usr/lib/jvm/java-17-openjdk": @"Java 17", - [NSString stringWithFormat:@"%s/jre8", getenv("POJAV_HOME")], @"Java 8 (sandbox)" - }; -*/ + rendererDict = @{ @"gl4es 1.1.4 - exports OpenGL 2.1": @"libgl4es_114.dylib", @"tinygl4angle (1.17+) - exports OpenGL 3.2 (Core Profile, limited)": @"libtinygl4angle.dylib", @@ -137,13 +127,6 @@ int tempIndex; blur = [UIBlurEffect effectWithStyle:UIBlurEffectStyleRegular]; blurView = [[UIVisualEffectView alloc] initWithEffect:blur]; - - // Update color mode once - if(@available(iOS 13.0, *)) { - [self traitCollectionDidChange:nil]; - } else { - self.view.backgroundColor = [UIColor whiteColor]; - } UILabel *btnsizeTextView = [[UILabel alloc] initWithFrame:CGRectMake(16.0, currY, 0.0, 30.0)]; btnsizeTextView.text = @"Button scale (%)"; @@ -219,8 +202,7 @@ int tempIndex; jargsTextField.delegate = self; jargsTextField.placeholder = @"Specify arguments..."; jargsTextField.text = (NSString *) getPreference(@"java_args"); - jargsTextField.autocorrectionType = UITextAutocorrectionTypeNo -; + jargsTextField.autocorrectionType = UITextAutocorrectionTypeNo; jargsTextField.contentVerticalAlignment = UIControlContentVerticalAlignmentTop; jargsTextField.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft; [tableView addSubview:jargsTextField]; @@ -234,6 +216,7 @@ int tempIndex; rendTextField = [[UITextField alloc] initWithFrame:CGRectMake(buttonSizeSlider.frame.origin.x + 3, currY, width - jargsTextView.bounds.size.width - 28.0, 30)]; [rendTextField addTarget:rendTextField action:@selector(resignFirstResponder) forControlEvents:UIControlEventEditingDidEndOnExit]; rendTextField.tag = TAG_REND; + rendTextField.autocorrectionType = UITextAutocorrectionTypeNo; rendTextField.delegate = self; rendTextField.placeholder = @"Override renderer..."; //rendTextField.text = self.rendererDict[getPreference(@"renderer")]; @@ -270,45 +253,26 @@ int tempIndex; jhomeTextField = [[UITextField alloc] initWithFrame:CGRectMake(buttonSizeSlider.frame.origin.x + 3, currY, width - jargsTextView.bounds.size.width - 28.0, 30)]; [jhomeTextField addTarget:jhomeTextField action:@selector(resignFirstResponder) forControlEvents:UIControlEventEditingDidEndOnExit]; jhomeTextField.tag = TAG_JHOME; + jhomeTextField.autocorrectionType = UITextAutocorrectionTypeNo; jhomeTextField.delegate = self; jhomeTextField.placeholder = @"Override Java path..."; - JRE8_HOME_SB = [NSString stringWithFormat:@"%s/jre8", getenv("POJAV_HOME")]; - if(getenv("POJAV_DETECTEDJB")) { - switch (getSelectedJavaVersion()) { - case 8: jhomeTextField.text = JRE8_NAME_JB; break; - case 16: jhomeTextField.text = JRE16_NAME_JB; break; - case 17: jhomeTextField.text = JRE17_NAME_JB; break; - } - } else { - jhomeTextField.text = JRE8_NAME_SB; - } - + jhomeTextField.text = [getPreference(@"java_home") lastPathComponent]; + jhomeTextField.contentVerticalAlignment = UIControlContentVerticalAlignmentTop; jhomeTextField.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft; [tableView addSubview:jhomeTextField]; - - jhomeList = [[NSMutableArray alloc] init]; - if ([[NSFileManager defaultManager] fileExistsAtPath:JRE8_HOME_JB]) { - [jhomeList addObject:JRE8_NAME_JB]; - } - if ([[NSFileManager defaultManager] fileExistsAtPath:JRE16_HOME_JB]) { - [jhomeList addObject:JRE16_NAME_JB]; - } - if ([[NSFileManager defaultManager] fileExistsAtPath:JRE17_HOME_JB]) { - [jhomeList addObject:JRE17_NAME_JB]; - } - if ([[NSFileManager defaultManager] fileExistsAtPath:JRE8_HOME_SB]) { - [jhomeList addObject:JRE8_NAME_SB]; - } - + + NSString *listPath = getenv("POJAV_DETECTEDJB") ? @"/usr/lib/jvm" : [NSString stringWithFormat:@"%s/jvm", getenv("BUNDLE_PATH")]; + jhomeList = [NSFileManager.defaultManager contentsOfDirectoryAtPath:listPath error:nil]; + jhomePickerView = [[UIPickerView alloc] init]; jhomePickerView.delegate = self; jhomePickerView.dataSource = self; jhomePickerView.tag = TAG_PICKER_JHOME; [jhomePickerView reloadAllComponents]; for (int i = 0; i < jhomeList.count; i++) { - if ([jhomeList[i] isEqualToString:jhomeTextField.text]) { + if ([jhomeTextField.text isEqualToString:jhomeList[i]]) { [jhomePickerView selectRow:i inComponent:0 animated:NO]; break; } @@ -616,24 +580,14 @@ int tempIndex; - (void)textFieldDidEndEditing:(UITextField *)textField { activeField = nil; if (textField.tag == TAG_JARGS) { - setPreference(@"java_args", textField.text); + setPreference(@"java_args", textField.text); } else if (textField.tag == TAG_REND) { setPreference(@"renderer", rendererDict[textField.text]); setenv("POJAV_RENDERER", [getPreference(@"renderer") UTF8String], 1); } else if (textField.tag == TAG_JHOME) { - if ([textField.text isEqualToString:JRE8_NAME_JB]) { - setPreference(@"java_home", JRE8_HOME_JB); - setenv("JAVA_HOME", [JRE8_HOME_JB cStringUsingEncoding:NSUTF8StringEncoding], 1); - } else if ([textField.text isEqualToString:JRE16_NAME_JB]) { - setPreference(@"java_home", JRE16_HOME_JB); - setenv("JAVA_HOME", [JRE16_HOME_JB cStringUsingEncoding:NSUTF8StringEncoding], 1); - } else if ([textField.text isEqualToString:JRE17_NAME_JB]) { - setPreference(@"java_home", JRE17_HOME_JB); - setenv("JAVA_HOME", [JRE17_HOME_JB cStringUsingEncoding:NSUTF8StringEncoding], 1); - } else if ([textField.text isEqualToString:JRE8_NAME_SB]) { - setPreference(@"java_home", JRE8_HOME_SB); - setenv("JAVA_HOME", [JRE8_HOME_SB cStringUsingEncoding:NSUTF8StringEncoding], 1); - } + NSString *listPath = getenv("POJAV_DETECTEDJB") ? @"/usr/lib/jvm" : [NSString stringWithFormat:@"%s/jvm", getenv("BUNDLE_PATH")]; + setPreference(@"java_home", [NSString stringWithFormat:@"%@/%@", listPath, textField.text]); + setenv("JAVA_HOME", [getPreference(@"java_home") UTF8String], 1); if (![textField.text containsString:JRE8_NAME_JB] && ![textField.text containsString:JRE8_NAME_SB] && [getPreference(@"java_warn") boolValue] == YES) { UIAlertController *javaAlert = [UIAlertController alertControllerWithTitle:@"Java version is not Java 8" message:@"Minecraft versions below 1.6, modded below 1.16.4, and the mod installer will not work unless you have Java 8 installed on your device." preferredStyle:UIAlertControllerStyleAlert]; UIAlertAction *ok = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:nil]; @@ -1018,16 +972,6 @@ int tempIndex; } } --(void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection { - if(@available(iOS 13.0, *)) { - if (UITraitCollection.currentTraitCollection.userInterfaceStyle == UIUserInterfaceStyleDark) { - self.view.backgroundColor = [UIColor blackColor]; - } else { - self.view.backgroundColor = [UIColor whiteColor]; - } - } -} - #pragma mark - UIPopoverPresentationControllerDelegate - (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller traitCollection:(UITraitCollection *)traitCollection { return UIModalPresentationNone; diff --git a/Natives/LauncherSplitViewController.h b/Natives/LauncherSplitViewController.h new file mode 100644 index 00000000..19515fcf --- /dev/null +++ b/Natives/LauncherSplitViewController.h @@ -0,0 +1,5 @@ +#import + +@interface LauncherSplitViewController : UISplitViewController + +@end diff --git a/Natives/LauncherSplitViewController.m b/Natives/LauncherSplitViewController.m new file mode 100644 index 00000000..f27c3a66 --- /dev/null +++ b/Natives/LauncherSplitViewController.m @@ -0,0 +1,42 @@ +#import "LauncherSplitViewController.h" +#import "LauncherMenuViewController.h" +#import "LauncherViewController.h" +#import "utils.h" + +@interface LauncherSplitViewController () { +} + +@end + +@implementation LauncherSplitViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + viewController = self; + setViewBackgroundColor(self.view); + + //TODO: maximumPrimaryColumnWidth + + LauncherMenuViewController *masterVc = [[LauncherMenuViewController alloc] init]; + UINavigationController *detailVc = [[UINavigationController alloc] init]; + + self.presentsWithGesture = YES; + self.preferredDisplayMode = UISplitViewControllerDisplayModeOneBesideSecondary; + self.viewControllers = @[[[UINavigationController alloc] initWithRootViewController:masterVc], detailVc]; + if (@available(iOS 14.0, tvOS 14.0, *)) { + self.preferredSplitBehavior = UISplitViewControllerSplitBehaviorTile; + } +} + +- (UITraitCollection *)traitCollection { + // Allows splitting on compact-sized iPhones + UITraitCollection *collection = super.traitCollection; + UITraitCollection *horizontalCollection = [UITraitCollection traitCollectionWithHorizontalSizeClass:UIUserInterfaceSizeClassRegular]; + return [UITraitCollection traitCollectionWithTraitsFromCollections:@[collection, horizontalCollection]]; +} + +- (void)dismissViewController { + [self dismissViewControllerAnimated:YES completion:nil]; +} + +@end diff --git a/Natives/LauncherViewController.m b/Natives/LauncherViewController.m index 8c538980..330134a7 100644 --- a/Natives/LauncherViewController.m +++ b/Natives/LauncherViewController.m @@ -28,8 +28,6 @@ int versionSelectedAt = 0; [[UIApplication sharedApplication] setIdleTimerDisabled:YES]; [self setNeedsUpdateOfScreenEdgesDeferringSystemGestures]; [self setNeedsUpdateOfHomeIndicatorAutoHidden]; - - [self setTitle:@"PojavLauncher"]; CGRect screenBounds = [[UIScreen mainScreen] bounds]; CGFloat screenScale = [[UIScreen mainScreen] scale]; @@ -41,13 +39,6 @@ int versionSelectedAt = 0; [self.view addSubview:scrollView]; scrollView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; - // Update color mode once - if(@available(iOS 13.0, *)) { - [self traitCollectionDidChange:nil]; - } else { - self.view.backgroundColor = [UIColor whiteColor]; - } - UILabel *versionTextView = [[UILabel alloc] initWithFrame:CGRectMake(4.0, 4.0, 0.0, 0.0)]; versionTextView.text = @"Minecraft version: "; versionTextView.numberOfLines = 0; @@ -82,10 +73,8 @@ int versionSelectedAt = 0; handler:^(__kindof UIAction * _Nonnull action) {[self enterModInstaller:self.navigationItem.rightBarButtonItem];}]; UIAction *option2 = [UIAction actionWithTitle:@"Custom controls" image:[[UIImage systemImageNamed:@"dpad.right.fill"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] identifier:nil handler:^(__kindof UIAction * _Nonnull action) {[self enterCustomControls];}]; - UIAction *option3 = [UIAction actionWithTitle:@"Preferences" image:[[UIImage systemImageNamed:@"wrench.and.screwdriver"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] identifier:nil - handler:^(__kindof UIAction * _Nonnull action) {[self enterPreferences];}]; UIMenu *menu = [UIMenu menuWithTitle:@"" image:nil identifier:nil - options:UIMenuOptionsDisplayInline children:@[option1, option2, option3]]; + options:UIMenuOptionsDisplayInline children:@[option1, option2]]; self.navigationItem.rightBarButtonItem.action = nil; self.navigationItem.rightBarButtonItem.primaryAction = nil; self.navigationItem.rightBarButtonItem.menu = menu; @@ -201,20 +190,18 @@ int versionSelectedAt = 0; handler:^(UIAlertAction * _Nonnull action) {[self enterModInstaller:self.navigationItem.rightBarButtonItem];}]; UIAlertAction *option2 = [UIAlertAction actionWithTitle:@"Custom controls" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {[self enterCustomControls];}]; - UIAlertAction *option3 = [UIAlertAction actionWithTitle:@"Preferences" style:UIAlertActionStyleDefault - handler:^(UIAlertAction * _Nonnull action) {[self enterPreferences];}]; fullAlert.popoverPresentationController.barButtonItem = sender; [self presentViewController:fullAlert animated:YES completion:nil]; [fullAlert addAction:option1]; [fullAlert addAction:option2]; - [fullAlert addAction:option3]; } } - (void)enterCustomControls { if (![getPreference(@"customctrl_warn") boolValue]) { CustomControlsViewController *vc = [[CustomControlsViewController alloc] init]; - [self.navigationController pushViewController:vc animated:YES]; + vc.modalPresentationStyle = UIModalPresentationOverFullScreen; + [self presentViewController:vc animated:YES completion:nil]; return; } setPreference(@"customctrl_warn", @(NO)); @@ -224,8 +211,7 @@ int versionSelectedAt = 0; alert.popoverPresentationController.sourceRect = CGRectMake(self.view.frame.size.width-10.0, 0, 10, 10); } UIAlertAction *ok = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) { - CustomControlsViewController *vc = [[CustomControlsViewController alloc] init]; - [self.navigationController pushViewController:vc animated:YES]; + [self enterCustomControls]; }]; [self presentViewController:alert animated:YES completion:nil]; [alert addAction:ok]; @@ -255,20 +241,15 @@ int versionSelectedAt = 0; - (void)documentPicker:(UIDocumentPickerViewController *)controller didPickDocumentAtURL:(NSURL *)url { if (controller.documentPickerMode == UIDocumentPickerModeImport) { JavaGUIViewController *vc = [[JavaGUIViewController alloc] init]; + vc.modalPresentationStyle = UIModalPresentationFullScreen; vc.filepath = url.path; NSLog(@"ModInstaller: launching %@", vc.filepath); - [self.navigationController pushViewController:vc animated:YES]; + [self presentViewController:vc animated:YES completion:nil]; } } -- (void)enterPreferences { - LauncherPreferencesViewController *vc = [[LauncherPreferencesViewController alloc] init]; - [self.navigationController pushViewController:vc animated:YES]; -} - - (void)launchMinecraft:(UIButton *)sender { sender.enabled = NO; - [self.navigationItem setHidesBackButton:YES animated:YES]; NSObject *object = [versionList objectAtIndex:[versionPickerView selectedRowInComponent:0]]; @@ -282,7 +263,6 @@ int versionSelectedAt = 0; = progress; if (stage == nil) { sender.enabled = YES; - [self.navigationItem setHidesBackButton:NO animated:YES]; if (mainProgress != nil) { UIKit_launchMinecraftSurfaceVC(); } @@ -335,14 +315,4 @@ int versionSelectedAt = 0; return NO; } -- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection { - if(@available(iOS 13.0, *)) { - if (UITraitCollection.currentTraitCollection.userInterfaceStyle == UIUserInterfaceStyleDark) { - self.view.backgroundColor = [UIColor blackColor]; - } else { - self.view.backgroundColor = [UIColor whiteColor]; - } - } -} - @end diff --git a/Natives/LoginViewController.m b/Natives/LoginViewController.m index 418baea8..b7bde543 100644 --- a/Natives/LoginViewController.m +++ b/Natives/LoginViewController.m @@ -2,27 +2,26 @@ #include #import - #import "authenticator/BaseAuthenticator.h" #import "AppDelegate.h" -#import "LauncherViewController.h" -#import "LoginViewController.h" #import "AboutLauncherViewController.h" #import "AccountListViewController.h" #import "LauncherFAQViewController.h" -#import "LauncherPreferences.h" +#import "LauncherSplitViewController.h" +#import "LoginViewController.h" #import "UpdateHistoryViewController.h" -#include "ios_uikit_bridge.h" -#include "utils.h" +#import "LauncherPreferences.h" +#import "ios_uikit_bridge.h" +#import "utils.h" #define TYPE_SELECTACC 0 #define TYPE_MICROSOFT 1 #define TYPE_OFFLINE 2 #pragma mark - LoginViewController -@interface LoginViewController () { +@interface LoginViewController () { } @property (nonatomic, strong) ASWebAuthenticationSession *authVC; @property (nonatomic, strong) UIActivityViewController *activityViewController; @@ -34,12 +33,10 @@ - (void)viewDidLoad { [super viewDidLoad]; + setViewBackgroundColor(self.view); [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(msaLoginCallback:) name:@"MSALoginCallback" object:nil]; - UIBarButtonItem *backItem = [[UIBarButtonItem alloc] initWithTitle:@"Back" style:UIBarButtonItemStylePlain target:nil action:nil]; - [self.navigationItem setBackBarButtonItem:backItem]; - CGRect screenBounds = [[UIScreen mainScreen] bounds]; int width = (int) roundf(screenBounds.size.width); @@ -50,12 +47,6 @@ scrollView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; [self.view addSubview:scrollView]; - if(@available(iOS 13.0, *)) { - [self traitCollectionDidChange:nil]; - } else { - self.view.backgroundColor = [UIColor whiteColor]; - } - if(getenv("POJAV_DETECTEDJB")) { if(strcmp(getenv("POJAV_DETECTEDJB"), "Other") == 0 && [getPreference(@"jb_warn") boolValue] == YES) { UIAlertController *jbAlert = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"login.warn.title.otherjb", nil) message:NSLocalizedString(@"login.warn.message.otherjb", nil) preferredStyle:UIAlertControllerStyleAlert]; @@ -85,7 +76,7 @@ [dateFormatter setDateFormat:@"MM-dd"]; NSString* date = [dateFormatter stringFromDate:[NSDate date]]; - if(@available (iOS 14.0, *)) { + if(@available(iOS 14.0, *)) { self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithImage:[[UIImage systemImageNamed:@"info.circle"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] style:UIBarButtonItemStyleDone target:self action:@selector(aboutLauncher)]; UIAction *option1 = [UIAction actionWithTitle:NSLocalizedString(@"login.menu.about", nil) image:[[UIImage systemImageNamed:@"eyes.inverse"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] identifier:nil handler:^(__kindof UIAction * _Nonnull action) {[self aboutLauncher];}]; @@ -191,16 +182,6 @@ } } -- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection { - if (@available(iOS 13.0, *)) { - if (UITraitCollection.currentTraitCollection.userInterfaceStyle == UIUserInterfaceStyleDark) { - self.view.backgroundColor = [UIColor blackColor]; - } else { - self.view.backgroundColor = [UIColor whiteColor]; - } - } -} - - (void)displayProgress:(NSString *)title { self.title = title; UIActivityIndicatorViewStyle style; @@ -260,10 +241,16 @@ id callback = ^(BOOL success) { self.title = @""; self.navigationItem.leftBarButtonItem = nil; - if (success) { - LauncherViewController *vc = [[LauncherViewController alloc] init]; - [self.navigationController pushViewController:vc animated:YES]; + if (!success) return; + + LauncherSplitViewController *splitVc; + if (@available(iOS 14.0, tvOS 14.0, *)) { + splitVc = [[LauncherSplitViewController alloc] initWithStyle:UISplitViewControllerStyleDoubleColumn]; + } else { + splitVc = [[LauncherSplitViewController alloc] init]; } + splitVc.modalPresentationStyle = UIModalPresentationFullScreen; + [self presentViewController:splitVc animated:YES completion:nil]; }; if (type == TYPE_SELECTACC) { [auth refreshTokenWithCallback:callback]; @@ -376,7 +363,7 @@ UIPopoverPresentationController *popoverController = [vc popoverPresentationController]; [self setPopoverProperties:popoverController sender:sender]; popoverController.permittedArrowDirections = UIPopoverArrowDirectionAny; - popoverController.delegate = self; + popoverController.delegate = vc; [self presentViewController:vc animated:YES completion:nil]; } @@ -413,11 +400,6 @@ } } -#pragma mark - UIPopoverPresentationControllerDelegate -- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller traitCollection:(UITraitCollection *)traitCollection { - return UIModalPresentationNone; -} - #pragma mark - ASWebAuthenticationPresentationContextProviding - (ASPresentationAnchor)presentationAnchorForWebAuthenticationSession:(ASWebAuthenticationSession *)session API_AVAILABLE(ios(13.0)){ return UIApplication.sharedApplication.windows.firstObject; diff --git a/Natives/MinecraftResourceUtils.m b/Natives/MinecraftResourceUtils.m index 743245de..dd2d5bc4 100644 --- a/Natives/MinecraftResourceUtils.m +++ b/Natives/MinecraftResourceUtils.m @@ -39,14 +39,11 @@ static AFURLSessionManager* manager; // Check if the account has permission to download + (BOOL)checkAccessWithDialog:(BOOL)show { // for now - if ([BaseAuthenticator.current.authData[@"username"] hasPrefix:@"Demo."] || BaseAuthenticator.current.authData[@"xboxGamertag"] != nil) { - return YES; - } else { - if (show) { - showDialog(viewController, @"Error", @"Minecraft can't be legally installed when logged in with a local account. Please switch to an online account to continue."); - } - return NO; + BOOL accessible = [BaseAuthenticator.current.authData[@"username"] hasPrefix:@"Demo."] || BaseAuthenticator.current.authData[@"xboxGamertag"] != nil; + if (!accessible && show) { + showDialog(viewController, @"Error", @"Minecraft can't be legally installed when logged in with a local account. Please switch to an online account to continue."); } + return accessible; } // Check SHA of the file diff --git a/Natives/SceneDelegate.m b/Natives/SceneDelegate.m index 032fecf9..e4c7bce9 100644 --- a/Natives/SceneDelegate.m +++ b/Natives/SceneDelegate.m @@ -16,7 +16,6 @@ - (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions API_AVAILABLE(ios(13.0)) API_AVAILABLE(ios(13.0)) API_AVAILABLE(ios(13.0)){ - if (@available(iOS 13.0, *)) { UIWindowScene *windowScene = (UIWindowScene *)scene; self.window = [[UIWindow alloc] initWithWindowScene:windowScene]; diff --git a/Natives/SurfaceViewController.m b/Natives/SurfaceViewController.m index 60d5adfe..a9a47947 100644 --- a/Natives/SurfaceViewController.m +++ b/Natives/SurfaceViewController.m @@ -26,10 +26,6 @@ // #define DEBUG_VISIBLE_TEXT_FIELD // #define DEBUG_VISIBLE_TOUCH -#define INPUT_SPACE_CHAR @" " -#define INPUT_FULL_LENGTH 40 -#define INPUT_SPACE_LENGTH 20 - #ifdef DEBUG_VISIBLE_TEXT_FIELD UILabel *inputLengthView; #endif @@ -41,30 +37,141 @@ BOOL slideableHotbar; // TODO: key modifiers impl +// There are private functions that we are unable to find public replacements +// (Both are found by placing breakpoints) +@interface UITextField(private) +- (NSRange)insertFilteredText:(NSString *)text; +- (id) replaceRangeWithTextWithoutClosingTyping:(UITextRange *)range replacementText:(NSString *)text; +@end + + #pragma mark Class TrackedTextField @interface TrackedTextField : UITextField -@property int lastPosition; -@property UITextPosition* lockPos; +@property int lastTextPos; +@property CGFloat lastPointX; @end @implementation TrackedTextField + +- (void)sendMultiBackspaces:(int)times { + for (int i = 0; i < times; i++) { + CallbackBridge_nativeSendKey(GLFW_KEY_BACKSPACE, 0, 1, 0); + CallbackBridge_nativeSendKey(GLFW_KEY_BACKSPACE, 0, 0, 0); + } +} + +- (void)sendText:(NSString *)text { + for (int i = 0; i < text.length; i++) { + // Directly convert unichar to jchar since both are in UTF-16 encoding. + jchar theChar = (jchar) [text characterAtIndex:i]; + if (isUseStackQueueCall) { + CallbackBridge_nativeSendCharMods(theChar, 0); + } else { + CallbackBridge_nativeSendChar(theChar); + } +#ifdef DEBUG_VISIBLE_TEXT_FIELD + inputLengthView.text = [NSString stringWithFormat:@"length=%lu", self.text.length]; +#endif + } +} + +- (void)beginFloatingCursorAtPoint:(CGPoint)point { + [super beginFloatingCursorAtPoint:point]; + self.lastPointX = point.x; +} + +// Handle cursor movement in the empty space +- (void)updateFloatingCursorAtPoint:(CGPoint)point { + [super updateFloatingCursorAtPoint:point]; + + if (self.lastPointX == 0 || (self.lastTextPos > 0 && self.lastTextPos < self.text.length)) { + // This is handled in -[TrackedTextField closestPositionToPoint:] + return; + } + +#ifdef DEBUG_VISIBLE_TEXT_FIELD + inputLengthView.text = [NSString stringWithFormat:@"updateFloatingCursorAtPoint lastPointX=%f, lastTextPos=%d\n", self.lastPointX, self.lastTextPos]; +#endif + + CGFloat diff = point.x - self.lastPointX; + if (ABS(diff) < 8) { + return; + } + self.lastPointX = point.x; + + int key = (diff > 0) ? GLFW_KEY_DPAD_RIGHT : GLFW_KEY_DPAD_LEFT; + CallbackBridge_nativeSendKey(key, 0, 1, 0); + CallbackBridge_nativeSendKey(key, 0, 0, 0); +} + +- (void)endFloatingCursor { + [super endFloatingCursor]; + self.lastPointX = 0; +} + - (UITextPosition *)closestPositionToPoint:(CGPoint)point { + // Handle cursor movement between characters UITextPosition *position = [super closestPositionToPoint:point]; int start = [self offsetFromPosition:self.beginningOfDocument toPosition:position]; - if (start - self.lastPosition != 0) { - int key = (start - self.lastPosition > 0) ? GLFW_KEY_DPAD_RIGHT : GLFW_KEY_DPAD_LEFT; + if (start - self.lastTextPos != 0) { + int key = (start - self.lastTextPos > 0) ? GLFW_KEY_DPAD_RIGHT : GLFW_KEY_DPAD_LEFT; CallbackBridge_nativeSendKey(key, 0, 1, 0); CallbackBridge_nativeSendKey(key, 0, 0, 0); } - self.lastPosition = start; - return [self positionFromPosition:self.beginningOfDocument offset:clamp(start, 20, self.text.length - 20)]; + self.lastTextPos = start; + return position; } -- (void)setText:(NSString *)text { - [super setText:text]; - self.lockPos = [self positionFromPosition:self.beginningOfDocument offset:20]; - self.selectedTextRange = [self textRangeFromPosition:self.lockPos toPosition:self.lockPos]; +- (void)deleteBackward { + if (self.text.length > 1) { + // Keep the first character (a space) + [super deleteBackward]; + } else { + self.text = @" "; + } + self.lastTextPos = [super offsetFromPosition:self.beginningOfDocument toPosition:self.selectedTextRange.start]; + + [self sendMultiBackspaces:1]; } + +- (BOOL)hasText { + self.lastTextPos = MAX(self.lastTextPos, 1); + return YES; +} + +// Old name: insertText +- (NSRange)insertFilteredText:(NSString *)text { + int cursorPos = [super offsetFromPosition:self.beginningOfDocument toPosition:self.selectedTextRange.start]; + + // This also makes sure that lastTextPos != cursorPos (text should never be empty) + if (self.lastTextPos - cursorPos == text.length) { + // Handle text markup by first deleting N amount of characters equal to the replaced text + [self sendMultiBackspaces:text.length]; + } + // What else is done by past-autocomplete (insert a space after autocompletion) + // See -[TrackedTextField replaceRangeWithTextWithoutClosingTyping:replacementText:] + + self.lastTextPos = cursorPos + text.length; + + [self sendText:text]; + + NSRange range = [super insertFilteredText:text]; + return range; +} + +- (id) replaceRangeWithTextWithoutClosingTyping:(UITextRange *)range replacementText:(NSString *)text +{ + int length = [super offsetFromPosition:range.start toPosition:range.end]; + + // Delete the range of needs for autocompletion + [self sendMultiBackspaces:length]; + + // Insert the autocompleted text + [self sendText:text]; + + return [super replaceRangeWithTextWithoutClosingTyping:range replacementText:text]; +} + @end @@ -113,8 +220,6 @@ BOOL slideableHotbar; CGRect screenBounds = [[UIScreen mainScreen] bounds]; CGFloat screenScale = [[UIScreen mainScreen] scale]; - UIEdgeInsets insets = UIApplication.sharedApplication.windows.firstObject.safeAreaInsets; - resolutionScale = ((NSNumber *)getPreference(@"resolution")).floatValue / 100.0; slideableHotbar = [getPreference(@"slideable_hotbar") boolValue]; @@ -222,22 +327,21 @@ self.view.frame.size.width * 0.3 - 36.0 * 0.7, self.view.frame.size.height)]; self.mousePointerView.userInteractionEnabled = NO; [self.rootView addSubview:self.mousePointerView]; -#ifndef DEBUG_VISIBLE_TEXT_FIELD - self.inputView = [[TrackedTextField alloc] initWithFrame:CGRectMake(0, -1, 1, 1)]; -#else - self.inputView = [[TrackedTextField alloc] initWithFrame:CGRectMake(5 * 2 + 160.0, 5 * 2 + 30.0, 200.0, 30.0)]; - self.inputView.backgroundColor = [UIColor colorWithWhite:0.0f alpha:0.5f]; - self.inputView.font = [self.inputView.font fontWithSize:20]; - - inputLengthView = [[UILabel alloc] initWithFrame:CGRectMake(5 * 2 + 80.0, 5 * 2 + 30.0, 80.0, 30.0)]; + self.inputView = [[TrackedTextField alloc] initWithFrame:CGRectMake(0, -32.0, self.view.frame.size.width, 30.0)]; +#ifdef DEBUG_VISIBLE_TEXT_FIELD + inputLengthView = [[UILabel alloc] initWithFrame:CGRectMake(0, -62.0, self.view.frame.size.width, 30.0)]; inputLengthView.text = @"length=?"; inputLengthView.backgroundColor = [UIColor colorWithWhite:1.0f alpha:0.6f]; [self.rootView addSubview:inputLengthView]; #endif - //self.inputView.autocorrectionType = UITextAutocorrectionTypeNo; - self.inputView.delegate = self; - self.inputView.lastPosition = 20; - [self.inputView addTarget:self action:@selector(inputViewDidChange) forControlEvents:UIControlEventEditingChanged]; + if (@available(iOS 13.0, *)) { + self.inputView.backgroundColor = UIColor.secondarySystemBackgroundColor; + } else { + self.inputView.backgroundColor = UIColor.groupTableViewBackgroundColor; + } + self.inputView.font = [UIFont fontWithName:@"Menlo-Regular" size:20]; + self.inputView.clearsOnBeginEditing = YES; + self.inputView.textAlignment = NSTextAlignmentCenter; NSString *controlFilePath = [NSString stringWithFormat:@"%s/controlmap/%@", getenv("POJAV_HOME"), (NSString *)getPreference(@"default_ctrl")]; @@ -364,6 +468,9 @@ CGPoint lastCenterPoint; self.rootView.transform = CGAffineTransformScale(CGAffineTransformIdentity, scale, scale); self.menuView.frame = CGRectMake(self.rootView.frame.size.width, self.rootView.frame.origin.y, self.menuView.frame.size.width, self.menuView.frame.size.height); + // scale is in range of 0.7-1 + // 1.1 - scale produces in range of 0.4-0.1 + // result in transform scale range of 1-0.25 self.menuView.transform = CGAffineTransformScale(CGAffineTransformIdentity, (1.1-scale)*2.5, (1.1-scale)*2.5); } else { CGPoint velocity = [sender velocityInView:sender.view]; @@ -372,6 +479,7 @@ CGPoint lastCenterPoint; // calculate duration to produce smooth movement // FIXME: any better way? CGFloat duration = fabs(self.rootView.center.x - centerX * scale) / centerX + 0.1; + duration = MIN(0.4, duration); //(110 - MIN(100, fabs(velocity.x))) / 100 [UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionCurveEaseOut @@ -602,7 +710,6 @@ CGPoint lastCenterPoint; if (sender.state == UIGestureRecognizerStateRecognized) { if (currentHotbarSlot == -1) { - self.inputView.text = INPUT_SPACE_CHAR; inputTextLength = 0; CallbackBridge_nativeSendMouseButton( @@ -631,9 +738,7 @@ CGPoint lastCenterPoint; - (void)surfaceOnHover:(UIHoverGestureRecognizer *)sender API_AVAILABLE(ios(13.0)) { if (@available(iOS 13.0, *)) { if (@available(iOS 14.0, *)) { - if(isGrabbing) { // Can't put into above if statement - return; - } + if (isGrabbing) return; } CGPoint point = [sender locationInView:self.rootView]; // NSLog(@"Mouse move!!"); @@ -666,7 +771,6 @@ CGPoint lastCenterPoint; if (sender.state == UIGestureRecognizerStateBegan) { self.shouldTriggerClick = NO; if (currentHotbarSlot == -1) { - self.inputView.text = INPUT_SPACE_CHAR; inputTextLength = 0; CallbackBridge_nativeSendMouseButton(GLFW_MOUSE_BUTTON_LEFT, 1, 0); @@ -681,9 +785,6 @@ CGPoint lastCenterPoint; || sender.state == UIGestureRecognizerStateEnded) { if (currentHotbarSlot == -1) { - self.inputView.text = INPUT_SPACE_CHAR; - inputTextLength = 0; - CallbackBridge_nativeSendMouseButton(GLFW_MOUSE_BUTTON_LEFT, 0, 0); } else { @@ -718,90 +819,6 @@ CallbackBridge_nativeSendKey(GLFW_KEY_Q, 0, 0, 0); #pragma mark - Input view stuff -NSString* inputStringBefore; -int inputStringLength = INPUT_FULL_LENGTH; --(void)inputViewDidChange { - int typedLength = (int)self.inputView.text.length - inputStringLength; - if (typedLength < 0) { - for (int i = 0; i < -typedLength; i++) { - if (self.inputView.text.length < INPUT_FULL_LENGTH) { - self.inputView.text = [@" " stringByAppendingString:self.inputView.text]; - } - CallbackBridge_nativeSendKey(GLFW_KEY_BACKSPACE, 0, 1, 0); - CallbackBridge_nativeSendKey(GLFW_KEY_BACKSPACE, 0, 0, 0); - if (inputTextLength > 0) { - --inputTextLength; - } - } - -#ifdef DEBUG_VISIBLE_TEXT_FIELD - inputLengthView.text = [@"length=" stringByAppendingFormat:@"%i", - inputTextLength]; -#endif - } else if (typedLength > 0) { - int index = [self.inputView offsetFromPosition:self.inputView.beginningOfDocument toPosition:self.inputView.selectedTextRange.start]; - NSString *newText = [self.inputView.text substringWithRange:NSMakeRange(index - typedLength, typedLength)]; - int charLength = (int) [newText length]; - for (int i = 0; i < charLength; i++) { - // Directly convert unichar to jchar since both are in UTF-16 encoding. - - jchar theChar = (jchar) [newText characterAtIndex:i]; - if (isUseStackQueueCall) { - CallbackBridge_nativeSendCharMods(theChar, /* mods */ 0); - } else { - CallbackBridge_nativeSendChar(theChar); - } - - ++inputTextLength; -#ifdef DEBUG_VISIBLE_TEXT_FIELD - inputLengthView.text = [@"length=" stringByAppendingFormat:@"%i", - inputTextLength]; -#endif - } - inputStringBefore = self.inputView.text; - // [self.inputView.text substringFromIndex:inputTextLength - 1]; - } else { -#ifdef DEBUG_VISIBLE_TEXT_FIELD - NSLog(@"Compare \"%@\" vs \"%@\"", self.inputView.text, inputStringBefore); -#endif - for (int i = 0; i < INPUT_FULL_LENGTH; i++) { - if ([self.inputView.text characterAtIndex:i] != [inputStringBefore characterAtIndex:i]) { - NSString *inputStringNow = [self.inputView.text substringFromIndex:i]; -/* - self.inputView.text = [self.inputView.text substringToIndex:i]; - // self notify - [self inputViewDidChange]; - - self.inputView.text = [self.inputView.text stringByAppendingString:inputStringNow]; - // self notify - [self inputViewDidChange]; -*/ - - for (int i2 = 0; i2 < [inputStringNow length]; i2++) { - CallbackBridge_nativeSendKey(GLFW_KEY_BACKSPACE, 0, 1, 0); - CallbackBridge_nativeSendKey(GLFW_KEY_BACKSPACE, 0, 0, 0); - } - - for (int i2 = 0; i2 < [inputStringNow length]; i2++) { - CallbackBridge_nativeSendCharMods((jchar) [inputStringNow characterAtIndex:i2], /* mods */ 0); - } - - break; - } - } - -#ifdef DEBUG_VISIBLE_TEXT_FIELD - inputLengthView.text = @"length ="; -#endif - inputStringBefore = self.inputView.text; - } - - inputStringLength = (int)self.inputView.text.length; - - // Reset to default value - // self.inputView.text = INPUT_SPACE_CHAR; -} - -(BOOL)textFieldShouldReturn:(UITextField *)textField { CallbackBridge_nativeSendKey(GLFW_KEY_ENTER, 0, 1, 0); CallbackBridge_nativeSendKey(GLFW_KEY_ENTER, 0, 0, 0); @@ -823,16 +840,10 @@ int currentVisibility = 1; if (self.inputView.isFirstResponder) { [self.inputView resignFirstResponder]; self.inputView.alpha = 1.0f; - self.inputView.text = @""; } else { [self.inputView becomeFirstResponder]; - // Empty the input field so that user will no longer able to select text inside. - self.inputView.text = INPUT_SPACE_CHAR; - inputStringLength = INPUT_FULL_LENGTH; - -#ifndef DEBUG_VISIBLE_TEXT_FIELD - self.inputView.alpha = 0.0f; -#endif + // Insert an undeletable space + self.inputView.text = @" "; inputTextLength = 0; } } @@ -864,6 +875,7 @@ int currentVisibility = 1; if (!held) { CallbackBridge_nativeSendScroll(0.0, -1.0); } + break; case SPECIALBTN_VIRTUALMOUSE: if (!isGrabbing && !held) { diff --git a/Natives/UpdateHistoryViewController.m b/Natives/UpdateHistoryViewController.m index b353cc34..d00d898d 100644 --- a/Natives/UpdateHistoryViewController.m +++ b/Natives/UpdateHistoryViewController.m @@ -18,6 +18,7 @@ CGFloat uhcurrY = 4.0; - (void)viewDidLoad { [super viewDidLoad]; + setViewBackgroundColor(self.view); [self setTitle:@"Update History"]; @@ -32,15 +33,8 @@ CGFloat uhcurrY = 4.0; [self.view addSubview:scrollView]; scrollView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; - // Update color mode once - if(@available(iOS 13.0, *)) { - [self traitCollectionDidChange:nil]; - } else { - self.view.backgroundColor = [UIColor whiteColor]; - } - uhcurrY = 4.0; - + [scrollView addSubview:[self uhContent:true size:25 text:@"Current version" width:width]]; [scrollView addSubview:[self uhContent:true size:20 text:[NSString stringWithFormat:@"2.1 (%s)", CONFIG_TYPE] width:width]]; [scrollView addSubview:[self uhContent:true size:17 text:@"Changes" width:width]]; @@ -136,15 +130,4 @@ CGFloat uhcurrY = 4.0; return label; } - --(void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection { - if(@available(iOS 13.0, *)) { - if (UITraitCollection.currentTraitCollection.userInterfaceStyle == UIUserInterfaceStyleDark) { - self.view.backgroundColor = [UIColor blackColor]; - } else { - self.view.backgroundColor = [UIColor whiteColor]; - } - } -} - @end diff --git a/Natives/egl_bridge.m b/Natives/egl_bridge.m index 3690d891..8d813cab 100644 --- a/Natives/egl_bridge.m +++ b/Natives/egl_bridge.m @@ -80,9 +80,6 @@ void* egl_make_current(void* window); int config_renderer; -typedef void gl4esInitialize_func(); -// typedef void gl4esSwapBuffers_func(); -// gl4esSwapBuffers_func *gl4esSwapBuffers; typedef jint RegalMakeCurrent_func(EGLContext context); // Called from JNI_OnLoad of liblwjgl_opengl, TODO: check if unused @@ -381,6 +378,7 @@ void pojavSwapBuffers() { case RENDERER_MTL_ANGLE: { if (!eglSwapBuffers_p(potatoBridge.eglDisplay, potatoBridge.eglSurface)) { if (eglGetError_p() == EGL_BAD_SURFACE) { + NSLog(@"eglSwapBuffers error 0x%x", eglGetError_p()); stopSwapBuffers = true; closeGLFWWindow(); } diff --git a/Natives/ios_uikit_bridge.m b/Natives/ios_uikit_bridge.m index 93d9861a..b748deb6 100644 --- a/Natives/ios_uikit_bridge.m +++ b/Natives/ios_uikit_bridge.m @@ -121,9 +121,19 @@ void UIKit_launchMinecraftSurfaceVC() { usleep(1000); exit(0); } else { - SurfaceViewController *vc = [[SurfaceViewController alloc] init]; - vc.modalPresentationStyle = UIModalPresentationFullScreen; - [viewController.navigationController pushViewController:vc animated:YES]; + id delegate = UIApplication.sharedApplication.delegate; + if (@available(iOS 13.0, *)) { + delegate = UIApplication.sharedApplication.connectedScenes.anyObject.delegate; + } + UIWindow *window = [delegate window]; + [UIView animateWithDuration:0.2 animations:^{ + window.alpha = 0; + } completion:^(BOOL b){ + [window resignKeyWindow]; + window.alpha = 1; + window.rootViewController = [[SurfaceViewController alloc] init]; + [window makeKeyAndVisible]; + }]; } }); } diff --git a/Natives/log.m b/Natives/log.m index 2f33e4c6..8b62e957 100644 --- a/Natives/log.m +++ b/Natives/log.m @@ -17,10 +17,9 @@ void debugLog(const char *message,...) NSLog(@"%@",[[NSString alloc] initWithFormat:[NSString stringWithUTF8String:message] arguments:args]); va_end(args); } else { + static BOOL debugLog_warned = NO; + if (debugLog_warned) return; + debugLog_warned = YES; NSLog(@"WARNING!!! DEBUG LOG DISABLED"); - va_list args; - va_start(args, message); - NSLog(@"%@",[[NSString alloc] initWithFormat:[NSString stringWithUTF8String:message] arguments:args]); - va_end(args); } } diff --git a/Natives/main.m b/Natives/main.m index f60fbdc1..edd7f7ea 100644 --- a/Natives/main.m +++ b/Natives/main.m @@ -141,6 +141,11 @@ void init_redirectStdio() { }); } +void init_setupAccounts() { + NSString *controlPath = [@(getenv("POJAV_HOME")) stringByAppendingPathComponent:@"accounts"]; + [fm createDirectoryAtPath:controlPath withIntermediateDirectories:NO attributes:nil error:nil]; +} + void init_setupCustomControls() { NSString *controlPath = [@(getenv("POJAV_HOME")) stringByAppendingPathComponent:@"controlmap"]; [fm createDirectoryAtPath:controlPath withIntermediateDirectories:NO attributes:nil error:nil]; @@ -178,6 +183,7 @@ void init_setupMultiDir() { [fm createDirectoryAtPath:multidirPath withIntermediateDirectories:YES attributes:nil error:nil]; [fm removeItemAtPath:lasmPath error:nil]; + [fm createDirectoryAtPath:lasmPath.stringByDeletingLastPathComponent withIntermediateDirectories:YES attributes:nil error:nil]; [fm createSymbolicLinkAtPath:lasmPath withDestinationPath:multidirPath error:nil]; setenv("POJAV_GAME_DIR", lasmPath.UTF8String, 1); @@ -230,7 +236,7 @@ int main(int argc, char * argv[]) { loadPreferences(); init_setupMultiDir(); init_setupLauncherProfiles(); - + init_setupAccounts(); init_setupCustomControls(); init_migrateToPlist("selected_version", "config_ver.txt"); diff --git a/Natives/main_hook.m b/Natives/main_hook.m index 56b65b98..00b0dba4 100644 --- a/Natives/main_hook.m +++ b/Natives/main_hook.m @@ -44,6 +44,11 @@ int hooked_dladdr(const void* addr, Dl_info* info) { } void* hooked_dlopen(const char* path, int mode) { + // Avoid loading the executable itself twice + if (path && [@(path) hasSuffix:@"PojavLauncher"]) { + return orig_dlopen(NULL, mode); + } + void *handle = orig_dlopen(path, mode); if (handle) { return handle; diff --git a/Natives/resources/Frameworks/libjnidispatch.dylib.framework/Info.plist b/Natives/resources/Frameworks/libjnidispatch.dylib.framework/Info.plist index 5e115da6..bec2cc7a 100644 --- a/Natives/resources/Frameworks/libjnidispatch.dylib.framework/Info.plist +++ b/Natives/resources/Frameworks/libjnidispatch.dylib.framework/Info.plist @@ -9,7 +9,7 @@ CFBundleIconFile CFBundleIdentifier - + dylib.java.libjnidispatch CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType diff --git a/Natives/resources/Frameworks/libvirgl_test_server.dylib.framework/Info.plist b/Natives/resources/Frameworks/libvirgl_test_server.dylib.framework/Info.plist index ca9f1a9c..290fe10a 100644 --- a/Natives/resources/Frameworks/libvirgl_test_server.dylib.framework/Info.plist +++ b/Natives/resources/Frameworks/libvirgl_test_server.dylib.framework/Info.plist @@ -9,7 +9,7 @@ CFBundleIconFile CFBundleIdentifier - + dylib.mesa3d.libvirgl_test_server CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType diff --git a/Natives/utils.h b/Natives/utils.h index a2bf0d9e..941fd5fd 100644 --- a/Natives/utils.h +++ b/Natives/utils.h @@ -64,6 +64,7 @@ CGFloat MathUtils_dist(CGFloat x1, CGFloat y1, CGFloat x2, CGFloat y2); CGFloat MathUtils_map(CGFloat x, CGFloat in_min, CGFloat in_max, CGFloat out_min, CGFloat out_max); CGFloat dpToPx(CGFloat dp); CGFloat pxToDp(CGFloat px); +void setViewBackgroundColor(UIView* view); void _CGDataProviderReleaseBytePointerCallback(void *info,const void *pointer); jboolean attachThread(bool isAndroid, JNIEnv** secondJNIEnvPtr); diff --git a/Natives/utils.m b/Natives/utils.m index dd81a401..0649d692 100644 --- a/Natives/utils.m +++ b/Natives/utils.m @@ -8,6 +8,13 @@ #include "utils.h" +// This forces the navigation bar to keep its height (44dp) in landscape +@implementation UINavigationBar(forceFullHeightInLandscape) +- (BOOL)forceFullHeightInLandscape { + return YES; +} +@end + NSMutableDictionary* parseJSONFromFile(NSString *path) { NSError *error; @@ -102,6 +109,14 @@ CGFloat pxToDp(CGFloat px) { return px / screenScale; } +void setViewBackgroundColor(UIView* view) { + if(@available(iOS 13.0, *)) { + view.backgroundColor = UIColor.systemBackgroundColor; + } else { + view.backgroundColor = UIColor.whiteColor; + } +} + jstring convertStringJVM(JNIEnv* srcEnv, JNIEnv* dstEnv, jstring srcStr) { if (srcStr == NULL) { return NULL;