Introduces a new `core/applications` QML/C++ module (`Nebula.Applications`) to discover `.desktop` entries, expose filterable application models, and launch installed apps safely from the shell. The desktop launcher now uses real installed apps with themed icon loading and fallback glyphs, adds output-aware surface sizing via `OutputTracker`, and wires in image/icon providers. It also adds VMware-focused Sway/shell wrapper scripts, updates Sway config/session env defaults, and refreshes README docs to document the new development flow and Desktop 0.1 behavior.
390 lines
10 KiB
QML
390 lines
10 KiB
QML
import QtQuick
|
|
|
|
Item {
|
|
id: root
|
|
|
|
property string name: "nebula"
|
|
property color color: Theme.textPrimary
|
|
property int size: 16
|
|
property real value: 1
|
|
|
|
implicitWidth: size
|
|
implicitHeight: size
|
|
Accessible.ignored: true
|
|
|
|
Canvas {
|
|
id: canvas
|
|
anchors.fill: parent
|
|
antialiasing: true
|
|
onPaint: root.paint(getContext("2d"))
|
|
}
|
|
|
|
onNameChanged: canvas.requestPaint()
|
|
onColorChanged: canvas.requestPaint()
|
|
onValueChanged: canvas.requestPaint()
|
|
onWidthChanged: canvas.requestPaint()
|
|
onHeightChanged: canvas.requestPaint()
|
|
|
|
function paint(ctx) {
|
|
ctx.reset()
|
|
ctx.strokeStyle = root.color
|
|
ctx.fillStyle = root.color
|
|
ctx.lineCap = "round"
|
|
ctx.lineJoin = "round"
|
|
ctx.scale(width / 24, height / 24)
|
|
|
|
switch (root.name) {
|
|
case "nebula":
|
|
paintNebula(ctx)
|
|
break
|
|
case "search":
|
|
paintSearch(ctx)
|
|
break
|
|
case "wifi":
|
|
paintWifi(ctx)
|
|
break
|
|
case "speaker":
|
|
paintSpeaker(ctx)
|
|
break
|
|
case "battery":
|
|
paintBattery(ctx)
|
|
break
|
|
case "power":
|
|
paintPower(ctx)
|
|
break
|
|
case "restart":
|
|
paintRestart(ctx)
|
|
break
|
|
case "folder":
|
|
paintFolder(ctx)
|
|
break
|
|
case "globe":
|
|
paintGlobe(ctx)
|
|
break
|
|
case "terminal":
|
|
paintTerminal(ctx)
|
|
break
|
|
case "settings":
|
|
paintSettings(ctx)
|
|
break
|
|
case "game":
|
|
paintGame(ctx)
|
|
break
|
|
case "photo":
|
|
paintPhoto(ctx)
|
|
break
|
|
case "music":
|
|
paintMusic(ctx)
|
|
break
|
|
case "document":
|
|
paintDocument(ctx)
|
|
break
|
|
case "application":
|
|
paintApplication(ctx)
|
|
break
|
|
default:
|
|
paintApplication(ctx)
|
|
break
|
|
}
|
|
}
|
|
|
|
function paintNebula(ctx) {
|
|
ctx.beginPath()
|
|
ctx.arc(12, 12, 4.2, 0, Math.PI * 2)
|
|
ctx.fill()
|
|
|
|
ctx.save()
|
|
ctx.translate(12, 12)
|
|
ctx.rotate(-26 * Math.PI / 180)
|
|
ctx.scale(10 / 4.15, 1)
|
|
ctx.lineWidth = 1.35 * (4.15 / 10)
|
|
ctx.beginPath()
|
|
ctx.arc(0, 0, 4.15, 0, Math.PI * 2)
|
|
ctx.stroke()
|
|
ctx.restore()
|
|
}
|
|
|
|
function paintSearch(ctx) {
|
|
ctx.lineWidth = 1.6
|
|
ctx.beginPath()
|
|
ctx.arc(11, 11, 6.25, 0, Math.PI * 2)
|
|
ctx.stroke()
|
|
ctx.beginPath()
|
|
ctx.moveTo(15.8, 15.8)
|
|
ctx.lineTo(20, 20)
|
|
ctx.stroke()
|
|
}
|
|
|
|
function paintWifi(ctx) {
|
|
const strength = root.value
|
|
ctx.lineWidth = 1.6
|
|
ctx.globalAlpha = strength > 0 ? 1 : 0.28
|
|
ctx.beginPath()
|
|
ctx.moveTo(4.8, 15.2)
|
|
ctx.bezierCurveTo(8.8, 11.2, 15.2, 11.2, 19.2, 15.2)
|
|
ctx.stroke()
|
|
ctx.globalAlpha = strength > 1 ? 1 : 0.28
|
|
ctx.beginPath()
|
|
ctx.moveTo(7.4, 17.4)
|
|
ctx.bezierCurveTo(10, 14.9, 14, 14.9, 16.6, 17.4)
|
|
ctx.stroke()
|
|
ctx.globalAlpha = 1
|
|
ctx.beginPath()
|
|
ctx.arc(12, 20, 1.15, 0, Math.PI * 2)
|
|
ctx.fill()
|
|
}
|
|
|
|
function paintSpeaker(ctx) {
|
|
ctx.beginPath()
|
|
ctx.moveTo(4.5, 9.4)
|
|
ctx.lineTo(7.6, 9.4)
|
|
ctx.lineTo(12, 6.2)
|
|
ctx.lineTo(12, 17.8)
|
|
ctx.lineTo(7.6, 14.6)
|
|
ctx.lineTo(4.5, 14.6)
|
|
ctx.closePath()
|
|
ctx.fill()
|
|
ctx.lineWidth = 1.5
|
|
ctx.beginPath()
|
|
ctx.arc(12.5, 12, 4.2, -0.7, 0.7)
|
|
ctx.stroke()
|
|
ctx.globalAlpha = 0.7
|
|
ctx.beginPath()
|
|
ctx.arc(12.5, 12, 7.2, -0.85, 0.85)
|
|
ctx.stroke()
|
|
ctx.globalAlpha = 1
|
|
}
|
|
|
|
function paintBattery(ctx) {
|
|
ctx.lineWidth = 1.5
|
|
ctx.beginPath()
|
|
roundedRect(ctx, 2.5, 7.25, 16.5, 9.5, 2)
|
|
ctx.stroke()
|
|
ctx.beginPath()
|
|
roundedRect(ctx, 19.5, 10, 2, 4, 0.6)
|
|
ctx.fill()
|
|
const fillWidth = Math.max(1.5, (14 * Math.min(100, Math.max(0, root.value))) / 100)
|
|
ctx.beginPath()
|
|
roundedRect(ctx, 4.2, 9, fillWidth, 6, 1)
|
|
ctx.fill()
|
|
}
|
|
|
|
function paintPower(ctx) {
|
|
ctx.lineWidth = 1.7
|
|
ctx.beginPath()
|
|
ctx.moveTo(12, 4.5)
|
|
ctx.lineTo(12, 11.7)
|
|
ctx.stroke()
|
|
ctx.beginPath()
|
|
ctx.arc(12, 13, 6.2, Math.PI * 1.15, Math.PI * -0.15, false)
|
|
ctx.stroke()
|
|
}
|
|
|
|
function paintRestart(ctx) {
|
|
ctx.lineWidth = 1.7
|
|
ctx.beginPath()
|
|
ctx.arc(12, 12, 7, -0.2, Math.PI * 1.55, true)
|
|
ctx.stroke()
|
|
ctx.beginPath()
|
|
ctx.moveTo(19, 5.2)
|
|
ctx.lineTo(19, 9.6)
|
|
ctx.lineTo(14.6, 9.6)
|
|
ctx.stroke()
|
|
}
|
|
|
|
function paintApplication(ctx) {
|
|
ctx.lineWidth = 1.5
|
|
ctx.beginPath()
|
|
roundedRect(ctx, 4.2, 5.2, 15.6, 13.6, 2.2)
|
|
ctx.stroke()
|
|
ctx.beginPath()
|
|
ctx.moveTo(4.2, 8.4)
|
|
ctx.lineTo(19.8, 8.4)
|
|
ctx.stroke()
|
|
ctx.beginPath()
|
|
ctx.arc(7, 6.8, 0.7, 0, Math.PI * 2)
|
|
ctx.fill()
|
|
ctx.beginPath()
|
|
ctx.arc(9.4, 6.8, 0.7, 0, Math.PI * 2)
|
|
ctx.fill()
|
|
}
|
|
|
|
function paintFolder(ctx) {
|
|
ctx.beginPath()
|
|
ctx.moveTo(3.5, 8.2)
|
|
ctx.quadraticCurveTo(3.5, 6.4, 5.3, 6.4)
|
|
ctx.lineTo(9.4, 6.4)
|
|
ctx.lineTo(11, 8.2)
|
|
ctx.lineTo(18.7, 8.2)
|
|
ctx.quadraticCurveTo(20.5, 8.2, 20.5, 10)
|
|
ctx.lineTo(20.5, 16.8)
|
|
ctx.quadraticCurveTo(20.5, 18.6, 18.7, 18.6)
|
|
ctx.lineTo(5.3, 18.6)
|
|
ctx.quadraticCurveTo(3.5, 18.6, 3.5, 16.8)
|
|
ctx.closePath()
|
|
ctx.fill()
|
|
}
|
|
|
|
function paintGlobe(ctx) {
|
|
ctx.lineWidth = 1.6
|
|
ctx.beginPath()
|
|
ctx.arc(12, 12, 7.25, 0, Math.PI * 2)
|
|
ctx.stroke()
|
|
ctx.lineWidth = 1.4
|
|
ctx.save()
|
|
ctx.translate(12, 12)
|
|
ctx.scale(3.1 / 7.25, 1)
|
|
ctx.beginPath()
|
|
ctx.arc(0, 0, 7.25, 0, Math.PI * 2)
|
|
ctx.stroke()
|
|
ctx.restore()
|
|
ctx.beginPath()
|
|
ctx.moveTo(5.2, 12)
|
|
ctx.lineTo(18.8, 12)
|
|
ctx.stroke()
|
|
}
|
|
|
|
function paintTerminal(ctx) {
|
|
ctx.lineWidth = 1.7
|
|
ctx.beginPath()
|
|
ctx.moveTo(7, 9.2)
|
|
ctx.lineTo(10.4, 12)
|
|
ctx.lineTo(7, 14.8)
|
|
ctx.stroke()
|
|
ctx.beginPath()
|
|
ctx.moveTo(12.2, 15.2)
|
|
ctx.lineTo(17, 15.2)
|
|
ctx.stroke()
|
|
}
|
|
|
|
function paintSettings(ctx) {
|
|
ctx.beginPath()
|
|
ctx.arc(12, 12, 2.4, 0, Math.PI * 2)
|
|
ctx.fill()
|
|
ctx.lineWidth = 1.6
|
|
const ticks = [
|
|
[12, 5.2, 12, 6.8],
|
|
[12, 17.2, 12, 18.8],
|
|
[5.2, 12, 6.8, 12],
|
|
[17.2, 12, 18.8, 12],
|
|
[7.2, 7.2, 8.3, 8.3],
|
|
[15.7, 15.7, 16.8, 16.8],
|
|
[16.8, 7.2, 15.7, 8.3],
|
|
[8.3, 15.7, 7.2, 16.8]
|
|
]
|
|
for (let i = 0; i < ticks.length; i++) {
|
|
const t = ticks[i]
|
|
ctx.beginPath()
|
|
ctx.moveTo(t[0], t[1])
|
|
ctx.lineTo(t[2], t[3])
|
|
ctx.stroke()
|
|
}
|
|
}
|
|
|
|
function paintGame(ctx) {
|
|
ctx.lineWidth = 1.5
|
|
ctx.beginPath()
|
|
ctx.moveTo(5.2, 10.4)
|
|
ctx.lineTo(18.8, 10.4)
|
|
ctx.quadraticCurveTo(20.4, 10.4, 20.3, 12.1)
|
|
ctx.lineTo(19.8, 15.3)
|
|
ctx.quadraticCurveTo(19.6, 16.9, 18.5, 16.9)
|
|
ctx.lineTo(16.3, 16.9)
|
|
ctx.lineTo(15, 15.1)
|
|
ctx.lineTo(10, 15.1)
|
|
ctx.lineTo(8.7, 16.9)
|
|
ctx.lineTo(6.5, 16.9)
|
|
ctx.quadraticCurveTo(5.4, 16.9, 5.2, 15.3)
|
|
ctx.lineTo(4.7, 12.1)
|
|
ctx.quadraticCurveTo(4.6, 10.4, 5.2, 10.4)
|
|
ctx.closePath()
|
|
ctx.stroke()
|
|
ctx.beginPath()
|
|
ctx.moveTo(8, 12.4)
|
|
ctx.lineTo(8, 15.6)
|
|
ctx.moveTo(6.4, 14)
|
|
ctx.lineTo(9.6, 14)
|
|
ctx.stroke()
|
|
ctx.beginPath()
|
|
ctx.arc(15.4, 13.2, 0.9, 0, Math.PI * 2)
|
|
ctx.fill()
|
|
ctx.beginPath()
|
|
ctx.arc(17.2, 15, 0.9, 0, Math.PI * 2)
|
|
ctx.fill()
|
|
}
|
|
|
|
function paintPhoto(ctx) {
|
|
ctx.lineWidth = 1.5
|
|
ctx.beginPath()
|
|
roundedRect(ctx, 4, 6.2, 16, 11.6, 2)
|
|
ctx.stroke()
|
|
ctx.beginPath()
|
|
ctx.arc(9, 10.2, 1.3, 0, Math.PI * 2)
|
|
ctx.fill()
|
|
ctx.beginPath()
|
|
ctx.moveTo(7.2, 15.8)
|
|
ctx.lineTo(10.6, 12.4)
|
|
ctx.lineTo(13.2, 15)
|
|
ctx.lineTo(15.4, 12.9)
|
|
ctx.lineTo(18.8, 15.8)
|
|
ctx.stroke()
|
|
}
|
|
|
|
function paintMusic(ctx) {
|
|
ctx.lineWidth = 1.6
|
|
ctx.beginPath()
|
|
ctx.moveTo(10, 16.6)
|
|
ctx.lineTo(10, 7.4)
|
|
ctx.lineTo(18, 5.8)
|
|
ctx.lineTo(18, 15.2)
|
|
ctx.stroke()
|
|
ctx.beginPath()
|
|
ctx.arc(8.2, 16.6, 2.2, 0, Math.PI * 2)
|
|
ctx.fill()
|
|
ctx.beginPath()
|
|
ctx.arc(16.2, 15.2, 2.2, 0, Math.PI * 2)
|
|
ctx.fill()
|
|
}
|
|
|
|
function paintDocument(ctx) {
|
|
ctx.lineWidth = 1.5
|
|
ctx.beginPath()
|
|
ctx.moveTo(7, 5.5)
|
|
ctx.lineTo(13.2, 5.5)
|
|
ctx.lineTo(17.5, 10)
|
|
ctx.lineTo(17.5, 18.5)
|
|
ctx.quadraticCurveTo(17.5, 20, 16, 20)
|
|
ctx.lineTo(7, 20)
|
|
ctx.quadraticCurveTo(5.5, 20, 5.5, 18.5)
|
|
ctx.lineTo(5.5, 7)
|
|
ctx.quadraticCurveTo(5.5, 5.5, 7, 5.5)
|
|
ctx.closePath()
|
|
ctx.stroke()
|
|
ctx.beginPath()
|
|
ctx.moveTo(13.2, 5.5)
|
|
ctx.lineTo(13.2, 10)
|
|
ctx.lineTo(17.5, 10)
|
|
ctx.stroke()
|
|
ctx.beginPath()
|
|
ctx.moveTo(8.8, 13.4)
|
|
ctx.lineTo(15.2, 13.4)
|
|
ctx.moveTo(8.8, 16.2)
|
|
ctx.lineTo(13.2, 16.2)
|
|
ctx.stroke()
|
|
}
|
|
|
|
function roundedRect(ctx, x, y, w, h, r) {
|
|
const radius = Math.min(r, w / 2, h / 2)
|
|
ctx.moveTo(x + radius, y)
|
|
ctx.lineTo(x + w - radius, y)
|
|
ctx.quadraticCurveTo(x + w, y, x + w, y + radius)
|
|
ctx.lineTo(x + w, y + h - radius)
|
|
ctx.quadraticCurveTo(x + w, y + h, x + w - radius, y + h)
|
|
ctx.lineTo(x + radius, y + h)
|
|
ctx.quadraticCurveTo(x, y + h, x, y + h - radius)
|
|
ctx.lineTo(x, y + radius)
|
|
ctx.quadraticCurveTo(x, y, x + radius, y)
|
|
ctx.closePath()
|
|
}
|
|
}
|