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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
|
pragma Singleton
import Quickshell
Singleton {
id: root
function doLayout(windowList, outerWidth, outerHeight) {
var N = windowList.length
if (N === 0) return []
// Gap: 0.8% of screen, clamped between 12px and 24px
var rawGap = Math.min(outerWidth * 0.08, outerHeight * 0.08)
var gap = Math.max(12, Math.min(24, rawGap))
// Safe Area: 90% of the screen
var contentScale = 0.90
var useW = outerWidth * contentScale
var useH = outerHeight * contentScale
// Global offsets to center everything
var offX = (outerWidth - useW) / 2
var offY = (outerHeight - useH) / 2
// Group by workspace
var groups = {}
var wsOrder = []
for (var i = 0; i < N; i++) {
var w = windowList[i]
var wsId = w.workspaceId
if (!groups[wsId]) {
groups[wsId] = []
wsOrder.push(wsId)
}
groups[wsId].push(w)
}
var bandCount = wsOrder.length
if (bandCount === 0) return []
// Band height & max thumb height
// Calculate the height allocated for each workspace band
var totalGapH = gap * (bandCount - 1)
var bandHeight = (useH - totalGapH) / bandCount
// Aesthetic Cap: Even if we have only 1 workspace,
// windows shouldn't exceed 45% of screen height.
var absoluteMaxH = useH * 0.45
// The effective max height is the smaller of the two.
// If we have 10 bands, bandHeight will be small (e.g. 100px), so that rules.
// If we have 1 band, bandHeight is huge (1000px), so absoluteMaxH (450px) rules.
var localMaxH = Math.min(bandHeight, absoluteMaxH)
// Minimum safety height to avoid division by zero errors
if (localMaxH < 10) localMaxH = 10
var result = []
var currentY = offY
// Process each band
for (var b = 0; b < bandCount; b++) {
var wsId = wsOrder[b]
var items = groups[wsId]
var itemCount = items.length
// ROW LAYOUT CALCULATION (Justified)
var rows = []
var currentRow = []
var currentAspectSum = 0
for (var k = 0; k < itemCount; k++) {
var item = items[k]
var w0 = (item.width > 0) ? item.width : 100
var h0 = (item.height > 0) ? item.height : 100
var aspect = w0 / h0
var wrapper = { win: item.win, aspect: aspect }
// Check overflow: (SumAspects * MaxH) + Gaps > Width
var hypotheticalWidth = (currentAspectSum + aspect) * localMaxH + (currentRow.length * gap)
if (currentRow.length > 0 && hypotheticalWidth > useW) {
rows.push({ items: currentRow, aspectSum: currentAspectSum })
currentRow = []
currentAspectSum = 0
}
currentRow.push(wrapper)
currentAspectSum += aspect
}
if (currentRow.length > 0) {
rows.push({ items: currentRow, aspectSum: currentAspectSum })
}
// SCALE & FIT ROWS
// Calculate how tall the content actually is
var totalContentH = 0
var finalRows = []
for (var r = 0; r < rows.length; r++) {
var rowObj = rows[r]
var rItems = rowObj.items
// Optimal Height = (Available Width / Sum Aspects)
var availRowW = useW - (gap * (rItems.length - 1))
var optimalH = availRowW / rowObj.aspectSum
// Clamp to limits
if (optimalH > localMaxH) optimalH = localMaxH
finalRows.push({ items: rItems, h: optimalH })
totalContentH += optimalH
}
// Add vertical gaps between rows inside the band
if (finalRows.length > 1) {
totalContentH += gap * (finalRows.length - 1)
}
// If rows overflow the band height (rare, but possible with many windows), scale down
var scaleFactor = 1.0
if (totalContentH > bandHeight) {
scaleFactor = bandHeight / totalContentH
totalContentH = bandHeight // Cap for centering math
}
// GENERATE COORDINATES
// Center the content vertically within the band slot
// Note: If bandCount=1, bandHeight is huge (90% screen), but totalContentH is constrained by absoluteMaxH.
// This ensures the single row floats nicely in the middle.
var rowY = currentY + (bandHeight - totalContentH) / 2
for (var r2 = 0; r2 < finalRows.length; r2++) {
var fRow = finalRows[r2]
var rHeight = fRow.h * scaleFactor
var rItems2 = fRow.items
// Calculate row width for horizontal centering
var actualRowW = 0
for (var j = 0; j < rItems2.length; j++) {
actualRowW += (rItems2[j].aspect * rHeight)
}
actualRowW += gap * (rItems2.length - 1)
var rowX = offX + (useW - actualRowW) / 2
for (var j2 = 0; j2 < rItems2.length; j2++) {
var it = rItems2[j2]
var finalW = it.aspect * rHeight
result.push({
win: it.win,
x: rowX,
y: rowY,
width: finalW,
height: rHeight
})
rowX += finalW + gap
}
rowY += rHeight + (gap * scaleFactor)
}
// Advance Y to the next band slot
currentY += bandHeight + gap
}
return result
}
}
|