Compare commits

...

2 commits

Author SHA1 Message Date
Damocles
a69507980b mpris menu: proper album art with gradient fade 2026-04-12 17:57:45 +02:00
Damocles
66dc628752 osd attached to triggering module position, per-screen filtering 2026-04-12 17:57:12 +02:00
5 changed files with 41 additions and 16 deletions

View file

@ -1,4 +1,5 @@
import QtQuick
import Quickshell
import Quickshell.Io
import "." as M
@ -11,7 +12,7 @@ M.BarSection {
property int percent: 0
onPercentChanged: if (percent > 0)
M.OsdState.show(percent / 100, "\uF185")
M.OsdState.show(percent / 100, "\uF185", root.mapToGlobal(root.width / 2, 0).x - (QsWindow.window?.screen?.x ?? 0), QsWindow.window?.screen ?? null)
Process {
id: adjProc

View file

@ -9,23 +9,35 @@ M.PopupPanel {
required property MprisPlayer player
// Album art placeholder (or real art if available)
Rectangle {
// Album art
Item {
width: menuWindow.panelWidth
height: 80
color: M.Theme.base02
radius: M.Theme.radius
height: _artImg.status === Image.Ready ? 140 : 60
clip: true
Rectangle {
anchors.fill: parent
color: M.Theme.base02
}
Image {
id: _artImg
anchors.fill: parent
source: menuWindow.player?.trackArtUrl ?? ""
fillMode: Image.PreserveAspectCrop
visible: status === Image.Ready
}
// Round top corners to match panel
layer.enabled: true
layer.effect: Item {
// simple clip the panel background behind handles the rounding
// Gradient fade at the bottom so art blends into the panel
Rectangle {
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
height: 40
visible: _artImg.visible
gradient: Gradient {
GradientStop { position: 0; color: "transparent" }
GradientStop { position: 1; color: M.Theme.base01 }
}
}
@ -36,7 +48,7 @@ M.PopupPanel {
color: M.Theme.base04
font.pixelSize: 28
font.family: M.Theme.iconFontFamily
visible: !menuWindow.player?.trackArtUrl
visible: _artImg.status !== Image.Ready
}
}

View file

@ -13,7 +13,7 @@ PanelWindow {
color: "transparent"
property bool _winVisible: false
property bool _shown: M.OsdState.visible
property bool _shown: M.OsdState.visible && M.OsdState.screen === root.screen
on_ShownChanged: {
if (_shown) {
@ -35,7 +35,10 @@ PanelWindow {
anchors.left: true
margins.top: 0
margins.left: Math.round((screen.width - implicitWidth) / 2)
margins.left: Math.max(0, Math.min(
Math.round(M.OsdState.itemX - implicitWidth / 2),
screen.width - implicitWidth
))
implicitWidth: 200
implicitHeight: 48

View file

@ -5,15 +5,19 @@ QtObject {
property bool visible: false
property real value: 0 // 0.01.0
property string icon: ""
property real itemX: 0
property var screen: null
property Timer _timer: Timer {
interval: 1500
onTriggered: visible = false
}
function show(val, ico) {
function show(val, ico, x, scr) {
value = val;
icon = ico;
itemX = x;
screen = scr;
visible = true;
_timer.restart();
}

View file

@ -1,4 +1,5 @@
import QtQuick
import Quickshell
import Quickshell.Services.Pipewire
import "." as M
@ -15,8 +16,12 @@ M.BarSection {
readonly property real volume: sink?.audio?.volume ?? 0
readonly property bool muted: sink?.audio?.muted ?? false
onVolumeChanged: M.OsdState.show(volume, root.muted ? "\uF026" : (volume > 0.5 ? "\uF028" : "\uF027"))
onMutedChanged: M.OsdState.show(volume, root.muted ? "\uF026" : (volume > 0.5 ? "\uF028" : "\uF027"))
function _showOsd() {
const ico = root.muted ? "\uF026" : (volume > 0.5 ? "\uF028" : "\uF027");
M.OsdState.show(volume, ico, root.mapToGlobal(root.width / 2, 0).x - (QsWindow.window?.screen?.x ?? 0), QsWindow.window?.screen ?? null);
}
onVolumeChanged: _showOsd()
onMutedChanged: _showOsd()
M.BarIcon {
icon: root.muted ? "\uF026" : (root.volume > 0.5 ? "\uF028" : (root.volume > 0 ? "\uF027" : "\uF026"))