early-access version 1611

This commit is contained in:
pineappleEA
2021-04-18 05:35:25 +02:00
parent 16f54e367d
commit 18db69f039
1409 changed files with 545335 additions and 10 deletions

View File

@@ -0,0 +1,154 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 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 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"
#include "SDL_assert.h"
#include "SDL_system.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(_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_cond * _cond = nullptr;
static void
WINRT_YieldXAMLThread()
{
SDL_LockMutex(_mutex);
SDL_assert(_threadState == ThreadState_Running);
_threadState = ThreadState_Yielding;
SDL_UnlockMutex(_mutex);
SDL_CondSignal(_cond);
SDL_LockMutex(_mutex);
while (_threadState != ThreadState_Running) {
SDL_CondWait(_cond, _mutex);
}
SDL_UnlockMutex(_mutex);
}
static int
WINRT_XAMLThreadMain(void * userdata)
{
// 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_CreateCond();
_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_CondWait(_cond, _mutex);
}
SDL_UnlockMutex(_mutex);
break;
}
case ThreadState_Running:
{
SDL_assert(false);
break;
}
case ThreadState_Yielding:
{
SDL_LockMutex(_mutex);
SDL_assert(_threadState == ThreadState_Yielding);
_threadState = ThreadState_Running;
SDL_UnlockMutex(_mutex);
SDL_CondSignal(_cond);
SDL_LockMutex(_mutex);
while (_threadState != ThreadState_Yielding) {
SDL_CondWait(_cond, _mutex);
}
SDL_UnlockMutex(_mutex);
}
}
}
#endif /* SDL_VIDEO_DRIVER_WINRT */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -0,0 +1,82 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 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_config.h"
extern "C" {
#include "../SDL_sysvideo.h"
}
/*
* Internal-use, C-style functions:
*/
#ifdef __cplusplus
extern "C" {
#endif
extern void WINRT_InitTouch(_THIS);
extern void WINRT_PumpEvents(_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 Uint8 WINRT_GetSDLButtonForPointerPoint(Windows::UI::Input::PointerPoint ^pt);
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 SDL_bool WINRT_HasScreenKeyboardSupport(_THIS);
extern void WINRT_ShowScreenKeyboard(_THIS, SDL_Window *window);
extern void WINRT_HideScreenKeyboard(_THIS, SDL_Window *window);
extern SDL_bool WINRT_IsScreenKeyboardShown(_THIS, SDL_Window *window);
#endif // NTDDI_VERSION >= ...
/* XAML Thread Management */
extern void WINRT_CycleXAMLThread(void);
#endif // ifdef __cplusplus_winrt
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -0,0 +1,196 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 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 SDL_VIDEO_DRIVER_WINRT
/* Windows includes */
#include <roapi.h>
#include <windows.foundation.h>
#include <EventToken.h>
/* SDL includes */
extern "C" {
#include "SDL_mouse.h"
#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()
{
wchar_t *wClassName = L"Windows.Gaming.UI.GameBar";
HSTRING hClassName;
IActivationFactory *pActivationFactory = NULL;
IGameBarStatics_ *pGameBar = NULL;
HRESULT hr;
hr = ::WindowsCreateString(wClassName, (UINT32)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) {
/* 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(_THIS)
{
SDL_VideoData *driverdata = (SDL_VideoData *)_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(_THIS)
{
SDL_VideoData *driverdata;
IGameBarStatics_ *gameBar;
if (!_this || !_this->driverdata) {
return;
}
gameBar = WINRT_GetGameBar();
if (!gameBar) {
return;
}
driverdata = (SDL_VideoData *)_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 */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -0,0 +1,35 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 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_config.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(_THIS);
extern void WINRT_QuitGameBar(_THIS);
#endif
#endif /* SDL_winrtgamebar_h_ */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -0,0 +1,430 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 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 SDL_VIDEO_DRIVER_WINRT
/* Windows-specific includes */
#include <Windows.h>
#include <agile.h>
/* SDL-specific includes */
#include "SDL.h"
#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(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(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_TEXTINPUT 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
SDL_bool WINRT_HasScreenKeyboardSupport(_THIS)
{
return SDL_TRUE;
}
void WINRT_ShowScreenKeyboard(_THIS, SDL_Window *window)
{
using namespace Windows::UI::ViewManagement;
InputPane ^ inputPane = InputPane::GetForCurrentView();
if (inputPane) {
inputPane->TryShow();
}
}
void WINRT_HideScreenKeyboard(_THIS, SDL_Window *window)
{
using namespace Windows::UI::ViewManagement;
InputPane ^ inputPane = InputPane::GetForCurrentView();
if (inputPane) {
inputPane->TryHide();
}
}
SDL_bool WINRT_IsScreenKeyboardShown(_THIS, SDL_Window *window)
{
using namespace Windows::UI::ViewManagement;
InputPane ^ inputPane = InputPane::GetForCurrentView();
if (inputPane) {
// dludwig@pobox.com: checking inputPane->Visible doesn't seem to detect visibility,
// at least not on the Windows Phone 10.0.10240.0 emulator. Checking
// the size of inputPane->OccludedRect, however, does seem to work.
Windows::Foundation::Rect rect = inputPane->OccludedRect;
if (rect.Width > 0 && rect.Height > 0) {
return SDL_TRUE;
}
}
return SDL_FALSE;
}
#endif // NTDDI_VERSION >= ...
#endif // SDL_VIDEO_DRIVER_WINRT

View File

@@ -0,0 +1,118 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 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 SDL_VIDEO_DRIVER_WINRT
extern "C" {
#include "SDL_messagebox.h"
#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 (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) && (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 WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
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 = safe_cast<IntPtr>((int)(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>((int)(operation->GetResults()->Id));
int clicked_index = results.ToInt32();
*buttonid = messageboxdata->buttons[clicked_index].buttonid;
}
return 0;
#endif /* if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP / else */
}
#endif /* SDL_VIDEO_DRIVER_WINRT */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -0,0 +1,29 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 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 SDL_VIDEO_DRIVER_WINRT
extern int WINRT_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid);
#endif /* SDL_VIDEO_DRIVER_WINRT */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -0,0 +1,224 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 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 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 "SDL_assert.h"
#include "../../events/SDL_mouse_c.h"
#include "../../events/SDL_touch_c.h"
#include "../SDL_sysvideo.h"
#include "SDL_events.h"
#include "SDL_log.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/SDL2-WinRTResource_BlankCursor.cur -- cursor pixel data
// - src/main/winrt/SDL2-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(_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 WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP
//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(_THIS)
{
}
#endif /* SDL_VIDEO_DRIVER_WINRT */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -0,0 +1,40 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 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_config.h"
#ifndef SDL_winrtmouse_h_
#define SDL_winrtmouse_h_
#ifdef __cplusplus
extern "C" {
#endif
extern void WINRT_InitMouse(_THIS);
extern void WINRT_QuitMouse(_THIS);
extern SDL_bool WINRT_UsingRelativeMouseMode;
#ifdef __cplusplus
}
#endif
#endif /* SDL_winrtmouse_h_ */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -0,0 +1,203 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 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 SDL_VIDEO_DRIVER_WINRT && SDL_VIDEO_OPENGL_EGL
/* EGL implementation of SDL OpenGL support */
#include "SDL_winrtvideo_cpp.h"
extern "C" {
#include "SDL_winrtopengles.h"
#include "SDL_loadso.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(_THIS, const char *path)
{
SDL_VideoData *video_data = (SDL_VideoData *)_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->egl_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 (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP)
/* 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(_THIS)
{
SDL_VideoData *video_data = (SDL_VideoData *)_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 */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -0,0 +1,70 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 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_config.h"
#ifndef SDL_winrtopengles_h_
#define SDL_winrtopengles_h_
#if SDL_VIDEO_DRIVER_WINRT && 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_GetProcAddress
#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(_THIS, const char *path);
extern void WINRT_GLES_UnloadLibrary(_THIS);
extern SDL_GLContext WINRT_GLES_CreateContext(_THIS, SDL_Window * window);
extern int WINRT_GLES_SwapWindow(_THIS, SDL_Window * window);
extern int WINRT_GLES_MakeCurrent(_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_ */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -0,0 +1,397 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 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 SDL_VIDEO_DRIVER_WINRT
/* SDL includes */
#include "SDL_winrtevents_c.h"
#include "SDL_winrtmouse_c.h"
#include "SDL_winrtvideo_cpp.h"
#include "SDL_assert.h"
#include "SDL_system.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(_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 = (SDL_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 (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP) || (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;
}
static inline int
_lround(float arg)
{
if (arg >= 0.0f) {
return (int)floor(arg + 0.5f);
} else {
return (int)ceil(arg - 0.5f);
}
}
Uint8
WINRT_GetSDLButtonForPointerPoint(Windows::UI::Input::PointerPoint ^pt)
{
using namespace Windows::UI::Input;
#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
return SDL_BUTTON_LEFT;
#else
switch (pt->Properties->PointerUpdateKind)
{
case PointerUpdateKind::LeftButtonPressed:
case PointerUpdateKind::LeftButtonReleased:
return SDL_BUTTON_LEFT;
case PointerUpdateKind::RightButtonPressed:
case PointerUpdateKind::RightButtonReleased:
return SDL_BUTTON_RIGHT;
case PointerUpdateKind::MiddleButtonPressed:
case PointerUpdateKind::MiddleButtonReleased:
return SDL_BUTTON_MIDDLE;
case PointerUpdateKind::XButton1Pressed:
case PointerUpdateKind::XButton1Released:
return SDL_BUTTON_X1;
case PointerUpdateKind::XButton2Pressed:
case PointerUpdateKind::XButton2Released:
return SDL_BUTTON_X2;
default:
break;
}
#endif
return 0;
}
//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 WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
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;
}
Uint8 button = WINRT_GetSDLButtonForPointerPoint(pointerPoint);
if ( ! WINRT_IsTouchEvent(pointerPoint)) {
SDL_SendMouseButton(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(
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)) {
SDL_SendMouseMotion(window, 0, 0, (int)windowPoint.X, (int)windowPoint.Y);
} else {
SDL_SendTouchMotion(
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;
}
Uint8 button = WINRT_GetSDLButtonForPointerPoint(pointerPoint);
if (!WINRT_IsTouchEvent(pointerPoint)) {
SDL_SendMouseButton(window, 0, SDL_RELEASED, button);
} else {
Windows::Foundation::Point normalizedPoint = WINRT_TransformCursorPosition(window, pointerPoint->Position, NormalizeZeroToOne);
SDL_SendTouch(
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(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. For now, however, the system-reported values are sent
// to SDL with minimal transformation: from native screen coordinates (in DIPs)
// to SDL window coordinates.
//
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(
window,
0,
1,
_lround(mouseDeltaInSDLWindowCoords.X),
_lround(mouseDeltaInSDLWindowCoords.Y));
}
#endif // SDL_VIDEO_DRIVER_WINRT

View File

@@ -0,0 +1,842 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 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 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.
*/
/* Windows includes */
#include <agile.h>
#include <windows.graphics.display.h>
#include <windows.system.display.h>
#include <dxgi.h>
#include <dxgi1_2.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 IID_IDisplayRequest = { 0xe5732044, 0xf49f, 0x4b60, { 0x8d, 0xd4, 0x5e, 0x7e, 0x3a, 0x63, 0x2a, 0xc0 } };
static const GUID IID_IDXGIFactory2 = { 0x50c83a1c, 0xe072, 0x4c48, { 0x87, 0xb0, 0x36, 0x30, 0xfa, 0x36, 0xa6, 0xd0 } };
/* SDL includes */
extern "C" {
#include "SDL_video.h"
#include "SDL_mouse.h"
#include "../SDL_sysvideo.h"
#include "../SDL_pixels_c.h"
#include "../../events/SDL_events_c.h"
#include "../../render/SDL_sysrender.h"
#include "SDL_syswm.h"
#include "SDL_winrtopengles.h"
#include "../../core/windows/SDL_windows.h"
}
#include "../../core/winrt/SDL_winrtapp_direct3d.h"
#include "../../core/winrt/SDL_winrtapp_xaml.h"
#include "SDL_winrtvideo_cpp.h"
#include "SDL_winrtevents_c.h"
#include "SDL_winrtgamebar_cpp.h"
#include "SDL_winrtmouse_c.h"
#include "SDL_main.h"
#include "SDL_system.h"
//#include "SDL_log.h"
/* Initialization/Query functions */
static int WINRT_VideoInit(_THIS);
static int WINRT_InitModes(_THIS);
static int WINRT_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode);
static void WINRT_VideoQuit(_THIS);
/* Window functions */
static int WINRT_CreateWindow(_THIS, SDL_Window * window);
static void WINRT_SetWindowSize(_THIS, SDL_Window * window);
static void WINRT_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen);
static void WINRT_DestroyWindow(_THIS, SDL_Window * window);
static SDL_bool WINRT_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info);
/* Misc functions */
static ABI::Windows::System::Display::IDisplayRequest * WINRT_CreateDisplayRequest(_THIS);
extern void WINRT_SuspendScreenSaver(_THIS);
/* SDL-internal globals: */
SDL_Window * WINRT_GlobalSDLWindow = NULL;
/* WinRT driver bootstrap functions */
static int
WINRT_Available(void)
{
return (1);
}
static void
WINRT_DeleteDevice(SDL_VideoDevice * device)
{
if (device->driverdata) {
SDL_VideoData * video_data = (SDL_VideoData *)device->driverdata;
if (video_data->winrtEglWindow) {
video_data->winrtEglWindow->Release();
}
SDL_free(video_data);
}
SDL_free(device);
}
static SDL_VideoDevice *
WINRT_CreateDevice(int devindex)
{
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) {
SDL_OutOfMemory();
return (0);
}
data = (SDL_VideoData *) SDL_calloc(1, sizeof(SDL_VideoData));
if (!data) {
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;
#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_Available, WINRT_CreateDevice
};
int
WINRT_VideoInit(_THIS)
{
SDL_VideoData * driverdata = (SDL_VideoData *) _this->driverdata;
if (WINRT_InitModes(_this) < 0) {
return -1;
}
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 = dxgiMode->RefreshRate.Numerator / dxgiMode->RefreshRate.Denominator;
sdlMode->format = D3D11_DXGIFormatToSDLPixelFormat(dxgiMode->Format);
}
static int
WINRT_AddDisplaysForOutput (_THIS, IDXGIAdapter1 * dxgiAdapter1, int outputIndex)
{
HRESULT hr;
IDXGIOutput * dxgiOutput = NULL;
DXGI_OUTPUT_DESC dxgiOutputDesc;
SDL_VideoDisplay display;
char * displayName = NULL;
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 = "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;
mode.refresh_rate = 0; /* Display mode is unknown, so just fill in zero, as specified by SDL's header files */
display.desktop_mode = mode;
display.current_mode = mode;
if ( ! SDL_AddDisplayMode(&display, &mode)) {
goto done;
}
} else if (FAILED(hr)) {
WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIOutput::FindClosestMatchingMode failed", hr);
goto done;
} else {
displayName = WIN_StringToUTF8(dxgiOutputDesc.DeviceName);
display.name = displayName;
WINRT_DXGIModeToSDLDisplayMode(&closestMatch, &display.desktop_mode);
display.current_mode = 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) {
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_AddDisplayMode(&display, &sdlMode);
}
}
if (SDL_AddVideoDisplay(&display) < 0) {
goto done;
}
functionResult = 0; /* 0 for Success! */
done:
if (dxgiModes) {
SDL_free(dxgiModes);
}
if (dxgiOutput) {
dxgiOutput->Release();
}
if (displayName) {
SDL_free(displayName);
}
return functionResult;
}
static int
WINRT_AddDisplaysForAdapter (_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 = "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 && WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
mode.w = WINRT_DIPS_TO_PHYSICAL_PIXELS(appView->VisibleBounds.Width);
mode.h = WINRT_DIPS_TO_PHYSICAL_PIXELS(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 = WINRT_DIPS_TO_PHYSICAL_PIXELS(coreWin->Bounds.Width);
mode.h = WINRT_DIPS_TO_PHYSICAL_PIXELS(coreWin->Bounds.Height);
#endif
mode.format = DXGI_FORMAT_B8G8R8A8_UNORM;
mode.refresh_rate = 0; /* Display mode is unknown, so just fill in zero, as specified by SDL's header files */
display.desktop_mode = mode;
display.current_mode = mode;
if ((SDL_AddDisplayMode(&display, &mode) < 0) ||
(SDL_AddVideoDisplay(&display) < 0))
{
return SDL_SetError("Failed to apply DXGI Display-detection workaround");
}
}
break;
}
}
dxgiAdapter1->Release();
return 0;
}
int
WINRT_InitModes(_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(IID_IDXGIFactory2, (void **)&dxgiFactory2);
if (FAILED(hr)) {
WIN_SetErrorFromHRESULT(__FUNCTION__ ", CreateDXGIFactory1() failed", hr);
return -1;
}
for (int adapterIndex = 0; ; ++adapterIndex) {
if (WINRT_AddDisplaysForAdapter(_this, dxgiFactory2, adapterIndex) < 0) {
break;
}
}
return 0;
}
static int
WINRT_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
{
return 0;
}
void
WINRT_VideoQuit(_THIS)
{
SDL_VideoData * driverdata = (SDL_VideoData *) _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_DESKTOP |
SDL_WINDOW_SHOWN |
SDL_WINDOW_HIDDEN |
SDL_WINDOW_MOUSE_FOCUS;
extern "C" Uint32
WINRT_DetectWindowFlags(SDL_Window * window)
{
Uint32 latestFlags = 0;
SDL_WindowData * data = (SDL_WindowData *) window->driverdata;
bool is_fullscreen = false;
#if SDL_WINRT_USE_APPLICATIONVIEW
if (data->appView) {
is_fullscreen = data->appView->IsFullScreen;
}
#elif (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) || (NTDDI_VERSION == NTDDI_WIN8)
is_fullscreen = true;
#endif
if (data->coreWindow.Get()) {
if (is_fullscreen) {
SDL_VideoDisplay * display = SDL_GetDisplayForWindow(window);
int w = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Width);
int h = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Height);
#if (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP) || (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 (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
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_DESKTOP;
}
}
if (data->coreWindow->Visible) {
latestFlags |= SDL_WINDOW_SHOWN;
} else {
latestFlags |= SDL_WINDOW_HIDDEN;
}
#if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) && (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);
if ((apply & mask) & SDL_WINDOW_FULLSCREEN) {
window->last_fullscreen_flags = window->flags; // seems necessary to programmatically un-fullscreen, via SDL APIs
}
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(_THIS, SDL_Window * window)
{
// Make sure that only one window gets created, at least until multimonitor
// support is added.
if (WINRT_GlobalSDLWindow != NULL) {
SDL_SetError("WinRT only supports one window");
return -1;
}
SDL_WindowData *data = new SDL_WindowData; /* use 'new' here as SDL_WindowData may use WinRT/C++ types */
if (!data) {
SDL_OutOfMemory();
return -1;
}
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;
#if 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 reuqested. Set up an EGL surface. */
SDL_VideoData * video_data = (SDL_VideoData *)_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) {
char buf[512];
SDL_snprintf(buf, sizeof(buf), "SDL_EGL_ChooseConfig failed: %s", SDL_GetError());
return SDL_SetError("%s", buf);
}
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,
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;
#if 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_SHOWN;
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 = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Left);
window->y = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Top);
#if NTDDI_VERSION < NTDDI_WIN10
/* On WinRT 8.x / pre-Win10, just use the size we were given. */
window->w = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Width);
window->h = WINRT_DIPS_TO_PHYSICAL_PIXELS(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)) {
const Windows::Foundation::Size size(WINRT_PHYSICAL_PIXELS_TO_DIPS(window->w),
WINRT_PHYSICAL_PIXELS_TO_DIPS(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 = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Width);
window->h = WINRT_DIPS_TO_PHYSICAL_PIXELS(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(_THIS, SDL_Window * window)
{
#if NTDDI_VERSION >= NTDDI_WIN10
SDL_WindowData * data = (SDL_WindowData *)window->driverdata;
const Windows::Foundation::Size size(WINRT_PHYSICAL_PIXELS_TO_DIPS(window->w),
WINRT_PHYSICAL_PIXELS_TO_DIPS(window->h));
data->appView->TryResizeView(size); // TODO, WinRT: return failure (to caller?) from TryResizeView()
#endif
}
void
WINRT_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen)
{
#if NTDDI_VERSION >= NTDDI_WIN10
SDL_WindowData * data = (SDL_WindowData *)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(_THIS, SDL_Window * window)
{
SDL_WindowData * data = (SDL_WindowData *) window->driverdata;
if (WINRT_GlobalSDLWindow == window) {
WINRT_GlobalSDLWindow = NULL;
}
if (data) {
// Delete the internal window data:
delete data;
data = NULL;
window->driverdata = NULL;
}
}
SDL_bool
WINRT_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
{
SDL_WindowData * data = (SDL_WindowData *) window->driverdata;
if (info->version.major <= SDL_MAJOR_VERSION) {
info->subsystem = SDL_SYSWM_WINRT;
info->info.winrt.window = reinterpret_cast<IInspectable *>(data->coreWindow.Get());
return SDL_TRUE;
} else {
SDL_SetError("Application not compiled with SDL %d.%d",
SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
return SDL_FALSE;
}
return SDL_FALSE;
}
static ABI::Windows::System::Display::IDisplayRequest *
WINRT_CreateDisplayRequest(_THIS)
{
/* Setup a WinRT DisplayRequest object, usable for enabling/disabling screensaver requests */
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)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(IID_IDisplayRequest, (void **) &pDisplayRequest);
if (FAILED(hr)) {
goto done;
}
done:
if (pDisplayRequestRaw) {
pDisplayRequestRaw->Release();
}
if (pActivationFactory) {
pActivationFactory->Release();
}
if (hClassName) {
::WindowsDeleteString(hClassName);
}
return pDisplayRequest;
}
void
WINRT_SuspendScreenSaver(_THIS)
{
SDL_VideoData *driverdata = (SDL_VideoData *)_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();
}
}
}
#endif /* SDL_VIDEO_DRIVER_WINRT */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -0,0 +1,106 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 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: */
#include "SDL_video.h"
#include "SDL_events.h"
#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 */
typedef 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;
} SDL_VideoData;
/* 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