From 260c74b3e071a9ec97e5765e9535eca1da5b80ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Atoch?= Date: Sat, 2 Aug 2025 21:04:26 -0400 Subject: [PATCH 1/5] Improve images resizing quality accross the board - Using mipmap: true and smooth: true for images that are downscaled (avatar, icons, ...) - Using mipmap: false and smooth: true for images that are potentially upscaled (background, overview, ...) --- Bar/Modules/Applauncher.qml | 1 + Bar/Modules/CustomTrayMenu.qml | 2 ++ Bar/Modules/Media.qml | 1 + Bar/Modules/Taskbar.qml | 1 + Widgets/Dock.qml | 1 + Widgets/LockScreen/LockScreen.qml | 5 ++++- Widgets/Notification/NotificationPopup.qml | 1 + Widgets/Overview.qml | 1 + Widgets/Sidebar/Config/ProfileSettings.qml | 4 ++-- Widgets/Sidebar/Panel/Music.qml | 1 + Widgets/Sidebar/Panel/System.qml | 4 ++-- Widgets/Sidebar/Panel/WallpaperPanel.qml | 4 ++-- 12 files changed, 19 insertions(+), 7 deletions(-) diff --git a/Bar/Modules/Applauncher.qml b/Bar/Modules/Applauncher.qml index 4536c15..2012032 100644 --- a/Bar/Modules/Applauncher.qml +++ b/Bar/Modules/Applauncher.qml @@ -347,6 +347,7 @@ PanelWithOverlay { anchors.fill: parent fillMode: Image.PreserveAspectFit smooth: true + mipmap: true cache: false asynchronous: true source: modelData.isCalculator ? "qrc:/icons/calculate.svg" : Quickshell.iconPath(modelData.icon, "application-x-executable") diff --git a/Bar/Modules/CustomTrayMenu.qml b/Bar/Modules/CustomTrayMenu.qml index 5366d7f..58a9605 100644 --- a/Bar/Modules/CustomTrayMenu.qml +++ b/Bar/Modules/CustomTrayMenu.qml @@ -115,6 +115,8 @@ PopupWindow { Image { Layout.preferredWidth: 16 Layout.preferredHeight: 16 + smooth: true + mipmap: true source: modelData?.icon ?? "" visible: (modelData?.icon ?? "") !== "" fillMode: Image.PreserveAspectFit diff --git a/Bar/Modules/Media.qml b/Bar/Modules/Media.qml index ca30cd6..1014134 100644 --- a/Bar/Modules/Media.qml +++ b/Bar/Modules/Media.qml @@ -54,6 +54,7 @@ Item { anchors.margins: 1 fillMode: Image.PreserveAspectCrop smooth: true + mipmap: true cache: false asynchronous: true sourceSize.width: 24 diff --git a/Bar/Modules/Taskbar.qml b/Bar/Modules/Taskbar.qml index 46fd78b..f74b989 100644 --- a/Bar/Modules/Taskbar.qml +++ b/Bar/Modules/Taskbar.qml @@ -75,6 +75,7 @@ Item { anchors.centerIn: parent source: getAppIcon(modelData) smooth: true + mipmap: true visible: source.toString() !== "" } diff --git a/Widgets/Dock.qml b/Widgets/Dock.qml index 6684878..ce7f043 100644 --- a/Widgets/Dock.qml +++ b/Widgets/Dock.qml @@ -155,6 +155,7 @@ PanelWindow { anchors.centerIn: parent source: taskbar.getAppIcon(modelData) smooth: true + mipmap: true visible: source.toString() !== "" } diff --git a/Widgets/LockScreen/LockScreen.qml b/Widgets/LockScreen/LockScreen.qml index 1097c29..20e747e 100644 --- a/Widgets/LockScreen/LockScreen.qml +++ b/Widgets/LockScreen/LockScreen.qml @@ -135,7 +135,8 @@ WlSessionLock { fillMode: Image.PreserveAspectCrop source: WallpaperManager.currentWallpaper !== "" ? WallpaperManager.currentWallpaper : "" cache: true - smooth: false + smooth: true + mipmap: false visible: true // source for MultiEffect } @@ -168,6 +169,8 @@ WlSessionLock { fillMode: Image.PreserveAspectCrop visible: false asynchronous: true + mipmap: true + smooth: true } OpacityMask { anchors.fill: avatarImage diff --git a/Widgets/Notification/NotificationPopup.qml b/Widgets/Notification/NotificationPopup.qml index 42ad0ba..58214d7 100644 --- a/Widgets/Notification/NotificationPopup.qml +++ b/Widgets/Notification/NotificationPopup.qml @@ -130,6 +130,7 @@ PanelWindow { anchors.margins: 4 fillMode: Image.PreserveAspectFit smooth: true + mipmap: true cache: false asynchronous: true sourceSize.width: 36 diff --git a/Widgets/Overview.qml b/Widgets/Overview.qml index c23b79f..5607548 100644 --- a/Widgets/Overview.qml +++ b/Widgets/Overview.qml @@ -34,6 +34,7 @@ ShellRoot { source: wallpaperSource cache: true smooth: true + mipmap: false visible: wallpaperSource !== "" // Show the original for FastBlur input } MultiEffect { diff --git a/Widgets/Sidebar/Config/ProfileSettings.qml b/Widgets/Sidebar/Config/ProfileSettings.qml index eac4e30..2d135b5 100644 --- a/Widgets/Sidebar/Config/ProfileSettings.qml +++ b/Widgets/Sidebar/Config/ProfileSettings.qml @@ -70,8 +70,8 @@ Rectangle { visible: false asynchronous: true cache: false - sourceSize.width: 64 - sourceSize.height: 64 + smooth: true + mipmap: true } OpacityMask { diff --git a/Widgets/Sidebar/Panel/Music.qml b/Widgets/Sidebar/Panel/Music.qml index 553f3b3..be9ac82 100644 --- a/Widgets/Sidebar/Panel/Music.qml +++ b/Widgets/Sidebar/Panel/Music.qml @@ -93,6 +93,7 @@ Rectangle { anchors.margins: 2 fillMode: Image.PreserveAspectCrop smooth: true + mipmap: true cache: false asynchronous: true sourceSize.width: 60 diff --git a/Widgets/Sidebar/Panel/System.qml b/Widgets/Sidebar/Panel/System.qml index 2d8b96a..3e53cf6 100644 --- a/Widgets/Sidebar/Panel/System.qml +++ b/Widgets/Sidebar/Panel/System.qml @@ -60,8 +60,8 @@ Rectangle { fillMode: Image.PreserveAspectCrop asynchronous: true cache: false - sourceSize.width: 44 - sourceSize.height: 44 + smooth: true + mipmap: true } maskSource: Rectangle { width: 44 diff --git a/Widgets/Sidebar/Panel/WallpaperPanel.qml b/Widgets/Sidebar/Panel/WallpaperPanel.qml index aa444a5..932e776 100644 --- a/Widgets/Sidebar/Panel/WallpaperPanel.qml +++ b/Widgets/Sidebar/Panel/WallpaperPanel.qml @@ -137,8 +137,8 @@ PanelWindow { fillMode: Image.PreserveAspectCrop asynchronous: true cache: true - sourceSize.width: Math.min(width, 150) - sourceSize.height: Math.min(height, 90) + smooth: true + mipmap: true } MouseArea { anchors.fill: parent From 5f97b4217a13a987a7b9188fd7c670e6963a4872 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Atoch?= Date: Sat, 2 Aug 2025 22:26:32 -0400 Subject: [PATCH 2/5] Limit memory usage on wallpapers grid. for now --- Widgets/Sidebar/Panel/WallpaperPanel.qml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Widgets/Sidebar/Panel/WallpaperPanel.qml b/Widgets/Sidebar/Panel/WallpaperPanel.qml index 932e776..ec7a0b2 100644 --- a/Widgets/Sidebar/Panel/WallpaperPanel.qml +++ b/Widgets/Sidebar/Panel/WallpaperPanel.qml @@ -136,9 +136,12 @@ PanelWindow { source: modelData fillMode: Image.PreserveAspectCrop asynchronous: true - cache: true + cache: false smooth: true mipmap: true + // Limit memory usage + sourceSize.width: 480 + sourceSize.height: 270 } MouseArea { anchors.fill: parent From e2d02afc9abb2d86ead531b4c25af76297d1b35c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Atoch?= Date: Sat, 2 Aug 2025 22:34:21 -0400 Subject: [PATCH 3/5] Bring back the .min(). May save a few bytes with extremely small source images. Not sure why one would want to display tiny wallpapers, but you never know. --- Widgets/Sidebar/Panel/WallpaperPanel.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Widgets/Sidebar/Panel/WallpaperPanel.qml b/Widgets/Sidebar/Panel/WallpaperPanel.qml index ec7a0b2..dd6219a 100644 --- a/Widgets/Sidebar/Panel/WallpaperPanel.qml +++ b/Widgets/Sidebar/Panel/WallpaperPanel.qml @@ -140,8 +140,8 @@ PanelWindow { smooth: true mipmap: true // Limit memory usage - sourceSize.width: 480 - sourceSize.height: 270 + sourceSize.width: Math.min(width, 480) + sourceSize.height: Math.min(height, 270) } MouseArea { anchors.fill: parent From 2f14dba1442bf4f07981ae114ee138f6cef015ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Atoch?= Date: Sun, 3 Aug 2025 08:49:03 -0400 Subject: [PATCH 4/5] Replaced Image {} per IconImage {} where applicable --- Bar/Modules/ActiveWindow.qml | 5 ++- Bar/Modules/Applauncher.qml | 10 ++--- Bar/Modules/CustomTrayMenu.qml | 7 ++-- Bar/Modules/Media.qml | 3 +- Bar/Modules/Taskbar.qml | 2 - Components/Avatar.qml | 43 ++++++++++++++++++++++ Widgets/Background.qml | 1 + Widgets/Dock.qml | 2 - Widgets/LockScreen/LockScreen.qml | 38 +++---------------- Widgets/Notification/NotificationPopup.qml | 10 ++--- Widgets/Sidebar/Config/ProfileSettings.qml | 36 ++---------------- Widgets/Sidebar/Panel/System.qml | 34 +---------------- Widgets/Sidebar/Panel/WallpaperPanel.qml | 5 +-- 13 files changed, 69 insertions(+), 127 deletions(-) create mode 100644 Components/Avatar.qml diff --git a/Bar/Modules/ActiveWindow.qml b/Bar/Modules/ActiveWindow.qml index c01d58d..ab39551 100644 --- a/Bar/Modules/ActiveWindow.qml +++ b/Bar/Modules/ActiveWindow.qml @@ -1,9 +1,9 @@ import QtQuick import Quickshell -import qs.Components -import qs.Settings import Quickshell.Wayland import Quickshell.Widgets +import qs.Components +import qs.Settings PanelWindow { id: activeWindowPanel @@ -121,6 +121,7 @@ PanelWindow { source: ToplevelManager?.activeToplevel ? getIcon() : "" visible: Settings.settings.showActiveWindowIcon anchors.verticalCenterOffset: -3 + } Text { diff --git a/Bar/Modules/Applauncher.qml b/Bar/Modules/Applauncher.qml index 2012032..50085c2 100644 --- a/Bar/Modules/Applauncher.qml +++ b/Bar/Modules/Applauncher.qml @@ -3,9 +3,11 @@ import QtQuick.Controls import QtQuick.Layouts import Quickshell import Quickshell.Io +import Quickshell.Wayland +import Quickshell.Widgets import qs.Components import qs.Settings -import Quickshell.Wayland + import "../../Helpers/Fuzzysort.js" as Fuzzysort PanelWithOverlay { @@ -342,13 +344,9 @@ PanelWithOverlay { width: 28 height: 28 property bool iconLoaded: !modelData.isCalculator && iconImg.status === Image.Ready && iconImg.source !== "" && iconImg.status !== Image.Error - Image { + IconImage { id: iconImg anchors.fill: parent - fillMode: Image.PreserveAspectFit - smooth: true - mipmap: true - cache: false asynchronous: true source: modelData.isCalculator ? "qrc:/icons/calculate.svg" : Quickshell.iconPath(modelData.icon, "application-x-executable") visible: modelData.isCalculator || parent.iconLoaded diff --git a/Bar/Modules/CustomTrayMenu.qml b/Bar/Modules/CustomTrayMenu.qml index 58a9605..9d897f0 100644 --- a/Bar/Modules/CustomTrayMenu.qml +++ b/Bar/Modules/CustomTrayMenu.qml @@ -3,6 +3,7 @@ import QtQuick import QtQuick.Controls import QtQuick.Layouts import Quickshell +import Quickshell.Widgets import qs.Settings PopupWindow { @@ -112,14 +113,12 @@ PopupWindow { elide: Text.ElideRight } - Image { + IconImage { Layout.preferredWidth: 16 Layout.preferredHeight: 16 - smooth: true - mipmap: true source: modelData?.icon ?? "" visible: (modelData?.icon ?? "") !== "" - fillMode: Image.PreserveAspectFit + backer.fillMode: Image.PreserveAspectFit } } diff --git a/Bar/Modules/Media.qml b/Bar/Modules/Media.qml index 1014134..02fd372 100644 --- a/Bar/Modules/Media.qml +++ b/Bar/Modules/Media.qml @@ -2,6 +2,7 @@ import QtQuick import QtQuick.Controls import QtQuick.Layouts import Qt5Compat.GraphicalEffects +import Quickshell.Widgets import qs.Settings import qs.Services import qs.Components @@ -57,8 +58,6 @@ Item { mipmap: true cache: false asynchronous: true - sourceSize.width: 24 - sourceSize.height: 24 source: MusicManager.trackArtUrl visible: source.toString() !== "" diff --git a/Bar/Modules/Taskbar.qml b/Bar/Modules/Taskbar.qml index f74b989..8f716e6 100644 --- a/Bar/Modules/Taskbar.qml +++ b/Bar/Modules/Taskbar.qml @@ -74,8 +74,6 @@ Item { height: Math.max(12, Settings.settings.taskbarIconSize * 0.625) anchors.centerIn: parent source: getAppIcon(modelData) - smooth: true - mipmap: true visible: source.toString() !== "" } diff --git a/Components/Avatar.qml b/Components/Avatar.qml new file mode 100644 index 0000000..ab02589 --- /dev/null +++ b/Components/Avatar.qml @@ -0,0 +1,43 @@ +import QtQuick +import Qt5Compat.GraphicalEffects +import Quickshell +import Quickshell.Widgets +import qs.Settings + +Item { + anchors.fill: parent + + IconImage { + id: avatarImage + anchors.fill: parent + anchors.margins: 2 + source: "file://" + Settings.settings.profileImage + visible: false + asynchronous: true + backer.fillMode: Image.PreserveAspectCrop + } + + OpacityMask { + anchors.fill: avatarImage + source: avatarImage + maskSource: Rectangle { + width: avatarImage.width + height: avatarImage.height + radius: avatarImage.width / 2 + visible: false + } + visible: Settings.settings.profileImage !== "" + } + + // Fallback icon + Text { + anchors.centerIn: parent + text: "person" + font.family: "Material Symbols Outlined" + font.pixelSize: 24 + color: Theme.onAccent + visible: Settings.settings.profileImage === undefined || Settings.settings.profileImage === "" + z: 0 + } +} + diff --git a/Widgets/Background.qml b/Widgets/Background.qml index b8eb602..b4d5dca 100644 --- a/Widgets/Background.qml +++ b/Widgets/Background.qml @@ -35,6 +35,7 @@ ShellRoot { visible: wallpaperSource !== "" cache: true smooth: true + mipmap: false } } } diff --git a/Widgets/Dock.qml b/Widgets/Dock.qml index ce7f043..5dbcb5d 100644 --- a/Widgets/Dock.qml +++ b/Widgets/Dock.qml @@ -154,8 +154,6 @@ PanelWindow { height: Math.max(20, Settings.settings.taskbarIconSize * 0.75) anchors.centerIn: parent source: taskbar.getAppIcon(modelData) - smooth: true - mipmap: true visible: source.toString() !== "" } diff --git a/Widgets/LockScreen/LockScreen.qml b/Widgets/LockScreen/LockScreen.qml index 20e747e..b344b4d 100644 --- a/Widgets/LockScreen/LockScreen.qml +++ b/Widgets/LockScreen/LockScreen.qml @@ -3,10 +3,11 @@ import QtQuick.Layouts import QtQuick.Controls import QtQuick.Effects import Qt5Compat.GraphicalEffects -import Quickshell.Wayland import Quickshell import Quickshell.Services.Pam import Quickshell.Io +import Quickshell.Wayland +import Quickshell.Widgets import qs.Components import qs.Settings import qs.Services @@ -137,7 +138,6 @@ WlSessionLock { cache: true smooth: true mipmap: false - visible: true // source for MultiEffect } MultiEffect { @@ -161,36 +161,8 @@ WlSessionLock { radius: 40 color: Theme.accentPrimary - Image { - id: avatarImage - anchors.fill: parent - anchors.margins: 4 - source: Settings.settings.profileImage - fillMode: Image.PreserveAspectCrop - visible: false - asynchronous: true - mipmap: true - smooth: true - } - OpacityMask { - anchors.fill: avatarImage - source: avatarImage - maskSource: Rectangle { - width: avatarImage.width - height: avatarImage.height - radius: avatarImage.width / 2 - visible: false - } - visible: Settings.settings.profileImage !== "" - } - Text { - anchors.centerIn: parent - text: "person" - font.family: "Material Symbols Outlined" - font.pixelSize: 32 - color: Theme.onAccent - visible: Settings.settings.profileImage === "" - } + Avatar {} + layer.enabled: true layer.effect: Glow { color: Theme.accentPrimary @@ -339,7 +311,7 @@ WlSessionLock { } Rectangle { - width: infoColumn.width + 16 + width: infoColumn.width + 32 height: infoColumn.height + 8 color: (Theme.backgroundPrimary !== undefined && Theme.backgroundPrimary !== null) ? Theme.backgroundPrimary : "#222" anchors.horizontalCenter: parent.horizontalCenter diff --git a/Widgets/Notification/NotificationPopup.qml b/Widgets/Notification/NotificationPopup.qml index 58214d7..dbce771 100644 --- a/Widgets/Notification/NotificationPopup.qml +++ b/Widgets/Notification/NotificationPopup.qml @@ -1,6 +1,7 @@ import QtQuick import QtQuick.Controls import Quickshell +import Quickshell.Widgets import qs.Settings PanelWindow { @@ -124,17 +125,12 @@ PanelWindow { property var iconSources: [rawNotification?.image || "", rawNotification?.appIcon || "", rawNotification?.icon || ""] // Try to load notification icon - Image { + IconImage { id: iconImage anchors.fill: parent anchors.margins: 4 - fillMode: Image.PreserveAspectFit - smooth: true - mipmap: true - cache: false asynchronous: true - sourceSize.width: 36 - sourceSize.height: 36 + backer.fillMode: Image.PreserveAspectFit source: { for (var i = 0; i < iconBackground.iconSources.length; i++) { var icon = iconBackground.iconSources[i]; diff --git a/Widgets/Sidebar/Config/ProfileSettings.qml b/Widgets/Sidebar/Config/ProfileSettings.qml index 2d135b5..4a4bf7c 100644 --- a/Widgets/Sidebar/Config/ProfileSettings.qml +++ b/Widgets/Sidebar/Config/ProfileSettings.qml @@ -2,6 +2,8 @@ import QtQuick import QtQuick.Layouts import QtQuick.Controls import Qt5Compat.GraphicalEffects +import Quickshell.Widgets +import qs.Components import qs.Settings Rectangle { @@ -61,39 +63,7 @@ Rectangle { border.color: profileImageInput.activeFocus ? Theme.accentPrimary : Theme.outline border.width: 1 - Image { - id: avatarImage - anchors.fill: parent - anchors.margins: 2 - source: Settings.settings.profileImage - fillMode: Image.PreserveAspectCrop - visible: false - asynchronous: true - cache: false - smooth: true - mipmap: true - } - - OpacityMask { - anchors.fill: avatarImage - source: avatarImage - maskSource: Rectangle { - width: avatarImage.width - height: avatarImage.height - radius: avatarImage.width / 2 - visible: false - } - visible: Settings.settings.profileImage !== "" - } - - Text { - anchors.centerIn: parent - text: "person" - font.family: "Material Symbols Outlined" - font.pixelSize: 20 - color: Theme.accentPrimary - visible: Settings.settings.profileImage === "" - } + Avatar {} } Rectangle { diff --git a/Widgets/Sidebar/Panel/System.qml b/Widgets/Sidebar/Panel/System.qml index 3e53cf6..902874a 100644 --- a/Widgets/Sidebar/Panel/System.qml +++ b/Widgets/Sidebar/Panel/System.qml @@ -4,6 +4,7 @@ import QtQuick.Controls import Qt5Compat.GraphicalEffects import Quickshell import Quickshell.Io +import Quickshell.Widgets import qs.Settings import qs.Widgets import qs.Widgets.LockScreen @@ -51,38 +52,7 @@ Rectangle { z: 2 } - OpacityMask { - anchors.fill: parent - source: Image { - id: avatarImage - anchors.fill: parent - source: Settings.settings.profileImage !== undefined ? Settings.settings.profileImage : "" - fillMode: Image.PreserveAspectCrop - asynchronous: true - cache: false - smooth: true - mipmap: true - } - maskSource: Rectangle { - width: 44 - height: 44 - radius: 22 - visible: false - } - visible: Settings.settings.profileImage !== undefined && Settings.settings.profileImage !== "" - z: 1 - } - - // Fallback icon - Text { - anchors.centerIn: parent - text: "person" - font.family: "Material Symbols Outlined" - font.pixelSize: 24 - color: Theme.onAccent - visible: Settings.settings.profileImage === undefined || Settings.settings.profileImage === "" - z: 0 - } + Avatar {} } // User info text diff --git a/Widgets/Sidebar/Panel/WallpaperPanel.qml b/Widgets/Sidebar/Panel/WallpaperPanel.qml index dd6219a..932e776 100644 --- a/Widgets/Sidebar/Panel/WallpaperPanel.qml +++ b/Widgets/Sidebar/Panel/WallpaperPanel.qml @@ -136,12 +136,9 @@ PanelWindow { source: modelData fillMode: Image.PreserveAspectCrop asynchronous: true - cache: false + cache: true smooth: true mipmap: true - // Limit memory usage - sourceSize.width: Math.min(width, 480) - sourceSize.height: Math.min(height, 270) } MouseArea { anchors.fill: parent From ced3adcead663134ff3cf49d969225e87c3f2d78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Atoch?= Date: Sun, 3 Aug 2025 09:14:45 -0400 Subject: [PATCH 5/5] Bring back the sourceSize on wallpaper - got removed by mistake --- Widgets/Sidebar/Panel/WallpaperPanel.qml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Widgets/Sidebar/Panel/WallpaperPanel.qml b/Widgets/Sidebar/Panel/WallpaperPanel.qml index 932e776..3747452 100644 --- a/Widgets/Sidebar/Panel/WallpaperPanel.qml +++ b/Widgets/Sidebar/Panel/WallpaperPanel.qml @@ -139,6 +139,9 @@ PanelWindow { cache: true smooth: true mipmap: true + // Limit memory usage + sourceSize.width: 480 + sourceSize.height: 270 } MouseArea { anchors.fill: parent