1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-01-24 13:32:50 -05:00

Add Desktop Actions to launcher + dock

This commit is contained in:
bbedward
2025-10-06 09:35:50 -04:00
parent 2b3b9d037c
commit 3524d365be
5 changed files with 234 additions and 7 deletions

View File

@@ -1,4 +1,6 @@
import QtQuick
import Quickshell
import Quickshell.Widgets
import qs.Common
import qs.Services
import qs.Widgets
@@ -13,7 +15,7 @@ Rectangle {
function show(x, y, app) {
currentApp = app
const menuWidth = 180
const menuWidth = Math.max(180, Math.min(300, menuColumn.implicitWidth + Theme.spacingS * 2))
const menuHeight = menuColumn.implicitHeight + Theme.spacingS * 2
let finalX = x + 8
let finalY = y + 8
@@ -29,6 +31,7 @@ Rectangle {
}
contextMenu.x = finalX
contextMenu.y = finalY
contextMenu.width = menuWidth
contextMenu.visible = true
contextMenu.menuVisible = true
}
@@ -144,6 +147,82 @@ Rectangle {
}
}
Repeater {
model: contextMenu.currentApp && contextMenu.currentApp.desktopEntry && contextMenu.currentApp.desktopEntry.actions ? contextMenu.currentApp.desktopEntry.actions : []
Rectangle {
width: parent.width
height: 32
radius: Theme.cornerRadius
color: actionMouseArea.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.right: parent.right
anchors.rightMargin: Theme.spacingS
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingS
Item {
anchors.verticalCenter: parent.verticalCenter
width: Theme.iconSize - 2
height: Theme.iconSize - 2
visible: modelData.icon && modelData.icon !== ""
IconImage {
anchors.fill: parent
source: modelData.icon ? Quickshell.iconPath(modelData.icon, true) : ""
smooth: true
asynchronous: true
visible: status === Image.Ready
}
}
StyledText {
text: modelData.name || ""
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
font.weight: Font.Normal
anchors.verticalCenter: parent.verticalCenter
elide: Text.ElideRight
width: parent.width - (modelData.icon && modelData.icon !== "" ? (Theme.iconSize - 2 + Theme.spacingS) : 0)
}
}
MouseArea {
id: actionMouseArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
if (modelData && contextMenu.currentApp && contextMenu.currentApp.desktopEntry) {
SessionService.launchDesktopAction(contextMenu.currentApp.desktopEntry, modelData)
if (appLauncher) {
appLauncher.appLaunched(contextMenu.currentApp)
}
}
contextMenu.close()
}
}
}
}
Rectangle {
visible: contextMenu.currentApp && contextMenu.currentApp.desktopEntry && contextMenu.currentApp.desktopEntry.actions && contextMenu.currentApp.desktopEntry.actions.length > 0
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 {
width: parent.width
height: 32

View File

@@ -797,6 +797,76 @@ DankPopout {
}
}
Repeater {
model: contextMenu.currentApp && contextMenu.currentApp.desktopEntry && contextMenu.currentApp.desktopEntry.actions ? contextMenu.currentApp.desktopEntry.actions : []
Rectangle {
width: parent.width
height: 32
radius: Theme.cornerRadius
color: actionMouseArea.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
Item {
anchors.verticalCenter: parent.verticalCenter
width: Theme.iconSize - 2
height: Theme.iconSize - 2
visible: modelData.icon && modelData.icon !== ""
IconImage {
anchors.fill: parent
source: modelData.icon ? Quickshell.iconPath(modelData.icon, true) : ""
smooth: true
asynchronous: true
visible: status === Image.Ready
}
}
StyledText {
text: modelData.name || ""
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
font.weight: Font.Normal
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
id: actionMouseArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
if (modelData && contextMenu.currentApp && contextMenu.currentApp.desktopEntry) {
SessionService.launchDesktopAction(contextMenu.currentApp.desktopEntry, modelData)
appLauncher.appLaunched(contextMenu.currentApp)
}
contextMenu.close()
}
}
}
}
Rectangle {
visible: contextMenu.currentApp && contextMenu.currentApp.desktopEntry && contextMenu.currentApp.desktopEntry.actions && contextMenu.currentApp.desktopEntry.actions.length > 0
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 {
width: parent.width
height: 32

View File

@@ -316,9 +316,8 @@ Item {
console.warn("No toplevel found for grouped app")
}
} else {
// For multiple windows, show context menu (hide pin option for left-click)
if (contextMenu) {
contextMenu.showForButton(root, appData, 65, true)
contextMenu.showForButton(root, appData, 65, true, cachedDesktopEntry)
}
}
}
@@ -338,8 +337,7 @@ Item {
}
} else if (mouse.button === Qt.RightButton) {
if (contextMenu && appData) {
console.log("Right-clicked on app:", appData.appId, "type:", appData.type, "windowCount:", appData.windowCount || 0)
contextMenu.showForButton(root, appData, 40, false)
contextMenu.showForButton(root, appData, 40, false, cachedDesktopEntry)
} else {
console.warn("No context menu or appData available")
}

View File

@@ -16,12 +16,14 @@ PanelWindow {
property real dockVisibleHeight: 40
property int margin: 10
property bool hidePin: false
property var desktopEntry: null
function showForButton(button, data, dockHeight, hidePinOption) {
function showForButton(button, data, dockHeight, hidePinOption, entry) {
anchorItem = button
appData = data
dockVisibleHeight = dockHeight || 40
hidePin = hidePinOption || false
desktopEntry = entry || null
const dockWindow = button.Window.window
if (dockWindow) {
@@ -134,7 +136,7 @@ PanelWindow {
Rectangle {
id: menuContainer
width: Math.min(400, Math.max(200, menuColumn.implicitWidth + Theme.spacingS * 2))
width: Math.min(400, Math.max(180, menuColumn.implicitWidth + Theme.spacingS * 2))
height: Math.max(60, menuColumn.implicitHeight + Theme.spacingS * 2)
x: {
@@ -289,6 +291,71 @@ PanelWindow {
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
}
Repeater {
model: root.desktopEntry && root.desktopEntry.actions ? root.desktopEntry.actions : []
Rectangle {
width: parent.width
height: 28
radius: Theme.cornerRadius
color: actionArea.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.right: parent.right
anchors.rightMargin: Theme.spacingS
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingXS
Item {
anchors.verticalCenter: parent.verticalCenter
width: 16
height: 16
visible: modelData.icon && modelData.icon !== ""
IconImage {
anchors.fill: parent
source: modelData.icon ? Quickshell.iconPath(modelData.icon, true) : ""
smooth: true
asynchronous: true
visible: status === Image.Ready
}
}
StyledText {
anchors.verticalCenter: parent.verticalCenter
text: modelData.name || ""
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
font.weight: Font.Normal
elide: Text.ElideRight
wrapMode: Text.NoWrap
}
}
MouseArea {
id: actionArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
if (modelData) {
SessionService.launchDesktopAction(root.desktopEntry, modelData)
}
root.close()
}
}
}
}
Rectangle {
visible: root.desktopEntry && root.desktopEntry.actions && root.desktopEntry.actions.length > 0
width: parent.width
height: 1
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
}
Rectangle {
visible: !root.hidePin
width: parent.width

View File

@@ -101,6 +101,19 @@ Singleton {
});
}
function launchDesktopAction(desktopEntry, action) {
let cmd = action.command
if (SessionData.launchPrefix && SessionData.launchPrefix.length > 0) {
const launchPrefix = SessionData.launchPrefix.trim().split(" ")
cmd = launchPrefix.concat(cmd)
}
Quickshell.execDetached({
command: cmd,
workingDirectory: desktopEntry.workingDirectory,
});
}
// * Session management
function logout() {
if (hasUwsm) {