From 733c4f553c56bb87b3328f2ee0bf2473f76ed8b7 Mon Sep 17 00:00:00 2001 From: rokups Date: Mon, 19 Apr 2021 13:47:31 +0300 Subject: [PATCH] Backends: OSX: Fix keys remaining stuck in pressed state when CMD-tabbing to a different application. (#3832) --- backends/imgui_impl_osx.mm | 71 +++++++++++++++++++++++++++----------- 1 file changed, 51 insertions(+), 20 deletions(-) diff --git a/backends/imgui_impl_osx.mm b/backends/imgui_impl_osx.mm index 62bba02398e20..bb02b6b71a48d 100644 --- a/backends/imgui_impl_osx.mm +++ b/backends/imgui_impl_osx.mm @@ -18,6 +18,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2021-04-19: Inputs: Added a fix for keys remaining stuck in pressed state when CMD-tabbing into different application. // 2021-01-27: Inputs: Added a fix for mouse position not being reported when mouse buttons other than left one are down. // 2020-10-28: Inputs: Added a fix for handling keypad-enter key. // 2020-05-25: Inputs: Added a fix for missing trackpad clicks when done with "soft tap". @@ -30,12 +31,15 @@ // 2018-11-30: Misc: Setting up io.BackendPlatformName so it can be displayed in the About Window. // 2018-07-07: Initial version. +@class ImFocusObserver; + // Data static CFAbsoluteTime g_Time = 0.0; static NSCursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = {}; static bool g_MouseCursorHidden = false; static bool g_MouseJustPressed[ImGuiMouseButton_COUNT] = {}; static bool g_MouseDown[ImGuiMouseButton_COUNT] = {}; +static ImFocusObserver* g_FocusObserver = NULL; // Undocumented methods for creating cursors. @interface NSCursor() @@ -45,6 +49,46 @@ + (id)_windowResizeNorthSouthCursor; + (id)_windowResizeEastWestCursor; @end +// Utility functions +static int mapCharacterToKey(int c) +{ + if (c >= 'a' && c <= 'z') + return c - 'a' + 'A'; + if (c == 25) // SHIFT+TAB -> TAB + return 9; + if (c >= 0 && c < 256) + return c; + if (c >= 0xF700 && c < 0xF700 + 256) + return c - 0xF700 + 256; + return -1; +} + +static void resetKeys() +{ + ImGuiIO& io = ImGui::GetIO(); + memset(io.KeysDown, 0, sizeof(io.KeysDown)); + io.KeyCtrl = io.KeyShift = io.KeyAlt = io.KeySuper = false; +} + + +@interface ImFocusObserver : NSObject + +- (void)onApplicationBecomeInactive:(NSNotification*)aNotification; + +@end + +@implementation ImFocusObserver + +- (void)onApplicationBecomeInactive:(NSNotification*)aNotification +{ + // 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 + resetKeys(); +} + +@end + // Functions bool ImGui_ImplOSX_Init() { @@ -122,12 +166,19 @@ bool ImGui_ImplOSX_Init() strcpy(s_clipboard.Data, string_c); return s_clipboard.Data; }; + + g_FocusObserver = [[ImFocusObserver alloc] init]; + [[NSNotificationCenter defaultCenter] addObserver:g_FocusObserver + selector:@selector(onApplicationBecomeInactive:) + name:NSApplicationDidResignActiveNotification + object:nil]; return true; } void ImGui_ImplOSX_Shutdown() { + g_FocusObserver = NULL; } static void ImGui_ImplOSX_UpdateMouseCursorAndButtons() @@ -187,26 +238,6 @@ void ImGui_ImplOSX_NewFrame(NSView* view) ImGui_ImplOSX_UpdateMouseCursorAndButtons(); } -static int mapCharacterToKey(int c) -{ - if (c >= 'a' && c <= 'z') - return c - 'a' + 'A'; - if (c == 25) // SHIFT+TAB -> TAB - return 9; - if (c >= 0 && c < 256) - return c; - if (c >= 0xF700 && c < 0xF700 + 256) - return c - 0xF700 + 256; - return -1; -} - -static void resetKeys() -{ - ImGuiIO& io = ImGui::GetIO(); - for (int n = 0; n < IM_ARRAYSIZE(io.KeysDown); n++) - io.KeysDown[n] = false; -} - bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view) { ImGuiIO& io = ImGui::GetIO();