WinRT: lots of display and windowing related fixes
authorDavid Ludwig <dludwig@pobox.com>
Thu, 26 Nov 2015 00:41:39 -0500
changeset 9924355cccccc7dc
parent 9923 934692406c03
child 9925 2be74843315c
WinRT: lots of display and windowing related fixes

This change-set fixes a lot of windowing related bugs, especially with
regards to Windows 8.x apps running on Windows 10 (which was the driver for
this work). The primary fixes include:
* listed display modes were wrong, especially when launching apps into a
non-fullscreen space
* reported window flags were often wrong, especially on Windows 10
* fullscreen/windowed mode switches weren't failing (they are not
programmatically possible in Win 8.x apps).
include/SDL_config_winrt.h
src/core/winrt/SDL_winrtapp_direct3d.cpp
src/core/winrt/SDL_winrtapp_direct3d.h
src/render/direct3d11/SDL_render_d3d11.c
src/video/SDL_video.c
src/video/winrt/SDL_winrtevents_c.h
src/video/winrt/SDL_winrtpointerinput.cpp
src/video/winrt/SDL_winrtvideo.cpp
src/video/winrt/SDL_winrtvideo_cpp.h
     1.1 --- a/include/SDL_config_winrt.h	Sun Nov 15 13:04:42 2015 -0500
     1.2 +++ b/include/SDL_config_winrt.h	Thu Nov 26 00:41:39 2015 -0500
     1.3 @@ -19,11 +19,23 @@
     1.4    3. This notice may not be removed or altered from any source distribution.
     1.5  */
     1.6  
     1.7 -#ifndef _SDL_config_windows_h
     1.8 -#define _SDL_config_windows_h
     1.9 +#ifndef _SDL_config_winrt_h
    1.10 +#define _SDL_config_winrt_h
    1.11  
    1.12  #include "SDL_platform.h"
    1.13  
    1.14 +/* Make sure the Windows SDK's NTDDI_VERSION macro gets defined.  This is used
    1.15 +   by SDL to determine which version of the Windows SDK is being used.
    1.16 +*/
    1.17 +#include <sdkddkver.h>
    1.18 +
    1.19 +/* Define possibly-undefined NTDDI values (used when compiling SDL against
    1.20 +   older versions of the Windows SDK.
    1.21 +*/
    1.22 +#ifndef NTDDI_WINBLUE
    1.23 +#define NTDDI_WINBLUE 0x06030000
    1.24 +#endif
    1.25 +
    1.26  /* This is a set of defines to configure the SDL features */
    1.27  
    1.28  #if !defined(_STDINT_H_) && (!defined(HAVE_STDINT_H) || !_HAVE_STDINT_H)
    1.29 @@ -191,4 +203,4 @@
    1.30  #define SDL_ASSEMBLY_ROUTINES	1
    1.31  #endif
    1.32  
    1.33 -#endif /* _SDL_config_windows_h */
    1.34 +#endif /* _SDL_config_winrt_h */
     2.1 --- a/src/core/winrt/SDL_winrtapp_direct3d.cpp	Sun Nov 15 13:04:42 2015 -0500
     2.2 +++ b/src/core/winrt/SDL_winrtapp_direct3d.cpp	Thu Nov 26 00:41:39 2015 -0500
     2.3 @@ -184,97 +184,48 @@
     2.4  }
     2.5  
     2.6  static void
     2.7 -WINRT_ProcessWindowSizeChange()
     2.8 +WINRT_ProcessWindowSizeChange() // TODO: Pass an SDL_Window-identifying thing into WINRT_ProcessWindowSizeChange()
     2.9  {
    2.10 -    SDL_VideoDevice *_this = SDL_GetVideoDevice();
    2.11 +    CoreWindow ^ coreWindow = CoreWindow::GetForCurrentThread();
    2.12 +    if (coreWindow) {
    2.13 +        if (WINRT_GlobalSDLWindow) {
    2.14 +            SDL_Window * window = WINRT_GlobalSDLWindow;
    2.15 +            SDL_WindowData * data = (SDL_WindowData *) window->driverdata;
    2.16  
    2.17 -    // Make the new window size be the one true fullscreen mode.
    2.18 -    // This change was initially done, in part, to allow the Direct3D 11.1
    2.19 -    // renderer to receive window-resize events as a device rotates.
    2.20 -    // Before, rotating a device from landscape, to portrait, and then
    2.21 -    // back to landscape would cause the Direct3D 11.1 swap buffer to
    2.22 -    // not get resized appropriately.  SDL would, on the rotation from
    2.23 -    // landscape to portrait, re-resize the SDL window to it's initial
    2.24 -    // size (landscape).  On the subsequent rotation, SDL would drop the
    2.25 -    // window-resize event as it appeared the SDL window didn't change
    2.26 -    // size, and the Direct3D 11.1 renderer wouldn't resize its swap
    2.27 -    // chain.
    2.28 -    SDL_DisplayMode newDisplayMode;
    2.29 -    if (WINRT_CalcDisplayModeUsingNativeWindow(&newDisplayMode) != 0) {
    2.30 -        return;
    2.31 -    }
    2.32 +            int x = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Left);
    2.33 +            int y = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Top);
    2.34 +            int w = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Width);
    2.35 +            int h = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Height);
    2.36  
    2.37 -    // Make note of the old display mode, and it's old driverdata.
    2.38 -    SDL_DisplayMode oldDisplayMode;
    2.39 -    SDL_zero(oldDisplayMode);
    2.40 -    if (_this) {
    2.41 -        oldDisplayMode = _this->displays[0].desktop_mode;
    2.42 -    }
    2.43 +#if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) && (NTDDI_VERSION == NTDDI_WIN8)
    2.44 +            /* WinPhone 8.0 always keeps its native window size in portrait,
    2.45 +               regardless of orientation.  This changes in WinPhone 8.1,
    2.46 +               in which the native window's size changes along with
    2.47 +               orientation.
    2.48  
    2.49 -    // Setup the new display mode in the appropriate spots.
    2.50 -    if (_this) {
    2.51 -        // Make a full copy of the display mode for display_modes[0],
    2.52 -        // one with with a separately malloced 'driverdata' field.
    2.53 -        // SDL_VideoQuit(), if called, will attempt to free the driverdata
    2.54 -        // fields in 'desktop_mode' and each entry in the 'display_modes'
    2.55 -        // array.
    2.56 -        if (_this->displays[0].display_modes[0].driverdata) {
    2.57 -            // Free the previous mode's memory
    2.58 -            SDL_free(_this->displays[0].display_modes[0].driverdata);
    2.59 -            _this->displays[0].display_modes[0].driverdata = NULL;
    2.60 -        }
    2.61 -        if (WINRT_DuplicateDisplayMode(&(_this->displays[0].display_modes[0]), &newDisplayMode) != 0) {
    2.62 -            // Uh oh, something went wrong.  A malloc call probably failed.
    2.63 -            SDL_free(newDisplayMode.driverdata);
    2.64 -            return;
    2.65 -        }
    2.66 -
    2.67 -        // Install 'newDisplayMode' into 'current_mode' and 'desktop_mode'.
    2.68 -        _this->displays[0].current_mode = newDisplayMode;
    2.69 -        _this->displays[0].desktop_mode = newDisplayMode;
    2.70 -    }
    2.71 -
    2.72 -    if (WINRT_GlobalSDLWindow) {
    2.73 -        // If the window size changed, send a resize event to SDL and its host app:
    2.74 -        int window_w = 0;
    2.75 -        int window_h = 0;
    2.76 -        SDL_GetWindowSize(WINRT_GlobalSDLWindow, &window_w, &window_h);
    2.77 -        if ((window_w != newDisplayMode.w) || (window_h != newDisplayMode.h)) {
    2.78 -            SDL_SendWindowEvent(
    2.79 -                WINRT_GlobalSDLWindow,
    2.80 -                SDL_WINDOWEVENT_RESIZED,
    2.81 -                newDisplayMode.w,
    2.82 -                newDisplayMode.h);
    2.83 -        } else {
    2.84 -#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
    2.85 -            // HACK: Make sure that orientation changes
    2.86 -            // lead to the Direct3D renderer's viewport getting updated:
    2.87 -            //
    2.88 -            // For some reason, this doesn't seem to need to be done on Windows 8.x,
    2.89 -            // even when going from Landscape to LandscapeFlipped.  It only seems to
    2.90 -            // be needed on Windows Phone, at least when I tested on my devices.
    2.91 -            // I'm not currently sure why this is, but it seems to work fine. -- David L.
    2.92 -            //
    2.93 -            // TODO, WinRT: do more extensive research into why orientation changes on Win 8.x don't need D3D changes, or if they might, in some cases
    2.94 -            const DisplayOrientations oldOrientation = ((SDL_DisplayModeData *)oldDisplayMode.driverdata)->currentOrientation;
    2.95 -            const DisplayOrientations newOrientation = ((SDL_DisplayModeData *)newDisplayMode.driverdata)->currentOrientation;
    2.96 -            if (oldOrientation != newOrientation)
    2.97 -            {
    2.98 -                SDL_SendWindowEvent(
    2.99 -                    WINRT_GlobalSDLWindow,
   2.100 -                    SDL_WINDOWEVENT_SIZE_CHANGED,
   2.101 -                    newDisplayMode.w,
   2.102 -                    newDisplayMode.h);
   2.103 +               Attempt to emulate WinPhone 8.1's behavior on WinPhone 8.0, with
   2.104 +               regards to window size.  This fixes a rendering bug that occurs
   2.105 +               when a WinPhone 8.0 app is rotated to either 90 or 270 degrees.
   2.106 +            */
   2.107 +            const DisplayOrientations currentOrientation = WINRT_DISPLAY_PROPERTY(CurrentOrientation);
   2.108 +            switch (currentOrientation) {
   2.109 +                case DisplayOrientations::Landscape:
   2.110 +                case DisplayOrientations::LandscapeFlipped: {
   2.111 +                    int tmp = w;
   2.112 +                    w = h;
   2.113 +                    h = tmp;
   2.114 +                } break;
   2.115              }
   2.116  #endif
   2.117 +
   2.118 +            WINRT_UpdateWindowFlags(window, SDL_WINDOW_MAXIMIZED | SDL_WINDOW_FULLSCREEN_DESKTOP);
   2.119 +
   2.120 +            /* The window can move during a resize event, such as when maximizing
   2.121 +               or resizing from a corner */
   2.122 +            SDL_SendWindowEvent(window, SDL_WINDOWEVENT_MOVED, x, y);
   2.123 +            SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, w, h);
   2.124          }
   2.125      }
   2.126 -    
   2.127 -    // Finally, free the 'driverdata' field of the old 'desktop_mode'.
   2.128 -    if (oldDisplayMode.driverdata) {
   2.129 -        SDL_free(oldDisplayMode.driverdata);
   2.130 -        oldDisplayMode.driverdata = NULL;
   2.131 -    }
   2.132  }
   2.133  
   2.134  SDL_WinRTApp::SDL_WinRTApp() :
   2.135 @@ -286,7 +237,7 @@
   2.136  void SDL_WinRTApp::Initialize(CoreApplicationView^ applicationView)
   2.137  {
   2.138      applicationView->Activated +=
   2.139 -        ref new TypedEventHandler<CoreApplicationView^, IActivatedEventArgs^>(this, &SDL_WinRTApp::OnActivated);
   2.140 +        ref new TypedEventHandler<CoreApplicationView^, IActivatedEventArgs^>(this, &SDL_WinRTApp::OnAppActivated);
   2.141  
   2.142      CoreApplication::Suspending +=
   2.143          ref new EventHandler<SuspendingEventArgs^>(this, &SDL_WinRTApp::OnSuspending);
   2.144 @@ -305,35 +256,61 @@
   2.145  #endif
   2.146  {
   2.147  #if LOG_ORIENTATION_EVENTS==1
   2.148 -    CoreWindow^ window = CoreWindow::GetForCurrentThread();
   2.149 -    if (window) {
   2.150 -        SDL_Log("%s, current orientation=%d, native orientation=%d, auto rot. pref=%d, CoreWindow Size={%f,%f}\n",
   2.151 -            __FUNCTION__,
   2.152 -            WINRT_DISPLAY_PROPERTY(CurrentOrientation),
   2.153 -            WINRT_DISPLAY_PROPERTY(NativeOrientation),
   2.154 -            WINRT_DISPLAY_PROPERTY(AutoRotationPreferences),
   2.155 -            window->Bounds.Width,
   2.156 -            window->Bounds.Height);
   2.157 -    } else {
   2.158 -        SDL_Log("%s, current orientation=%d, native orientation=%d, auto rot. pref=%d\n",
   2.159 -            __FUNCTION__,
   2.160 -            WINRT_DISPLAY_PROPERTY(CurrentOrientation),
   2.161 -            WINRT_DISPLAY_PROPERTY(NativeOrientation),
   2.162 -            WINRT_DISPLAY_PROPERTY(AutoRotationPreferences));
   2.163 +    {
   2.164 +        CoreWindow^ window = CoreWindow::GetForCurrentThread();
   2.165 +        if (window) {
   2.166 +            SDL_Log("%s, current orientation=%d, native orientation=%d, auto rot. pref=%d, CoreWindow Bounds={%f,%f,%f,%f}\n",
   2.167 +                __FUNCTION__,
   2.168 +                WINRT_DISPLAY_PROPERTY(CurrentOrientation),
   2.169 +                WINRT_DISPLAY_PROPERTY(NativeOrientation),
   2.170 +                WINRT_DISPLAY_PROPERTY(AutoRotationPreferences),
   2.171 +                window->Bounds.X,
   2.172 +                window->Bounds.Y,
   2.173 +                window->Bounds.Width,
   2.174 +                window->Bounds.Height);
   2.175 +        } else {
   2.176 +            SDL_Log("%s, current orientation=%d, native orientation=%d, auto rot. pref=%d\n",
   2.177 +                __FUNCTION__,
   2.178 +                WINRT_DISPLAY_PROPERTY(CurrentOrientation),
   2.179 +                WINRT_DISPLAY_PROPERTY(NativeOrientation),
   2.180 +                WINRT_DISPLAY_PROPERTY(AutoRotationPreferences));
   2.181 +        }
   2.182      }
   2.183  #endif
   2.184  
   2.185      WINRT_ProcessWindowSizeChange();
   2.186 +
   2.187 +#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
   2.188 +    // HACK: Make sure that orientation changes
   2.189 +    // lead to the Direct3D renderer's viewport getting updated:
   2.190 +    //
   2.191 +    // For some reason, this doesn't seem to need to be done on Windows 8.x,
   2.192 +    // even when going from Landscape to LandscapeFlipped.  It only seems to
   2.193 +    // be needed on Windows Phone, at least when I tested on my devices.
   2.194 +    // I'm not currently sure why this is, but it seems to work fine. -- David L.
   2.195 +    //
   2.196 +    // TODO, WinRT: do more extensive research into why orientation changes on Win 8.x don't need D3D changes, or if they might, in some cases
   2.197 +    SDL_Window * window = WINRT_GlobalSDLWindow;
   2.198 +    if (window) {
   2.199 +        SDL_WindowData * data = (SDL_WindowData *)window->driverdata;
   2.200 +        int w = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Width);
   2.201 +        int h = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Height);
   2.202 +        SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_WINDOWEVENT_SIZE_CHANGED, w, h);
   2.203 +    }
   2.204 +#endif
   2.205 +
   2.206  }
   2.207  
   2.208  void SDL_WinRTApp::SetWindow(CoreWindow^ window)
   2.209  {
   2.210  #if LOG_WINDOW_EVENTS==1
   2.211 -    SDL_Log("%s, current orientation=%d, native orientation=%d, auto rot. pref=%d, window Size={%f,%f}\n",
   2.212 +    SDL_Log("%s, current orientation=%d, native orientation=%d, auto rot. pref=%d, window bounds={%f, %f, %f,%f}\n",
   2.213          __FUNCTION__,
   2.214          WINRT_DISPLAY_PROPERTY(CurrentOrientation),
   2.215          WINRT_DISPLAY_PROPERTY(NativeOrientation),
   2.216          WINRT_DISPLAY_PROPERTY(AutoRotationPreferences),
   2.217 +        window->Bounds.X,
   2.218 +        window->Bounds.Y,
   2.219          window->Bounds.Width,
   2.220          window->Bounds.Height);
   2.221  #endif
   2.222 @@ -344,6 +321,9 @@
   2.223      window->VisibilityChanged +=
   2.224          ref new TypedEventHandler<CoreWindow^, VisibilityChangedEventArgs^>(this, &SDL_WinRTApp::OnVisibilityChanged);
   2.225  
   2.226 +    window->Activated +=
   2.227 +        ref new TypedEventHandler<CoreWindow^, WindowActivatedEventArgs^>(this, &SDL_WinRTApp::OnWindowActivated);
   2.228 +
   2.229      window->Closed += 
   2.230          ref new TypedEventHandler<CoreWindow^, CoreWindowEventArgs^>(this, &SDL_WinRTApp::OnWindowClosed);
   2.231  
   2.232 @@ -360,6 +340,12 @@
   2.233      window->PointerReleased +=
   2.234          ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &SDL_WinRTApp::OnPointerReleased);
   2.235  
   2.236 +    window->PointerEntered +=
   2.237 +        ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &SDL_WinRTApp::OnPointerEntered);
   2.238 +
   2.239 +    window->PointerExited +=
   2.240 +        ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &SDL_WinRTApp::OnPointerExited);
   2.241 +
   2.242      window->PointerWheelChanged +=
   2.243          ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &SDL_WinRTApp::OnPointerWheelChanged);
   2.244  
   2.245 @@ -535,9 +521,10 @@
   2.246  void SDL_WinRTApp::OnWindowSizeChanged(CoreWindow^ sender, WindowSizeChangedEventArgs^ args)
   2.247  {
   2.248  #if LOG_WINDOW_EVENTS==1
   2.249 -    SDL_Log("%s, size={%f,%f}, current orientation=%d, native orientation=%d, auto rot. pref=%d, WINRT_GlobalSDLWindow?=%s\n",
   2.250 +    SDL_Log("%s, size={%f,%f}, bounds={%f,%f,%f,%f}, current orientation=%d, native orientation=%d, auto rot. pref=%d, WINRT_GlobalSDLWindow?=%s\n",
   2.251          __FUNCTION__,
   2.252          args->Size.Width, args->Size.Height,
   2.253 +        sender->Bounds.X, sender->Bounds.Y, sender->Bounds.Width, sender->Bounds.Height,
   2.254          WINRT_DISPLAY_PROPERTY(CurrentOrientation),
   2.255          WINRT_DISPLAY_PROPERTY(NativeOrientation),
   2.256          WINRT_DISPLAY_PROPERTY(AutoRotationPreferences),
   2.257 @@ -550,20 +537,26 @@
   2.258  void SDL_WinRTApp::OnVisibilityChanged(CoreWindow^ sender, VisibilityChangedEventArgs^ args)
   2.259  {
   2.260  #if LOG_WINDOW_EVENTS==1
   2.261 -    SDL_Log("%s, visible?=%s, WINRT_GlobalSDLWindow?=%s\n",
   2.262 +    SDL_Log("%s, visible?=%s, bounds={%f,%f,%f,%f}, WINRT_GlobalSDLWindow?=%s\n",
   2.263          __FUNCTION__,
   2.264          (args->Visible ? "yes" : "no"),
   2.265 +        sender->Bounds.X, sender->Bounds.Y,
   2.266 +        sender->Bounds.Width, sender->Bounds.Height,
   2.267          (WINRT_GlobalSDLWindow ? "yes" : "no"));
   2.268  #endif
   2.269  
   2.270      m_windowVisible = args->Visible;
   2.271      if (WINRT_GlobalSDLWindow) {
   2.272          SDL_bool wasSDLWindowSurfaceValid = WINRT_GlobalSDLWindow->surface_valid;
   2.273 -
   2.274 +        Uint32 latestWindowFlags = WINRT_DetectWindowFlags(WINRT_GlobalSDLWindow);
   2.275          if (args->Visible) {
   2.276              SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_WINDOWEVENT_SHOWN, 0, 0);
   2.277              SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_WINDOWEVENT_FOCUS_GAINED, 0, 0);
   2.278 -            SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_WINDOWEVENT_RESTORED, 0, 0);
   2.279 +            if (latestWindowFlags & SDL_WINDOW_MAXIMIZED) {
   2.280 +                SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_WINDOWEVENT_MAXIMIZED, 0, 0);
   2.281 +            } else {
   2.282 +                SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_WINDOWEVENT_RESTORED, 0, 0);
   2.283 +            }
   2.284          } else {
   2.285              SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_WINDOWEVENT_HIDDEN, 0, 0);
   2.286              SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_WINDOWEVENT_FOCUS_LOST, 0, 0);
   2.287 @@ -580,6 +573,59 @@
   2.288      }
   2.289  }
   2.290  
   2.291 +void SDL_WinRTApp::OnWindowActivated(CoreWindow^ sender, WindowActivatedEventArgs^ args)
   2.292 +{
   2.293 +#if LOG_WINDOW_EVENTS==1
   2.294 +    SDL_Log("%s, WINRT_GlobalSDLWindow?=%s\n\n",
   2.295 +        __FUNCTION__,
   2.296 +        (WINRT_GlobalSDLWindow ? "yes" : "no"));
   2.297 +#endif
   2.298 +
   2.299 +    /* There's no property in Win 8.x to tell whether a window is active or
   2.300 +       not.  [De]activation events are, however, sent to the app.  We'll just
   2.301 +       record those, in case the CoreWindow gets wrapped by an SDL_Window at
   2.302 +       some future time.
   2.303 +    */
   2.304 +    sender->CustomProperties->Insert("SDLHelperWindowActivationState", args->WindowActivationState);
   2.305 +
   2.306 +    SDL_Window * window = WINRT_GlobalSDLWindow;
   2.307 +    if (window) {
   2.308 +        if (args->WindowActivationState != CoreWindowActivationState::Deactivated) {
   2.309 +            SDL_SendWindowEvent(window, SDL_WINDOWEVENT_SHOWN, 0, 0);
   2.310 +            if (SDL_GetKeyboardFocus() != window) {
   2.311 +                SDL_SetKeyboardFocus(window);
   2.312 +            }
   2.313 +        
   2.314 +            /* Send a mouse-motion event as appropriate.
   2.315 +               This doesn't work when called from OnPointerEntered, at least
   2.316 +               not in WinRT CoreWindow apps (as OnPointerEntered doesn't
   2.317 +               appear to be called after window-reactivation, at least not
   2.318 +               in Windows 10, Build 10586.3 (November 2015 update, non-beta).
   2.319 +
   2.320 +               Don't do it on WinPhone 8.0 though, as CoreWindow's 'PointerPosition'
   2.321 +               property isn't available.
   2.322 +             */
   2.323 +#if (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP) || (NTDDI_VERSION >= NTDDI_WINBLUE)
   2.324 +            Point cursorPos = WINRT_TransformCursorPosition(window, sender->PointerPosition, TransformToSDLWindowSize);
   2.325 +            SDL_SendMouseMotion(window, 0, 0, (int)cursorPos.X, (int)cursorPos.Y);
   2.326 +#endif
   2.327 +
   2.328 +            /* TODO, WinRT: see if the Win32 bugfix from https://hg.libsdl.org/SDL/rev/d278747da408 needs to be applied (on window activation) */
   2.329 +            //WIN_CheckAsyncMouseRelease(data);
   2.330 +
   2.331 +            /* TODO, WinRT: implement clipboard support, if possible */
   2.332 +            ///*
   2.333 +            // * FIXME: Update keyboard state
   2.334 +            // */
   2.335 +            //WIN_CheckClipboardUpdate(data->videodata);
   2.336 +        } else {
   2.337 +            if (SDL_GetKeyboardFocus() == window) {
   2.338 +                SDL_SetKeyboardFocus(NULL);
   2.339 +            }
   2.340 +        }
   2.341 +    }
   2.342 +}
   2.343 +
   2.344  void SDL_WinRTApp::OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args)
   2.345  {
   2.346  #if LOG_WINDOW_EVENTS==1
   2.347 @@ -588,7 +634,7 @@
   2.348      m_windowClosed = true;
   2.349  }
   2.350  
   2.351 -void SDL_WinRTApp::OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args)
   2.352 +void SDL_WinRTApp::OnAppActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args)
   2.353  {
   2.354      CoreWindow::GetForCurrentThread()->Activate();
   2.355  }
   2.356 @@ -688,8 +734,26 @@
   2.357  #if LOG_POINTER_EVENTS
   2.358      WINRT_LogPointerEvent("pointer released", args, WINRT_TransformCursorPosition(WINRT_GlobalSDLWindow, args->CurrentPoint->Position, TransformToSDLWindowSize));
   2.359  #endif
   2.360 +    
   2.361 +    WINRT_ProcessPointerReleasedEvent(WINRT_GlobalSDLWindow, args->CurrentPoint);
   2.362 +}
   2.363  
   2.364 -    WINRT_ProcessPointerReleasedEvent(WINRT_GlobalSDLWindow, args->CurrentPoint);
   2.365 +void SDL_WinRTApp::OnPointerEntered(CoreWindow^ sender, PointerEventArgs^ args)
   2.366 +{
   2.367 +#if LOG_POINTER_EVENTS
   2.368 +    WINRT_LogPointerEvent("pointer entered", args, WINRT_TransformCursorPosition(WINRT_GlobalSDLWindow, args->CurrentPoint->Position, TransformToSDLWindowSize));
   2.369 +#endif
   2.370 +
   2.371 +    WINRT_ProcessPointerEnteredEvent(WINRT_GlobalSDLWindow, args->CurrentPoint);
   2.372 +}
   2.373 +
   2.374 +void SDL_WinRTApp::OnPointerExited(CoreWindow^ sender, PointerEventArgs^ args)
   2.375 +{
   2.376 +#if LOG_POINTER_EVENTS
   2.377 +    WINRT_LogPointerEvent("pointer exited", args, WINRT_TransformCursorPosition(WINRT_GlobalSDLWindow, args->CurrentPoint->Position, TransformToSDLWindowSize));
   2.378 +#endif
   2.379 +
   2.380 +    WINRT_ProcessPointerExitedEvent(WINRT_GlobalSDLWindow, args->CurrentPoint);
   2.381  }
   2.382  
   2.383  void SDL_WinRTApp::OnPointerWheelChanged(CoreWindow^ sender, PointerEventArgs^ args)
     3.1 --- a/src/core/winrt/SDL_winrtapp_direct3d.h	Sun Nov 15 13:04:42 2015 -0500
     3.2 +++ b/src/core/winrt/SDL_winrtapp_direct3d.h	Thu Nov 26 00:41:39 2015 -0500
     3.3 @@ -56,16 +56,19 @@
     3.4  #endif
     3.5      void OnWindowSizeChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::WindowSizeChangedEventArgs^ args);
     3.6      void OnLogicalDpiChanged(Platform::Object^ sender);
     3.7 -    void OnActivated(Windows::ApplicationModel::Core::CoreApplicationView^ applicationView, Windows::ApplicationModel::Activation::IActivatedEventArgs^ args);
     3.8 +    void OnAppActivated(Windows::ApplicationModel::Core::CoreApplicationView^ applicationView, Windows::ApplicationModel::Activation::IActivatedEventArgs^ args);
     3.9      void OnSuspending(Platform::Object^ sender, Windows::ApplicationModel::SuspendingEventArgs^ args);
    3.10      void OnResuming(Platform::Object^ sender, Platform::Object^ args);
    3.11      void OnExiting(Platform::Object^ sender, Platform::Object^ args);
    3.12 +    void OnWindowActivated(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::WindowActivatedEventArgs^ args);
    3.13      void OnWindowClosed(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::CoreWindowEventArgs^ args);
    3.14      void OnVisibilityChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::VisibilityChangedEventArgs^ args);
    3.15      void OnPointerPressed(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
    3.16      void OnPointerReleased(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
    3.17      void OnPointerWheelChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
    3.18      void OnPointerMoved(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
    3.19 +    void OnPointerEntered(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
    3.20 +    void OnPointerExited(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
    3.21      void OnMouseMoved(Windows::Devices::Input::MouseDevice^ mouseDevice, Windows::Devices::Input::MouseEventArgs^ args);
    3.22      void OnKeyDown(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyEventArgs^ args);
    3.23      void OnKeyUp(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyEventArgs^ args);
     4.1 --- a/src/render/direct3d11/SDL_render_d3d11.c	Sun Nov 15 13:04:42 2015 -0500
     4.2 +++ b/src/render/direct3d11/SDL_render_d3d11.c	Thu Nov 26 00:41:39 2015 -0500
     4.3 @@ -760,8 +760,8 @@
     4.4  };
     4.5  
     4.6  
     4.7 -static Uint32
     4.8 -DXGIFormatToSDLPixelFormat(DXGI_FORMAT dxgiFormat) {
     4.9 +Uint32
    4.10 +D3D11_DXGIFormatToSDLPixelFormat(DXGI_FORMAT dxgiFormat) {
    4.11      switch (dxgiFormat) {
    4.12          case DXGI_FORMAT_B8G8R8A8_UNORM:
    4.13              return SDL_PIXELFORMAT_ARGB8888;
    4.14 @@ -2911,7 +2911,7 @@
    4.15       */
    4.16      if (SDL_ConvertPixels(
    4.17          rect->w, rect->h,
    4.18 -        DXGIFormatToSDLPixelFormat(stagingTextureDesc.Format),
    4.19 +        D3D11_DXGIFormatToSDLPixelFormat(stagingTextureDesc.Format),
    4.20          textureMemory.pData,
    4.21          textureMemory.RowPitch,
    4.22          format,
     5.1 --- a/src/video/SDL_video.c	Sun Nov 15 13:04:42 2015 -0500
     5.2 +++ b/src/video/SDL_video.c	Thu Nov 26 00:41:39 2015 -0500
     5.3 @@ -1125,6 +1125,10 @@
     5.4      }
     5.5  }
     5.6  
     5.7 +#if __WINRT__
     5.8 +extern Uint32 WINRT_DetectWindowFlags(SDL_Window * window);
     5.9 +#endif
    5.10 +
    5.11  static int
    5.12  SDL_UpdateFullscreenMode(SDL_Window * window, SDL_bool fullscreen)
    5.13  {
    5.14 @@ -1164,6 +1168,30 @@
    5.15          window->last_fullscreen_flags = window->flags;
    5.16          return 0;
    5.17      }
    5.18 +#elif __WINRT__
    5.19 +    /* HACK: WinRT 8.x apps can't choose whether or not they are fullscreen
    5.20 +       or not.  The user can choose this, via OS-provided UI, but this can't
    5.21 +       be set programmatically.
    5.22 +
    5.23 +       Just look at what SDL's WinRT video backend code detected with regards
    5.24 +       to fullscreen (being active, or not), and figure out a return/error code
    5.25 +       from that.
    5.26 +    */
    5.27 +    if (fullscreen == !(WINRT_DetectWindowFlags(window) & FULLSCREEN_MASK)) {
    5.28 +        /* Uh oh, either:
    5.29 +            1. fullscreen was requested, and we're already windowed
    5.30 +            2. windowed-mode was requested, and we're already fullscreen
    5.31 +
    5.32 +            WinRT 8.x can't resolve either programmatically, so we're
    5.33 +            giving up.
    5.34 +        */
    5.35 +        return -1;
    5.36 +    } else {
    5.37 +        /* Whatever was requested, fullscreen or windowed mode, is already
    5.38 +            in-place.
    5.39 +        */
    5.40 +        return 0;
    5.41 +    }
    5.42  #endif
    5.43  
    5.44      display = SDL_GetDisplayForWindow(window);
    5.45 @@ -1377,6 +1405,18 @@
    5.46          return NULL;
    5.47      }
    5.48  
    5.49 +#if __WINRT__
    5.50 +    /* HACK: WinRT 8.x apps can't choose whether or not they are fullscreen
    5.51 +       or not.  The user can choose this, via OS-provided UI, but this can't
    5.52 +       be set programmatically.
    5.53 +
    5.54 +       Just look at what SDL's WinRT video backend code detected with regards
    5.55 +       to fullscreen (being active, or not), and figure out a return/error code
    5.56 +       from that.
    5.57 +    */
    5.58 +    flags = window->flags;
    5.59 +#endif
    5.60 +
    5.61      if (title) {
    5.62          SDL_SetWindowTitle(window, title);
    5.63      }
     6.1 --- a/src/video/winrt/SDL_winrtevents_c.h	Sun Nov 15 13:04:42 2015 -0500
     6.2 +++ b/src/video/winrt/SDL_winrtevents_c.h	Thu Nov 26 00:41:39 2015 -0500
     6.3 @@ -57,6 +57,8 @@
     6.4  extern void WINRT_ProcessPointerPressedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint);
     6.5  extern void WINRT_ProcessPointerMovedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint);
     6.6  extern void WINRT_ProcessPointerReleasedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint);
     6.7 +extern void WINRT_ProcessPointerEnteredEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint);
     6.8 +extern void WINRT_ProcessPointerExitedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint);
     6.9  extern void WINRT_ProcessPointerWheelChangedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint);
    6.10  extern void WINRT_ProcessMouseMovedEvent(SDL_Window * window, Windows::Devices::Input::MouseEventArgs ^args);
    6.11  
     7.1 --- a/src/video/winrt/SDL_winrtpointerinput.cpp	Sun Nov 15 13:04:42 2015 -0500
     7.2 +++ b/src/video/winrt/SDL_winrtpointerinput.cpp	Thu Nov 26 00:41:39 2015 -0500
     7.3 @@ -306,6 +306,28 @@
     7.4      }
     7.5  }
     7.6  
     7.7 +void WINRT_ProcessPointerEnteredEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint)
     7.8 +{
     7.9 +    if (!window) {
    7.10 +        return;
    7.11 +    }
    7.12 +
    7.13 +    if (!WINRT_IsTouchEvent(pointerPoint)) {
    7.14 +        SDL_SetMouseFocus(window);
    7.15 +    }
    7.16 +}
    7.17 +
    7.18 +void WINRT_ProcessPointerExitedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint)
    7.19 +{
    7.20 +    if (!window) {
    7.21 +        return;
    7.22 +    }
    7.23 +
    7.24 +    if (!WINRT_IsTouchEvent(pointerPoint)) {
    7.25 +        SDL_SetMouseFocus(NULL);
    7.26 +    }
    7.27 +}
    7.28 +
    7.29  void
    7.30  WINRT_ProcessPointerWheelChangedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint)
    7.31  {
     8.1 --- a/src/video/winrt/SDL_winrtvideo.cpp	Sun Nov 15 13:04:42 2015 -0500
     8.2 +++ b/src/video/winrt/SDL_winrtvideo.cpp	Thu Nov 26 00:41:39 2015 -0500
     8.3 @@ -30,8 +30,17 @@
     8.4  
     8.5  /* Windows includes */
     8.6  #include <agile.h>
     8.7 -#include <wrl/client.h>
     8.8 +#include <windows.graphics.display.h>
     8.9 +#include <dxgi.h>
    8.10 +#include <dxgi1_2.h>
    8.11 +using namespace Windows::ApplicationModel::Core;
    8.12 +using namespace Windows::Foundation;
    8.13  using namespace Windows::UI::Core;
    8.14 +using namespace Windows::UI::ViewManagement;
    8.15 +
    8.16 +
    8.17 +/* [re]declare Windows GUIDs locally, to limit the amount of external lib(s) SDL has to link to */
    8.18 +static const GUID IID_IDXGIFactory2 = { 0x50c83a1c, 0xe072, 0x4c48,{ 0x87, 0xb0, 0x36, 0x30, 0xfa, 0x36, 0xa6, 0xd0 } };
    8.19  
    8.20  
    8.21  /* SDL includes */
    8.22 @@ -44,6 +53,7 @@
    8.23  #include "../../render/SDL_sysrender.h"
    8.24  #include "SDL_syswm.h"
    8.25  #include "SDL_winrtopengles.h"
    8.26 +#include "../../core/windows/SDL_windows.h"
    8.27  }
    8.28  
    8.29  #include "../../core/winrt/SDL_winrtapp_direct3d.h"
    8.30 @@ -161,110 +171,178 @@
    8.31      return 0;
    8.32  }
    8.33  
    8.34 -int
    8.35 -WINRT_CalcDisplayModeUsingNativeWindow(SDL_DisplayMode * mode)
    8.36 +extern "C"
    8.37 +Uint32 D3D11_DXGIFormatToSDLPixelFormat(DXGI_FORMAT dxgiFormat);
    8.38 +
    8.39 +static void
    8.40 +WINRT_DXGIModeToSDLDisplayMode(const DXGI_MODE_DESC * dxgiMode, SDL_DisplayMode * sdlMode)
    8.41  {
    8.42 -    SDL_DisplayModeData * driverdata;
    8.43 +    SDL_zerop(sdlMode);
    8.44 +    sdlMode->w = dxgiMode->Width;
    8.45 +    sdlMode->h = dxgiMode->Height;
    8.46 +    sdlMode->refresh_rate = dxgiMode->RefreshRate.Numerator / dxgiMode->RefreshRate.Denominator;
    8.47 +    sdlMode->format = D3D11_DXGIFormatToSDLPixelFormat(dxgiMode->Format);
    8.48 +}
    8.49  
    8.50 -    using namespace Windows::Graphics::Display;
    8.51 +static int
    8.52 +WINRT_AddDisplaysForOutput (_THIS, IDXGIAdapter1 * dxgiAdapter1, int outputIndex)
    8.53 +{
    8.54 +    HRESULT hr;
    8.55 +    IDXGIOutput * dxgiOutput = NULL;
    8.56 +    DXGI_OUTPUT_DESC dxgiOutputDesc;
    8.57 +    SDL_VideoDisplay display;
    8.58 +    char * displayName = NULL;
    8.59 +    UINT numModes;
    8.60 +    DXGI_MODE_DESC * dxgiModes = NULL;
    8.61 +    int functionResult = -1;        /* -1 for failure, 0 for success */
    8.62 +    DXGI_MODE_DESC modeToMatch, closestMatch;
    8.63  
    8.64 -    // Go no further if a native window cannot be accessed.  This can happen,
    8.65 -    // for example, if this function is called from certain threads, such as
    8.66 -    // the SDL/XAML thread.
    8.67 -    if (!CoreWindow::GetForCurrentThread()) {
    8.68 -        return SDL_SetError("SDL/WinRT display modes cannot be calculated outside of the main thread, such as in SDL's XAML thread");
    8.69 +    SDL_zero(display);
    8.70 +
    8.71 +    hr = dxgiAdapter1->EnumOutputs(outputIndex, &dxgiOutput);
    8.72 +    if (FAILED(hr)) {
    8.73 +        if (hr != DXGI_ERROR_NOT_FOUND) {
    8.74 +            WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIAdapter1::EnumOutputs failed", hr);
    8.75 +        }
    8.76 +        goto done;
    8.77      }
    8.78  
    8.79 -    //SDL_Log("%s, size={%f,%f}, current orientation=%d, native orientation=%d, auto rot. pref=%d, DPI = %f\n",
    8.80 -    //    __FUNCTION__,
    8.81 -    //    CoreWindow::GetForCurrentThread()->Bounds.Width, CoreWindow::GetForCurrentThread()->Bounds.Height,
    8.82 -    //    WINRT_DISPLAY_PROPERTY(CurrentOrientation),
    8.83 -    //    WINRT_DISPLAY_PROPERTY(NativeOrientation),
    8.84 -    //    WINRT_DISPLAY_PROPERTY(AutoRotationPreferences),
    8.85 -    //    WINRT_DISPLAY_PROPERTY(LogicalDpi));
    8.86 -
    8.87 -    // Calculate the display size given the window size, taking into account
    8.88 -    // the current display's DPI:
    8.89 -    const float currentDPI = WINRT_DISPLAY_PROPERTY(LogicalDpi);
    8.90 -    const float dipsPerInch = 96.0f;
    8.91 -    const int w = (int) ((CoreWindow::GetForCurrentThread()->Bounds.Width * currentDPI) / dipsPerInch);
    8.92 -    const int h = (int) ((CoreWindow::GetForCurrentThread()->Bounds.Height * currentDPI) / dipsPerInch);
    8.93 -    if (w == 0 || w == h) {
    8.94 -        return SDL_SetError("Unable to calculate the WinRT window/display's size");
    8.95 +    hr = dxgiOutput->GetDesc(&dxgiOutputDesc);
    8.96 +    if (FAILED(hr)) {
    8.97 +        WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIOutput::GetDesc failed", hr);
    8.98 +        goto done;
    8.99      }
   8.100  
   8.101 -    // Create a driverdata field:
   8.102 -    driverdata = (SDL_DisplayModeData *) SDL_malloc(sizeof(*driverdata));
   8.103 -    if (!driverdata) {
   8.104 -        return SDL_OutOfMemory();
   8.105 +    SDL_zero(modeToMatch);
   8.106 +    modeToMatch.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
   8.107 +    modeToMatch.Width = (dxgiOutputDesc.DesktopCoordinates.right - dxgiOutputDesc.DesktopCoordinates.left);
   8.108 +    modeToMatch.Height = (dxgiOutputDesc.DesktopCoordinates.bottom - dxgiOutputDesc.DesktopCoordinates.top);
   8.109 +    hr = dxgiOutput->FindClosestMatchingMode(&modeToMatch, &closestMatch, NULL);
   8.110 +    if (hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE) {
   8.111 +        /* DXGI_ERROR_NOT_CURRENTLY_AVAILABLE gets returned by IDXGIOutput::FindClosestMatchingMode
   8.112 +           when running under the Windows Simulator, which uses Remote Desktop (formerly known as Terminal
   8.113 +           Services) under the hood.  According to the MSDN docs for the similar function,
   8.114 +           IDXGIOutput::GetDisplayModeList, DXGI_ERROR_NOT_CURRENTLY_AVAILABLE is returned if and
   8.115 +           when an app is run under a Terminal Services session, hence the assumption.
   8.116 +
   8.117 +           In this case, just add an SDL display mode, with approximated values.
   8.118 +        */
   8.119 +        SDL_DisplayMode mode;
   8.120 +        SDL_zero(mode);
   8.121 +        display.name = "Windows Simulator / Terminal Services Display";
   8.122 +        mode.w = (dxgiOutputDesc.DesktopCoordinates.right - dxgiOutputDesc.DesktopCoordinates.left);
   8.123 +        mode.h = (dxgiOutputDesc.DesktopCoordinates.bottom - dxgiOutputDesc.DesktopCoordinates.top);
   8.124 +        mode.format = DXGI_FORMAT_B8G8R8A8_UNORM;
   8.125 +        mode.refresh_rate = 0;  /* Display mode is unknown, so just fill in zero, as specified by SDL's header files */
   8.126 +        display.desktop_mode = mode;
   8.127 +        display.current_mode = mode;
   8.128 +        if ( ! SDL_AddDisplayMode(&display, &mode)) {
   8.129 +            goto done;
   8.130 +        }
   8.131 +    } else if (FAILED(hr)) {
   8.132 +        WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIOutput::FindClosestMatchingMode failed", hr);
   8.133 +        goto done;
   8.134 +    } else {
   8.135 +        displayName = WIN_StringToUTF8(dxgiOutputDesc.DeviceName);
   8.136 +        display.name = displayName;
   8.137 +        WINRT_DXGIModeToSDLDisplayMode(&closestMatch, &display.desktop_mode);
   8.138 +        display.current_mode = display.desktop_mode;
   8.139 +
   8.140 +        hr = dxgiOutput->GetDisplayModeList(DXGI_FORMAT_B8G8R8A8_UNORM, 0, &numModes, NULL);
   8.141 +        if (FAILED(hr)) {
   8.142 +            if (hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE) {
   8.143 +                // TODO, WinRT: make sure display mode(s) are added when using Terminal Services / Windows Simulator
   8.144 +            }
   8.145 +            WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIOutput::GetDisplayModeList [get mode list size] failed", hr);
   8.146 +            goto done;
   8.147 +        }
   8.148 +
   8.149 +        dxgiModes = (DXGI_MODE_DESC *)SDL_calloc(numModes, sizeof(DXGI_MODE_DESC));
   8.150 +        if ( ! dxgiModes) {
   8.151 +            SDL_OutOfMemory();
   8.152 +            goto done;
   8.153 +        }
   8.154 +
   8.155 +        hr = dxgiOutput->GetDisplayModeList(DXGI_FORMAT_B8G8R8A8_UNORM, 0, &numModes, dxgiModes);
   8.156 +        if (FAILED(hr)) {
   8.157 +            WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIOutput::GetDisplayModeList [get mode contents] failed", hr);
   8.158 +            goto done;
   8.159 +        }
   8.160 +
   8.161 +        for (UINT i = 0; i < numModes; ++i) {
   8.162 +            SDL_DisplayMode sdlMode;
   8.163 +            WINRT_DXGIModeToSDLDisplayMode(&dxgiModes[i], &sdlMode);
   8.164 +            SDL_AddDisplayMode(&display, &sdlMode);
   8.165 +        }
   8.166      }
   8.167 -    SDL_zerop(driverdata);
   8.168  
   8.169 -    // Fill in most fields:
   8.170 -    SDL_zerop(mode);
   8.171 -    mode->format = SDL_PIXELFORMAT_RGB888;
   8.172 -    mode->refresh_rate = 0;  // TODO, WinRT: see if refresh rate data is available, or relevant (for WinRT apps)
   8.173 -    mode->w = w;
   8.174 -    mode->h = h;
   8.175 -    mode->driverdata = driverdata;
   8.176 -    driverdata->currentOrientation = WINRT_DISPLAY_PROPERTY(CurrentOrientation);
   8.177 +    if (SDL_AddVideoDisplay(&display) < 0) {
   8.178 +        goto done;
   8.179 +    }
   8.180  
   8.181 -#if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) && (NTDDI_VERSION == NTDDI_WIN8)
   8.182 -    // On Windows Phone 8.0, the native window's size is always in portrait,
   8.183 -    // regardless of the device's orientation.  This is in contrast to
   8.184 -    // Windows 8.x/RT and Windows Phone 8.1, which will resize the native window as the device's
   8.185 -    // orientation changes.  In order to compensate for this behavior,
   8.186 -    // on Windows Phone, the mode's width and height will be swapped when
   8.187 -    // the device is in a landscape (non-portrait) mode.
   8.188 -    switch (driverdata->currentOrientation) {
   8.189 -        case DisplayOrientations::Landscape:
   8.190 -        case DisplayOrientations::LandscapeFlipped:
   8.191 -        {
   8.192 -            const int tmp = mode->h;
   8.193 -            mode->h = mode->w;
   8.194 -            mode->w = tmp;
   8.195 +    functionResult = 0;     /* 0 for Success! */
   8.196 +done:
   8.197 +    if (dxgiModes) {
   8.198 +        SDL_free(dxgiModes);
   8.199 +    }
   8.200 +    if (dxgiOutput) {
   8.201 +        dxgiOutput->Release();
   8.202 +    }
   8.203 +    if (displayName) {
   8.204 +        SDL_free(displayName);
   8.205 +    }
   8.206 +    return functionResult;
   8.207 +}
   8.208 +
   8.209 +static int
   8.210 +WINRT_AddDisplaysForAdapter (_THIS, IDXGIFactory2 * dxgiFactory2, int adapterIndex)
   8.211 +{
   8.212 +    HRESULT hr;
   8.213 +    IDXGIAdapter1 * dxgiAdapter1;
   8.214 +
   8.215 +    hr = dxgiFactory2->EnumAdapters1(adapterIndex, &dxgiAdapter1);
   8.216 +    if (FAILED(hr)) {
   8.217 +        if (hr != DXGI_ERROR_NOT_FOUND) {
   8.218 +            WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIFactory1::EnumAdapters1() failed", hr);
   8.219 +        }
   8.220 +        return -1;
   8.221 +    }
   8.222 +
   8.223 +    for (int outputIndex = 0; ; ++outputIndex) {
   8.224 +        if (WINRT_AddDisplaysForOutput(_this, dxgiAdapter1, outputIndex) < 0) {
   8.225              break;
   8.226          }
   8.227 +    }
   8.228  
   8.229 -        default:
   8.230 -            break;
   8.231 -    }
   8.232 -#endif
   8.233 -
   8.234 -    return 0;
   8.235 -}
   8.236 -
   8.237 -int
   8.238 -WINRT_DuplicateDisplayMode(SDL_DisplayMode * dest, const SDL_DisplayMode * src)
   8.239 -{
   8.240 -    SDL_DisplayModeData * driverdata;
   8.241 -    driverdata = (SDL_DisplayModeData *) SDL_malloc(sizeof(*driverdata));
   8.242 -    if (!driverdata) {
   8.243 -        return SDL_OutOfMemory();
   8.244 -    }
   8.245 -    SDL_memcpy(driverdata, src->driverdata, sizeof(SDL_DisplayModeData));
   8.246 -    SDL_memcpy(dest, src, sizeof(SDL_DisplayMode));
   8.247 -    dest->driverdata = driverdata;
   8.248 +    dxgiAdapter1->Release();
   8.249      return 0;
   8.250  }
   8.251  
   8.252  int
   8.253  WINRT_InitModes(_THIS)
   8.254  {
   8.255 -    // Retrieve the display mode:
   8.256 -    SDL_DisplayMode mode, desktop_mode;
   8.257 -    if (WINRT_CalcDisplayModeUsingNativeWindow(&mode) != 0) {
   8.258 -        return -1;	// If WINRT_CalcDisplayModeUsingNativeWindow fails, it'll already have set the SDL error
   8.259 -    }
   8.260 +    /* HACK: Initialize a single display, for whatever screen the app's
   8.261 +         CoreApplicationView is on.
   8.262 +       TODO, WinRT: Try initializing multiple displays, one for each monitor.
   8.263 +         Appropriate WinRT APIs for this seem elusive, though.  -- DavidL
   8.264 +    */
   8.265  
   8.266 -    if (WINRT_DuplicateDisplayMode(&desktop_mode, &mode) != 0) {
   8.267 -        return -1;
   8.268 -    }
   8.269 -    if (SDL_AddBasicVideoDisplay(&desktop_mode) < 0) {
   8.270 +    HRESULT hr;
   8.271 +    IDXGIFactory2 * dxgiFactory2 = NULL;
   8.272 +
   8.273 +    hr = CreateDXGIFactory1(IID_IDXGIFactory2, (void **)&dxgiFactory2);
   8.274 +    if (FAILED(hr)) {
   8.275 +        WIN_SetErrorFromHRESULT(__FUNCTION__ ", CreateDXGIFactory1() failed", hr);
   8.276          return -1;
   8.277      }
   8.278  
   8.279 -    SDL_AddDisplayMode(&_this->displays[0], &mode);
   8.280 +    int adapterIndex = 0;
   8.281 +    for (int adapterIndex = 0; ; ++adapterIndex) {
   8.282 +        if (WINRT_AddDisplaysForAdapter(_this, dxgiFactory2, adapterIndex) < 0) {
   8.283 +            break;
   8.284 +        }
   8.285 +    }
   8.286 +
   8.287      return 0;
   8.288  }
   8.289  
   8.290 @@ -280,6 +358,64 @@
   8.291      WINRT_QuitMouse(_this);
   8.292  }
   8.293  
   8.294 +extern "C" Uint32
   8.295 +WINRT_DetectWindowFlags(SDL_Window * window)
   8.296 +{
   8.297 +    Uint32 latestFlags = 0;
   8.298 +    SDL_WindowData * data = (SDL_WindowData *) window->driverdata;
   8.299 +    bool is_fullscreen = false;
   8.300 +
   8.301 +#if SDL_WINRT_USE_APPLICATIONVIEW
   8.302 +    if (data->appView) {
   8.303 +        is_fullscreen = data->appView->IsFullScreen;
   8.304 +    }
   8.305 +#elif (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
   8.306 +    is_fullscreen = true;
   8.307 +#endif
   8.308 +
   8.309 +    if (data->coreWindow.Get()) {
   8.310 +        if (is_fullscreen) {
   8.311 +            SDL_VideoDisplay * display = SDL_GetDisplayForWindow(window);
   8.312 +            if (display->desktop_mode.w != WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Width) ||
   8.313 +                display->desktop_mode.h != WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Height))
   8.314 +            {
   8.315 +                latestFlags |= SDL_WINDOW_MAXIMIZED;
   8.316 +            } else {
   8.317 +                latestFlags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
   8.318 +            }
   8.319 +        }
   8.320 +
   8.321 +        if (data->coreWindow->Visible) {
   8.322 +            latestFlags |= SDL_WINDOW_SHOWN;
   8.323 +        } else {
   8.324 +            latestFlags |= SDL_WINDOW_HIDDEN;
   8.325 +        }
   8.326 +
   8.327 +#if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) && (NTDDI_VERSION < NTDDI_WINBLUE)
   8.328 +        // data->coreWindow->PointerPosition is not supported on WinPhone 8.0
   8.329 +        latestFlags |= SDL_WINDOW_MOUSE_FOCUS;
   8.330 +#else
   8.331 +        if (data->coreWindow->Bounds.Contains(data->coreWindow->PointerPosition)) {
   8.332 +            latestFlags |= SDL_WINDOW_MOUSE_FOCUS;
   8.333 +        }
   8.334 +#endif
   8.335 +    }
   8.336 +
   8.337 +    return latestFlags;
   8.338 +}
   8.339 +
   8.340 +void
   8.341 +WINRT_UpdateWindowFlags(SDL_Window * window, Uint32 mask)
   8.342 +{
   8.343 +    if (window) {
   8.344 +        Uint32 apply = WINRT_DetectWindowFlags(window);
   8.345 +        if ((apply & mask) & SDL_WINDOW_FULLSCREEN) {
   8.346 +            window->last_fullscreen_flags = window->flags;  // seems necessary to programmatically un-fullscreen, via SDL APIs
   8.347 +        }
   8.348 +        window->flags = (window->flags & ~mask) | (apply & mask);
   8.349 +    }
   8.350 +}
   8.351 +
   8.352  int
   8.353  WINRT_CreateWindow(_THIS, SDL_Window * window)
   8.354  {
   8.355 @@ -290,7 +426,7 @@
   8.356          return -1;
   8.357      }
   8.358  
   8.359 -    SDL_WindowData *data = new SDL_WindowData;
   8.360 +    SDL_WindowData *data = new SDL_WindowData;  /* use 'new' here as SDL_WindowData may use WinRT/C++ types */
   8.361      if (!data) {
   8.362          SDL_OutOfMemory();
   8.363          return -1;
   8.364 @@ -306,6 +442,9 @@
   8.365      */
   8.366      if (!WINRT_XAMLWasEnabled) {
   8.367          data->coreWindow = CoreWindow::GetForCurrentThread();
   8.368 +#if SDL_WINRT_USE_APPLICATIONVIEW
   8.369 +        data->appView = ApplicationView::GetForCurrentView();
   8.370 +#endif
   8.371      }
   8.372  
   8.373  #if SDL_VIDEO_OPENGL_EGL
   8.374 @@ -359,17 +498,18 @@
   8.375      }
   8.376  #endif
   8.377  
   8.378 -    /* Make sure the window is considered to be positioned at {0,0},
   8.379 -       and is considered fullscreen, shown, and the like.
   8.380 -    */
   8.381 -    window->x = 0;
   8.382 -    window->y = 0;
   8.383 +#if SDL_WINRT_USE_APPLICATIONVIEW
   8.384 +    /* Determine as many flags dynamically, as possible. */
   8.385      window->flags =
   8.386 -        SDL_WINDOW_FULLSCREEN |
   8.387 -        SDL_WINDOW_SHOWN |
   8.388 +        SDL_WINDOW_BORDERLESS;
   8.389 +#else
   8.390 +    /* Set SDL_Window flags for Windows Phone 8.0 */
   8.391 +    window->flags =
   8.392 +        SDL_WINDOW_FULLSCREEN_DESKTOP |
   8.393          SDL_WINDOW_BORDERLESS |
   8.394          SDL_WINDOW_MAXIMIZED |
   8.395          SDL_WINDOW_INPUT_GRABBED;
   8.396 +#endif
   8.397  
   8.398  #if SDL_VIDEO_OPENGL_EGL
   8.399      if (data->egl_surface) {
   8.400 @@ -377,20 +517,40 @@
   8.401      }
   8.402  #endif
   8.403  
   8.404 -    /* WinRT does not, as of this writing, appear to support app-adjustable
   8.405 -       window sizes.  Set the window size to whatever the native WinRT
   8.406 -       CoreWindow is set at.
   8.407 +    if (WINRT_XAMLWasEnabled) {
   8.408 +        /* TODO, WinRT: set SDL_Window size, maybe position too, from XAML control */
   8.409 +        window->x = 0;
   8.410 +        window->y = 0;
   8.411 +        window->flags |= SDL_WINDOW_SHOWN;
   8.412 +        SDL_SetMouseFocus(NULL);        // TODO: detect this
   8.413 +        SDL_SetKeyboardFocus(NULL);     // TODO: detect this
   8.414 +    } else {
   8.415 +        /* WinRT apps seem to live in an environment where the OS controls the
   8.416 +           app's window size, with some apps being fullscreen, depending on
   8.417 +           user choice of various things.  For now, just adapt the SDL_Window to
   8.418 +           whatever Windows set-up as the native-window's geometry.
   8.419 +        */
   8.420 +        window->x = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Left);
   8.421 +        window->y = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Top);
   8.422 +        window->w = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Width);
   8.423 +        window->h = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Height);
   8.424  
   8.425 -       TODO, WinRT: if and when non-fullscreen XAML control support is added to SDL, consider making those resizable via SDL_Window's interfaces.
   8.426 -    */
   8.427 -    window->w = _this->displays[0].current_mode.w;
   8.428 -    window->h = _this->displays[0].current_mode.h;
   8.429 +        WINRT_UpdateWindowFlags(
   8.430 +            window,
   8.431 +            0xffffffff      /* Update any window flag(s) that WINRT_UpdateWindow can handle */
   8.432 +        );
   8.433  
   8.434 -    /* For now, treat WinRT apps as if they always have focus.
   8.435 -       TODO, WinRT: try tracking keyboard and mouse focus state with respect to snapped apps
   8.436 -     */
   8.437 -    SDL_SetMouseFocus(window);
   8.438 -    SDL_SetKeyboardFocus(window);
   8.439 +        /* Try detecting if the window is active */
   8.440 +        bool isWindowActive = true;     /* Presume the window is active, unless we've been told otherwise */
   8.441 +        if (data->coreWindow->CustomProperties->HasKey("SDLHelperWindowActivationState")) {
   8.442 +            CoreWindowActivationState activationState = \
   8.443 +                safe_cast<CoreWindowActivationState>(data->coreWindow->CustomProperties->Lookup("SDLHelperWindowActivationState"));
   8.444 +            isWindowActive = (activationState != CoreWindowActivationState::Deactivated);
   8.445 +        }
   8.446 +        if (isWindowActive) {
   8.447 +            SDL_SetKeyboardFocus(window);
   8.448 +        }
   8.449 +    }
   8.450   
   8.451      /* Make sure the WinRT app's IFramworkView can post events on
   8.452         behalf of SDL:
     9.1 --- a/src/video/winrt/SDL_winrtvideo_cpp.h	Sun Nov 15 13:04:42 2015 -0500
     9.2 +++ b/src/video/winrt/SDL_winrtvideo_cpp.h	Thu Nov 26 00:41:39 2015 -0500
     9.3 @@ -29,6 +29,12 @@
     9.4  #include "SDL_video.h"
     9.5  #include "SDL_events.h"
     9.6  
     9.7 +#if NTDDI_VERSION >= NTDDI_WINBLUE  /* ApplicationView's functionality only becomes
     9.8 +                                       useful for SDL in Win[Phone] 8.1 and up.
     9.9 +                                       Plus, it is not available at all in WinPhone 8.0. */
    9.10 +#define SDL_WINRT_USE_APPLICATIONVIEW 1
    9.11 +#endif
    9.12 +
    9.13  extern "C" {
    9.14  #include "../SDL_sysvideo.h"
    9.15  #include "../SDL_egl_c.h"
    9.16 @@ -48,25 +54,17 @@
    9.17  */
    9.18  extern SDL_Window * WINRT_GlobalSDLWindow;
    9.19  
    9.20 -/* Creates a display mode for Plain Direct3D (non-XAML) apps, using the lone, native window's settings.
    9.21 -
    9.22 -   Pass in an allocated SDL_DisplayMode field to store the data in.
    9.23 -
    9.24 -   This function will return 0 on success, -1 on failure.
    9.25 -
    9.26 -   If this function succeeds, be sure to call SDL_free on the
    9.27 -   SDL_DisplayMode's driverdata field.
    9.28 +/* Updates one or more SDL_Window flags, by querying the OS' native windowing APIs.
    9.29 +   SDL_Window flags that can be updated should be specified in 'mask'.
    9.30  */
    9.31 -extern int WINRT_CalcDisplayModeUsingNativeWindow(SDL_DisplayMode * mode);
    9.32 -
    9.33 -/* Duplicates a display mode, copying over driverdata as necessary */
    9.34 -extern int WINRT_DuplicateDisplayMode(SDL_DisplayMode * dest, const SDL_DisplayMode * src);
    9.35 +extern void WINRT_UpdateWindowFlags(SDL_Window * window, Uint32 mask);
    9.36 +extern "C" Uint32 WINRT_DetectWindowFlags(SDL_Window * window);  /* detects flags w/o applying them */
    9.37  
    9.38  /* Display mode internals */
    9.39 -typedef struct
    9.40 -{
    9.41 -    Windows::Graphics::Display::DisplayOrientations currentOrientation;
    9.42 -} SDL_DisplayModeData;
    9.43 +//typedef struct
    9.44 +//{
    9.45 +//    Windows::Graphics::Display::DisplayOrientations currentOrientation;
    9.46 +//} SDL_DisplayModeData;
    9.47  
    9.48  #ifdef __cplusplus_winrt
    9.49  
    9.50 @@ -77,6 +75,10 @@
    9.51  #define WINRT_DISPLAY_PROPERTY(NAME) (Windows::Graphics::Display::DisplayProperties::NAME)
    9.52  #endif
    9.53  
    9.54 +/* Converts DIPS to physical pixels */
    9.55 +#define WINRT_DIPS_TO_PHYSICAL_PIXELS(DIPS) ((int)(0.5f + (((float)(DIPS) * (float)WINRT_DISPLAY_PROPERTY(LogicalDpi)) / 96.f)))
    9.56 +
    9.57 +
    9.58  /* Internal window data */
    9.59  struct SDL_WindowData
    9.60  {
    9.61 @@ -85,6 +87,9 @@
    9.62  #ifdef SDL_VIDEO_OPENGL_EGL
    9.63      EGLSurface egl_surface;
    9.64  #endif
    9.65 +#if SDL_WINRT_USE_APPLICATIONVIEW
    9.66 +    Windows::UI::ViewManagement::ApplicationView ^ appView;
    9.67 +#endif
    9.68  };
    9.69  
    9.70  #endif // ifdef __cplusplus_winrt