src/video/windows/SDL_windowswindow.c
author Ryan C. Gordon <icculus@icculus.org>
Fri, 14 Sep 2012 13:14:20 -0400
changeset 6428 0028fa91dfc6
parent 6427 34059553702a
child 6430 48d519500f7e
permissions -rwxr-xr-x
Made Windows version of SDL_SetWindowBordered() mostly work.

The sizing still isn't quite right.
     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     DWORD style = GetWindowLong(hwnd, GWL_STYLE);
   491 
   492     if (bordered) {
   493         style &= ~STYLE_BORDERLESS;
   494         style |= STYLE_NORMAL;
   495     } else {
   496         style &= ~STYLE_NORMAL;
   497         style |= STYLE_BORDERLESS;
   498     }
   499 
   500     SetWindowLong(hwnd, GWL_STYLE, style);
   501     SetWindowPos(hwnd, hwnd, window->x, window->y, window->w, window->h, SWP_FRAMECHANGED | SWP_NOREPOSITION | SWP_NOZORDER |SWP_NOACTIVATE | SWP_NOSENDCHANGING);
   502 }
   503 
   504 void
   505 WIN_RestoreWindow(_THIS, SDL_Window * window)
   506 {
   507     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   508 
   509     ShowWindow(hwnd, SW_RESTORE);
   510 }
   511 
   512 void
   513 WIN_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen)
   514 {
   515     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
   516     HWND hwnd = data->hwnd;
   517     RECT rect;
   518     SDL_Rect bounds;
   519     DWORD style;
   520     HWND top;
   521     BOOL menu;
   522     int x, y;
   523     int w, h;
   524 
   525     if (fullscreen) {
   526         top = HWND_TOPMOST;
   527     } else {
   528         top = HWND_NOTOPMOST;
   529     }
   530     style = GetWindowLong(hwnd, GWL_STYLE);
   531     style &= ~STYLE_MASK;
   532     style |= GetWindowStyle(window);
   533 
   534     WIN_GetDisplayBounds(_this, display, &bounds);
   535 
   536     if (fullscreen) {
   537         x = bounds.x;
   538         y = bounds.y;
   539         w = bounds.w;
   540         h = bounds.h;
   541     } else {
   542         rect.left = 0;
   543         rect.top = 0;
   544         rect.right = window->windowed.w;
   545         rect.bottom = window->windowed.h;
   546 #ifdef _WIN32_WCE
   547         menu = FALSE;
   548 #else
   549         menu = (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL);
   550 #endif
   551         AdjustWindowRectEx(&rect, style, menu, 0);
   552         w = (rect.right - rect.left);
   553         h = (rect.bottom - rect.top);
   554         x = window->windowed.x + rect.left;
   555         y = window->windowed.y + rect.top;
   556     }
   557     SetWindowLong(hwnd, GWL_STYLE, style);
   558     SetWindowPos(hwnd, top, x, y, w, h, SWP_NOCOPYBITS);
   559 }
   560 
   561 int
   562 WIN_SetWindowGammaRamp(_THIS, SDL_Window * window, const Uint16 * ramp)
   563 {
   564 #ifdef _WIN32_WCE
   565     SDL_Unsupported();
   566     return -1;
   567 #else
   568     SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
   569     SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
   570     HDC hdc;
   571     BOOL succeeded = FALSE;
   572 
   573     hdc = CreateDC(data->DeviceName, NULL, NULL, NULL);
   574     if (hdc) {
   575         succeeded = SetDeviceGammaRamp(hdc, (LPVOID)ramp);
   576         if (!succeeded) {
   577             WIN_SetError("SetDeviceGammaRamp()");
   578         }
   579         DeleteDC(hdc);
   580     }
   581     return succeeded ? 0 : -1;
   582 #endif
   583 }
   584 
   585 int
   586 WIN_GetWindowGammaRamp(_THIS, SDL_Window * window, Uint16 * ramp)
   587 {
   588 #ifdef _WIN32_WCE
   589     SDL_Unsupported();
   590     return -1;
   591 #else
   592     SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
   593     SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
   594     HDC hdc;
   595     BOOL succeeded = FALSE;
   596 
   597     hdc = CreateDC(data->DeviceName, NULL, NULL, NULL);
   598     if (hdc) {
   599         succeeded = GetDeviceGammaRamp(hdc, (LPVOID)ramp);
   600         if (!succeeded) {
   601             WIN_SetError("GetDeviceGammaRamp()");
   602         }
   603         DeleteDC(hdc);
   604     }
   605     return succeeded ? 0 : -1;
   606 #endif
   607 }
   608 
   609 void
   610 WIN_SetWindowGrab(_THIS, SDL_Window * window)
   611 {
   612     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   613 
   614     if ((window->flags & SDL_WINDOW_INPUT_GRABBED) &&
   615         (window->flags & SDL_WINDOW_INPUT_FOCUS)) {
   616         RECT rect;
   617         GetClientRect(hwnd, &rect);
   618         ClientToScreen(hwnd, (LPPOINT) & rect);
   619         ClientToScreen(hwnd, (LPPOINT) & rect + 1);
   620         ClipCursor(&rect);
   621     } else {
   622         ClipCursor(NULL);
   623     }
   624 }
   625 
   626 void
   627 WIN_DestroyWindow(_THIS, SDL_Window * window)
   628 {
   629     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
   630 
   631     if (data) {
   632 #ifdef _WIN32_WCE
   633         WINCE_ShowWindow(_this, window, 0);
   634 #endif
   635         ReleaseDC(data->hwnd, data->hdc);
   636         if (data->created) {
   637             DestroyWindow(data->hwnd);
   638         } else {
   639             /* Restore any original event handler... */
   640             if (data->wndproc != NULL) {
   641 #ifdef GWLP_WNDPROC
   642                 SetWindowLongPtr(data->hwnd, GWLP_WNDPROC,
   643                                  (LONG_PTR) data->wndproc);
   644 #else
   645                 SetWindowLong(data->hwnd, GWL_WNDPROC,
   646                               (LONG_PTR) data->wndproc);
   647 #endif
   648             }
   649         }
   650         SDL_free(data);
   651     }
   652 }
   653 
   654 SDL_bool
   655 WIN_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
   656 {
   657     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   658     if (info->version.major <= SDL_MAJOR_VERSION) {
   659         info->subsystem = SDL_SYSWM_WINDOWS;
   660         info->info.win.window = hwnd;
   661         return SDL_TRUE;
   662     } else {
   663         SDL_SetError("Application not compiled with SDL %d.%d\n",
   664                      SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
   665         return SDL_FALSE;
   666     }
   667 }
   668 
   669 
   670 /*
   671  * Creates a HelperWindow used for DirectInput events.
   672  */
   673 int
   674 SDL_HelperWindowCreate(void)
   675 {
   676     HINSTANCE hInstance = GetModuleHandle(NULL);
   677     WNDCLASS wce;
   678     HWND hWndParent = NULL;
   679 
   680     /* Make sure window isn't created twice. */
   681     if (SDL_HelperWindow != NULL) {
   682         return 0;
   683     }
   684 
   685     /* Create the class. */
   686     SDL_zero(wce);
   687     wce.lpfnWndProc = DefWindowProc;
   688     wce.lpszClassName = (LPCWSTR) SDL_HelperWindowClassName;
   689     wce.hInstance = hInstance;
   690 
   691     /* Register the class. */
   692     SDL_HelperWindowClass = RegisterClass(&wce);
   693     if (SDL_HelperWindowClass == 0) {
   694         WIN_SetError("Unable to create Helper Window Class");
   695         return -1;
   696     }
   697 
   698 #ifndef _WIN32_WCE
   699     /* WinCE doesn't have HWND_MESSAGE */
   700     hWndParent = HWND_MESSAGE;
   701 #endif
   702 
   703     /* Create the window. */
   704     SDL_HelperWindow = CreateWindowEx(0, SDL_HelperWindowClassName,
   705                                       SDL_HelperWindowName,
   706                                       WS_OVERLAPPED, CW_USEDEFAULT,
   707                                       CW_USEDEFAULT, CW_USEDEFAULT,
   708                                       CW_USEDEFAULT, hWndParent, NULL,
   709                                       hInstance, NULL);
   710     if (SDL_HelperWindow == NULL) {
   711         UnregisterClass(SDL_HelperWindowClassName, hInstance);
   712         WIN_SetError("Unable to create Helper Window");
   713         return -1;
   714     }
   715 
   716     return 0;
   717 }
   718 
   719 
   720 /*
   721  * Destroys the HelperWindow previously created with SDL_HelperWindowCreate.
   722  */
   723 void
   724 SDL_HelperWindowDestroy(void)
   725 {
   726     HINSTANCE hInstance = GetModuleHandle(NULL);
   727 
   728     /* Destroy the window. */
   729     if (SDL_HelperWindow != NULL) {
   730         if (DestroyWindow(SDL_HelperWindow) == 0) {
   731             WIN_SetError("Unable to destroy Helper Window");
   732             return;
   733         }
   734         SDL_HelperWindow = NULL;
   735     }
   736 
   737     /* Unregister the class. */
   738     if (SDL_HelperWindowClass != 0) {
   739         if ((UnregisterClass(SDL_HelperWindowClassName, hInstance)) == 0) {
   740             WIN_SetError("Unable to destroy Helper Window Class");
   741             return;
   742         }
   743         SDL_HelperWindowClass = 0;
   744     }
   745 }
   746 
   747 #endif /* SDL_VIDEO_DRIVER_WINDOWS */
   748 
   749 /* vi: set ts=4 sw=4 expandtab: */