From 6be5a35752d0ee30849d5bd25c0cd8dea1fc0dee Mon Sep 17 00:00:00 2001 From: Alex Bilger Date: Tue, 13 Jan 2026 10:46:26 +0100 Subject: [PATCH 1/3] Fix font size --- SofaImGui/src/SofaImGui/ImGuiGUIEngine.cpp | 22 +++++++--------------- SofaImGui/src/SofaImGui/ImGuiGUIEngine.h | 2 +- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/SofaImGui/src/SofaImGui/ImGuiGUIEngine.cpp b/SofaImGui/src/SofaImGui/ImGuiGUIEngine.cpp index c283e7a4e6..0ba817e05a 100644 --- a/SofaImGui/src/SofaImGui/ImGuiGUIEngine.cpp +++ b/SofaImGui/src/SofaImGui/ImGuiGUIEngine.cpp @@ -178,14 +178,15 @@ void ImGuiGUIEngine::initBackend(GLFWwindow* glfwWindow) ImGuiIO& io = ImGui::GetIO(); - io.Fonts->AddFontFromMemoryCompressedTTF(ROBOTO_MEDIUM_compressed_data, ROBOTO_MEDIUM_compressed_size, 16 * yscale); + io.Fonts->AddFontFromMemoryCompressedTTF(ROBOTO_MEDIUM_compressed_data, ROBOTO_MEDIUM_compressed_size, 16.f * yscale); ImFontConfig config; config.MergeMode = true; - config.GlyphMinAdvanceX = 16.0f; // Use if you want to make the icon monospaced + config.GlyphMinAdvanceX = 16.f * yscale; + static const ImWchar icon_ranges[] = { ICON_MIN_FA, ICON_MAX_FA, 0 }; - io.Fonts->AddFontFromMemoryCompressedTTF(FA_REGULAR_400_compressed_data, FA_REGULAR_400_compressed_size, 16 * yscale, &config, icon_ranges); - io.Fonts->AddFontFromMemoryCompressedTTF(FA_SOLID_900_compressed_data, FA_SOLID_900_compressed_size, 16 * yscale, &config, icon_ranges); + io.Fonts->AddFontFromMemoryCompressedTTF(FA_REGULAR_400_compressed_data, FA_REGULAR_400_compressed_size, 16.f * yscale, &config, icon_ranges); + io.Fonts->AddFontFromMemoryCompressedTTF(FA_SOLID_900_compressed_data, FA_SOLID_900_compressed_size, 16.f * yscale, &config, icon_ranges); // restore the global scale stored in the Settings ini file const float globalScale = static_cast(ini.GetDoubleValue("Visualization", "globalScale", 1.0)); @@ -885,19 +886,10 @@ bool ImGuiGUIEngine::dispatchMouseEvents() } -void ImGuiGUIEngine::setScale(double globalScale, GLFWmonitor* monitor) +void ImGuiGUIEngine::setScale(float globalScale, GLFWmonitor* monitor) { - if(!monitor) - { - monitor = glfwGetPrimaryMonitor(); - } - ImGuiIO& io = ImGui::GetIO(); - - float xscale{}, yscale{}; - glfwGetMonitorContentScale(monitor, &xscale, &yscale); - - io.FontGlobalScale = globalScale / yscale; + io.FontGlobalScale = globalScale; } type::Vec2i ImGuiGUIEngine::getFrameBufferPixels(std::vector& pixels) diff --git a/SofaImGui/src/SofaImGui/ImGuiGUIEngine.h b/SofaImGui/src/SofaImGui/ImGuiGUIEngine.h index ada302fd89..5112649964 100644 --- a/SofaImGui/src/SofaImGui/ImGuiGUIEngine.h +++ b/SofaImGui/src/SofaImGui/ImGuiGUIEngine.h @@ -62,7 +62,7 @@ class ImGuiGUIEngine : public sofaglfw::BaseGUIEngine bool dispatchMouseEvents() override; // apply global scale on the given monitor (if null, it will fetch the main monitor) - void setScale(double globalScale, GLFWmonitor* monitor); + void setScale(float globalScale, GLFWmonitor* monitor); // reset counters void resetCounter() override; From 0c1717d31cc550155b0db77e94620afcb579fdd4 Mon Sep 17 00:00:00 2001 From: Alex Bilger Date: Tue, 13 Jan 2026 11:25:58 +0100 Subject: [PATCH 2/3] refactoring --- SofaImGui/src/SofaImGui/ImGuiGUIEngine.cpp | 154 ++++++++++--------- SofaImGui/src/SofaImGui/ImGuiGUIEngine.h | 3 +- SofaImGui/src/SofaImGui/windows/Settings.cpp | 2 +- 3 files changed, 84 insertions(+), 75 deletions(-) diff --git a/SofaImGui/src/SofaImGui/ImGuiGUIEngine.cpp b/SofaImGui/src/SofaImGui/ImGuiGUIEngine.cpp index 0ba817e05a..e7a9e3a088 100644 --- a/SofaImGui/src/SofaImGui/ImGuiGUIEngine.cpp +++ b/SofaImGui/src/SofaImGui/ImGuiGUIEngine.cpp @@ -166,86 +166,29 @@ void ImGuiGUIEngine::initBackend(GLFWwindow* glfwWindow) ImGui_ImplOpenGL3_Init(nullptr); #endif // SOFAIMGUI_FORCE_OPENGL2 == 1 - GLFWmonitor* windowMonitor = glfwGetWindowMonitor(glfwWindow); - if (!windowMonitor) + float yscale { 1.f }; + if (GLFWmonitor* windowMonitor = findMyMonitor(glfwWindow)) { - windowMonitor = glfwGetPrimaryMonitor(); - } - if (windowMonitor) - { - float xscale{}, yscale{}; + float xscale{}; glfwGetMonitorContentScale(windowMonitor, &xscale, &yscale); - - ImGuiIO& io = ImGui::GetIO(); - - io.Fonts->AddFontFromMemoryCompressedTTF(ROBOTO_MEDIUM_compressed_data, ROBOTO_MEDIUM_compressed_size, 16.f * yscale); - - ImFontConfig config; - config.MergeMode = true; - config.GlyphMinAdvanceX = 16.f * yscale; - - static const ImWchar icon_ranges[] = { ICON_MIN_FA, ICON_MAX_FA, 0 }; - io.Fonts->AddFontFromMemoryCompressedTTF(FA_REGULAR_400_compressed_data, FA_REGULAR_400_compressed_size, 16.f * yscale, &config, icon_ranges); - io.Fonts->AddFontFromMemoryCompressedTTF(FA_SOLID_900_compressed_data, FA_SOLID_900_compressed_size, 16.f * yscale, &config, icon_ranges); - - // restore the global scale stored in the Settings ini file - const float globalScale = static_cast(ini.GetDoubleValue("Visualization", "globalScale", 1.0)); - this->setScale(globalScale, windowMonitor); } - - // restore window settings if set - const bool rememberWindowPosition = ini.GetBoolValue("Window", "rememberWindowPosition", true); - if(rememberWindowPosition) - { - if(ini.KeyExists("Window", "windowPosX") && ini.KeyExists("Window", "windowPosY")) - { - const long windowPosX = ini.GetLongValue("Window", "windowPosX"); - const long windowPosY = ini.GetLongValue("Window", "windowPosY"); - int monitorCount; - GLFWmonitor** monitors = glfwGetMonitors(&monitorCount); - - bool foundValidMonitor = false; - for (int i = 0; i < monitorCount; ++i) - { - if (GLFWmonitor* monitor = monitors[i]) - { - //retrieve the work area of the monitor in the whole desktop space, in screen coordinates - int monitorXPos{0}, monitorYPos{0}, monitorWidth{0}, monitorHeight{0}; - glfwGetMonitorWorkarea(monitor, &monitorXPos, &monitorYPos, &monitorWidth, &monitorHeight); - if(!monitorWidth || !monitorHeight) - { - msg_error("ImGuiGUIEngine") << "Unknown error while trying to fetch the monitor information."; - } - else - { - constexpr long margin = 5; // avoid the case where the window is positioned on the border of the monitor (almost invisible/non-selectable) + constexpr float fontSize = 16.f; + ImGuiIO& io = ImGui::GetIO(); - if(windowPosX >= (monitorXPos) && - windowPosX <= (monitorXPos + monitorWidth-margin) && - windowPosY >= (monitorYPos) && - windowPosY <= (monitorYPos + monitorHeight-margin)) - { - glfwSetWindowPos(glfwWindow, static_cast(windowPosX), static_cast(windowPosY)); - foundValidMonitor = true; - break; - } + io.Fonts->AddFontFromMemoryCompressedTTF(ROBOTO_MEDIUM_compressed_data, ROBOTO_MEDIUM_compressed_size, fontSize * yscale); - } - } - } + ImFontConfig config; + config.MergeMode = true; + config.GlyphMinAdvanceX = fontSize * yscale; - if (!foundValidMonitor) - { - msg_error("ImGuiGUIEngine") << "The window position from settings is invalid for any monitor."; - } - } - else - { - msg_error("ImGuiGUIEngine") << "Cannot set window position from settings."; - } + static const ImWchar icon_ranges[] = { ICON_MIN_FA, ICON_MAX_FA, 0 }; + io.Fonts->AddFontFromMemoryCompressedTTF(FA_REGULAR_400_compressed_data, FA_REGULAR_400_compressed_size, fontSize * yscale, &config, icon_ranges); + io.Fonts->AddFontFromMemoryCompressedTTF(FA_SOLID_900_compressed_data, FA_SOLID_900_compressed_size, fontSize * yscale, &config, icon_ranges); - } + // restore the global scale stored in the Settings ini file + const float globalScale = static_cast(ini.GetDoubleValue("Visualization", "globalScale", 1.0)); + this->setScale(globalScale); const bool rememberWindowSize = ini.GetBoolValue("Window", "rememberWindowSize", true); if(rememberWindowSize) @@ -806,6 +749,71 @@ void ImGuiGUIEngine::resetView(ImGuiID dockspace_id, const char* windowNameScene firstRunState.setState(true);// Mark first run as complete } +GLFWmonitor* ImGuiGUIEngine::findMyMonitor(GLFWwindow* glfwWindow) +{ + GLFWmonitor* foundMonitor { nullptr }; + + const bool rememberWindowPosition = ini.GetBoolValue("Window", "rememberWindowPosition", true); + if(rememberWindowPosition) + { + if(ini.KeyExists("Window", "windowPosX") && ini.KeyExists("Window", "windowPosY")) + { + const long windowPosX = ini.GetLongValue("Window", "windowPosX"); + const long windowPosY = ini.GetLongValue("Window", "windowPosY"); + + int monitorCount; + GLFWmonitor** monitors = glfwGetMonitors(&monitorCount); + + bool foundValidMonitor = false; + for (int i = 0; i < monitorCount; ++i) + { + if (GLFWmonitor* monitor = monitors[i]) + { + //retrieve the work area of the monitor in the whole desktop space, in screen coordinates + int monitorXPos{0}, monitorYPos{0}, monitorWidth{0}, monitorHeight{0}; + glfwGetMonitorWorkarea(monitor, &monitorXPos, &monitorYPos, &monitorWidth, &monitorHeight); + if(!monitorWidth || !monitorHeight) + { + msg_error("ImGuiGUIEngine") << "Unknown error while trying to fetch the monitor information."; + } + else + { + constexpr long margin = 5; // avoid the case where the window is positioned on the border of the monitor (almost invisible/non-selectable) + + if(windowPosX >= (monitorXPos) && + windowPosX <= (monitorXPos + monitorWidth-margin) && + windowPosY >= (monitorYPos) && + windowPosY <= (monitorYPos + monitorHeight-margin)) + { + glfwSetWindowPos(glfwWindow, static_cast(windowPosX), static_cast(windowPosY)); + foundValidMonitor = true; + foundMonitor = monitor; + break; + } + + } + } + } + + if (!foundValidMonitor) + { + msg_error("ImGuiGUIEngine") << "The window position from settings is invalid for any monitor."; + } + } + else + { + msg_error("ImGuiGUIEngine") << "Cannot set window position from settings."; + } + } + + if (!foundMonitor) + { + foundMonitor = glfwGetPrimaryMonitor(); + } + + return foundMonitor; +} + void ImGuiGUIEngine::beforeDraw(GLFWwindow*) { @@ -886,7 +894,7 @@ bool ImGuiGUIEngine::dispatchMouseEvents() } -void ImGuiGUIEngine::setScale(float globalScale, GLFWmonitor* monitor) +void ImGuiGUIEngine::setScale(float globalScale) { ImGuiIO& io = ImGui::GetIO(); io.FontGlobalScale = globalScale; diff --git a/SofaImGui/src/SofaImGui/ImGuiGUIEngine.h b/SofaImGui/src/SofaImGui/ImGuiGUIEngine.h index 5112649964..1421576ce6 100644 --- a/SofaImGui/src/SofaImGui/ImGuiGUIEngine.h +++ b/SofaImGui/src/SofaImGui/ImGuiGUIEngine.h @@ -62,7 +62,7 @@ class ImGuiGUIEngine : public sofaglfw::BaseGUIEngine bool dispatchMouseEvents() override; // apply global scale on the given monitor (if null, it will fetch the main monitor) - void setScale(float globalScale, GLFWmonitor* monitor); + void setScale(float globalScale); // reset counters void resetCounter() override; @@ -85,6 +85,7 @@ class ImGuiGUIEngine : public sofaglfw::BaseGUIEngine bool isMouseOnViewport { false }; CSimpleIniA ini; void resetView(ImGuiID dockspace_id, const char *windowNameSceneGraph, const char *winNameSelectionDescription, const char *windowNameLog, const char *windowNameViewport) ; + GLFWmonitor* findMyMonitor(GLFWwindow* glfwWindow); // WindowState members windows::WindowState winManagerProfiler; diff --git a/SofaImGui/src/SofaImGui/windows/Settings.cpp b/SofaImGui/src/SofaImGui/windows/Settings.cpp index 899084972e..ea7e541575 100644 --- a/SofaImGui/src/SofaImGui/windows/Settings.cpp +++ b/SofaImGui/src/SofaImGui/windows/Settings.cpp @@ -74,7 +74,7 @@ namespace windows constexpr float MAX_SCALE = 2.0f; ImGui::DragFloat("global scale", &globalScale, 0.005f, MIN_SCALE, MAX_SCALE, "%.2f", ImGuiSliderFlags_AlwaysClamp); // Scale everything - engine->setScale(globalScale, nullptr); + engine->setScale(globalScale); ini.SetDoubleValue("Visualization", "globalScale", static_cast(globalScale)); if (std::abs(iniGlobalScale - globalScale) > 0.005f) From c36a900ea4ee186e5969df9b390762c7311c94db Mon Sep 17 00:00:00 2001 From: Alex Bilger Date: Tue, 13 Jan 2026 12:02:01 +0100 Subject: [PATCH 3/3] reload fonts when content scale change --- SofaGLFW/src/SofaGLFW/BaseGUIEngine.h | 1 + SofaGLFW/src/SofaGLFW/SofaGLFWBaseGUI.cpp | 10 ++++ SofaGLFW/src/SofaGLFW/SofaGLFWBaseGUI.h | 1 + SofaImGui/src/SofaImGui/ImGuiGUIEngine.cpp | 53 +++++++++++++++------- SofaImGui/src/SofaImGui/ImGuiGUIEngine.h | 2 + 5 files changed, 51 insertions(+), 16 deletions(-) diff --git a/SofaGLFW/src/SofaGLFW/BaseGUIEngine.h b/SofaGLFW/src/SofaGLFW/BaseGUIEngine.h index 8a99fd0411..697381b761 100644 --- a/SofaGLFW/src/SofaGLFW/BaseGUIEngine.h +++ b/SofaGLFW/src/SofaGLFW/BaseGUIEngine.h @@ -50,6 +50,7 @@ class BaseGUIEngine virtual sofa::type::Vec2i getFrameBufferPixels(std::vector& pixels) = 0; virtual void openFile(SofaGLFWBaseGUI* baseGUI, sofa::core::sptr& groot) {}; virtual void loadFile(SofaGLFWBaseGUI* baseGUI, sofa::core::sptr& groot, std::string filePathName, bool reload = false) {}; + virtual void contentScaleChanged(float xscale, float yscale) {} }; } // namespace sofaglfw diff --git a/SofaGLFW/src/SofaGLFW/SofaGLFWBaseGUI.cpp b/SofaGLFW/src/SofaGLFW/SofaGLFWBaseGUI.cpp index 68ee16069e..bbba19867b 100644 --- a/SofaGLFW/src/SofaGLFW/SofaGLFWBaseGUI.cpp +++ b/SofaGLFW/src/SofaGLFW/SofaGLFWBaseGUI.cpp @@ -305,6 +305,7 @@ bool SofaGLFWBaseGUI::createWindow(int width, int height, const char* title, boo glfwSetCursorEnterCallback(glfwWindow, cursor_enter_callback); glfwSetMonitorCallback(monitor_callback); glfwSetCharCallback(glfwWindow, character_callback); + glfwSetWindowContentScaleCallback(glfwWindow, content_scale_callback); glfwSetWindowUserPointer(glfwWindow, this); @@ -995,6 +996,15 @@ void SofaGLFWBaseGUI::translateToViewportCoordinates (SofaGLFWBaseGUI* gui,doubl gui->m_translatedCursorPos = Vec2d{xpos, ypos} - (gui->m_viewPortPosition - gui->m_windowPosition); } +void SofaGLFWBaseGUI::content_scale_callback(GLFWwindow *window, float xscale, float yscale) +{ + auto currentGUI = s_mapGUIs[window]; + if (currentGUI && currentGUI->m_guiEngine) + { + currentGUI->m_guiEngine->contentScaleChanged(xscale, yscale); + } +} + void SofaGLFWBaseGUI::cursor_position_callback(GLFWwindow* window, double xpos, double ypos) { auto currentGUI = s_mapGUIs.find(window); diff --git a/SofaGLFW/src/SofaGLFW/SofaGLFWBaseGUI.h b/SofaGLFW/src/SofaGLFW/SofaGLFWBaseGUI.h index 83328d29b1..3bb8d86800 100644 --- a/SofaGLFW/src/SofaGLFW/SofaGLFWBaseGUI.h +++ b/SofaGLFW/src/SofaGLFW/SofaGLFWBaseGUI.h @@ -156,6 +156,7 @@ class SOFAGLFW_API SofaGLFWBaseGUI : public BaseViewer static void window_pos_callback(GLFWwindow* window, int xpos, int ypos); static int handleArrowKeys(int key); static void translateToViewportCoordinates (SofaGLFWBaseGUI* gui,double xpos, double ypos); + static void content_scale_callback(GLFWwindow* window, float xscale, float yscale); void makeCurrentContext(GLFWwindow* sofaWindow); void runStep(); diff --git a/SofaImGui/src/SofaImGui/ImGuiGUIEngine.cpp b/SofaImGui/src/SofaImGui/ImGuiGUIEngine.cpp index e7a9e3a088..ca0380966f 100644 --- a/SofaImGui/src/SofaImGui/ImGuiGUIEngine.cpp +++ b/SofaImGui/src/SofaImGui/ImGuiGUIEngine.cpp @@ -173,22 +173,7 @@ void ImGuiGUIEngine::initBackend(GLFWwindow* glfwWindow) glfwGetMonitorContentScale(windowMonitor, &xscale, &yscale); } - constexpr float fontSize = 16.f; - ImGuiIO& io = ImGui::GetIO(); - - io.Fonts->AddFontFromMemoryCompressedTTF(ROBOTO_MEDIUM_compressed_data, ROBOTO_MEDIUM_compressed_size, fontSize * yscale); - - ImFontConfig config; - config.MergeMode = true; - config.GlyphMinAdvanceX = fontSize * yscale; - - static const ImWchar icon_ranges[] = { ICON_MIN_FA, ICON_MAX_FA, 0 }; - io.Fonts->AddFontFromMemoryCompressedTTF(FA_REGULAR_400_compressed_data, FA_REGULAR_400_compressed_size, fontSize * yscale, &config, icon_ranges); - io.Fonts->AddFontFromMemoryCompressedTTF(FA_SOLID_900_compressed_data, FA_SOLID_900_compressed_size, fontSize * yscale, &config, icon_ranges); - - // restore the global scale stored in the Settings ini file - const float globalScale = static_cast(ini.GetDoubleValue("Visualization", "globalScale", 1.0)); - this->setScale(globalScale); + loadFont(yscale); const bool rememberWindowSize = ini.GetBoolValue("Window", "rememberWindowSize", true); if(rememberWindowSize) @@ -814,6 +799,38 @@ GLFWmonitor* ImGuiGUIEngine::findMyMonitor(GLFWwindow* glfwWindow) return foundMonitor; } +void ImGuiGUIEngine::loadFont(float yscale) +{ + constexpr float fontSize = 16.f; + + ImGuiIO& io = ImGui::GetIO(); + io.Fonts->Clear(); + + io.Fonts->AddFontFromMemoryCompressedTTF(ROBOTO_MEDIUM_compressed_data, ROBOTO_MEDIUM_compressed_size, fontSize * yscale); + + ImFontConfig config; + config.MergeMode = true; + config.GlyphMinAdvanceX = fontSize * yscale; + + static const ImWchar icon_ranges[] = { ICON_MIN_FA, ICON_MAX_FA, 0 }; + io.Fonts->AddFontFromMemoryCompressedTTF(FA_REGULAR_400_compressed_data, FA_REGULAR_400_compressed_size, fontSize * yscale, &config, icon_ranges); + io.Fonts->AddFontFromMemoryCompressedTTF(FA_SOLID_900_compressed_data, FA_SOLID_900_compressed_size, fontSize * yscale, &config, icon_ranges); + + // restore the global scale stored in the Settings ini file + const float globalScale = static_cast(ini.GetDoubleValue("Visualization", "globalScale", 1.0)); + this->setScale(globalScale); + + io.Fonts->Build(); + +#if SOFAIMGUI_FORCE_OPENGL2 == 1 + ImGui_ImplOpenGL2_DestroyFontsTexture(); + ImGui_ImplOpenGL2_CreateFontsTexture(); +#else + ImGui_ImplOpenGL3_DestroyFontsTexture(); + ImGui_ImplOpenGL3_CreateFontsTexture(); +#endif +} + void ImGuiGUIEngine::beforeDraw(GLFWwindow*) { @@ -893,6 +910,10 @@ bool ImGuiGUIEngine::dispatchMouseEvents() return !ImGui::GetIO().WantCaptureMouse || isMouseOnViewport; } +void ImGuiGUIEngine::contentScaleChanged(float xscale, float yscale) +{ + loadFont(yscale); +} void ImGuiGUIEngine::setScale(float globalScale) { diff --git a/SofaImGui/src/SofaImGui/ImGuiGUIEngine.h b/SofaImGui/src/SofaImGui/ImGuiGUIEngine.h index 1421576ce6..a2c2cb0ae4 100644 --- a/SofaImGui/src/SofaImGui/ImGuiGUIEngine.h +++ b/SofaImGui/src/SofaImGui/ImGuiGUIEngine.h @@ -60,6 +60,7 @@ class ImGuiGUIEngine : public sofaglfw::BaseGUIEngine void terminate() override; bool isTerminated() const override { return m_isTerminated; }; bool dispatchMouseEvents() override; + void contentScaleChanged(float xscale, float yscale) override; // apply global scale on the given monitor (if null, it will fetch the main monitor) void setScale(float globalScale); @@ -86,6 +87,7 @@ class ImGuiGUIEngine : public sofaglfw::BaseGUIEngine CSimpleIniA ini; void resetView(ImGuiID dockspace_id, const char *windowNameSceneGraph, const char *winNameSelectionDescription, const char *windowNameLog, const char *windowNameViewport) ; GLFWmonitor* findMyMonitor(GLFWwindow* glfwWindow); + void loadFont(float yscale); // WindowState members windows::WindowState winManagerProfiler;