quickshell: size the tray menu from the model, not the laid-out Card
Every previous attempt read the panel height off menuItems, which by definition lags the data: the Repeater must build delegates and the Column re-measure before the Card reports its real size. Reading it during that gap is the flash, and no amount of gating on the model closes it, because the gap is between the model and the layout. fullHeight now sums the rows from menuOpener.children directly. That is exact — cardSpacing is 0, so the sum plus 2*cardPad is precisely what the Card lays out — and it lands in the same binding pass as the data, so size and content never disagree. Row metrics moved to menuRowHeight/menuSepHeight, shared by the sum and the delegate so they cannot drift. The previous-height hold stays for the DBus fetch itself. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
31c584e7d1
commit
d866cae4f7
1 changed files with 31 additions and 24 deletions
|
|
@ -2116,32 +2116,38 @@ in
|
|||
// across. Hold the last loaded height until the new items
|
||||
// arrive so the morph stays continuous. The correction is
|
||||
// small, and nil when it is the same menu as last time.
|
||||
readonly property bool menuLoaded:
|
||||
menuOpener.children && menuOpener.children.values.length > 0
|
||||
// The model populating is NOT the same instant as the
|
||||
// layout catching up: the Repeater still has to build its
|
||||
// delegates and the Column re-measure. Gating on the model
|
||||
// alone left a frame where menuLoaded was true but the Card
|
||||
// was still empty-sized, so the panel collapsed and then
|
||||
// regrew — visible when switching between two tray icons,
|
||||
// which is the only path that reassigns the handle.
|
||||
// Require the height to have actually grown past an empty
|
||||
// Card (which measures 2*cardPad, not 0).
|
||||
readonly property bool menuReady:
|
||||
menuLoaded && menuItems.height > 2 * Theme.cardPad
|
||||
property real lastMenuHeight: 0
|
||||
fullHeight: (menuReady ? menuItems.height
|
||||
: Math.max(menuItems.height, lastMenuHeight))
|
||||
+ 2 * Theme.panelGap
|
||||
// Row metrics, shared by the delegate below and the height
|
||||
// sum — these two must never drift apart.
|
||||
readonly property int menuRowHeight: 28
|
||||
readonly property int menuSepHeight: 9
|
||||
|
||||
Connections {
|
||||
target: menuItems
|
||||
function onHeightChanged() {
|
||||
if (contextMenu.menuReady)
|
||||
contextMenu.lastMenuHeight = menuItems.height;
|
||||
}
|
||||
// Size the panel from the MODEL, not from the laid-out
|
||||
// Card. The Card only reaches its true height a frame or
|
||||
// more after the model populates — the Repeater has to
|
||||
// build delegates and the Column re-measure — and every
|
||||
// previous attempt here read the Card during that gap,
|
||||
// which is the flash. Summing the rows is exact and
|
||||
// available the instant the data lands, so the height and
|
||||
// its content update in the same binding pass.
|
||||
readonly property real menuContentHeight: {
|
||||
if (!menuOpener.children) return 0;
|
||||
const items = menuOpener.children.values;
|
||||
let h = 0;
|
||||
for (let i = 0; i < items.length; i++)
|
||||
h += items[i].isSeparator ? menuSepHeight : menuRowHeight;
|
||||
return h;
|
||||
}
|
||||
|
||||
// Hold the previous size across the DBus fetch of a newly
|
||||
// assigned menu (the tray-to-tray path), so the switch
|
||||
// morphs instead of collapsing to empty and regrowing.
|
||||
property real lastMenuHeight: 0
|
||||
onMenuContentHeightChanged: {
|
||||
if (menuContentHeight > 0) lastMenuHeight = menuContentHeight;
|
||||
}
|
||||
fullHeight: (menuContentHeight > 0 ? menuContentHeight : lastMenuHeight)
|
||||
+ 2 * Theme.cardPad + 2 * Theme.panelGap
|
||||
|
||||
// Deliberately NOT cleared on close. Nulling the menu threw
|
||||
// away the loaded items, and the only thing that refills
|
||||
// them is a hover-enter — which never fires if the cursor
|
||||
|
|
@ -2177,7 +2183,8 @@ in
|
|||
Rectangle {
|
||||
required property var modelData
|
||||
width: parent.width
|
||||
height: modelData.isSeparator ? 9 : 28
|
||||
height: modelData.isSeparator ? contextMenu.menuSepHeight
|
||||
: contextMenu.menuRowHeight
|
||||
color: !modelData.isSeparator && itemMouse.containsMouse && modelData.enabled
|
||||
? Theme.base02 : Theme.base02t
|
||||
Behavior on color { ColorAnimation { duration: Theme.animFade } }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue