src/video/windows/SDL_windowsevents.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 31 Dec 2011 09:28:07 -0500
changeset 6138 4c64952a58fb
parent 6044 35448a5ea044
child 6350 19545983ac76
permissions -rwxr-xr-x
Happy New Year!
     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_windowsvideo.h"
    26 #include "SDL_windowsshape.h"
    27 #include "SDL_syswm.h"
    28 #include "SDL_vkeys.h"
    29 #include "../../events/SDL_events_c.h"
    30 #include "../../events/SDL_touch_c.h"
    31 
    32 
    33 
    34 /*#define WMMSG_DEBUG*/
    35 #ifdef WMMSG_DEBUG
    36 #include <stdio.h>	
    37 #include "wmmsg.h"
    38 #endif
    39 
    40 /* Masks for processing the windows KEYDOWN and KEYUP messages */
    41 #define REPEATED_KEYMASK    (1<<30)
    42 #define EXTENDED_KEYMASK    (1<<24)
    43 
    44 #define VK_ENTER    10          /* Keypad Enter ... no VKEY defined? */
    45 
    46 /* Make sure XBUTTON stuff is defined that isn't in older Platform SDKs... */
    47 #ifndef WM_XBUTTONDOWN
    48 #define WM_XBUTTONDOWN 0x020B
    49 #endif
    50 #ifndef WM_XBUTTONUP
    51 #define WM_XBUTTONUP 0x020C
    52 #endif
    53 #ifndef GET_XBUTTON_WPARAM
    54 #define GET_XBUTTON_WPARAM(w) (HIWORD(w))
    55 #endif
    56 #ifndef WM_INPUT
    57 #define WM_INPUT 0x00ff
    58 #endif
    59 #ifndef WM_TOUCH
    60 #define WM_TOUCH 0x0240
    61 #endif
    62 
    63 
    64 static WPARAM
    65 RemapVKEY(WPARAM wParam, LPARAM lParam)
    66 {
    67     int i;
    68     BYTE scancode = (BYTE) ((lParam >> 16) & 0xFF);
    69 
    70     /* Windows remaps alphabetic keys based on current layout.
    71        We try to provide USB scancodes, so undo this mapping.
    72      */
    73     if (wParam >= 'A' && wParam <= 'Z') {
    74         if (scancode != alpha_scancodes[wParam - 'A']) {
    75             for (i = 0; i < SDL_arraysize(alpha_scancodes); ++i) {
    76                 if (scancode == alpha_scancodes[i]) {
    77                     wParam = 'A' + i;
    78                     break;
    79                 }
    80             }
    81         }
    82     }
    83 
    84     /* Keypad keys are a little trickier, we always scan for them.
    85        Keypad arrow keys have the same scancode as normal arrow keys,
    86        except they don't have the extended bit (0x1000000) set.
    87      */
    88     if (!(lParam & 0x1000000)) {
    89         if (wParam == VK_DELETE) {
    90             wParam = VK_DECIMAL;
    91         } else {
    92             for (i = 0; i < SDL_arraysize(keypad_scancodes); ++i) {
    93                 if (scancode == keypad_scancodes[i]) {
    94                     wParam = VK_NUMPAD0 + i;
    95                     break;
    96                 }
    97             }
    98         }
    99     }
   100 
   101     return wParam;
   102 }
   103 
   104 LRESULT CALLBACK
   105 WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
   106 {
   107     SDL_WindowData *data;
   108     LRESULT returnCode = -1;
   109 
   110     /* Send a SDL_SYSWMEVENT if the application wants them */
   111     if (SDL_GetEventState(SDL_SYSWMEVENT) == SDL_ENABLE) {
   112         SDL_SysWMmsg wmmsg;
   113 
   114         SDL_VERSION(&wmmsg.version);
   115         wmmsg.subsystem = SDL_SYSWM_WINDOWS;
   116         wmmsg.msg.win.hwnd = hwnd;
   117         wmmsg.msg.win.msg = msg;
   118         wmmsg.msg.win.wParam = wParam;
   119         wmmsg.msg.win.lParam = lParam;
   120         SDL_SendSysWMEvent(&wmmsg);
   121     }
   122 
   123     /* Get the window data for the window */
   124     data = (SDL_WindowData *) GetProp(hwnd, TEXT("SDL_WindowData"));
   125     if (!data) {
   126         return CallWindowProc(DefWindowProc, hwnd, msg, wParam, lParam);
   127     }
   128 
   129 #ifdef WMMSG_DEBUG
   130     {		
   131         FILE *log = fopen("wmmsg.txt", "a");		
   132         fprintf(log, "Received windows message: %p ", hwnd);
   133         if (msg > MAX_WMMSG) {
   134             fprintf(log, "%d", msg);
   135         } else {
   136             fprintf(log, "%s", wmtab[msg]);
   137         }
   138         fprintf(log, " -- 0x%X, 0x%X\n", wParam, lParam);
   139         fclose(log);
   140     }
   141 #endif
   142 
   143     if (IME_HandleMessage(hwnd, msg, wParam, &lParam, data->videodata))
   144         return 0;
   145 
   146     switch (msg) {
   147 
   148     case WM_SHOWWINDOW:
   149         {
   150             if (wParam) {
   151                 SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_SHOWN, 0, 0);
   152             } else {
   153                 SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_HIDDEN, 0, 0);
   154             }
   155         }
   156         break;
   157 
   158     case WM_ACTIVATE:
   159         {
   160             BOOL minimized;
   161 
   162             minimized = HIWORD(wParam);
   163             if (!minimized && (LOWORD(wParam) != WA_INACTIVE)) {
   164                 SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_SHOWN, 0, 0);
   165                 SDL_SendWindowEvent(data->window,
   166                                     SDL_WINDOWEVENT_RESTORED, 0, 0);
   167 #ifndef _WIN32_WCE              /* WinCE misses IsZoomed() */
   168                 if (IsZoomed(hwnd)) {
   169                     SDL_SendWindowEvent(data->window,
   170                                         SDL_WINDOWEVENT_MAXIMIZED, 0, 0);
   171                 }
   172 #endif
   173                 if (SDL_GetKeyboardFocus() != data->window) {
   174                     SDL_SetKeyboardFocus(data->window);
   175                 }
   176                 /*
   177                  * FIXME: Update keyboard state
   178                  */
   179                 WIN_CheckClipboardUpdate(data->videodata);
   180             } else {
   181                 if (SDL_GetKeyboardFocus() == data->window) {
   182                     SDL_SetKeyboardFocus(NULL);
   183                 }
   184                 if (minimized) {
   185                     SDL_SendWindowEvent(data->window,
   186                                         SDL_WINDOWEVENT_MINIMIZED, 0, 0);
   187                 }
   188             }
   189         }
   190         returnCode = 0;
   191         break;
   192 
   193 	case WM_MOUSEMOVE:
   194 #ifdef _WIN32_WCE
   195         /* transform coords for VGA, WVGA... */
   196         {
   197             SDL_VideoData *videodata = data->videodata;
   198             if(videodata->CoordTransform) {
   199                 POINT pt;
   200                 pt.x = LOWORD(lParam);
   201                 pt.y = HIWORD(lParam);
   202                 videodata->CoordTransform(data->window, &pt);
   203                 SDL_SendMouseMotion(data->window, 0, pt.x, pt.y);
   204                 break;
   205             }
   206         }
   207 #endif
   208         SDL_SendMouseMotion(data->window, 0, LOWORD(lParam), HIWORD(lParam));
   209         break;
   210 
   211     case WM_LBUTTONDOWN:
   212         SDL_SendMouseButton(data->window, SDL_PRESSED, SDL_BUTTON_LEFT);
   213         break;
   214 
   215     case WM_LBUTTONUP:
   216         SDL_SendMouseButton(data->window, SDL_RELEASED, SDL_BUTTON_LEFT);
   217         break;
   218 
   219     case WM_RBUTTONDOWN:
   220         SDL_SendMouseButton(data->window, SDL_PRESSED, SDL_BUTTON_RIGHT);
   221         break;
   222 
   223     case WM_RBUTTONUP:
   224         SDL_SendMouseButton(data->window, SDL_RELEASED, SDL_BUTTON_RIGHT);
   225         break;
   226 
   227     case WM_MBUTTONDOWN:
   228         SDL_SendMouseButton(data->window, SDL_PRESSED, SDL_BUTTON_MIDDLE);
   229         break;
   230 
   231     case WM_MBUTTONUP:
   232         SDL_SendMouseButton(data->window, SDL_RELEASED, SDL_BUTTON_MIDDLE);
   233         break;
   234 
   235     case WM_XBUTTONDOWN:
   236         SDL_SendMouseButton(data->window, SDL_PRESSED, SDL_BUTTON_X1 + GET_XBUTTON_WPARAM(wParam) - 1);
   237         returnCode = TRUE;
   238         break;
   239 
   240     case WM_XBUTTONUP:
   241         SDL_SendMouseButton(data->window, SDL_RELEASED, SDL_BUTTON_X1 + GET_XBUTTON_WPARAM(wParam) - 1);
   242         returnCode = TRUE;
   243         break;
   244 
   245     case WM_MOUSEWHEEL:
   246         {
   247             int motion = (short) HIWORD(wParam);
   248 
   249             SDL_SendMouseWheel(data->window, 0, motion);
   250             break;
   251         }
   252 
   253 #ifdef WM_MOUSELEAVE
   254     /* FIXME: Do we need the SDL 1.2 hack to generate WM_MOUSELEAVE now? */
   255     case WM_MOUSELEAVE:
   256         if (SDL_GetMouseFocus() == data->window) {
   257             SDL_SetMouseFocus(NULL);
   258         }
   259         returnCode = 0;
   260         break;
   261 #endif /* WM_MOUSELEAVE */
   262 
   263     case WM_SYSKEYDOWN:
   264     case WM_KEYDOWN:
   265         {
   266             wParam = RemapVKEY(wParam, lParam);
   267             switch (wParam) {
   268             case VK_CONTROL:
   269                 if (lParam & EXTENDED_KEYMASK)
   270                     wParam = VK_RCONTROL;
   271                 else
   272                     wParam = VK_LCONTROL;
   273                 break;
   274             case VK_SHIFT:
   275                 /* EXTENDED trick doesn't work here */
   276                 {
   277                     Uint8 *state = SDL_GetKeyboardState(NULL);
   278                     if (state[SDL_SCANCODE_LSHIFT] == SDL_RELEASED
   279                         && (GetKeyState(VK_LSHIFT) & 0x8000)) {
   280                         wParam = VK_LSHIFT;
   281                     } else if (state[SDL_SCANCODE_RSHIFT] == SDL_RELEASED
   282                                && (GetKeyState(VK_RSHIFT) & 0x8000)) {
   283                         wParam = VK_RSHIFT;
   284                     } else {
   285                         /* Probably a key repeat */
   286                         wParam = 256;
   287                     }
   288                 }
   289                 break;
   290             case VK_MENU:
   291                 if (lParam & EXTENDED_KEYMASK)
   292                     wParam = VK_RMENU;
   293                 else
   294                     wParam = VK_LMENU;
   295                 break;
   296             case VK_RETURN:
   297                 if (lParam & EXTENDED_KEYMASK)
   298                     wParam = VK_ENTER;
   299                 break;
   300             }
   301             if (wParam < 256) {
   302                 SDL_SendKeyboardKey(SDL_PRESSED,
   303                                     data->videodata->key_layout[wParam]);
   304             }
   305         }
   306         returnCode = 0;
   307         break;
   308 
   309     case WM_SYSKEYUP:
   310     case WM_KEYUP:
   311         {
   312             wParam = RemapVKEY(wParam, lParam);
   313             switch (wParam) {
   314             case VK_CONTROL:
   315                 if (lParam & EXTENDED_KEYMASK)
   316                     wParam = VK_RCONTROL;
   317                 else
   318                     wParam = VK_LCONTROL;
   319                 break;
   320             case VK_SHIFT:
   321                 /* EXTENDED trick doesn't work here */
   322                 {
   323                     Uint8 *state = SDL_GetKeyboardState(NULL);
   324                     if (state[SDL_SCANCODE_LSHIFT] == SDL_PRESSED
   325                         && !(GetKeyState(VK_LSHIFT) & 0x8000)) {
   326                         wParam = VK_LSHIFT;
   327                     } else if (state[SDL_SCANCODE_RSHIFT] == SDL_PRESSED
   328                                && !(GetKeyState(VK_RSHIFT) & 0x8000)) {
   329                         wParam = VK_RSHIFT;
   330                     } else {
   331                         /* Probably a key repeat */
   332                         wParam = 256;
   333                     }
   334                 }
   335                 break;
   336             case VK_MENU:
   337                 if (lParam & EXTENDED_KEYMASK)
   338                     wParam = VK_RMENU;
   339                 else
   340                     wParam = VK_LMENU;
   341                 break;
   342             case VK_RETURN:
   343                 if (lParam & EXTENDED_KEYMASK)
   344                     wParam = VK_ENTER;
   345                 break;
   346             }
   347 
   348             /* Windows only reports keyup for print screen */
   349             if (wParam == VK_SNAPSHOT
   350                 && SDL_GetKeyboardState(NULL)[SDL_SCANCODE_PRINTSCREEN] ==
   351                 SDL_RELEASED) {
   352                 SDL_SendKeyboardKey(SDL_PRESSED,
   353                                     data->videodata->key_layout[wParam]);
   354             }
   355             if (wParam < 256) {
   356                 SDL_SendKeyboardKey(SDL_RELEASED,
   357                                     data->videodata->key_layout[wParam]);
   358             }
   359         }
   360         returnCode = 0;
   361         break;
   362 
   363     case WM_CHAR:
   364         {
   365             char text[4];
   366 
   367             /* Convert to UTF-8 and send it on... */
   368             if (wParam <= 0x7F) {
   369                 text[0] = (char) wParam;
   370                 text[1] = '\0';
   371             } else if (wParam <= 0x7FF) {
   372                 text[0] = 0xC0 | (char) ((wParam >> 6) & 0x1F);
   373                 text[1] = 0x80 | (char) (wParam & 0x3F);
   374                 text[2] = '\0';
   375             } else {
   376                 text[0] = 0xE0 | (char) ((wParam >> 12) & 0x0F);
   377                 text[1] = 0x80 | (char) ((wParam >> 6) & 0x3F);
   378                 text[2] = 0x80 | (char) (wParam & 0x3F);
   379                 text[3] = '\0';
   380             }
   381             SDL_SendKeyboardText(text);
   382         }
   383         returnCode = 0;
   384         break;
   385 
   386 #ifdef WM_INPUTLANGCHANGE
   387     case WM_INPUTLANGCHANGE:
   388         {
   389             WIN_UpdateKeymap();
   390         }
   391         returnCode = 1;
   392         break;
   393 #endif /* WM_INPUTLANGCHANGE */
   394 
   395 #ifdef WM_GETMINMAXINFO
   396     case WM_GETMINMAXINFO:
   397         {
   398             MINMAXINFO *info;
   399             RECT size;
   400             int x, y;
   401             int w, h;
   402             int style;
   403             BOOL menu;
   404 
   405             /* If we allow resizing, let the resize happen naturally */
   406             if(SDL_IsShapedWindow(data->window))
   407                 Win32_ResizeWindowShape(data->window);
   408             if (SDL_GetWindowFlags(data->window) & SDL_WINDOW_RESIZABLE) {
   409                 returnCode = 0;
   410                 break;
   411             }
   412 
   413             /* Get the current position of our window */
   414             GetWindowRect(hwnd, &size);
   415             x = size.left;
   416             y = size.top;
   417 
   418             /* Calculate current size of our window */
   419             SDL_GetWindowSize(data->window, &w, &h);
   420             size.top = 0;
   421             size.left = 0;
   422             size.bottom = h;
   423             size.right = w;
   424 
   425 
   426             style = GetWindowLong(hwnd, GWL_STYLE);
   427 #ifdef _WIN32_WCE
   428             menu = FALSE;
   429 #else
   430             /* DJM - according to the docs for GetMenu(), the
   431                return value is undefined if hwnd is a child window.
   432                Aparently it's too difficult for MS to check
   433                inside their function, so I have to do it here.
   434              */
   435             menu = (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL);
   436 #endif
   437             AdjustWindowRectEx(&size, style, menu, 0);
   438             w = size.right - size.left;
   439             h = size.bottom - size.top;
   440 
   441             /* Fix our size to the current size */
   442             info = (MINMAXINFO *) lParam;
   443             info->ptMaxSize.x = w;
   444             info->ptMaxSize.y = h;
   445             info->ptMaxPosition.x = x;
   446             info->ptMaxPosition.y = y;
   447             info->ptMinTrackSize.x = w;
   448             info->ptMinTrackSize.y = h;
   449             info->ptMaxTrackSize.x = w;
   450             info->ptMaxTrackSize.y = h;
   451         }
   452         returnCode = 0;
   453         break;
   454 #endif /* WM_GETMINMAXINFO */
   455 
   456     case WM_WINDOWPOSCHANGED:
   457         {
   458             RECT rect;
   459             int x, y;
   460             int w, h;
   461             Uint32 window_flags;
   462 
   463             if (!GetClientRect(hwnd, &rect) ||
   464                 (rect.right == rect.left && rect.bottom == rect.top)) {
   465                 break;
   466             }
   467             ClientToScreen(hwnd, (LPPOINT) & rect);
   468             ClientToScreen(hwnd, (LPPOINT) & rect + 1);
   469 
   470             window_flags = SDL_GetWindowFlags(data->window);
   471             if ((window_flags & SDL_WINDOW_INPUT_GRABBED) &&
   472                 (window_flags & SDL_WINDOW_INPUT_FOCUS)) {
   473                 ClipCursor(&rect);
   474             }
   475 
   476             x = rect.left;
   477             y = rect.top;
   478             SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_MOVED, x, y);
   479 
   480             w = rect.right - rect.left;
   481             h = rect.bottom - rect.top;
   482             SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_RESIZED, w,
   483                                 h);
   484         }
   485         break;
   486 
   487     case WM_SETCURSOR:
   488         {
   489             Uint16 hittest;
   490 
   491             hittest = LOWORD(lParam);
   492             if (hittest == HTCLIENT) {
   493                 SetCursor(SDL_cursor);
   494                 returnCode = TRUE;
   495             }
   496         }
   497         break;
   498 
   499         /* We were occluded, refresh our display */
   500     case WM_PAINT:
   501         {
   502             RECT rect;
   503             if (GetUpdateRect(hwnd, &rect, FALSE)) {
   504                 ValidateRect(hwnd, &rect);
   505                 SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_EXPOSED,
   506                                     0, 0);
   507             }
   508         }
   509         returnCode = 0;
   510         break;
   511 
   512         /* We'll do our own drawing, prevent flicker */
   513     case WM_ERASEBKGND:
   514         {
   515         }
   516         return (1);
   517 
   518 #if defined(SC_SCREENSAVE) || defined(SC_MONITORPOWER)
   519     case WM_SYSCOMMAND:
   520         {
   521             /* Don't start the screensaver or blank the monitor in fullscreen apps */
   522             if ((wParam & 0xFFF0) == SC_SCREENSAVE ||
   523                 (wParam & 0xFFF0) == SC_MONITORPOWER) {
   524                 if (SDL_GetVideoDevice()->suspend_screensaver) {
   525                     return (0);
   526                 }
   527             }
   528         }
   529         break;
   530 #endif /* System has screensaver support */
   531 
   532     case WM_CLOSE:
   533         {
   534             SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_CLOSE, 0, 0);
   535         }
   536         returnCode = 0;
   537         break;
   538 
   539 	case WM_TOUCH:
   540 		{
   541 			UINT i, num_inputs = LOWORD(wParam);
   542 			PTOUCHINPUT inputs = SDL_stack_alloc(TOUCHINPUT, num_inputs);
   543 			if (data->videodata->GetTouchInputInfo((HTOUCHINPUT)lParam, num_inputs, inputs, sizeof(TOUCHINPUT))) {
   544 				RECT rect;
   545 				float x, y;
   546 
   547 				if (!GetClientRect(hwnd, &rect) ||
   548 				    (rect.right == rect.left && rect.bottom == rect.top)) {
   549 					break;
   550 				}
   551 				ClientToScreen(hwnd, (LPPOINT) & rect);
   552 				ClientToScreen(hwnd, (LPPOINT) & rect + 1);
   553 				rect.top *= 100;
   554 				rect.left *= 100;
   555 				rect.bottom *= 100;
   556 				rect.right *= 100;
   557 
   558 				for (i = 0; i < num_inputs; ++i) {
   559 					PTOUCHINPUT input = &inputs[i];
   560 
   561 					const SDL_TouchID touchId = (SDL_TouchID)
   562 												((size_t)input->hSource);
   563 					if (!SDL_GetTouch(touchId)) {
   564 						SDL_Touch touch;
   565 
   566 						touch.id = touchId;
   567 						touch.x_min = 0;
   568 						touch.x_max = 1;
   569 						touch.native_xres = touch.x_max - touch.x_min;
   570 						touch.y_min = 0;
   571 						touch.y_max = 1;
   572 						touch.native_yres = touch.y_max - touch.y_min;
   573 						touch.pressure_min = 0;
   574 						touch.pressure_max = 1;
   575 						touch.native_pressureres = touch.pressure_max - touch.pressure_min;
   576 
   577 						if (SDL_AddTouch(&touch, "") < 0) {
   578 							continue;
   579 						}
   580 					}
   581 
   582 					// Get the normalized coordinates for the window
   583 					x = (float)(input->x - rect.left)/(rect.right - rect.left);
   584 					y = (float)(input->y - rect.top)/(rect.bottom - rect.top);
   585 
   586 					if (input->dwFlags & TOUCHEVENTF_DOWN) {
   587 						SDL_SendFingerDown(touchId, input->dwID, SDL_TRUE, x, y, 1);
   588 					}
   589 					if (input->dwFlags & TOUCHEVENTF_MOVE) {
   590 						SDL_SendTouchMotion(touchId, input->dwID, SDL_FALSE, x, y, 1);
   591 					}
   592 					if (input->dwFlags & TOUCHEVENTF_UP) {
   593 						SDL_SendFingerDown(touchId, input->dwID, SDL_FALSE, x, y, 1);
   594 					}
   595 				}
   596 			}
   597 			SDL_stack_free(inputs);
   598 
   599 			data->videodata->CloseTouchInputHandle((HTOUCHINPUT)lParam);
   600 			return 0;
   601 		}
   602 		break;
   603 	}
   604 
   605     /* If there's a window proc, assume it's going to handle messages */
   606     if (data->wndproc) {
   607         return CallWindowProc(data->wndproc, hwnd, msg, wParam, lParam);
   608     } else if (returnCode >= 0) {
   609         return returnCode;
   610     } else {
   611         return CallWindowProc(DefWindowProc, hwnd, msg, wParam, lParam);
   612     }
   613 }
   614 
   615 void
   616 WIN_PumpEvents(_THIS)
   617 {
   618     MSG msg;
   619     while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
   620         TranslateMessage(&msg);
   621         DispatchMessage(&msg);
   622     }
   623 }
   624 
   625 static int app_registered = 0;
   626 LPTSTR SDL_Appname = NULL;
   627 Uint32 SDL_Appstyle = 0;
   628 HINSTANCE SDL_Instance = NULL;
   629 
   630 /* Register the class for this application */
   631 int
   632 SDL_RegisterApp(char *name, Uint32 style, void *hInst)
   633 {
   634     WNDCLASS class;
   635 
   636     /* Only do this once... */
   637     if (app_registered) {
   638         ++app_registered;
   639         return (0);
   640     }
   641     if (!name && !SDL_Appname) {
   642         name = "SDL_app";
   643 #if defined(CS_BYTEALIGNCLIENT) || defined(CS_OWNDC)
   644         SDL_Appstyle = (CS_BYTEALIGNCLIENT | CS_OWNDC);
   645 #endif
   646         SDL_Instance = hInst ? hInst : GetModuleHandle(NULL);
   647     }
   648 
   649     if (name) {
   650         SDL_Appname = WIN_UTF8ToString(name);
   651         SDL_Appstyle = style;
   652         SDL_Instance = hInst ? hInst : GetModuleHandle(NULL);
   653     }
   654 
   655     /* Register the application class */
   656     class.hCursor = NULL;
   657     class.hIcon =
   658         LoadImage(SDL_Instance, SDL_Appname, IMAGE_ICON, 0, 0,
   659                   LR_DEFAULTCOLOR);
   660     class.lpszMenuName = NULL;
   661     class.lpszClassName = SDL_Appname;
   662     class.hbrBackground = NULL;
   663     class.hInstance = SDL_Instance;
   664     class.style = SDL_Appstyle;
   665     class.lpfnWndProc = WIN_WindowProc;
   666     class.cbWndExtra = 0;
   667     class.cbClsExtra = 0;
   668     if (!RegisterClass(&class)) {
   669         SDL_SetError("Couldn't register application class");
   670         return (-1);
   671     }
   672 
   673     app_registered = 1;
   674     return (0);
   675 }
   676 
   677 /* Unregisters the windowclass registered in SDL_RegisterApp above. */
   678 void
   679 SDL_UnregisterApp()
   680 {
   681     WNDCLASS class;
   682 
   683     /* SDL_RegisterApp might not have been called before */
   684     if (!app_registered) {
   685         return;
   686     }
   687     --app_registered;
   688     if (app_registered == 0) {
   689         /* Check for any registered window classes. */
   690         if (GetClassInfo(SDL_Instance, SDL_Appname, &class)) {
   691             UnregisterClass(SDL_Appname, SDL_Instance);
   692         }
   693         SDL_free(SDL_Appname);
   694         SDL_Appname = NULL;
   695     }
   696 }
   697 
   698 #endif /* SDL_VIDEO_DRIVER_WINDOWS */
   699 
   700 /* vi: set ts=4 sw=4 expandtab: */