From c2a2a443789aec1dd777ca274b08cde34857374b Mon Sep 17 00:00:00 2001 From: Lemmy Date: Sun, 29 Mar 2026 10:33:21 -0400 Subject: [PATCH] fix(ncontextmenu): improved parent constraining --- Widgets/NContextMenu.qml | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/Widgets/NContextMenu.qml b/Widgets/NContextMenu.qml index 97b72c2eb..0975a1219 100644 --- a/Widgets/NContextMenu.qml +++ b/Widgets/NContextMenu.qml @@ -38,6 +38,10 @@ Popup { property real itemPadding: Style.marginM property int verticalPolicy: ScrollBar.AsNeeded property int horizontalPolicy: ScrollBar.AsNeeded + // Optional: explicit item whose bounds the menu must stay within. + // When unset, openAtItem auto-detects the nearest clipping ancestor. + property Item constrainTo: null + property Item _detectedConstraint: null signal triggered(string action) @@ -144,8 +148,15 @@ Popup { var menuWidth = root.width; var itemCount = root.filteredModel.length; var menuHeight = Math.max(itemCount * root.itemHeight + Math.max(0, itemCount - 1) * listView.spacing, root.itemHeight) + root.topPadding + root.bottomPadding; - x = Math.max(0, Math.min(x, root.parent.width - menuWidth)); - y = Math.max(0, Math.min(y, root.parent.height - menuHeight)); + var constraint = root.constrainTo || root._detectedConstraint; + if (constraint) { + var tl = constraint.mapToItem(root.parent, 0, 0); + x = Math.max(tl.x, Math.min(x, tl.x + constraint.width - menuWidth)); + y = Math.max(tl.y, Math.min(y, tl.y + constraint.height - menuHeight)); + } else { + x = Math.max(0, Math.min(x, root.parent.width - menuWidth)); + y = Math.max(0, Math.min(y, root.parent.height - menuHeight)); + } } root.x = x; root.y = y; @@ -154,6 +165,17 @@ Popup { // Helper function to open at item function openAtItem(item, mouseX, mouseY) { + if (!root.constrainTo) { + root._detectedConstraint = null; + var p = item; + while (p && p !== root.parent) { + if (p.clip && p.width > 0 && p.height > 0) { + root._detectedConstraint = p; + break; + } + p = p.parent; + } + } var pos = item.mapToItem(root.parent, mouseX || 0, mouseY || 0); openAt(pos.x, pos.y); }