Skip to content

Conversation

Krasjet
Copy link

@Krasjet Krasjet commented Aug 18, 2022

The current framebuffer scaling for GLFW backend is obtained by dividing
the framebuffer size by window size, but this is unreliable and only
works on macOS.

On Windows, it is possible to let GLFW scale the framebuffer according
to monitor DPI (similar to macOS behavior) using the hint

glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE);

but unlike macOS, the window size and framebuffer size is always the
same on Windows. The automatic scaling scales both the framebuffer and
window size. The actual framebuffer scaling should be obtained from
glfwGetWindowContentScale. Try the following:

int w, h;
glfwGetWindowSize(win, &w, &h);
ImGui::Text("window size: %d %d", w, h);
glfwGetFramebufferSize(win, &w, &h);
ImGui::Text("framebuffer size: %d %d", w, h);
float x, y;
glfwGetWindowContentScale(win, &x, &y);
ImGui::Text("glfw scale: %f %f", x, y);

You should see both the window size and framebuffer size changes after
moving the window to a different DPI screen.

Therefore, the actual DisplaySize for ImGui should be computed by
framebuffer size divided by the content scale. Because GLFW mouse
position is based on window size, there is some additional mouse
position scaling that needs to be done.

The current framebuffer scaling for GLFW backend is obtained by dividing
the framebuffer size by window size, but this is unreliable and only
works on macOS.

On Windows, it is possible to let GLFW scale the framebuffer according
to monitor DPI (similar to macOS behavior) using the hint

```c
glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE);
```

but unlike macOS, the window size and framebuffer size is always the
same on Windows. The automatic scaling scales both the framebuffer and
window size. The actual framebuffer scaling should be obtained from
`glfwGetWindowContentScale`. Try the following:

```c
int w, h;
glfwGetWindowSize(win, &w, &h);
ImGui::Text("window size: %d %d", w, h);
glfwGetFramebufferSize(win, &w, &h);
ImGui::Text("framebuffer size: %d %d", w, h);
float x, y;
glfwGetWindowContentScale(win, &x, &y);
ImGui::Text("glfw scale: %f %f", x, y);
```

You should see both the window size and framebuffer size changes after
moving the window to a different DPI screen.

Therefore, the actual `DisplaySize` for ImGui should be computed by
framebuffer size divided by the content scale. Because GLFW mouse
position is based on window size, there is some additional mouse
position scaling that needs to be done.
@Krasjet
Copy link
Author

Krasjet commented Aug 18, 2022

I suspect the mouse position here also needs to be scaled, but I'm not familiar with the use case for this so I can't test it.

        if (io.WantSetMousePos)
            glfwSetCursorPos(bd->Window, (double)io.MousePos.x, (double)io.MousePos.y);

@ocornut
Copy link
Owner

ocornut commented May 5, 2025

Hello,

I am struggling to understand the relationship between the patch in imgui_impl_glfw.cpp and actual use of glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE);.

It seems like GLFW_SCALE_TO_MONITOR would have strictly no effect on the main code patched in imgui_impl_glfw.cpp.
Even though they both relate to scaling I don't see to see a connection or fix between one and the other thing. Can you clarify?

(About the changes in imgui_impl_glfw.cpp: we have dozens of issues/PR related to this for variety of backends. I will tackle this as as whole as there are challenges to handle this with multi-viewports + multi-monitors. Thanks!)

@Krasjet
Copy link
Author

Krasjet commented May 5, 2025

This is from a long time ago so my memory might be incorrect: you should be able to see the difference if you have two monitors of different scaling factor and move the window between them. GLFW_SCALE_TO_MONITOR should be necessary to report the scaling update.

ocornut added a commit that referenced this pull request May 15, 2025
…mebufferScale() + Backends: GLFW, SDL2, SDL3, Apple: added support. (#1065, #1542, #1676, #1786, #2826, #3757, #5081, #5580, #5592, #6465, #7273, #7779 etc.)

)

Metal backend is not in charge of writing to DpiScale/FramebufferScale (tho it was a neat workaround).
elbadcode added a commit to elbadcode/imgui that referenced this pull request Jul 3, 2025
* origin/docking-dev: (1059 commits)
  Backends: Vulkan: Fix failing assertion for platforms where viewports are not supported (ocornut#8734)
  Backends: GLFW: Fixed not installing WndProc hook in all GLFW version, so AddMouseSourceEvent() logic was missing for some viewports.
  Backends: GLFW: Fixed crash when using GLFW 3.3 (ocornut#8713, ocornut#8676, ocornut#8239, ocornut#8069)
  Backends: warning fixes (for docking branch).
  Backends: GLFW: amend for multi-context support with multi-viewport. (ocornut#8676, ocornut#8239, ocornut#8069)
  Backends: OSX: ImGui_ImplOSX_HandleEvent() only process event for window containing our viewports. Amend 7ac99a4 for docking. (ocornut#8644)
  Fixed duplicate symbols in some compile-time configurations.
  Fonts: Misc merge fixes.
  Examples: set ConfigDpiScaleFonts / ConfigDpiScaleViewports in all examples already setup for scaling.
  Backends: GLFW, SDL2, SDL3, update for docking to use helpers.
  (Breaking) renamed/moved ImGuiConfigFlags_DpiEnableScaleFonts -> ioConfigDpiScaleFonts, ImGuiConfigFlags_DpiEnableScaleViewports -> io.ConfigDpiScaleViewports
  Backends: Win32: Viewports: handle WM_DPICHANGED in backend when ImGuiConfigFlags_DpiEnableScaleViewports flag is enabled.
  Viewports: fixed handling of simultaneous move + resize (e.g. toggling maximized) when ImGuiConfigFlags_DpiEnableScaleViewports is enabled.
  Refactor: move SetCurrentFont(), PushFont(), PopFont() to a section.
  Platform IME: Fixed multi-viewports IME support, affecting SDL backends. (ocornut#8648, ocornut#8584, ocornut#7492, ocornut#6341)
  Viewports: added per-viewport FramebufferScale, Platform_GetWindowFramebufferScale() + Backends: GLFW, SDL2, SDL3, Apple: added support. (ocornut#1065, ocornut#1542, ocornut#1676, ocornut#1786, ocornut#2826, ocornut#3757, ocornut#5081, ocornut#5580, ocornut#5592, ocornut#6465, ocornut#7273, ocornut#7779 etc.) )
  Backends: OSX: rename internal struct for consistency with other backends.
  Viewports: fallback DpiScale pulled from fallback Monitor for consistency.
  Backends: Vulkan: fixed build with VK_NO_PROTOTYPES.
  Backends: Vulkan: fixed validation errors during window detach in multi-viewport mode. [docking branch amend] (ocornut#8600, ocornut#8176)
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants