Platform Input Focus Change

Reporter: RobertBColton  |  Status: open  |  Last Modified: June 25, 2020, 10:12:06 AM

This is something else I want to clean up after the mouse capture anomalies are fixed. We have made a total mess of handling the focus gain and lost events across different platforms, and seemingly performing the same redundant code. The origin of this had to deal with freezing on focus lost setting and clearing of the input state on focus lost. This can be tested in GM8.1 with ALT+TAB and I can confirm that GM always seems to clear the state of input when losing focus regardless of whether the freeze setting is enabled.

What we need to do is extract a common helper method that performs the generalized logic we want focus gain and lost events to apply. I also want to research how this is handled in other game engines and test GMS.

We can see Windows just has the original duplicate code and has literally inlined what our general input_initialize method does.

SDL was only handling the freeze setting.

game_window_focused = true;

xlib is repeating the same as Windows, except not fully handling focus lost clearing of the input?

It doesn't look like Cocoa handles focus at all.

RobertBColton  
So just testing with my example in #1828, I figured something out. We are almost certainly handling WM_SETFOCUS wrong somehow. With GM8.1 and GMSv1.4, although switching to another window with ALT+TAB clears the down state, if we leave the button held and switch back to the window to release, we should still see the mouse flash a release on the right of the first line. ENIGMA does not pick up this mouse release at all.

Another anomaly though is if we press the mouse in GM8.1, hold it and ALT+TAB, release the mouse and repress it, ALT+TAB back to the game, then release, then it will not be picked up by GM. That suggests GM8.1 is somehow remembering the mouse press started in its window.

I think what we are doing wrong is clearing the previous state when we don't need to be. I may need to expand my unit test to really be sure.

RobertBColton  

I've discovered that the infamous imgui is working on a fix to make it do what ENIGMA does on Windows or whatever.
ocornut/imgui#2062

Thanks to CMU, I also found that some Disney Panda 3D Software will actually poll the keyboard state on focus lost.
http://www.etc.cmu.edu/projects/tabletopia/abuse/out/Panda/html/winGraphicsWindow_8cxx-source.html

00958       case WM_KILLFOCUS: 
00959         // Record the current state of the keyboard when the focus is
00960         // lost, so we can check it for changes when we regain focus.
00961         GetKeyboardState(_keyboard_state);
00962         break;

Processing the input on focus lost is also something I see some other GitHub projects doing.
https://github.com/akinomyoga/contra/blob/28cadbc912917e2155b8b5dd3e770e8ff26bceac/src/twin/twin.cpp#L1258

      case WM_SETFOCUS:
        if (is_session_ready())
          this->process_input(key_focus);
        goto defproc;
      case WM_KILLFOCUS:
        this->cancel_ime_composition();
        this->process_input(key_blur);
        goto defproc;

It seems DOSBox likes to do this as well.
http://dosbox-x.com/doxygen/html/sdlmain_8cpp_source.html

04863                     /* Window has lost focus, pause the emulator.
04864                      * This is similar to what PauseDOSBox() does, but the exit criteria is different.
04865                      * Instead of waiting for the user to hit Alt-Break, we wait for the window to
04866                      * regain window or input focus.
04867                      */
04868                     bool paused = true;
04869                     SDL_Event ev;
04870 
04871                     GFX_SetTitle(-1,-1,-1,true);
04872                     KEYBOARD_ClrBuffer();

Please sign in to post comments, or you can view this issue on GitHub.