src/video/winrt/SDL_winrtgamebar.cpp
author Sam Lantinga
Fri, 27 Jan 2017 21:23:27 -0800
changeset 10861 71d8f9afb690
parent 10737 3406a0f8b041
child 11811 5d94cb6b24d3
permissions -rw-r--r--
Fixed bug 3569 - GL_UpdateViewport leaves PROJECTION matrix selected

Tom Seddon

GL_ActivateRenderer may call GL_UpdateViewport, which leaves the GL_PROJECTION matrix selected. But after GL_ResetState, the GL_MODELVIEW matrix is selected, suggesting that's the intended default state.

It seems at least like these should be consistent. Presumably GL_UpdateViewport should be doing a glMatrixMode(GL_MODELVIEW) before it finishes.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2017 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 */
    32 extern "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 */
    42 static 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 */
    51 MIDL_INTERFACE("1DB9A292-CC78-4173-BE45-B61E67283EA7")
    52 IGameBarStatics_ : public IInspectable
    53 {
    54 public:
    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 */
    77 static 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 */
    83 static IGameBarStatics_ *
    84 WINRT_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 
   104 done:
   105     if (pActivationFactory) {
   106         pActivationFactory->Release();
   107     }
   108     if (hClassName) {
   109         ::WindowsDeleteString(hClassName);
   110     }
   111     return pGameBar;
   112 }
   113 
   114 static void
   115 WINRT_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             */
   134             SDL_Cursor *cursor = SDL_GetCursor();
   135             SDL_SetCursor(cursor);
   136         }
   137     }
   138     gameBar->Release();
   139 }
   140 
   141 static void
   142 WINRT_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 
   152 void
   153 WINRT_InitGameBar(_THIS)
   154 {
   155     SDL_VideoData *driverdata = (SDL_VideoData *)_this->driverdata;
   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 
   173 void
   174 WINRT_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: */