Files
Nebula-OS/shells/desktop/shell/qml/components/TrafficLightButton.qml
T
andrew 4d70014242 Align window chrome with Sway title bars
Adds focused title-bar geometry to the window service and updates the Sway backend to derive frame data more reliably (including parent node fallback and content rect tracking for wrapped/floating views). Window chrome positioning now centers against the actual title bar instead of deco offsets, improving alignment. Also refreshes visual sizing/padding for traffic-light controls and Sway titlebar spacing to match the new chrome metrics.
2026-08-26 22:45:50 +12:00

127 lines
3.5 KiB
QML

import QtQuick
import Nebula.UI
Item {
id: root
property string label: ""
property color fill: Theme.trafficClose
property string glyph: "close"
property bool showGlyph: false
readonly property bool hovered: hover.containsMouse
readonly property bool pressed: hover.pressed
signal clicked()
implicitWidth: Theme.trafficLightSize + 6
implicitHeight: Theme.trafficLightSize + 6
Accessible.role: Accessible.Button
Accessible.name: root.label
Accessible.onPressAction: root.clicked()
Rectangle {
id: disc
anchors.centerIn: parent
width: Theme.trafficLightSize
height: Theme.trafficLightSize
radius: width / 2
color: hover.pressed ? Qt.darker(root.fill, 1.18) : root.fill
border.width: 1
border.color: Qt.rgba(0, 0, 0, 0.22)
Behavior on color {
ColorAnimation {
duration: Theme.animationFast
}
}
Rectangle {
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.topMargin: 1
width: parent.width - 4
height: Math.max(2, parent.height * 0.38)
radius: height / 2
color: Qt.rgba(1, 1, 1, 0.28)
Accessible.ignored: true
}
}
Canvas {
id: glyph
anchors.centerIn: parent
width: Math.round(Theme.trafficLightSize * 0.58)
height: width
antialiasing: true
opacity: root.showGlyph ? 1 : 0
visible: opacity > 0.01
onWidthChanged: requestPaint()
onHeightChanged: requestPaint()
onPaint: {
const ctx = getContext("2d")
ctx.reset()
ctx.scale(width / 8, height / 8)
ctx.strokeStyle = Qt.rgba(0.18, 0.12, 0.1, 0.78)
ctx.fillStyle = ctx.strokeStyle
ctx.lineWidth = 1.35
ctx.lineCap = "round"
ctx.lineJoin = "round"
switch (root.glyph) {
case "minimize":
ctx.beginPath()
ctx.moveTo(1.2, 4)
ctx.lineTo(6.8, 4)
ctx.stroke()
break
case "zoom":
ctx.beginPath()
ctx.moveTo(1.4, 4)
ctx.lineTo(6.6, 4)
ctx.moveTo(4, 1.4)
ctx.lineTo(4, 6.6)
ctx.stroke()
break
case "restore":
ctx.beginPath()
ctx.rect(2.3, 0.7, 4.3, 4.3)
ctx.stroke()
ctx.beginPath()
ctx.rect(0.7, 2.3, 4.3, 4.3)
ctx.stroke()
break
default:
ctx.beginPath()
ctx.moveTo(1.6, 1.6)
ctx.lineTo(6.4, 6.4)
ctx.moveTo(6.4, 1.6)
ctx.lineTo(1.6, 6.4)
ctx.stroke()
break
}
}
Behavior on opacity {
NumberAnimation {
duration: Theme.animationFast
}
}
}
onGlyphChanged: glyph.requestPaint()
onShowGlyphChanged: if (showGlyph) glyph.requestPaint()
MouseArea {
id: hover
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: root.clicked()
}
NebulaToolTip {
text: root.label
active: hover.containsMouse && !hover.pressed && root.label.length > 0
}
}