Add a coffee break

Every so often a mug appears at the cat's nose, it sits down, dips its head in
and takes a few slow sips while steam rises. M01, optional stop.

The mug lives in its own click-through window like the chip, or inside the
overlay on Wayland. It goes away as soon as the cat is petted, dragged, sent to
sleep or moves on to something else, so no mug is ever left standing.

Also renames OverlayWindow's mode flag, which shadowed QWindow::active.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
JulianandClaude Opus 5 committed 2026-09-10 23:00:22 +02:00
1 parent 0f1df75a1d
commit 403ac30b3a
14 files changed
+283 -18

No files matched your search

+109
View File
@@ -0,0 +1,109 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Shapes
// A mug of coffee with steam. Design space is 44 x 52 units, mug on the ground.
Item {
id: cup
readonly property real unit: width / 44
implicitWidth: 44
implicitHeight: 52
Item {
width: 44
height: 52
transformOrigin: Item.TopLeft
scale: cup.unit
Rectangle { // ground shadow
x: 8; y: 46
width: 26; height: 5
radius: 2.5
color: "#000000"
opacity: 0.18
antialiasing: true
}
// steam
Repeater {
model: 3
Shape {
id: wisp
required property int index
x: 10 + index * 7
y: 2
width: 8
height: 16
opacity: 0
preferredRendererType: Shape.CurveRenderer
ShapePath {
strokeColor: "#ffffff"
strokeWidth: 1.8
capStyle: ShapePath.RoundCap
fillColor: "transparent"
startX: 4; startY: 15
PathQuad { controlX: 0; controlY: 10; x: 4; y: 7 }
PathQuad { controlX: 8; controlY: 4; x: 4; y: 0 }
}
SequentialAnimation {
running: true
loops: Animation.Infinite
PauseAnimation { duration: wisp.index * 600 }
ParallelAnimation {
NumberAnimation { target: wisp; property: "opacity"; from: 0; to: 0.55; duration: 700 }
NumberAnimation { target: wisp; property: "y"; from: 8; to: 2; duration: 700 }
}
ParallelAnimation {
NumberAnimation { target: wisp; property: "opacity"; to: 0; duration: 1000 }
NumberAnimation { target: wisp; property: "y"; to: -6; duration: 1000 }
}
PauseAnimation { duration: 1800 - wisp.index * 600 }
}
}
}
// handle
Shape {
x: 28; y: 24
width: 14; height: 18
preferredRendererType: Shape.CurveRenderer
ShapePath {
strokeColor: "#e8e3da"
strokeWidth: 3.5
capStyle: ShapePath.RoundCap
fillColor: "transparent"
startX: 1; startY: 2
PathCubic { control1X: 12; control1Y: 0; control2X: 12; control2Y: 14; x: 1; y: 13 }
}
}
// mug
Rectangle {
x: 9; y: 20
width: 22; height: 27
radius: 4
color: "#f7f4ee"
antialiasing: true
Rectangle { // band
x: 0; y: 13
width: parent.width
height: 5
color: "#4d7ea8"
}
}
// coffee surface
Rectangle {
x: 10.5; y: 19
width: 19; height: 5
radius: 2.5
color: "#4a2c17"
antialiasing: true
}
}
}