diff --git a/include/SDL_hints.h b/include/SDL_hints.h index 514580fa4..348c6d148 100644 --- a/include/SDL_hints.h +++ b/include/SDL_hints.h @@ -412,6 +412,19 @@ extern "C" { */ #define SDL_HINT_EVENT_LOGGING "SDL_EVENT_LOGGING" +/** + * \brief A variable controlling whether raising the window should be done more forcefully + * + * This variable can be set to the following values: + * "0" - No forcing (the default) + * "1" - Extra level of forcing + * + * At present, this is only an issue under MS Windows, which makes it nearly impossible to + * programmatically move a window to the foreground, for "security" reasons. See + * http://stackoverflow.com/a/34414846 for a discussion. + */ +#define SDL_HINT_FORCE_RAISEWINDOW "SDL_HINT_FORCE_RAISEWINDOW" + /** * \brief A variable controlling how 3D acceleration is used to accelerate the SDL screen surface. * diff --git a/src/video/windows/SDL_windowswindow.c b/src/video/windows/SDL_windowswindow.c index e392e5869..3776fb8c1 100644 --- a/src/video/windows/SDL_windowswindow.c +++ b/src/video/windows/SDL_windowswindow.c @@ -573,8 +573,38 @@ WIN_HideWindow(_THIS, SDL_Window * window) void WIN_RaiseWindow(_THIS, SDL_Window * window) { + /* If desired, raise the window more forcefully. + * Technique taken from http://stackoverflow.com/questions/916259/ . + * Specifically, http://stackoverflow.com/a/34414846 . + * + * The issue is that Microsoft has gone through a lot of trouble to make it + * nearly impossible to programmatically move a window to the foreground, + * for "security" reasons. Apparently, the following song-and-dance gets + * around their objections. */ + SDL_bool bForce = SDL_GetHintBoolean(SDL_HINT_FORCE_RAISEWINDOW, SDL_FALSE); + + HWND hCurWnd = NULL; + DWORD dwMyID = 0u; + DWORD dwCurID = 0u; + HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd; + if(bForce) + { + hCurWnd = GetForegroundWindow(); + dwMyID = GetCurrentThreadId(); + dwCurID = GetWindowThreadProcessId(hCurWnd, NULL); + ShowWindow(hwnd, SW_RESTORE); + AttachThreadInput(dwCurID, dwMyID, TRUE); + SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE); + SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE); + } SetForegroundWindow(hwnd); + if (bForce) + { + AttachThreadInput(dwCurID, dwMyID, FALSE); + SetFocus(hwnd); + SetActiveWindow(hwnd); + } } void