Merge commit 'dec0d4ec4153bf9fc2b78ae6c2df45b6ea8dde7a' as 'external/sdl/SDL'

This commit is contained in:
2023-07-25 22:27:55 +02:00
1663 changed files with 627495 additions and 0 deletions

View File

@@ -0,0 +1,143 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 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.
*/
#include "SDL_internal.h"
#ifdef SDL_VIDEO_DRIVER_WINRT
/*
* Windows includes:
*/
#include <Windows.h>
using namespace Windows::UI::Core;
using Windows::UI::Core::CoreCursor;
/*
* SDL includes:
*/
#include "SDL_winrtevents_c.h"
#include "../../core/winrt/SDL_winrtapp_common.h"
#include "../../core/winrt/SDL_winrtapp_direct3d.h"
#include "../../core/winrt/SDL_winrtapp_xaml.h"
extern "C" {
#include "../../thread/SDL_systhread.h"
#include "../SDL_sysvideo.h"
#include "../../events/SDL_events_c.h"
}
/* Forward declarations */
static void WINRT_YieldXAMLThread();
/* Global event management */
void WINRT_PumpEvents(SDL_VideoDevice *_this)
{
if (SDL_WinRTGlobalApp) {
SDL_WinRTGlobalApp->PumpEvents();
} else if (WINRT_XAMLWasEnabled) {
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_Condition *_cond = nullptr;
static void WINRT_YieldXAMLThread()
{
SDL_LockMutex(_mutex);
SDL_assert(_threadState == ThreadState_Running);
_threadState = ThreadState_Yielding;
SDL_UnlockMutex(_mutex);
SDL_SignalCondition(_cond);
SDL_LockMutex(_mutex);
while (_threadState != ThreadState_Running) {
SDL_WaitCondition(_cond, _mutex);
}
SDL_UnlockMutex(_mutex);
}
static int WINRT_XAMLThreadMain(void *userdata)
{
// TODO, WinRT: pass the C-style main() a reasonably realistic
// representation of command line arguments.
int argc = 0;
char **argv = NULL;
return WINRT_SDLAppEntryPoint(argc, argv);
}
void WINRT_CycleXAMLThread(void)
{
switch (_threadState) {
case ThreadState_NotLaunched:
{
_cond = SDL_CreateCondition();
_mutex = SDL_CreateMutex();
_threadState = ThreadState_Running;
_XAMLThread = SDL_CreateThreadInternal(WINRT_XAMLThreadMain, "SDL/XAML App Thread", 0, nullptr);
SDL_LockMutex(_mutex);
while (_threadState != ThreadState_Yielding) {
SDL_WaitCondition(_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_SignalCondition(_cond);
SDL_LockMutex(_mutex);
while (_threadState != ThreadState_Yielding) {
SDL_WaitCondition(_cond, _mutex);
}
SDL_UnlockMutex(_mutex);
}
}
}
#endif /* SDL_VIDEO_DRIVER_WINRT */

View File

@@ -0,0 +1,81 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 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.
*/
#include "SDL_internal.h"
extern "C" {
#include "../SDL_sysvideo.h"
}
/*
* Internal-use, C-style functions:
*/
#ifdef __cplusplus
extern "C" {
#endif
extern void WINRT_InitTouch(SDL_VideoDevice *_this);
extern void WINRT_PumpEvents(SDL_VideoDevice *_this);
#ifdef __cplusplus
}
#endif
/*
* Internal-use, C++/CX functions:
*/
#ifdef __cplusplus_winrt
/* Pointers (Mice, Touch, etc.) */
typedef enum
{
NormalizeZeroToOne,
TransformToSDLWindowSize
} WINRT_CursorNormalizationType;
extern Windows::Foundation::Point WINRT_TransformCursorPosition(SDL_Window *window,
Windows::Foundation::Point rawPosition,
WINRT_CursorNormalizationType normalization);
extern SDL_bool WINRT_GetSDLButtonForPointerPoint(Windows::UI::Input::PointerPoint ^ pt, Uint8 *button, Uint8 *pressed);
extern void WINRT_ProcessPointerPressedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^ pointerPoint);
extern void WINRT_ProcessPointerMovedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^ pointerPoint);
extern void WINRT_ProcessPointerReleasedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^ pointerPoint);
extern void WINRT_ProcessPointerEnteredEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^ pointerPoint);
extern void WINRT_ProcessPointerExitedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^ pointerPoint);
extern void WINRT_ProcessPointerWheelChangedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^ pointerPoint);
extern void WINRT_ProcessMouseMovedEvent(SDL_Window *window, Windows::Devices::Input::MouseEventArgs ^ args);
/* Keyboard */
extern void WINRT_ProcessKeyDownEvent(Windows::UI::Core::KeyEventArgs ^ args);
extern void WINRT_ProcessKeyUpEvent(Windows::UI::Core::KeyEventArgs ^ args);
extern void WINRT_ProcessCharacterReceivedEvent(Windows::UI::Core::CharacterReceivedEventArgs ^ args);
#if NTDDI_VERSION >= NTDDI_WIN10
extern void WINTRT_InitialiseInputPaneEvents(SDL_VideoDevice *_this);
extern SDL_bool WINRT_HasScreenKeyboardSupport(SDL_VideoDevice *_this);
extern void WINRT_ShowScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window);
extern void WINRT_HideScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window);
extern SDL_bool WINRT_IsScreenKeyboardShown(SDL_VideoDevice *_this, SDL_Window *window);
#endif // NTDDI_VERSION >= ...
/* XAML Thread Management */
extern void WINRT_CycleXAMLThread(void);
#endif // ifdef __cplusplus_winrt

View File

@@ -0,0 +1,185 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 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.
*/
#include "SDL_internal.h"
#ifdef SDL_VIDEO_DRIVER_WINRT
/* Windows includes */
#include <roapi.h>
#include <windows.foundation.h>
#include <windows.system.h>
/* SDL includes */
extern "C" {
#include "../SDL_sysvideo.h"
}
#include "SDL_winrtvideo_cpp.h"
/* Game Bar events can come in off the main thread. Use the following
WinRT CoreDispatcher to deal with them on SDL's thread.
*/
static Platform::WeakReference WINRT_MainThreadDispatcher;
/* Win10's initial SDK (the 10.0.10240.0 release) does not include references
to Game Bar APIs, as the Game Bar was released via Win10 10.0.10586.0.
Declare its WinRT/COM interface here, to allow compilation with earlier
Windows SDKs.
*/
MIDL_INTERFACE("1DB9A292-CC78-4173-BE45-B61E67283EA7")
IGameBarStatics_ : public IInspectable
{
public:
virtual HRESULT STDMETHODCALLTYPE add_VisibilityChanged(
__FIEventHandler_1_IInspectable * handler,
Windows::Foundation::EventRegistrationToken * token) = 0;
virtual HRESULT STDMETHODCALLTYPE remove_VisibilityChanged(
Windows::Foundation::EventRegistrationToken token) = 0;
virtual HRESULT STDMETHODCALLTYPE add_IsInputRedirectedChanged(
__FIEventHandler_1_IInspectable * handler,
Windows::Foundation::EventRegistrationToken * token) = 0;
virtual HRESULT STDMETHODCALLTYPE remove_IsInputRedirectedChanged(
Windows::Foundation::EventRegistrationToken token) = 0;
virtual HRESULT STDMETHODCALLTYPE get_Visible(
boolean * value) = 0;
virtual HRESULT STDMETHODCALLTYPE get_IsInputRedirected(
boolean * value) = 0;
};
/* Declare the game bar's COM GUID */
static GUID IID_IGameBarStatics_ = { MAKELONG(0xA292, 0x1DB9), 0xCC78, 0x4173, { 0xBE, 0x45, 0xB6, 0x1E, 0x67, 0x28, 0x3E, 0xA7 } };
/* Retrieves a pointer to the game bar, or NULL if it is not available.
If a pointer is returned, it's ->Release() method must be called
after the caller has finished using it.
*/
static IGameBarStatics_ *WINRT_GetGameBar()
{
const wchar_t *wClassName = L"Windows.Gaming.UI.GameBar";
HSTRING hClassName;
IActivationFactory *pActivationFactory = NULL;
IGameBarStatics_ *pGameBar = NULL;
HRESULT hr;
hr = ::WindowsCreateString(wClassName, (UINT32)SDL_wcslen(wClassName), &hClassName);
if (FAILED(hr)) {
goto done;
}
hr = Windows::Foundation::GetActivationFactory(hClassName, &pActivationFactory);
if (FAILED(hr)) {
goto done;
}
pActivationFactory->QueryInterface(IID_IGameBarStatics_, (void **)&pGameBar);
done:
if (pActivationFactory) {
pActivationFactory->Release();
}
if (hClassName) {
::WindowsDeleteString(hClassName);
}
return pGameBar;
}
static void WINRT_HandleGameBarIsInputRedirected_MainThread()
{
IGameBarStatics_ *gameBar;
boolean isInputRedirected = 0;
if (!WINRT_MainThreadDispatcher) {
/* The game bar event handler has been deregistered! */
return;
}
gameBar = WINRT_GetGameBar();
if (gameBar == NULL) {
/* Shouldn't happen, but just in case... */
return;
}
if (SUCCEEDED(gameBar->get_IsInputRedirected(&isInputRedirected))) {
if (!isInputRedirected) {
/* Input-control is now back to the SDL app. Restore the cursor,
in case Windows does not (it does not in either Win10
10.0.10240.0 or 10.0.10586.0, maybe later version(s) too.
*/
SDL_Cursor *cursor = SDL_GetCursor();
SDL_SetCursor(cursor);
}
}
gameBar->Release();
}
static void WINRT_HandleGameBarIsInputRedirected_NonMainThread(Platform::Object ^ o1, Platform::Object ^ o2)
{
Windows::UI::Core::CoreDispatcher ^ dispatcher = WINRT_MainThreadDispatcher.Resolve<Windows::UI::Core::CoreDispatcher>();
if (dispatcher) {
dispatcher->RunAsync(
Windows::UI::Core::CoreDispatcherPriority::Normal,
ref new Windows::UI::Core::DispatchedHandler(&WINRT_HandleGameBarIsInputRedirected_MainThread));
}
}
void WINRT_InitGameBar(SDL_VideoDevice *_this)
{
SDL_VideoData *driverdata = _this->driverdata;
IGameBarStatics_ *gameBar = WINRT_GetGameBar();
if (gameBar) {
/* GameBar.IsInputRedirected events can come in via something other than
the main/SDL thread.
Get a WinRT 'CoreDispatcher' that can be used to call back into the
SDL thread.
*/
WINRT_MainThreadDispatcher = Windows::UI::Core::CoreWindow::GetForCurrentThread()->Dispatcher;
Windows::Foundation::EventHandler<Platform::Object ^> ^ handler =
ref new Windows::Foundation::EventHandler<Platform::Object ^>(&WINRT_HandleGameBarIsInputRedirected_NonMainThread);
__FIEventHandler_1_IInspectable *pHandler = reinterpret_cast<__FIEventHandler_1_IInspectable *>(handler);
gameBar->add_IsInputRedirectedChanged(pHandler, &driverdata->gameBarIsInputRedirectedToken);
gameBar->Release();
}
}
void WINRT_QuitGameBar(SDL_VideoDevice *_this)
{
SDL_VideoData *driverdata;
IGameBarStatics_ *gameBar;
if (_this == NULL || _this->driverdata == NULL) {
return;
}
gameBar = WINRT_GetGameBar();
if (gameBar == NULL) {
return;
}
driverdata = _this->driverdata;
if (driverdata->gameBarIsInputRedirectedToken.Value) {
gameBar->remove_IsInputRedirectedChanged(driverdata->gameBarIsInputRedirectedToken);
driverdata->gameBarIsInputRedirectedToken.Value = 0;
}
WINRT_MainThreadDispatcher = nullptr;
gameBar->Release();
}
#endif /* SDL_VIDEO_DRIVER_WINRT */

View File

@@ -0,0 +1,33 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 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.
*/
#include "SDL_internal.h"
#ifndef SDL_winrtgamebar_h_
#define SDL_winrtgamebar_h_
#ifdef __cplusplus
/* These are exported as C++ functions, rather than C, to fix a compilation
bug with MSVC 2013, for Windows 8.x builds. */
extern void WINRT_InitGameBar(SDL_VideoDevice *_this);
extern void WINRT_QuitGameBar(SDL_VideoDevice *_this);
#endif
#endif /* SDL_winrtgamebar_h_ */

View File

@@ -0,0 +1,478 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 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.
*/
#include "SDL_internal.h"
#ifdef SDL_VIDEO_DRIVER_WINRT
/* Windows-specific includes */
#include <Windows.h>
#include <agile.h>
/* SDL-specific includes */
#include "SDL_winrtevents_c.h"
extern "C" {
#include "../../events/scancodes_windows.h"
#include "../../events/SDL_keyboard_c.h"
}
static SDL_Scancode WinRT_Official_Keycodes[] = {
SDL_SCANCODE_UNKNOWN, /* VirtualKey.None -- 0 */
SDL_SCANCODE_UNKNOWN, /* VirtualKey.LeftButton -- 1 */
SDL_SCANCODE_UNKNOWN, /* VirtualKey.RightButton -- 2 */
SDL_SCANCODE_CANCEL, /* VirtualKey.Cancel -- 3 */
SDL_SCANCODE_UNKNOWN, /* VirtualKey.MiddleButton -- 4 */
SDL_SCANCODE_UNKNOWN, /* VirtualKey.XButton1 -- 5 */
SDL_SCANCODE_UNKNOWN, /* VirtualKey.XButton2 -- 6 */
SDL_SCANCODE_UNKNOWN, /* -- 7 */
SDL_SCANCODE_BACKSPACE, /* VirtualKey.Back -- 8 */
SDL_SCANCODE_TAB, /* VirtualKey.Tab -- 9 */
SDL_SCANCODE_UNKNOWN, /* -- 10 */
SDL_SCANCODE_UNKNOWN, /* -- 11 */
SDL_SCANCODE_CLEAR, /* VirtualKey.Clear -- 12 */
SDL_SCANCODE_RETURN, /* VirtualKey.Enter -- 13 */
SDL_SCANCODE_UNKNOWN, /* -- 14 */
SDL_SCANCODE_UNKNOWN, /* -- 15 */
SDL_SCANCODE_LSHIFT, /* VirtualKey.Shift -- 16 */
SDL_SCANCODE_LCTRL, /* VirtualKey.Control -- 17 */
SDL_SCANCODE_MENU, /* VirtualKey.Menu -- 18 */
SDL_SCANCODE_PAUSE, /* VirtualKey.Pause -- 19 */
SDL_SCANCODE_CAPSLOCK, /* VirtualKey.CapitalLock -- 20 */
SDL_SCANCODE_UNKNOWN, /* VirtualKey.Kana or VirtualKey.Hangul -- 21 */
SDL_SCANCODE_UNKNOWN, /* -- 22 */
SDL_SCANCODE_UNKNOWN, /* VirtualKey.Junja -- 23 */
SDL_SCANCODE_UNKNOWN, /* VirtualKey.Final -- 24 */
SDL_SCANCODE_UNKNOWN, /* VirtualKey.Hanja or VirtualKey.Kanji -- 25 */
SDL_SCANCODE_UNKNOWN, /* -- 26 */
SDL_SCANCODE_ESCAPE, /* VirtualKey.Escape -- 27 */
SDL_SCANCODE_UNKNOWN, /* VirtualKey.Convert -- 28 */
SDL_SCANCODE_UNKNOWN, /* VirtualKey.NonConvert -- 29 */
SDL_SCANCODE_UNKNOWN, /* VirtualKey.Accept -- 30 */
SDL_SCANCODE_UNKNOWN, /* VirtualKey.ModeChange -- 31 (maybe SDL_SCANCODE_MODE ?) */
SDL_SCANCODE_SPACE, /* VirtualKey.Space -- 32 */
SDL_SCANCODE_PAGEUP, /* VirtualKey.PageUp -- 33 */
SDL_SCANCODE_PAGEDOWN, /* VirtualKey.PageDown -- 34 */
SDL_SCANCODE_END, /* VirtualKey.End -- 35 */
SDL_SCANCODE_HOME, /* VirtualKey.Home -- 36 */
SDL_SCANCODE_LEFT, /* VirtualKey.Left -- 37 */
SDL_SCANCODE_UP, /* VirtualKey.Up -- 38 */
SDL_SCANCODE_RIGHT, /* VirtualKey.Right -- 39 */
SDL_SCANCODE_DOWN, /* VirtualKey.Down -- 40 */
SDL_SCANCODE_SELECT, /* VirtualKey.Select -- 41 */
SDL_SCANCODE_UNKNOWN, /* VirtualKey.Print -- 42 (maybe SDL_SCANCODE_PRINTSCREEN ?) */
SDL_SCANCODE_EXECUTE, /* VirtualKey.Execute -- 43 */
SDL_SCANCODE_UNKNOWN, /* VirtualKey.Snapshot -- 44 */
SDL_SCANCODE_INSERT, /* VirtualKey.Insert -- 45 */
SDL_SCANCODE_DELETE, /* VirtualKey.Delete -- 46 */
SDL_SCANCODE_HELP, /* VirtualKey.Help -- 47 */
SDL_SCANCODE_0, /* VirtualKey.Number0 -- 48 */
SDL_SCANCODE_1, /* VirtualKey.Number1 -- 49 */
SDL_SCANCODE_2, /* VirtualKey.Number2 -- 50 */
SDL_SCANCODE_3, /* VirtualKey.Number3 -- 51 */
SDL_SCANCODE_4, /* VirtualKey.Number4 -- 52 */
SDL_SCANCODE_5, /* VirtualKey.Number5 -- 53 */
SDL_SCANCODE_6, /* VirtualKey.Number6 -- 54 */
SDL_SCANCODE_7, /* VirtualKey.Number7 -- 55 */
SDL_SCANCODE_8, /* VirtualKey.Number8 -- 56 */
SDL_SCANCODE_9, /* VirtualKey.Number9 -- 57 */
SDL_SCANCODE_UNKNOWN, /* -- 58 */
SDL_SCANCODE_UNKNOWN, /* -- 59 */
SDL_SCANCODE_UNKNOWN, /* -- 60 */
SDL_SCANCODE_UNKNOWN, /* -- 61 */
SDL_SCANCODE_UNKNOWN, /* -- 62 */
SDL_SCANCODE_UNKNOWN, /* -- 63 */
SDL_SCANCODE_UNKNOWN, /* -- 64 */
SDL_SCANCODE_A, /* VirtualKey.A -- 65 */
SDL_SCANCODE_B, /* VirtualKey.B -- 66 */
SDL_SCANCODE_C, /* VirtualKey.C -- 67 */
SDL_SCANCODE_D, /* VirtualKey.D -- 68 */
SDL_SCANCODE_E, /* VirtualKey.E -- 69 */
SDL_SCANCODE_F, /* VirtualKey.F -- 70 */
SDL_SCANCODE_G, /* VirtualKey.G -- 71 */
SDL_SCANCODE_H, /* VirtualKey.H -- 72 */
SDL_SCANCODE_I, /* VirtualKey.I -- 73 */
SDL_SCANCODE_J, /* VirtualKey.J -- 74 */
SDL_SCANCODE_K, /* VirtualKey.K -- 75 */
SDL_SCANCODE_L, /* VirtualKey.L -- 76 */
SDL_SCANCODE_M, /* VirtualKey.M -- 77 */
SDL_SCANCODE_N, /* VirtualKey.N -- 78 */
SDL_SCANCODE_O, /* VirtualKey.O -- 79 */
SDL_SCANCODE_P, /* VirtualKey.P -- 80 */
SDL_SCANCODE_Q, /* VirtualKey.Q -- 81 */
SDL_SCANCODE_R, /* VirtualKey.R -- 82 */
SDL_SCANCODE_S, /* VirtualKey.S -- 83 */
SDL_SCANCODE_T, /* VirtualKey.T -- 84 */
SDL_SCANCODE_U, /* VirtualKey.U -- 85 */
SDL_SCANCODE_V, /* VirtualKey.V -- 86 */
SDL_SCANCODE_W, /* VirtualKey.W -- 87 */
SDL_SCANCODE_X, /* VirtualKey.X -- 88 */
SDL_SCANCODE_Y, /* VirtualKey.Y -- 89 */
SDL_SCANCODE_Z, /* VirtualKey.Z -- 90 */
SDL_SCANCODE_UNKNOWN, /* VirtualKey.LeftWindows -- 91 (maybe SDL_SCANCODE_APPLICATION or SDL_SCANCODE_LGUI ?) */
SDL_SCANCODE_UNKNOWN, /* VirtualKey.RightWindows -- 92 (maybe SDL_SCANCODE_APPLICATION or SDL_SCANCODE_RGUI ?) */
SDL_SCANCODE_APPLICATION, /* VirtualKey.Application -- 93 */
SDL_SCANCODE_UNKNOWN, /* -- 94 */
SDL_SCANCODE_SLEEP, /* VirtualKey.Sleep -- 95 */
SDL_SCANCODE_KP_0, /* VirtualKey.NumberPad0 -- 96 */
SDL_SCANCODE_KP_1, /* VirtualKey.NumberPad1 -- 97 */
SDL_SCANCODE_KP_2, /* VirtualKey.NumberPad2 -- 98 */
SDL_SCANCODE_KP_3, /* VirtualKey.NumberPad3 -- 99 */
SDL_SCANCODE_KP_4, /* VirtualKey.NumberPad4 -- 100 */
SDL_SCANCODE_KP_5, /* VirtualKey.NumberPad5 -- 101 */
SDL_SCANCODE_KP_6, /* VirtualKey.NumberPad6 -- 102 */
SDL_SCANCODE_KP_7, /* VirtualKey.NumberPad7 -- 103 */
SDL_SCANCODE_KP_8, /* VirtualKey.NumberPad8 -- 104 */
SDL_SCANCODE_KP_9, /* VirtualKey.NumberPad9 -- 105 */
SDL_SCANCODE_KP_MULTIPLY, /* VirtualKey.Multiply -- 106 */
SDL_SCANCODE_KP_PLUS, /* VirtualKey.Add -- 107 */
SDL_SCANCODE_UNKNOWN, /* VirtualKey.Separator -- 108 */
SDL_SCANCODE_KP_MINUS, /* VirtualKey.Subtract -- 109 */
SDL_SCANCODE_UNKNOWN, /* VirtualKey.Decimal -- 110 (maybe SDL_SCANCODE_DECIMALSEPARATOR, SDL_SCANCODE_KP_DECIMAL, or SDL_SCANCODE_KP_PERIOD ?) */
SDL_SCANCODE_KP_DIVIDE, /* VirtualKey.Divide -- 111 */
SDL_SCANCODE_F1, /* VirtualKey.F1 -- 112 */
SDL_SCANCODE_F2, /* VirtualKey.F2 -- 113 */
SDL_SCANCODE_F3, /* VirtualKey.F3 -- 114 */
SDL_SCANCODE_F4, /* VirtualKey.F4 -- 115 */
SDL_SCANCODE_F5, /* VirtualKey.F5 -- 116 */
SDL_SCANCODE_F6, /* VirtualKey.F6 -- 117 */
SDL_SCANCODE_F7, /* VirtualKey.F7 -- 118 */
SDL_SCANCODE_F8, /* VirtualKey.F8 -- 119 */
SDL_SCANCODE_F9, /* VirtualKey.F9 -- 120 */
SDL_SCANCODE_F10, /* VirtualKey.F10 -- 121 */
SDL_SCANCODE_F11, /* VirtualKey.F11 -- 122 */
SDL_SCANCODE_F12, /* VirtualKey.F12 -- 123 */
SDL_SCANCODE_F13, /* VirtualKey.F13 -- 124 */
SDL_SCANCODE_F14, /* VirtualKey.F14 -- 125 */
SDL_SCANCODE_F15, /* VirtualKey.F15 -- 126 */
SDL_SCANCODE_F16, /* VirtualKey.F16 -- 127 */
SDL_SCANCODE_F17, /* VirtualKey.F17 -- 128 */
SDL_SCANCODE_F18, /* VirtualKey.F18 -- 129 */
SDL_SCANCODE_F19, /* VirtualKey.F19 -- 130 */
SDL_SCANCODE_F20, /* VirtualKey.F20 -- 131 */
SDL_SCANCODE_F21, /* VirtualKey.F21 -- 132 */
SDL_SCANCODE_F22, /* VirtualKey.F22 -- 133 */
SDL_SCANCODE_F23, /* VirtualKey.F23 -- 134 */
SDL_SCANCODE_F24, /* VirtualKey.F24 -- 135 */
SDL_SCANCODE_UNKNOWN, /* -- 136 */
SDL_SCANCODE_UNKNOWN, /* -- 137 */
SDL_SCANCODE_UNKNOWN, /* -- 138 */
SDL_SCANCODE_UNKNOWN, /* -- 139 */
SDL_SCANCODE_UNKNOWN, /* -- 140 */
SDL_SCANCODE_UNKNOWN, /* -- 141 */
SDL_SCANCODE_UNKNOWN, /* -- 142 */
SDL_SCANCODE_UNKNOWN, /* -- 143 */
SDL_SCANCODE_NUMLOCKCLEAR, /* VirtualKey.NumberKeyLock -- 144 */
SDL_SCANCODE_SCROLLLOCK, /* VirtualKey.Scroll -- 145 */
SDL_SCANCODE_UNKNOWN, /* -- 146 */
SDL_SCANCODE_UNKNOWN, /* -- 147 */
SDL_SCANCODE_UNKNOWN, /* -- 148 */
SDL_SCANCODE_UNKNOWN, /* -- 149 */
SDL_SCANCODE_UNKNOWN, /* -- 150 */
SDL_SCANCODE_UNKNOWN, /* -- 151 */
SDL_SCANCODE_UNKNOWN, /* -- 152 */
SDL_SCANCODE_UNKNOWN, /* -- 153 */
SDL_SCANCODE_UNKNOWN, /* -- 154 */
SDL_SCANCODE_UNKNOWN, /* -- 155 */
SDL_SCANCODE_UNKNOWN, /* -- 156 */
SDL_SCANCODE_UNKNOWN, /* -- 157 */
SDL_SCANCODE_UNKNOWN, /* -- 158 */
SDL_SCANCODE_UNKNOWN, /* -- 159 */
SDL_SCANCODE_LSHIFT, /* VirtualKey.LeftShift -- 160 */
SDL_SCANCODE_RSHIFT, /* VirtualKey.RightShift -- 161 */
SDL_SCANCODE_LCTRL, /* VirtualKey.LeftControl -- 162 */
SDL_SCANCODE_RCTRL, /* VirtualKey.RightControl -- 163 */
SDL_SCANCODE_MENU, /* VirtualKey.LeftMenu -- 164 */
SDL_SCANCODE_MENU, /* VirtualKey.RightMenu -- 165 */
SDL_SCANCODE_AC_BACK, /* VirtualKey.GoBack -- 166 : The go back key. */
SDL_SCANCODE_AC_FORWARD, /* VirtualKey.GoForward -- 167 : The go forward key. */
SDL_SCANCODE_AC_REFRESH, /* VirtualKey.Refresh -- 168 : The refresh key. */
SDL_SCANCODE_AC_STOP, /* VirtualKey.Stop -- 169 : The stop key. */
SDL_SCANCODE_AC_SEARCH, /* VirtualKey.Search -- 170 : The search key. */
SDL_SCANCODE_AC_BOOKMARKS, /* VirtualKey.Favorites -- 171 : The favorites key. */
SDL_SCANCODE_AC_HOME /* VirtualKey.GoHome -- 172 : The go home key. */
};
/* Attempt to translate a keycode that isn't listed in WinRT's VirtualKey enum.
*/
static SDL_Scancode WINRT_TranslateUnofficialKeycode(int keycode)
{
switch (keycode) {
case 173:
return SDL_SCANCODE_MUTE; /* VK_VOLUME_MUTE */
case 174:
return SDL_SCANCODE_VOLUMEDOWN; /* VK_VOLUME_DOWN */
case 175:
return SDL_SCANCODE_VOLUMEUP; /* VK_VOLUME_UP */
case 176:
return SDL_SCANCODE_AUDIONEXT; /* VK_MEDIA_NEXT_TRACK */
case 177:
return SDL_SCANCODE_AUDIOPREV; /* VK_MEDIA_PREV_TRACK */
// case 178: return ; /* VK_MEDIA_STOP */
case 179:
return SDL_SCANCODE_AUDIOPLAY; /* VK_MEDIA_PLAY_PAUSE */
case 180:
return SDL_SCANCODE_MAIL; /* VK_LAUNCH_MAIL */
case 181:
return SDL_SCANCODE_MEDIASELECT; /* VK_LAUNCH_MEDIA_SELECT */
// case 182: return ; /* VK_LAUNCH_APP1 */
case 183:
return SDL_SCANCODE_CALCULATOR; /* VK_LAUNCH_APP2 */
// case 184: return ; /* ... reserved ... */
// case 185: return ; /* ... reserved ... */
case 186:
return SDL_SCANCODE_SEMICOLON; /* VK_OEM_1, ';:' key on US standard keyboards */
case 187:
return SDL_SCANCODE_EQUALS; /* VK_OEM_PLUS */
case 188:
return SDL_SCANCODE_COMMA; /* VK_OEM_COMMA */
case 189:
return SDL_SCANCODE_MINUS; /* VK_OEM_MINUS */
case 190:
return SDL_SCANCODE_PERIOD; /* VK_OEM_PERIOD */
case 191:
return SDL_SCANCODE_SLASH; /* VK_OEM_2, '/?' key on US standard keyboards */
case 192:
return SDL_SCANCODE_GRAVE; /* VK_OEM_3, '`~' key on US standard keyboards */
// ?
// ... reserved or unassigned ...
// ?
case 219:
return SDL_SCANCODE_LEFTBRACKET; /* VK_OEM_4, '[{' key on US standard keyboards */
case 220:
return SDL_SCANCODE_BACKSLASH; /* VK_OEM_5, '\|' key on US standard keyboards */
case 221:
return SDL_SCANCODE_RIGHTBRACKET; /* VK_OEM_6, ']}' key on US standard keyboards */
case 222:
return SDL_SCANCODE_APOSTROPHE; /* VK_OEM_7, 'single/double quote' on US standard keyboards */
default:
break;
}
return SDL_SCANCODE_UNKNOWN;
}
static SDL_Scancode WINRT_TranslateKeycode(int keycode, unsigned int nativeScancode)
{
// TODO, WinRT: try filling out the WinRT keycode table as much as possible, using the Win32 table for interpretation hints
SDL_Scancode scancode = SDL_SCANCODE_UNKNOWN;
/* HACK ALERT: At least one VirtualKey constant (Shift) with a left/right
* designation might not get reported with its correct handedness, however
* its hardware scan code can fill in the gaps. If this is detected,
* use the hardware scan code to try telling if the left, or the right
* side's key was used.
*
* If Microsoft ever allows MapVirtualKey or MapVirtualKeyEx to be used
* in WinRT apps, or something similar to these (it doesn't appear to be,
* at least not for Windows [Phone] 8/8.1, as of Oct 24, 2014), then this
* hack might become deprecated, or obsolete.
*/
if (nativeScancode < SDL_arraysize(windows_scancode_table)) {
switch (keycode) {
case 16: // VirtualKey.Shift
switch (windows_scancode_table[nativeScancode]) {
case SDL_SCANCODE_LSHIFT:
case SDL_SCANCODE_RSHIFT:
return windows_scancode_table[nativeScancode];
}
break;
// Add others, as necessary.
//
// Unfortunately, this hack doesn't seem to work in determining
// handedness with Control keys.
default:
break;
}
}
/* Try to get a documented, WinRT, 'VirtualKey' next (as documented at
http://msdn.microsoft.com/en-us/library/windows/apps/windows.system.virtualkey.aspx ).
If that fails, fall back to a Win32 virtual key.
If that fails, attempt to fall back to a scancode-derived key.
*/
if (keycode < SDL_arraysize(WinRT_Official_Keycodes)) {
scancode = WinRT_Official_Keycodes[keycode];
}
if (scancode == SDL_SCANCODE_UNKNOWN) {
scancode = WINRT_TranslateUnofficialKeycode(keycode);
}
if (scancode == SDL_SCANCODE_UNKNOWN) {
if (nativeScancode < SDL_arraysize(windows_scancode_table)) {
scancode = windows_scancode_table[nativeScancode];
}
}
/*
if (scancode == SDL_SCANCODE_UNKNOWN) {
SDL_Log("WinRT TranslateKeycode, unknown keycode=%d\n", (int)keycode);
}
*/
return scancode;
}
void WINRT_ProcessKeyDownEvent(Windows::UI::Core::KeyEventArgs ^ args)
{
SDL_Scancode sdlScancode = WINRT_TranslateKeycode((int)args->VirtualKey, args->KeyStatus.ScanCode);
#if 0
SDL_Keycode keycode = SDL_GetKeyFromScancode(sdlScancode);
SDL_Log("key down, handled=%s, ext?=%s, released?=%s, menu key down?=%s, "
"repeat count=%d, native scan code=0x%x, was down?=%s, vkey=%d, "
"sdl scan code=%d (%s), sdl key code=%d (%s)\n",
(args->Handled ? "1" : "0"),
(args->KeyStatus.IsExtendedKey ? "1" : "0"),
(args->KeyStatus.IsKeyReleased ? "1" : "0"),
(args->KeyStatus.IsMenuKeyDown ? "1" : "0"),
args->KeyStatus.RepeatCount,
args->KeyStatus.ScanCode,
(args->KeyStatus.WasKeyDown ? "1" : "0"),
args->VirtualKey,
sdlScancode,
SDL_GetScancodeName(sdlScancode),
keycode,
SDL_GetKeyName(keycode));
//args->Handled = true;
#endif
SDL_SendKeyboardKey(0, SDL_PRESSED, sdlScancode);
}
void WINRT_ProcessKeyUpEvent(Windows::UI::Core::KeyEventArgs ^ args)
{
SDL_Scancode sdlScancode = WINRT_TranslateKeycode((int)args->VirtualKey, args->KeyStatus.ScanCode);
#if 0
SDL_Keycode keycode = SDL_GetKeyFromScancode(sdlScancode);
SDL_Log("key up, handled=%s, ext?=%s, released?=%s, menu key down?=%s, "
"repeat count=%d, native scan code=0x%x, was down?=%s, vkey=%d, "
"sdl scan code=%d (%s), sdl key code=%d (%s)\n",
(args->Handled ? "1" : "0"),
(args->KeyStatus.IsExtendedKey ? "1" : "0"),
(args->KeyStatus.IsKeyReleased ? "1" : "0"),
(args->KeyStatus.IsMenuKeyDown ? "1" : "0"),
args->KeyStatus.RepeatCount,
args->KeyStatus.ScanCode,
(args->KeyStatus.WasKeyDown ? "1" : "0"),
args->VirtualKey,
sdlScancode,
SDL_GetScancodeName(sdlScancode),
keycode,
SDL_GetKeyName(keycode));
//args->Handled = true;
#endif
SDL_SendKeyboardKey(0, SDL_RELEASED, sdlScancode);
}
void WINRT_ProcessCharacterReceivedEvent(Windows::UI::Core::CharacterReceivedEventArgs ^ args)
{
wchar_t src_ucs2[2];
char dest_utf8[16];
int result;
/* Setup src */
src_ucs2[0] = args->KeyCode;
src_ucs2[1] = L'\0';
/* Convert the text, then send an SDL_EVENT_TEXT_INPUT event. */
result = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR)&src_ucs2, -1, (LPSTR)dest_utf8, sizeof(dest_utf8), NULL, NULL);
if (result > 0) {
SDL_SendKeyboardText(dest_utf8);
}
}
#if NTDDI_VERSION >= NTDDI_WIN10
static bool WINRT_InputPaneVisible = false;
void WINTRT_OnInputPaneShowing(Windows::UI::ViewManagement::InputPane ^ sender, Windows::UI::ViewManagement::InputPaneVisibilityEventArgs ^ args)
{
WINRT_InputPaneVisible = true;
}
void WINTRT_OnInputPaneHiding(Windows::UI::ViewManagement::InputPane ^ sender, Windows::UI::ViewManagement::InputPaneVisibilityEventArgs ^ args)
{
WINRT_InputPaneVisible = false;
}
void WINTRT_InitialiseInputPaneEvents(SDL_VideoDevice *_this)
{
using namespace Windows::UI::ViewManagement;
InputPane ^ inputPane = InputPane::GetForCurrentView();
if (inputPane) {
inputPane->Showing += ref new Windows::Foundation::TypedEventHandler<Windows::UI::ViewManagement::InputPane ^,
Windows::UI::ViewManagement::InputPaneVisibilityEventArgs ^>(&WINTRT_OnInputPaneShowing);
inputPane->Hiding += ref new Windows::Foundation::TypedEventHandler<Windows::UI::ViewManagement::InputPane ^,
Windows::UI::ViewManagement::InputPaneVisibilityEventArgs ^>(&WINTRT_OnInputPaneHiding);
}
}
SDL_bool WINRT_HasScreenKeyboardSupport(SDL_VideoDevice *_this)
{
return SDL_TRUE;
}
void WINRT_ShowScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window)
{
using namespace Windows::UI::ViewManagement;
InputPane ^ inputPane = InputPane::GetForCurrentView();
if (inputPane) {
inputPane->TryShow();
}
}
void WINRT_HideScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window)
{
using namespace Windows::UI::ViewManagement;
InputPane ^ inputPane = InputPane::GetForCurrentView();
if (inputPane) {
inputPane->TryHide();
}
}
SDL_bool WINRT_IsScreenKeyboardShown(SDL_VideoDevice *_this, SDL_Window *window)
{
using namespace Windows::UI::ViewManagement;
InputPane ^ inputPane = InputPane::GetForCurrentView();
if (inputPane) {
switch (SDL_WinRTGetDeviceFamily()) {
case SDL_WINRT_DEVICEFAMILY_XBOX:
// Documentation recommends using inputPane->Visible
// https://learn.microsoft.com/en-us/uwp/api/windows.ui.viewmanagement.inputpane.visible?view=winrt-22621
// This does not seem to work on latest UWP/Xbox.
// Workaround: Listen to Showing/Hiding events
if (WINRT_InputPaneVisible) {
return SDL_TRUE;
}
break;
default:
// OccludedRect is recommend on universal apps per docs
// https://learn.microsoft.com/en-us/uwp/api/windows.ui.viewmanagement.inputpane.visible?view=winrt-22621
Windows::Foundation::Rect rect = inputPane->OccludedRect;
if (rect.Width > 0 && rect.Height > 0) {
return SDL_TRUE;
}
break;
}
}
return SDL_FALSE;
}
#endif // NTDDI_VERSION >= ...
#endif // SDL_VIDEO_DRIVER_WINRT

View File

@@ -0,0 +1,111 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 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.
*/
#include "SDL_internal.h"
#ifdef SDL_VIDEO_DRIVER_WINRT
extern "C" {
#include "../../core/windows/SDL_windows.h"
}
#include "SDL_winrtevents_c.h"
#include <windows.ui.popups.h>
using namespace Platform;
using namespace Windows::Foundation;
using namespace Windows::UI::Popups;
static String ^ WINRT_UTF8ToPlatformString(const char *str) {
wchar_t *wstr = WIN_UTF8ToString(str);
String ^ rtstr = ref new String(wstr);
SDL_free(wstr);
return rtstr;
}
extern "C" int WINRT_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
{
#if SDL_WINAPI_FAMILY_PHONE && NTDDI_VERSION == NTDDI_WIN8
/* Sadly, Windows Phone 8 doesn't include the MessageDialog class that
* Windows 8.x/RT does, even though MSDN's reference documentation for
* Windows Phone 8 mentions it.
*
* The .NET runtime on Windows Phone 8 does, however, include a
* MessageBox class. Perhaps this could be called, somehow?
*/
return SDL_SetError("SDL_messagebox support is not available for Windows Phone 8.0");
#else
SDL_VideoDevice *_this = SDL_GetVideoDevice();
#if SDL_WINAPI_FAMILY_PHONE
const int maxbuttons = 2;
const char *platform = "Windows Phone 8.1+";
#else
const int maxbuttons = 3;
const char *platform = "Windows 8.x";
#endif
if (messageboxdata->numbuttons > maxbuttons) {
return SDL_SetError("WinRT's MessageDialog only supports %d buttons, at most, on %s. %d were requested.",
maxbuttons, platform, messageboxdata->numbuttons);
}
/* Build a MessageDialog object and its buttons */
MessageDialog ^ dialog = ref new MessageDialog(WINRT_UTF8ToPlatformString(messageboxdata->message));
dialog->Title = WINRT_UTF8ToPlatformString(messageboxdata->title);
for (int i = 0; i < messageboxdata->numbuttons; ++i) {
const SDL_MessageBoxButtonData *sdlButton;
if (messageboxdata->flags & SDL_MESSAGEBOX_BUTTONS_RIGHT_TO_LEFT) {
sdlButton = &messageboxdata->buttons[messageboxdata->numbuttons - 1 - i];
} else {
sdlButton = &messageboxdata->buttons[i];
}
UICommand ^ button = ref new UICommand(WINRT_UTF8ToPlatformString(sdlButton->text));
button->Id = IntPtr((int)((size_t)(sdlButton - messageboxdata->buttons)));
dialog->Commands->Append(button);
if (sdlButton->flags & SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT) {
dialog->CancelCommandIndex = i;
}
if (sdlButton->flags & SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT) {
dialog->DefaultCommandIndex = i;
}
}
/* Display the MessageDialog, then wait for it to be closed */
/* TODO, WinRT: Find a way to redraw MessageDialog instances if a GPU device-reset occurs during the following event-loop */
auto operation = dialog->ShowAsync();
while (operation->Status == Windows::Foundation::AsyncStatus::Started) {
WINRT_PumpEvents(_this);
}
/* Retrieve results from the MessageDialog and process them accordingly */
if (operation->Status != Windows::Foundation::AsyncStatus::Completed) {
return SDL_SetError("An unknown error occurred in displaying the WinRT MessageDialog");
}
if (buttonid) {
IntPtr results = safe_cast<IntPtr>(operation->GetResults()->Id);
int clicked_index = results.ToInt32();
*buttonid = messageboxdata->buttons[clicked_index].buttonid;
}
return 0;
#endif /* if SDL_WINAPI_FAMILY_PHONE / else */
}
#endif /* SDL_VIDEO_DRIVER_WINRT */

View File

@@ -0,0 +1,27 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 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.
*/
#include "SDL_internal.h"
#ifdef SDL_VIDEO_DRIVER_WINRT
extern int WINRT_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid);
#endif /* SDL_VIDEO_DRIVER_WINRT */

View File

@@ -0,0 +1,233 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 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.
*/
#include "SDL_internal.h"
#ifdef SDL_VIDEO_DRIVER_WINRT
/*
* Windows includes:
*/
#include <Windows.h>
#include <windows.ui.core.h>
using namespace Windows::UI::Core;
using Windows::UI::Core::CoreCursor;
/*
* SDL includes:
*/
extern "C" {
#include "../../events/SDL_mouse_c.h"
#include "../../events/SDL_touch_c.h"
#include "../SDL_sysvideo.h"
}
#include "../../core/winrt/SDL_winrtapp_direct3d.h"
#include "SDL_winrtvideo_cpp.h"
#include "SDL_winrtmouse_c.h"
extern "C" SDL_bool WINRT_UsingRelativeMouseMode = SDL_FALSE;
static SDL_Cursor *WINRT_CreateSystemCursor(SDL_SystemCursor id)
{
SDL_Cursor *cursor;
CoreCursorType cursorType = CoreCursorType::Arrow;
switch (id) {
default:
SDL_assert(0);
return NULL;
case SDL_SYSTEM_CURSOR_ARROW:
cursorType = CoreCursorType::Arrow;
break;
case SDL_SYSTEM_CURSOR_IBEAM:
cursorType = CoreCursorType::IBeam;
break;
case SDL_SYSTEM_CURSOR_WAIT:
cursorType = CoreCursorType::Wait;
break;
case SDL_SYSTEM_CURSOR_CROSSHAIR:
cursorType = CoreCursorType::Cross;
break;
case SDL_SYSTEM_CURSOR_WAITARROW:
cursorType = CoreCursorType::Wait;
break;
case SDL_SYSTEM_CURSOR_SIZENWSE:
cursorType = CoreCursorType::SizeNorthwestSoutheast;
break;
case SDL_SYSTEM_CURSOR_SIZENESW:
cursorType = CoreCursorType::SizeNortheastSouthwest;
break;
case SDL_SYSTEM_CURSOR_SIZEWE:
cursorType = CoreCursorType::SizeWestEast;
break;
case SDL_SYSTEM_CURSOR_SIZENS:
cursorType = CoreCursorType::SizeNorthSouth;
break;
case SDL_SYSTEM_CURSOR_SIZEALL:
cursorType = CoreCursorType::SizeAll;
break;
case SDL_SYSTEM_CURSOR_NO:
cursorType = CoreCursorType::UniversalNo;
break;
case SDL_SYSTEM_CURSOR_HAND:
cursorType = CoreCursorType::Hand;
break;
}
cursor = (SDL_Cursor *)SDL_calloc(1, sizeof(*cursor));
if (cursor) {
/* Create a pointer to a COM reference to a cursor. The extra
pointer is used (on top of the COM reference) to allow the cursor
to be referenced by the SDL_cursor's driverdata field, which is
a void pointer.
*/
CoreCursor ^ *theCursor = new CoreCursor ^ (nullptr);
*theCursor = ref new CoreCursor(cursorType, 0);
cursor->driverdata = (void *)theCursor;
} else {
SDL_OutOfMemory();
}
return cursor;
}
static SDL_Cursor *WINRT_CreateDefaultCursor()
{
return WINRT_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW);
}
static void WINRT_FreeCursor(SDL_Cursor *cursor)
{
if (cursor->driverdata) {
CoreCursor ^ *theCursor = (CoreCursor ^ *)cursor->driverdata;
*theCursor = nullptr; // Release the COM reference to the CoreCursor
delete theCursor; // Delete the pointer to the COM reference
}
SDL_free(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;
}
CoreWindow ^ coreWindow = CoreWindow::GetForCurrentThread();
if (cursor) {
CoreCursor ^ *theCursor = (CoreCursor ^ *)cursor->driverdata;
coreWindow->PointerCursor = *theCursor;
} else {
// HACK ALERT: TL;DR - Hiding the cursor in WinRT/UWP apps is weird, and
// a Win32-style cursor resource file must be directly included in apps,
// otherwise hiding the cursor will cause mouse-motion data to never be
// received.
//
// Here's the lengthy explanation:
//
// There are two ways to hide a cursor in WinRT/UWP apps.
// Both involve setting the WinRT CoreWindow's (which is somewhat analogous
// to a Win32 HWND) 'PointerCursor' property.
//
// The first way to hide a cursor sets PointerCursor to nullptr. This
// is, arguably, the easiest to implement for an app. It does have an
// unfortunate side-effect: it'll prevent mouse-motion events from being
// sent to the app (via CoreWindow).
//
// The second way to hide a cursor sets PointerCursor to a transparent
// cursor. This allows mouse-motion events to be sent to the app, but is
// more difficult to set up, as:
// 1. WinRT/UWP, while providing a few stock cursors, does not provide
// a completely transparent cursor.
// 2. WinRT/UWP allows apps to provide custom-built cursors, but *ONLY*
// if they are linked directly inside the app, via Win32-style
// cursor resource files. APIs to create cursors at runtime are
// not provided to apps, and attempting to link-to or use Win32
// cursor-creation APIs could cause an app to fail Windows Store
// certification.
//
// SDL can use either means of hiding the cursor. It provides a Win32-style
// set of cursor resource files in its source distribution, inside
// src/main/winrt/. If those files are linked to an SDL-for-WinRT/UWP app
// (by including them in a MSVC project, for example), SDL will attempt to
// use those, if and when the cursor is hidden via SDL APIs. If those
// files are not linked in, SDL will attempt to hide the cursor via the
// 'set PointerCursor to nullptr' means (which, if you recall, causes
// mouse-motion data to NOT be sent to the app!).
//
// Tech notes:
// - SDL's blank cursor resource uses a resource ID of 5000.
// - SDL's cursor resources consist of the following two files:
// - src/main/winrt/SDL3-WinRTResource_BlankCursor.cur -- cursor pixel data
// - src/main/winrt/SDL3-WinRTResources.rc -- declares the cursor resource, and its ID (of 5000)
//
const unsigned int win32CursorResourceID = 5000;
CoreCursor ^ blankCursor = ref new CoreCursor(CoreCursorType::Custom, win32CursorResourceID);
// Set 'PointerCursor' to 'blankCursor' in a way that shouldn't throw
// an exception if the app hasn't loaded that resource.
ABI::Windows::UI::Core::ICoreCursor *iblankCursor = reinterpret_cast<ABI::Windows::UI::Core::ICoreCursor *>(blankCursor);
ABI::Windows::UI::Core::ICoreWindow *icoreWindow = reinterpret_cast<ABI::Windows::UI::Core::ICoreWindow *>(coreWindow);
HRESULT hr = icoreWindow->put_PointerCursor(iblankCursor);
if (FAILED(hr)) {
// The app doesn't contain the cursor resource, or some other error
// occurred. Just use the other, but mouse-motion-preventing, means of
// hiding the cursor.
coreWindow->PointerCursor = nullptr;
}
}
return 0;
}
static int WINRT_SetRelativeMouseMode(SDL_bool enabled)
{
WINRT_UsingRelativeMouseMode = enabled;
return 0;
}
void WINRT_InitMouse(SDL_VideoDevice *_this)
{
SDL_Mouse *mouse = SDL_GetMouse();
/* DLudwig, Dec 3, 2012: WinRT does not currently provide APIs for
the following features, AFAIK:
- custom cursors (multiple system cursors are, however, available)
- programmatically moveable cursors
*/
#if !SDL_WINAPI_FAMILY_PHONE
// mouse->CreateCursor = WINRT_CreateCursor;
mouse->CreateSystemCursor = WINRT_CreateSystemCursor;
mouse->ShowCursor = WINRT_ShowCursor;
mouse->FreeCursor = WINRT_FreeCursor;
// mouse->WarpMouse = WINRT_WarpMouse;
mouse->SetRelativeMouseMode = WINRT_SetRelativeMouseMode;
SDL_SetDefaultCursor(WINRT_CreateDefaultCursor());
#endif
}
void WINRT_QuitMouse(SDL_VideoDevice *_this)
{
}
#endif /* SDL_VIDEO_DRIVER_WINRT */

View File

@@ -0,0 +1,38 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 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.
*/
#include "SDL_internal.h"
#ifndef SDL_winrtmouse_h_
#define SDL_winrtmouse_h_
#ifdef __cplusplus
extern "C" {
#endif
extern void WINRT_InitMouse(SDL_VideoDevice *_this);
extern void WINRT_QuitMouse(SDL_VideoDevice *_this);
extern SDL_bool WINRT_UsingRelativeMouseMode;
#ifdef __cplusplus
}
#endif
#endif /* SDL_winrtmouse_h_ */

View File

@@ -0,0 +1,207 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 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.
*/
#include "SDL_internal.h"
#if defined(SDL_VIDEO_DRIVER_WINRT) && defined(SDL_VIDEO_OPENGL_EGL)
/* EGL implementation of SDL OpenGL support */
#include "SDL_winrtvideo_cpp.h"
extern "C" {
#include "SDL_winrtopengles.h"
#include "../SDL_egl_c.h"
}
/* Windows includes */
#include <wrl/client.h>
using namespace Windows::UI::Core;
/* ANGLE/WinRT constants */
static const int ANGLE_D3D_FEATURE_LEVEL_ANY = 0;
#define EGL_PLATFORM_ANGLE_ANGLE 0x3202
#define EGL_PLATFORM_ANGLE_TYPE_ANGLE 0x3203
#define EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE 0x3204
#define EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE 0x3205
#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3208
#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE 0x3209
#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE 0x320B
#define EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE 0x320F
#define EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER 0x320B
/*
* SDL/EGL top-level implementation
*/
extern "C" int
WINRT_GLES_LoadLibrary(SDL_VideoDevice *_this, const char *path)
{
SDL_VideoData *video_data = _this->driverdata;
if (SDL_EGL_LoadLibrary(_this, path, EGL_DEFAULT_DISPLAY, 0) != 0) {
return -1;
}
/* Load ANGLE/WinRT-specific functions */
CreateWinrtEglWindow_Old_Function CreateWinrtEglWindow = (CreateWinrtEglWindow_Old_Function)SDL_LoadFunction(_this->egl_data->opengl_dll_handle, "CreateWinrtEglWindow");
if (CreateWinrtEglWindow) {
/* 'CreateWinrtEglWindow' was found, which means that an an older
* version of ANGLE/WinRT is being used. Continue setting up EGL,
* as appropriate to this version of ANGLE.
*/
/* Create an ANGLE/WinRT EGL-window */
/* TODO, WinRT: check for XAML usage before accessing the CoreWindow, as not doing so could lead to a crash */
CoreWindow ^ native_win = CoreWindow::GetForCurrentThread();
Microsoft::WRL::ComPtr<IUnknown> cpp_win = reinterpret_cast<IUnknown *>(native_win);
HRESULT result = CreateWinrtEglWindow(cpp_win, ANGLE_D3D_FEATURE_LEVEL_ANY, &(video_data->winrtEglWindow));
if (FAILED(result)) {
return -1;
}
/* Call eglGetDisplay and eglInitialize as appropriate. On other
* platforms, this would probably get done by SDL_EGL_LoadLibrary,
* however ANGLE/WinRT's current implementation (as of Mar 22, 2014) of
* eglGetDisplay requires that a C++ object be passed into it, so the
* call will be made in this file, a C++ file, instead.
*/
Microsoft::WRL::ComPtr<IUnknown> cpp_display = video_data->winrtEglWindow;
_this->egl_data->egl_display = ((eglGetDisplay_Old_Function)_this->egl_data->eglGetDisplay)(cpp_display);
if (!_this->egl_data->egl_display) {
return SDL_EGL_SetError("Could not get Windows 8.0 EGL display", "eglGetDisplay");
}
if (_this->egl_data->eglInitialize(_this->egl_data->egl_display, NULL, NULL) != EGL_TRUE) {
return SDL_EGL_SetError("Could not initialize Windows 8.0 EGL", "eglInitialize");
}
} else {
/* Declare some ANGLE/EGL initialization property-sets, as suggested by
* MSOpenTech's ANGLE-for-WinRT template apps:
*/
const EGLint defaultDisplayAttributes[] = {
EGL_PLATFORM_ANGLE_TYPE_ANGLE,
EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER,
EGL_TRUE,
EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE,
EGL_TRUE,
EGL_NONE,
};
const EGLint fl9_3DisplayAttributes[] = {
EGL_PLATFORM_ANGLE_TYPE_ANGLE,
EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE,
9,
EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE,
3,
EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER,
EGL_TRUE,
EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE,
EGL_TRUE,
EGL_NONE,
};
const EGLint warpDisplayAttributes[] = {
EGL_PLATFORM_ANGLE_TYPE_ANGLE,
EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE,
EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE,
EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER,
EGL_TRUE,
EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE,
EGL_TRUE,
EGL_NONE,
};
/* 'CreateWinrtEglWindow' was NOT found, which either means that a
* newer version of ANGLE/WinRT is being used, or that we don't have
* a valid copy of ANGLE.
*
* Try loading ANGLE as if it were the newer version.
*/
eglGetPlatformDisplayEXT_Function eglGetPlatformDisplayEXT = (eglGetPlatformDisplayEXT_Function)_this->egl_data->eglGetProcAddress("eglGetPlatformDisplayEXT");
if (!eglGetPlatformDisplayEXT) {
return SDL_EGL_SetError("Could not retrieve ANGLE/WinRT display function(s)", "eglGetProcAddress");
}
#if !SDL_WINAPI_FAMILY_PHONE
/* Try initializing EGL at D3D11 Feature Level 10_0+ (which is not
* supported on WinPhone 8.x.
*/
_this->egl_data->egl_display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, defaultDisplayAttributes);
if (!_this->egl_data->egl_display) {
return SDL_EGL_SetError("Could not get EGL display for Direct3D 10_0+", "eglGetPlatformDisplayEXT");
}
if (_this->egl_data->eglInitialize(_this->egl_data->egl_display, NULL, NULL) != EGL_TRUE)
#endif
{
/* Try initializing EGL at D3D11 Feature Level 9_3, in case the
* 10_0 init fails, or we're on Windows Phone (which only supports
* 9_3).
*/
_this->egl_data->egl_display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, fl9_3DisplayAttributes);
if (!_this->egl_data->egl_display) {
return SDL_EGL_SetError("Could not get EGL display for Direct3D 9_3", "eglGetPlatformDisplayEXT");
}
if (_this->egl_data->eglInitialize(_this->egl_data->egl_display, NULL, NULL) != EGL_TRUE) {
/* Try initializing EGL at D3D11 Feature Level 11_0 on WARP
* (a Windows-provided, software rasterizer) if all else fails.
*/
_this->egl_data->egl_display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, warpDisplayAttributes);
if (!_this->egl_data->egl_display) {
return SDL_EGL_SetError("Could not get EGL display for Direct3D WARP", "eglGetPlatformDisplayEXT");
}
if (_this->egl_data->eglInitialize(_this->egl_data->egl_display, NULL, NULL) != EGL_TRUE) {
return SDL_EGL_SetError("Could not initialize WinRT 8.x+ EGL", "eglInitialize");
}
}
}
}
return 0;
}
extern "C" void
WINRT_GLES_UnloadLibrary(SDL_VideoDevice *_this)
{
SDL_VideoData *video_data = _this->driverdata;
/* Release SDL's own COM reference to the ANGLE/WinRT IWinrtEglWindow */
if (video_data->winrtEglWindow) {
video_data->winrtEglWindow->Release();
video_data->winrtEglWindow = nullptr;
}
/* Perform the bulk of the unloading */
SDL_EGL_UnloadLibrary(_this);
}
extern "C" {
SDL_EGL_CreateContext_impl(WINRT)
SDL_EGL_SwapWindow_impl(WINRT)
SDL_EGL_MakeCurrent_impl(WINRT)
}
#endif /* SDL_VIDEO_DRIVER_WINRT && SDL_VIDEO_OPENGL_EGL */

View File

@@ -0,0 +1,67 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 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.
*/
#include "SDL_internal.h"
#ifndef SDL_winrtopengles_h_
#define SDL_winrtopengles_h_
#if defined(SDL_VIDEO_DRIVER_WINRT) && defined(SDL_VIDEO_OPENGL_EGL)
#include "../SDL_sysvideo.h"
#include "../SDL_egl_c.h"
/* OpenGLES functions */
#define WINRT_GLES_GetAttribute SDL_EGL_GetAttribute
#define WINRT_GLES_GetProcAddress SDL_EGL_GetProcAddressInternal
#define WINRT_GLES_SetSwapInterval SDL_EGL_SetSwapInterval
#define WINRT_GLES_GetSwapInterval SDL_EGL_GetSwapInterval
#define WINRT_GLES_DeleteContext SDL_EGL_DeleteContext
extern int WINRT_GLES_LoadLibrary(SDL_VideoDevice *_this, const char *path);
extern void WINRT_GLES_UnloadLibrary(SDL_VideoDevice *_this);
extern SDL_GLContext WINRT_GLES_CreateContext(SDL_VideoDevice *_this, SDL_Window *window);
extern int WINRT_GLES_SwapWindow(SDL_VideoDevice *_this, SDL_Window *window);
extern int WINRT_GLES_MakeCurrent(SDL_VideoDevice *_this, SDL_Window *window, SDL_GLContext context);
#ifdef __cplusplus
/* Typedefs for ANGLE/WinRT's C++-based native-display and native-window types,
* which are used when calling eglGetDisplay and eglCreateWindowSurface.
*/
typedef Microsoft::WRL::ComPtr<IUnknown> WINRT_EGLNativeWindowType_Old;
/* Function pointer typedefs for 'old' ANGLE/WinRT's functions, which may
* require that C++ objects be passed in:
*/
typedef EGLDisplay(EGLAPIENTRY *eglGetDisplay_Old_Function)(WINRT_EGLNativeWindowType_Old);
typedef EGLSurface(EGLAPIENTRY *eglCreateWindowSurface_Old_Function)(EGLDisplay, EGLConfig, WINRT_EGLNativeWindowType_Old, const EGLint *);
typedef HRESULT(EGLAPIENTRY *CreateWinrtEglWindow_Old_Function)(Microsoft::WRL::ComPtr<IUnknown>, int, IUnknown **result);
#endif /* __cplusplus */
/* Function pointer typedefs for 'new' ANGLE/WinRT functions, which, unlike
* the old functions, do not require C++ support and work with plain C.
*/
typedef EGLDisplay(EGLAPIENTRY *eglGetPlatformDisplayEXT_Function)(EGLenum, void *, const EGLint *);
#endif /* SDL_VIDEO_DRIVER_WINRT && SDL_VIDEO_OPENGL_EGL */
#endif /* SDL_winrtopengles_h_ */

View File

@@ -0,0 +1,394 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 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.
*/
#include "SDL_internal.h"
#ifdef SDL_VIDEO_DRIVER_WINRT
/* SDL includes */
#include "SDL_winrtevents_c.h"
#include "SDL_winrtmouse_c.h"
#include "SDL_winrtvideo_cpp.h"
extern "C" {
#include "../SDL_sysvideo.h"
#include "../../events/SDL_events_c.h"
#include "../../events/SDL_mouse_c.h"
#include "../../events/SDL_touch_c.h"
}
/* File-specific globals: */
static SDL_TouchID WINRT_TouchID = 1;
void WINRT_InitTouch(SDL_VideoDevice *_this)
{
SDL_AddTouch(WINRT_TouchID, SDL_TOUCH_DEVICE_DIRECT, "");
}
//
// Applies necessary geometric transformations to raw cursor positions:
//
Windows::Foundation::Point
WINRT_TransformCursorPosition(SDL_Window *window,
Windows::Foundation::Point rawPosition,
WINRT_CursorNormalizationType normalization)
{
using namespace Windows::UI::Core;
using namespace Windows::Graphics::Display;
if (!window) {
return rawPosition;
}
SDL_WindowData *windowData = window->driverdata;
if (windowData->coreWindow == nullptr) {
// For some reason, the window isn't associated with a CoreWindow.
// This might end up being the case as XAML support is extended.
// For now, if there's no CoreWindow attached to the SDL_Window,
// don't do any transforms.
// TODO, WinRT: make sure touch input coordinate ranges are correct when using XAML support
return rawPosition;
}
// The CoreWindow can only be accessed on certain thread(s).
SDL_assert(CoreWindow::GetForCurrentThread() != nullptr);
CoreWindow ^ nativeWindow = windowData->coreWindow.Get();
Windows::Foundation::Point outputPosition;
// Compute coordinates normalized from 0..1.
// If the coordinates need to be sized to the SDL window,
// we'll do that after.
#if !SDL_WINAPI_FAMILY_PHONE || NTDDI_VERSION > NTDDI_WIN8
outputPosition.X = rawPosition.X / nativeWindow->Bounds.Width;
outputPosition.Y = rawPosition.Y / nativeWindow->Bounds.Height;
#else
switch (WINRT_DISPLAY_PROPERTY(CurrentOrientation)) {
case DisplayOrientations::Portrait:
outputPosition.X = rawPosition.X / nativeWindow->Bounds.Width;
outputPosition.Y = rawPosition.Y / nativeWindow->Bounds.Height;
break;
case DisplayOrientations::PortraitFlipped:
outputPosition.X = 1.0f - (rawPosition.X / nativeWindow->Bounds.Width);
outputPosition.Y = 1.0f - (rawPosition.Y / nativeWindow->Bounds.Height);
break;
case DisplayOrientations::Landscape:
outputPosition.X = rawPosition.Y / nativeWindow->Bounds.Height;
outputPosition.Y = 1.0f - (rawPosition.X / nativeWindow->Bounds.Width);
break;
case DisplayOrientations::LandscapeFlipped:
outputPosition.X = 1.0f - (rawPosition.Y / nativeWindow->Bounds.Height);
outputPosition.Y = rawPosition.X / nativeWindow->Bounds.Width;
break;
default:
break;
}
#endif
if (normalization == TransformToSDLWindowSize) {
outputPosition.X *= ((float32)window->w);
outputPosition.Y *= ((float32)window->h);
}
return outputPosition;
}
SDL_bool WINRT_GetSDLButtonForPointerPoint(Windows::UI::Input::PointerPoint ^ pt, Uint8 *button, Uint8 *pressed)
{
using namespace Windows::UI::Input;
#if SDL_WINAPI_FAMILY_PHONE
*button = SDL_BUTTON_LEFT;
return SDL_TRUE;
#else
switch (pt->Properties->PointerUpdateKind) {
case PointerUpdateKind::LeftButtonPressed:
case PointerUpdateKind::LeftButtonReleased:
*button = SDL_BUTTON_LEFT;
*pressed = (pt->Properties->PointerUpdateKind == PointerUpdateKind::LeftButtonPressed);
return SDL_TRUE;
case PointerUpdateKind::RightButtonPressed:
case PointerUpdateKind::RightButtonReleased:
*button = SDL_BUTTON_RIGHT;
*pressed = (pt->Properties->PointerUpdateKind == PointerUpdateKind::RightButtonPressed);
return SDL_TRUE;
case PointerUpdateKind::MiddleButtonPressed:
case PointerUpdateKind::MiddleButtonReleased:
*button = SDL_BUTTON_MIDDLE;
*pressed = (pt->Properties->PointerUpdateKind == PointerUpdateKind::MiddleButtonPressed);
return SDL_TRUE;
case PointerUpdateKind::XButton1Pressed:
case PointerUpdateKind::XButton1Released:
*button = SDL_BUTTON_X1;
*pressed = (pt->Properties->PointerUpdateKind == PointerUpdateKind::XButton1Pressed);
return SDL_TRUE;
case PointerUpdateKind::XButton2Pressed:
case PointerUpdateKind::XButton2Released:
*button = SDL_BUTTON_X2;
*pressed = (pt->Properties->PointerUpdateKind == PointerUpdateKind::XButton2Pressed);
return SDL_TRUE;
default:
break;
}
#endif
*button = 0;
*pressed = 0;
return SDL_FALSE;
}
// const char *
// WINRT_ConvertPointerUpdateKindToString(Windows::UI::Input::PointerUpdateKind kind)
//{
// using namespace Windows::UI::Input;
//
// switch (kind)
// {
// case PointerUpdateKind::Other:
// return "Other";
// case PointerUpdateKind::LeftButtonPressed:
// return "LeftButtonPressed";
// case PointerUpdateKind::LeftButtonReleased:
// return "LeftButtonReleased";
// case PointerUpdateKind::RightButtonPressed:
// return "RightButtonPressed";
// case PointerUpdateKind::RightButtonReleased:
// return "RightButtonReleased";
// case PointerUpdateKind::MiddleButtonPressed:
// return "MiddleButtonPressed";
// case PointerUpdateKind::MiddleButtonReleased:
// return "MiddleButtonReleased";
// case PointerUpdateKind::XButton1Pressed:
// return "XButton1Pressed";
// case PointerUpdateKind::XButton1Released:
// return "XButton1Released";
// case PointerUpdateKind::XButton2Pressed:
// return "XButton2Pressed";
// case PointerUpdateKind::XButton2Released:
// return "XButton2Released";
// }
//
// return "";
// }
static bool WINRT_IsTouchEvent(Windows::UI::Input::PointerPoint ^ pointerPoint)
{
#if SDL_WINAPI_FAMILY_PHONE
return true;
#else
using namespace Windows::Devices::Input;
switch (pointerPoint->PointerDevice->PointerDeviceType) {
case PointerDeviceType::Touch:
case PointerDeviceType::Pen:
return true;
default:
return false;
}
#endif
}
void WINRT_ProcessPointerPressedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^ pointerPoint)
{
if (!window) {
return;
}
if (!WINRT_IsTouchEvent(pointerPoint)) {
Uint8 button, pressed;
WINRT_GetSDLButtonForPointerPoint(pointerPoint, &button, &pressed);
SDL_assert(pressed == 1);
SDL_SendMouseButton(0, window, 0, SDL_PRESSED, button);
} else {
Windows::Foundation::Point normalizedPoint = WINRT_TransformCursorPosition(window, pointerPoint->Position, NormalizeZeroToOne);
Windows::Foundation::Point windowPoint = WINRT_TransformCursorPosition(window, pointerPoint->Position, TransformToSDLWindowSize);
SDL_SendTouch(0,
WINRT_TouchID,
(SDL_FingerID)pointerPoint->PointerId,
window,
SDL_TRUE,
normalizedPoint.X,
normalizedPoint.Y,
pointerPoint->Properties->Pressure);
}
}
void WINRT_ProcessPointerMovedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^ pointerPoint)
{
if (!window || WINRT_UsingRelativeMouseMode) {
return;
}
Windows::Foundation::Point normalizedPoint = WINRT_TransformCursorPosition(window, pointerPoint->Position, NormalizeZeroToOne);
Windows::Foundation::Point windowPoint = WINRT_TransformCursorPosition(window, pointerPoint->Position, TransformToSDLWindowSize);
if (!WINRT_IsTouchEvent(pointerPoint)) {
/* For some odd reason Moved events are used for multiple mouse buttons */
Uint8 button, pressed;
if (WINRT_GetSDLButtonForPointerPoint(pointerPoint, &button, &pressed)) {
SDL_SendMouseButton(0, window, 0, pressed, button);
}
SDL_SendMouseMotion(0, window, 0, 0, windowPoint.X, windowPoint.Y);
} else {
SDL_SendTouchMotion(0,
WINRT_TouchID,
(SDL_FingerID)pointerPoint->PointerId,
window,
normalizedPoint.X,
normalizedPoint.Y,
pointerPoint->Properties->Pressure);
}
}
void WINRT_ProcessPointerReleasedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^ pointerPoint)
{
if (!window) {
return;
}
if (!WINRT_IsTouchEvent(pointerPoint)) {
Uint8 button, pressed;
WINRT_GetSDLButtonForPointerPoint(pointerPoint, &button, &pressed);
SDL_assert(pressed == 0);
SDL_SendMouseButton(0, window, 0, SDL_RELEASED, button);
} else {
Windows::Foundation::Point normalizedPoint = WINRT_TransformCursorPosition(window, pointerPoint->Position, NormalizeZeroToOne);
SDL_SendTouch(0,
WINRT_TouchID,
(SDL_FingerID)pointerPoint->PointerId,
window,
SDL_FALSE,
normalizedPoint.X,
normalizedPoint.Y,
pointerPoint->Properties->Pressure);
}
}
void WINRT_ProcessPointerEnteredEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^ pointerPoint)
{
if (!window) {
return;
}
if (!WINRT_IsTouchEvent(pointerPoint)) {
SDL_SetMouseFocus(window);
}
}
void WINRT_ProcessPointerExitedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^ pointerPoint)
{
if (!window) {
return;
}
if (!WINRT_IsTouchEvent(pointerPoint)) {
SDL_SetMouseFocus(NULL);
}
}
void WINRT_ProcessPointerWheelChangedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^ pointerPoint)
{
if (!window) {
return;
}
float motion = (float)pointerPoint->Properties->MouseWheelDelta / WHEEL_DELTA;
SDL_SendMouseWheel(0, window, 0, 0, (float)motion, SDL_MOUSEWHEEL_NORMAL);
}
void WINRT_ProcessMouseMovedEvent(SDL_Window *window, Windows::Devices::Input::MouseEventArgs ^ args)
{
if (!window || !WINRT_UsingRelativeMouseMode) {
return;
}
// DLudwig, 2012-12-28: On some systems, namely Visual Studio's Windows
// Simulator, as well as Windows 8 in a Parallels 8 VM, MouseEventArgs'
// MouseDelta field often reports very large values. More information
// on this can be found at the following pages on MSDN:
// - http://social.msdn.microsoft.com/Forums/en-US/winappswithnativecode/thread/a3c789fa-f1c5-49c4-9c0a-7db88d0f90f8
// - https://connect.microsoft.com/VisualStudio/Feedback/details/756515
//
// The values do not appear to be as large when running on some systems,
// most notably a Surface RT. Furthermore, the values returned by
// CoreWindow's PointerMoved event, and sent to this class' OnPointerMoved
// method, do not ever appear to be large, even when MouseEventArgs'
// MouseDelta is reporting to the contrary.
//
// On systems with the large-values behavior, it appears that the values
// get reported as if the screen's size is 65536 units in both the X and Y
// dimensions. This can be viewed by using Windows' now-private, "Raw Input"
// APIs. (GetRawInputData, RegisterRawInputDevices, WM_INPUT, etc.)
//
// MSDN's documentation on MouseEventArgs' MouseDelta field (at
// http://msdn.microsoft.com/en-us/library/windows/apps/windows.devices.input.mouseeventargs.mousedelta ),
// does not seem to indicate (to me) that its values should be so large. It
// says that its values should be a "change in screen location". I could
// be misinterpreting this, however a post on MSDN from a Microsoft engineer (see:
// http://social.msdn.microsoft.com/Forums/en-US/winappswithnativecode/thread/09a9868e-95bb-4858-ba1a-cb4d2c298d62 ),
// indicates that these values are in DIPs, which is the same unit used
// by CoreWindow's PointerMoved events (via the Position field in its CurrentPoint
// property. See http://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.input.pointerpoint.position.aspx
// for details.)
//
// To note, PointerMoved events are sent a 'RawPosition' value (via the
// CurrentPoint property in MouseEventArgs), however these do not seem
// to exhibit the same large-value behavior.
//
// The values passed via PointerMoved events can't always be used for relative
// mouse motion, unfortunately. Its values are bound to the cursor's position,
// which stops when it hits one of the screen's edges. This can be a problem in
// first person shooters, whereby it is normal for mouse motion to travel far
// along any one axis for a period of time. MouseMoved events do not have the
// screen-bounding limitation, and can be used regardless of where the system's
// cursor is.
//
// One possible workaround would be to programmatically set the cursor's
// position to the screen's center (when SDL's relative mouse mode is enabled),
// however WinRT does not yet seem to have the ability to set the cursor's
// position via a public API. Win32 did this via an API call, SetCursorPos,
// however WinRT makes this function be private. Apps that use it won't get
// approved for distribution in the Windows Store. I've yet to be able to find
// a suitable, store-friendly counterpart for WinRT.
//
// There may be some room for a workaround whereby OnPointerMoved's values
// are compared to the values from OnMouseMoved in order to detect
// when this bug is active. A suitable transformation could then be made to
// OnMouseMoved's values.
//
const Windows::Foundation::Point mouseDeltaInDIPs((float)args->MouseDelta.X, (float)args->MouseDelta.Y);
const Windows::Foundation::Point mouseDeltaInSDLWindowCoords = WINRT_TransformCursorPosition(window, mouseDeltaInDIPs, TransformToSDLWindowSize);
SDL_SendMouseMotion(0,
window,
0,
1,
mouseDeltaInSDLWindowCoords.X,
mouseDeltaInSDLWindowCoords.Y);
}
#endif // SDL_VIDEO_DRIVER_WINRT

View File

@@ -0,0 +1,849 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 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.
*/
#include "SDL_internal.h"
#ifdef SDL_VIDEO_DRIVER_WINRT
/* WinRT SDL video driver implementation
Initial work on this was done by David Ludwig (dludwig@pobox.com), and
was based off of SDL's "dummy" video driver.
*/
/* Standard C++11 includes */
#include <functional>
#include <sstream>
#include <string>
using namespace std;
/* Windows includes */
#include <agile.h>
#include <dxgi.h>
#include <dxgi1_2.h>
#include <windows.graphics.display.h>
#include <windows.system.display.h>
using namespace Windows::ApplicationModel::Core;
using namespace Windows::Foundation;
using namespace Windows::Graphics::Display;
using namespace Windows::UI::Core;
using namespace Windows::UI::ViewManagement;
/* [re]declare Windows GUIDs locally, to limit the amount of external lib(s) SDL has to link to */
static const GUID SDL_IID_IDisplayRequest = { 0xe5732044, 0xf49f, 0x4b60, { 0x8d, 0xd4, 0x5e, 0x7e, 0x3a, 0x63, 0x2a, 0xc0 } };
static const GUID SDL_IID_IDXGIFactory2 = { 0x50c83a1c, 0xe072, 0x4c48, { 0x87, 0xb0, 0x36, 0x30, 0xfa, 0x36, 0xa6, 0xd0 } };
/* SDL includes */
extern "C" {
#include "../../core/windows/SDL_windows.h"
#include "../../events/SDL_events_c.h"
#include "../../render/SDL_sysrender.h"
#include "../SDL_pixels_c.h"
#include "../SDL_sysvideo.h"
#include "SDL_winrtopengles.h"
}
#include "../../core/winrt/SDL_winrtapp_direct3d.h"
#include "../../core/winrt/SDL_winrtapp_xaml.h"
#include "SDL_winrtevents_c.h"
#include "SDL_winrtgamebar_cpp.h"
#include "SDL_winrtmouse_c.h"
#include "SDL_winrtvideo_cpp.h"
#include <SDL3/SDL_syswm.h>
/* Initialization/Query functions */
static int WINRT_VideoInit(SDL_VideoDevice *_this);
static int WINRT_InitModes(SDL_VideoDevice *_this);
static int WINRT_SetDisplayMode(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_DisplayMode *mode);
static void WINRT_VideoQuit(SDL_VideoDevice *_this);
/* Window functions */
static int WINRT_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window);
static void WINRT_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window);
static void WINRT_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen);
static void WINRT_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window);
static int WINRT_GetWindowWMInfo(SDL_VideoDevice *_this, SDL_Window *window, SDL_SysWMinfo *info);
/* Misc functions */
static ABI::Windows::System::Display::IDisplayRequest *WINRT_CreateDisplayRequest(SDL_VideoDevice *_this);
extern int WINRT_SuspendScreenSaver(SDL_VideoDevice *_this);
/* SDL-internal globals: */
SDL_Window *WINRT_GlobalSDLWindow = NULL;
/* WinRT driver bootstrap functions */
static void WINRT_DeleteDevice(SDL_VideoDevice *device)
{
if (device->driverdata) {
SDL_VideoData *video_data = device->driverdata;
if (video_data->winrtEglWindow) {
video_data->winrtEglWindow->Release();
}
SDL_free(video_data);
}
SDL_free(device);
}
static SDL_VideoDevice *WINRT_CreateDevice(void)
{
SDL_VideoDevice *device;
SDL_VideoData *data;
/* Initialize all variables that we clean on shutdown */
device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice));
if (device == NULL) {
SDL_OutOfMemory();
return 0;
}
data = (SDL_VideoData *)SDL_calloc(1, sizeof(SDL_VideoData));
if (data == NULL) {
SDL_OutOfMemory();
SDL_free(device);
return 0;
}
device->driverdata = data;
/* Set the function pointers */
device->VideoInit = WINRT_VideoInit;
device->VideoQuit = WINRT_VideoQuit;
device->CreateSDLWindow = WINRT_CreateWindow;
device->SetWindowSize = WINRT_SetWindowSize;
device->SetWindowFullscreen = WINRT_SetWindowFullscreen;
device->DestroyWindow = WINRT_DestroyWindow;
device->SetDisplayMode = WINRT_SetDisplayMode;
device->PumpEvents = WINRT_PumpEvents;
device->GetWindowWMInfo = WINRT_GetWindowWMInfo;
device->SuspendScreenSaver = WINRT_SuspendScreenSaver;
#if NTDDI_VERSION >= NTDDI_WIN10
device->HasScreenKeyboardSupport = WINRT_HasScreenKeyboardSupport;
device->ShowScreenKeyboard = WINRT_ShowScreenKeyboard;
device->HideScreenKeyboard = WINRT_HideScreenKeyboard;
device->IsScreenKeyboardShown = WINRT_IsScreenKeyboardShown;
WINTRT_InitialiseInputPaneEvents(device);
#endif
#ifdef SDL_VIDEO_OPENGL_EGL
device->GL_LoadLibrary = WINRT_GLES_LoadLibrary;
device->GL_GetProcAddress = WINRT_GLES_GetProcAddress;
device->GL_UnloadLibrary = WINRT_GLES_UnloadLibrary;
device->GL_CreateContext = WINRT_GLES_CreateContext;
device->GL_MakeCurrent = WINRT_GLES_MakeCurrent;
device->GL_SetSwapInterval = WINRT_GLES_SetSwapInterval;
device->GL_GetSwapInterval = WINRT_GLES_GetSwapInterval;
device->GL_SwapWindow = WINRT_GLES_SwapWindow;
device->GL_DeleteContext = WINRT_GLES_DeleteContext;
#endif
device->free = WINRT_DeleteDevice;
return device;
}
#define WINRTVID_DRIVER_NAME "winrt"
VideoBootStrap WINRT_bootstrap = {
WINRTVID_DRIVER_NAME, "SDL WinRT video driver",
WINRT_CreateDevice
};
static void SDLCALL WINRT_SetDisplayOrientationsPreference(void *userdata, const char *name, const char *oldValue, const char *newValue)
{
SDL_assert(SDL_strcmp(name, SDL_HINT_ORIENTATIONS) == 0);
/* HACK: prevent SDL from altering an app's .appxmanifest-set orientation
* from being changed on startup, by detecting when SDL_HINT_ORIENTATIONS
* is getting registered.
*
* TODO, WinRT: consider reading in an app's .appxmanifest file, and apply its orientation when 'newValue == NULL'.
*/
if ((oldValue == NULL) && (newValue == NULL)) {
return;
}
// Start with no orientation flags, then add each in as they're parsed
// from newValue.
unsigned int orientationFlags = 0;
if (newValue) {
std::istringstream tokenizer(newValue);
while (!tokenizer.eof()) {
std::string orientationName;
std::getline(tokenizer, orientationName, ' ');
if (orientationName == "LandscapeLeft") {
orientationFlags |= (unsigned int)DisplayOrientations::LandscapeFlipped;
} else if (orientationName == "LandscapeRight") {
orientationFlags |= (unsigned int)DisplayOrientations::Landscape;
} else if (orientationName == "Portrait") {
orientationFlags |= (unsigned int)DisplayOrientations::Portrait;
} else if (orientationName == "PortraitUpsideDown") {
orientationFlags |= (unsigned int)DisplayOrientations::PortraitFlipped;
}
}
}
// If no valid orientation flags were specified, use a reasonable set of defaults:
if (!orientationFlags) {
// TODO, WinRT: consider seeing if an app's default orientation flags can be found out via some API call(s).
orientationFlags = (unsigned int)(DisplayOrientations::Landscape |
DisplayOrientations::LandscapeFlipped |
DisplayOrientations::Portrait |
DisplayOrientations::PortraitFlipped);
}
// Set the orientation/rotation preferences. Please note that this does
// not constitute a 100%-certain lock of a given set of possible
// orientations. According to Microsoft's documentation on WinRT [1]
// when a device is not capable of being rotated, Windows may ignore
// the orientation preferences, and stick to what the device is capable of
// displaying.
//
// [1] Documentation on the 'InitialRotationPreference' setting for a
// Windows app's manifest file describes how some orientation/rotation
// preferences may be ignored. See
// http://msdn.microsoft.com/en-us/library/windows/apps/hh700343.aspx
// for details. Microsoft's "Display orientation sample" also gives an
// outline of how Windows treats device rotation
// (http://code.msdn.microsoft.com/Display-Orientation-Sample-19a58e93).
WINRT_DISPLAY_PROPERTY(AutoRotationPreferences) = (DisplayOrientations)orientationFlags;
}
int WINRT_VideoInit(SDL_VideoDevice *_this)
{
SDL_VideoData *driverdata = _this->driverdata;
if (WINRT_InitModes(_this) < 0) {
return -1;
}
// Register the hint, SDL_HINT_ORIENTATIONS, with SDL.
// TODO, WinRT: see if an app's default orientation can be found out via WinRT API(s), then set the initial value of SDL_HINT_ORIENTATIONS accordingly.
SDL_AddHintCallback(SDL_HINT_ORIENTATIONS, WINRT_SetDisplayOrientationsPreference, NULL);
WINRT_InitMouse(_this);
WINRT_InitTouch(_this);
WINRT_InitGameBar(_this);
if (driverdata) {
/* Initialize screensaver-disabling support */
driverdata->displayRequest = WINRT_CreateDisplayRequest(_this);
}
return 0;
}
extern "C" Uint32 D3D11_DXGIFormatToSDLPixelFormat(DXGI_FORMAT dxgiFormat);
static void WINRT_DXGIModeToSDLDisplayMode(const DXGI_MODE_DESC *dxgiMode, SDL_DisplayMode *sdlMode)
{
SDL_zerop(sdlMode);
sdlMode->w = dxgiMode->Width;
sdlMode->h = dxgiMode->Height;
sdlMode->refresh_rate = (((100 * dxgiMode->RefreshRate.Numerator) / dxgiMode->RefreshRate.Denominator) / 100.0f);
sdlMode->format = D3D11_DXGIFormatToSDLPixelFormat(dxgiMode->Format);
}
static int WINRT_AddDisplaysForOutput(SDL_VideoDevice *_this, IDXGIAdapter1 *dxgiAdapter1, int outputIndex)
{
HRESULT hr;
IDXGIOutput *dxgiOutput = NULL;
DXGI_OUTPUT_DESC dxgiOutputDesc;
SDL_VideoDisplay display;
UINT numModes;
DXGI_MODE_DESC *dxgiModes = NULL;
int functionResult = -1; /* -1 for failure, 0 for success */
DXGI_MODE_DESC modeToMatch, closestMatch;
SDL_zero(display);
hr = dxgiAdapter1->EnumOutputs(outputIndex, &dxgiOutput);
if (FAILED(hr)) {
if (hr != DXGI_ERROR_NOT_FOUND) {
WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIAdapter1::EnumOutputs failed", hr);
}
goto done;
}
hr = dxgiOutput->GetDesc(&dxgiOutputDesc);
if (FAILED(hr)) {
WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIOutput::GetDesc failed", hr);
goto done;
}
SDL_zero(modeToMatch);
modeToMatch.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
modeToMatch.Width = (dxgiOutputDesc.DesktopCoordinates.right - dxgiOutputDesc.DesktopCoordinates.left);
modeToMatch.Height = (dxgiOutputDesc.DesktopCoordinates.bottom - dxgiOutputDesc.DesktopCoordinates.top);
hr = dxgiOutput->FindClosestMatchingMode(&modeToMatch, &closestMatch, NULL);
if (hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE) {
/* DXGI_ERROR_NOT_CURRENTLY_AVAILABLE gets returned by IDXGIOutput::FindClosestMatchingMode
when running under the Windows Simulator, which uses Remote Desktop (formerly known as Terminal
Services) under the hood. According to the MSDN docs for the similar function,
IDXGIOutput::GetDisplayModeList, DXGI_ERROR_NOT_CURRENTLY_AVAILABLE is returned if and
when an app is run under a Terminal Services session, hence the assumption.
In this case, just add an SDL display mode, with approximated values.
*/
SDL_DisplayMode mode;
SDL_zero(mode);
display.name = SDL_strdup("Windows Simulator / Terminal Services Display");
mode.w = (dxgiOutputDesc.DesktopCoordinates.right - dxgiOutputDesc.DesktopCoordinates.left);
mode.h = (dxgiOutputDesc.DesktopCoordinates.bottom - dxgiOutputDesc.DesktopCoordinates.top);
mode.format = DXGI_FORMAT_B8G8R8A8_UNORM;
display.desktop_mode = mode;
} else if (FAILED(hr)) {
WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIOutput::FindClosestMatchingMode failed", hr);
goto done;
} else {
display.name = WIN_StringToUTF8(dxgiOutputDesc.DeviceName);
WINRT_DXGIModeToSDLDisplayMode(&closestMatch, &display.desktop_mode);
hr = dxgiOutput->GetDisplayModeList(DXGI_FORMAT_B8G8R8A8_UNORM, 0, &numModes, NULL);
if (FAILED(hr)) {
if (hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE) {
// TODO, WinRT: make sure display mode(s) are added when using Terminal Services / Windows Simulator
}
WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIOutput::GetDisplayModeList [get mode list size] failed", hr);
goto done;
}
dxgiModes = (DXGI_MODE_DESC *)SDL_calloc(numModes, sizeof(DXGI_MODE_DESC));
if (dxgiModes == NULL) {
SDL_OutOfMemory();
goto done;
}
hr = dxgiOutput->GetDisplayModeList(DXGI_FORMAT_B8G8R8A8_UNORM, 0, &numModes, dxgiModes);
if (FAILED(hr)) {
WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIOutput::GetDisplayModeList [get mode contents] failed", hr);
goto done;
}
for (UINT i = 0; i < numModes; ++i) {
SDL_DisplayMode sdlMode;
WINRT_DXGIModeToSDLDisplayMode(&dxgiModes[i], &sdlMode);
SDL_AddFullscreenDisplayMode(&display, &sdlMode);
}
}
if (SDL_AddVideoDisplay(&display, SDL_FALSE) == 0) {
goto done;
}
functionResult = 0; /* 0 for Success! */
done:
if (dxgiModes) {
SDL_free(dxgiModes);
}
if (dxgiOutput) {
dxgiOutput->Release();
}
if (display.name) {
SDL_free(display.name);
}
return functionResult;
}
static int WINRT_AddDisplaysForAdapter(SDL_VideoDevice *_this, IDXGIFactory2 *dxgiFactory2, int adapterIndex)
{
HRESULT hr;
IDXGIAdapter1 *dxgiAdapter1;
hr = dxgiFactory2->EnumAdapters1(adapterIndex, &dxgiAdapter1);
if (FAILED(hr)) {
if (hr != DXGI_ERROR_NOT_FOUND) {
WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIFactory1::EnumAdapters1() failed", hr);
}
return -1;
}
for (int outputIndex = 0;; ++outputIndex) {
if (WINRT_AddDisplaysForOutput(_this, dxgiAdapter1, outputIndex) < 0) {
/* HACK: The Windows App Certification Kit 10.0 can fail, when
running the Store Apps' test, "Direct3D Feature Test". The
certification kit's error is:
"Application App was not running at the end of the test. It likely crashed or was terminated for having become unresponsive."
This was caused by SDL/WinRT's DXGI failing to report any
outputs. Attempts to get the 1st display-output from the
1st display-adapter can fail, with IDXGIAdapter::EnumOutputs
returning DXGI_ERROR_NOT_FOUND. This could be a bug in Windows,
the Windows App Certification Kit, or possibly in SDL/WinRT's
display detection code. Either way, try to detect when this
happens, and use a hackish means to create a reasonable-as-possible
'display mode'. -- DavidL
*/
if (adapterIndex == 0 && outputIndex == 0) {
SDL_VideoDisplay display;
SDL_DisplayMode mode;
#if SDL_WINRT_USE_APPLICATIONVIEW
ApplicationView ^ appView = ApplicationView::GetForCurrentView();
#endif
CoreWindow ^ coreWin = CoreWindow::GetForCurrentThread();
SDL_zero(display);
SDL_zero(mode);
display.name = SDL_strdup("DXGI Display-detection Workaround");
/* HACK: ApplicationView's VisibleBounds property, appeared, via testing, to
give a better approximation of display-size, than did CoreWindow's
Bounds property, insofar that ApplicationView::VisibleBounds seems like
it will, at least some of the time, give the full display size (during the
failing test), whereas CoreWindow might not. -- DavidL
*/
#if (NTDDI_VERSION >= NTDDI_WIN10) || (SDL_WINRT_USE_APPLICATIONVIEW && SDL_WINAPI_FAMILY_PHONE)
mode.w = (int)SDL_floorf(appView->VisibleBounds.Width);
mode.h = (int)SDL_floorf(appView->VisibleBounds.Height);
#else
/* On platform(s) that do not support VisibleBounds, such as Windows 8.1,
fall back to CoreWindow's Bounds property.
*/
mode.w = (int)SDL_floorf(coreWin->Bounds.Width);
mode.h = (int)SDL_floorf(coreWin->Bounds.Height);
#endif
mode.pixel_density = WINRT_DISPLAY_PROPERTY(LogicalDpi) / 96.0f;
mode.format = DXGI_FORMAT_B8G8R8A8_UNORM;
display.desktop_mode = mode;
bool error = (SDL_AddVideoDisplay(&display, SDL_FALSE) == 0);
if (display.name) {
SDL_free(display.name);
}
if (error) {
return SDL_SetError("Failed to apply DXGI Display-detection workaround");
}
}
break;
}
}
dxgiAdapter1->Release();
return 0;
}
int WINRT_InitModes(SDL_VideoDevice *_this)
{
/* HACK: Initialize a single display, for whatever screen the app's
CoreApplicationView is on.
TODO, WinRT: Try initializing multiple displays, one for each monitor.
Appropriate WinRT APIs for this seem elusive, though. -- DavidL
*/
HRESULT hr;
IDXGIFactory2 *dxgiFactory2 = NULL;
hr = CreateDXGIFactory1(SDL_IID_IDXGIFactory2, (void **)&dxgiFactory2);
if (FAILED(hr)) {
return WIN_SetErrorFromHRESULT(__FUNCTION__ ", CreateDXGIFactory1() failed", hr);
}
for (int adapterIndex = 0;; ++adapterIndex) {
if (WINRT_AddDisplaysForAdapter(_this, dxgiFactory2, adapterIndex) < 0) {
break;
}
}
return 0;
}
static int WINRT_SetDisplayMode(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_DisplayMode *mode)
{
return 0;
}
void WINRT_VideoQuit(SDL_VideoDevice *_this)
{
SDL_VideoData *driverdata = _this->driverdata;
if (driverdata && driverdata->displayRequest) {
driverdata->displayRequest->Release();
driverdata->displayRequest = NULL;
}
WINRT_QuitGameBar(_this);
WINRT_QuitMouse(_this);
}
static const Uint32 WINRT_DetectableFlags = SDL_WINDOW_MAXIMIZED | SDL_WINDOW_FULLSCREEN | SDL_WINDOW_HIDDEN | SDL_WINDOW_MOUSE_FOCUS;
extern "C" Uint32
WINRT_DetectWindowFlags(SDL_Window *window)
{
Uint32 latestFlags = 0;
SDL_WindowData *data = window->driverdata;
bool is_fullscreen = false;
#if SDL_WINRT_USE_APPLICATIONVIEW
if (data->appView) {
is_fullscreen = data->appView->IsFullScreenMode;
}
#elif SDL_WINAPI_FAMILY_PHONE || NTDDI_VERSION == NTDDI_WIN8
is_fullscreen = true;
#endif
if (data->coreWindow.Get()) {
if (is_fullscreen) {
SDL_VideoDisplay *display = SDL_GetVideoDisplayForWindow(window);
int w = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Width);
int h = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Height);
#if !SDL_WINAPI_FAMILY_PHONE || NTDDI_VERSION > NTDDI_WIN8
// On all WinRT platforms, except for WinPhone 8.0, rotate the
// window size. This is needed to properly calculate
// fullscreen vs. maximized.
const DisplayOrientations currentOrientation = WINRT_DISPLAY_PROPERTY(CurrentOrientation);
switch (currentOrientation) {
#if SDL_WINAPI_FAMILY_PHONE
case DisplayOrientations::Landscape:
case DisplayOrientations::LandscapeFlipped:
#else
case DisplayOrientations::Portrait:
case DisplayOrientations::PortraitFlipped:
#endif
{
int tmp = w;
w = h;
h = tmp;
} break;
}
#endif
if (display->desktop_mode.w != w || display->desktop_mode.h != h) {
latestFlags |= SDL_WINDOW_MAXIMIZED;
} else {
latestFlags |= SDL_WINDOW_FULLSCREEN;
}
}
if (data->coreWindow->Visible) {
latestFlags &= ~SDL_WINDOW_HIDDEN;
} else {
latestFlags |= SDL_WINDOW_HIDDEN;
}
#if SDL_WINAPI_FAMILY_PHONE && NTDDI_VERSION < NTDDI_WINBLUE
// data->coreWindow->PointerPosition is not supported on WinPhone 8.0
latestFlags |= SDL_WINDOW_MOUSE_FOCUS;
#else
if (data->coreWindow->Visible && data->coreWindow->Bounds.Contains(data->coreWindow->PointerPosition)) {
latestFlags |= SDL_WINDOW_MOUSE_FOCUS;
}
#endif
}
return latestFlags;
}
// TODO, WinRT: consider removing WINRT_UpdateWindowFlags, and just calling WINRT_DetectWindowFlags as-appropriate (with appropriate calls to SDL_SendWindowEvent)
void WINRT_UpdateWindowFlags(SDL_Window *window, Uint32 mask)
{
mask &= WINRT_DetectableFlags;
if (window) {
Uint32 apply = WINRT_DetectWindowFlags(window);
window->flags = (window->flags & ~mask) | (apply & mask);
}
}
static bool WINRT_IsCoreWindowActive(CoreWindow ^ coreWindow)
{
/* WinRT does not appear to offer API(s) to determine window-activation state,
at least not that I am aware of in Win8 - Win10. As such, SDL tracks this
itself, via window-activation events.
If there *is* an API to track this, it should probably get used instead
of the following hack (that uses "SDLHelperWindowActivationState").
-- DavidL.
*/
if (coreWindow->CustomProperties->HasKey("SDLHelperWindowActivationState")) {
CoreWindowActivationState activationState =
safe_cast<CoreWindowActivationState>(coreWindow->CustomProperties->Lookup("SDLHelperWindowActivationState"));
return activationState != CoreWindowActivationState::Deactivated;
}
/* Assume that non-SDL tracked windows are active, although this should
probably be avoided, if possible.
This might not even be possible, in normal SDL use, at least as of
this writing (Dec 22, 2015; via latest hg.libsdl.org/SDL clone) -- DavidL
*/
return true;
}
int WINRT_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window)
{
// Make sure that only one window gets created, at least until multimonitor
// support is added.
if (WINRT_GlobalSDLWindow != NULL) {
return SDL_SetError("WinRT only supports one window");
}
SDL_WindowData *data = new SDL_WindowData; /* use 'new' here as SDL_WindowData may use WinRT/C++ types */
if (!data) {
return SDL_OutOfMemory();
}
window->driverdata = data;
data->sdlWindow = window;
/* 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();
#if SDL_WINRT_USE_APPLICATIONVIEW
data->appView = ApplicationView::GetForCurrentView();
#endif
}
/* Make note of the requested window flags, before they start getting changed. */
const Uint32 requestedFlags = window->flags;
#ifdef SDL_VIDEO_OPENGL_EGL
/* Setup the EGL surface, but only if OpenGL ES 2 was requested. */
if (!(window->flags & SDL_WINDOW_OPENGL)) {
/* OpenGL ES 2 wasn't requested. Don't set up an EGL surface. */
data->egl_surface = EGL_NO_SURFACE;
} else {
/* OpenGL ES 2 was requested. Set up an EGL surface. */
SDL_VideoData *video_data = _this->driverdata;
/* Call SDL_EGL_ChooseConfig and eglCreateWindowSurface directly,
* rather than via SDL_EGL_CreateSurface, as older versions of
* ANGLE/WinRT may require that a C++ object, ComPtr<IUnknown>,
* be passed into eglCreateWindowSurface.
*/
if (SDL_EGL_ChooseConfig(_this) != 0) {
/* SDL_EGL_ChooseConfig failed, SDL_GetError() should have info */
return -1;
}
if (video_data->winrtEglWindow) { /* ... is the 'old' version of ANGLE/WinRT being used? */
/* Attempt to create a window surface using older versions of
* ANGLE/WinRT:
*/
Microsoft::WRL::ComPtr<IUnknown> cpp_winrtEglWindow = video_data->winrtEglWindow;
data->egl_surface = ((eglCreateWindowSurface_Old_Function)_this->egl_data->eglCreateWindowSurface)(
_this->egl_data->egl_display,
_this->egl_data->egl_config,
cpp_winrtEglWindow, NULL);
if (data->egl_surface == NULL) {
return SDL_EGL_SetError("unable to create EGL native-window surface", "eglCreateWindowSurface");
}
} else if (data->coreWindow.Get() != nullptr) {
/* Attempt to create a window surface using newer versions of
* ANGLE/WinRT:
*/
IInspectable *coreWindowAsIInspectable = reinterpret_cast<IInspectable *>(data->coreWindow.Get());
data->egl_surface = _this->egl_data->eglCreateWindowSurface(
_this->egl_data->egl_display,
_this->egl_data->egl_config,
(NativeWindowType)coreWindowAsIInspectable,
NULL);
if (data->egl_surface == NULL) {
return SDL_EGL_SetError("unable to create EGL native-window surface", "eglCreateWindowSurface");
}
} else {
return SDL_SetError("No supported means to create an EGL window surface are available");
}
}
#endif
/* Determine as many flags dynamically, as possible. */
window->flags =
SDL_WINDOW_BORDERLESS |
SDL_WINDOW_RESIZABLE;
#ifdef SDL_VIDEO_OPENGL_EGL
if (data->egl_surface) {
window->flags |= SDL_WINDOW_OPENGL;
}
#endif
if (WINRT_XAMLWasEnabled) {
/* TODO, WinRT: set SDL_Window size, maybe position too, from XAML control */
window->x = 0;
window->y = 0;
window->flags &= ~SDL_WINDOW_HIDDEN;
SDL_SetMouseFocus(NULL); // TODO: detect this
SDL_SetKeyboardFocus(NULL); // TODO: detect this
} else {
/* WinRT 8.x apps seem to live in an environment where the OS controls the
app's window size, with some apps being fullscreen, depending on
user choice of various things. For now, just adapt the SDL_Window to
whatever Windows set-up as the native-window's geometry.
*/
window->x = (int)SDL_lroundf(data->coreWindow->Bounds.Left);
window->y = (int)SDL_lroundf(data->coreWindow->Bounds.Top);
#if NTDDI_VERSION < NTDDI_WIN10
/* On WinRT 8.x / pre-Win10, just use the size we were given. */
window->w = (int)SDL_floorf(data->coreWindow->Bounds.Width);
window->h = (int)SDL_floorf(data->coreWindow->Bounds.Height);
#else
/* On Windows 10, we occasionally get control over window size. For windowed
mode apps, try this.
*/
bool didSetSize = false;
if ((requestedFlags & SDL_WINDOW_FULLSCREEN) == 0) {
const Windows::Foundation::Size size((float)window->w, (float)window->h);
didSetSize = data->appView->TryResizeView(size);
}
if (!didSetSize) {
/* We either weren't able to set the window size, or a request for
fullscreen was made. Get window-size info from the OS.
*/
window->w = (int)SDL_floorf(data->coreWindow->Bounds.Width);
window->h = (int)SDL_floorf(data->coreWindow->Bounds.Height);
}
#endif
WINRT_UpdateWindowFlags(
window,
0xffffffff /* Update any window flag(s) that WINRT_UpdateWindow can handle */
);
/* Try detecting if the window is active */
bool isWindowActive = WINRT_IsCoreWindowActive(data->coreWindow.Get());
if (isWindowActive) {
SDL_SetKeyboardFocus(window);
}
}
/* Make sure the WinRT app's IFramworkView can post events on
behalf of SDL:
*/
WINRT_GlobalSDLWindow = window;
/* All done! */
return 0;
}
void WINRT_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window)
{
#if NTDDI_VERSION >= NTDDI_WIN10
SDL_WindowData *data = window->driverdata;
const Windows::Foundation::Size size((float)window->w, (float)window->h);
data->appView->TryResizeView(size); // TODO, WinRT: return failure (to caller?) from TryResizeView()
#endif
}
void WINRT_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen)
{
#if NTDDI_VERSION >= NTDDI_WIN10
SDL_WindowData *data = window->driverdata;
bool isWindowActive = WINRT_IsCoreWindowActive(data->coreWindow.Get());
if (isWindowActive) {
if (fullscreen) {
if (!data->appView->IsFullScreenMode) {
data->appView->TryEnterFullScreenMode(); // TODO, WinRT: return failure (to caller?) from TryEnterFullScreenMode()
}
} else {
if (data->appView->IsFullScreenMode) {
data->appView->ExitFullScreenMode();
}
}
}
#endif
}
void WINRT_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window)
{
SDL_WindowData *data = window->driverdata;
if (WINRT_GlobalSDLWindow == window) {
WINRT_GlobalSDLWindow = NULL;
}
if (data) {
// Delete the internal window data:
delete data;
data = NULL;
window->driverdata = NULL;
}
}
int WINRT_GetWindowWMInfo(SDL_VideoDevice *_this, SDL_Window *window, SDL_SysWMinfo *info)
{
SDL_WindowData *data = window->driverdata;
info->subsystem = SDL_SYSWM_WINRT;
info->info.winrt.window = reinterpret_cast<IInspectable *>(data->coreWindow.Get());
return 0;
}
static ABI::Windows::System::Display::IDisplayRequest *WINRT_CreateDisplayRequest(SDL_VideoDevice *_this)
{
/* Setup a WinRT DisplayRequest object, usable for enabling/disabling screensaver requests */
const wchar_t *wClassName = L"Windows.System.Display.DisplayRequest";
HSTRING hClassName;
IActivationFactory *pActivationFactory = NULL;
IInspectable *pDisplayRequestRaw = nullptr;
ABI::Windows::System::Display::IDisplayRequest *pDisplayRequest = nullptr;
HRESULT hr;
hr = ::WindowsCreateString(wClassName, (UINT32)SDL_wcslen(wClassName), &hClassName);
if (FAILED(hr)) {
goto done;
}
hr = Windows::Foundation::GetActivationFactory(hClassName, &pActivationFactory);
if (FAILED(hr)) {
goto done;
}
hr = pActivationFactory->ActivateInstance(&pDisplayRequestRaw);
if (FAILED(hr)) {
goto done;
}
hr = pDisplayRequestRaw->QueryInterface(SDL_IID_IDisplayRequest, (void **)&pDisplayRequest);
if (FAILED(hr)) {
goto done;
}
done:
if (pDisplayRequestRaw) {
pDisplayRequestRaw->Release();
}
if (pActivationFactory) {
pActivationFactory->Release();
}
if (hClassName) {
::WindowsDeleteString(hClassName);
}
return pDisplayRequest;
}
int WINRT_SuspendScreenSaver(SDL_VideoDevice *_this)
{
SDL_VideoData *driverdata = _this->driverdata;
if (driverdata && driverdata->displayRequest) {
ABI::Windows::System::Display::IDisplayRequest *displayRequest = (ABI::Windows::System::Display::IDisplayRequest *)driverdata->displayRequest;
if (_this->suspend_screensaver) {
displayRequest->RequestActive();
} else {
displayRequest->RequestRelease();
}
}
return 0;
}
#endif /* SDL_VIDEO_DRIVER_WINRT */

View File

@@ -0,0 +1,105 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 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 <windows.h>
#ifdef __cplusplus_winrt
#include <agile.h>
#endif
/* SDL includes: */
#if NTDDI_VERSION >= NTDDI_WINBLUE /* ApplicationView's functionality only becomes \
useful for SDL in Win[Phone] 8.1 and up. \
Plus, it is not available at all in WinPhone 8.0. */
#define SDL_WINRT_USE_APPLICATIONVIEW 1
#endif
extern "C" {
#include "../SDL_sysvideo.h"
#include "../SDL_egl_c.h"
}
/* Private display data */
struct SDL_VideoData
{
/* An object created by ANGLE/WinRT (OpenGL ES 2 for WinRT) that gets
* passed to eglGetDisplay and eglCreateWindowSurface:
*/
IUnknown *winrtEglWindow;
/* Event token(s), for unregistering WinRT event handler(s).
These are just a struct with a 64-bit integer inside them
*/
Windows::Foundation::EventRegistrationToken gameBarIsInputRedirectedToken;
/* A WinRT DisplayRequest, used for implementing SDL_*ScreenSaver() functions.
* This is really a pointer to a 'ABI::Windows::System::Display::IDisplayRequest *',
* It's casted to 'IUnknown *', to help with building SDL.
*/
IUnknown *displayRequest;
};
/* The global, WinRT, SDL Window.
For now, SDL/WinRT only supports one window (due to platform limitations of
WinRT.
*/
extern SDL_Window *WINRT_GlobalSDLWindow;
/* Updates one or more SDL_Window flags, by querying the OS' native windowing APIs.
SDL_Window flags that can be updated should be specified in 'mask'.
*/
extern void WINRT_UpdateWindowFlags(SDL_Window *window, Uint32 mask);
extern "C" Uint32 WINRT_DetectWindowFlags(SDL_Window *window); /* detects flags w/o applying them */
/* Display mode internals */
// typedef struct
//{
// Windows::Graphics::Display::DisplayOrientations currentOrientation;
// } SDL_DisplayModeData;
#ifdef __cplusplus_winrt
/* A convenience macro to get a WinRT display property */
#if NTDDI_VERSION > NTDDI_WIN8
#define WINRT_DISPLAY_PROPERTY(NAME) (Windows::Graphics::Display::DisplayInformation::GetForCurrentView()->NAME)
#else
#define WINRT_DISPLAY_PROPERTY(NAME) (Windows::Graphics::Display::DisplayProperties::NAME)
#endif
/* Converts DIPS to/from physical pixels */
#define WINRT_DIPS_TO_PHYSICAL_PIXELS(DIPS) ((int)(0.5f + (((float)(DIPS) * (float)WINRT_DISPLAY_PROPERTY(LogicalDpi)) / 96.f)))
#define WINRT_PHYSICAL_PIXELS_TO_DIPS(PHYSPIX) (((float)(PHYSPIX)*96.f) / WINRT_DISPLAY_PROPERTY(LogicalDpi))
/* Internal window data */
struct SDL_WindowData
{
SDL_Window *sdlWindow;
Platform::Agile<Windows::UI::Core::CoreWindow> coreWindow;
#ifdef SDL_VIDEO_OPENGL_EGL
EGLSurface egl_surface;
#endif
#if SDL_WINRT_USE_APPLICATIONVIEW
Windows::UI::ViewManagement::ApplicationView ^ appView;
#endif
};
#endif // ifdef __cplusplus_winrt