Merge commit 'dec0d4ec4153bf9fc2b78ae6c2df45b6ea8dde7a' as 'external/sdl/SDL'
This commit is contained in:
143
external/sdl/SDL/src/video/winrt/SDL_winrtevents.cpp
vendored
Normal file
143
external/sdl/SDL/src/video/winrt/SDL_winrtevents.cpp
vendored
Normal file
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_WINRT
|
||||
|
||||
/*
|
||||
* Windows includes:
|
||||
*/
|
||||
#include <Windows.h>
|
||||
using namespace Windows::UI::Core;
|
||||
using Windows::UI::Core::CoreCursor;
|
||||
|
||||
/*
|
||||
* SDL includes:
|
||||
*/
|
||||
#include "SDL_winrtevents_c.h"
|
||||
#include "../../core/winrt/SDL_winrtapp_common.h"
|
||||
#include "../../core/winrt/SDL_winrtapp_direct3d.h"
|
||||
#include "../../core/winrt/SDL_winrtapp_xaml.h"
|
||||
|
||||
extern "C" {
|
||||
#include "../../thread/SDL_systhread.h"
|
||||
#include "../SDL_sysvideo.h"
|
||||
#include "../../events/SDL_events_c.h"
|
||||
}
|
||||
|
||||
/* Forward declarations */
|
||||
static void WINRT_YieldXAMLThread();
|
||||
|
||||
/* Global event management */
|
||||
|
||||
void WINRT_PumpEvents(SDL_VideoDevice *_this)
|
||||
{
|
||||
if (SDL_WinRTGlobalApp) {
|
||||
SDL_WinRTGlobalApp->PumpEvents();
|
||||
} else if (WINRT_XAMLWasEnabled) {
|
||||
WINRT_YieldXAMLThread();
|
||||
}
|
||||
}
|
||||
|
||||
/* XAML Thread management */
|
||||
|
||||
enum SDL_XAMLAppThreadState
|
||||
{
|
||||
ThreadState_NotLaunched = 0,
|
||||
ThreadState_Running,
|
||||
ThreadState_Yielding
|
||||
};
|
||||
|
||||
static SDL_XAMLAppThreadState _threadState = ThreadState_NotLaunched;
|
||||
static SDL_Thread *_XAMLThread = nullptr;
|
||||
static SDL_Mutex *_mutex = nullptr;
|
||||
static SDL_Condition *_cond = nullptr;
|
||||
|
||||
static void WINRT_YieldXAMLThread()
|
||||
{
|
||||
SDL_LockMutex(_mutex);
|
||||
SDL_assert(_threadState == ThreadState_Running);
|
||||
_threadState = ThreadState_Yielding;
|
||||
SDL_UnlockMutex(_mutex);
|
||||
|
||||
SDL_SignalCondition(_cond);
|
||||
|
||||
SDL_LockMutex(_mutex);
|
||||
while (_threadState != ThreadState_Running) {
|
||||
SDL_WaitCondition(_cond, _mutex);
|
||||
}
|
||||
SDL_UnlockMutex(_mutex);
|
||||
}
|
||||
|
||||
static int WINRT_XAMLThreadMain(void *userdata)
|
||||
{
|
||||
// TODO, WinRT: pass the C-style main() a reasonably realistic
|
||||
// representation of command line arguments.
|
||||
int argc = 0;
|
||||
char **argv = NULL;
|
||||
return WINRT_SDLAppEntryPoint(argc, argv);
|
||||
}
|
||||
|
||||
void WINRT_CycleXAMLThread(void)
|
||||
{
|
||||
switch (_threadState) {
|
||||
case ThreadState_NotLaunched:
|
||||
{
|
||||
_cond = SDL_CreateCondition();
|
||||
|
||||
_mutex = SDL_CreateMutex();
|
||||
_threadState = ThreadState_Running;
|
||||
_XAMLThread = SDL_CreateThreadInternal(WINRT_XAMLThreadMain, "SDL/XAML App Thread", 0, nullptr);
|
||||
|
||||
SDL_LockMutex(_mutex);
|
||||
while (_threadState != ThreadState_Yielding) {
|
||||
SDL_WaitCondition(_cond, _mutex);
|
||||
}
|
||||
SDL_UnlockMutex(_mutex);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ThreadState_Running:
|
||||
{
|
||||
SDL_assert(false);
|
||||
break;
|
||||
}
|
||||
|
||||
case ThreadState_Yielding:
|
||||
{
|
||||
SDL_LockMutex(_mutex);
|
||||
SDL_assert(_threadState == ThreadState_Yielding);
|
||||
_threadState = ThreadState_Running;
|
||||
SDL_UnlockMutex(_mutex);
|
||||
|
||||
SDL_SignalCondition(_cond);
|
||||
|
||||
SDL_LockMutex(_mutex);
|
||||
while (_threadState != ThreadState_Yielding) {
|
||||
SDL_WaitCondition(_cond, _mutex);
|
||||
}
|
||||
SDL_UnlockMutex(_mutex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_WINRT */
|
81
external/sdl/SDL/src/video/winrt/SDL_winrtevents_c.h
vendored
Normal file
81
external/sdl/SDL/src/video/winrt/SDL_winrtevents_c.h
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
extern "C" {
|
||||
#include "../SDL_sysvideo.h"
|
||||
}
|
||||
|
||||
/*
|
||||
* Internal-use, C-style functions:
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern void WINRT_InitTouch(SDL_VideoDevice *_this);
|
||||
extern void WINRT_PumpEvents(SDL_VideoDevice *_this);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Internal-use, C++/CX functions:
|
||||
*/
|
||||
#ifdef __cplusplus_winrt
|
||||
|
||||
/* Pointers (Mice, Touch, etc.) */
|
||||
typedef enum
|
||||
{
|
||||
NormalizeZeroToOne,
|
||||
TransformToSDLWindowSize
|
||||
} WINRT_CursorNormalizationType;
|
||||
extern Windows::Foundation::Point WINRT_TransformCursorPosition(SDL_Window *window,
|
||||
Windows::Foundation::Point rawPosition,
|
||||
WINRT_CursorNormalizationType normalization);
|
||||
extern SDL_bool WINRT_GetSDLButtonForPointerPoint(Windows::UI::Input::PointerPoint ^ pt, Uint8 *button, Uint8 *pressed);
|
||||
extern void WINRT_ProcessPointerPressedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^ pointerPoint);
|
||||
extern void WINRT_ProcessPointerMovedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^ pointerPoint);
|
||||
extern void WINRT_ProcessPointerReleasedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^ pointerPoint);
|
||||
extern void WINRT_ProcessPointerEnteredEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^ pointerPoint);
|
||||
extern void WINRT_ProcessPointerExitedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^ pointerPoint);
|
||||
extern void WINRT_ProcessPointerWheelChangedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^ pointerPoint);
|
||||
extern void WINRT_ProcessMouseMovedEvent(SDL_Window *window, Windows::Devices::Input::MouseEventArgs ^ args);
|
||||
|
||||
/* Keyboard */
|
||||
extern void WINRT_ProcessKeyDownEvent(Windows::UI::Core::KeyEventArgs ^ args);
|
||||
extern void WINRT_ProcessKeyUpEvent(Windows::UI::Core::KeyEventArgs ^ args);
|
||||
extern void WINRT_ProcessCharacterReceivedEvent(Windows::UI::Core::CharacterReceivedEventArgs ^ args);
|
||||
|
||||
#if NTDDI_VERSION >= NTDDI_WIN10
|
||||
extern void WINTRT_InitialiseInputPaneEvents(SDL_VideoDevice *_this);
|
||||
extern SDL_bool WINRT_HasScreenKeyboardSupport(SDL_VideoDevice *_this);
|
||||
extern void WINRT_ShowScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
extern void WINRT_HideScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
extern SDL_bool WINRT_IsScreenKeyboardShown(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
#endif // NTDDI_VERSION >= ...
|
||||
|
||||
/* XAML Thread Management */
|
||||
extern void WINRT_CycleXAMLThread(void);
|
||||
|
||||
#endif // ifdef __cplusplus_winrt
|
185
external/sdl/SDL/src/video/winrt/SDL_winrtgamebar.cpp
vendored
Normal file
185
external/sdl/SDL/src/video/winrt/SDL_winrtgamebar.cpp
vendored
Normal file
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_WINRT
|
||||
|
||||
/* Windows includes */
|
||||
#include <roapi.h>
|
||||
#include <windows.foundation.h>
|
||||
#include <windows.system.h>
|
||||
|
||||
/* SDL includes */
|
||||
extern "C" {
|
||||
#include "../SDL_sysvideo.h"
|
||||
}
|
||||
#include "SDL_winrtvideo_cpp.h"
|
||||
|
||||
/* Game Bar events can come in off the main thread. Use the following
|
||||
WinRT CoreDispatcher to deal with them on SDL's thread.
|
||||
*/
|
||||
static Platform::WeakReference WINRT_MainThreadDispatcher;
|
||||
|
||||
/* Win10's initial SDK (the 10.0.10240.0 release) does not include references
|
||||
to Game Bar APIs, as the Game Bar was released via Win10 10.0.10586.0.
|
||||
|
||||
Declare its WinRT/COM interface here, to allow compilation with earlier
|
||||
Windows SDKs.
|
||||
*/
|
||||
MIDL_INTERFACE("1DB9A292-CC78-4173-BE45-B61E67283EA7")
|
||||
IGameBarStatics_ : public IInspectable
|
||||
{
|
||||
public:
|
||||
virtual HRESULT STDMETHODCALLTYPE add_VisibilityChanged(
|
||||
__FIEventHandler_1_IInspectable * handler,
|
||||
Windows::Foundation::EventRegistrationToken * token) = 0;
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE remove_VisibilityChanged(
|
||||
Windows::Foundation::EventRegistrationToken token) = 0;
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE add_IsInputRedirectedChanged(
|
||||
__FIEventHandler_1_IInspectable * handler,
|
||||
Windows::Foundation::EventRegistrationToken * token) = 0;
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE remove_IsInputRedirectedChanged(
|
||||
Windows::Foundation::EventRegistrationToken token) = 0;
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE get_Visible(
|
||||
boolean * value) = 0;
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE get_IsInputRedirected(
|
||||
boolean * value) = 0;
|
||||
};
|
||||
|
||||
/* Declare the game bar's COM GUID */
|
||||
static GUID IID_IGameBarStatics_ = { MAKELONG(0xA292, 0x1DB9), 0xCC78, 0x4173, { 0xBE, 0x45, 0xB6, 0x1E, 0x67, 0x28, 0x3E, 0xA7 } };
|
||||
|
||||
/* Retrieves a pointer to the game bar, or NULL if it is not available.
|
||||
If a pointer is returned, it's ->Release() method must be called
|
||||
after the caller has finished using it.
|
||||
*/
|
||||
static IGameBarStatics_ *WINRT_GetGameBar()
|
||||
{
|
||||
const wchar_t *wClassName = L"Windows.Gaming.UI.GameBar";
|
||||
HSTRING hClassName;
|
||||
IActivationFactory *pActivationFactory = NULL;
|
||||
IGameBarStatics_ *pGameBar = NULL;
|
||||
HRESULT hr;
|
||||
|
||||
hr = ::WindowsCreateString(wClassName, (UINT32)SDL_wcslen(wClassName), &hClassName);
|
||||
if (FAILED(hr)) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
hr = Windows::Foundation::GetActivationFactory(hClassName, &pActivationFactory);
|
||||
if (FAILED(hr)) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
pActivationFactory->QueryInterface(IID_IGameBarStatics_, (void **)&pGameBar);
|
||||
|
||||
done:
|
||||
if (pActivationFactory) {
|
||||
pActivationFactory->Release();
|
||||
}
|
||||
if (hClassName) {
|
||||
::WindowsDeleteString(hClassName);
|
||||
}
|
||||
return pGameBar;
|
||||
}
|
||||
|
||||
static void WINRT_HandleGameBarIsInputRedirected_MainThread()
|
||||
{
|
||||
IGameBarStatics_ *gameBar;
|
||||
boolean isInputRedirected = 0;
|
||||
if (!WINRT_MainThreadDispatcher) {
|
||||
/* The game bar event handler has been deregistered! */
|
||||
return;
|
||||
}
|
||||
gameBar = WINRT_GetGameBar();
|
||||
if (gameBar == NULL) {
|
||||
/* Shouldn't happen, but just in case... */
|
||||
return;
|
||||
}
|
||||
if (SUCCEEDED(gameBar->get_IsInputRedirected(&isInputRedirected))) {
|
||||
if (!isInputRedirected) {
|
||||
/* Input-control is now back to the SDL app. Restore the cursor,
|
||||
in case Windows does not (it does not in either Win10
|
||||
10.0.10240.0 or 10.0.10586.0, maybe later version(s) too.
|
||||
*/
|
||||
SDL_Cursor *cursor = SDL_GetCursor();
|
||||
SDL_SetCursor(cursor);
|
||||
}
|
||||
}
|
||||
gameBar->Release();
|
||||
}
|
||||
|
||||
static void WINRT_HandleGameBarIsInputRedirected_NonMainThread(Platform::Object ^ o1, Platform::Object ^ o2)
|
||||
{
|
||||
Windows::UI::Core::CoreDispatcher ^ dispatcher = WINRT_MainThreadDispatcher.Resolve<Windows::UI::Core::CoreDispatcher>();
|
||||
if (dispatcher) {
|
||||
dispatcher->RunAsync(
|
||||
Windows::UI::Core::CoreDispatcherPriority::Normal,
|
||||
ref new Windows::UI::Core::DispatchedHandler(&WINRT_HandleGameBarIsInputRedirected_MainThread));
|
||||
}
|
||||
}
|
||||
|
||||
void WINRT_InitGameBar(SDL_VideoDevice *_this)
|
||||
{
|
||||
SDL_VideoData *driverdata = _this->driverdata;
|
||||
IGameBarStatics_ *gameBar = WINRT_GetGameBar();
|
||||
if (gameBar) {
|
||||
/* GameBar.IsInputRedirected events can come in via something other than
|
||||
the main/SDL thread.
|
||||
|
||||
Get a WinRT 'CoreDispatcher' that can be used to call back into the
|
||||
SDL thread.
|
||||
*/
|
||||
WINRT_MainThreadDispatcher = Windows::UI::Core::CoreWindow::GetForCurrentThread()->Dispatcher;
|
||||
Windows::Foundation::EventHandler<Platform::Object ^> ^ handler =
|
||||
ref new Windows::Foundation::EventHandler<Platform::Object ^>(&WINRT_HandleGameBarIsInputRedirected_NonMainThread);
|
||||
__FIEventHandler_1_IInspectable *pHandler = reinterpret_cast<__FIEventHandler_1_IInspectable *>(handler);
|
||||
gameBar->add_IsInputRedirectedChanged(pHandler, &driverdata->gameBarIsInputRedirectedToken);
|
||||
gameBar->Release();
|
||||
}
|
||||
}
|
||||
|
||||
void WINRT_QuitGameBar(SDL_VideoDevice *_this)
|
||||
{
|
||||
SDL_VideoData *driverdata;
|
||||
IGameBarStatics_ *gameBar;
|
||||
if (_this == NULL || _this->driverdata == NULL) {
|
||||
return;
|
||||
}
|
||||
gameBar = WINRT_GetGameBar();
|
||||
if (gameBar == NULL) {
|
||||
return;
|
||||
}
|
||||
driverdata = _this->driverdata;
|
||||
if (driverdata->gameBarIsInputRedirectedToken.Value) {
|
||||
gameBar->remove_IsInputRedirectedChanged(driverdata->gameBarIsInputRedirectedToken);
|
||||
driverdata->gameBarIsInputRedirectedToken.Value = 0;
|
||||
}
|
||||
WINRT_MainThreadDispatcher = nullptr;
|
||||
gameBar->Release();
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_WINRT */
|
33
external/sdl/SDL/src/video/winrt/SDL_winrtgamebar_cpp.h
vendored
Normal file
33
external/sdl/SDL/src/video/winrt/SDL_winrtgamebar_cpp.h
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifndef SDL_winrtgamebar_h_
|
||||
#define SDL_winrtgamebar_h_
|
||||
|
||||
#ifdef __cplusplus
|
||||
/* These are exported as C++ functions, rather than C, to fix a compilation
|
||||
bug with MSVC 2013, for Windows 8.x builds. */
|
||||
extern void WINRT_InitGameBar(SDL_VideoDevice *_this);
|
||||
extern void WINRT_QuitGameBar(SDL_VideoDevice *_this);
|
||||
#endif
|
||||
|
||||
#endif /* SDL_winrtgamebar_h_ */
|
478
external/sdl/SDL/src/video/winrt/SDL_winrtkeyboard.cpp
vendored
Normal file
478
external/sdl/SDL/src/video/winrt/SDL_winrtkeyboard.cpp
vendored
Normal file
@@ -0,0 +1,478 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_WINRT
|
||||
|
||||
/* Windows-specific includes */
|
||||
#include <Windows.h>
|
||||
#include <agile.h>
|
||||
|
||||
/* SDL-specific includes */
|
||||
#include "SDL_winrtevents_c.h"
|
||||
|
||||
extern "C" {
|
||||
#include "../../events/scancodes_windows.h"
|
||||
#include "../../events/SDL_keyboard_c.h"
|
||||
}
|
||||
|
||||
static SDL_Scancode WinRT_Official_Keycodes[] = {
|
||||
SDL_SCANCODE_UNKNOWN, /* VirtualKey.None -- 0 */
|
||||
SDL_SCANCODE_UNKNOWN, /* VirtualKey.LeftButton -- 1 */
|
||||
SDL_SCANCODE_UNKNOWN, /* VirtualKey.RightButton -- 2 */
|
||||
SDL_SCANCODE_CANCEL, /* VirtualKey.Cancel -- 3 */
|
||||
SDL_SCANCODE_UNKNOWN, /* VirtualKey.MiddleButton -- 4 */
|
||||
SDL_SCANCODE_UNKNOWN, /* VirtualKey.XButton1 -- 5 */
|
||||
SDL_SCANCODE_UNKNOWN, /* VirtualKey.XButton2 -- 6 */
|
||||
SDL_SCANCODE_UNKNOWN, /* -- 7 */
|
||||
SDL_SCANCODE_BACKSPACE, /* VirtualKey.Back -- 8 */
|
||||
SDL_SCANCODE_TAB, /* VirtualKey.Tab -- 9 */
|
||||
SDL_SCANCODE_UNKNOWN, /* -- 10 */
|
||||
SDL_SCANCODE_UNKNOWN, /* -- 11 */
|
||||
SDL_SCANCODE_CLEAR, /* VirtualKey.Clear -- 12 */
|
||||
SDL_SCANCODE_RETURN, /* VirtualKey.Enter -- 13 */
|
||||
SDL_SCANCODE_UNKNOWN, /* -- 14 */
|
||||
SDL_SCANCODE_UNKNOWN, /* -- 15 */
|
||||
SDL_SCANCODE_LSHIFT, /* VirtualKey.Shift -- 16 */
|
||||
SDL_SCANCODE_LCTRL, /* VirtualKey.Control -- 17 */
|
||||
SDL_SCANCODE_MENU, /* VirtualKey.Menu -- 18 */
|
||||
SDL_SCANCODE_PAUSE, /* VirtualKey.Pause -- 19 */
|
||||
SDL_SCANCODE_CAPSLOCK, /* VirtualKey.CapitalLock -- 20 */
|
||||
SDL_SCANCODE_UNKNOWN, /* VirtualKey.Kana or VirtualKey.Hangul -- 21 */
|
||||
SDL_SCANCODE_UNKNOWN, /* -- 22 */
|
||||
SDL_SCANCODE_UNKNOWN, /* VirtualKey.Junja -- 23 */
|
||||
SDL_SCANCODE_UNKNOWN, /* VirtualKey.Final -- 24 */
|
||||
SDL_SCANCODE_UNKNOWN, /* VirtualKey.Hanja or VirtualKey.Kanji -- 25 */
|
||||
SDL_SCANCODE_UNKNOWN, /* -- 26 */
|
||||
SDL_SCANCODE_ESCAPE, /* VirtualKey.Escape -- 27 */
|
||||
SDL_SCANCODE_UNKNOWN, /* VirtualKey.Convert -- 28 */
|
||||
SDL_SCANCODE_UNKNOWN, /* VirtualKey.NonConvert -- 29 */
|
||||
SDL_SCANCODE_UNKNOWN, /* VirtualKey.Accept -- 30 */
|
||||
SDL_SCANCODE_UNKNOWN, /* VirtualKey.ModeChange -- 31 (maybe SDL_SCANCODE_MODE ?) */
|
||||
SDL_SCANCODE_SPACE, /* VirtualKey.Space -- 32 */
|
||||
SDL_SCANCODE_PAGEUP, /* VirtualKey.PageUp -- 33 */
|
||||
SDL_SCANCODE_PAGEDOWN, /* VirtualKey.PageDown -- 34 */
|
||||
SDL_SCANCODE_END, /* VirtualKey.End -- 35 */
|
||||
SDL_SCANCODE_HOME, /* VirtualKey.Home -- 36 */
|
||||
SDL_SCANCODE_LEFT, /* VirtualKey.Left -- 37 */
|
||||
SDL_SCANCODE_UP, /* VirtualKey.Up -- 38 */
|
||||
SDL_SCANCODE_RIGHT, /* VirtualKey.Right -- 39 */
|
||||
SDL_SCANCODE_DOWN, /* VirtualKey.Down -- 40 */
|
||||
SDL_SCANCODE_SELECT, /* VirtualKey.Select -- 41 */
|
||||
SDL_SCANCODE_UNKNOWN, /* VirtualKey.Print -- 42 (maybe SDL_SCANCODE_PRINTSCREEN ?) */
|
||||
SDL_SCANCODE_EXECUTE, /* VirtualKey.Execute -- 43 */
|
||||
SDL_SCANCODE_UNKNOWN, /* VirtualKey.Snapshot -- 44 */
|
||||
SDL_SCANCODE_INSERT, /* VirtualKey.Insert -- 45 */
|
||||
SDL_SCANCODE_DELETE, /* VirtualKey.Delete -- 46 */
|
||||
SDL_SCANCODE_HELP, /* VirtualKey.Help -- 47 */
|
||||
SDL_SCANCODE_0, /* VirtualKey.Number0 -- 48 */
|
||||
SDL_SCANCODE_1, /* VirtualKey.Number1 -- 49 */
|
||||
SDL_SCANCODE_2, /* VirtualKey.Number2 -- 50 */
|
||||
SDL_SCANCODE_3, /* VirtualKey.Number3 -- 51 */
|
||||
SDL_SCANCODE_4, /* VirtualKey.Number4 -- 52 */
|
||||
SDL_SCANCODE_5, /* VirtualKey.Number5 -- 53 */
|
||||
SDL_SCANCODE_6, /* VirtualKey.Number6 -- 54 */
|
||||
SDL_SCANCODE_7, /* VirtualKey.Number7 -- 55 */
|
||||
SDL_SCANCODE_8, /* VirtualKey.Number8 -- 56 */
|
||||
SDL_SCANCODE_9, /* VirtualKey.Number9 -- 57 */
|
||||
SDL_SCANCODE_UNKNOWN, /* -- 58 */
|
||||
SDL_SCANCODE_UNKNOWN, /* -- 59 */
|
||||
SDL_SCANCODE_UNKNOWN, /* -- 60 */
|
||||
SDL_SCANCODE_UNKNOWN, /* -- 61 */
|
||||
SDL_SCANCODE_UNKNOWN, /* -- 62 */
|
||||
SDL_SCANCODE_UNKNOWN, /* -- 63 */
|
||||
SDL_SCANCODE_UNKNOWN, /* -- 64 */
|
||||
SDL_SCANCODE_A, /* VirtualKey.A -- 65 */
|
||||
SDL_SCANCODE_B, /* VirtualKey.B -- 66 */
|
||||
SDL_SCANCODE_C, /* VirtualKey.C -- 67 */
|
||||
SDL_SCANCODE_D, /* VirtualKey.D -- 68 */
|
||||
SDL_SCANCODE_E, /* VirtualKey.E -- 69 */
|
||||
SDL_SCANCODE_F, /* VirtualKey.F -- 70 */
|
||||
SDL_SCANCODE_G, /* VirtualKey.G -- 71 */
|
||||
SDL_SCANCODE_H, /* VirtualKey.H -- 72 */
|
||||
SDL_SCANCODE_I, /* VirtualKey.I -- 73 */
|
||||
SDL_SCANCODE_J, /* VirtualKey.J -- 74 */
|
||||
SDL_SCANCODE_K, /* VirtualKey.K -- 75 */
|
||||
SDL_SCANCODE_L, /* VirtualKey.L -- 76 */
|
||||
SDL_SCANCODE_M, /* VirtualKey.M -- 77 */
|
||||
SDL_SCANCODE_N, /* VirtualKey.N -- 78 */
|
||||
SDL_SCANCODE_O, /* VirtualKey.O -- 79 */
|
||||
SDL_SCANCODE_P, /* VirtualKey.P -- 80 */
|
||||
SDL_SCANCODE_Q, /* VirtualKey.Q -- 81 */
|
||||
SDL_SCANCODE_R, /* VirtualKey.R -- 82 */
|
||||
SDL_SCANCODE_S, /* VirtualKey.S -- 83 */
|
||||
SDL_SCANCODE_T, /* VirtualKey.T -- 84 */
|
||||
SDL_SCANCODE_U, /* VirtualKey.U -- 85 */
|
||||
SDL_SCANCODE_V, /* VirtualKey.V -- 86 */
|
||||
SDL_SCANCODE_W, /* VirtualKey.W -- 87 */
|
||||
SDL_SCANCODE_X, /* VirtualKey.X -- 88 */
|
||||
SDL_SCANCODE_Y, /* VirtualKey.Y -- 89 */
|
||||
SDL_SCANCODE_Z, /* VirtualKey.Z -- 90 */
|
||||
SDL_SCANCODE_UNKNOWN, /* VirtualKey.LeftWindows -- 91 (maybe SDL_SCANCODE_APPLICATION or SDL_SCANCODE_LGUI ?) */
|
||||
SDL_SCANCODE_UNKNOWN, /* VirtualKey.RightWindows -- 92 (maybe SDL_SCANCODE_APPLICATION or SDL_SCANCODE_RGUI ?) */
|
||||
SDL_SCANCODE_APPLICATION, /* VirtualKey.Application -- 93 */
|
||||
SDL_SCANCODE_UNKNOWN, /* -- 94 */
|
||||
SDL_SCANCODE_SLEEP, /* VirtualKey.Sleep -- 95 */
|
||||
SDL_SCANCODE_KP_0, /* VirtualKey.NumberPad0 -- 96 */
|
||||
SDL_SCANCODE_KP_1, /* VirtualKey.NumberPad1 -- 97 */
|
||||
SDL_SCANCODE_KP_2, /* VirtualKey.NumberPad2 -- 98 */
|
||||
SDL_SCANCODE_KP_3, /* VirtualKey.NumberPad3 -- 99 */
|
||||
SDL_SCANCODE_KP_4, /* VirtualKey.NumberPad4 -- 100 */
|
||||
SDL_SCANCODE_KP_5, /* VirtualKey.NumberPad5 -- 101 */
|
||||
SDL_SCANCODE_KP_6, /* VirtualKey.NumberPad6 -- 102 */
|
||||
SDL_SCANCODE_KP_7, /* VirtualKey.NumberPad7 -- 103 */
|
||||
SDL_SCANCODE_KP_8, /* VirtualKey.NumberPad8 -- 104 */
|
||||
SDL_SCANCODE_KP_9, /* VirtualKey.NumberPad9 -- 105 */
|
||||
SDL_SCANCODE_KP_MULTIPLY, /* VirtualKey.Multiply -- 106 */
|
||||
SDL_SCANCODE_KP_PLUS, /* VirtualKey.Add -- 107 */
|
||||
SDL_SCANCODE_UNKNOWN, /* VirtualKey.Separator -- 108 */
|
||||
SDL_SCANCODE_KP_MINUS, /* VirtualKey.Subtract -- 109 */
|
||||
SDL_SCANCODE_UNKNOWN, /* VirtualKey.Decimal -- 110 (maybe SDL_SCANCODE_DECIMALSEPARATOR, SDL_SCANCODE_KP_DECIMAL, or SDL_SCANCODE_KP_PERIOD ?) */
|
||||
SDL_SCANCODE_KP_DIVIDE, /* VirtualKey.Divide -- 111 */
|
||||
SDL_SCANCODE_F1, /* VirtualKey.F1 -- 112 */
|
||||
SDL_SCANCODE_F2, /* VirtualKey.F2 -- 113 */
|
||||
SDL_SCANCODE_F3, /* VirtualKey.F3 -- 114 */
|
||||
SDL_SCANCODE_F4, /* VirtualKey.F4 -- 115 */
|
||||
SDL_SCANCODE_F5, /* VirtualKey.F5 -- 116 */
|
||||
SDL_SCANCODE_F6, /* VirtualKey.F6 -- 117 */
|
||||
SDL_SCANCODE_F7, /* VirtualKey.F7 -- 118 */
|
||||
SDL_SCANCODE_F8, /* VirtualKey.F8 -- 119 */
|
||||
SDL_SCANCODE_F9, /* VirtualKey.F9 -- 120 */
|
||||
SDL_SCANCODE_F10, /* VirtualKey.F10 -- 121 */
|
||||
SDL_SCANCODE_F11, /* VirtualKey.F11 -- 122 */
|
||||
SDL_SCANCODE_F12, /* VirtualKey.F12 -- 123 */
|
||||
SDL_SCANCODE_F13, /* VirtualKey.F13 -- 124 */
|
||||
SDL_SCANCODE_F14, /* VirtualKey.F14 -- 125 */
|
||||
SDL_SCANCODE_F15, /* VirtualKey.F15 -- 126 */
|
||||
SDL_SCANCODE_F16, /* VirtualKey.F16 -- 127 */
|
||||
SDL_SCANCODE_F17, /* VirtualKey.F17 -- 128 */
|
||||
SDL_SCANCODE_F18, /* VirtualKey.F18 -- 129 */
|
||||
SDL_SCANCODE_F19, /* VirtualKey.F19 -- 130 */
|
||||
SDL_SCANCODE_F20, /* VirtualKey.F20 -- 131 */
|
||||
SDL_SCANCODE_F21, /* VirtualKey.F21 -- 132 */
|
||||
SDL_SCANCODE_F22, /* VirtualKey.F22 -- 133 */
|
||||
SDL_SCANCODE_F23, /* VirtualKey.F23 -- 134 */
|
||||
SDL_SCANCODE_F24, /* VirtualKey.F24 -- 135 */
|
||||
SDL_SCANCODE_UNKNOWN, /* -- 136 */
|
||||
SDL_SCANCODE_UNKNOWN, /* -- 137 */
|
||||
SDL_SCANCODE_UNKNOWN, /* -- 138 */
|
||||
SDL_SCANCODE_UNKNOWN, /* -- 139 */
|
||||
SDL_SCANCODE_UNKNOWN, /* -- 140 */
|
||||
SDL_SCANCODE_UNKNOWN, /* -- 141 */
|
||||
SDL_SCANCODE_UNKNOWN, /* -- 142 */
|
||||
SDL_SCANCODE_UNKNOWN, /* -- 143 */
|
||||
SDL_SCANCODE_NUMLOCKCLEAR, /* VirtualKey.NumberKeyLock -- 144 */
|
||||
SDL_SCANCODE_SCROLLLOCK, /* VirtualKey.Scroll -- 145 */
|
||||
SDL_SCANCODE_UNKNOWN, /* -- 146 */
|
||||
SDL_SCANCODE_UNKNOWN, /* -- 147 */
|
||||
SDL_SCANCODE_UNKNOWN, /* -- 148 */
|
||||
SDL_SCANCODE_UNKNOWN, /* -- 149 */
|
||||
SDL_SCANCODE_UNKNOWN, /* -- 150 */
|
||||
SDL_SCANCODE_UNKNOWN, /* -- 151 */
|
||||
SDL_SCANCODE_UNKNOWN, /* -- 152 */
|
||||
SDL_SCANCODE_UNKNOWN, /* -- 153 */
|
||||
SDL_SCANCODE_UNKNOWN, /* -- 154 */
|
||||
SDL_SCANCODE_UNKNOWN, /* -- 155 */
|
||||
SDL_SCANCODE_UNKNOWN, /* -- 156 */
|
||||
SDL_SCANCODE_UNKNOWN, /* -- 157 */
|
||||
SDL_SCANCODE_UNKNOWN, /* -- 158 */
|
||||
SDL_SCANCODE_UNKNOWN, /* -- 159 */
|
||||
SDL_SCANCODE_LSHIFT, /* VirtualKey.LeftShift -- 160 */
|
||||
SDL_SCANCODE_RSHIFT, /* VirtualKey.RightShift -- 161 */
|
||||
SDL_SCANCODE_LCTRL, /* VirtualKey.LeftControl -- 162 */
|
||||
SDL_SCANCODE_RCTRL, /* VirtualKey.RightControl -- 163 */
|
||||
SDL_SCANCODE_MENU, /* VirtualKey.LeftMenu -- 164 */
|
||||
SDL_SCANCODE_MENU, /* VirtualKey.RightMenu -- 165 */
|
||||
SDL_SCANCODE_AC_BACK, /* VirtualKey.GoBack -- 166 : The go back key. */
|
||||
SDL_SCANCODE_AC_FORWARD, /* VirtualKey.GoForward -- 167 : The go forward key. */
|
||||
SDL_SCANCODE_AC_REFRESH, /* VirtualKey.Refresh -- 168 : The refresh key. */
|
||||
SDL_SCANCODE_AC_STOP, /* VirtualKey.Stop -- 169 : The stop key. */
|
||||
SDL_SCANCODE_AC_SEARCH, /* VirtualKey.Search -- 170 : The search key. */
|
||||
SDL_SCANCODE_AC_BOOKMARKS, /* VirtualKey.Favorites -- 171 : The favorites key. */
|
||||
SDL_SCANCODE_AC_HOME /* VirtualKey.GoHome -- 172 : The go home key. */
|
||||
};
|
||||
|
||||
/* Attempt to translate a keycode that isn't listed in WinRT's VirtualKey enum.
|
||||
*/
|
||||
static SDL_Scancode WINRT_TranslateUnofficialKeycode(int keycode)
|
||||
{
|
||||
switch (keycode) {
|
||||
case 173:
|
||||
return SDL_SCANCODE_MUTE; /* VK_VOLUME_MUTE */
|
||||
case 174:
|
||||
return SDL_SCANCODE_VOLUMEDOWN; /* VK_VOLUME_DOWN */
|
||||
case 175:
|
||||
return SDL_SCANCODE_VOLUMEUP; /* VK_VOLUME_UP */
|
||||
case 176:
|
||||
return SDL_SCANCODE_AUDIONEXT; /* VK_MEDIA_NEXT_TRACK */
|
||||
case 177:
|
||||
return SDL_SCANCODE_AUDIOPREV; /* VK_MEDIA_PREV_TRACK */
|
||||
// case 178: return ; /* VK_MEDIA_STOP */
|
||||
case 179:
|
||||
return SDL_SCANCODE_AUDIOPLAY; /* VK_MEDIA_PLAY_PAUSE */
|
||||
case 180:
|
||||
return SDL_SCANCODE_MAIL; /* VK_LAUNCH_MAIL */
|
||||
case 181:
|
||||
return SDL_SCANCODE_MEDIASELECT; /* VK_LAUNCH_MEDIA_SELECT */
|
||||
// case 182: return ; /* VK_LAUNCH_APP1 */
|
||||
case 183:
|
||||
return SDL_SCANCODE_CALCULATOR; /* VK_LAUNCH_APP2 */
|
||||
// case 184: return ; /* ... reserved ... */
|
||||
// case 185: return ; /* ... reserved ... */
|
||||
case 186:
|
||||
return SDL_SCANCODE_SEMICOLON; /* VK_OEM_1, ';:' key on US standard keyboards */
|
||||
case 187:
|
||||
return SDL_SCANCODE_EQUALS; /* VK_OEM_PLUS */
|
||||
case 188:
|
||||
return SDL_SCANCODE_COMMA; /* VK_OEM_COMMA */
|
||||
case 189:
|
||||
return SDL_SCANCODE_MINUS; /* VK_OEM_MINUS */
|
||||
case 190:
|
||||
return SDL_SCANCODE_PERIOD; /* VK_OEM_PERIOD */
|
||||
case 191:
|
||||
return SDL_SCANCODE_SLASH; /* VK_OEM_2, '/?' key on US standard keyboards */
|
||||
case 192:
|
||||
return SDL_SCANCODE_GRAVE; /* VK_OEM_3, '`~' key on US standard keyboards */
|
||||
// ?
|
||||
// ... reserved or unassigned ...
|
||||
// ?
|
||||
case 219:
|
||||
return SDL_SCANCODE_LEFTBRACKET; /* VK_OEM_4, '[{' key on US standard keyboards */
|
||||
case 220:
|
||||
return SDL_SCANCODE_BACKSLASH; /* VK_OEM_5, '\|' key on US standard keyboards */
|
||||
case 221:
|
||||
return SDL_SCANCODE_RIGHTBRACKET; /* VK_OEM_6, ']}' key on US standard keyboards */
|
||||
case 222:
|
||||
return SDL_SCANCODE_APOSTROPHE; /* VK_OEM_7, 'single/double quote' on US standard keyboards */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return SDL_SCANCODE_UNKNOWN;
|
||||
}
|
||||
|
||||
static SDL_Scancode WINRT_TranslateKeycode(int keycode, unsigned int nativeScancode)
|
||||
{
|
||||
// TODO, WinRT: try filling out the WinRT keycode table as much as possible, using the Win32 table for interpretation hints
|
||||
|
||||
SDL_Scancode scancode = SDL_SCANCODE_UNKNOWN;
|
||||
|
||||
/* HACK ALERT: At least one VirtualKey constant (Shift) with a left/right
|
||||
* designation might not get reported with its correct handedness, however
|
||||
* its hardware scan code can fill in the gaps. If this is detected,
|
||||
* use the hardware scan code to try telling if the left, or the right
|
||||
* side's key was used.
|
||||
*
|
||||
* If Microsoft ever allows MapVirtualKey or MapVirtualKeyEx to be used
|
||||
* in WinRT apps, or something similar to these (it doesn't appear to be,
|
||||
* at least not for Windows [Phone] 8/8.1, as of Oct 24, 2014), then this
|
||||
* hack might become deprecated, or obsolete.
|
||||
*/
|
||||
if (nativeScancode < SDL_arraysize(windows_scancode_table)) {
|
||||
switch (keycode) {
|
||||
case 16: // VirtualKey.Shift
|
||||
switch (windows_scancode_table[nativeScancode]) {
|
||||
case SDL_SCANCODE_LSHIFT:
|
||||
case SDL_SCANCODE_RSHIFT:
|
||||
return windows_scancode_table[nativeScancode];
|
||||
}
|
||||
break;
|
||||
|
||||
// Add others, as necessary.
|
||||
//
|
||||
// Unfortunately, this hack doesn't seem to work in determining
|
||||
// handedness with Control keys.
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Try to get a documented, WinRT, 'VirtualKey' next (as documented at
|
||||
http://msdn.microsoft.com/en-us/library/windows/apps/windows.system.virtualkey.aspx ).
|
||||
If that fails, fall back to a Win32 virtual key.
|
||||
If that fails, attempt to fall back to a scancode-derived key.
|
||||
*/
|
||||
if (keycode < SDL_arraysize(WinRT_Official_Keycodes)) {
|
||||
scancode = WinRT_Official_Keycodes[keycode];
|
||||
}
|
||||
if (scancode == SDL_SCANCODE_UNKNOWN) {
|
||||
scancode = WINRT_TranslateUnofficialKeycode(keycode);
|
||||
}
|
||||
if (scancode == SDL_SCANCODE_UNKNOWN) {
|
||||
if (nativeScancode < SDL_arraysize(windows_scancode_table)) {
|
||||
scancode = windows_scancode_table[nativeScancode];
|
||||
}
|
||||
}
|
||||
/*
|
||||
if (scancode == SDL_SCANCODE_UNKNOWN) {
|
||||
SDL_Log("WinRT TranslateKeycode, unknown keycode=%d\n", (int)keycode);
|
||||
}
|
||||
*/
|
||||
return scancode;
|
||||
}
|
||||
|
||||
void WINRT_ProcessKeyDownEvent(Windows::UI::Core::KeyEventArgs ^ args)
|
||||
{
|
||||
SDL_Scancode sdlScancode = WINRT_TranslateKeycode((int)args->VirtualKey, args->KeyStatus.ScanCode);
|
||||
#if 0
|
||||
SDL_Keycode keycode = SDL_GetKeyFromScancode(sdlScancode);
|
||||
SDL_Log("key down, handled=%s, ext?=%s, released?=%s, menu key down?=%s, "
|
||||
"repeat count=%d, native scan code=0x%x, was down?=%s, vkey=%d, "
|
||||
"sdl scan code=%d (%s), sdl key code=%d (%s)\n",
|
||||
(args->Handled ? "1" : "0"),
|
||||
(args->KeyStatus.IsExtendedKey ? "1" : "0"),
|
||||
(args->KeyStatus.IsKeyReleased ? "1" : "0"),
|
||||
(args->KeyStatus.IsMenuKeyDown ? "1" : "0"),
|
||||
args->KeyStatus.RepeatCount,
|
||||
args->KeyStatus.ScanCode,
|
||||
(args->KeyStatus.WasKeyDown ? "1" : "0"),
|
||||
args->VirtualKey,
|
||||
sdlScancode,
|
||||
SDL_GetScancodeName(sdlScancode),
|
||||
keycode,
|
||||
SDL_GetKeyName(keycode));
|
||||
//args->Handled = true;
|
||||
#endif
|
||||
SDL_SendKeyboardKey(0, SDL_PRESSED, sdlScancode);
|
||||
}
|
||||
|
||||
void WINRT_ProcessKeyUpEvent(Windows::UI::Core::KeyEventArgs ^ args)
|
||||
{
|
||||
SDL_Scancode sdlScancode = WINRT_TranslateKeycode((int)args->VirtualKey, args->KeyStatus.ScanCode);
|
||||
#if 0
|
||||
SDL_Keycode keycode = SDL_GetKeyFromScancode(sdlScancode);
|
||||
SDL_Log("key up, handled=%s, ext?=%s, released?=%s, menu key down?=%s, "
|
||||
"repeat count=%d, native scan code=0x%x, was down?=%s, vkey=%d, "
|
||||
"sdl scan code=%d (%s), sdl key code=%d (%s)\n",
|
||||
(args->Handled ? "1" : "0"),
|
||||
(args->KeyStatus.IsExtendedKey ? "1" : "0"),
|
||||
(args->KeyStatus.IsKeyReleased ? "1" : "0"),
|
||||
(args->KeyStatus.IsMenuKeyDown ? "1" : "0"),
|
||||
args->KeyStatus.RepeatCount,
|
||||
args->KeyStatus.ScanCode,
|
||||
(args->KeyStatus.WasKeyDown ? "1" : "0"),
|
||||
args->VirtualKey,
|
||||
sdlScancode,
|
||||
SDL_GetScancodeName(sdlScancode),
|
||||
keycode,
|
||||
SDL_GetKeyName(keycode));
|
||||
//args->Handled = true;
|
||||
#endif
|
||||
SDL_SendKeyboardKey(0, SDL_RELEASED, sdlScancode);
|
||||
}
|
||||
|
||||
void WINRT_ProcessCharacterReceivedEvent(Windows::UI::Core::CharacterReceivedEventArgs ^ args)
|
||||
{
|
||||
wchar_t src_ucs2[2];
|
||||
char dest_utf8[16];
|
||||
int result;
|
||||
|
||||
/* Setup src */
|
||||
src_ucs2[0] = args->KeyCode;
|
||||
src_ucs2[1] = L'\0';
|
||||
|
||||
/* Convert the text, then send an SDL_EVENT_TEXT_INPUT event. */
|
||||
result = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR)&src_ucs2, -1, (LPSTR)dest_utf8, sizeof(dest_utf8), NULL, NULL);
|
||||
if (result > 0) {
|
||||
SDL_SendKeyboardText(dest_utf8);
|
||||
}
|
||||
}
|
||||
|
||||
#if NTDDI_VERSION >= NTDDI_WIN10
|
||||
|
||||
static bool WINRT_InputPaneVisible = false;
|
||||
|
||||
void WINTRT_OnInputPaneShowing(Windows::UI::ViewManagement::InputPane ^ sender, Windows::UI::ViewManagement::InputPaneVisibilityEventArgs ^ args)
|
||||
{
|
||||
WINRT_InputPaneVisible = true;
|
||||
}
|
||||
|
||||
void WINTRT_OnInputPaneHiding(Windows::UI::ViewManagement::InputPane ^ sender, Windows::UI::ViewManagement::InputPaneVisibilityEventArgs ^ args)
|
||||
{
|
||||
WINRT_InputPaneVisible = false;
|
||||
}
|
||||
|
||||
void WINTRT_InitialiseInputPaneEvents(SDL_VideoDevice *_this)
|
||||
{
|
||||
using namespace Windows::UI::ViewManagement;
|
||||
InputPane ^ inputPane = InputPane::GetForCurrentView();
|
||||
if (inputPane) {
|
||||
inputPane->Showing += ref new Windows::Foundation::TypedEventHandler<Windows::UI::ViewManagement::InputPane ^,
|
||||
Windows::UI::ViewManagement::InputPaneVisibilityEventArgs ^>(&WINTRT_OnInputPaneShowing);
|
||||
inputPane->Hiding += ref new Windows::Foundation::TypedEventHandler<Windows::UI::ViewManagement::InputPane ^,
|
||||
Windows::UI::ViewManagement::InputPaneVisibilityEventArgs ^>(&WINTRT_OnInputPaneHiding);
|
||||
}
|
||||
}
|
||||
|
||||
SDL_bool WINRT_HasScreenKeyboardSupport(SDL_VideoDevice *_this)
|
||||
{
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
void WINRT_ShowScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
{
|
||||
using namespace Windows::UI::ViewManagement;
|
||||
InputPane ^ inputPane = InputPane::GetForCurrentView();
|
||||
if (inputPane) {
|
||||
inputPane->TryShow();
|
||||
}
|
||||
}
|
||||
|
||||
void WINRT_HideScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
{
|
||||
using namespace Windows::UI::ViewManagement;
|
||||
InputPane ^ inputPane = InputPane::GetForCurrentView();
|
||||
if (inputPane) {
|
||||
inputPane->TryHide();
|
||||
}
|
||||
}
|
||||
|
||||
SDL_bool WINRT_IsScreenKeyboardShown(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
{
|
||||
using namespace Windows::UI::ViewManagement;
|
||||
InputPane ^ inputPane = InputPane::GetForCurrentView();
|
||||
if (inputPane) {
|
||||
switch (SDL_WinRTGetDeviceFamily()) {
|
||||
case SDL_WINRT_DEVICEFAMILY_XBOX:
|
||||
// Documentation recommends using inputPane->Visible
|
||||
// https://learn.microsoft.com/en-us/uwp/api/windows.ui.viewmanagement.inputpane.visible?view=winrt-22621
|
||||
// This does not seem to work on latest UWP/Xbox.
|
||||
// Workaround: Listen to Showing/Hiding events
|
||||
if (WINRT_InputPaneVisible) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// OccludedRect is recommend on universal apps per docs
|
||||
// https://learn.microsoft.com/en-us/uwp/api/windows.ui.viewmanagement.inputpane.visible?view=winrt-22621
|
||||
Windows::Foundation::Rect rect = inputPane->OccludedRect;
|
||||
if (rect.Width > 0 && rect.Height > 0) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
#endif // NTDDI_VERSION >= ...
|
||||
|
||||
#endif // SDL_VIDEO_DRIVER_WINRT
|
111
external/sdl/SDL/src/video/winrt/SDL_winrtmessagebox.cpp
vendored
Normal file
111
external/sdl/SDL/src/video/winrt/SDL_winrtmessagebox.cpp
vendored
Normal file
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_WINRT
|
||||
|
||||
extern "C" {
|
||||
#include "../../core/windows/SDL_windows.h"
|
||||
}
|
||||
|
||||
#include "SDL_winrtevents_c.h"
|
||||
|
||||
#include <windows.ui.popups.h>
|
||||
using namespace Platform;
|
||||
using namespace Windows::Foundation;
|
||||
using namespace Windows::UI::Popups;
|
||||
|
||||
static String ^ WINRT_UTF8ToPlatformString(const char *str) {
|
||||
wchar_t *wstr = WIN_UTF8ToString(str);
|
||||
String ^ rtstr = ref new String(wstr);
|
||||
SDL_free(wstr);
|
||||
return rtstr;
|
||||
}
|
||||
|
||||
extern "C" int WINRT_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
|
||||
{
|
||||
#if SDL_WINAPI_FAMILY_PHONE && NTDDI_VERSION == NTDDI_WIN8
|
||||
/* Sadly, Windows Phone 8 doesn't include the MessageDialog class that
|
||||
* Windows 8.x/RT does, even though MSDN's reference documentation for
|
||||
* Windows Phone 8 mentions it.
|
||||
*
|
||||
* The .NET runtime on Windows Phone 8 does, however, include a
|
||||
* MessageBox class. Perhaps this could be called, somehow?
|
||||
*/
|
||||
return SDL_SetError("SDL_messagebox support is not available for Windows Phone 8.0");
|
||||
#else
|
||||
SDL_VideoDevice *_this = SDL_GetVideoDevice();
|
||||
|
||||
#if SDL_WINAPI_FAMILY_PHONE
|
||||
const int maxbuttons = 2;
|
||||
const char *platform = "Windows Phone 8.1+";
|
||||
#else
|
||||
const int maxbuttons = 3;
|
||||
const char *platform = "Windows 8.x";
|
||||
#endif
|
||||
|
||||
if (messageboxdata->numbuttons > maxbuttons) {
|
||||
return SDL_SetError("WinRT's MessageDialog only supports %d buttons, at most, on %s. %d were requested.",
|
||||
maxbuttons, platform, messageboxdata->numbuttons);
|
||||
}
|
||||
|
||||
/* Build a MessageDialog object and its buttons */
|
||||
MessageDialog ^ dialog = ref new MessageDialog(WINRT_UTF8ToPlatformString(messageboxdata->message));
|
||||
dialog->Title = WINRT_UTF8ToPlatformString(messageboxdata->title);
|
||||
for (int i = 0; i < messageboxdata->numbuttons; ++i) {
|
||||
const SDL_MessageBoxButtonData *sdlButton;
|
||||
if (messageboxdata->flags & SDL_MESSAGEBOX_BUTTONS_RIGHT_TO_LEFT) {
|
||||
sdlButton = &messageboxdata->buttons[messageboxdata->numbuttons - 1 - i];
|
||||
} else {
|
||||
sdlButton = &messageboxdata->buttons[i];
|
||||
}
|
||||
UICommand ^ button = ref new UICommand(WINRT_UTF8ToPlatformString(sdlButton->text));
|
||||
button->Id = IntPtr((int)((size_t)(sdlButton - messageboxdata->buttons)));
|
||||
dialog->Commands->Append(button);
|
||||
if (sdlButton->flags & SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT) {
|
||||
dialog->CancelCommandIndex = i;
|
||||
}
|
||||
if (sdlButton->flags & SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT) {
|
||||
dialog->DefaultCommandIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
/* Display the MessageDialog, then wait for it to be closed */
|
||||
/* TODO, WinRT: Find a way to redraw MessageDialog instances if a GPU device-reset occurs during the following event-loop */
|
||||
auto operation = dialog->ShowAsync();
|
||||
while (operation->Status == Windows::Foundation::AsyncStatus::Started) {
|
||||
WINRT_PumpEvents(_this);
|
||||
}
|
||||
|
||||
/* Retrieve results from the MessageDialog and process them accordingly */
|
||||
if (operation->Status != Windows::Foundation::AsyncStatus::Completed) {
|
||||
return SDL_SetError("An unknown error occurred in displaying the WinRT MessageDialog");
|
||||
}
|
||||
if (buttonid) {
|
||||
IntPtr results = safe_cast<IntPtr>(operation->GetResults()->Id);
|
||||
int clicked_index = results.ToInt32();
|
||||
*buttonid = messageboxdata->buttons[clicked_index].buttonid;
|
||||
}
|
||||
return 0;
|
||||
#endif /* if SDL_WINAPI_FAMILY_PHONE / else */
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_WINRT */
|
27
external/sdl/SDL/src/video/winrt/SDL_winrtmessagebox.h
vendored
Normal file
27
external/sdl/SDL/src/video/winrt/SDL_winrtmessagebox.h
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_WINRT
|
||||
|
||||
extern int WINRT_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid);
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_WINRT */
|
233
external/sdl/SDL/src/video/winrt/SDL_winrtmouse.cpp
vendored
Normal file
233
external/sdl/SDL/src/video/winrt/SDL_winrtmouse.cpp
vendored
Normal file
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_WINRT
|
||||
|
||||
/*
|
||||
* Windows includes:
|
||||
*/
|
||||
#include <Windows.h>
|
||||
#include <windows.ui.core.h>
|
||||
using namespace Windows::UI::Core;
|
||||
using Windows::UI::Core::CoreCursor;
|
||||
|
||||
/*
|
||||
* SDL includes:
|
||||
*/
|
||||
extern "C" {
|
||||
#include "../../events/SDL_mouse_c.h"
|
||||
#include "../../events/SDL_touch_c.h"
|
||||
#include "../SDL_sysvideo.h"
|
||||
}
|
||||
|
||||
#include "../../core/winrt/SDL_winrtapp_direct3d.h"
|
||||
#include "SDL_winrtvideo_cpp.h"
|
||||
#include "SDL_winrtmouse_c.h"
|
||||
|
||||
extern "C" SDL_bool WINRT_UsingRelativeMouseMode = SDL_FALSE;
|
||||
|
||||
static SDL_Cursor *WINRT_CreateSystemCursor(SDL_SystemCursor id)
|
||||
{
|
||||
SDL_Cursor *cursor;
|
||||
CoreCursorType cursorType = CoreCursorType::Arrow;
|
||||
|
||||
switch (id) {
|
||||
default:
|
||||
SDL_assert(0);
|
||||
return NULL;
|
||||
case SDL_SYSTEM_CURSOR_ARROW:
|
||||
cursorType = CoreCursorType::Arrow;
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_IBEAM:
|
||||
cursorType = CoreCursorType::IBeam;
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_WAIT:
|
||||
cursorType = CoreCursorType::Wait;
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_CROSSHAIR:
|
||||
cursorType = CoreCursorType::Cross;
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_WAITARROW:
|
||||
cursorType = CoreCursorType::Wait;
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_SIZENWSE:
|
||||
cursorType = CoreCursorType::SizeNorthwestSoutheast;
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_SIZENESW:
|
||||
cursorType = CoreCursorType::SizeNortheastSouthwest;
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_SIZEWE:
|
||||
cursorType = CoreCursorType::SizeWestEast;
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_SIZENS:
|
||||
cursorType = CoreCursorType::SizeNorthSouth;
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_SIZEALL:
|
||||
cursorType = CoreCursorType::SizeAll;
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_NO:
|
||||
cursorType = CoreCursorType::UniversalNo;
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_HAND:
|
||||
cursorType = CoreCursorType::Hand;
|
||||
break;
|
||||
}
|
||||
|
||||
cursor = (SDL_Cursor *)SDL_calloc(1, sizeof(*cursor));
|
||||
if (cursor) {
|
||||
/* Create a pointer to a COM reference to a cursor. The extra
|
||||
pointer is used (on top of the COM reference) to allow the cursor
|
||||
to be referenced by the SDL_cursor's driverdata field, which is
|
||||
a void pointer.
|
||||
*/
|
||||
CoreCursor ^ *theCursor = new CoreCursor ^ (nullptr);
|
||||
*theCursor = ref new CoreCursor(cursorType, 0);
|
||||
cursor->driverdata = (void *)theCursor;
|
||||
} else {
|
||||
SDL_OutOfMemory();
|
||||
}
|
||||
|
||||
return cursor;
|
||||
}
|
||||
|
||||
static SDL_Cursor *WINRT_CreateDefaultCursor()
|
||||
{
|
||||
return WINRT_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW);
|
||||
}
|
||||
|
||||
static void WINRT_FreeCursor(SDL_Cursor *cursor)
|
||||
{
|
||||
if (cursor->driverdata) {
|
||||
CoreCursor ^ *theCursor = (CoreCursor ^ *)cursor->driverdata;
|
||||
*theCursor = nullptr; // Release the COM reference to the CoreCursor
|
||||
delete theCursor; // Delete the pointer to the COM reference
|
||||
}
|
||||
SDL_free(cursor);
|
||||
}
|
||||
|
||||
static int WINRT_ShowCursor(SDL_Cursor *cursor)
|
||||
{
|
||||
// TODO, WinRT, XAML: make WINRT_ShowCursor work when XAML support is enabled.
|
||||
if (!CoreWindow::GetForCurrentThread()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
CoreWindow ^ coreWindow = CoreWindow::GetForCurrentThread();
|
||||
if (cursor) {
|
||||
CoreCursor ^ *theCursor = (CoreCursor ^ *)cursor->driverdata;
|
||||
coreWindow->PointerCursor = *theCursor;
|
||||
} else {
|
||||
// HACK ALERT: TL;DR - Hiding the cursor in WinRT/UWP apps is weird, and
|
||||
// a Win32-style cursor resource file must be directly included in apps,
|
||||
// otherwise hiding the cursor will cause mouse-motion data to never be
|
||||
// received.
|
||||
//
|
||||
// Here's the lengthy explanation:
|
||||
//
|
||||
// There are two ways to hide a cursor in WinRT/UWP apps.
|
||||
// Both involve setting the WinRT CoreWindow's (which is somewhat analogous
|
||||
// to a Win32 HWND) 'PointerCursor' property.
|
||||
//
|
||||
// The first way to hide a cursor sets PointerCursor to nullptr. This
|
||||
// is, arguably, the easiest to implement for an app. It does have an
|
||||
// unfortunate side-effect: it'll prevent mouse-motion events from being
|
||||
// sent to the app (via CoreWindow).
|
||||
//
|
||||
// The second way to hide a cursor sets PointerCursor to a transparent
|
||||
// cursor. This allows mouse-motion events to be sent to the app, but is
|
||||
// more difficult to set up, as:
|
||||
// 1. WinRT/UWP, while providing a few stock cursors, does not provide
|
||||
// a completely transparent cursor.
|
||||
// 2. WinRT/UWP allows apps to provide custom-built cursors, but *ONLY*
|
||||
// if they are linked directly inside the app, via Win32-style
|
||||
// cursor resource files. APIs to create cursors at runtime are
|
||||
// not provided to apps, and attempting to link-to or use Win32
|
||||
// cursor-creation APIs could cause an app to fail Windows Store
|
||||
// certification.
|
||||
//
|
||||
// SDL can use either means of hiding the cursor. It provides a Win32-style
|
||||
// set of cursor resource files in its source distribution, inside
|
||||
// src/main/winrt/. If those files are linked to an SDL-for-WinRT/UWP app
|
||||
// (by including them in a MSVC project, for example), SDL will attempt to
|
||||
// use those, if and when the cursor is hidden via SDL APIs. If those
|
||||
// files are not linked in, SDL will attempt to hide the cursor via the
|
||||
// 'set PointerCursor to nullptr' means (which, if you recall, causes
|
||||
// mouse-motion data to NOT be sent to the app!).
|
||||
//
|
||||
// Tech notes:
|
||||
// - SDL's blank cursor resource uses a resource ID of 5000.
|
||||
// - SDL's cursor resources consist of the following two files:
|
||||
// - src/main/winrt/SDL3-WinRTResource_BlankCursor.cur -- cursor pixel data
|
||||
// - src/main/winrt/SDL3-WinRTResources.rc -- declares the cursor resource, and its ID (of 5000)
|
||||
//
|
||||
|
||||
const unsigned int win32CursorResourceID = 5000;
|
||||
CoreCursor ^ blankCursor = ref new CoreCursor(CoreCursorType::Custom, win32CursorResourceID);
|
||||
|
||||
// Set 'PointerCursor' to 'blankCursor' in a way that shouldn't throw
|
||||
// an exception if the app hasn't loaded that resource.
|
||||
ABI::Windows::UI::Core::ICoreCursor *iblankCursor = reinterpret_cast<ABI::Windows::UI::Core::ICoreCursor *>(blankCursor);
|
||||
ABI::Windows::UI::Core::ICoreWindow *icoreWindow = reinterpret_cast<ABI::Windows::UI::Core::ICoreWindow *>(coreWindow);
|
||||
HRESULT hr = icoreWindow->put_PointerCursor(iblankCursor);
|
||||
if (FAILED(hr)) {
|
||||
// The app doesn't contain the cursor resource, or some other error
|
||||
// occurred. Just use the other, but mouse-motion-preventing, means of
|
||||
// hiding the cursor.
|
||||
coreWindow->PointerCursor = nullptr;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int WINRT_SetRelativeMouseMode(SDL_bool enabled)
|
||||
{
|
||||
WINRT_UsingRelativeMouseMode = enabled;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void WINRT_InitMouse(SDL_VideoDevice *_this)
|
||||
{
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
|
||||
/* DLudwig, Dec 3, 2012: WinRT does not currently provide APIs for
|
||||
the following features, AFAIK:
|
||||
- custom cursors (multiple system cursors are, however, available)
|
||||
- programmatically moveable cursors
|
||||
*/
|
||||
|
||||
#if !SDL_WINAPI_FAMILY_PHONE
|
||||
// mouse->CreateCursor = WINRT_CreateCursor;
|
||||
mouse->CreateSystemCursor = WINRT_CreateSystemCursor;
|
||||
mouse->ShowCursor = WINRT_ShowCursor;
|
||||
mouse->FreeCursor = WINRT_FreeCursor;
|
||||
// mouse->WarpMouse = WINRT_WarpMouse;
|
||||
mouse->SetRelativeMouseMode = WINRT_SetRelativeMouseMode;
|
||||
|
||||
SDL_SetDefaultCursor(WINRT_CreateDefaultCursor());
|
||||
#endif
|
||||
}
|
||||
|
||||
void WINRT_QuitMouse(SDL_VideoDevice *_this)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_WINRT */
|
38
external/sdl/SDL/src/video/winrt/SDL_winrtmouse_c.h
vendored
Normal file
38
external/sdl/SDL/src/video/winrt/SDL_winrtmouse_c.h
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifndef SDL_winrtmouse_h_
|
||||
#define SDL_winrtmouse_h_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern void WINRT_InitMouse(SDL_VideoDevice *_this);
|
||||
extern void WINRT_QuitMouse(SDL_VideoDevice *_this);
|
||||
extern SDL_bool WINRT_UsingRelativeMouseMode;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SDL_winrtmouse_h_ */
|
207
external/sdl/SDL/src/video/winrt/SDL_winrtopengles.cpp
vendored
Normal file
207
external/sdl/SDL/src/video/winrt/SDL_winrtopengles.cpp
vendored
Normal file
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#if defined(SDL_VIDEO_DRIVER_WINRT) && defined(SDL_VIDEO_OPENGL_EGL)
|
||||
|
||||
/* EGL implementation of SDL OpenGL support */
|
||||
|
||||
#include "SDL_winrtvideo_cpp.h"
|
||||
extern "C" {
|
||||
#include "SDL_winrtopengles.h"
|
||||
#include "../SDL_egl_c.h"
|
||||
}
|
||||
|
||||
/* Windows includes */
|
||||
#include <wrl/client.h>
|
||||
using namespace Windows::UI::Core;
|
||||
|
||||
/* ANGLE/WinRT constants */
|
||||
static const int ANGLE_D3D_FEATURE_LEVEL_ANY = 0;
|
||||
#define EGL_PLATFORM_ANGLE_ANGLE 0x3202
|
||||
#define EGL_PLATFORM_ANGLE_TYPE_ANGLE 0x3203
|
||||
#define EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE 0x3204
|
||||
#define EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE 0x3205
|
||||
#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3208
|
||||
#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE 0x3209
|
||||
#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE 0x320B
|
||||
#define EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE 0x320F
|
||||
|
||||
#define EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER 0x320B
|
||||
|
||||
/*
|
||||
* SDL/EGL top-level implementation
|
||||
*/
|
||||
|
||||
extern "C" int
|
||||
WINRT_GLES_LoadLibrary(SDL_VideoDevice *_this, const char *path)
|
||||
{
|
||||
SDL_VideoData *video_data = _this->driverdata;
|
||||
|
||||
if (SDL_EGL_LoadLibrary(_this, path, EGL_DEFAULT_DISPLAY, 0) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Load ANGLE/WinRT-specific functions */
|
||||
CreateWinrtEglWindow_Old_Function CreateWinrtEglWindow = (CreateWinrtEglWindow_Old_Function)SDL_LoadFunction(_this->egl_data->opengl_dll_handle, "CreateWinrtEglWindow");
|
||||
if (CreateWinrtEglWindow) {
|
||||
/* 'CreateWinrtEglWindow' was found, which means that an an older
|
||||
* version of ANGLE/WinRT is being used. Continue setting up EGL,
|
||||
* as appropriate to this version of ANGLE.
|
||||
*/
|
||||
|
||||
/* Create an ANGLE/WinRT EGL-window */
|
||||
/* TODO, WinRT: check for XAML usage before accessing the CoreWindow, as not doing so could lead to a crash */
|
||||
CoreWindow ^ native_win = CoreWindow::GetForCurrentThread();
|
||||
Microsoft::WRL::ComPtr<IUnknown> cpp_win = reinterpret_cast<IUnknown *>(native_win);
|
||||
HRESULT result = CreateWinrtEglWindow(cpp_win, ANGLE_D3D_FEATURE_LEVEL_ANY, &(video_data->winrtEglWindow));
|
||||
if (FAILED(result)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Call eglGetDisplay and eglInitialize as appropriate. On other
|
||||
* platforms, this would probably get done by SDL_EGL_LoadLibrary,
|
||||
* however ANGLE/WinRT's current implementation (as of Mar 22, 2014) of
|
||||
* eglGetDisplay requires that a C++ object be passed into it, so the
|
||||
* call will be made in this file, a C++ file, instead.
|
||||
*/
|
||||
Microsoft::WRL::ComPtr<IUnknown> cpp_display = video_data->winrtEglWindow;
|
||||
_this->egl_data->egl_display = ((eglGetDisplay_Old_Function)_this->egl_data->eglGetDisplay)(cpp_display);
|
||||
if (!_this->egl_data->egl_display) {
|
||||
return SDL_EGL_SetError("Could not get Windows 8.0 EGL display", "eglGetDisplay");
|
||||
}
|
||||
|
||||
if (_this->egl_data->eglInitialize(_this->egl_data->egl_display, NULL, NULL) != EGL_TRUE) {
|
||||
return SDL_EGL_SetError("Could not initialize Windows 8.0 EGL", "eglInitialize");
|
||||
}
|
||||
} else {
|
||||
/* Declare some ANGLE/EGL initialization property-sets, as suggested by
|
||||
* MSOpenTech's ANGLE-for-WinRT template apps:
|
||||
*/
|
||||
const EGLint defaultDisplayAttributes[] = {
|
||||
EGL_PLATFORM_ANGLE_TYPE_ANGLE,
|
||||
EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
|
||||
EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER,
|
||||
EGL_TRUE,
|
||||
EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE,
|
||||
EGL_TRUE,
|
||||
EGL_NONE,
|
||||
};
|
||||
|
||||
const EGLint fl9_3DisplayAttributes[] = {
|
||||
EGL_PLATFORM_ANGLE_TYPE_ANGLE,
|
||||
EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
|
||||
EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE,
|
||||
9,
|
||||
EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE,
|
||||
3,
|
||||
EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER,
|
||||
EGL_TRUE,
|
||||
EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE,
|
||||
EGL_TRUE,
|
||||
EGL_NONE,
|
||||
};
|
||||
|
||||
const EGLint warpDisplayAttributes[] = {
|
||||
EGL_PLATFORM_ANGLE_TYPE_ANGLE,
|
||||
EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
|
||||
EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE,
|
||||
EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE,
|
||||
EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER,
|
||||
EGL_TRUE,
|
||||
EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE,
|
||||
EGL_TRUE,
|
||||
EGL_NONE,
|
||||
};
|
||||
|
||||
/* 'CreateWinrtEglWindow' was NOT found, which either means that a
|
||||
* newer version of ANGLE/WinRT is being used, or that we don't have
|
||||
* a valid copy of ANGLE.
|
||||
*
|
||||
* Try loading ANGLE as if it were the newer version.
|
||||
*/
|
||||
eglGetPlatformDisplayEXT_Function eglGetPlatformDisplayEXT = (eglGetPlatformDisplayEXT_Function)_this->egl_data->eglGetProcAddress("eglGetPlatformDisplayEXT");
|
||||
if (!eglGetPlatformDisplayEXT) {
|
||||
return SDL_EGL_SetError("Could not retrieve ANGLE/WinRT display function(s)", "eglGetProcAddress");
|
||||
}
|
||||
|
||||
#if !SDL_WINAPI_FAMILY_PHONE
|
||||
/* Try initializing EGL at D3D11 Feature Level 10_0+ (which is not
|
||||
* supported on WinPhone 8.x.
|
||||
*/
|
||||
_this->egl_data->egl_display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, defaultDisplayAttributes);
|
||||
if (!_this->egl_data->egl_display) {
|
||||
return SDL_EGL_SetError("Could not get EGL display for Direct3D 10_0+", "eglGetPlatformDisplayEXT");
|
||||
}
|
||||
|
||||
if (_this->egl_data->eglInitialize(_this->egl_data->egl_display, NULL, NULL) != EGL_TRUE)
|
||||
#endif
|
||||
{
|
||||
/* Try initializing EGL at D3D11 Feature Level 9_3, in case the
|
||||
* 10_0 init fails, or we're on Windows Phone (which only supports
|
||||
* 9_3).
|
||||
*/
|
||||
_this->egl_data->egl_display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, fl9_3DisplayAttributes);
|
||||
if (!_this->egl_data->egl_display) {
|
||||
return SDL_EGL_SetError("Could not get EGL display for Direct3D 9_3", "eglGetPlatformDisplayEXT");
|
||||
}
|
||||
|
||||
if (_this->egl_data->eglInitialize(_this->egl_data->egl_display, NULL, NULL) != EGL_TRUE) {
|
||||
/* Try initializing EGL at D3D11 Feature Level 11_0 on WARP
|
||||
* (a Windows-provided, software rasterizer) if all else fails.
|
||||
*/
|
||||
_this->egl_data->egl_display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, warpDisplayAttributes);
|
||||
if (!_this->egl_data->egl_display) {
|
||||
return SDL_EGL_SetError("Could not get EGL display for Direct3D WARP", "eglGetPlatformDisplayEXT");
|
||||
}
|
||||
|
||||
if (_this->egl_data->eglInitialize(_this->egl_data->egl_display, NULL, NULL) != EGL_TRUE) {
|
||||
return SDL_EGL_SetError("Could not initialize WinRT 8.x+ EGL", "eglInitialize");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
WINRT_GLES_UnloadLibrary(SDL_VideoDevice *_this)
|
||||
{
|
||||
SDL_VideoData *video_data = _this->driverdata;
|
||||
|
||||
/* Release SDL's own COM reference to the ANGLE/WinRT IWinrtEglWindow */
|
||||
if (video_data->winrtEglWindow) {
|
||||
video_data->winrtEglWindow->Release();
|
||||
video_data->winrtEglWindow = nullptr;
|
||||
}
|
||||
|
||||
/* Perform the bulk of the unloading */
|
||||
SDL_EGL_UnloadLibrary(_this);
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
SDL_EGL_CreateContext_impl(WINRT)
|
||||
SDL_EGL_SwapWindow_impl(WINRT)
|
||||
SDL_EGL_MakeCurrent_impl(WINRT)
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_WINRT && SDL_VIDEO_OPENGL_EGL */
|
67
external/sdl/SDL/src/video/winrt/SDL_winrtopengles.h
vendored
Normal file
67
external/sdl/SDL/src/video/winrt/SDL_winrtopengles.h
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifndef SDL_winrtopengles_h_
|
||||
#define SDL_winrtopengles_h_
|
||||
|
||||
#if defined(SDL_VIDEO_DRIVER_WINRT) && defined(SDL_VIDEO_OPENGL_EGL)
|
||||
|
||||
#include "../SDL_sysvideo.h"
|
||||
#include "../SDL_egl_c.h"
|
||||
|
||||
/* OpenGLES functions */
|
||||
#define WINRT_GLES_GetAttribute SDL_EGL_GetAttribute
|
||||
#define WINRT_GLES_GetProcAddress SDL_EGL_GetProcAddressInternal
|
||||
#define WINRT_GLES_SetSwapInterval SDL_EGL_SetSwapInterval
|
||||
#define WINRT_GLES_GetSwapInterval SDL_EGL_GetSwapInterval
|
||||
#define WINRT_GLES_DeleteContext SDL_EGL_DeleteContext
|
||||
|
||||
extern int WINRT_GLES_LoadLibrary(SDL_VideoDevice *_this, const char *path);
|
||||
extern void WINRT_GLES_UnloadLibrary(SDL_VideoDevice *_this);
|
||||
extern SDL_GLContext WINRT_GLES_CreateContext(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
extern int WINRT_GLES_SwapWindow(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
extern int WINRT_GLES_MakeCurrent(SDL_VideoDevice *_this, SDL_Window *window, SDL_GLContext context);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
/* Typedefs for ANGLE/WinRT's C++-based native-display and native-window types,
|
||||
* which are used when calling eglGetDisplay and eglCreateWindowSurface.
|
||||
*/
|
||||
typedef Microsoft::WRL::ComPtr<IUnknown> WINRT_EGLNativeWindowType_Old;
|
||||
|
||||
/* Function pointer typedefs for 'old' ANGLE/WinRT's functions, which may
|
||||
* require that C++ objects be passed in:
|
||||
*/
|
||||
typedef EGLDisplay(EGLAPIENTRY *eglGetDisplay_Old_Function)(WINRT_EGLNativeWindowType_Old);
|
||||
typedef EGLSurface(EGLAPIENTRY *eglCreateWindowSurface_Old_Function)(EGLDisplay, EGLConfig, WINRT_EGLNativeWindowType_Old, const EGLint *);
|
||||
typedef HRESULT(EGLAPIENTRY *CreateWinrtEglWindow_Old_Function)(Microsoft::WRL::ComPtr<IUnknown>, int, IUnknown **result);
|
||||
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/* Function pointer typedefs for 'new' ANGLE/WinRT functions, which, unlike
|
||||
* the old functions, do not require C++ support and work with plain C.
|
||||
*/
|
||||
typedef EGLDisplay(EGLAPIENTRY *eglGetPlatformDisplayEXT_Function)(EGLenum, void *, const EGLint *);
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_WINRT && SDL_VIDEO_OPENGL_EGL */
|
||||
|
||||
#endif /* SDL_winrtopengles_h_ */
|
394
external/sdl/SDL/src/video/winrt/SDL_winrtpointerinput.cpp
vendored
Normal file
394
external/sdl/SDL/src/video/winrt/SDL_winrtpointerinput.cpp
vendored
Normal file
@@ -0,0 +1,394 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_WINRT
|
||||
|
||||
/* SDL includes */
|
||||
#include "SDL_winrtevents_c.h"
|
||||
#include "SDL_winrtmouse_c.h"
|
||||
#include "SDL_winrtvideo_cpp.h"
|
||||
|
||||
extern "C" {
|
||||
#include "../SDL_sysvideo.h"
|
||||
#include "../../events/SDL_events_c.h"
|
||||
#include "../../events/SDL_mouse_c.h"
|
||||
#include "../../events/SDL_touch_c.h"
|
||||
}
|
||||
|
||||
/* File-specific globals: */
|
||||
static SDL_TouchID WINRT_TouchID = 1;
|
||||
|
||||
void WINRT_InitTouch(SDL_VideoDevice *_this)
|
||||
{
|
||||
SDL_AddTouch(WINRT_TouchID, SDL_TOUCH_DEVICE_DIRECT, "");
|
||||
}
|
||||
|
||||
//
|
||||
// Applies necessary geometric transformations to raw cursor positions:
|
||||
//
|
||||
Windows::Foundation::Point
|
||||
WINRT_TransformCursorPosition(SDL_Window *window,
|
||||
Windows::Foundation::Point rawPosition,
|
||||
WINRT_CursorNormalizationType normalization)
|
||||
{
|
||||
using namespace Windows::UI::Core;
|
||||
using namespace Windows::Graphics::Display;
|
||||
|
||||
if (!window) {
|
||||
return rawPosition;
|
||||
}
|
||||
|
||||
SDL_WindowData *windowData = window->driverdata;
|
||||
if (windowData->coreWindow == nullptr) {
|
||||
// For some reason, the window isn't associated with a CoreWindow.
|
||||
// This might end up being the case as XAML support is extended.
|
||||
// For now, if there's no CoreWindow attached to the SDL_Window,
|
||||
// don't do any transforms.
|
||||
|
||||
// TODO, WinRT: make sure touch input coordinate ranges are correct when using XAML support
|
||||
return rawPosition;
|
||||
}
|
||||
|
||||
// The CoreWindow can only be accessed on certain thread(s).
|
||||
SDL_assert(CoreWindow::GetForCurrentThread() != nullptr);
|
||||
|
||||
CoreWindow ^ nativeWindow = windowData->coreWindow.Get();
|
||||
Windows::Foundation::Point outputPosition;
|
||||
|
||||
// Compute coordinates normalized from 0..1.
|
||||
// If the coordinates need to be sized to the SDL window,
|
||||
// we'll do that after.
|
||||
#if !SDL_WINAPI_FAMILY_PHONE || NTDDI_VERSION > NTDDI_WIN8
|
||||
outputPosition.X = rawPosition.X / nativeWindow->Bounds.Width;
|
||||
outputPosition.Y = rawPosition.Y / nativeWindow->Bounds.Height;
|
||||
#else
|
||||
switch (WINRT_DISPLAY_PROPERTY(CurrentOrientation)) {
|
||||
case DisplayOrientations::Portrait:
|
||||
outputPosition.X = rawPosition.X / nativeWindow->Bounds.Width;
|
||||
outputPosition.Y = rawPosition.Y / nativeWindow->Bounds.Height;
|
||||
break;
|
||||
case DisplayOrientations::PortraitFlipped:
|
||||
outputPosition.X = 1.0f - (rawPosition.X / nativeWindow->Bounds.Width);
|
||||
outputPosition.Y = 1.0f - (rawPosition.Y / nativeWindow->Bounds.Height);
|
||||
break;
|
||||
case DisplayOrientations::Landscape:
|
||||
outputPosition.X = rawPosition.Y / nativeWindow->Bounds.Height;
|
||||
outputPosition.Y = 1.0f - (rawPosition.X / nativeWindow->Bounds.Width);
|
||||
break;
|
||||
case DisplayOrientations::LandscapeFlipped:
|
||||
outputPosition.X = 1.0f - (rawPosition.Y / nativeWindow->Bounds.Height);
|
||||
outputPosition.Y = rawPosition.X / nativeWindow->Bounds.Width;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (normalization == TransformToSDLWindowSize) {
|
||||
outputPosition.X *= ((float32)window->w);
|
||||
outputPosition.Y *= ((float32)window->h);
|
||||
}
|
||||
|
||||
return outputPosition;
|
||||
}
|
||||
|
||||
SDL_bool WINRT_GetSDLButtonForPointerPoint(Windows::UI::Input::PointerPoint ^ pt, Uint8 *button, Uint8 *pressed)
|
||||
{
|
||||
using namespace Windows::UI::Input;
|
||||
|
||||
#if SDL_WINAPI_FAMILY_PHONE
|
||||
*button = SDL_BUTTON_LEFT;
|
||||
return SDL_TRUE;
|
||||
#else
|
||||
switch (pt->Properties->PointerUpdateKind) {
|
||||
case PointerUpdateKind::LeftButtonPressed:
|
||||
case PointerUpdateKind::LeftButtonReleased:
|
||||
*button = SDL_BUTTON_LEFT;
|
||||
*pressed = (pt->Properties->PointerUpdateKind == PointerUpdateKind::LeftButtonPressed);
|
||||
return SDL_TRUE;
|
||||
|
||||
case PointerUpdateKind::RightButtonPressed:
|
||||
case PointerUpdateKind::RightButtonReleased:
|
||||
*button = SDL_BUTTON_RIGHT;
|
||||
*pressed = (pt->Properties->PointerUpdateKind == PointerUpdateKind::RightButtonPressed);
|
||||
return SDL_TRUE;
|
||||
|
||||
case PointerUpdateKind::MiddleButtonPressed:
|
||||
case PointerUpdateKind::MiddleButtonReleased:
|
||||
*button = SDL_BUTTON_MIDDLE;
|
||||
*pressed = (pt->Properties->PointerUpdateKind == PointerUpdateKind::MiddleButtonPressed);
|
||||
return SDL_TRUE;
|
||||
|
||||
case PointerUpdateKind::XButton1Pressed:
|
||||
case PointerUpdateKind::XButton1Released:
|
||||
*button = SDL_BUTTON_X1;
|
||||
*pressed = (pt->Properties->PointerUpdateKind == PointerUpdateKind::XButton1Pressed);
|
||||
return SDL_TRUE;
|
||||
|
||||
case PointerUpdateKind::XButton2Pressed:
|
||||
case PointerUpdateKind::XButton2Released:
|
||||
*button = SDL_BUTTON_X2;
|
||||
*pressed = (pt->Properties->PointerUpdateKind == PointerUpdateKind::XButton2Pressed);
|
||||
return SDL_TRUE;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
*button = 0;
|
||||
*pressed = 0;
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
// const char *
|
||||
// WINRT_ConvertPointerUpdateKindToString(Windows::UI::Input::PointerUpdateKind kind)
|
||||
//{
|
||||
// using namespace Windows::UI::Input;
|
||||
//
|
||||
// switch (kind)
|
||||
// {
|
||||
// case PointerUpdateKind::Other:
|
||||
// return "Other";
|
||||
// case PointerUpdateKind::LeftButtonPressed:
|
||||
// return "LeftButtonPressed";
|
||||
// case PointerUpdateKind::LeftButtonReleased:
|
||||
// return "LeftButtonReleased";
|
||||
// case PointerUpdateKind::RightButtonPressed:
|
||||
// return "RightButtonPressed";
|
||||
// case PointerUpdateKind::RightButtonReleased:
|
||||
// return "RightButtonReleased";
|
||||
// case PointerUpdateKind::MiddleButtonPressed:
|
||||
// return "MiddleButtonPressed";
|
||||
// case PointerUpdateKind::MiddleButtonReleased:
|
||||
// return "MiddleButtonReleased";
|
||||
// case PointerUpdateKind::XButton1Pressed:
|
||||
// return "XButton1Pressed";
|
||||
// case PointerUpdateKind::XButton1Released:
|
||||
// return "XButton1Released";
|
||||
// case PointerUpdateKind::XButton2Pressed:
|
||||
// return "XButton2Pressed";
|
||||
// case PointerUpdateKind::XButton2Released:
|
||||
// return "XButton2Released";
|
||||
// }
|
||||
//
|
||||
// return "";
|
||||
// }
|
||||
|
||||
static bool WINRT_IsTouchEvent(Windows::UI::Input::PointerPoint ^ pointerPoint)
|
||||
{
|
||||
#if SDL_WINAPI_FAMILY_PHONE
|
||||
return true;
|
||||
#else
|
||||
using namespace Windows::Devices::Input;
|
||||
switch (pointerPoint->PointerDevice->PointerDeviceType) {
|
||||
case PointerDeviceType::Touch:
|
||||
case PointerDeviceType::Pen:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void WINRT_ProcessPointerPressedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^ pointerPoint)
|
||||
{
|
||||
if (!window) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!WINRT_IsTouchEvent(pointerPoint)) {
|
||||
Uint8 button, pressed;
|
||||
WINRT_GetSDLButtonForPointerPoint(pointerPoint, &button, &pressed);
|
||||
SDL_assert(pressed == 1);
|
||||
SDL_SendMouseButton(0, window, 0, SDL_PRESSED, button);
|
||||
} else {
|
||||
Windows::Foundation::Point normalizedPoint = WINRT_TransformCursorPosition(window, pointerPoint->Position, NormalizeZeroToOne);
|
||||
Windows::Foundation::Point windowPoint = WINRT_TransformCursorPosition(window, pointerPoint->Position, TransformToSDLWindowSize);
|
||||
|
||||
SDL_SendTouch(0,
|
||||
WINRT_TouchID,
|
||||
(SDL_FingerID)pointerPoint->PointerId,
|
||||
window,
|
||||
SDL_TRUE,
|
||||
normalizedPoint.X,
|
||||
normalizedPoint.Y,
|
||||
pointerPoint->Properties->Pressure);
|
||||
}
|
||||
}
|
||||
|
||||
void WINRT_ProcessPointerMovedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^ pointerPoint)
|
||||
{
|
||||
if (!window || WINRT_UsingRelativeMouseMode) {
|
||||
return;
|
||||
}
|
||||
|
||||
Windows::Foundation::Point normalizedPoint = WINRT_TransformCursorPosition(window, pointerPoint->Position, NormalizeZeroToOne);
|
||||
Windows::Foundation::Point windowPoint = WINRT_TransformCursorPosition(window, pointerPoint->Position, TransformToSDLWindowSize);
|
||||
|
||||
if (!WINRT_IsTouchEvent(pointerPoint)) {
|
||||
/* For some odd reason Moved events are used for multiple mouse buttons */
|
||||
Uint8 button, pressed;
|
||||
if (WINRT_GetSDLButtonForPointerPoint(pointerPoint, &button, &pressed)) {
|
||||
SDL_SendMouseButton(0, window, 0, pressed, button);
|
||||
}
|
||||
|
||||
SDL_SendMouseMotion(0, window, 0, 0, windowPoint.X, windowPoint.Y);
|
||||
} else {
|
||||
SDL_SendTouchMotion(0,
|
||||
WINRT_TouchID,
|
||||
(SDL_FingerID)pointerPoint->PointerId,
|
||||
window,
|
||||
normalizedPoint.X,
|
||||
normalizedPoint.Y,
|
||||
pointerPoint->Properties->Pressure);
|
||||
}
|
||||
}
|
||||
|
||||
void WINRT_ProcessPointerReleasedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^ pointerPoint)
|
||||
{
|
||||
if (!window) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!WINRT_IsTouchEvent(pointerPoint)) {
|
||||
Uint8 button, pressed;
|
||||
WINRT_GetSDLButtonForPointerPoint(pointerPoint, &button, &pressed);
|
||||
SDL_assert(pressed == 0);
|
||||
SDL_SendMouseButton(0, window, 0, SDL_RELEASED, button);
|
||||
} else {
|
||||
Windows::Foundation::Point normalizedPoint = WINRT_TransformCursorPosition(window, pointerPoint->Position, NormalizeZeroToOne);
|
||||
|
||||
SDL_SendTouch(0,
|
||||
WINRT_TouchID,
|
||||
(SDL_FingerID)pointerPoint->PointerId,
|
||||
window,
|
||||
SDL_FALSE,
|
||||
normalizedPoint.X,
|
||||
normalizedPoint.Y,
|
||||
pointerPoint->Properties->Pressure);
|
||||
}
|
||||
}
|
||||
|
||||
void WINRT_ProcessPointerEnteredEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^ pointerPoint)
|
||||
{
|
||||
if (!window) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!WINRT_IsTouchEvent(pointerPoint)) {
|
||||
SDL_SetMouseFocus(window);
|
||||
}
|
||||
}
|
||||
|
||||
void WINRT_ProcessPointerExitedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^ pointerPoint)
|
||||
{
|
||||
if (!window) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!WINRT_IsTouchEvent(pointerPoint)) {
|
||||
SDL_SetMouseFocus(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void WINRT_ProcessPointerWheelChangedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^ pointerPoint)
|
||||
{
|
||||
if (!window) {
|
||||
return;
|
||||
}
|
||||
|
||||
float motion = (float)pointerPoint->Properties->MouseWheelDelta / WHEEL_DELTA;
|
||||
SDL_SendMouseWheel(0, window, 0, 0, (float)motion, SDL_MOUSEWHEEL_NORMAL);
|
||||
}
|
||||
|
||||
void WINRT_ProcessMouseMovedEvent(SDL_Window *window, Windows::Devices::Input::MouseEventArgs ^ args)
|
||||
{
|
||||
if (!window || !WINRT_UsingRelativeMouseMode) {
|
||||
return;
|
||||
}
|
||||
|
||||
// DLudwig, 2012-12-28: On some systems, namely Visual Studio's Windows
|
||||
// Simulator, as well as Windows 8 in a Parallels 8 VM, MouseEventArgs'
|
||||
// MouseDelta field often reports very large values. More information
|
||||
// on this can be found at the following pages on MSDN:
|
||||
// - http://social.msdn.microsoft.com/Forums/en-US/winappswithnativecode/thread/a3c789fa-f1c5-49c4-9c0a-7db88d0f90f8
|
||||
// - https://connect.microsoft.com/VisualStudio/Feedback/details/756515
|
||||
//
|
||||
// The values do not appear to be as large when running on some systems,
|
||||
// most notably a Surface RT. Furthermore, the values returned by
|
||||
// CoreWindow's PointerMoved event, and sent to this class' OnPointerMoved
|
||||
// method, do not ever appear to be large, even when MouseEventArgs'
|
||||
// MouseDelta is reporting to the contrary.
|
||||
//
|
||||
// On systems with the large-values behavior, it appears that the values
|
||||
// get reported as if the screen's size is 65536 units in both the X and Y
|
||||
// dimensions. This can be viewed by using Windows' now-private, "Raw Input"
|
||||
// APIs. (GetRawInputData, RegisterRawInputDevices, WM_INPUT, etc.)
|
||||
//
|
||||
// MSDN's documentation on MouseEventArgs' MouseDelta field (at
|
||||
// http://msdn.microsoft.com/en-us/library/windows/apps/windows.devices.input.mouseeventargs.mousedelta ),
|
||||
// does not seem to indicate (to me) that its values should be so large. It
|
||||
// says that its values should be a "change in screen location". I could
|
||||
// be misinterpreting this, however a post on MSDN from a Microsoft engineer (see:
|
||||
// http://social.msdn.microsoft.com/Forums/en-US/winappswithnativecode/thread/09a9868e-95bb-4858-ba1a-cb4d2c298d62 ),
|
||||
// indicates that these values are in DIPs, which is the same unit used
|
||||
// by CoreWindow's PointerMoved events (via the Position field in its CurrentPoint
|
||||
// property. See http://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.input.pointerpoint.position.aspx
|
||||
// for details.)
|
||||
//
|
||||
// To note, PointerMoved events are sent a 'RawPosition' value (via the
|
||||
// CurrentPoint property in MouseEventArgs), however these do not seem
|
||||
// to exhibit the same large-value behavior.
|
||||
//
|
||||
// The values passed via PointerMoved events can't always be used for relative
|
||||
// mouse motion, unfortunately. Its values are bound to the cursor's position,
|
||||
// which stops when it hits one of the screen's edges. This can be a problem in
|
||||
// first person shooters, whereby it is normal for mouse motion to travel far
|
||||
// along any one axis for a period of time. MouseMoved events do not have the
|
||||
// screen-bounding limitation, and can be used regardless of where the system's
|
||||
// cursor is.
|
||||
//
|
||||
// One possible workaround would be to programmatically set the cursor's
|
||||
// position to the screen's center (when SDL's relative mouse mode is enabled),
|
||||
// however WinRT does not yet seem to have the ability to set the cursor's
|
||||
// position via a public API. Win32 did this via an API call, SetCursorPos,
|
||||
// however WinRT makes this function be private. Apps that use it won't get
|
||||
// approved for distribution in the Windows Store. I've yet to be able to find
|
||||
// a suitable, store-friendly counterpart for WinRT.
|
||||
//
|
||||
// There may be some room for a workaround whereby OnPointerMoved's values
|
||||
// are compared to the values from OnMouseMoved in order to detect
|
||||
// when this bug is active. A suitable transformation could then be made to
|
||||
// OnMouseMoved's values.
|
||||
//
|
||||
const Windows::Foundation::Point mouseDeltaInDIPs((float)args->MouseDelta.X, (float)args->MouseDelta.Y);
|
||||
const Windows::Foundation::Point mouseDeltaInSDLWindowCoords = WINRT_TransformCursorPosition(window, mouseDeltaInDIPs, TransformToSDLWindowSize);
|
||||
SDL_SendMouseMotion(0,
|
||||
window,
|
||||
0,
|
||||
1,
|
||||
mouseDeltaInSDLWindowCoords.X,
|
||||
mouseDeltaInSDLWindowCoords.Y);
|
||||
}
|
||||
|
||||
#endif // SDL_VIDEO_DRIVER_WINRT
|
849
external/sdl/SDL/src/video/winrt/SDL_winrtvideo.cpp
vendored
Normal file
849
external/sdl/SDL/src/video/winrt/SDL_winrtvideo.cpp
vendored
Normal file
@@ -0,0 +1,849 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_WINRT
|
||||
|
||||
/* WinRT SDL video driver implementation
|
||||
|
||||
Initial work on this was done by David Ludwig (dludwig@pobox.com), and
|
||||
was based off of SDL's "dummy" video driver.
|
||||
*/
|
||||
|
||||
/* Standard C++11 includes */
|
||||
#include <functional>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
/* Windows includes */
|
||||
#include <agile.h>
|
||||
#include <dxgi.h>
|
||||
#include <dxgi1_2.h>
|
||||
#include <windows.graphics.display.h>
|
||||
#include <windows.system.display.h>
|
||||
using namespace Windows::ApplicationModel::Core;
|
||||
using namespace Windows::Foundation;
|
||||
using namespace Windows::Graphics::Display;
|
||||
using namespace Windows::UI::Core;
|
||||
using namespace Windows::UI::ViewManagement;
|
||||
|
||||
/* [re]declare Windows GUIDs locally, to limit the amount of external lib(s) SDL has to link to */
|
||||
static const GUID SDL_IID_IDisplayRequest = { 0xe5732044, 0xf49f, 0x4b60, { 0x8d, 0xd4, 0x5e, 0x7e, 0x3a, 0x63, 0x2a, 0xc0 } };
|
||||
static const GUID SDL_IID_IDXGIFactory2 = { 0x50c83a1c, 0xe072, 0x4c48, { 0x87, 0xb0, 0x36, 0x30, 0xfa, 0x36, 0xa6, 0xd0 } };
|
||||
|
||||
/* SDL includes */
|
||||
extern "C" {
|
||||
#include "../../core/windows/SDL_windows.h"
|
||||
#include "../../events/SDL_events_c.h"
|
||||
#include "../../render/SDL_sysrender.h"
|
||||
#include "../SDL_pixels_c.h"
|
||||
#include "../SDL_sysvideo.h"
|
||||
#include "SDL_winrtopengles.h"
|
||||
}
|
||||
|
||||
#include "../../core/winrt/SDL_winrtapp_direct3d.h"
|
||||
#include "../../core/winrt/SDL_winrtapp_xaml.h"
|
||||
#include "SDL_winrtevents_c.h"
|
||||
#include "SDL_winrtgamebar_cpp.h"
|
||||
#include "SDL_winrtmouse_c.h"
|
||||
#include "SDL_winrtvideo_cpp.h"
|
||||
|
||||
#include <SDL3/SDL_syswm.h>
|
||||
|
||||
/* Initialization/Query functions */
|
||||
static int WINRT_VideoInit(SDL_VideoDevice *_this);
|
||||
static int WINRT_InitModes(SDL_VideoDevice *_this);
|
||||
static int WINRT_SetDisplayMode(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_DisplayMode *mode);
|
||||
static void WINRT_VideoQuit(SDL_VideoDevice *_this);
|
||||
|
||||
/* Window functions */
|
||||
static int WINRT_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
static void WINRT_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
static void WINRT_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen);
|
||||
static void WINRT_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
static int WINRT_GetWindowWMInfo(SDL_VideoDevice *_this, SDL_Window *window, SDL_SysWMinfo *info);
|
||||
|
||||
/* Misc functions */
|
||||
static ABI::Windows::System::Display::IDisplayRequest *WINRT_CreateDisplayRequest(SDL_VideoDevice *_this);
|
||||
extern int WINRT_SuspendScreenSaver(SDL_VideoDevice *_this);
|
||||
|
||||
/* SDL-internal globals: */
|
||||
SDL_Window *WINRT_GlobalSDLWindow = NULL;
|
||||
|
||||
/* WinRT driver bootstrap functions */
|
||||
|
||||
static void WINRT_DeleteDevice(SDL_VideoDevice *device)
|
||||
{
|
||||
if (device->driverdata) {
|
||||
SDL_VideoData *video_data = device->driverdata;
|
||||
if (video_data->winrtEglWindow) {
|
||||
video_data->winrtEglWindow->Release();
|
||||
}
|
||||
SDL_free(video_data);
|
||||
}
|
||||
|
||||
SDL_free(device);
|
||||
}
|
||||
|
||||
static SDL_VideoDevice *WINRT_CreateDevice(void)
|
||||
{
|
||||
SDL_VideoDevice *device;
|
||||
SDL_VideoData *data;
|
||||
|
||||
/* Initialize all variables that we clean on shutdown */
|
||||
device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice));
|
||||
if (device == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
return 0;
|
||||
}
|
||||
|
||||
data = (SDL_VideoData *)SDL_calloc(1, sizeof(SDL_VideoData));
|
||||
if (data == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
SDL_free(device);
|
||||
return 0;
|
||||
}
|
||||
device->driverdata = data;
|
||||
|
||||
/* Set the function pointers */
|
||||
device->VideoInit = WINRT_VideoInit;
|
||||
device->VideoQuit = WINRT_VideoQuit;
|
||||
device->CreateSDLWindow = WINRT_CreateWindow;
|
||||
device->SetWindowSize = WINRT_SetWindowSize;
|
||||
device->SetWindowFullscreen = WINRT_SetWindowFullscreen;
|
||||
device->DestroyWindow = WINRT_DestroyWindow;
|
||||
device->SetDisplayMode = WINRT_SetDisplayMode;
|
||||
device->PumpEvents = WINRT_PumpEvents;
|
||||
device->GetWindowWMInfo = WINRT_GetWindowWMInfo;
|
||||
device->SuspendScreenSaver = WINRT_SuspendScreenSaver;
|
||||
|
||||
#if NTDDI_VERSION >= NTDDI_WIN10
|
||||
device->HasScreenKeyboardSupport = WINRT_HasScreenKeyboardSupport;
|
||||
device->ShowScreenKeyboard = WINRT_ShowScreenKeyboard;
|
||||
device->HideScreenKeyboard = WINRT_HideScreenKeyboard;
|
||||
device->IsScreenKeyboardShown = WINRT_IsScreenKeyboardShown;
|
||||
|
||||
WINTRT_InitialiseInputPaneEvents(device);
|
||||
#endif
|
||||
|
||||
#ifdef SDL_VIDEO_OPENGL_EGL
|
||||
device->GL_LoadLibrary = WINRT_GLES_LoadLibrary;
|
||||
device->GL_GetProcAddress = WINRT_GLES_GetProcAddress;
|
||||
device->GL_UnloadLibrary = WINRT_GLES_UnloadLibrary;
|
||||
device->GL_CreateContext = WINRT_GLES_CreateContext;
|
||||
device->GL_MakeCurrent = WINRT_GLES_MakeCurrent;
|
||||
device->GL_SetSwapInterval = WINRT_GLES_SetSwapInterval;
|
||||
device->GL_GetSwapInterval = WINRT_GLES_GetSwapInterval;
|
||||
device->GL_SwapWindow = WINRT_GLES_SwapWindow;
|
||||
device->GL_DeleteContext = WINRT_GLES_DeleteContext;
|
||||
#endif
|
||||
device->free = WINRT_DeleteDevice;
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
#define WINRTVID_DRIVER_NAME "winrt"
|
||||
VideoBootStrap WINRT_bootstrap = {
|
||||
WINRTVID_DRIVER_NAME, "SDL WinRT video driver",
|
||||
WINRT_CreateDevice
|
||||
};
|
||||
|
||||
static void SDLCALL WINRT_SetDisplayOrientationsPreference(void *userdata, const char *name, const char *oldValue, const char *newValue)
|
||||
{
|
||||
SDL_assert(SDL_strcmp(name, SDL_HINT_ORIENTATIONS) == 0);
|
||||
|
||||
/* HACK: prevent SDL from altering an app's .appxmanifest-set orientation
|
||||
* from being changed on startup, by detecting when SDL_HINT_ORIENTATIONS
|
||||
* is getting registered.
|
||||
*
|
||||
* TODO, WinRT: consider reading in an app's .appxmanifest file, and apply its orientation when 'newValue == NULL'.
|
||||
*/
|
||||
if ((oldValue == NULL) && (newValue == NULL)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Start with no orientation flags, then add each in as they're parsed
|
||||
// from newValue.
|
||||
unsigned int orientationFlags = 0;
|
||||
if (newValue) {
|
||||
std::istringstream tokenizer(newValue);
|
||||
while (!tokenizer.eof()) {
|
||||
std::string orientationName;
|
||||
std::getline(tokenizer, orientationName, ' ');
|
||||
if (orientationName == "LandscapeLeft") {
|
||||
orientationFlags |= (unsigned int)DisplayOrientations::LandscapeFlipped;
|
||||
} else if (orientationName == "LandscapeRight") {
|
||||
orientationFlags |= (unsigned int)DisplayOrientations::Landscape;
|
||||
} else if (orientationName == "Portrait") {
|
||||
orientationFlags |= (unsigned int)DisplayOrientations::Portrait;
|
||||
} else if (orientationName == "PortraitUpsideDown") {
|
||||
orientationFlags |= (unsigned int)DisplayOrientations::PortraitFlipped;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If no valid orientation flags were specified, use a reasonable set of defaults:
|
||||
if (!orientationFlags) {
|
||||
// TODO, WinRT: consider seeing if an app's default orientation flags can be found out via some API call(s).
|
||||
orientationFlags = (unsigned int)(DisplayOrientations::Landscape |
|
||||
DisplayOrientations::LandscapeFlipped |
|
||||
DisplayOrientations::Portrait |
|
||||
DisplayOrientations::PortraitFlipped);
|
||||
}
|
||||
|
||||
// Set the orientation/rotation preferences. Please note that this does
|
||||
// not constitute a 100%-certain lock of a given set of possible
|
||||
// orientations. According to Microsoft's documentation on WinRT [1]
|
||||
// when a device is not capable of being rotated, Windows may ignore
|
||||
// the orientation preferences, and stick to what the device is capable of
|
||||
// displaying.
|
||||
//
|
||||
// [1] Documentation on the 'InitialRotationPreference' setting for a
|
||||
// Windows app's manifest file describes how some orientation/rotation
|
||||
// preferences may be ignored. See
|
||||
// http://msdn.microsoft.com/en-us/library/windows/apps/hh700343.aspx
|
||||
// for details. Microsoft's "Display orientation sample" also gives an
|
||||
// outline of how Windows treats device rotation
|
||||
// (http://code.msdn.microsoft.com/Display-Orientation-Sample-19a58e93).
|
||||
WINRT_DISPLAY_PROPERTY(AutoRotationPreferences) = (DisplayOrientations)orientationFlags;
|
||||
}
|
||||
|
||||
int WINRT_VideoInit(SDL_VideoDevice *_this)
|
||||
{
|
||||
SDL_VideoData *driverdata = _this->driverdata;
|
||||
if (WINRT_InitModes(_this) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Register the hint, SDL_HINT_ORIENTATIONS, with SDL.
|
||||
// TODO, WinRT: see if an app's default orientation can be found out via WinRT API(s), then set the initial value of SDL_HINT_ORIENTATIONS accordingly.
|
||||
SDL_AddHintCallback(SDL_HINT_ORIENTATIONS, WINRT_SetDisplayOrientationsPreference, NULL);
|
||||
|
||||
WINRT_InitMouse(_this);
|
||||
WINRT_InitTouch(_this);
|
||||
WINRT_InitGameBar(_this);
|
||||
if (driverdata) {
|
||||
/* Initialize screensaver-disabling support */
|
||||
driverdata->displayRequest = WINRT_CreateDisplayRequest(_this);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" Uint32 D3D11_DXGIFormatToSDLPixelFormat(DXGI_FORMAT dxgiFormat);
|
||||
|
||||
static void WINRT_DXGIModeToSDLDisplayMode(const DXGI_MODE_DESC *dxgiMode, SDL_DisplayMode *sdlMode)
|
||||
{
|
||||
SDL_zerop(sdlMode);
|
||||
sdlMode->w = dxgiMode->Width;
|
||||
sdlMode->h = dxgiMode->Height;
|
||||
sdlMode->refresh_rate = (((100 * dxgiMode->RefreshRate.Numerator) / dxgiMode->RefreshRate.Denominator) / 100.0f);
|
||||
sdlMode->format = D3D11_DXGIFormatToSDLPixelFormat(dxgiMode->Format);
|
||||
}
|
||||
|
||||
static int WINRT_AddDisplaysForOutput(SDL_VideoDevice *_this, IDXGIAdapter1 *dxgiAdapter1, int outputIndex)
|
||||
{
|
||||
HRESULT hr;
|
||||
IDXGIOutput *dxgiOutput = NULL;
|
||||
DXGI_OUTPUT_DESC dxgiOutputDesc;
|
||||
SDL_VideoDisplay display;
|
||||
UINT numModes;
|
||||
DXGI_MODE_DESC *dxgiModes = NULL;
|
||||
int functionResult = -1; /* -1 for failure, 0 for success */
|
||||
DXGI_MODE_DESC modeToMatch, closestMatch;
|
||||
|
||||
SDL_zero(display);
|
||||
|
||||
hr = dxgiAdapter1->EnumOutputs(outputIndex, &dxgiOutput);
|
||||
if (FAILED(hr)) {
|
||||
if (hr != DXGI_ERROR_NOT_FOUND) {
|
||||
WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIAdapter1::EnumOutputs failed", hr);
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
|
||||
hr = dxgiOutput->GetDesc(&dxgiOutputDesc);
|
||||
if (FAILED(hr)) {
|
||||
WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIOutput::GetDesc failed", hr);
|
||||
goto done;
|
||||
}
|
||||
|
||||
SDL_zero(modeToMatch);
|
||||
modeToMatch.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
modeToMatch.Width = (dxgiOutputDesc.DesktopCoordinates.right - dxgiOutputDesc.DesktopCoordinates.left);
|
||||
modeToMatch.Height = (dxgiOutputDesc.DesktopCoordinates.bottom - dxgiOutputDesc.DesktopCoordinates.top);
|
||||
hr = dxgiOutput->FindClosestMatchingMode(&modeToMatch, &closestMatch, NULL);
|
||||
if (hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE) {
|
||||
/* DXGI_ERROR_NOT_CURRENTLY_AVAILABLE gets returned by IDXGIOutput::FindClosestMatchingMode
|
||||
when running under the Windows Simulator, which uses Remote Desktop (formerly known as Terminal
|
||||
Services) under the hood. According to the MSDN docs for the similar function,
|
||||
IDXGIOutput::GetDisplayModeList, DXGI_ERROR_NOT_CURRENTLY_AVAILABLE is returned if and
|
||||
when an app is run under a Terminal Services session, hence the assumption.
|
||||
|
||||
In this case, just add an SDL display mode, with approximated values.
|
||||
*/
|
||||
SDL_DisplayMode mode;
|
||||
SDL_zero(mode);
|
||||
display.name = SDL_strdup("Windows Simulator / Terminal Services Display");
|
||||
mode.w = (dxgiOutputDesc.DesktopCoordinates.right - dxgiOutputDesc.DesktopCoordinates.left);
|
||||
mode.h = (dxgiOutputDesc.DesktopCoordinates.bottom - dxgiOutputDesc.DesktopCoordinates.top);
|
||||
mode.format = DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
display.desktop_mode = mode;
|
||||
} else if (FAILED(hr)) {
|
||||
WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIOutput::FindClosestMatchingMode failed", hr);
|
||||
goto done;
|
||||
} else {
|
||||
display.name = WIN_StringToUTF8(dxgiOutputDesc.DeviceName);
|
||||
WINRT_DXGIModeToSDLDisplayMode(&closestMatch, &display.desktop_mode);
|
||||
|
||||
hr = dxgiOutput->GetDisplayModeList(DXGI_FORMAT_B8G8R8A8_UNORM, 0, &numModes, NULL);
|
||||
if (FAILED(hr)) {
|
||||
if (hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE) {
|
||||
// TODO, WinRT: make sure display mode(s) are added when using Terminal Services / Windows Simulator
|
||||
}
|
||||
WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIOutput::GetDisplayModeList [get mode list size] failed", hr);
|
||||
goto done;
|
||||
}
|
||||
|
||||
dxgiModes = (DXGI_MODE_DESC *)SDL_calloc(numModes, sizeof(DXGI_MODE_DESC));
|
||||
if (dxgiModes == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
goto done;
|
||||
}
|
||||
|
||||
hr = dxgiOutput->GetDisplayModeList(DXGI_FORMAT_B8G8R8A8_UNORM, 0, &numModes, dxgiModes);
|
||||
if (FAILED(hr)) {
|
||||
WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIOutput::GetDisplayModeList [get mode contents] failed", hr);
|
||||
goto done;
|
||||
}
|
||||
|
||||
for (UINT i = 0; i < numModes; ++i) {
|
||||
SDL_DisplayMode sdlMode;
|
||||
WINRT_DXGIModeToSDLDisplayMode(&dxgiModes[i], &sdlMode);
|
||||
SDL_AddFullscreenDisplayMode(&display, &sdlMode);
|
||||
}
|
||||
}
|
||||
|
||||
if (SDL_AddVideoDisplay(&display, SDL_FALSE) == 0) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
functionResult = 0; /* 0 for Success! */
|
||||
done:
|
||||
if (dxgiModes) {
|
||||
SDL_free(dxgiModes);
|
||||
}
|
||||
if (dxgiOutput) {
|
||||
dxgiOutput->Release();
|
||||
}
|
||||
if (display.name) {
|
||||
SDL_free(display.name);
|
||||
}
|
||||
return functionResult;
|
||||
}
|
||||
|
||||
static int WINRT_AddDisplaysForAdapter(SDL_VideoDevice *_this, IDXGIFactory2 *dxgiFactory2, int adapterIndex)
|
||||
{
|
||||
HRESULT hr;
|
||||
IDXGIAdapter1 *dxgiAdapter1;
|
||||
|
||||
hr = dxgiFactory2->EnumAdapters1(adapterIndex, &dxgiAdapter1);
|
||||
if (FAILED(hr)) {
|
||||
if (hr != DXGI_ERROR_NOT_FOUND) {
|
||||
WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIFactory1::EnumAdapters1() failed", hr);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (int outputIndex = 0;; ++outputIndex) {
|
||||
if (WINRT_AddDisplaysForOutput(_this, dxgiAdapter1, outputIndex) < 0) {
|
||||
/* HACK: The Windows App Certification Kit 10.0 can fail, when
|
||||
running the Store Apps' test, "Direct3D Feature Test". The
|
||||
certification kit's error is:
|
||||
|
||||
"Application App was not running at the end of the test. It likely crashed or was terminated for having become unresponsive."
|
||||
|
||||
This was caused by SDL/WinRT's DXGI failing to report any
|
||||
outputs. Attempts to get the 1st display-output from the
|
||||
1st display-adapter can fail, with IDXGIAdapter::EnumOutputs
|
||||
returning DXGI_ERROR_NOT_FOUND. This could be a bug in Windows,
|
||||
the Windows App Certification Kit, or possibly in SDL/WinRT's
|
||||
display detection code. Either way, try to detect when this
|
||||
happens, and use a hackish means to create a reasonable-as-possible
|
||||
'display mode'. -- DavidL
|
||||
*/
|
||||
if (adapterIndex == 0 && outputIndex == 0) {
|
||||
SDL_VideoDisplay display;
|
||||
SDL_DisplayMode mode;
|
||||
#if SDL_WINRT_USE_APPLICATIONVIEW
|
||||
ApplicationView ^ appView = ApplicationView::GetForCurrentView();
|
||||
#endif
|
||||
CoreWindow ^ coreWin = CoreWindow::GetForCurrentThread();
|
||||
SDL_zero(display);
|
||||
SDL_zero(mode);
|
||||
display.name = SDL_strdup("DXGI Display-detection Workaround");
|
||||
|
||||
/* HACK: ApplicationView's VisibleBounds property, appeared, via testing, to
|
||||
give a better approximation of display-size, than did CoreWindow's
|
||||
Bounds property, insofar that ApplicationView::VisibleBounds seems like
|
||||
it will, at least some of the time, give the full display size (during the
|
||||
failing test), whereas CoreWindow might not. -- DavidL
|
||||
*/
|
||||
|
||||
#if (NTDDI_VERSION >= NTDDI_WIN10) || (SDL_WINRT_USE_APPLICATIONVIEW && SDL_WINAPI_FAMILY_PHONE)
|
||||
mode.w = (int)SDL_floorf(appView->VisibleBounds.Width);
|
||||
mode.h = (int)SDL_floorf(appView->VisibleBounds.Height);
|
||||
#else
|
||||
/* On platform(s) that do not support VisibleBounds, such as Windows 8.1,
|
||||
fall back to CoreWindow's Bounds property.
|
||||
*/
|
||||
mode.w = (int)SDL_floorf(coreWin->Bounds.Width);
|
||||
mode.h = (int)SDL_floorf(coreWin->Bounds.Height);
|
||||
#endif
|
||||
mode.pixel_density = WINRT_DISPLAY_PROPERTY(LogicalDpi) / 96.0f;
|
||||
mode.format = DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
|
||||
display.desktop_mode = mode;
|
||||
bool error = (SDL_AddVideoDisplay(&display, SDL_FALSE) == 0);
|
||||
if (display.name) {
|
||||
SDL_free(display.name);
|
||||
}
|
||||
if (error) {
|
||||
return SDL_SetError("Failed to apply DXGI Display-detection workaround");
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
dxgiAdapter1->Release();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int WINRT_InitModes(SDL_VideoDevice *_this)
|
||||
{
|
||||
/* HACK: Initialize a single display, for whatever screen the app's
|
||||
CoreApplicationView is on.
|
||||
TODO, WinRT: Try initializing multiple displays, one for each monitor.
|
||||
Appropriate WinRT APIs for this seem elusive, though. -- DavidL
|
||||
*/
|
||||
|
||||
HRESULT hr;
|
||||
IDXGIFactory2 *dxgiFactory2 = NULL;
|
||||
|
||||
hr = CreateDXGIFactory1(SDL_IID_IDXGIFactory2, (void **)&dxgiFactory2);
|
||||
if (FAILED(hr)) {
|
||||
return WIN_SetErrorFromHRESULT(__FUNCTION__ ", CreateDXGIFactory1() failed", hr);
|
||||
}
|
||||
|
||||
for (int adapterIndex = 0;; ++adapterIndex) {
|
||||
if (WINRT_AddDisplaysForAdapter(_this, dxgiFactory2, adapterIndex) < 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int WINRT_SetDisplayMode(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_DisplayMode *mode)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void WINRT_VideoQuit(SDL_VideoDevice *_this)
|
||||
{
|
||||
SDL_VideoData *driverdata = _this->driverdata;
|
||||
if (driverdata && driverdata->displayRequest) {
|
||||
driverdata->displayRequest->Release();
|
||||
driverdata->displayRequest = NULL;
|
||||
}
|
||||
WINRT_QuitGameBar(_this);
|
||||
WINRT_QuitMouse(_this);
|
||||
}
|
||||
|
||||
static const Uint32 WINRT_DetectableFlags = SDL_WINDOW_MAXIMIZED | SDL_WINDOW_FULLSCREEN | SDL_WINDOW_HIDDEN | SDL_WINDOW_MOUSE_FOCUS;
|
||||
|
||||
extern "C" Uint32
|
||||
WINRT_DetectWindowFlags(SDL_Window *window)
|
||||
{
|
||||
Uint32 latestFlags = 0;
|
||||
SDL_WindowData *data = window->driverdata;
|
||||
bool is_fullscreen = false;
|
||||
|
||||
#if SDL_WINRT_USE_APPLICATIONVIEW
|
||||
if (data->appView) {
|
||||
is_fullscreen = data->appView->IsFullScreenMode;
|
||||
}
|
||||
#elif SDL_WINAPI_FAMILY_PHONE || NTDDI_VERSION == NTDDI_WIN8
|
||||
is_fullscreen = true;
|
||||
#endif
|
||||
|
||||
if (data->coreWindow.Get()) {
|
||||
if (is_fullscreen) {
|
||||
SDL_VideoDisplay *display = SDL_GetVideoDisplayForWindow(window);
|
||||
int w = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Width);
|
||||
int h = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Height);
|
||||
|
||||
#if !SDL_WINAPI_FAMILY_PHONE || NTDDI_VERSION > NTDDI_WIN8
|
||||
// On all WinRT platforms, except for WinPhone 8.0, rotate the
|
||||
// window size. This is needed to properly calculate
|
||||
// fullscreen vs. maximized.
|
||||
const DisplayOrientations currentOrientation = WINRT_DISPLAY_PROPERTY(CurrentOrientation);
|
||||
switch (currentOrientation) {
|
||||
#if SDL_WINAPI_FAMILY_PHONE
|
||||
case DisplayOrientations::Landscape:
|
||||
case DisplayOrientations::LandscapeFlipped:
|
||||
#else
|
||||
case DisplayOrientations::Portrait:
|
||||
case DisplayOrientations::PortraitFlipped:
|
||||
#endif
|
||||
{
|
||||
int tmp = w;
|
||||
w = h;
|
||||
h = tmp;
|
||||
} break;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (display->desktop_mode.w != w || display->desktop_mode.h != h) {
|
||||
latestFlags |= SDL_WINDOW_MAXIMIZED;
|
||||
} else {
|
||||
latestFlags |= SDL_WINDOW_FULLSCREEN;
|
||||
}
|
||||
}
|
||||
|
||||
if (data->coreWindow->Visible) {
|
||||
latestFlags &= ~SDL_WINDOW_HIDDEN;
|
||||
} else {
|
||||
latestFlags |= SDL_WINDOW_HIDDEN;
|
||||
}
|
||||
|
||||
#if SDL_WINAPI_FAMILY_PHONE && NTDDI_VERSION < NTDDI_WINBLUE
|
||||
// data->coreWindow->PointerPosition is not supported on WinPhone 8.0
|
||||
latestFlags |= SDL_WINDOW_MOUSE_FOCUS;
|
||||
#else
|
||||
if (data->coreWindow->Visible && data->coreWindow->Bounds.Contains(data->coreWindow->PointerPosition)) {
|
||||
latestFlags |= SDL_WINDOW_MOUSE_FOCUS;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return latestFlags;
|
||||
}
|
||||
|
||||
// TODO, WinRT: consider removing WINRT_UpdateWindowFlags, and just calling WINRT_DetectWindowFlags as-appropriate (with appropriate calls to SDL_SendWindowEvent)
|
||||
void WINRT_UpdateWindowFlags(SDL_Window *window, Uint32 mask)
|
||||
{
|
||||
mask &= WINRT_DetectableFlags;
|
||||
if (window) {
|
||||
Uint32 apply = WINRT_DetectWindowFlags(window);
|
||||
window->flags = (window->flags & ~mask) | (apply & mask);
|
||||
}
|
||||
}
|
||||
|
||||
static bool WINRT_IsCoreWindowActive(CoreWindow ^ coreWindow)
|
||||
{
|
||||
/* WinRT does not appear to offer API(s) to determine window-activation state,
|
||||
at least not that I am aware of in Win8 - Win10. As such, SDL tracks this
|
||||
itself, via window-activation events.
|
||||
|
||||
If there *is* an API to track this, it should probably get used instead
|
||||
of the following hack (that uses "SDLHelperWindowActivationState").
|
||||
-- DavidL.
|
||||
*/
|
||||
if (coreWindow->CustomProperties->HasKey("SDLHelperWindowActivationState")) {
|
||||
CoreWindowActivationState activationState =
|
||||
safe_cast<CoreWindowActivationState>(coreWindow->CustomProperties->Lookup("SDLHelperWindowActivationState"));
|
||||
return activationState != CoreWindowActivationState::Deactivated;
|
||||
}
|
||||
|
||||
/* Assume that non-SDL tracked windows are active, although this should
|
||||
probably be avoided, if possible.
|
||||
|
||||
This might not even be possible, in normal SDL use, at least as of
|
||||
this writing (Dec 22, 2015; via latest hg.libsdl.org/SDL clone) -- DavidL
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
int WINRT_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
{
|
||||
// Make sure that only one window gets created, at least until multimonitor
|
||||
// support is added.
|
||||
if (WINRT_GlobalSDLWindow != NULL) {
|
||||
return SDL_SetError("WinRT only supports one window");
|
||||
}
|
||||
|
||||
SDL_WindowData *data = new SDL_WindowData; /* use 'new' here as SDL_WindowData may use WinRT/C++ types */
|
||||
if (!data) {
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
window->driverdata = data;
|
||||
data->sdlWindow = window;
|
||||
|
||||
/* To note, when XAML support is enabled, access to the CoreWindow will not
|
||||
be possible, at least not via the SDL/XAML thread. Attempts to access it
|
||||
from there will throw exceptions. As such, the SDL_WindowData's
|
||||
'coreWindow' field will only be set (to a non-null value) if XAML isn't
|
||||
enabled.
|
||||
*/
|
||||
if (!WINRT_XAMLWasEnabled) {
|
||||
data->coreWindow = CoreWindow::GetForCurrentThread();
|
||||
#if SDL_WINRT_USE_APPLICATIONVIEW
|
||||
data->appView = ApplicationView::GetForCurrentView();
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Make note of the requested window flags, before they start getting changed. */
|
||||
const Uint32 requestedFlags = window->flags;
|
||||
|
||||
#ifdef SDL_VIDEO_OPENGL_EGL
|
||||
/* Setup the EGL surface, but only if OpenGL ES 2 was requested. */
|
||||
if (!(window->flags & SDL_WINDOW_OPENGL)) {
|
||||
/* OpenGL ES 2 wasn't requested. Don't set up an EGL surface. */
|
||||
data->egl_surface = EGL_NO_SURFACE;
|
||||
} else {
|
||||
/* OpenGL ES 2 was requested. Set up an EGL surface. */
|
||||
SDL_VideoData *video_data = _this->driverdata;
|
||||
|
||||
/* Call SDL_EGL_ChooseConfig and eglCreateWindowSurface directly,
|
||||
* rather than via SDL_EGL_CreateSurface, as older versions of
|
||||
* ANGLE/WinRT may require that a C++ object, ComPtr<IUnknown>,
|
||||
* be passed into eglCreateWindowSurface.
|
||||
*/
|
||||
if (SDL_EGL_ChooseConfig(_this) != 0) {
|
||||
/* SDL_EGL_ChooseConfig failed, SDL_GetError() should have info */
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (video_data->winrtEglWindow) { /* ... is the 'old' version of ANGLE/WinRT being used? */
|
||||
/* Attempt to create a window surface using older versions of
|
||||
* ANGLE/WinRT:
|
||||
*/
|
||||
Microsoft::WRL::ComPtr<IUnknown> cpp_winrtEglWindow = video_data->winrtEglWindow;
|
||||
data->egl_surface = ((eglCreateWindowSurface_Old_Function)_this->egl_data->eglCreateWindowSurface)(
|
||||
_this->egl_data->egl_display,
|
||||
_this->egl_data->egl_config,
|
||||
cpp_winrtEglWindow, NULL);
|
||||
if (data->egl_surface == NULL) {
|
||||
return SDL_EGL_SetError("unable to create EGL native-window surface", "eglCreateWindowSurface");
|
||||
}
|
||||
} else if (data->coreWindow.Get() != nullptr) {
|
||||
/* Attempt to create a window surface using newer versions of
|
||||
* ANGLE/WinRT:
|
||||
*/
|
||||
IInspectable *coreWindowAsIInspectable = reinterpret_cast<IInspectable *>(data->coreWindow.Get());
|
||||
data->egl_surface = _this->egl_data->eglCreateWindowSurface(
|
||||
_this->egl_data->egl_display,
|
||||
_this->egl_data->egl_config,
|
||||
(NativeWindowType)coreWindowAsIInspectable,
|
||||
NULL);
|
||||
if (data->egl_surface == NULL) {
|
||||
return SDL_EGL_SetError("unable to create EGL native-window surface", "eglCreateWindowSurface");
|
||||
}
|
||||
} else {
|
||||
return SDL_SetError("No supported means to create an EGL window surface are available");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Determine as many flags dynamically, as possible. */
|
||||
window->flags =
|
||||
SDL_WINDOW_BORDERLESS |
|
||||
SDL_WINDOW_RESIZABLE;
|
||||
|
||||
#ifdef SDL_VIDEO_OPENGL_EGL
|
||||
if (data->egl_surface) {
|
||||
window->flags |= SDL_WINDOW_OPENGL;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (WINRT_XAMLWasEnabled) {
|
||||
/* TODO, WinRT: set SDL_Window size, maybe position too, from XAML control */
|
||||
window->x = 0;
|
||||
window->y = 0;
|
||||
window->flags &= ~SDL_WINDOW_HIDDEN;
|
||||
SDL_SetMouseFocus(NULL); // TODO: detect this
|
||||
SDL_SetKeyboardFocus(NULL); // TODO: detect this
|
||||
} else {
|
||||
/* WinRT 8.x apps seem to live in an environment where the OS controls the
|
||||
app's window size, with some apps being fullscreen, depending on
|
||||
user choice of various things. For now, just adapt the SDL_Window to
|
||||
whatever Windows set-up as the native-window's geometry.
|
||||
*/
|
||||
window->x = (int)SDL_lroundf(data->coreWindow->Bounds.Left);
|
||||
window->y = (int)SDL_lroundf(data->coreWindow->Bounds.Top);
|
||||
#if NTDDI_VERSION < NTDDI_WIN10
|
||||
/* On WinRT 8.x / pre-Win10, just use the size we were given. */
|
||||
window->w = (int)SDL_floorf(data->coreWindow->Bounds.Width);
|
||||
window->h = (int)SDL_floorf(data->coreWindow->Bounds.Height);
|
||||
#else
|
||||
/* On Windows 10, we occasionally get control over window size. For windowed
|
||||
mode apps, try this.
|
||||
*/
|
||||
bool didSetSize = false;
|
||||
if ((requestedFlags & SDL_WINDOW_FULLSCREEN) == 0) {
|
||||
const Windows::Foundation::Size size((float)window->w, (float)window->h);
|
||||
didSetSize = data->appView->TryResizeView(size);
|
||||
}
|
||||
if (!didSetSize) {
|
||||
/* We either weren't able to set the window size, or a request for
|
||||
fullscreen was made. Get window-size info from the OS.
|
||||
*/
|
||||
window->w = (int)SDL_floorf(data->coreWindow->Bounds.Width);
|
||||
window->h = (int)SDL_floorf(data->coreWindow->Bounds.Height);
|
||||
}
|
||||
#endif
|
||||
|
||||
WINRT_UpdateWindowFlags(
|
||||
window,
|
||||
0xffffffff /* Update any window flag(s) that WINRT_UpdateWindow can handle */
|
||||
);
|
||||
|
||||
/* Try detecting if the window is active */
|
||||
bool isWindowActive = WINRT_IsCoreWindowActive(data->coreWindow.Get());
|
||||
if (isWindowActive) {
|
||||
SDL_SetKeyboardFocus(window);
|
||||
}
|
||||
}
|
||||
|
||||
/* Make sure the WinRT app's IFramworkView can post events on
|
||||
behalf of SDL:
|
||||
*/
|
||||
WINRT_GlobalSDLWindow = window;
|
||||
|
||||
/* All done! */
|
||||
return 0;
|
||||
}
|
||||
|
||||
void WINRT_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
{
|
||||
#if NTDDI_VERSION >= NTDDI_WIN10
|
||||
SDL_WindowData *data = window->driverdata;
|
||||
const Windows::Foundation::Size size((float)window->w, (float)window->h);
|
||||
data->appView->TryResizeView(size); // TODO, WinRT: return failure (to caller?) from TryResizeView()
|
||||
#endif
|
||||
}
|
||||
|
||||
void WINRT_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen)
|
||||
{
|
||||
#if NTDDI_VERSION >= NTDDI_WIN10
|
||||
SDL_WindowData *data = window->driverdata;
|
||||
bool isWindowActive = WINRT_IsCoreWindowActive(data->coreWindow.Get());
|
||||
if (isWindowActive) {
|
||||
if (fullscreen) {
|
||||
if (!data->appView->IsFullScreenMode) {
|
||||
data->appView->TryEnterFullScreenMode(); // TODO, WinRT: return failure (to caller?) from TryEnterFullScreenMode()
|
||||
}
|
||||
} else {
|
||||
if (data->appView->IsFullScreenMode) {
|
||||
data->appView->ExitFullScreenMode();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void WINRT_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
{
|
||||
SDL_WindowData *data = window->driverdata;
|
||||
|
||||
if (WINRT_GlobalSDLWindow == window) {
|
||||
WINRT_GlobalSDLWindow = NULL;
|
||||
}
|
||||
|
||||
if (data) {
|
||||
// Delete the internal window data:
|
||||
delete data;
|
||||
data = NULL;
|
||||
window->driverdata = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int WINRT_GetWindowWMInfo(SDL_VideoDevice *_this, SDL_Window *window, SDL_SysWMinfo *info)
|
||||
{
|
||||
SDL_WindowData *data = window->driverdata;
|
||||
|
||||
info->subsystem = SDL_SYSWM_WINRT;
|
||||
info->info.winrt.window = reinterpret_cast<IInspectable *>(data->coreWindow.Get());
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ABI::Windows::System::Display::IDisplayRequest *WINRT_CreateDisplayRequest(SDL_VideoDevice *_this)
|
||||
{
|
||||
/* Setup a WinRT DisplayRequest object, usable for enabling/disabling screensaver requests */
|
||||
const wchar_t *wClassName = L"Windows.System.Display.DisplayRequest";
|
||||
HSTRING hClassName;
|
||||
IActivationFactory *pActivationFactory = NULL;
|
||||
IInspectable *pDisplayRequestRaw = nullptr;
|
||||
ABI::Windows::System::Display::IDisplayRequest *pDisplayRequest = nullptr;
|
||||
HRESULT hr;
|
||||
|
||||
hr = ::WindowsCreateString(wClassName, (UINT32)SDL_wcslen(wClassName), &hClassName);
|
||||
if (FAILED(hr)) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
hr = Windows::Foundation::GetActivationFactory(hClassName, &pActivationFactory);
|
||||
if (FAILED(hr)) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
hr = pActivationFactory->ActivateInstance(&pDisplayRequestRaw);
|
||||
if (FAILED(hr)) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
hr = pDisplayRequestRaw->QueryInterface(SDL_IID_IDisplayRequest, (void **)&pDisplayRequest);
|
||||
if (FAILED(hr)) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
done:
|
||||
if (pDisplayRequestRaw) {
|
||||
pDisplayRequestRaw->Release();
|
||||
}
|
||||
if (pActivationFactory) {
|
||||
pActivationFactory->Release();
|
||||
}
|
||||
if (hClassName) {
|
||||
::WindowsDeleteString(hClassName);
|
||||
}
|
||||
|
||||
return pDisplayRequest;
|
||||
}
|
||||
|
||||
int WINRT_SuspendScreenSaver(SDL_VideoDevice *_this)
|
||||
{
|
||||
SDL_VideoData *driverdata = _this->driverdata;
|
||||
if (driverdata && driverdata->displayRequest) {
|
||||
ABI::Windows::System::Display::IDisplayRequest *displayRequest = (ABI::Windows::System::Display::IDisplayRequest *)driverdata->displayRequest;
|
||||
if (_this->suspend_screensaver) {
|
||||
displayRequest->RequestActive();
|
||||
} else {
|
||||
displayRequest->RequestRelease();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_WINRT */
|
105
external/sdl/SDL/src/video/winrt/SDL_winrtvideo_cpp.h
vendored
Normal file
105
external/sdl/SDL/src/video/winrt/SDL_winrtvideo_cpp.h
vendored
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/* Windows includes: */
|
||||
#include <windows.h>
|
||||
#ifdef __cplusplus_winrt
|
||||
#include <agile.h>
|
||||
#endif
|
||||
|
||||
/* SDL includes: */
|
||||
|
||||
#if NTDDI_VERSION >= NTDDI_WINBLUE /* ApplicationView's functionality only becomes \
|
||||
useful for SDL in Win[Phone] 8.1 and up. \
|
||||
Plus, it is not available at all in WinPhone 8.0. */
|
||||
#define SDL_WINRT_USE_APPLICATIONVIEW 1
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
#include "../SDL_sysvideo.h"
|
||||
#include "../SDL_egl_c.h"
|
||||
}
|
||||
|
||||
/* Private display data */
|
||||
struct SDL_VideoData
|
||||
{
|
||||
/* An object created by ANGLE/WinRT (OpenGL ES 2 for WinRT) that gets
|
||||
* passed to eglGetDisplay and eglCreateWindowSurface:
|
||||
*/
|
||||
IUnknown *winrtEglWindow;
|
||||
|
||||
/* Event token(s), for unregistering WinRT event handler(s).
|
||||
These are just a struct with a 64-bit integer inside them
|
||||
*/
|
||||
Windows::Foundation::EventRegistrationToken gameBarIsInputRedirectedToken;
|
||||
|
||||
/* A WinRT DisplayRequest, used for implementing SDL_*ScreenSaver() functions.
|
||||
* This is really a pointer to a 'ABI::Windows::System::Display::IDisplayRequest *',
|
||||
* It's casted to 'IUnknown *', to help with building SDL.
|
||||
*/
|
||||
IUnknown *displayRequest;
|
||||
};
|
||||
|
||||
/* The global, WinRT, SDL Window.
|
||||
For now, SDL/WinRT only supports one window (due to platform limitations of
|
||||
WinRT.
|
||||
*/
|
||||
extern SDL_Window *WINRT_GlobalSDLWindow;
|
||||
|
||||
/* Updates one or more SDL_Window flags, by querying the OS' native windowing APIs.
|
||||
SDL_Window flags that can be updated should be specified in 'mask'.
|
||||
*/
|
||||
extern void WINRT_UpdateWindowFlags(SDL_Window *window, Uint32 mask);
|
||||
extern "C" Uint32 WINRT_DetectWindowFlags(SDL_Window *window); /* detects flags w/o applying them */
|
||||
|
||||
/* Display mode internals */
|
||||
// typedef struct
|
||||
//{
|
||||
// Windows::Graphics::Display::DisplayOrientations currentOrientation;
|
||||
// } SDL_DisplayModeData;
|
||||
|
||||
#ifdef __cplusplus_winrt
|
||||
|
||||
/* A convenience macro to get a WinRT display property */
|
||||
#if NTDDI_VERSION > NTDDI_WIN8
|
||||
#define WINRT_DISPLAY_PROPERTY(NAME) (Windows::Graphics::Display::DisplayInformation::GetForCurrentView()->NAME)
|
||||
#else
|
||||
#define WINRT_DISPLAY_PROPERTY(NAME) (Windows::Graphics::Display::DisplayProperties::NAME)
|
||||
#endif
|
||||
|
||||
/* Converts DIPS to/from physical pixels */
|
||||
#define WINRT_DIPS_TO_PHYSICAL_PIXELS(DIPS) ((int)(0.5f + (((float)(DIPS) * (float)WINRT_DISPLAY_PROPERTY(LogicalDpi)) / 96.f)))
|
||||
#define WINRT_PHYSICAL_PIXELS_TO_DIPS(PHYSPIX) (((float)(PHYSPIX)*96.f) / WINRT_DISPLAY_PROPERTY(LogicalDpi))
|
||||
|
||||
/* Internal window data */
|
||||
struct SDL_WindowData
|
||||
{
|
||||
SDL_Window *sdlWindow;
|
||||
Platform::Agile<Windows::UI::Core::CoreWindow> coreWindow;
|
||||
#ifdef SDL_VIDEO_OPENGL_EGL
|
||||
EGLSurface egl_surface;
|
||||
#endif
|
||||
#if SDL_WINRT_USE_APPLICATIONVIEW
|
||||
Windows::UI::ViewManagement::ApplicationView ^ appView;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // ifdef __cplusplus_winrt
|
Reference in New Issue
Block a user