diff --git a/VisualC-WinRT/UWP_VS2015/SDL-UWP.vcxproj b/VisualC-WinRT/UWP_VS2015/SDL-UWP.vcxproj index 305a3ca5f..998040ff3 100644 --- a/VisualC-WinRT/UWP_VS2015/SDL-UWP.vcxproj +++ b/VisualC-WinRT/UWP_VS2015/SDL-UWP.vcxproj @@ -156,6 +156,7 @@ + @@ -311,6 +312,14 @@ true true + + true + true + true + true + true + true + true true diff --git a/VisualC-WinRT/UWP_VS2015/SDL-UWP.vcxproj.filters b/VisualC-WinRT/UWP_VS2015/SDL-UWP.vcxproj.filters index b8c6d712d..652c04172 100644 --- a/VisualC-WinRT/UWP_VS2015/SDL-UWP.vcxproj.filters +++ b/VisualC-WinRT/UWP_VS2015/SDL-UWP.vcxproj.filters @@ -402,6 +402,9 @@ Source Files + + Source Files + @@ -716,5 +719,8 @@ Source Files + + Source Files + \ No newline at end of file diff --git a/VisualC-WinRT/WinPhone80_VS2012/SDL-WinPhone80.vcxproj b/VisualC-WinRT/WinPhone80_VS2012/SDL-WinPhone80.vcxproj index 3776d2433..469e5c67c 100644 --- a/VisualC-WinRT/WinPhone80_VS2012/SDL-WinPhone80.vcxproj +++ b/VisualC-WinRT/WinPhone80_VS2012/SDL-WinPhone80.vcxproj @@ -273,6 +273,7 @@ + @@ -408,6 +409,12 @@ true true + + true + true + true + true + true true diff --git a/VisualC-WinRT/WinPhone80_VS2012/SDL-WinPhone80.vcxproj.filters b/VisualC-WinRT/WinPhone80_VS2012/SDL-WinPhone80.vcxproj.filters index 1f4df44e4..c3c309cd3 100644 --- a/VisualC-WinRT/WinPhone80_VS2012/SDL-WinPhone80.vcxproj.filters +++ b/VisualC-WinRT/WinPhone80_VS2012/SDL-WinPhone80.vcxproj.filters @@ -372,6 +372,9 @@ Source Files + + Source Files + @@ -674,5 +677,8 @@ Source Files + + Source Files + \ No newline at end of file diff --git a/VisualC-WinRT/WinPhone81_VS2013/SDL-WinPhone81.vcxproj b/VisualC-WinRT/WinPhone81_VS2013/SDL-WinPhone81.vcxproj index 573bc4286..29a7adac6 100644 --- a/VisualC-WinRT/WinPhone81_VS2013/SDL-WinPhone81.vcxproj +++ b/VisualC-WinRT/WinPhone81_VS2013/SDL-WinPhone81.vcxproj @@ -139,6 +139,7 @@ + @@ -275,6 +276,12 @@ true true + + true + true + true + true + true true diff --git a/VisualC-WinRT/WinPhone81_VS2013/SDL-WinPhone81.vcxproj.filters b/VisualC-WinRT/WinPhone81_VS2013/SDL-WinPhone81.vcxproj.filters index 907e1bfb7..d96e06e70 100644 --- a/VisualC-WinRT/WinPhone81_VS2013/SDL-WinPhone81.vcxproj.filters +++ b/VisualC-WinRT/WinPhone81_VS2013/SDL-WinPhone81.vcxproj.filters @@ -381,6 +381,9 @@ Source Files + + Source Files + @@ -686,5 +689,8 @@ Source Files + + Source Files + \ No newline at end of file diff --git a/VisualC-WinRT/WinRT80_VS2012/SDL-WinRT80.vcxproj b/VisualC-WinRT/WinRT80_VS2012/SDL-WinRT80.vcxproj index fbcd94b6b..0ad0cc014 100644 --- a/VisualC-WinRT/WinRT80_VS2012/SDL-WinRT80.vcxproj +++ b/VisualC-WinRT/WinRT80_VS2012/SDL-WinRT80.vcxproj @@ -175,6 +175,14 @@ true true + + true + true + true + true + true + true + true true @@ -353,6 +361,7 @@ + diff --git a/VisualC-WinRT/WinRT80_VS2012/SDL-WinRT80.vcxproj.filters b/VisualC-WinRT/WinRT80_VS2012/SDL-WinRT80.vcxproj.filters index aa539d37e..6ad1ef486 100644 --- a/VisualC-WinRT/WinRT80_VS2012/SDL-WinRT80.vcxproj.filters +++ b/VisualC-WinRT/WinRT80_VS2012/SDL-WinRT80.vcxproj.filters @@ -316,6 +316,9 @@ Source Files + + Source Files + @@ -714,6 +717,9 @@ Source Files + + Source Files + diff --git a/VisualC-WinRT/WinRT81_VS2013/SDL-WinRT81.vcxproj b/VisualC-WinRT/WinRT81_VS2013/SDL-WinRT81.vcxproj index a56516ead..88093b7e2 100644 --- a/VisualC-WinRT/WinRT81_VS2013/SDL-WinRT81.vcxproj +++ b/VisualC-WinRT/WinRT81_VS2013/SDL-WinRT81.vcxproj @@ -153,6 +153,7 @@ + @@ -309,6 +310,14 @@ true true + + true + true + true + true + true + true + true true diff --git a/VisualC-WinRT/WinRT81_VS2013/SDL-WinRT81.vcxproj.filters b/VisualC-WinRT/WinRT81_VS2013/SDL-WinRT81.vcxproj.filters index a36811dd4..20f7423cc 100644 --- a/VisualC-WinRT/WinRT81_VS2013/SDL-WinRT81.vcxproj.filters +++ b/VisualC-WinRT/WinRT81_VS2013/SDL-WinRT81.vcxproj.filters @@ -393,6 +393,9 @@ Source Files + + Source Files + @@ -710,5 +713,8 @@ Source Files + + Source Files + \ No newline at end of file diff --git a/src/video/winrt/SDL_winrtgamebar.cpp b/src/video/winrt/SDL_winrtgamebar.cpp new file mode 100644 index 000000000..215dfcc83 --- /dev/null +++ b/src/video/winrt/SDL_winrtgamebar.cpp @@ -0,0 +1,196 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2016 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_VIDEO_DRIVER_WINRT + +/* Windows includes */ +#include +#include +#include + + +/* SDL includes */ +extern "C" { +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" +} +#include "SDL_winrtvideo_cpp.h" + + +/* Game Bar events can come in off the main thread. Use the following + WinRT CoreDispatcher to deal with them on SDL's thread. +*/ +static Platform::WeakReference WINRT_MainThreadDispatcher; + + +/* Win10's initial SDK (the 10.0.10240.0 release) does not include references + to Game Bar APIs, as the Game Bar was released via Win10 10.0.10586.0. + + Declare its WinRT/COM interface here, to allow compilation with earlier + Windows SDKs. +*/ +MIDL_INTERFACE("1DB9A292-CC78-4173-BE45-B61E67283EA7") +IGameBarStatics_ : public IInspectable +{ +public: + virtual HRESULT STDMETHODCALLTYPE add_VisibilityChanged( + __FIEventHandler_1_IInspectable *handler, + Windows::Foundation::EventRegistrationToken *token) = 0; + + virtual HRESULT STDMETHODCALLTYPE remove_VisibilityChanged( + Windows::Foundation::EventRegistrationToken token) = 0; + + virtual HRESULT STDMETHODCALLTYPE add_IsInputRedirectedChanged( + __FIEventHandler_1_IInspectable *handler, + Windows::Foundation::EventRegistrationToken *token) = 0; + + virtual HRESULT STDMETHODCALLTYPE remove_IsInputRedirectedChanged( + Windows::Foundation::EventRegistrationToken token) = 0; + + virtual HRESULT STDMETHODCALLTYPE get_Visible( + boolean *value) = 0; + + virtual HRESULT STDMETHODCALLTYPE get_IsInputRedirected( + boolean *value) = 0; +}; + +/* Declare the game bar's COM GUID */ +static GUID IID_IGameBarStatics_ = { MAKELONG(0xA292, 0x1DB9), 0xCC78, 0x4173, { 0xBE, 0x45, 0xB6, 0x1E, 0x67, 0x28, 0x3E, 0xA7 } }; + +/* Retrieves a pointer to the game bar, or NULL if it is not available. + If a pointer is returned, it's ->Release() method must be called + after the caller has finished using it. +*/ +static IGameBarStatics_ * +WINRT_GetGameBar() +{ + wchar_t *wClassName = L"Windows.Gaming.UI.GameBar"; + HSTRING hClassName; + IActivationFactory *pActivationFactory = NULL; + IGameBarStatics_ *pGameBar = NULL; + HRESULT hr; + + hr = ::WindowsCreateString(wClassName, (UINT32)wcslen(wClassName), &hClassName); + if (FAILED(hr)) { + goto done; + } + + hr = Windows::Foundation::GetActivationFactory(hClassName, &pActivationFactory); + if (FAILED(hr)) { + goto done; + } + + pActivationFactory->QueryInterface(IID_IGameBarStatics_, (void **) &pGameBar); + +done: + if (pActivationFactory) { + pActivationFactory->Release(); + } + if (hClassName) { + ::WindowsDeleteString(hClassName); + } + return pGameBar; +} + +static void +WINRT_HandleGameBarIsInputRedirected_MainThread() +{ + IGameBarStatics_ *gameBar; + boolean isInputRedirected = 0; + if (!WINRT_MainThreadDispatcher) { + /* The game bar event handler has been deregistered! */ + return; + } + gameBar = WINRT_GetGameBar(); + if (!gameBar) { + /* Shouldn't happen, but just in case... */ + return; + } + if (SUCCEEDED(gameBar->get_IsInputRedirected(&isInputRedirected))) { + if ( ! isInputRedirected) { + /* Input-control is now back to the SDL app. Restore the cursor, + in case Windows does not (it does not in either Win10 + 10.0.10240.0 or 10.0.10586.0, maybe later version(s) too. + */ + SDL_Cursor *cursor = SDL_GetCursor(); + SDL_SetCursor(cursor); + } + } + gameBar->Release(); +} + +static void +WINRT_HandleGameBarIsInputRedirected_NonMainThread(Platform::Object ^ o1, Platform::Object ^o2) +{ + Windows::UI::Core::CoreDispatcher ^dispatcher = WINRT_MainThreadDispatcher.Resolve(); + if (dispatcher) { + dispatcher->RunAsync( + Windows::UI::Core::CoreDispatcherPriority::Normal, + ref new Windows::UI::Core::DispatchedHandler(&WINRT_HandleGameBarIsInputRedirected_MainThread)); + } +} + +void +WINRT_InitGameBar(_THIS) +{ + SDL_VideoData *driverdata = (SDL_VideoData *)_this->driverdata; + IGameBarStatics_ *gameBar = WINRT_GetGameBar(); + if (gameBar) { + /* GameBar.IsInputRedirected events can come in via something other than + the main/SDL thread. + + Get a WinRT 'CoreDispatcher' that can be used to call back into the + SDL thread. + */ + WINRT_MainThreadDispatcher = Windows::UI::Core::CoreWindow::GetForCurrentThread()->Dispatcher; + Windows::Foundation::EventHandler ^handler = \ + ref new Windows::Foundation::EventHandler(&WINRT_HandleGameBarIsInputRedirected_NonMainThread); + __FIEventHandler_1_IInspectable * pHandler = reinterpret_cast<__FIEventHandler_1_IInspectable *>(handler); + gameBar->add_IsInputRedirectedChanged(pHandler, &driverdata->gameBarIsInputRedirectedToken); + gameBar->Release(); + } +} + +void +WINRT_QuitGameBar(_THIS) +{ + SDL_VideoData *driverdata; + IGameBarStatics_ *gameBar; + if (!_this || !_this->driverdata) { + return; + } + gameBar = WINRT_GetGameBar(); + if (!gameBar) { + return; + } + driverdata = (SDL_VideoData *)_this->driverdata; + if (driverdata->gameBarIsInputRedirectedToken.Value) { + gameBar->remove_IsInputRedirectedChanged(driverdata->gameBarIsInputRedirectedToken); + driverdata->gameBarIsInputRedirectedToken.Value = 0; + } + WINRT_MainThreadDispatcher = nullptr; + gameBar->Release(); +} + +#endif /* SDL_VIDEO_DRIVER_WINRT */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/winrt/SDL_winrtgamebar_cpp.h b/src/video/winrt/SDL_winrtgamebar_cpp.h new file mode 100644 index 000000000..afcef37b2 --- /dev/null +++ b/src/video/winrt/SDL_winrtgamebar_cpp.h @@ -0,0 +1,35 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2016 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "SDL_config.h" + +#ifndef _SDL_winrtgamebar_h +#define _SDL_winrtgamebar_h + +#ifdef __cplusplus +/* These are exported as C++ functions, rather than C, to fix a compilation + bug with MSVC 2013, for Windows 8.x builds. */ +extern void WINRT_InitGameBar(_THIS); +extern void WINRT_QuitGameBar(_THIS); +#endif + +#endif /* _SDL_winrtmouse_h */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/winrt/SDL_winrtvideo.cpp b/src/video/winrt/SDL_winrtvideo.cpp index 4a936df24..e4c29a456 100644 --- a/src/video/winrt/SDL_winrtvideo.cpp +++ b/src/video/winrt/SDL_winrtvideo.cpp @@ -61,6 +61,7 @@ extern "C" { #include "../../core/winrt/SDL_winrtapp_xaml.h" #include "SDL_winrtvideo_cpp.h" #include "SDL_winrtevents_c.h" +#include "SDL_winrtgamebar_cpp.h" #include "SDL_winrtmouse_c.h" #include "SDL_main.h" #include "SDL_system.h" @@ -177,6 +178,7 @@ WINRT_VideoInit(_THIS) } WINRT_InitMouse(_this); WINRT_InitTouch(_this); + WINRT_InitGameBar(_this); return 0; } @@ -419,6 +421,7 @@ WINRT_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode) void WINRT_VideoQuit(_THIS) { + WINRT_QuitGameBar(_this); WINRT_QuitMouse(_this); } diff --git a/src/video/winrt/SDL_winrtvideo_cpp.h b/src/video/winrt/SDL_winrtvideo_cpp.h index 26eb008d4..da5f6abeb 100644 --- a/src/video/winrt/SDL_winrtvideo_cpp.h +++ b/src/video/winrt/SDL_winrtvideo_cpp.h @@ -46,6 +46,11 @@ typedef struct SDL_VideoData { * 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; } SDL_VideoData; /* The global, WinRT, SDL Window.