src/video/windows/SDL_windowswindow.c
author Ryan C. Gordon <icculus@icculus.org>
Thu, 01 Aug 2013 00:27:22 -0400
changeset 7559 0dd3b05797f9
parent 7556 574f465da18a
child 7583 7e053ad01aa3
permissions -rw-r--r--
Move the fix for Bugzilla #1395 into WIN_GL_SetupWindow() directly.

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