Files
DankMaterialShell/quickshell/Modules/Dock/DockContextMenuBase.qml
T
bbedward 0bd3e85150 settings: fix window rules overflow, unify popout border settings
cards: fix regression that created borders
matugen: run on a low priority worker and seeds dms-colors before other
templates
2026-09-21 11:47:52 -04:00

168 lines
4.9 KiB
QML

import QtQuick
import Quickshell
import Quickshell.Wayland
import qs.Common
import qs.Services
import qs.Widgets
PanelWindow {
id: root
property var options: ({})
default property alias content: menuColumn.children
property var anchorItem: null
property var surfaceContext: null
property real dockVisibleHeight: 40
property int margin: 10
property string layerNamespace: "dms:dock-context-menu"
property real menuMaxWidth: 400
property real menuMinWidth: 180
property point anchorPos: Qt.point(screen ? screen.width / 2 : 0, screen ? screen.height - 100 : 0)
function show(button, dockHeight, dockScreen) {
if (dockScreen)
screen = dockScreen;
surfaceContext = button?.dockApps?.surfaceContext ?? null;
anchorItem = button;
dockVisibleHeight = dockHeight || 40;
visible = true;
}
function close() {
visible = false;
}
function updatePosition() {
if (!anchorItem || !screen)
return;
const point = surfaceContext?.screenPoint(anchorItem, anchorItem.width / 2, anchorItem.height / 2);
if (!point)
return;
const extent = (surfaceContext?.thickness ?? dockVisibleHeight) / 2 + Theme.spacingS;
switch (root.options.position) {
case SettingsData.Position.Left:
anchorPos = Qt.point(point.x + extent, point.y);
return;
case SettingsData.Position.Right:
anchorPos = Qt.point(point.x - extent, point.y);
return;
case SettingsData.Position.Top:
anchorPos = Qt.point(point.x, point.y + extent);
return;
default:
anchorPos = Qt.point(point.x, point.y - extent);
}
}
onAnchorItemChanged: {
if (!anchorItem) {
close();
return;
}
updatePosition();
}
onVisibleChanged: {
if (visible) {
updatePosition();
return;
}
anchorItem = null;
surfaceContext = null;
}
WindowBlur {
targetWindow: root
surfaceColor: menuContainer.color
blurX: menuContainer.x
blurY: menuContainer.y
blurWidth: root.visible ? menuContainer.width : 0
blurHeight: root.visible ? menuContainer.height : 0
blurRadius: Theme.windowRadius
}
WlrLayershell.namespace: root.layerNamespace
WlrLayershell.layer: WlrLayershell.Overlay
WlrLayershell.exclusiveZone: -1
WlrLayershell.keyboardFocus: WlrKeyboardFocus.None
screen: null
visible: false
color: "transparent"
anchors {
top: true
left: true
right: true
bottom: true
}
Rectangle {
id: menuContainer
readonly property bool isVertical: root.options.position === SettingsData.Position.Left || root.options.position === SettingsData.Position.Right
x: {
if (!isVertical) {
const want = root.anchorPos.x - width / 2;
return Math.max(10, Math.min(root.width - width - 10, want));
}
if (root.options.position === SettingsData.Position.Right)
return Math.max(10, root.anchorPos.x - width);
return Math.min(root.width - width - 10, root.anchorPos.x);
}
y: {
if (isVertical) {
const want = root.anchorPos.y - height / 2;
return Math.max(10, Math.min(root.height - height - 10, want));
}
if (root.options.position === SettingsData.Position.Bottom)
return Math.max(10, root.anchorPos.y - height);
return Math.min(root.height - height - 10, root.anchorPos.y);
}
width: Math.min(root.menuMaxWidth, Math.max(root.menuMinWidth, menuColumn.implicitWidth + Theme.spacingS * 2))
height: menuColumn.implicitHeight + Theme.spacingS * 2
color: Theme.floatingSurface
radius: Theme.windowRadius
border.color: BlurService.borderColor
border.width: BlurService.borderWidth
opacity: root.visible ? 1 : 0
visible: opacity > 0
Behavior on opacity {
NumberAnimation {
duration: Theme.shortDuration
easing.type: Theme.emphasizedEasing
}
}
Rectangle {
anchors.fill: parent
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
}
Column {
id: menuColumn
width: parent.width - Theme.spacingS * 2
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.topMargin: Theme.spacingS
spacing: 1
}
}
MouseArea {
anchors.fill: parent
z: -1
onClicked: root.close()
}
}