Add floating traffic-light window chrome

Introduces a dedicated layer-shell `WindowChromeSurface` that renders macOS-style traffic-light controls over the focused Sway window titlebar, replacing the old top-bar window controls. Adds theme tokens and a reusable `TrafficLightButton` component, updates shell QML/CMake wiring, and adjusts Sway titlebar padding/title format so window titles do not overlap the overlay. Window tracking was extended with focused-window geometry/deco/fullscreen properties plus backend refresh support so the chrome follows window movement and state changes in near real time.
This commit is contained in:
2026-08-26 22:38:33 +12:00
parent 08e67845a5
commit 4321209e92
14 changed files with 452 additions and 92 deletions
@@ -6,71 +6,43 @@ Item {
id: root
readonly property bool maximized: WindowService.focusedWindowMaximized
readonly property bool hovered: closeButton.hovered || minimizeButton.hovered || zoomButton.hovered
visible: WindowService.hasFocusedWindow
implicitWidth: well.implicitWidth
implicitHeight: Theme.controlHeight
width: visible ? implicitWidth : 0
implicitWidth: row.implicitWidth
implicitHeight: row.implicitHeight
Accessible.role: Accessible.Grouping
Accessible.name: qsTr("Window controls")
Rectangle {
id: well
anchors.fill: parent
implicitWidth: row.implicitWidth + 2
implicitHeight: Theme.controlHeight
radius: Theme.radiusSmall
color: Theme.iconWell
border.width: 1
border.color: Theme.border
Row {
id: row
anchors.centerIn: parent
spacing: Theme.trafficLightGap
Row {
id: row
anchors.centerIn: parent
spacing: 0
TrafficLightButton {
id: closeButton
fill: Theme.trafficClose
glyph: "close"
label: qsTr("Close")
showGlyph: root.hovered
onClicked: WindowService.closeFocusedWindow()
}
NebulaIconButton {
id: minimizeButton
width: 26
height: 26
label: qsTr("Minimise")
onClicked: WindowService.minimizeFocusedWindow()
TrafficLightButton {
id: minimizeButton
fill: Theme.trafficMinimise
glyph: "minimize"
label: qsTr("Minimise")
showGlyph: root.hovered
onClicked: WindowService.minimizeFocusedWindow()
}
NebulaIcon {
name: "minimize"
size: 14
color: minimizeButton.iconColor
}
}
NebulaIconButton {
id: maximizeButton
width: 26
height: 26
label: root.maximized ? qsTr("Restore") : qsTr("Maximise")
onClicked: WindowService.toggleMaximizeFocusedWindow()
NebulaIcon {
name: root.maximized ? "restore" : "maximize"
size: 14
color: maximizeButton.iconColor
}
}
NebulaIconButton {
id: closeButton
width: 26
height: 26
label: qsTr("Close")
danger: true
onClicked: WindowService.closeFocusedWindow()
NebulaIcon {
name: "close"
size: 14
color: closeButton.iconColor
}
}
TrafficLightButton {
id: zoomButton
fill: Theme.trafficZoom
glyph: root.maximized ? "restore" : "zoom"
label: root.maximized ? qsTr("Restore") : qsTr("Maximise")
showGlyph: root.hovered
onClicked: WindowService.toggleMaximizeFocusedWindow()
}
}
}