mirror of
https://github.com/Ryujinx/SDL.git
synced 2024-12-23 11:55:38 +00:00
WinRT: experimental and preliminary support for XAML-based overlays on Windows 8/RT
The XAML support here is still rudimentary. Bugs do exist. You've been warned. XAML support in Windows Phone 8 is not yet available (in SDL/WinRT).
This commit is contained in:
parent
86ea4c4edf
commit
2cafee9de1
|
@ -70,6 +70,14 @@
|
|||
<CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</CompileAsWinRT>
|
||||
<CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</CompileAsWinRT>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\core\winrt\SDL_winrtxaml.cpp">
|
||||
<CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">true</CompileAsWinRT>
|
||||
<CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">true</CompileAsWinRT>
|
||||
<CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</CompileAsWinRT>
|
||||
<CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</CompileAsWinRT>
|
||||
<CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</CompileAsWinRT>
|
||||
<CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</CompileAsWinRT>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\cpuinfo\SDL_cpuinfo.c" />
|
||||
<ClCompile Include="..\..\src\events\SDL_clipboardevents.c" />
|
||||
<ClCompile Include="..\..\src\events\SDL_dropevents.c" />
|
||||
|
|
|
@ -270,6 +270,9 @@
|
|||
<ClCompile Include="..\..\src\joystick\winrt\SDL_xinputjoystick.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\core\winrt\SDL_winrtxaml.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\include\begin_code.h">
|
||||
|
|
|
@ -155,6 +155,20 @@ extern DECLSPEC const wchar_t * SDLCALL SDL_WinRTGetFSPathUNICODE(SDL_WinRT_Path
|
|||
*/
|
||||
extern DECLSPEC const char * SDLCALL SDL_WinRTGetFSPathUTF8(SDL_WinRT_Path pathType);
|
||||
|
||||
#ifdef __cplusplus_winrt
|
||||
/**
|
||||
* \brief Initializes a WinRT and XAML based application.
|
||||
*
|
||||
* \param backgroundPanel The XAML background panel to draw onto and receive
|
||||
* events from.
|
||||
* \param mainFunction The SDL app's C-style main().
|
||||
* \ret 0 on success, -1 on failure. On failure, use SDL_GetError to retrieve more
|
||||
* information on the failure.
|
||||
*/
|
||||
/* TODO, WinRT: consider making SDL_WinRTInitXAMLApp accept a void pointer to IUnknown, rather than a C++/CX reference */
|
||||
extern DECLSPEC int SDLCALL SDL_WinRTInitXAMLApp(Platform::Object^ backgroundPanel, int (*mainFunction)(int, char **));
|
||||
|
||||
#endif // ifdef __cplusplus_winrt
|
||||
|
||||
#endif /* __WINRT__ */
|
||||
|
||||
|
|
|
@ -361,17 +361,17 @@ void SDL_WinRTApp::OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args)
|
|||
|
||||
void SDL_WinRTApp::OnPointerPressed(CoreWindow^ sender, PointerEventArgs^ args)
|
||||
{
|
||||
WINRT_ProcessPointerPressedEvent(WINRT_GlobalSDLWindow, args);
|
||||
WINRT_ProcessPointerPressedEvent(WINRT_GlobalSDLWindow, args->CurrentPoint);
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::OnPointerReleased(CoreWindow^ sender, PointerEventArgs^ args)
|
||||
{
|
||||
WINRT_ProcessPointerReleasedEvent(WINRT_GlobalSDLWindow, args);
|
||||
WINRT_ProcessPointerReleasedEvent(WINRT_GlobalSDLWindow, args->CurrentPoint);
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::OnPointerWheelChanged(CoreWindow^ sender, PointerEventArgs^ args)
|
||||
{
|
||||
WINRT_ProcessPointerWheelChangedEvent(WINRT_GlobalSDLWindow, args);
|
||||
WINRT_ProcessPointerWheelChangedEvent(WINRT_GlobalSDLWindow, args->CurrentPoint);
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::OnMouseMoved(MouseDevice^ mouseDevice, MouseEventArgs^ args)
|
||||
|
@ -381,7 +381,7 @@ void SDL_WinRTApp::OnMouseMoved(MouseDevice^ mouseDevice, MouseEventArgs^ args)
|
|||
|
||||
void SDL_WinRTApp::OnPointerMoved(CoreWindow^ sender, PointerEventArgs^ args)
|
||||
{
|
||||
WINRT_ProcessPointerMovedEvent(WINRT_GlobalSDLWindow, args);
|
||||
WINRT_ProcessPointerMovedEvent(WINRT_GlobalSDLWindow, args->CurrentPoint);
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::OnKeyDown(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyEventArgs^ args)
|
||||
|
|
162
src/core/winrt/SDL_winrtxaml.cpp
Normal file
162
src/core/winrt/SDL_winrtxaml.cpp
Normal file
|
@ -0,0 +1,162 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/* Windows includes */
|
||||
#include <agile.h>
|
||||
#include <Windows.h>
|
||||
|
||||
#if WINAPI_FAMILY == WINAPI_FAMILY_APP
|
||||
#include <windows.ui.xaml.media.dxinterop.h>
|
||||
#endif
|
||||
|
||||
|
||||
/* SDL includes */
|
||||
#include "SDL.h"
|
||||
//#include "SDL_error.h"
|
||||
//#include "SDL_log.h"
|
||||
//#include "SDL_main.h"
|
||||
//#include "SDL_system.h"
|
||||
#include "../../video/winrt/SDL_winrtevents_c.h"
|
||||
|
||||
|
||||
/* External globals: */
|
||||
extern SDL_Window * WINRT_GlobalSDLWindow;
|
||||
|
||||
|
||||
/* Internal globals: */
|
||||
SDL_bool WINRT_XAMLWasEnabled = SDL_FALSE;
|
||||
int (*WINRT_XAMLAppMainFunction)(int, char **) = NULL;
|
||||
|
||||
#if WINAPI_FAMILY == WINAPI_FAMILY_APP
|
||||
ISwapChainBackgroundPanelNative * WINRT_GlobalSwapChainBackgroundPanelNative = NULL;
|
||||
static Windows::Foundation::EventRegistrationToken WINRT_XAMLAppEventToken;
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Input event handlers (XAML)
|
||||
*/
|
||||
#if WINAPI_FAMILY == WINAPI_FAMILY_APP
|
||||
|
||||
static void
|
||||
WINRT_OnPointerPressedViaXAML(Platform::Object^ sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs^ args)
|
||||
{
|
||||
WINRT_ProcessPointerPressedEvent(WINRT_GlobalSDLWindow, args->GetCurrentPoint(nullptr));
|
||||
}
|
||||
|
||||
static void
|
||||
WINRT_OnPointerReleasedViaXAML(Platform::Object^ sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs^ args)
|
||||
{
|
||||
WINRT_ProcessPointerReleasedEvent(WINRT_GlobalSDLWindow, args->GetCurrentPoint(nullptr));
|
||||
}
|
||||
|
||||
static void
|
||||
WINRT_OnPointerWheelChangedViaXAML(Platform::Object^ sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs^ args)
|
||||
{
|
||||
WINRT_ProcessPointerWheelChangedEvent(WINRT_GlobalSDLWindow, args->GetCurrentPoint(nullptr));
|
||||
}
|
||||
|
||||
static void
|
||||
WINRT_OnPointerMovedViaXAML(Platform::Object^ sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs^ args)
|
||||
{
|
||||
WINRT_ProcessPointerMovedEvent(WINRT_GlobalSDLWindow, args->GetCurrentPoint(nullptr));
|
||||
}
|
||||
|
||||
#endif // WINAPI_FAMILY == WINAPI_FAMILY_APP
|
||||
|
||||
|
||||
/*
|
||||
* XAML-to-SDL Rendering Callback
|
||||
*/
|
||||
#if WINAPI_FAMILY == WINAPI_FAMILY_APP
|
||||
|
||||
static void
|
||||
WINRT_OnRenderViaXAML(_In_ Platform::Object^ sender, _In_ Platform::Object^ args)
|
||||
{
|
||||
WINRT_CycleXAMLThread();
|
||||
}
|
||||
|
||||
#endif // WINAPI_FAMILY == WINAPI_FAMILY_APP
|
||||
|
||||
|
||||
/*
|
||||
* SDL + XAML Initialization
|
||||
*/
|
||||
|
||||
extern "C" int
|
||||
SDL_WinRTInitXAMLApp(Platform::Object ^backgroundPanel, int (*mainFunction)(int, char **))
|
||||
{
|
||||
#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
|
||||
return SDL_SetError("XAML support is not yet available in Windows Phone.");
|
||||
#else
|
||||
// Declare C++/CX namespaces:
|
||||
using namespace Platform;
|
||||
using namespace Windows::Foundation;
|
||||
using namespace Windows::UI::Core;
|
||||
using namespace Windows::UI::Xaml;
|
||||
using namespace Windows::UI::Xaml::Controls;
|
||||
using namespace Windows::UI::Xaml::Input;
|
||||
using namespace Windows::UI::Xaml::Media;
|
||||
|
||||
// Make sure we have a valid XAML element (to draw onto):
|
||||
if ( ! backgroundPanel) {
|
||||
return SDL_SetError("'backgroundPanel' can't be NULL");
|
||||
}
|
||||
|
||||
SwapChainBackgroundPanel ^swapChainBackgroundPanel = dynamic_cast<SwapChainBackgroundPanel ^>(backgroundPanel);
|
||||
if ( ! swapChainBackgroundPanel) {
|
||||
return SDL_SetError("An unknown or unsupported type of XAML control was specified.");
|
||||
}
|
||||
|
||||
// Setup event handlers:
|
||||
swapChainBackgroundPanel->PointerPressed += ref new PointerEventHandler(WINRT_OnPointerPressedViaXAML);
|
||||
swapChainBackgroundPanel->PointerReleased += ref new PointerEventHandler(WINRT_OnPointerReleasedViaXAML);
|
||||
swapChainBackgroundPanel->PointerWheelChanged += ref new PointerEventHandler(WINRT_OnPointerWheelChangedViaXAML);
|
||||
swapChainBackgroundPanel->PointerMoved += ref new PointerEventHandler(WINRT_OnPointerMovedViaXAML);
|
||||
|
||||
// Setup for rendering:
|
||||
IInspectable *panelInspectable = (IInspectable*) reinterpret_cast<IInspectable*>(swapChainBackgroundPanel);
|
||||
panelInspectable->QueryInterface(__uuidof(ISwapChainBackgroundPanelNative), (void **)&WINRT_GlobalSwapChainBackgroundPanelNative);
|
||||
|
||||
WINRT_XAMLAppEventToken = CompositionTarget::Rendering::add(ref new EventHandler<Object^>(WINRT_OnRenderViaXAML));
|
||||
|
||||
// Make sure the app is ready to call the SDL-centric main() function:
|
||||
WINRT_XAMLAppMainFunction = mainFunction;
|
||||
SDL_SetMainReady();
|
||||
|
||||
// Make sure video-init knows that we're initializing XAML:
|
||||
SDL_bool oldXAMLWasEnabledValue = WINRT_XAMLWasEnabled;
|
||||
WINRT_XAMLWasEnabled = SDL_TRUE;
|
||||
|
||||
// Make sure video modes are detected now, while we still have access to the WinRT
|
||||
// CoreWindow. WinRT will not allow the app's CoreWindow to be accessed via the
|
||||
// SDL/WinRT thread.
|
||||
if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) {
|
||||
// SDL_InitSubSystem will, on error, set the SDL error. Let that propogate to
|
||||
// the caller to here:
|
||||
WINRT_XAMLWasEnabled = oldXAMLWasEnabledValue;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// All done, for now.
|
||||
return 0;
|
||||
#endif // WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP / else
|
||||
}
|
|
@ -26,6 +26,11 @@
|
|||
#ifdef __WINRT__
|
||||
#include <windows.ui.core.h>
|
||||
#include <windows.foundation.h>
|
||||
|
||||
#if WINAPI_FAMILY == WINAPI_FAMILY_APP
|
||||
#include <windows.ui.xaml.media.dxinterop.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
|
@ -608,6 +613,13 @@ D3D11_ConvertDipsToPixels(float dips)
|
|||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if WINAPI_FAMILY == WINAPI_FAMILY_APP
|
||||
// TODO, WinRT, XAML: get the ISwapChainBackgroundPanelNative from something other than a global var
|
||||
extern ISwapChainBackgroundPanelNative * WINRT_GlobalSwapChainBackgroundPanelNative;
|
||||
#endif
|
||||
|
||||
|
||||
// Initialize all resources that change when the window's size changes.
|
||||
// TODO, WinRT: get D3D11_CreateWindowSizeDependentResources working on Win32
|
||||
HRESULT
|
||||
|
@ -619,15 +631,28 @@ D3D11_CreateWindowSizeDependentResources(SDL_Renderer * renderer)
|
|||
|
||||
// Store the window bounds so the next time we get a SizeChanged event we can
|
||||
// avoid rebuilding everything if the size is identical.
|
||||
ABI::Windows::Foundation::Rect coreWindowBounds;
|
||||
result = coreWindow->get_Bounds(&coreWindowBounds);
|
||||
if (FAILED(result)) {
|
||||
WIN_SetErrorFromHRESULT(__FUNCTION__", Get Window Bounds", result);
|
||||
return result;
|
||||
ABI::Windows::Foundation::Rect nativeWindowBounds;
|
||||
if (coreWindow) {
|
||||
result = coreWindow->get_Bounds(&nativeWindowBounds);
|
||||
if (FAILED(result)) {
|
||||
WIN_SetErrorFromHRESULT(__FUNCTION__", Get Window Bounds", result);
|
||||
return result;
|
||||
}
|
||||
} else {
|
||||
// TODO, WinRT, XAML: clean up window-bounds code in D3D11_CreateWindowSizeDependentResources
|
||||
SDL_DisplayMode displayMode;
|
||||
if (SDL_GetDesktopDisplayMode(0, &displayMode) < 0) {
|
||||
SDL_SetError(__FUNCTION__", Get Window Bounds (XAML): Unable to retrieve the native window's size");
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
nativeWindowBounds.Width = (FLOAT) displayMode.w;
|
||||
nativeWindowBounds.Height = (FLOAT) displayMode.h;
|
||||
}
|
||||
|
||||
data->windowSizeInDIPs.x = coreWindowBounds.Width;
|
||||
data->windowSizeInDIPs.y = coreWindowBounds.Height;
|
||||
// TODO, WinRT, XAML: see if window/control sizes are in DIPs, or something else. If something else, then adjust renderer size tracking accordingly.
|
||||
data->windowSizeInDIPs.x = nativeWindowBounds.Width;
|
||||
data->windowSizeInDIPs.y = nativeWindowBounds.Height;
|
||||
|
||||
// Calculate the necessary swap chain and render target size in pixels.
|
||||
float windowWidth = D3D11_ConvertDipsToPixels(data->windowSizeInDIPs.x);
|
||||
|
@ -660,6 +685,8 @@ D3D11_CreateWindowSizeDependentResources(SDL_Renderer * renderer)
|
|||
}
|
||||
else
|
||||
{
|
||||
const bool usingXAML = (coreWindow == nullptr);
|
||||
|
||||
// Otherwise, create a new one using the same adapter as the existing Direct3D device.
|
||||
DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0};
|
||||
swapChainDesc.Width = static_cast<UINT>(data->renderTargetSize.x); // Match the size of the window.
|
||||
|
@ -674,7 +701,11 @@ D3D11_CreateWindowSizeDependentResources(SDL_Renderer * renderer)
|
|||
swapChainDesc.Scaling = DXGI_SCALING_STRETCH; // On phone, only stretch and aspect-ratio stretch scaling are allowed.
|
||||
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; // On phone, no swap effects are supported.
|
||||
#else
|
||||
swapChainDesc.Scaling = DXGI_SCALING_NONE;
|
||||
if (usingXAML) {
|
||||
swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
|
||||
} else {
|
||||
swapChainDesc.Scaling = DXGI_SCALING_NONE;
|
||||
}
|
||||
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; // All Windows Store apps must use this SwapEffect.
|
||||
#endif
|
||||
swapChainDesc.Flags = 0;
|
||||
|
@ -703,25 +734,48 @@ D3D11_CreateWindowSizeDependentResources(SDL_Renderer * renderer)
|
|||
return result;
|
||||
}
|
||||
|
||||
IUnknown * coreWindowAsIUnknown = nullptr;
|
||||
result = coreWindow->QueryInterface(&coreWindowAsIUnknown);
|
||||
if (FAILED(result)) {
|
||||
WIN_SetErrorFromHRESULT(__FUNCTION__ ", CoreWindow to IUnknown", result);
|
||||
return result;
|
||||
}
|
||||
if (usingXAML) {
|
||||
result = dxgiFactory->CreateSwapChainForComposition(
|
||||
data->d3dDevice.Get(),
|
||||
&swapChainDesc,
|
||||
nullptr,
|
||||
&data->swapChain);
|
||||
if (FAILED(result)) {
|
||||
WIN_SetErrorFromHRESULT(__FUNCTION__ ", CreateSwapChainForComposition", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
result = dxgiFactory->CreateSwapChainForCoreWindow(
|
||||
data->d3dDevice.Get(),
|
||||
coreWindowAsIUnknown,
|
||||
&swapChainDesc,
|
||||
nullptr, // Allow on all displays.
|
||||
&data->swapChain
|
||||
);
|
||||
if (FAILED(result)) {
|
||||
WIN_SetErrorFromHRESULT(__FUNCTION__, result);
|
||||
return result;
|
||||
#if WINAPI_FAMILY == WINAPI_FAMILY_APP
|
||||
result = WINRT_GlobalSwapChainBackgroundPanelNative->SetSwapChain(data->swapChain.Get());
|
||||
if (FAILED(result)) {
|
||||
WIN_SetErrorFromHRESULT(__FUNCTION__ ", ISwapChainBackgroundPanelNative::SetSwapChain", result);
|
||||
return result;
|
||||
}
|
||||
#else
|
||||
SDL_SetError(__FUNCTION__ ", XAML support is not yet available for Windows Phone");
|
||||
return E_FAIL;
|
||||
#endif
|
||||
} else {
|
||||
IUnknown * coreWindowAsIUnknown = nullptr;
|
||||
result = coreWindow->QueryInterface(&coreWindowAsIUnknown);
|
||||
if (FAILED(result)) {
|
||||
WIN_SetErrorFromHRESULT(__FUNCTION__ ", CoreWindow to IUnknown", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
result = dxgiFactory->CreateSwapChainForCoreWindow(
|
||||
data->d3dDevice.Get(),
|
||||
coreWindowAsIUnknown,
|
||||
&swapChainDesc,
|
||||
nullptr, // Allow on all displays.
|
||||
&data->swapChain
|
||||
);
|
||||
if (FAILED(result)) {
|
||||
WIN_SetErrorFromHRESULT(__FUNCTION__, result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Ensure that DXGI does not queue more than one frame at a time. This both reduces latency and
|
||||
// ensures that the application will only render after each VSync, minimizing power consumption.
|
||||
result = dxgiDevice->SetMaximumFrameLatency(1);
|
||||
|
|
|
@ -25,23 +25,117 @@
|
|||
/* SDL includes */
|
||||
#include "SDL_winrtevents_c.h"
|
||||
#include "../../core/winrt/SDL_winrtapp.h"
|
||||
#include "SDL_assert.h"
|
||||
#include "SDL_system.h"
|
||||
|
||||
extern "C" {
|
||||
#include "../SDL_sysvideo.h"
|
||||
#include "../../events/SDL_events_c.h"
|
||||
}
|
||||
|
||||
|
||||
/* Forward declarations and globals */
|
||||
extern SDL_WinRTApp ^ SDL_WinRTGlobalApp;
|
||||
extern int (*WINRT_XAMLAppMainFunction)(int, char **);
|
||||
extern void WINRT_YieldXAMLThread();
|
||||
|
||||
|
||||
/* General event-management function(s) */
|
||||
/* Global event management */
|
||||
|
||||
void
|
||||
WINRT_PumpEvents(_THIS)
|
||||
{
|
||||
SDL_WinRTGlobalApp->PumpEvents();
|
||||
if (SDL_WinRTGlobalApp) {
|
||||
SDL_WinRTGlobalApp->PumpEvents();
|
||||
} else if (WINRT_XAMLAppMainFunction) {
|
||||
WINRT_YieldXAMLThread();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* XAML Thread management */
|
||||
|
||||
enum SDL_XAMLAppThreadState
|
||||
{
|
||||
ThreadState_NotLaunched = 0,
|
||||
ThreadState_Running,
|
||||
ThreadState_Yielding
|
||||
};
|
||||
|
||||
static SDL_XAMLAppThreadState _threadState = ThreadState_NotLaunched;
|
||||
static SDL_Thread * _XAMLThread = nullptr;
|
||||
static SDL_mutex * _mutex = nullptr;
|
||||
static SDL_cond * _cond = nullptr;
|
||||
|
||||
static void
|
||||
WINRT_YieldXAMLThread()
|
||||
{
|
||||
SDL_LockMutex(_mutex);
|
||||
SDL_assert(_threadState == ThreadState_Running);
|
||||
_threadState = ThreadState_Yielding;
|
||||
SDL_UnlockMutex(_mutex);
|
||||
|
||||
SDL_CondSignal(_cond);
|
||||
|
||||
SDL_LockMutex(_mutex);
|
||||
while (_threadState != ThreadState_Running) {
|
||||
SDL_CondWait(_cond, _mutex);
|
||||
}
|
||||
SDL_UnlockMutex(_mutex);
|
||||
}
|
||||
|
||||
static int
|
||||
WINRT_XAMLThreadMain(void * userdata)
|
||||
{
|
||||
return WINRT_XAMLAppMainFunction(0, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
WINRT_CycleXAMLThread()
|
||||
{
|
||||
switch (_threadState) {
|
||||
case ThreadState_NotLaunched:
|
||||
{
|
||||
_cond = SDL_CreateCond();
|
||||
|
||||
_mutex = SDL_CreateMutex();
|
||||
_threadState = ThreadState_Running;
|
||||
_XAMLThread = SDL_CreateThread(WINRT_XAMLThreadMain, "SDL/XAML App Thread", nullptr);
|
||||
|
||||
SDL_LockMutex(_mutex);
|
||||
while (_threadState != ThreadState_Yielding) {
|
||||
SDL_CondWait(_cond, _mutex);
|
||||
}
|
||||
SDL_UnlockMutex(_mutex);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ThreadState_Running:
|
||||
{
|
||||
SDL_assert(false);
|
||||
break;
|
||||
}
|
||||
|
||||
case ThreadState_Yielding:
|
||||
{
|
||||
SDL_LockMutex(_mutex);
|
||||
SDL_assert(_threadState == ThreadState_Yielding);
|
||||
_threadState = ThreadState_Running;
|
||||
SDL_UnlockMutex(_mutex);
|
||||
|
||||
SDL_CondSignal(_cond);
|
||||
|
||||
SDL_LockMutex(_mutex);
|
||||
while (_threadState != ThreadState_Yielding) {
|
||||
SDL_CondWait(_cond, _mutex);
|
||||
}
|
||||
SDL_UnlockMutex(_mutex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_WINRT */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
|
|
@ -50,10 +50,13 @@ extern void WINRT_ProcessKeyUpEvent(Windows::UI::Core::KeyEventArgs ^args);
|
|||
|
||||
/* Pointers (Mice, Touch, etc.) */
|
||||
extern void WINRT_ProcessMouseMovedEvent(SDL_Window * window, Windows::Devices::Input::MouseEventArgs ^args);
|
||||
extern void WINRT_ProcessPointerMovedEvent(SDL_Window *window, Windows::UI::Core::PointerEventArgs ^args);
|
||||
extern void WINRT_ProcessPointerWheelChangedEvent(SDL_Window *window, Windows::UI::Core::PointerEventArgs ^args);
|
||||
extern void WINRT_ProcessPointerReleasedEvent(SDL_Window *window, Windows::UI::Core::PointerEventArgs ^args);
|
||||
extern void WINRT_ProcessPointerPressedEvent(SDL_Window *window, Windows::UI::Core::PointerEventArgs ^args);
|
||||
extern void WINRT_ProcessPointerMovedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint);
|
||||
extern void WINRT_ProcessPointerWheelChangedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint);
|
||||
extern void WINRT_ProcessPointerReleasedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint);
|
||||
extern void WINRT_ProcessPointerPressedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint);
|
||||
|
||||
/* XAML Thread Management */
|
||||
extern void WINRT_CycleXAMLThread();
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -110,6 +110,11 @@ WINRT_FreeCursor(SDL_Cursor * cursor)
|
|||
static int
|
||||
WINRT_ShowCursor(SDL_Cursor * cursor)
|
||||
{
|
||||
// TODO, WinRT, XAML: make WINRT_ShowCursor work when XAML support is enabled.
|
||||
if ( ! CoreWindow::GetForCurrentThread()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (cursor) {
|
||||
CoreCursor ^* theCursor = (CoreCursor ^*) cursor->driverdata;
|
||||
CoreWindow::GetForCurrentThread()->PointerCursor = *theCursor;
|
||||
|
@ -334,25 +339,25 @@ WINRT_LogPointerEvent(const char * header, PointerEventArgs ^ args, Windows::Fou
|
|||
}
|
||||
|
||||
void
|
||||
WINRT_ProcessPointerMovedEvent(SDL_Window *window, Windows::UI::Core::PointerEventArgs ^args)
|
||||
WINRT_ProcessPointerMovedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint)
|
||||
{
|
||||
#if LOG_POINTER_EVENTS
|
||||
WINRT_LogPointerEvent("pointer moved", args, TransformCursor(args->CurrentPoint->Position));
|
||||
WINRT_LogPointerEvent("pointer moved", args, TransformCursor(pointerPoint->Position));
|
||||
#endif
|
||||
|
||||
if (!window || WINRT_UseRelativeMouseMode) {
|
||||
return;
|
||||
}
|
||||
|
||||
Windows::Foundation::Point transformedPoint = TransformCursor(window, args->CurrentPoint->Position);
|
||||
Windows::Foundation::Point transformedPoint = TransformCursor(window, pointerPoint->Position);
|
||||
SDL_SendMouseMotion(window, 0, 0, (int)transformedPoint.X, (int)transformedPoint.Y);
|
||||
}
|
||||
|
||||
void
|
||||
WINRT_ProcessPointerWheelChangedEvent(SDL_Window *window, Windows::UI::Core::PointerEventArgs ^args)
|
||||
WINRT_ProcessPointerWheelChangedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint)
|
||||
{
|
||||
#if LOG_POINTER_EVENTS
|
||||
WINRT_LogPointerEvent("wheel changed", args, TransformCursor(args->CurrentPoint->Position));
|
||||
WINRT_LogPointerEvent("wheel changed", args, TransformCursor(pointerPoint->Position));
|
||||
#endif
|
||||
|
||||
if (!window) {
|
||||
|
@ -360,11 +365,11 @@ WINRT_ProcessPointerWheelChangedEvent(SDL_Window *window, Windows::UI::Core::Poi
|
|||
}
|
||||
|
||||
// FIXME: This may need to accumulate deltas up to WHEEL_DELTA
|
||||
short motion = args->CurrentPoint->Properties->MouseWheelDelta / WHEEL_DELTA;
|
||||
short motion = pointerPoint->Properties->MouseWheelDelta / WHEEL_DELTA;
|
||||
SDL_SendMouseWheel(window, 0, 0, motion);
|
||||
}
|
||||
|
||||
void WINRT_ProcessPointerReleasedEvent(SDL_Window *window, Windows::UI::Core::PointerEventArgs ^args)
|
||||
void WINRT_ProcessPointerReleasedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint)
|
||||
{
|
||||
#if LOG_POINTER_EVENTS
|
||||
WINRT_LogPointerEvent("mouse up", args, TransformCursor(args->CurrentPoint->Position));
|
||||
|
@ -374,13 +379,13 @@ void WINRT_ProcessPointerReleasedEvent(SDL_Window *window, Windows::UI::Core::Po
|
|||
return;
|
||||
}
|
||||
|
||||
Uint8 button = WINRT_GetSDLButtonForPointerPoint(args->CurrentPoint);
|
||||
Uint8 button = WINRT_GetSDLButtonForPointerPoint(pointerPoint);
|
||||
if (button) {
|
||||
SDL_SendMouseButton(window, 0, SDL_RELEASED, button);
|
||||
}
|
||||
}
|
||||
|
||||
void WINRT_ProcessPointerPressedEvent(SDL_Window *window, Windows::UI::Core::PointerEventArgs ^args)
|
||||
void WINRT_ProcessPointerPressedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint)
|
||||
{
|
||||
#if LOG_POINTER_EVENTS
|
||||
WINRT_LogPointerEvent("mouse down", args, TransformCursor(args->CurrentPoint->Position));
|
||||
|
@ -390,7 +395,7 @@ void WINRT_ProcessPointerPressedEvent(SDL_Window *window, Windows::UI::Core::Poi
|
|||
return;
|
||||
}
|
||||
|
||||
Uint8 button = WINRT_GetSDLButtonForPointerPoint(args->CurrentPoint);
|
||||
Uint8 button = WINRT_GetSDLButtonForPointerPoint(pointerPoint);
|
||||
if (button) {
|
||||
SDL_SendMouseButton(window, 0, SDL_PRESSED, button);
|
||||
}
|
||||
|
|
|
@ -47,8 +47,11 @@ extern "C" {
|
|||
#include "../../core/winrt/SDL_winrtapp.h"
|
||||
#include "SDL_winrtevents_c.h"
|
||||
#include "SDL_winrtmouse.h"
|
||||
#include "SDL_main.h"
|
||||
#include "SDL_system.h"
|
||||
|
||||
extern SDL_WinRTApp ^ SDL_WinRTGlobalApp;
|
||||
extern SDL_bool WINRT_XAMLWasEnabled;
|
||||
|
||||
|
||||
/* Initialization/Query functions */
|
||||
|
@ -84,6 +87,7 @@ SDL_Window * WINRT_GlobalSDLWindow = NULL;
|
|||
SDL_VideoDevice * WINRT_GlobalSDLVideoDevice = NULL;
|
||||
|
||||
|
||||
|
||||
/* WinRT driver bootstrap functions */
|
||||
|
||||
static int
|
||||
|
@ -154,6 +158,13 @@ WINRT_CalcDisplayModeUsingNativeWindow()
|
|||
SDL_DisplayMode mode;
|
||||
SDL_zero(mode);
|
||||
|
||||
// Go no further if a native window cannot be accessed. This can happen,
|
||||
// for example, if this function is called from certain threads, such as
|
||||
// the SDL/XAML thread.
|
||||
if (!CoreWindow::GetForCurrentThread()) {
|
||||
return mode;
|
||||
}
|
||||
|
||||
// Fill in most fields:
|
||||
mode.format = SDL_PIXELFORMAT_RGB888;
|
||||
mode.refresh_rate = 0; // TODO, WinRT: see if refresh rate data is available, or relevant (for WinRT apps)
|
||||
|
@ -169,11 +180,15 @@ WINRT_CalcDisplayModeUsingNativeWindow()
|
|||
return mode;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
int
|
||||
WINRT_InitModes(_THIS)
|
||||
{
|
||||
// Retrieve the display mode:
|
||||
SDL_DisplayMode mode = WINRT_CalcDisplayModeUsingNativeWindow();
|
||||
if (mode.w == 0 || mode.h == 0) {
|
||||
return SDL_SetError("Unable to calculate the WinRT window/display's size");
|
||||
}
|
||||
|
||||
if (SDL_AddBasicVideoDisplay(&mode) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -211,7 +226,16 @@ WINRT_CreateWindow(_THIS, SDL_Window * window)
|
|||
}
|
||||
window->driverdata = data;
|
||||
data->sdlWindow = window;
|
||||
data->coreWindow = CoreWindow::GetForCurrentThread();
|
||||
|
||||
/* To note, when XAML support is enabled, access to the CoreWindow will not
|
||||
be possible, at least not via the SDL/XAML thread. Attempts to access it
|
||||
from there will throw exceptions. As such, the SDL_WindowData's
|
||||
'coreWindow' field will only be set (to a non-null value) if XAML isn't
|
||||
enabled.
|
||||
*/
|
||||
if (!WINRT_XAMLWasEnabled) {
|
||||
data->coreWindow = CoreWindow::GetForCurrentThread();
|
||||
}
|
||||
|
||||
/* Make sure the window is considered to be positioned at {0,0},
|
||||
and is considered fullscreen, shown, and the like.
|
||||
|
|
Loading…
Reference in a new issue