1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
|
//@ pragma UseQApplication
// Copyright (C) 2026 Danilo M. <danix@danix.xyz>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
// published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// UseQApplication (line 1) is for the island's tray menus: SystemTrayItem
// display() fails without it. Pragmas are read only at launch, so changing
// it needs a restart, not a hot reload.
import Quickshell
import Quickshell.Io
import Quickshell.Wayland
import QtQuick
import "modules/ai"
import "modules/appearance"
import "modules/bluetooth"
import "modules/clipboard"
import "modules/git"
import "modules/kdeconnect"
import "modules/mail"
import "modules/network"
import "modules/perf"
import "modules/sound"
import "modules/status"
import "modules/updates"
import "modules/user"
import "modules/vm"
import "island"
import "assistant"
ShellRoot {
// Quickshell exits once no window is visible, and the drawer is closed
// most of the time. See AGENTS.md.
//
// It is also the window the idle inhibitor attaches to: IdleInhibitor
// needs a non-null window, and this is the one window that exists for
// the whole life of the shell.
PanelWindow {
id: keepalive
visible: true
implicitWidth: 1
implicitHeight: 1
color: "transparent"
exclusionMode: ExclusionMode.Ignore
mask: Region {}
WlrLayershell.keyboardFocus: WlrKeyboardFocus.None
// The singleton has no window of its own and IdleInhibitor needs one.
Component.onCompleted: Status.inhibitWindow = keepalive
}
Drawer {
id: drawer
modules: [
SoundModule { id: soundModule },
NetworkModule {},
BluetoothModule {},
KdeConnectModule {},
MailModule {},
StatusModule {},
PerfModule {},
ClipboardModule {},
UpdatesModule {},
VmModule {},
AiModule {},
AppearanceModule {},
UserModule {},
GitModule {},
]
}
// The island on DP-1. It reads the sound module's service rather than
// binding PipeWire a second time.
Island {
id: island
sound: soundModule.service
drawer: drawer
asst: assistant
}
// The assistant canvas on SUPER+Home, a view over desktop-assistant's
// socket. See assistant/README.md.
Assistant { id: assistant }
// The waybar launcher and the deep-link keybinds all reach this:
// qs -p <this dir> ipc call drawer toggle -> the grid
// qs -p <this dir> ipc call drawer open mail -> the mail page
// Quickshell 0.3.1 IPC requires every declared argument to be present,
// and a parameter with a JS default registers as QVariant, which IPC
// rejects. So the page name cannot be optional: `open` always takes a
// page, and the page-less grid is `toggle`, the zero-argument shape the
// appearance shell uses for its routes and the waybar launcher calls.
IpcHandler {
target: "drawer"
function open(page: string) { drawer.show(page); }
function toggle() { drawer.toggle(""); }
function close() { drawer.close(); }
}
// qs -p <this dir> ipc call assistant toggle -> SUPER+Home
IpcHandler {
target: "assistant"
function toggle() { assistant.toggle(); }
}
}
|