From 04ce9ccbb4a1b4ee8ee1850f90af886412852b9f Mon Sep 17 00:00:00 2001 From: 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> Date: Thu, 14 Aug 2025 16:25:46 +1000 Subject: internal: better colourisation --- components/effects/ColouredIcon.qml | 83 ++++++++++++++++++++++ components/effects/Colouriser.qml | 4 +- modules/bar/components/OsIcon.qml | 11 +-- .../bar/components/workspaces/ActiveIndicator.qml | 1 + modules/dashboard/dash/User.qml | 9 +-- modules/lock/Fetch.qml | 10 +-- modules/lock/NotifGroup.qml | 16 ++--- modules/notifications/Notification.qml | 8 +-- 8 files changed, 100 insertions(+), 42 deletions(-) create mode 100644 components/effects/ColouredIcon.qml diff --git a/components/effects/ColouredIcon.qml b/components/effects/ColouredIcon.qml new file mode 100644 index 0000000..8ba6c5d --- /dev/null +++ b/components/effects/ColouredIcon.qml @@ -0,0 +1,83 @@ +pragma ComponentBehavior: Bound + +import Quickshell.Widgets +import QtQuick + +IconImage { + id: root + + required property color colour + property color sourceColour + property url lastSource + + asynchronous: true + + layer.enabled: true + layer.effect: Colouriser { + sourceColor: root.sourceColour + colorizationColor: root.colour + } + + layer.onEnabledChanged: { + if (layer.enabled) + canvas.requestPaint(); + } + + onStatusChanged: { + if (layer.enabled && status === Image.Ready) + canvas.requestPaint(); + } + + Canvas { + id: canvas + + property int retryCount + + implicitWidth: 32 + implicitHeight: 32 + visible: false + + onPaint: { + if (!root.layer.enabled) + return; + + const ctx = getContext("2d"); + ctx.reset(); + ctx.drawImage(root.backer, 0, 0, width, height); + + const colours = {} as Object; + const data = ctx.getImageData(0, 0, width, height).data; + + for (let i = 0; i < data.length; i += 4) { + if (data[i + 3] === 0) + continue; + + const c = `${data[i]},${data[i + 1]},${data[i + 2]}`; + if (colours.hasOwnProperty(c)) + colours[c]++; + else + colours[c] = 1; + } + + // Canvas is empty, try again next frame + if (retryCount < 5 && !Object.keys(colours).length) { + retryCount++; + Qt.callLater(() => requestPaint()); + return; + } + + let max = 0; + let maxColour = "0,0,0"; + for (const [colour, occurences] of Object.entries(colours)) { + if (occurences > max) { + max = occurences; + maxColour = colour; + } + } + + const [r, g, b] = maxColour.split(","); + root.sourceColour = Qt.rgba(r / 255, g / 255, b / 255, 1); + retryCount = 0; + } + } +} diff --git a/components/effects/Colouriser.qml b/components/effects/Colouriser.qml index b621ecd..bddf573 100644 --- a/components/effects/Colouriser.qml +++ b/components/effects/Colouriser.qml @@ -3,8 +3,10 @@ import QtQuick import QtQuick.Effects MultiEffect { + property color sourceColor: "black" + colorization: 1 - brightness: colorizationColor.hslLightness + brightness: 1 - sourceColor.hslLightness Behavior on colorizationColor { ColorAnimation { diff --git a/modules/bar/components/OsIcon.qml b/modules/bar/components/OsIcon.qml index 8418902..ed6da5d 100644 --- a/modules/bar/components/OsIcon.qml +++ b/modules/bar/components/OsIcon.qml @@ -1,15 +1,10 @@ import qs.components.effects import qs.services -import qs.utils import qs.config -import Quickshell.Widgets +import qs.utils -IconImage { +ColouredIcon { source: SysInfo.osLogo implicitSize: Appearance.font.size.large * 1.2 - - layer.enabled: true - layer.effect: Colouriser { - colorizationColor: Colours.palette.m3tertiary - } + colour: Colours.palette.m3tertiary } diff --git a/modules/bar/components/workspaces/ActiveIndicator.qml b/modules/bar/components/workspaces/ActiveIndicator.qml index b18cac2..3167d6e 100644 --- a/modules/bar/components/workspaces/ActiveIndicator.qml +++ b/modules/bar/components/workspaces/ActiveIndicator.qml @@ -51,6 +51,7 @@ StyledRect { Colouriser { source: root.mask + sourceColor: Colours.palette.m3onSurface colorizationColor: Colours.palette.m3onPrimary x: 0 diff --git a/modules/dashboard/dash/User.qml b/modules/dashboard/dash/User.qml index e45153e..ffdc72a 100644 --- a/modules/dashboard/dash/User.qml +++ b/modules/dashboard/dash/User.qml @@ -5,7 +5,6 @@ import qs.services import qs.config import qs.utils import Quickshell -import Quickshell.Widgets import QtQuick Row { @@ -119,7 +118,7 @@ Row { implicitWidth: icon.implicitWidth + text.width + text.anchors.leftMargin implicitHeight: Math.max(icon.implicitHeight, text.implicitHeight) - IconImage { + ColouredIcon { id: icon anchors.left: parent.left @@ -127,11 +126,7 @@ Row { source: SysInfo.osLogo implicitSize: Math.floor(Appearance.font.size.normal * 1.34) - - layer.enabled: true - layer.effect: Colouriser { - colorizationColor: Colours.palette.m3primary - } + colour: Colours.palette.m3primary } StyledText { diff --git a/modules/lock/Fetch.qml b/modules/lock/Fetch.qml index ce64c8c..8f82e88 100644 --- a/modules/lock/Fetch.qml +++ b/modules/lock/Fetch.qml @@ -1,12 +1,10 @@ pragma ComponentBehavior: Bound import qs.components -import qs.components.widgets import qs.components.effects import qs.services import qs.config import qs.utils -import Quickshell.Widgets import Quickshell.Services.UPower import QtQuick import QtQuick.Layouts @@ -149,15 +147,11 @@ ColumnLayout { visible: active } - component OsLogo: IconImage { + component OsLogo: ColouredIcon { source: SysInfo.osLogo implicitSize: height - asynchronous: true - + colour: Colours.palette.m3primary layer.enabled: Config.lock.recolourLogo || SysInfo.isDefaultLogo - layer.effect: Colouriser { - colorizationColor: Colours.palette.m3primary - } } component FetchText: MonoText { diff --git a/modules/lock/NotifGroup.qml b/modules/lock/NotifGroup.qml index b119503..9af3947 100644 --- a/modules/lock/NotifGroup.qml +++ b/modules/lock/NotifGroup.qml @@ -62,15 +62,11 @@ StyledRect { Component { id: appIconComp - IconImage { + ColouredIcon { implicitSize: Math.round(Config.notifs.sizes.image * 0.6) source: Quickshell.iconPath(root.appIcon) - asynchronous: true - + colour: root.urgency === "critical" ? Colours.palette.m3onError : root.urgency === "low" ? Colours.palette.m3onSurface : Colours.palette.m3onSecondaryContainer layer.enabled: root.appIcon.endsWith("symbolic") - layer.effect: Colouriser { - colorizationColor: root.urgency === "critical" ? Colours.palette.m3onError : root.urgency === "low" ? Colours.palette.m3onSurface : Colours.palette.m3onSecondaryContainer - } } } @@ -109,16 +105,12 @@ StyledRect { color: root.urgency === "critical" ? Colours.palette.m3error : root.urgency === "low" ? Colours.palette.m3surfaceContainerHighest : Colours.palette.m3secondaryContainer radius: Appearance.rounding.full - IconImage { + ColouredIcon { anchors.centerIn: parent implicitSize: Math.round(Config.notifs.sizes.badge * 0.6) source: Quickshell.iconPath(root.appIcon) - asynchronous: true - + colour: root.urgency === "critical" ? Colours.palette.m3onError : root.urgency === "low" ? Colours.palette.m3onSurface : Colours.palette.m3onSecondaryContainer layer.enabled: root.appIcon.endsWith("symbolic") - layer.effect: Colouriser { - colorizationColor: root.urgency === "critical" ? Colours.palette.m3onError : root.urgency === "low" ? Colours.palette.m3onSurface : Colours.palette.m3onSecondaryContainer - } } } } diff --git a/modules/notifications/Notification.qml b/modules/notifications/Notification.qml index 73bfce2..d1426fa 100644 --- a/modules/notifications/Notification.qml +++ b/modules/notifications/Notification.qml @@ -162,15 +162,11 @@ StyledRect { width: Math.round(parent.width * 0.6) height: Math.round(parent.width * 0.6) - sourceComponent: IconImage { + sourceComponent: ColouredIcon { anchors.fill: parent source: Quickshell.iconPath(root.modelData.appIcon) - asynchronous: true - + colour: root.modelData.urgency === NotificationUrgency.Critical ? Colours.palette.m3onError : root.modelData.urgency === NotificationUrgency.Low ? Colours.palette.m3onSurface : Colours.palette.m3onTertiaryContainer layer.enabled: root.modelData.appIcon.endsWith("symbolic") - layer.effect: Colouriser { - colorizationColor: root.modelData.urgency === NotificationUrgency.Critical ? Colours.palette.m3onError : root.modelData.urgency === NotificationUrgency.Low ? Colours.palette.m3onSurface : Colours.palette.m3onTertiaryContainer - } } } -- cgit v1.2.3-freya