Files
monoshell/Panes/Overview.qml
T
2026-09-15 20:02:17 -07:00

146 lines
4.9 KiB
QML

import QtQuick
import QtQuick.Effects
import Quickshell
import Quickshell.Hyprland
import Quickshell.Widgets
import Quickshell.Wayland
Grid {
id: overview
anchors {
top: parent.top
horizontalCenter: parent.horiontalCenter
}
spacing: 4
padding: 6
columns: 5
horizontalItemAlignment: Grid.AlignHCenter
verticalItemAlignment: Grid.AlignVCenter
onVisibleChanged: {
if (!visible) return;
Hyprland.refreshToplevels()
}
component WorkspaceView: ClippingRectangle {
id: workspaceView
color: "#282828"
height: Hyprland.focusedMonitor?.height * widthRatio
width: 192
radius: 8
topLeftRadius: modelData == 0 ? 12 : this.radius
topRightRadius: modelData == 4 ? 12 : this.radius
bottomLeftRadius: modelData == 5 ? 12 : this.radius
property var widthRatio: this.width / Hyprland.focusedMonitor?.width
property var toplevels: Hyprland.toplevels.values.filter(
tl => tl.workspace?.id == modelData + 1
)
border {
width: 2
color: {
if (Hyprland.focusedWorkspace?.id == modelData + 1 || hover.hovered) {
return "#ffffffff"
}
if (toplevels.length) {
return "#44ffffff"
}
return "#00ffffff"
}
Behavior on color { ColorAnimation {duration: 150} }
}
required property var modelData
Image {
anchors.fill: parent
source: Quickshell.shellPath('assets/wallpaper')
fillMode: Image.PreserveAspectCrop
}
Repeater {
model: Hyprland.toplevels.values
.filter(tl => tl.workspace?.id == modelData + 1)
.sort((a, b) => {
if (a.lastIpcObject.floating) return 1;
if (b.lastIpcObject.floating) return -1;
return 0
})
delegate: ClippingRectangle {
id: toplevelView
x: modelData.lastIpcObject.at?.[0] * workspaceView.widthRatio - 2
y: modelData.lastIpcObject.at?.[1] * workspaceView.widthRatio - 2
width: modelData.lastIpcObject.size?.[0] * workspaceView.widthRatio
height: modelData.lastIpcObject.size?.[1] * workspaceView.widthRatio
radius: modelData.lastIpcObject.floating ? 4 : 0
ScreencopyView {
anchors.fill: parent
captureSource: modelData.wayland
live: overview.visible
layer.enabled: true
layer.effect: MultiEffect {
blurEnabled: true
blurMax: 4
blur: 1
autoPaddingEnabled: false
}
}
Image {
id: appicon
anchors.centerIn: parent
width: 24 + 24 * Math.min(
(parent.width / workspaceView.width),
(parent.height / workspaceView.height)
)
height: width
sourceSize.width: width
sourceSize.height: height
source: {
const appId = modelData.wayland?.appId
const iconName = DesktopEntries.applications.values.find(
app => app.startupClass === appId || app.id === appId
)?.icon;
return Quickshell.iconPath(iconName)
}
layer.enabled: true
visible: false
}
MultiEffect {
anchors.fill: appicon
source: appicon
blurMax: 12
shadowEnabled: true
}
MultiEffect {
anchors.fill: appicon
source: appicon
blurMax: 12
shadowEnabled: true
}
Rectangle {
anchors.fill: parent
color: 'transparent'
border { width: 1; color: "#44ffffff" }
radius: toplevelView.radius + 1
}
}
}
TapHandler { onTapped: {
if (modelData < 0) return;
Hyprland.dispatch(`hl.dsp.focus({workspace = ${modelData + 1}})`)
root.close()
}}
HoverHandler { id: hover }
}
Repeater {
model: 9
WorkspaceView {}
}
WorkspaceView {
modelData: -100
bottomRightRadius: 12
TapHandler {
onTapped: {
Hyprland.dispatch('hl.dsp.workspace.toggle_special()')
root.close()
}
}
}
}