src/video/winrt/SDL_winrtvideo.cpp
author David Ludwig <dludwig@pobox.com>
Mon, 02 Sep 2013 15:29:46 -0400
changeset 8516 f3e0e381bdcd
parent 8515 bc6cf9201dab
child 8522 3ae9dc9c439f
permissions -rw-r--r--
WinRT: renamed a mouse-related header file for naming-consistency's sake
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 #include "SDL_config.h"
    22 
    23 #if SDL_VIDEO_DRIVER_WINRT
    24 
    25 /* WinRT SDL video driver implementation
    26 
    27    Initial work on this was done by David Ludwig (dludwig@pobox.com), and
    28    was based off of SDL's "dummy" video driver.
    29  */
    30 
    31 /* Windows includes */
    32 #include <agile.h>
    33 using namespace Windows::UI::Core;
    34 
    35 
    36 /* SDL includes */
    37 extern "C" {
    38 #include "SDL_video.h"
    39 #include "SDL_mouse.h"
    40 #include "../SDL_sysvideo.h"
    41 #include "../SDL_pixels_c.h"
    42 #include "../../events/SDL_events_c.h"
    43 #include "../../render/SDL_sysrender.h"
    44 #include "SDL_syswm.h"
    45 }
    46 
    47 #include "../../core/winrt/SDL_winrtapp.h"
    48 #include "../../core/winrt/SDL_winrtxaml_cpp.h"
    49 #include "SDL_winrtvideo_cpp.h"
    50 #include "SDL_winrtevents_c.h"
    51 #include "SDL_winrtmouse_c.h"
    52 #include "SDL_main.h"
    53 #include "SDL_system.h"
    54 
    55 
    56 /* Initialization/Query functions */
    57 static int WINRT_VideoInit(_THIS);
    58 static int WINRT_InitModes(_THIS);
    59 static int WINRT_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode);
    60 static void WINRT_VideoQuit(_THIS);
    61 
    62 
    63 /* Window functions */
    64 static int WINRT_CreateWindow(_THIS, SDL_Window * window);
    65 static void WINRT_DestroyWindow(_THIS, SDL_Window * window);
    66 static SDL_bool WINRT_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info);
    67 
    68 
    69 /* SDL-internal globals: */
    70 SDL_Window * WINRT_GlobalSDLWindow = NULL;
    71 SDL_VideoDevice * WINRT_GlobalSDLVideoDevice = NULL;
    72 
    73 
    74 /* WinRT driver bootstrap functions */
    75 
    76 static int
    77 WINRT_Available(void)
    78 {
    79     return (1);
    80 }
    81 
    82 static void
    83 WINRT_DeleteDevice(SDL_VideoDevice * device)
    84 {
    85     if (device == WINRT_GlobalSDLVideoDevice) {
    86         WINRT_GlobalSDLVideoDevice = NULL;
    87     }
    88     SDL_free(device);
    89 }
    90 
    91 static SDL_VideoDevice *
    92 WINRT_CreateDevice(int devindex)
    93 {
    94     SDL_VideoDevice *device;
    95 
    96     /* Initialize all variables that we clean on shutdown */
    97     device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice));
    98     if (!device) {
    99         SDL_OutOfMemory();
   100         if (device) {
   101             SDL_free(device);
   102         }
   103         return (0);
   104     }
   105 
   106     /* Set the function pointers */
   107     device->VideoInit = WINRT_VideoInit;
   108     device->VideoQuit = WINRT_VideoQuit;
   109     device->CreateWindow = WINRT_CreateWindow;
   110     device->DestroyWindow = WINRT_DestroyWindow;
   111     device->SetDisplayMode = WINRT_SetDisplayMode;
   112     device->PumpEvents = WINRT_PumpEvents;
   113     device->GetWindowWMInfo = WINRT_GetWindowWMInfo;
   114     device->free = WINRT_DeleteDevice;
   115     WINRT_GlobalSDLVideoDevice = device;
   116 
   117     return device;
   118 }
   119 
   120 #define WINRTVID_DRIVER_NAME "winrt"
   121 VideoBootStrap WINRT_bootstrap = {
   122     WINRTVID_DRIVER_NAME, "SDL WinRT video driver",
   123     WINRT_Available, WINRT_CreateDevice
   124 };
   125 
   126 int
   127 WINRT_VideoInit(_THIS)
   128 {
   129     if (WINRT_InitModes(_this) < 0) {
   130         return -1;
   131     }
   132     WINRT_InitMouse(_this);
   133     WINRT_InitTouch(_this);
   134 
   135     return 0;
   136 }
   137 
   138 SDL_DisplayMode
   139 WINRT_CalcDisplayModeUsingNativeWindow()
   140 {
   141     using namespace Windows::Graphics::Display;
   142 
   143     // Create an empty, zeroed-out display mode:
   144     SDL_DisplayMode mode;
   145     SDL_zero(mode);
   146 
   147     // Go no further if a native window cannot be accessed.  This can happen,
   148     // for example, if this function is called from certain threads, such as
   149     // the SDL/XAML thread.
   150     if (!CoreWindow::GetForCurrentThread()) {
   151         return mode;
   152     }
   153 
   154     // Fill in most fields:
   155     mode.format = SDL_PIXELFORMAT_RGB888;
   156     mode.refresh_rate = 0;  // TODO, WinRT: see if refresh rate data is available, or relevant (for WinRT apps)
   157     mode.driverdata = (void *) DisplayProperties::CurrentOrientation;
   158 
   159     // Calculate the display size given the window size, taking into account
   160     // the current display's DPI:
   161     const float currentDPI = Windows::Graphics::Display::DisplayProperties::LogicalDpi; 
   162     const float dipsPerInch = 96.0f;
   163     mode.w = (int) ((CoreWindow::GetForCurrentThread()->Bounds.Width * currentDPI) / dipsPerInch);
   164     mode.h = (int) ((CoreWindow::GetForCurrentThread()->Bounds.Height * currentDPI) / dipsPerInch);
   165 
   166 #if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
   167     // On Windows Phone, the native window's size is always in portrait,
   168     // regardless of the device's orientation.  This is in contrast to
   169     // Windows 8/RT, which will resize the native window as the device's
   170     // orientation changes.  In order to compensate for this behavior,
   171     // on Windows Phone, the mode's width and height will be swapped when
   172     // the device is in a landscape (non-portrait) mode.
   173     switch (DisplayProperties::CurrentOrientation) {
   174         case DisplayOrientations::Landscape:
   175         case DisplayOrientations::LandscapeFlipped:
   176         {
   177             const int tmp = mode.h;
   178             mode.h = mode.w;
   179             mode.w = tmp;
   180             break;
   181         }
   182 
   183         default:
   184             break;
   185     }
   186 
   187     // Attach the mode to te
   188 #endif
   189 
   190     return mode;
   191 }
   192 
   193 int
   194 WINRT_InitModes(_THIS)
   195 {
   196     // Retrieve the display mode:
   197     SDL_DisplayMode mode = WINRT_CalcDisplayModeUsingNativeWindow();
   198     if (mode.w == 0 || mode.h == 0) {
   199         return SDL_SetError("Unable to calculate the WinRT window/display's size");
   200     }
   201 
   202     if (SDL_AddBasicVideoDisplay(&mode) < 0) {
   203         return -1;
   204     }
   205 
   206     SDL_AddDisplayMode(&_this->displays[0], &mode);
   207     return 0;
   208 }
   209 
   210 static int
   211 WINRT_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
   212 {
   213     return 0;
   214 }
   215 
   216 void
   217 WINRT_VideoQuit(_THIS)
   218 {
   219     WINRT_QuitMouse(_this);
   220 }
   221 
   222 int
   223 WINRT_CreateWindow(_THIS, SDL_Window * window)
   224 {
   225     // Make sure that only one window gets created, at least until multimonitor
   226     // support is added.
   227     if (WINRT_GlobalSDLWindow != NULL) {
   228         SDL_SetError("WinRT only supports one window");
   229         return -1;
   230     }
   231 
   232     SDL_WindowData *data = new SDL_WindowData;
   233     if (!data) {
   234         SDL_OutOfMemory();
   235         return -1;
   236     }
   237     window->driverdata = data;
   238     data->sdlWindow = window;
   239 
   240     /* To note, when XAML support is enabled, access to the CoreWindow will not
   241        be possible, at least not via the SDL/XAML thread.  Attempts to access it
   242        from there will throw exceptions.  As such, the SDL_WindowData's
   243        'coreWindow' field will only be set (to a non-null value) if XAML isn't
   244        enabled.
   245     */
   246     if (!WINRT_XAMLWasEnabled) {
   247         data->coreWindow = CoreWindow::GetForCurrentThread();
   248     }
   249 
   250     /* Make sure the window is considered to be positioned at {0,0},
   251        and is considered fullscreen, shown, and the like.
   252     */
   253     window->x = 0;
   254     window->y = 0;
   255     window->flags =
   256         SDL_WINDOW_FULLSCREEN |
   257         SDL_WINDOW_SHOWN |
   258         SDL_WINDOW_BORDERLESS |
   259         SDL_WINDOW_MAXIMIZED |
   260         SDL_WINDOW_INPUT_GRABBED;
   261 
   262     /* WinRT does not, as of this writing, appear to support app-adjustable
   263        window sizes.  Set the window size to whatever the native WinRT
   264        CoreWindow is set at.
   265 
   266        TODO, WinRT: if and when non-fullscreen XAML control support is added to SDL, consider making those resizable via SDL_Window's interfaces.
   267     */
   268     window->w = _this->displays[0].current_mode.w;
   269     window->h = _this->displays[0].current_mode.h;
   270  
   271     /* Make sure the WinRT app's IFramworkView can post events on
   272        behalf of SDL:
   273     */
   274     WINRT_GlobalSDLWindow = window;
   275 
   276     /* All done! */
   277     return 0;
   278 }
   279 
   280 void
   281 WINRT_DestroyWindow(_THIS, SDL_Window * window)
   282 {
   283     SDL_WindowData * data = (SDL_WindowData *) window->driverdata;
   284 
   285     if (WINRT_GlobalSDLWindow == window) {
   286         WINRT_GlobalSDLWindow = NULL;
   287     }
   288 
   289     if (data) {
   290         // Delete the internal window data:
   291         delete data;
   292         data = NULL;
   293     }
   294 }
   295 
   296 SDL_bool
   297 WINRT_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
   298 {
   299     SDL_WindowData * data = (SDL_WindowData *) window->driverdata;
   300 
   301     if (info->version.major <= SDL_MAJOR_VERSION) {
   302         info->subsystem = SDL_SYSWM_WINRT;
   303         info->info.winrt.window = reinterpret_cast<IUnknown *>(data->coreWindow.Get());
   304         return SDL_TRUE;
   305     } else {
   306         SDL_SetError("Application not compiled with SDL %d.%d\n",
   307                      SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
   308         return SDL_FALSE;
   309     }
   310     return SDL_FALSE;
   311 }
   312 
   313 #endif /* SDL_VIDEO_DRIVER_WINRT */
   314 
   315 /* vi: set ts=4 sw=4 expandtab: */