From 53dcb40c5d97a23164705606a5d683f750051017 Mon Sep 17 00:00:00 2001 From: Fimeg Date: Mon, 27 Jul 2026 08:29:44 -0400 Subject: [PATCH] dial: bind the ring origin instead of assigning it before the surface is sized --- .../modules/souveraine/dial/DialHost.qml | 5 ++- .../modules/souveraine/dial/RadialDial.qml | 35 ++++++++++++++----- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/surfaces/quickshell/modules/souveraine/dial/DialHost.qml b/surfaces/quickshell/modules/souveraine/dial/DialHost.qml index a46530c..b1ba919 100644 --- a/surfaces/quickshell/modules/souveraine/dial/DialHost.qml +++ b/surfaces/quickshell/modules/souveraine/dial/DialHost.qml @@ -58,8 +58,11 @@ Scope { Connections { target: scope function onDialOpenChanged() { + // No touch point to hand over — and none can be computed + // here, because this fires on the same signal that maps + // the surface, when win.width/height are still 0. if (scope.dialOpen) - dial.openAt(win.width / 2, win.height * 0.68); + dial.openAt(); else dial.close(); } diff --git a/surfaces/quickshell/modules/souveraine/dial/RadialDial.qml b/surfaces/quickshell/modules/souveraine/dial/RadialDial.qml index 5bae364..f668ea6 100644 --- a/surfaces/quickshell/modules/souveraine/dial/RadialDial.qml +++ b/surfaces/quickshell/modules/souveraine/dial/RadialDial.qml @@ -27,11 +27,26 @@ Item { property bool open: false - // Where the ring is centred. Set by whatever opened it — a long-press - // hands over the touch point so the ring appears under the thumb rather - // than in the middle of a phone you are holding by one edge. - property real originX: width / 2 - property real originY: height * 0.68 + // The point the opener asked for — a long-press hands over its touch point + // so the ring appears under the thumb rather than in the middle of a phone + // you are holding by one edge. NaN means no point was given. + // + // Held as a request, not written into originX/originY, because openAt() + // runs on the same signal that maps the layer surface: width and height + // are still 0 at that instant, so an assigned origin clamps to 0,0 and + // stays there once the window sizes. As a binding it corrects itself. + property real requestedX: NaN + property real requestedY: NaN + + // Where the ring is centred. + readonly property real originX: isNaN(root.requestedX) + ? root.width / 2 + : Math.max(root.ringRadius * 1.3, + Math.min(root.width - root.ringRadius * 1.3, root.requestedX)) + readonly property real originY: isNaN(root.requestedY) + ? root.height * 0.68 + : Math.max(root.ringRadius * 1.3, + Math.min(root.height - root.ringRadius * 1.3, root.requestedY)) readonly property real ringRadius: Math.min(width, height) * 0.30 readonly property real deadZone: ringRadius * 0.42 @@ -47,13 +62,13 @@ Item { signal invoked(var entry) + // Call with no arguments when there is no touch point to hand over: the + // ring then centres itself on the surface it was given. function openAt(x, y) { if (root.entries.length === 0) return; - root.originX = Math.max(root.ringRadius * 1.3, - Math.min(root.width - root.ringRadius * 1.3, x)); - root.originY = Math.max(root.ringRadius * 1.3, - Math.min(root.height - root.ringRadius * 1.3, y)); + root.requestedX = x === undefined ? NaN : x; + root.requestedY = y === undefined ? NaN : y; root.selected = -1; root.lastDetent = -1; root.open = true; @@ -62,6 +77,8 @@ Item { function close() { root.open = false; root.selected = -1; + root.requestedX = NaN; + root.requestedY = NaN; } // Angle of entry i, measured so the first entry sits at the top and the