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