mirror of
https://github.com/libsdl-org/SDL.git
synced 2024-11-24 03:13:34 +08:00
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).
This commit is contained in:
parent
a5a80cd033
commit
623898f70b
@ -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 @@ typedef unsigned int uintptr_t;
|
||||
#define SDL_ASSEMBLY_ROUTINES 1
|
||||
#endif
|
||||
|
||||
#endif /* _SDL_config_windows_h */
|
||||
#endif /* _SDL_config_winrt_h */
|
||||
|
@ -184,97 +184,48 @@ static void WINRT_SetDisplayOrientationsPreference(void *userdata, const char *n
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
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);
|
||||
|
||||
// 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;
|
||||
}
|
||||
#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.
|
||||
|
||||
// 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 (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 @@ SDL_WinRTApp::SDL_WinRTApp() :
|
||||
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 @@ void SDL_WinRTApp::OnOrientationChanged(Object^ sender)
|
||||
#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 @@ void SDL_WinRTApp::SetWindow(CoreWindow^ window)
|
||||
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 @@ void SDL_WinRTApp::SetWindow(CoreWindow^ window)
|
||||
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::OnSettingsPaneCommandsRequested(
|
||||
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::OnWindowSizeChanged(CoreWindow^ sender, WindowSizeChangedEven
|
||||
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::OnVisibilityChanged(CoreWindow^ sender, VisibilityChangedEven
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ void SDL_WinRTApp::OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args)
|
||||
m_windowClosed = true;
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args)
|
||||
void SDL_WinRTApp::OnAppActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args)
|
||||
{
|
||||
CoreWindow::GetForCurrentThread()->Activate();
|
||||
}
|
||||
@ -688,10 +734,28 @@ void SDL_WinRTApp::OnPointerReleased(CoreWindow^ sender, PointerEventArgs^ args)
|
||||
#if LOG_POINTER_EVENTS
|
||||
WINRT_LogPointerEvent("pointer released", args, WINRT_TransformCursorPosition(WINRT_GlobalSDLWindow, args->CurrentPoint->Position, TransformToSDLWindowSize));
|
||||
#endif
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
#if LOG_POINTER_EVENTS
|
||||
|
@ -56,16 +56,19 @@ protected:
|
||||
#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);
|
||||
|
@ -760,8 +760,8 @@ SDL_RenderDriver D3D11_RenderDriver = {
|
||||
};
|
||||
|
||||
|
||||
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 @@ D3D11_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
|
||||
*/
|
||||
if (SDL_ConvertPixels(
|
||||
rect->w, rect->h,
|
||||
DXGIFormatToSDLPixelFormat(stagingTextureDesc.Format),
|
||||
D3D11_DXGIFormatToSDLPixelFormat(stagingTextureDesc.Format),
|
||||
textureMemory.pData,
|
||||
textureMemory.RowPitch,
|
||||
format,
|
||||
|
@ -1125,6 +1125,10 @@ SDL_RestoreMousePosition(SDL_Window *window)
|
||||
}
|
||||
}
|
||||
|
||||
#if __WINRT__
|
||||
extern Uint32 WINRT_DetectWindowFlags(SDL_Window * window);
|
||||
#endif
|
||||
|
||||
static int
|
||||
SDL_UpdateFullscreenMode(SDL_Window * window, SDL_bool fullscreen)
|
||||
{
|
||||
@ -1164,6 +1168,30 @@ SDL_UpdateFullscreenMode(SDL_Window * window, SDL_bool fullscreen)
|
||||
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 @@ SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags)
|
||||
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);
|
||||
}
|
||||
|
@ -57,6 +57,8 @@ extern Uint8 WINRT_GetSDLButtonForPointerPoint(Windows::UI::Input::PointerPoint
|
||||
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);
|
||||
|
||||
|
@ -306,6 +306,28 @@ void WINRT_ProcessPointerReleasedEvent(SDL_Window *window, Windows::UI::Input::P
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -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 @@ extern "C" {
|
||||
#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 @@ WINRT_VideoInit(_THIS)
|
||||
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;
|
||||
|
||||
using namespace Windows::Graphics::Display;
|
||||
|
||||
// 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_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");
|
||||
}
|
||||
|
||||
// Create a driverdata field:
|
||||
driverdata = (SDL_DisplayModeData *) SDL_malloc(sizeof(*driverdata));
|
||||
if (!driverdata) {
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
SDL_zerop(driverdata);
|
||||
|
||||
// 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);
|
||||
|
||||
#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;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
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);
|
||||
}
|
||||
|
||||
int
|
||||
WINRT_DuplicateDisplayMode(SDL_DisplayMode * dest, const SDL_DisplayMode * src)
|
||||
static int
|
||||
WINRT_AddDisplaysForOutput (_THIS, IDXGIAdapter1 * dxgiAdapter1, int outputIndex)
|
||||
{
|
||||
SDL_DisplayModeData * driverdata;
|
||||
driverdata = (SDL_DisplayModeData *) SDL_malloc(sizeof(*driverdata));
|
||||
if (!driverdata) {
|
||||
return SDL_OutOfMemory();
|
||||
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;
|
||||
|
||||
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_memcpy(driverdata, src->driverdata, sizeof(SDL_DisplayModeData));
|
||||
SDL_memcpy(dest, src, sizeof(SDL_DisplayMode));
|
||||
dest->driverdata = driverdata;
|
||||
|
||||
hr = dxgiOutput->GetDesc(&dxgiOutputDesc);
|
||||
if (FAILED(hr)) {
|
||||
WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIOutput::GetDesc failed", hr);
|
||||
goto done;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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_VideoQuit(_THIS)
|
||||
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 @@ WINRT_CreateWindow(_THIS, SDL_Window * window)
|
||||
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 @@ WINRT_CreateWindow(_THIS, SDL_Window * window)
|
||||
*/
|
||||
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 @@ WINRT_CreateWindow(_THIS, SDL_Window * window)
|
||||
}
|
||||
#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 @@ WINRT_CreateWindow(_THIS, SDL_Window * window)
|
||||
}
|
||||
#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:
|
||||
|
@ -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 @@ typedef struct SDL_VideoData {
|
||||
*/
|
||||
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 @@ typedef struct
|
||||
#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 @@ struct SDL_WindowData
|
||||
#ifdef SDL_VIDEO_OPENGL_EGL
|
||||
EGLSurface egl_surface;
|
||||
#endif
|
||||
#if SDL_WINRT_USE_APPLICATIONVIEW
|
||||
Windows::UI::ViewManagement::ApplicationView ^ appView;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // ifdef __cplusplus_winrt
|
||||
|
Loading…
Reference in New Issue
Block a user