Merge pull request #327 from ouchihao/codex/fix-295-retained-dpi

fix(ui): refresh DPI when reusing render targets
This commit is contained in:
Neptrue_Lin authored and GitHub committed 2026-09-11 20:34:43 +08:00
commit 2b6bfafeec
3 files changed
+88

No files matched your search

+4
View File
@@ -78,6 +78,8 @@ bool DeviceResources::EnsureForWindow(HWND hwnd)
}
if (hwndRenderTarget_)
{
const FLOAT dpi = DpiForHwnd();
hwndRenderTarget_->SetDpi(dpi, dpi);
return true;
}
@@ -143,6 +145,8 @@ bool DeviceResources::EnsureForComposition(HWND hwnd)
if (composition_ && deviceContext_ && swapChain_ && pixelWidth_ >= width && pixelHeight_ >= height)
{
const FLOAT dpi = DpiForHwnd();
deviceContext_->SetDpi(dpi, dpi);
return true;
}
+1
View File
@@ -2,6 +2,7 @@ set(TEST_EXECUTABLE_NAME "msimeui-tests")
add_executable(${TEST_EXECUTABLE_NAME}
src/main.cpp
src/test_device_resources.cpp
src/test_fonts.cpp
src/test_layout.cpp
src/test_font_fallback.cpp
+83
View File
@@ -0,0 +1,83 @@
#include "tests/includes/test_framework.h"
#include "msimeui/DeviceResources.h"
#include <cmath>
#include <cstdio>
namespace
{
class HiddenWindow
{
public:
HiddenWindow()
{
REQUIRE(SUCCEEDED(CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED)));
hwnd = CreateWindowExW(WS_EX_NOREDIRECTIONBITMAP, L"STATIC", L"DPI resource test", WS_POPUP, 0, 0, 256, 128,
nullptr, nullptr, GetModuleHandleW(nullptr), nullptr);
REQUIRE(hwnd != nullptr);
}
~HiddenWindow()
{
DestroyWindow(hwnd);
CoUninitialize();
}
HWND hwnd = nullptr;
};
void CheckReusedTargetDpi(bool composition)
{
HiddenWindow window;
msimeui::DeviceResources resources;
const auto ensure = [&]() {
return composition ? resources.EnsureForComposition(window.hwnd) : resources.EnsureForWindow(window.hwnd);
};
REQUIRE(ensure());
ID2D1RenderTarget *const target = resources.GetRenderTarget();
REQUIRE(target != nullptr);
const float windowDpi = static_cast<float>(GetDpiForWindow(window.hwnd));
// Reproduce the retained render target from the previous monitor DPI without
// changing the user's display settings. Reuse must refresh DPI, not recreate it.
for (const float previousDpi : {windowDpi / 2.0f, 96.0f, 120.0f, 144.0f, 192.0f, windowDpi * 2.0f})
{
target->SetDpi(previousDpi, previousDpi);
REQUIRE(ensure());
REQUIRE(resources.GetRenderTarget() == target);
float dpiX = 0.0f;
float dpiY = 0.0f;
target->GetDpi(&dpiX, &dpiY);
std::printf("%s retained DPI %.0f -> window %.0f, target %.0f/%.0f\n", composition ? "composition" : "HWND",
previousDpi, windowDpi, dpiX, dpiY);
REQUIRE_NEAR(dpiX, windowDpi);
REQUIRE_NEAR(dpiY, windowDpi);
const D2D1_SIZE_F size = target->GetSize();
const D2D1_SIZE_U pixels = target->GetPixelSize();
REQUIRE_NEAR(size.width, pixels.width * 96.0f / windowDpi);
REQUIRE_NEAR(size.height, pixels.height * 96.0f / windowDpi);
}
// A smaller client area also reuses the larger composition surface.
REQUIRE(SetWindowPos(window.hwnd, nullptr, 0, 0, 128, 64, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE));
target->SetDpi(windowDpi * 1.25f, windowDpi * 1.25f);
REQUIRE(ensure());
REQUIRE(resources.GetRenderTarget() == target);
float dpiX = 0.0f;
float dpiY = 0.0f;
target->GetDpi(&dpiX, &dpiY);
REQUIRE_NEAR(dpiX, windowDpi);
REQUIRE_NEAR(dpiY, windowDpi);
}
} // namespace
TEST_CASE(hwnd_target_refreshes_dpi_when_reused)
{
CheckReusedTargetDpi(false);
}
TEST_CASE(composition_target_refreshes_dpi_when_reused)
{
CheckReusedTargetDpi(true);
}