From 3e55dc3c043712109018232a2bb3e51bddfebed4 Mon Sep 17 00:00:00 2001 From: quadbyte Date: Mon, 18 Aug 2025 18:24:49 -0400 Subject: [PATCH] Settings/Display: Scaling per monitor \o/ --- Commons/Settings.qml | 6 ++- Modules/SettingsPanel/Tabs/DisplayTab.qml | 63 +++++++++++++++++++++-- Services/ScalingService.qml | 55 ++++---------------- 3 files changed, 74 insertions(+), 50 deletions(-) diff --git a/Commons/Settings.qml b/Commons/Settings.qml index bafd1d6..4c34668 100644 --- a/Commons/Settings.qml +++ b/Commons/Settings.qml @@ -185,7 +185,11 @@ Singleton { ui: JsonObject { property string fontFamily: "Roboto" // Family for all text - property list monitorsScale: [] + } + + // Scaling (not stored as JsonObject) + property var monitorsScaling: { + } // brightness diff --git a/Modules/SettingsPanel/Tabs/DisplayTab.qml b/Modules/SettingsPanel/Tabs/DisplayTab.qml index e9ed436..2a49a4f 100644 --- a/Modules/SettingsPanel/Tabs/DisplayTab.qml +++ b/Modules/SettingsPanel/Tabs/DisplayTab.qml @@ -7,7 +7,7 @@ import qs.Services import qs.Widgets Item { - property real scaling: 1 + readonly property real scaling: ScalingService.scale(screen) readonly property string tabIcon: "monitor" readonly property string tabLabel: "Display" readonly property int tabIndex: 5 @@ -72,7 +72,7 @@ Item { NText { text: (modelData.name || "Unknown") - font.pointSize: Style.fontSizeL * scaling + font.pointSize: Style.fontSizeXL * scaling font.weight: Style.fontWeightBold color: Color.mSecondary } @@ -80,7 +80,7 @@ Item { NText { text: `Resolution: ${modelData.width}x${modelData.height} - Position: (${modelData.x}, ${modelData.y})` font.pointSize: Style.fontSizeXS * scaling - color: Color.mOnSurface + color: Color.mOnSurfaceVariant } ColumnLayout { @@ -127,11 +127,66 @@ Item { } } } + + ColumnLayout { + spacing: Style.marginL * scaling + + RowLayout { + ColumnLayout { + spacing: Style.marginXXS * scaling + Layout.fillWidth: true + NText { + text: "Scaling" + font.pointSize: Style.fontSizeM * scaling + font.weight: Style.fontWeightBold + color: Color.mOnSurface + } + NText { + text: `Controls the scaling on this monitor.` + font.pointSize: Style.fontSizeS * scaling + color: Color.mOnSurfaceVariant + wrapMode: Text.WordWrap + Layout.fillWidth: true + } + } + NText { + text: `${Math.round(ScalingService.scaleByName(modelData.name) * 100)}%` + Layout.alignment: Qt.AlignVCenter + } + } + + RowLayout { + spacing: Style.marginS * scaling + NSlider { + id: scaleSlider + from: 0.6 + to: 1.8 + stepSize: 0.01 + value: ScalingService.scaleByName(modelData.name) + onPressedChanged: { + var data = Settings.data.monitorsScaling || {} + data[modelData.name] = value + Settings.data.monitorsScaling = data + } + Layout.fillWidth: true + } + + NIconButton { + icon: "refresh" + tooltipText: "Reset Scaling" + fontPointSize: Style.fontSizeL * scaling + onClicked: { + var data = Settings.data.monitorsScaling || {} + data[modelData.name] = 1.0 + Settings.data.monitorsScaling = data + } + } + } + } } } } } - Item { Layout.fillHeight: true } diff --git a/Services/ScalingService.qml b/Services/ScalingService.qml index 912cee5..42a5a65 100644 --- a/Services/ScalingService.qml +++ b/Services/ScalingService.qml @@ -1,62 +1,27 @@ pragma Singleton import Quickshell +import qs.Commons Singleton { id: root - // Manual override for testing UI scale across the whole shell - // Enable this from the DemoPanel slider - property bool overrideEnabled: false - property real overrideScale: 1.0 - - // Design reference resolution (for scale = 1.0) - readonly property int designScreenWidth: 2560 - readonly property int designScreenHeight: 1440 - // Automatic, orientation-agnostic scaling function scale(aScreen) { - // 0) Manual override (for development/testing) + return scaleByName(aScreen.name) + } + + function scaleByName(aScreenName) { try { - if (overrideEnabled && isFinite(overrideScale)) { - // Clamp to keep UI usable - const clamped = Math.max(0.6, Math.min(1.8, overrideScale)) - return clamped + if (Settings.data.monitorsScaling !== undefined) { + if (Settings.data.monitorsScaling[aScreenName] !== undefined) { + return Settings.data.monitorsScaling[aScreenName] + } } } catch (e) { - + Logger.warn(e) } - if (typeof aScreen !== 'undefined' & aScreen) { - - // // 1) Per-monitor override wins - // try { - // const overrides = Settings.data.ui.monitorsScale || {}; - // if (currentScreen && currentScreen.name && overrides[currentScreen.name] !== undefined) { - // const overrideValue = overrides[currentScreen.name] - // if (isFinite(overrideValue)) return overrideValue - // } - // } catch (e) { - // // ignore - // } - - // // 2) Fallback: scale by diagonal pixel count relative to design resolution - // try { - // const w = Math.max(1, currentScreen ? (currentScreen.width || 0) : 0) - // const h = Math.max(1, currentScreen ? (currentScreen.height || 0) : 0) - // if (w > 1 && h > 1) { - // const diag = Math.sqrt(w * w + h * h) - // const baseDiag = Math.sqrt(designScreenWidth * designScreenWidth + designScreenHeight * designScreenHeight) - // const ratio = diag / baseDiag - // // Clamp to a reasonable range for UI legibility - // return Math.max(0.9, Math.min(1.6, ratio)) - // } - // } catch (e) { - // // ignore and fall through - // } - } - - // 3) Safe default return 1.0 } }