mirror of
https://github.com/vcmi/vcmi.git
synced 2025-11-25 22:42:04 +02:00
[iOS] enable portrait mode
launcher stays landscape-only on iPhones
This commit is contained in:
@@ -237,7 +237,7 @@ void InputHandler::preprocessEvent(const SDL_Event & ev)
|
|||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case SDL_WINDOWEVENT_SIZE_CHANGED:
|
case SDL_WINDOWEVENT_SIZE_CHANGED:
|
||||||
#ifdef VCMI_ANDROID
|
#ifdef VCMI_MOBILE
|
||||||
{
|
{
|
||||||
boost::mutex::scoped_lock interfaceLock(GH.interfaceMutex);
|
boost::mutex::scoped_lock interfaceLock(GH.interfaceMutex);
|
||||||
GH.onScreenResize(true);
|
GH.onScreenResize(true);
|
||||||
|
|||||||
@@ -53,10 +53,5 @@
|
|||||||
<true/>
|
<true/>
|
||||||
<key>UIStatusBarHidden</key>
|
<key>UIStatusBarHidden</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>UISupportedInterfaceOrientations</key>
|
|
||||||
<array>
|
|
||||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
|
||||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
|
||||||
</array>
|
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
@@ -31,6 +31,11 @@ if(APPLE_IOS)
|
|||||||
ios/revealdirectoryinfiles.mm
|
ios/revealdirectoryinfiles.mm
|
||||||
ios/selectdirectory.h
|
ios/selectdirectory.h
|
||||||
ios/selectdirectory.mm
|
ios/selectdirectory.mm
|
||||||
|
prepare_ios.mm
|
||||||
|
)
|
||||||
|
elseif(ANDROID)
|
||||||
|
list(APPEND launcher_SRCS
|
||||||
|
prepare_android.cpp
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@@ -55,6 +60,7 @@ set(launcher_HEADERS
|
|||||||
helper.h
|
helper.h
|
||||||
innoextract.h
|
innoextract.h
|
||||||
prepare.h
|
prepare.h
|
||||||
|
prepare_p.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(launcher_FORMS
|
set(launcher_FORMS
|
||||||
|
|||||||
@@ -9,75 +9,17 @@
|
|||||||
*/
|
*/
|
||||||
#include "StdInc.h"
|
#include "StdInc.h"
|
||||||
#include "prepare.h"
|
#include "prepare.h"
|
||||||
|
#include "prepare_p.h"
|
||||||
#include "../vcmiqt/launcherdirs.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
|
namespace launcher
|
||||||
{
|
{
|
||||||
void prepare()
|
void prepare()
|
||||||
{
|
{
|
||||||
#ifdef VCMI_ANDROID
|
#ifdef VCMI_ANDROID
|
||||||
prepareAndroid();
|
prepareAndroid();
|
||||||
|
#elif defined(VCMI_IOS)
|
||||||
|
prepareIos();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
CLauncherDirs::prepare();
|
CLauncherDirs::prepare();
|
||||||
|
|||||||
71
launcher/prepare_android.cpp
Normal file
71
launcher/prepare_android.cpp
Normal file
@@ -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
launcher/prepare_ios.mm
Normal file
40
launcher/prepare_ios.mm
Normal file
@@ -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
launcher/prepare_p.h
Normal file
19
launcher/prepare_p.h
Normal file
@@ -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
|
||||||
|
}
|
||||||
@@ -120,6 +120,8 @@ void CSettingsView::loadSettings()
|
|||||||
ui->labelHapticFeedback->hide();
|
ui->labelHapticFeedback->hide();
|
||||||
ui->labelResetTutorialTouchscreen->hide();
|
ui->labelResetTutorialTouchscreen->hide();
|
||||||
ui->pushButtonResetTutorialTouchscreen->hide();
|
ui->pushButtonResetTutorialTouchscreen->hide();
|
||||||
|
ui->labelAllowPortrait->hide();
|
||||||
|
ui->buttonAllowPortrait->hide();
|
||||||
if (settings["video"]["realFullscreen"].Bool())
|
if (settings["video"]["realFullscreen"].Bool())
|
||||||
ui->comboBoxFullScreen->setCurrentIndex(2);
|
ui->comboBoxFullScreen->setCurrentIndex(2);
|
||||||
else
|
else
|
||||||
@@ -128,8 +130,6 @@ void CSettingsView::loadSettings()
|
|||||||
#ifndef VCMI_ANDROID
|
#ifndef VCMI_ANDROID
|
||||||
ui->buttonHandleBackRightMouseButton->hide();
|
ui->buttonHandleBackRightMouseButton->hide();
|
||||||
ui->labelHandleBackRightMouseButton->hide();
|
ui->labelHandleBackRightMouseButton->hide();
|
||||||
ui->buttonAllowPortrait->hide();
|
|
||||||
ui->labelAllowPortrait->hide();
|
|
||||||
#endif
|
#endif
|
||||||
fillValidScalingRange();
|
fillValidScalingRange();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user