ocornut / imgui

Dear ImGui: Bloat-free Graphical User interface for C++ with minimal dependencies
MIT License
57.74k stars 9.9k forks source link

ViewPort scaling messed up on secondary screen with different scaling #7689

Open BraunSilas opened 2 weeks ago

BraunSilas commented 2 weeks ago

Version/Branch of Dear ImGui:

V1.90.8 Branch Docking

Back-ends:

glfw glad

Compiler, OS:

Windows 10 + CLion + Bundled MinGW

Full config/build information:

No response

Details:

I am using ImGui (Branch: Docking) and attempting to use it to dock and with multiple viewports.

I did not used the example project as guide but only took the parts that worked with by libs.

I was able to get it running pretty smoothly, but once I drag an ImGui Winodw on its own onto another screen, the scalling breaks, [image 1] This does not happen with a Windows window or if the ImGui window is in a Windows window.

But I am still able to change the size of the ImGui window and once I do that all Widgets jump back to where they belong to. [image 2]

But once I drag the window back onto the MainScreen this happens. [image 3] My mouse is not highlighting the widget when it is on top of them. in the image imagine the top red circle being my cursor and the bottom circle indicating the higlighted widget.

However if I now drop the imgui window (including black padding) into the Windows window it snaps back and the black padding disapears and my mouse highlights the correct widgets again.

I also think that the font size in the imgui window differs between the 2 screen.

In the Windows setting I see: main screen: 150% scale and 3840 2160 secondary screen: 100% scale and 1080 1920

And I just tested setting the scaling of the secondary screen to 150%

and it fixed it. any Tips how I can adjust my window to the scale?

Thank you for your support

Screenshots/Video:

image 1 image 2 image 3

Minimal, Complete and Verifiable Example code:


#include "imgui.h"
#include "imgui_impl_glfw.h"
#include "imgui_impl_opengl3.h"

#include "glad/glad.h" // this come form OpenGL Course free COde Camp min1 - glad.dav1d.de
#include <GLFW/glfw3.h>
#include "iostream"

int main(void)
{
    glfwInit();

    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);//only modern functions

    GLFWwindow* window = glfwCreateWindow(800,800,"OpenGL", NULL, NULL);

    if(!window){
        std::cout << "Failed to create GLFW Window!" << std::endl;
        glfwTerminate();
        return -1;
    }

    glfwMakeContextCurrent(window);
    glfwSwapInterval(1);//enable Vsync
    gladLoadGL();

    IMGUI_CHECKVERSION();
    ImGui::CreateContext();
    ImGuiIO& io = ImGui::GetIO(); (void) io;
    io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;     // Enable Keyboard Controls
    io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;      // Enable Gamepad Controls
    io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;         // Enable Docking
    io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;       // Enable Multi-Viewport / 

    ImGui::StyleColorsDark();

    ImGuiStyle& style = ImGui::GetStyle();
    if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable){
        style.WindowRounding = 0.0f;
        style.Colors[ImGuiCol_WindowBg].w = 1.0f;
    }

    ImGui_ImplGlfw_InitForOpenGL(window, true);
    ImGui_ImplOpenGL3_Init("#version 330");

    // Our state
    bool show_demo_window = true;
    bool show_another_window = false;
    ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);

    while(!glfwWindowShouldClose(window)){

        glfwPollEvents();

        ImGui_ImplOpenGL3_NewFrame();
        ImGui_ImplGlfw_NewFrame();
        ImGui::NewFrame();

        ImGui::ShowDemoWindow();

        ImGui::Render();
        int display_w, display_h;
        glfwGetFramebufferSize(window, &display_w, &display_h);
        glViewport(0, 0, 800, 800);
        glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w);
        glClear(GL_COLOR_BUFFER_BIT);
        ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());

        if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable){
            GLFWwindow* backup_current_context = glfwGetCurrentContext();
            ImGui::UpdatePlatformWindows();
            ImGui::RenderPlatformWindowsDefault();
            glfwMakeContextCurrent(backup_current_context);
        }

        glfwSwapBuffers(window);
    }

    ImGui_ImplOpenGL3_Shutdown();
    ImGui_ImplGlfw_Shutdown();
    ImGui::DestroyContext();

    glfwDestroyWindow(window);
    glfwTerminate();

    return 0;
}
BraunSilas commented 2 weeks ago

I have seen #6444 but It don't see what I need to do?

BraunSilas commented 2 weeks ago

I also found this: https://github.com/ocornut/imgui/blob/master/docs/FAQ.md#q-how-should-i-handle-dpi-in-my-application

BraunSilas commented 2 weeks ago

What I understand is: for each view port I need to check the scale and then switch the fontsize. But how can get the specific scale of a specific window/viewport? I would imagine that at every Begin() I can check the scale and then insert a function that assignes the correct font size regarding the scale. I just don't understand how I know which scal belongs to which Imgui Window

the-loki commented 3 days ago

Reason:

I discovered the root cause of this issue, as you mentioned, is due to different monitors' DPI scaling. When using GLFW with the docking version of ImGui and disabling the system window decoration, this issue arises. The reason is that in this setting, window movement uses glfwSetWindowPos (this is also the case when the number of viewports is greater than one). When the window crosses monitors with different DPI scaling, GLFW triggers a DPI change event and updates the window size. The new size triggers a GLFW resize event. The problem is that the resize event triggered by glfwSetWindowPos happens in the same frame, and the viewport's PlatformRequestResize is cleared without being used after being set, causing the issue.

However, when enabling the system window decoration, the window size is also updated, but the new size recommended by the system does not trigger a GLFW resize event, so the issue does not occur with system window decoration enabled.

Temporary workaround: You can actively set the window size when the DPI changes to solve the issue, as long as it triggers a window size change.

Suggested fix: Consider detecting the usage of the viewport's PlatformRequestResize parameter when enabling ImGuiConfigFlags_ViewportsEnable. If it is not used, retain it until the next frame instead of clearing it.

BraunSilas commented 2 days ago

Hey @the-loki, thanks for helping me. I can also see that you made a merge request to @ocornut. The diff look doesn't look too complicated. Do you think it is save to just apply that to my project backend? Did @ocornut say anything to it.

But to apply the workaround u suggested I would need a little more specific help. Could you share a minimal viable solution? Cause I don't fully understand that side of IMGUI yet?

the-loki commented 1 day ago

Hey @the-loki, thanks for helping me. I can also see that you made a merge request to @ocornut. The diff look doesn't look too complicated. Do you think it is save to just apply that to my project backend? Did @ocornut say anything to it.嘿,谢谢你帮助我。我还可以看到您向 .差异外观看起来并不太复杂。你认为把它应用到我的项目后端是保存的吗?确实对它说了什么。

But to apply the workaround u suggested I would need a little more specific help.但是要应用您建议的解决方法,我需要更具体的帮助。 Could you share a minimal viable solution?您能分享一个最小的可行解决方案吗? Cause I don't fully understand that side of IMGUI yet?因为我还不完全理解IMGUI的那一面?

Since I have only recently started using ImGui, to minimize the impact, I have only made modifications to GLFW. However, I still cannot guarantee whether there are other impacts; this depends on @ocornut 's perspective.

Additionally, if you want to address this issue without modifying the GLFW backend, you can consider handling it in your application by actively monitoring changes in DPI scaling and triggering window size adjustments accordingly.

You need two variables to save window size and dpi scale:

YoloMouse_zd1NErPztg

and use window like this:

image

This is a provisional code that has not yet been tested, but it may help you solve the problem without updating ImGui.