src/video/win32/SDL_win32window.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 04 Jan 2009 17:14:27 +0000
changeset 2990 502adab079a4
parent 2971 a3012c6652ff
child 3045 9acb9f0f7f0d
permissions -rw-r--r--
indent
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2009 Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Lesser General Public
     7     License as published by the Free Software Foundation; either
     8     version 2.1 of the License, or (at your option) any later version.
     9 
    10     This library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Lesser General Public License for more details.
    14 
    15     You should have received a copy of the GNU Lesser General Public
    16     License along with this library; if not, write to the Free Software
    17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 */
    22 
    23 /* we need to define it, so that raw input is included */
    24 
    25 #if (_WIN32_WINNT < 0x0501)
    26 #undef _WIN32_WINNT
    27 #define _WIN32_WINNT 0x0501
    28 #endif
    29 
    30 #include "SDL_config.h"
    31 
    32 #include "../SDL_sysvideo.h"
    33 #include "../SDL_pixels_c.h"
    34 #include "../../events/SDL_keyboard_c.h"
    35 
    36 #include "SDL_win32video.h"
    37 
    38 /* This is included after SDL_win32video.h, which includes windows.h */
    39 #include "SDL_syswm.h"
    40 
    41 extern HCTX *g_hCtx;            /* the table of tablet event contexts, each windows has to have it's own tablet context */
    42 static Uint32 highestId = 0;    /* the highest id of the tablet context */
    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 static int
    51 SetupWindowData(_THIS, SDL_Window * window, HWND hwnd, SDL_bool created)
    52 {
    53     SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
    54     SDL_WindowData *data;
    55 
    56     /* Allocate the window data */
    57     data = (SDL_WindowData *) SDL_malloc(sizeof(*data));
    58     if (!data) {
    59         SDL_OutOfMemory();
    60         return -1;
    61     }
    62     data->windowID = window->id;
    63     data->hwnd = hwnd;
    64     data->hdc = GetDC(hwnd);
    65     data->created = created;
    66     data->mouse_pressed = SDL_FALSE;
    67     data->videodata = videodata;
    68 
    69     /* Associate the data with the window */
    70     if (!SetProp(hwnd, TEXT("SDL_WindowData"), data)) {
    71         ReleaseDC(hwnd, data->hdc);
    72         SDL_free(data);
    73         WIN_SetError("SetProp() failed");
    74         return -1;
    75     }
    76 
    77     /* Set up the window proc function */
    78     data->wndproc = (WNDPROC) GetWindowLongPtr(hwnd, GWLP_WNDPROC);
    79     if (data->wndproc == NULL) {
    80         data->wndproc = DefWindowProc;
    81     } else {
    82         SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR) WIN_WindowProc);
    83     }
    84 
    85     /* Fill in the SDL window with the window data */
    86     {
    87         POINT point;
    88         point.x = 0;
    89         point.y = 0;
    90         if (ClientToScreen(hwnd, &point)) {
    91             window->x = point.x;
    92             window->y = point.y;
    93         }
    94     }
    95     {
    96         RECT rect;
    97         if (GetClientRect(hwnd, &rect)) {
    98             window->w = rect.right;
    99             window->h = rect.bottom;
   100         }
   101     }
   102     {
   103         DWORD style = GetWindowLong(hwnd, GWL_STYLE);
   104         if (style & WS_VISIBLE) {
   105             window->flags |= SDL_WINDOW_SHOWN;
   106         } else {
   107             window->flags &= ~SDL_WINDOW_SHOWN;
   108         }
   109         if (style & (WS_BORDER | WS_THICKFRAME)) {
   110             window->flags &= ~SDL_WINDOW_BORDERLESS;
   111         } else {
   112             window->flags |= SDL_WINDOW_BORDERLESS;
   113         }
   114         if (style & WS_THICKFRAME) {
   115             window->flags |= SDL_WINDOW_RESIZABLE;
   116         } else {
   117             window->flags &= ~SDL_WINDOW_RESIZABLE;
   118         }
   119         if (style & WS_MAXIMIZE) {
   120             window->flags |= SDL_WINDOW_MAXIMIZED;
   121         } else {
   122             window->flags &= ~SDL_WINDOW_MAXIMIZED;
   123         }
   124         if (style & WS_MINIMIZE) {
   125             window->flags |= SDL_WINDOW_MINIMIZED;
   126         } else {
   127             window->flags &= ~SDL_WINDOW_MINIMIZED;
   128         }
   129     }
   130     if (GetFocus() == hwnd) {
   131         int index = data->videodata->keyboard;
   132         window->flags |= SDL_WINDOW_INPUT_FOCUS;
   133         SDL_SetKeyboardFocus(index, data->windowID);
   134 
   135         if (window->flags & SDL_WINDOW_INPUT_GRABBED) {
   136             RECT rect;
   137             GetClientRect(hwnd, &rect);
   138             ClientToScreen(hwnd, (LPPOINT) & rect);
   139             ClientToScreen(hwnd, (LPPOINT) & rect + 1);
   140             ClipCursor(&rect);
   141         }
   142     }
   143 
   144     /* All done! */
   145     window->driverdata = data;
   146     return 0;
   147 }
   148 
   149 int
   150 WIN_CreateWindow(_THIS, SDL_Window * window)
   151 {
   152     SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
   153     RAWINPUTDEVICE Rid;
   154     AXIS TabX, TabY;
   155     LOGCONTEXTA lc;
   156     HWND hwnd;
   157     HWND top;
   158     RECT rect;
   159     DWORD style = (WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
   160     int x, y;
   161     int w, h;
   162 
   163     if (window->flags & (SDL_WINDOW_BORDERLESS | SDL_WINDOW_FULLSCREEN)) {
   164         style |= WS_POPUP;
   165     } else {
   166         style |= (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX);
   167     }
   168     if ((window->flags & SDL_WINDOW_RESIZABLE)
   169         && !(window->flags & SDL_WINDOW_FULLSCREEN)) {
   170         style |= (WS_THICKFRAME | WS_MAXIMIZEBOX);
   171     }
   172 
   173     /* Figure out what the window area will be */
   174     if (window->flags & SDL_WINDOW_FULLSCREEN) {
   175         top = HWND_TOPMOST;
   176     } else {
   177         top = HWND_NOTOPMOST;
   178     }
   179     rect.left = 0;
   180     rect.top = 0;
   181     rect.right = window->w;
   182     rect.bottom = window->h;
   183     AdjustWindowRectEx(&rect, style, FALSE, 0);
   184     w = (rect.right - rect.left);
   185     h = (rect.bottom - rect.top);
   186 
   187     if ((window->flags & SDL_WINDOW_FULLSCREEN)
   188         || window->x == SDL_WINDOWPOS_CENTERED) {
   189         x = (GetSystemMetrics(SM_CXSCREEN) - w) / 2;
   190     } else if (window->x == SDL_WINDOWPOS_UNDEFINED) {
   191         x = CW_USEDEFAULT;
   192     } else {
   193         x = window->x + rect.left;
   194     }
   195     if ((window->flags & SDL_WINDOW_FULLSCREEN)
   196         || window->y == SDL_WINDOWPOS_CENTERED) {
   197         y = (GetSystemMetrics(SM_CYSCREEN) - h) / 2;
   198     } else if (window->y == SDL_WINDOWPOS_UNDEFINED) {
   199         y = CW_USEDEFAULT;
   200     } else {
   201         y = window->y + rect.top;
   202     }
   203 
   204     hwnd =
   205         CreateWindow(SDL_Appname, TEXT(""), style, x, y, w, h, NULL, NULL,
   206                      SDL_Instance, NULL);
   207     if (!hwnd) {
   208         WIN_SetError("Couldn't create window");
   209         return -1;
   210     }
   211 
   212     /* we're configuring the tablet data. See Wintab reference for more info */
   213     if (videodata->wintabDLL
   214         && videodata->WTInfoA(WTI_DEFSYSCTX, 0, &lc) != 0) {
   215         lc.lcPktData = PACKETDATA;
   216         lc.lcPktMode = PACKETMODE;
   217         lc.lcOptions |= CXO_MESSAGES;
   218         lc.lcOptions |= CXO_SYSTEM;
   219         lc.lcMoveMask = PACKETDATA;
   220         lc.lcBtnDnMask = lc.lcBtnUpMask = PACKETDATA;
   221         videodata->WTInfoA(WTI_DEVICES, DVC_X, &TabX);
   222         videodata->WTInfoA(WTI_DEVICES, DVC_Y, &TabY);
   223         lc.lcInOrgX = 0;
   224         lc.lcInOrgY = 0;
   225         lc.lcInExtX = TabX.axMax;
   226         lc.lcInExtY = TabY.axMax;
   227         lc.lcOutOrgX = 0;
   228         lc.lcOutOrgY = 0;
   229         lc.lcOutExtX = GetSystemMetrics(SM_CXSCREEN);
   230         lc.lcOutExtY = -GetSystemMetrics(SM_CYSCREEN);
   231         if (window->id > highestId) {
   232             HCTX *tmp_hctx;
   233             highestId = window->id;
   234             tmp_hctx =
   235                 (HCTX *) SDL_realloc(g_hCtx, (highestId + 1) * sizeof(HCTX));
   236             if (!tmp_hctx) {
   237                 SDL_OutOfMemory();
   238                 DestroyWindow(hwnd);
   239                 return -1;
   240             }
   241             g_hCtx = tmp_hctx;
   242         }
   243         g_hCtx[window->id] = videodata->WTOpenA(hwnd, &lc, TRUE);
   244     }
   245 
   246     /* we're telling the window, we want it to report raw input events from mice */
   247     Rid.usUsagePage = 0x01;
   248     Rid.usUsage = 0x02;
   249     Rid.dwFlags = RIDEV_INPUTSINK;
   250     Rid.hwndTarget = hwnd;
   251     RegisterRawInputDevices(&Rid, 1, sizeof(Rid));
   252 
   253     WIN_PumpEvents(_this);
   254 
   255     if (SetupWindowData(_this, window, hwnd, SDL_TRUE) < 0) {
   256         DestroyWindow(hwnd);
   257         return -1;
   258     }
   259 #ifdef SDL_VIDEO_OPENGL_WGL
   260     if (window->flags & SDL_WINDOW_OPENGL) {
   261         if (WIN_GL_SetupWindow(_this, window) < 0) {
   262             WIN_DestroyWindow(_this, window);
   263             return -1;
   264         }
   265     }
   266 #endif
   267     return 0;
   268 }
   269 
   270 int
   271 WIN_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
   272 {
   273     HWND hwnd = (HWND) data;
   274     LPTSTR title;
   275     int titleLen;
   276 
   277     /* Query the title from the existing window */
   278     titleLen = GetWindowTextLength(hwnd);
   279     title = SDL_stack_alloc(TCHAR, titleLen + 1);
   280     if (title) {
   281         titleLen = GetWindowText(hwnd, title, titleLen);
   282     } else {
   283         titleLen = 0;
   284     }
   285     if (titleLen > 0) {
   286         window->title = WIN_StringToUTF8(title);
   287     }
   288     if (title) {
   289         SDL_stack_free(title);
   290     }
   291 
   292     if (SetupWindowData(_this, window, hwnd, SDL_FALSE) < 0) {
   293         return -1;
   294     }
   295     return 0;
   296 }
   297 
   298 void
   299 WIN_SetWindowTitle(_THIS, SDL_Window * window)
   300 {
   301     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   302     LPTSTR title;
   303 
   304     if (window->title) {
   305         title = WIN_UTF8ToString(window->title);
   306     } else {
   307         title = NULL;
   308     }
   309     SetWindowText(hwnd, title ? title : TEXT(""));
   310     if (title) {
   311         SDL_free(title);
   312     }
   313 }
   314 
   315 void
   316 WIN_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon)
   317 {
   318     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   319     HICON hicon = NULL;
   320 
   321     if (icon) {
   322         BYTE *icon_bmp;
   323         int icon_len;
   324         SDL_RWops *dst;
   325         SDL_PixelFormat format;
   326         SDL_Surface *surface;
   327 
   328         /* Create temporary bitmap buffer */
   329         icon_len = 40 + icon->h * icon->w * 4;
   330         icon_bmp = SDL_stack_alloc(BYTE, icon_len);
   331         dst = SDL_RWFromMem(icon_bmp, icon_len);
   332         if (!dst) {
   333             SDL_stack_free(icon_bmp);
   334             return;
   335         }
   336 
   337         /* Write the BITMAPINFO header */
   338         SDL_WriteLE32(dst, 40);
   339         SDL_WriteLE32(dst, icon->w);
   340         SDL_WriteLE32(dst, icon->h * 2);
   341         SDL_WriteLE16(dst, 1);
   342         SDL_WriteLE16(dst, 32);
   343         SDL_WriteLE32(dst, BI_RGB);
   344         SDL_WriteLE32(dst, icon->h * icon->w * 4);
   345         SDL_WriteLE32(dst, 0);
   346         SDL_WriteLE32(dst, 0);
   347         SDL_WriteLE32(dst, 0);
   348         SDL_WriteLE32(dst, 0);
   349 
   350         /* Convert the icon to a 32-bit surface with alpha channel */
   351         SDL_InitFormat(&format, 32,
   352                        0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000);
   353         surface = SDL_ConvertSurface(icon, &format, 0);
   354         if (surface) {
   355             /* Write the pixels upside down into the bitmap buffer */
   356             int y = surface->h;
   357             while (y--) {
   358                 Uint8 *src = (Uint8 *) surface->pixels + y * surface->pitch;
   359                 SDL_RWwrite(dst, src, surface->pitch, 1);
   360             }
   361             SDL_FreeSurface(surface);
   362 
   363             hicon =
   364                 CreateIconFromResource(icon_bmp, icon_len, TRUE, 0x00030000);
   365         }
   366         SDL_RWclose(dst);
   367         SDL_stack_free(icon_bmp);
   368     }
   369 
   370     /* Set the icon for the window */
   371     SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM) hicon);
   372 
   373     /* Set the icon in the task manager (should we do this?) */
   374     SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM) hicon);
   375 }
   376 
   377 void
   378 WIN_SetWindowPosition(_THIS, SDL_Window * window)
   379 {
   380     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   381     RECT rect;
   382     DWORD style;
   383     HWND top;
   384     int x, y;
   385 
   386     /* Figure out what the window area will be */
   387     if (window->flags & SDL_WINDOW_FULLSCREEN) {
   388         top = HWND_TOPMOST;
   389     } else {
   390         top = HWND_NOTOPMOST;
   391     }
   392     style = GetWindowLong(hwnd, GWL_STYLE);
   393     rect.left = 0;
   394     rect.top = 0;
   395     rect.right = window->w;
   396     rect.bottom = window->h;
   397     AdjustWindowRectEx(&rect, style,
   398                        (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) !=
   399                                                            NULL), 0);
   400 
   401     if ((window->flags & SDL_WINDOW_FULLSCREEN)
   402         || window->x == SDL_WINDOWPOS_CENTERED) {
   403         x = (GetSystemMetrics(SM_CXSCREEN) - window->w) / 2;
   404     } else {
   405         x = window->x + rect.left;
   406     }
   407     if ((window->flags & SDL_WINDOW_FULLSCREEN)
   408         || window->y == SDL_WINDOWPOS_CENTERED) {
   409         y = (GetSystemMetrics(SM_CYSCREEN) - window->h) / 2;
   410     } else {
   411         y = window->y + rect.top;
   412     }
   413 
   414     SetWindowPos(hwnd, top, x, y, 0, 0, (SWP_NOCOPYBITS | SWP_NOSIZE));
   415 }
   416 
   417 void
   418 WIN_SetWindowSize(_THIS, SDL_Window * window)
   419 {
   420     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   421     RECT rect;
   422     DWORD style;
   423     HWND top;
   424     int w, h;
   425 
   426     /* Figure out what the window area will be */
   427     if (window->flags & SDL_WINDOW_FULLSCREEN) {
   428         top = HWND_TOPMOST;
   429     } else {
   430         top = HWND_NOTOPMOST;
   431     }
   432     style = GetWindowLong(hwnd, GWL_STYLE);
   433     rect.left = 0;
   434     rect.top = 0;
   435     rect.right = window->w;
   436     rect.bottom = window->h;
   437     AdjustWindowRectEx(&rect, style,
   438                        (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) !=
   439                                                            NULL), 0);
   440     w = (rect.right - rect.left);
   441     h = (rect.bottom - rect.top);
   442 
   443     SetWindowPos(hwnd, top, 0, 0, w, h, (SWP_NOCOPYBITS | SWP_NOMOVE));
   444 }
   445 
   446 void
   447 WIN_ShowWindow(_THIS, SDL_Window * window)
   448 {
   449     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   450 
   451     ShowWindow(hwnd, SW_SHOW);
   452 }
   453 
   454 void
   455 WIN_HideWindow(_THIS, SDL_Window * window)
   456 {
   457     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   458 
   459     ShowWindow(hwnd, SW_HIDE);
   460 }
   461 
   462 void
   463 WIN_RaiseWindow(_THIS, SDL_Window * window)
   464 {
   465     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   466     HWND top;
   467 
   468     if (window->flags & SDL_WINDOW_FULLSCREEN) {
   469         top = HWND_TOPMOST;
   470     } else {
   471         top = HWND_NOTOPMOST;
   472     }
   473     SetWindowPos(hwnd, top, 0, 0, 0, 0, (SWP_NOMOVE | SWP_NOSIZE));
   474 }
   475 
   476 void
   477 WIN_MaximizeWindow(_THIS, SDL_Window * window)
   478 {
   479     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   480 
   481     ShowWindow(hwnd, SW_MAXIMIZE);
   482 }
   483 
   484 void
   485 WIN_MinimizeWindow(_THIS, SDL_Window * window)
   486 {
   487     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   488 
   489     ShowWindow(hwnd, SW_MINIMIZE);
   490 }
   491 
   492 void
   493 WIN_RestoreWindow(_THIS, SDL_Window * window)
   494 {
   495     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   496 
   497     ShowWindow(hwnd, SW_RESTORE);
   498 }
   499 
   500 void
   501 WIN_SetWindowGrab(_THIS, SDL_Window * window)
   502 {
   503     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   504 
   505     if ((window->flags & (SDL_WINDOW_INPUT_GRABBED | SDL_WINDOW_FULLSCREEN))
   506         && (window->flags & SDL_WINDOW_INPUT_FOCUS)) {
   507         RECT rect;
   508         GetClientRect(hwnd, &rect);
   509         ClientToScreen(hwnd, (LPPOINT) & rect);
   510         ClientToScreen(hwnd, (LPPOINT) & rect + 1);
   511         ClipCursor(&rect);
   512     } else {
   513         ClipCursor(NULL);
   514     }
   515 }
   516 
   517 void
   518 WIN_DestroyWindow(_THIS, SDL_Window * window)
   519 {
   520     SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
   521     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
   522 
   523     if (data) {
   524 #ifdef SDL_VIDEO_OPENGL_WGL
   525         if (window->flags & SDL_WINDOW_OPENGL) {
   526             WIN_GL_CleanupWindow(_this, window);
   527         }
   528 #endif
   529         ReleaseDC(data->hwnd, data->hdc);
   530         if (data->created) {
   531             if (videodata->wintabDLL) {
   532                 videodata->WTClose(g_hCtx[window->id]);
   533             }
   534             DestroyWindow(data->hwnd);
   535         }
   536         SDL_free(data);
   537     }
   538 }
   539 
   540 SDL_bool
   541 WIN_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
   542 {
   543     HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   544     if (info->version.major <= SDL_MAJOR_VERSION) {
   545         info->window = hwnd;
   546         return SDL_TRUE;
   547     } else {
   548         SDL_SetError("Application not compiled with SDL %d.%d\n",
   549                      SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
   550         return SDL_FALSE;
   551     }
   552 }
   553 
   554 
   555 /*
   556  * Creates a HelperWindow used for DirectInput events.
   557  */
   558 int
   559 SDL_HelperWindowCreate(void)
   560 {
   561     HINSTANCE hInstance = GetModuleHandleA(NULL);
   562     WNDCLASSEX wce;
   563 
   564     /* Create the class. */
   565     SDL_zero(wce);
   566     wce.cbSize = sizeof(WNDCLASSEX);
   567     wce.lpfnWndProc = DefWindowProcA;
   568     wce.lpszClassName = (LPCWSTR) SDL_HelperWindowClassName;
   569     wce.hInstance = hInstance;
   570 
   571     /* Register the class. */
   572     SDL_HelperWindowClass = RegisterClassEx(&wce);
   573     if (SDL_HelperWindowClass == 0) {
   574         SDL_SetError("Unable to create Helper Window Class: error %d.",
   575                      GetLastError());
   576         return -1;
   577     }
   578 
   579     /* Create the window. */
   580     SDL_HelperWindow = CreateWindowEx(0, SDL_HelperWindowClassName,
   581                                       SDL_HelperWindowName,
   582                                       WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,
   583                                       CW_USEDEFAULT, CW_USEDEFAULT,
   584                                       CW_USEDEFAULT, HWND_MESSAGE, NULL,
   585                                       hInstance, NULL);
   586     if (SDL_HelperWindow == NULL) {
   587         SDL_SetError("Unable to create Helper Window: error %d.",
   588                      GetLastError());
   589         return -1;
   590     }
   591 
   592     return 0;
   593 }
   594 
   595 
   596 /*
   597  * Destroys the HelperWindow previously created with SDL_HelperWindowCreate.
   598  */
   599 void
   600 SDL_HelperWindowDestroy(void)
   601 {
   602     HINSTANCE hInstance = GetModuleHandleA(NULL);
   603 
   604     /* Destroy the window. */
   605     if (SDL_HelperWindow != NULL) {
   606         if (DestroyWindow(SDL_HelperWindow) == 0) {
   607             SDL_SetError("Unable to destroy Helper Window: error %d.",
   608                          GetLastError());
   609             return;
   610         }
   611         SDL_HelperWindow = NULL;
   612     }
   613 
   614     /* Unregister the class. */
   615     if (SDL_HelperWindowClass != 0) {
   616         if ((UnregisterClass(SDL_HelperWindowClassName, hInstance)) == 0) {
   617             SDL_SetError("Unable to destroy Helper Window Class: error %d.",
   618                          GetLastError());
   619             return;
   620         }
   621         SDL_HelperWindowClass = 0;
   622     }
   623 }
   624 
   625 
   626 /* vi: set ts=4 sw=4 expandtab: */