diff --git a/JavaApp/src/main/java/net/kdt/pojavlaunch/Tools.java b/JavaApp/src/main/java/net/kdt/pojavlaunch/Tools.java index b28e1ea3..6e6554cd 100644 --- a/JavaApp/src/main/java/net/kdt/pojavlaunch/Tools.java +++ b/JavaApp/src/main/java/net/kdt/pojavlaunch/Tools.java @@ -117,19 +117,19 @@ public final class Tools // URLClassLoader loader = new URLClassLoader(urlList.toArray(new URL[0]), ClassLoader.getSystemClassLoader()); - PojavClassLoader loader = (PojavClassLoader) ClassLoader.getSystemClassLoader(); - - for (String s : launchClassPath.split(":")) { - if (!s.isEmpty()) { - loader.addURL(new File(s).toURI().toURL()); + PojavClassLoader loader = (PojavClassLoader) ClassLoader.getSystemClassLoader(); + + for (String s : launchClassPath.split(":")) { + if (!s.isEmpty()) { + loader.addURL(new File(s).toURI().toURL()); + } } - } Class clazz = loader.loadClass(versionInfo.mainClass); Method method = clazz.getMethod("main", String[].class); method.invoke(null, new Object[]{launchArgs}); - - System.out.println("It went past main(). Should not reach here!"); + + // throw new RuntimeException("Game exited. Check latestlog.txt for more details."); } catch (Throwable th) { showError(th); } diff --git a/JavaApp/src/main/java/net/kdt/pojavlaunch/uikit/UIKit.java b/JavaApp/src/main/java/net/kdt/pojavlaunch/uikit/UIKit.java index a4b05981..441c031e 100644 --- a/JavaApp/src/main/java/net/kdt/pojavlaunch/uikit/UIKit.java +++ b/JavaApp/src/main/java/net/kdt/pojavlaunch/uikit/UIKit.java @@ -1,7 +1,11 @@ package net.kdt.pojavlaunch.uikit; +import java.io.*; +import java.lang.reflect.*; +import java.util.jar.*; +import net.java.openjdk.cacio.ctc.CTCScreen; import net.kdt.pojavlaunch.utils.MCOptionUtils; -import net.kdt.pojavlaunch.PLaunchApp; +import net.kdt.pojavlaunch.*; import org.lwjgl.glfw.*; public class UIKit { @@ -10,6 +14,59 @@ public class UIKit { public static final int ACTION_MOVE = 2; private static int guiScale; + + public static void callback_JavaGUIViewController_launchJarFile(final String filepath, int width, int height) { + System.setProperty("cacio.managed.screensize", width + "x" + height); + + // Thread for refreshing the AWT buffer + new Thread(() -> { + try { + long lastTime = System.currentTimeMillis(); + while (true) { + int[] pixelsArray = null; + try{ + pixelsArray = CTCScreen.getCurrentScreenRGB(); + } catch (NullPointerException e) { + Thread.sleep(500); + } + if (pixelsArray != null) { + //System.out.println(java.util.Arrays.toString(pixelsArray)); + refreshAWTBuffer(pixelsArray); + } + long currentTime = System.currentTimeMillis(); + if (currentTime - lastTime < 16) { + Thread.sleep(16 - (currentTime - lastTime)); + } + lastTime = currentTime; + } + } catch (InterruptedException e) { + e.printStackTrace(); + } + }, "AWTFBRefreshThread").start(); + + // Thread for launching the JAR file + new Thread(() -> { + String mainClassName = null; + try { + JarFile jarfile = new JarFile(filepath); + String mainClass = jarfile.getManifest().getMainAttributes().getValue("Main-Class"); + jarfile.close(); + if (mainClass == null) { + throw new IllegalArgumentException("no main manifest attribute, in \"" + filepath + "\""); + } + + PojavClassLoader loader = (PojavClassLoader) ClassLoader.getSystemClassLoader(); + loader.addURL(new File(filepath).toURI().toURL()); + Class clazz = loader.loadClass(mainClass); + Method method = clazz.getMethod("main", String[].class); + method.invoke(null, new Object[]{new String[]{}}); + + // throw new RuntimeException("Application exited"); + } catch (Throwable th) { + Tools.showError(th, true); + } + }, "ModInstallerThread").start(); + } public static void callback_LauncherViewController_installMinecraft(String versionPath) { PLaunchApp.installMinecraft(versionPath); @@ -73,7 +130,9 @@ public class UIKit { static { System.loadLibrary("pojavexec"); } - + + public static native void refreshAWTBuffer(int[] array); + public static native int launchUI(String[] uiArgs); // public static native void runOnUIThread(UIKitCallback callback); diff --git a/Makefile b/Makefile index 7355ef59..ed0ff2e8 100644 --- a/Makefile +++ b/Makefile @@ -107,14 +107,14 @@ native: -DCONFIG_COMMIT="$(COMMIT)" \ .. @cd Natives/build && cmake --build . --config Release --target awt_headless awt_xawt pojavexec PojavLauncher - @rm Natives/build/libawt_headless.dylib || exit 1 + @rm Natives/build/libawt_headless.dylib @echo 'Finished build task - native application' java: @echo 'Starting build task - java application' @cd JavaApp; \ mkdir -p local_out/classes; \ - $(JDK)/javac -cp "libs/*" -d local_out/classes $(JAVAFILES) || exit 1; \ + $(JDK)/javac -cp "libs/*:libs_caciocavallo/*" -d local_out/classes $(JAVAFILES) || exit 1; \ cd local_out/classes; \ $(JDK)/jar -cf ../launcher.jar * || exit 1; \ echo 'Finished build task - java application' @@ -135,7 +135,8 @@ package: @echo 'Starting build task - package for external devices' @if [ '$(IOS)' = '0' ]; then \ cp -R Natives/resources/* Natives/build/PojavLauncher.app/ || exit 1; \ - cp Natives/build/*.dylib Natives/build/PojavLauncher.app/Frameworks/ || exit 1; \ + cp Natives/build/libawt_xawt.dylib Natives/build/PojavLauncher.app/Frameworks/ || exit 1; \ + cp Natives/build/libpojavexec.dylib Natives/build/PojavLauncher.app/Frameworks/ || exit 1; \ mkdir Natives/build/PojavLauncher.app/{libs,libs_caciocavallo}; \ cp JavaApp/local_out/launcher.jar Natives/build/PojavLauncher.app/libs/launcher.jar || exit 1; \ cp -R JavaApp/libs/* Natives/build/PojavLauncher.app/libs/ || exit 1; \ @@ -151,7 +152,8 @@ package: cp -R Natives/en.lproj/*.storyboardc Natives/build/PojavLauncher.app/Base.lproj/ || exit 1; \ cp -R Natives/Info.plist Natives/build/PojavLauncher.app/Info.plist || exit 1;\ cp -R Natives/PkgInfo Natives/build/PojavLauncher.app/PkgInfo || exit 1; \ - cp -R Natives/build/*.dylib Natives/build/PojavLauncher.app/Frameworks/ || exit 1; \ + cp Natives/build/libawt_xawt.dylib Natives/build/PojavLauncher.app/Frameworks/ || exit 1; \ + cp Natives/build/libpojavexec.dylib Natives/build/PojavLauncher.app/Frameworks/ || exit 1; \ cp -R Natives/resources/* Natives/build/PojavLauncher.app/ || exit 1; \ cp -R JavaApp/libs Natives/build/PojavLauncher.app/libs || exit 1; \ cp -R JavaApp/libs_caciocavallo Natives/build/PojavLauncher.app/libs_caciocavallo || exit 1; \ @@ -217,7 +219,8 @@ deploy: sudo ldid -Sentitlements.xml Natives/build/PojavLauncher.app/PojavLauncher; \ sudo cp JavaApp/local_out/launcher.jar /Applications/PojavLauncher.app/libs/launcher.jar; \ sudo cp Natives/build/PojavLauncher.app/PojavLauncher /Applications/PojavLauncher.app/PojavLauncher; \ - sudo cp Natives/build/*.dylib /Applications/PojavLauncher.app/Frameworks/; \ + sudo cp Natives/build/libawt_xawt.dylib /Applications/PojavLauncher.app/Frameworks/; \ + sudo cp Natives/build/libpojavexec.dylib /Applications/PojavLauncher.app/Frameworks/; \ sudo killall PojavLauncher; \ fi @echo 'Finished build task - deploy to local device' diff --git a/Natives/AboutLauncherViewController.m b/Natives/AboutLauncherViewController.m index d2f695ce..a897a810 100644 --- a/Natives/AboutLauncherViewController.m +++ b/Natives/AboutLauncherViewController.m @@ -5,7 +5,7 @@ #import -#ifndef NDEBUG +#ifdef NDEBUG # define CONFIG_TYPE "release" #else # define CONFIG_TYPE "debug" diff --git a/Natives/CMakeLists.txt b/Natives/CMakeLists.txt index 89e382d3..97addf93 100644 --- a/Natives/CMakeLists.txt +++ b/Natives/CMakeLists.txt @@ -32,6 +32,7 @@ add_library(pojavexec SHARED AboutLauncherViewController.m AppDelegate.m CustomControlsViewController.m + JavaGUIViewController.m LauncherFAQViewController.m LauncherPreferences.m LauncherPreferencesViewController.m diff --git a/Natives/JavaGUIViewController.h b/Natives/JavaGUIViewController.h new file mode 100644 index 00000000..641206de --- /dev/null +++ b/Natives/JavaGUIViewController.h @@ -0,0 +1,12 @@ +#import + +@interface SurfaceView : UIView { + CALayer* layer; + CGColorSpaceRef colorSpace; + CGDataProviderDirectCallbacks callbacks; +} +@end + +@interface JavaGUIViewController : UIViewController + @property NSString* filepath; +@end diff --git a/Natives/JavaGUIViewController.m b/Natives/JavaGUIViewController.m new file mode 100644 index 00000000..e7855fab --- /dev/null +++ b/Natives/JavaGUIViewController.m @@ -0,0 +1,170 @@ +#import "JavaGUIViewController.h" +#import "ios_uikit_bridge.h" +#include "utils.h" + +static int* rgbArray; +SurfaceView* surfaceView; + +jclass class_CTCAndroidInput; +jmethodID method_ReceiveInput; + +JNIEXPORT void JNICALL Java_net_kdt_pojavlaunch_uikit_UIKit_refreshAWTBuffer(JNIEnv* env, jclass clazz, jintArray jreRgbArray) { + int *tmpArray = (*env)->GetIntArrayElements(env, jreRgbArray, 0); + memcpy(rgbArray, tmpArray, savedWidth * savedHeight * 4); + (*env)->ReleaseIntArrayElements(env, jreRgbArray, tmpArray, JNI_ABORT); + dispatch_async(dispatch_get_main_queue(), ^{ + [surfaceView displayLayer:surfaceView.layer]; + }); +} + +@implementation SurfaceView +const void * _CGDataProviderGetBytePointerCallback(void *info) { + return (const void *)rgbArray; +} + +void _CGDataProviderReleaseBytePointerCallback(void *info,const void *pointer) { +} + +- (void)displayLayer:(CALayer *)theLayer +{ + CGDataProviderRef bitmapProvider = CGDataProviderCreateDirect(NULL, savedWidth * savedHeight * 4, &callbacks); + CGImageRef bitmap = CGImageCreate(savedWidth, savedHeight, 8, 32, 4 * savedWidth, colorSpace, kCGImageAlphaFirst | kCGBitmapByteOrder32Little, bitmapProvider, NULL, FALSE, kCGRenderingIntentDefault); + + theLayer.contents = (__bridge id) bitmap; + CGImageRelease(bitmap); + CGDataProviderRelease(bitmapProvider); + // CGColorSpaceRelease(colorSpace); +} + +- (id)initWithFrame:(CGRect)frame +{ + self = [super initWithFrame:frame]; + layer = [self layer]; + layer.opaque = YES; + + colorSpace = CGColorSpaceCreateDeviceRGB(); + + callbacks.version = 0; + callbacks.getBytePointer = _CGDataProviderGetBytePointerCallback; + callbacks.releaseBytePointer = _CGDataProviderReleaseBytePointerCallback; + callbacks.getBytesAtPosition = NULL; + callbacks.releaseInfo = NULL; + + return self; +} +@end + +@interface JavaGUIViewController () { +} + +// - (void)method + +@end + +@implementation JavaGUIViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + [self.navigationController setNavigationBarHidden:YES animated:NO]; + [self setNeedsUpdateOfScreenEdgesDeferringSystemGestures]; + [self setNeedsUpdateOfHomeIndicatorAutoHidden]; + + CGRect screenBounds = [[UIScreen mainScreen] bounds]; + CGFloat screenScale = [[UIScreen mainScreen] scale]; + + int width = (int) roundf(screenBounds.size.width); + int height = (int) roundf(screenBounds.size.height); + + savedWidth = roundf(width * screenScale); + savedHeight = roundf(height * screenScale); + + UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:self.view.frame]; + scrollView.delegate = self; + scrollView.minimumZoomScale = 1; + scrollView.maximumZoomScale = 5; + scrollView.zoomScale = 1; + + surfaceView = [[SurfaceView alloc] initWithFrame:self.view.frame]; + [scrollView addSubview:surfaceView]; + + [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; + tapGesture.numberOfTapsRequired = 1; + tapGesture.numberOfTouchesRequired = 1; + tapGesture.cancelsTouchesInView = NO; + [surfaceView addGestureRecognizer:tapGesture]; + + rgbArray = calloc(4, (size_t) (savedWidth * savedHeight)); + + UIKit_launchJarFile(self.filepath.UTF8String); +} + +- (void)surfaceOnClick:(UITapGestureRecognizer *)sender { + if (method_ReceiveInput == NULL) { + class_CTCAndroidInput = (*runtimeJNIEnvPtr_JRE)->FindClass(runtimeJNIEnvPtr_JRE, "net/java/openjdk/cacio/ctc/CTCAndroidInput"); + assert(class_CTCAndroidInput != NULL); + method_ReceiveInput = (*runtimeJNIEnvPtr_JRE)->GetStaticMethodID(runtimeJNIEnvPtr_JRE, class_CTCAndroidInput, "receiveData", "(IIIII)V"); + assert(method_ReceiveInput != NULL); + } + + if (sender.state == UIGestureRecognizerStateRecognized) { + CGFloat screenScale = [[UIScreen mainScreen] scale]; + CGPoint location = [sender locationInView:sender.view]; + CGFloat x = location.x * screenScale; + CGFloat y = location.y * screenScale; + (*runtimeJNIEnvPtr_JRE)->CallStaticVoidMethod( + runtimeJNIEnvPtr_JRE, + class_CTCAndroidInput, + method_ReceiveInput, + EVENT_TYPE_CURSOR_POS, (int)x, (int)y, 0, 0 + ); + (*runtimeJNIEnvPtr_JRE)->CallStaticVoidMethod( + runtimeJNIEnvPtr_JRE, + class_CTCAndroidInput, + method_ReceiveInput, + EVENT_TYPE_MOUSE_BUTTON, BUTTON1_DOWN_MASK, 1, 0, 0 + ); + (*runtimeJNIEnvPtr_JRE)->CallStaticVoidMethod( + runtimeJNIEnvPtr_JRE, + class_CTCAndroidInput, + method_ReceiveInput, + EVENT_TYPE_MOUSE_BUTTON, BUTTON1_DOWN_MASK, 0, 0, 0 + ); + } +} + +- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView { + return surfaceView; +} + +- (UIRectEdge)preferredScreenEdgesDeferringSystemGestures { + return UIRectEdgeBottom; +} + +- (BOOL)prefersHomeIndicatorAutoHidden { + 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/LauncherViewController.m b/Natives/LauncherViewController.m index eda1ba58..11c57ecd 100644 --- a/Natives/LauncherViewController.m +++ b/Natives/LauncherViewController.m @@ -1,11 +1,12 @@ #import "CustomControlsViewController.h" +#import "JavaGUIViewController.h" #import "LauncherPreferences.h" #import "LauncherPreferencesViewController.h" #import "LauncherViewController.h" #include "utils.h" -@interface LauncherViewController () { +@interface LauncherViewController () { } // - (void)method @@ -72,11 +73,23 @@ int versionSelectedAt = 0; [scrollView addSubview:versionTextField]; - self.navigationItem.rightBarButtonItems = @[ - [[UIBarButtonItem alloc] initWithTitle:@"Custom controls" style:UIBarButtonItemStyleDone target:self action:@selector(enterCustomControls)], - [[UIBarButtonItem alloc] initWithTitle:@"Settings" style:UIBarButtonItemStyleDone target:self action:@selector(enterPreferences)] - ]; - + self.navigationItem.rightBarButtonItem = + [[UIBarButtonItem alloc] initWithTitle:@"Options" style:UIBarButtonItemStyleDone target:self action:@selector(displayOptions:)]; + if (@available(iOS 14.0, *)) { + // use UIMenu + UIAction *option1 = [UIAction actionWithTitle:@"Launch a mod installer" image:nil identifier:nil + handler:^(__kindof UIAction * _Nonnull action) {[self enterModInstaller];}]; + UIAction *option2 = [UIAction actionWithTitle:@"Custom controls" image:nil identifier:nil + handler:^(__kindof UIAction * _Nonnull action) {[self enterCustomControls];}]; + UIAction *option3 = [UIAction actionWithTitle:@"Settings" image:nil identifier:nil + handler:^(__kindof UIAction * _Nonnull action) {[self enterPreferences];}]; + UIMenu *menu = [UIMenu menuWithTitle:@"Options" image:nil identifier:nil + options:UIMenuOptionsDisplayInline children:@[option1, option2, option3]]; + self.navigationItem.rightBarButtonItem.action = nil; + self.navigationItem.rightBarButtonItem.primaryAction = nil; + self.navigationItem.rightBarButtonItem.menu = menu; + } + install_progress_bar = [[UIProgressView alloc] initWithFrame:CGRectMake(4.0, height - 58.0, width - 8.0, 6.0)]; [scrollView addSubview:install_progress_bar]; @@ -181,23 +194,60 @@ int versionSelectedAt = 0; } #pragma mark - Button click events +- (void)displayOptions:(UIBarButtonItem*)sender { + if (@available(iOS 14.0, *)) { + // use UIMenu + } else { + // use UIAlertController + UIAlertController *fullAlert = [UIAlertController alertControllerWithTitle:@"Options" message:@"" preferredStyle:UIAlertControllerStyleActionSheet]; + UIAlertAction *option1 = [UIAlertAction actionWithTitle:@"Launch a mod installer" style:UIAlertActionStyleDefault + handler:^(UIAlertAction * _Nonnull action) {[self enterModInstaller];}]; + UIAlertAction *option2 = [UIAlertAction actionWithTitle:@"Custom controls" style:UIAlertActionStyleDefault + handler:^(UIAlertAction * _Nonnull action) {[self enterCustomControls];}]; + UIAlertAction *option3 = [UIAlertAction actionWithTitle:@"Settings" 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 { CustomControlsViewController *vc = [[CustomControlsViewController alloc] init]; [self.navigationController pushViewController:vc animated:YES]; } +- (void)enterModInstaller { + UIDocumentPickerViewController *documentPicker = [[UIDocumentPickerViewController alloc] initWithDocumentTypes:@[@"com.sun.java-archive"] + inMode:UIDocumentPickerModeImport]; + documentPicker.delegate = self; + documentPicker.modalPresentationStyle = UIModalPresentationFormSheet; + [self presentViewController:documentPicker animated:YES completion:nil]; +} + +- (void)documentPicker:(UIDocumentPickerViewController *)controller didPickDocumentAtURL:(NSURL *)url { + if (controller.documentPickerMode == UIDocumentPickerModeImport) { + JavaGUIViewController *vc = [[JavaGUIViewController alloc] init]; + vc.filepath = url.path; + NSLog(@"ModInstaller: launching %@", vc.filepath); + [self.navigationController pushViewController:vc animated:YES]; + } +} + - (void)enterPreferences { LauncherPreferencesViewController *vc = [[LauncherPreferencesViewController alloc] init]; [self.navigationController pushViewController:vc animated:YES]; } -- (void)launchMinecraft:(id)sender { - [(UIButton*) sender setEnabled:NO]; +- (void)launchMinecraft:(UIButton *)sender { + [sender setEnabled:NO]; NSObject *object = [versionList objectAtIndex:[versionPickerView selectedRowInComponent:0]]; NSString *result; if ([object isKindOfClass:[NSString class]]) { - result = (NSString*) object; + result = (NSString *)object; } else { result = [object valueForKey:@"url"]; } diff --git a/Natives/LoginViewController.m b/Natives/LoginViewController.m index 24ab5c58..74bab828 100644 --- a/Natives/LoginViewController.m +++ b/Natives/LoginViewController.m @@ -19,7 +19,7 @@ void loginAccountInput(UINavigationController *controller, int type, const char* data_c) { JNIEnv *env; - (*runtimeJavaVMPtr)->AttachCurrentThread(runtimeJavaVMPtr, &env, NULL); + (*runtimeJavaVMPtr)->GetEnv(runtimeJavaVMPtr, &env, JNI_VERSION_1_6); jstring data = (*env)->NewStringUTF(env, data_c); diff --git a/Natives/customcontrols/CustomControlsUtils.m b/Natives/customcontrols/CustomControlsUtils.m index 76069002..6aa532f8 100644 --- a/Natives/customcontrols/CustomControlsUtils.m +++ b/Natives/customcontrols/CustomControlsUtils.m @@ -168,6 +168,13 @@ void generateAndSaveDefaultControl() { @"${bottom} - ${margin}", BTN_RECT )]; + // Additional button for old versions that don't enter fullscreen automatically + [dict[@"mControlDataList"] addObject:createButton(@"Fullscreen", + (int[]){GLFW_KEY_F11,0,0,0}, + @"${right} - ${margin}", + @"${bottom} - ${margin} * 2 - ${height}", + BTN_RECT + )]; NSOutputStream *os = [[NSOutputStream alloc] initToFileAtPath: [@(getenv("POJAV_PATH_CONTROL")) stringByAppendingString:@"/default.json"] append:NO]; [os open]; diff --git a/Natives/input_bridge_v3.m b/Natives/input_bridge_v3.m index fad37a48..480e9975 100644 --- a/Natives/input_bridge_v3.m +++ b/Natives/input_bridge_v3.m @@ -56,14 +56,6 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) { // Should be? void JNI_OnUnload(JavaVM* vm, void* reserved) { -/* - if (dalvikJavaVMPtr == vm) { - } else { - } - - DetachCurrentThread(vm); -*/ - runtimeJNIEnvPtr_JRE = NULL; } @@ -88,24 +80,6 @@ ADD_CALLBACK_WWIN(WindowPos); #undef ADD_CALLBACK_WWIN -jboolean attachThread(bool isAndroid, JNIEnv** secondJNIEnvPtr) { -#ifdef DEBUG - debug("Debug: Attaching %s thread to %s, javavm.isNull=%d\n", isAndroid ? "Android" : "JRE", isAndroid ? "JRE" : "Android", (isAndroid ? runtimeJavaVMPtr : dalvikJavaVMPtr) == NULL); -#endif - - if (*secondJNIEnvPtr != NULL || (!isUseStackQueueCall)) return JNI_TRUE; - - if (isAndroid && runtimeJavaVMPtr) { - (*runtimeJavaVMPtr)->AttachCurrentThread(runtimeJavaVMPtr, secondJNIEnvPtr, NULL); - return JNI_TRUE; - } else if (!isAndroid && dalvikJavaVMPtr) { - (*dalvikJavaVMPtr)->AttachCurrentThread(dalvikJavaVMPtr, secondJNIEnvPtr, NULL); - return JNI_TRUE; - } - - return JNI_FALSE; -} - void getJavaInputBridge(jclass* clazz, jmethodID* method) { #ifdef DEBUG debug("Debug: Initializing input bridge, method.isNull=%d, jnienv.isNull=%d\n", *method == NULL, runtimeJNIEnvPtr_ANDROID == NULL); @@ -272,29 +246,6 @@ JNIEXPORT jint JNICALL Java_net_kdt_pojavlaunch_uikit_UIKit_launchUI(JNIEnv* env } } -JNIEXPORT jboolean JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeAttachThreadToOther(JNIEnv* env, jclass clazz, jboolean isAndroid, jboolean isUseStackQueueBool) { -#ifdef DEBUG - LOGD("Debug: JNI attaching thread, isUseStackQueue=%d\n", isUseStackQueue); -#endif - - jboolean result; - - isUseStackQueueCall = (int) isUseStackQueueBool; - if (isAndroid) { - result = attachThread(true, &runtimeJNIEnvPtr_ANDROID); - } else { - result = attachThread(false, &dalvikJNIEnvPtr_JRE); - // getJavaInputBridge(&inputBridgeClass_JRE, &inputBridgeMethod_JRE); - } - - if (isUseStackQueueCall && isAndroid && result) { - isPrepareGrabPos = true; - } - getJavaInputBridge(&inputBridgeClass_ANDROID, &inputBridgeMethod_ANDROID); - - return result; -} - JNIEXPORT jstring JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeClipboard(JNIEnv* env, jclass clazz, jint action, jstring copySrc) { DEBUG_LOGD("Debug: Clipboard access is going on\n"); return UIKit_accessClipboard(env, action, copySrc); diff --git a/Natives/ios_uikit_bridge.h b/Natives/ios_uikit_bridge.h index ff6ce251..c1f9d422 100644 --- a/Natives/ios_uikit_bridge.h +++ b/Natives/ios_uikit_bridge.h @@ -5,5 +5,6 @@ void showDialog(UIViewController *viewController, NSString* title, NSString* message); jstring UIKit_accessClipboard(JNIEnv* env, jint action, jstring copySrc); jboolean UIKit_updateProgress(float progress, const char* message); +void UIKit_launchJarFile(const char* filepath); void UIKit_launchMinecraftSurfaceVC(); void UIKit_setButtonSkippable(); diff --git a/Natives/ios_uikit_bridge.m b/Natives/ios_uikit_bridge.m index 6a13a826..f2bdf7ea 100644 --- a/Natives/ios_uikit_bridge.m +++ b/Natives/ios_uikit_bridge.m @@ -13,6 +13,12 @@ jboolean skipDownloadAssets; +jclass class_CTCScreen; +jmethodID method_GetRGB; + +jclass class_CTCAndroidInput; +jmethodID method_ReceiveInput; + void internal_showDialog(UIViewController *viewController, NSString* title, NSString* message) { UIAlertController* alert = [UIAlertController alertControllerWithTitle:title message:message @@ -45,12 +51,7 @@ JNIEXPORT void JNICALL Java_net_kdt_pojavlaunch_uikit_UIKit_showError(JNIEnv* en dispatch_async(dispatch_get_main_queue(), ^{ - UIViewController *viewController = nil; - if (@available(iOS 13.0, *)) { - viewController = UIApplication.sharedApplication.windows.lastObject.rootViewController; - } else { - viewController = [[(AppDelegate*) [[UIApplication sharedApplication]delegate] window] rootViewController]; - } + UIViewController *viewController = UIApplication.sharedApplication.windows.lastObject.rootViewController; UIAlertController* alert = [UIAlertController alertControllerWithTitle:title_o message:message_o @@ -128,15 +129,26 @@ void UIKit_setButtonSkippable() { skipDownloadAssets = JNI_FALSE; } +void UIKit_launchJarFile(const char* filepath) { + jclass uikitBridgeClass = (*runtimeJNIEnvPtr_JRE)->FindClass(runtimeJNIEnvPtr_JRE, "net/kdt/pojavlaunch/uikit/UIKit"); + assert(uikitBridgeClass != NULL); + + jstring filepathStr = (*runtimeJNIEnvPtr_JRE)->NewStringUTF(runtimeJNIEnvPtr_JRE, filepath); + jmethodID method = (*runtimeJNIEnvPtr_JRE)->GetStaticMethodID(runtimeJNIEnvPtr_JRE, uikitBridgeClass, "callback_JavaGUIViewController_launchJarFile", "(Ljava/lang/String;II)V"); + assert(method != NULL); + + (*runtimeJNIEnvPtr_JRE)->CallStaticVoidMethod( + runtimeJNIEnvPtr_JRE, + uikitBridgeClass, method, + filepathStr, + savedWidth, savedHeight + ); + (*runtimeJNIEnvPtr_JRE)->DeleteLocalRef(runtimeJNIEnvPtr_JRE, filepathStr); +} + void UIKit_launchMinecraftSurfaceVC() { dispatch_async(dispatch_get_main_queue(), ^{ - UIViewController *rootController = nil; - if (@available(iOS 13.0, *)) { - rootController = UIApplication.sharedApplication.windows.lastObject.rootViewController; - } else { - rootController = (UIViewController*) [[(AppDelegate*) [[UIApplication sharedApplication]delegate] window] rootViewController]; - } - + UIViewController *rootController = UIApplication.sharedApplication.windows.lastObject.rootViewController; UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MinecraftSurface" bundle:nil]; SurfaceViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"MinecraftSurfaceVC"]; vc.modalPresentationStyle = UIModalPresentationFullScreen; diff --git a/Natives/utils.h b/Natives/utils.h index bd069510..ad1bd64e 100644 --- a/Natives/utils.h +++ b/Natives/utils.h @@ -7,6 +7,10 @@ #define ACTION_UP 1 #define ACTION_MOVE 2 +#define BUTTON1_DOWN_MASK 1 << 10 // left btn +#define BUTTON2_DOWN_MASK 1 << 11 // mid btn +#define BUTTON3_DOWN_MASK 1 << 12 // right btn + #define EVENT_TYPE_CHAR 1000 #define EVENT_TYPE_CHAR_MODS 1001 #define EVENT_TYPE_CURSOR_ENTER 1002 @@ -33,7 +37,6 @@ JavaVM* runtimeJavaVMPtr; JNIEnv* runtimeJNIEnvPtr_ANDROID; JNIEnv* runtimeJNIEnvPtr_JRE; -JavaVM* dalvikJavaVMPtr; JNIEnv* dalvikJNIEnvPtr_ANDROID; JNIEnv* dalvikJNIEnvPtr_JRE;