dash: hold panel height while dragging cards unless hung from a top bar

lyrics: ignore floored position samples and shell refresh emits
This commit is contained in:
bbedward committed 2026-10-21 13:15:53 -04:00
1 parent 8f2a486006
commit 28f921fa02
10 files changed
+34 -6

No files matched your search

+4 -1
View File
@@ -680,6 +680,8 @@ DPopout {
readonly property bool ready: targetHeight >= 0 && settledHeight === targetHeight
readonly property real availableHeight: root.screen ? root.screen.height - mainContainer.horizontalChromeHeight - DashMetrics.contentPadding * 2 - Theme.barHeight - Theme.spacingL * 2 : contentHeight
readonly property int rowBudget: DashMetrics.rowCapFor(availableHeight)
// Growing a panel not hung from a top bar moves the grid under a held card, which retargets the drop.
readonly property bool heightHeld: (currentItem?.cardInteracting ?? false) && root.effectiveBarPosition % 4 !== SettingsData.Top
x: (root.verticalNavigation && root.navigationEdge === SettingsData.Left ? root.navigationWidth : 0) - root.editGutter
y: (!root.verticalNavigation && root.navigationEdge !== SettingsData.Bottom ? mainContainer.horizontalChromeHeight : 0) - root.editGutter
@@ -691,12 +693,13 @@ DPopout {
clip: contentHeight > height
function updateContentHeight() {
if (targetHeight < 0)
if (targetHeight < 0 || heightHeld)
return;
settledHeight = targetHeight;
}
onTargetHeightChanged: Qt.callLater(updateContentHeight)
onHeightHeldChanged: Qt.callLater(updateContentHeight)
Column {
id: emptyContent
+1
View File
@@ -214,6 +214,7 @@ Singleton {
readonly property int mediaLyricsRequestTimeout: 16000
readonly property int mediaLyricsLoadingDelay: 300
readonly property real mediaLyricsPositionTolerance: 0.05
readonly property real mediaLyricsWholeSecondSlack: 0.005
readonly property int mediaLyricsPositionProbeInterval: 5000
readonly property real mediaLyricsPositionProbeDrift: 1.5
readonly property real mediaLyricsPositionProbeThreshold: 1
@@ -25,6 +25,7 @@ Item {
readonly property Item focusTarget: grid
readonly property bool blocksTabNavigation: editMode || addMenu.open || optionsSheet.shown
readonly property bool cardResizing: grid.sizePreview !== null
readonly property bool cardInteracting: grid.interacting
implicitHeight: Math.max(DashMetrics.tabMinHeight, grid.implicitHeight)
LayoutMirroring.enabled: I18n.isRtl
+1 -1
View File
@@ -123,7 +123,7 @@ Item {
interval: DashMetrics.mediaPositionPollInterval
running: root.live && root.activePlayer?.playbackState === MprisPlaybackState.Playing && !root.isSeeking
repeat: true
onTriggered: root.activePlayer?.positionChanged()
onTriggered: MprisController.refreshPosition(root.activePlayer)
}
function syncAudioRef(wanted) {
@@ -53,7 +53,7 @@ Card {
interval: DashMetrics.mediaPositionPollInterval
running: root.live && root.visible && root.interactive && root.showSeekbar && root.playing && !root.isSeeking
repeat: true
onTriggered: root.activePlayer?.positionSupported && root.activePlayer.positionChanged()
onTriggered: MprisController.refreshPosition(root.activePlayer)
}
Loader {
+1
View File
@@ -26,6 +26,7 @@ FocusScope {
readonly property var addable: grid.addableEntries
readonly property int usedColumns: grid.usedColumns
readonly property bool cardResizing: grid.sizePreview !== null
readonly property bool cardInteracting: grid.interacting
readonly property bool blocksTabNavigation: grid.blocksTabNavigation || detailSheet.shown || editorSheet.shown || optionsSheet.shown || addMenu.open
implicitWidth: DashMetrics.contentWidthFor(SettingsData.showWeekNumber)
+1
View File
@@ -36,6 +36,7 @@ Item {
}
]
readonly property bool blocksTabNavigation: widgets.blocksTabNavigation
readonly property bool cardInteracting: widgets.cardInteracting
readonly property var forecastOptions: [DashRegistry.choice("forecast", I18n.tr("Forecast", "weather widget option label for forecast display type"), "chart", [
{
"value": "chart",
+13 -1
View File
@@ -90,7 +90,11 @@ QtObject {
if (enabled && (state === "none" || state === "error"))
useEmbeddedText(state);
}
onPositionChanged: scheduleAnchor()
onPositionChanged: {
if (MprisController.refreshingPosition || flooredEcho())
return;
scheduleAnchor();
}
onRateChanged: updatePlaybackClock()
onPlayingChanged: {
probe = null;
@@ -379,6 +383,7 @@ QtObject {
if (!line || !Number.isFinite(line.t))
return false;
player.position = Math.max(0.1, Math.min(line.t, duration * 0.99));
reanchor();
return true;
}
@@ -434,6 +439,13 @@ QtObject {
resync();
}
// pear-desktop floors Position to whole seconds on pause, resume and track events.
function flooredEcho() {
const lead = currentTime() - position;
const whole = Math.abs(position - Math.round(position)) < DashMetrics.mediaLyricsWholeSecondSlack;
return whole && lead >= 0 && lead < 1 + DashMetrics.mediaLyricsPositionTolerance;
}
function scheduleAnchor() {
positionWall = Date.now();
if (enabled && synced && !stopped && !anchorUpdate.running)
+10 -1
View File
@@ -34,6 +34,15 @@ Singleton {
property bool _mprisPublishDirty: false
property int _mprisConnectionEpoch: 0
property int positionConsumers: 0
property bool refreshingPosition: false
function refreshPosition(player) {
if (!player?.positionSupported)
return;
refreshingPosition = true;
player.positionChanged();
refreshingPosition = false;
}
function addPositionRef() {
positionConsumers++;
@@ -398,7 +407,7 @@ Singleton {
interval: 1000
running: root.positionConsumers > 0 && root.activePlayer?.playbackState === MprisPlaybackState.Playing
repeat: true
onTriggered: root.activePlayer?.positionChanged()
onTriggered: root.refreshPosition(root.activePlayer)
}
function _hasMPRISSubscription(): bool {
+1 -1
View File
@@ -227,7 +227,7 @@ Item {
isPlaying: activePlayer && activePlayer.playbackState === MprisPlaybackState.Playing
onFrameTicked: {
if (!root.isSeeking)
activePlayer.positionChanged();
MprisController.refreshPosition(activePlayer);
}
MouseArea {