Skip to content

Commit b4a2e9c

Browse files
authored
Merge pull request #54 from zao/fix/honor-dpi-override
fix: don't scale UI if user overrides scaling mode
2 parents 61477ee + d8c2c56 commit b4a2e9c

File tree

1 file changed

+66
-2
lines changed

1 file changed

+66
-2
lines changed

engine/system/win/sys_video.cpp

+66-2
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)