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