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