Răsfoiți Sursa

[iOS] enable portrait mode

launcher stays landscape-only on iPhones
Andrey Filipenkov 7 luni în urmă
părinte
comite
20be327902

+ 1 - 1
client/eventsSDL/InputHandler.cpp

@@ -237,7 +237,7 @@ void InputHandler::preprocessEvent(const SDL_Event & ev)
 #endif
 				break;
 			case SDL_WINDOWEVENT_SIZE_CHANGED:
-#ifdef VCMI_ANDROID
+#ifdef VCMI_MOBILE
 			{
 				boost::mutex::scoped_lock interfaceLock(GH.interfaceMutex);
 				GH.onScreenResize(true);

+ 0 - 5
clientapp/ios/Info.plist

@@ -53,10 +53,5 @@
 	<true/>
 	<key>UIStatusBarHidden</key>
 	<true/>
-	<key>UISupportedInterfaceOrientations</key>
-	<array>
-		<string>UIInterfaceOrientationLandscapeLeft</string>
-		<string>UIInterfaceOrientationLandscapeRight</string>
-	</array>
 </dict>
 </plist>

+ 6 - 0
launcher/CMakeLists.txt

@@ -31,6 +31,11 @@ if(APPLE_IOS)
 		ios/revealdirectoryinfiles.mm
 		ios/selectdirectory.h
 		ios/selectdirectory.mm
+		prepare_ios.mm
+	)
+elseif(ANDROID)
+	list(APPEND launcher_SRCS
+		prepare_android.cpp
 	)
 endif()
 
@@ -55,6 +60,7 @@ set(launcher_HEADERS
 		helper.h
 		innoextract.h
 		prepare.h
+		prepare_p.h
 )
 
 set(launcher_FORMS

+ 3 - 61
launcher/prepare.cpp

@@ -9,75 +9,17 @@
  */
 #include "StdInc.h"
 #include "prepare.h"
+#include "prepare_p.h"
 #include "../vcmiqt/launcherdirs.h"
 
-#include <QDir>
-#include <QFile>
-#include <QFileInfo>
-
-#ifdef VCMI_ANDROID
-#include "../lib/CAndroidVMHelper.h"
-
-#include <QAndroidJniEnvironment>
-#include <QAndroidJniObject>
-#include <QtAndroid>
-
-namespace
-{
-// https://gist.github.com/ssendeavour/7324701
-bool copyRecursively(const QString &srcFilePath, const QString &tgtFilePath)
-{
-	QFileInfo srcFileInfo{srcFilePath};
-	if(srcFileInfo.isDir()) {
-		QDir targetDir{tgtFilePath};
-		targetDir.cdUp();
-		if(!targetDir.mkpath(QFileInfo{tgtFilePath}.fileName()))
-			return false;
-		targetDir.setPath(tgtFilePath);
-
-		QDir sourceDir{srcFilePath};
-		const auto fileNames = sourceDir.entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot | QDir::Hidden | QDir::System);
-		for(const auto & fileName : fileNames) {
-			const auto newSrcFilePath = sourceDir.filePath(fileName);
-			const auto newTgtFilePath = targetDir.filePath(fileName);
-			if(!copyRecursively(newSrcFilePath, newTgtFilePath))
-				return false;
-		}
-	} else {
-		if(!QFile::copy(srcFilePath, tgtFilePath))
-			return false;
-	}
-	return true;
-}
-
-void prepareAndroid()
-{
-	QAndroidJniEnvironment jniEnv;
-	CAndroidVMHelper::initClassloader(static_cast<JNIEnv *>(jniEnv));
-
-	const bool justLaunched = QtAndroid::androidActivity().getField<jboolean>("justLaunched") == JNI_TRUE;
-	if(!justLaunched)
-		return;
-
-	// copy core data to internal directory
-	const auto vcmiDir = QAndroidJniObject::callStaticObjectMethod<jstring>("eu/vcmi/vcmi/NativeMethods", "internalDataRoot").toString();
-	for(auto vcmiFilesResource : {QLatin1String{"config"}, QLatin1String{"Mods"}})
-	{
-		QDir destDir = QString{"%1/%2"}.arg(vcmiDir, vcmiFilesResource);
-		destDir.removeRecursively();
-		copyRecursively(QString{":/%1"}.arg(vcmiFilesResource), destDir.absolutePath());
-	}
-}
-}
-#endif
-
-
 namespace launcher
 {
 void prepare()
 {
 #ifdef VCMI_ANDROID
 	prepareAndroid();
+#elif defined(VCMI_IOS)
+	prepareIos();
 #endif
 
 	CLauncherDirs::prepare();

+ 71 - 0
launcher/prepare_android.cpp

@@ -0,0 +1,71 @@
+/*
+ * prepare_android.cpp, 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 "StdInc.h"
+#include "prepare_p.h"
+#include "../lib/CAndroidVMHelper.h"
+
+#include <QDir>
+#include <QFile>
+#include <QFileInfo>
+
+#include <QAndroidJniEnvironment>
+#include <QAndroidJniObject>
+#include <QtAndroid>
+
+namespace
+{
+// https://gist.github.com/ssendeavour/7324701
+bool copyRecursively(const QString & srcFilePath, const QString & tgtFilePath)
+{
+	QFileInfo srcFileInfo{srcFilePath};
+	if(srcFileInfo.isDir()) {
+		QDir targetDir{tgtFilePath};
+		targetDir.cdUp();
+		if(!targetDir.mkpath(QFileInfo{tgtFilePath}.fileName()))
+			return false;
+		targetDir.setPath(tgtFilePath);
+
+		QDir sourceDir{srcFilePath};
+		const auto fileNames = sourceDir.entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot | QDir::Hidden | QDir::System);
+		for(const auto & fileName : fileNames) {
+			const auto newSrcFilePath = sourceDir.filePath(fileName);
+			const auto newTgtFilePath = targetDir.filePath(fileName);
+			if(!copyRecursively(newSrcFilePath, newTgtFilePath))
+				return false;
+		}
+	} else {
+		if(!QFile::copy(srcFilePath, tgtFilePath))
+			return false;
+	}
+	return true;
+}
+}
+
+namespace launcher
+{
+void prepareAndroid()
+{
+	QAndroidJniEnvironment jniEnv;
+	CAndroidVMHelper::initClassloader(static_cast<JNIEnv *>(jniEnv));
+
+	const bool justLaunched = QtAndroid::androidActivity().getField<jboolean>("justLaunched") == JNI_TRUE;
+	if(!justLaunched)
+		return;
+
+	// copy core data to internal directory
+	const auto vcmiDir = QAndroidJniObject::callStaticObjectMethod<jstring>("eu/vcmi/vcmi/NativeMethods", "internalDataRoot").toString();
+	for(auto vcmiFilesResource : {QLatin1String{"config"}, QLatin1String{"Mods"}})
+	{
+		QDir destDir = QString{"%1/%2"}.arg(vcmiDir, vcmiFilesResource);
+		destDir.removeRecursively();
+		copyRecursively(QString{":/%1"}.arg(vcmiFilesResource), destDir.absolutePath());
+	}
+}
+}

+ 40 - 0
launcher/prepare_ios.mm

@@ -0,0 +1,40 @@
+/*
+ * prepare_ios.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 "StdInc.h"
+#include "prepare_p.h"
+
+#import <UIKit/UIKit.h>
+
+#include <objc/runtime.h>
+
+namespace
+{
+UIInterfaceOrientationMask swizzled_supportedInterfaceOrientationsForWindow
+	(id __unused self, SEL __unused _cmd, UIApplication * __unused application, UIWindow * __unused _Nullable window)
+{
+	if(UIDevice.currentDevice.userInterfaceIdiom == UIUserInterfaceIdiomPad)
+		return UIInterfaceOrientationMaskAll;
+	return UIInterfaceOrientationMaskLandscape;
+}
+}
+
+namespace launcher
+{
+void prepareIos()
+{
+	auto sel = @selector(application:supportedInterfaceOrientationsForWindow:);
+	auto methodDesc = protocol_getMethodDescription(@protocol(UIApplicationDelegate), sel, NO, YES);
+	auto appDelegateClass = object_getClass(UIApplication.sharedApplication.delegate);
+	[[maybe_unused]] auto existingImp = class_replaceMethod(
+		appDelegateClass, sel, (IMP)swizzled_supportedInterfaceOrientationsForWindow, methodDesc.types);
+	// also check implementation in qtbase - src/plugins/platforms/ios/qiosapplicationdelegate.mm
+	NSCAssert(existingImp == nullptr, @"original app delegate has this method, don't ignore it");
+}
+}

+ 19 - 0
launcher/prepare_p.h

@@ -0,0 +1,19 @@
+/*
+ * prepare_p.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
+
+namespace launcher
+{
+#ifdef VCMI_ANDROID
+void prepareAndroid();
+#elif defined(VCMI_IOS)
+void prepareIos();
+#endif
+}

+ 2 - 2
launcher/settingsView/csettingsview_moc.cpp

@@ -120,6 +120,8 @@ void CSettingsView::loadSettings()
 	ui->labelHapticFeedback->hide();
 	ui->labelResetTutorialTouchscreen->hide();
 	ui->pushButtonResetTutorialTouchscreen->hide();
+	ui->labelAllowPortrait->hide();
+	ui->buttonAllowPortrait->hide();
 	if (settings["video"]["realFullscreen"].Bool())
 		ui->comboBoxFullScreen->setCurrentIndex(2);
 	else
@@ -128,8 +130,6 @@ void CSettingsView::loadSettings()
 #ifndef VCMI_ANDROID
 	ui->buttonHandleBackRightMouseButton->hide();
 	ui->labelHandleBackRightMouseButton->hide();
-	ui->buttonAllowPortrait->hide();
-	ui->labelAllowPortrait->hide();
 #endif
 	fillValidScalingRange();