src/video/windows/SDL_windowswindow.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 28 Sep 2013 14:06:20 -0700
changeset 7756 f45660a4974c
parent 7719 31b5f9ff36ca
child 7762 51abf7664304
permissions -rw-r--r--
Moved D3D_LoadDLL and SDL_Direct3D9GetAdapterIndex to SDL_windowswindow.c at Jorgen's insistence. That file is wrapped in a more appropriate define check so it will work if somebody builds a binary without D3D support.

Added a reference to SDL_Direct3D9GetAdapterIndex to SDL_test_common.c so SDL will fail to compile if the new symbol isn't included properly.

CR: Jorgen
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2013 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_WINDOWS
    24 
    25 #include "../../core/windows/SDL_windows.h"
    26 
    27 #include "SDL_assert.h"
    28 #include "SDL_system.h"
    29 #include "../SDL_sysvideo.h"
    30 #include "../SDL_pixels_c.h"
    31 #include "../../events/SDL_keyboard_c.h"
    32 #include "../../video/SDL_sysvideo.h"
    33 #include "../../video/windows/SDL_windowsmodes.h"
    34 
    35 #include "SDL_windowsvideo.h"
    36 #include "SDL_windowswindow.h"
    37 
    38 /* Dropfile support */
    39 #include <shellapi.h>
    40 
    41 /* This is included after SDL_windowsvideo.h, which includes windows.h */
    42 #include "SDL_syswm.h"
    43 
    44 #define D3D_DEBUG_INFO
    45 #include <d3d9.h>
    46 
    47 /* Windows CE compatibility */
    48 #ifndef SWP_NOCOPYBITS
    49 #define SWP_NOCOPYBITS 0
    50 #endif
    51 
    52 /* Fake window to help with DirectInput events. */
    53 HWND SDL_HelperWindow = NULL;
    54 static WCHAR *SDL_HelperWindowClassName = TEXT("SDLHelperWindowInputCatcher");
    55 static WCHAR *SDL_HelperWindowName = TEXT("SDLHelperWindowInputMsgWindow");
    56 static ATOM SDL_HelperWindowClass = 0;
    57 
    58 #define STYLE_BASIC         (WS_CLIPSIBLINGS | WS_CLIPCHILDREN)
    59 #define STYLE_FULLSCREEN    (WS_POPUP)
    60 #define STYLE_BORDERLESS    (WS_POPUP)
    61 #define STYLE_NORMAL        (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX)
    62 #define STYLE_RESIZABLE     (WS_THICKFRAME | WS_MAXIMIZEBOX)
    63 #define STYLE_MASK          (STYLE_FULLSCREEN | STYLE_BORDERLESS | STYLE_NORMAL | STYLE_RESIZABLE)
    64 
    65 static DWORD
    66 GetWindowStyle(SDL_Window * window)
    67 {
    68     DWORD style = 0;
    69 
    70     if (window->flags & SDL_WINDOW_FULLSCREEN) {
    71         style |= STYLE_FULLSCREEN;
    72     } else {
    73         if (window->flags & SDL_WINDOW_BORDERLESS) {
    74             style |= STYLE_BORDERLESS;
    75         } else {
    76             style |= STYLE_NORMAL;
    77         }
    78         if (window->flags & SDL_WINDOW_RESIZABLE) {
    79             style |= STYLE_RESIZABLE;
    80         }
    81     }
    82     return style;
    83 }
    84 
    85 static void
    86 WIN_SetWindowPositionInternal(_THIS, SDL_Window * window, UINT flags)
    87 {
    88     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
    89     RECT rect;
    90     DWORD style;
    91     HWND top;
    92     BOOL menu;
    93     int x, y;
    94     int w, h;
    95 
    96     /* Figure out what the window area will be */
    97     if (SDL_ShouldAllowTopmost() && (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_INPUT_FOCUS)) == (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_INPUT_FOCUS)) {
    98         top = HWND_TOPMOST;
    99     } else {
   100         top = HWND_NOTOPMOST;
   101     }
   102     style = GetWindowLong(hwnd, GWL_STYLE);
   103     rect.left = 0;
   104     rect.top = 0;
   105     rect.right = window->w;
   106     rect.bottom = window->h;
   107     menu = (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL);
   108     AdjustWindowRectEx(&rect, style, menu, 0);
   109     w = (rect.right - rect.left);
   110     h = (rect.bottom - rect.top);
   111     x = window->x + rect.left;
   112     y = window->y + rect.top;
   113 
   114     SetWindowPos(hwnd, top, x, y, w, h, flags);
   115 }
   116 
   117 static int
   118 SetupWindowData(_THIS, SDL_Window * window, HWND hwnd, SDL_bool created)
   119 {
   120     SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
   121     SDL_WindowData *data;
   122 
   123     /* Allocate the window data */
   124     data = (SDL_WindowData *) SDL_malloc(sizeof(*data));
   125     if (!data) {
   126         return SDL_OutOfMemory();
   127     }
   128     data->window = window;
   129     data->hwnd = hwnd;
   130     data->hdc = GetDC(hwnd);
   131     data->created = created;
   132     data->mouse_button_flags = 0;
   133     data->videodata = videodata;
   134 
   135     window->driverdata = data;
   136 
   137     /* Associate the data with the window */
   138     if (!SetProp(hwnd, TEXT("SDL_WindowData"), data)) {
   139         ReleaseDC(hwnd, data->hdc);
   140         SDL_free(data);
   141         return WIN_SetError("SetProp() failed");
   142     }
   143 
   144     /* Set up the window proc function */
   145 #ifdef GWLP_WNDPROC
   146     data->wndproc = (WNDPROC) GetWindowLongPtr(hwnd, GWLP_WNDPROC);
   147     if (data->wndproc == WIN_WindowProc) {
   148         data->wndproc = NULL;
   149     } else {
   150         SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR) WIN_WindowProc);
   151     }
   152 #else
   153     data->wndproc = (WNDPROC) GetWindowLong(hwnd, GWL_WNDPROC);
   154     if (data->wndproc == WIN_WindowProc) {
   155         data->wndproc = NULL;
   156     } else {
   157         SetWindowLong(hwnd, GWL_WNDPROC, (LONG_PTR) WIN_WindowProc);
   158     }
   159 #endif
   160 
   161     /* Fill in the SDL window with the window data */
   162     {
   163         RECT rect;
   164         if (GetClientRect(hwnd, &rect)) {
   165             int w = rect.right;
   166             int h = rect.bottom;
   167             if ((window->w && window->w != w) || (window->h && window->h != h)) {
   168                 /* We tried to create a window larger than the desktop and Windows didn't allow it.  Override! */
   169                 WIN_SetWindowPositionInternal(_this, window, SWP_NOCOPYBITS | SWP_NOZORDER | SWP_NOACTIVATE);
   170             } else {
   171                 window->w = w;
   172                 window->h = h;
   173             }
   174         }
   175     }
   176     {
   177         POINT point;
   178         point.x = 0;
   179         point.y = 0;
   180         if (ClientToScreen(hwnd, &point)) {
   181             window->x = point.x;
   182             window->y = point.y;
   183         }
   184     }
   185     {
   186         DWORD style = GetWindowLong(hwnd, GWL_STYLE);
   187         if (style & WS_VISIBLE) {
   188             window->flags |= SDL_WINDOW_SHOWN;
   189         } else {
   190             window->flags &= ~SDL_WINDOW_SHOWN;
   191         }
   192         if (style & (WS_BORDER | WS_THICKFRAME)) {
   193             window->flags &= ~SDL_WINDOW_BORDERLESS;
   194         } else {
   195             window->flags |= SDL_WINDOW_BORDERLESS;
   196         }
   197         if (style & WS_THICKFRAME) {
   198             window->flags |= SDL_WINDOW_RESIZABLE;
   199         } else {
   200             window->flags &= ~SDL_WINDOW_RESIZABLE;
   201         }
   202 #ifdef WS_MAXIMIZE
   203         if (style & WS_MAXIMIZE) {
   204             window->flags |= SDL_WINDOW_MAXIMIZED;
   205         } else
   206 #endif
   207         {
   208             window->flags &= ~SDL_WINDOW_MAXIMIZED;
   209         }
   210 #ifdef WS_MINIMIZE
   211         if (style & WS_MINIMIZE) {
   212             window->flags |= SDL_WINDOW_MINIMIZED;
   213         } else
   214 #endif
   215         {
   216             window->flags &= ~SDL_WINDOW_MINIMIZED;
   217         }
   218     }
   219     if (GetFocus() == hwnd) {
   220         window->flags |= SDL_WINDOW_INPUT_FOCUS;
   221         SDL_SetKeyboardFocus(data->window);
   222 
   223         if (window->flags & SDL_WINDOW_INPUT_GRABBED) {
   224             RECT rect;
   225             GetClientRect(hwnd, &rect);
   226             ClientToScreen(hwnd, (LPPOINT) & rect);
   227             ClientToScreen(hwnd, (LPPOINT) & rect + 1);
   228             ClipCursor(&rect);
   229         }
   230     }
   231 
   232     /* Enable multi-touch */
   233     if (videodata->RegisterTouchWindow) {
   234         videodata->RegisterTouchWindow(hwnd, (TWF_FINETOUCH|TWF_WANTPALM));
   235     }
   236 
   237     /* Enable dropping files */
   238     DragAcceptFiles(hwnd, TRUE);
   239 
   240     /* All done! */
   241     return 0;
   242 }
   243 
   244 int
   245 WIN_CreateWindow(_THIS, SDL_Window * window)
   246 {
   247     HWND hwnd;
   248     RECT rect;
   249     DWORD style = STYLE_BASIC;
   250     int x, y;
   251     int w, h;
   252 
   253     style |= GetWindowStyle(window);
   254 
   255     /* Figure out what the window area will be */
   256     rect.left = window->x;
   257     rect.top = window->y;
   258     rect.right = window->x + window->w;
   259     rect.bottom = window->y + window->h;
   260     AdjustWindowRectEx(&rect, style, FALSE, 0);
   261     x = rect.left;
   262     y = rect.top;
   263     w = (rect.right - rect.left);
   264     h = (rect.bottom - rect.top);
   265 
   266     hwnd =
   267         CreateWindow(SDL_Appname, TEXT(""), style, x, y, w, h, NULL, NULL,
   268                      SDL_Instance, NULL);
   269     if (!hwnd) {
   270         return WIN_SetError("Couldn't create window");
   271     }
   272 
   273     WIN_PumpEvents(_this);
   274 
   275     if (SetupWindowData(_this, window, hwnd, SDL_TRUE) < 0) {
   276         DestroyWindow(hwnd);
   277         return -1;
   278     }
   279 #if SDL_VIDEO_OPENGL_WGL
   280     if (window->flags & SDL_WINDOW_OPENGL) {
   281         if (WIN_GL_SetupWindow(_this, window) < 0) {
   282             WIN_DestroyWindow(_this, window);
   283             return -1;
   284         }
   285     }
   286 #endif
   287     return 0;
   288 }
   289 
   290 int
   291 WIN_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
   292 {
   293     HWND hwnd = (HWND) data;
   294     LPTSTR title;
   295     int titleLen;
   296 
   297     /* Query the title from the existing window */
   298     titleLen = GetWindowTextLength(hwnd);
   299     title = SDL_stack_alloc(TCHAR, titleLen + 1);
   300     if (title) {
   301         titleLen = GetWindowText(hwnd, title, titleLen);
   302     } else {
   303         titleLen = 0;
   304     }
   305     if (titleLen > 0) {
   306         window->title = WIN_StringToUTF8(title);
   307     }
   308     if (title) {
   309         SDL_stack_free(title);
   310     }
   311 
   312     if (SetupWindowData(_this, window, hwnd, SDL_FALSE) < 0) {
   313         return -1;
   314     }
   315     return 0;
   316 }
   317 
   318 void
   319 WIN_SetWindowTitle(_THIS, SDL_Window * window)
   320 {
   321     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   322     LPTSTR title;
   323 
   324     if (window->title) {
   325         title = WIN_UTF8ToString(window->title);
   326     } else {
   327         title = NULL;
   328     }
   329     SetWindowText(hwnd, title ? title : TEXT(""));
   330     SDL_free(title);
   331 }
   332 
   333 void
   334 WIN_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon)
   335 {
   336     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   337     HICON hicon = NULL;
   338     BYTE *icon_bmp;
   339     int icon_len, y;
   340     SDL_RWops *dst;
   341 
   342     /* Create temporary bitmap buffer */
   343     icon_len = 40 + icon->h * icon->w * 4;
   344     icon_bmp = SDL_stack_alloc(BYTE, icon_len);
   345     dst = SDL_RWFromMem(icon_bmp, icon_len);
   346     if (!dst) {
   347         SDL_stack_free(icon_bmp);
   348         return;
   349     }
   350 
   351     /* Write the BITMAPINFO header */
   352     SDL_WriteLE32(dst, 40);
   353     SDL_WriteLE32(dst, icon->w);
   354     SDL_WriteLE32(dst, icon->h * 2);
   355     SDL_WriteLE16(dst, 1);
   356     SDL_WriteLE16(dst, 32);
   357     SDL_WriteLE32(dst, BI_RGB);
   358     SDL_WriteLE32(dst, icon->h * icon->w * 4);
   359     SDL_WriteLE32(dst, 0);
   360     SDL_WriteLE32(dst, 0);
   361     SDL_WriteLE32(dst, 0);
   362     SDL_WriteLE32(dst, 0);
   363 
   364     /* Write the pixels upside down into the bitmap buffer */
   365     SDL_assert(icon->format->format == SDL_PIXELFORMAT_ARGB8888);
   366     y = icon->h;
   367     while (y--) {
   368         Uint8 *src = (Uint8 *) icon->pixels + y * icon->pitch;
   369         SDL_RWwrite(dst, src, icon->pitch, 1);
   370     }
   371 
   372     hicon = CreateIconFromResource(icon_bmp, icon_len, TRUE, 0x00030000);
   373 
   374     SDL_RWclose(dst);
   375     SDL_stack_free(icon_bmp);
   376 
   377     /* Set the icon for the window */
   378     SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM) hicon);
   379 
   380     /* Set the icon in the task manager (should we do this?) */
   381     SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM) hicon);
   382 }
   383 
   384 void
   385 WIN_SetWindowPosition(_THIS, SDL_Window * window)
   386 {
   387     WIN_SetWindowPositionInternal(_this, window, SWP_NOCOPYBITS | SWP_NOSIZE | SWP_NOACTIVATE);
   388 }
   389 
   390 void
   391 WIN_SetWindowSize(_THIS, SDL_Window * window)
   392 {
   393     WIN_SetWindowPositionInternal(_this, window, SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOACTIVATE);
   394 }
   395 
   396 void
   397 WIN_ShowWindow(_THIS, SDL_Window * window)
   398 {
   399     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   400     ShowWindow(hwnd, SW_SHOW);
   401 }
   402 
   403 void
   404 WIN_HideWindow(_THIS, SDL_Window * window)
   405 {
   406     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   407     ShowWindow(hwnd, SW_HIDE);
   408 }
   409 
   410 void
   411 WIN_RaiseWindow(_THIS, SDL_Window * window)
   412 {
   413     WIN_SetWindowPositionInternal(_this, window, SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOSIZE);
   414 }
   415 
   416 void
   417 WIN_MaximizeWindow(_THIS, SDL_Window * window)
   418 {
   419     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   420     ShowWindow(hwnd, SW_MAXIMIZE);
   421 }
   422 
   423 void
   424 WIN_MinimizeWindow(_THIS, SDL_Window * window)
   425 {
   426     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   427     ShowWindow(hwnd, SW_MINIMIZE);
   428 }
   429 
   430 void
   431 WIN_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered)
   432 {
   433     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   434     DWORD style = GetWindowLong(hwnd, GWL_STYLE);
   435 
   436     if (bordered) {
   437         style &= ~STYLE_BORDERLESS;
   438         style |= STYLE_NORMAL;
   439     } else {
   440         style &= ~STYLE_NORMAL;
   441         style |= STYLE_BORDERLESS;
   442     }
   443 
   444     SetWindowLong(hwnd, GWL_STYLE, style);
   445     WIN_SetWindowPositionInternal(_this, window, SWP_NOCOPYBITS | SWP_FRAMECHANGED | SWP_NOREPOSITION | SWP_NOZORDER |SWP_NOACTIVATE | SWP_NOSENDCHANGING);
   446 }
   447 
   448 void
   449 WIN_RestoreWindow(_THIS, SDL_Window * window)
   450 {
   451     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   452 
   453     ShowWindow(hwnd, SW_RESTORE);
   454 }
   455 
   456 void
   457 WIN_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen)
   458 {
   459     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
   460     HWND hwnd = data->hwnd;
   461     RECT rect;
   462     SDL_Rect bounds;
   463     DWORD style;
   464     HWND top;
   465     BOOL menu;
   466     int x, y;
   467     int w, h;
   468 
   469     if (SDL_ShouldAllowTopmost() && (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_INPUT_FOCUS)) == (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_INPUT_FOCUS)) {
   470         top = HWND_TOPMOST;
   471     } else {
   472         top = HWND_NOTOPMOST;
   473     }
   474 
   475     style = GetWindowLong(hwnd, GWL_STYLE);
   476     style &= ~STYLE_MASK;
   477     style |= GetWindowStyle(window);
   478 
   479     WIN_GetDisplayBounds(_this, display, &bounds);
   480 
   481     if (fullscreen) {
   482         x = bounds.x;
   483         y = bounds.y;
   484         w = bounds.w;
   485         h = bounds.h;
   486     } else {
   487         rect.left = 0;
   488         rect.top = 0;
   489         rect.right = window->windowed.w;
   490         rect.bottom = window->windowed.h;
   491         menu = (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL);
   492         AdjustWindowRectEx(&rect, style, menu, 0);
   493         w = (rect.right - rect.left);
   494         h = (rect.bottom - rect.top);
   495         x = window->windowed.x + rect.left;
   496         y = window->windowed.y + rect.top;
   497     }
   498     SetWindowLong(hwnd, GWL_STYLE, style);
   499     SetWindowPos(hwnd, top, x, y, w, h, SWP_NOCOPYBITS);
   500 }
   501 
   502 int
   503 WIN_SetWindowGammaRamp(_THIS, SDL_Window * window, const Uint16 * ramp)
   504 {
   505     SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
   506     SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
   507     HDC hdc;
   508     BOOL succeeded = FALSE;
   509 
   510     hdc = CreateDC(data->DeviceName, NULL, NULL, NULL);
   511     if (hdc) {
   512         succeeded = SetDeviceGammaRamp(hdc, (LPVOID)ramp);
   513         if (!succeeded) {
   514             WIN_SetError("SetDeviceGammaRamp()");
   515         }
   516         DeleteDC(hdc);
   517     }
   518     return succeeded ? 0 : -1;
   519 }
   520 
   521 int
   522 WIN_GetWindowGammaRamp(_THIS, SDL_Window * window, Uint16 * ramp)
   523 {
   524     SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
   525     SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
   526     HDC hdc;
   527     BOOL succeeded = FALSE;
   528 
   529     hdc = CreateDC(data->DeviceName, NULL, NULL, NULL);
   530     if (hdc) {
   531         succeeded = GetDeviceGammaRamp(hdc, (LPVOID)ramp);
   532         if (!succeeded) {
   533             WIN_SetError("GetDeviceGammaRamp()");
   534         }
   535         DeleteDC(hdc);
   536     }
   537     return succeeded ? 0 : -1;
   538 }
   539 
   540 void
   541 WIN_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
   542 {
   543     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   544 
   545     if (grabbed) {
   546         RECT rect;
   547         GetClientRect(hwnd, &rect);
   548         ClientToScreen(hwnd, (LPPOINT) & rect);
   549         ClientToScreen(hwnd, (LPPOINT) & rect + 1);
   550         ClipCursor(&rect);
   551     } else {
   552         ClipCursor(NULL);
   553     }
   554 
   555     if (window->flags & SDL_WINDOW_FULLSCREEN) {
   556         UINT flags = SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOSIZE;
   557 
   558         if (!(window->flags & SDL_WINDOW_SHOWN)) {
   559             flags |= SWP_NOACTIVATE;
   560         }
   561         WIN_SetWindowPositionInternal(_this, window, flags);
   562     }
   563 }
   564 
   565 void
   566 WIN_DestroyWindow(_THIS, SDL_Window * window)
   567 {
   568     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
   569 
   570     if (data) {
   571         ReleaseDC(data->hwnd, data->hdc);
   572         if (data->created) {
   573             DestroyWindow(data->hwnd);
   574         } else {
   575             /* Restore any original event handler... */
   576             if (data->wndproc != NULL) {
   577 #ifdef GWLP_WNDPROC
   578                 SetWindowLongPtr(data->hwnd, GWLP_WNDPROC,
   579                                  (LONG_PTR) data->wndproc);
   580 #else
   581                 SetWindowLong(data->hwnd, GWL_WNDPROC,
   582                               (LONG_PTR) data->wndproc);
   583 #endif
   584             }
   585         }
   586         SDL_free(data);
   587     }
   588 }
   589 
   590 SDL_bool
   591 WIN_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
   592 {
   593     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   594     if (info->version.major <= SDL_MAJOR_VERSION) {
   595         info->subsystem = SDL_SYSWM_WINDOWS;
   596         info->info.win.window = hwnd;
   597         return SDL_TRUE;
   598     } else {
   599         SDL_SetError("Application not compiled with SDL %d.%d\n",
   600                      SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
   601         return SDL_FALSE;
   602     }
   603 }
   604 
   605 
   606 /*
   607  * Creates a HelperWindow used for DirectInput events.
   608  */
   609 int
   610 SDL_HelperWindowCreate(void)
   611 {
   612     HINSTANCE hInstance = GetModuleHandle(NULL);
   613     WNDCLASS wce;
   614 
   615     /* Make sure window isn't created twice. */
   616     if (SDL_HelperWindow != NULL) {
   617         return 0;
   618     }
   619 
   620     /* Create the class. */
   621     SDL_zero(wce);
   622     wce.lpfnWndProc = DefWindowProc;
   623     wce.lpszClassName = (LPCWSTR) SDL_HelperWindowClassName;
   624     wce.hInstance = hInstance;
   625 
   626     /* Register the class. */
   627     SDL_HelperWindowClass = RegisterClass(&wce);
   628     if (SDL_HelperWindowClass == 0) {
   629         return WIN_SetError("Unable to create Helper Window Class");
   630     }
   631 
   632     /* Create the window. */
   633     SDL_HelperWindow = CreateWindowEx(0, SDL_HelperWindowClassName,
   634                                       SDL_HelperWindowName,
   635                                       WS_OVERLAPPED, CW_USEDEFAULT,
   636                                       CW_USEDEFAULT, CW_USEDEFAULT,
   637                                       CW_USEDEFAULT, HWND_MESSAGE, NULL,
   638                                       hInstance, NULL);
   639     if (SDL_HelperWindow == NULL) {
   640         UnregisterClass(SDL_HelperWindowClassName, hInstance);
   641         return WIN_SetError("Unable to create Helper Window");
   642     }
   643 
   644     return 0;
   645 }
   646 
   647 
   648 /*
   649  * Destroys the HelperWindow previously created with SDL_HelperWindowCreate.
   650  */
   651 void
   652 SDL_HelperWindowDestroy(void)
   653 {
   654     HINSTANCE hInstance = GetModuleHandle(NULL);
   655 
   656     /* Destroy the window. */
   657     if (SDL_HelperWindow != NULL) {
   658         if (DestroyWindow(SDL_HelperWindow) == 0) {
   659             WIN_SetError("Unable to destroy Helper Window");
   660             return;
   661         }
   662         SDL_HelperWindow = NULL;
   663     }
   664 
   665     /* Unregister the class. */
   666     if (SDL_HelperWindowClass != 0) {
   667         if ((UnregisterClass(SDL_HelperWindowClassName, hInstance)) == 0) {
   668             WIN_SetError("Unable to destroy Helper Window Class");
   669             return;
   670         }
   671         SDL_HelperWindowClass = 0;
   672     }
   673 }
   674 
   675 void WIN_OnWindowEnter(_THIS, SDL_Window * window)
   676 {
   677 #ifdef WM_MOUSELEAVE
   678     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
   679     TRACKMOUSEEVENT trackMouseEvent;
   680 
   681     if (!data || !data->hwnd) {
   682         /* The window wasn't fully initialized */
   683         return;
   684     }
   685 
   686     trackMouseEvent.cbSize = sizeof(TRACKMOUSEEVENT);
   687     trackMouseEvent.dwFlags = TME_LEAVE;
   688     trackMouseEvent.hwndTrack = data->hwnd;
   689 
   690     TrackMouseEvent(&trackMouseEvent);
   691 #endif /* WM_MOUSELEAVE */
   692 }
   693 
   694 SDL_bool 
   695 D3D_LoadDLL( void **pD3DDLL, IDirect3D9 **pDirect3D9Interface )
   696 {
   697 	*pD3DDLL = SDL_LoadObject("D3D9.DLL");
   698 	if (*pD3DDLL) {
   699 		IDirect3D9 *(WINAPI * D3DCreate) (UINT SDKVersion);
   700 
   701 		D3DCreate =
   702 			(IDirect3D9 * (WINAPI *) (UINT)) SDL_LoadFunction(*pD3DDLL,
   703 			"Direct3DCreate9");
   704 		if (D3DCreate) {
   705 			*pDirect3D9Interface = D3DCreate(D3D_SDK_VERSION);
   706 		}
   707 		if (!*pDirect3D9Interface) {
   708 			SDL_UnloadObject(*pD3DDLL);
   709 			*pD3DDLL = NULL;
   710 			return SDL_FALSE;
   711 		}
   712 
   713 		return SDL_TRUE;
   714 	} else {
   715 		*pDirect3D9Interface = NULL;
   716 		return SDL_FALSE;
   717 	}
   718 }
   719 
   720 
   721 int 
   722 SDL_Direct3D9GetAdapterIndex( int displayIndex )
   723 {
   724 	void *pD3DDLL;
   725 	IDirect3D9 *pD3D;
   726 	if (!D3D_LoadDLL(&pD3DDLL, &pD3D)) {
   727 		SDL_SetError("Unable to create Direct3D interface");
   728 		return D3DADAPTER_DEFAULT;
   729 	} else {
   730 		SDL_DisplayData *pData = (SDL_DisplayData *)SDL_GetDisplayDriverData(displayIndex);
   731 		int adapterIndex = D3DADAPTER_DEFAULT;
   732 
   733 		if (!pData) {
   734 			SDL_SetError("Invalid display index");
   735 			adapterIndex = -1; /* make sure we return something invalid */
   736 		} else {
   737 			char *displayName = WIN_StringToUTF8(pData->DeviceName);
   738 			unsigned int count = IDirect3D9_GetAdapterCount(pD3D);
   739 			unsigned int i;
   740 			for (i=0; i<count; i++) {
   741 				D3DADAPTER_IDENTIFIER9 id;
   742 				IDirect3D9_GetAdapterIdentifier(pD3D, i, 0, &id);
   743 
   744 				if (SDL_strcmp(id.DeviceName, displayName) == 0) {
   745 					adapterIndex = i;
   746 					break;
   747 				}
   748 			}
   749 			SDL_free(displayName);
   750 		}
   751 
   752 		/* free up the D3D stuff we inited */
   753 		IDirect3D9_Release(pD3D);
   754 		SDL_UnloadObject(pD3DDLL);
   755 
   756 		return adapterIndex;
   757 	}
   758 }
   759 
   760 
   761 
   762 #endif /* SDL_VIDEO_DRIVER_WINDOWS */
   763 
   764 /* vi: set ts=4 sw=4 expandtab: */