Add Qt/QML desktop shell and Nebula.UI
Introduce a new production desktop shell at `shells/desktop/shell` built with C++20, Qt Quick/QML, and LayerShellQt, including top bar, launcher, desktop surfaces, shell state, and mock app data. Add the shared `packages/nebula-ui` QML module (theme, controls, focus, icons) and wire it into the shell build. Retire the old GTK/WebKit native host by removing `shells/desktop/native`, move the React shell UI to `shells/desktop/prototype-react` as an archived design reference, and update root/compositor/session documentation to reflect the new Linux-only production architecture and temporary Sway role.
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
import QtQuick
|
||||
import QtQuick.Window
|
||||
import org.kde.layershell 1.0 as LayerShell
|
||||
import Nebula.UI
|
||||
|
||||
Window {
|
||||
id: root
|
||||
|
||||
title: qsTr("Nebula Desktop")
|
||||
color: "transparent"
|
||||
flags: Qt.FramelessWindowHint | Qt.WindowDoesNotAcceptFocus
|
||||
visible: true
|
||||
width: Screen.width
|
||||
height: Screen.height
|
||||
|
||||
LayerShell.Window.scope: "nebula-desktop"
|
||||
LayerShell.Window.layer: LayerShell.Window.LayerBackground
|
||||
LayerShell.Window.anchors: LayerShell.Window.AnchorTop
|
||||
| LayerShell.Window.AnchorBottom
|
||||
| LayerShell.Window.AnchorLeft
|
||||
| LayerShell.Window.AnchorRight
|
||||
LayerShell.Window.exclusionZone: 0
|
||||
LayerShell.Window.keyboardInteractivity: LayerShell.Window.KeyboardInteractivityNone
|
||||
|
||||
Canvas {
|
||||
id: backdrop
|
||||
anchors.fill: parent
|
||||
onPaint: {
|
||||
const ctx = getContext("2d")
|
||||
ctx.reset()
|
||||
ctx.fillStyle = Theme.background
|
||||
ctx.fillRect(0, 0, width, height)
|
||||
|
||||
let glow = ctx.createRadialGradient(width * 0.12, height * -0.08, 0, width * 0.12, height * -0.08, width * 0.7)
|
||||
glow.addColorStop(0, "rgba(110, 140, 180, 0.16)")
|
||||
glow.addColorStop(0.52, "rgba(110, 140, 180, 0)")
|
||||
ctx.fillStyle = glow
|
||||
ctx.fillRect(0, 0, width, height)
|
||||
|
||||
glow = ctx.createRadialGradient(width * 0.88, height * 1.08, 0, width * 0.88, height * 1.08, width * 0.45)
|
||||
glow.addColorStop(0, "rgba(42, 68, 98, 0.28)")
|
||||
glow.addColorStop(0.58, "rgba(42, 68, 98, 0)")
|
||||
ctx.fillStyle = glow
|
||||
ctx.fillRect(0, 0, width, height)
|
||||
|
||||
glow = ctx.createRadialGradient(width * 0.62, height * 0.38, 0, width * 0.62, height * 0.38, width * 0.28)
|
||||
glow.addColorStop(0, "rgba(72, 92, 120, 0.08)")
|
||||
glow.addColorStop(0.7, "rgba(72, 92, 120, 0)")
|
||||
ctx.fillStyle = glow
|
||||
ctx.fillRect(0, 0, width, height)
|
||||
|
||||
const veil = ctx.createLinearGradient(0, 0, 0, height)
|
||||
veil.addColorStop(0, "rgba(8, 11, 17, 0.22)")
|
||||
veil.addColorStop(0.16, "rgba(8, 11, 17, 0)")
|
||||
veil.addColorStop(0.78, "rgba(8, 11, 17, 0)")
|
||||
veil.addColorStop(1, "rgba(8, 11, 17, 0.38)")
|
||||
ctx.fillStyle = veil
|
||||
ctx.fillRect(0, 0, width, height)
|
||||
}
|
||||
|
||||
onWidthChanged: requestPaint()
|
||||
onHeightChanged: requestPaint()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
import QtQuick
|
||||
import QtQuick.Window
|
||||
import org.kde.layershell 1.0 as LayerShell
|
||||
import Nebula.UI
|
||||
|
||||
Window {
|
||||
id: root
|
||||
|
||||
title: qsTr("Nebula Launcher")
|
||||
color: "transparent"
|
||||
flags: Qt.FramelessWindowHint
|
||||
visible: ShellState.launcherOpen || launcher.opacity > 0.01
|
||||
width: Screen.width
|
||||
height: Screen.height - Theme.topBarHeight
|
||||
|
||||
LayerShell.Window.scope: "nebula-launcher"
|
||||
LayerShell.Window.layer: LayerShell.Window.LayerOverlay
|
||||
LayerShell.Window.anchors: LayerShell.Window.AnchorTop
|
||||
| LayerShell.Window.AnchorBottom
|
||||
| LayerShell.Window.AnchorLeft
|
||||
| LayerShell.Window.AnchorRight
|
||||
LayerShell.Window.margins.top: Theme.topBarHeight
|
||||
LayerShell.Window.exclusionZone: 0
|
||||
LayerShell.Window.keyboardInteractivity: ShellState.launcherOpen
|
||||
? LayerShell.Window.KeyboardInteractivityExclusive
|
||||
: LayerShell.Window.KeyboardInteractivityNone
|
||||
|
||||
Item {
|
||||
anchors.fill: parent
|
||||
focus: ShellState.launcherOpen
|
||||
Keys.onEscapePressed: {
|
||||
event.accepted = true
|
||||
ShellState.closeLauncher()
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||
onClicked: ShellState.closeLauncher()
|
||||
}
|
||||
|
||||
Launcher {
|
||||
id: launcher
|
||||
x: 10
|
||||
y: 10
|
||||
width: Math.min(420, parent.width - 20)
|
||||
height: Math.min(implicitHeight, Math.min(640, parent.height - 24))
|
||||
opacity: ShellState.launcherOpen ? 1 : 0
|
||||
yOffset: ShellState.launcherOpen ? 0 : -6
|
||||
scale: ShellState.launcherOpen ? 1 : 0.985
|
||||
focus: ShellState.launcherOpen
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
duration: Theme.animationNormal
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on yOffset {
|
||||
NumberAnimation {
|
||||
duration: Theme.animationNormal
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on scale {
|
||||
NumberAnimation {
|
||||
duration: Theme.animationNormal
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import QtQuick
|
||||
import QtQuick.Window
|
||||
import org.kde.layershell 1.0 as LayerShell
|
||||
import Nebula.UI
|
||||
|
||||
Window {
|
||||
id: root
|
||||
|
||||
title: qsTr("Nebula Top Bar")
|
||||
color: "transparent"
|
||||
flags: Qt.FramelessWindowHint | Qt.WindowDoesNotAcceptFocus
|
||||
visible: true
|
||||
width: Screen.width
|
||||
height: Theme.topBarHeight
|
||||
|
||||
LayerShell.Window.scope: "nebula-topbar"
|
||||
LayerShell.Window.layer: LayerShell.Window.LayerTop
|
||||
LayerShell.Window.anchors: LayerShell.Window.AnchorTop
|
||||
| LayerShell.Window.AnchorLeft
|
||||
| LayerShell.Window.AnchorRight
|
||||
LayerShell.Window.exclusionZone: Theme.topBarHeight
|
||||
LayerShell.Window.keyboardInteractivity: LayerShell.Window.KeyboardInteractivityNone
|
||||
|
||||
TopBar {
|
||||
anchors.fill: parent
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user