aboutsummaryrefslogtreecommitdiffstats
path: root/config/quickshell/overview/modules
diff options
context:
space:
mode:
authorDon Williams <don.e.williams@gmail.com>2025-11-30 20:04:02 -0500
committerDon Williams <don.e.williams@gmail.com>2025-11-30 20:04:02 -0500
commitca0c23cce006ea3f7d793c5fa8eee6acff196470 (patch)
tree092a7446c0f494c958b11b1af09474d99718a74e /config/quickshell/overview/modules
parent510eafbe0560cff6e459b64fcb778d645cd43ab3 (diff)
Integrate Quickshell-Overview with Qt6 fixes and automation scripts
## Overview This commit integrates the corrected Quickshell-Overview feature across all installation and update workflows. The overview provides an AGS alternative with live window previews toggled via Super+TAB keybind. ## Changes ### 1. Quickshell Overview QML Files - Added config/quickshell/overview/ subdirectory with Qt6-compatible QML - Includes 20+ files covering: * OverviewWindow.qml with proper clipping (no OpacityMask, uses QtQuick.Effects) * OverviewWidget.qml for window handling * Overview.qml main component with Hyprland integration * Common utilities and styling * Services for Hyprland data and global state management ### 2. copy.sh Updates - Removes default shell.qml that blocks quickshell named config detection - Auto-copies config/quickshell/overview to ~/.config/quickshell/overview/ - Updates old 'qs' startup commands to 'qs -c overview' - Handles both fresh installs and config overwrite scenarios ### 3. upgrade.sh Updates - Added config/quickshell/ to upgrade directory list - Excludes shell.qml to preserve overview config detection capability - Enables seamless upgrades without losing quickshell settings ### 4. IPC Command Fixes - Corrected OverviewToggle.sh to use proper 'qs ipc -c overview call overview toggle' - Fixed startup commands from old 'qs' to 'qs -c overview' - Hyprland-Dots now uses corrected toggle script ## Qt6 Compatibility - Replaced Qt5Compat.GraphicalEffects with QtQuick.Effects - Removed OpacityMask in favor of Qt6-compatible clipping technique - All QML properly imports Qt6 modules ## Release Script - release.sh automatically uses copy.sh, inheriting all quickshell updates ## Testing - Verified on target systems (Fedora 43 VM, jak-nixos) - qs -c overview successfully launches overview config when shell.qml is removed - IPC toggle commands work correctly within Wayland sessions ## Files Modified - config/quickshell/overview/* (20 new files) - copy.sh (enhanced QS handling) - upgrade.sh (added quickshell to upgrade paths)
Diffstat (limited to 'config/quickshell/overview/modules')
-rw-r--r--config/quickshell/overview/modules/overview/Overview.qml147
-rw-r--r--config/quickshell/overview/modules/overview/OverviewWidget.qml303
-rw-r--r--config/quickshell/overview/modules/overview/OverviewWindow.qml112
-rw-r--r--config/quickshell/overview/modules/overview/qmldir3
4 files changed, 565 insertions, 0 deletions
diff --git a/config/quickshell/overview/modules/overview/Overview.qml b/config/quickshell/overview/modules/overview/Overview.qml
new file mode 100644
index 00000000..b3a299cb
--- /dev/null
+++ b/config/quickshell/overview/modules/overview/Overview.qml
@@ -0,0 +1,147 @@
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+import Quickshell
+import Quickshell.Io
+import Quickshell.Wayland
+import Quickshell.Hyprland
+import "../../common"
+import "../../services"
+import "."
+
+Scope {
+ id: overviewScope
+ Variants {
+ id: overviewVariants
+ model: Quickshell.screens
+ PanelWindow {
+ id: root
+ required property var modelData
+ readonly property HyprlandMonitor monitor: Hyprland.monitorFor(root.screen)
+ property bool monitorIsFocused: (Hyprland.focusedMonitor?.id == monitor?.id)
+ screen: modelData
+ visible: GlobalStates.overviewOpen
+
+ WlrLayershell.namespace: "quickshell:overview"
+ WlrLayershell.layer: WlrLayer.Overlay
+ WlrLayershell.keyboardFocus: WlrKeyboardFocus.Exclusive
+ color: "transparent"
+
+ mask: Region {
+ item: GlobalStates.overviewOpen ? keyHandler : null
+ }
+
+ anchors {
+ top: true
+ bottom: true
+ left: !(Config?.options.overview.enable ?? true)
+ right: !(Config?.options.overview.enable ?? true)
+ }
+
+ HyprlandFocusGrab {
+ id: grab
+ windows: [root]
+ property bool canBeActive: root.monitorIsFocused
+ active: false
+ onCleared: () => {
+ if (!active)
+ GlobalStates.overviewOpen = false;
+ }
+ }
+
+ Connections {
+ target: GlobalStates
+ function onOverviewOpenChanged() {
+ if (GlobalStates.overviewOpen) {
+ delayedGrabTimer.start();
+ }
+ }
+ }
+
+ Timer {
+ id: delayedGrabTimer
+ interval: Config.options.hacks.arbitraryRaceConditionDelay
+ repeat: false
+ onTriggered: {
+ if (!grab.canBeActive)
+ return;
+ grab.active = GlobalStates.overviewOpen;
+ }
+ }
+
+ implicitWidth: columnLayout.implicitWidth
+ implicitHeight: columnLayout.implicitHeight
+
+ Item {
+ id: keyHandler
+ anchors.fill: parent
+ visible: GlobalStates.overviewOpen
+ focus: GlobalStates.overviewOpen
+
+ Keys.onPressed: event => {
+ if (event.key === Qt.Key_Escape || event.key === Qt.Key_Return) {
+ GlobalStates.overviewOpen = false;
+ event.accepted = true;
+ } else if (event.key === Qt.Key_Left || event.key === Qt.Key_Right || event.key === Qt.Key_Up || event.key === Qt.Key_Down) {
+ const workspacesPerGroup = Config.options.overview.rows * Config.options.overview.columns;
+ const currentId = Hyprland.focusedMonitor?.activeWorkspace?.id ?? 1;
+ const currentGroup = Math.floor((currentId - 1) / workspacesPerGroup);
+ const minWorkspaceId = currentGroup * workspacesPerGroup + 1;
+ const maxWorkspaceId = minWorkspaceId + workspacesPerGroup - 1;
+
+ let targetId;
+ if (event.key === Qt.Key_Left) {
+ targetId = currentId - 1;
+ if (targetId < minWorkspaceId) targetId = maxWorkspaceId;
+ } else if (event.key === Qt.Key_Right) {
+ targetId = currentId + 1;
+ if (targetId > maxWorkspaceId) targetId = minWorkspaceId;
+ } else if (event.key === Qt.Key_Up) {
+ targetId = currentId - Config.options.overview.columns;
+ if (targetId < minWorkspaceId) targetId += workspacesPerGroup;
+ } else {
+ targetId = currentId + Config.options.overview.columns;
+ if (targetId > maxWorkspaceId) targetId -= workspacesPerGroup;
+ }
+
+ Hyprland.dispatch("workspace " + targetId);
+ event.accepted = true;
+ }
+ }
+ }
+
+ ColumnLayout {
+ id: columnLayout
+ visible: GlobalStates.overviewOpen
+ anchors {
+ horizontalCenter: parent.horizontalCenter
+ top: parent.top
+ topMargin: 100
+ }
+
+ Loader {
+ id: overviewLoader
+ active: GlobalStates.overviewOpen && (Config?.options.overview.enable ?? true)
+ sourceComponent: OverviewWidget {
+ panelWindow: root
+ visible: true
+ }
+ }
+ }
+ }
+ }
+
+ IpcHandler {
+ target: "overview"
+
+ function toggle() {
+ GlobalStates.overviewOpen = !GlobalStates.overviewOpen;
+ }
+ function close() {
+ GlobalStates.overviewOpen = false;
+ }
+ function open() {
+ GlobalStates.overviewOpen = true;
+ }
+ }
+}
diff --git a/config/quickshell/overview/modules/overview/OverviewWidget.qml b/config/quickshell/overview/modules/overview/OverviewWidget.qml
new file mode 100644
index 00000000..7defa64d
--- /dev/null
+++ b/config/quickshell/overview/modules/overview/OverviewWidget.qml
@@ -0,0 +1,303 @@
+import QtQuick
+import QtQuick.Layouts
+import Quickshell
+import Quickshell.Wayland
+import Quickshell.Hyprland
+import "../../common"
+import "../../common/functions"
+import "../../common/widgets"
+import "../../services"
+import "."
+
+Item {
+ id: root
+ required property var panelWindow
+ readonly property HyprlandMonitor monitor: Hyprland.monitorFor(panelWindow.screen)
+ readonly property var toplevels: ToplevelManager.toplevels
+ readonly property int workspacesShown: Config.options.overview.rows * Config.options.overview.columns
+ readonly property int workspaceGroup: Math.floor((monitor.activeWorkspace?.id - 1) / workspacesShown)
+ property bool monitorIsFocused: (Hyprland.focusedMonitor?.name == monitor.name)
+ property var windows: HyprlandData.windowList
+ property var windowByAddress: HyprlandData.windowByAddress
+ property var windowAddresses: HyprlandData.addresses
+ property var monitorData: HyprlandData.monitors.find(m => m.id === root.monitor?.id)
+ property real scale: Config.options.overview.scale
+ property color activeBorderColor: Appearance.colors.colSecondary
+
+ property real workspaceImplicitWidth: (monitorData?.transform % 2 === 1) ?
+ ((monitor.height / monitor.scale - (monitorData?.reserved?.[0] ?? 0) - (monitorData?.reserved?.[2] ?? 0)) * root.scale) :
+ ((monitor.width / monitor.scale - (monitorData?.reserved?.[0] ?? 0) - (monitorData?.reserved?.[2] ?? 0)) * root.scale)
+ property real workspaceImplicitHeight: (monitorData?.transform % 2 === 1) ?
+ ((monitor.width / monitor.scale - (monitorData?.reserved?.[1] ?? 0) - (monitorData?.reserved?.[3] ?? 0)) * root.scale) :
+ ((monitor.height / monitor.scale - (monitorData?.reserved?.[1] ?? 0) - (monitorData?.reserved?.[3] ?? 0)) * root.scale)
+
+ property real workspaceNumberMargin: 80
+ property real workspaceNumberSize: 250 * monitor.scale
+ property int workspaceZ: 0
+ property int windowZ: 1
+ property int windowDraggingZ: 99999
+ property real workspaceSpacing: 5
+
+ property int draggingFromWorkspace: -1
+ property int draggingTargetWorkspace: -1
+
+ implicitWidth: overviewBackground.implicitWidth + Appearance.sizes.elevationMargin * 2
+ implicitHeight: overviewBackground.implicitHeight + Appearance.sizes.elevationMargin * 2
+
+ property Component windowComponent: OverviewWindow {}
+ property list<OverviewWindow> windowWidgets: []
+
+ StyledRectangularShadow {
+ target: overviewBackground
+ }
+ Rectangle { // Background
+ id: overviewBackground
+ property real padding: 10
+ anchors.fill: parent
+ anchors.margins: Appearance.sizes.elevationMargin
+
+ implicitWidth: workspaceColumnLayout.implicitWidth + padding * 2
+ implicitHeight: workspaceColumnLayout.implicitHeight + padding * 2
+ radius: Appearance.rounding.screenRounding * root.scale + padding
+ color: Appearance.colors.colLayer0
+ border.width: 1
+ border.color: Appearance.colors.colLayer0Border
+
+ ColumnLayout { // Workspaces
+ id: workspaceColumnLayout
+
+ z: root.workspaceZ
+ anchors.centerIn: parent
+ spacing: workspaceSpacing
+ Repeater {
+ model: Config.options.overview.rows
+ delegate: RowLayout {
+ id: row
+ property int rowIndex: index
+ spacing: workspaceSpacing
+
+ Repeater { // Workspace repeater
+ model: Config.options.overview.columns
+ Rectangle { // Workspace
+ id: workspace
+ property int colIndex: index
+ property int workspaceValue: root.workspaceGroup * workspacesShown + rowIndex * Config.options.overview.columns + colIndex + 1
+ property color defaultWorkspaceColor: Appearance.colors.colLayer1
+ property color hoveredWorkspaceColor: ColorUtils.mix(defaultWorkspaceColor, Appearance.colors.colLayer1Hover, 0.1)
+ property color hoveredBorderColor: Appearance.colors.colLayer2Hover
+ property bool hoveredWhileDragging: false
+
+ implicitWidth: root.workspaceImplicitWidth
+ implicitHeight: root.workspaceImplicitHeight
+ color: hoveredWhileDragging ? hoveredWorkspaceColor : defaultWorkspaceColor
+ radius: Appearance.rounding.screenRounding * root.scale
+ border.width: 2
+ border.color: hoveredWhileDragging ? hoveredBorderColor : "transparent"
+
+ StyledText {
+ anchors.centerIn: parent
+ text: workspaceValue
+ font {
+ pixelSize: root.workspaceNumberSize * root.scale
+ weight: Font.DemiBold
+ family: Appearance.font.family.expressive
+ }
+ color: ColorUtils.transparentize(Appearance.colors.colOnLayer1, 0.8)
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ }
+
+ MouseArea {
+ id: workspaceArea
+ anchors.fill: parent
+ acceptedButtons: Qt.LeftButton
+ onClicked: {
+ if (root.draggingTargetWorkspace === -1) {
+ GlobalStates.overviewOpen = false
+ Hyprland.dispatch(`workspace ${workspaceValue}`)
+ }
+ }
+ }
+
+ DropArea {
+ anchors.fill: parent
+ onEntered: {
+ root.draggingTargetWorkspace = workspaceValue
+ if (root.draggingFromWorkspace == root.draggingTargetWorkspace) return;
+ hoveredWhileDragging = true
+ }
+ onExited: {
+ hoveredWhileDragging = false
+ if (root.draggingTargetWorkspace == workspaceValue) root.draggingTargetWorkspace = -1
+ }
+ }
+
+ }
+ }
+ }
+ }
+ }
+
+ Item { // Windows & focused workspace indicator
+ id: windowSpace
+ anchors.centerIn: parent
+ implicitWidth: workspaceColumnLayout.implicitWidth
+ implicitHeight: workspaceColumnLayout.implicitHeight
+
+ Repeater { // Window repeater
+ model: ScriptModel {
+ values: {
+ return ToplevelManager.toplevels.values.filter((toplevel) => {
+ const address = `0x${toplevel.HyprlandToplevel.address}`
+ var win = windowByAddress[address]
+ const inWorkspaceGroup = (root.workspaceGroup * root.workspacesShown < win?.workspace?.id && win?.workspace?.id <= (root.workspaceGroup + 1) * root.workspacesShown)
+ return inWorkspaceGroup;
+ }).sort((a, b) => {
+ // Proper stacking order based on Hyprland's window properties
+ const addrA = `0x${a.HyprlandToplevel.address}`
+ const addrB = `0x${b.HyprlandToplevel.address}`
+ const winA = windowByAddress[addrA]
+ const winB = windowByAddress[addrB]
+
+ // 1. Pinned windows are always on top
+ if (winA?.pinned !== winB?.pinned) {
+ return winA?.pinned ? 1 : -1
+ }
+
+ // 2. Floating windows above tiled windows
+ if (winA?.floating !== winB?.floating) {
+ return winA?.floating ? 1 : -1
+ }
+
+ // 3. Within same category, sort by focus history
+ // Lower focusHistoryID = more recently focused = higher in stack
+ return (winB?.focusHistoryID ?? 0) - (winA?.focusHistoryID ?? 0)
+ })
+ }
+ }
+ delegate: OverviewWindow {
+ id: window
+ required property var modelData
+ required property int index
+ property int monitorId: windowData?.monitor
+ property var monitor: HyprlandData.monitors.find(m => m.id === monitorId)
+ property var address: `0x${modelData.HyprlandToplevel.address}`
+ windowData: windowByAddress[address]
+ toplevel: modelData
+ monitorData: monitor
+
+ // Calculate scale relative to window's source monitor
+ property real sourceMonitorWidth: (monitor?.transform % 2 === 1) ?
+ (monitor?.height ?? 1920) / (monitor?.scale ?? 1) - (monitor?.reserved?.[0] ?? 0) - (monitor?.reserved?.[2] ?? 0) :
+ (monitor?.width ?? 1920) / (monitor?.scale ?? 1) - (monitor?.reserved?.[0] ?? 0) - (monitor?.reserved?.[2] ?? 0)
+ property real sourceMonitorHeight: (monitor?.transform % 2 === 1) ?
+ (monitor?.width ?? 1080) / (monitor?.scale ?? 1) - (monitor?.reserved?.[1] ?? 0) - (monitor?.reserved?.[3] ?? 0) :
+ (monitor?.height ?? 1080) / (monitor?.scale ?? 1) - (monitor?.reserved?.[1] ?? 0) - (monitor?.reserved?.[3] ?? 0)
+
+ // Scale windows to fit the workspace size, accounting for different monitor sizes
+ scale: Math.min(
+ root.workspaceImplicitWidth / sourceMonitorWidth,
+ root.workspaceImplicitHeight / sourceMonitorHeight
+ )
+
+ availableWorkspaceWidth: root.workspaceImplicitWidth
+ availableWorkspaceHeight: root.workspaceImplicitHeight
+ widgetMonitorId: root.monitor.id
+
+ property bool atInitPosition: (initX == x && initY == y)
+
+ property int workspaceColIndex: (windowData?.workspace.id - 1) % Config.options.overview.columns
+ property int workspaceRowIndex: Math.floor((windowData?.workspace.id - 1) % root.workspacesShown / Config.options.overview.columns)
+ xOffset: (root.workspaceImplicitWidth + workspaceSpacing) * workspaceColIndex
+ yOffset: (root.workspaceImplicitHeight + workspaceSpacing) * workspaceRowIndex
+
+ Timer {
+ id: updateWindowPosition
+ interval: Config.options.hacks.arbitraryRaceConditionDelay
+ repeat: false
+ running: false
+ onTriggered: {
+ window.x = Math.round(Math.max((windowData?.at[0] - (monitor?.x ?? 0) - (monitorData?.reserved?.[0] ?? 0)) * root.scale, 0) + xOffset)
+ window.y = Math.round(Math.max((windowData?.at[1] - (monitor?.y ?? 0) - (monitorData?.reserved?.[1] ?? 0)) * root.scale, 0) + yOffset)
+ }
+ }
+
+ z: atInitPosition ? (root.windowZ + index) : root.windowDraggingZ
+ Drag.hotSpot.x: targetWindowWidth / 2
+ Drag.hotSpot.y: targetWindowHeight / 2
+ MouseArea {
+ id: dragArea
+ anchors.fill: parent
+ hoverEnabled: true
+ onEntered: hovered = true
+ onExited: hovered = false
+ acceptedButtons: Qt.LeftButton | Qt.MiddleButton
+ drag.target: parent
+ onPressed: (mouse) => {
+ root.draggingFromWorkspace = windowData?.workspace.id
+ window.pressed = true
+ window.Drag.active = true
+ window.Drag.source = window
+ window.Drag.hotSpot.x = mouse.x
+ window.Drag.hotSpot.y = mouse.y
+ }
+ onReleased: {
+ const targetWorkspace = root.draggingTargetWorkspace
+ window.pressed = false
+ window.Drag.active = false
+ root.draggingFromWorkspace = -1
+ if (targetWorkspace !== -1 && targetWorkspace !== windowData?.workspace.id) {
+ Hyprland.dispatch(`movetoworkspacesilent ${targetWorkspace}, address:${window.windowData?.address}`)
+ updateWindowPosition.restart()
+ }
+ else {
+ window.x = window.initX
+ window.y = window.initY
+ }
+ }
+ onClicked: (event) => {
+ if (!windowData) return;
+
+ if (event.button === Qt.LeftButton) {
+ GlobalStates.overviewOpen = false
+ Hyprland.dispatch(`focuswindow address:${windowData.address}`)
+ event.accepted = true
+ } else if (event.button === Qt.MiddleButton) {
+ Hyprland.dispatch(`closewindow address:${windowData.address}`)
+ event.accepted = true
+ }
+ }
+
+ StyledToolTip {
+ extraVisibleCondition: false
+ alternativeVisibleCondition: dragArea.containsMouse && !window.Drag.active
+ text: `${windowData?.title ?? "Unknown"}\n[${windowData?.class ?? "unknown"}] ${windowData?.xwayland ? "[XWayland] " : ""}`
+ }
+ }
+ }
+ }
+
+ Rectangle { // Focused workspace indicator
+ id: focusedWorkspaceIndicator
+ property int activeWorkspaceInGroup: monitor.activeWorkspace?.id - (root.workspaceGroup * root.workspacesShown)
+ property int activeWorkspaceRowIndex: Math.floor((activeWorkspaceInGroup - 1) / Config.options.overview.columns)
+ property int activeWorkspaceColIndex: (activeWorkspaceInGroup - 1) % Config.options.overview.columns
+ x: (root.workspaceImplicitWidth + workspaceSpacing) * activeWorkspaceColIndex
+ y: (root.workspaceImplicitHeight + workspaceSpacing) * activeWorkspaceRowIndex
+ z: root.windowZ
+ width: root.workspaceImplicitWidth
+ height: root.workspaceImplicitHeight
+ color: "transparent"
+ radius: Appearance.rounding.screenRounding * root.scale
+ border.width: 2
+ border.color: root.activeBorderColor
+ Behavior on x {
+ animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this)
+ }
+ Behavior on y {
+ animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this)
+ }
+ }
+ }
+ }
+}
diff --git a/config/quickshell/overview/modules/overview/OverviewWindow.qml b/config/quickshell/overview/modules/overview/OverviewWindow.qml
new file mode 100644
index 00000000..fac3e22e
--- /dev/null
+++ b/config/quickshell/overview/modules/overview/OverviewWindow.qml
@@ -0,0 +1,112 @@
+import QtQuick.Effects
+import QtQuick
+import QtQuick.Layouts
+import Quickshell
+import Quickshell.Wayland
+import "../../common"
+import "../../common/functions"
+import "../../services"
+
+Item { // Window
+ id: root
+ property var toplevel
+ property var windowData
+ property var monitorData
+ property var scale
+ property var availableWorkspaceWidth
+ property var availableWorkspaceHeight
+ property bool restrictToWorkspace: true
+ property real initX: Math.max(((windowData?.at[0] ?? 0) - (monitorData?.x ?? 0) - (monitorData?.reserved?.[0] ?? 0)) * root.scale, 0) + xOffset
+ property real initY: Math.max(((windowData?.at[1] ?? 0) - (monitorData?.y ?? 0) - (monitorData?.reserved?.[1] ?? 0)) * root.scale, 0) + yOffset
+ property real xOffset: 0
+ property real yOffset: 0
+ property int widgetMonitorId: 0
+
+ property var targetWindowWidth: (windowData?.size[0] ?? 100) * scale
+ property var targetWindowHeight: (windowData?.size[1] ?? 100) * scale
+ property bool hovered: false
+ property bool pressed: false
+
+ property var iconToWindowRatio: 0.25
+ property var xwaylandIndicatorToIconRatio: 0.35
+ property var iconToWindowRatioCompact: 0.45
+ property var entry: DesktopEntries.heuristicLookup(windowData?.class)
+ property var iconPath: Quickshell.iconPath(entry?.icon ?? windowData?.class ?? "application-x-executable", "image-missing")
+ property bool compactMode: Appearance.font.pixelSize.smaller * 4 > targetWindowHeight || Appearance.font.pixelSize.smaller * 4 > targetWindowWidth
+
+ property bool indicateXWayland: windowData?.xwayland ?? false
+
+ x: initX
+ y: initY
+ width: Math.min((windowData?.size[0] ?? 100) * root.scale, availableWorkspaceWidth)
+ height: Math.min((windowData?.size[1] ?? 100) * root.scale, availableWorkspaceHeight)
+ opacity: (windowData?.monitor ?? -1) == widgetMonitorId ? 1 : 0.4
+
+ layer.enabled: true
+ layer.smooth: true
+ layer.mipmap: true
+
+ Behavior on x {
+ animation: Appearance.animation.elementMoveEnter.numberAnimation.createObject(this)
+ }
+ Behavior on y {
+ animation: Appearance.animation.elementMoveEnter.numberAnimation.createObject(this)
+ }
+ Behavior on width {
+ animation: Appearance.animation.elementMoveEnter.numberAnimation.createObject(this)
+ }
+ Behavior on height {
+ animation: Appearance.animation.elementMoveEnter.numberAnimation.createObject(this)
+ }
+
+ Rectangle {
+ id: clipContainer
+ anchors.fill: parent
+ radius: Appearance.rounding.windowRounding * root.scale
+ clip: true
+ color: "transparent"
+
+ ScreencopyView {
+ id: windowPreview
+ anchors.fill: parent
+ captureSource: GlobalStates.overviewOpen ? root.toplevel : null
+ live: true
+
+ Rectangle {
+ anchors.fill: parent
+ radius: Appearance.rounding.windowRounding * root.scale
+ color: pressed ? ColorUtils.transparentize(Appearance.colors.colLayer2Active, 0.5) :
+ hovered ? ColorUtils.transparentize(Appearance.colors.colLayer2Hover, 0.7) :
+ ColorUtils.transparentize(Appearance.colors.colLayer2)
+ border.color : ColorUtils.transparentize(Appearance.m3colors.m3outline, 0.7)
+ border.width : 1
+ }
+
+ ColumnLayout {
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.left: parent.left
+ anchors.right: parent.right
+ spacing: Appearance.font.pixelSize.smaller * 0.5
+
+ Image {
+ id: windowIcon
+ property var iconSize: {
+ return Math.min(targetWindowWidth, targetWindowHeight) * (root.compactMode ? root.iconToWindowRatioCompact : root.iconToWindowRatio) / (root.monitorData?.scale ?? 1);
+ }
+ Layout.alignment: Qt.AlignHCenter
+ source: root.iconPath
+ width: iconSize
+ height: iconSize
+ sourceSize: Qt.size(iconSize, iconSize)
+
+ Behavior on width {
+ animation: Appearance.animation.elementMoveEnter.numberAnimation.createObject(this)
+ }
+ Behavior on height {
+ animation: Appearance.animation.elementMoveEnter.numberAnimation.createObject(this)
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/config/quickshell/overview/modules/overview/qmldir b/config/quickshell/overview/modules/overview/qmldir
new file mode 100644
index 00000000..9b15b45b
--- /dev/null
+++ b/config/quickshell/overview/modules/overview/qmldir
@@ -0,0 +1,3 @@
+Overview 1.0 Overview.qml
+OverviewWidget 1.0 OverviewWidget.qml
+OverviewWindow 1.0 OverviewWindow.qml
send patches to the email below
yukais@pinapelz.com
include the subject [PATCH repo_name]
pinapelz.com
homepage