SDL 2.0
SDL_winrtgamebar.cpp
Go to the documentation of this file.
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "../../SDL_internal.h"
22
23#if SDL_VIDEO_DRIVER_WINRT
24
25/* Windows includes */
26#include <roapi.h>
27#include <windows.foundation.h>
28#include <EventToken.h>
29
30
31/* SDL includes */
32extern "C" {
33#include "SDL_mouse.h"
34#include "../SDL_sysvideo.h"
35}
36#include "SDL_winrtvideo_cpp.h"
37
38
39/* Game Bar events can come in off the main thread. Use the following
40 WinRT CoreDispatcher to deal with them on SDL's thread.
41*/
42static Platform::WeakReference WINRT_MainThreadDispatcher;
43
44
45/* Win10's initial SDK (the 10.0.10240.0 release) does not include references
46 to Game Bar APIs, as the Game Bar was released via Win10 10.0.10586.0.
47
48 Declare its WinRT/COM interface here, to allow compilation with earlier
49 Windows SDKs.
50*/
51MIDL_INTERFACE("1DB9A292-CC78-4173-BE45-B61E67283EA7")
52IGameBarStatics_ : public IInspectable
53{
54public:
55 virtual HRESULT STDMETHODCALLTYPE add_VisibilityChanged(
56 __FIEventHandler_1_IInspectable *handler,
57 Windows::Foundation::EventRegistrationToken *token) = 0;
58
59 virtual HRESULT STDMETHODCALLTYPE remove_VisibilityChanged(
60 Windows::Foundation::EventRegistrationToken token) = 0;
61
62 virtual HRESULT STDMETHODCALLTYPE add_IsInputRedirectedChanged(
63 __FIEventHandler_1_IInspectable *handler,
64 Windows::Foundation::EventRegistrationToken *token) = 0;
65
66 virtual HRESULT STDMETHODCALLTYPE remove_IsInputRedirectedChanged(
67 Windows::Foundation::EventRegistrationToken token) = 0;
68
69 virtual HRESULT STDMETHODCALLTYPE get_Visible(
70 boolean *value) = 0;
71
72 virtual HRESULT STDMETHODCALLTYPE get_IsInputRedirected(
73 boolean *value) = 0;
74};
75
76/* Declare the game bar's COM GUID */
77static GUID IID_IGameBarStatics_ = { MAKELONG(0xA292, 0x1DB9), 0xCC78, 0x4173, { 0xBE, 0x45, 0xB6, 0x1E, 0x67, 0x28, 0x3E, 0xA7 } };
78
79/* Retrieves a pointer to the game bar, or NULL if it is not available.
80 If a pointer is returned, it's ->Release() method must be called
81 after the caller has finished using it.
82*/
83static IGameBarStatics_ *
84WINRT_GetGameBar()
85{
86 wchar_t *wClassName = L"Windows.Gaming.UI.GameBar";
87 HSTRING hClassName;
88 IActivationFactory *pActivationFactory = NULL;
89 IGameBarStatics_ *pGameBar = NULL;
90 HRESULT hr;
91
92 hr = ::WindowsCreateString(wClassName, (UINT32)wcslen(wClassName), &hClassName);
93 if (FAILED(hr)) {
94 goto done;
95 }
96
97 hr = Windows::Foundation::GetActivationFactory(hClassName, &pActivationFactory);
98 if (FAILED(hr)) {
99 goto done;
100 }
101
102 pActivationFactory->QueryInterface(IID_IGameBarStatics_, (void **) &pGameBar);
103
104done:
105 if (pActivationFactory) {
106 pActivationFactory->Release();
107 }
108 if (hClassName) {
109 ::WindowsDeleteString(hClassName);
110 }
111 return pGameBar;
112}
113
114static void
115WINRT_HandleGameBarIsInputRedirected_MainThread()
116{
117 IGameBarStatics_ *gameBar;
118 boolean isInputRedirected = 0;
119 if (!WINRT_MainThreadDispatcher) {
120 /* The game bar event handler has been deregistered! */
121 return;
122 }
123 gameBar = WINRT_GetGameBar();
124 if (!gameBar) {
125 /* Shouldn't happen, but just in case... */
126 return;
127 }
128 if (SUCCEEDED(gameBar->get_IsInputRedirected(&isInputRedirected))) {
129 if ( ! isInputRedirected) {
130 /* Input-control is now back to the SDL app. Restore the cursor,
131 in case Windows does not (it does not in either Win10
132 10.0.10240.0 or 10.0.10586.0, maybe later version(s) too.
133 */
136 }
137 }
138 gameBar->Release();
139}
140
141static void
142WINRT_HandleGameBarIsInputRedirected_NonMainThread(Platform::Object ^ o1, Platform::Object ^o2)
143{
144 Windows::UI::Core::CoreDispatcher ^dispatcher = WINRT_MainThreadDispatcher.Resolve<Windows::UI::Core::CoreDispatcher>();
145 if (dispatcher) {
146 dispatcher->RunAsync(
147 Windows::UI::Core::CoreDispatcherPriority::Normal,
148 ref new Windows::UI::Core::DispatchedHandler(&WINRT_HandleGameBarIsInputRedirected_MainThread));
149 }
150}
151
152void
153WINRT_InitGameBar(_THIS)
154{
156 IGameBarStatics_ *gameBar = WINRT_GetGameBar();
157 if (gameBar) {
158 /* GameBar.IsInputRedirected events can come in via something other than
159 the main/SDL thread.
160
161 Get a WinRT 'CoreDispatcher' that can be used to call back into the
162 SDL thread.
163 */
164 WINRT_MainThreadDispatcher = Windows::UI::Core::CoreWindow::GetForCurrentThread()->Dispatcher;
165 Windows::Foundation::EventHandler<Platform::Object ^> ^handler = \
166 ref new Windows::Foundation::EventHandler<Platform::Object ^>(&WINRT_HandleGameBarIsInputRedirected_NonMainThread);
167 __FIEventHandler_1_IInspectable * pHandler = reinterpret_cast<__FIEventHandler_1_IInspectable *>(handler);
168 gameBar->add_IsInputRedirectedChanged(pHandler, &driverdata->gameBarIsInputRedirectedToken);
169 gameBar->Release();
170 }
171}
172
173void
174WINRT_QuitGameBar(_THIS)
175{
176 SDL_VideoData *driverdata;
177 IGameBarStatics_ *gameBar;
178 if (!_this || !_this->driverdata) {
179 return;
180 }
181 gameBar = WINRT_GetGameBar();
182 if (!gameBar) {
183 return;
184 }
185 driverdata = (SDL_VideoData *)_this->driverdata;
186 if (driverdata->gameBarIsInputRedirectedToken.Value) {
187 gameBar->remove_IsInputRedirectedChanged(driverdata->gameBarIsInputRedirectedToken);
188 driverdata->gameBarIsInputRedirectedToken.Value = 0;
189 }
190 WINRT_MainThreadDispatcher = nullptr;
191 gameBar->Release();
192}
193
194#endif /* SDL_VIDEO_DRIVER_WINRT */
195
196/* vi: set ts=4 sw=4 expandtab: */
#define _THIS
#define SUCCEEDED(x)
Definition: SDL_directx.h:51
#define FAILED(x)
Definition: SDL_directx.h:54
#define SDL_GetCursor
#define SDL_SetCursor
GLenum GLint ref
GLsizei const GLfloat * value
static SDL_VideoDevice * _this
Definition: SDL_video.c:118
#define NULL
Definition: begin_code.h:167
int done
Definition: checkkeys.c:28
Windows::Foundation::EventRegistrationToken gameBarIsInputRedirectedToken
SDL_Cursor * cursor
Definition: testwm2.c:40