Input focus not going to created window

I’m calling SDL_CreateWindow() from a console window. The window pops up in front of my console window, the display runs correctly, but I have to actually click in it with the mouse to give it keyboard focus before the SDL input will register any keypresses.

I’ve tried several different things, but I always have to manually click with the mouse:

  • SDL_HideWindow()/SDL_ShowWindow()
  • SDL_GetWindowWMinfo() followed by Win32 SetFocus(HWND)

Is there a way to force keyboard input that I’m missing here?

try Win32’s SetForegroundWindow:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms633539(v=vs.85).aspx
"Brings the thread that created the specified window into the foreground and activates the window. Keyboard input is directed to the window, and various visual cues are changed for the user."------------------------
Nate Fries

Thanks for the suggestion, Nate. Just gave it a go:

Code:

SDL_SysWMinfo info;
SDL_GetWindowWMInfo(m_pMainWnd, &info);
SetForegroundWindow(info.info.win.window);

No luck. The console window is behind the SDL window, but still maintains focus until I click in the SDL window. Besides the keys not responding in the SDL window, I know the console window has focus because the title bar dims when I click int he SDL window.

Well given what I know about SetForegroundWindow, this suggests you’re either not on Microsoft Windows (ReactOS or Wine, maybe?) or you’re creating the SDL Window on a different thread than the console window (typically the main thread).

If it’s the second, you’re violating a general portability rule about using SDL. Only create and manage windows from the main thread.
If it’s the first, this is a bug in the implementation of the Windows API and you can reasonably assume that SDL will work fine on Windows.

I use SDL with a console window quite regularly and I’ve never encountered this issue.------------------------
Nate Fries

I am on Windows 7, SDL 2.0.3. My application is single-threaded.

The issue seems to be that I’m taking input from stdin before creating the SDL window. If I don’t do that, input focus does go directly to the SDL window as you’d expect.

Of course I can work around it by not using stdin, but this is prototype code, and I’d still like to know why it’s happening/how to fix it to satisfy my own curiosity.

The code looks like this (stdcin and stdcout are conditional defines for unicode/multibyte character sets):

Code:

int _tmain(int argc, _TCHAR *argv[])
{
CGame game;
stdcout << _T("Select game ") << std::endl;
UINT iSel = 0;
stdcin >> iSel; // If I comment this out, focus goes to the SDL window when created
game.display.Init();
game.Run();
}

bool CDisplay::Init(int wndX, int wndY, int cx, int cy)
{
m_pMainWnd = SDL_CreateWindow(“Hello world”, wndX, wndY, cx, cy, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
if (m_pMainWnd == NULL)
… setup other surfaces
}

void CGame::Run()
{
while (flag)
{
cpu.GameLogic();
if (SDL_PollEvent(&sdlEvent))
{
switch (sdlEvent.type)
{
// Handle events we care about
}
}
display.Render();
}
}

Well, you learn something new every day. Turns out that the console window is not owned by the application’s main thread; how odd.

(can test via printf(“Thread ID for Console Window: %lu Window: %lu\n”, GetWindowThreadProcessId(GetConsoleWindow(), 0), GetCurrentThreadId()); )

The workaround is pretty simple (tested with MinGW-W64).
Just build a Windows-subsystem app, and include the following in _tmain before reading/writing:

Code:

/* create a basic console window and bind to process /
AllocConsole();
/
See: http://msdn.microsoft.com/en-us/library/windows/desktop/ms682075(v=vs.85).aspx */
freopen(“CONIN$”, “rt”, stdin);
freopen(“CONOUT$”, “wt”, stdout);
freopen(“CONOUT$”, “wt”, stderr);------------------------
Nate Fries

Oh, you’ll still need to call SetForegroundWindow (for some reason, SetFocus did not work).------------------------
Nate Fries

Fascinating! I’ve been writing Windows code since Windows 95 and am embarrassed to say I never knew that either. I guess it just never came up.

It turns out that the real reason SetForegroundWindow() wasn’t working is because SDL_GetWindowWMInfo() was failing! I didn’t even think to check that. How could a function just fail to give me a handle for a window it created?

Here’s how:

Code:

ERROR: SDL_GetWindowWMInfo failed: Application not compiled with SDL 2.0

Huh? I’m compiling with 2.0.3. I checked the modules in the debug window and it shows correctly:

Code:

SDL2.dll \Debug\SDL2.dll N/A N/A Exports loaded. 5 2, 0, 3, 0

Is there some #define that’s getting hidden? Is sdl.h finicky about where and when I must include it in the source?

Make sure you read the note hidden at the bottom of the docs for
SDL_GetWindowWMInfo.

"The info structure must be initialized with the SDL version, and is then
filled in with information about the given window, as shown in the Code
Example https://wiki.libsdl.org/SDL_GetWindowWMInfo#Code_Examples."On Mon, Mar 24, 2014 at 10:49 AM, manskirtbrew wrote:

Fascinating! I’ve been writing Windows code since Windows 95 and am
embarrassed to say I never knew that either. I guess it just never came up.

It turns out that the real reason SetForegroundWindow() wasn’t working is
because SDL_GetWindowWMInfo() was failing! I didn’t even think to check
that. How could a function just fail to give me a handle for a window it
created?

Here’s how:

Code:

ERROR: SDL_GetWindowWMInfo failed: Application not compiled with SDL 2.0

Huh? I’m compiling with 2.0.3. I checked the modules in the debug window
and it shows correctly:

Code:

SDL2.dll \Debug\SDL2.dll N/A N/A Exports loaded. 5 2, 0, 3,
0

Is there some #define that’s getting hidden? Is sdl.h finicky about where
and when I must include it in the source?


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

Andre D wrote:

Make sure you read the note hidden at the bottom of the docs for?SDL_GetWindowWMInfo.

Thanks Andre, I literally just found it and was coming here to post about it. I completely missed it when I read the wiki the first time.

It now works correctly, even in normal console mode. Apologies for the snipe hunt, but I appreciate all the good info in this thread.