src/video/wincommon/SDL_sysevents.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 19 Aug 2002 18:09:44 +0000
changeset 451 24edec3cafe4
parent 447 16d0449891b8
child 453 a6fa62b1be09
permissions -rw-r--r--
Added SDL_BUTTON_WHEELUP (4) and SDL_BUTTON_WHEELDOWN (5)
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997, 1998, 1999  Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Library General Public
     7     License as published by the Free Software Foundation; either
     8     version 2 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     Library General Public License for more details.
    14 
    15     You should have received a copy of the GNU Library General Public
    16     License along with this library; if not, write to the Free
    17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 */
    22 
    23 #ifdef SAVE_RCSID
    24 static char rcsid =
    25  "@(#) $Id$";
    26 #endif
    27 
    28 #include <stdlib.h>
    29 #include <stdio.h>
    30 #include <windows.h>
    31 
    32 #include "SDL_getenv.h"
    33 #include "SDL_events.h"
    34 #include "SDL_video.h"
    35 #include "SDL_error.h"
    36 #include "SDL_syswm.h"
    37 #include "SDL_sysevents.h"
    38 #include "SDL_events_c.h"
    39 #include "SDL_sysvideo.h"
    40 #include "SDL_lowvideo.h"
    41 #include "SDL_syswm_c.h"
    42 #include "SDL_main.h"
    43 
    44 #ifdef WMMSG_DEBUG
    45 #include "wmmsg.h"
    46 #endif
    47 
    48 #ifdef _WIN32_WCE
    49 #define NO_GETKEYBOARDSTATE
    50 #endif
    51 
    52 /* The window we use for everything... */
    53 const char *SDL_Appname = NULL;
    54 HINSTANCE SDL_Instance = NULL;
    55 HWND SDL_Window = NULL;
    56 RECT SDL_bounds = {0, 0, 0, 0};
    57 int SDL_resizing = 0;
    58 int mouse_relative = 0;
    59 int posted = 0;
    60 #ifndef NO_CHANGEDISPLAYSETTINGS
    61 DEVMODE SDL_fullscreen_mode;
    62 #endif
    63 WORD *gamma_saved = NULL;
    64 
    65 
    66 /* Functions called by the message processing function */
    67 LONG
    68 (*HandleMessage)(_THIS, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)=NULL;
    69 void (*WIN_RealizePalette)(_THIS);
    70 void (*WIN_PaletteChanged)(_THIS, HWND window);
    71 void (*WIN_WinPAINT)(_THIS, HDC hdc);
    72 extern void DIB_SwapGamma(_THIS);
    73 
    74 static void SDL_RestoreGameMode(void)
    75 {
    76 #ifndef NO_CHANGEDISPLAYSETTINGS
    77 	ShowWindow(SDL_Window, SW_RESTORE);
    78 	ChangeDisplaySettings(&SDL_fullscreen_mode, CDS_FULLSCREEN);
    79 #endif
    80 }
    81 static void SDL_RestoreDesktopMode(void)
    82 {
    83 #ifndef NO_CHANGEDISPLAYSETTINGS
    84 	ShowWindow(SDL_Window, SW_MINIMIZE);
    85 	ChangeDisplaySettings(NULL, 0);
    86 #endif
    87 }
    88 
    89 #ifdef WM_MOUSELEAVE
    90 /* 
    91    Special code to handle mouse leave events - this sucks...
    92    http://support.microsoft.com/support/kb/articles/q183/1/07.asp
    93 
    94    TrackMouseEvent() is only available on Win98 and WinNT.
    95    _TrackMouseEvent() is available on Win95, but isn't yet in the mingw32
    96    development environment, and only works on systems that have had IE 3.0
    97    or newer installed on them (which is not the case with the base Win95).
    98    Therefore, we implement our own version of _TrackMouseEvent() which
    99    uses our own implementation if TrackMouseEvent() is not available.
   100 */
   101 static BOOL (WINAPI *_TrackMouseEvent)(TRACKMOUSEEVENT *ptme) = NULL;
   102 
   103 static VOID CALLBACK
   104 TrackMouseTimerProc(HWND hWnd, UINT uMsg, UINT idEvent, DWORD dwTime)
   105 {
   106 	RECT rect;
   107 	POINT pt;
   108 
   109 	GetClientRect(hWnd, &rect);
   110 	MapWindowPoints(hWnd, NULL, (LPPOINT)&rect, 2);
   111 	GetCursorPos(&pt);
   112 	if ( !PtInRect(&rect, pt) || (WindowFromPoint(pt) != hWnd) ) {
   113 		if ( !KillTimer(hWnd, idEvent) ) {
   114 			/* Error killing the timer! */
   115 		}
   116 		PostMessage(hWnd, WM_MOUSELEAVE, 0, 0);
   117 	}
   118 }
   119 static BOOL WINAPI WIN_TrackMouseEvent(TRACKMOUSEEVENT *ptme)
   120 {
   121 	if ( ptme->dwFlags == TME_LEAVE ) {
   122 		return SetTimer(ptme->hwndTrack, ptme->dwFlags, 100,
   123 		                (TIMERPROC)TrackMouseTimerProc);
   124 	}
   125 	return FALSE;
   126 }
   127 #endif /* WM_MOUSELEAVE */
   128 
   129 /* Function to retrieve the current keyboard modifiers */
   130 static void WIN_GetKeyboardState(void)
   131 {
   132 #ifndef NO_GETKEYBOARDSTATE
   133 	SDLMod state;
   134 	BYTE keyboard[256];
   135 	Uint8 *kstate = SDL_GetKeyState(NULL);
   136 
   137 	state = KMOD_NONE;
   138 	if ( GetKeyboardState(keyboard) ) {
   139 		if ( keyboard[VK_LSHIFT] & 0x80) {
   140 			state |= KMOD_LSHIFT;
   141 		}
   142 		if ( keyboard[VK_RSHIFT] & 0x80) {
   143 			state |= KMOD_RSHIFT;
   144 		}
   145 		if ( keyboard[VK_LCONTROL] & 0x80) {
   146 			state |= KMOD_LCTRL;
   147 		}
   148 		if ( keyboard[VK_RCONTROL] & 0x80) {
   149 			state |= KMOD_RCTRL;
   150 		}
   151 		if ( keyboard[VK_LMENU] & 0x80) {
   152 			state |= KMOD_LALT;
   153 		}
   154 		if ( keyboard[VK_RMENU] & 0x80) {
   155 			state |= KMOD_RALT;
   156 		}
   157 		if ( keyboard[VK_NUMLOCK] & 0x01) {
   158 			state |= KMOD_NUM;
   159 			kstate[SDLK_NUMLOCK] = SDL_PRESSED;
   160 		}
   161 		if ( keyboard[VK_CAPITAL] & 0x01) {
   162 			state |= KMOD_CAPS;
   163 			kstate[SDLK_CAPSLOCK] = SDL_PRESSED;
   164 		}
   165 	}
   166 	SDL_SetModState(state);
   167 #endif /* !NO_GETKEYBOARDSTATE */
   168 }
   169 
   170 /* The main Win32 event handler
   171 DJM: This is no longer static as (DX5/DIB)_CreateWindow needs it
   172 */
   173 LONG CALLBACK WinMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
   174 {
   175 	SDL_VideoDevice *this = current_video;
   176 	static int mouse_pressed = 0;
   177 	static int in_window = 0;
   178 #ifdef WMMSG_DEBUG
   179 	fprintf(stderr, "Received windows message:  ");
   180 	if ( msg > MAX_WMMSG ) {
   181 		fprintf(stderr, "%d", msg);
   182 	} else {
   183 		fprintf(stderr, "%s", wmtab[msg]);
   184 	}
   185 	fprintf(stderr, " -- 0x%X, 0x%X\n", wParam, lParam);
   186 #endif
   187 	switch (msg) {
   188 
   189 		case WM_ACTIVATE: {
   190 			SDL_VideoDevice *this = current_video;
   191 			BOOL minimized;
   192 			Uint8 appstate;
   193 
   194 			minimized = HIWORD(wParam);
   195 			if ( !minimized && (LOWORD(wParam) != WA_INACTIVE) ) {
   196 				/* Gain the following states */
   197 				appstate = SDL_APPACTIVE|SDL_APPINPUTFOCUS;
   198 				if ( this->input_grab != SDL_GRAB_OFF ) {
   199 					WIN_GrabInput(this, SDL_GRAB_ON);
   200 				}
   201 				if ( !(SDL_GetAppState()&SDL_APPINPUTFOCUS) ) {
   202 					if ( ! DDRAW_FULLSCREEN() ) {
   203 						DIB_SwapGamma(this);
   204 					}
   205 					if ( WINDIB_FULLSCREEN() ) {
   206 						SDL_RestoreGameMode();
   207 					}
   208 				}
   209 				posted = SDL_PrivateAppActive(1, appstate);
   210 				WIN_GetKeyboardState();
   211 			} else {
   212 				/* Lose the following states */
   213 				appstate = SDL_APPINPUTFOCUS;
   214 				if ( minimized ) {
   215 					appstate |= SDL_APPACTIVE;
   216 				}
   217 				if ( this->input_grab != SDL_GRAB_OFF ) {
   218 					WIN_GrabInput(this, SDL_GRAB_OFF);
   219 				}
   220 				if ( SDL_GetAppState() & SDL_APPINPUTFOCUS ) {
   221 					if ( ! DDRAW_FULLSCREEN() ) {
   222 						DIB_SwapGamma(this);
   223 					}
   224 					if ( WINDIB_FULLSCREEN() ) {
   225 						SDL_RestoreDesktopMode();
   226 					}
   227 				}
   228 				posted = SDL_PrivateAppActive(0, appstate);
   229 			}
   230 			return(0);
   231 		}
   232 		break;
   233 
   234 		case WM_MOUSEMOVE: {
   235 			
   236 			/* Mouse is handled by DirectInput when fullscreen */
   237 			if ( SDL_VideoSurface && ! DINPUT_FULLSCREEN() ) {
   238 				Sint16 x, y;
   239 
   240 				/* mouse has entered the window */
   241 				if ( ! in_window ) {
   242 #ifdef WM_MOUSELEAVE
   243 					TRACKMOUSEEVENT tme;
   244 
   245 					tme.cbSize = sizeof(tme);
   246 					tme.dwFlags = TME_LEAVE;
   247 					tme.hwndTrack = SDL_Window;
   248 					_TrackMouseEvent(&tme);
   249 #endif /* WM_MOUSELEAVE */
   250 					in_window = TRUE;
   251 
   252 					posted = SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS);
   253 				}
   254 
   255 				/* mouse has moved within the window */
   256 				x = LOWORD(lParam);
   257 				y = HIWORD(lParam);
   258 				if ( mouse_relative ) {
   259 					POINT center;
   260 					center.x = (SDL_VideoSurface->w/2);
   261 					center.y = (SDL_VideoSurface->h/2);
   262 					x -= (Sint16)center.x;
   263 					y -= (Sint16)center.y;
   264 					if ( x || y ) {
   265 						ClientToScreen(SDL_Window, &center);
   266 						SetCursorPos(center.x, center.y);
   267 						posted = SDL_PrivateMouseMotion(0, 1, x, y);
   268 					}
   269 				} else {
   270 					posted = SDL_PrivateMouseMotion(0, 0, x, y);
   271 				}
   272 			}
   273 		}
   274 		return(0);
   275 
   276 #ifdef WM_MOUSELEAVE
   277 		case WM_MOUSELEAVE: {
   278 
   279 			/* Mouse is handled by DirectInput when fullscreen */
   280 			if ( SDL_VideoSurface && ! DINPUT_FULLSCREEN() ) {
   281 				/* mouse has left the window */
   282 				/* or */
   283 				/* Elvis has left the building! */
   284 				in_window = FALSE;
   285 				posted = SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS);
   286 			}
   287 		}
   288 		return(0);
   289 #endif /* WM_MOUSELEAVE */
   290 
   291 		case WM_LBUTTONDOWN:
   292 		case WM_LBUTTONUP:
   293 		case WM_MBUTTONDOWN:
   294 		case WM_MBUTTONUP:
   295 		case WM_RBUTTONDOWN:
   296 		case WM_RBUTTONUP: {
   297 			/* Mouse is handled by DirectInput when fullscreen */
   298 			if ( SDL_VideoSurface && ! DINPUT_FULLSCREEN() ) {
   299 				Sint16 x, y;
   300 				Uint8 button, state;
   301 
   302 				/* DJM:
   303 				   We want the SDL window to take focus so that
   304 				   it acts like a normal windows "component"
   305 				   (e.g. gains keyboard focus on a mouse click).
   306 				 */
   307 				SetFocus(SDL_Window);
   308 
   309 				/* Figure out which button to use */
   310 				switch (msg) {
   311 					case WM_LBUTTONDOWN:
   312 						button = 1;
   313 						state = SDL_PRESSED;
   314 						break;
   315 					case WM_LBUTTONUP:
   316 						button = 1;
   317 						state = SDL_RELEASED;
   318 						break;
   319 					case WM_MBUTTONDOWN:
   320 						button = 2;
   321 						state = SDL_PRESSED;
   322 						break;
   323 					case WM_MBUTTONUP:
   324 						button = 2;
   325 						state = SDL_RELEASED;
   326 						break;
   327 					case WM_RBUTTONDOWN:
   328 						button = 3;
   329 						state = SDL_PRESSED;
   330 						break;
   331 					case WM_RBUTTONUP:
   332 						button = 3;
   333 						state = SDL_RELEASED;
   334 						break;
   335 					default:
   336 						/* Eh? Unknown button? */
   337 						return(0);
   338 				}
   339 				if ( state == SDL_PRESSED ) {
   340 					/* Grab mouse so we get up events */
   341 					if ( ++mouse_pressed > 0 ) {
   342 						SetCapture(hwnd);
   343 					}
   344 				} else {
   345 					/* Release mouse after all up events */
   346 					if ( --mouse_pressed <= 0 ) {
   347 						ReleaseCapture();
   348 						mouse_pressed = 0;
   349 					}
   350 				}
   351 				if ( mouse_relative ) {
   352 				/*	RJR: March 28, 2000
   353 					report internal mouse position if in relative mode */
   354 					x = 0; y = 0;
   355 				} else {
   356 					x = (Sint16)LOWORD(lParam);
   357 					y = (Sint16)HIWORD(lParam);
   358 				}
   359 				posted = SDL_PrivateMouseButton(
   360 							state, button, x, y);
   361 			}
   362 		}
   363 		return(0);
   364 
   365 
   366 #if (_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)
   367 		case WM_MOUSEWHEEL: 
   368 			if ( SDL_VideoSurface && ! DINPUT_FULLSCREEN() ) {
   369 				int move = (short)HIWORD(wParam);
   370 				if ( move ) {
   371 					Uint8 button;
   372 					if ( move > 0 )
   373 						button = SDL_BUTTON_WHEELUP;
   374 					else
   375 						button = SDL_BUTTON_WHEELDOWN;
   376 					posted = SDL_PrivateMouseButton(
   377 						SDL_PRESSED, button, 0, 0);
   378 					posted |= SDL_PrivateMouseButton(
   379 						SDL_RELEASED, button, 0, 0);
   380 				}
   381 			}
   382 			return(0);
   383 #endif
   384 
   385 #ifdef WM_GETMINMAXINFO
   386 		/* This message is sent as a way for us to "check" the values
   387 		 * of a position change.  If we don't like it, we can adjust
   388 		 * the values before they are changed.
   389 		 */
   390 		case WM_GETMINMAXINFO: {
   391 			MINMAXINFO *info;
   392 			RECT        size;
   393 			int x, y;
   394 			int width;
   395 			int height;
   396 
   397 			/* We don't want to clobber an internal resize */
   398 			if ( SDL_resizing )
   399 				return(0);
   400 
   401 			/* We allow resizing with the SDL_RESIZABLE flag */
   402 			if ( SDL_PublicSurface &&
   403 				(SDL_PublicSurface->flags & SDL_RESIZABLE) ) {
   404 				return(0);
   405 			}
   406 
   407 			/* Get the current position of our window */
   408 			GetWindowRect(SDL_Window, &size);
   409 			x = size.left;
   410 			y = size.top;
   411 
   412 			/* Calculate current width and height of our window */
   413 			size.top = 0;
   414 			size.left = 0;
   415 			if ( SDL_PublicSurface != NULL ) {
   416 				size.bottom = SDL_PublicSurface->h;
   417 				size.right = SDL_PublicSurface->w;
   418 			} else {
   419 				size.bottom = 0;
   420 				size.right = 0;
   421 			}
   422 			AdjustWindowRect(&size, GetWindowLong(hwnd, GWL_STYLE),
   423 									FALSE);
   424 			width = size.right - size.left;
   425 			height = size.bottom - size.top;
   426 
   427 			/* Fix our size to the current size */
   428 			info = (MINMAXINFO *)lParam;
   429 			info->ptMaxSize.x = width;
   430 			info->ptMaxSize.y = height;
   431 			info->ptMaxPosition.x = x;
   432 			info->ptMaxPosition.y = y;
   433 			info->ptMinTrackSize.x = width;
   434 			info->ptMinTrackSize.y = height;
   435 			info->ptMaxTrackSize.x = width;
   436 			info->ptMaxTrackSize.y = height;
   437 		}
   438 		return(0);
   439 #endif /* WM_GETMINMAXINFO */
   440 
   441 		case WM_WINDOWPOSCHANGED: {
   442 			SDL_VideoDevice *this = current_video;
   443 			int w, h;
   444 
   445 			GetClientRect(SDL_Window, &SDL_bounds);
   446 			ClientToScreen(SDL_Window, (LPPOINT)&SDL_bounds);
   447 			ClientToScreen(SDL_Window, (LPPOINT)&SDL_bounds+1);
   448 			w = SDL_bounds.right-SDL_bounds.left;
   449 			h = SDL_bounds.bottom-SDL_bounds.top;
   450 			if ( this->input_grab != SDL_GRAB_OFF ) {
   451 				ClipCursor(&SDL_bounds);
   452 			}
   453 			if ( SDL_PublicSurface && 
   454 				(SDL_PublicSurface->flags & SDL_RESIZABLE) ) {
   455 				SDL_PrivateResize(w, h);
   456 			}
   457 			return(0);
   458 		}
   459 		break;
   460 
   461 		/* We need to set the cursor */
   462 		case WM_SETCURSOR: {
   463 			Uint16 hittest;
   464 
   465 			hittest = LOWORD(lParam);
   466 			if ( hittest == HTCLIENT ) {
   467 				SetCursor(SDL_hcursor);
   468 				return(TRUE);
   469 			}
   470 		}
   471 		break;
   472 
   473 		/* We are about to get palette focus! */
   474 		case WM_QUERYNEWPALETTE: {
   475 			WIN_RealizePalette(current_video);
   476 			return(TRUE);
   477 		}
   478 		break;
   479 
   480 		/* Another application changed the palette */
   481 		case WM_PALETTECHANGED: {
   482 			WIN_PaletteChanged(current_video, (HWND)wParam);
   483 		}
   484 		break;
   485 
   486 		/* We were occluded, refresh our display */
   487 		case WM_PAINT: {
   488 			HDC hdc;
   489 			PAINTSTRUCT ps;
   490 
   491 			hdc = BeginPaint(SDL_Window, &ps);
   492 			if ( current_video->screen &&
   493 			     !(current_video->screen->flags & SDL_OPENGL) ) {
   494 				WIN_WinPAINT(current_video, hdc);
   495 			}
   496 			EndPaint(SDL_Window, &ps);
   497 		}
   498 		return(0);
   499 
   500 		/* DJM: Send an expose event in this case */
   501 		case WM_ERASEBKGND: {
   502 			posted = SDL_PrivateExpose();
   503 		}
   504 		return(0);
   505 
   506 		case WM_CLOSE: {
   507 			if ( (posted = SDL_PrivateQuit()) )
   508 				PostQuitMessage(0);
   509 		}
   510 		return(0);
   511 
   512 		case WM_DESTROY: {
   513 			PostQuitMessage(0);
   514 		}
   515 		return(0);
   516 
   517 		default: {
   518 			/* Special handling by the video driver */
   519 			if (HandleMessage) {
   520 				return(HandleMessage(current_video,
   521 			                     hwnd, msg, wParam, lParam));
   522 			}
   523 		}
   524 		break;
   525 	}
   526 	return(DefWindowProc(hwnd, msg, wParam, lParam));
   527 }
   528 
   529 /* Allow the application handle to be stored and retrieved later */
   530 static void *SDL_handle = NULL;
   531 
   532 void SDL_SetModuleHandle(void *handle)
   533 {
   534 	SDL_handle = handle;
   535 }
   536 void *SDL_GetModuleHandle(void)
   537 {
   538 	void *handle;
   539 
   540 	if ( SDL_handle ) {
   541 		handle = SDL_handle;
   542 	} else {
   543 		/* Warning:
   544 		   If SDL is built as a DLL, this will return a handle to
   545 		   the DLL, not the application, and DirectInput may fail
   546 		   to initialize.
   547 		 */
   548 		handle = GetModuleHandle(NULL);
   549 	}
   550 	return(handle);
   551 }
   552 
   553 /* This allows the SDL_WINDOWID hack */
   554 const char *SDL_windowid = NULL;
   555 
   556 /* Register the class for this application -- exported for winmain.c */
   557 int SDL_RegisterApp(char *name, Uint32 style, void *hInst)
   558 {
   559 	static int initialized = 0;
   560 	WNDCLASS class;
   561 #ifdef WM_MOUSELEAVE
   562 	HMODULE handle;
   563 #endif
   564 
   565 	/* Only do this once... */
   566 	if ( initialized ) {
   567 		return(0);
   568 	}
   569 
   570 	/* This function needs to be passed the correct process handle
   571 	   by the application.
   572 	 */
   573 	if ( ! hInst ) {
   574 		hInst = SDL_GetModuleHandle();
   575 	}
   576 
   577 	/* Register the application class */
   578 	class.hCursor		= NULL;
   579 #ifdef _WIN32_WCE
   580     {
   581 	/* WinCE uses the UNICODE version */
   582 	int nLen = strlen(name)+1;
   583 	LPWSTR lpszW = alloca(nLen*2);
   584 	MultiByteToWideChar(CP_ACP, 0, name, -1, lpszW, nLen);
   585 	class.hIcon		= LoadImage(hInst, lpszW, IMAGE_ICON,
   586 	                                    0, 0, LR_DEFAULTCOLOR);
   587 	class.lpszMenuName	= NULL;
   588 	class.lpszClassName	= lpszW;
   589     }
   590 #else
   591 	class.hIcon		= LoadImage(hInst, name, IMAGE_ICON,
   592 	                                    0, 0, LR_DEFAULTCOLOR);
   593 	class.lpszMenuName	= "(none)";
   594 	class.lpszClassName	= name;
   595 #endif /* _WIN32_WCE */
   596 	class.hbrBackground	= NULL;
   597 	class.hInstance		= hInst;
   598 	class.style		= style;
   599 #ifdef HAVE_OPENGL
   600 	class.style		|= CS_OWNDC;
   601 #endif
   602 	class.lpfnWndProc	= WinMessage;
   603 	class.cbWndExtra	= 0;
   604 	class.cbClsExtra	= 0;
   605 	if ( ! RegisterClass(&class) ) {
   606 		SDL_SetError("Couldn't register application class");
   607 		return(-1);
   608 	}
   609 	SDL_Appname = name;
   610 	SDL_Instance = hInst;
   611 
   612 #ifdef WM_MOUSELEAVE
   613 	/* Get the version of TrackMouseEvent() we use */
   614 	_TrackMouseEvent = NULL;
   615 	handle = GetModuleHandle("USER32.DLL");
   616 	if ( handle ) {
   617 		_TrackMouseEvent = (BOOL (WINAPI *)(TRACKMOUSEEVENT *))GetProcAddress(handle, "TrackMouseEvent");
   618 	}
   619 	if ( _TrackMouseEvent == NULL ) {
   620 		_TrackMouseEvent = WIN_TrackMouseEvent;
   621 	}
   622 #endif /* WM_MOUSELEAVE */
   623 
   624 	/* Check for SDL_WINDOWID hack */
   625 	SDL_windowid = getenv("SDL_WINDOWID");
   626 
   627 	initialized = 1;
   628 	return(0);
   629 }
   630