Skip to content

Commit d8c2c56

Browse files
committed
fix: don't scale UI if user overrides scaling mode
Historically users could make PoB render at 100% scale on a machine that had higher display scaling factors by overriding the compatibility settings on the executable to indicate that DPI scaling should be done by "Application". As we're now DPI-aware the scaling setting does no longer enable that user intent as scaling is always done by the application. We can however still manually read out the override intent from the AppCompat registry keys to honor the user's old intent. This change checks both the machine and user registry keys for overrides and honors them in that order, if any.
1 parent c9e1865 commit d8c2c56

File tree

1 file changed

+66
-2
lines changed

1 file changed

+66
-2
lines changed

engine/system/win/sys_video.cpp

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ class sys_video_c : public sys_IVideo {
5151
sys_main_c* sys = nullptr;
5252

5353
bool initialised = false;
54+
bool ignoreDpiScale = false;
5455
GLFWwindow* wnd = nullptr;
5556

5657
void RefreshMonitorInfo();
@@ -278,6 +279,63 @@ struct sys_programIcons_c {
278279
std::deque<std::vector<uint8_t>> imageDatas;
279280
};
280281

282+
bool ShouldIgnoreDpiScale() {
283+
#ifdef _WIN32
284+
std::wstring const appChoice = L"HIGHDPIAWARE", sysChoice = L"DPIUNAWARE", enhanceFlag = L"GDIDPISCALING";
285+
std::wstring const subKey = LR"(Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers)";
286+
287+
std::vector<wchar_t> progStr(1 << 16);
288+
GetModuleFileNameW(NULL, progStr.data(), progStr.size());
289+
std::filesystem::path progPath(progStr.data());
290+
progPath = std::filesystem::canonical(progPath);
291+
292+
auto considerKey = [&](HKEY rootKey) -> std::optional<bool> {
293+
std::vector<wchar_t> valData(1 << 16);
294+
DWORD valType{}, valSize = valData.size() / 2;
295+
LRESULT res = RegGetValueW(rootKey, subKey.c_str(), progPath.wstring().c_str(), RRF_RT_REG_SZ, &valType, valData.data(), &valSize);
296+
if (res == ERROR_SUCCESS) {
297+
std::wstring val = valData.data();
298+
if (wcsstr(val.c_str(), appChoice.c_str())) {
299+
return true;
300+
}
301+
else if (wcsstr(val.c_str(), sysChoice.c_str())) {
302+
return false;
303+
}
304+
}
305+
return {};
306+
};
307+
308+
struct ScopedRegKey {
309+
HKEY key{};
310+
311+
ScopedRegKey& operator = (ScopedRegKey const&) = delete;
312+
ScopedRegKey(ScopedRegKey const&) = delete;
313+
~ScopedRegKey() {
314+
if (key) { RegCloseKey(key); }
315+
}
316+
317+
HKEY* operator & () { return &key; }
318+
operator HKEY () const { return key; }
319+
};
320+
321+
// Prioritize the global setting over the user setting to follow Windows' semantics.
322+
ScopedRegKey hklm{};
323+
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, nullptr, 0, KEY_READ, &hklm) == ERROR_SUCCESS) {
324+
if (auto ignore = considerKey(hklm)) {
325+
return *ignore;
326+
}
327+
}
328+
329+
ScopedRegKey hkcu{};
330+
if (RegOpenCurrentUser(KEY_READ, &hkcu) == ERROR_SUCCESS) {
331+
if (auto ignore = considerKey(hkcu)) {
332+
return *ignore;
333+
}
334+
}
335+
#endif
336+
return false;
337+
}
338+
281339
// ==================
282340
// System Video Class
283341
// ==================
@@ -383,6 +441,7 @@ int sys_video_c::Apply(sys_vidSet_s* set)
383441
}
384442
}
385443
else {
444+
ignoreDpiScale = ShouldIgnoreDpiScale();
386445
glfwWindowHint(GLFW_RESIZABLE, !!(cur.flags & VID_RESIZABLE));
387446
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); // Start hidden to not flash the user with a stock window.
388447
glfwWindowHint(GLFW_MAXIMIZED, GLFW_FALSE); // Start restored in order to position the window before maximizing.
@@ -551,7 +610,10 @@ int sys_video_c::Apply(sys_vidSet_s* set)
551610
});
552611
glfwSetWindowContentScaleCallback(wnd, [](GLFWwindow* wnd, float xScale, float yScale) {
553612
auto sys = (sys_main_c*)glfwGetWindowUserPointer(wnd);
554-
sys->video->vid.dpiScale = xScale;
613+
auto video = (sys_video_c*)sys->video;
614+
if (!video->ignoreDpiScale) {
615+
video->vid.dpiScale = xScale;
616+
}
555617
});
556618

557619
// Adjust window look and position
@@ -576,7 +638,9 @@ int sys_video_c::Apply(sys_vidSet_s* set)
576638

577639
glfwGetFramebufferSize(wnd, &vid.fbSize[0], &vid.fbSize[1]);
578640
glfwGetWindowSize(wnd, &vid.size[0], &vid.size[1]);
579-
glfwGetWindowContentScale(wnd, &sys->video->vid.dpiScale, nullptr);
641+
if (!ignoreDpiScale) {
642+
glfwGetWindowContentScale(wnd, &sys->video->vid.dpiScale, nullptr);
643+
}
580644

581645
initialised = true;
582646
return 0;

0 commit comments

Comments
 (0)