comparison src/video/windows/SDL_windowsevents.c @ 5062:e8916fe9cfc8

Fixed bug #925 Changed "win32" to "windows"
author Sam Lantinga <slouken@libsdl.org>
date Thu, 20 Jan 2011 18:04:05 -0800
parents src/video/win32/SDL_win32events.c@8b7988f42fcb
children c2539ff054c8
comparison
equal deleted inserted replaced
5061:9e9940eae455 5062:e8916fe9cfc8
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
23 #include "SDL_config.h"
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 (videodata->render == RENDER_GAPI || videodata->render == RENDER_RAW))
200 {
201 POINT pt;
202 pt.x = LOWORD(lParam);
203 pt.y = HIWORD(lParam);
204 videodata->CoordTransform(data->window, &pt);
205 SDL_SendMouseMotion(data->window, 0, pt.x, pt.y);
206 break;
207 }
208 }
209 #endif
210 SDL_SendMouseMotion(data->window, 0, LOWORD(lParam), HIWORD(lParam));
211 break;
212
213 case WM_LBUTTONDOWN:
214 SDL_SendMouseButton(data->window, SDL_PRESSED, SDL_BUTTON_LEFT);
215 break;
216
217 case WM_LBUTTONUP:
218 SDL_SendMouseButton(data->window, SDL_RELEASED, SDL_BUTTON_LEFT);
219 break;
220
221 case WM_RBUTTONDOWN:
222 SDL_SendMouseButton(data->window, SDL_PRESSED, SDL_BUTTON_RIGHT);
223 break;
224
225 case WM_RBUTTONUP:
226 SDL_SendMouseButton(data->window, SDL_RELEASED, SDL_BUTTON_RIGHT);
227 break;
228
229 case WM_MBUTTONDOWN:
230 SDL_SendMouseButton(data->window, SDL_PRESSED, SDL_BUTTON_MIDDLE);
231 break;
232
233 case WM_MBUTTONUP:
234 SDL_SendMouseButton(data->window, SDL_RELEASED, SDL_BUTTON_MIDDLE);
235 break;
236
237 case WM_XBUTTONDOWN:
238 SDL_SendMouseButton(data->window, SDL_PRESSED, SDL_BUTTON_X1 + GET_XBUTTON_WPARAM(wParam) - 1);
239 returnCode = TRUE;
240 break;
241
242 case WM_XBUTTONUP:
243 SDL_SendMouseButton(data->window, SDL_RELEASED, SDL_BUTTON_X1 + GET_XBUTTON_WPARAM(wParam) - 1);
244 returnCode = TRUE;
245 break;
246
247 case WM_MOUSEWHEEL:
248 {
249 int motion = (short) HIWORD(wParam);
250
251 SDL_SendMouseWheel(data->window, 0, motion);
252 break;
253 }
254
255 case WM_MOUSELEAVE:
256 if (SDL_GetMouseFocus() == data->window) {
257 SDL_SetMouseFocus(NULL);
258 }
259 returnCode = 0;
260 break;
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 case WM_INPUTLANGCHANGE:
386 {
387 WIN_UpdateKeymap();
388 }
389 returnCode = 1;
390 break;
391
392 case WM_GETMINMAXINFO:
393 {
394 MINMAXINFO *info;
395 RECT size;
396 int x, y;
397 int w, h;
398 int style;
399 BOOL menu;
400
401 /* If we allow resizing, let the resize happen naturally */
402 if(SDL_IsShapedWindow(data->window))
403 Win32_ResizeWindowShape(data->window);
404 if (SDL_GetWindowFlags(data->window) & SDL_WINDOW_RESIZABLE) {
405 returnCode = 0;
406 break;
407 }
408
409 /* Get the current position of our window */
410 GetWindowRect(hwnd, &size);
411 x = size.left;
412 y = size.top;
413
414 /* Calculate current size of our window */
415 SDL_GetWindowSize(data->window, &w, &h);
416 size.top = 0;
417 size.left = 0;
418 size.bottom = h;
419 size.right = w;
420
421
422 style = GetWindowLong(hwnd, GWL_STYLE);
423 #ifdef _WIN32_WCE
424 menu = FALSE;
425 #else
426 /* DJM - according to the docs for GetMenu(), the
427 return value is undefined if hwnd is a child window.
428 Aparently it's too difficult for MS to check
429 inside their function, so I have to do it here.
430 */
431 menu = (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL);
432 #endif
433 AdjustWindowRectEx(&size, style, menu, 0);
434 w = size.right - size.left;
435 h = size.bottom - size.top;
436
437 /* Fix our size to the current size */
438 info = (MINMAXINFO *) lParam;
439 info->ptMaxSize.x = w;
440 info->ptMaxSize.y = h;
441 info->ptMaxPosition.x = x;
442 info->ptMaxPosition.y = y;
443 info->ptMinTrackSize.x = w;
444 info->ptMinTrackSize.y = h;
445 info->ptMaxTrackSize.x = w;
446 info->ptMaxTrackSize.y = h;
447 }
448 returnCode = 0;
449 break;
450
451 case WM_WINDOWPOSCHANGED:
452 {
453 RECT rect;
454 int x, y;
455 int w, h;
456 Uint32 window_flags;
457
458 if (!GetClientRect(hwnd, &rect) ||
459 (rect.right == rect.left && rect.bottom == rect.top)) {
460 break;
461 }
462 ClientToScreen(hwnd, (LPPOINT) & rect);
463 ClientToScreen(hwnd, (LPPOINT) & rect + 1);
464
465 window_flags = SDL_GetWindowFlags(data->window);
466 if ((window_flags & SDL_WINDOW_INPUT_GRABBED) &&
467 (window_flags & SDL_WINDOW_INPUT_FOCUS)) {
468 ClipCursor(&rect);
469 }
470
471 x = rect.left;
472 y = rect.top;
473 SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_MOVED, x, y);
474
475 w = rect.right - rect.left;
476 h = rect.bottom - rect.top;
477 SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_RESIZED, w,
478 h);
479 }
480 break;
481
482 case WM_SETCURSOR:
483 {
484 Uint16 hittest;
485
486 hittest = LOWORD(lParam);
487 if (hittest == HTCLIENT) {
488 /* FIXME: Implement the cursor API */
489 static HCURSOR cursor;
490 if (!cursor) {
491 cursor = LoadCursor(NULL, IDC_ARROW);
492 }
493 SetCursor(cursor);
494 returnCode = TRUE;
495 }
496 }
497 break;
498
499 /* We are about to get palette focus! */
500 case WM_QUERYNEWPALETTE:
501 {
502 /*
503 WIN_RealizePalette(current_video);
504 returnCode = TRUE;
505 */
506 }
507 break;
508
509 /* Another application changed the palette */
510 case WM_PALETTECHANGED:
511 {
512 /*
513 WIN_PaletteChanged(current_video, (HWND) wParam);
514 */
515 }
516 break;
517
518 /* We were occluded, refresh our display */
519 case WM_PAINT:
520 {
521 RECT rect;
522 if (GetUpdateRect(hwnd, &rect, FALSE)) {
523 ValidateRect(hwnd, &rect);
524 SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_EXPOSED,
525 0, 0);
526 }
527 }
528 returnCode = 0;
529 break;
530
531 /* We'll do our own drawing, prevent flicker */
532 case WM_ERASEBKGND:
533 {
534 }
535 return (1);
536
537 case WM_SYSCOMMAND:
538 {
539 /* Don't start the screensaver or blank the monitor in fullscreen apps */
540 if ((wParam & 0xFFF0) == SC_SCREENSAVE ||
541 (wParam & 0xFFF0) == SC_MONITORPOWER) {
542 if (SDL_GetVideoDevice()->suspend_screensaver) {
543 return (0);
544 }
545 }
546 }
547 break;
548
549 case WM_CLOSE:
550 {
551 SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_CLOSE, 0, 0);
552 }
553 returnCode = 0;
554 break;
555
556 case WM_TOUCH:
557 {
558 UINT i, num_inputs = LOWORD(wParam);
559 PTOUCHINPUT inputs = SDL_stack_alloc(TOUCHINPUT, num_inputs);
560 if (data->videodata->GetTouchInputInfo((HTOUCHINPUT)lParam, num_inputs, inputs, sizeof(TOUCHINPUT))) {
561 RECT rect;
562 float x, y;
563
564 if (!GetClientRect(hwnd, &rect) ||
565 (rect.right == rect.left && rect.bottom == rect.top)) {
566 break;
567 }
568 ClientToScreen(hwnd, (LPPOINT) & rect);
569 ClientToScreen(hwnd, (LPPOINT) & rect + 1);
570 rect.top *= 100;
571 rect.left *= 100;
572 rect.bottom *= 100;
573 rect.right *= 100;
574
575 for (i = 0; i < num_inputs; ++i) {
576 PTOUCHINPUT input = &inputs[i];
577
578 SDL_TouchID touchId = (SDL_TouchID)input->hSource;
579 if (!SDL_GetTouch(touchId)) {
580 SDL_Touch touch;
581
582 touch.id = touchId;
583 touch.x_min = 0;
584 touch.x_max = 1;
585 touch.native_xres = touch.x_max - touch.x_min;
586 touch.y_min = 0;
587 touch.y_max = 1;
588 touch.native_yres = touch.y_max - touch.y_min;
589 touch.pressure_min = 0;
590 touch.pressure_max = 1;
591 touch.native_pressureres = touch.pressure_max - touch.pressure_min;
592
593 if (SDL_AddTouch(&touch, "") < 0) {
594 continue;
595 }
596 }
597
598 // Get the normalized coordinates for the window
599 x = (float)(input->x - rect.left)/(rect.right - rect.left);
600 y = (float)(input->y - rect.top)/(rect.bottom - rect.top);
601
602 if (input->dwFlags & TOUCHEVENTF_DOWN) {
603 SDL_SendFingerDown(touchId, input->dwID, SDL_TRUE, x, y, 1);
604 }
605 if (input->dwFlags & TOUCHEVENTF_MOVE) {
606 SDL_SendTouchMotion(touchId, input->dwID, SDL_FALSE, x, y, 1);
607 }
608 if (input->dwFlags & TOUCHEVENTF_UP) {
609 SDL_SendFingerDown(touchId, input->dwID, SDL_FALSE, x, y, 1);
610 }
611 }
612 }
613 SDL_stack_free(inputs);
614
615 data->videodata->CloseTouchInputHandle((HTOUCHINPUT)lParam);
616 return 0;
617 }
618 break;
619 }
620
621 /* If there's a window proc, assume it's going to handle messages */
622 if (data->wndproc) {
623 return CallWindowProc(data->wndproc, hwnd, msg, wParam, lParam);
624 } else if (returnCode >= 0) {
625 return returnCode;
626 } else {
627 return CallWindowProc(DefWindowProc, hwnd, msg, wParam, lParam);
628 }
629 }
630
631 void
632 WIN_PumpEvents(_THIS)
633 {
634 MSG msg;
635 while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
636 TranslateMessage(&msg);
637 DispatchMessage(&msg);
638 }
639 }
640
641 static int app_registered = 0;
642 LPTSTR SDL_Appname = NULL;
643 Uint32 SDL_Appstyle = 0;
644 HINSTANCE SDL_Instance = NULL;
645
646 /* Register the class for this application */
647 int
648 SDL_RegisterApp(char *name, Uint32 style, void *hInst)
649 {
650 WNDCLASS class;
651
652 /* Only do this once... */
653 if (app_registered) {
654 ++app_registered;
655 return (0);
656 }
657 if (!name && !SDL_Appname) {
658 name = "SDL_app";
659 SDL_Appstyle = (CS_BYTEALIGNCLIENT | CS_OWNDC);
660 SDL_Instance = hInst ? hInst : GetModuleHandle(NULL);
661 }
662
663 if (name) {
664 SDL_Appname = WIN_UTF8ToString(name);
665 SDL_Appstyle = style;
666 SDL_Instance = hInst ? hInst : GetModuleHandle(NULL);
667 }
668
669 /* Register the application class */
670 class.hCursor = NULL;
671 class.hIcon =
672 LoadImage(SDL_Instance, SDL_Appname, IMAGE_ICON, 0, 0,
673 LR_DEFAULTCOLOR);
674 class.lpszMenuName = NULL;
675 class.lpszClassName = SDL_Appname;
676 class.hbrBackground = NULL;
677 class.hInstance = SDL_Instance;
678 class.style = SDL_Appstyle;
679 class.lpfnWndProc = WIN_WindowProc;
680 class.cbWndExtra = 0;
681 class.cbClsExtra = 0;
682 if (!RegisterClass(&class)) {
683 SDL_SetError("Couldn't register application class");
684 return (-1);
685 }
686
687 app_registered = 1;
688 return (0);
689 }
690
691 /* Unregisters the windowclass registered in SDL_RegisterApp above. */
692 void
693 SDL_UnregisterApp()
694 {
695 WNDCLASS class;
696
697 /* SDL_RegisterApp might not have been called before */
698 if (!app_registered) {
699 return;
700 }
701 --app_registered;
702 if (app_registered == 0) {
703 /* Check for any registered window classes. */
704 if (GetClassInfo(SDL_Instance, SDL_Appname, &class)) {
705 UnregisterClass(SDL_Appname, SDL_Instance);
706 }
707 SDL_free(SDL_Appname);
708 SDL_Appname = NULL;
709 }
710 }
711
712 /* vi: set ts=4 sw=4 expandtab: */