SDL-1.2.14
[sdl_omap.git] / src / video / wincommon / SDL_sysevents.c
CommitLineData
e14743d1 1/*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2009 Sam Lantinga
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
19 Sam Lantinga
20 slouken@libsdl.org
21*/
22#include "SDL_config.h"
23
24#define WIN32_LEAN_AND_MEAN
25#include <windows.h>
26
27/* Make sure XBUTTON stuff is defined that isn't in older Platform SDKs... */
28#ifndef WM_XBUTTONDOWN
29#define WM_XBUTTONDOWN 0x020B
30#endif
31#ifndef WM_XBUTTONUP
32#define WM_XBUTTONUP 0x020C
33#endif
34#ifndef GET_XBUTTON_WPARAM
35#define GET_XBUTTON_WPARAM(w) (HIWORD(w))
36#endif
37
38#include "SDL_events.h"
39#include "SDL_video.h"
40#include "SDL_syswm.h"
41#include "../SDL_sysvideo.h"
42#include "../../events/SDL_sysevents.h"
43#include "../../events/SDL_events_c.h"
44#include "SDL_lowvideo.h"
45#include "SDL_syswm_c.h"
46#include "SDL_main.h"
47#include "SDL_loadso.h"
48
49#ifdef WMMSG_DEBUG
50#include "wmmsg.h"
51#endif
52
53#include "../windib/SDL_gapidibvideo.h"
54
55#ifdef SDL_VIDEO_DRIVER_GAPI
56#include "../gapi/SDL_gapivideo.h"
57#endif
58
59#ifdef _WIN32_WCE
60#define IsZoomed(HWND) 1
61#define NO_GETKEYBOARDSTATE
62#if _WIN32_WCE < 420
63#define NO_CHANGEDISPLAYSETTINGS
64#endif
65#endif
66
67/* The window we use for everything... */
68#ifdef _WIN32_WCE
69LPWSTR SDL_Appname = NULL;
70#else
71LPSTR SDL_Appname = NULL;
72#endif
73Uint32 SDL_Appstyle = 0;
74HINSTANCE SDL_Instance = NULL;
75HWND SDL_Window = NULL;
76RECT SDL_bounds = {0, 0, 0, 0};
77int SDL_windowX = 0;
78int SDL_windowY = 0;
79int SDL_resizing = 0;
80int mouse_relative = 0;
81int posted = 0;
82#ifndef NO_CHANGEDISPLAYSETTINGS
83DEVMODE SDL_desktop_mode;
84DEVMODE SDL_fullscreen_mode;
85#endif
86WORD *gamma_saved = NULL;
87
88
89/* Functions called by the message processing function */
90LONG (*HandleMessage)(_THIS, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)=NULL;
91void (*WIN_Activate)(_THIS, BOOL active, BOOL iconic);
92void (*WIN_RealizePalette)(_THIS);
93void (*WIN_PaletteChanged)(_THIS, HWND window);
94void (*WIN_WinPAINT)(_THIS, HDC hdc);
95extern void DIB_SwapGamma(_THIS);
96
97#ifndef NO_GETKEYBOARDSTATE
98/* Variables and support functions for SDL_ToUnicode() */
99static int codepage;
100static int Is9xME();
101static int GetCodePage();
102static int WINAPI ToUnicode9xME(UINT vkey, UINT scancode, BYTE *keystate, LPWSTR wchars, int wsize, UINT flags);
103
104ToUnicodeFN SDL_ToUnicode = ToUnicode9xME;
105#endif /* !NO_GETKEYBOARDSTATE */
106
107
108#if defined(_WIN32_WCE)
109
110//AdjustWindowRect is not available under WinCE 2003
111#define AdjustWindowRect(a,b,c) (AdjustWindowRectEx((a),(b),(c),0))
112
113// dynamically load aygshell dll because we want SDL to work on HPC and be300
114HINSTANCE aygshell = NULL;
115BOOL (WINAPI *SHFullScreen)(HWND hwndRequester, DWORD dwState) = 0;
116
117#define SHFS_SHOWTASKBAR 0x0001
118#define SHFS_HIDETASKBAR 0x0002
119#define SHFS_SHOWSIPBUTTON 0x0004
120#define SHFS_HIDESIPBUTTON 0x0008
121#define SHFS_SHOWSTARTICON 0x0010
122#define SHFS_HIDESTARTICON 0x0020
123
124static void LoadAygshell(void)
125{
126 if( !aygshell )
127 aygshell = SDL_LoadObject("aygshell.dll");
128 if( (aygshell != 0) && (SHFullScreen == 0) )
129 {
130 SHFullScreen = (int (WINAPI *)(struct HWND__ *,unsigned long)) SDL_LoadFunction(aygshell, "SHFullScreen");
131 }
132}
133
134#endif
135
136/* JC 14 Mar 2006
137 This is used all over the place, in the windib driver and in the dx5 driver
138 So we may as well stick it here instead of having multiple copies scattered
139 about
140*/
141void WIN_FlushMessageQueue()
142{
143 MSG msg;
144 while ( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) ) {
145 if ( msg.message == WM_QUIT ) break;
146 TranslateMessage( &msg );
147 DispatchMessage( &msg );
148 }
149}
150
151static void SDL_RestoreGameMode(void)
152{
153#ifdef _WIN32_WCE //Under ce we don't minimize, therefore no restore
154
155#ifdef SDL_VIDEO_DRIVER_GAPI
156 SDL_VideoDevice *this = current_video;
157 if(SDL_strcmp(this->name, "gapi") == 0)
158 {
159 if( this->hidden->gapiInfo->suspended )
160 {
161 this->hidden->gapiInfo->suspended = 0;
162 }
163 }
164#endif
165
166#else
167 ShowWindow(SDL_Window, SW_RESTORE);
168#endif
169
170#ifndef NO_CHANGEDISPLAYSETTINGS
171#ifndef _WIN32_WCE
172 ChangeDisplaySettings(&SDL_fullscreen_mode, CDS_FULLSCREEN);
173#endif
174#endif /* NO_CHANGEDISPLAYSETTINGS */
175}
176static void SDL_RestoreDesktopMode(void)
177{
178
179#ifdef _WIN32_WCE
180
181#ifdef SDL_VIDEO_DRIVER_GAPI
182 SDL_VideoDevice *this = current_video;
183 if(SDL_strcmp(this->name, "gapi") == 0)
184 {
185 if( !this->hidden->gapiInfo->suspended )
186 {
187 this->hidden->gapiInfo->suspended = 1;
188 }
189 }
190#endif
191
192#else
193 /* WinCE does not have a taskbar, so minimizing is not convenient */
194 ShowWindow(SDL_Window, SW_MINIMIZE);
195#endif
196
197#ifndef NO_CHANGEDISPLAYSETTINGS
198#ifndef _WIN32_WCE
199 ChangeDisplaySettings(NULL, 0);
200#endif
201#endif /* NO_CHANGEDISPLAYSETTINGS */
202}
203
204#ifdef WM_MOUSELEAVE
205/*
206 Special code to handle mouse leave events - this sucks...
207 http://support.microsoft.com/support/kb/articles/q183/1/07.asp
208
209 TrackMouseEvent() is only available on Win98 and WinNT.
210 _TrackMouseEvent() is available on Win95, but isn't yet in the mingw32
211 development environment, and only works on systems that have had IE 3.0
212 or newer installed on them (which is not the case with the base Win95).
213 Therefore, we implement our own version of _TrackMouseEvent() which
214 uses our own implementation if TrackMouseEvent() is not available.
215*/
216static BOOL (WINAPI *_TrackMouseEvent)(TRACKMOUSEEVENT *ptme) = NULL;
217
218static VOID CALLBACK
219TrackMouseTimerProc(HWND hWnd, UINT uMsg, UINT idEvent, DWORD dwTime)
220{
221 RECT rect;
222 POINT pt;
223
224 GetClientRect(hWnd, &rect);
225 MapWindowPoints(hWnd, NULL, (LPPOINT)&rect, 2);
226 GetCursorPos(&pt);
227 if ( !PtInRect(&rect, pt) || (WindowFromPoint(pt) != hWnd) ) {
228 if ( !KillTimer(hWnd, idEvent) ) {
229 /* Error killing the timer! */
230 }
231 PostMessage(hWnd, WM_MOUSELEAVE, 0, 0);
232 }
233}
234static BOOL WINAPI WIN_TrackMouseEvent(TRACKMOUSEEVENT *ptme)
235{
236 if ( ptme->dwFlags == TME_LEAVE ) {
237 return SetTimer(ptme->hwndTrack, ptme->dwFlags, 100,
238 (TIMERPROC)TrackMouseTimerProc) != 0;
239 }
240 return FALSE;
241}
242#endif /* WM_MOUSELEAVE */
243
244/* Function to retrieve the current keyboard modifiers */
245static void WIN_GetKeyboardState(void)
246{
247#ifndef NO_GETKEYBOARDSTATE
248 SDLMod state;
249 BYTE keyboard[256];
250 Uint8 *kstate = SDL_GetKeyState(NULL);
251
252 state = KMOD_NONE;
253 if ( GetKeyboardState(keyboard) ) {
254 if ( keyboard[VK_LSHIFT] & 0x80) {
255 state |= KMOD_LSHIFT;
256 kstate[SDLK_LSHIFT] = SDL_PRESSED;
257 }
258 if ( keyboard[VK_RSHIFT] & 0x80) {
259 state |= KMOD_RSHIFT;
260 kstate[SDLK_RSHIFT] = SDL_PRESSED;
261 }
262 if ( keyboard[VK_LCONTROL] & 0x80) {
263 state |= KMOD_LCTRL;
264 kstate[SDLK_LCTRL] = SDL_PRESSED;
265 }
266 if ( keyboard[VK_RCONTROL] & 0x80) {
267 state |= KMOD_RCTRL;
268 kstate[SDLK_RCTRL] = SDL_PRESSED;
269 }
270 if ( keyboard[VK_LMENU] & 0x80) {
271 state |= KMOD_LALT;
272 kstate[SDLK_LALT] = SDL_PRESSED;
273 }
274 if ( keyboard[VK_RMENU] & 0x80) {
275 state |= KMOD_RALT;
276 kstate[SDLK_RALT] = SDL_PRESSED;
277 }
278 if ( keyboard[VK_NUMLOCK] & 0x01) {
279 state |= KMOD_NUM;
280 kstate[SDLK_NUMLOCK] = SDL_PRESSED;
281 }
282 if ( keyboard[VK_CAPITAL] & 0x01) {
283 state |= KMOD_CAPS;
284 kstate[SDLK_CAPSLOCK] = SDL_PRESSED;
285 }
286 }
287 SDL_SetModState(state);
288#endif /* !NO_GETKEYBOARDSTATE */
289}
290
291/* The main Win32 event handler
292DJM: This is no longer static as (DX5/DIB)_CreateWindow needs it
293*/
294LRESULT CALLBACK WinMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
295{
296 SDL_VideoDevice *this = current_video;
297 static int mouse_pressed = 0;
298#ifdef WMMSG_DEBUG
299 fprintf(stderr, "Received windows message: ");
300 if ( msg > MAX_WMMSG ) {
301 fprintf(stderr, "%d", msg);
302 } else {
303 fprintf(stderr, "%s", wmtab[msg]);
304 }
305 fprintf(stderr, " -- 0x%X, 0x%X\n", wParam, lParam);
306#endif
307 switch (msg) {
308
309 case WM_ACTIVATE: {
310 SDL_VideoDevice *this = current_video;
311 BOOL active, minimized;
312 Uint8 appstate;
313
314 minimized = HIWORD(wParam);
315 active = (LOWORD(wParam) != WA_INACTIVE) && !minimized;
316 if ( active ) {
317 /* Gain the following states */
318 appstate = SDL_APPACTIVE|SDL_APPINPUTFOCUS;
319 if ( this->input_grab != SDL_GRAB_OFF ) {
320 WIN_GrabInput(this, SDL_GRAB_ON);
321 }
322 if ( !(SDL_GetAppState()&SDL_APPINPUTFOCUS) ) {
323 if ( ! DDRAW_FULLSCREEN() ) {
324 DIB_SwapGamma(this);
325 }
326 if ( WINDIB_FULLSCREEN() ) {
327 SDL_RestoreGameMode();
328 }
329 }
330#if defined(_WIN32_WCE)
331 if ( WINDIB_FULLSCREEN() ) {
332 LoadAygshell();
333 if( SHFullScreen )
334 SHFullScreen(SDL_Window, SHFS_HIDESTARTICON|SHFS_HIDETASKBAR|SHFS_HIDESIPBUTTON);
335 else
336 ShowWindow(FindWindow(TEXT("HHTaskBar"),NULL),SW_HIDE);
337 }
338#endif
339 posted = SDL_PrivateAppActive(1, appstate);
340 WIN_GetKeyboardState();
341 } else {
342 /* Lose the following states */
343 appstate = SDL_APPINPUTFOCUS;
344 if ( minimized ) {
345 appstate |= SDL_APPACTIVE;
346 }
347 if ( this->input_grab != SDL_GRAB_OFF ) {
348 WIN_GrabInput(this, SDL_GRAB_OFF);
349 }
350 if ( SDL_GetAppState() & SDL_APPINPUTFOCUS ) {
351 if ( ! DDRAW_FULLSCREEN() ) {
352 DIB_SwapGamma(this);
353 }
354 if ( WINDIB_FULLSCREEN() ) {
355 SDL_RestoreDesktopMode();
356#if defined(_WIN32_WCE)
357 LoadAygshell();
358 if( SHFullScreen )
359 SHFullScreen(SDL_Window, SHFS_SHOWSTARTICON|SHFS_SHOWTASKBAR|SHFS_SHOWSIPBUTTON);
360 else
361 ShowWindow(FindWindow(TEXT("HHTaskBar"),NULL),SW_SHOW);
362#endif
363 }
364 }
365 posted = SDL_PrivateAppActive(0, appstate);
366 }
367 WIN_Activate(this, active, minimized);
368 return(0);
369 }
370 break;
371
372 case WM_MOUSEMOVE: {
373
374#ifdef WM_MOUSELEAVE
375 /* No need to handle SDL_APPMOUSEFOCUS when fullscreen */
376 if ( SDL_VideoSurface && !FULLSCREEN() ) {
377 /* mouse has entered the window */
378
379 if ( !(SDL_GetAppState() & SDL_APPMOUSEFOCUS) ) {
380 TRACKMOUSEEVENT tme;
381
382 tme.cbSize = sizeof(tme);
383 tme.dwFlags = TME_LEAVE;
384 tme.hwndTrack = SDL_Window;
385 _TrackMouseEvent(&tme);
386 }
387 }
388#endif /* WM_MOUSELEAVE */
389
390 /* Mouse motion is handled in DIB_PumpEvents or
391 * DX5_PumpEvents, depending on the video driver
392 * in use */
393
394 posted = SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS);
395 }
396 return(0);
397
398#ifdef WM_MOUSELEAVE
399 case WM_MOUSELEAVE: {
400
401 /* No need to handle SDL_APPMOUSEFOCUS when fullscreen */
402 if ( SDL_VideoSurface && !FULLSCREEN() ) {
403 /* mouse has left the window */
404 /* or */
405 /* Elvis has left the building! */
406 posted = SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS);
407 }
408 }
409 return(0);
410#endif /* WM_MOUSELEAVE */
411
412 case WM_LBUTTONDOWN:
413 case WM_LBUTTONUP:
414 case WM_MBUTTONDOWN:
415 case WM_MBUTTONUP:
416 case WM_RBUTTONDOWN:
417 case WM_RBUTTONUP:
418 case WM_XBUTTONDOWN:
419 case WM_XBUTTONUP: {
420 /* Mouse is handled by DirectInput when fullscreen */
421 if ( SDL_VideoSurface && ! DINPUT() ) {
422 WORD xbuttonval = 0;
423 Uint8 button, state;
424
425 /* DJM:
426 We want the SDL window to take focus so that
427 it acts like a normal windows "component"
428 (e.g. gains keyboard focus on a mouse click).
429 */
430 SetFocus(SDL_Window);
431
432 /* Figure out which button to use */
433 switch (msg) {
434 case WM_LBUTTONDOWN:
435 button = SDL_BUTTON_LEFT;
436 state = SDL_PRESSED;
437 break;
438 case WM_LBUTTONUP:
439 button = SDL_BUTTON_LEFT;
440 state = SDL_RELEASED;
441 break;
442 case WM_MBUTTONDOWN:
443 button = SDL_BUTTON_MIDDLE;
444 state = SDL_PRESSED;
445 break;
446 case WM_MBUTTONUP:
447 button = SDL_BUTTON_MIDDLE;
448 state = SDL_RELEASED;
449 break;
450 case WM_RBUTTONDOWN:
451 button = SDL_BUTTON_RIGHT;
452 state = SDL_PRESSED;
453 break;
454 case WM_RBUTTONUP:
455 button = SDL_BUTTON_RIGHT;
456 state = SDL_RELEASED;
457 break;
458 case WM_XBUTTONDOWN:
459 xbuttonval = GET_XBUTTON_WPARAM(wParam);
460 button = SDL_BUTTON_X1 + xbuttonval - 1;
461 state = SDL_PRESSED;
462 break;
463 case WM_XBUTTONUP:
464 xbuttonval = GET_XBUTTON_WPARAM(wParam);
465 button = SDL_BUTTON_X1 + xbuttonval - 1;
466 state = SDL_RELEASED;
467 break;
468 default:
469 /* Eh? Unknown button? */
470 return(0);
471 }
472 if ( state == SDL_PRESSED ) {
473 /* Grab mouse so we get up events */
474 if ( ++mouse_pressed > 0 ) {
475 SetCapture(hwnd);
476 }
477 } else {
478 /* Release mouse after all up events */
479 if ( --mouse_pressed <= 0 ) {
480 ReleaseCapture();
481 mouse_pressed = 0;
482 }
483 }
484 posted = SDL_PrivateMouseButton(
485 state, button, 0, 0);
486
487 /*
488 * MSDN says:
489 * "Unlike the WM_LBUTTONUP, WM_MBUTTONUP, and WM_RBUTTONUP
490 * messages, an application should return TRUE from [an
491 * XBUTTON message] if it processes it. Doing so will allow
492 * software that simulates this message on Microsoft Windows
493 * systems earlier than Windows 2000 to determine whether
494 * the window procedure processed the message or called
495 * DefWindowProc to process it.
496 */
497 if (xbuttonval > 0)
498 return(TRUE);
499 }
500 }
501 return(0);
502
503
504#if (_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)
505 case WM_MOUSEWHEEL:
506 if ( SDL_VideoSurface && ! DINPUT() ) {
507 int move = (short)HIWORD(wParam);
508 if ( move ) {
509 Uint8 button;
510 if ( move > 0 )
511 button = SDL_BUTTON_WHEELUP;
512 else
513 button = SDL_BUTTON_WHEELDOWN;
514 posted = SDL_PrivateMouseButton(
515 SDL_PRESSED, button, 0, 0);
516 posted |= SDL_PrivateMouseButton(
517 SDL_RELEASED, button, 0, 0);
518 }
519 }
520 return(0);
521#endif
522
523#ifdef WM_GETMINMAXINFO
524 /* This message is sent as a way for us to "check" the values
525 * of a position change. If we don't like it, we can adjust
526 * the values before they are changed.
527 */
528 case WM_GETMINMAXINFO: {
529 MINMAXINFO *info;
530 RECT size;
531 int x, y;
532 int style;
533 int width;
534 int height;
535
536 /* We don't want to clobber an internal resize */
537 if ( SDL_resizing )
538 return(0);
539
540 /* We allow resizing with the SDL_RESIZABLE flag */
541 if ( SDL_PublicSurface &&
542 (SDL_PublicSurface->flags & SDL_RESIZABLE) ) {
543 return(0);
544 }
545
546 /* Get the current position of our window */
547 GetWindowRect(SDL_Window, &size);
548 x = size.left;
549 y = size.top;
550
551 /* Calculate current width and height of our window */
552 size.top = 0;
553 size.left = 0;
554 if ( SDL_PublicSurface != NULL ) {
555 size.bottom = SDL_PublicSurface->h;
556 size.right = SDL_PublicSurface->w;
557 } else {
558 size.bottom = 0;
559 size.right = 0;
560 }
561
562 /* DJM - according to the docs for GetMenu(), the
563 return value is undefined if hwnd is a child window.
564 Aparently it's too difficult for MS to check
565 inside their function, so I have to do it here.
566 */
567 style = GetWindowLong(hwnd, GWL_STYLE);
568 AdjustWindowRect(
569 &size,
570 style,
571 style & WS_CHILDWINDOW ? FALSE
572 : GetMenu(hwnd) != NULL);
573
574 width = size.right - size.left;
575 height = size.bottom - size.top;
576
577 /* Fix our size to the current size */
578 info = (MINMAXINFO *)lParam;
579 info->ptMaxSize.x = width;
580 info->ptMaxSize.y = height;
581 info->ptMaxPosition.x = x;
582 info->ptMaxPosition.y = y;
583 info->ptMinTrackSize.x = width;
584 info->ptMinTrackSize.y = height;
585 info->ptMaxTrackSize.x = width;
586 info->ptMaxTrackSize.y = height;
587 }
588 return(0);
589#endif /* WM_GETMINMAXINFO */
590
591 case WM_WINDOWPOSCHANGING: {
592 WINDOWPOS *windowpos = (WINDOWPOS*)lParam;
593
594 /* When menu is at the side or top, Windows likes
595 to try to reposition the fullscreen window when
596 changing video modes.
597 */
598 if ( !SDL_resizing &&
599 SDL_PublicSurface &&
600 (SDL_PublicSurface->flags & SDL_FULLSCREEN) ) {
601 windowpos->x = 0;
602 windowpos->y = 0;
603 }
604 }
605 return(0);
606
607 case WM_WINDOWPOSCHANGED: {
608 SDL_VideoDevice *this = current_video;
609 int w, h;
610
611 GetClientRect(SDL_Window, &SDL_bounds);
612 ClientToScreen(SDL_Window, (LPPOINT)&SDL_bounds);
613 ClientToScreen(SDL_Window, (LPPOINT)&SDL_bounds+1);
614 if ( !SDL_resizing && !IsZoomed(SDL_Window) &&
615 SDL_PublicSurface &&
616 !(SDL_PublicSurface->flags & SDL_FULLSCREEN) ) {
617 SDL_windowX = SDL_bounds.left;
618 SDL_windowY = SDL_bounds.top;
619 }
620 w = SDL_bounds.right-SDL_bounds.left;
621 h = SDL_bounds.bottom-SDL_bounds.top;
622 if ( this->input_grab != SDL_GRAB_OFF ) {
623 ClipCursor(&SDL_bounds);
624 }
625 if ( SDL_PublicSurface &&
626 (SDL_PublicSurface->flags & SDL_RESIZABLE) ) {
627 SDL_PrivateResize(w, h);
628 }
629 }
630 break;
631
632 /* We need to set the cursor */
633 case WM_SETCURSOR: {
634 Uint16 hittest;
635
636 hittest = LOWORD(lParam);
637 if ( hittest == HTCLIENT ) {
638 SetCursor(SDL_hcursor);
639 return(TRUE);
640 }
641 }
642 break;
643
644 /* We are about to get palette focus! */
645 case WM_QUERYNEWPALETTE: {
646 WIN_RealizePalette(current_video);
647 return(TRUE);
648 }
649 break;
650
651 /* Another application changed the palette */
652 case WM_PALETTECHANGED: {
653 WIN_PaletteChanged(current_video, (HWND)wParam);
654 }
655 break;
656
657 /* We were occluded, refresh our display */
658 case WM_PAINT: {
659 HDC hdc;
660 PAINTSTRUCT ps;
661
662 hdc = BeginPaint(SDL_Window, &ps);
663 if ( current_video->screen &&
664 !(current_video->screen->flags & SDL_OPENGL) ) {
665 WIN_WinPAINT(current_video, hdc);
666 }
667 EndPaint(SDL_Window, &ps);
668 }
669 return(0);
670
671 /* DJM: Send an expose event in this case */
672 case WM_ERASEBKGND: {
673 posted = SDL_PrivateExpose();
674 }
675 return(0);
676
677 case WM_CLOSE: {
678 if ( (posted = SDL_PrivateQuit()) )
679 PostQuitMessage(0);
680 }
681 return(0);
682
683 case WM_DESTROY: {
684 PostQuitMessage(0);
685 }
686 return(0);
687
688#ifndef NO_GETKEYBOARDSTATE
689 case WM_INPUTLANGCHANGE: {
690 codepage = GetCodePage();
691 }
692 return(TRUE);
693#endif
694
695 default: {
696 /* Special handling by the video driver */
697 if (HandleMessage) {
698 return(HandleMessage(current_video,
699 hwnd, msg, wParam, lParam));
700 }
701 }
702 break;
703 }
704 return(DefWindowProc(hwnd, msg, wParam, lParam));
705}
706
707/* Allow the application handle to be stored and retrieved later */
708static void *SDL_handle = NULL;
709
710void SDL_SetModuleHandle(void *handle)
711{
712 SDL_handle = handle;
713}
714void *SDL_GetModuleHandle(void)
715{
716 void *handle;
717
718 if ( SDL_handle ) {
719 handle = SDL_handle;
720 } else {
721 handle = GetModuleHandle(NULL);
722 }
723 return(handle);
724}
725
726/* This allows the SDL_WINDOWID hack */
727BOOL SDL_windowid = FALSE;
728
729static int app_registered = 0;
730
731/* Register the class for this application -- exported for winmain.c */
732int SDL_RegisterApp(char *name, Uint32 style, void *hInst)
733{
734 WNDCLASS class;
735#ifdef WM_MOUSELEAVE
736 HMODULE handle;
737#endif
738
739 /* Only do this once... */
740 if ( app_registered ) {
741 ++app_registered;
742 return(0);
743 }
744
745#ifndef CS_BYTEALIGNCLIENT
746#define CS_BYTEALIGNCLIENT 0
747#endif
748 if ( ! name && ! SDL_Appname ) {
749 name = "SDL_app";
750 SDL_Appstyle = CS_BYTEALIGNCLIENT;
751 SDL_Instance = hInst ? hInst : SDL_GetModuleHandle();
752 }
753
754 if ( name ) {
755#ifdef _WIN32_WCE
756 /* WinCE uses the UNICODE version */
757 SDL_Appname = SDL_iconv_utf8_ucs2(name);
758#else
759 SDL_Appname = SDL_iconv_utf8_locale(name);
760#endif /* _WIN32_WCE */
761 SDL_Appstyle = style;
762 SDL_Instance = hInst ? hInst : SDL_GetModuleHandle();
763 }
764
765 /* Register the application class */
766 class.hCursor = NULL;
767 class.hIcon = LoadImage(SDL_Instance, SDL_Appname,
768 IMAGE_ICON,
769 0, 0, LR_DEFAULTCOLOR);
770 class.lpszMenuName = NULL;
771 class.lpszClassName = SDL_Appname;
772 class.hbrBackground = NULL;
773 class.hInstance = SDL_Instance;
774 class.style = SDL_Appstyle;
775#if SDL_VIDEO_OPENGL
776 class.style |= CS_OWNDC;
777#endif
778 class.lpfnWndProc = WinMessage;
779 class.cbWndExtra = 0;
780 class.cbClsExtra = 0;
781 if ( ! RegisterClass(&class) ) {
782 SDL_SetError("Couldn't register application class");
783 return(-1);
784 }
785
786#ifdef WM_MOUSELEAVE
787 /* Get the version of TrackMouseEvent() we use */
788 _TrackMouseEvent = NULL;
789 handle = GetModuleHandle("USER32.DLL");
790 if ( handle ) {
791 _TrackMouseEvent = (BOOL (WINAPI *)(TRACKMOUSEEVENT *))GetProcAddress(handle, "TrackMouseEvent");
792 }
793 if ( _TrackMouseEvent == NULL ) {
794 _TrackMouseEvent = WIN_TrackMouseEvent;
795 }
796#endif /* WM_MOUSELEAVE */
797
798#ifndef NO_GETKEYBOARDSTATE
799 /* Initialise variables for SDL_ToUnicode() */
800 codepage = GetCodePage();
801 SDL_ToUnicode = Is9xME() ? ToUnicode9xME : ToUnicode;
802#endif
803
804 app_registered = 1;
805 return(0);
806}
807
808/* Unregisters the windowclass registered in SDL_RegisterApp above. */
809void SDL_UnregisterApp()
810{
811 WNDCLASS class;
812
813 /* SDL_RegisterApp might not have been called before */
814 if ( !app_registered ) {
815 return;
816 }
817 --app_registered;
818 if ( app_registered == 0 ) {
819 /* Check for any registered window classes. */
820 if ( GetClassInfo(SDL_Instance, SDL_Appname, &class) ) {
821 UnregisterClass(SDL_Appname, SDL_Instance);
822 }
823 SDL_free(SDL_Appname);
824 SDL_Appname = NULL;
825 }
826}
827
828#ifndef NO_GETKEYBOARDSTATE
829/* JFP: Implementation of ToUnicode() that works on 9x/ME/2K/XP */
830
831static int Is9xME()
832{
833 OSVERSIONINFO info;
834
835 SDL_memset(&info, 0, sizeof(info));
836 info.dwOSVersionInfoSize = sizeof(info);
837 if (!GetVersionEx(&info)) {
838 return 0;
839 }
840 return (info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS);
841}
842
843static int GetCodePage()
844{
845 char buff[8];
846 int lcid = MAKELCID(LOWORD(GetKeyboardLayout(0)), SORT_DEFAULT);
847 int cp = GetACP();
848
849 if (GetLocaleInfo(lcid, LOCALE_IDEFAULTANSICODEPAGE, buff, sizeof(buff))) {
850 cp = SDL_atoi(buff);
851 }
852 return cp;
853}
854
855static int WINAPI ToUnicode9xME(UINT vkey, UINT scancode, PBYTE keystate, LPWSTR wchars, int wsize, UINT flags)
856{
857 BYTE chars[2];
858
859 if (ToAsciiEx(vkey, scancode, keystate, (WORD*)chars, 0, GetKeyboardLayout(0)) == 1) {
860 return MultiByteToWideChar(codepage, 0, chars, 1, wchars, wsize);
861 }
862 return 0;
863}
864
865#endif /* !NO_GETKEYBOARDSTATE */