Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clear pressed keys after loosing input focus (#3532) #4388

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions backends/imgui_impl_allegro5.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,19 @@ 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);
#if defined(ALLEGRO_UNSTABLE)
al_clear_keyboard_state(bd->Display);
#endif
}
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