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>
128 lines
3.9 KiB
QML
128 lines
3.9 KiB
QML
pragma ComponentBehavior: Bound
|
|
import QtQuick
|
|
import TNCat
|
|
|
|
// One screen-filling, click-through window that holds the cat and the chip.
|
|
// Wayland does not let a client place its own window, so there the cat moves
|
|
// inside this overlay instead of the window moving across the desktop.
|
|
Window {
|
|
id: win
|
|
|
|
required property CatController cat
|
|
required property AppSettings settings
|
|
|
|
signal settingsRequested()
|
|
|
|
// Fullscreen is a visibility, not a visible flag, so the mode switch has to
|
|
// go through visibility or the two fight each other.
|
|
property bool overlayActive: false
|
|
|
|
readonly property int catW: settings.catSize
|
|
readonly property int catH: Math.round(settings.catSize * 0.9)
|
|
readonly property real groundY: height - catH - settings.bottomMargin
|
|
|
|
// Only the cat itself should swallow clicks; everything else falls through.
|
|
function refreshInputRegion() {
|
|
Platform.setInputRegion(win, Qt.rect(Math.round(cat.x), Math.round(groundY), catW, catH))
|
|
}
|
|
|
|
visibility: overlayActive ? Window.FullScreen : Window.Hidden
|
|
color: "transparent"
|
|
flags: Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint | Qt.Tool
|
|
| Qt.NoDropShadowWindowHint | Qt.WindowDoesNotAcceptFocus
|
|
title: qsTr("TNCat")
|
|
|
|
onOverlayActiveChanged: {
|
|
if (!overlayActive)
|
|
return
|
|
cat.stageWidth = width
|
|
cat.catWidth = catW
|
|
refreshInputRegion()
|
|
}
|
|
onWidthChanged: cat.stageWidth = width
|
|
onCatWChanged: cat.catWidth = catW
|
|
|
|
Binding {
|
|
target: win.cat
|
|
property: "catCenter"
|
|
value: Qt.point(win.x + win.cat.x + win.catW / 2, win.y + win.groundY + win.catH / 2)
|
|
}
|
|
|
|
// Coalesce mask updates: one X11 round trip per frame of walking is plenty.
|
|
Timer {
|
|
interval: 33
|
|
running: win.overlayActive
|
|
repeat: true
|
|
onTriggered: win.refreshInputRegion()
|
|
}
|
|
|
|
Chip {
|
|
x: win.cat.chipX - width / 2
|
|
y: win.height - height - win.settings.bottomMargin
|
|
width: Math.round(win.settings.catSize * 0.45)
|
|
height: Math.round(width * 0.73)
|
|
visible: win.cat.chipVisible
|
|
kick: win.cat.chipKick
|
|
|
|
Behavior on x {
|
|
NumberAnimation { duration: 320; easing.type: Easing.OutQuad }
|
|
}
|
|
}
|
|
|
|
Cup {
|
|
x: win.cat.cupX - width / 2
|
|
y: win.height - height - win.settings.bottomMargin
|
|
width: Math.round(win.settings.catSize * 0.38)
|
|
height: Math.round(width * 1.18)
|
|
visible: win.cat.cupVisible
|
|
}
|
|
|
|
Item {
|
|
id: catItem
|
|
x: win.cat.x
|
|
y: win.groundY
|
|
width: win.catW
|
|
height: win.catH
|
|
|
|
Cat {
|
|
anchors.fill: parent
|
|
coat: win.settings.coat
|
|
facingRight: win.cat.facingRight
|
|
mood: CatMoods.name(win.cat.mood)
|
|
lifted: win.cat.dragging
|
|
petted: win.cat.hovered && !win.cat.dragging
|
|
look: win.cat.look
|
|
showCodes: win.settings.showCodes
|
|
|
|
Accessible.role: Accessible.Button
|
|
Accessible.name: qsTr("TNCat")
|
|
}
|
|
|
|
HoverHandler {
|
|
onHoveredChanged: win.cat.hovered = hovered
|
|
}
|
|
|
|
DragHandler {
|
|
target: null
|
|
onActiveChanged: win.cat.dragging = active
|
|
onCentroidChanged: {
|
|
if (active)
|
|
win.cat.x = Math.max(0, Math.min(win.cat.stageWidth - win.catW,
|
|
catItem.x + centroid.position.x - centroid.pressPosition.x))
|
|
}
|
|
}
|
|
|
|
TapHandler {
|
|
acceptedButtons: Qt.LeftButton
|
|
onTapped: win.cat.pet()
|
|
onDoubleTapped: win.settingsRequested()
|
|
onLongPressed: win.settingsRequested()
|
|
}
|
|
|
|
TapHandler {
|
|
acceptedButtons: Qt.RightButton
|
|
onTapped: win.settingsRequested()
|
|
}
|
|
}
|
|
}
|