From 22782b643971e2f065380b7b270432919374a413 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 7 Mar 2017 10:33:53 +0100 Subject: [PATCH] UWP: Fix DPI calculations for touch. Implement back button support. --- GPU/Common/ShaderTranslation.cpp | 10 ++-- UI/GamepadEmu.cpp | 17 +++--- UWP/App.cpp | 21 +++++++ UWP/App.h | 11 ++++ UWP/Common/DeviceResources.cpp | 3 +- UWP/Common/DeviceResources.h | 5 +- UWP/NativeUWP/NativeUWP.vcxproj | 1 - UWP/NativeUWP/NativeUWP.vcxproj.filters | 3 - UWP/PPSSPP_UWPMain.cpp | 76 ++++++++++++------------- UWP/PPSSPP_UWPMain.h | 2 + UWP/UWP.vcxproj | 9 +++ Windows/main.cpp | 2 + android/jni/app-android.cpp | 2 + ext/native/base/NativeApp.h | 1 + ext/native/base/PCMain.cpp | 2 + ext/native/base/QtMain.cpp | 2 + ios/main.mm | 2 + 17 files changed, 111 insertions(+), 58 deletions(-) diff --git a/GPU/Common/ShaderTranslation.cpp b/GPU/Common/ShaderTranslation.cpp index c3289a9d35..40c90fabd1 100644 --- a/GPU/Common/ShaderTranslation.cpp +++ b/GPU/Common/ShaderTranslation.cpp @@ -15,6 +15,8 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. +#include "ppsspp_config.h" + #if !defined(ANDROID) #include @@ -55,13 +57,13 @@ static EShLanguage GetLanguage(const Draw::ShaderStage stage) { } void ShaderTranslationInit() { - // TODO: We have TLS issues on mobile -#ifndef _M_ARM + // TODO: We have TLS issues on UWP +#if !PPSSPP_PLATFORM(UWP) glslang::InitializeProcess(); #endif } void ShaderTranslationShutdown() { -#ifndef _M_ARM +#if !PPSSPP_PLATFORM(UWP) glslang::FinalizeProcess(); #endif } @@ -172,7 +174,7 @@ bool TranslateShader(std::string *dest, ShaderLanguage destLang, TranslatedShade if (srcLang != GLSL_300 && srcLang != GLSL_140) return false; -#ifdef _M_ARM +#if PPSSPP_PLATFORM(UWP) return false; #endif diff --git a/UI/GamepadEmu.cpp b/UI/GamepadEmu.cpp index 577185e26f..62dddc9788 100644 --- a/UI/GamepadEmu.cpp +++ b/UI/GamepadEmu.cpp @@ -620,11 +620,6 @@ UI::ViewGroup *CreatePadLayout(float xres, float yres, bool *pause) { const int roundImage = g_Config.iTouchButtonStyle ? I_ROUND_LINE : I_ROUND; - // These platforms always need the pause menu button to be shown. -#if defined(IOS) - root->Add(new BoolButton(pause, roundImage, I_ARROW, 1.0f, new AnchorLayoutParams(halfW, 20, NONE, NONE, true)))->SetAngle(90); -#endif - if (g_Config.bShowTouchControls) { const int rectImage = g_Config.iTouchButtonStyle ? I_RECT_LINE : I_RECT; const int shoulderImage = g_Config.iTouchButtonStyle ? I_SHOULDER_LINE : I_SHOULDER; @@ -633,10 +628,10 @@ UI::ViewGroup *CreatePadLayout(float xres, float yres, bool *pause) { const int stickBg = g_Config.iTouchButtonStyle ? I_STICK_BG_LINE : I_STICK_BG; static const int comboKeyImages[5] = { I_1, I_2, I_3, I_4, I_5 }; -#if !defined(IOS) - if (g_Config.bShowTouchPause) + if (!System_GetPropertyInt(SYSPROP_HAS_BACK_BUTTON)) { root->Add(new BoolButton(pause, roundImage, I_ARROW, 1.0f, new AnchorLayoutParams(halfW, 20, NONE, NONE, true)))->SetAngle(90); -#endif + } + if (g_Config.bShowTouchCircle) root->Add(new PSPButton(CTRL_CIRCLE, roundImage, I_CIRCLE, Action_button_scale, new AnchorLayoutParams(Action_circle_button_X, Action_circle_button_Y, NONE, NONE, true))); @@ -685,6 +680,12 @@ UI::ViewGroup *CreatePadLayout(float xres, float yres, bool *pause) { if (g_Config.bShowComboKey4) root->Add(new ComboKey(g_Config.iCombokey4, roundImage, comboKeyImages[4], combo4_key_scale, new AnchorLayoutParams(combo4_key_X, combo4_key_Y, NONE, NONE, true))); } + else { + // If there's no hardware back button (or ESC key), add a soft button. + if (!System_GetPropertyInt(SYSPROP_HAS_BACK_BUTTON)) { + root->Add(new BoolButton(pause, roundImage, I_ARROW, 1.0f, new AnchorLayoutParams(halfW, 20, NONE, NONE, true)))->SetAngle(90); + } + } return root; } diff --git a/UWP/App.cpp b/UWP/App.cpp index 964b12232d..5950a5ada2 100644 --- a/UWP/App.cpp +++ b/UWP/App.cpp @@ -90,9 +90,26 @@ void App::SetWindow(CoreWindow^ window) { window->PointerCaptureLost += ref new TypedEventHandler(this, &App::OnPointerCaptureLost); window->PointerWheelChanged += ref new TypedEventHandler(this, &App::OnPointerWheelChanged); + if (Windows::Foundation::Metadata::ApiInformation::IsTypePresent("Windows.Phone.UI.Input.HardwareButtons")) { + m_hardwareButtons.insert(HardwareButton::BACK); + } + + Windows::UI::Core::SystemNavigationManager::GetForCurrentView()-> + BackRequested += ref new Windows::Foundation::EventHandler< + Windows::UI::Core::BackRequestedEventArgs^>( + this, &App::App_BackRequested); + m_deviceResources->SetWindow(window); } +bool App::HasBackButton() { + return m_hardwareButtons.find(HardwareButton::BACK) != m_hardwareButtons.end(); +} + +void App::App_BackRequested(Platform::Object^ sender, Windows::UI::Core::BackRequestedEventArgs^ e) { + e->Handled = m_main->OnHardwareButton(HardwareButton::BACK); +} + void App::OnKeyDown(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyEventArgs^ args) { m_main->OnKeyDown(args->KeyStatus.ScanCode, args->VirtualKey, args->KeyStatus.RepeatCount); } @@ -185,6 +202,10 @@ void App::Uninitialize() { void App::OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) { // Run() won't start until the CoreWindow is activated. CoreWindow::GetForCurrentThread()->Activate(); + // On mobile, we force-enter fullscreen mode. +#ifdef _ARM + Windows::UI::ViewManagement::ApplicationView::GetForCurrentView()->TryEnterFullScreenMode(); +#endif } void App::OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) { diff --git a/UWP/App.h b/UWP/App.h index b34558f924..d329ac2c20 100644 --- a/UWP/App.h +++ b/UWP/App.h @@ -1,5 +1,7 @@ #pragma once +#include + #include "pch.h" #include "Common/DeviceResources.h" #include "PPSSPP_UWPMain.h" @@ -45,6 +47,10 @@ namespace UWP { Touch touches[maxTouches]{}; }; + enum class HardwareButton { + BACK, + }; + // Main entry point for our app. Connects the app with the Windows shell and handles application lifecycle events. ref class App sealed : public Windows::ApplicationModel::Core::IFrameworkView { public: @@ -57,6 +63,8 @@ namespace UWP { virtual void Run(); virtual void Uninitialize(); + bool HasBackButton(); + protected: // Application lifecycle event handlers. void OnActivated(Windows::ApplicationModel::Core::CoreApplicationView^ applicationView, Windows::ApplicationModel::Activation::IActivatedEventArgs^ args); @@ -85,8 +93,11 @@ namespace UWP { void OnPointerCaptureLost(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args); void OnPointerWheelChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args); + void App_BackRequested(Platform::Object^ sender, Windows::UI::Core::BackRequestedEventArgs^ e); + private: std::shared_ptr m_deviceResources; + std::set m_hardwareButtons; std::unique_ptr m_main; bool m_windowClosed; bool m_windowVisible; diff --git a/UWP/Common/DeviceResources.cpp b/UWP/Common/DeviceResources.cpp index 6d83cb8c03..fa1e71be5a 100644 --- a/UWP/Common/DeviceResources.cpp +++ b/UWP/Common/DeviceResources.cpp @@ -19,7 +19,7 @@ namespace DisplayMetrics // games attempt to render at 60 frames per second at full fidelity. // The decision to render at full fidelity across all platforms and form factors // should be deliberate. - static const bool SupportHighResolutions = false; + static const bool SupportHighResolutions = true; // The default thresholds that define a "high resolution" display. If the thresholds // are exceeded and SupportHighResolutions is false, the dimensions will be scaled @@ -441,7 +441,6 @@ void DX::DeviceResources::UpdateRenderTargetSize() m_effectiveDpi /= 2.0f; } } - // Calculate the necessary render target size in pixels. m_outputSize.Width = DX::ConvertDipsToPixels(m_logicalSize.Width, m_effectiveDpi); m_outputSize.Height = DX::ConvertDipsToPixels(m_logicalSize.Height, m_effectiveDpi); diff --git a/UWP/Common/DeviceResources.h b/UWP/Common/DeviceResources.h index 92ff6f3e14..8942c49014 100644 --- a/UWP/Common/DeviceResources.h +++ b/UWP/Common/DeviceResources.h @@ -29,7 +29,8 @@ namespace DX // The size of the render target, in dips. Windows::Foundation::Size GetLogicalSize() const { return m_logicalSize; } - float GetDpi() const { return m_effectiveDpi; } + float GetDpi() const { return m_effectiveDpi; } + float GetActualDpi() const { return m_dpi; } // D3D Accessors. ID3D11Device3* GetD3DDevice() const { return m_d3dDevice.Get(); } @@ -86,7 +87,7 @@ namespace DX Windows::Foundation::Size m_logicalSize; Windows::Graphics::Display::DisplayOrientations m_nativeOrientation; Windows::Graphics::Display::DisplayOrientations m_currentOrientation; - float m_dpi; + float m_dpi; // This is the DPI that will be reported back to the app. It takes into account whether the app supports high resolution screens or not. float m_effectiveDpi; diff --git a/UWP/NativeUWP/NativeUWP.vcxproj b/UWP/NativeUWP/NativeUWP.vcxproj index 6ee7de506e..9c453f9e44 100644 --- a/UWP/NativeUWP/NativeUWP.vcxproj +++ b/UWP/NativeUWP/NativeUWP.vcxproj @@ -1163,7 +1163,6 @@ - diff --git a/UWP/NativeUWP/NativeUWP.vcxproj.filters b/UWP/NativeUWP/NativeUWP.vcxproj.filters index e5f654a8fc..46cc23aaa7 100644 --- a/UWP/NativeUWP/NativeUWP.vcxproj.filters +++ b/UWP/NativeUWP/NativeUWP.vcxproj.filters @@ -220,9 +220,6 @@ ext\vjson - - ext\vjson - ext\libzip diff --git a/UWP/PPSSPP_UWPMain.cpp b/UWP/PPSSPP_UWPMain.cpp index 6a24bcb855..92a00d69ff 100644 --- a/UWP/PPSSPP_UWPMain.cpp +++ b/UWP/PPSSPP_UWPMain.cpp @@ -26,6 +26,7 @@ #include "UWPHost.h" #include "UWPUtil.h" #include "StorageFileLoader.h" +#include "App.h" using namespace UWP; using namespace Windows::Foundation; @@ -121,7 +122,7 @@ PPSSPP_UWPMain::PPSSPP_UWPMain(App ^app, const std::shared_ptrLocalFolder->Path->Data()); - + NativeInit(1, argv, "", "", cacheFolder.c_str(), false); NativeInitGraphics(ctx_.get()); @@ -145,10 +146,10 @@ PPSSPP_UWPMain::~PPSSPP_UWPMain() { // Updates application state when the window size changes (e.g. device orientation change) void PPSSPP_UWPMain::CreateWindowSizeDependentResources() { - // TODO: Replace this with the size-dependent initialization of your app's content. ctx_->GetDrawContext()->HandleEvent(Draw::Event::LOST_BACKBUFFER, 0, 0, nullptr); NativeResized(); + int width = m_deviceResources->GetScreenViewport().Width; int height = m_deviceResources->GetScreenViewport().Height; ctx_->GetDrawContext()->HandleEvent(Draw::Event::GOT_BACKBUFFER, width, height, m_deviceResources->GetBackBufferRenderTargetView()); @@ -169,8 +170,12 @@ bool PPSSPP_UWPMain::Render() { time_update(); auto context = m_deviceResources->GetD3DDeviceContext(); - // Reset the viewport to target the whole screen. - auto viewport = m_deviceResources->GetScreenViewport(); + auto bounds = Windows::UI::ViewManagement::ApplicationView::GetForCurrentView()->VisibleBounds; + + int boundTop = bounds.Top; + int boundLeft = bounds.Left; + int boundedWidth = bounds.Width; + int boundedHeight = bounds.Height; switch (m_deviceResources->ComputeDisplayRotation()) { case DXGI_MODE_ROTATION_IDENTITY: g_display_rotation = DisplayRotation::ROTATE_0; break; @@ -181,6 +186,9 @@ bool PPSSPP_UWPMain::Render() { // Not super elegant but hey. memcpy(&g_display_rot_matrix, &m_deviceResources->GetOrientationTransform3D(), sizeof(float) * 16); + // Reset the viewport to target the whole screen. + auto viewport = m_deviceResources->GetScreenViewport(); + pixel_xres = viewport.Width; pixel_yres = viewport.Height; @@ -189,14 +197,15 @@ bool PPSSPP_UWPMain::Render() { std::swap(pixel_xres, pixel_yres); } - g_dpi = m_deviceResources->GetDpi(); + g_dpi = m_deviceResources->GetActualDpi(); + pixel_xres = (g_dpi / 96.0f) * boundedWidth; + pixel_yres = (g_dpi / 96.0f) * boundedHeight; if (System_GetPropertyInt(SYSPROP_DEVICE_TYPE) == DEVICE_TYPE_MOBILE) { // Boost DPI a bit to look better. - g_dpi_scale = 120.0f / g_dpi; - } else { - g_dpi_scale = 96.0f / g_dpi; + g_dpi *= 96.0f / 136.0f; } + g_dpi_scale = 96.0f / g_dpi; pixel_in_dps = 1.0f / g_dpi_scale; @@ -260,30 +269,29 @@ void PPSSPP_UWPMain::OnMouseWheel(float delta) { NativeKey(keyInput); } -void PPSSPP_UWPMain::RotateXYToDisplay(float &x, float &y) { - switch (m_deviceResources->ComputeDisplayRotation()) { - case DXGI_MODE_ROTATION_IDENTITY: - // Nothing to do here. - break; - case DXGI_MODE_ROTATION_ROTATE90: - // TODO - break; - case DXGI_MODE_ROTATION_ROTATE180: - x = m_deviceResources->GetScreenViewport().Width - x; - y = m_deviceResources->GetScreenViewport().Height - y; - break; - case DXGI_MODE_ROTATION_ROTATE270: - // TODO - break; +bool PPSSPP_UWPMain::OnHardwareButton(HardwareButton button) { + KeyInput keyInput{}; + keyInput.deviceId = DEVICE_ID_KEYBOARD; + keyInput.flags = KEY_DOWN | KEY_UP; + switch (button) { + case HardwareButton::BACK: + keyInput.keyCode = NKCODE_BACK; + return NativeKey(keyInput); + default: + return false; } } void PPSSPP_UWPMain::OnTouchEvent(int touchEvent, int touchId, float x, float y, double timestamp) { + // We get the coordinate in Windows' device independent pixels already. So let's undo that, + // and then apply our own "dpi". + float dpiFactor = m_deviceResources->GetActualDpi() / 96.0f; + dpiFactor /= pixel_in_dps; + TouchInput input{}; input.id = touchId; - RotateXYToDisplay(x, y); - input.x = x * pixel_in_dps; - input.y = y * pixel_in_dps; + input.x = x * dpiFactor; + input.y = y * dpiFactor; input.flags = touchEvent; input.timestamp = timestamp; NativeTouch(input); @@ -360,8 +368,10 @@ int System_GetPropertyInt(SystemProperty prop) { #else return DEVICE_TYPE_DESKTOP; #endif + case SYSPROP_HAS_BACK_BUTTON: + return 1; case SYSPROP_HAS_FILE_BROWSER: - return true; + return 1; default: return -1; } @@ -389,16 +399,6 @@ void System_SendMessage(const char *command, const char *parameter) { if (file) { g_main->LoadStorageFile(file); } - /* - std::thread([file] { - create_task(file->OpenReadAsync()).then([](IRandomAccessStreamWithContentType^ imgStream) { - imgStream->Seek(0); - IBuffer ^buffer = ref new Streams::Buffer(2048); - auto readTask = create_task(imgStream->ReadAsync(buffer, 2048, InputStreamOptions::None)); - readTask.wait(); - }); - }).detach(); - */ }); } } @@ -441,7 +441,7 @@ bool System_InputBoxGetWString(const wchar_t *title, const std::wstring &default return false; } -// Emulation of TlsAlloc for Windows 10. Used by glslang. +// Emulation of TlsAlloc for Windows 10. Used by glslang. Doesn't actually seem to work, other than fixing the linking errors? extern "C" { DWORD WINAPI __imp_TlsAlloc() { diff --git a/UWP/PPSSPP_UWPMain.h b/UWP/PPSSPP_UWPMain.h index 97da7997b9..3b38deeb3d 100644 --- a/UWP/PPSSPP_UWPMain.h +++ b/UWP/PPSSPP_UWPMain.h @@ -12,6 +12,7 @@ namespace UWP { ref class App; +enum class HardwareButton; class UWPGraphicsContext : public GraphicsContext { public: @@ -50,6 +51,7 @@ public: void OnMouseWheel(float delta); + bool OnHardwareButton(HardwareButton button); void RotateXYToDisplay(float &x, float &y); diff --git a/UWP/UWP.vcxproj b/UWP/UWP.vcxproj index 4920c3480e..1eb7303395 100644 --- a/UWP/UWP.vcxproj +++ b/UWP/UWP.vcxproj @@ -117,9 +117,11 @@ + + @@ -127,9 +129,11 @@ + + @@ -137,9 +141,11 @@ + + @@ -470,6 +476,9 @@ copy AssetsGold\*.* Assets /Y true + + + diff --git a/Windows/main.cpp b/Windows/main.cpp index c9b3c1ad02..bf77d68fcb 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -214,6 +214,8 @@ int System_GetPropertyInt(SystemProperty prop) { return ScreenDPI(); case SYSPROP_HAS_FILE_BROWSER: return true; + case SYSPROP_HAS_BACK_BUTTON: + return 1; default: return -1; } diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index 239e687647..8296b1acce 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -443,6 +443,8 @@ int System_GetPropertyInt(SystemProperty prop) { return (int)(display_hz * 1000.0); case SYSPROP_SUPPORTS_PERMISSIONS: return androidVersion >= 23; // 6.0 Marshmallow introduced run time permissions. + case SYSPROP_HAS_BACK_BUTTON: + return 1; default: return -1; } diff --git a/ext/native/base/NativeApp.h b/ext/native/base/NativeApp.h index 588b3d482e..6de2e92ed2 100644 --- a/ext/native/base/NativeApp.h +++ b/ext/native/base/NativeApp.h @@ -153,6 +153,7 @@ enum SystemProperty { SYSPROP_GPUDRIVER_VERSION, SYSPROP_HAS_FILE_BROWSER, + SYSPROP_HAS_BACK_BUTTON, // Available as Int: SYSPROP_SYSTEMVERSION, diff --git a/ext/native/base/PCMain.cpp b/ext/native/base/PCMain.cpp index fa47e7abfc..ad856bf75b 100644 --- a/ext/native/base/PCMain.cpp +++ b/ext/native/base/PCMain.cpp @@ -339,6 +339,8 @@ int System_GetPropertyInt(SystemProperty prop) { #else return DEVICE_TYPE_DESKTOP; #endif + case SYSPROP_HAS_BACK_BUTTON: + return 1; default: return -1; } diff --git a/ext/native/base/QtMain.cpp b/ext/native/base/QtMain.cpp index 10f651e62b..d59e18b251 100644 --- a/ext/native/base/QtMain.cpp +++ b/ext/native/base/QtMain.cpp @@ -77,6 +77,8 @@ int System_GetPropertyInt(SystemProperty prop) { #else return DEVICE_TYPE_DESKTOP; #endif + case SYSPROP_HAS_BACK_BUTTON: + return 1; default: return -1; } diff --git a/ios/main.mm b/ios/main.mm index ceffaceca8..97a99d2d0b 100644 --- a/ios/main.mm +++ b/ios/main.mm @@ -66,6 +66,8 @@ int System_GetPropertyInt(SystemProperty prop) { return 60000; case SYSPROP_DEVICE_TYPE: return DEVICE_TYPE_MOBILE; + case SYSPROP_HAS_BACK_BUTTON: + return 0; default: return -1; }