Applied David MacCormack's patch to fix SDL_WINDOWID on Windows,
authorSam Lantinga <slouken@libsdl.org>
Thu, 09 Aug 2001 12:21:32 +0000
changeset 145 29a638dc26db
parent 144 1cfa4282f2eb
child 146 ddd322dba625
Applied David MacCormack's patch to fix SDL_WINDOWID on Windows, and added a function to cache the application handle so DirectInput still works properly.
include/SDL_main.h
src/main/win32/SDL_main.c
src/main/win32/exports/SDL.def
src/main/win32/exports/gendef.pl
src/video/wincommon/SDL_lowvideo.h
src/video/wincommon/SDL_sysevents.c
src/video/windib/SDL_dibevents.c
src/video/windib/SDL_dibvideo.c
src/video/windx5/SDL_dx5events.c
--- a/include/SDL_main.h	Thu Aug 09 06:14:06 2001 +0000
+++ b/include/SDL_main.h	Thu Aug 09 12:21:32 2001 +0000
@@ -64,7 +64,9 @@
 #endif
 
 /* This should be called from your WinMain() function, if any */
-extern DECLSPEC int SDL_RegisterApp(char *name, Uint32 style, void *hInst);
+extern DECLSPEC void SDL_SetModuleHandle(HMODULE hInst);
+/* This can also be called, but is no longer necessary */
+extern DECLSPEC int SDL_RegisterApp(char *name, Uint32 style, HMODULE hInst);
 
 #ifdef __cplusplus
 }
--- a/src/main/win32/SDL_main.c	Thu Aug 09 06:14:06 2001 +0000
+++ b/src/main/win32/SDL_main.c	Thu Aug 09 12:21:32 2001 +0000
@@ -199,12 +199,16 @@
 	atexit(SDL_Quit);
 
 #ifndef DISABLE_VIDEO
-	/* Create and register our class */
+	/* Create and register our class *
+      DJM: If we do this here, the user nevers gets a chance to
+      putenv(SDL_WINDOWID).  This is already called later by
+      the (DIB|DX5)_CreateWindow function, so it should be
+      safe to comment it out here.
 	if ( SDL_RegisterApp(appname, CS_BYTEALIGNCLIENT, 
 	                     GetModuleHandle(NULL)) < 0 ) {
 		ShowError("WinMain() error", SDL_GetError());
 		exit(1);
-	}
+	}*/
 #endif /* !DISABLE_VIDEO */
 
 	/* Run the application main() code */
--- a/src/main/win32/exports/SDL.def	Thu Aug 09 06:14:06 2001 +0000
+++ b/src/main/win32/exports/SDL.def	Thu Aug 09 12:21:32 2001 +0000
@@ -174,4 +174,6 @@
 	SDL_WM_IconifyWindow
 	SDL_WM_ToggleFullScreen
 	SDL_WM_GrabInput
+	SDL_SoftStretch
 	SDL_RegisterApp
+	SDL_SetModuleHandle
--- a/src/main/win32/exports/gendef.pl	Thu Aug 09 06:14:06 2001 +0000
+++ b/src/main/win32/exports/gendef.pl	Thu Aug 09 12:21:32 2001 +0000
@@ -20,3 +20,4 @@
 }
 # Special exports not in the header files
 print "\tSDL_RegisterApp\n";
+print "\tSDL_SetModuleHandle\n";
--- a/src/video/wincommon/SDL_lowvideo.h	Thu Aug 09 06:14:06 2001 +0000
+++ b/src/video/wincommon/SDL_lowvideo.h	Thu Aug 09 12:21:32 2001 +0000
@@ -87,4 +87,8 @@
 /* This is really from SDL_dx5audio.c */
 extern void DX5_SoundFocus(HWND window);
 
+/* DJM: This is really from SDL_sysevents.c, we need it in
+   GDL_CreateWindow as well */
+LONG CALLBACK WinMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
 #endif /* SDL_lowvideo_h */
--- a/src/video/wincommon/SDL_sysevents.c	Thu Aug 09 06:14:06 2001 +0000
+++ b/src/video/wincommon/SDL_sysevents.c	Thu Aug 09 12:21:32 2001 +0000
@@ -145,8 +145,10 @@
 #endif /* !NO_GETKEYBOARDSTATE */
 }
 
-/* The main Win32 event handler */
-static LONG CALLBACK WinMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+/* The main Win32 event handler
+DJM: This is no longer static as (DX5/DIB)_CreateWindow needs it
+*/
+LONG CALLBACK WinMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
 {
 	SDL_VideoDevice *this = current_video;
 	static int mouse_pressed = 0;
@@ -265,6 +267,13 @@
 				Sint16 x, y;
 				Uint8 button, state;
 
+				/* 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);
+
 				/* Figure out which button to use */
 				switch (msg) {
 					case WM_LBUTTONDOWN:
@@ -465,10 +474,11 @@
 		}
 		return(0);
 
+		/* DJM: Send an expose event in this case */
 		case WM_ERASEBKGND: {
-			/* Just do nothing */ ;
+			posted = SDL_PrivateExpose();
 		}
-		return(1);
+		return(0);
 
 		case WM_CLOSE: {
 			if ( (posted = SDL_PrivateQuit()) )
@@ -493,11 +503,35 @@
 	return(DefWindowProc(hwnd, msg, wParam, lParam));
 }
 
+/* Allow the application handle to be stored and retrieved later */
+static HMODULE SDL_handle = NULL;
+
+void SDL_SetModuleHandle(HMODULE handle)
+{
+	SDL_handle = handle;
+}
+HMODULE SDL_GetModuleHandle(void)
+{
+	void *handle;
+
+	if ( SDL_handle ) {
+		handle = SDL_handle;
+	} else {
+		/* Warning:
+		   If SDL is built as a DLL, this will return a handle to
+		   the DLL, not the application, and DirectInput may fail
+		   to initialize.
+		 */
+		handle = GetModuleHandle(NULL);
+	}
+	return(handle);
+}
+
 /* This allows the SDL_WINDOWID hack */
 const char *SDL_windowid = NULL;
 
 /* Register the class for this application -- exported for winmain.c */
-int SDL_RegisterApp(char *name, Uint32 style, void *hInst)
+int SDL_RegisterApp(char *name, Uint32 style, HMODULE hInst)
 {
 	static int initialized = 0;
 	WNDCLASS class;
@@ -511,12 +545,10 @@
 	}
 
 	/* This function needs to be passed the correct process handle
-	   by the application.  The following call just returns a handle
-	   to the SDL DLL, which is useless for our purposes and causes
-	   DirectInput to fail to initialize.
+	   by the application.
 	 */
 	if ( ! hInst ) {
-		hInst = GetModuleHandle(NULL);
+		hInst = SDL_GetModuleHandle();
 	}
 
 	/* Register the application class */
--- a/src/video/windib/SDL_dibevents.c	Thu Aug 09 06:14:06 2001 +0000
+++ b/src/video/windib/SDL_dibevents.c	Thu Aug 09 12:21:32 2001 +0000
@@ -54,6 +54,10 @@
 #define REPEATED_KEYMASK	(1<<30)
 #define EXTENDED_KEYMASK	(1<<24)
 
+/* DJM: If the user setup the window for us, we want to save his window proc,
+   and give him a chance to handle some messages. */
+static WNDPROC userWindowProc = NULL;
+
 /* The main Win32 event handler */
 LONG
  DIB_HandleMessage(_THIS, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
@@ -150,6 +154,13 @@
 				wmmsg.wParam = wParam;
 				wmmsg.lParam = lParam;
 				posted = SDL_PrivateSysWMEvent(&wmmsg);
+
+			/* DJM: If the user isn't watching for private
+				messages in her SDL event loop, then pass it
+				along to any win32 specific window proc.
+			 */
+			} else if (userWindowProc) {
+				return userWindowProc(hwnd, msg, wParam, lParam);
 			}
 		}
 		break;
@@ -339,6 +350,14 @@
 	SDL_RegisterApp("SDL_app", CS_BYTEALIGNCLIENT, 0);
 	if ( SDL_windowid ) {
 		SDL_Window = (HWND)strtol(SDL_windowid, NULL, 0);
+
+      /* DJM: we want all event's for the user specified
+         window to be handled by SDL.
+       */
+      if (SDL_Window) {
+         userWindowProc = (WNDPROC)GetWindowLong(SDL_Window, GWL_WNDPROC);
+         SetWindowLong(SDL_Window, GWL_WNDPROC, (LONG)WinMessage);
+      }
 	} else {
 		SDL_Window = CreateWindow(SDL_Appname, SDL_Appname,
                         (WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX),
--- a/src/video/windib/SDL_dibvideo.c	Thu Aug 09 06:14:06 2001 +0000
+++ b/src/video/windib/SDL_dibvideo.c	Thu Aug 09 12:21:32 2001 +0000
@@ -574,7 +574,10 @@
 		if (IsZoomed(SDL_Window)) style |= WS_MAXIMIZE;
 #endif
 	}
-	SetWindowLong(SDL_Window, GWL_STYLE, style);
+
+   /* DJM: Don't piss of anyone who has setup his own window */
+   if (!SDL_windowid)
+	   SetWindowLong(SDL_Window, GWL_STYLE, style);
 
 	/* Delete the old bitmap if necessary */
 	if ( screen_bmp != NULL ) {
--- a/src/video/windx5/SDL_dx5events.c	Thu Aug 09 06:14:06 2001 +0000
+++ b/src/video/windx5/SDL_dx5events.c	Thu Aug 09 12:21:32 2001 +0000
@@ -59,6 +59,10 @@
 static SDLKey DIK_keymap[256];
 static SDL_keysym *TranslateKey(UINT scancode, SDL_keysym *keysym, int pressed);
 
+/* DJM: If the user setup the window for us, we want to save his window proc,
+   and give him a chance to handle some messages. */
+static WNDPROC userWindowProc = NULL;
+
 /* Convert a DirectInput return code to a text message */
 static void SetDIerror(char *function, int code)
 {
@@ -509,7 +513,14 @@
 				wmmsg.wParam = wParam;
 				wmmsg.lParam = lParam;
 				posted = SDL_PrivateSysWMEvent(&wmmsg);
-			}
+
+         /* DJM: If the user isn't watching for private messages in her
+            SDL event loop, then pass it along to any win32 specific
+            window proc.
+          */
+         } else if (userWindowProc) {
+            return userWindowProc(hwnd, msg, wParam, lParam);
+         }
 		}
 		break;
 	}
@@ -764,6 +775,14 @@
 	SDL_RegisterApp("SDL_app", CS_BYTEALIGNCLIENT, 0);
 	if ( SDL_windowid ) {
 		SDL_Window = (HWND)strtol(SDL_windowid, NULL, 0);
+
+      /* DJM: we want all event's for the user specified
+         window to be handled by SDL.
+       */
+      if (SDL_Window) {
+         userWindowProc = (WNDPROC)GetWindowLong(SDL_Window, GWL_WNDPROC);
+         SetWindowLong(SDL_Window, GWL_WNDPROC, (LONG)WinMessage);
+      }
 	} else {
 		SDL_Window = CreateWindow(SDL_Appname, SDL_Appname,
                         (WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX),