Introduces a new `core/windows` module (`Nebula.Windows`) with `WindowService`, window/workspace models, and a Sway IPC backend for live window tracking and control (focus, close, move/resize, snap, maximize/restore, minimize, workspace switch). The desktop shell now links this module, uses compositor focus for top-bar active app text, and adds an Open Windows section in the launcher with focus/close actions. Also updates application metadata handling to parse `StartupWMClass` and map window `app_id`/class to friendly names and icons, and revises Sway config/docs for the new floating-first Desktop 0.2 behavior with temporary compositor-provided decorations.
136 lines
3.5 KiB
QML
136 lines
3.5 KiB
QML
import QtQuick
|
||
import Nebula.UI
|
||
import Nebula.Windows
|
||
|
||
Item {
|
||
id: root
|
||
|
||
required property string windowId
|
||
required property string displayName
|
||
required property string iconName
|
||
required property bool focused
|
||
required property bool minimized
|
||
|
||
implicitWidth: parent ? parent.width : 200
|
||
implicitHeight: 36
|
||
Accessible.role: Accessible.ListItem
|
||
Accessible.name: displayName
|
||
Accessible.onPressAction: root.activate()
|
||
|
||
readonly property url iconSource: iconName.length > 0
|
||
? ("image://desktopicon/" + encodeURIComponent(iconName))
|
||
: ""
|
||
|
||
function activate() {
|
||
WindowService.focusWindow(windowId)
|
||
ShellState.closeLauncher()
|
||
}
|
||
|
||
Rectangle {
|
||
anchors.fill: parent
|
||
radius: Theme.radiusSmall
|
||
color: {
|
||
if (hover.containsMouse)
|
||
return Theme.tileHover
|
||
if (root.focused)
|
||
return Theme.accentSoft
|
||
return "transparent"
|
||
}
|
||
|
||
Behavior on color {
|
||
ColorAnimation {
|
||
duration: Theme.animationFast
|
||
}
|
||
}
|
||
}
|
||
|
||
Row {
|
||
anchors.fill: parent
|
||
anchors.leftMargin: 8
|
||
anchors.rightMargin: 4
|
||
spacing: 8
|
||
|
||
Rectangle {
|
||
width: 22
|
||
height: 22
|
||
radius: 6
|
||
anchors.verticalCenter: parent.verticalCenter
|
||
color: Theme.iconWell
|
||
|
||
Image {
|
||
id: icon
|
||
anchors.centerIn: parent
|
||
width: 14
|
||
height: 14
|
||
fillMode: Image.PreserveAspectFit
|
||
asynchronous: true
|
||
smooth: true
|
||
cache: true
|
||
visible: status === Image.Ready
|
||
source: root.iconSource
|
||
}
|
||
|
||
NebulaIcon {
|
||
anchors.centerIn: parent
|
||
visible: icon.status !== Image.Ready
|
||
name: "application"
|
||
size: 12
|
||
color: Theme.accent
|
||
}
|
||
}
|
||
|
||
Text {
|
||
anchors.verticalCenter: parent.verticalCenter
|
||
width: parent.width - 22 - 28 - 16
|
||
text: root.displayName
|
||
color: {
|
||
if (root.minimized)
|
||
return Theme.textTertiary
|
||
if (root.focused)
|
||
return Theme.textPrimary
|
||
return Theme.textSecondary
|
||
}
|
||
font.family: Theme.fontFamily
|
||
font.pixelSize: Theme.fontSizeApp
|
||
elide: Text.ElideRight
|
||
}
|
||
|
||
Item {
|
||
width: 28
|
||
height: parent.height
|
||
|
||
Text {
|
||
anchors.centerIn: parent
|
||
text: "×"
|
||
color: closeHover.containsMouse ? Theme.danger : Theme.textTertiary
|
||
font.pixelSize: 14
|
||
font.family: Theme.fontFamily
|
||
}
|
||
|
||
MouseArea {
|
||
id: closeHover
|
||
anchors.fill: parent
|
||
hoverEnabled: true
|
||
cursorShape: Qt.PointingHandCursor
|
||
onClicked: WindowService.closeWindow(root.windowId)
|
||
}
|
||
|
||
Accessible.role: Accessible.Button
|
||
Accessible.name: qsTr("Close %1").arg(root.displayName)
|
||
}
|
||
}
|
||
|
||
MouseArea {
|
||
id: hover
|
||
anchors.fill: parent
|
||
anchors.rightMargin: 28
|
||
hoverEnabled: true
|
||
cursorShape: Qt.PointingHandCursor
|
||
onClicked: root.activate()
|
||
}
|
||
|
||
FocusFrame {
|
||
radius: Theme.radiusSmall
|
||
}
|
||
}
|