From 7817e8a5560d6639e5ac7db0a2d570a6548cfcac Mon Sep 17 00:00:00 2001 From: LFRon Date: Tue, 22 Sep 2026 19:23:43 +0800 Subject: [PATCH] fix(xsettings): keep fractional DPI in Gdk/UnscaledDPI GTK and Electron/Chromium clients rendered fractional scales (125%) at 100%: treeland published Gdk/UnscaledDPI as the fixed 96 DPI base and kept the fractional part only in Xft/DPI, but GDK/GTK use Gdk/UnscaledDPI in preference to Xft/DPI. - GTK resolves gtk-xft-dpi from Gdk/UnscaledDPI first, so applications received 96 DPI at every scale. - Chromium (Electron) derives its X11 device scale factor from GTK's display config: max(1, gdk_monitor_get_scale_factor()) * gtk-xft-dpi / 1024 / 96. With the fixed base DPI it stayed at 1.0. Qt clients were unaffected because they read Xft/DPI directly. Publish the effective DPI divided by the integer window scaling factor in Gdk/UnscaledDPI, and clamp that factor to at least 1 so that a scale below 1 can not publish Gdk/WindowScalingFactor = 0. Integer scales keep their previous values (100% and 200% still use the 96 DPI base with the integer window scale), while 125% now publishes 120 DPI and restores 1.25 rendering in GTK and Electron/Chromium clients. Log: fractional scaling (e.g. 125%) works again in GTK and Electron/Chromium X11 clients Influence: XSETTINGS DPI values at fractional scales change; integer scales are unaffected --- src/xsettings/settingmanager.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/xsettings/settingmanager.cpp b/src/xsettings/settingmanager.cpp index bd01ef4e8..b6045fe2c 100644 --- a/src/xsettings/settingmanager.cpp +++ b/src/xsettings/settingmanager.cpp @@ -110,9 +110,17 @@ void SettingManager::setDoubleClickInterval(int interval) void SettingManager::setGlobalScale(qreal scale) { + const int windowScale = qMax(1, qFloor(scale)); + m_resource->setPropertyValue(XResource::toByteArray(XResource::Xft_DPI), scale * BASE_DPI); - m_settings->setPropertyValue(XSettings::toByteArray(XSettings::Gdk_WindowScalingFactor), qFloor(scale)); - m_settings->setPropertyValue(XSettings::toByteArray(XSettings::Gdk_UnscaledDPI), XSETTINGS_BASE_DPI_FIXED); + m_settings->setPropertyValue(XSettings::toByteArray(XSettings::Gdk_WindowScalingFactor), windowScale); + // Gdk/UnscaledDPI is defined as the DPI without the integer window scaling + // factor, but GDK/GTK (and Chromium through GTK's display config) prefer it + // over Xft/DPI. Keep the fractional part in it, otherwise GTK and Electron/ + // Chromium clients resolve to the base 96 DPI and ignore Xft/DPI entirely, + // so fractional scales end up rendered at 100%. + m_settings->setPropertyValue(XSettings::toByteArray(XSettings::Gdk_UnscaledDPI), + qRound(scale / windowScale * XSETTINGS_BASE_DPI_FIXED)); m_settings->setPropertyValue(XSettings::toByteArray(XSettings::Xft_DPI), qRound(scale * XSETTINGS_BASE_DPI_FIXED)); }