mirror of
https://github.com/Relintai/sdl2_frt.git
synced 2024-12-29 20:27:12 +01:00
197 lines
6.5 KiB
C++
197 lines
6.5 KiB
C++
/*
|
|
Simple DirectMedia Layer
|
|
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
|
|
|
This software is provided 'as-is', without any express or implied
|
|
warranty. In no event will the authors be held liable for any damages
|
|
arising from the use of this software.
|
|
|
|
Permission is granted to anyone to use this software for any purpose,
|
|
including commercial applications, and to alter it and redistribute it
|
|
freely, subject to the following restrictions:
|
|
|
|
1. The origin of this software must not be misrepresented; you must not
|
|
claim that you wrote the original software. If you use this software
|
|
in a product, an acknowledgment in the product documentation would be
|
|
appreciated but is not required.
|
|
2. Altered source versions must be plainly marked as such, and must not be
|
|
misrepresented as being the original software.
|
|
3. This notice may not be removed or altered from any source distribution.
|
|
*/
|
|
#include "../../SDL_internal.h"
|
|
|
|
#if SDL_VIDEO_DRIVER_WINRT
|
|
|
|
/* Windows includes */
|
|
#include <roapi.h>
|
|
#include <windows.foundation.h>
|
|
#include <EventToken.h>
|
|
|
|
|
|
/* SDL includes */
|
|
extern "C" {
|
|
#include "SDL_mouse.h"
|
|
#include "../SDL_sysvideo.h"
|
|
}
|
|
#include "SDL_winrtvideo_cpp.h"
|
|
|
|
|
|
/* Game Bar events can come in off the main thread. Use the following
|
|
WinRT CoreDispatcher to deal with them on SDL's thread.
|
|
*/
|
|
static Platform::WeakReference WINRT_MainThreadDispatcher;
|
|
|
|
|
|
/* Win10's initial SDK (the 10.0.10240.0 release) does not include references
|
|
to Game Bar APIs, as the Game Bar was released via Win10 10.0.10586.0.
|
|
|
|
Declare its WinRT/COM interface here, to allow compilation with earlier
|
|
Windows SDKs.
|
|
*/
|
|
MIDL_INTERFACE("1DB9A292-CC78-4173-BE45-B61E67283EA7")
|
|
IGameBarStatics_ : public IInspectable
|
|
{
|
|
public:
|
|
virtual HRESULT STDMETHODCALLTYPE add_VisibilityChanged(
|
|
__FIEventHandler_1_IInspectable *handler,
|
|
Windows::Foundation::EventRegistrationToken *token) = 0;
|
|
|
|
virtual HRESULT STDMETHODCALLTYPE remove_VisibilityChanged(
|
|
Windows::Foundation::EventRegistrationToken token) = 0;
|
|
|
|
virtual HRESULT STDMETHODCALLTYPE add_IsInputRedirectedChanged(
|
|
__FIEventHandler_1_IInspectable *handler,
|
|
Windows::Foundation::EventRegistrationToken *token) = 0;
|
|
|
|
virtual HRESULT STDMETHODCALLTYPE remove_IsInputRedirectedChanged(
|
|
Windows::Foundation::EventRegistrationToken token) = 0;
|
|
|
|
virtual HRESULT STDMETHODCALLTYPE get_Visible(
|
|
boolean *value) = 0;
|
|
|
|
virtual HRESULT STDMETHODCALLTYPE get_IsInputRedirected(
|
|
boolean *value) = 0;
|
|
};
|
|
|
|
/* Declare the game bar's COM GUID */
|
|
static GUID IID_IGameBarStatics_ = { MAKELONG(0xA292, 0x1DB9), 0xCC78, 0x4173, { 0xBE, 0x45, 0xB6, 0x1E, 0x67, 0x28, 0x3E, 0xA7 } };
|
|
|
|
/* Retrieves a pointer to the game bar, or NULL if it is not available.
|
|
If a pointer is returned, it's ->Release() method must be called
|
|
after the caller has finished using it.
|
|
*/
|
|
static IGameBarStatics_ *
|
|
WINRT_GetGameBar()
|
|
{
|
|
wchar_t *wClassName = L"Windows.Gaming.UI.GameBar";
|
|
HSTRING hClassName;
|
|
IActivationFactory *pActivationFactory = NULL;
|
|
IGameBarStatics_ *pGameBar = NULL;
|
|
HRESULT hr;
|
|
|
|
hr = ::WindowsCreateString(wClassName, (UINT32)wcslen(wClassName), &hClassName);
|
|
if (FAILED(hr)) {
|
|
goto done;
|
|
}
|
|
|
|
hr = Windows::Foundation::GetActivationFactory(hClassName, &pActivationFactory);
|
|
if (FAILED(hr)) {
|
|
goto done;
|
|
}
|
|
|
|
pActivationFactory->QueryInterface(IID_IGameBarStatics_, (void **) &pGameBar);
|
|
|
|
done:
|
|
if (pActivationFactory) {
|
|
pActivationFactory->Release();
|
|
}
|
|
if (hClassName) {
|
|
::WindowsDeleteString(hClassName);
|
|
}
|
|
return pGameBar;
|
|
}
|
|
|
|
static void
|
|
WINRT_HandleGameBarIsInputRedirected_MainThread()
|
|
{
|
|
IGameBarStatics_ *gameBar;
|
|
boolean isInputRedirected = 0;
|
|
if (!WINRT_MainThreadDispatcher) {
|
|
/* The game bar event handler has been deregistered! */
|
|
return;
|
|
}
|
|
gameBar = WINRT_GetGameBar();
|
|
if (!gameBar) {
|
|
/* Shouldn't happen, but just in case... */
|
|
return;
|
|
}
|
|
if (SUCCEEDED(gameBar->get_IsInputRedirected(&isInputRedirected))) {
|
|
if ( ! isInputRedirected) {
|
|
/* Input-control is now back to the SDL app. Restore the cursor,
|
|
in case Windows does not (it does not in either Win10
|
|
10.0.10240.0 or 10.0.10586.0, maybe later version(s) too.
|
|
*/
|
|
SDL_Cursor *cursor = SDL_GetCursor();
|
|
SDL_SetCursor(cursor);
|
|
}
|
|
}
|
|
gameBar->Release();
|
|
}
|
|
|
|
static void
|
|
WINRT_HandleGameBarIsInputRedirected_NonMainThread(Platform::Object ^ o1, Platform::Object ^o2)
|
|
{
|
|
Windows::UI::Core::CoreDispatcher ^dispatcher = WINRT_MainThreadDispatcher.Resolve<Windows::UI::Core::CoreDispatcher>();
|
|
if (dispatcher) {
|
|
dispatcher->RunAsync(
|
|
Windows::UI::Core::CoreDispatcherPriority::Normal,
|
|
ref new Windows::UI::Core::DispatchedHandler(&WINRT_HandleGameBarIsInputRedirected_MainThread));
|
|
}
|
|
}
|
|
|
|
void
|
|
WINRT_InitGameBar(_THIS)
|
|
{
|
|
SDL_VideoData *driverdata = (SDL_VideoData *)_this->driverdata;
|
|
IGameBarStatics_ *gameBar = WINRT_GetGameBar();
|
|
if (gameBar) {
|
|
/* GameBar.IsInputRedirected events can come in via something other than
|
|
the main/SDL thread.
|
|
|
|
Get a WinRT 'CoreDispatcher' that can be used to call back into the
|
|
SDL thread.
|
|
*/
|
|
WINRT_MainThreadDispatcher = Windows::UI::Core::CoreWindow::GetForCurrentThread()->Dispatcher;
|
|
Windows::Foundation::EventHandler<Platform::Object ^> ^handler = \
|
|
ref new Windows::Foundation::EventHandler<Platform::Object ^>(&WINRT_HandleGameBarIsInputRedirected_NonMainThread);
|
|
__FIEventHandler_1_IInspectable * pHandler = reinterpret_cast<__FIEventHandler_1_IInspectable *>(handler);
|
|
gameBar->add_IsInputRedirectedChanged(pHandler, &driverdata->gameBarIsInputRedirectedToken);
|
|
gameBar->Release();
|
|
}
|
|
}
|
|
|
|
void
|
|
WINRT_QuitGameBar(_THIS)
|
|
{
|
|
SDL_VideoData *driverdata;
|
|
IGameBarStatics_ *gameBar;
|
|
if (!_this || !_this->driverdata) {
|
|
return;
|
|
}
|
|
gameBar = WINRT_GetGameBar();
|
|
if (!gameBar) {
|
|
return;
|
|
}
|
|
driverdata = (SDL_VideoData *)_this->driverdata;
|
|
if (driverdata->gameBarIsInputRedirectedToken.Value) {
|
|
gameBar->remove_IsInputRedirectedChanged(driverdata->gameBarIsInputRedirectedToken);
|
|
driverdata->gameBarIsInputRedirectedToken.Value = 0;
|
|
}
|
|
WINRT_MainThreadDispatcher = nullptr;
|
|
gameBar->Release();
|
|
}
|
|
|
|
#endif /* SDL_VIDEO_DRIVER_WINRT */
|
|
|
|
/* vi: set ts=4 sw=4 expandtab: */
|