diff --git a/lib/third_party/imgui/custom/include/imgui_impl_glfw.h b/lib/third_party/imgui/custom/include/imgui_impl_glfw.h index 6fe6882cb..78776cd28 100644 --- a/lib/third_party/imgui/custom/include/imgui_impl_glfw.h +++ b/lib/third_party/imgui/custom/include/imgui_impl_glfw.h @@ -6,7 +6,7 @@ // Implemented features: // [X] Platform: Clipboard support. // [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen (Windows only). -// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLFW_KEY_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set] +// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLFW_KEY_* values are obsolete since 1.87 and not supported since 1.91.5] // [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange' (note: the resizing cursors requires GLFW 3.4+). // [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'. @@ -28,15 +28,17 @@ struct GLFWwindow; struct GLFWmonitor; +// Follow "Getting Started" link and check examples/ folder to learn about using backends! IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForOpenGL(GLFWwindow* window, bool install_callbacks); IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForVulkan(GLFWwindow* window, bool install_callbacks); IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForOther(GLFWwindow* window, bool install_callbacks); IMGUI_IMPL_API void ImGui_ImplGlfw_Shutdown(); IMGUI_IMPL_API void ImGui_ImplGlfw_NewFrame(); -// Emscripten related initialization phase methods +// Emscripten related initialization phase methods (call after ImGui_ImplGlfw_InitForOpenGL) #ifdef __EMSCRIPTEN__ -IMGUI_IMPL_API void ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback(const char* canvas_selector); +IMGUI_IMPL_API void ImGui_ImplGlfw_InstallEmscriptenCallbacks(GLFWwindow* window, const char* canvas_selector); +//static inline void ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback(const char* canvas_selector) { ImGui_ImplGlfw_InstallEmscriptenCallbacks(nullptr, canvas_selector); } } // Renamed in 1.91.0 #endif // GLFW callbacks install @@ -59,4 +61,7 @@ IMGUI_IMPL_API void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int key, IMGUI_IMPL_API void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c); IMGUI_IMPL_API void ImGui_ImplGlfw_MonitorCallback(GLFWmonitor* monitor, int event); +// GLFW helpers +IMGUI_IMPL_API void ImGui_ImplGlfw_Sleep(int milliseconds); + #endif // #ifndef IMGUI_DISABLE diff --git a/lib/third_party/imgui/custom/source/imgui_impl_glfw.cpp b/lib/third_party/imgui/custom/source/imgui_impl_glfw.cpp index c2a4226c7..134cc9802 100644 --- a/lib/third_party/imgui/custom/source/imgui_impl_glfw.cpp +++ b/lib/third_party/imgui/custom/source/imgui_impl_glfw.cpp @@ -6,7 +6,7 @@ // Implemented features: // [X] Platform: Clipboard support. // [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen (Windows only). -// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLFW_KEY_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set] +// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLFW_KEY_* values are obsolete since 1.87 and not supported since 1.91.5] // [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange' (note: the resizing cursors requires GLFW 3.4+). // [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'. @@ -21,9 +21,23 @@ // - Documentation https://dearimgui.com/docs (same as your local docs/ folder). // - Introduction, links and more at the top of imgui.cpp +// About Emscripten support: +// - Emscripten provides its own GLFW (3.2.1) implementation (syntax: "-sUSE_GLFW=3"), but Joystick is broken and several features are not supported (multiple windows, clipboard, timer, etc.) +// - A third-party Emscripten GLFW (3.4.0) implementation (syntax: "--use-port=contrib.glfw3") fixes the Joystick issue and implements all relevant features for the browser. +// See https://github.com/pongasoft/emscripten-glfw/blob/master/docs/Comparison.md for details. + // CHANGELOG // (minor and older changes stripped away, please see git history for details) // 2024-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. +// 2024-11-05: [Docking] Added Linux workaround for spurious mouse up events emitted while dragging and creating new viewport. (#3158, #7733, #7922) +// 2024-08-22: moved some OS/backend related function pointers from ImGuiIO to ImGuiPlatformIO: +// - io.GetClipboardTextFn -> platform_io.Platform_GetClipboardTextFn +// - io.SetClipboardTextFn -> platform_io.Platform_SetClipboardTextFn +// - io.PlatformOpenInShellFn -> platform_io.Platform_OpenInShellFn +// 2024-07-31: Added ImGui_ImplGlfw_Sleep() helper function for usage by our examples app, since GLFW doesn't provide one. +// 2024-07-08: *BREAKING* Renamed ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback to ImGui_ImplGlfw_InstallEmscriptenCallbacks(), added GLFWWindow* parameter. +// 2024-07-08: Emscripten: Added support for GLFW3 contrib port (GLFW 3.4.0 features + bug fixes): to enable, replace -sUSE_GLFW=3 with --use-port=contrib.glfw3 (requires emscripten 3.1.59+) (https://github.com/pongasoft/emscripten-glfw) +// 2024-07-02: Emscripten: Added io.PlatformOpenInShellFn() handler for Emscripten versions. // 2023-12-19: Emscripten: Added ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback() to register canvas selector and auto-resize GLFW window. // 2023-10-05: Inputs: Added support for extra ImGuiKey values: F13 to F24 function keys. // 2023-07-18: Inputs: Revert ignoring mouse data on GLFW_CURSOR_DISABLED as it can be used differently. User may set ImGuiConfigFLags_NoMouse if desired. (#5625, #6609) @@ -104,15 +118,25 @@ //#include // for glfwGetCocoaWindow() // #endif // IMHEX PATCH END +#ifndef _WIN32 +#include // for usleep() +#endif #ifdef __EMSCRIPTEN__ #include #include + // IMHEX PATCH BEGIN #include static std::string clipboardContent; // IMHEX PATCH END + +#ifdef EMSCRIPTEN_USE_PORT_CONTRIB_GLFW3 +#include +#else +#define EMSCRIPTEN_USE_EMBEDDED_GLFW3 +#endif #endif // We gather version tests as define in order to easily see which features are version-dependent. @@ -159,12 +183,14 @@ struct ImGui_ImplGlfw_Data double Time; GLFWwindow* MouseWindow; GLFWcursor* MouseCursors[ImGuiMouseCursor_COUNT]; + bool MouseIgnoreButtonUpWaitForFocusLoss; + bool MouseIgnoreButtonUp; ImVec2 LastValidMousePos; GLFWwindow* KeyOwnerWindows[GLFW_KEY_LAST]; bool InstalledCallbacks; bool CallbacksChainForAllWindows; bool WantUpdateMonitors; -#ifdef __EMSCRIPTEN__ +#ifdef EMSCRIPTEN_USE_EMBEDDED_GLFW3 const char* CanvasSelector; #endif @@ -198,8 +224,8 @@ static ImGui_ImplGlfw_Data* ImGui_ImplGlfw_GetBackendData() // Forward Declarations static void ImGui_ImplGlfw_UpdateMonitors(); -static void ImGui_ImplGlfw_InitPlatformInterface(); -static void ImGui_ImplGlfw_ShutdownPlatformInterface(); +static void ImGui_ImplGlfw_InitMultiViewportSupport(); +static void ImGui_ImplGlfw_ShutdownMultiViewportSupport(); // Functions static const char* ImGui_ImplGlfw_GetClipboardText(void* user_data) @@ -224,9 +250,12 @@ static void ImGui_ImplGlfw_SetClipboardText(void* user_data, const char* text) // IMHEX PATCH END } -static ImGuiKey ImGui_ImplGlfw_KeyToImGuiKey(int key) +// Not static to allow third-party code to use that if they want to (but undocumented) +ImGuiKey ImGui_ImplGlfw_KeyToImGuiKey(int keycode, int scancode); +ImGuiKey ImGui_ImplGlfw_KeyToImGuiKey(int keycode, int scancode) { - switch (key) + IM_UNUSED(scancode); + switch (keycode) { case GLFW_KEY_TAB: return ImGuiKey_Tab; case GLFW_KEY_LEFT: return ImGuiKey_LeftArrow; @@ -372,6 +401,10 @@ void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int acti if (bd->PrevUserCallbackMousebutton != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window)) bd->PrevUserCallbackMousebutton(window, button, action, mods); + // Workaround for Linux: ignore mouse up events which are following an focus loss following a viewport creation + if (bd->MouseIgnoreButtonUp && action == GLFW_RELEASE) + return; + ImGui_ImplGlfw_UpdateKeyModifiers(window); ImGuiIO& io = ImGui::GetIO(); @@ -385,7 +418,7 @@ void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yo if (bd->PrevUserCallbackScroll != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window)) bd->PrevUserCallbackScroll(window, xoffset, yoffset); -#ifdef __EMSCRIPTEN__ +#ifdef EMSCRIPTEN_USE_EMBEDDED_GLFW3 // Ignore GLFW events: will be processed in ImGui_ImplEmscripten_WheelCallback(). return; #endif @@ -394,9 +427,10 @@ void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yo io.AddMouseWheelEvent((float)xoffset, (float)yoffset); } +// FIXME: should this be baked into ImGui_ImplGlfw_KeyToImGuiKey()? then what about the values passed to io.SetKeyEventNativeData()? static int ImGui_ImplGlfw_TranslateUntranslatedKey(int key, int scancode) { -#if GLFW_HAS_GETKEYNAME && !defined(__EMSCRIPTEN__) +#if GLFW_HAS_GETKEYNAME && !defined(EMSCRIPTEN_USE_EMBEDDED_GLFW3) // GLFW 3.1+ attempts to "untranslate" keys, which goes the opposite of what every other framework does, making using lettered shortcuts difficult. // (It had reasons to do so: namely GLFW is/was more likely to be used for WASD-type game controls rather than lettered shortcuts, but IHMO the 3.1 change could have been done differently) // See https://github.com/glfw/glfw/issues/1502 for details. @@ -407,7 +441,7 @@ static int ImGui_ImplGlfw_TranslateUntranslatedKey(int key, int scancode) GLFWerrorfun prev_error_callback = glfwSetErrorCallback(nullptr); const char* key_name = glfwGetKeyName(key, scancode); glfwSetErrorCallback(prev_error_callback); -#if GLFW_HAS_GETERROR && !defined(__EMSCRIPTEN__) // Eat errors (see #5908) +#if GLFW_HAS_GETERROR && !defined(EMSCRIPTEN_USE_EMBEDDED_GLFW3) // Eat errors (see #5908) (void)glfwGetError(nullptr); #endif if (key_name && key_name[0] != 0 && key_name[1] == 0) @@ -444,7 +478,7 @@ void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int keycode, int scancode, i keycode = ImGui_ImplGlfw_TranslateUntranslatedKey(keycode, scancode); ImGuiIO& io = ImGui::GetIO(); - ImGuiKey imgui_key = ImGui_ImplGlfw_KeyToImGuiKey(keycode); + ImGuiKey imgui_key = ImGui_ImplGlfw_KeyToImGuiKey(keycode, scancode); io.AddKeyEvent(imgui_key, (action == GLFW_PRESS)); io.SetKeyEventNativeData(imgui_key, keycode, scancode); // To support legacy indexing (<1.87 user code) } @@ -455,6 +489,10 @@ void ImGui_ImplGlfw_WindowFocusCallback(GLFWwindow* window, int focused) if (bd->PrevUserCallbackWindowFocus != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window)) bd->PrevUserCallbackWindowFocus(window, focused); + // Workaround for Linux: when losing focus with MouseIgnoreButtonUpWaitForFocusLoss set, we will temporarily ignore subsequent Mouse Up events + bd->MouseIgnoreButtonUp = (bd->MouseIgnoreButtonUpWaitForFocusLoss && focused == 0); + bd->MouseIgnoreButtonUpWaitForFocusLoss = false; + ImGuiIO& io = ImGui::GetIO(); io.AddFocusEvent(focused != 0); } @@ -515,7 +553,7 @@ void ImGui_ImplGlfw_MonitorCallback(GLFWmonitor*, int) bd->WantUpdateMonitors = true; } -#ifdef __EMSCRIPTEN__ +#ifdef EMSCRIPTEN_USE_EMBEDDED_GLFW3 static EM_BOOL ImGui_ImplEmscripten_WheelCallback(int, const EmscriptenWheelEvent* ev, void*) { // Mimic Emscripten_HandleWheel() in SDL. @@ -600,6 +638,7 @@ EM_JS(void, ImGui_ImplGlfw_EmscriptenOpenURL, (const char* url), { url = url ? U static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, GlfwClientApi client_api) { ImGuiIO& io = ImGui::GetIO(); + IMGUI_CHECKVERSION(); IM_ASSERT(io.BackendPlatformUserData == nullptr && "Already initialized a platform backend!"); //printf("GLFW_VERSION: %d.%d.%d (%d)", GLFW_VERSION_MAJOR, GLFW_VERSION_MINOR, GLFW_VERSION_REVISION, GLFW_VERSION_COMBINED); @@ -665,14 +704,9 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw // Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any. if (install_callbacks) ImGui_ImplGlfw_InstallCallbacks(window); - // Register Emscripten Wheel callback to workaround issue in Emscripten GLFW Emulation (#6096) - // We intentionally do not check 'if (install_callbacks)' here, as some users may set it to false and call GLFW callback themselves. - // FIXME: May break chaining in case user registered their own Emscripten callback? -#ifdef __EMSCRIPTEN__ - emscripten_set_wheel_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, nullptr, false, ImGui_ImplEmscripten_WheelCallback); -#endif - // Update monitors the first time (note: monitor callback are broken in GLFW 3.2 and earlier, see github.com/glfw/glfw/issues/784) + // Update monitor a first time during init + // (note: monitor callback are broken in GLFW 3.2 and earlier, see github.com/glfw/glfw/issues/784) ImGui_ImplGlfw_UpdateMonitors(); glfwSetMonitorCallback(ImGui_ImplGlfw_MonitorCallback); @@ -689,8 +723,7 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw #else IM_UNUSED(main_viewport); #endif - if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) - ImGui_ImplGlfw_InitPlatformInterface(); + ImGui_ImplGlfw_InitMultiViewportSupport(); // Windows: register a WndProc hook so we can intercept some messages. #ifdef _WIN32 @@ -699,6 +732,23 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw ::SetWindowLongPtrW((HWND)main_viewport->PlatformHandleRaw, GWLP_WNDPROC, (LONG_PTR)ImGui_ImplGlfw_WndProc); #endif + // Emscripten: the same application can run on various platforms, so we detect the Apple platform at runtime + // to override io.ConfigMacOSXBehaviors from its default (which is always false in Emscripten). +#ifdef __EMSCRIPTEN__ +#if EMSCRIPTEN_USE_PORT_CONTRIB_GLFW3 >= 34020240817 + if (emscripten::glfw3::IsRuntimePlatformApple()) + { + ImGui::GetIO().ConfigMacOSXBehaviors = true; + + // Due to how the browser (poorly) handles the Meta Key, this line essentially disables repeats when used. + // This means that Meta + V only registers a single key-press, even if the keys are held. + // This is a compromise for dealing with this issue in ImGui since ImGui implements key repeat itself. + // See https://github.com/pongasoft/emscripten-glfw/blob/v3.4.0.20240817/docs/Usage.md#the-problem-of-the-super-key + emscripten::glfw3::SetSuperPlusKeyTimeouts(10, 10); + } +#endif +#endif + bd->ClientApi = client_api; return true; } @@ -724,12 +774,13 @@ void ImGui_ImplGlfw_Shutdown() IM_ASSERT(bd != nullptr && "No platform backend to shutdown, or already shutdown?"); ImGuiIO& io = ImGui::GetIO(); - ImGui_ImplGlfw_ShutdownPlatformInterface(); + ImGui_ImplGlfw_ShutdownMultiViewportSupport(); if (bd->InstalledCallbacks) ImGui_ImplGlfw_RestoreCallbacks(bd->Window); -#ifdef __EMSCRIPTEN__ - emscripten_set_wheel_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, nullptr, false, nullptr); +#ifdef EMSCRIPTEN_USE_EMBEDDED_GLFW3 + if (bd->CanvasSelector) + emscripten_set_wheel_callback(bd->CanvasSelector, nullptr, false, nullptr); #endif for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++) @@ -761,14 +812,14 @@ static void ImGui_ImplGlfw_UpdateMouseData() ImGuiViewport* viewport = platform_io.Viewports[n]; GLFWwindow* window = (GLFWwindow*)viewport->PlatformHandle; -#ifdef __EMSCRIPTEN__ +#ifdef EMSCRIPTEN_USE_EMBEDDED_GLFW3 const bool is_window_focused = true; #else const bool is_window_focused = glfwGetWindowAttrib(window, GLFW_FOCUSED) != 0; #endif if (is_window_focused) { - // (Optional) Set OS mouse position from Dear ImGui if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user) + // (Optional) Set OS mouse position from Dear ImGui if requested (rarely used, only when io.ConfigNavMoveSetMousePos is enabled by user) // When multi-viewports are enabled, all Dear ImGui positions are same as OS positions. if (io.WantSetMousePos) glfwSetCursorPos(window, (double)(mouse_pos_prev.x - viewport->Pos.x), (double)(mouse_pos_prev.y - viewport->Pos.y)); @@ -840,7 +891,6 @@ static void ImGui_ImplGlfw_UpdateMouseCursor() { // Show OS mouse cursor // FIXME-PLATFORM: Unfocused windows seems to fail changing the mouse cursor with GLFW 3.2, but 3.3 works here. - // IMHEX PATCH BEGIN #if !defined(_WIN32) glfwSetCursor(window, bd->MouseCursors[imgui_cursor] ? bd->MouseCursors[imgui_cursor] : bd->MouseCursors[ImGuiMouseCursor_Arrow]); @@ -861,7 +911,7 @@ static void ImGui_ImplGlfw_UpdateGamepads() return; io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad; -#if GLFW_HAS_GAMEPAD_API && !defined(__EMSCRIPTEN__) +#if GLFW_HAS_GAMEPAD_API && !defined(EMSCRIPTEN_USE_EMBEDDED_GLFW3) GLFWgamepadstate gamepad; if (!glfwGetGamepadState(GLFW_JOYSTICK_1, &gamepad)) return; @@ -940,13 +990,9 @@ static void ImGui_ImplGlfw_UpdateMonitors() // Warning: the validity of monitor DPI information on Windows depends on the application DPI awareness settings, which generally needs to be set in the manifest or at runtime. float x_scale, y_scale; glfwGetMonitorContentScale(glfw_monitors[n], &x_scale, &y_scale); + if (x_scale == 0.0f) + continue; // Some accessibility applications are declaring virtual monitors with a DPI of 0, see #7902. monitor.DpiScale = x_scale; - - // IMHEX PATCH BEGIN - // REASON: Prevent occasional crash when a monitor connection status is changed - if (x_scale > 0) - monitor.DpiScale = x_scale; - // IMHEX PATCH END #endif monitor.PlatformHandle = (void*)glfw_monitors[n]; // [...] GLFW doc states: "guaranteed to be valid only until the monitor configuration changes" platform_io.Monitors.push_back(monitor); @@ -978,6 +1024,7 @@ void ImGui_ImplGlfw_NewFrame() io.DeltaTime = bd->Time > 0.0 ? (float)(current_time - bd->Time) : (float)(1.0f / 60.0f); bd->Time = current_time; + bd->MouseIgnoreButtonUp = false; ImGui_ImplGlfw_UpdateMouseData(); ImGui_ImplGlfw_UpdateMouseCursor(); @@ -985,7 +1032,17 @@ void ImGui_ImplGlfw_NewFrame() ImGui_ImplGlfw_UpdateGamepads(); } -#ifdef __EMSCRIPTEN__ +// GLFW doesn't provide a portable sleep function +void ImGui_ImplGlfw_Sleep(int milliseconds) +{ +#ifdef _WIN32 + ::Sleep(milliseconds); +#else + usleep(milliseconds * 1000); +#endif +} + +#ifdef EMSCRIPTEN_USE_EMBEDDED_GLFW3 static EM_BOOL ImGui_ImplGlfw_OnCanvasSizeChange(int event_type, const EmscriptenUiEvent* event, void* user_data) { ImGui_ImplGlfw_Data* bd = (ImGui_ImplGlfw_Data*)user_data; @@ -1006,7 +1063,7 @@ static EM_BOOL ImGui_ImplEmscripten_FullscreenChangeCallback(int event_type, con // 'canvas_selector' is a CSS selector. The event listener is applied to the first element that matches the query. // STRING MUST PERSIST FOR THE APPLICATION DURATION. PLEASE USE A STRING LITERAL OR ENSURE POINTER WILL STAY VALID. -void ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback(const char* canvas_selector) +void ImGui_ImplGlfw_InstallEmscriptenCallbacks(GLFWwindow*, const char* canvas_selector) { IM_ASSERT(canvas_selector != nullptr); ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); @@ -1018,8 +1075,24 @@ void ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback(const char* canvas_sel // Change the size of the GLFW window according to the size of the canvas ImGui_ImplGlfw_OnCanvasSizeChange(EMSCRIPTEN_EVENT_RESIZE, {}, bd); + + // Register Emscripten Wheel callback to workaround issue in Emscripten GLFW Emulation (#6096) + // We intentionally do not check 'if (install_callbacks)' here, as some users may set it to false and call GLFW callback themselves. + // FIXME: May break chaining in case user registered their own Emscripten callback? + emscripten_set_wheel_callback(bd->CanvasSelector, nullptr, false, ImGui_ImplEmscripten_WheelCallback); } -#endif +#elif defined(EMSCRIPTEN_USE_PORT_CONTRIB_GLFW3) +// When using --use-port=contrib.glfw3 for the GLFW implementation, you can override the behavior of this call +// by invoking emscripten_glfw_make_canvas_resizable afterward. +// See https://github.com/pongasoft/emscripten-glfw/blob/master/docs/Usage.md#how-to-make-the-canvas-resizable-by-the-user for an explanation +void ImGui_ImplGlfw_InstallEmscriptenCallbacks(GLFWwindow* window, const char* canvas_selector) +{ + GLFWwindow* w = (GLFWwindow*)(EM_ASM_INT({ return Module.glfwGetWindow(UTF8ToString($0)); }, canvas_selector)); + IM_ASSERT(window == w); // Sanity check + IM_UNUSED(w); + emscripten_glfw_make_canvas_resizable(window, "window", nullptr); +} +#endif // #ifdef EMSCRIPTEN_USE_PORT_CONTRIB_GLFW3 //-------------------------------------------------------------------------------------------------------- @@ -1091,6 +1164,11 @@ static void ImGui_ImplGlfw_CreateWindow(ImGuiViewport* viewport) ImGui_ImplGlfw_ViewportData* vd = IM_NEW(ImGui_ImplGlfw_ViewportData)(); viewport->PlatformUserData = vd; + // Workaround for Linux: ignore mouse up events corresponding to losing focus of the previously focused window (#7733, #3158, #7922) +#ifdef __linux__ + bd->MouseIgnoreButtonUpWaitForFocusLoss = true; +#endif + // GLFW 3.2 unfortunately always set focus on glfwCreateWindow() if GLFW_VISIBLE is set, regardless of GLFW_FOCUSED // With GLFW 3.3, the hint GLFW_FOCUS_ON_SHOW fixes this problem glfwWindowHint(GLFW_VISIBLE, false); @@ -1152,6 +1230,7 @@ static void ImGui_ImplGlfw_DestroyWindow(ImGuiViewport* viewport) if (bd->KeyOwnerWindows[i] == vd->Window) ImGui_ImplGlfw_KeyCallback(vd->Window, i, 0, GLFW_RELEASE, 0); // Later params are only used for main viewport, on which this function is never called. } + glfwDestroyWindow(vd->Window); } vd->Window = nullptr; @@ -1324,7 +1403,7 @@ static int ImGui_ImplGlfw_CreateVkSurface(ImGuiViewport* viewport, ImU64 vk_inst } #endif // GLFW_HAS_VULKAN -static void ImGui_ImplGlfw_InitPlatformInterface() +static void ImGui_ImplGlfw_InitMultiViewportSupport() { // Register platform interface (will be coupled with a renderer interface) ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); @@ -1359,7 +1438,7 @@ static void ImGui_ImplGlfw_InitPlatformInterface() main_viewport->PlatformHandle = (void*)bd->Window; } -static void ImGui_ImplGlfw_ShutdownPlatformInterface() +static void ImGui_ImplGlfw_ShutdownMultiViewportSupport() { ImGui::DestroyPlatformWindows(); }