From a085581057ae89491be86782920981b5d0b3f969 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 3 Feb 2023 17:53:53 +0100 Subject: [PATCH] Backends: GLFW: added ImGui_ImplGlfw_SetCallbacksChainForAllWindows(). (#6142) --- backends/imgui_impl_glfw.cpp | 31 ++++++++++++++++++++++++------- backends/imgui_impl_glfw.h | 8 ++++++-- docs/CHANGELOG.txt | 3 +++ 3 files changed, 33 insertions(+), 9 deletions(-) diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp index c0b9a165b..c39afa388 100644 --- a/backends/imgui_impl_glfw.cpp +++ b/backends/imgui_impl_glfw.cpp @@ -108,6 +108,7 @@ struct ImGui_ImplGlfw_Data GLFWcursor* MouseCursors[ImGuiMouseCursor_COUNT]; ImVec2 LastValidMousePos; bool InstalledCallbacks; + bool CallbacksChainForAllWindows; // Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any. GLFWwindowfocusfun PrevUserCallbackWindowFocus; @@ -270,10 +271,16 @@ static void ImGui_ImplGlfw_UpdateKeyModifiers() io.AddKeyEvent(ImGuiMod_Super, (glfwGetKey(bd->Window, GLFW_KEY_LEFT_SUPER) == GLFW_PRESS) || (glfwGetKey(bd->Window, GLFW_KEY_RIGHT_SUPER) == GLFW_PRESS)); } +static bool ImGui_ImplGlfw_ShouldChainCallback(GLFWwindow* window) +{ + ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); + return bd->CallbacksChainForAllWindows ? true : (window == bd->Window); +} + void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods) { ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); - if (bd->PrevUserCallbackMousebutton != nullptr && window == bd->Window) + if (bd->PrevUserCallbackMousebutton != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window)) bd->PrevUserCallbackMousebutton(window, button, action, mods); ImGui_ImplGlfw_UpdateKeyModifiers(); @@ -286,7 +293,7 @@ void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int acti void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset) { ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); - if (bd->PrevUserCallbackScroll != nullptr && window == bd->Window) + if (bd->PrevUserCallbackScroll != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window)) bd->PrevUserCallbackScroll(window, xoffset, yoffset); #ifdef __EMSCRIPTEN__ @@ -334,7 +341,7 @@ static int ImGui_ImplGlfw_TranslateUntranslatedKey(int key, int scancode) void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int keycode, int scancode, int action, int mods) { ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); - if (bd->PrevUserCallbackKey != nullptr && window == bd->Window) + if (bd->PrevUserCallbackKey != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window)) bd->PrevUserCallbackKey(window, keycode, scancode, action, mods); if (action != GLFW_PRESS && action != GLFW_RELEASE) @@ -353,7 +360,7 @@ void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int keycode, int scancode, i void ImGui_ImplGlfw_WindowFocusCallback(GLFWwindow* window, int focused) { ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); - if (bd->PrevUserCallbackWindowFocus != nullptr && window == bd->Window) + if (bd->PrevUserCallbackWindowFocus != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window)) bd->PrevUserCallbackWindowFocus(window, focused); ImGuiIO& io = ImGui::GetIO(); @@ -363,7 +370,7 @@ void ImGui_ImplGlfw_WindowFocusCallback(GLFWwindow* window, int focused) void ImGui_ImplGlfw_CursorPosCallback(GLFWwindow* window, double x, double y) { ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); - if (bd->PrevUserCallbackCursorPos != nullptr && window == bd->Window) + if (bd->PrevUserCallbackCursorPos != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window)) bd->PrevUserCallbackCursorPos(window, x, y); if (glfwGetInputMode(window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED) return; @@ -378,7 +385,7 @@ void ImGui_ImplGlfw_CursorPosCallback(GLFWwindow* window, double x, double y) void ImGui_ImplGlfw_CursorEnterCallback(GLFWwindow* window, int entered) { ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); - if (bd->PrevUserCallbackCursorEnter != nullptr && window == bd->Window) + if (bd->PrevUserCallbackCursorEnter != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window)) bd->PrevUserCallbackCursorEnter(window, entered); if (glfwGetInputMode(window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED) return; @@ -400,7 +407,7 @@ void ImGui_ImplGlfw_CursorEnterCallback(GLFWwindow* window, int entered) void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c) { ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); - if (bd->PrevUserCallbackChar != nullptr && window == bd->Window) + if (bd->PrevUserCallbackChar != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window)) bd->PrevUserCallbackChar(window, c); ImGuiIO& io = ImGui::GetIO(); @@ -472,6 +479,16 @@ void ImGui_ImplGlfw_RestoreCallbacks(GLFWwindow* window) bd->PrevUserCallbackMonitor = nullptr; } +// Set to 'true' to enable chaining installed callbacks for all windows (including secondary viewports created by backends or by user. +// This is 'false' by default meaning we only chain callbacks for the main viewport. +// We cannot set this to 'true' by default because user callbacks code may be not testing the 'window' parameter of their callback. +// If you set this to 'true' your user callback code will need to make sure you are testing the 'window' parameter. +void ImGui_ImplGlfw_SetCallbacksChainForAllWindows(bool chain_for_all_windows) +{ + ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); + bd->CallbacksChainForAllWindows = chain_for_all_windows; +} + static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, GlfwClientApi client_api) { ImGuiIO& io = ImGui::GetIO(); diff --git a/backends/imgui_impl_glfw.h b/backends/imgui_impl_glfw.h index 9f5e35c6e..f2f340598 100644 --- a/backends/imgui_impl_glfw.h +++ b/backends/imgui_impl_glfw.h @@ -25,13 +25,17 @@ IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForOther(GLFWwindow* window, bool ins IMGUI_IMPL_API void ImGui_ImplGlfw_Shutdown(); IMGUI_IMPL_API void ImGui_ImplGlfw_NewFrame(); -// GLFW callbacks (installer) +// GLFW callbacks install // - When calling Init with 'install_callbacks=true': ImGui_ImplGlfw_InstallCallbacks() is called. GLFW callbacks will be installed for you. They will chain-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 individual function yourself from your own GLFW callbacks. IMGUI_IMPL_API void ImGui_ImplGlfw_InstallCallbacks(GLFWwindow* window); IMGUI_IMPL_API void ImGui_ImplGlfw_RestoreCallbacks(GLFWwindow* window); -// GLFW callbacks (individual callbacks to call if you didn't install callbacks) +// GFLW callbacks options: +// - Set 'chain_for_all_windows=true' to enable chaining callbacks for all windows (including secondary viewports created by backends or by user) +IMGUI_IMPL_API void ImGui_ImplGlfw_SetCallbacksChainForAllWindows(bool chain_for_all_windows); + +// GLFW callbacks (individual callbacks to call yourself if you didn't install callbacks) IMGUI_IMPL_API void ImGui_ImplGlfw_WindowFocusCallback(GLFWwindow* window, int focused); // Since 1.84 IMGUI_IMPL_API void ImGui_ImplGlfw_CursorEnterCallback(GLFWwindow* window, int entered); // Since 1.84 IMGUI_IMPL_API void ImGui_ImplGlfw_CursorPosCallback(GLFWwindow* window, double x, double y); // Since 1.87 diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index b09a248e6..a79fa0ae2 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -90,6 +90,9 @@ All changes: is surprisingly costly on Mac with latest SDL (may be fixed in next SDL version). (#6113) - Backends: GLFW: Registering custom low-level mouse wheel handler to get more accurate scrolling impulses on Emscripten. (#4019, #6096) [@ocornut, @wolfpld, @tolopolarity] +- Backends: GLFW: Added ImGui_ImplGlfw_SetCallbacksChainForAllWindows() to instruct backend + to chain callbacks even for secondary viewports/windows. User callbacks may need to test + the 'window' parameter. (#6142) - Backends: WebGPU: Fix building for latest WebGPU specs (remove implicit layout generation). (#6117, #4116, #3632) [@tonygrue, @bfierz] - Examples: refactord all examples to use a "MainLoopStep()" function. This is in order