diff --git a/quickshell/Modules/DankBar/DankBarBody.qml b/quickshell/Modules/DankBar/DankBarBody.qml index 9e955e8bf..57ad1a68d 100644 --- a/quickshell/Modules/DankBar/DankBarBody.qml +++ b/quickshell/Modules/DankBar/DankBarBody.qml @@ -812,20 +812,11 @@ Item { } topBarCore.evaluateReveal(); } - y: !barWindow.isVertical && !barWindow.isIsland ? (barPos === SettingsData.Position.Bottom ? parent.height - height : 0) : 0 - x: barWindow.isVertical && !barWindow.isIsland ? (barPos === SettingsData.Position.Right ? parent.width - width : 0) : 0 - height: !barWindow.isVertical ? (barWindow.isIsland ? parent.height : Theme.px(barWindow.effectiveBarThickness + barWindow.effectiveSpacing, barWindow._dpr)) : undefined - width: barWindow.isVertical ? (barWindow.isIsland ? parent.width : Theme.px(barWindow.effectiveBarThickness + barWindow.effectiveSpacing, barWindow._dpr)) : undefined - anchors { - leftMargin: !barWindow.isVertical && !barWindow.isIsland ? barWindow.taskbarStartInset : 0 - rightMargin: !barWindow.isVertical && !barWindow.isIsland ? barWindow.taskbarEndInset : 0 - topMargin: barWindow.isVertical && !barWindow.isIsland ? barWindow.taskbarStartInset : 0 - bottomMargin: barWindow.isVertical && !barWindow.isIsland ? barWindow.taskbarEndInset : 0 - left: !barWindow.isVertical ? parent.left : (barPos === SettingsData.Position.Left ? parent.left : undefined) - right: !barWindow.isVertical ? parent.right : (barPos === SettingsData.Position.Right ? parent.right : undefined) - top: barWindow.isVertical ? parent.top : undefined - bottom: barWindow.isVertical ? parent.bottom : undefined - } + // Switching stretch anchors can leave stale dimensions after an orientation change + x: barWindow.isIsland ? 0 : !barWindow.isVertical ? barWindow.taskbarStartInset : barPos === SettingsData.Position.Right ? parent.width - width : 0 + y: barWindow.isIsland ? 0 : barWindow.isVertical ? barWindow.taskbarStartInset : barPos === SettingsData.Position.Bottom ? parent.height - height : 0 + width: barWindow.isIsland ? parent.width : barWindow.isVertical ? Theme.px(barWindow.effectiveBarThickness + barWindow.effectiveSpacing, barWindow._dpr) : Math.max(0, parent.width - barWindow.taskbarStartInset - barWindow.taskbarEndInset) + height: barWindow.isIsland ? parent.height : !barWindow.isVertical ? Theme.px(barWindow.effectiveBarThickness + barWindow.effectiveSpacing, barWindow._dpr) : Math.max(0, parent.height - barWindow.taskbarStartInset - barWindow.taskbarEndInset) readonly property bool inOverview: CompositorService.overviewActiveOnScreen(barWindow.screenName) && barWindow.effectiveOpenOnOverview hoverEnabled: topBarCore.autoHide && !inOverview && !topBarCore.popoutPinsReveal acceptedButtons: barWindow.clickThroughEnabled || barWindow.isIsland ? Qt.NoButton : Qt.RightButton diff --git a/quickshell/tests/qml/frame-bar-flip.qml b/quickshell/tests/qml/frame-bar-flip.qml new file mode 100644 index 000000000..f090a522c --- /dev/null +++ b/quickshell/tests/qml/frame-bar-flip.qml @@ -0,0 +1,83 @@ +import QtQuick +import Quickshell +import qs.Common +import qs.Modules.DankBar +import qs.DankCommon.Common as DC + +ShellRoot { + id: root + + readonly property var positions: [0, 2, 0, 3, 0, 2, 1, 3, 1, 0] + property int step: 0 + readonly property int position: positions[step] + readonly property bool vertical: position === SettingsData.Position.Left || position === SettingsData.Position.Right + property var barConfig: ({ id: "fixture", position, spacing: 0, innerPadding: 4 }) + property var hyprlandOverviewLoader: null + property bool systemTrayMenuOpen: false + + ScriptModel { + id: widgets + values: [{ widgetId: "clock", id: "clock_0" }] + } + + FloatingWindow { + id: window + visible: true + implicitWidth: 800 + implicitHeight: 600 + + Item { + width: root.vertical ? Theme.px(body.effectiveBarThickness + body.effectiveSpacing, body._dpr) : 800 + height: root.vertical ? 600 : Theme.px(body.effectiveBarThickness + body.effectiveSpacing, body._dpr) + + // FrameBarHost retains the body while its slot changes orientation. + DankBarBody { + id: body + anchors.fill: parent + rootWindow: root + hostWindow: window + modelData: Quickshell.screens[0] + barConfig: root.barConfig + leftWidgetsModel: widgets + centerWidgetsModel: widgets + rightWidgetsModel: widgets + } + } + } + + function checkSections() { + for (const section of [body._leftSection, body._centerSection, body._rightSection]) { + section.widgetLayoutLoader?.item?.forceLayout(); + const point = section.mapToItem(body, 0, 0); + const crossCenter = root.vertical ? point.x + section.width / 2 : point.y + section.height / 2; + const expectedCenter = (root.vertical ? body.width : body.height) / 2; + if (Math.abs(crossCenter - expectedCenter) > 1) + throw new Error(`step ${step}, edge ${body.axis.edge}, ${section.section}: center ${crossCenter}, expected ${expectedCenter}`); + if (point.x < -1 || point.y < -1 || point.x + section.width > body.width + 1 || point.y + section.height > body.height + 1) + throw new Error(`step ${step}, edge ${body.axis.edge}, ${section.section}: section outside bar`); + } + } + + function advance() { + try { + checkSections(); + if (step === positions.length - 1) { + console.log("FIXTURE_PASS"); + Qt.quit(); + return; + } + step++; + Qt.callLater(advance); + } catch (error) { + console.error("FIXTURE_FAIL", error.message); + Qt.quit(); + } + } + + Component.onCompleted: { + DC.Style.theme = Theme; + DC.Style.settings = SettingsData; + DC.I18n.backend = I18n; + Qt.callLater(advance); + } +} diff --git a/quickshell/tests/run-qml.py b/quickshell/tests/run-qml.py index 463de08d3..b9ee6ade6 100644 --- a/quickshell/tests/run-qml.py +++ b/quickshell/tests/run-qml.py @@ -51,7 +51,7 @@ def main(): parser.error("--jobs must be positive") selected = args.suites or ["widgets", "media", "qt", "logic"] commands = { - "widgets": [sys.executable, "quickshell/tests/run-surface-fixture.py", "--suite", "quickshell/tests/qml/bar-content.qml", "quickshell/tests/qml/instance-routing.qml", "quickshell/tests/qml/font-weights.qml", "quickshell/tests/qml/theme-selected-container.qml", "quickshell/tests/qml/theme-accents.qml", "quickshell/tests/qml/clipboard-preview.qml", "quickshell/tests/qml/launcher-plugin-instances.qml", "quickshell/tests/qml/island-launcher-focus.qml", "quickshell/tests/qml/workspace-switcher.qml", "quickshell/tests/qml/focused-app.qml", "quickshell/tests/qml/slider-wheel.qml", "quickshell/tests/qml/control-center-sizes.qml", "quickshell/tests/qml/grid-edit-layout.qml"], + "widgets": [sys.executable, "quickshell/tests/run-surface-fixture.py", "--suite", "quickshell/tests/qml/bar-content.qml", "quickshell/tests/qml/frame-bar-flip.qml", "quickshell/tests/qml/instance-routing.qml", "quickshell/tests/qml/font-weights.qml", "quickshell/tests/qml/theme-selected-container.qml", "quickshell/tests/qml/theme-accents.qml", "quickshell/tests/qml/clipboard-preview.qml", "quickshell/tests/qml/launcher-plugin-instances.qml", "quickshell/tests/qml/island-launcher-focus.qml", "quickshell/tests/qml/workspace-switcher.qml", "quickshell/tests/qml/focused-app.qml", "quickshell/tests/qml/slider-wheel.qml", "quickshell/tests/qml/control-center-sizes.qml", "quickshell/tests/qml/grid-edit-layout.qml"], "media": [sys.executable, "quickshell/tests/run-surface-fixture.py", "--suite", "quickshell/tests/qml/media-presentation.qml", "quickshell/tests/qml/media-playback.qml", "quickshell/tests/qml/media-artwork.qml", "quickshell/tests/qml/media-lyrics.qml", "--mpris", "--artwork"], "logic": ["node", "--test", *sorted(str(path.relative_to(repo)) for path in (repo / "quickshell/tests").glob("*.test.mjs"))], }