diff --git a/Assets/Translations/de.json b/Assets/Translations/de.json index 16d3042d..b97c91b8 100644 --- a/Assets/Translations/de.json +++ b/Assets/Translations/de.json @@ -318,6 +318,10 @@ "floating-distance": { "label": "Dock-Schwebeabstand", "description": "Schwebeabstand vom Bildschirmrand anpassen." + }, + "colorize-icons": { + "label": "Symbole einfärben", + "description": "Theme-Farben auf Dock-App-Symbole anwenden (nur nicht fokussierte Apps)." } }, "monitors": { @@ -929,6 +933,10 @@ "width": { "description": "Steuert die horizontale Größe des Widgets.", "label": "Widget-Breite" + }, + "colorize-icons": { + "label": "Symbole einfärben", + "description": "Theme-Farben auf das aktive Fenster-Symbol anwenden." } }, "system-monitor": { @@ -1122,6 +1130,16 @@ "only-same-output": { "label": "Nur vom gleichen Bildschirm", "description": "Zeige nur Apps vom dem Bildschirm an, wo sich die Taskbar befindet." + }, + "colorize-icons": { + "label": "Symbole einfärben", + "description": "Theme-Farben auf Taskbar-Symbole anwenden." + } + }, + "tray": { + "colorize-icons": { + "label": "Symbole einfärben", + "description": "Theme-Farben auf Tray-Symbole anwenden." } } } diff --git a/Assets/Translations/en.json b/Assets/Translations/en.json index 41800513..1a0409a2 100644 --- a/Assets/Translations/en.json +++ b/Assets/Translations/en.json @@ -318,6 +318,10 @@ "floating-distance": { "label": "Dock floating distance", "description": "Adjust the floating distance from the screen edge." + }, + "colorize-icons": { + "label": "Colorize Icons", + "description": "Apply theme colors to dock app icons (non-focused apps only)." } }, "monitors": { @@ -912,6 +916,10 @@ "width": { "label": "Widget Width", "description": "Controls the horizontal size of the widget." + }, + "colorize-icons": { + "label": "Colorize Icons", + "description": "Apply theme colors to active window icon." } }, "system-monitor": { @@ -1105,6 +1113,16 @@ "only-same-output": { "label": "Only from same output", "description": "Show only apps from the output where the bar is located." + }, + "colorize-icons": { + "label": "Colorize Icons", + "description": "Apply theme colors to taskbar icons." + } + }, + "tray": { + "colorize-icons": { + "label": "Colorize Icons", + "description": "Apply theme colors to tray icons." } } } diff --git a/Assets/Translations/es.json b/Assets/Translations/es.json index 6602519f..10aa1ce5 100644 --- a/Assets/Translations/es.json +++ b/Assets/Translations/es.json @@ -318,6 +318,10 @@ "floating-distance": { "label": "Distancia de flotación del dock", "description": "Ajusta la distancia de flotación desde el borde de la pantalla." + }, + "colorize-icons": { + "label": "Colorear iconos", + "description": "Aplicar colores del tema a los iconos de aplicaciones del dock (solo aplicaciones no enfocadas)." } }, "monitors": { @@ -912,6 +916,10 @@ "width": { "description": "Controla el tamaño horizontal del widget.", "label": "Ancho del widget" + }, + "colorize-icons": { + "label": "Colorear iconos", + "description": "Aplicar colores del tema al icono de la ventana activa." } }, "system-monitor": { @@ -1105,6 +1113,16 @@ "only-same-output": { "description": "Muestra solo las aplicaciones del resultado donde se encuentra la barra.", "label": "Solo de la misma salida" + }, + "colorize-icons": { + "label": "Colorear iconos", + "description": "Aplicar colores del tema a los iconos de la barra de tareas." + } + }, + "tray": { + "colorize-icons": { + "label": "Colorear iconos", + "description": "Aplicar colores del tema a los iconos de la bandeja del sistema." } } } diff --git a/Assets/Translations/fr.json b/Assets/Translations/fr.json index d62cace9..004a1224 100644 --- a/Assets/Translations/fr.json +++ b/Assets/Translations/fr.json @@ -318,6 +318,10 @@ "floating-distance": { "label": "Distance de flottaison du dock", "description": "Ajustez la distance de flottaison par rapport au bord de l'écran." + }, + "colorize-icons": { + "label": "Coloriser les icônes", + "description": "Appliquer les couleurs du thème aux icônes d'applications du dock (applications non focalisées uniquement)." } }, "monitors": { @@ -912,6 +916,10 @@ "width": { "description": "Contrôle la taille horizontale du widget.", "label": "Largeur du widget" + }, + "colorize-icons": { + "label": "Coloriser les icônes", + "description": "Appliquer les couleurs du thème à l'icône de la fenêtre active." } }, "system-monitor": { @@ -1105,6 +1113,16 @@ "only-same-output": { "description": "Afficher uniquement les applications de la sortie où la barre est située.", "label": "Seulement à partir de la même sortie" + }, + "colorize-icons": { + "label": "Coloriser les icônes", + "description": "Appliquer les couleurs du thème aux icônes de la barre des tâches." + } + }, + "tray": { + "colorize-icons": { + "label": "Coloriser les icônes", + "description": "Appliquer les couleurs du thème aux icônes de la barre système." } } } diff --git a/Assets/Translations/pt.json b/Assets/Translations/pt.json index 25522957..03b3d37a 100644 --- a/Assets/Translations/pt.json +++ b/Assets/Translations/pt.json @@ -318,6 +318,10 @@ "floating-distance": { "label": "Distância de flutuação da dock", "description": "Ajuste a distância de flutuação da borda da tela." + }, + "colorize-icons": { + "label": "Colorir ícones", + "description": "Aplicar cores do tema aos ícones de aplicativos da dock (apenas aplicativos não focados)." } }, "monitors": { @@ -912,6 +916,10 @@ "width": { "description": "Controla o tamanho horizontal do widget.", "label": "Largura do Widget" + }, + "colorize-icons": { + "label": "Colorir ícones", + "description": "Aplicar cores do tema ao ícone da janela ativa." } }, "system-monitor": { @@ -1105,6 +1113,16 @@ "only-same-output": { "description": "Mostrar apenas os aplicativos da saída onde a barra está localizada.", "label": "Apenas da mesma saída" + }, + "colorize-icons": { + "label": "Colorir ícones", + "description": "Aplicar cores do tema aos ícones da barra de tarefas." + } + }, + "tray": { + "colorize-icons": { + "label": "Colorir ícones", + "description": "Aplicar cores do tema aos ícones da bandeja do sistema." } } } diff --git a/Assets/Translations/zh-CN.json b/Assets/Translations/zh-CN.json index 3bbe1d89..609bdb31 100644 --- a/Assets/Translations/zh-CN.json +++ b/Assets/Translations/zh-CN.json @@ -318,6 +318,10 @@ "floating-distance": { "label": "Dock 浮动距离", "description": "调整距离屏幕边缘的浮动距离。" + }, + "colorize-icons": { + "label": "着色图标", + "description": "将主题颜色应用到 Dock 应用图标(仅限非聚焦应用)。" } }, "monitors": { @@ -912,6 +916,10 @@ "width": { "description": "控制小部件的水平尺寸。", "label": "小部件宽度" + }, + "colorize-icons": { + "label": "着色图标", + "description": "将主题颜色应用到活动窗口图标。" } }, "system-monitor": { @@ -1105,6 +1113,16 @@ "only-same-output": { "label": "仅显示同屏幕", "description": "仅显示任务栏所在屏幕上的应用程序" + }, + "colorize-icons": { + "label": "着色图标", + "description": "将主题颜色应用到任务栏图标。" + } + }, + "tray": { + "colorize-icons": { + "label": "着色图标", + "description": "将主题颜色应用到系统托盘图标。" } } } diff --git a/Assets/settings-default.json b/Assets/settings-default.json index 9b63d3ae..55d8bf07 100644 --- a/Assets/settings-default.json +++ b/Assets/settings-default.json @@ -138,7 +138,8 @@ "floatingRatio": 1, "onlySameOutput": true, "monitors": [], - "pinnedApps": [] + "pinnedApps": [], + "colorizeIcons": false }, "network": { "wifiEnabled": true diff --git a/Commons/Settings.qml b/Commons/Settings.qml index af6c0598..676c4575 100644 --- a/Commons/Settings.qml +++ b/Commons/Settings.qml @@ -272,6 +272,7 @@ Singleton { property list monitors: [] // Desktop entry IDs pinned to the dock (e.g., "org.kde.konsole", "firefox.desktop") property list pinnedApps: [] + property bool colorizeIcons: false } // network diff --git a/Modules/Bar/Widgets/ActiveWindow.qml b/Modules/Bar/Widgets/ActiveWindow.qml index de10760d..817d7cc4 100644 --- a/Modules/Bar/Widgets/ActiveWindow.qml +++ b/Modules/Bar/Widgets/ActiveWindow.qml @@ -149,6 +149,15 @@ Item { asynchronous: true smooth: true visible: source !== "" + + // Apply dock shader to active window icon (always themed) + layer.enabled: widgetSettings.colorizeIcons !== false + layer.effect: ShaderEffect { + property color targetColor: Color.mOnSurface + property real colorizeMode: 0.0 // Dock mode (grayscale) + + fragmentShader: Qt.resolvedUrl(Quickshell.shellDir + "/Shaders/qsb/appicon_colorize.frag.qsb") + } } } @@ -315,6 +324,15 @@ Item { asynchronous: true smooth: true visible: source !== "" + + // Apply dock shader to active window icon (always themed) + layer.enabled: widgetSettings.colorizeIcons !== false + layer.effect: ShaderEffect { + property color targetColor: Color.mOnSurface + property real colorizeMode: 0.0 // Dock mode (grayscale) + + fragmentShader: Qt.resolvedUrl(Quickshell.shellDir + "/Shaders/qsb/appicon_colorize.frag.qsb") + } } } } diff --git a/Modules/Bar/Widgets/Taskbar.qml b/Modules/Bar/Widgets/Taskbar.qml index e9035002..6f1782f3 100644 --- a/Modules/Bar/Widgets/Taskbar.qml +++ b/Modules/Bar/Widgets/Taskbar.qml @@ -81,6 +81,15 @@ Rectangle { asynchronous: true opacity: modelData.isFocused ? Style.opacityFull : 0.6 + // Apply dock shader to all taskbar icons + layer.enabled: widgetSettings.colorizeIcons !== false + layer.effect: ShaderEffect { + property color targetColor: Color.mOnSurface + property real colorizeMode: 0.0 // Dock mode (grayscale) + + fragmentShader: Qt.resolvedUrl(Quickshell.shellDir + "/Shaders/qsb/appicon_colorize.frag.qsb") + } + Rectangle { anchors.bottomMargin: -2 * scaling anchors.bottom: parent.bottom diff --git a/Modules/Bar/Widgets/Tray.qml b/Modules/Bar/Widgets/Tray.qml index 0365cc2e..5237a82e 100644 --- a/Modules/Bar/Widgets/Tray.qml +++ b/Modules/Bar/Widgets/Tray.qml @@ -193,6 +193,14 @@ Rectangle { } opacity: status === Image.Ready ? 1 : 0 + layer.enabled: widgetSettings.colorizeIcons !== false + layer.effect: ShaderEffect { + property color targetColor: Color.mOnSurface + property real colorizeMode: 1.0 // Tray mode (intensity-based) + + fragmentShader: Qt.resolvedUrl(Quickshell.shellDir + "/Shaders/qsb/appicon_colorize.frag.qsb") + } + MouseArea { anchors.fill: parent hoverEnabled: true diff --git a/Modules/Dock/Dock.qml b/Modules/Dock/Dock.qml index b23c90bc..c0dd0a5a 100644 --- a/Modules/Dock/Dock.qml +++ b/Modules/Dock/Dock.qml @@ -401,6 +401,15 @@ Variants { scale: appButton.hovered ? 1.15 : 1.0 + // Apply dock-specific colorization shader only to non-focused apps + layer.enabled: !appButton.isActive && Settings.data.dock.colorizeIcons + layer.effect: ShaderEffect { + property color targetColor: Color.mOnSurface + property real colorizeMode: 0.0 // Dock mode (grayscale) + + fragmentShader: Qt.resolvedUrl(Quickshell.shellDir + "/Shaders/qsb/appicon_colorize.frag.qsb") + } + Behavior on scale { NumberAnimation { duration: Style.animationNormal diff --git a/Modules/Settings/Bar/WidgetSettings/ActiveWindowSettings.qml b/Modules/Settings/Bar/WidgetSettings/ActiveWindowSettings.qml index 3d1be163..81184595 100644 --- a/Modules/Settings/Bar/WidgetSettings/ActiveWindowSettings.qml +++ b/Modules/Settings/Bar/WidgetSettings/ActiveWindowSettings.qml @@ -18,6 +18,7 @@ ColumnLayout { property bool valueAutoHide: widgetData.autoHide !== undefined ? widgetData.autoHide : widgetMetadata.autoHide property string valueScrollingMode: widgetData.scrollingMode || widgetMetadata.scrollingMode property int valueWidth: widgetData.width !== undefined ? widgetData.width : widgetMetadata.width + property bool valueColorizeIcons: widgetData.colorizeIcons !== undefined ? widgetData.colorizeIcons : widgetMetadata.colorizeIcons function saveSettings() { var settings = Object.assign({}, widgetData || {}) @@ -25,6 +26,7 @@ ColumnLayout { settings.showIcon = valueShowIcon settings.scrollingMode = valueScrollingMode settings.width = parseInt(widthInput.text) || widgetMetadata.width + settings.colorizeIcons = valueColorizeIcons return settings } @@ -44,6 +46,14 @@ ColumnLayout { onToggled: checked => root.valueShowIcon = checked } + NToggle { + Layout.fillWidth: true + label: I18n.tr("bar.widget-settings.active-window.colorize-icons.label") + description: I18n.tr("bar.widget-settings.active-window.colorize-icons.description") + checked: root.valueColorizeIcons + onToggled: checked => root.valueColorizeIcons = checked + } + NTextInput { id: widthInput Layout.fillWidth: true diff --git a/Modules/Settings/Bar/WidgetSettings/TaskbarSettings.qml b/Modules/Settings/Bar/WidgetSettings/TaskbarSettings.qml index c80dd09f..5ff3b418 100644 --- a/Modules/Settings/Bar/WidgetSettings/TaskbarSettings.qml +++ b/Modules/Settings/Bar/WidgetSettings/TaskbarSettings.qml @@ -16,11 +16,13 @@ ColumnLayout { // Local state property bool valueOnlyActiveWorkspaces: widgetData.onlyActiveWorkspaces !== undefined ? widgetData.onlyActiveWorkspaces : widgetMetadata.onlyActiveWorkspaces property bool valueOnlySameOutput: widgetData.onlySameOutput !== undefined ? widgetData.onlySameOutput : widgetMetadata.onlySameOutput + property bool valueColorizeIcons: widgetData.colorizeIcons !== undefined ? widgetData.colorizeIcons : widgetMetadata.colorizeIcons function saveSettings() { var settings = Object.assign({}, widgetData || {}) settings.onlySameOutput = valueOnlySameOutput settings.onlyActiveWorkspaces = valueOnlyActiveWorkspaces + settings.colorizeIcons = valueColorizeIcons return settings } @@ -39,4 +41,12 @@ ColumnLayout { checked: root.valueOnlyActiveWorkspaces onToggled: checked => root.valueOnlyActiveWorkspaces = checked } + + NToggle { + Layout.fillWidth: true + label: I18n.tr("bar.widget-settings.taskbar.colorize-icons.label") + description: I18n.tr("bar.widget-settings.taskbar.colorize-icons.description") + checked: root.valueColorizeIcons + onToggled: checked => root.valueColorizeIcons = checked + } } diff --git a/Modules/Settings/Bar/WidgetSettings/TraySettings.qml b/Modules/Settings/Bar/WidgetSettings/TraySettings.qml index 25d08bce..d1f38261 100644 --- a/Modules/Settings/Bar/WidgetSettings/TraySettings.qml +++ b/Modules/Settings/Bar/WidgetSettings/TraySettings.qml @@ -5,12 +5,14 @@ import qs.Commons import qs.Widgets ColumnLayout { + id: root // Properties to receive data from parent property var widgetData: ({}) // Expected by BarWidgetSettingsDialog property var widgetMetadata: ({}) // Expected by BarWidgetSettingsDialog - // Local state for the blacklist + // Local state property var localBlacklist: widgetData.blacklist || [] + property bool valueColorizeIcons: widgetData.colorizeIcons !== undefined ? widgetData.colorizeIcons : widgetMetadata.colorizeIcons ListModel { id: blacklistModel @@ -27,6 +29,14 @@ ColumnLayout { spacing: Style.marginM * scaling + NToggle { + Layout.fillWidth: true + label: I18n.tr("bar.widget-settings.tray.colorize-icons.label") + description: I18n.tr("bar.widget-settings.tray.colorize-icons.description") + checked: root.valueColorizeIcons + onToggled: checked => root.valueColorizeIcons = checked + } + ColumnLayout { Layout.fillWidth: true spacing: Style.marginS * scaling @@ -135,6 +145,7 @@ ColumnLayout { // Return the updated settings for this widget instance var settings = Object.assign({}, widgetData || {}) settings.blacklist = newBlacklist + settings.colorizeIcons = root.valueColorizeIcons return settings } } diff --git a/Modules/Settings/Tabs/DockTab.qml b/Modules/Settings/Tabs/DockTab.qml index 5d31c074..d272aacf 100644 --- a/Modules/Settings/Tabs/DockTab.qml +++ b/Modules/Settings/Tabs/DockTab.qml @@ -93,6 +93,20 @@ ColumnLayout { Layout.bottomMargin: Style.marginXL * scaling } + NToggle { + Layout.fillWidth: true + label: I18n.tr("settings.dock.appearance.colorize-icons.label") + description: I18n.tr("settings.dock.appearance.colorize-icons.description") + checked: Settings.data.dock.colorizeIcons + onToggled: checked => Settings.data.dock.colorizeIcons = checked + } + + NDivider { + Layout.fillWidth: true + Layout.topMargin: Style.marginXL * scaling + Layout.bottomMargin: Style.marginXL * scaling + } + // Monitor Configuration ColumnLayout { spacing: Style.marginM * scaling diff --git a/Services/BarWidgetRegistry.qml b/Services/BarWidgetRegistry.qml index efb85537..f2809e14 100644 --- a/Services/BarWidgetRegistry.qml +++ b/Services/BarWidgetRegistry.qml @@ -43,7 +43,8 @@ Singleton { "showIcon": true, "autoHide": false, "scrollingMode": "hover", - "width": 145 + "width": 145, + "colorizeIcons": false }, "Battery": { "allowUserSettings": true, @@ -114,11 +115,13 @@ Singleton { "Taskbar": { "allowUserSettings": true, "onlySameOutput": true, - "onlyActiveWorkspaces": true + "onlyActiveWorkspaces": true, + "colorizeIcons": false }, "Tray": { "allowUserSettings": true, - "blacklist": [] + "blacklist": [], + "colorizeIcons": false }, "Workspace": { "allowUserSettings": true, diff --git a/Shaders/frag/appicon_colorize.frag b/Shaders/frag/appicon_colorize.frag new file mode 100644 index 00000000..ae108701 --- /dev/null +++ b/Shaders/frag/appicon_colorize.frag @@ -0,0 +1,29 @@ +#version 450 +layout(location = 0) in vec2 qt_TexCoord0; +layout(location = 0) out vec4 fragColor; +layout(binding = 1) uniform sampler2D source; +layout(std140, binding = 0) uniform buf { + mat4 qt_Matrix; + float qt_Opacity; + vec4 targetColor; + float colorizeMode; // 0.0 = dock mode (grayscale), 1.0 = tray mode (intensity) +} ubuf; + +void main() { + vec4 tex = texture(source, qt_TexCoord0); + + float intensity; + + if (ubuf.colorizeMode < 0.5) { + // Dock mode: Convert to grayscale using proper luminance weights + intensity = dot(tex.rgb, vec3(0.299, 0.587, 0.114)); + } else { + // Tray mode: Use the maximum RGB channel value as intensity + intensity = max(max(tex.r, tex.g), tex.b); + + // Normalize intensity to make all icons more uniform + intensity = smoothstep(0.1, 0.9, intensity); + } + + fragColor = vec4(ubuf.targetColor.rgb * intensity, tex.a) * ubuf.qt_Opacity; +} diff --git a/Shaders/qsb/appicon_colorize.frag.qsb b/Shaders/qsb/appicon_colorize.frag.qsb new file mode 100644 index 00000000..15618b86 Binary files /dev/null and b/Shaders/qsb/appicon_colorize.frag.qsb differ