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).
--- a/include/SDL_config_winrt.h Sun Nov 15 13:04:42 2015 -0500
+++ b/include/SDL_config_winrt.h Thu Nov 26 00:41:39 2015 -0500
@@ -19,11 +19,23 @@
3. This notice may not be removed or altered from any source distribution.
*/
-#ifndef _SDL_config_windows_h
-#define _SDL_config_windows_h
+#ifndef _SDL_config_winrt_h
+#define _SDL_config_winrt_h
#include "SDL_platform.h"
+/* Make sure the Windows SDK's NTDDI_VERSION macro gets defined. This is used
+ by SDL to determine which version of the Windows SDK is being used.
+*/
+#include <sdkddkver.h>
+
+/* Define possibly-undefined NTDDI values (used when compiling SDL against
+ older versions of the Windows SDK.
+*/
+#ifndef NTDDI_WINBLUE
+#define NTDDI_WINBLUE 0x06030000
+#endif
+
/* This is a set of defines to configure the SDL features */
#if !defined(_STDINT_H_) && (!defined(HAVE_STDINT_H) || !_HAVE_STDINT_H)
@@ -191,4 +203,4 @@
#define SDL_ASSEMBLY_ROUTINES 1
#endif
-#endif /* _SDL_config_windows_h */
+#endif /* _SDL_config_winrt_h */
--- a/src/core/winrt/SDL_winrtapp_direct3d.cpp Sun Nov 15 13:04:42 2015 -0500
+++ b/src/core/winrt/SDL_winrtapp_direct3d.cpp Thu Nov 26 00:41:39 2015 -0500
@@ -184,97 +184,48 @@
}
static void
-WINRT_ProcessWindowSizeChange()
+WINRT_ProcessWindowSizeChange() // TODO: Pass an SDL_Window-identifying thing into WINRT_ProcessWindowSizeChange()
{
- SDL_VideoDevice *_this = SDL_GetVideoDevice();
+ CoreWindow ^ coreWindow = CoreWindow::GetForCurrentThread();
+ if (coreWindow) {
+ if (WINRT_GlobalSDLWindow) {
+ SDL_Window * window = WINRT_GlobalSDLWindow;
+ SDL_WindowData * data = (SDL_WindowData *) window->driverdata;
- // Make the new window size be the one true fullscreen mode.
- // This change was initially done, in part, to allow the Direct3D 11.1
- // renderer to receive window-resize events as a device rotates.
- // Before, rotating a device from landscape, to portrait, and then
- // back to landscape would cause the Direct3D 11.1 swap buffer to
- // not get resized appropriately. SDL would, on the rotation from
- // landscape to portrait, re-resize the SDL window to it's initial
- // size (landscape). On the subsequent rotation, SDL would drop the
- // window-resize event as it appeared the SDL window didn't change
- // size, and the Direct3D 11.1 renderer wouldn't resize its swap
- // chain.
- SDL_DisplayMode newDisplayMode;
- if (WINRT_CalcDisplayModeUsingNativeWindow(&newDisplayMode) != 0) {
- return;
- }
-
- // Make note of the old display mode, and it's old driverdata.
- SDL_DisplayMode oldDisplayMode;
- SDL_zero(oldDisplayMode);
- if (_this) {
- oldDisplayMode = _this->displays[0].desktop_mode;
- }
+ int x = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Left);
+ int y = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Top);
+ int w = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Width);
+ int h = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Height);
- // Setup the new display mode in the appropriate spots.
- if (_this) {
- // Make a full copy of the display mode for display_modes[0],
- // one with with a separately malloced 'driverdata' field.
- // SDL_VideoQuit(), if called, will attempt to free the driverdata
- // fields in 'desktop_mode' and each entry in the 'display_modes'
- // array.
- if (_this->displays[0].display_modes[0].driverdata) {
- // Free the previous mode's memory
- SDL_free(_this->displays[0].display_modes[0].driverdata);
- _this->displays[0].display_modes[0].driverdata = NULL;
- }
- if (WINRT_DuplicateDisplayMode(&(_this->displays[0].display_modes[0]), &newDisplayMode) != 0) {
- // Uh oh, something went wrong. A malloc call probably failed.
- SDL_free(newDisplayMode.driverdata);
- return;
- }
-
- // Install 'newDisplayMode' into 'current_mode' and 'desktop_mode'.
- _this->displays[0].current_mode = newDisplayMode;
- _this->displays[0].desktop_mode = newDisplayMode;
- }
+#if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) && (NTDDI_VERSION == NTDDI_WIN8)
+ /* WinPhone 8.0 always keeps its native window size in portrait,
+ regardless of orientation. This changes in WinPhone 8.1,
+ in which the native window's size changes along with
+ orientation.
- if (WINRT_GlobalSDLWindow) {
- // If the window size changed, send a resize event to SDL and its host app:
- int window_w = 0;
- int window_h = 0;
- SDL_GetWindowSize(WINRT_GlobalSDLWindow, &window_w, &window_h);
- if ((window_w != newDisplayMode.w) || (window_h != newDisplayMode.h)) {
- SDL_SendWindowEvent(
- WINRT_GlobalSDLWindow,
- SDL_WINDOWEVENT_RESIZED,
- newDisplayMode.w,
- newDisplayMode.h);
- } else {
-#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
- // HACK: Make sure that orientation changes
- // lead to the Direct3D renderer's viewport getting updated:
- //
- // For some reason, this doesn't seem to need to be done on Windows 8.x,
- // even when going from Landscape to LandscapeFlipped. It only seems to
- // be needed on Windows Phone, at least when I tested on my devices.
- // I'm not currently sure why this is, but it seems to work fine. -- David L.
- //
- // 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
- const DisplayOrientations oldOrientation = ((SDL_DisplayModeData *)oldDisplayMode.driverdata)->currentOrientation;
- const DisplayOrientations newOrientation = ((SDL_DisplayModeData *)newDisplayMode.driverdata)->currentOrientation;
- if (oldOrientation != newOrientation)
- {
- SDL_SendWindowEvent(
- WINRT_GlobalSDLWindow,
- SDL_WINDOWEVENT_SIZE_CHANGED,
- newDisplayMode.w,
- newDisplayMode.h);
+ Attempt to emulate WinPhone 8.1's behavior on WinPhone 8.0, with
+ regards to window size. This fixes a rendering bug that occurs
+ when a WinPhone 8.0 app is rotated to either 90 or 270 degrees.
+ */
+ const DisplayOrientations currentOrientation = WINRT_DISPLAY_PROPERTY(CurrentOrientation);
+ switch (currentOrientation) {
+ case DisplayOrientations::Landscape:
+ case DisplayOrientations::LandscapeFlipped: {
+ int tmp = w;
+ w = h;
+ h = tmp;
+ } break;
}
#endif
+
+ WINRT_UpdateWindowFlags(window, SDL_WINDOW_MAXIMIZED | SDL_WINDOW_FULLSCREEN_DESKTOP);
+
+ /* The window can move during a resize event, such as when maximizing
+ or resizing from a corner */
+ SDL_SendWindowEvent(window, SDL_WINDOWEVENT_MOVED, x, y);
+ SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, w, h);
}
}
-
- // Finally, free the 'driverdata' field of the old 'desktop_mode'.
- if (oldDisplayMode.driverdata) {
- SDL_free(oldDisplayMode.driverdata);
- oldDisplayMode.driverdata = NULL;
- }
}
SDL_WinRTApp::SDL_WinRTApp() :
@@ -286,7 +237,7 @@
void SDL_WinRTApp::Initialize(CoreApplicationView^ applicationView)
{
applicationView->Activated +=
- ref new TypedEventHandler<CoreApplicationView^, IActivatedEventArgs^>(this, &SDL_WinRTApp::OnActivated);
+ ref new TypedEventHandler<CoreApplicationView^, IActivatedEventArgs^>(this, &SDL_WinRTApp::OnAppActivated);
CoreApplication::Suspending +=
ref new EventHandler<SuspendingEventArgs^>(this, &SDL_WinRTApp::OnSuspending);
@@ -305,35 +256,61 @@
#endif
{
#if LOG_ORIENTATION_EVENTS==1
- CoreWindow^ window = CoreWindow::GetForCurrentThread();
- if (window) {
- SDL_Log("%s, current orientation=%d, native orientation=%d, auto rot. pref=%d, CoreWindow Size={%f,%f}\n",
- __FUNCTION__,
- WINRT_DISPLAY_PROPERTY(CurrentOrientation),
- WINRT_DISPLAY_PROPERTY(NativeOrientation),
- WINRT_DISPLAY_PROPERTY(AutoRotationPreferences),
- window->Bounds.Width,
- window->Bounds.Height);
- } else {
- SDL_Log("%s, current orientation=%d, native orientation=%d, auto rot. pref=%d\n",
- __FUNCTION__,
- WINRT_DISPLAY_PROPERTY(CurrentOrientation),
- WINRT_DISPLAY_PROPERTY(NativeOrientation),
- WINRT_DISPLAY_PROPERTY(AutoRotationPreferences));
+ {
+ CoreWindow^ window = CoreWindow::GetForCurrentThread();
+ if (window) {
+ SDL_Log("%s, current orientation=%d, native orientation=%d, auto rot. pref=%d, CoreWindow Bounds={%f,%f,%f,%f}\n",
+ __FUNCTION__,
+ WINRT_DISPLAY_PROPERTY(CurrentOrientation),
+ WINRT_DISPLAY_PROPERTY(NativeOrientation),
+ WINRT_DISPLAY_PROPERTY(AutoRotationPreferences),
+ window->Bounds.X,
+ window->Bounds.Y,
+ window->Bounds.Width,
+ window->Bounds.Height);
+ } else {
+ SDL_Log("%s, current orientation=%d, native orientation=%d, auto rot. pref=%d\n",
+ __FUNCTION__,
+ WINRT_DISPLAY_PROPERTY(CurrentOrientation),
+ WINRT_DISPLAY_PROPERTY(NativeOrientation),
+ WINRT_DISPLAY_PROPERTY(AutoRotationPreferences));
+ }
}
#endif
WINRT_ProcessWindowSizeChange();
+
+#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
+ // HACK: Make sure that orientation changes
+ // lead to the Direct3D renderer's viewport getting updated:
+ //
+ // For some reason, this doesn't seem to need to be done on Windows 8.x,
+ // even when going from Landscape to LandscapeFlipped. It only seems to
+ // be needed on Windows Phone, at least when I tested on my devices.
+ // I'm not currently sure why this is, but it seems to work fine. -- David L.
+ //
+ // 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
+ SDL_Window * window = WINRT_GlobalSDLWindow;
+ if (window) {
+ SDL_WindowData * data = (SDL_WindowData *)window->driverdata;
+ int w = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Width);
+ int h = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Height);
+ SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_WINDOWEVENT_SIZE_CHANGED, w, h);
+ }
+#endif
+
}
void SDL_WinRTApp::SetWindow(CoreWindow^ window)
{
#if LOG_WINDOW_EVENTS==1
- SDL_Log("%s, current orientation=%d, native orientation=%d, auto rot. pref=%d, window Size={%f,%f}\n",
+ SDL_Log("%s, current orientation=%d, native orientation=%d, auto rot. pref=%d, window bounds={%f, %f, %f,%f}\n",
__FUNCTION__,
WINRT_DISPLAY_PROPERTY(CurrentOrientation),
WINRT_DISPLAY_PROPERTY(NativeOrientation),
WINRT_DISPLAY_PROPERTY(AutoRotationPreferences),
+ window->Bounds.X,
+ window->Bounds.Y,
window->Bounds.Width,
window->Bounds.Height);
#endif
@@ -344,6 +321,9 @@
window->VisibilityChanged +=
ref new TypedEventHandler<CoreWindow^, VisibilityChangedEventArgs^>(this, &SDL_WinRTApp::OnVisibilityChanged);
+ window->Activated +=
+ ref new TypedEventHandler<CoreWindow^, WindowActivatedEventArgs^>(this, &SDL_WinRTApp::OnWindowActivated);
+
window->Closed +=
ref new TypedEventHandler<CoreWindow^, CoreWindowEventArgs^>(this, &SDL_WinRTApp::OnWindowClosed);
@@ -360,6 +340,12 @@
window->PointerReleased +=
ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &SDL_WinRTApp::OnPointerReleased);
+ window->PointerEntered +=
+ ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &SDL_WinRTApp::OnPointerEntered);
+
+ window->PointerExited +=
+ ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &SDL_WinRTApp::OnPointerExited);
+
window->PointerWheelChanged +=
ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &SDL_WinRTApp::OnPointerWheelChanged);
@@ -535,9 +521,10 @@
void SDL_WinRTApp::OnWindowSizeChanged(CoreWindow^ sender, WindowSizeChangedEventArgs^ args)
{
#if LOG_WINDOW_EVENTS==1
- SDL_Log("%s, size={%f,%f}, current orientation=%d, native orientation=%d, auto rot. pref=%d, WINRT_GlobalSDLWindow?=%s\n",
+ 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",
__FUNCTION__,
args->Size.Width, args->Size.Height,
+ sender->Bounds.X, sender->Bounds.Y, sender->Bounds.Width, sender->Bounds.Height,
WINRT_DISPLAY_PROPERTY(CurrentOrientation),
WINRT_DISPLAY_PROPERTY(NativeOrientation),
WINRT_DISPLAY_PROPERTY(AutoRotationPreferences),
@@ -550,20 +537,26 @@
void SDL_WinRTApp::OnVisibilityChanged(CoreWindow^ sender, VisibilityChangedEventArgs^ args)
{
#if LOG_WINDOW_EVENTS==1
- SDL_Log("%s, visible?=%s, WINRT_GlobalSDLWindow?=%s\n",
+ SDL_Log("%s, visible?=%s, bounds={%f,%f,%f,%f}, WINRT_GlobalSDLWindow?=%s\n",
__FUNCTION__,
(args->Visible ? "yes" : "no"),
+ sender->Bounds.X, sender->Bounds.Y,
+ sender->Bounds.Width, sender->Bounds.Height,
(WINRT_GlobalSDLWindow ? "yes" : "no"));
#endif
m_windowVisible = args->Visible;
if (WINRT_GlobalSDLWindow) {
SDL_bool wasSDLWindowSurfaceValid = WINRT_GlobalSDLWindow->surface_valid;
-
+ Uint32 latestWindowFlags = WINRT_DetectWindowFlags(WINRT_GlobalSDLWindow);
if (args->Visible) {
SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_WINDOWEVENT_SHOWN, 0, 0);
SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_WINDOWEVENT_FOCUS_GAINED, 0, 0);
- SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_WINDOWEVENT_RESTORED, 0, 0);
+ if (latestWindowFlags & SDL_WINDOW_MAXIMIZED) {
+ SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_WINDOWEVENT_MAXIMIZED, 0, 0);
+ } else {
+ SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_WINDOWEVENT_RESTORED, 0, 0);
+ }
} else {
SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_WINDOWEVENT_HIDDEN, 0, 0);
SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_WINDOWEVENT_FOCUS_LOST, 0, 0);
@@ -580,6 +573,59 @@
}
}
+void SDL_WinRTApp::OnWindowActivated(CoreWindow^ sender, WindowActivatedEventArgs^ args)
+{
+#if LOG_WINDOW_EVENTS==1
+ SDL_Log("%s, WINRT_GlobalSDLWindow?=%s\n\n",
+ __FUNCTION__,
+ (WINRT_GlobalSDLWindow ? "yes" : "no"));
+#endif
+
+ /* There's no property in Win 8.x to tell whether a window is active or
+ not. [De]activation events are, however, sent to the app. We'll just
+ record those, in case the CoreWindow gets wrapped by an SDL_Window at
+ some future time.
+ */
+ sender->CustomProperties->Insert("SDLHelperWindowActivationState", args->WindowActivationState);
+
+ SDL_Window * window = WINRT_GlobalSDLWindow;
+ if (window) {
+ if (args->WindowActivationState != CoreWindowActivationState::Deactivated) {
+ SDL_SendWindowEvent(window, SDL_WINDOWEVENT_SHOWN, 0, 0);
+ if (SDL_GetKeyboardFocus() != window) {
+ SDL_SetKeyboardFocus(window);
+ }
+
+ /* Send a mouse-motion event as appropriate.
+ This doesn't work when called from OnPointerEntered, at least
+ not in WinRT CoreWindow apps (as OnPointerEntered doesn't
+ appear to be called after window-reactivation, at least not
+ in Windows 10, Build 10586.3 (November 2015 update, non-beta).
+
+ Don't do it on WinPhone 8.0 though, as CoreWindow's 'PointerPosition'
+ property isn't available.
+ */
+#if (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP) || (NTDDI_VERSION >= NTDDI_WINBLUE)
+ Point cursorPos = WINRT_TransformCursorPosition(window, sender->PointerPosition, TransformToSDLWindowSize);
+ SDL_SendMouseMotion(window, 0, 0, (int)cursorPos.X, (int)cursorPos.Y);
+#endif
+
+ /* TODO, WinRT: see if the Win32 bugfix from https://hg.libsdl.org/SDL/rev/d278747da408 needs to be applied (on window activation) */
+ //WIN_CheckAsyncMouseRelease(data);
+
+ /* TODO, WinRT: implement clipboard support, if possible */
+ ///*
+ // * FIXME: Update keyboard state
+ // */
+ //WIN_CheckClipboardUpdate(data->videodata);
+ } else {
+ if (SDL_GetKeyboardFocus() == window) {
+ SDL_SetKeyboardFocus(NULL);
+ }
+ }
+ }
+}
+
void SDL_WinRTApp::OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args)
{
#if LOG_WINDOW_EVENTS==1
@@ -588,7 +634,7 @@
m_windowClosed = true;
}
-void SDL_WinRTApp::OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args)
+void SDL_WinRTApp::OnAppActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args)
{
CoreWindow::GetForCurrentThread()->Activate();
}
@@ -688,8 +734,26 @@
#if LOG_POINTER_EVENTS
WINRT_LogPointerEvent("pointer released", args, WINRT_TransformCursorPosition(WINRT_GlobalSDLWindow, args->CurrentPoint->Position, TransformToSDLWindowSize));
#endif
+
+ WINRT_ProcessPointerReleasedEvent(WINRT_GlobalSDLWindow, args->CurrentPoint);
+}
- WINRT_ProcessPointerReleasedEvent(WINRT_GlobalSDLWindow, args->CurrentPoint);
+void SDL_WinRTApp::OnPointerEntered(CoreWindow^ sender, PointerEventArgs^ args)
+{
+#if LOG_POINTER_EVENTS
+ WINRT_LogPointerEvent("pointer entered", args, WINRT_TransformCursorPosition(WINRT_GlobalSDLWindow, args->CurrentPoint->Position, TransformToSDLWindowSize));
+#endif
+
+ WINRT_ProcessPointerEnteredEvent(WINRT_GlobalSDLWindow, args->CurrentPoint);
+}
+
+void SDL_WinRTApp::OnPointerExited(CoreWindow^ sender, PointerEventArgs^ args)
+{
+#if LOG_POINTER_EVENTS
+ WINRT_LogPointerEvent("pointer exited", args, WINRT_TransformCursorPosition(WINRT_GlobalSDLWindow, args->CurrentPoint->Position, TransformToSDLWindowSize));
+#endif
+
+ WINRT_ProcessPointerExitedEvent(WINRT_GlobalSDLWindow, args->CurrentPoint);
}
void SDL_WinRTApp::OnPointerWheelChanged(CoreWindow^ sender, PointerEventArgs^ args)
--- a/src/core/winrt/SDL_winrtapp_direct3d.h Sun Nov 15 13:04:42 2015 -0500
+++ b/src/core/winrt/SDL_winrtapp_direct3d.h Thu Nov 26 00:41:39 2015 -0500
@@ -56,16 +56,19 @@
#endif
void OnWindowSizeChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::WindowSizeChangedEventArgs^ args);
void OnLogicalDpiChanged(Platform::Object^ sender);
- void OnActivated(Windows::ApplicationModel::Core::CoreApplicationView^ applicationView, Windows::ApplicationModel::Activation::IActivatedEventArgs^ args);
+ void OnAppActivated(Windows::ApplicationModel::Core::CoreApplicationView^ applicationView, Windows::ApplicationModel::Activation::IActivatedEventArgs^ args);
void OnSuspending(Platform::Object^ sender, Windows::ApplicationModel::SuspendingEventArgs^ args);
void OnResuming(Platform::Object^ sender, Platform::Object^ args);
void OnExiting(Platform::Object^ sender, Platform::Object^ args);
+ void OnWindowActivated(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::WindowActivatedEventArgs^ args);
void OnWindowClosed(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::CoreWindowEventArgs^ args);
void OnVisibilityChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::VisibilityChangedEventArgs^ args);
void OnPointerPressed(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
void OnPointerReleased(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
void OnPointerWheelChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
void OnPointerMoved(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
+ void OnPointerEntered(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
+ void OnPointerExited(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
void OnMouseMoved(Windows::Devices::Input::MouseDevice^ mouseDevice, Windows::Devices::Input::MouseEventArgs^ args);
void OnKeyDown(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyEventArgs^ args);
void OnKeyUp(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyEventArgs^ args);
--- a/src/render/direct3d11/SDL_render_d3d11.c Sun Nov 15 13:04:42 2015 -0500
+++ b/src/render/direct3d11/SDL_render_d3d11.c Thu Nov 26 00:41:39 2015 -0500
@@ -760,8 +760,8 @@
};
-static Uint32
-DXGIFormatToSDLPixelFormat(DXGI_FORMAT dxgiFormat) {
+Uint32
+D3D11_DXGIFormatToSDLPixelFormat(DXGI_FORMAT dxgiFormat) {
switch (dxgiFormat) {
case DXGI_FORMAT_B8G8R8A8_UNORM:
return SDL_PIXELFORMAT_ARGB8888;
@@ -2911,7 +2911,7 @@
*/
if (SDL_ConvertPixels(
rect->w, rect->h,
- DXGIFormatToSDLPixelFormat(stagingTextureDesc.Format),
+ D3D11_DXGIFormatToSDLPixelFormat(stagingTextureDesc.Format),
textureMemory.pData,
textureMemory.RowPitch,
format,
--- a/src/video/SDL_video.c Sun Nov 15 13:04:42 2015 -0500
+++ b/src/video/SDL_video.c Thu Nov 26 00:41:39 2015 -0500
@@ -1125,6 +1125,10 @@
}
}
+#if __WINRT__
+extern Uint32 WINRT_DetectWindowFlags(SDL_Window * window);
+#endif
+
static int
SDL_UpdateFullscreenMode(SDL_Window * window, SDL_bool fullscreen)
{
@@ -1164,6 +1168,30 @@
window->last_fullscreen_flags = window->flags;
return 0;
}
+#elif __WINRT__
+ /* HACK: WinRT 8.x apps can't choose whether or not they are fullscreen
+ or not. The user can choose this, via OS-provided UI, but this can't
+ be set programmatically.
+
+ Just look at what SDL's WinRT video backend code detected with regards
+ to fullscreen (being active, or not), and figure out a return/error code
+ from that.
+ */
+ if (fullscreen == !(WINRT_DetectWindowFlags(window) & FULLSCREEN_MASK)) {
+ /* Uh oh, either:
+ 1. fullscreen was requested, and we're already windowed
+ 2. windowed-mode was requested, and we're already fullscreen
+
+ WinRT 8.x can't resolve either programmatically, so we're
+ giving up.
+ */
+ return -1;
+ } else {
+ /* Whatever was requested, fullscreen or windowed mode, is already
+ in-place.
+ */
+ return 0;
+ }
#endif
display = SDL_GetDisplayForWindow(window);
@@ -1377,6 +1405,18 @@
return NULL;
}
+#if __WINRT__
+ /* HACK: WinRT 8.x apps can't choose whether or not they are fullscreen
+ or not. The user can choose this, via OS-provided UI, but this can't
+ be set programmatically.
+
+ Just look at what SDL's WinRT video backend code detected with regards
+ to fullscreen (being active, or not), and figure out a return/error code
+ from that.
+ */
+ flags = window->flags;
+#endif
+
if (title) {
SDL_SetWindowTitle(window, title);
}
--- a/src/video/winrt/SDL_winrtevents_c.h Sun Nov 15 13:04:42 2015 -0500
+++ b/src/video/winrt/SDL_winrtevents_c.h Thu Nov 26 00:41:39 2015 -0500
@@ -57,6 +57,8 @@
extern void WINRT_ProcessPointerPressedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint);
extern void WINRT_ProcessPointerMovedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint);
extern void WINRT_ProcessPointerReleasedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint);
+extern void WINRT_ProcessPointerEnteredEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint);
+extern void WINRT_ProcessPointerExitedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint);
extern void WINRT_ProcessPointerWheelChangedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint);
extern void WINRT_ProcessMouseMovedEvent(SDL_Window * window, Windows::Devices::Input::MouseEventArgs ^args);
--- a/src/video/winrt/SDL_winrtpointerinput.cpp Sun Nov 15 13:04:42 2015 -0500
+++ b/src/video/winrt/SDL_winrtpointerinput.cpp Thu Nov 26 00:41:39 2015 -0500
@@ -306,6 +306,28 @@
}
}
+void WINRT_ProcessPointerEnteredEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint)
+{
+ if (!window) {
+ return;
+ }
+
+ if (!WINRT_IsTouchEvent(pointerPoint)) {
+ SDL_SetMouseFocus(window);
+ }
+}
+
+void WINRT_ProcessPointerExitedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint)
+{
+ if (!window) {
+ return;
+ }
+
+ if (!WINRT_IsTouchEvent(pointerPoint)) {
+ SDL_SetMouseFocus(NULL);
+ }
+}
+
void
WINRT_ProcessPointerWheelChangedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint)
{
--- a/src/video/winrt/SDL_winrtvideo.cpp Sun Nov 15 13:04:42 2015 -0500
+++ b/src/video/winrt/SDL_winrtvideo.cpp Thu Nov 26 00:41:39 2015 -0500
@@ -30,8 +30,17 @@
/* Windows includes */
#include <agile.h>
-#include <wrl/client.h>
+#include <windows.graphics.display.h>
+#include <dxgi.h>
+#include <dxgi1_2.h>
+using namespace Windows::ApplicationModel::Core;
+using namespace Windows::Foundation;
using namespace Windows::UI::Core;
+using namespace Windows::UI::ViewManagement;
+
+
+/* [re]declare Windows GUIDs locally, to limit the amount of external lib(s) SDL has to link to */
+static const GUID IID_IDXGIFactory2 = { 0x50c83a1c, 0xe072, 0x4c48,{ 0x87, 0xb0, 0x36, 0x30, 0xfa, 0x36, 0xa6, 0xd0 } };
/* SDL includes */
@@ -44,6 +53,7 @@
#include "../../render/SDL_sysrender.h"
#include "SDL_syswm.h"
#include "SDL_winrtopengles.h"
+#include "../../core/windows/SDL_windows.h"
}
#include "../../core/winrt/SDL_winrtapp_direct3d.h"
@@ -161,110 +171,178 @@
return 0;
}
-int
-WINRT_CalcDisplayModeUsingNativeWindow(SDL_DisplayMode * mode)
+extern "C"
+Uint32 D3D11_DXGIFormatToSDLPixelFormat(DXGI_FORMAT dxgiFormat);
+
+static void
+WINRT_DXGIModeToSDLDisplayMode(const DXGI_MODE_DESC * dxgiMode, SDL_DisplayMode * sdlMode)
{
- SDL_DisplayModeData * driverdata;
+ SDL_zerop(sdlMode);
+ sdlMode->w = dxgiMode->Width;
+ sdlMode->h = dxgiMode->Height;
+ sdlMode->refresh_rate = dxgiMode->RefreshRate.Numerator / dxgiMode->RefreshRate.Denominator;
+ sdlMode->format = D3D11_DXGIFormatToSDLPixelFormat(dxgiMode->Format);
+}
- using namespace Windows::Graphics::Display;
+static int
+WINRT_AddDisplaysForOutput (_THIS, IDXGIAdapter1 * dxgiAdapter1, int outputIndex)
+{
+ HRESULT hr;
+ IDXGIOutput * dxgiOutput = NULL;
+ DXGI_OUTPUT_DESC dxgiOutputDesc;
+ SDL_VideoDisplay display;
+ char * displayName = NULL;
+ UINT numModes;
+ DXGI_MODE_DESC * dxgiModes = NULL;
+ int functionResult = -1; /* -1 for failure, 0 for success */
+ DXGI_MODE_DESC modeToMatch, closestMatch;
- // Go no further if a native window cannot be accessed. This can happen,
- // for example, if this function is called from certain threads, such as
- // the SDL/XAML thread.
- if (!CoreWindow::GetForCurrentThread()) {
- return SDL_SetError("SDL/WinRT display modes cannot be calculated outside of the main thread, such as in SDL's XAML thread");
+ SDL_zero(display);
+
+ hr = dxgiAdapter1->EnumOutputs(outputIndex, &dxgiOutput);
+ if (FAILED(hr)) {
+ if (hr != DXGI_ERROR_NOT_FOUND) {
+ WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIAdapter1::EnumOutputs failed", hr);
+ }
+ goto done;
}
- //SDL_Log("%s, size={%f,%f}, current orientation=%d, native orientation=%d, auto rot. pref=%d, DPI = %f\n",
- // __FUNCTION__,
- // CoreWindow::GetForCurrentThread()->Bounds.Width, CoreWindow::GetForCurrentThread()->Bounds.Height,
- // WINRT_DISPLAY_PROPERTY(CurrentOrientation),
- // WINRT_DISPLAY_PROPERTY(NativeOrientation),
- // WINRT_DISPLAY_PROPERTY(AutoRotationPreferences),
- // WINRT_DISPLAY_PROPERTY(LogicalDpi));
-
- // Calculate the display size given the window size, taking into account
- // the current display's DPI:
- const float currentDPI = WINRT_DISPLAY_PROPERTY(LogicalDpi);
- const float dipsPerInch = 96.0f;
- const int w = (int) ((CoreWindow::GetForCurrentThread()->Bounds.Width * currentDPI) / dipsPerInch);
- const int h = (int) ((CoreWindow::GetForCurrentThread()->Bounds.Height * currentDPI) / dipsPerInch);
- if (w == 0 || w == h) {
- return SDL_SetError("Unable to calculate the WinRT window/display's size");
+ hr = dxgiOutput->GetDesc(&dxgiOutputDesc);
+ if (FAILED(hr)) {
+ WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIOutput::GetDesc failed", hr);
+ goto done;
}
- // Create a driverdata field:
- driverdata = (SDL_DisplayModeData *) SDL_malloc(sizeof(*driverdata));
- if (!driverdata) {
- return SDL_OutOfMemory();
- }
- SDL_zerop(driverdata);
+ SDL_zero(modeToMatch);
+ modeToMatch.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
+ modeToMatch.Width = (dxgiOutputDesc.DesktopCoordinates.right - dxgiOutputDesc.DesktopCoordinates.left);
+ modeToMatch.Height = (dxgiOutputDesc.DesktopCoordinates.bottom - dxgiOutputDesc.DesktopCoordinates.top);
+ hr = dxgiOutput->FindClosestMatchingMode(&modeToMatch, &closestMatch, NULL);
+ if (hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE) {
+ /* DXGI_ERROR_NOT_CURRENTLY_AVAILABLE gets returned by IDXGIOutput::FindClosestMatchingMode
+ when running under the Windows Simulator, which uses Remote Desktop (formerly known as Terminal
+ Services) under the hood. According to the MSDN docs for the similar function,
+ IDXGIOutput::GetDisplayModeList, DXGI_ERROR_NOT_CURRENTLY_AVAILABLE is returned if and
+ when an app is run under a Terminal Services session, hence the assumption.
+
+ In this case, just add an SDL display mode, with approximated values.
+ */
+ SDL_DisplayMode mode;
+ SDL_zero(mode);
+ display.name = "Windows Simulator / Terminal Services Display";
+ mode.w = (dxgiOutputDesc.DesktopCoordinates.right - dxgiOutputDesc.DesktopCoordinates.left);
+ mode.h = (dxgiOutputDesc.DesktopCoordinates.bottom - dxgiOutputDesc.DesktopCoordinates.top);
+ mode.format = DXGI_FORMAT_B8G8R8A8_UNORM;
+ mode.refresh_rate = 0; /* Display mode is unknown, so just fill in zero, as specified by SDL's header files */
+ display.desktop_mode = mode;
+ display.current_mode = mode;
+ if ( ! SDL_AddDisplayMode(&display, &mode)) {
+ goto done;
+ }
+ } else if (FAILED(hr)) {
+ WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIOutput::FindClosestMatchingMode failed", hr);
+ goto done;
+ } else {
+ displayName = WIN_StringToUTF8(dxgiOutputDesc.DeviceName);
+ display.name = displayName;
+ WINRT_DXGIModeToSDLDisplayMode(&closestMatch, &display.desktop_mode);
+ display.current_mode = display.desktop_mode;
+
+ hr = dxgiOutput->GetDisplayModeList(DXGI_FORMAT_B8G8R8A8_UNORM, 0, &numModes, NULL);
+ if (FAILED(hr)) {
+ if (hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE) {
+ // TODO, WinRT: make sure display mode(s) are added when using Terminal Services / Windows Simulator
+ }
+ WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIOutput::GetDisplayModeList [get mode list size] failed", hr);
+ goto done;
+ }
- // Fill in most fields:
- SDL_zerop(mode);
- mode->format = SDL_PIXELFORMAT_RGB888;
- mode->refresh_rate = 0; // TODO, WinRT: see if refresh rate data is available, or relevant (for WinRT apps)
- mode->w = w;
- mode->h = h;
- mode->driverdata = driverdata;
- driverdata->currentOrientation = WINRT_DISPLAY_PROPERTY(CurrentOrientation);
+ dxgiModes = (DXGI_MODE_DESC *)SDL_calloc(numModes, sizeof(DXGI_MODE_DESC));
+ if ( ! dxgiModes) {
+ SDL_OutOfMemory();
+ goto done;
+ }
+
+ hr = dxgiOutput->GetDisplayModeList(DXGI_FORMAT_B8G8R8A8_UNORM, 0, &numModes, dxgiModes);
+ if (FAILED(hr)) {
+ WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIOutput::GetDisplayModeList [get mode contents] failed", hr);
+ goto done;
+ }
+
+ for (UINT i = 0; i < numModes; ++i) {
+ SDL_DisplayMode sdlMode;
+ WINRT_DXGIModeToSDLDisplayMode(&dxgiModes[i], &sdlMode);
+ SDL_AddDisplayMode(&display, &sdlMode);
+ }
+ }
+
+ if (SDL_AddVideoDisplay(&display) < 0) {
+ goto done;
+ }
-#if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) && (NTDDI_VERSION == NTDDI_WIN8)
- // On Windows Phone 8.0, the native window's size is always in portrait,
- // regardless of the device's orientation. This is in contrast to
- // Windows 8.x/RT and Windows Phone 8.1, which will resize the native window as the device's
- // orientation changes. In order to compensate for this behavior,
- // on Windows Phone, the mode's width and height will be swapped when
- // the device is in a landscape (non-portrait) mode.
- switch (driverdata->currentOrientation) {
- case DisplayOrientations::Landscape:
- case DisplayOrientations::LandscapeFlipped:
- {
- const int tmp = mode->h;
- mode->h = mode->w;
- mode->w = tmp;
+ functionResult = 0; /* 0 for Success! */
+done:
+ if (dxgiModes) {
+ SDL_free(dxgiModes);
+ }
+ if (dxgiOutput) {
+ dxgiOutput->Release();
+ }
+ if (displayName) {
+ SDL_free(displayName);
+ }
+ return functionResult;
+}
+
+static int
+WINRT_AddDisplaysForAdapter (_THIS, IDXGIFactory2 * dxgiFactory2, int adapterIndex)
+{
+ HRESULT hr;
+ IDXGIAdapter1 * dxgiAdapter1;
+
+ hr = dxgiFactory2->EnumAdapters1(adapterIndex, &dxgiAdapter1);
+ if (FAILED(hr)) {
+ if (hr != DXGI_ERROR_NOT_FOUND) {
+ WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIFactory1::EnumAdapters1() failed", hr);
+ }
+ return -1;
+ }
+
+ for (int outputIndex = 0; ; ++outputIndex) {
+ if (WINRT_AddDisplaysForOutput(_this, dxgiAdapter1, outputIndex) < 0) {
break;
}
-
- default:
- break;
}
-#endif
-
- return 0;
-}
-int
-WINRT_DuplicateDisplayMode(SDL_DisplayMode * dest, const SDL_DisplayMode * src)
-{
- SDL_DisplayModeData * driverdata;
- driverdata = (SDL_DisplayModeData *) SDL_malloc(sizeof(*driverdata));
- if (!driverdata) {
- return SDL_OutOfMemory();
- }
- SDL_memcpy(driverdata, src->driverdata, sizeof(SDL_DisplayModeData));
- SDL_memcpy(dest, src, sizeof(SDL_DisplayMode));
- dest->driverdata = driverdata;
+ dxgiAdapter1->Release();
return 0;
}
int
WINRT_InitModes(_THIS)
{
- // Retrieve the display mode:
- SDL_DisplayMode mode, desktop_mode;
- if (WINRT_CalcDisplayModeUsingNativeWindow(&mode) != 0) {
- return -1; // If WINRT_CalcDisplayModeUsingNativeWindow fails, it'll already have set the SDL error
- }
+ /* HACK: Initialize a single display, for whatever screen the app's
+ CoreApplicationView is on.
+ TODO, WinRT: Try initializing multiple displays, one for each monitor.
+ Appropriate WinRT APIs for this seem elusive, though. -- DavidL
+ */
- if (WINRT_DuplicateDisplayMode(&desktop_mode, &mode) != 0) {
- return -1;
- }
- if (SDL_AddBasicVideoDisplay(&desktop_mode) < 0) {
+ HRESULT hr;
+ IDXGIFactory2 * dxgiFactory2 = NULL;
+
+ hr = CreateDXGIFactory1(IID_IDXGIFactory2, (void **)&dxgiFactory2);
+ if (FAILED(hr)) {
+ WIN_SetErrorFromHRESULT(__FUNCTION__ ", CreateDXGIFactory1() failed", hr);
return -1;
}
- SDL_AddDisplayMode(&_this->displays[0], &mode);
+ int adapterIndex = 0;
+ for (int adapterIndex = 0; ; ++adapterIndex) {
+ if (WINRT_AddDisplaysForAdapter(_this, dxgiFactory2, adapterIndex) < 0) {
+ break;
+ }
+ }
+
return 0;
}
@@ -280,6 +358,64 @@
WINRT_QuitMouse(_this);
}
+extern "C" Uint32
+WINRT_DetectWindowFlags(SDL_Window * window)
+{
+ Uint32 latestFlags = 0;
+ SDL_WindowData * data = (SDL_WindowData *) window->driverdata;
+ bool is_fullscreen = false;
+
+#if SDL_WINRT_USE_APPLICATIONVIEW
+ if (data->appView) {
+ is_fullscreen = data->appView->IsFullScreen;
+ }
+#elif (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
+ is_fullscreen = true;
+#endif
+
+ if (data->coreWindow.Get()) {
+ if (is_fullscreen) {
+ SDL_VideoDisplay * display = SDL_GetDisplayForWindow(window);
+ if (display->desktop_mode.w != WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Width) ||
+ display->desktop_mode.h != WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Height))
+ {
+ latestFlags |= SDL_WINDOW_MAXIMIZED;
+ } else {
+ latestFlags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
+ }
+ }
+
+ if (data->coreWindow->Visible) {
+ latestFlags |= SDL_WINDOW_SHOWN;
+ } else {
+ latestFlags |= SDL_WINDOW_HIDDEN;
+ }
+
+#if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) && (NTDDI_VERSION < NTDDI_WINBLUE)
+ // data->coreWindow->PointerPosition is not supported on WinPhone 8.0
+ latestFlags |= SDL_WINDOW_MOUSE_FOCUS;
+#else
+ if (data->coreWindow->Bounds.Contains(data->coreWindow->PointerPosition)) {
+ latestFlags |= SDL_WINDOW_MOUSE_FOCUS;
+ }
+#endif
+ }
+
+ return latestFlags;
+}
+
+void
+WINRT_UpdateWindowFlags(SDL_Window * window, Uint32 mask)
+{
+ if (window) {
+ Uint32 apply = WINRT_DetectWindowFlags(window);
+ if ((apply & mask) & SDL_WINDOW_FULLSCREEN) {
+ window->last_fullscreen_flags = window->flags; // seems necessary to programmatically un-fullscreen, via SDL APIs
+ }
+ window->flags = (window->flags & ~mask) | (apply & mask);
+ }
+}
+
int
WINRT_CreateWindow(_THIS, SDL_Window * window)
{
@@ -290,7 +426,7 @@
return -1;
}
- SDL_WindowData *data = new SDL_WindowData;
+ SDL_WindowData *data = new SDL_WindowData; /* use 'new' here as SDL_WindowData may use WinRT/C++ types */
if (!data) {
SDL_OutOfMemory();
return -1;
@@ -306,6 +442,9 @@
*/
if (!WINRT_XAMLWasEnabled) {
data->coreWindow = CoreWindow::GetForCurrentThread();
+#if SDL_WINRT_USE_APPLICATIONVIEW
+ data->appView = ApplicationView::GetForCurrentView();
+#endif
}
#if SDL_VIDEO_OPENGL_EGL
@@ -359,17 +498,18 @@
}
#endif
- /* Make sure the window is considered to be positioned at {0,0},
- and is considered fullscreen, shown, and the like.
- */
- window->x = 0;
- window->y = 0;
+#if SDL_WINRT_USE_APPLICATIONVIEW
+ /* Determine as many flags dynamically, as possible. */
window->flags =
- SDL_WINDOW_FULLSCREEN |
- SDL_WINDOW_SHOWN |
+ SDL_WINDOW_BORDERLESS;
+#else
+ /* Set SDL_Window flags for Windows Phone 8.0 */
+ window->flags =
+ SDL_WINDOW_FULLSCREEN_DESKTOP |
SDL_WINDOW_BORDERLESS |
SDL_WINDOW_MAXIMIZED |
SDL_WINDOW_INPUT_GRABBED;
+#endif
#if SDL_VIDEO_OPENGL_EGL
if (data->egl_surface) {
@@ -377,20 +517,40 @@
}
#endif
- /* WinRT does not, as of this writing, appear to support app-adjustable
- window sizes. Set the window size to whatever the native WinRT
- CoreWindow is set at.
+ if (WINRT_XAMLWasEnabled) {
+ /* TODO, WinRT: set SDL_Window size, maybe position too, from XAML control */
+ window->x = 0;
+ window->y = 0;
+ window->flags |= SDL_WINDOW_SHOWN;
+ SDL_SetMouseFocus(NULL); // TODO: detect this
+ SDL_SetKeyboardFocus(NULL); // TODO: detect this
+ } else {
+ /* WinRT apps seem to live in an environment where the OS controls the
+ app's window size, with some apps being fullscreen, depending on
+ user choice of various things. For now, just adapt the SDL_Window to
+ whatever Windows set-up as the native-window's geometry.
+ */
+ window->x = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Left);
+ window->y = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Top);
+ window->w = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Width);
+ window->h = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Height);
- TODO, WinRT: if and when non-fullscreen XAML control support is added to SDL, consider making those resizable via SDL_Window's interfaces.
- */
- window->w = _this->displays[0].current_mode.w;
- window->h = _this->displays[0].current_mode.h;
+ WINRT_UpdateWindowFlags(
+ window,
+ 0xffffffff /* Update any window flag(s) that WINRT_UpdateWindow can handle */
+ );
- /* For now, treat WinRT apps as if they always have focus.
- TODO, WinRT: try tracking keyboard and mouse focus state with respect to snapped apps
- */
- SDL_SetMouseFocus(window);
- SDL_SetKeyboardFocus(window);
+ /* Try detecting if the window is active */
+ bool isWindowActive = true; /* Presume the window is active, unless we've been told otherwise */
+ if (data->coreWindow->CustomProperties->HasKey("SDLHelperWindowActivationState")) {
+ CoreWindowActivationState activationState = \
+ safe_cast<CoreWindowActivationState>(data->coreWindow->CustomProperties->Lookup("SDLHelperWindowActivationState"));
+ isWindowActive = (activationState != CoreWindowActivationState::Deactivated);
+ }
+ if (isWindowActive) {
+ SDL_SetKeyboardFocus(window);
+ }
+ }
/* Make sure the WinRT app's IFramworkView can post events on
behalf of SDL:
--- a/src/video/winrt/SDL_winrtvideo_cpp.h Sun Nov 15 13:04:42 2015 -0500
+++ b/src/video/winrt/SDL_winrtvideo_cpp.h Thu Nov 26 00:41:39 2015 -0500
@@ -29,6 +29,12 @@
#include "SDL_video.h"
#include "SDL_events.h"
+#if NTDDI_VERSION >= NTDDI_WINBLUE /* ApplicationView's functionality only becomes
+ useful for SDL in Win[Phone] 8.1 and up.
+ Plus, it is not available at all in WinPhone 8.0. */
+#define SDL_WINRT_USE_APPLICATIONVIEW 1
+#endif
+
extern "C" {
#include "../SDL_sysvideo.h"
#include "../SDL_egl_c.h"
@@ -48,25 +54,17 @@
*/
extern SDL_Window * WINRT_GlobalSDLWindow;
-/* Creates a display mode for Plain Direct3D (non-XAML) apps, using the lone, native window's settings.
-
- Pass in an allocated SDL_DisplayMode field to store the data in.
-
- This function will return 0 on success, -1 on failure.
-
- If this function succeeds, be sure to call SDL_free on the
- SDL_DisplayMode's driverdata field.
+/* Updates one or more SDL_Window flags, by querying the OS' native windowing APIs.
+ SDL_Window flags that can be updated should be specified in 'mask'.
*/
-extern int WINRT_CalcDisplayModeUsingNativeWindow(SDL_DisplayMode * mode);
-
-/* Duplicates a display mode, copying over driverdata as necessary */
-extern int WINRT_DuplicateDisplayMode(SDL_DisplayMode * dest, const SDL_DisplayMode * src);
+extern void WINRT_UpdateWindowFlags(SDL_Window * window, Uint32 mask);
+extern "C" Uint32 WINRT_DetectWindowFlags(SDL_Window * window); /* detects flags w/o applying them */
/* Display mode internals */
-typedef struct
-{
- Windows::Graphics::Display::DisplayOrientations currentOrientation;
-} SDL_DisplayModeData;
+//typedef struct
+//{
+// Windows::Graphics::Display::DisplayOrientations currentOrientation;
+//} SDL_DisplayModeData;
#ifdef __cplusplus_winrt
@@ -77,6 +75,10 @@
#define WINRT_DISPLAY_PROPERTY(NAME) (Windows::Graphics::Display::DisplayProperties::NAME)
#endif
+/* Converts DIPS to physical pixels */
+#define WINRT_DIPS_TO_PHYSICAL_PIXELS(DIPS) ((int)(0.5f + (((float)(DIPS) * (float)WINRT_DISPLAY_PROPERTY(LogicalDpi)) / 96.f)))
+
+
/* Internal window data */
struct SDL_WindowData
{
@@ -85,6 +87,9 @@
#ifdef SDL_VIDEO_OPENGL_EGL
EGLSurface egl_surface;
#endif
+#if SDL_WINRT_USE_APPLICATIONVIEW
+ Windows::UI::ViewManagement::ApplicationView ^ appView;
+#endif
};
#endif // ifdef __cplusplus_winrt