1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2025-12-06 05:25:41 -05:00

launcher + dock menu improvements

This commit is contained in:
bbedward
2025-10-06 17:46:19 -04:00
parent b507b08e34
commit 7c5d1ec0f6
8 changed files with 162 additions and 183 deletions

View File

@@ -157,6 +157,7 @@ PanelWindow {
radius: root.cornerRadius radius: root.cornerRadius
border.color: root.borderColor border.color: root.borderColor
border.width: root.borderWidth border.width: root.borderWidth
clip: false
layer.enabled: true layer.enabled: true
transform: root.animationType === "slide" ? slideTransform : null transform: root.animationType === "slide" ? slideTransform : null
@@ -170,6 +171,7 @@ PanelWindow {
FocusScope { FocusScope {
anchors.fill: parent anchors.fill: parent
focus: root.shouldBeVisible focus: root.shouldBeVisible
clip: false
Loader { Loader {
id: contentLoader id: contentLoader
@@ -178,6 +180,7 @@ PanelWindow {
active: root.keepContentLoaded || root.shouldBeVisible || root.visible active: root.keepContentLoaded || root.shouldBeVisible || root.visible
asynchronous: false asynchronous: false
focus: true focus: true
clip: false
onLoaded: { onLoaded: {
if (item) { if (item) {

View File

@@ -13,8 +13,13 @@ Item {
property alias searchField: searchField property alias searchField: searchField
property var parentModal: null property var parentModal: null
function resetScroll() {
resultsView.resetScroll()
}
anchors.fill: parent anchors.fill: parent
focus: true focus: true
clip: false
Keys.onPressed: event => { Keys.onPressed: event => {
if (event.key === Qt.Key_Escape) { if (event.key === Qt.Key_Escape) {
if (parentModal) if (parentModal)
@@ -101,6 +106,7 @@ Item {
anchors.fill: parent anchors.fill: parent
anchors.margins: Theme.spacingM anchors.margins: Theme.spacingM
spacing: Theme.spacingM spacing: Theme.spacingM
clip: false
Rectangle { Rectangle {
width: parent.width width: parent.width
@@ -228,6 +234,7 @@ Item {
} }
SpotlightResults { SpotlightResults {
id: resultsView
appLauncher: spotlightKeyHandler.appLauncher appLauncher: spotlightKeyHandler.appLauncher
contextMenu: contextMenu contextMenu: contextMenu
} }
@@ -245,7 +252,7 @@ Item {
visible: contextMenu.visible visible: contextMenu.visible
z: 999 z: 999
onClicked: () => { onClicked: () => {
contextMenu.close() contextMenu.hide()
} }
MouseArea { MouseArea {

View File

@@ -1,68 +1,72 @@
import QtQuick import QtQuick
import QtQuick.Controls
import Quickshell import Quickshell
import Quickshell.Widgets import Quickshell.Widgets
import qs.Common import qs.Common
import qs.Services import qs.Services
import qs.Widgets import qs.Widgets
Rectangle { Popup {
id: contextMenu id: contextMenu
property var currentApp: null property var currentApp: null
property bool menuVisible: false
property var appLauncher: null property var appLauncher: null
property var parentHandler: null property var parentHandler: null
function show(x, y, app) { function show(x, y, app) {
currentApp = app currentApp = app
const menuWidth = Math.max(180, Math.min(300, menuColumn.implicitWidth + Theme.spacingS * 2)) contextMenu.x = x + 4
const menuHeight = menuColumn.implicitHeight + Theme.spacingS * 2 contextMenu.y = y + 4
let finalX = x + 8 contextMenu.open()
let finalY = y + 8
if (parentHandler) {
if (finalX + menuWidth > parentHandler.width)
finalX = x - menuWidth - 8
if (finalY + menuHeight > parentHandler.height)
finalY = y - menuHeight - 8
finalX = Math.max(8, Math.min(finalX, parentHandler.width - menuWidth - 8))
finalY = Math.max(8, Math.min(finalY, parentHandler.height - menuHeight - 8))
}
contextMenu.x = finalX
contextMenu.y = finalY
contextMenu.width = menuWidth
contextMenu.visible = true
contextMenu.menuVisible = true
} }
function close() { function hide() {
contextMenu.menuVisible = false contextMenu.close()
Qt.callLater(() => {
contextMenu.visible = false
})
} }
visible: false width: Math.max(180, Math.min(300, menuColumn.implicitWidth + Theme.spacingS * 2))
width: 180
height: menuColumn.implicitHeight + Theme.spacingS * 2 height: menuColumn.implicitHeight + Theme.spacingS * 2
radius: Theme.cornerRadius padding: 0
color: Theme.popupBackground() closePolicy: Popup.CloseOnPressOutside
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) modal: false
border.width: 1 dim: false
z: 1000
opacity: menuVisible ? 1 : 0
scale: menuVisible ? 1 : 0.85
Rectangle { background: Rectangle {
anchors.fill: parent radius: Theme.cornerRadius
anchors.topMargin: 4 color: Theme.popupBackground()
anchors.leftMargin: 2 border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
anchors.rightMargin: -2 border.width: 1
anchors.bottomMargin: -4
radius: parent.radius Rectangle {
color: Qt.rgba(0, 0, 0, 0.15) anchors.fill: parent
z: parent.z - 1 anchors.topMargin: 4
anchors.leftMargin: 2
anchors.rightMargin: -2
anchors.bottomMargin: -4
radius: parent.radius
color: Qt.rgba(0, 0, 0, 0.15)
z: -1
}
}
enter: Transition {
NumberAnimation {
property: "opacity"
from: 0
to: 1
duration: Theme.shortDuration
easing.type: Theme.emphasizedEasing
}
}
exit: Transition {
NumberAnimation {
property: "opacity"
from: 1
to: 0
duration: Theme.shortDuration
easing.type: Theme.emphasizedEasing
}
} }
Column { Column {
@@ -128,7 +132,7 @@ Rectangle {
SessionData.removePinnedApp(appId) SessionData.removePinnedApp(appId)
else else
SessionData.addPinnedApp(appId) SessionData.addPinnedApp(appId)
contextMenu.close() contextMenu.hide()
} }
} }
} }
@@ -202,7 +206,7 @@ Rectangle {
appLauncher.appLaunched(contextMenu.currentApp) appLauncher.appLaunched(contextMenu.currentApp)
} }
} }
contextMenu.close() contextMenu.hide()
} }
} }
} }
@@ -262,23 +266,9 @@ Rectangle {
if (contextMenu.currentApp && appLauncher) if (contextMenu.currentApp && appLauncher)
appLauncher.launchApp(contextMenu.currentApp) appLauncher.launchApp(contextMenu.currentApp)
contextMenu.close() contextMenu.hide()
} }
} }
} }
} }
Behavior on opacity {
NumberAnimation {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
Behavior on scale {
NumberAnimation {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
} }

View File

@@ -18,21 +18,33 @@ DankModal {
function show() { function show() {
spotlightOpen = true spotlightOpen = true
open() open()
if (contentLoader.item && contentLoader.item.appLauncher) {
contentLoader.item.appLauncher.searchQuery = ""
}
Qt.callLater(() => { Qt.callLater(() => {
if (contentLoader.item && contentLoader.item.searchField) { if (contentLoader.item && contentLoader.item.searchField) {
contentLoader.item.searchField.forceActiveFocus() contentLoader.item.searchField.forceActiveFocus()
} }
}) })
} }
function hide() { function hide() {
spotlightOpen = false spotlightOpen = false
close() close()
cleanupTimer.restart() }
onDialogClosed: {
if (contentLoader.item) {
if (contentLoader.item.appLauncher) {
contentLoader.item.appLauncher.searchQuery = ""
contentLoader.item.appLauncher.selectedIndex = 0
contentLoader.item.appLauncher.setCategory("All")
}
if (contentLoader.item.resetScroll) {
contentLoader.item.resetScroll()
}
if (contentLoader.item.searchField) {
contentLoader.item.searchField.text = ""
}
}
} }
function toggle() { function toggle() {
@@ -69,19 +81,6 @@ DankModal {
} }
content: spotlightContent content: spotlightContent
Timer {
id: cleanupTimer
interval: animationDuration + 50
onTriggered: {
if (contentLoader.item && contentLoader.item.appLauncher) {
contentLoader.item.appLauncher.searchQuery = ""
contentLoader.item.appLauncher.selectedIndex = 0
contentLoader.item.appLauncher.setCategory("All")
}
}
}
Connections { Connections {
function onCloseAllModalsExcept(excludedModal) { function onCloseAllModalsExcept(excludedModal) {
if (excludedModal !== spotlightModal && !allowStacking && spotlightOpen) { if (excludedModal !== spotlightModal && !allowStacking && spotlightOpen) {

View File

@@ -10,10 +10,16 @@ Rectangle {
property var appLauncher: null property var appLauncher: null
property var contextMenu: null property var contextMenu: null
function resetScroll() {
resultsList.contentY = 0
resultsGrid.contentY = 0
}
width: parent.width width: parent.width
height: parent.height - y height: parent.height - y
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: "transparent" color: "transparent"
clip: false
DankListView { DankListView {
id: resultsList id: resultsList
@@ -157,7 +163,8 @@ Rectangle {
if (mouse.button === Qt.LeftButton) { if (mouse.button === Qt.LeftButton) {
resultsList.itemClicked(index, model) resultsList.itemClicked(index, model)
} else if (mouse.button === Qt.RightButton) { } else if (mouse.button === Qt.RightButton) {
const modalPos = mapToItem(resultsContainer.parent, mouse.x, mouse.y) const globalPos = mapToItem(null, mouse.x, mouse.y)
const modalPos = resultsContainer.parent.mapFromItem(null, globalPos.x, globalPos.y)
resultsList.itemRightClicked(index, model, modalPos.x, modalPos.y) resultsList.itemRightClicked(index, model, modalPos.x, modalPos.y)
} }
} }
@@ -308,7 +315,8 @@ Rectangle {
if (mouse.button === Qt.LeftButton) { if (mouse.button === Qt.LeftButton) {
resultsGrid.itemClicked(index, model) resultsGrid.itemClicked(index, model)
} else if (mouse.button === Qt.RightButton) { } else if (mouse.button === Qt.RightButton) {
const modalPos = mapToItem(resultsContainer.parent, mouse.x, mouse.y) const globalPos = mapToItem(null, mouse.x, mouse.y)
const modalPos = resultsContainer.parent.mapFromItem(null, globalPos.x, globalPos.y)
resultsGrid.itemRightClicked(index, model, modalPos.x, modalPos.y) resultsGrid.itemRightClicked(index, model, modalPos.x, modalPos.y)
} }
} }

View File

@@ -1,4 +1,5 @@
import QtQuick import QtQuick
import QtQuick.Controls
import QtQuick.Effects import QtQuick.Effects
import Quickshell import Quickshell
import Quickshell.Io import Quickshell.Io
@@ -488,7 +489,8 @@ DankPopout {
if (mouse.button === Qt.LeftButton) { if (mouse.button === Qt.LeftButton) {
appList.itemClicked(index, model) appList.itemClicked(index, model)
} else if (mouse.button === Qt.RightButton) { } else if (mouse.button === Qt.RightButton) {
var panelPos = mapToItem(contextMenu.parent, mouse.x, mouse.y) var globalPos = mapToItem(null, mouse.x, mouse.y)
var panelPos = contextMenu.parent.mapFromItem(null, globalPos.x, globalPos.y)
appList.itemRightClicked(index, model, panelPos.x, panelPos.y) appList.itemRightClicked(index, model, panelPos.x, panelPos.y)
} }
} }
@@ -649,7 +651,8 @@ DankPopout {
if (mouse.button === Qt.LeftButton) { if (mouse.button === Qt.LeftButton) {
appGrid.itemClicked(index, model) appGrid.itemClicked(index, model)
} else if (mouse.button === Qt.RightButton) { } else if (mouse.button === Qt.RightButton) {
var panelPos = mapToItem(contextMenu.parent, mouse.x, mouse.y) var globalPos = mapToItem(null, mouse.x, mouse.y)
var panelPos = contextMenu.parent.mapFromItem(null, globalPos.x, globalPos.y)
appGrid.itemRightClicked(index, model, panelPos.x, panelPos.y) appGrid.itemRightClicked(index, model, panelPos.x, panelPos.y)
} }
} }
@@ -662,68 +665,68 @@ DankPopout {
} }
} }
Rectangle { Popup {
id: contextMenu id: contextMenu
property var currentApp: null property var currentApp: null
property bool menuVisible: false
readonly property string appId: (currentApp && currentApp.desktopEntry) ? (currentApp.desktopEntry.id || currentApp.desktopEntry.execString || "") : "" readonly property string appId: (currentApp && currentApp.desktopEntry) ? (currentApp.desktopEntry.id || currentApp.desktopEntry.execString || "") : ""
readonly property bool isPinned: appId && SessionData.isPinnedApp(appId) readonly property bool isPinned: appId && SessionData.isPinnedApp(appId)
function show(x, y, app) { function show(x, y, app) {
currentApp = app currentApp = app
contextMenu.x = x + 4
const menuWidth = 180 contextMenu.y = y + 4
const menuHeight = menuColumn.implicitHeight + Theme.spacingS * 2 contextMenu.open()
let finalX = x + 8
let finalY = y + 8
if (finalX + menuWidth > appDrawerPopout.popupWidth) {
finalX = x - menuWidth - 8
}
if (finalY + menuHeight > appDrawerPopout.popupHeight) {
finalY = y - menuHeight - 8
}
finalX = Math.max(8, Math.min(finalX, appDrawerPopout.popupWidth - menuWidth - 8))
finalY = Math.max(8, Math.min(finalY, appDrawerPopout.popupHeight - menuHeight - 8))
contextMenu.x = finalX
contextMenu.y = finalY
contextMenu.visible = true
contextMenu.menuVisible = true
} }
function close() { function hide() {
contextMenu.menuVisible = false contextMenu.close()
Qt.callLater(() => {
contextMenu.visible = false
})
} }
visible: false
width: 180 width: 180
height: menuColumn.implicitHeight + Theme.spacingS * 2 height: menuColumn.implicitHeight + Theme.spacingS * 2
radius: Theme.cornerRadius padding: 0
color: Theme.popupBackground() closePolicy: Popup.CloseOnPressOutside
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) modal: false
border.width: 0 dim: false
z: 1000
opacity: menuVisible ? 1 : 0
scale: menuVisible ? 1 : 0.85
Rectangle { background: Rectangle {
anchors.fill: parent radius: Theme.cornerRadius
anchors.topMargin: 4 color: Theme.popupBackground()
anchors.leftMargin: 2 border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
anchors.rightMargin: -2 border.width: 1
anchors.bottomMargin: -4
radius: parent.radius Rectangle {
color: Qt.rgba(0, 0, 0, 0.15) anchors.fill: parent
z: parent.z - 1 anchors.topMargin: 4
anchors.leftMargin: 2
anchors.rightMargin: -2
anchors.bottomMargin: -4
radius: parent.radius
color: Qt.rgba(0, 0, 0, 0.15)
z: -1
}
}
enter: Transition {
NumberAnimation {
property: "opacity"
from: 0
to: 1
duration: Theme.shortDuration
easing.type: Theme.emphasizedEasing
}
}
exit: Transition {
NumberAnimation {
property: "opacity"
from: 1
to: 0
duration: Theme.shortDuration
easing.type: Theme.emphasizedEasing
}
} }
Column { Column {
@@ -778,7 +781,7 @@ DankPopout {
} else { } else {
SessionData.addPinnedApp(contextMenu.appId) SessionData.addPinnedApp(contextMenu.appId)
} }
contextMenu.close() contextMenu.hide()
} }
} }
} }
@@ -846,7 +849,7 @@ DankPopout {
SessionService.launchDesktopAction(contextMenu.currentApp.desktopEntry, modelData) SessionService.launchDesktopAction(contextMenu.currentApp.desktopEntry, modelData)
appLauncher.appLaunched(contextMenu.currentApp) appLauncher.appLaunched(contextMenu.currentApp)
} }
contextMenu.close() contextMenu.hide()
} }
} }
} }
@@ -906,25 +909,11 @@ DankPopout {
if (contextMenu.currentApp) if (contextMenu.currentApp)
appLauncher.launchApp(contextMenu.currentApp) appLauncher.launchApp(contextMenu.currentApp)
contextMenu.close() contextMenu.hide()
} }
} }
} }
} }
Behavior on opacity {
NumberAnimation {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
Behavior on scale {
NumberAnimation {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
} }
MouseArea { MouseArea {
@@ -932,7 +921,7 @@ DankPopout {
visible: contextMenu.visible visible: contextMenu.visible
z: 999 z: 999
onClicked: { onClicked: {
contextMenu.close() contextMenu.hide()
} }
MouseArea { MouseArea {

View File

@@ -18,7 +18,6 @@ Item {
readonly property color unselectedBorderColor: "transparent" readonly property color unselectedBorderColor: "transparent"
function handleCategoryClick(category) { function handleCategoryClick(category) {
selectedCategory = category
categorySelected(category) categorySelected(category)
} }

View File

@@ -1,5 +1,4 @@
import QtQuick import QtQuick
import QtQuick.Controls
import Quickshell import Quickshell
import Quickshell.Wayland import Quickshell.Wayland
import Quickshell.Widgets import Quickshell.Widgets
@@ -136,9 +135,6 @@ PanelWindow {
Rectangle { Rectangle {
id: menuContainer id: menuContainer
width: Math.min(400, Math.max(180, menuColumn.implicitWidth + Theme.spacingS * 2))
height: Math.max(60, menuColumn.implicitHeight + Theme.spacingS * 2)
x: { x: {
const isVertical = SettingsData.dockPosition === SettingsData.Position.Left || SettingsData.dockPosition === SettingsData.Position.Right const isVertical = SettingsData.dockPosition === SettingsData.Position.Left || SettingsData.dockPosition === SettingsData.Position.Right
if (isVertical) { if (isVertical) {
@@ -171,12 +167,23 @@ PanelWindow {
} }
} }
} }
width: Math.min(400, Math.max(180, menuColumn.implicitWidth + Theme.spacingS * 2))
height: Math.max(60, menuColumn.implicitHeight + Theme.spacingS * 2)
color: Theme.popupBackground() color: Theme.popupBackground()
radius: Theme.cornerRadius radius: Theme.cornerRadius
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.width: 1 border.width: 1
opacity: showContextMenu ? 1 : 0
scale: showContextMenu ? 1 : 0.85 opacity: root.showContextMenu ? 1 : 0
visible: opacity > 0
Behavior on opacity {
NumberAnimation {
duration: Theme.shortDuration
easing.type: Theme.emphasizedEasing
}
}
Rectangle { Rectangle {
anchors.fill: parent anchors.fill: parent
@@ -186,7 +193,7 @@ PanelWindow {
anchors.bottomMargin: -4 anchors.bottomMargin: -4
radius: parent.radius radius: parent.radius
color: Qt.rgba(0, 0, 0, 0.15) color: Qt.rgba(0, 0, 0, 0.15)
z: parent.z - 1 z: -1
} }
Column { Column {
@@ -403,13 +410,6 @@ PanelWindow {
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2) color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
} }
Rectangle {
visible: root.appData && root.appData.type === "window"
width: parent.width
height: 1
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
}
Rectangle { Rectangle {
visible: root.appData && (root.appData.type === "window" || (root.appData.type === "grouped" && root.appData.windowCount > 0)) visible: root.appData && (root.appData.type === "window" || (root.appData.type === "grouped" && root.appData.windowCount > 0))
width: parent.width width: parent.width
@@ -468,27 +468,11 @@ PanelWindow {
} }
} }
} }
Behavior on opacity {
NumberAnimation {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
Behavior on scale {
NumberAnimation {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
} }
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
z: -1 z: -1
onClicked: { onClicked: root.close()
root.close()
}
} }
} }