summaryrefslogtreecommitdiff
path: root/raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modules/WorkspaceOverlays/OverviewWidget.qml
diff options
context:
space:
mode:
authornippy <you@example.com>2026-04-18 13:49:56 +0200
committernippy <you@example.com>2026-04-18 13:49:56 +0200
commit5d94c0a7d44a2255b81815a52a7056a94a39842d (patch)
tree759bdea9645c6a62f9e1e4c001f7d81cccd120d2 /raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modules/WorkspaceOverlays/OverviewWidget.qml
parente79cdf210b267f21a186255ce1a4d50029439d54 (diff)
downloadRaveOS-PKGBUILD-5d94c0a7d44a2255b81815a52a7056a94a39842d.tar.gz
RaveOS-PKGBUILD-5d94c0a7d44a2255b81815a52a7056a94a39842d.zip
update Raveos themes
Diffstat (limited to 'raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modules/WorkspaceOverlays/OverviewWidget.qml')
-rw-r--r--raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modules/WorkspaceOverlays/OverviewWidget.qml443
1 files changed, 443 insertions, 0 deletions
diff --git a/raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modules/WorkspaceOverlays/OverviewWidget.qml b/raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modules/WorkspaceOverlays/OverviewWidget.qml
new file mode 100644
index 0000000..03d39fb
--- /dev/null
+++ b/raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modules/WorkspaceOverlays/OverviewWidget.qml
@@ -0,0 +1,443 @@
+import QtQuick
+import QtQuick.Layouts
+import Quickshell
+import Quickshell.Hyprland
+import qs.Common
+import qs.Services
+import qs.Widgets
+
+Item {
+ id: root
+ required property var panelWindow
+ required property bool overviewOpen
+ readonly property HyprlandMonitor monitor: Hyprland.monitorFor(panelWindow.screen)
+ readonly property real dpr: CompositorService.getScreenScale(panelWindow.screen)
+ readonly property int workspacesShown: SettingsData.overviewRows * SettingsData.overviewColumns
+
+ readonly property var allWorkspaces: Hyprland.workspaces?.values || []
+ readonly property var allWorkspaceIds: {
+ const workspaces = allWorkspaces;
+ if (!workspaces || workspaces.length === 0)
+ return [];
+ try {
+ const ids = workspaces.map(ws => ws?.id).filter(id => id !== null && id !== undefined);
+ return ids.sort((a, b) => a - b);
+ } catch (e) {
+ return [];
+ }
+ }
+
+ readonly property var thisMonitorWorkspaceIds: {
+ const workspaces = allWorkspaces;
+ const mon = monitor;
+ if (!workspaces || workspaces.length === 0 || !mon)
+ return [];
+ try {
+ const filtered = workspaces.filter(ws => ws?.monitor?.name === mon.name);
+ return filtered.map(ws => ws?.id).filter(id => id !== null && id !== undefined).sort((a, b) => a - b);
+ } catch (e) {
+ return [];
+ }
+ }
+
+ readonly property var displayedWorkspaceIds: {
+ if (!allWorkspaceIds || allWorkspaceIds.length === 0) {
+ const result = [];
+ for (let i = 1; i <= workspacesShown; i++) {
+ result.push(i);
+ }
+ return result;
+ }
+
+ try {
+ const maxExisting = Math.max(...allWorkspaceIds);
+ const totalNeeded = Math.max(workspacesShown, allWorkspaceIds.length);
+ const result = [];
+
+ for (let i = 1; i <= maxExisting; i++) {
+ result.push(i);
+ }
+
+ let nextId = maxExisting + 1;
+ while (result.length < totalNeeded) {
+ result.push(nextId);
+ nextId++;
+ }
+
+ return result;
+ } catch (e) {
+ const result = [];
+ for (let i = 1; i <= workspacesShown; i++) {
+ result.push(i);
+ }
+ return result;
+ }
+ }
+
+ readonly property int minWorkspaceId: displayedWorkspaceIds.length > 0 ? displayedWorkspaceIds[0] : 1
+ readonly property int maxWorkspaceId: displayedWorkspaceIds.length > 0 ? displayedWorkspaceIds[displayedWorkspaceIds.length - 1] : workspacesShown
+ readonly property int displayWorkspaceCount: displayedWorkspaceIds.length
+
+ readonly property int effectiveColumns: SettingsData.overviewColumns
+ readonly property int effectiveRows: Math.max(SettingsData.overviewRows, Math.ceil(displayWorkspaceCount / effectiveColumns))
+
+ function getWorkspaceMonitorName(workspaceId) {
+ if (!allWorkspaces || !workspaceId)
+ return "";
+ try {
+ const ws = allWorkspaces.find(w => w?.id === workspaceId);
+ return ws?.monitor?.name ?? "";
+ } catch (e) {
+ return "";
+ }
+ }
+
+ function workspaceHasWindows(workspaceId) {
+ if (!workspaceId)
+ return false;
+ try {
+ const workspace = allWorkspaces.find(ws => ws?.id === workspaceId);
+ if (!workspace)
+ return false;
+ const toplevels = workspace?.toplevels?.values || [];
+ return toplevels.length > 0;
+ } catch (e) {
+ return false;
+ }
+ }
+
+ property bool monitorIsFocused: monitor?.focused ?? false
+ property real scale: SettingsData.overviewScale
+ property color activeBorderColor: Theme.primary
+
+ readonly property real monitorPhysicalWidth: panelWindow.screen ? (panelWindow.screen.width / root.dpr) : (monitor?.width ?? 1920)
+ readonly property real monitorPhysicalHeight: panelWindow.screen ? (panelWindow.screen.height / root.dpr) : (monitor?.height ?? 1080)
+ property real workspaceImplicitWidth: monitorPhysicalWidth * root.scale
+ property real workspaceImplicitHeight: monitorPhysicalHeight * root.scale
+
+ property int workspaceZ: 0
+ property int windowZ: 1
+ property int monitorLabelZ: 2
+ property int windowDraggingZ: 99999
+ property real workspaceSpacing: 5
+
+ property int draggingFromWorkspace: -1
+ property int draggingTargetWorkspace: -1
+
+ implicitWidth: overviewBackground.implicitWidth + Theme.spacingL * 2
+ implicitHeight: overviewBackground.implicitHeight + Theme.spacingL * 2
+
+ Component.onCompleted: {
+ Hyprland.refreshToplevels();
+ Hyprland.refreshWorkspaces();
+ Hyprland.refreshMonitors();
+ }
+
+ onOverviewOpenChanged: {
+ if (overviewOpen) {
+ Hyprland.refreshToplevels();
+ Hyprland.refreshWorkspaces();
+ Hyprland.refreshMonitors();
+ }
+ }
+
+ Rectangle {
+ id: overviewBackground
+ property real padding: 10
+ anchors.fill: parent
+ anchors.margins: Theme.spacingL
+
+ implicitWidth: workspaceColumnLayout.implicitWidth + padding * 2
+ implicitHeight: workspaceColumnLayout.implicitHeight + padding * 2
+ radius: Theme.cornerRadius
+ color: Theme.surfaceContainer
+
+ ElevationShadow {
+ anchors.fill: parent
+ z: -1
+ level: Theme.elevationLevel2
+ fallbackOffset: 4
+ targetRadius: Theme.cornerRadius
+ targetColor: Theme.surfaceContainer
+ shadowOpacity: Theme.elevationLevel2 && Theme.elevationLevel2.alpha !== undefined ? Theme.elevationLevel2.alpha : 0.25
+ shadowEnabled: Theme.elevationEnabled
+ }
+
+ ColumnLayout {
+ id: workspaceColumnLayout
+
+ z: root.workspaceZ
+ anchors.centerIn: parent
+ spacing: workspaceSpacing
+
+ Repeater {
+ model: root.effectiveRows
+ delegate: RowLayout {
+ id: row
+ property int rowIndex: index
+ spacing: workspaceSpacing
+
+ Repeater {
+ model: root.effectiveColumns
+ Rectangle {
+ id: workspace
+ property int colIndex: index
+ property int workspaceIndex: rowIndex * root.effectiveColumns + colIndex
+ property int workspaceValue: (root.displayedWorkspaceIds && workspaceIndex < root.displayedWorkspaceIds.length) ? root.displayedWorkspaceIds[workspaceIndex] : -1
+ property bool workspaceExists: (root.allWorkspaceIds && workspaceValue > 0) ? root.allWorkspaceIds.includes(workspaceValue) : false
+ property var workspaceObj: (workspaceExists && Hyprland.workspaces?.values) ? Hyprland.workspaces.values.find(ws => ws?.id === workspaceValue) : null
+ property bool isActive: workspaceObj?.active ?? false
+ property bool isOnThisMonitor: (workspaceObj && root.monitor) ? (workspaceObj.monitor?.name === root.monitor.name) : true
+ property bool hasWindows: (workspaceValue > 0) ? root.workspaceHasWindows(workspaceValue) : false
+ property string workspaceMonitorName: (workspaceValue > 0) ? root.getWorkspaceMonitorName(workspaceValue) : ""
+ property color defaultWorkspaceColor: workspaceExists ? Theme.surfaceContainer : Theme.withAlpha(Theme.surfaceContainer, 0.3)
+ property color hoveredWorkspaceColor: Qt.lighter(defaultWorkspaceColor, 1.1)
+ property color hoveredBorderColor: Theme.surfaceVariant
+ property bool hoveredWhileDragging: false
+ property bool shouldShowActiveIndicator: isActive && isOnThisMonitor && hasWindows
+
+ visible: workspaceValue !== -1
+
+ implicitWidth: root.workspaceImplicitWidth
+ implicitHeight: root.workspaceImplicitHeight
+ color: hoveredWhileDragging ? hoveredWorkspaceColor : defaultWorkspaceColor
+ radius: Theme.cornerRadius
+ border.width: 2
+ border.color: hoveredWhileDragging ? hoveredBorderColor : (shouldShowActiveIndicator ? root.activeBorderColor : "transparent")
+
+ StyledText {
+ anchors.centerIn: parent
+ text: workspaceValue
+ font.pixelSize: Theme.fontSizeXLarge * 6
+ font.weight: Font.DemiBold
+ color: Theme.withAlpha(Theme.surfaceText, workspaceExists ? 0.2 : 0.1)
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ }
+
+ MouseArea {
+ id: workspaceArea
+ anchors.fill: parent
+ acceptedButtons: Qt.LeftButton
+ onClicked: {
+ if (root.draggingTargetWorkspace === -1) {
+ root.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 {
+ id: windowSpace
+ anchors.centerIn: parent
+ implicitWidth: workspaceColumnLayout.implicitWidth
+ implicitHeight: workspaceColumnLayout.implicitHeight
+
+ Repeater {
+ model: ScriptModel {
+ values: {
+ const workspaces = root.allWorkspaces;
+ const minId = root.minWorkspaceId;
+ const maxId = root.maxWorkspaceId;
+
+ if (!workspaces || workspaces.length === 0)
+ return [];
+
+ try {
+ const result = [];
+ for (const workspace of workspaces) {
+ const wsId = workspace?.id ?? -1;
+ if (wsId >= minId && wsId <= maxId) {
+ const toplevels = workspace?.toplevels?.values || [];
+ for (const toplevel of toplevels) {
+ result.push(toplevel);
+ }
+ }
+ }
+ return result;
+ } catch (e) {
+ console.error("OverviewWidget filter error:", e);
+ return [];
+ }
+ }
+ }
+ delegate: OverviewWindow {
+ id: window
+ required property var modelData
+
+ overviewOpen: root.overviewOpen
+ readonly property int windowWorkspaceId: modelData?.workspace?.id ?? -1
+
+ function getWorkspaceIndex() {
+ if (!root.displayedWorkspaceIds || root.displayedWorkspaceIds.length === 0)
+ return 0;
+ if (!windowWorkspaceId || windowWorkspaceId < 0)
+ return 0;
+ try {
+ for (let i = 0; i < root.displayedWorkspaceIds.length; i++) {
+ if (root.displayedWorkspaceIds[i] === windowWorkspaceId) {
+ return i;
+ }
+ }
+ return 0;
+ } catch (e) {
+ return 0;
+ }
+ }
+
+ readonly property int workspaceIndex: getWorkspaceIndex()
+ readonly property int workspaceColIndex: workspaceIndex % root.effectiveColumns
+ readonly property int workspaceRowIndex: Math.floor(workspaceIndex / root.effectiveColumns)
+
+ toplevel: modelData
+ scale: root.scale
+ monitorDpr: root.dpr
+ availableWorkspaceWidth: root.workspaceImplicitWidth
+ availableWorkspaceHeight: root.workspaceImplicitHeight
+ widgetMonitorId: root.monitor.id
+
+ xOffset: (root.workspaceImplicitWidth + workspaceSpacing) * workspaceColIndex
+ yOffset: (root.workspaceImplicitHeight + workspaceSpacing) * workspaceRowIndex
+
+ z: atInitPosition ? root.windowZ : root.windowDraggingZ
+ property bool atInitPosition: (initX == x && initY == y)
+
+ Drag.hotSpot.x: width / 2
+ Drag.hotSpot.y: height / 2
+
+ MouseArea {
+ id: dragArea
+ anchors.fill: parent
+ hoverEnabled: true
+ onEntered: window.hovered = true
+ onExited: window.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;
+ root.draggingTargetWorkspace = -1;
+
+ if (targetWorkspace !== -1 && targetWorkspace !== windowData?.workspace.id) {
+ Hyprland.dispatch(`movetoworkspacesilent ${targetWorkspace},address:${windowData?.address}`);
+ Qt.callLater(() => {
+ Hyprland.refreshToplevels();
+ Hyprland.refreshWorkspaces();
+ Qt.callLater(() => {
+ window.x = window.initX;
+ window.y = window.initY;
+ });
+ });
+ } else {
+ window.x = window.initX;
+ window.y = window.initY;
+ }
+ }
+
+ onClicked: event => {
+ if (!windowData || !windowData.address)
+ return;
+ if (event.button === Qt.LeftButton) {
+ root.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;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ Item {
+ id: monitorLabelSpace
+ anchors.centerIn: parent
+ implicitWidth: workspaceColumnLayout.implicitWidth
+ implicitHeight: workspaceColumnLayout.implicitHeight
+ z: root.monitorLabelZ
+
+ Repeater {
+ model: root.effectiveRows
+ delegate: Item {
+ id: labelRow
+ property int rowIndex: index
+ y: (root.workspaceImplicitHeight + workspaceSpacing) * rowIndex
+ width: parent.width
+ height: root.workspaceImplicitHeight
+
+ Repeater {
+ model: root.effectiveColumns
+ delegate: Item {
+ id: labelItem
+ property int colIndex: index
+ property int workspaceIndex: labelRow.rowIndex * root.effectiveColumns + colIndex
+ property int workspaceValue: (root.displayedWorkspaceIds && workspaceIndex < root.displayedWorkspaceIds.length) ? root.displayedWorkspaceIds[workspaceIndex] : -1
+ property bool workspaceExists: (root.allWorkspaceIds && workspaceValue > 0) ? root.allWorkspaceIds.includes(workspaceValue) : false
+ property string workspaceMonitorName: (workspaceValue > 0) ? root.getWorkspaceMonitorName(workspaceValue) : ""
+
+ x: (root.workspaceImplicitWidth + workspaceSpacing) * colIndex
+ width: root.workspaceImplicitWidth
+ height: root.workspaceImplicitHeight
+
+ Rectangle {
+ anchors.right: parent.right
+ anchors.top: parent.top
+ anchors.margins: Theme.spacingS
+ width: monitorNameText.contentWidth + Theme.spacingS * 2
+ height: monitorNameText.contentHeight + Theme.spacingXS * 2
+ radius: Theme.cornerRadius
+ color: Theme.surface
+ visible: labelItem.workspaceExists && labelItem.workspaceMonitorName !== ""
+
+ StyledText {
+ id: monitorNameText
+ anchors.centerIn: parent
+ text: labelItem.workspaceMonitorName
+ font.pixelSize: Theme.fontSizeSmall
+ font.weight: Font.Medium
+ color: Theme.surfaceText
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}