mirror of
https://github.com/elasota/Aerofoil.git
synced 2025-09-23 06:53:43 +00:00
Override alt-enter behavior, use borderless fullscreen instead of exclusive fullscreen. This should fix the game breaking when bringing up the open file dialog in fullscreen.
(Note that this doesn't handle resolution changes yet)
This commit is contained in:
@@ -94,9 +94,9 @@ void GpAppEnvironment::Render()
|
||||
GpAppInterface_Get()->PL_Render(m_displayDriver);
|
||||
}
|
||||
|
||||
bool GpAppEnvironment::AdjustRequestedResolution(unsigned int &width, unsigned int &height)
|
||||
bool GpAppEnvironment::AdjustRequestedResolution(uint32_t &physicalWidth, uint32_t &physicalHeight, uint32_t &virtualWidth, uint32_t &virtualheight, float &pixelScaleX, float &pixelScaleY)
|
||||
{
|
||||
return GpAppInterface_Get()->PL_AdjustRequestedResolution(width, height);
|
||||
return GpAppInterface_Get()->PL_AdjustRequestedResolution(physicalWidth, physicalHeight, virtualWidth, virtualheight, pixelScaleX, pixelScaleY);
|
||||
}
|
||||
|
||||
void GpAppEnvironment::SetDisplayDriver(IGpDisplayDriver *displayDriver)
|
||||
@@ -175,6 +175,10 @@ void GpAppEnvironment::DispatchSystemCall(PortabilityLayer::HostSuspendCallID ca
|
||||
m_applicationState = ApplicationState_TimedSuspend;
|
||||
m_delaySuspendTicks = args[0].m_uint;
|
||||
break;
|
||||
case PortabilityLayer::HostSuspendCallID_CallOnVOSThread:
|
||||
args[0].m_functionPtr(static_cast<const PortabilityLayer::HostSuspendCallArgument*>(args[1].m_constPointer), static_cast<PortabilityLayer::HostSuspendCallArgument*>(args[2].m_pointer));
|
||||
m_applicationState = ApplicationState_Running;
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
|
@@ -28,7 +28,7 @@ public:
|
||||
|
||||
GpDisplayDriverTickStatus_t Tick(IGpFiber *vosFiber);
|
||||
void Render();
|
||||
bool AdjustRequestedResolution(unsigned int &width, unsigned int &height);
|
||||
bool AdjustRequestedResolution(uint32_t &physicalWidth, uint32_t &physicalHeight, uint32_t &virtualWidth, uint32_t &virtualheight, float &pixelScaleX, float &pixelScaleY);
|
||||
|
||||
void SetDisplayDriver(IGpDisplayDriver *displayDriver);
|
||||
void SetAudioDriver(IGpAudioDriver *audioDriver);
|
||||
|
@@ -13,6 +13,8 @@
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
extern GpWindowsGlobals g_gpWindowsGlobals;
|
||||
|
||||
class GpDirectoryCursor_Win32 final : public PortabilityLayer::HostDirectoryCursor
|
||||
{
|
||||
public:
|
||||
@@ -307,6 +309,7 @@ bool GpFileSystem_Win32::PromptSaveFile(PortabilityLayer::VirtualDirectory_t vir
|
||||
ofn.nMaxFile = MAX_PATH;
|
||||
ofn.lpstrInitialDir = baseDir;
|
||||
ofn.Flags = OFN_EXPLORER | OFN_NOCHANGEDIR | OFN_OVERWRITEPROMPT;
|
||||
ofn.hwndOwner = g_gpWindowsGlobals.m_hwnd;
|
||||
|
||||
if (!GetSaveFileNameW(&ofn))
|
||||
return false;
|
||||
@@ -387,6 +390,7 @@ bool GpFileSystem_Win32::PromptOpenFile(PortabilityLayer::VirtualDirectory_t vir
|
||||
ofn.nMaxFile = MAX_PATH;
|
||||
ofn.lpstrInitialDir = baseDir;
|
||||
ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST;
|
||||
ofn.hwndOwner = g_gpWindowsGlobals.m_hwnd;
|
||||
|
||||
if (!GetOpenFileNameW(&ofn))
|
||||
return false;
|
||||
|
@@ -28,9 +28,9 @@ namespace
|
||||
static_cast<GpAppEnvironment*>(context)->Render();
|
||||
}
|
||||
|
||||
bool AdjustRequestedResolution(void *context, unsigned int &width, unsigned int &height)
|
||||
bool AdjustRequestedResolution(void *context, uint32_t &physicalWidth, uint32_t &physicalHeight, uint32_t &virtualWidth, uint32_t &virtualheight, float &pixelScaleX, float &pixelScaleY)
|
||||
{
|
||||
return static_cast<GpAppEnvironment*>(context)->AdjustRequestedResolution(width, height);
|
||||
return static_cast<GpAppEnvironment*>(context)->AdjustRequestedResolution(physicalWidth, physicalHeight, virtualWidth, virtualheight, pixelScaleX, pixelScaleY);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -24,7 +24,7 @@ extern "C" __declspec(dllimport) IGpAudioDriver *GpDriver_CreateAudioDriver_XAud
|
||||
extern "C" __declspec(dllimport) IGpDisplayDriver *GpDriver_CreateDisplayDriver_D3D11(const GpDisplayDriverProperties &properties);
|
||||
extern "C" __declspec(dllimport) IGpInputDriver *GpDriver_CreateInputDriver_XInput(const GpInputDriverProperties &properties);
|
||||
|
||||
static void PostMouseEvent(IGpVOSEventQueue *eventQueue, GpMouseEventType_t eventType, GpMouseButton_t button, int32_t x, int32_t y)
|
||||
static void PostMouseEvent(IGpVOSEventQueue *eventQueue, GpMouseEventType_t eventType, GpMouseButton_t button, int32_t x, int32_t y, float pixelScaleX, float pixelScaleY)
|
||||
{
|
||||
if (GpVOSEvent *evt = eventQueue->QueueEvent())
|
||||
{
|
||||
@@ -35,6 +35,12 @@ static void PostMouseEvent(IGpVOSEventQueue *eventQueue, GpMouseEventType_t even
|
||||
mEvent.m_x = x;
|
||||
mEvent.m_y = y;
|
||||
mEvent.m_eventType = eventType;
|
||||
|
||||
if (pixelScaleX != 1.0f)
|
||||
mEvent.m_x = static_cast<int32_t>(static_cast<float>(x) / pixelScaleX);
|
||||
|
||||
if (pixelScaleY != 1.0f)
|
||||
mEvent.m_y = static_cast<int32_t>(static_cast<float>(y) / pixelScaleX);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -291,7 +297,7 @@ static void PostKeyboardEvent(IGpVOSEventQueue *eventQueue, GpKeyboardInputEvent
|
||||
}
|
||||
}
|
||||
|
||||
static void TranslateWindowsMessage(const MSG *msg, IGpVOSEventQueue *eventQueue)
|
||||
static void TranslateWindowsMessage(const MSG *msg, IGpVOSEventQueue *eventQueue, float pixelScaleX, float pixelScaleY)
|
||||
{
|
||||
WPARAM wParam = msg->wParam;
|
||||
LPARAM lParam = msg->lParam;
|
||||
@@ -299,40 +305,40 @@ static void TranslateWindowsMessage(const MSG *msg, IGpVOSEventQueue *eventQueue
|
||||
switch (msg->message)
|
||||
{
|
||||
case WM_LBUTTONDOWN:
|
||||
PostMouseEvent(eventQueue, GpMouseEventTypes::kDown, GpMouseButtons::kLeft, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
|
||||
PostMouseEvent(eventQueue, GpMouseEventTypes::kDown, GpMouseButtons::kLeft, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), pixelScaleX, pixelScaleY);
|
||||
break;
|
||||
case WM_LBUTTONUP:
|
||||
PostMouseEvent(eventQueue, GpMouseEventTypes::kUp, GpMouseButtons::kLeft, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
|
||||
PostMouseEvent(eventQueue, GpMouseEventTypes::kUp, GpMouseButtons::kLeft, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), pixelScaleX, pixelScaleY);
|
||||
break;
|
||||
case WM_MBUTTONDOWN:
|
||||
PostMouseEvent(eventQueue, GpMouseEventTypes::kDown, GpMouseButtons::kMiddle, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
|
||||
PostMouseEvent(eventQueue, GpMouseEventTypes::kDown, GpMouseButtons::kMiddle, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), pixelScaleX, pixelScaleY);
|
||||
break;
|
||||
case WM_MBUTTONUP:
|
||||
PostMouseEvent(eventQueue, GpMouseEventTypes::kUp, GpMouseButtons::kMiddle, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
|
||||
PostMouseEvent(eventQueue, GpMouseEventTypes::kUp, GpMouseButtons::kMiddle, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), pixelScaleX, pixelScaleY);
|
||||
break;
|
||||
case WM_RBUTTONDOWN:
|
||||
PostMouseEvent(eventQueue, GpMouseEventTypes::kDown, GpMouseButtons::kRight, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
|
||||
PostMouseEvent(eventQueue, GpMouseEventTypes::kDown, GpMouseButtons::kRight, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), pixelScaleX, pixelScaleY);
|
||||
break;
|
||||
case WM_RBUTTONUP:
|
||||
PostMouseEvent(eventQueue, GpMouseEventTypes::kUp, GpMouseButtons::kRight, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
|
||||
PostMouseEvent(eventQueue, GpMouseEventTypes::kUp, GpMouseButtons::kRight, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), pixelScaleX, pixelScaleY);
|
||||
break;
|
||||
case WM_XBUTTONDOWN:
|
||||
if (GET_XBUTTON_WPARAM(wParam) == XBUTTON1)
|
||||
PostMouseEvent(eventQueue, GpMouseEventTypes::kDown, GpMouseButtons::kX1, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
|
||||
PostMouseEvent(eventQueue, GpMouseEventTypes::kDown, GpMouseButtons::kX1, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), pixelScaleX, pixelScaleY);
|
||||
else if (GET_XBUTTON_WPARAM(wParam) == XBUTTON2)
|
||||
PostMouseEvent(eventQueue, GpMouseEventTypes::kDown, GpMouseButtons::kX2, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
|
||||
PostMouseEvent(eventQueue, GpMouseEventTypes::kDown, GpMouseButtons::kX2, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), pixelScaleX, pixelScaleY);
|
||||
break;
|
||||
case WM_XBUTTONUP:
|
||||
if (GET_XBUTTON_WPARAM(wParam) == XBUTTON1)
|
||||
PostMouseEvent(eventQueue, GpMouseEventTypes::kUp, GpMouseButtons::kX1, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
|
||||
PostMouseEvent(eventQueue, GpMouseEventTypes::kUp, GpMouseButtons::kX1, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), pixelScaleX, pixelScaleY);
|
||||
else if (GET_XBUTTON_WPARAM(wParam) == XBUTTON2)
|
||||
PostMouseEvent(eventQueue, GpMouseEventTypes::kUp, GpMouseButtons::kX2, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
|
||||
PostMouseEvent(eventQueue, GpMouseEventTypes::kUp, GpMouseButtons::kX2, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), pixelScaleX, pixelScaleY);
|
||||
break;
|
||||
case WM_MOUSEMOVE:
|
||||
PostMouseEvent(eventQueue, GpMouseEventTypes::kMove, GpMouseButtons::kNone, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
|
||||
PostMouseEvent(eventQueue, GpMouseEventTypes::kMove, GpMouseButtons::kNone, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), pixelScaleX, pixelScaleY);
|
||||
break;
|
||||
case WM_MOUSELEAVE:
|
||||
PostMouseEvent(eventQueue, GpMouseEventTypes::kLeave, GpMouseButtons::kNone, 0, 0);
|
||||
PostMouseEvent(eventQueue, GpMouseEventTypes::kLeave, GpMouseButtons::kNone, 0, 0, pixelScaleX, pixelScaleY);
|
||||
break;
|
||||
case WM_KEYDOWN:
|
||||
case WM_SYSKEYDOWN:
|
||||
@@ -388,6 +394,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
||||
g_gpWindowsGlobals.m_cmdLine = lpCmdLine;
|
||||
g_gpWindowsGlobals.m_nCmdShow = nCmdShow;
|
||||
g_gpWindowsGlobals.m_baseDir = GpFileSystem_Win32::GetInstance()->GetBasePath();
|
||||
g_gpWindowsGlobals.m_hwnd = nullptr;
|
||||
|
||||
g_gpWindowsGlobals.m_createFiberFunc = GpFiber_Win32::Create;
|
||||
g_gpWindowsGlobals.m_loadCursorFunc = GpCursor_Win32::Load;
|
||||
|
@@ -17,6 +17,8 @@
|
||||
#include "IGpDisplayDriver.h"
|
||||
#include "WindowManager.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#define kSwitchDepthAlert 130
|
||||
#define kSetMemoryAlert 180
|
||||
#define kLowMemoryAlert 181
|
||||
@@ -344,8 +346,20 @@ public:
|
||||
HandleResolutionChange(prevWidth, prevHeight, newWidth, newHeight);
|
||||
}
|
||||
|
||||
void AdjustRequestedResolution(uint32_t &width, uint32_t &height) override
|
||||
void AdjustRequestedResolution(uint32_t &physicalWidth, uint32_t &physicalHeight, uint32_t &virtualWidth, uint32_t &virtualHeight, float &pixelScaleX, float &pixelScaleY) override
|
||||
{
|
||||
double xMul = static_cast<double>(physicalWidth) / 640;
|
||||
double yMul = static_cast<double>(physicalHeight) / 480;
|
||||
|
||||
xMul = floor(xMul);
|
||||
yMul = floor(yMul);
|
||||
|
||||
double minMul = std::max<double>(1.0, std::min(xMul, yMul));
|
||||
|
||||
virtualWidth = physicalWidth / minMul;
|
||||
virtualHeight = physicalHeight / minMul;
|
||||
pixelScaleX = static_cast<float>(minMul);
|
||||
pixelScaleY = static_cast<float>(minMul);
|
||||
}
|
||||
|
||||
static GpAppResolutionChangeHandler ms_instance;
|
||||
|
@@ -25,7 +25,7 @@ public:
|
||||
void PL_HostFontHandler_SetInstance(PortabilityLayer::HostFontHandler *instance) override;
|
||||
void PL_HostVOSEventQueue_SetInstance(PortabilityLayer::HostVOSEventQueue *instance) override;
|
||||
void PL_InstallHostSuspendHook(PortabilityLayer::HostSuspendHook_t hook, void *context) override;
|
||||
bool PL_AdjustRequestedResolution(unsigned int &width, unsigned int &height) override;
|
||||
bool PL_AdjustRequestedResolution(uint32_t &physicalWidth, uint32_t &physicalHeight, uint32_t &virtualWidth, uint32_t &virtualheight, float &pixelScaleX, float &pixelScaleY) override;
|
||||
};
|
||||
|
||||
|
||||
@@ -80,18 +80,14 @@ void GpAppInterfaceImpl::PL_InstallHostSuspendHook(PortabilityLayer::HostSuspend
|
||||
PortabilityLayer::InstallHostSuspendHook(hook, context);
|
||||
}
|
||||
|
||||
bool GpAppInterfaceImpl::PL_AdjustRequestedResolution(unsigned int &width, unsigned int &height)
|
||||
bool GpAppInterfaceImpl::PL_AdjustRequestedResolution(uint32_t &physicalWidth, uint32_t &physicalHeight, uint32_t &virtualWidth, uint32_t &virtualheight, float &pixelScaleX, float &pixelScaleY)
|
||||
{
|
||||
PortabilityLayer::DisplayDeviceManager::IResolutionChangeHandler *handler = PortabilityLayer::DisplayDeviceManager::GetInstance()->GetResolutionChangeHandler();
|
||||
|
||||
if (!handler)
|
||||
return false;
|
||||
|
||||
uint32_t w32 = width;
|
||||
uint32_t h32 = height;
|
||||
handler->AdjustRequestedResolution(w32, h32);
|
||||
width = w32;
|
||||
height = h32;
|
||||
handler->AdjustRequestedResolution(physicalWidth, physicalHeight, virtualWidth, virtualheight, pixelScaleX, pixelScaleY);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@@ -3,6 +3,8 @@
|
||||
#include "EGpDisplayDriverType.h"
|
||||
#include "GpDisplayDriverTickStatus.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct IGpDisplayDriver;
|
||||
struct IGpFiber;
|
||||
struct IGpVOSEventQueue;
|
||||
@@ -11,7 +13,7 @@ struct GpDisplayDriverProperties
|
||||
{
|
||||
typedef GpDisplayDriverTickStatus_t (*TickFunc_t)(void *context, IGpFiber *vosFiber);
|
||||
typedef void(*RenderFunc_t)(void *context);
|
||||
typedef bool(*AdjustRequestedResolutionFunc_t)(void *context, unsigned int &width, unsigned int &height);
|
||||
typedef bool(*AdjustRequestedResolutionFunc_t)(void *context, uint32_t &physicalWidth, uint32_t &physicalHeight, uint32_t &virtualWidth, uint32_t &virtualheight, float &pixelScaleX, float &pixelScaleY);
|
||||
|
||||
EGpDisplayDriverType m_type;
|
||||
|
||||
|
@@ -21,9 +21,10 @@ struct GpWindowsGlobals
|
||||
HINSTANCE m_hPrevInstance;
|
||||
LPCSTR m_cmdLine;
|
||||
LPCWSTR m_baseDir;
|
||||
HWND m_hwnd;
|
||||
int m_nCmdShow;
|
||||
|
||||
IGpFiber *(*m_createFiberFunc)(LPVOID fiber);
|
||||
IGpCursor_Win32 *(*m_loadCursorFunc)(const wchar_t *path);
|
||||
void (*m_translateWindowsMessageFunc)(const MSG *msg, IGpVOSEventQueue *eventQueue);
|
||||
void (*m_translateWindowsMessageFunc)(const MSG *msg, IGpVOSEventQueue *eventQueue, float pixelScaleX, float pixelScaleY);
|
||||
};
|
||||
|
@@ -25,4 +25,6 @@ public:
|
||||
virtual void UpdatePalette(const void *paletteData) = 0;
|
||||
|
||||
virtual void SetBackgroundColor(uint8_t r, uint8_t g, uint8_t b, uint8_t a) = 0;
|
||||
|
||||
virtual void RequestToggleFullScreen(uint32_t timestamp) = 0;
|
||||
};
|
||||
|
@@ -102,11 +102,9 @@ bool InitSwapChainForWindow(HWND hWnd, ID3D11Device *device, GpComPtr<IDXGISwapC
|
||||
if (result != S_OK)
|
||||
return false;
|
||||
|
||||
#if 0
|
||||
result = dxgiFactory->MakeWindowAssociation(hWnd, DXGI_MWA_NO_ALT_ENTER);
|
||||
if (result != S_OK)
|
||||
return false;
|
||||
#endif
|
||||
|
||||
outSwapChain = swapChain;
|
||||
|
||||
@@ -413,8 +411,8 @@ GpDisplayDriverTickStatus_t GpDisplayDriverD3D11::PresentFrameAndSync()
|
||||
D3D11_VIEWPORT viewport;
|
||||
viewport.TopLeftX = 0;
|
||||
viewport.TopLeftY = 0;
|
||||
viewport.Width = static_cast<FLOAT>(m_windowWidth);
|
||||
viewport.Height = static_cast<FLOAT>(m_windowHeight);
|
||||
viewport.Width = static_cast<FLOAT>(m_windowWidthPhysical);
|
||||
viewport.Height = static_cast<FLOAT>(m_windowHeightPhysical);
|
||||
viewport.MinDepth = 0.0f;
|
||||
viewport.MaxDepth = 1.0f;
|
||||
|
||||
@@ -592,7 +590,7 @@ void GpDisplayDriverD3D11::ChangeToCursor(HCURSOR cursor)
|
||||
if (m_mouseIsInClientArea)
|
||||
::SetCursor(cursor);
|
||||
|
||||
SetClassLongPtrW(m_hwnd, GCLP_HCURSOR, reinterpret_cast<LONG_PTR>(cursor));
|
||||
SetClassLongPtrW(m_osGlobals->m_hwnd, GCLP_HCURSOR, reinterpret_cast<LONG_PTR>(cursor));
|
||||
}
|
||||
|
||||
void GpDisplayDriverD3D11::ChangeToStandardCursor(EGpStandardCursor_t cursor)
|
||||
@@ -612,6 +610,105 @@ void GpDisplayDriverD3D11::ChangeToStandardCursor(EGpStandardCursor_t cursor)
|
||||
}
|
||||
}
|
||||
|
||||
void GpDisplayDriverD3D11::BecomeFullScreen(LONG &windowStyle)
|
||||
{
|
||||
assert(!m_isFullScreen);
|
||||
|
||||
RECT windowRect;
|
||||
if (!GetWindowRect(m_osGlobals->m_hwnd, &windowRect))
|
||||
return; // ???
|
||||
|
||||
HMONITOR monitor = MonitorFromRect(&windowRect, MONITOR_DEFAULTTONULL);
|
||||
if (!monitor)
|
||||
{
|
||||
// If the window is off-screen, use the primary monitor
|
||||
monitor = MonitorFromRect(&windowRect, MONITOR_DEFAULTTOPRIMARY);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise, use the nearest
|
||||
monitor = MonitorFromRect(&windowRect, MONITOR_DEFAULTTONEAREST);
|
||||
}
|
||||
|
||||
if (!monitor)
|
||||
return; // No monitor?
|
||||
|
||||
MONITORINFO monitorInfo;
|
||||
monitorInfo.cbSize = sizeof(monitorInfo);
|
||||
if (!GetMonitorInfoA(monitor, &monitorInfo))
|
||||
return;
|
||||
|
||||
m_windowModeRevertRect = windowRect;
|
||||
SetWindowLongPtr(m_osGlobals->m_hwnd, GWL_STYLE, WS_VISIBLE | WS_POPUP);
|
||||
|
||||
SetWindowPos(m_osGlobals->m_hwnd, HWND_TOP, monitorInfo.rcMonitor.left, monitorInfo.rcMonitor.top, monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left, monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top, SWP_FRAMECHANGED);
|
||||
|
||||
m_isFullScreen = true;
|
||||
windowStyle = (WS_VISIBLE | WS_POPUP);
|
||||
}
|
||||
|
||||
void GpDisplayDriverD3D11::BecomeWindowed(LONG &windowStyle)
|
||||
{
|
||||
assert(m_isFullScreen);
|
||||
|
||||
RECT revertRect = m_windowModeRevertRect;
|
||||
|
||||
HMONITOR monitor = MonitorFromRect(&m_windowModeRevertRect, MONITOR_DEFAULTTONULL);
|
||||
if (!monitor)
|
||||
{
|
||||
// If the window is off-screen, use the primary monitor
|
||||
monitor = MonitorFromRect(&revertRect, MONITOR_DEFAULTTOPRIMARY);
|
||||
if (!monitor)
|
||||
return;
|
||||
|
||||
MONITORINFO monitorInfo;
|
||||
monitorInfo.cbSize = sizeof(monitorInfo);
|
||||
if (!GetMonitorInfoA(monitor, &monitorInfo))
|
||||
return;
|
||||
|
||||
RECT monitorRect = monitorInfo.rcWork;
|
||||
LONG monitorWidth = monitorRect.right - monitorRect.left;
|
||||
LONG monitorHeight = monitorRect.bottom - monitorRect.top;
|
||||
|
||||
LONG revertHeight = revertRect.bottom - revertRect.top;
|
||||
LONG revertWidth = revertRect.right - revertRect.left;
|
||||
|
||||
if (revertWidth > monitorWidth)
|
||||
revertWidth = monitorWidth;
|
||||
|
||||
if (revertHeight > monitorHeight)
|
||||
revertHeight = monitorHeight;
|
||||
|
||||
revertRect.bottom = revertRect.top + revertHeight;
|
||||
revertRect.right = revertRect.right + revertWidth;
|
||||
|
||||
LONG xDelta = 0;
|
||||
if (revertRect.right > monitorRect.right)
|
||||
xDelta = monitorRect.right - revertRect.right;
|
||||
else if (revertRect.left < monitorRect.left)
|
||||
xDelta = monitorRect.left - revertRect.left;
|
||||
|
||||
LONG yDelta = 0;
|
||||
if (revertRect.bottom > monitorRect.bottom)
|
||||
yDelta = monitorRect.bottom - revertRect.bottom;
|
||||
else if (revertRect.top < monitorRect.top)
|
||||
yDelta = monitorRect.top - revertRect.top;
|
||||
|
||||
|
||||
revertRect.left = revertRect.left + xDelta;
|
||||
revertRect.top = revertRect.top + yDelta;
|
||||
revertRect.bottom = revertRect.top + revertHeight;
|
||||
revertRect.right = revertRect.right + revertWidth;
|
||||
}
|
||||
|
||||
SetWindowLongPtr(m_osGlobals->m_hwnd, GWL_STYLE, WS_VISIBLE | WS_OVERLAPPEDWINDOW);
|
||||
|
||||
SetWindowPos(m_osGlobals->m_hwnd, HWND_TOP, revertRect.left, revertRect.top, revertRect.right - revertRect.left, revertRect.bottom - revertRect.top, SWP_FRAMECHANGED);
|
||||
|
||||
m_isFullScreen = false;
|
||||
windowStyle = (WS_VISIBLE | WS_OVERLAPPEDWINDOW);
|
||||
}
|
||||
|
||||
void GpDisplayDriverD3D11::Run()
|
||||
{
|
||||
WNDCLASSEX wc;
|
||||
@@ -638,14 +735,14 @@ void GpDisplayDriverD3D11::Run()
|
||||
HMENU menus = NULL;
|
||||
|
||||
// TODO: Fix the resolution here
|
||||
RECT wr = { 0, 0, m_windowWidth, m_windowHeight };
|
||||
RECT wr = { 0, 0, m_windowWidthPhysical, m_windowHeightPhysical };
|
||||
AdjustWindowRect(&wr, windowStyle, menus != NULL);
|
||||
|
||||
m_hwnd = CreateWindowExW(NULL, L"GPD3D11WindowClass", GP_APPLICATION_NAME_W L" (Direct3D 11)", WS_OVERLAPPEDWINDOW, 300, 300, wr.right - wr.left, wr.bottom - wr.top, NULL, menus, m_osGlobals->m_hInstance, NULL);
|
||||
m_osGlobals->m_hwnd = CreateWindowExW(NULL, L"GPD3D11WindowClass", GP_APPLICATION_NAME_W L" (Direct3D 11)", WS_OVERLAPPEDWINDOW, 300, 300, wr.right - wr.left, wr.bottom - wr.top, NULL, menus, m_osGlobals->m_hInstance, NULL);
|
||||
|
||||
ShowWindow(m_hwnd, m_osGlobals->m_nCmdShow);
|
||||
ShowWindow(m_osGlobals->m_hwnd, m_osGlobals->m_nCmdShow);
|
||||
|
||||
StartD3DForWindow(m_hwnd, m_swapChain, m_device, m_deviceContext);
|
||||
StartD3DForWindow(m_osGlobals->m_hwnd, m_swapChain, m_device, m_deviceContext);
|
||||
|
||||
InitResources();
|
||||
|
||||
@@ -674,7 +771,7 @@ void GpDisplayDriverD3D11::Run()
|
||||
|
||||
tme.cbSize = sizeof(tme);
|
||||
tme.dwFlags = TME_LEAVE;
|
||||
tme.hwndTrack = m_hwnd;
|
||||
tme.hwndTrack = m_osGlobals->m_hwnd;
|
||||
tme.dwHoverTime = HOVER_DEFAULT;
|
||||
TrackMouseEvent(&tme);
|
||||
}
|
||||
@@ -682,38 +779,55 @@ void GpDisplayDriverD3D11::Run()
|
||||
else if (msg.message == WM_MOUSELEAVE)
|
||||
m_mouseIsInClientArea = false;
|
||||
|
||||
m_osGlobals->m_translateWindowsMessageFunc(&msg, m_properties.m_eventQueue);
|
||||
m_osGlobals->m_translateWindowsMessageFunc(&msg, m_properties.m_eventQueue, m_pixelScaleX, m_pixelScaleY);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_isFullScreen != m_isFullScreenDesired)
|
||||
{
|
||||
if (m_isFullScreenDesired)
|
||||
BecomeFullScreen(windowStyle);
|
||||
else
|
||||
BecomeWindowed(windowStyle);
|
||||
}
|
||||
|
||||
RECT clientRect;
|
||||
GetClientRect(m_hwnd, &clientRect);
|
||||
GetClientRect(m_osGlobals->m_hwnd, &clientRect);
|
||||
|
||||
unsigned int desiredWidth = clientRect.right - clientRect.left;
|
||||
unsigned int desiredHeight = clientRect.bottom - clientRect.top;
|
||||
if (clientRect.right - clientRect.left != m_windowWidth || clientRect.bottom - clientRect.top != m_windowHeight)
|
||||
if (clientRect.right - clientRect.left != m_windowWidthPhysical || clientRect.bottom - clientRect.top != m_windowHeightPhysical)
|
||||
{
|
||||
uint32_t prevWidth = m_windowWidth;
|
||||
uint32_t prevHeight = m_windowHeight;
|
||||
uint32_t prevWidth = m_windowWidthPhysical;
|
||||
uint32_t prevHeight = m_windowHeightPhysical;
|
||||
uint32_t virtualWidth = m_windowWidthVirtual;
|
||||
uint32_t virtualHeight = m_windowHeightVirtual;
|
||||
float pixelScaleX = 1.0f;
|
||||
float pixelScaleY = 1.0f;
|
||||
|
||||
if (m_properties.m_adjustRequestedResolutionFunc(m_properties.m_adjustRequestedResolutionFuncContext, desiredWidth, desiredHeight))
|
||||
if (m_properties.m_adjustRequestedResolutionFunc(m_properties.m_adjustRequestedResolutionFuncContext, desiredWidth, desiredHeight, virtualWidth, virtualHeight, pixelScaleX, pixelScaleY))
|
||||
{
|
||||
bool resizedOK = ResizeD3DWindow(m_hwnd, m_windowWidth, m_windowHeight, desiredWidth, desiredHeight, windowStyle, menus);
|
||||
bool resizedOK = ResizeD3DWindow(m_osGlobals->m_hwnd, m_windowWidthPhysical, m_windowHeightPhysical, desiredWidth, desiredHeight, windowStyle, menus);
|
||||
resizedOK = resizedOK && DetachSwapChain();
|
||||
resizedOK = resizedOK && ResizeSwapChain(m_swapChain, m_windowWidth, m_windowHeight);
|
||||
resizedOK = resizedOK && ResizeSwapChain(m_swapChain, m_windowWidthPhysical, m_windowHeightPhysical);
|
||||
resizedOK = resizedOK && InitBackBuffer();
|
||||
|
||||
if (!resizedOK)
|
||||
break; // Critical video driver error, exit
|
||||
|
||||
m_windowWidthVirtual = virtualWidth;
|
||||
m_windowHeightVirtual = virtualHeight;
|
||||
m_pixelScaleX = pixelScaleX;
|
||||
m_pixelScaleY = pixelScaleY;
|
||||
|
||||
if (GpVOSEvent *resizeEvent = m_properties.m_eventQueue->QueueEvent())
|
||||
{
|
||||
resizeEvent->m_eventType = GpVOSEventTypes::kVideoResolutionChanged;
|
||||
resizeEvent->m_event.m_resolutionChangedEvent.m_prevWidth = prevWidth;
|
||||
resizeEvent->m_event.m_resolutionChangedEvent.m_prevHeight = prevHeight;
|
||||
resizeEvent->m_event.m_resolutionChangedEvent.m_newWidth = m_windowWidth;
|
||||
resizeEvent->m_event.m_resolutionChangedEvent.m_newHeight = m_windowHeight;
|
||||
resizeEvent->m_event.m_resolutionChangedEvent.m_newWidth = m_windowWidthVirtual;
|
||||
resizeEvent->m_event.m_resolutionChangedEvent.m_newHeight = m_windowHeightVirtual;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -737,9 +851,9 @@ void GpDisplayDriverD3D11::Shutdown()
|
||||
void GpDisplayDriverD3D11::GetDisplayResolution(unsigned int *width, unsigned int *height, GpPixelFormat_t *pixelFormat)
|
||||
{
|
||||
if (width)
|
||||
*width = m_windowWidth;
|
||||
*width = m_windowWidthVirtual;
|
||||
if (height)
|
||||
*height = m_windowHeight;
|
||||
*height = m_windowHeightVirtual;
|
||||
if (pixelFormat)
|
||||
*pixelFormat = GpPixelFormats::k8BitStandard;
|
||||
}
|
||||
@@ -760,8 +874,8 @@ void GpDisplayDriverD3D11::DrawSurface(IGpDisplayDriverSurface *surface, int32_t
|
||||
//m_deviceContext->OMSetDepthStencilState(m_drawQuadDepthStencilState, 0);
|
||||
|
||||
{
|
||||
const float twoDivWidth = 2.0f / static_cast<float>(m_windowWidth);
|
||||
const float negativeTwoDivHeight = -2.0f / static_cast<float>(m_windowHeight);
|
||||
const float twoDivWidth = 2.0f / static_cast<float>(m_windowWidthVirtual);
|
||||
const float negativeTwoDivHeight = -2.0f / static_cast<float>(m_windowHeightVirtual);
|
||||
|
||||
DrawQuadVertexConstants constantsData;
|
||||
constantsData.m_ndcOriginX = static_cast<float>(x) * twoDivWidth - 1.0f;
|
||||
@@ -906,6 +1020,16 @@ void GpDisplayDriverD3D11::SetBackgroundColor(uint8_t r, uint8_t g, uint8_t b, u
|
||||
m_bgColor[3] = static_cast<float>(a) / 255.0f;
|
||||
}
|
||||
|
||||
void GpDisplayDriverD3D11::RequestToggleFullScreen(uint32_t timestamp)
|
||||
{
|
||||
// Alt-Enter gets re-sent after a full-screen toggle, so we ignore toggle requests until half a second has seconds have elapsed
|
||||
if (timestamp > m_lastFullScreenToggleTimeStamp + 30)
|
||||
{
|
||||
m_isFullScreenDesired = !m_isFullScreenDesired;
|
||||
m_lastFullScreenToggleTimeStamp = timestamp;
|
||||
}
|
||||
}
|
||||
|
||||
GpDisplayDriverD3D11 *GpDisplayDriverD3D11::Create(const GpDisplayDriverProperties &properties)
|
||||
{
|
||||
void *storage = malloc(sizeof(GpDisplayDriverD3D11));
|
||||
@@ -918,8 +1042,12 @@ GpDisplayDriverD3D11 *GpDisplayDriverD3D11::Create(const GpDisplayDriverProperti
|
||||
GpDisplayDriverD3D11::GpDisplayDriverD3D11(const GpDisplayDriverProperties &properties)
|
||||
: m_properties(properties)
|
||||
, m_frameTimeAccumulated(0)
|
||||
, m_windowWidth(640)
|
||||
, m_windowHeight(480)
|
||||
, m_windowWidthPhysical(640)
|
||||
, m_windowHeightPhysical(480)
|
||||
, m_windowWidthVirtual(640)
|
||||
, m_windowHeightVirtual(480)
|
||||
, m_pixelScaleX(1.0f)
|
||||
, m_pixelScaleY(1.0f)
|
||||
, m_vosFiber(nullptr)
|
||||
, m_osGlobals(static_cast<GpWindowsGlobals*>(properties.m_osGlobals))
|
||||
, m_pendingCursor(nullptr)
|
||||
@@ -927,8 +1055,12 @@ GpDisplayDriverD3D11::GpDisplayDriverD3D11(const GpDisplayDriverProperties &prop
|
||||
, m_currentStandardCursor(EGpStandardCursors::kArrow)
|
||||
, m_pendingStandardCursor(EGpStandardCursors::kArrow)
|
||||
, m_mouseIsInClientArea(false)
|
||||
, m_isFullScreen(false)
|
||||
, m_isFullScreenDesired(false)
|
||||
, m_lastFullScreenToggleTimeStamp(0)
|
||||
{
|
||||
memset(&m_syncTimeBase, 0, sizeof(m_syncTimeBase));
|
||||
memset(&m_windowModeRevertRect, 0, sizeof(m_windowModeRevertRect));
|
||||
|
||||
QueryPerformanceFrequency(&m_QPFrequency);
|
||||
|
||||
|
@@ -48,6 +48,8 @@ public:
|
||||
|
||||
void SetBackgroundColor(uint8_t r, uint8_t g, uint8_t b, uint8_t a) override;
|
||||
|
||||
void RequestToggleFullScreen(uint32_t timestamp) override;
|
||||
|
||||
static GpDisplayDriverD3D11 *Create(const GpDisplayDriverProperties &properties);
|
||||
|
||||
private:
|
||||
@@ -81,6 +83,9 @@ private:
|
||||
void ChangeToCursor(HCURSOR cursor);
|
||||
void ChangeToStandardCursor(EGpStandardCursor_t cursor);
|
||||
|
||||
void BecomeFullScreen(LONG &windowStyle);
|
||||
void BecomeWindowed(LONG &windowStyle);
|
||||
|
||||
GpComPtr<IDXGISwapChain1> m_swapChain;
|
||||
GpComPtr<ID3D11Device> m_device;
|
||||
GpComPtr<ID3D11DeviceContext> m_deviceContext;
|
||||
@@ -108,11 +113,20 @@ private:
|
||||
UINT m_expectedSyncDelta;
|
||||
bool m_isResettingSwapChain;
|
||||
|
||||
bool m_isFullScreen;
|
||||
bool m_isFullScreenDesired;
|
||||
RECT m_windowModeRevertRect;
|
||||
uint32_t m_lastFullScreenToggleTimeStamp;
|
||||
|
||||
LONGLONG m_frameTimeAccumulated;
|
||||
LONGLONG m_frameTimeSliceSize;
|
||||
|
||||
DWORD m_windowWidth;
|
||||
DWORD m_windowHeight;
|
||||
DWORD m_windowWidthPhysical; // Physical resolution is the resolution of the actual window
|
||||
DWORD m_windowHeightPhysical;
|
||||
DWORD m_windowWidthVirtual; // Virtual resolution is the resolution reported to teh game
|
||||
DWORD m_windowHeightVirtual;
|
||||
float m_pixelScaleX;
|
||||
float m_pixelScaleY;
|
||||
|
||||
IGpCursor_Win32 *m_activeCursor;
|
||||
IGpCursor_Win32 *m_pendingCursor;
|
||||
@@ -126,7 +140,6 @@ private:
|
||||
HCURSOR m_arrowCursor;
|
||||
HCURSOR m_waitCursor;
|
||||
HCURSOR m_ibeamCursor;
|
||||
HWND m_hwnd;
|
||||
|
||||
float m_bgColor[4];
|
||||
};
|
||||
|
@@ -15,7 +15,7 @@ namespace PortabilityLayer
|
||||
struct IResolutionChangeHandler
|
||||
{
|
||||
virtual void OnResolutionChanged(uint32_t prevWidth, uint32_t prevHeight, uint32_t newWidth, uint32_t newHeight) = 0;
|
||||
virtual void AdjustRequestedResolution(uint32_t &width, uint32_t &height) = 0;
|
||||
virtual void AdjustRequestedResolution(uint32_t &physicalWidth, uint32_t &physicalHeight, uint32_t &virtualWidth, uint32_t &virtualheight, float &pixelScaleX, float &pixelScaleY) = 0;
|
||||
};
|
||||
|
||||
virtual void Init() = 0;
|
||||
|
@@ -6,6 +6,7 @@
|
||||
#include "MacFileMem.h"
|
||||
#include "PLPasStr.h"
|
||||
#include "PLErrorCodes.h"
|
||||
#include "PLSysCalls.h"
|
||||
#include "ResTypeID.h"
|
||||
#include "HostSystemServices.h"
|
||||
|
||||
@@ -184,7 +185,7 @@ namespace PortabilityLayer
|
||||
|
||||
bool FileManagerImpl::PromptOpenFile(VirtualDirectory_t dirID, char *path, size_t &outPathLength, size_t pathCapacity)
|
||||
{
|
||||
return PortabilityLayer::HostFileSystem::GetInstance()->PromptOpenFile(dirID, path, outPathLength, pathCapacity);
|
||||
return PLSysCalls::PromptOpenFile(dirID, path, outPathLength, pathCapacity);
|
||||
}
|
||||
|
||||
FileManagerImpl *FileManagerImpl::GetInstance()
|
||||
|
@@ -46,7 +46,7 @@ public:
|
||||
virtual void PL_HostVOSEventQueue_SetInstance(PortabilityLayer::HostVOSEventQueue *instance) = 0;
|
||||
|
||||
virtual void PL_InstallHostSuspendHook(PortabilityLayer::HostSuspendHook_t hook, void *context) = 0;
|
||||
virtual bool PL_AdjustRequestedResolution(unsigned int &width, unsigned int &height) = 0;
|
||||
virtual bool PL_AdjustRequestedResolution(uint32_t &physicalWidth, uint32_t &physicalHeight, uint32_t &virtualWidth, uint32_t &virtualheight, float &pixelScaleX, float &pixelScaleY) = 0;
|
||||
};
|
||||
|
||||
GP_APP_DLL_EXPORT_API GpAppInterface *GpAppInterface_Get();
|
||||
|
@@ -13,5 +13,6 @@ namespace PortabilityLayer
|
||||
size_t m_size;
|
||||
void *m_pointer;
|
||||
const void *m_constPointer;
|
||||
void (*m_functionPtr)(const HostSuspendCallArgument *args, HostSuspendCallArgument *returnValue);
|
||||
};
|
||||
}
|
||||
|
@@ -9,6 +9,7 @@ namespace PortabilityLayer
|
||||
HostSuspendCallID_Unknown,
|
||||
|
||||
HostSuspendCallID_Delay,
|
||||
HostSuspendCallID_CallOnVOSThread,
|
||||
};
|
||||
}
|
||||
|
||||
|
@@ -6,7 +6,10 @@
|
||||
#include "PLTimeTaggedVOSEvent.h"
|
||||
#include "DisplayDeviceManager.h"
|
||||
#include "GpVOSEvent.h"
|
||||
#include "IGpDisplayDriver.h"
|
||||
#include "InputManager.h"
|
||||
#include "HostDisplayDriver.h"
|
||||
#include "HostFileSystem.h"
|
||||
#include "HostSuspendCallArgument.h"
|
||||
#include "HostSuspendHook.h"
|
||||
#include "HostVOSEventQueue.h"
|
||||
@@ -66,6 +69,20 @@ static void TranslateKeyboardInputEvent(const GpVOSEvent &vosEventBase, uint32_t
|
||||
if (vosEvent.m_eventType == GpKeyboardInputEventTypes::kUp || vosEvent.m_eventType == GpKeyboardInputEventTypes::kDown)
|
||||
inputManager->ApplyKeyboardEvent(vosEvent);
|
||||
|
||||
// Special handling of alt-enter, redirect to display driver
|
||||
if (vosEventBase.m_eventType == GpKeyboardInputEventTypes::kDown &&
|
||||
vosEventBase.m_event.m_keyboardInputEvent.m_keyIDSubset == GpKeyIDSubsets::kSpecial &&
|
||||
vosEventBase.m_event.m_keyboardInputEvent.m_key.m_specialKey == GpKeySpecials::kEnter)
|
||||
{
|
||||
const KeyDownStates *keyStates = inputManager->GetKeys();
|
||||
if (keyStates->m_special.Get(GpKeySpecials::kLeftAlt) || keyStates->m_special.Get(GpKeySpecials::kRightAlt))
|
||||
{
|
||||
IGpDisplayDriver *dd = PortabilityLayer::HostDisplayDriver::GetInstance();
|
||||
if (dd)
|
||||
dd->RequestToggleFullScreen(timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
if (TimeTaggedVOSEvent *evt = queue->Enqueue())
|
||||
*evt = TimeTaggedVOSEvent::Create(vosEventBase, timestamp);
|
||||
}
|
||||
@@ -149,4 +166,63 @@ namespace PLSysCalls
|
||||
AnimationManager::GetInstance()->TickPlayers(ticks);
|
||||
}
|
||||
}
|
||||
|
||||
static void PromptOpenFileCallback(const PortabilityLayer::HostSuspendCallArgument *args, PortabilityLayer::HostSuspendCallArgument *returnValue)
|
||||
{
|
||||
bool result = PortabilityLayer::HostFileSystem::GetInstance()->PromptOpenFile(static_cast<PortabilityLayer::VirtualDirectory_t>(args[0].m_int), static_cast<char*>(args[1].m_pointer), *static_cast<size_t*>(args[2].m_pointer), args[3].m_uint);
|
||||
returnValue->m_uint = (result ? 1 : 0);
|
||||
}
|
||||
|
||||
bool PromptOpenFile(PortabilityLayer::VirtualDirectory_t dirID, char *path, size_t &outPathLength, size_t pathCapacity)
|
||||
{
|
||||
PortabilityLayer::HostSuspendCallArgument cbArgs[4];
|
||||
cbArgs[0].m_int = static_cast<int32_t>(dirID);
|
||||
cbArgs[1].m_pointer = path;
|
||||
cbArgs[2].m_pointer = &outPathLength;
|
||||
cbArgs[3].m_size = pathCapacity;
|
||||
|
||||
PortabilityLayer::HostSuspendCallArgument cbReturnValue;
|
||||
|
||||
PortabilityLayer::HostSuspendCallArgument dispatchArgs[3];
|
||||
dispatchArgs[0].m_functionPtr = PromptOpenFileCallback;
|
||||
dispatchArgs[1].m_constPointer = cbArgs;
|
||||
dispatchArgs[2].m_pointer = &cbReturnValue;
|
||||
|
||||
PortabilityLayer::SuspendApplication(PortabilityLayer::HostSuspendCallID_CallOnVOSThread, dispatchArgs, nullptr);
|
||||
|
||||
return cbReturnValue.m_uint != 0;
|
||||
}
|
||||
|
||||
static void PromptSaveFileCallback(const PortabilityLayer::HostSuspendCallArgument *args, PortabilityLayer::HostSuspendCallArgument *returnValue)
|
||||
{
|
||||
bool result = PortabilityLayer::HostFileSystem::GetInstance()->PromptSaveFile(
|
||||
static_cast<PortabilityLayer::VirtualDirectory_t>(args[0].m_int),
|
||||
static_cast<char*>(args[1].m_pointer),
|
||||
*static_cast<size_t*>(args[2].m_pointer),
|
||||
args[3].m_uint,
|
||||
static_cast<const char*>(args[4].m_constPointer));
|
||||
|
||||
returnValue->m_uint = (result ? 1 : 0);
|
||||
}
|
||||
|
||||
bool PromptSaveFile(PortabilityLayer::VirtualDirectory_t virtualDirectory, char *path, size_t &outPathLength, size_t pathCapacity, const char *initialFileName)
|
||||
{
|
||||
PortabilityLayer::HostSuspendCallArgument cbArgs[5];
|
||||
cbArgs[0].m_int = static_cast<int32_t>(virtualDirectory);
|
||||
cbArgs[1].m_pointer = path;
|
||||
cbArgs[2].m_pointer = &outPathLength;
|
||||
cbArgs[3].m_size = pathCapacity;
|
||||
cbArgs[3].m_constPointer = initialFileName;
|
||||
|
||||
PortabilityLayer::HostSuspendCallArgument cbReturnValue;
|
||||
|
||||
PortabilityLayer::HostSuspendCallArgument dispatchArgs[3];
|
||||
dispatchArgs[0].m_functionPtr = PromptSaveFileCallback;
|
||||
dispatchArgs[1].m_constPointer = cbArgs;
|
||||
dispatchArgs[2].m_pointer = &cbReturnValue;
|
||||
|
||||
PortabilityLayer::SuspendApplication(PortabilityLayer::HostSuspendCallID_CallOnVOSThread, dispatchArgs, nullptr);
|
||||
|
||||
return cbReturnValue.m_uint != 0;
|
||||
}
|
||||
}
|
||||
|
@@ -1,8 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include "VirtualDirectory.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace PLSysCalls
|
||||
{
|
||||
void Sleep(uint32_t ticks);
|
||||
bool PromptOpenFile(PortabilityLayer::VirtualDirectory_t dirID, char *path, size_t &outPathLength, size_t pathCapacity);
|
||||
bool PromptSaveFile(PortabilityLayer::VirtualDirectory_t virtualDirectory, char *path, size_t &outPathLength, size_t pathCapacity, const char *initialFileName);
|
||||
}
|
||||
|
Reference in New Issue
Block a user