From 772354377bc1dffd0e161279efbf48a9a2f1548e Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 8 Nov 2018 16:24:41 +0100 Subject: [PATCH] Examples: GLFW: User previously installed GLFW callbacks are now saved and chain-called by the default callbacks. (#1759) --- docs/CHANGELOG.txt | 1 + examples/example_glfw_opengl2/main.cpp | 1 - examples/example_glfw_opengl3/main.cpp | 1 - examples/example_glfw_vulkan/main.cpp | 1 - examples/imgui_impl_glfw.cpp | 52 +++++++++++++++++++------- examples/imgui_impl_glfw.h | 6 +-- 6 files changed, 41 insertions(+), 21 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index ef8d9645c..b0409bf98 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -78,6 +78,7 @@ Other Changes: in particular, points_count==0 could lead to a memory stomp if the draw list was previously empty. - Examples: DirectX10, DirectX11: Removed seemingly unnecessary calls to invalidate and recreate device objects in the WM_SIZE handler. (#2088) [@ice1000] +- Examples: GLFW: User previously installed GLFW callbacks are now saved and chain-called by the default callbacks. (#1759) - Examples: OpenGL3+GLFW: Fixed error condition when using the GLAD loader. (#2157) [@blackball] - Examples: OpenGL3+GLFW/SDL: Made main.cpp compile with IMGUI_IMPL_OPENGL_LOADER_CUSTOM (may be missing init). (#2178) [@doug-moen] diff --git a/examples/example_glfw_opengl2/main.cpp b/examples/example_glfw_opengl2/main.cpp index 6010b6895..7074b5d7a 100644 --- a/examples/example_glfw_opengl2/main.cpp +++ b/examples/example_glfw_opengl2/main.cpp @@ -44,7 +44,6 @@ int main(int, char**) //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls // Setup Platform/Renderer bindings - // If you have already installed GLFW callbacks in your app, call ImGui_ImplGlfw_InitForOpenGL() with install_callbacks=false and call them yourself. ImGui_ImplGlfw_InitForOpenGL(window, true); ImGui_ImplOpenGL2_Init(); diff --git a/examples/example_glfw_opengl3/main.cpp b/examples/example_glfw_opengl3/main.cpp index 2e0ebbf9a..cf939c111 100644 --- a/examples/example_glfw_opengl3/main.cpp +++ b/examples/example_glfw_opengl3/main.cpp @@ -90,7 +90,6 @@ int main(int, char**) //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls // Setup Platform/Renderer bindings - // If you have already installed GLFW callbacks in your app, call ImGui_ImplGlfw_InitForOpenGL() with install_callbacks=false and call them yourself. ImGui_ImplGlfw_InitForOpenGL(window, true); ImGui_ImplOpenGL3_Init(glsl_version); diff --git a/examples/example_glfw_vulkan/main.cpp b/examples/example_glfw_vulkan/main.cpp index 8eba5df1f..180160038 100644 --- a/examples/example_glfw_vulkan/main.cpp +++ b/examples/example_glfw_vulkan/main.cpp @@ -358,7 +358,6 @@ int main(int, char**) //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls // Setup Platform/Renderer bindings - // If you have already installed GLFW callbacks in your app, call ImGui_ImplGlfw_InitForVulkan() with install_callbacks=false and call the functions yourself. ImGui_ImplGlfw_InitForVulkan(window, true); ImGui_ImplVulkan_InitInfo init_info = {}; init_info.Instance = g_Instance; diff --git a/examples/imgui_impl_glfw.cpp b/examples/imgui_impl_glfw.cpp index 32baea7fe..a4bcc31a5 100644 --- a/examples/imgui_impl_glfw.cpp +++ b/examples/imgui_impl_glfw.cpp @@ -14,6 +14,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2018-11-07: Inputs: When installing our GLFW callbacks, we save user's previously installed ones - if any - and chain call them. // 2018-08-01: Inputs: Workaround for Emscripten which doesn't seem to handle focus related calls. // 2018-06-29: Inputs: Added support for the ImGuiMouseCursor_Hand cursor. // 2018-06-08: Misc: Extracted imgui_impl_glfw.cpp/.h away from the old combined GLFW+OpenGL/Vulkan examples. @@ -51,11 +52,17 @@ enum GlfwClientApi GlfwClientApi_OpenGL, GlfwClientApi_Vulkan }; -static GLFWwindow* g_Window = NULL; -static GlfwClientApi g_ClientApi = GlfwClientApi_Unknown; -static double g_Time = 0.0; -static bool g_MouseJustPressed[5] = { false, false, false, false, false }; -static GLFWcursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = { 0 }; +static GLFWwindow* g_Window = NULL; +static GlfwClientApi g_ClientApi = GlfwClientApi_Unknown; +static double g_Time = 0.0; +static bool g_MouseJustPressed[5] = { false, false, false, false, false }; +static GLFWcursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = { 0 }; + +// Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any. +static GLFWmousebuttonfun g_PrevUserCallbackMousebutton = NULL; +static GLFWscrollfun g_PrevUserCallbackScroll = NULL; +static GLFWkeyfun g_PrevUserCallbackKey = NULL; +static GLFWcharfun g_PrevUserCallbackChar = NULL; static const char* ImGui_ImplGlfw_GetClipboardText(void* user_data) { @@ -67,36 +74,48 @@ static void ImGui_ImplGlfw_SetClipboardText(void* user_data, const char* text) glfwSetClipboardString((GLFWwindow*)user_data, text); } -void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow*, int button, int action, int /*mods*/) +void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods) { + if (g_PrevUserCallbackMousebutton != NULL) + g_PrevUserCallbackMousebutton(window, button, action, mods); + if (action == GLFW_PRESS && button >= 0 && button < IM_ARRAYSIZE(g_MouseJustPressed)) g_MouseJustPressed[button] = true; } -void ImGui_ImplGlfw_ScrollCallback(GLFWwindow*, double xoffset, double yoffset) +void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset) { + if (g_PrevUserCallbackScroll != NULL) + g_PrevUserCallbackScroll(window, xoffset, yoffset); + ImGuiIO& io = ImGui::GetIO(); io.MouseWheelH += (float)xoffset; io.MouseWheel += (float)yoffset; } -void ImGui_ImplGlfw_KeyCallback(GLFWwindow*, int key, int, int action, int mods) +void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods) { + if (g_PrevUserCallbackKey != NULL) + g_PrevUserCallbackKey(window, key, scancode, action, mods); + ImGuiIO& io = ImGui::GetIO(); if (action == GLFW_PRESS) io.KeysDown[key] = true; if (action == GLFW_RELEASE) io.KeysDown[key] = false; - (void)mods; // Modifiers are not reliable across systems + // Modifiers are not reliable across systems io.KeyCtrl = io.KeysDown[GLFW_KEY_LEFT_CONTROL] || io.KeysDown[GLFW_KEY_RIGHT_CONTROL]; io.KeyShift = io.KeysDown[GLFW_KEY_LEFT_SHIFT] || io.KeysDown[GLFW_KEY_RIGHT_SHIFT]; io.KeyAlt = io.KeysDown[GLFW_KEY_LEFT_ALT] || io.KeysDown[GLFW_KEY_RIGHT_ALT]; io.KeySuper = io.KeysDown[GLFW_KEY_LEFT_SUPER] || io.KeysDown[GLFW_KEY_RIGHT_SUPER]; } -void ImGui_ImplGlfw_CharCallback(GLFWwindow*, unsigned int c) +void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c) { + if (g_PrevUserCallbackChar != NULL) + g_PrevUserCallbackChar(window, c); + ImGuiIO& io = ImGui::GetIO(); if (c > 0 && c < 0x10000) io.AddInputCharacter((unsigned short)c); @@ -151,12 +170,17 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw g_MouseCursors[ImGuiMouseCursor_ResizeNWSE] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); // FIXME: GLFW doesn't have this. g_MouseCursors[ImGuiMouseCursor_Hand] = glfwCreateStandardCursor(GLFW_HAND_CURSOR); + // Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any. + g_PrevUserCallbackMousebutton = NULL; + g_PrevUserCallbackScroll = NULL; + g_PrevUserCallbackKey = NULL; + g_PrevUserCallbackChar = NULL; if (install_callbacks) { - glfwSetMouseButtonCallback(window, ImGui_ImplGlfw_MouseButtonCallback); - glfwSetScrollCallback(window, ImGui_ImplGlfw_ScrollCallback); - glfwSetKeyCallback(window, ImGui_ImplGlfw_KeyCallback); - glfwSetCharCallback(window, ImGui_ImplGlfw_CharCallback); + g_PrevUserCallbackMousebutton = glfwSetMouseButtonCallback(window, ImGui_ImplGlfw_MouseButtonCallback); + g_PrevUserCallbackScroll = glfwSetScrollCallback(window, ImGui_ImplGlfw_ScrollCallback); + g_PrevUserCallbackKey = glfwSetKeyCallback(window, ImGui_ImplGlfw_KeyCallback); + g_PrevUserCallbackChar = glfwSetCharCallback(window, ImGui_ImplGlfw_CharCallback); } g_ClientApi = client_api; diff --git a/examples/imgui_impl_glfw.h b/examples/imgui_impl_glfw.h index 4bacd77b1..ccbe840d4 100644 --- a/examples/imgui_impl_glfw.h +++ b/examples/imgui_impl_glfw.h @@ -25,10 +25,8 @@ IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForVulkan(GLFWwindow* window, bool in IMGUI_IMPL_API void ImGui_ImplGlfw_Shutdown(); IMGUI_IMPL_API void ImGui_ImplGlfw_NewFrame(); -// GLFW callbacks are installed by default if you call the InitXXX function with 'install_callbacks=true'. -// If you already have GLFW callbacks installed by your application, call the InitXXX function with install_callbacks=false, -// then call the functions yourselves from your own GLFW callbacks. -// You may also handle inputs yourself and use those as a reference. +// InitXXX function with 'install_callbacks=true': install GLFW callbacks. They will call user's previously installed callbacks, if any. +// InitXXX function with 'install_callbacks=false': do not install GLFW callbacks. You will need to call them yourself from your own GLFW callbacks. 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); IMGUI_IMPL_API void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods);