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