mirror of
https://github.com/Drezil/imgui.git
synced 2024-12-22 07:36:35 +00:00
IO, Backends: add io.AddFocusEvent(). Clear pressed keys after loosing input focus (#3532)
Amend/fix #2445, #2696, #3751, #4377
This commit is contained in:
parent
86afe966d3
commit
2f40be638f
@ -16,6 +16,7 @@
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2021-08-17: Calling io.AddFocusEvent() on ALLEGRO_EVENT_DISPLAY_SWITCH_OUT/ALLEGRO_EVENT_DISPLAY_SWITCH_IN events.
|
||||
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
|
||||
// 2021-05-19: Renderer: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
|
||||
// 2021-02-18: Change blending equation to preserve alpha in output buffer.
|
||||
@ -390,6 +391,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 true;
|
||||
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 true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -16,7 +16,8 @@
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2021-07-29: *BREAKING CHANGE*: Inputs: MousePos is correctly reported when the host platform window is hovered but not focused (using glfwSetCursorEnterCallback). If you called ImGui_ImplGlfw_InitXXX() with install_callbacks = false, you MUST install the glfwSetCursorEnterCallback() callback and the forward to the backend via ImGui_ImplGlfw_CursorEnterCallback().
|
||||
// 2021-08-17: *BREAKING CHANGE*: Now using glfwSetWindowFocusCallback() to calling io.AddFocusEvent(). If you called ImGui_ImplGlfw_InitXXX() with install_callbacks = false, you MUST install glfwSetWindowFocusCallback() and forward it to the backend via ImGui_ImplGlfw_WindowFocusCallback().
|
||||
// 2021-07-29: *BREAKING CHANGE*: Now using glfwSetCursorEnterCallback(). MousePos is correctly reported when the host platform window is hovered but not focused. If you called ImGui_ImplGlfw_InitXXX() with install_callbacks = false, you MUST install glfwSetWindowFocusCallback() callback and forward it to the backend via ImGui_ImplGlfw_CursorEnterCallback().
|
||||
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
|
||||
// 2020-01-17: Inputs: Disable error callback while assigning mouse cursors because some X11 setup don't have them and it generates errors.
|
||||
// 2019-12-05: Inputs: Added support for new mouse cursors added in GLFW 3.4+ (resizing cursors, not allowed cursor).
|
||||
@ -80,6 +81,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;
|
||||
@ -160,11 +162,22 @@ 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 && window == bd->Window)
|
||||
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();
|
||||
if (bd->PrevUserCallbackCursorEnter != NULL)
|
||||
if (bd->PrevUserCallbackCursorEnter != NULL && window == bd->Window)
|
||||
bd->PrevUserCallbackCursorEnter(window, entered);
|
||||
|
||||
if (entered)
|
||||
bd->MouseWindow = window;
|
||||
if (!entered && bd->MouseWindow == window)
|
||||
@ -256,6 +269,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;
|
||||
@ -264,6 +278,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);
|
||||
@ -298,6 +313,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);
|
||||
|
@ -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);
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2021-08-17: Calling io.AddFocusEvent() on NSApplicationDidBecomeActiveNotification/NSApplicationDidResignActiveNotification events.
|
||||
// 2021-06-23: Inputs: Added a fix for shortcuts using CTRL key instead of CMD key.
|
||||
// 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.
|
||||
@ -60,14 +61,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
|
||||
@ -155,6 +166,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
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2021-08-17: Calling io.AddFocusEvent() on SDL_WINDOWEVENT_FOCUS_GAINED/SDL_WINDOWEVENT_FOCUS_LOST.
|
||||
// 2021-07-29: Inputs: MousePos is correctly reported when the host platform window is hovered but not focused (using SDL_GetMouseFocus() + SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, requires SDL 2.0.5+)
|
||||
// 2021-06-29: *BREAKING CHANGE* Removed 'SDL_Window* window' parameter to ImGui_ImplSDL2_NewFrame() which was unnecessary.
|
||||
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
|
||||
@ -148,6 +149,14 @@ 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 true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -33,7 +33,8 @@ typedef DWORD (WINAPI *PFN_XInputGetState)(DWORD, XINPUT_STATE*);
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2021-08-02: Inputs: Fixed keyboard modifiers being reported when host window doesn't have focus.
|
||||
// 2021-08-17: Calling io.AddFocusEvent() on WM_SETFOCUS/WM_KILLFOCUS messages.
|
||||
// 2021-08-02: Inputs: Fixed keyboard modifiers being reported when host windo doesn't have focus.
|
||||
// 2021-07-29: Inputs: MousePos is correctly reported when the host platform window is hovered but not focused (using TrackMouseEvent() to receive WM_MOUSELEAVE events).
|
||||
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
|
||||
// 2021-06-08: Fixed ImGui_ImplWin32_EnableDpiAwareness() and ImGui_ImplWin32_GetDpiScaleForMonitor() to handle Windows 8.1/10 features without a manifest (per-monitor DPI, and properly calls SetProcessDpiAwareness() on 8.1).
|
||||
@ -431,9 +432,9 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA
|
||||
io.KeyAlt = down;
|
||||
return 0;
|
||||
}
|
||||
case WM_SETFOCUS:
|
||||
case WM_KILLFOCUS:
|
||||
memset(io.KeysDown, 0, sizeof(io.KeysDown));
|
||||
io.KeyCtrl = io.KeyShift = io.KeyAlt = io.KeySuper = false;
|
||||
io.AddFocusEvent(msg == WM_SETFOCUS);
|
||||
return 0;
|
||||
case WM_CHAR:
|
||||
// You can also use ToAscii()+GetKeyboardState() to retrieve characters.
|
||||
|
@ -40,10 +40,13 @@ Breaking Changes:
|
||||
- Commented out redirecting functions/enums names that were marked obsolete in 1.67 and 1.69 (March 2019):
|
||||
- ImGui::GetOverlayDrawList() -> use ImGui::GetForegroundDrawList()
|
||||
- ImFont::GlyphRangesBuilder -> use ImFontGlyphRangesBuilder
|
||||
- Backends: GLFW: backend now needs to use glfwSetCursorEnterCallback(). (#3751, #4377, #2445)
|
||||
- Backends: GLFW: backend now uses glfwSetCursorEnterCallback(). (#3751, #4377, #2445)
|
||||
- Backends: GLFW: backend now uses glfwSetWindowFocusCallback(). (#4388) [@thedmd]
|
||||
- If calling ImGui_ImplGlfw_InitXXX with install_callbacks=true: this is already done for you.
|
||||
- If calling ImGui_ImplGlfw_InitXXX with install_callbacks=false: you WILL NEED to register the GLFW callback
|
||||
with glfwSetCursorEnterCallback(), and forward events to the backend via ImGui_ImplGlfw_CursorEnterCallback().
|
||||
- If calling ImGui_ImplGlfw_InitXXX with install_callbacks=false: you WILL NEED to register the GLFW callbacks
|
||||
and forward them to the backend:
|
||||
- Register glfwSetCursorEnterCallback, forward events to ImGui_ImplGlfw_CursorEnterCallback().
|
||||
- Register glfwSetWindowFocusCallback, forward events to ImGui_ImplGlfw_WindowFocusCallback().
|
||||
- Backends: SDL2: removed unnecessary SDL_Window* parameter from ImGui_ImplSDL2_NewFrame(). (#3244) [@funchal]
|
||||
Kept inline redirection function (will obsolete).
|
||||
- Backends: SDL2: backend needs to set 'SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1")' in order to
|
||||
@ -56,6 +59,8 @@ Breaking Changes:
|
||||
return value of ButtonBehavior() rather than (HoveredId == id).
|
||||
|
||||
Other Changes:
|
||||
- IO: Added io.AddFocusEvent() api for backend to tell when host window has gained/lost focus. (#4388) [@thedmd]
|
||||
If you use a custom backend, consider adding support for this!
|
||||
- Windows: ImGuiWindowFlags_UnsavedDocument/ImGuiTabItmeFlags_UnsavedDocument display a dot instead of a '*' so it
|
||||
is independent from font style. When in a tab, the dot is displayed at the same position as the close button.
|
||||
Added extra comments to clarify the purpose of this flag in the context of docked windows.
|
||||
@ -101,6 +106,9 @@ Other Changes:
|
||||
- Backends: Win32: IME functions are disabled by default for non-Visual Studio compilers (MinGW etc.). Enable with
|
||||
'#define IMGUI_ENABLE_WIN32_DEFAULT_IME_FUNCTIONS' for those compilers. Undo change from 1.82. (#2590, #738, #4185, #4301)
|
||||
- Backends: Win32: Mouse position is correctly reported when the host window is hovered but not focused. (#2445, #2696, #3751, #4377)
|
||||
- Backends: Win32, SDL2, GLFW, OSX, Allegro: now calling io.AddFocusEvent() on focus gain/loss. (#4388) [@thedmd]
|
||||
This allow us to ignore certain inputs on focus loss (previously relied on mouse loss but backends are now
|
||||
reporting mouse even when host window is unfocused, as per #2445, #2696, #3751, #4377)
|
||||
- Backends: Fixed keyboard modifiers being reported when host window doesn't have focus. (#2622)
|
||||
- Backends: GLFW: Mouse position is correctly reported when the host window is hovered but not focused. (#3751, #4377, #2445)
|
||||
(backend now uses glfwSetCursorEnterCallback(). If you called ImGui_ImplGlfw_InitXXX with install_callbacks=false, you will
|
||||
|
21
imgui.cpp
21
imgui.cpp
@ -1180,6 +1180,22 @@ void ImGuiIO::ClearInputCharacters()
|
||||
InputQueueCharacters.resize(0);
|
||||
}
|
||||
|
||||
void ImGuiIO::AddFocusEvent(bool focused)
|
||||
{
|
||||
if (focused)
|
||||
return;
|
||||
|
||||
// Clear buttons state when focus is lost
|
||||
// (this is useful so e.g. releasing Alt after focus loss on Alt-Tab doesn't trigger the Alt menu toggle)
|
||||
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 = KeyModsPrev = ImGuiKeyModFlags_None;
|
||||
for (int n = 0; n < IM_ARRAYSIZE(NavInputsDownDuration); n++)
|
||||
NavInputsDownDuration[n] = NavInputsDownDurationPrev[n] = -1.0f;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] MISC HELPERS/UTILITIES (Geometry functions)
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -9694,8 +9710,9 @@ static void ImGui::NavUpdateWindowing()
|
||||
g.NavWindowingToggleLayer = false;
|
||||
|
||||
// Apply layer toggle on release
|
||||
// FIXME: We lack an explicit IO variable for "is the platform window focused", so compare mouse validity to detect the common case of backend clearing releases all keys on ALT-TAB
|
||||
if (!io.KeyAlt && g.NavWindowingToggleLayer)
|
||||
// Important: we don't assume that Alt was previously held in order to handle loss of focus when backend calls io.AddFocusEvent(false)
|
||||
// Important: as before version <18314 we lacked an explicit IO event for focus gain/loss, we also compare mouse validity to detect old backends clearing mouse pos on focus loss.
|
||||
if (!(io.KeyMods & ImGuiKeyModFlags_Alt) && (io.KeyModsPrev & ImGuiKeyModFlags_Alt) && g.NavWindowingToggleLayer)
|
||||
if (g.ActiveId == 0 || g.ActiveIdAllowOverlap)
|
||||
if (IsMousePosValid(&io.MousePos) == IsMousePosValid(&io.MousePosPrev))
|
||||
apply_toggle_layer = true;
|
||||
|
3
imgui.h
3
imgui.h
@ -61,7 +61,7 @@ Index of this file:
|
||||
// Version
|
||||
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens)
|
||||
#define IMGUI_VERSION "1.84 WIP"
|
||||
#define IMGUI_VERSION_NUM 18313
|
||||
#define IMGUI_VERSION_NUM 18314
|
||||
#define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx))
|
||||
#define IMGUI_HAS_TABLE
|
||||
|
||||
@ -1868,6 +1868,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 focused); // Notifies Dear ImGui when hosting platform windows lose or gain input focus
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Output - Updated by NewFrame() or EndFrame()/Render()
|
||||
|
Loading…
Reference in New Issue
Block a user