src/core/winrt/SDL_winrtapp_direct3d.cpp
changeset 8522 3ae9dc9c439f
parent 8521 cefdaf414ead
child 8531 d481485a1b85
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/core/winrt/SDL_winrtapp_direct3d.cpp	Fri Sep 06 21:13:15 2013 -0400
     1.3 @@ -0,0 +1,549 @@
     1.4 +
     1.5 +/* Standard C++11 includes */
     1.6 +#include <functional>
     1.7 +#include <string>
     1.8 +#include <sstream>
     1.9 +using namespace std;
    1.10 +
    1.11 +
    1.12 +/* Windows includes */
    1.13 +#include "ppltasks.h"
    1.14 +using namespace concurrency;
    1.15 +using namespace Windows::ApplicationModel;
    1.16 +using namespace Windows::ApplicationModel::Core;
    1.17 +using namespace Windows::ApplicationModel::Activation;
    1.18 +using namespace Windows::Devices::Input;
    1.19 +using namespace Windows::Graphics::Display;
    1.20 +using namespace Windows::Foundation;
    1.21 +using namespace Windows::System;
    1.22 +using namespace Windows::UI::Core;
    1.23 +using namespace Windows::UI::Input;
    1.24 +
    1.25 +
    1.26 +/* SDL includes */
    1.27 +extern "C" {
    1.28 +#include "SDL_assert.h"
    1.29 +#include "SDL_events.h"
    1.30 +#include "SDL_hints.h"
    1.31 +#include "SDL_log.h"
    1.32 +#include "SDL_main.h"
    1.33 +#include "SDL_stdinc.h"
    1.34 +#include "SDL_render.h"
    1.35 +#include "../../video/SDL_sysvideo.h"
    1.36 +//#include "../../SDL_hints_c.h"
    1.37 +#include "../../events/SDL_mouse_c.h"
    1.38 +#include "../../events/SDL_windowevents_c.h"
    1.39 +#include "../../render/SDL_sysrender.h"
    1.40 +}
    1.41 +
    1.42 +#include "../../video/winrt/SDL_winrtevents_c.h"
    1.43 +#include "../../video/winrt/SDL_winrtvideo_cpp.h"
    1.44 +#include "SDL_winrtapp_direct3d.h"
    1.45 +
    1.46 +
    1.47 +// Compile-time debugging options:
    1.48 +// To enable, uncomment; to disable, comment them out.
    1.49 +//#define LOG_POINTER_EVENTS 1
    1.50 +//#define LOG_WINDOW_EVENTS 1
    1.51 +//#define LOG_ORIENTATION_EVENTS 1
    1.52 +
    1.53 +
    1.54 +// HACK, DLudwig: The C-style main() will get loaded via the app's
    1.55 +// WinRT-styled main(), which is part of SDLmain_for_WinRT.cpp.
    1.56 +// This seems wrong on some level, but does seem to work.
    1.57 +typedef int (*SDL_WinRT_MainFunction)(int, char **);
    1.58 +static SDL_WinRT_MainFunction SDL_WinRT_main = nullptr;
    1.59 +
    1.60 +// HACK, DLudwig: record a reference to the global, WinRT 'app'/view.
    1.61 +// SDL/WinRT will use this throughout its code.
    1.62 +//
    1.63 +// TODO, WinRT: consider replacing SDL_WinRTGlobalApp with something
    1.64 +// non-global, such as something created inside
    1.65 +// SDL_InitSubSystem(SDL_INIT_VIDEO), or something inside
    1.66 +// SDL_CreateWindow().
    1.67 +SDL_WinRTApp ^ SDL_WinRTGlobalApp = nullptr;
    1.68 +
    1.69 +ref class SDLApplicationSource sealed : Windows::ApplicationModel::Core::IFrameworkViewSource
    1.70 +{
    1.71 +public:
    1.72 +    virtual Windows::ApplicationModel::Core::IFrameworkView^ CreateView();
    1.73 +};
    1.74 +
    1.75 +IFrameworkView^ SDLApplicationSource::CreateView()
    1.76 +{
    1.77 +    // TODO, WinRT: see if this function (CreateView) can ever get called
    1.78 +    // more than once.  For now, just prevent it from ever assigning
    1.79 +    // SDL_WinRTGlobalApp more than once.
    1.80 +    SDL_assert(!SDL_WinRTGlobalApp);
    1.81 +    SDL_WinRTApp ^ app = ref new SDL_WinRTApp();
    1.82 +    if (!SDL_WinRTGlobalApp)
    1.83 +    {
    1.84 +        SDL_WinRTGlobalApp = app;
    1.85 +    }
    1.86 +    return app;
    1.87 +}
    1.88 +
    1.89 +__declspec(dllexport) int SDL_WinRT_RunApplication(SDL_WinRT_MainFunction mainFunction)
    1.90 +{
    1.91 +    SDL_WinRT_main = mainFunction;
    1.92 +    auto direct3DApplicationSource = ref new SDLApplicationSource();
    1.93 +    CoreApplication::Run(direct3DApplicationSource);
    1.94 +    return 0;
    1.95 +}
    1.96 +
    1.97 +static void WINRT_SetDisplayOrientationsPreference(void *userdata, const char *name, const char *oldValue, const char *newValue)
    1.98 +{
    1.99 +    SDL_assert(SDL_strcmp(name, SDL_HINT_ORIENTATIONS) == 0);
   1.100 +
   1.101 +    // Start with no orientation flags, then add each in as they're parsed
   1.102 +    // from newValue.
   1.103 +    unsigned int orientationFlags = 0;
   1.104 +    if (newValue) {
   1.105 +        std::istringstream tokenizer(newValue);
   1.106 +        while (!tokenizer.eof()) {
   1.107 +            std::string orientationName;
   1.108 +            std::getline(tokenizer, orientationName, ' ');
   1.109 +            if (orientationName == "LandscapeLeft") {
   1.110 +                orientationFlags |= (unsigned int) DisplayOrientations::LandscapeFlipped;
   1.111 +            } else if (orientationName == "LandscapeRight") {
   1.112 +                orientationFlags |= (unsigned int) DisplayOrientations::Landscape;
   1.113 +            } else if (orientationName == "Portrait") {
   1.114 +                orientationFlags |= (unsigned int) DisplayOrientations::Portrait;
   1.115 +            } else if (orientationName == "PortraitUpsideDown") {
   1.116 +                orientationFlags |= (unsigned int) DisplayOrientations::PortraitFlipped;
   1.117 +            }
   1.118 +        }
   1.119 +    }
   1.120 +
   1.121 +    // If no valid orientation flags were specified, use a reasonable set of defaults:
   1.122 +    if (!orientationFlags) {
   1.123 +        // TODO, WinRT: consider seeing if an app's default orientation flags can be found out via some API call(s).
   1.124 +        orientationFlags = (unsigned int) ( \
   1.125 +            DisplayOrientations::Landscape |
   1.126 +            DisplayOrientations::LandscapeFlipped |
   1.127 +            DisplayOrientations::Portrait |
   1.128 +            DisplayOrientations::PortraitFlipped);
   1.129 +    }
   1.130 +
   1.131 +    // Set the orientation/rotation preferences.  Please note that this does
   1.132 +    // not constitute a 100%-certain lock of a given set of possible
   1.133 +    // orientations.  According to Microsoft's documentation on WinRT [1]
   1.134 +    // when a device is not capable of being rotated, Windows may ignore
   1.135 +    // the orientation preferences, and stick to what the device is capable of
   1.136 +    // displaying.
   1.137 +    //
   1.138 +    // [1] Documentation on the 'InitialRotationPreference' setting for a
   1.139 +    // Windows app's manifest file describes how some orientation/rotation
   1.140 +    // preferences may be ignored.  See
   1.141 +    // http://msdn.microsoft.com/en-us/library/windows/apps/hh700343.aspx
   1.142 +    // for details.  Microsoft's "Display orientation sample" also gives an
   1.143 +    // outline of how Windows treats device rotation
   1.144 +    // (http://code.msdn.microsoft.com/Display-Orientation-Sample-19a58e93).
   1.145 +    DisplayProperties::AutoRotationPreferences = (DisplayOrientations) orientationFlags;
   1.146 +}
   1.147 +
   1.148 +static void
   1.149 +WINRT_ProcessWindowSizeChange()
   1.150 +{
   1.151 +    // Make the new window size be the one true fullscreen mode.
   1.152 +    // This change was initially done, in part, to allow the Direct3D 11.1
   1.153 +    // renderer to receive window-resize events as a device rotates.
   1.154 +    // Before, rotating a device from landscape, to portrait, and then
   1.155 +    // back to landscape would cause the Direct3D 11.1 swap buffer to
   1.156 +    // not get resized appropriately.  SDL would, on the rotation from
   1.157 +    // landscape to portrait, re-resize the SDL window to it's initial
   1.158 +    // size (landscape).  On the subsequent rotation, SDL would drop the
   1.159 +    // window-resize event as it appeared the SDL window didn't change
   1.160 +    // size, and the Direct3D 11.1 renderer wouldn't resize its swap
   1.161 +    // chain.
   1.162 +    SDL_DisplayMode resizedDisplayMode = WINRT_CalcDisplayModeUsingNativeWindow();
   1.163 +    if (resizedDisplayMode.w == 0 || resizedDisplayMode.h == 0) {
   1.164 +        return;
   1.165 +    }
   1.166 +
   1.167 +    SDL_DisplayMode oldDisplayMode;
   1.168 +    SDL_zero(oldDisplayMode);
   1.169 +    if (WINRT_GlobalSDLVideoDevice) {
   1.170 +        oldDisplayMode = WINRT_GlobalSDLVideoDevice->displays[0].desktop_mode;
   1.171 +        WINRT_GlobalSDLVideoDevice->displays[0].current_mode = resizedDisplayMode;
   1.172 +        WINRT_GlobalSDLVideoDevice->displays[0].desktop_mode = resizedDisplayMode;
   1.173 +        WINRT_GlobalSDLVideoDevice->displays[0].display_modes[0] = resizedDisplayMode;
   1.174 +    }
   1.175 +
   1.176 +    if (WINRT_GlobalSDLWindow) {
   1.177 +        // Send a window-resize event to the rest of SDL, and to apps:
   1.178 +        SDL_SendWindowEvent(
   1.179 +            WINRT_GlobalSDLWindow,
   1.180 +            SDL_WINDOWEVENT_RESIZED,
   1.181 +            resizedDisplayMode.w,
   1.182 +            resizedDisplayMode.h);
   1.183 +
   1.184 +#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
   1.185 +        // HACK: On Windows Phone, make sure that orientation changes from
   1.186 +        // Landscape to LandscapeFlipped, Portrait to PortraitFlipped,
   1.187 +        // or vice-versa on either of those two, lead to the Direct3D renderer
   1.188 +        // getting updated.
   1.189 +        const DisplayOrientations oldOrientation = (DisplayOrientations) (unsigned int) oldDisplayMode.driverdata;
   1.190 +        const DisplayOrientations newOrientation = (DisplayOrientations) (unsigned int) resizedDisplayMode.driverdata;
   1.191 +
   1.192 +        if ((oldOrientation == DisplayOrientations::Landscape && newOrientation == DisplayOrientations::LandscapeFlipped) ||
   1.193 +            (oldOrientation == DisplayOrientations::LandscapeFlipped && newOrientation == DisplayOrientations::Landscape) ||
   1.194 +            (oldOrientation == DisplayOrientations::Portrait && newOrientation == DisplayOrientations::PortraitFlipped) ||
   1.195 +            (oldOrientation == DisplayOrientations::PortraitFlipped && newOrientation == DisplayOrientations::Portrait))
   1.196 +        {
   1.197 +            // One of the reasons this event is getting sent out is because SDL
   1.198 +            // will ignore requests to send out SDL_WINDOWEVENT_RESIZED events
   1.199 +            // if and when the event size doesn't change (and the Direct3D 11.1
   1.200 +            // renderer doesn't get the memo).
   1.201 +            //
   1.202 +            // Make sure that the display/window size really didn't change.  If
   1.203 +            // it did, then a SDL_WINDOWEVENT_SIZE_CHANGED event got sent, and
   1.204 +            // the Direct3D 11.1 renderer picked it up, presumably.
   1.205 +            if (oldDisplayMode.w == resizedDisplayMode.w &&
   1.206 +                oldDisplayMode.h == resizedDisplayMode.h)
   1.207 +            {
   1.208 +                SDL_SendWindowEvent(
   1.209 +                    WINRT_GlobalSDLWindow,
   1.210 +                    SDL_WINDOWEVENT_SIZE_CHANGED,
   1.211 +                    resizedDisplayMode.w,
   1.212 +                    resizedDisplayMode.h);
   1.213 +            }
   1.214 +        }
   1.215 +#endif
   1.216 +    }
   1.217 +}
   1.218 +
   1.219 +SDL_WinRTApp::SDL_WinRTApp() :
   1.220 +    m_windowClosed(false),
   1.221 +    m_windowVisible(true)
   1.222 +{
   1.223 +}
   1.224 +
   1.225 +void SDL_WinRTApp::Initialize(CoreApplicationView^ applicationView)
   1.226 +{
   1.227 +    applicationView->Activated +=
   1.228 +        ref new TypedEventHandler<CoreApplicationView^, IActivatedEventArgs^>(this, &SDL_WinRTApp::OnActivated);
   1.229 +
   1.230 +    CoreApplication::Suspending +=
   1.231 +        ref new EventHandler<SuspendingEventArgs^>(this, &SDL_WinRTApp::OnSuspending);
   1.232 +
   1.233 +    CoreApplication::Resuming +=
   1.234 +        ref new EventHandler<Platform::Object^>(this, &SDL_WinRTApp::OnResuming);
   1.235 +
   1.236 +    DisplayProperties::OrientationChanged +=
   1.237 +        ref new DisplayPropertiesEventHandler(this, &SDL_WinRTApp::OnOrientationChanged);
   1.238 +
   1.239 +    // Register the hint, SDL_HINT_ORIENTATIONS, with SDL.  This needs to be
   1.240 +    // done before the hint's callback is registered (as of Feb 22, 2013),
   1.241 +    // otherwise the hint callback won't get registered.
   1.242 +    //
   1.243 +    // 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.
   1.244 +    //SDL_SetHint(SDL_HINT_ORIENTATIONS, "LandscapeLeft LandscapeRight Portrait PortraitUpsideDown");   // DavidL: this is no longer needed (for SDL_AddHintCallback)
   1.245 +    SDL_AddHintCallback(SDL_HINT_ORIENTATIONS, WINRT_SetDisplayOrientationsPreference, NULL);
   1.246 +}
   1.247 +
   1.248 +void SDL_WinRTApp::OnOrientationChanged(Object^ sender)
   1.249 +{
   1.250 +#if LOG_ORIENTATION_EVENTS==1
   1.251 +    CoreWindow^ window = CoreWindow::GetForCurrentThread();
   1.252 +    if (window) {
   1.253 +        SDL_Log("%s, current orientation=%d, native orientation=%d, auto rot. pref=%d, CoreWindow Size={%f,%f}\n",
   1.254 +            __FUNCTION__,
   1.255 +            (int)DisplayProperties::CurrentOrientation,
   1.256 +            (int)DisplayProperties::NativeOrientation,
   1.257 +            (int)DisplayProperties::AutoRotationPreferences,
   1.258 +            window->Bounds.Width,
   1.259 +            window->Bounds.Height);
   1.260 +    } else {
   1.261 +        SDL_Log("%s, current orientation=%d, native orientation=%d, auto rot. pref=%d\n",
   1.262 +            __FUNCTION__,
   1.263 +            (int)DisplayProperties::CurrentOrientation,
   1.264 +            (int)DisplayProperties::NativeOrientation,
   1.265 +            (int)DisplayProperties::AutoRotationPreferences);
   1.266 +    }
   1.267 +#endif
   1.268 +
   1.269 +#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
   1.270 +    // On Windows Phone, treat an orientation change as a change in window size.
   1.271 +    // The native window's size doesn't seem to change, however SDL will simulate
   1.272 +    // a window size change.
   1.273 +    WINRT_ProcessWindowSizeChange();
   1.274 +#endif
   1.275 +}
   1.276 +
   1.277 +void SDL_WinRTApp::SetWindow(CoreWindow^ window)
   1.278 +{
   1.279 +#if LOG_WINDOW_EVENTS==1
   1.280 +    SDL_Log("%s, current orientation=%d, native orientation=%d, auto rot. pref=%d, window Size={%f,%f}\n",
   1.281 +        __FUNCTION__,
   1.282 +        (int)DisplayProperties::CurrentOrientation,
   1.283 +        (int)DisplayProperties::NativeOrientation,
   1.284 +        (int)DisplayProperties::AutoRotationPreferences,
   1.285 +        window->Bounds.Width,
   1.286 +        window->Bounds.Height);
   1.287 +#endif
   1.288 +
   1.289 +    window->SizeChanged += 
   1.290 +        ref new TypedEventHandler<CoreWindow^, WindowSizeChangedEventArgs^>(this, &SDL_WinRTApp::OnWindowSizeChanged);
   1.291 +
   1.292 +    window->VisibilityChanged +=
   1.293 +        ref new TypedEventHandler<CoreWindow^, VisibilityChangedEventArgs^>(this, &SDL_WinRTApp::OnVisibilityChanged);
   1.294 +
   1.295 +    window->Closed += 
   1.296 +        ref new TypedEventHandler<CoreWindow^, CoreWindowEventArgs^>(this, &SDL_WinRTApp::OnWindowClosed);
   1.297 +
   1.298 +#if WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP
   1.299 +    window->PointerCursor = ref new CoreCursor(CoreCursorType::Arrow, 0);
   1.300 +#endif
   1.301 +
   1.302 +    window->PointerPressed +=
   1.303 +        ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &SDL_WinRTApp::OnPointerPressed);
   1.304 +
   1.305 +    window->PointerMoved +=
   1.306 +        ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &SDL_WinRTApp::OnPointerMoved);
   1.307 +
   1.308 +    window->PointerReleased +=
   1.309 +        ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &SDL_WinRTApp::OnPointerReleased);
   1.310 +
   1.311 +    window->PointerWheelChanged +=
   1.312 +        ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &SDL_WinRTApp::OnPointerWheelChanged);
   1.313 +
   1.314 +#if WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP
   1.315 +    // Retrieves relative-only mouse movements:
   1.316 +    Windows::Devices::Input::MouseDevice::GetForCurrentView()->MouseMoved +=
   1.317 +        ref new TypedEventHandler<MouseDevice^, MouseEventArgs^>(this, &SDL_WinRTApp::OnMouseMoved);
   1.318 +#endif
   1.319 +
   1.320 +    window->KeyDown +=
   1.321 +        ref new TypedEventHandler<CoreWindow^, KeyEventArgs^>(this, &SDL_WinRTApp::OnKeyDown);
   1.322 +
   1.323 +    window->KeyUp +=
   1.324 +        ref new TypedEventHandler<CoreWindow^, KeyEventArgs^>(this, &SDL_WinRTApp::OnKeyUp);
   1.325 +}
   1.326 +
   1.327 +void SDL_WinRTApp::Load(Platform::String^ entryPoint)
   1.328 +{
   1.329 +}
   1.330 +
   1.331 +void SDL_WinRTApp::Run()
   1.332 +{
   1.333 +    SDL_SetMainReady();
   1.334 +    if (SDL_WinRT_main)
   1.335 +    {
   1.336 +        // TODO, WinRT: pass the C-style main() a reasonably realistic
   1.337 +        // representation of command line arguments.
   1.338 +        int argc = 0;
   1.339 +        char **argv = NULL;
   1.340 +        SDL_WinRT_main(argc, argv);
   1.341 +    }
   1.342 +}
   1.343 +
   1.344 +void SDL_WinRTApp::PumpEvents()
   1.345 +{
   1.346 +    if (!m_windowClosed)
   1.347 +    {
   1.348 +        if (m_windowVisible)
   1.349 +        {
   1.350 +            CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent);
   1.351 +        }
   1.352 +        else
   1.353 +        {
   1.354 +            CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessOneAndAllPending);
   1.355 +        }
   1.356 +    }
   1.357 +}
   1.358 +
   1.359 +void SDL_WinRTApp::Uninitialize()
   1.360 +{
   1.361 +}
   1.362 +
   1.363 +void SDL_WinRTApp::OnWindowSizeChanged(CoreWindow^ sender, WindowSizeChangedEventArgs^ args)
   1.364 +{
   1.365 +#if LOG_WINDOW_EVENTS==1
   1.366 +    SDL_Log("%s, size={%f,%f}, current orientation=%d, native orientation=%d, auto rot. pref=%d, WINRT_GlobalSDLWindow?=%s\n",
   1.367 +        __FUNCTION__,
   1.368 +        args->Size.Width, args->Size.Height,
   1.369 +        (int)DisplayProperties::CurrentOrientation,
   1.370 +        (int)DisplayProperties::NativeOrientation,
   1.371 +        (int)DisplayProperties::AutoRotationPreferences,
   1.372 +        (WINRT_GlobalSDLWindow ? "yes" : "no"));
   1.373 +#endif
   1.374 +
   1.375 +    WINRT_ProcessWindowSizeChange();
   1.376 +}
   1.377 +
   1.378 +void SDL_WinRTApp::OnVisibilityChanged(CoreWindow^ sender, VisibilityChangedEventArgs^ args)
   1.379 +{
   1.380 +#if LOG_WINDOW_EVENTS==1
   1.381 +    SDL_Log("%s, visible?=%s, WINRT_GlobalSDLWindow?=%s\n",
   1.382 +        __FUNCTION__,
   1.383 +        (args->Visible ? "yes" : "no"),
   1.384 +        (WINRT_GlobalSDLWindow ? "yes" : "no"));
   1.385 +#endif
   1.386 +
   1.387 +    m_windowVisible = args->Visible;
   1.388 +    if (WINRT_GlobalSDLWindow) {
   1.389 +        SDL_bool wasSDLWindowSurfaceValid = WINRT_GlobalSDLWindow->surface_valid;
   1.390 +
   1.391 +        if (args->Visible) {
   1.392 +            SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_WINDOWEVENT_SHOWN, 0, 0);
   1.393 +        } else {
   1.394 +            SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_WINDOWEVENT_HIDDEN, 0, 0);
   1.395 +        }
   1.396 +
   1.397 +        // HACK: Prevent SDL's window-hide handling code, which currently
   1.398 +        // triggers a fake window resize (possibly erronously), from
   1.399 +        // marking the SDL window's surface as invalid.
   1.400 +        //
   1.401 +        // A better solution to this probably involves figuring out if the
   1.402 +        // fake window resize can be prevented.
   1.403 +        WINRT_GlobalSDLWindow->surface_valid = wasSDLWindowSurfaceValid;
   1.404 +    }
   1.405 +}
   1.406 +
   1.407 +void SDL_WinRTApp::OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args)
   1.408 +{
   1.409 +#if LOG_WINDOW_EVENTS==1
   1.410 +    SDL_Log("%s\n", __FUNCTION__);
   1.411 +#endif
   1.412 +    m_windowClosed = true;
   1.413 +}
   1.414 +
   1.415 +void SDL_WinRTApp::OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args)
   1.416 +{
   1.417 +    CoreWindow::GetForCurrentThread()->Activate();
   1.418 +}
   1.419 +
   1.420 +static int SDLCALL RemoveAppSuspendAndResumeEvents(void * userdata, SDL_Event * event)
   1.421 +{
   1.422 +    if (event->type == SDL_WINDOWEVENT)
   1.423 +    {
   1.424 +        switch (event->window.event)
   1.425 +        {
   1.426 +            case SDL_WINDOWEVENT_MINIMIZED:
   1.427 +            case SDL_WINDOWEVENT_RESTORED:
   1.428 +                // Return 0 to indicate that the event should be removed from the
   1.429 +                // event queue:
   1.430 +                return 0;
   1.431 +            default:
   1.432 +                break;
   1.433 +        }
   1.434 +    }
   1.435 +
   1.436 +    // Return 1 to indicate that the event should stay in the event queue:
   1.437 +    return 1;
   1.438 +}
   1.439 +
   1.440 +void SDL_WinRTApp::OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args)
   1.441 +{
   1.442 +    // Save app state asynchronously after requesting a deferral. Holding a deferral
   1.443 +    // indicates that the application is busy performing suspending operations. Be
   1.444 +    // aware that a deferral may not be held indefinitely. After about five seconds,
   1.445 +    // the app will be forced to exit.
   1.446 +    SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral();
   1.447 +    create_task([this, deferral]()
   1.448 +    {
   1.449 +        // Send a window-minimized event immediately to observers.
   1.450 +        // CoreDispatcher::ProcessEvents, which is the backbone on which
   1.451 +        // SDL_WinRTApp::PumpEvents is built, will not return to its caller
   1.452 +        // once it sends out a suspend event.  Any events posted to SDL's
   1.453 +        // event queue won't get received until the WinRT app is resumed.
   1.454 +        // SDL_AddEventWatch() may be used to receive app-suspend events on
   1.455 +        // WinRT.
   1.456 +        //
   1.457 +        // In order to prevent app-suspend events from being received twice:
   1.458 +        // first via a callback passed to SDL_AddEventWatch, and second via
   1.459 +        // SDL's event queue, the event will be sent to SDL, then immediately
   1.460 +        // removed from the queue.
   1.461 +        if (WINRT_GlobalSDLWindow)
   1.462 +        {
   1.463 +            SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_WINDOWEVENT_MINIMIZED, 0, 0);   // TODO: see if SDL_WINDOWEVENT_SIZE_CHANGED should be getting triggered here (it is, currently)
   1.464 +            SDL_FilterEvents(RemoveAppSuspendAndResumeEvents, 0);
   1.465 +        }
   1.466 +        deferral->Complete();
   1.467 +    });
   1.468 +}
   1.469 +
   1.470 +void SDL_WinRTApp::OnResuming(Platform::Object^ sender, Platform::Object^ args)
   1.471 +{
   1.472 +    // Restore any data or state that was unloaded on suspend. By default, data
   1.473 +    // and state are persisted when resuming from suspend. Note that this event
   1.474 +    // does not occur if the app was previously terminated.
   1.475 +    if (WINRT_GlobalSDLWindow)
   1.476 +    {
   1.477 +        SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_WINDOWEVENT_RESTORED, 0, 0);    // TODO: see if SDL_WINDOWEVENT_SIZE_CHANGED should be getting triggered here (it is, currently)
   1.478 +
   1.479 +        // Remove the app-resume event from the queue, as is done with the
   1.480 +        // app-suspend event.
   1.481 +        //
   1.482 +        // TODO, WinRT: consider posting this event to the queue even though
   1.483 +        // its counterpart, the app-suspend event, effectively has to be
   1.484 +        // processed immediately.
   1.485 +        SDL_FilterEvents(RemoveAppSuspendAndResumeEvents, 0);
   1.486 +    }
   1.487 +}
   1.488 +
   1.489 +static void
   1.490 +WINRT_LogPointerEvent(const char * header, Windows::UI::Core::PointerEventArgs ^ args, Windows::Foundation::Point transformedPoint)
   1.491 +{
   1.492 +    Windows::UI::Input::PointerPoint ^ pt = args->CurrentPoint;
   1.493 +    SDL_Log("%s: Position={%f,%f}, Transformed Pos={%f, %f}, MouseWheelDelta=%d, FrameId=%d, PointerId=%d, SDL button=%d\n",
   1.494 +        header,
   1.495 +        pt->Position.X, pt->Position.Y,
   1.496 +        transformedPoint.X, transformedPoint.Y,
   1.497 +        pt->Properties->MouseWheelDelta,
   1.498 +        pt->FrameId,
   1.499 +        pt->PointerId,
   1.500 +        WINRT_GetSDLButtonForPointerPoint(pt));
   1.501 +}
   1.502 +
   1.503 +void SDL_WinRTApp::OnPointerPressed(CoreWindow^ sender, PointerEventArgs^ args)
   1.504 +{
   1.505 +#if LOG_POINTER_EVENTS
   1.506 +    WINRT_LogPointerEvent("pointer pressed", args, WINRT_TransformCursorPosition(WINRT_GlobalSDLWindow, args->CurrentPoint->Position));
   1.507 +#endif
   1.508 +
   1.509 +    WINRT_ProcessPointerPressedEvent(WINRT_GlobalSDLWindow, args->CurrentPoint);
   1.510 +}
   1.511 +
   1.512 +void SDL_WinRTApp::OnPointerMoved(CoreWindow^ sender, PointerEventArgs^ args)
   1.513 +{
   1.514 +#if LOG_POINTER_EVENTS
   1.515 +    WINRT_LogPointerEvent("pointer moved", args, WINRT_TransformCursorPosition(WINRT_GlobalSDLWindow, args->CurrentPoint->Position));
   1.516 +#endif
   1.517 +
   1.518 +    WINRT_ProcessPointerMovedEvent(WINRT_GlobalSDLWindow, args->CurrentPoint);
   1.519 +}
   1.520 +
   1.521 +void SDL_WinRTApp::OnPointerReleased(CoreWindow^ sender, PointerEventArgs^ args)
   1.522 +{
   1.523 +#if LOG_POINTER_EVENTS
   1.524 +    WINRT_LogPointerEvent("pointer released", args, WINRT_TransformCursorPosition(WINRT_GlobalSDLWindow, args->CurrentPoint->Position));
   1.525 +#endif
   1.526 +
   1.527 +    WINRT_ProcessPointerReleasedEvent(WINRT_GlobalSDLWindow, args->CurrentPoint);
   1.528 +}
   1.529 +
   1.530 +void SDL_WinRTApp::OnPointerWheelChanged(CoreWindow^ sender, PointerEventArgs^ args)
   1.531 +{
   1.532 +#if LOG_POINTER_EVENTS
   1.533 +    WINRT_LogPointerEvent("pointer wheel changed", args, WINRT_TransformCursorPosition(WINRT_GlobalSDLWindow, args->CurrentPoint->Position));
   1.534 +#endif
   1.535 +
   1.536 +    WINRT_ProcessPointerWheelChangedEvent(WINRT_GlobalSDLWindow, args->CurrentPoint);
   1.537 +}
   1.538 +
   1.539 +void SDL_WinRTApp::OnMouseMoved(MouseDevice^ mouseDevice, MouseEventArgs^ args)
   1.540 +{
   1.541 +    WINRT_ProcessMouseMovedEvent(WINRT_GlobalSDLWindow, args);
   1.542 +}
   1.543 +
   1.544 +void SDL_WinRTApp::OnKeyDown(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyEventArgs^ args)
   1.545 +{
   1.546 +    WINRT_ProcessKeyDownEvent(args);
   1.547 +}
   1.548 +
   1.549 +void SDL_WinRTApp::OnKeyUp(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyEventArgs^ args)
   1.550 +{
   1.551 +    WINRT_ProcessKeyUpEvent(args);
   1.552 +}