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