diff --git a/include/SDL_main.h b/include/SDL_main.h index df291a615..f1eb13100 100644 --- a/include/SDL_main.h +++ b/include/SDL_main.h @@ -64,7 +64,9 @@ extern "C" { #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 } diff --git a/src/main/win32/SDL_main.c b/src/main/win32/SDL_main.c index 7d28af488..3685861ef 100644 --- a/src/main/win32/SDL_main.c +++ b/src/main/win32/SDL_main.c @@ -199,12 +199,16 @@ int console_main(int argc, char *argv[]) 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 */ diff --git a/src/main/win32/exports/SDL.def b/src/main/win32/exports/SDL.def index 26d4fc7d4..717229c22 100644 --- a/src/main/win32/exports/SDL.def +++ b/src/main/win32/exports/SDL.def @@ -174,4 +174,6 @@ SDL_WM_IconifyWindow SDL_WM_ToggleFullScreen SDL_WM_GrabInput + SDL_SoftStretch SDL_RegisterApp + SDL_SetModuleHandle diff --git a/src/main/win32/exports/gendef.pl b/src/main/win32/exports/gendef.pl index 0fd83c4eb..1d2f554dd 100755 --- a/src/main/win32/exports/gendef.pl +++ b/src/main/win32/exports/gendef.pl @@ -20,3 +20,4 @@ while ( ($file = shift(@ARGV)) ) { } # Special exports not in the header files print "\tSDL_RegisterApp\n"; +print "\tSDL_SetModuleHandle\n"; diff --git a/src/video/wincommon/SDL_lowvideo.h b/src/video/wincommon/SDL_lowvideo.h index 18ff50abe..1ee87226c 100644 --- a/src/video/wincommon/SDL_lowvideo.h +++ b/src/video/wincommon/SDL_lowvideo.h @@ -87,4 +87,8 @@ extern int mouse_relative; /* 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 */ diff --git a/src/video/wincommon/SDL_sysevents.c b/src/video/wincommon/SDL_sysevents.c index 8c9f136b6..ea0a458cc 100644 --- a/src/video/wincommon/SDL_sysevents.c +++ b/src/video/wincommon/SDL_sysevents.c @@ -145,8 +145,10 @@ static void WIN_GetKeyboardState(void) #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 @@ static LONG CALLBACK WinMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara 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 @@ static LONG CALLBACK WinMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara } 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 @@ static LONG CALLBACK WinMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara 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 @@ int SDL_RegisterApp(char *name, Uint32 style, void *hInst) } /* 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 */ diff --git a/src/video/windib/SDL_dibevents.c b/src/video/windib/SDL_dibevents.c index 841a0cab5..678780101 100644 --- a/src/video/windib/SDL_dibevents.c +++ b/src/video/windib/SDL_dibevents.c @@ -54,6 +54,10 @@ static SDL_keysym *TranslateKey(UINT vkey, UINT scancode, SDL_keysym *keysym, in #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 @@ LONG 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 @@ int DIB_CreateWindow(_THIS) 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), diff --git a/src/video/windib/SDL_dibvideo.c b/src/video/windib/SDL_dibvideo.c index ae5546a01..10dccf618 100644 --- a/src/video/windib/SDL_dibvideo.c +++ b/src/video/windib/SDL_dibvideo.c @@ -574,7 +574,10 @@ SDL_Surface *DIB_SetVideoMode(_THIS, SDL_Surface *current, 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 ) { diff --git a/src/video/windx5/SDL_dx5events.c b/src/video/windx5/SDL_dx5events.c index 3514ede22..95ba16f32 100644 --- a/src/video/windx5/SDL_dx5events.c +++ b/src/video/windx5/SDL_dx5events.c @@ -59,6 +59,10 @@ static int mouse_pressed; 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 @@ LONG 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 @@ int DX5_CreateWindow(_THIS) 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),