src/core/winrt/SDL_winrtapp_direct3d.cpp
author David Ludwig <dludwig@pobox.com>
Wed, 26 Nov 2014 21:34:15 -0500
changeset 9240 dc4ad21d8596
parent 8757 aeeeb47a5a77
child 9256 9c45fc8605d9
permissions -rw-r--r--
WinRT: added initial SDL_TEXTINPUT support

Further support regarding IME and on-screen keyboards is pending, some of
which might not be 100% compatible with other platforms, given WinRT platform
restrictions. An MSDN article at http://msdn.microsoft.com/en-us/library/windows/apps/hh465404.aspx
indicates that on-screen keyboard display requires that the user first tap on
a Windows/XAML text control.

This change adds basic SDL_TEXTINPUT support, with input coming from hardware
keyboards, at a minimum, and without the need for XAML integration (which is
still pending integration into SDL, by and large).
slouken@8616
     1
/*
slouken@8616
     2
  Simple DirectMedia Layer
slouken@8616
     3
  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
slouken@8616
     4
slouken@8616
     5
  This software is provided 'as-is', without any express or implied
slouken@8616
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@8616
     7
  arising from the use of this software.
slouken@8616
     8
slouken@8616
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@8616
    10
  including commercial applications, and to alter it and redistribute it
slouken@8616
    11
  freely, subject to the following restrictions:
slouken@8616
    12
slouken@8616
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@8616
    14
     claim that you wrote the original software. If you use this software
slouken@8616
    15
     in a product, an acknowledgment in the product documentation would be
slouken@8616
    16
     appreciated but is not required.
slouken@8616
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@8616
    18
     misrepresented as being the original software.
slouken@8616
    19
  3. This notice may not be removed or altered from any source distribution.
slouken@8616
    20
*/
slouken@8616
    21
#include "../../SDL_internal.h"
slouken@8616
    22
slouken@8582
    23
/* Standard C++11 includes */
slouken@8582
    24
#include <functional>
slouken@8582
    25
#include <string>
slouken@8582
    26
#include <sstream>
slouken@8582
    27
using namespace std;
slouken@8582
    28
slouken@8582
    29
slouken@8582
    30
/* Windows includes */
slouken@8582
    31
#include "ppltasks.h"
slouken@8582
    32
using namespace concurrency;
slouken@8582
    33
using namespace Windows::ApplicationModel;
slouken@8582
    34
using namespace Windows::ApplicationModel::Core;
slouken@8582
    35
using namespace Windows::ApplicationModel::Activation;
slouken@8582
    36
using namespace Windows::Devices::Input;
slouken@8582
    37
using namespace Windows::Graphics::Display;
slouken@8582
    38
using namespace Windows::Foundation;
slouken@8582
    39
using namespace Windows::System;
slouken@8582
    40
using namespace Windows::UI::Core;
slouken@8582
    41
using namespace Windows::UI::Input;
slouken@8582
    42
slouken@8582
    43
#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
slouken@8582
    44
using namespace Windows::Phone::UI::Input;
slouken@8582
    45
#endif
slouken@8582
    46
slouken@8582
    47
slouken@8582
    48
/* SDL includes */
slouken@8582
    49
extern "C" {
dludwig@8600
    50
#include "../../SDL_internal.h"
slouken@8582
    51
#include "SDL_assert.h"
slouken@8582
    52
#include "SDL_events.h"
slouken@8582
    53
#include "SDL_hints.h"
slouken@8582
    54
#include "SDL_log.h"
slouken@8582
    55
#include "SDL_main.h"
slouken@8582
    56
#include "SDL_stdinc.h"
slouken@8582
    57
#include "SDL_render.h"
slouken@8582
    58
#include "../../video/SDL_sysvideo.h"
slouken@8582
    59
//#include "../../SDL_hints_c.h"
slouken@8582
    60
#include "../../events/SDL_events_c.h"
slouken@8582
    61
#include "../../events/SDL_keyboard_c.h"
slouken@8582
    62
#include "../../events/SDL_mouse_c.h"
slouken@8582
    63
#include "../../events/SDL_windowevents_c.h"
slouken@8582
    64
#include "../../render/SDL_sysrender.h"
slouken@8582
    65
#include "../windows/SDL_windows.h"
slouken@8582
    66
}
slouken@8582
    67
slouken@8582
    68
#include "../../video/winrt/SDL_winrtevents_c.h"
slouken@8582
    69
#include "../../video/winrt/SDL_winrtvideo_cpp.h"
slouken@8582
    70
#include "SDL_winrtapp_common.h"
slouken@8582
    71
#include "SDL_winrtapp_direct3d.h"
slouken@8582
    72
dludwig@8679
    73
#if SDL_VIDEO_RENDER_D3D11 && !SDL_RENDER_DISABLED
dludwig@8679
    74
/* Calling IDXGIDevice3::Trim on the active Direct3D 11.x device is necessary
dludwig@8679
    75
 * when Windows 8.1 apps are about to get suspended.
dludwig@8679
    76
 */
dludwig@8679
    77
extern "C" void D3D11_Trim(SDL_Renderer *);
dludwig@8679
    78
#endif
dludwig@8679
    79
slouken@8582
    80
slouken@8582
    81
// Compile-time debugging options:
slouken@8582
    82
// To enable, uncomment; to disable, comment them out.
slouken@8582
    83
//#define LOG_POINTER_EVENTS 1
slouken@8582
    84
//#define LOG_WINDOW_EVENTS 1
slouken@8582
    85
//#define LOG_ORIENTATION_EVENTS 1
slouken@8582
    86
slouken@8582
    87
slouken@8582
    88
// HACK, DLudwig: record a reference to the global, WinRT 'app'/view.
slouken@8582
    89
// SDL/WinRT will use this throughout its code.
slouken@8582
    90
//
slouken@8582
    91
// TODO, WinRT: consider replacing SDL_WinRTGlobalApp with something
slouken@8582
    92
// non-global, such as something created inside
slouken@8582
    93
// SDL_InitSubSystem(SDL_INIT_VIDEO), or something inside
slouken@8582
    94
// SDL_CreateWindow().
slouken@8582
    95
SDL_WinRTApp ^ SDL_WinRTGlobalApp = nullptr;
slouken@8582
    96
slouken@8582
    97
ref class SDLApplicationSource sealed : Windows::ApplicationModel::Core::IFrameworkViewSource
slouken@8582
    98
{
slouken@8582
    99
public:
slouken@8582
   100
    virtual Windows::ApplicationModel::Core::IFrameworkView^ CreateView();
slouken@8582
   101
};
slouken@8582
   102
slouken@8582
   103
IFrameworkView^ SDLApplicationSource::CreateView()
slouken@8582
   104
{
slouken@8582
   105
    // TODO, WinRT: see if this function (CreateView) can ever get called
slouken@8582
   106
    // more than once.  For now, just prevent it from ever assigning
slouken@8582
   107
    // SDL_WinRTGlobalApp more than once.
slouken@8582
   108
    SDL_assert(!SDL_WinRTGlobalApp);
slouken@8582
   109
    SDL_WinRTApp ^ app = ref new SDL_WinRTApp();
slouken@8582
   110
    if (!SDL_WinRTGlobalApp)
slouken@8582
   111
    {
slouken@8582
   112
        SDL_WinRTGlobalApp = app;
slouken@8582
   113
    }
slouken@8582
   114
    return app;
slouken@8582
   115
}
slouken@8582
   116
slouken@8582
   117
int SDL_WinRTInitNonXAMLApp(int (*mainFunction)(int, char **))
slouken@8582
   118
{
slouken@8582
   119
    WINRT_SDLAppEntryPoint = mainFunction;
slouken@8582
   120
    auto direct3DApplicationSource = ref new SDLApplicationSource();
slouken@8582
   121
    CoreApplication::Run(direct3DApplicationSource);
slouken@8582
   122
    return 0;
slouken@8582
   123
}
slouken@8582
   124
slouken@8582
   125
static void WINRT_SetDisplayOrientationsPreference(void *userdata, const char *name, const char *oldValue, const char *newValue)
slouken@8582
   126
{
slouken@8582
   127
    SDL_assert(SDL_strcmp(name, SDL_HINT_ORIENTATIONS) == 0);
slouken@8582
   128
slouken@8582
   129
    // Start with no orientation flags, then add each in as they're parsed
slouken@8582
   130
    // from newValue.
slouken@8582
   131
    unsigned int orientationFlags = 0;
slouken@8582
   132
    if (newValue) {
slouken@8582
   133
        std::istringstream tokenizer(newValue);
slouken@8582
   134
        while (!tokenizer.eof()) {
slouken@8582
   135
            std::string orientationName;
slouken@8582
   136
            std::getline(tokenizer, orientationName, ' ');
slouken@8582
   137
            if (orientationName == "LandscapeLeft") {
slouken@8582
   138
                orientationFlags |= (unsigned int) DisplayOrientations::LandscapeFlipped;
slouken@8582
   139
            } else if (orientationName == "LandscapeRight") {
slouken@8582
   140
                orientationFlags |= (unsigned int) DisplayOrientations::Landscape;
slouken@8582
   141
            } else if (orientationName == "Portrait") {
slouken@8582
   142
                orientationFlags |= (unsigned int) DisplayOrientations::Portrait;
slouken@8582
   143
            } else if (orientationName == "PortraitUpsideDown") {
slouken@8582
   144
                orientationFlags |= (unsigned int) DisplayOrientations::PortraitFlipped;
slouken@8582
   145
            }
slouken@8582
   146
        }
slouken@8582
   147
    }
slouken@8582
   148
slouken@8582
   149
    // If no valid orientation flags were specified, use a reasonable set of defaults:
slouken@8582
   150
    if (!orientationFlags) {
slouken@8582
   151
        // TODO, WinRT: consider seeing if an app's default orientation flags can be found out via some API call(s).
slouken@8582
   152
        orientationFlags = (unsigned int) ( \
slouken@8582
   153
            DisplayOrientations::Landscape |
slouken@8582
   154
            DisplayOrientations::LandscapeFlipped |
slouken@8582
   155
            DisplayOrientations::Portrait |
slouken@8582
   156
            DisplayOrientations::PortraitFlipped);
slouken@8582
   157
    }
slouken@8582
   158
slouken@8582
   159
    // Set the orientation/rotation preferences.  Please note that this does
slouken@8582
   160
    // not constitute a 100%-certain lock of a given set of possible
slouken@8582
   161
    // orientations.  According to Microsoft's documentation on WinRT [1]
slouken@8582
   162
    // when a device is not capable of being rotated, Windows may ignore
slouken@8582
   163
    // the orientation preferences, and stick to what the device is capable of
slouken@8582
   164
    // displaying.
slouken@8582
   165
    //
slouken@8582
   166
    // [1] Documentation on the 'InitialRotationPreference' setting for a
slouken@8582
   167
    // Windows app's manifest file describes how some orientation/rotation
slouken@8582
   168
    // preferences may be ignored.  See
slouken@8582
   169
    // http://msdn.microsoft.com/en-us/library/windows/apps/hh700343.aspx
slouken@8582
   170
    // for details.  Microsoft's "Display orientation sample" also gives an
slouken@8582
   171
    // outline of how Windows treats device rotation
slouken@8582
   172
    // (http://code.msdn.microsoft.com/Display-Orientation-Sample-19a58e93).
dludwig@8757
   173
    WINRT_DISPLAY_PROPERTY(AutoRotationPreferences) = (DisplayOrientations) orientationFlags;
slouken@8582
   174
}
slouken@8582
   175
slouken@8582
   176
static void
slouken@8582
   177
WINRT_ProcessWindowSizeChange()
slouken@8582
   178
{
dludwig@8664
   179
    SDL_VideoDevice *_this = SDL_GetVideoDevice();
dludwig@8664
   180
slouken@8582
   181
    // Make the new window size be the one true fullscreen mode.
slouken@8582
   182
    // This change was initially done, in part, to allow the Direct3D 11.1
slouken@8582
   183
    // renderer to receive window-resize events as a device rotates.
slouken@8582
   184
    // Before, rotating a device from landscape, to portrait, and then
slouken@8582
   185
    // back to landscape would cause the Direct3D 11.1 swap buffer to
slouken@8582
   186
    // not get resized appropriately.  SDL would, on the rotation from
slouken@8582
   187
    // landscape to portrait, re-resize the SDL window to it's initial
slouken@8582
   188
    // size (landscape).  On the subsequent rotation, SDL would drop the
slouken@8582
   189
    // window-resize event as it appeared the SDL window didn't change
slouken@8582
   190
    // size, and the Direct3D 11.1 renderer wouldn't resize its swap
slouken@8582
   191
    // chain.
slouken@8582
   192
    SDL_DisplayMode newDisplayMode;
slouken@8582
   193
    if (WINRT_CalcDisplayModeUsingNativeWindow(&newDisplayMode) != 0) {
slouken@8582
   194
        return;
slouken@8582
   195
    }
slouken@8582
   196
slouken@8582
   197
    // Make note of the old display mode, and it's old driverdata.
slouken@8582
   198
    SDL_DisplayMode oldDisplayMode;
slouken@8582
   199
    SDL_zero(oldDisplayMode);
dludwig@8664
   200
    if (_this) {
dludwig@8664
   201
        oldDisplayMode = _this->displays[0].desktop_mode;
slouken@8582
   202
    }
slouken@8582
   203
slouken@8582
   204
    // Setup the new display mode in the appropriate spots.
dludwig@8664
   205
    if (_this) {
slouken@8582
   206
        // Make a full copy of the display mode for display_modes[0],
slouken@8582
   207
        // one with with a separately malloced 'driverdata' field.
slouken@8582
   208
        // SDL_VideoQuit(), if called, will attempt to free the driverdata
slouken@8582
   209
        // fields in 'desktop_mode' and each entry in the 'display_modes'
slouken@8582
   210
        // array.
dludwig@8664
   211
        if (_this->displays[0].display_modes[0].driverdata) {
slouken@8582
   212
            // Free the previous mode's memory
dludwig@8664
   213
            SDL_free(_this->displays[0].display_modes[0].driverdata);
dludwig@8664
   214
            _this->displays[0].display_modes[0].driverdata = NULL;
slouken@8582
   215
        }
dludwig@8664
   216
        if (WINRT_DuplicateDisplayMode(&(_this->displays[0].display_modes[0]), &newDisplayMode) != 0) {
slouken@8582
   217
            // Uh oh, something went wrong.  A malloc call probably failed.
slouken@8582
   218
            SDL_free(newDisplayMode.driverdata);
slouken@8582
   219
            return;
slouken@8582
   220
        }
slouken@8582
   221
slouken@8582
   222
        // Install 'newDisplayMode' into 'current_mode' and 'desktop_mode'.
dludwig@8664
   223
        _this->displays[0].current_mode = newDisplayMode;
dludwig@8664
   224
        _this->displays[0].desktop_mode = newDisplayMode;
slouken@8582
   225
    }
slouken@8582
   226
slouken@8582
   227
    if (WINRT_GlobalSDLWindow) {
dludwig@8755
   228
        // If the window size changed, send a resize event to SDL and its host app:
dludwig@8755
   229
        int window_w = 0;
dludwig@8755
   230
        int window_h = 0;
dludwig@8755
   231
        SDL_GetWindowSize(WINRT_GlobalSDLWindow, &window_w, &window_h);
dludwig@8755
   232
        if ((window_w != newDisplayMode.w) || (window_h != newDisplayMode.h)) {
dludwig@8755
   233
            SDL_SendWindowEvent(
dludwig@8755
   234
                WINRT_GlobalSDLWindow,
dludwig@8755
   235
                SDL_WINDOWEVENT_RESIZED,
dludwig@8755
   236
                newDisplayMode.w,
dludwig@8755
   237
                newDisplayMode.h);
dludwig@8755
   238
        } else {
slouken@8582
   239
#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
dludwig@8755
   240
            // HACK: Make sure that orientation changes
dludwig@8755
   241
            // lead to the Direct3D renderer's viewport getting updated:
slouken@8582
   242
            //
dludwig@8755
   243
            // For some reason, this doesn't seem to need to be done on Windows 8.x,
dludwig@8755
   244
            // even when going from Landscape to LandscapeFlipped.  It only seems to
dludwig@8755
   245
            // be needed on Windows Phone, at least when I tested on my devices.
dludwig@8755
   246
            // I'm not currently sure why this is, but it seems to work fine. -- David L.
dludwig@8755
   247
            //
dludwig@8755
   248
            // 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
dludwig@8755
   249
            const DisplayOrientations oldOrientation = ((SDL_DisplayModeData *)oldDisplayMode.driverdata)->currentOrientation;
dludwig@8755
   250
            const DisplayOrientations newOrientation = ((SDL_DisplayModeData *)newDisplayMode.driverdata)->currentOrientation;
dludwig@8755
   251
            if (oldOrientation != newOrientation)
slouken@8582
   252
            {
slouken@8582
   253
                SDL_SendWindowEvent(
slouken@8582
   254
                    WINRT_GlobalSDLWindow,
slouken@8582
   255
                    SDL_WINDOWEVENT_SIZE_CHANGED,
slouken@8582
   256
                    newDisplayMode.w,
slouken@8582
   257
                    newDisplayMode.h);
slouken@8582
   258
            }
dludwig@8755
   259
#endif
slouken@8582
   260
        }
slouken@8582
   261
    }
slouken@8582
   262
    
slouken@8582
   263
    // Finally, free the 'driverdata' field of the old 'desktop_mode'.
slouken@8582
   264
    if (oldDisplayMode.driverdata) {
slouken@8582
   265
        SDL_free(oldDisplayMode.driverdata);
slouken@8582
   266
        oldDisplayMode.driverdata = NULL;
slouken@8582
   267
    }
slouken@8582
   268
}
slouken@8582
   269
slouken@8582
   270
SDL_WinRTApp::SDL_WinRTApp() :
slouken@8582
   271
    m_windowClosed(false),
slouken@8582
   272
    m_windowVisible(true)
slouken@8582
   273
{
slouken@8582
   274
}
slouken@8582
   275
slouken@8582
   276
void SDL_WinRTApp::Initialize(CoreApplicationView^ applicationView)
slouken@8582
   277
{
slouken@8582
   278
    applicationView->Activated +=
slouken@8582
   279
        ref new TypedEventHandler<CoreApplicationView^, IActivatedEventArgs^>(this, &SDL_WinRTApp::OnActivated);
slouken@8582
   280
slouken@8582
   281
    CoreApplication::Suspending +=
slouken@8582
   282
        ref new EventHandler<SuspendingEventArgs^>(this, &SDL_WinRTApp::OnSuspending);
slouken@8582
   283
slouken@8582
   284
    CoreApplication::Resuming +=
slouken@8582
   285
        ref new EventHandler<Platform::Object^>(this, &SDL_WinRTApp::OnResuming);
slouken@8582
   286
slouken@8582
   287
    CoreApplication::Exiting +=
slouken@8582
   288
        ref new EventHandler<Platform::Object^>(this, &SDL_WinRTApp::OnExiting);
slouken@8582
   289
}
slouken@8582
   290
dludwig@8621
   291
#if NTDDI_VERSION > NTDDI_WIN8
dludwig@8621
   292
void SDL_WinRTApp::OnOrientationChanged(DisplayInformation^ sender, Object^ args)
dludwig@8621
   293
#else
slouken@8582
   294
void SDL_WinRTApp::OnOrientationChanged(Object^ sender)
dludwig@8621
   295
#endif
slouken@8582
   296
{
slouken@8582
   297
#if LOG_ORIENTATION_EVENTS==1
slouken@8582
   298
    CoreWindow^ window = CoreWindow::GetForCurrentThread();
slouken@8582
   299
    if (window) {
slouken@8582
   300
        SDL_Log("%s, current orientation=%d, native orientation=%d, auto rot. pref=%d, CoreWindow Size={%f,%f}\n",
slouken@8582
   301
            __FUNCTION__,
dludwig@8755
   302
            WINRT_DISPLAY_PROPERTY(CurrentOrientation),
dludwig@8755
   303
            WINRT_DISPLAY_PROPERTY(NativeOrientation),
dludwig@8755
   304
            WINRT_DISPLAY_PROPERTY(AutoRotationPreferences),
slouken@8582
   305
            window->Bounds.Width,
slouken@8582
   306
            window->Bounds.Height);
slouken@8582
   307
    } else {
slouken@8582
   308
        SDL_Log("%s, current orientation=%d, native orientation=%d, auto rot. pref=%d\n",
slouken@8582
   309
            __FUNCTION__,
dludwig@8755
   310
            WINRT_DISPLAY_PROPERTY(CurrentOrientation),
dludwig@8755
   311
            WINRT_DISPLAY_PROPERTY(NativeOrientation),
dludwig@8755
   312
            WINRT_DISPLAY_PROPERTY(AutoRotationPreferences));
slouken@8582
   313
    }
slouken@8582
   314
#endif
slouken@8582
   315
slouken@8582
   316
    WINRT_ProcessWindowSizeChange();
slouken@8582
   317
}
slouken@8582
   318
slouken@8582
   319
void SDL_WinRTApp::SetWindow(CoreWindow^ window)
slouken@8582
   320
{
slouken@8582
   321
#if LOG_WINDOW_EVENTS==1
slouken@8582
   322
    SDL_Log("%s, current orientation=%d, native orientation=%d, auto rot. pref=%d, window Size={%f,%f}\n",
slouken@8582
   323
        __FUNCTION__,
dludwig@8755
   324
        WINRT_DISPLAY_PROPERTY(CurrentOrientation),
dludwig@8755
   325
        WINRT_DISPLAY_PROPERTY(NativeOrientation),
dludwig@8755
   326
        WINRT_DISPLAY_PROPERTY(AutoRotationPreferences),
slouken@8582
   327
        window->Bounds.Width,
slouken@8582
   328
        window->Bounds.Height);
slouken@8582
   329
#endif
slouken@8582
   330
slouken@8582
   331
    window->SizeChanged += 
slouken@8582
   332
        ref new TypedEventHandler<CoreWindow^, WindowSizeChangedEventArgs^>(this, &SDL_WinRTApp::OnWindowSizeChanged);
slouken@8582
   333
slouken@8582
   334
    window->VisibilityChanged +=
slouken@8582
   335
        ref new TypedEventHandler<CoreWindow^, VisibilityChangedEventArgs^>(this, &SDL_WinRTApp::OnVisibilityChanged);
slouken@8582
   336
slouken@8582
   337
    window->Closed += 
slouken@8582
   338
        ref new TypedEventHandler<CoreWindow^, CoreWindowEventArgs^>(this, &SDL_WinRTApp::OnWindowClosed);
slouken@8582
   339
slouken@8582
   340
#if WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP
slouken@8582
   341
    window->PointerCursor = ref new CoreCursor(CoreCursorType::Arrow, 0);
slouken@8582
   342
#endif
slouken@8582
   343
slouken@8582
   344
    window->PointerPressed +=
slouken@8582
   345
        ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &SDL_WinRTApp::OnPointerPressed);
slouken@8582
   346
slouken@8582
   347
    window->PointerMoved +=
slouken@8582
   348
        ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &SDL_WinRTApp::OnPointerMoved);
slouken@8582
   349
slouken@8582
   350
    window->PointerReleased +=
slouken@8582
   351
        ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &SDL_WinRTApp::OnPointerReleased);
slouken@8582
   352
slouken@8582
   353
    window->PointerWheelChanged +=
slouken@8582
   354
        ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &SDL_WinRTApp::OnPointerWheelChanged);
slouken@8582
   355
slouken@8582
   356
#if WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP
slouken@8582
   357
    // Retrieves relative-only mouse movements:
slouken@8582
   358
    Windows::Devices::Input::MouseDevice::GetForCurrentView()->MouseMoved +=
slouken@8582
   359
        ref new TypedEventHandler<MouseDevice^, MouseEventArgs^>(this, &SDL_WinRTApp::OnMouseMoved);
slouken@8582
   360
#endif
slouken@8582
   361
slouken@8582
   362
    window->KeyDown +=
slouken@8582
   363
        ref new TypedEventHandler<CoreWindow^, KeyEventArgs^>(this, &SDL_WinRTApp::OnKeyDown);
slouken@8582
   364
slouken@8582
   365
    window->KeyUp +=
slouken@8582
   366
        ref new TypedEventHandler<CoreWindow^, KeyEventArgs^>(this, &SDL_WinRTApp::OnKeyUp);
slouken@8582
   367
dludwig@9240
   368
    window->CharacterReceived +=
dludwig@9240
   369
        ref new TypedEventHandler<CoreWindow^, CharacterReceivedEventArgs^>(this, &SDL_WinRTApp::OnCharacterReceived);
dludwig@9240
   370
slouken@8582
   371
#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
slouken@8582
   372
    HardwareButtons::BackPressed +=
slouken@8582
   373
        ref new EventHandler<BackPressedEventArgs^>(this, &SDL_WinRTApp::OnBackButtonPressed);
slouken@8582
   374
#endif
slouken@8582
   375
dludwig@8621
   376
#if NTDDI_VERSION > NTDDI_WIN8
dludwig@8621
   377
    DisplayInformation::GetForCurrentView()->OrientationChanged +=
dludwig@8621
   378
        ref new TypedEventHandler<Windows::Graphics::Display::DisplayInformation^, Object^>(this, &SDL_WinRTApp::OnOrientationChanged);
dludwig@8621
   379
#else
dludwig@8621
   380
    DisplayProperties::OrientationChanged +=
dludwig@8621
   381
        ref new DisplayPropertiesEventHandler(this, &SDL_WinRTApp::OnOrientationChanged);
dludwig@8621
   382
#endif
dludwig@8621
   383
dludwig@8621
   384
    // Register the hint, SDL_HINT_ORIENTATIONS, with SDL.
dludwig@8621
   385
    // TODO, WinRT: see if an app's default orientation can be found out via WinRT API(s), then set the initial value of SDL_HINT_ORIENTATIONS accordingly.
dludwig@8621
   386
    SDL_AddHintCallback(SDL_HINT_ORIENTATIONS, WINRT_SetDisplayOrientationsPreference, NULL);
dludwig@8621
   387
slouken@8582
   388
#if WINAPI_FAMILY == WINAPI_FAMILY_APP  // for Windows 8/8.1/RT apps... (and not Phone apps)
slouken@8582
   389
    // Make sure we know when a user has opened the app's settings pane.
slouken@8582
   390
    // This is needed in order to display a privacy policy, which needs
slouken@8582
   391
    // to be done for network-enabled apps, as per Windows Store requirements.
slouken@8582
   392
    using namespace Windows::UI::ApplicationSettings;
slouken@8582
   393
    SettingsPane::GetForCurrentView()->CommandsRequested +=
slouken@8582
   394
        ref new TypedEventHandler<SettingsPane^, SettingsPaneCommandsRequestedEventArgs^>
slouken@8582
   395
            (this, &SDL_WinRTApp::OnSettingsPaneCommandsRequested);
slouken@8582
   396
#endif
slouken@8582
   397
}
slouken@8582
   398
slouken@8582
   399
void SDL_WinRTApp::Load(Platform::String^ entryPoint)
slouken@8582
   400
{
slouken@8582
   401
}
slouken@8582
   402
slouken@8582
   403
void SDL_WinRTApp::Run()
slouken@8582
   404
{
slouken@8582
   405
    SDL_SetMainReady();
slouken@8582
   406
    if (WINRT_SDLAppEntryPoint)
slouken@8582
   407
    {
slouken@8582
   408
        // TODO, WinRT: pass the C-style main() a reasonably realistic
slouken@8582
   409
        // representation of command line arguments.
slouken@8582
   410
        int argc = 0;
slouken@8582
   411
        char **argv = NULL;
slouken@8582
   412
        WINRT_SDLAppEntryPoint(argc, argv);
slouken@8582
   413
    }
slouken@8582
   414
}
slouken@8582
   415
dludwig@8666
   416
static bool IsSDLWindowEventPending(SDL_WindowEventID windowEventID)
dludwig@8666
   417
{
dludwig@8666
   418
    SDL_Event events[128];
dludwig@8666
   419
    const int count = SDL_PeepEvents(events, sizeof(events)/sizeof(SDL_Event), SDL_PEEKEVENT, SDL_WINDOWEVENT, SDL_WINDOWEVENT);
dludwig@8666
   420
    for (int i = 0; i < count; ++i) {
dludwig@8666
   421
        if (events[i].window.event == windowEventID) {
dludwig@8666
   422
            return true;
dludwig@8666
   423
        }
dludwig@8666
   424
    }
dludwig@8666
   425
    return false;
dludwig@8666
   426
}
dludwig@8666
   427
dludwig@8666
   428
bool SDL_WinRTApp::ShouldWaitForAppResumeEvents()
dludwig@8666
   429
{
dludwig@8666
   430
    /* Don't wait if the app is visible: */
dludwig@8666
   431
    if (m_windowVisible) {
dludwig@8666
   432
        return false;
dludwig@8666
   433
    }
dludwig@8666
   434
    
dludwig@8666
   435
    /* Don't wait until the window-hide events finish processing.
dludwig@8666
   436
     * Do note that if an app-suspend event is sent (as indicated
dludwig@8666
   437
     * by SDL_APP_WILLENTERBACKGROUND and SDL_APP_DIDENTERBACKGROUND
dludwig@8666
   438
     * events), then this code may be a moot point, as WinRT's
dludwig@8666
   439
     * own event pump (aka ProcessEvents()) will pause regardless
dludwig@8666
   440
     * of what we do here.  This happens on Windows Phone 8, to note.
dludwig@8666
   441
     * Windows 8.x apps, on the other hand, may get a chance to run
dludwig@8666
   442
     * these.
dludwig@8666
   443
     */
dludwig@8666
   444
    if (IsSDLWindowEventPending(SDL_WINDOWEVENT_HIDDEN)) {
dludwig@8666
   445
        return false;
dludwig@8666
   446
    } else if (IsSDLWindowEventPending(SDL_WINDOWEVENT_FOCUS_LOST)) {
dludwig@8666
   447
        return false;
dludwig@8666
   448
    } else if (IsSDLWindowEventPending(SDL_WINDOWEVENT_MINIMIZED)) {
dludwig@8666
   449
        return false;
dludwig@8666
   450
    }
dludwig@8666
   451
dludwig@8666
   452
    return true;
dludwig@8666
   453
}
dludwig@8666
   454
slouken@8582
   455
void SDL_WinRTApp::PumpEvents()
slouken@8582
   456
{
dludwig@8666
   457
    if (!m_windowClosed) {
dludwig@8666
   458
        if (!ShouldWaitForAppResumeEvents()) {
dludwig@8666
   459
            /* This is the normal way in which events should be pumped.
dludwig@8666
   460
             * 'ProcessAllIfPresent' will make ProcessEvents() process anywhere
dludwig@8666
   461
             * from zero to N events, and will then return.
dludwig@8666
   462
             */
slouken@8582
   463
            CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent);
dludwig@8666
   464
        } else {
dludwig@8666
   465
            /* This style of event-pumping, with 'ProcessOneAndAllPending',
dludwig@8666
   466
             * will cause anywhere from one to N events to be processed.  If
dludwig@8666
   467
             * at least one event is processed, the call will return.  If
dludwig@8666
   468
             * no events are pending, then the call will wait until one is
dludwig@8666
   469
             * available, and will not return (to the caller) until this
dludwig@8666
   470
             * happens!  This should only occur when the app is hidden.
dludwig@8666
   471
             */
slouken@8582
   472
            CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessOneAndAllPending);
slouken@8582
   473
        }
slouken@8582
   474
    }
slouken@8582
   475
}
slouken@8582
   476
slouken@8582
   477
void SDL_WinRTApp::Uninitialize()
slouken@8582
   478
{
slouken@8582
   479
}
slouken@8582
   480
slouken@8582
   481
#if WINAPI_FAMILY == WINAPI_FAMILY_APP
slouken@8582
   482
void SDL_WinRTApp::OnSettingsPaneCommandsRequested(
slouken@8582
   483
    Windows::UI::ApplicationSettings::SettingsPane ^p,
slouken@8582
   484
    Windows::UI::ApplicationSettings::SettingsPaneCommandsRequestedEventArgs ^args)
slouken@8582
   485
{
slouken@8582
   486
    using namespace Platform;
slouken@8582
   487
    using namespace Windows::UI::ApplicationSettings;
slouken@8582
   488
    using namespace Windows::UI::Popups;
slouken@8582
   489
slouken@8582
   490
    String ^privacyPolicyURL = nullptr;     // a URL to an app's Privacy Policy
slouken@8582
   491
    String ^privacyPolicyLabel = nullptr;   // label/link text
slouken@8582
   492
    const char *tmpHintValue = NULL;        // SDL_GetHint-retrieved value, used immediately
slouken@8582
   493
    wchar_t *tmpStr = NULL;                 // used for UTF8 to UCS2 conversion
slouken@8582
   494
slouken@8582
   495
    // Setup a 'Privacy Policy' link, if one is available (via SDL_GetHint):
slouken@8582
   496
    tmpHintValue = SDL_GetHint(SDL_HINT_WINRT_PRIVACY_POLICY_URL);
slouken@8582
   497
    if (tmpHintValue && tmpHintValue[0] != '\0') {
slouken@8582
   498
        // Convert the privacy policy's URL to UCS2:
slouken@8582
   499
        tmpStr = WIN_UTF8ToString(tmpHintValue);
slouken@8582
   500
        privacyPolicyURL = ref new String(tmpStr);
slouken@8582
   501
        SDL_free(tmpStr);
slouken@8582
   502
slouken@8582
   503
        // Optionally retrieve custom label-text for the link.  If this isn't
slouken@8582
   504
        // available, a default value will be used instead.
slouken@8582
   505
        tmpHintValue = SDL_GetHint(SDL_HINT_WINRT_PRIVACY_POLICY_LABEL);
slouken@8582
   506
        if (tmpHintValue && tmpHintValue[0] != '\0') {
slouken@8582
   507
            tmpStr = WIN_UTF8ToString(tmpHintValue);
slouken@8582
   508
            privacyPolicyLabel = ref new String(tmpStr);
slouken@8582
   509
            SDL_free(tmpStr);
slouken@8582
   510
        } else {
slouken@8582
   511
            privacyPolicyLabel = ref new String(L"Privacy Policy");
slouken@8582
   512
        }
slouken@8582
   513
slouken@8582
   514
        // Register the link, along with a handler to be called if and when it is
slouken@8582
   515
        // clicked:
slouken@8582
   516
        auto cmd = ref new SettingsCommand(L"privacyPolicy", privacyPolicyLabel,
slouken@8582
   517
            ref new UICommandInvokedHandler([=](IUICommand ^) {
slouken@8582
   518
                Windows::System::Launcher::LaunchUriAsync(ref new Uri(privacyPolicyURL));
slouken@8582
   519
        }));
slouken@8582
   520
        args->Request->ApplicationCommands->Append(cmd);
slouken@8582
   521
    }
slouken@8582
   522
}
slouken@8582
   523
#endif // if WINAPI_FAMILY == WINAPI_FAMILY_APP
slouken@8582
   524
slouken@8582
   525
void SDL_WinRTApp::OnWindowSizeChanged(CoreWindow^ sender, WindowSizeChangedEventArgs^ args)
slouken@8582
   526
{
slouken@8582
   527
#if LOG_WINDOW_EVENTS==1
slouken@8582
   528
    SDL_Log("%s, size={%f,%f}, current orientation=%d, native orientation=%d, auto rot. pref=%d, WINRT_GlobalSDLWindow?=%s\n",
slouken@8582
   529
        __FUNCTION__,
slouken@8582
   530
        args->Size.Width, args->Size.Height,
dludwig@8755
   531
        WINRT_DISPLAY_PROPERTY(CurrentOrientation),
dludwig@8755
   532
        WINRT_DISPLAY_PROPERTY(NativeOrientation),
dludwig@8755
   533
        WINRT_DISPLAY_PROPERTY(AutoRotationPreferences),
slouken@8582
   534
        (WINRT_GlobalSDLWindow ? "yes" : "no"));
slouken@8582
   535
#endif
slouken@8582
   536
slouken@8582
   537
    WINRT_ProcessWindowSizeChange();
slouken@8582
   538
}
slouken@8582
   539
slouken@8582
   540
void SDL_WinRTApp::OnVisibilityChanged(CoreWindow^ sender, VisibilityChangedEventArgs^ args)
slouken@8582
   541
{
slouken@8582
   542
#if LOG_WINDOW_EVENTS==1
slouken@8582
   543
    SDL_Log("%s, visible?=%s, WINRT_GlobalSDLWindow?=%s\n",
slouken@8582
   544
        __FUNCTION__,
slouken@8582
   545
        (args->Visible ? "yes" : "no"),
slouken@8582
   546
        (WINRT_GlobalSDLWindow ? "yes" : "no"));
slouken@8582
   547
#endif
slouken@8582
   548
slouken@8582
   549
    m_windowVisible = args->Visible;
slouken@8582
   550
    if (WINRT_GlobalSDLWindow) {
slouken@8582
   551
        SDL_bool wasSDLWindowSurfaceValid = WINRT_GlobalSDLWindow->surface_valid;
slouken@8582
   552
slouken@8582
   553
        if (args->Visible) {
slouken@8582
   554
            SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_WINDOWEVENT_SHOWN, 0, 0);
dludwig@8678
   555
            SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_WINDOWEVENT_FOCUS_GAINED, 0, 0);
dludwig@8678
   556
            SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_WINDOWEVENT_RESTORED, 0, 0);
slouken@8582
   557
        } else {
slouken@8582
   558
            SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_WINDOWEVENT_HIDDEN, 0, 0);
dludwig@8678
   559
            SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_WINDOWEVENT_FOCUS_LOST, 0, 0);
dludwig@8678
   560
            SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_WINDOWEVENT_MINIMIZED, 0, 0);
slouken@8582
   561
        }
slouken@8582
   562
slouken@8582
   563
        // HACK: Prevent SDL's window-hide handling code, which currently
slouken@8582
   564
        // triggers a fake window resize (possibly erronously), from
slouken@8582
   565
        // marking the SDL window's surface as invalid.
slouken@8582
   566
        //
slouken@8582
   567
        // A better solution to this probably involves figuring out if the
slouken@8582
   568
        // fake window resize can be prevented.
slouken@8582
   569
        WINRT_GlobalSDLWindow->surface_valid = wasSDLWindowSurfaceValid;
slouken@8582
   570
    }
slouken@8582
   571
}
slouken@8582
   572
slouken@8582
   573
void SDL_WinRTApp::OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args)
slouken@8582
   574
{
slouken@8582
   575
#if LOG_WINDOW_EVENTS==1
slouken@8582
   576
    SDL_Log("%s\n", __FUNCTION__);
slouken@8582
   577
#endif
slouken@8582
   578
    m_windowClosed = true;
slouken@8582
   579
}
slouken@8582
   580
slouken@8582
   581
void SDL_WinRTApp::OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args)
slouken@8582
   582
{
slouken@8582
   583
    CoreWindow::GetForCurrentThread()->Activate();
slouken@8582
   584
}
slouken@8582
   585
slouken@8582
   586
void SDL_WinRTApp::OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args)
slouken@8582
   587
{
slouken@8582
   588
    // Save app state asynchronously after requesting a deferral. Holding a deferral
slouken@8582
   589
    // indicates that the application is busy performing suspending operations. Be
slouken@8582
   590
    // aware that a deferral may not be held indefinitely. After about five seconds,
slouken@8582
   591
    // the app will be forced to exit.
dludwig@8665
   592
dludwig@8665
   593
    // ... but first, let the app know it's about to go to the background.
dludwig@8665
   594
    // The separation of events may be important, given that the deferral
dludwig@8665
   595
    // runs in a separate thread.  This'll make SDL_APP_WILLENTERBACKGROUND
dludwig@8665
   596
    // the only event among the two that runs in the main thread.  Given
dludwig@8665
   597
    // that a few WinRT operations can only be done from the main thread
dludwig@8665
   598
    // (things that access the WinRT CoreWindow are one example of this),
dludwig@8665
   599
    // this could be important.
dludwig@8665
   600
    SDL_SendAppEvent(SDL_APP_WILLENTERBACKGROUND);
dludwig@8665
   601
slouken@8582
   602
    SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral();
slouken@8582
   603
    create_task([this, deferral]()
slouken@8582
   604
    {
dludwig@8666
   605
        // Send an app did-enter-background event immediately to observers.
slouken@8582
   606
        // CoreDispatcher::ProcessEvents, which is the backbone on which
slouken@8582
   607
        // SDL_WinRTApp::PumpEvents is built, will not return to its caller
slouken@8582
   608
        // once it sends out a suspend event.  Any events posted to SDL's
slouken@8582
   609
        // event queue won't get received until the WinRT app is resumed.
slouken@8582
   610
        // SDL_AddEventWatch() may be used to receive app-suspend events on
slouken@8582
   611
        // WinRT.
slouken@8582
   612
        SDL_SendAppEvent(SDL_APP_DIDENTERBACKGROUND);
slouken@8582
   613
dludwig@8679
   614
        // Let the Direct3D 11 renderer prepare for the app to be backgrounded.
dludwig@8679
   615
        // This is necessary for Windows 8.1, possibly elsewhere in the future.
dludwig@8679
   616
        // More details at: http://msdn.microsoft.com/en-us/library/windows/apps/Hh994929.aspx
dludwig@8679
   617
#if SDL_VIDEO_RENDER_D3D11 && !SDL_RENDER_DISABLED
dludwig@8679
   618
        if (WINRT_GlobalSDLWindow) {
dludwig@8679
   619
            SDL_Renderer * renderer = SDL_GetRenderer(WINRT_GlobalSDLWindow);
dludwig@8679
   620
            if (renderer && (SDL_strcmp(renderer->info.name, "direct3d11") == 0)) {
dludwig@8679
   621
                D3D11_Trim(renderer);
dludwig@8679
   622
            }
dludwig@8679
   623
        }
dludwig@8679
   624
#endif
dludwig@8679
   625
slouken@8582
   626
        deferral->Complete();
slouken@8582
   627
    });
slouken@8582
   628
}
slouken@8582
   629
slouken@8582
   630
void SDL_WinRTApp::OnResuming(Platform::Object^ sender, Platform::Object^ args)
slouken@8582
   631
{
dludwig@8666
   632
    // Restore any data or state that was unloaded on suspend. By default, data
dludwig@8666
   633
    // and state are persisted when resuming from suspend. Note that these events
dludwig@8666
   634
    // do not occur if the app was previously terminated.
slouken@8582
   635
    SDL_SendAppEvent(SDL_APP_WILLENTERFOREGROUND);
slouken@8582
   636
    SDL_SendAppEvent(SDL_APP_DIDENTERFOREGROUND);
slouken@8582
   637
}
slouken@8582
   638
slouken@8582
   639
void SDL_WinRTApp::OnExiting(Platform::Object^ sender, Platform::Object^ args)
slouken@8582
   640
{
slouken@8582
   641
    SDL_SendAppEvent(SDL_APP_TERMINATING);
slouken@8582
   642
}
slouken@8582
   643
slouken@8582
   644
static void
slouken@8582
   645
WINRT_LogPointerEvent(const char * header, Windows::UI::Core::PointerEventArgs ^ args, Windows::Foundation::Point transformedPoint)
slouken@8582
   646
{
slouken@8582
   647
    Windows::UI::Input::PointerPoint ^ pt = args->CurrentPoint;
slouken@8582
   648
    SDL_Log("%s: Position={%f,%f}, Transformed Pos={%f, %f}, MouseWheelDelta=%d, FrameId=%d, PointerId=%d, SDL button=%d\n",
slouken@8582
   649
        header,
slouken@8582
   650
        pt->Position.X, pt->Position.Y,
slouken@8582
   651
        transformedPoint.X, transformedPoint.Y,
slouken@8582
   652
        pt->Properties->MouseWheelDelta,
slouken@8582
   653
        pt->FrameId,
slouken@8582
   654
        pt->PointerId,
slouken@8582
   655
        WINRT_GetSDLButtonForPointerPoint(pt));
slouken@8582
   656
}
slouken@8582
   657
slouken@8582
   658
void SDL_WinRTApp::OnPointerPressed(CoreWindow^ sender, PointerEventArgs^ args)
slouken@8582
   659
{
slouken@8582
   660
#if LOG_POINTER_EVENTS
slouken@8582
   661
    WINRT_LogPointerEvent("pointer pressed", args, WINRT_TransformCursorPosition(WINRT_GlobalSDLWindow, args->CurrentPoint->Position, TransformToSDLWindowSize));
slouken@8582
   662
#endif
slouken@8582
   663
slouken@8582
   664
    WINRT_ProcessPointerPressedEvent(WINRT_GlobalSDLWindow, args->CurrentPoint);
slouken@8582
   665
}
slouken@8582
   666
slouken@8582
   667
void SDL_WinRTApp::OnPointerMoved(CoreWindow^ sender, PointerEventArgs^ args)
slouken@8582
   668
{
slouken@8582
   669
#if LOG_POINTER_EVENTS
slouken@8582
   670
    WINRT_LogPointerEvent("pointer moved", args, WINRT_TransformCursorPosition(WINRT_GlobalSDLWindow, args->CurrentPoint->Position, TransformToSDLWindowSize));
slouken@8582
   671
#endif
slouken@8582
   672
slouken@8582
   673
    WINRT_ProcessPointerMovedEvent(WINRT_GlobalSDLWindow, args->CurrentPoint);
slouken@8582
   674
}
slouken@8582
   675
slouken@8582
   676
void SDL_WinRTApp::OnPointerReleased(CoreWindow^ sender, PointerEventArgs^ args)
slouken@8582
   677
{
slouken@8582
   678
#if LOG_POINTER_EVENTS
slouken@8582
   679
    WINRT_LogPointerEvent("pointer released", args, WINRT_TransformCursorPosition(WINRT_GlobalSDLWindow, args->CurrentPoint->Position, TransformToSDLWindowSize));
slouken@8582
   680
#endif
slouken@8582
   681
slouken@8582
   682
    WINRT_ProcessPointerReleasedEvent(WINRT_GlobalSDLWindow, args->CurrentPoint);
slouken@8582
   683
}
slouken@8582
   684
slouken@8582
   685
void SDL_WinRTApp::OnPointerWheelChanged(CoreWindow^ sender, PointerEventArgs^ args)
slouken@8582
   686
{
slouken@8582
   687
#if LOG_POINTER_EVENTS
slouken@8582
   688
    WINRT_LogPointerEvent("pointer wheel changed", args, WINRT_TransformCursorPosition(WINRT_GlobalSDLWindow, args->CurrentPoint->Position, TransformToSDLWindowSize));
slouken@8582
   689
#endif
slouken@8582
   690
slouken@8582
   691
    WINRT_ProcessPointerWheelChangedEvent(WINRT_GlobalSDLWindow, args->CurrentPoint);
slouken@8582
   692
}
slouken@8582
   693
slouken@8582
   694
void SDL_WinRTApp::OnMouseMoved(MouseDevice^ mouseDevice, MouseEventArgs^ args)
slouken@8582
   695
{
slouken@8582
   696
    WINRT_ProcessMouseMovedEvent(WINRT_GlobalSDLWindow, args);
slouken@8582
   697
}
slouken@8582
   698
slouken@8582
   699
void SDL_WinRTApp::OnKeyDown(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyEventArgs^ args)
slouken@8582
   700
{
slouken@8582
   701
    WINRT_ProcessKeyDownEvent(args);
slouken@8582
   702
}
slouken@8582
   703
slouken@8582
   704
void SDL_WinRTApp::OnKeyUp(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyEventArgs^ args)
slouken@8582
   705
{
slouken@8582
   706
    WINRT_ProcessKeyUpEvent(args);
slouken@8582
   707
}
slouken@8582
   708
dludwig@9240
   709
void SDL_WinRTApp::OnCharacterReceived(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::CharacterReceivedEventArgs^ args)
dludwig@9240
   710
{
dludwig@9240
   711
    WINRT_ProcessCharacterReceivedEvent(args);
dludwig@9240
   712
}
dludwig@9240
   713
slouken@8582
   714
#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
slouken@8582
   715
void SDL_WinRTApp::OnBackButtonPressed(Platform::Object^ sender, Windows::Phone::UI::Input::BackPressedEventArgs^ args)
slouken@8582
   716
{
slouken@8582
   717
    SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_AC_BACK);
slouken@8582
   718
    SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_AC_BACK);
slouken@8582
   719
dludwig@8577
   720
    const char *hint = SDL_GetHint(SDL_HINT_WINRT_HANDLE_BACK_BUTTON);
dludwig@8577
   721
    if (hint) {
dludwig@8577
   722
        if (*hint == '1') {
dludwig@8577
   723
            args->Handled = true;
dludwig@8577
   724
        }
slouken@8582
   725
    }
slouken@8582
   726
}
slouken@8582
   727
#endif
slouken@8582
   728