From de4a2990a28caef66518831db62ac59d3df09d73 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 6 Aug 2026 22:12:39 +0200 Subject: [PATCH] Backends: Metal, Metal4: fixed resizing windows losing framebuffer scale. (#6828, #8856) Untested for Metal4 --- backends/imgui_impl_metal.mm | 23 ++++++++++++++++------- backends/imgui_impl_metal4.mm | 15 ++++++++------- docs/CHANGELOG.txt | 5 +++++ 3 files changed, 29 insertions(+), 14 deletions(-) diff --git a/backends/imgui_impl_metal.mm b/backends/imgui_impl_metal.mm index 926b75b49..dca2ab878 100644 --- a/backends/imgui_impl_metal.mm +++ b/backends/imgui_impl_metal.mm @@ -18,6 +18,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) // 2026-XX-XX: Metal: Added support for multiple windows via the ImGuiPlatformIO interface. +// 2026-08-06: Metal: fixed resizing windows losing framebuffer scale. (#6828, #8856) // 2026-04-28: Added support for standard draw callbacks (in platform_io): DrawCallback_SetSamplerLinear and DrawCallback_SetSamplerNearest. (#9378, #9381) // 2026-04-23: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState (others are not yet supported). (#9378) // 2026-04-14: Metal: use a dedicated bufferCacheLock to avoid crashing when bufferCache is replaced by a new object while being used for @synchronize(). (#9367) @@ -541,7 +542,15 @@ inline static CGSize MakeScaledSize(CGSize size, CGFloat scale) static void ImGui_ImplMetal_SetWindowSize(ImGuiViewport* viewport, ImVec2 size) { ImGuiViewportDataMetal* data = (ImGuiViewportDataMetal*)viewport->RendererUserData; - data->MetalLayer.drawableSize = MakeScaledSize(CGSizeMake(size.x, size.y), viewport->DpiScale); +#if 0 && TARGET_OS_OSX + void* handle = viewport->PlatformHandleRaw ? viewport->PlatformHandleRaw : viewport->PlatformHandle; + NSWindow* window = (__bridge NSWindow*)handle; + CGFloat scale = window.backingScaleFactor; + data->MetalLayer.contentsScale = scale; + data->MetalLayer.drawableSize = MakeScaledSize(CGSizeMake(size.x, size.y), scale); +#else + data->MetalLayer.drawableSize = MakeScaledSize(CGSizeMake(size.x, size.y), data->MetalLayer.contentsScale); +#endif } static void ImGui_ImplMetal_RenderWindow(ImGuiViewport* viewport, void*) @@ -561,12 +570,12 @@ static void ImGui_ImplMetal_RenderWindow(ImGuiViewport* viewport, void*) } data->FirstFrame = false; - float fb_scale = (float)window.backingScaleFactor; - if (data->MetalLayer.contentsScale != fb_scale) - { - data->MetalLayer.contentsScale = fb_scale; - data->MetalLayer.drawableSize = MakeScaledSize(window.frame.size, fb_scale); - } + // The layer is installed on the window's contentView; window.frame additionally includes the title bar. + CGFloat fb_scale = window.backingScaleFactor; + data->MetalLayer.contentsScale = fb_scale; + CGSize want_size = MakeScaledSize(window.contentView.bounds.size, fb_scale); + if (!CGSizeEqualToSize(data->MetalLayer.drawableSize, want_size)) + data->MetalLayer.drawableSize = want_size; #endif id drawable = [data->MetalLayer nextDrawable]; diff --git a/backends/imgui_impl_metal4.mm b/backends/imgui_impl_metal4.mm index 092be123a..6044c237b 100644 --- a/backends/imgui_impl_metal4.mm +++ b/backends/imgui_impl_metal4.mm @@ -21,6 +21,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2026-08-06: Metal 4: fixed resizing windows losing framebuffer scale. (#6828, #8856) // 2026-07-07: Metal 4: Added metal-cpp support. (#9461) // 2026-07-02: Metal 4: Added new Metal 4 backend implementation. (#9458) @@ -847,7 +848,7 @@ inline static CGSize MakeScaledSize(CGSize size, CGFloat scale) static void ImGui_ImplMetal_SetWindowSize(ImGuiViewport* viewport, ImVec2 size) { ImGuiViewportDataMetal* data = (ImGuiViewportDataMetal*)viewport->RendererUserData; - data->MetalLayer.drawableSize = MakeScaledSize(CGSizeMake(size.x, size.y), viewport->DpiScale); + data->MetalLayer.drawableSize = MakeScaledSize(CGSizeMake(size.x, size.y), data->MetalLayer.contentsScale); } static void ImGui_ImplMetal_RenderWindow(ImGuiViewport* viewport, void*) @@ -867,12 +868,12 @@ static void ImGui_ImplMetal_RenderWindow(ImGuiViewport* viewport, void*) } data->FirstFrame = false; - float fb_scale = (float)window.backingScaleFactor; - if (data->MetalLayer.contentsScale != fb_scale) - { - data->MetalLayer.contentsScale = fb_scale; - data->MetalLayer.drawableSize = MakeScaledSize(window.frame.size, fb_scale); - } + // The layer is installed on the window's contentView; window.frame additionally includes the title bar. + CGFloat fb_scale = window.backingScaleFactor; + data->MetalLayer.contentsScale = fb_scale; + CGSize want_size = MakeScaledSize(window.contentView.bounds.size, fb_scale); + if (!CGSizeEqualToSize(data->MetalLayer.drawableSize, want_size)) + data->MetalLayer.drawableSize = want_size; #endif id drawable = [data->MetalLayer nextDrawable]; diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 73b5bfdc1..b2a179c98 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -68,6 +68,11 @@ Other Changes: - SDL2+Metal: create Metal context without using a SDL_Renderer. - QNX+OpenGL3, QNX+Vulkan: added QNX Screen examples. (#9492) [@mgorchak-blackberry] +Docking+Viewports Branch: + +- Backends: + - Metal: fixed resizing windows losing framebuffer scale. (#6828, #8856) [@laikoken] + ----------------------------------------------------------------------- VERSION 1.92.9b (Released 2026-07-31)