improvements

This commit is contained in:
2026-08-11 17:35:26 +02:00
parent 39f925cb58
commit a868f50ab7
24 changed files with 924 additions and 239 deletions
+74 -13
View File
@@ -4,8 +4,8 @@ import Quickshell.Hyprland
import "root:/config"
import "root:/components"
// Focused window title, glitching on every change the way a Persona 5 caption
// snaps into place.
// Focused window title. Rapid application title churn is settled before it is
// painted, then the stable caption lands like a misregistered print layer.
Item {
id: root
@@ -19,7 +19,8 @@ Item {
&& (root.monitor === null || toplevel.monitor === null
|| toplevel.monitor.id === root.monitor.id)
readonly property string title: mine && toplevel.title ? toplevel.title : "—"
readonly property string incomingTitle: mine && toplevel.title ? toplevel.title : "—"
property string displayedTitle: "—"
// The bar shrinks this when the three clusters would otherwise collide.
property real maxWidth: 240
@@ -31,18 +32,60 @@ Item {
NumberAnimation { duration: Theme.durSlow; easing.type: Easing.OutExpo }
}
Marquee {
id: label
Item {
id: titleStage
anchors.fill: parent
text: root.title
color: root.mine ? Theme.subtext : Theme.muted
pixelSize: Theme.fsSmall
family: Theme.fontDisplay
italic: true
weight: Font.DemiBold
clip: true
Text {
id: label
anchors.verticalCenter: parent.verticalCenter
width: parent.width
text: root.displayedTitle
color: root.mine ? Theme.subtext : Theme.muted
elide: Text.ElideRight
font.pixelSize: Theme.fsSmall
font.family: Theme.fontDisplay
font.italic: true
font.weight: Font.DemiBold
renderType: Text.NativeRendering
}
// Crimson duplicate: visible only during the landing transition. The
// small opposing offset gives the title Persona's rough print snap
// without leaving permanent motion in the bar.
Text {
id: ghost
anchors.verticalCenter: parent.verticalCenter
width: parent.width
text: root.displayedTitle
color: Theme.accent
opacity: 0
elide: Text.ElideRight
font: label.font
renderType: Text.NativeRendering
}
}
onTitleChanged: flash.restart()
function commitTitle(): void {
if (root.displayedTitle === root.incomingTitle)
return;
root.displayedTitle = root.incomingTitle;
titleLanding.restart();
}
// Browser tabs, terminals and editors can update titles several times in a
// frame. Keep the old caption steady until the stream settles instead of
// restarting an animation for every intermediate value.
Timer {
id: titleSettle
interval: 120
repeat: false
onTriggered: root.commitTitle()
}
onIncomingTitleChanged: titleSettle.restart()
Component.onCompleted: displayedTitle = incomingTitle
// A quick crimson wipe under the title on focus change.
Rectangle {
@@ -55,7 +98,7 @@ Item {
}
SequentialAnimation {
id: flash
id: titleLanding
ParallelAnimation {
NumberAnimation {
target: wipe; property: "width"
@@ -66,6 +109,24 @@ Item {
target: wipe; property: "opacity"
from: 0; to: 1; duration: Theme.durFast
}
NumberAnimation {
target: label; property: "x"
from: -10; to: 0
duration: Theme.durBase; easing.type: Easing.OutBack
}
NumberAnimation {
target: label; property: "opacity"
from: 0.35; to: 1; duration: Theme.durFast
}
NumberAnimation {
target: ghost; property: "x"
from: 9; to: -3
duration: Theme.durBase; easing.type: Easing.OutExpo
}
NumberAnimation {
target: ghost; property: "opacity"
from: 0.8; to: 0; duration: Theme.durBase
}
}
NumberAnimation {
target: wipe; property: "opacity"