diff options
Diffstat (limited to 'accounts/gkleen@sif/shell/quickshell/Bar.qml')
-rw-r--r-- | accounts/gkleen@sif/shell/quickshell/Bar.qml | 321 |
1 files changed, 14 insertions, 307 deletions
diff --git a/accounts/gkleen@sif/shell/quickshell/Bar.qml b/accounts/gkleen@sif/shell/quickshell/Bar.qml index 09554a39..38225d74 100644 --- a/accounts/gkleen@sif/shell/quickshell/Bar.qml +++ b/accounts/gkleen@sif/shell/quickshell/Bar.qml | |||
@@ -1,16 +1,11 @@ | |||
1 | import Quickshell | 1 | import Quickshell |
2 | import Quickshell.Io | ||
3 | import Quickshell.Services.SystemTray | ||
4 | import Quickshell.Widgets | ||
5 | import Custom as Custom | ||
6 | import QtQuick | 2 | import QtQuick |
7 | import qs.Services | ||
8 | 3 | ||
9 | 4 | ||
10 | PanelWindow { | 5 | PanelWindow { |
11 | id: bar | 6 | id: bar |
12 | 7 | ||
13 | property var modelData | 8 | required property var screen |
14 | 9 | ||
15 | anchors { | 10 | anchors { |
16 | top: true | 11 | top: true |
@@ -22,12 +17,11 @@ PanelWindow { | |||
22 | right: 26 + 8 | 17 | right: 26 + 8 |
23 | } | 18 | } |
24 | 19 | ||
25 | screen: modelData | ||
26 | implicitHeight: 21 | 20 | implicitHeight: 21 |
27 | color: "transparent" | 21 | color: "transparent" |
28 | 22 | ||
29 | Rectangle { | 23 | Rectangle { |
30 | color: Qt.rgba(0, 0, 0, 0.66) | 24 | color: Qt.rgba(0, 0, 0, 0.75) |
31 | anchors.fill: parent | 25 | anchors.fill: parent |
32 | // bottomLeftRadius: 8 | 26 | // bottomLeftRadius: 8 |
33 | // bottomRightRadius: 8 | 27 | // bottomRightRadius: 8 |
@@ -43,74 +37,7 @@ PanelWindow { | |||
43 | anchors.verticalCenter: parent.verticalCenter | 37 | anchors.verticalCenter: parent.verticalCenter |
44 | spacing: 8 | 38 | spacing: 8 |
45 | 39 | ||
46 | Row { | 40 | WorkspaceSwitcher {} |
47 | id: workspaces | ||
48 | |||
49 | property var ignoreWorkspaces: @ignore_workspaces@ | ||
50 | |||
51 | height: parent.height | ||
52 | anchors.verticalCenter: parent.verticalCenter | ||
53 | spacing: 0 | ||
54 | |||
55 | Repeater { | ||
56 | model: { | ||
57 | let currWorkspaces = NiriService.workspaces; | ||
58 | const ignoreWorkspaces = Array.from(workspaces.ignoreWorkspaces); | ||
59 | currWorkspaces = currWorkspaces.filter(ws => ws.is_active || ignoreWorkspaces.every(iws => iws !== ws.name)); | ||
60 | currWorkspaces.sort((a, b) => { | ||
61 | if (NiriService.outputs?.[a.output]?.logical?.x !== NiriService.outputs?.[b.output]?.logical?.x) | ||
62 | return NiriService.outputs?.[a.output]?.logical?.x - NiriService.outputs?.[b.output]?.logical?.x | ||
63 | if (NiriService.outputs?.[a.output]?.logical?.y !== NiriService.outputs?.[b.output]?.logical?.y) | ||
64 | return NiriService.outputs?.[a.output]?.logical?.y - NiriService.outputs?.[b.output]?.logical?.y | ||
65 | return a.idx - b.idx; | ||
66 | }); | ||
67 | return currWorkspaces; | ||
68 | } | ||
69 | |||
70 | Rectangle { | ||
71 | property var workspaceData: modelData | ||
72 | |||
73 | width: wsLabel.contentWidth + 8 | ||
74 | color: { | ||
75 | if (mouseArea.containsMouse) { | ||
76 | return "#33808080"; | ||
77 | } | ||
78 | return "transparent"; | ||
79 | } | ||
80 | height: parent.height | ||
81 | anchors.verticalCenter: parent.verticalCenter | ||
82 | |||
83 | MouseArea { | ||
84 | id: mouseArea | ||
85 | |||
86 | anchors.fill: parent | ||
87 | hoverEnabled: true | ||
88 | cursorShape: Qt.PointingHandCursor | ||
89 | enabled: true | ||
90 | onClicked: { | ||
91 | NiriService.sendCommand({ "Action": { "FocusWorkspace": { "reference": { "Id": workspaceData.id } } } }, _ => {}) | ||
92 | } | ||
93 | } | ||
94 | |||
95 | Text { | ||
96 | id: wsLabel | ||
97 | |||
98 | font.pointSize: 10 | ||
99 | font.family: "Fira Sans" | ||
100 | color: { | ||
101 | if (workspaceData.active_window_id === null) | ||
102 | return "#555"; | ||
103 | if (workspaceData.is_active) | ||
104 | return "#23fd00"; | ||
105 | return "white"; | ||
106 | } | ||
107 | anchors.centerIn: parent | ||
108 | |||
109 | text: workspaceData.name ? workspaceData.name : workspaceData.idx | ||
110 | } | ||
111 | } | ||
112 | } | ||
113 | } | ||
114 | } | 41 | } |
115 | 42 | ||
116 | Row { | 43 | Row { |
@@ -121,91 +48,9 @@ PanelWindow { | |||
121 | anchors.centerIn: parent | 48 | anchors.centerIn: parent |
122 | spacing: 5 | 49 | spacing: 5 |
123 | 50 | ||
124 | Item { | 51 | ActiveWindowDisplay { |
125 | id: activeWindowDisplay | 52 | screen: bar.screen |
126 | 53 | maxWidth: bar.width - 2*Math.max(left.width, right.width) - 2*8 | |
127 | property var activeWindow: { | ||
128 | let currWindowId = Array.from(NiriService.workspaces).find(ws => { | ||
129 | return ws.output === bar.screen.name && ws.is_active; | ||
130 | })?.active_window_id; | ||
131 | |||
132 | return currWindowId ? Array.from(NiriService.windows).find(win => win.id == currWindowId) : null; | ||
133 | } | ||
134 | property var windowEntry: activeWindow ? DesktopEntries.heuristicLookup(activeWindow.app_id) : null | ||
135 | |||
136 | anchors.verticalCenter: parent.verticalCenter | ||
137 | width: activeWindowDisplayContent.width | ||
138 | height: parent.height | ||
139 | |||
140 | Row { | ||
141 | id: activeWindowDisplayContent | ||
142 | |||
143 | width: childrenRect.width | ||
144 | height: parent.height | ||
145 | anchors.verticalCenter: parent.verticalCenter | ||
146 | spacing: 8 | ||
147 | |||
148 | IconImage { | ||
149 | id: activeWindowIcon | ||
150 | |||
151 | height: 14 | ||
152 | width: 14 | ||
153 | |||
154 | anchors.verticalCenter: parent.verticalCenter | ||
155 | |||
156 | source: { | ||
157 | let icon = activeWindowDisplay.windowEntry?.icon | ||
158 | if (typeof icon === 'string' || icon instanceof String) { | ||
159 | if (icon.includes("?path=")) { | ||
160 | const split = icon.split("?path=") | ||
161 | if (split.length !== 2) | ||
162 | return icon | ||
163 | const name = split[0] | ||
164 | const path = split[1] | ||
165 | const fileName = name.substring( | ||
166 | name.lastIndexOf("/") + 1) | ||
167 | return `file://${path}/${fileName}` | ||
168 | } else | ||
169 | icon = Quickshell.iconPath(icon); | ||
170 | return icon | ||
171 | } | ||
172 | return "" | ||
173 | } | ||
174 | asynchronous: true | ||
175 | smooth: true | ||
176 | mipmap: true | ||
177 | } | ||
178 | |||
179 | Text { | ||
180 | id: windowTitle | ||
181 | |||
182 | width: Math.min(implicitWidth, bar.width - 2*Math.max(left.width, right.width) - 2*8 - activeWindowIcon.width - activeWindowDisplayContent.spacing) | ||
183 | |||
184 | property var appAliases: { "Firefox": "Mozilla Firefox", "mpv Media Player": "mpv", "Thunderbird": "Mozilla Thunderbird", "Thunderbird (LMU)": "Mozilla Thunderbird" } | ||
185 | |||
186 | elide: Text.ElideRight | ||
187 | maximumLineCount: 1 | ||
188 | color: "white" | ||
189 | anchors.verticalCenter: parent.verticalCenter | ||
190 | text: { | ||
191 | if (!activeWindowDisplay.activeWindow) | ||
192 | return ""; | ||
193 | |||
194 | var title = activeWindowDisplay.activeWindow.title; | ||
195 | var appName = activeWindowDisplay.windowEntry?.name; | ||
196 | if (appAliases[appName]) | ||
197 | appName = appAliases[appName]; | ||
198 | if (appName && title.endsWith(appName)) { | ||
199 | const oldTitle = title; | ||
200 | title = title.substring(0, title.length - appName.length); | ||
201 | title = title.replace(/\s*(—|-)\s*$/, ""); | ||
202 | if (!title) | ||
203 | title = oldTitle; | ||
204 | } | ||
205 | return title; | ||
206 | } | ||
207 | } | ||
208 | } | ||
209 | } | 54 | } |
210 | } | 55 | } |
211 | 56 | ||
@@ -217,160 +62,22 @@ PanelWindow { | |||
217 | anchors.right: parent.right | 62 | anchors.right: parent.right |
218 | anchors.rightMargin: 8 | 63 | anchors.rightMargin: 8 |
219 | anchors.verticalCenter: parent.verticalCenter | 64 | anchors.verticalCenter: parent.verticalCenter |
220 | spacing: 8 | 65 | spacing: 0 |
221 | |||
222 | Rectangle { | ||
223 | id: kbdWidget | ||
224 | 66 | ||
225 | property var keyboardAbbrev: { "English (programmer Dvorak)": "dvp", "English (US)": "us" } | 67 | SystemTray {} |
226 | 68 | ||
227 | width: kbdLabel.contentWidth | 69 | Item { |
228 | color: { | ||
229 | /* if (kbdMouseArea.containsMouse) { | ||
230 | return "#33808080"; | ||
231 | } */ | ||
232 | return "transparent"; | ||
233 | } | ||
234 | height: parent.height | 70 | height: parent.height |
235 | anchors.verticalCenter: parent.verticalCenter | 71 | width: 4 |
236 | |||
237 | MouseArea { | ||
238 | id: kbdMouseArea | ||
239 | |||
240 | anchors.fill: parent | ||
241 | hoverEnabled: true | ||
242 | cursorShape: Qt.PointingHandCursor | ||
243 | enabled: true | ||
244 | onClicked: { | ||
245 | NiriService.sendCommand({ "Action": { "SwitchLayout": { "layout": "Next" } } }, _ => {}) | ||
246 | } | ||
247 | } | ||
248 | |||
249 | Text { | ||
250 | id: kbdLabel | ||
251 | |||
252 | font.pointSize: 10 | ||
253 | font.family: "Fira Sans" | ||
254 | color: { | ||
255 | if (NiriService.keyboardLayouts?.current_idx === 0) | ||
256 | return "#555"; | ||
257 | return "white"; | ||
258 | } | ||
259 | anchors.centerIn: parent | ||
260 | |||
261 | text: { | ||
262 | const currentLayout = NiriService.keyboardLayouts?.names?.[NiriService.keyboardLayouts.current_idx]; | ||
263 | return kbdWidget.keyboardAbbrev[currentLayout] ? kbdWidget.keyboardAbbrev[currentLayout] : currentLayout; | ||
264 | } | ||
265 | } | ||
266 | } | 72 | } |
267 | 73 | ||
74 | KeyboardLayout {} | ||
75 | |||
268 | Item { | 76 | Item { |
269 | anchors.verticalCenter: parent.verticalCenter | ||
270 | width: systemTrayRow.childrenRect.width | ||
271 | height: parent.height | 77 | height: parent.height |
272 | clip: true | 78 | width: 4 |
273 | |||
274 | Row { | ||
275 | id: systemTrayRow | ||
276 | anchors.centerIn: parent | ||
277 | width: childrenRect.width | ||
278 | height: parent.height | ||
279 | spacing: 0 | ||
280 | |||
281 | Repeater { | ||
282 | model: SystemTray.items.values | ||
283 | |||
284 | delegate: Item { | ||
285 | property var trayItem: modelData | ||
286 | property string iconSource: { | ||
287 | let icon = trayItem && trayItem.icon | ||
288 | if (typeof icon === 'string' || icon instanceof String) { | ||
289 | if (icon.includes("?path=")) { | ||
290 | const split = icon.split("?path=") | ||
291 | if (split.length !== 2) | ||
292 | return icon | ||
293 | const name = split[0] | ||
294 | const path = split[1] | ||
295 | const fileName = name.substring( | ||
296 | name.lastIndexOf("/") + 1) | ||
297 | return `file://${path}/${fileName}` | ||
298 | } | ||
299 | return icon | ||
300 | } | ||
301 | return "" | ||
302 | } | ||
303 | |||
304 | width: 16 | ||
305 | height: parent.height | ||
306 | anchors.verticalCenter: parent.verticalCenter | ||
307 | |||
308 | IconImage { | ||
309 | anchors.centerIn: parent | ||
310 | width: parent.width | ||
311 | height: parent.width | ||
312 | source: parent.iconSource | ||
313 | asynchronous: true | ||
314 | smooth: true | ||
315 | mipmap: true | ||
316 | } | ||
317 | |||
318 | MouseArea { | ||
319 | id: trayItemArea | ||
320 | |||
321 | anchors.fill: parent | ||
322 | acceptedButtons: Qt.LeftButton | Qt.RightButton | ||
323 | hoverEnabled: true | ||
324 | cursorShape: Qt.PointingHandCursor | ||
325 | onClicked: mouse => { | ||
326 | if (!trayItem) | ||
327 | return | ||
328 | |||
329 | if (mouse.button === Qt.LeftButton | ||
330 | && !trayItem.onlyMenu) { | ||
331 | trayItem.activate() | ||
332 | return | ||
333 | } | ||
334 | |||
335 | if (trayItem.hasMenu) { | ||
336 | var globalPos = mapToGlobal(0, 0) | ||
337 | var currentScreen = screen || Screen | ||
338 | var screenX = currentScreen.x || 0 | ||
339 | var relativeX = globalPos.x - screenX | ||
340 | menuAnchor.menu = trayItem.menu | ||
341 | menuAnchor.anchor.window = bar | ||
342 | menuAnchor.anchor.rect = Qt.rect( | ||
343 | relativeX, | ||
344 | 21, | ||
345 | parent.width, 1) | ||
346 | menuAnchor.open() | ||
347 | } | ||
348 | } | ||
349 | } | ||
350 | } | ||
351 | } | ||
352 | } | ||
353 | QsMenuAnchor { | ||
354 | id: menuAnchor | ||
355 | } | ||
356 | } | 79 | } |
357 | 80 | ||
358 | Text { | 81 | Clock {} |
359 | id: clock | ||
360 | color: "white" | ||
361 | |||
362 | anchors.verticalCenter: parent.verticalCenter | ||
363 | |||
364 | Custom.Chrono { | ||
365 | id: chrono | ||
366 | format: "W{0:%V-%u} {0:%F} {0:%H:%M:%S%Ez}" | ||
367 | } | ||
368 | |||
369 | text: chrono.date | ||
370 | |||
371 | font.pointSize: 10 | ||
372 | font.family: "Fira Sans" | ||
373 | font.features: { "tnum": 1 } | ||
374 | } | ||
375 | } | 82 | } |
376 | } \ No newline at end of file | 83 | } \ No newline at end of file |