From 6eba57730f52fdeec124e123a7b5334d82a1883b Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Fri, 8 Apr 2022 13:28:18 +0200 Subject: [PATCH] Dynamic DPI scaling (#1980) * DPI scaling 1. Add the ability to query the operating system's DPI scaling values 2. Expose those values through a new Lua function 3. Add an asset that sets the CEF gui and the Dashboard font sizes and placements based on the DPI scaling 4. Add that new asset into the base_blank asset * Add message when including the dpiscaling --- apps/OpenSpace/main.cpp | 31 +++++++++++++++++++ data/assets/base_blank.asset | 5 ++- data/assets/util/dpiscaling.asset | 37 +++++++++++++++++++++++ include/openspace/engine/windowdelegate.h | 2 ++ src/rendering/renderengine.cpp | 3 +- src/rendering/renderengine_lua.inl | 6 ++++ 6 files changed, 82 insertions(+), 2 deletions(-) create mode 100644 data/assets/util/dpiscaling.asset diff --git a/apps/OpenSpace/main.cpp b/apps/OpenSpace/main.cpp index 4e53181f64..b98fe3a5a2 100644 --- a/apps/OpenSpace/main.cpp +++ b/apps/OpenSpace/main.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -810,6 +811,36 @@ void setSgctDelegateFunctions() { vec2 scale = currentWindow->scale(); return glm::vec2(scale.x, scale.y); }; + sgctDelegate.osDpiScaling = []() { + ZoneScoped + + // Detect which DPI scaling to use + // 1. If there is a GUI window, use the GUI window's content scale value + const Window* dpiWindow = nullptr; + for (const std::unique_ptr& window : Engine::instance().windows()) { + if (window->hasTag("GUI")) { + dpiWindow = window.get(); + break; + } + } + + // 2. If there isn't a GUI window, use the first window's value + if (!dpiWindow) { + dpiWindow = Engine::instance().windows().front().get(); + } + + glm::vec2 scale = glm::vec2(1.f, 1.f); + glfwGetWindowContentScale(dpiWindow->windowHandle(), &scale.x, &scale.y); + + if (scale.x != scale.y) { + LWARNING(fmt::format( + "Non-square window scaling detected ({0}x{1}), using {0}x{0} instead", + scale.x, scale.y + )); + } + + return scale.x; + }; sgctDelegate.hasGuiWindow = []() { ZoneScoped diff --git a/data/assets/base_blank.asset b/data/assets/base_blank.asset index 5b771af9ab..4531f6b28b 100644 --- a/data/assets/base_blank.asset +++ b/data/assets/base_blank.asset @@ -5,13 +5,16 @@ local propertyHelper = asset.require("util/property_helper") -- Specifying which other assets should be loaded in this scene asset.require("spice/base") --- Load default key bindings applicable to most scenes asset.require("dashboard/default_dashboard") +-- Load default key bindings applicable to most scenes asset.require("util/default_keybindings") -- Load web gui local webGui = asset.require("util/webgui") +-- Scale the different UI components based on the operating system's DPI scaling value +asset.require("util/dpiscaling") + local toggle_trails = { Identifier = "os_default.toggle_trails", Name = "Toggle Trails", diff --git a/data/assets/util/dpiscaling.asset b/data/assets/util/dpiscaling.asset new file mode 100644 index 0000000000..11757e3809 --- /dev/null +++ b/data/assets/util/dpiscaling.asset @@ -0,0 +1,37 @@ +asset.onInitialize(function () + local scale = openspace.dpiScaling() + openspace.printInfo("Setting the DPI scaling factor to " .. tostring(scale)) + + + if openspace.modules.isLoaded("CefWebGui") then + openspace.setPropertyValueSingle( + "Modules.CefWebGui.GuiScale", + openspace.getPropertyValue("Modules.CefWebGui.GuiScale") * scale + ) + end + + local dashboards = openspace.getProperty("Dashboard.*.FontSize"); + for _, v in ipairs(dashboards) do + openspace.setPropertyValueSingle( + v, + openspace.getPropertyValue(v) * scale + ) + end + + local offset = openspace.getPropertyValue("Dashboard.StartPositionOffset") + openspace.setPropertyValueSingle( + "Dashboard.StartPositionOffset", + { offset[1] * scale, offset[2] * scale } + ) +end) + +asset.meta = { + Name = "DPI Scaling", + Version = "1.0", + Description = [[ Retrieves the DPI scaling from the operating system and applies it to + a few selected places to make them scale better on "large resolution but small size" + monitors ]], + Author = "OpenSpace Team", + URL = "http://openspaceproject.com", + License = "MIT license" +} diff --git a/include/openspace/engine/windowdelegate.h b/include/openspace/engine/windowdelegate.h index 2ebdb6853a..3a3e2d1768 100644 --- a/include/openspace/engine/windowdelegate.h +++ b/include/openspace/engine/windowdelegate.h @@ -64,6 +64,8 @@ struct WindowDelegate { glm::vec2 (*dpiScaling)() = []() { return glm::vec2(1.f); }; + float (*osDpiScaling)() = []() { return 1.f; }; + bool (*hasGuiWindow)() = []() { return false; }; bool (*isGuiWindow)() = []() { return false; }; diff --git a/src/rendering/renderengine.cpp b/src/rendering/renderengine.cpp index 06d7a6a3ab..cca003d0b9 100644 --- a/src/rendering/renderengine.cpp +++ b/src/rendering/renderengine.cpp @@ -1072,7 +1072,8 @@ scripting::LuaLibrary RenderEngine::luaLibrary() { { codegen::lua::AddScreenSpaceRenderable, codegen::lua::RemoveScreenSpaceRenderable, - codegen::lua::TakeScreenshot + codegen::lua::TakeScreenshot, + codegen::lua::DpiScaling } }; } diff --git a/src/rendering/renderengine_lua.inl b/src/rendering/renderengine_lua.inl index 86f8a70ff6..b37e6ad993 100644 --- a/src/rendering/renderengine_lua.inl +++ b/src/rendering/renderengine_lua.inl @@ -67,6 +67,12 @@ namespace { return static_cast(screenshotNumber); } +// Extracts the DPI scaling for either the GUI window or if there is no dedicated GUI +// window, the first window. +[[codegen::luawrap]] float dpiScaling() { + return openspace::global::windowDelegate->osDpiScaling(); +} + #include "renderengine_lua_codegen.cpp" } // namespace