diff options
| author | Don Williams <Don.e.williams@gmail.com> | 2026-07-11 04:31:59 -0400 |
|---|---|---|
| committer | Pinapelz <yukais@pinapelz.com> | 2026-08-29 21:40:34 -0700 |
| commit | 1ee78be8453f86ef366fe7a73e4e8cf245d2d336 (patch) | |
| tree | 72fbbfa17e61299f3eb400b6fd5a27ec52f9b291 /config/quickshell/qs-hyprview/layouts/HeroLayout.qml | |
| parent | 4d39fc9670d5cb0b3e0624ead386d30db3b8110f (diff) | |
Added qs-hyprview as alternative overview
Signed-off-by: Don Williams <Don.e.williams@gmail.com>
On branch development
Your branch is up to date with 'origin/development'.
Changes to be committed:
deleted: ./
new file: LICENSE
new file: README.md
new file: common/Appearance.qml
new file: layouts/BandsLayout.qml
new file: layouts/ColumnarLayout.qml
new file: layouts/HeroLayout.qml
new file: layouts/JustifiedLayout.qml
new file: layouts/LayoutsManager.qml
new file: layouts/MasonryLayout.qml
new file: layouts/SatelliteLayout.qml
new file: layouts/SmartGridLayout.qml
new file: layouts/SpiralLayout.qml
new file: layouts/StarggeredLayout.qml
new file: layouts/VortexLayout.qml
new file: layouts/qmldir
new file: modules/Hyprview.qml
new file: modules/SearchBox.qml
new file: modules/WindowThumbnail.qml
new file: modules/qmldir
new file: qs-hyprview-template.qml
new file: screenshots/bands.jpeg
new file: screenshots/hero.jpeg
new file: screenshots/masonry.jpeg
new file: screenshots/satellite.jpeg
new file: screenshots/smartgrid.jpeg
new file: screenshots/spiral.jpeg
new file: screenshots/staggered.jpeg
new file: screenshots/vortex.jpeg
new file: shell.qml
Diffstat (limited to 'config/quickshell/qs-hyprview/layouts/HeroLayout.qml')
| -rw-r--r-- | config/quickshell/qs-hyprview/layouts/HeroLayout.qml | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/config/quickshell/qs-hyprview/layouts/HeroLayout.qml b/config/quickshell/qs-hyprview/layouts/HeroLayout.qml new file mode 100644 index 00000000..e45ecf2c --- /dev/null +++ b/config/quickshell/qs-hyprview/layouts/HeroLayout.qml @@ -0,0 +1,144 @@ +pragma Singleton +import Quickshell +import Quickshell.Hyprland + +Singleton { + id: root + + function doLayout(windowList, outerWidth, outerHeight) { + if (windowList.length === 0) return [] + + // Gap: 0.8% of screen, clamped between 12px and 32px + var rawGap = Math.min(outerWidth * 0.08, outerHeight * 0.08) + var gap = Math.max(12, Math.min(32, rawGap)) + + // Move active window to the head of windowList + var activeAddr = Hyprland.activeToplevel?.lastIpcObject?.address + if (activeAddr) { + var activeIdx = windowList.findIndex(it => it.lastIpcObject.address === activeAddr) + if (activeIdx !== -1) { + windowList = [windowList[activeIdx], ...windowList.filter(it => it !== windowList[activeIdx])] + } + } + + // Safe area definition (90%) + var contentScale = 0.90 + var useW = outerWidth * contentScale + var useH = outerHeight * contentScale + + // Global offset - center Safe area + var offX = (outerWidth - useW) / 2 + var offY = (outerHeight - useH) / 2 + + var result = [] + + // Screen zones (Hero/Stack) + var heroRatio = 0.40 // 40% Hero + var heroAreaW = useW * heroRatio + var stackAreaW = useW - heroAreaW - gap // 60% Stack + + var heroItem = windowList[0] + + // Aspect Fit + var hScale = Math.min(heroAreaW / heroItem.width, useH / heroItem.height) + var hW = heroItem.width * hScale + var hH = heroItem.height * hScale + + result.push({ + win: heroItem.win, + x: offX + (heroAreaW - hW) / 2, + y: offY + (useH - hH) / 2, + width: hW, + height: hH, + isHero: true + }) + + var others = windowList.slice(1) + var N = others.length + + if (N > 0) { + var stackStartX = offX + heroAreaW + gap + + // Evaluate col number + var bestCols = 1 + var bestRows = N + + // Windows height on a single column + var oneColH = (useH - (gap * (N - 1))) / N + + // TOLERANCE THRESHOLD (0.15 = 15% of screen height) + // If the windows are at least 15% of the screen height, we stay on 1 column. + // With 4 windows we are at ~25% -> OK (1 Column) + // With 7 windows we are at ~14% -> NO (Go to grid calculation) + var useSingleCol = oneColH > (useH * 0.15) + + if (!useSingleCol) { + // If space is limited, we look for the optimal grid starting with 2 columns. + var bestScale = 0 + var TARGET_ASPECT = 16.0 / 9.0 + + for (var cols = 2; cols <= N; cols++) { + var rows = Math.ceil(N / cols) + var availW = stackAreaW - (gap * (cols - 1)) + var availH = useH - (gap * (rows - 1)) + + if (availW <= 0 || availH <= 0) continue + + var cellW = availW / cols + var cellH = availH / rows + + // Size score + var sW = cellW / TARGET_ASPECT + var sH = cellH / 1.0 + var currentScale = Math.min(sW, sH) + + if (currentScale > bestScale) { + bestScale = currentScale + bestCols = cols + bestRows = rows + } + } + } + + // Evaluation of the final dimensions of the selected grid + var finalAvailW = stackAreaW - (gap * (bestCols - 1)) + var finalAvailH = useH - (gap * (bestRows - 1)) + + var finalCellW = finalAvailW / bestCols + var finalCellH = finalAvailH / bestRows + + // Vertical centering of the total stack + var totalGridH = bestRows * finalCellH + (bestRows - 1) * gap + var stackStartY = offY + (useH - totalGridH) / 2 + + // Items positioning + for (var i = 0; i < N; ++i) { + var item = others[i] + + var row = Math.floor(i / bestCols) + var col = i % bestCols + + // Cell coords (Standard Grid Alignment) + // No “rowOffsetX”, cell 0 always starts on the left + var cellAbsX = stackStartX + col * (finalCellW + gap) + var cellAbsY = stackStartY + row * (finalCellH + gap) + + // Thumb aspect Fit + var sc = Math.min(finalCellW / item.width, finalCellH / item.height) + var w = item.width * sc + var h = item.height * sc + + result.push({ + win: item.win, + x: cellAbsX + (finalCellW - w) / 2, + y: cellAbsY + (finalCellH - h) / 2, + width: w, + height: h, + isHero: false + }) + } + } + + return result + } +} |
