diff --git a/client/eventsSDL/InputHandler.cpp b/client/eventsSDL/InputHandler.cpp index f6e32166b..b0d20711a 100644 --- a/client/eventsSDL/InputHandler.cpp +++ b/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); diff --git a/clientapp/ios/Info.plist b/clientapp/ios/Info.plist index 0fba21025..32d1f671d 100644 --- a/clientapp/ios/Info.plist +++ b/clientapp/ios/Info.plist @@ -53,10 +53,5 @@ UIStatusBarHidden - UISupportedInterfaceOrientations - - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 7f163cbf1..47530635a 100644 --- a/launcher/CMakeLists.txt +++ b/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 diff --git a/launcher/prepare.cpp b/launcher/prepare.cpp index 7e158d4ac..f971bf644 100644 --- a/launcher/prepare.cpp +++ b/launcher/prepare.cpp @@ -9,75 +9,17 @@ */ #include "StdInc.h" #include "prepare.h" +#include "prepare_p.h" #include "../vcmiqt/launcherdirs.h" -#include -#include -#include - -#ifdef VCMI_ANDROID -#include "../lib/CAndroidVMHelper.h" - -#include -#include -#include - -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)); - - const bool justLaunched = QtAndroid::androidActivity().getField("justLaunched") == JNI_TRUE; - if(!justLaunched) - return; - - // copy core data to internal directory - const auto vcmiDir = QAndroidJniObject::callStaticObjectMethod("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(); diff --git a/launcher/prepare_android.cpp b/launcher/prepare_android.cpp new file mode 100644 index 000000000..0a25b3972 --- /dev/null +++ b/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 +#include +#include + +#include +#include +#include + +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)); + + const bool justLaunched = QtAndroid::androidActivity().getField("justLaunched") == JNI_TRUE; + if(!justLaunched) + return; + + // copy core data to internal directory + const auto vcmiDir = QAndroidJniObject::callStaticObjectMethod("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()); + } +} +} diff --git a/launcher/prepare_ios.mm b/launcher/prepare_ios.mm new file mode 100644 index 000000000..25f4d2c79 --- /dev/null +++ b/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 + +#include + +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"); +} +} diff --git a/launcher/prepare_p.h b/launcher/prepare_p.h new file mode 100644 index 000000000..904353cea --- /dev/null +++ b/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 +} diff --git a/launcher/settingsView/csettingsview_moc.cpp b/launcher/settingsView/csettingsview_moc.cpp index c1cb1cbb5..b45025274 100644 --- a/launcher/settingsView/csettingsview_moc.cpp +++ b/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();