Skip to content

Commit

Permalink
Clear pressed keys after loosing input focus (ocornut#3532)
Browse files Browse the repository at this point in the history
  • Loading branch information
thedmd committed Aug 2, 2021
1 parent f99fe72 commit 5750de5
Show file tree
Hide file tree
Showing 8 changed files with 66 additions and 2 deletions.
8 changes: 8 additions & 0 deletions backends/imgui_impl_allegro5.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,14 @@ bool ImGui_ImplAllegro5_ProcessEvent(ALLEGRO_EVENT* ev)
if (ev->keyboard.display == bd->Display)
io.KeysDown[ev->keyboard.keycode] = (ev->type == ALLEGRO_EVENT_KEY_DOWN);
return true;
case ALLEGRO_EVENT_DISPLAY_SWITCH_OUT:
if (ev->display.source == bd->Display)
io.AddFocusEvent(false);
return false; // don't consume event
case ALLEGRO_EVENT_DISPLAY_SWITCH_IN:
if (ev->display.source == bd->Display)
io.AddFocusEvent(true);
return false; // don't consume event
}
return false;
}
Expand Down
14 changes: 14 additions & 0 deletions backends/imgui_impl_glfw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ struct ImGui_ImplGlfw_Data
bool InstalledCallbacks;

// Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any.
GLFWwindowfocusfun PrevUserCallbackWindowFocus;
GLFWcursorenterfun PrevUserCallbackCursorEnter;
GLFWmousebuttonfun PrevUserCallbackMousebutton;
GLFWscrollfun PrevUserCallbackScroll;
Expand Down Expand Up @@ -160,6 +161,16 @@ void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int key, int scancode, int a
#endif
}

void ImGui_ImplGlfw_WindowFocusCallback(GLFWwindow* window, int focused)
{
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
if (bd->PrevUserCallbackWindowFocus != NULL)
bd->PrevUserCallbackWindowFocus(window, focused);

ImGuiIO& io = ImGui::GetIO();
io.AddFocusEvent(focused != 0);
}

void ImGui_ImplGlfw_CursorEnterCallback(GLFWwindow* window, int entered)
{
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
Expand Down Expand Up @@ -256,6 +267,7 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
glfwSetErrorCallback(prev_error_callback);

// Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any.
bd->PrevUserCallbackWindowFocus = NULL;
bd->PrevUserCallbackMousebutton = NULL;
bd->PrevUserCallbackScroll = NULL;
bd->PrevUserCallbackKey = NULL;
Expand All @@ -264,6 +276,7 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
if (install_callbacks)
{
bd->InstalledCallbacks = true;
bd->PrevUserCallbackWindowFocus = glfwSetWindowFocusCallback(window, ImGui_ImplGlfw_WindowFocusCallback);
bd->PrevUserCallbackCursorEnter = glfwSetCursorEnterCallback(window, ImGui_ImplGlfw_CursorEnterCallback);
bd->PrevUserCallbackMousebutton = glfwSetMouseButtonCallback(window, ImGui_ImplGlfw_MouseButtonCallback);
bd->PrevUserCallbackScroll = glfwSetScrollCallback(window, ImGui_ImplGlfw_ScrollCallback);
Expand Down Expand Up @@ -298,6 +311,7 @@ void ImGui_ImplGlfw_Shutdown()

if (bd->InstalledCallbacks)
{
glfwSetWindowFocusCallback(bd->Window, bd->PrevUserCallbackWindowFocus);
glfwSetCursorEnterCallback(bd->Window, bd->PrevUserCallbackCursorEnter);
glfwSetMouseButtonCallback(bd->Window, bd->PrevUserCallbackMousebutton);
glfwSetScrollCallback(bd->Window, bd->PrevUserCallbackScroll);
Expand Down
1 change: 1 addition & 0 deletions backends/imgui_impl_glfw.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ IMGUI_IMPL_API void ImGui_ImplGlfw_NewFrame();
// GLFW callbacks
// - When calling Init with 'install_callbacks=true': GLFW callbacks will be installed for you. They will call user's previously installed callbacks, if any.
// - When calling Init with 'install_callbacks=false': GLFW callbacks won't be installed. You will need to call those function yourself from your own GLFW callbacks.
IMGUI_IMPL_API void ImGui_ImplGlfw_WindowFocusCallback(GLFWwindow* window, int focused);
IMGUI_IMPL_API void ImGui_ImplGlfw_CursorEnterCallback(GLFWwindow* window, int entered);
IMGUI_IMPL_API void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods);
IMGUI_IMPL_API void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset);
Expand Down
14 changes: 14 additions & 0 deletions backends/imgui_impl_osx.mm
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,24 @@ static void resetKeys()

@interface ImFocusObserver : NSObject

- (void)onApplicationBecomeActive:(NSNotification*)aNotification;
- (void)onApplicationBecomeInactive:(NSNotification*)aNotification;

@end

@implementation ImFocusObserver

- (void)onApplicationBecomeActive:(NSNotification*)aNotification
{
ImGuiIO& io = ImGui::GetIO();
io.AddFocusEvent(true);
}

- (void)onApplicationBecomeInactive:(NSNotification*)aNotification
{
ImGuiIO& io = ImGui::GetIO();
io.AddFocusEvent(false);

// Unfocused applications do not receive input events, therefore we must manually
// release any pressed keys when application loses focus, otherwise they would remain
// stuck in a pressed state. https://github.com/ocornut/imgui/issues/3832
Expand Down Expand Up @@ -155,6 +165,10 @@ bool ImGui_ImplOSX_Init()
};

g_FocusObserver = [[ImFocusObserver alloc] init];
[[NSNotificationCenter defaultCenter] addObserver:g_FocusObserver
selector:@selector(onApplicationBecomeActive:)
name:NSApplicationDidBecomeActiveNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:g_FocusObserver
selector:@selector(onApplicationBecomeInactive:)
name:NSApplicationDidResignActiveNotification
Expand Down
9 changes: 9 additions & 0 deletions backends/imgui_impl_sdl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,15 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event)
#endif
return true;
}
case SDL_WINDOWEVENT:
{
if (event->window.event == SDL_WINDOWEVENT_FOCUS_GAINED)
io.AddFocusEvent(true);
else if (event->window.event == SDL_WINDOWEVENT_FOCUS_LOST)
io.AddFocusEvent(false);

return false; // don't consume event
}
}
return false;
}
Expand Down
6 changes: 4 additions & 2 deletions backends/imgui_impl_win32.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -431,9 +431,11 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA
io.KeyAlt = down;
return 0;
}
case WM_SETFOCUS:
io.AddFocusEvent(true);
return 0;
case WM_KILLFOCUS:
memset(io.KeysDown, 0, sizeof(io.KeysDown));
io.KeyCtrl = io.KeyShift = io.KeyAlt = io.KeySuper = false;
io.AddFocusEvent(false);
return 0;
case WM_CHAR:
// You can also use ToAscii()+GetKeyboardState() to retrieve characters.
Expand Down
15 changes: 15 additions & 0 deletions imgui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1180,6 +1180,21 @@ void ImGuiIO::ClearInputCharacters()
InputQueueCharacters.resize(0);
}

void ImGuiIO::AddFocusEvent(bool gain)
{
if (!gain)
{
// Reset pressed buttons when focus is lost
memset(KeysDown, 0, sizeof(KeysDown));
for (int n = 0; n < IM_ARRAYSIZE(KeysDownDuration); n++)
KeysDownDuration[n] = KeysDownDurationPrev[n] = -1.0f;
KeyCtrl = KeyShift = KeyAlt = KeySuper = false;
KeyMods = 0;
for (int n = 0; n < IM_ARRAYSIZE(NavInputsDownDuration); n++)
NavInputsDownDuration[n] = NavInputsDownDurationPrev[n] = -1.0f;
}
}

//-----------------------------------------------------------------------------
// [SECTION] MISC HELPERS/UTILITIES (Geometry functions)
//-----------------------------------------------------------------------------
Expand Down
1 change: 1 addition & 0 deletions imgui.h
Original file line number Diff line number Diff line change
Expand Up @@ -1869,6 +1869,7 @@ struct ImGuiIO
IMGUI_API void AddInputCharacterUTF16(ImWchar16 c); // Queue new character input from an UTF-16 character, it can be a surrogate
IMGUI_API void AddInputCharactersUTF8(const char* str); // Queue new characters input from an UTF-8 string
IMGUI_API void ClearInputCharacters(); // Clear the text input buffer manually
IMGUI_API void AddFocusEvent(bool gain); // Notifies ImGui when underlying windows lose or gain input focus

//------------------------------------------------------------------
// Output - Updated by NewFrame() or EndFrame()/Render()
Expand Down

0 comments on commit 5750de5

Please sign in to comment.