浏览代码

start app with launcher, start SDL from launcher

kambala-decapitator/vcmi#33
Andrey Filipenkov 3 年之前
父节点
当前提交
1e01780d17

+ 9 - 1
client/CMT.cpp

@@ -159,7 +159,7 @@ static void SDLLogCallback(void*           userdata,
 
 #if defined(VCMI_WINDOWS) && !defined(__GNUC__) && defined(VCMI_WITH_DEBUG_CONSOLE)
 int wmain(int argc, wchar_t* argv[])
-#elif defined(VCMI_ANDROID)
+#elif defined(VCMI_IOS) || defined(VCMI_ANDROID)
 int SDL_main(int argc, char *argv[])
 #else
 int main(int argc, char * argv[])
@@ -217,12 +217,20 @@ int main(int argc, char * argv[])
 	if(vm.count("help"))
 	{
 		prog_help(opts);
+#ifdef VCMI_IOS
+		exit(0);
+#else
 		return 0;
+#endif
 	}
 	if(vm.count("version"))
 	{
 		prog_version();
+#ifdef VCMI_IOS
+		exit(0);
+#else
 		return 0;
+#endif
 	}
 
 	// Init old logging system and new (temporary) logging system

+ 5 - 1
client/CMakeLists.txt

@@ -148,12 +148,16 @@ set(client_HEADERS
 if(APPLE_IOS)
 	set(client_SRCS ${client_SRCS}
 		CFocusableHelper.cpp
+		ios/AppDelegate.mm
 		ios/GameChatKeyboardHanlder.m
-		ios/SDL_uikit_main.mm
+		ios/main.m
+		ios/startSDL.mm
 	)
 	set(client_HEADERS ${client_HEADERS}
 		CFocusableHelper.h
+		ios/AppDelegate.h
 		ios/GameChatKeyboardHanlder.h
+		ios/startSDL.h
 	)
 endif()
 

+ 18 - 0
client/ios/AppDelegate.h

@@ -0,0 +1,18 @@
+/*
+ * AppDelegate.h, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+#import <UIKit/UIKit.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface AppDelegate : UIResponder <UIApplicationDelegate>
+@property (nonatomic, strong) UIWindow *window;
+@end
+
+NS_ASSUME_NONNULL_END

+ 49 - 0
client/ios/AppDelegate.mm

@@ -0,0 +1,49 @@
+/*
+ * AppDelegate.mm, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+#import "AppDelegate.h"
+
+#include "startSDL.h"
+#include "../launcher/main.h"
+
+#include <vector>
+
+@implementation AppDelegate
+
+- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary<UIApplicationLaunchOptionsKey, id> *)launchOptions {
+	self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
+	self.window.rootViewController = [UIViewController new];
+	[self.window makeKeyAndVisible];
+
+	[NSNotificationCenter.defaultCenter addObserverForName:@"StartGame" object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) {
+		[self startMainFunc:startSDL];
+	}];
+	return YES;
+}
+
+- (void)applicationDidBecomeActive:(UIApplication *)application {
+	static dispatch_once_t onceToken;
+	dispatch_once(&onceToken, ^{
+		[self startMainFunc:qt_main];
+	});
+}
+
+#pragma mark - Private
+
+- (void)startMainFunc:(int(*)(int argc, char * argv[]))mainPtr {
+	auto args = NSProcessInfo.processInfo.arguments;
+	std::vector<char *> argv;
+	argv.reserve(args.count);
+	for (NSString *arg in args)
+		argv.push_back(const_cast<char *>(arg.UTF8String));
+
+	mainPtr(argv.size(), argv.data());
+}
+
+@end

+ 17 - 0
client/ios/main.m

@@ -0,0 +1,17 @@
+/*
+ * main.m, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+#import "AppDelegate.h"
+
+int main(int argc, char * argv[])
+{
+	@autoreleasepool {
+		return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
+	}
+}

+ 12 - 0
client/ios/startSDL.h

@@ -0,0 +1,12 @@
+/*
+ * startSDL.h, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+#pragma once
+
+int startSDL(int argc, char * argv[]);

+ 28 - 22
client/ios/SDL_uikit_main.mm → client/ios/startSDL.mm

@@ -1,12 +1,17 @@
 /*
-    SDL_uikit_main.c, placed in the public domain by Sam Lantinga  3/18/2019
-*/
-
-/* Include the SDL main definition header */
+ * startSDL.mm, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
 #include <SDL_main.h>
 
 #include <SDL_events.h>
 #include <SDL_render.h>
+#include <SDL_system.h>
 
 #include "../Global.h"
 #include "CMT.h"
@@ -17,8 +22,8 @@
 
 #import <UIKit/UIKit.h>
 
-double ios_screenScale() { return UIScreen.mainScreen.nativeScale; }
 
+double ios_screenScale() { return UIScreen.mainScreen.nativeScale; }
 
 @interface SDLViewObserver : NSObject <UIGestureRecognizerDelegate>
 @property (nonatomic, strong) GameChatKeyboardHanlder * gameChatHandler;
@@ -117,23 +122,24 @@ double ios_screenScale() { return UIScreen.mainScreen.nativeScale; }
 @end
 
 
-#ifdef main
-#undef main
-#endif
-
-int
-main(int argc, char *argv[])
+int startSDL(int argc, char * argv[])
 {
-    @autoreleasepool
-    {
-        auto observer = [SDLViewObserver new];
+	@autoreleasepool {
+		auto observer = [SDLViewObserver new];
 		observer.gameChatHandler = [GameChatKeyboardHanlder new];
-        [NSNotificationCenter.defaultCenter addObserverForName:UIWindowDidBecomeKeyNotification object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) {
-            [UIApplication.sharedApplication.keyWindow.rootViewController addObserver:observer forKeyPath:NSStringFromSelector(@selector(view)) options:NSKeyValueObservingOptionNew context:NULL];
-        }];
-        [NSNotificationCenter.defaultCenter addObserverForName:UITextFieldTextDidEndEditingNotification object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) {
-            removeFocusFromActiveInput();
-        }];
-        return SDL_UIKitRunApp(argc, argv, SDL_main);
-    }
+		[NSNotificationCenter.defaultCenter addObserverForName:UIWindowDidBecomeKeyNotification object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) {
+			[UIApplication.sharedApplication.keyWindow.rootViewController addObserver:observer forKeyPath:NSStringFromSelector(@selector(view)) options:NSKeyValueObservingOptionNew context:NULL];
+		}];
+		[NSNotificationCenter.defaultCenter addObserverForName:UITextFieldTextDidEndEditingNotification object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) {
+			removeFocusFromActiveInput();
+		}];
+
+		// copied from -[SDLUIKitDelegate postFinishLaunch]
+		SDL_SetMainReady();
+		SDL_iOSSetEventPump(SDL_TRUE);
+		auto result = SDL_main(argc, argv);
+		SDL_iOSSetEventPump(SDL_FALSE);
+
+		return result;
+	}
 }

+ 4 - 1
launcher/CMakeLists.txt

@@ -43,6 +43,7 @@ set(launcher_HEADERS
 		launcherdirs.h
 		jsonutils.h
 		updatedialog_moc.h
+		main.h
 )
 
 set(launcher_FORMS
@@ -54,7 +55,9 @@ set(launcher_FORMS
 )
 
 if(APPLE_IOS)
-	set(launcher_SRCS ${launcher_SRCS} ios/mainwindow_moc.mm)
+	list(APPEND launcher_SRCS
+		ios/mainwindow_moc.mm
+	)
 endif()
 
 assign_source_group(${launcher_SRCS} ${launcher_HEADERS} VCMI_launcher.rc)

+ 21 - 8
launcher/ios/mainwindow_moc.mm

@@ -10,16 +10,29 @@
 
 #include "../mainwindow_moc.h"
 
+#include <QGuiApplication>
+#include <QWindow>
+
 #import <UIKit/UIKit.h>
 
 void MainWindow::startExecutable(QString /*name*/)
 {
-    NSString * vcmiScheme = NSBundle.mainBundle.infoDictionary[@"LSApplicationQueriesSchemes"][0];
-    [UIApplication.sharedApplication openURL:[NSURL URLWithString:[vcmiScheme stringByAppendingString:@":"]] options:@{} completionHandler:^(BOOL success) {
-        if (success)
-            return;
-        auto alert = [UIAlertController alertControllerWithTitle:@"Can't open VCMI client" message:nil preferredStyle:UIAlertControllerStyleAlert];
-        [alert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]];
-        [UIApplication.sharedApplication.keyWindow.rootViewController presentViewController:alert animated:YES completion:nil];
-    }];
+	qApp->quit();
+	[NSNotificationCenter.defaultCenter postNotificationName:@"StartGame" object:nil];
+}
+
+void showQtWindow()
+{
+	auto app = UIApplication.sharedApplication;
+	auto qtNativeWindowIndex = [app.windows indexOfObjectPassingTest:^BOOL(__kindof UIWindow * _Nonnull window, NSUInteger idx, BOOL * _Nonnull stop) {
+		return [NSStringFromClass([window class]) isEqualToString:@"QUIWindow"];
+	}];
+	Q_ASSERT(qtNativeWindowIndex != NSNotFound);
+
+	auto qtWindow = qApp->topLevelWindows()[0];
+	auto qtWindowNativeView = (__bridge UIView*)reinterpret_cast<void*>(qtWindow->winId());
+
+	auto qtNativeWindow = app.windows[qtNativeWindowIndex];
+	[qtNativeWindow.rootViewController.view addSubview:qtWindowNativeView];
+	[qtNativeWindow makeKeyAndVisible];
 }

+ 4 - 0
launcher/main.cpp

@@ -10,11 +10,15 @@
 #include <QApplication>
 #include "StdInc.h"
 #include "mainwindow_moc.h"
+#include "main.h"
 
 int main(int argc, char * argv[])
 {
 	QApplication vcmilauncher(argc, argv);
 	MainWindow mainWindow;
 	mainWindow.show();
+#ifdef Q_OS_IOS
+	showQtWindow();
+#endif
 	return vcmilauncher.exec();
 }

+ 19 - 0
launcher/main.h

@@ -0,0 +1,19 @@
+/*
+ * main.h, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+#pragma once
+
+#include <QtGlobal>
+
+#ifdef Q_OS_IOS
+void showQtWindow();
+
+#define main qt_main
+#endif
+int main(int argc, char * argv[]);