From 4c3b7ca60ff0397a8b4793126d2c913b9cbed567 Mon Sep 17 00:00:00 2001 From: bbedward Date: Mon, 6 Oct 2025 20:50:36 -0400 Subject: [PATCH] Support prime-run --- Modals/Spotlight/SpotlightContextMenu.qml | 63 +++++++++++++++++++++++ Modules/AppDrawer/AppDrawerPopout.qml | 61 ++++++++++++++++++++++ Modules/Dock/DockContextMenu.qml | 46 +++++++++++++++-- Services/SessionService.qml | 22 +++++++- 4 files changed, 187 insertions(+), 5 deletions(-) diff --git a/Modals/Spotlight/SpotlightContextMenu.qml b/Modals/Spotlight/SpotlightContextMenu.qml index 85c9073e..b41cc717 100644 --- a/Modals/Spotlight/SpotlightContextMenu.qml +++ b/Modals/Spotlight/SpotlightContextMenu.qml @@ -270,5 +270,68 @@ Popup { } } } + + Rectangle { + visible: SessionService.hasPrimeRun + width: parent.width - Theme.spacingS * 2 + height: 5 + anchors.horizontalCenter: parent.horizontalCenter + color: "transparent" + + Rectangle { + anchors.centerIn: parent + width: parent.width + height: 1 + color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2) + } + } + + Rectangle { + visible: SessionService.hasPrimeRun + width: parent.width + height: 32 + radius: Theme.cornerRadius + color: primeRunMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent" + + Row { + anchors.left: parent.left + anchors.leftMargin: Theme.spacingS + anchors.verticalCenter: parent.verticalCenter + spacing: Theme.spacingS + + DankIcon { + name: "memory" + size: Theme.iconSize - 2 + color: Theme.surfaceText + opacity: 0.7 + anchors.verticalCenter: parent.verticalCenter + } + + StyledText { + text: qsTr("Launch on dGPU") + font.pixelSize: Theme.fontSizeSmall + color: Theme.surfaceText + font.weight: Font.Normal + anchors.verticalCenter: parent.verticalCenter + } + } + + MouseArea { + id: primeRunMouseArea + + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + onClicked: () => { + if (contextMenu.currentApp && contextMenu.currentApp.desktopEntry) { + SessionService.launchDesktopEntry(contextMenu.currentApp.desktopEntry, true) + if (appLauncher) { + appLauncher.appLaunched(contextMenu.currentApp) + } + } + contextMenu.hide() + } + } + } } } diff --git a/Modules/AppDrawer/AppDrawerPopout.qml b/Modules/AppDrawer/AppDrawerPopout.qml index e6b838e3..b35d5f91 100644 --- a/Modules/AppDrawer/AppDrawerPopout.qml +++ b/Modules/AppDrawer/AppDrawerPopout.qml @@ -913,6 +913,67 @@ DankPopout { } } } + + Rectangle { + visible: SessionService.hasPrimeRun + width: parent.width - Theme.spacingS * 2 + height: 5 + anchors.horizontalCenter: parent.horizontalCenter + color: "transparent" + + Rectangle { + anchors.centerIn: parent + width: parent.width + height: 1 + color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2) + } + } + + Rectangle { + visible: SessionService.hasPrimeRun + width: parent.width + height: 32 + radius: Theme.cornerRadius + color: primeRunMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent" + + Row { + anchors.left: parent.left + anchors.leftMargin: Theme.spacingS + anchors.verticalCenter: parent.verticalCenter + spacing: Theme.spacingS + + DankIcon { + name: "memory" + size: Theme.iconSize - 2 + color: Theme.surfaceText + opacity: 0.7 + anchors.verticalCenter: parent.verticalCenter + } + + StyledText { + text: qsTr("Launch on dGPU") + font.pixelSize: Theme.fontSizeSmall + color: Theme.surfaceText + font.weight: Font.Normal + anchors.verticalCenter: parent.verticalCenter + } + } + + MouseArea { + id: primeRunMouseArea + + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + onClicked: { + if (contextMenu.currentApp && contextMenu.currentApp.desktopEntry) { + SessionService.launchDesktopEntry(contextMenu.currentApp.desktopEntry, true) + appLauncher.appLaunched(contextMenu.currentApp) + } + contextMenu.hide() + } + } + } } } diff --git a/Modules/Dock/DockContextMenu.qml b/Modules/Dock/DockContextMenu.qml index c095bc05..e02549e5 100644 --- a/Modules/Dock/DockContextMenu.qml +++ b/Modules/Dock/DockContextMenu.qml @@ -404,7 +404,49 @@ PanelWindow { } Rectangle { - visible: root.appData && root.appData.type === "window" + visible: (root.appData && root.appData.type === "window") || (root.desktopEntry && SessionService.hasPrimeRun) + width: parent.width + height: 1 + color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2) + } + + Rectangle { + visible: root.desktopEntry && SessionService.hasPrimeRun + width: parent.width + height: 28 + radius: Theme.cornerRadius + color: primeRunArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent" + + StyledText { + anchors.left: parent.left + anchors.leftMargin: Theme.spacingS + anchors.right: parent.right + anchors.rightMargin: Theme.spacingS + anchors.verticalCenter: parent.verticalCenter + text: qsTr("Launch on dGPU") + font.pixelSize: Theme.fontSizeSmall + color: Theme.surfaceText + font.weight: Font.Normal + elide: Text.ElideRight + wrapMode: Text.NoWrap + } + + MouseArea { + id: primeRunArea + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + onClicked: { + if (root.desktopEntry) { + SessionService.launchDesktopEntry(root.desktopEntry, true) + } + root.close() + } + } + } + + Rectangle { + visible: root.appData && (root.appData.type === "window" || (root.appData.type === "grouped" && root.appData.windowCount > 0)) width: parent.width height: 1 color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2) @@ -444,7 +486,6 @@ PanelWindow { onClicked: { const sortedToplevels = CompositorService.sortedToplevels if (root.appData && root.appData.type === "window") { - // Find and close the specific window for (var i = 0; i < sortedToplevels.length; i++) { const toplevel = sortedToplevels[i] const checkId = toplevel.title + "|" + (toplevel.appId || "") + "|" + i @@ -454,7 +495,6 @@ PanelWindow { } } } else if (root.appData && root.appData.type === "grouped") { - // Close all windows for this app const allToplevels = ToplevelManager.toplevels.values for (let i = 0; i < allToplevels.length; i++) { const toplevel = allToplevels[i] diff --git a/Services/SessionService.qml b/Services/SessionService.qml index ae3ab4a5..256a3a45 100644 --- a/Services/SessionService.qml +++ b/Services/SessionService.qml @@ -18,6 +18,7 @@ Singleton { property bool inhibitorAvailable: true property bool idleInhibited: false property string inhibitReason: "Keep system awake" + property bool hasPrimeRun: false readonly property bool nativeInhibitorAvailable: { try { @@ -30,6 +31,7 @@ Singleton { Component.onCompleted: { detectElogindProcess.running = true detectHibernateProcess.running = true + detectPrimeRunProcess.running = true console.log("SessionService: Native inhibitor available:", nativeInhibitorAvailable) } @@ -65,6 +67,16 @@ Singleton { } } + Process { + id: detectPrimeRunProcess + running: false + command: ["which", "prime-run"] + + onExited: function (exitCode) { + hasPrimeRun = (exitCode === 0) + } + } + Process { id: uwsmLogout command: ["uwsm", "stop"] @@ -88,8 +100,11 @@ Singleton { } // * Apps - function launchDesktopEntry(desktopEntry) { + function launchDesktopEntry(desktopEntry, usePrimeRun) { let cmd = desktopEntry.command + if (usePrimeRun && hasPrimeRun) { + cmd = ["prime-run"].concat(cmd) + } if (SessionData.launchPrefix && SessionData.launchPrefix.length > 0) { const launchPrefix = SessionData.launchPrefix.trim().split(" ") cmd = launchPrefix.concat(cmd) @@ -101,8 +116,11 @@ Singleton { }); } - function launchDesktopAction(desktopEntry, action) { + function launchDesktopAction(desktopEntry, action, usePrimeRun) { let cmd = action.command + if (usePrimeRun && hasPrimeRun) { + cmd = ["prime-run"].concat(cmd) + } if (SessionData.launchPrefix && SessionData.launchPrefix.length > 0) { const launchPrefix = SessionData.launchPrefix.trim().split(" ") cmd = launchPrefix.concat(cmd)