From 23487eb2c04c632a07eef7de483fea40cc3b4e0e Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 31 Dec 2012 09:30:15 -0800 Subject: [PATCH] Improvements from Alfred: - Added new SDL_HINT_ALLOW_TOPMOST hint, when set to "0" then never set the topmost bit on a window. Useful when debugging fullscreen issues. - fixed crash in windows joystick scanning if we failed to load the xinput dll - added support for SDL_WINDOW_FULLSCREEN_DESKTOP under windows - synthesize relative mouse movements if directinput fails to send relative moves, happens under virtual box. --- include/SDL_hints.h | 12 ++++++ src/joystick/windows/SDL_dxjoystick.c | 34 +++++++-------- src/render/direct3d/SDL_render_d3d.c | 5 +++ src/video/windows/SDL_windowsevents.c | 20 +++++++++ src/video/windows/SDL_windowswindow.c | 59 +++++++++++++++++++++------ 5 files changed, 102 insertions(+), 28 deletions(-) diff --git a/include/SDL_hints.h b/include/SDL_hints.h index c81a0954b..6352bad77 100644 --- a/include/SDL_hints.h +++ b/include/SDL_hints.h @@ -204,6 +204,18 @@ extern "C" { #define SDL_HINT_GAMECONTROLLERCONFIG "SDL_GAMECONTROLLERCONFIG" +/** + * \brief If set to 0 then never set the top most bit on a SDL Window, even if the video mode expects it. + * This is a debugging aid for developers and not expected to be used by end users. The default is "1" + * + * This variable can be set to the following values: + * "0" - don't allow topmost + * "1" - allow topmost + */ +#define SDL_HINT_ALLOW_TOPMOST "SDL_ALLOW_TOPMOST" + + + /** * \brief An enumeration of hint priorities */ diff --git a/src/joystick/windows/SDL_dxjoystick.c b/src/joystick/windows/SDL_dxjoystick.c index f63bdc41d..d6ed69afa 100644 --- a/src/joystick/windows/SDL_dxjoystick.c +++ b/src/joystick/windows/SDL_dxjoystick.c @@ -569,28 +569,30 @@ SDL_JoystickThread(void *_data) } } - // scan for any change in XInput devices - for ( userId = 0; userId < 4; userId++ ) + if ( XINPUTGETCAPABILITIES ) { - XINPUT_CAPABILITIES capabilities; - DWORD result; + // scan for any change in XInput devices + for ( userId = 0; userId < 4; userId++ ) + { + XINPUT_CAPABILITIES capabilities; + DWORD result; - if ( bOpenedXInputDevices[userId] == SDL_TRUE ) - nCurrentOpenedXInputDevices++; + if ( bOpenedXInputDevices[userId] == SDL_TRUE ) + nCurrentOpenedXInputDevices++; - result = XINPUTGETCAPABILITIES( userId, XINPUT_FLAG_GAMEPAD, &capabilities ); - if ( result == ERROR_SUCCESS ) - { - bOpenedXInputDevices[userId] = SDL_TRUE; - nNewOpenedXInputDevices++; - } - else - { - bOpenedXInputDevices[userId] = SDL_FALSE; + result = XINPUTGETCAPABILITIES( userId, XINPUT_FLAG_GAMEPAD, &capabilities ); + if ( result == ERROR_SUCCESS ) + { + bOpenedXInputDevices[userId] = SDL_TRUE; + nNewOpenedXInputDevices++; + } + else + { + bOpenedXInputDevices[userId] = SDL_FALSE; + } } } - if ( s_pKnownJoystickGUIDs && ( s_bWindowsDeviceChanged || nNewOpenedXInputDevices != nCurrentOpenedXInputDevices ) ) { SDL_Delay( 300 ); // wait for direct input to find out about this device diff --git a/src/render/direct3d/SDL_render_d3d.c b/src/render/direct3d/SDL_render_d3d.c index 0ebb7474f..c86dc6cfc 100644 --- a/src/render/direct3d/SDL_render_d3d.c +++ b/src/render/direct3d/SDL_render_d3d.c @@ -538,9 +538,14 @@ D3D_CreateRenderer(SDL_Window * window, Uint32 flags) pparams.SwapEffect = D3DSWAPEFFECT_DISCARD; if (window_flags & SDL_WINDOW_FULLSCREEN) { + if ( ( window_flags & SDL_WINDOW_FULLSCREEN_DESKTOP ) == SDL_WINDOW_FULLSCREEN_DESKTOP ) { + pparams.Windowed = TRUE; + pparams.FullScreen_RefreshRateInHz = 0; + } else { pparams.Windowed = FALSE; pparams.FullScreen_RefreshRateInHz = fullscreen_mode.refresh_rate; + } } else { pparams.Windowed = TRUE; pparams.FullScreen_RefreshRateInHz = 0; diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index 0193062e2..9cd2fb144 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -221,6 +221,10 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) HRAWINPUT hRawInput = (HRAWINPUT)lParam; RAWINPUT inp; UINT size = sizeof(inp); + + if(!SDL_GetMouse()->relative_mode) + break; + GetRawInputData(hRawInput, RID_INPUT, &inp, &size, sizeof(RAWINPUTHEADER)); /* Mouse data */ @@ -229,8 +233,24 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) RAWMOUSE* mouse = &inp.data.mouse; if((mouse->usFlags & 0x01) == MOUSE_MOVE_RELATIVE) + { SDL_SendMouseMotion(data->window, 1, (int)mouse->lLastX, (int)mouse->lLastY); + } + else + { + // synthesize relative moves from the abs position + static SDL_Point initialMousePoint; + if ( initialMousePoint.x == 0 && initialMousePoint.y == 0 ) + { + initialMousePoint.x = mouse->lLastX; + initialMousePoint.y = mouse->lLastY; + } + + SDL_SendMouseMotion(data->window, 1, (int)(mouse->lLastX-initialMousePoint.x), (int)(mouse->lLastY-initialMousePoint.y) ); + initialMousePoint.x = mouse->lLastX; + initialMousePoint.y = mouse->lLastY; + } } break; } diff --git a/src/video/windows/SDL_windowswindow.c b/src/video/windows/SDL_windowswindow.c index bb6a786a9..2e29061ed 100644 --- a/src/video/windows/SDL_windowswindow.c +++ b/src/video/windows/SDL_windowswindow.c @@ -28,6 +28,7 @@ #include "SDL_windowsvideo.h" #include "SDL_windowswindow.h" +#include "SDL_hints.h" /* Dropfile support */ #include @@ -73,6 +74,22 @@ GetWindowStyle(SDL_Window * window) return style; } +static SDL_bool +ShouldAllowTopMost() +{ + const char *hint; + + /* If the user has specified a software renderer we can't use a + texture framebuffer, or renderer creation will go recursive. + */ + hint = SDL_GetHint(SDL_HINT_ALLOW_TOPMOST); + if (hint && hint[0] == '0' ) { + return SDL_FALSE; + } + + return SDL_TRUE; +} + static int SetupWindowData(_THIS, SDL_Window * window, HWND hwnd, SDL_bool created) { @@ -354,8 +371,8 @@ WIN_SetWindowPositionInternal(_THIS, SDL_Window * window, UINT flags) int w, h; /* Figure out what the window area will be */ - if (window->flags & SDL_WINDOW_FULLSCREEN) { - top = HWND_TOPMOST; + if ( ShouldAllowTopMost() && (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_INPUT_FOCUS)) == (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_INPUT_FOCUS )) { + top = HWND_TOPMOST; } else { top = HWND_NOTOPMOST; } @@ -406,11 +423,11 @@ WIN_RaiseWindow(_THIS, SDL_Window * window) HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd; HWND top; - if (window->flags & SDL_WINDOW_FULLSCREEN) { - top = HWND_TOPMOST; - } else { - top = HWND_NOTOPMOST; - } + if ( ShouldAllowTopMost() && (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_INPUT_FOCUS)) == (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_INPUT_FOCUS )) { + top = HWND_TOPMOST; + } else { + top = HWND_NOTOPMOST; + } SetWindowPos(hwnd, top, 0, 0, 0, 0, (SWP_NOMOVE | SWP_NOSIZE)); } @@ -467,11 +484,12 @@ WIN_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, int x, y; int w, h; - if (fullscreen) { - top = HWND_TOPMOST; - } else { - top = HWND_NOTOPMOST; - } + if ( ShouldAllowTopMost() && (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_INPUT_FOCUS)) == (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_INPUT_FOCUS )) { + top = HWND_TOPMOST; + } else { + top = HWND_NOTOPMOST; + } + style = GetWindowLong(hwnd, GWL_STYLE); style &= ~STYLE_MASK; style |= GetWindowStyle(window); @@ -551,6 +569,23 @@ WIN_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed) } else { ClipCursor(NULL); } + + if ( window->flags & SDL_WINDOW_FULLSCREEN ) + { + HWND top; + SDL_WindowData *data = (SDL_WindowData *) window->driverdata; + HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd; + UINT flags = SWP_NOMOVE | SWP_NOSIZE; + + if ( ShouldAllowTopMost() && (window->flags & SDL_WINDOW_INPUT_FOCUS ) ) { + top = HWND_TOPMOST; + } else { + top = HWND_NOTOPMOST; + flags |= SWP_NOZORDER; + } + + SetWindowPos(hwnd, top, 0, 0, 0, 0, flags); + } } void