summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--accounts/gkleen@sif/shell/quickshell/ActiveWindowDisplay.qml3
-rw-r--r--accounts/gkleen@sif/shell/quickshell/Bar.qml10
-rw-r--r--accounts/gkleen@sif/shell/quickshell/Clock.qml277
-rw-r--r--accounts/gkleen@sif/shell/quickshell/KeyboardLayout.qml104
-rw-r--r--accounts/gkleen@sif/shell/quickshell/Services/NiriService.qml8
-rw-r--r--accounts/gkleen@sif/shell/quickshell/SystemTray.qml55
-rw-r--r--accounts/gkleen@sif/shell/quickshell/WorkspaceSwitcher.qml85
-rw-r--r--accounts/gkleen@sif/shell/quickshell/shell.qml12
8 files changed, 333 insertions, 221 deletions
diff --git a/accounts/gkleen@sif/shell/quickshell/ActiveWindowDisplay.qml b/accounts/gkleen@sif/shell/quickshell/ActiveWindowDisplay.qml
index d7e8e7c5..57ade488 100644
--- a/accounts/gkleen@sif/shell/quickshell/ActiveWindowDisplay.qml
+++ b/accounts/gkleen@sif/shell/quickshell/ActiveWindowDisplay.qml
@@ -7,10 +7,11 @@ Item {
7 id: activeWindowDisplay 7 id: activeWindowDisplay
8 8
9 required property int maxWidth 9 required property int maxWidth
10 required property var screen
10 11
11 property var activeWindow: { 12 property var activeWindow: {
12 let currWindowId = Array.from(NiriService.workspaces).find(ws => { 13 let currWindowId = Array.from(NiriService.workspaces).find(ws => {
13 return ws.output === bar.screen.name && ws.is_active; 14 return ws.output === screen.name && ws.is_active;
14 })?.active_window_id; 15 })?.active_window_id;
15 16
16 return currWindowId ? Array.from(NiriService.windows).find(win => win.id == currWindowId) : null; 17 return currWindowId ? Array.from(NiriService.windows).find(win => win.id == currWindowId) : null;
diff --git a/accounts/gkleen@sif/shell/quickshell/Bar.qml b/accounts/gkleen@sif/shell/quickshell/Bar.qml
index accad2a9..aab1607f 100644
--- a/accounts/gkleen@sif/shell/quickshell/Bar.qml
+++ b/accounts/gkleen@sif/shell/quickshell/Bar.qml
@@ -5,7 +5,9 @@ import QtQuick
5PanelWindow { 5PanelWindow {
6 id: bar 6 id: bar
7 7
8 property var modelData 8 required property var screen
9
10 property var calendarMouseArea: clock.calendarMouseArea
9 11
10 anchors { 12 anchors {
11 top: true 13 top: true
@@ -17,7 +19,6 @@ PanelWindow {
17 right: 26 + 8 19 right: 26 + 8
18 } 20 }
19 21
20 screen: modelData
21 implicitHeight: 21 22 implicitHeight: 21
22 color: "transparent" 23 color: "transparent"
23 24
@@ -50,6 +51,7 @@ PanelWindow {
50 spacing: 5 51 spacing: 5
51 52
52 ActiveWindowDisplay { 53 ActiveWindowDisplay {
54 screen: bar.screen
53 maxWidth: bar.width - 2*Math.max(left.width, right.width) - 2*8 55 maxWidth: bar.width - 2*Math.max(left.width, right.width) - 2*8
54 } 56 }
55 } 57 }
@@ -78,6 +80,8 @@ PanelWindow {
78 width: 4 80 width: 4
79 } 81 }
80 82
81 Clock {} 83 Clock {
84 id: clock
85 }
82 } 86 }
83} \ No newline at end of file 87} \ No newline at end of file
diff --git a/accounts/gkleen@sif/shell/quickshell/Clock.qml b/accounts/gkleen@sif/shell/quickshell/Clock.qml
index 68efb558..d645cfa7 100644
--- a/accounts/gkleen@sif/shell/quickshell/Clock.qml
+++ b/accounts/gkleen@sif/shell/quickshell/Clock.qml
@@ -7,11 +7,13 @@ import QtQuick.Layouts
7import Quickshell.Widgets 7import Quickshell.Widgets
8 8
9Item { 9Item {
10 id: clockItem
11
10 width: clock.contentWidth 12 width: clock.contentWidth
11 height: parent.height 13 height: parent.height
12 anchors.verticalCenter: parent.verticalCenter 14 anchors.verticalCenter: parent.verticalCenter
13 15
14 MouseArea { 16 WrapperMouseArea {
15 id: clockMouseArea 17 id: clockMouseArea
16 18
17 anchors.fill: parent 19 anchors.fill: parent
@@ -21,38 +23,56 @@ Item {
21 property real angleRem: 0 23 property real angleRem: 0
22 property real sensitivity: 1 / 120 24 property real sensitivity: 1 / 120
23 25
24 onWheel: event => { 26 function scrollYear(event) {
25 angleRem += event.angleDelta.y; 27 angleRem += event.angleDelta.y;
26 const d = Math.round(angleRem * sensitivity); 28 const d = Math.round(angleRem * sensitivity);
27 yearCalendar.year += d; 29 yearCalendar.year += d;
28 angleRem -= d / sensitivity; 30 angleRem -= d / sensitivity;
29 } 31 }
30 }
31 32
32 Text { 33 onWheel: event => scrollYear(event)
33 id: clock
34 color: "white"
35 34
36 anchors.verticalCenter: parent.verticalCenter 35 Item {
36 anchors.fill: parent
37 37
38 Custom.Chrono { 38 Text {
39 id: chrono 39 id: clock
40 format: "W{0:%V-%u} {0:%F} {0:%H:%M:%S%Ez}" 40 color: "white"
41 } 41
42 anchors.verticalCenter: parent.verticalCenter
43
44 Custom.Chrono {
45 id: chrono
46 format: "W{0:%V-%u} {0:%F} {0:%H:%M:%S%Ez}"
47 }
42 48
43 text: chrono.date 49 text: chrono.date
44 50
45 font.pointSize: 10 51 font.pointSize: 10
46 font.family: "Fira Sans" 52 font.family: "Fira Sans"
47 font.features: { "tnum": 1 } 53 font.features: { "tnum": 1 }
54 }
55 }
48 } 56 }
49 57
50 PopupWindow { 58 PopupWindow {
59 id: tooltip
60
61 property bool nextVisible: clockMouseArea.containsMouse || tooltipMouseArea.containsMouse
62
51 anchor { 63 anchor {
52 item: clockMouseArea 64 item: clockMouseArea
53 edges: Edges.Bottom 65 edges: Edges.Bottom | Edges.Left
66 }
67 visible: false
68
69 onNextVisibleChanged: hangTimer.restart()
70
71 Timer {
72 id: hangTimer
73 interval: 100
74 onTriggered: tooltip.visible = tooltip.nextVisible
54 } 75 }
55 visible: clockMouseArea.containsMouse
56 76
57 implicitWidth: clockTooltipContent.width 77 implicitWidth: clockTooltipContent.width
58 implicitHeight: clockTooltipContent.height 78 implicitHeight: clockTooltipContent.height
@@ -64,159 +84,170 @@ Item {
64 clockMouseArea.angleRem = 0; 84 clockMouseArea.angleRem = 0;
65 } 85 }
66 86
67 WrapperItem { 87 WrapperMouseArea {
68 id: clockTooltipContent 88 id: tooltipMouseArea
69
70 margin: 8
71 leftMargin: 0
72 89
73 ColumnLayout { 90 hoverEnabled: true
74 Text { 91 enabled: true
75 id: yearLabel
76 92
77 horizontalAlignment: Text.AlignHCenter 93 onWheel: event => clockMouseArea.scrollYear(event)
78 94
79 font.pointSize: 14 95 anchors.fill: parent
80 font.family: "Fira Sans"
81 font.features: { "tnum": 1 }
82 color: "white"
83 96
84 text: yearCalendar.year 97 WrapperItem {
98 id: clockTooltipContent
85 99
86 Layout.fillWidth: true 100 margin: 8
87 Layout.bottomMargin: 8 101 leftMargin: 0
88 }
89 102
90 GridLayout { 103 ColumnLayout {
91 property int year: { const d = new Date(); return d.getFullYear(); } 104 Text {
105 id: yearLabel
92 106
93 id: yearCalendar 107 horizontalAlignment: Text.AlignHCenter
94 108
95 columns: 3 109 font.pointSize: 14
96 columnSpacing: 16 110 font.family: "Fira Sans"
97 rowSpacing: 16 111 font.features: { "tnum": 1 }
112 color: "white"
98 113
99 Layout.alignment: Qt.AlignHCenter 114 text: yearCalendar.year
100 Layout.fillWidth: false
101 115
102 Repeater { 116 Layout.fillWidth: true
103 model: 12 117 Layout.bottomMargin: 8
118 }
104 119
105 GridLayout { 120 GridLayout {
106 columns: 2 121 property int year: { const d = new Date(); return d.getFullYear(); }
107 122
108 required property int index 123 id: yearCalendar
109 property int month: index
110 124
111 id: monthCalendar 125 columns: 3
126 columnSpacing: 16
127 rowSpacing: 16
112 128
113 Layout.alignment: Qt.AlignTop | Qt.AlignRight 129 Layout.alignment: Qt.AlignHCenter
114 Layout.fillWidth: false 130 Layout.fillWidth: false
115 131
116 Text { 132 Repeater {
117 Layout.column: 1 133 model: 12
118 Layout.fillWidth: true
119 134
120 horizontalAlignment: Text.AlignHCenter 135 GridLayout {
136 columns: 2
121 137
122 font.pointSize: 10 138 required property int index
123 font.family: "Fira Sans" 139 property int month: index
124 140
125 text: { 141 id: monthCalendar
126 const date = Date.fromLocaleDateString(Qt.locale(), `${yearCalendar.year}-${monthCalendar.month + 1}-01`, "yyyy-M-dd");
127 return date.toLocaleString(Qt.locale("en_DK"), "MMMM")
128 }
129 142
130 color: "#ffead3" 143 Layout.alignment: Qt.AlignTop | Qt.AlignRight
131 } 144 Layout.fillWidth: false
132 145
133 DayOfWeekRow { 146 Text {
134 locale: grid.locale 147 Layout.column: 1
148 Layout.fillWidth: true
135 149
136 Layout.row: 1 150 horizontalAlignment: Text.AlignHCenter
137 Layout.column: 1
138 Layout.fillWidth: true
139
140 delegate: Text {
141 required property string shortName
142 151
143 font.pointSize: 10 152 font.pointSize: 10
144 font.family: "Fira Mono" 153 font.family: "Fira Sans"
145 154
146 text: shortName 155 text: {
147 color: "#ffcc66" 156 const date = Date.fromLocaleDateString(Qt.locale(), `${yearCalendar.year}-${monthCalendar.month + 1}-01`, "yyyy-M-dd");
157 return date.toLocaleString(Qt.locale("en_DK"), "MMMM")
158 }
148 159
149 horizontalAlignment: Text.AlignRight 160 color: "#ffead3"
150 verticalAlignment: Text.AlignVCenter
151 } 161 }
152 }
153
154 WeekNumberColumn {
155 month: grid.month
156 year: grid.year
157 locale: grid.locale
158 162
159 Layout.fillHeight: true 163 DayOfWeekRow {
164 locale: grid.locale
160 165
161 delegate: Text { 166 Layout.row: 1
162 required property int weekNumber 167 Layout.column: 1
168 Layout.fillWidth: true
163 169
164 opacity: { 170 delegate: Text {
165 const simple = new Date(weekNumber == 1 && monthCalendar.month == 12 ? yearCalendar.year + 1 : yearCalendar.year, 0, 1 + (weekNumber - 1) * 7); 171 required property string shortName
166 const dayOfWeek = simple.getDay();
167 const isoWeekStart = simple;
168 172
169 isoWeekStart.setDate(simple.getDate() - dayOfWeek + 1); 173 font.pointSize: 10
170 if (dayOfWeek > 4) { 174 font.family: "Fira Mono"
171 isoWeekStart.setDate(isoWeekStart.getDate() + 7);
172 }
173 175
174 for (let i = 0; i < 7; i++) { 176 text: shortName
175 const dayInWeek = new Date(isoWeekStart); 177 color: "#ffcc66"
176 dayInWeek.setDate(dayInWeek.getDate() + i);
177 if (dayInWeek.getMonth() == monthCalendar.month)
178 return 1;
179 }
180 178
181 return 0; 179 horizontalAlignment: Text.AlignRight
180 verticalAlignment: Text.AlignVCenter
182 } 181 }
182 }
183 183
184 font.pointSize: 10 184 WeekNumberColumn {
185 font.family: "Fira Sans" 185 month: grid.month
186 font.features: { "tnum": 1 } 186 year: grid.year
187 187 locale: grid.locale
188 text: weekNumber
189 color: "#99ffdd"
190 188
191 horizontalAlignment: Text.AlignRight 189 Layout.fillHeight: true
192 verticalAlignment: Text.AlignVCenter
193 }
194 }
195 190
196 MonthGrid { 191 delegate: Text {
197 id: grid 192 required property int weekNumber
198 193
199 year: yearCalendar.year 194 opacity: {
200 month: monthCalendar.month 195 const simple = new Date(weekNumber == 1 && monthCalendar.month == 12 ? yearCalendar.year + 1 : yearCalendar.year, 0, 1 + (weekNumber - 1) * 7);
201 locale: Qt.locale("en_DK") 196 const dayOfWeek = simple.getDay();
197 const isoWeekStart = simple;
202 198
203 Layout.fillWidth: true 199 isoWeekStart.setDate(simple.getDate() - dayOfWeek + 1);
204 Layout.fillHeight: true 200 if (dayOfWeek > 4) {
201 isoWeekStart.setDate(isoWeekStart.getDate() + 7);
202 }
205 203
206 delegate: Text { 204 for (let i = 0; i < 7; i++) {
207 required property var model 205 const dayInWeek = new Date(isoWeekStart);
206 dayInWeek.setDate(dayInWeek.getDate() + i);
207 if (dayInWeek.getMonth() == monthCalendar.month)
208 return 1;
209 }
208 210
209 opacity: model.month === monthCalendar.month ? 1 : 0 211 return 0;
212 }
210 213
211 font.pointSize: 10 214 font.pointSize: 10
212 font.family: "Fira Sans" 215 font.family: "Fira Sans"
213 font.features: { "tnum": 1 } 216 font.features: { "tnum": 1 }
214 217
215 text: model.day 218 text: weekNumber
216 color: model.today ? "#ff6699" : "white" 219 color: "#99ffdd"
217 220
218 horizontalAlignment: Text.AlignRight 221 horizontalAlignment: Text.AlignRight
219 verticalAlignment: Text.AlignVCenter 222 verticalAlignment: Text.AlignVCenter
223 }
224 }
225
226 MonthGrid {
227 id: grid
228
229 year: yearCalendar.year
230 month: monthCalendar.month
231 locale: Qt.locale("en_DK")
232
233 Layout.fillWidth: true
234 Layout.fillHeight: true
235
236 delegate: Text {
237 required property var model
238
239 opacity: model.month === monthCalendar.month ? 1 : 0
240
241 font.pointSize: 10
242 font.family: "Fira Sans"
243 font.features: { "tnum": 1 }
244
245 text: model.day
246 color: model.today ? "#ff6699" : "white"
247
248 horizontalAlignment: Text.AlignRight
249 verticalAlignment: Text.AlignVCenter
250 }
220 } 251 }
221 } 252 }
222 } 253 }
@@ -225,4 +256,4 @@ Item {
225 } 256 }
226 } 257 }
227 } 258 }
228} \ No newline at end of file 259}
diff --git a/accounts/gkleen@sif/shell/quickshell/KeyboardLayout.qml b/accounts/gkleen@sif/shell/quickshell/KeyboardLayout.qml
index 710ea10c..bc3750f9 100644
--- a/accounts/gkleen@sif/shell/quickshell/KeyboardLayout.qml
+++ b/accounts/gkleen@sif/shell/quickshell/KeyboardLayout.qml
@@ -1,77 +1,105 @@
1import Quickshell 1import Quickshell
2import QtQuick 2import QtQuick
3import qs.Services 3import qs.Services
4import Quickshell.Widgets
4 5
5Rectangle { 6Item {
6 id: kbdWidget
7
8 property var keyboardAbbrev: { "English (programmer Dvorak)": "dvp", "English (US)": "us" }
9
10 width: kbdLabel.contentWidth + 8 7 width: kbdLabel.contentWidth + 8
11 color: {
12 if (kbdMouseArea.containsMouse) {
13 return "#33808080";
14 }
15 return "transparent";
16 }
17 height: parent.height 8 height: parent.height
18 anchors.verticalCenter: parent.verticalCenter 9 anchors.verticalCenter: parent.verticalCenter
19 10
20 MouseArea { 11 WrapperMouseArea {
21 id: kbdMouseArea 12 id: kbdMouseArea
22 13
23 anchors.fill: parent 14 anchors.fill: parent
15
24 hoverEnabled: true 16 hoverEnabled: true
25 cursorShape: Qt.PointingHandCursor 17 cursorShape: Qt.PointingHandCursor
26 enabled: true 18 enabled: true
27 onClicked: { 19 onClicked: {
28 NiriService.sendCommand({ "Action": { "SwitchLayout": { "layout": "Next" } } }, _ => {}) 20 NiriService.sendCommand({ "Action": { "SwitchLayout": { "layout": "Next" } } }, _ => {})
29 } 21 }
30 } 22 onWheel: event => {
23 NiriService.sendCommand({ "Action": { "SwitchLayout": { "layout": event.angleDelta > 0 ? "Next" : "Prev" } } }, _ => {})
24 }
31 25
32 Text { 26 Rectangle {
33 id: kbdLabel 27 id: kbdWidget
34 28
35 font.pointSize: 10 29 property var keyboardAbbrev: { "English (programmer Dvorak)": "dvp", "English (US)": "us" }
36 font.family: "Fira Sans" 30
37 color: { 31 anchors.fill: parent
38 if (NiriService.keyboardLayouts?.current_idx === 0) 32 color: {
39 return "#555"; 33 if (kbdMouseArea.containsMouse) {
40 return "white"; 34 return "#33808080";
41 } 35 }
42 anchors.centerIn: parent 36 return "transparent";
37 }
43 38
44 text: { 39 Text {
45 const currentLayout = NiriService.keyboardLayouts?.names?.[NiriService.keyboardLayouts.current_idx]; 40 id: kbdLabel
46 if (!currentLayout) 41
47 return ""; 42 font.pointSize: 10
48 return kbdWidget.keyboardAbbrev[currentLayout] ? kbdWidget.keyboardAbbrev[currentLayout] : currentLayout; 43 font.family: "Fira Sans"
44 color: {
45 if (NiriService.keyboardLayouts?.current_idx === 0)
46 return "#555";
47 return "white";
48 }
49 anchors.centerIn: parent
50
51 text: {
52 const currentLayout = NiriService.keyboardLayouts?.names?.[NiriService.keyboardLayouts.current_idx];
53 if (!currentLayout)
54 return "";
55 return kbdWidget.keyboardAbbrev[currentLayout] ? kbdWidget.keyboardAbbrev[currentLayout] : currentLayout;
56 }
57 }
49 } 58 }
50 } 59 }
51 60
52 PopupWindow { 61 PopupWindow {
62 id: tooltip
63
64 property bool nextVisible: kbdMouseArea.containsMouse || tooltipMouseArea.containsMouse
65
53 anchor { 66 anchor {
54 item: kbdMouseArea 67 item: kbdMouseArea
55 edges: Edges.Bottom 68 edges: Edges.Bottom | Edges.Left
69 }
70 visible: false
71
72 onNextVisibleChanged: hangTimer.restart()
73
74 Timer {
75 id: hangTimer
76 interval: 100
77 onTriggered: tooltip.visible = tooltip.nextVisible
56 } 78 }
57 visible: kbdMouseArea.containsMouse
58 79
59 implicitWidth: kbdTooltipText.contentWidth + 16 80 implicitWidth: kbdTooltipText.contentWidth + 16
60 implicitHeight: kbdTooltipText.contentHeight + 16 81 implicitHeight: kbdTooltipText.contentHeight + 16
61 color: "black" 82 color: "black"
62 83
63 Text { 84 WrapperMouseArea {
64 id: kbdTooltipText 85 id: tooltipMouseArea
86
87 hoverEnabled: true
88 enabled: true
65 89
66 anchors.centerIn: parent 90 anchors.centerIn: parent
67 91
68 font.pointSize: 10 92 Text {
69 font.family: "Fira Sans" 93 id: kbdTooltipText
70 color: "white" 94
95 font.pointSize: 10
96 font.family: "Fira Sans"
97 color: "white"
71 98
72 text: { 99 text: {
73 const currentLayout = NiriService.keyboardLayouts?.names?.[NiriService.keyboardLayouts.current_idx]; 100 const currentLayout = NiriService.keyboardLayouts?.names?.[NiriService.keyboardLayouts.current_idx];
74 return currentLayout || ""; 101 return currentLayout || "";
102 }
75 } 103 }
76 } 104 }
77 } 105 }
diff --git a/accounts/gkleen@sif/shell/quickshell/Services/NiriService.qml b/accounts/gkleen@sif/shell/quickshell/Services/NiriService.qml
index c82caaa6..179b55e0 100644
--- a/accounts/gkleen@sif/shell/quickshell/Services/NiriService.qml
+++ b/accounts/gkleen@sif/shell/quickshell/Services/NiriService.qml
@@ -28,9 +28,12 @@ Singleton {
28 path: root.socketPath 28 path: root.socketPath
29 connected: true 29 connected: true
30 30
31 property bool acked: false
32
31 onConnectionStateChanged: { 33 onConnectionStateChanged: {
32 if (connected) { 34 if (connected) {
33 write('"EventStream"\n') 35 acked = false;
36 write('"EventStream"\n');
34 } 37 }
35 } 38 }
36 39
@@ -66,6 +69,9 @@ Singleton {
66 eventWindowUrgencyChanged(event.WindowUrgencyChanged); 69 eventWindowUrgencyChanged(event.WindowUrgencyChanged);
67 else if (event.WindowLayoutsChanged) 70 else if (event.WindowLayoutsChanged)
68 eventWindowLayoutsChanged(event.WindowLayoutsChanged); 71 eventWindowLayoutsChanged(event.WindowLayoutsChanged);
72 else if (event.Ok && !eventStreamSocket.acked) { eventStreamSocket.acked = true; }
73 else if (event.OverviewOpenedOrClosed) {}
74 else if (event.ConfigLoaded) {}
69 else 75 else
70 console.log(JSON.stringify(event)); 76 console.log(JSON.stringify(event));
71 } catch (e) { 77 } catch (e) {
diff --git a/accounts/gkleen@sif/shell/quickshell/SystemTray.qml b/accounts/gkleen@sif/shell/quickshell/SystemTray.qml
index afed4bf0..55b1690e 100644
--- a/accounts/gkleen@sif/shell/quickshell/SystemTray.qml
+++ b/accounts/gkleen@sif/shell/quickshell/SystemTray.qml
@@ -17,13 +17,17 @@ Item {
17 spacing: 0 17 spacing: 0
18 18
19 Repeater { 19 Repeater {
20 model: { 20 model: ScriptModel {
21 var trayItems = Array.from(SystemTray.items.values).filter(item => item.status !== Status.Passive); 21 values: {
22 trayItems.sort((a, b) => a.category !== b.category ? b.category - a.category : a.id.localeCompare(b.id)) 22 var trayItems = Array.from(SystemTray.items.values).filter(item => item.status !== Status.Passive);
23 return trayItems; 23 trayItems.sort((a, b) => a.category !== b.category ? b.category - a.category : a.id.localeCompare(b.id))
24 return trayItems;
25 }
24 } 26 }
25 27
26 delegate: Item { 28 delegate: Item {
29 id: trayItemWrapper
30
27 property var trayItem: modelData 31 property var trayItem: modelData
28 property string iconSource: { 32 property string iconSource: {
29 let icon = trayItem && trayItem.icon 33 let icon = trayItem && trayItem.icon
@@ -47,17 +51,7 @@ Item {
47 height: parent.height 51 height: parent.height
48 anchors.verticalCenter: parent.verticalCenter 52 anchors.verticalCenter: parent.verticalCenter
49 53
50 IconImage { 54 WrapperMouseArea {
51 anchors.centerIn: parent
52 width: parent.width
53 height: parent.width
54 source: parent.iconSource
55 asynchronous: true
56 smooth: true
57 mipmap: true
58 }
59
60 MouseArea {
61 id: trayItemArea 55 id: trayItemArea
62 56
63 anchors.fill: parent 57 anchors.fill: parent
@@ -88,21 +82,48 @@ Item {
88 menuAnchor.open() 82 menuAnchor.open()
89 } 83 }
90 } 84 }
85
86 IconImage {
87 anchors.centerIn: parent
88 width: parent.width
89 height: parent.width
90 source: trayItemWrapper.iconSource
91 asynchronous: true
92 smooth: true
93 mipmap: true
94 }
91 } 95 }
92 96
93 PopupWindow { 97 PopupWindow {
98 id: tooltip
99
100 property bool nextVisible: (trayItem.tooltipTitle || trayItem.tooltipDescription) && (trayItemArea.containsMouse || tooltipMouseArea.containsMouse) && !menuAnchor.visible
101
94 anchor { 102 anchor {
95 item: trayItemArea 103 item: trayItemArea
96 edges: Edges.Bottom 104 edges: Edges.Bottom
97 } 105 }
98 visible: (trayItem.tooltipTitle || trayItem.tooltipDescription) && trayItemArea.containsMouse && !menuAnchor.visible 106
107 visible: false
108 onNextVisibleChanged: hangTimer.restart()
109
110 Timer {
111 id: hangTimer
112 interval: 100
113 onTriggered: tooltip.visible = tooltip.nextVisible
114 }
99 115
100 color: "black" 116 color: "black"
101 117
102 implicitWidth: Math.max(tooltipTitle.contentWidth, tooltipDescription.contentWidth) + 16 118 implicitWidth: Math.max(tooltipTitle.contentWidth, tooltipDescription.contentWidth) + 16
103 implicitHeight: tooltipTitle.contentHeight + tooltipDescription.contentHeight + 16 119 implicitHeight: tooltipTitle.contentHeight + tooltipDescription.contentHeight + 16
104 120
105 WrapperItem { 121 WrapperMouseArea {
122 id: tooltipMouseArea
123
124 hoverEnabled: true
125 enabled: true
126
106 margin: 8 127 margin: 8
107 128
108 Column { 129 Column {
diff --git a/accounts/gkleen@sif/shell/quickshell/WorkspaceSwitcher.qml b/accounts/gkleen@sif/shell/quickshell/WorkspaceSwitcher.qml
index 153c56bb..9546abb4 100644
--- a/accounts/gkleen@sif/shell/quickshell/WorkspaceSwitcher.qml
+++ b/accounts/gkleen@sif/shell/quickshell/WorkspaceSwitcher.qml
@@ -1,5 +1,7 @@
1import Quickshell
1import QtQuick 2import QtQuick
2import qs.Services 3import qs.Services
4import Quickshell.Widgets
3 5
4Row { 6Row {
5 id: workspaces 7 id: workspaces
@@ -11,61 +13,72 @@ Row {
11 spacing: 0 13 spacing: 0
12 14
13 Repeater { 15 Repeater {
14 model: { 16 model: ScriptModel {
15 let currWorkspaces = NiriService.workspaces; 17 values: {
16 const ignoreWorkspaces = Array.from(workspaces.ignoreWorkspaces); 18 let currWorkspaces = NiriService.workspaces;
17 currWorkspaces = currWorkspaces.filter(ws => ws.is_active || ignoreWorkspaces.every(iws => iws !== ws.name)); 19 const ignoreWorkspaces = Array.from(workspaces.ignoreWorkspaces);
18 currWorkspaces.sort((a, b) => { 20 currWorkspaces = currWorkspaces.filter(ws => ws.is_active || ignoreWorkspaces.every(iws => iws !== ws.name));
19 if (NiriService.outputs?.[a.output]?.logical?.x !== NiriService.outputs?.[b.output]?.logical?.x) 21 currWorkspaces.sort((a, b) => {
20 return NiriService.outputs?.[a.output]?.logical?.x - NiriService.outputs?.[b.output]?.logical?.x 22 if (NiriService.outputs?.[a.output]?.logical?.x !== NiriService.outputs?.[b.output]?.logical?.x)
21 if (NiriService.outputs?.[a.output]?.logical?.y !== NiriService.outputs?.[b.output]?.logical?.y) 23 return NiriService.outputs?.[a.output]?.logical?.x - NiriService.outputs?.[b.output]?.logical?.x
22 return NiriService.outputs?.[a.output]?.logical?.y - NiriService.outputs?.[b.output]?.logical?.y 24 if (NiriService.outputs?.[a.output]?.logical?.y !== NiriService.outputs?.[b.output]?.logical?.y)
23 return a.idx - b.idx; 25 return NiriService.outputs?.[a.output]?.logical?.y - NiriService.outputs?.[b.output]?.logical?.y
24 }); 26 return a.idx - b.idx;
25 return currWorkspaces; 27 });
28 return currWorkspaces;
29 }
26 } 30 }
27 31
28 Rectangle { 32 Item {
33 id: wsItem
34
29 property var workspaceData: modelData 35 property var workspaceData: modelData
30 36
31 width: wsLabel.contentWidth + 8 37 width: wsLabel.contentWidth + 8
32 color: {
33 if (mouseArea.containsMouse) {
34 return "#33808080";
35 }
36 return "transparent";
37 }
38 height: parent.height 38 height: parent.height
39 anchors.verticalCenter: parent.verticalCenter 39 anchors.verticalCenter: parent.verticalCenter
40 40
41 MouseArea { 41 WrapperMouseArea {
42 id: mouseArea 42 id: mouseArea
43 43
44 anchors.fill: parent 44 anchors.fill: parent
45
45 hoverEnabled: true 46 hoverEnabled: true
46 cursorShape: Qt.PointingHandCursor 47 cursorShape: Qt.PointingHandCursor
47 enabled: true 48 enabled: true
48 onClicked: { 49 onClicked: {
49 NiriService.sendCommand({ "Action": { "FocusWorkspace": { "reference": { "Id": workspaceData.id } } } }, _ => {}) 50 NiriService.sendCommand({ "Action": { "FocusWorkspace": { "reference": { "Id": workspaceData.id } } } }, _ => {})
50 } 51 }
51 }
52 52
53 Text { 53 Rectangle {
54 id: wsLabel 54 anchors.fill: parent
55 55
56 font.pointSize: 10 56 color: {
57 font.family: "Fira Sans" 57 if (mouseArea.containsMouse) {
58 color: { 58 return "#33808080";
59 if (workspaceData.is_active) 59 }
60 return "#23fd00"; 60 return "transparent";
61 if (workspaceData.active_window_id === null) 61 }
62 return "#555"; 62
63 return "white"; 63 Text {
64 } 64 id: wsLabel
65 anchors.centerIn: parent
66 65
67 text: workspaceData.name ? workspaceData.name : workspaceData.idx 66 anchors.centerIn: parent
67
68 font.pointSize: 10
69 font.family: "Fira Sans"
70 color: {
71 if (workspaceData.is_active)
72 return "#23fd00";
73 if (workspaceData.active_window_id === null)
74 return "#555";
75 return "white";
76 }
77
78 text: workspaceData.name ? workspaceData.name : workspaceData.idx
79 }
80 }
68 } 81 }
69 } 82 }
70 } 83 }
71} \ No newline at end of file 84}
diff --git a/accounts/gkleen@sif/shell/quickshell/shell.qml b/accounts/gkleen@sif/shell/quickshell/shell.qml
index 2abd1fef..4934cd4d 100644
--- a/accounts/gkleen@sif/shell/quickshell/shell.qml
+++ b/accounts/gkleen@sif/shell/quickshell/shell.qml
@@ -8,8 +8,16 @@ ShellRoot {
8 Variants { 8 Variants {
9 model: Quickshell.screens 9 model: Quickshell.screens
10 10
11 delegate: Bar { 11 delegate: Scope {
12 modelData: item 12 id: screenScope
13
14 required property var modelData
15
16 Bar {
17 id: bar
18
19 screen: screenScope.modelData
20 }
13 } 21 }
14 } 22 }
15} 23}