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