From b1e2bb3bc691dc2a2722dad1de4e9ddc021f5328 Mon Sep 17 00:00:00 2001 From: 28allday Date: Sat, 13 Jun 2026 23:26:55 +0100 Subject: [PATCH] =?UTF-8?q?feat(bar):=20horizontal=20top=20bar=20=E2=80=94?= =?UTF-8?q?=20Phase=20A=20geometry=20(NoSignal=20layout)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Convert the bar from a vertical left-edge strip to a horizontal top bar. The shell had no orientation abstraction, so this flips the geometry across the bar and the drawer/region/interaction layer: - Bar.qml: ColumnLayout -> RowLayout; hit-testing (checkPopout/handleWheel), scroll halves and popout-center anchoring all keyed off x instead of y; first/last padding -> left/right margins. - BarWrapper.qml: the bar's "thickness" is now its height (clampedHeight/ contentHeight/implicitHeight); content anchors left/right/top. - drawers: Exclusions (exclusive zone moved left->top), Panels (content inset topMargin = bar height), Regions + ContentWindow (panel->window coordinate mapping and the thick border flip left->top), Interactions (bar-region check y --- modules/bar/Bar.qml | 44 ++++++++++--------- modules/bar/BarWrapper.qml | 33 +++++++------- modules/bar/components/Clock.qml | 33 ++++++++------ modules/bar/components/StatusIcons.qml | 13 +++--- modules/bar/components/Tray.qml | 40 ++++++++--------- .../bar/components/workspaces/Workspace.qml | 2 +- .../bar/components/workspaces/Workspaces.qml | 8 ++-- modules/drawers/ContentWindow.qml | 23 +++++----- modules/drawers/Exclusions.qml | 2 +- modules/drawers/Interactions.qml | 36 ++++++++------- modules/drawers/Panels.qml | 2 +- modules/drawers/Regions.qml | 12 ++--- 12 files changed, 131 insertions(+), 117 deletions(-) diff --git a/modules/bar/Bar.qml b/modules/bar/Bar.qml index db648a9c..6e5cdb54 100644 --- a/modules/bar/Bar.qml +++ b/modules/bar/Bar.qml @@ -10,14 +10,18 @@ import Caelestia.Config import qs.components import qs.services -ColumnLayout { +// NoSignal: horizontal top bar. The widgets flow left->right in a RowLayout and +// the bar's "thickness" is its HEIGHT; hit-testing / scroll / popout anchoring all +// key off the x-axis (the position along the bar). Upstream caelestia is a +// vertical left-edge bar — this is the NoSignal layout fork (Phase 3). +RowLayout { id: root required property ShellScreen screen required property DrawerVisibilities visibilities required property BarPopouts.Wrapper popouts required property bool fullscreen - readonly property int vPadding: Tokens.padding.large + readonly property int hPadding: Tokens.padding.large function closeTray(): void { if (!Config.bar.tray.compact) @@ -31,8 +35,8 @@ ColumnLayout { } } - function checkPopout(y: real): void { - const ch = childAt(width / 2, y) as WrappedLoader; + function checkPopout(x: real): void { + const ch = childAt(x, height / 2) as WrappedLoader; if (ch?.id !== "tray") closeTray(); @@ -43,24 +47,24 @@ ColumnLayout { } const id = ch.id; - const top = ch.y; + const left = ch.x; if (id === "statusIcons" && Config.bar.popouts.statusIcons) { const items = (ch.item as StatusIcons).items; - const icon = items.childAt(items.width / 2, mapToItem(items, 0, y).y); + const icon = items.childAt(mapToItem(items, x, 0).x, items.height / 2); if (icon) { popouts.currentName = icon.name; - popouts.currentCenter = Qt.binding(() => icon.mapToItem(root, 0, icon.implicitHeight / 2).y); + popouts.currentCenter = Qt.binding(() => icon.mapToItem(root, icon.implicitWidth / 2, 0).x); popouts.hasCurrent = true; } } else if (id === "tray" && Config.bar.popouts.tray) { const tray = ch.item as Tray; - if (!Config.bar.tray.compact || (tray.expanded && !tray.expandIcon.contains(mapToItem(tray.expandIcon, tray.implicitWidth / 2, y)))) { - const index = Math.floor(((y - top - tray.padding * 2 + tray.spacing) / tray.layout.implicitHeight) * tray.items.count); + if (!Config.bar.tray.compact || (tray.expanded && !tray.expandIcon.contains(mapToItem(tray.expandIcon, x, tray.implicitHeight / 2)))) { + const index = Math.floor(((x - left - tray.padding * 2 + tray.spacing) / tray.layout.implicitWidth) * tray.items.count); const trayItem = tray.items.itemAt(index); if (trayItem) { popouts.currentName = `traymenu${index}`; - popouts.currentCenter = Qt.binding(() => trayItem.mapToItem(root, 0, trayItem.implicitHeight / 2).y); + popouts.currentCenter = Qt.binding(() => trayItem.mapToItem(root, trayItem.implicitWidth / 2, 0).x); popouts.hasCurrent = true; } else { popouts.hasCurrent = false; @@ -71,13 +75,13 @@ ColumnLayout { } } else if (id === "activeWindow" && Config.bar.popouts.activeWindow && Config.bar.activeWindow.showOnHover) { popouts.currentName = id.toLowerCase(); - popouts.currentCenter = (ch.item as Item).mapToItem(root, 0, (ch.item as Item).implicitHeight / 2).y ?? 0; + popouts.currentCenter = (ch.item as Item).mapToItem(root, (ch.item as Item).implicitWidth / 2, 0).x ?? 0; popouts.hasCurrent = true; } } - function handleWheel(y: real, angleDelta: point): void { - const ch = childAt(width / 2, y) as WrappedLoader; + function handleWheel(x: real, angleDelta: point): void { + const ch = childAt(x, height / 2) as WrappedLoader; if (ch?.id === "workspaces" && Config.bar.scrollActions.workspaces) { // Workspace scroll const mon = (GlobalConfig.bar.workspaces.perMonitorWorkspaces ? Hypr.monitorFor(screen) : Hypr.focusedMonitor); @@ -86,14 +90,14 @@ ColumnLayout { Hypr.dispatch(`togglespecialworkspace ${specialWs.slice(8)}`); else if (angleDelta.y < 0 || (GlobalConfig.bar.workspaces.perMonitorWorkspaces ? mon.activeWorkspace?.id : Hypr.activeWsId) > 1) Hypr.dispatch(`workspace r${angleDelta.y > 0 ? "-" : "+"}1`); - } else if (y < screen.height / 2 && Config.bar.scrollActions.volume) { - // Volume scroll on top half + } else if (x < screen.width / 2 && Config.bar.scrollActions.volume) { + // Volume scroll on left half if (angleDelta.y > 0) Audio.incrementVolume(); else if (angleDelta.y < 0) Audio.decrementVolume(); } else if (Config.bar.scrollActions.brightness) { - // Brightness scroll on bottom half + // Brightness scroll on right half const monitor = Brightness.getMonitorForScreen(screen); if (angleDelta.y > 0) monitor.setBrightness(monitor.brightness + GlobalConfig.services.brightnessIncrement); @@ -115,7 +119,7 @@ ColumnLayout { DelegateChoice { roleValue: "spacer" delegate: WrappedLoader { - Layout.fillHeight: enabled + Layout.fillWidth: enabled } } DelegateChoice { @@ -201,11 +205,11 @@ ColumnLayout { } asynchronous: true - Layout.alignment: Qt.AlignHCenter + Layout.alignment: Qt.AlignVCenter // Cursed ahh thing to add padding to first and last enabled components - Layout.topMargin: findFirstEnabled() === this ? root.vPadding : 0 - Layout.bottomMargin: findLastEnabled() === this ? root.vPadding : 0 + Layout.leftMargin: findFirstEnabled() === this ? root.hPadding : 0 + Layout.rightMargin: findLastEnabled() === this ? root.hPadding : 0 visible: enabled active: enabled diff --git a/modules/bar/BarWrapper.qml b/modules/bar/BarWrapper.qml index b111d1da..f1216f57 100644 --- a/modules/bar/BarWrapper.qml +++ b/modules/bar/BarWrapper.qml @@ -17,10 +17,13 @@ Item { readonly property bool disabled: Strings.testRegexList(Config.bar.excludedScreens, screen.name) - readonly property int clampedWidth: Math.max(Config.border.minThickness, implicitWidth) + // NoSignal horizontal top bar: the bar's "thickness" is its HEIGHT (was width + // for the upstream vertical left-edge bar). clampedHeight/contentHeight and + // implicitHeight carry the thickness; the wrapper fills the screen width. + readonly property int clampedHeight: Math.max(Config.border.minThickness, implicitHeight) readonly property int padding: Math.max(Tokens.padding.small, Config.border.thickness) - readonly property int contentWidth: Tokens.sizes.bar.innerWidth + padding * 2 - readonly property int exclusiveZone: !disabled && (Config.bar.persistent || visibilities.bar) ? contentWidth : Config.border.thickness + readonly property int contentHeight: Tokens.sizes.bar.innerWidth + padding * 2 + readonly property int exclusiveZone: !disabled && (Config.bar.persistent || visibilities.bar) ? contentHeight : Config.border.thickness readonly property bool shouldBeVisible: !fullscreen && !disabled && (Config.bar.persistent || visibilities.bar || isHovered) property bool isHovered @@ -28,24 +31,24 @@ Item { (content.item as Bar)?.closeTray(); } - function checkPopout(y: real): void { - (content.item as Bar)?.checkPopout(y); + function checkPopout(x: real): void { + (content.item as Bar)?.checkPopout(x); } - function handleWheel(y: real, angleDelta: point): void { - (content.item as Bar)?.handleWheel(y, angleDelta); + function handleWheel(x: real, angleDelta: point): void { + (content.item as Bar)?.handleWheel(x, angleDelta); } clip: true - visible: width > Config.border.thickness - implicitWidth: fullscreen ? 0 : Config.border.thickness + visible: height > Config.border.thickness + implicitHeight: fullscreen ? 0 : Config.border.thickness states: State { name: "visible" when: root.shouldBeVisible PropertyChanges { - root.implicitWidth: root.contentWidth + root.implicitHeight: root.contentHeight } } @@ -56,7 +59,7 @@ Item { Anim { target: root - property: "implicitWidth" + property: "implicitHeight" } }, Transition { @@ -65,7 +68,7 @@ Item { Anim { target: root - property: "implicitWidth" + property: "implicitHeight" type: Anim.Emphasized } } @@ -74,14 +77,14 @@ Item { Loader { id: content - anchors.top: parent.top - anchors.bottom: parent.bottom + anchors.left: parent.left anchors.right: parent.right + anchors.top: parent.top active: root.shouldBeVisible sourceComponent: Bar { - width: root.contentWidth + height: root.contentHeight screen: root.screen visibilities: root.visibilities popouts: root.popouts // qmllint disable incompatible-type diff --git a/modules/bar/components/Clock.qml b/modules/bar/components/Clock.qml index 7e86ac47..d279a7f9 100644 --- a/modules/bar/components/Clock.qml +++ b/modules/bar/components/Clock.qml @@ -13,20 +13,20 @@ StyledRect { readonly property int padding: Config.bar.clock.background ? Tokens.padding.medium : Tokens.padding.extraSmall readonly property var font: Tokens.font.body.builders.small.scale(1.1) - implicitWidth: Tokens.sizes.bar.innerWidth - implicitHeight: layout.implicitHeight + root.padding * 2 + implicitHeight: Tokens.sizes.bar.innerWidth + implicitWidth: layout.implicitWidth + root.padding * 2 color: Qt.alpha(Colours.tPalette.m3surfaceContainer, Config.bar.clock.background ? Colours.tPalette.m3surfaceContainer.a : 0) radius: Tokens.rounding.full - ColumnLayout { + RowLayout { id: layout anchors.centerIn: parent spacing: Tokens.spacing.small Loader { - Layout.alignment: Qt.AlignHCenter + Layout.alignment: Qt.AlignVCenter asynchronous: true active: Config.bar.clock.showIcon visible: active @@ -38,24 +38,26 @@ StyledRect { } StyledText { - Layout.alignment: Qt.AlignHCenter + Layout.alignment: Qt.AlignVCenter visible: Config.bar.clock.showDate horizontalAlignment: StyledText.AlignHCenter - text: Time.format("ddd\nd") + text: Time.format("ddd d") font: Tokens.font.body.small color: root.colour } Rectangle { - Layout.fillWidth: true + Layout.fillHeight: true + Layout.topMargin: root.padding + Layout.bottomMargin: root.padding visible: Config.bar.clock.showDate - implicitHeight: 1 + implicitWidth: 1 color: Colours.palette.m3outlineVariant } StyledText { - Layout.alignment: Qt.AlignHCenter + Layout.alignment: Qt.AlignVCenter text: Time.hourStr font: { const scale = text === "11" ? 1.15 : Math.min(1.05, Math.max(hourMetrics.width, minMetrics.width) / hourMetrics.width); @@ -72,8 +74,14 @@ StyledRect { } StyledText { - Layout.topMargin: -parent.spacing - 4 - Layout.alignment: Qt.AlignHCenter + Layout.alignment: Qt.AlignVCenter + text: ":" + font: root.font.build() + color: root.colour + } + + StyledText { + Layout.alignment: Qt.AlignVCenter text: Time.minuteStr font: { const scale = text === "11" ? 1.15 : Math.min(1.05, Math.max(hourMetrics.width, minMetrics.width) / minMetrics.width); @@ -90,8 +98,7 @@ StyledRect { } Loader { - Layout.topMargin: -parent.spacing - 4 - Layout.alignment: Qt.AlignHCenter + Layout.alignment: Qt.AlignVCenter asynchronous: true active: GlobalConfig.services.useTwelveHourClock visible: active diff --git a/modules/bar/components/StatusIcons.qml b/modules/bar/components/StatusIcons.qml index 539a07f2..1a025fbd 100644 --- a/modules/bar/components/StatusIcons.qml +++ b/modules/bar/components/StatusIcons.qml @@ -20,16 +20,13 @@ StyledRect { radius: Tokens.rounding.full clip: true - implicitWidth: Tokens.sizes.bar.innerWidth - implicitHeight: iconColumn.implicitHeight + Tokens.padding.medium * 2 - (Config.bar.status.showLockStatus && !Hypr.capsLock && !Hypr.numLock ? iconColumn.spacing : 0) + implicitHeight: Tokens.sizes.bar.innerWidth + implicitWidth: iconColumn.implicitWidth + Tokens.padding.medium * 2 - (Config.bar.status.showLockStatus && !Hypr.capsLock && !Hypr.numLock ? iconColumn.spacing : 0) - ColumnLayout { + RowLayout { id: iconColumn - anchors.left: parent.left - anchors.right: parent.right - anchors.bottom: parent.bottom - anchors.bottomMargin: Tokens.padding.medium + anchors.centerIn: parent spacing: Tokens.spacing.medium / 2 @@ -261,7 +258,7 @@ StyledRect { required property string name asynchronous: true - Layout.alignment: Qt.AlignHCenter + Layout.alignment: Qt.AlignVCenter visible: active } } diff --git a/modules/bar/components/Tray.qml b/modules/bar/components/Tray.qml index 4545d554..f31c2dea 100644 --- a/modules/bar/components/Tray.qml +++ b/modules/bar/components/Tray.qml @@ -19,27 +19,27 @@ StyledRect { property bool expanded - readonly property real nonAnimHeight: { + readonly property real nonAnimWidth: { if (!Config.bar.tray.compact) - return layout.implicitHeight + padding * 2; - return (expanded ? expandIcon.implicitHeight + layout.implicitHeight + spacing : expandIcon.implicitHeight) + padding * 2; + return layout.implicitWidth + padding * 2; + return (expanded ? expandIcon.implicitWidth + layout.implicitWidth + spacing : expandIcon.implicitWidth) + padding * 2; } clip: true - visible: height > 0 + visible: width > 0 - implicitWidth: Tokens.sizes.bar.innerWidth - implicitHeight: nonAnimHeight + implicitHeight: Tokens.sizes.bar.innerWidth + implicitWidth: nonAnimWidth color: Qt.alpha(Colours.tPalette.m3surfaceContainer, (Config.bar.tray.background && items.count > 0) ? Colours.tPalette.m3surfaceContainer.a : 0) radius: Tokens.rounding.full - Column { + Row { id: layout - anchors.horizontalCenter: parent.horizontalCenter - anchors.top: parent.top - anchors.topMargin: root.padding + anchors.verticalCenter: parent.verticalCenter + anchors.left: parent.left + anchors.leftMargin: root.padding spacing: Tokens.spacing.small opacity: root.expanded || !Config.bar.tray.compact ? 1 : 0 @@ -86,37 +86,37 @@ StyledRect { asynchronous: true - anchors.horizontalCenter: parent.horizontalCenter - anchors.bottom: parent.bottom + anchors.verticalCenter: parent.verticalCenter + anchors.right: parent.right active: Config.bar.tray.compact && items.count > 0 sourceComponent: Item { - implicitWidth: expandIconInner.implicitWidth - implicitHeight: expandIconInner.implicitHeight - Tokens.padding.small + implicitHeight: expandIconInner.implicitHeight + implicitWidth: expandIconInner.implicitWidth - Tokens.padding.small MaterialIcon { id: expandIconInner - anchors.horizontalCenter: parent.horizontalCenter - anchors.bottom: parent.bottom - anchors.bottomMargin: Config.bar.tray.background ? Tokens.padding.extraSmall : -Tokens.padding.extraSmall + anchors.verticalCenter: parent.verticalCenter + anchors.right: parent.right + anchors.rightMargin: Config.bar.tray.background ? Tokens.padding.extraSmall : -Tokens.padding.extraSmall text: "expand_less" fontStyle: Tokens.font.icon.large - rotation: root.expanded ? 180 : 0 + rotation: root.expanded ? 270 : 90 Behavior on rotation { Anim {} } - Behavior on anchors.bottomMargin { + Behavior on anchors.rightMargin { Anim {} } } } } - Behavior on implicitHeight { + Behavior on implicitWidth { Anim {} } } diff --git a/modules/bar/components/workspaces/Workspace.qml b/modules/bar/components/workspaces/Workspace.qml index 42ac844e..3afa4f65 100644 --- a/modules/bar/components/workspaces/Workspace.qml +++ b/modules/bar/components/workspaces/Workspace.qml @@ -24,7 +24,7 @@ ColumnLayout { readonly property bool isOccupied: occupied[ws] ?? false readonly property bool hasWindows: isOccupied && Config.bar.workspaces.showWindows - Layout.alignment: Qt.AlignHCenter + Layout.alignment: Qt.AlignVCenter Layout.preferredHeight: size spacing: 0 diff --git a/modules/bar/components/workspaces/Workspaces.qml b/modules/bar/components/workspaces/Workspaces.qml index 2120aef9..2e506a3e 100644 --- a/modules/bar/components/workspaces/Workspaces.qml +++ b/modules/bar/components/workspaces/Workspaces.qml @@ -27,8 +27,8 @@ StyledClippingRect { property real blur: onSpecial ? 1 : 0 - implicitWidth: Tokens.sizes.bar.innerWidth - implicitHeight: layout.implicitHeight + Tokens.padding.small + implicitHeight: Tokens.sizes.bar.innerWidth + implicitWidth: layout.implicitWidth + Tokens.padding.small color: Colours.tPalette.m3surfaceContainer radius: Tokens.rounding.full @@ -60,7 +60,7 @@ StyledClippingRect { } } - ColumnLayout { + RowLayout { id: layout anchors.centerIn: parent @@ -81,7 +81,7 @@ StyledClippingRect { Loader { asynchronous: true - anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter active: Config.bar.workspaces.activeIndicator sourceComponent: ActiveIndicator { diff --git a/modules/drawers/ContentWindow.qml b/modules/drawers/ContentWindow.qml index d2865fff..e6d60cad 100644 --- a/modules/drawers/ContentWindow.qml +++ b/modules/drawers/ContentWindow.qml @@ -85,14 +85,14 @@ StyledWindow { Region { id: emptyRegion - x: panels.notifications.x + bar.implicitWidth - y: panels.notifications.y + root.borderThickness + x: panels.notifications.x + root.borderThickness + y: panels.notifications.y + bar.implicitHeight width: panels.notifications.width height: panels.notifications.height Region { x: root.width - width - y: panels.osdWrapper.y + root.borderThickness + y: panels.osdWrapper.y + bar.implicitHeight width: panels.osdWrapper.width * (1 - panels.osd.offsetScale) + root.borderThickness height: panels.osd.height } @@ -155,9 +155,9 @@ StyledWindow { anchors.margins: -50 // Make border thicker to smooth out bulge from closed drawers group: blobGroup radius: root.borderRounding - borderLeft: bar.implicitWidth - anchors.margins - root.sdfBorderOffset + borderLeft: root.borderThickness - anchors.margins - root.sdfBorderOffset borderRight: root.borderThickness - anchors.margins - root.sdfBorderOffset - borderTop: root.borderThickness - anchors.margins - root.sdfBorderOffset + borderTop: bar.implicitHeight - anchors.margins - root.sdfBorderOffset borderBottom: root.borderThickness - anchors.margins - root.sdfBorderOffset } @@ -180,7 +180,7 @@ StyledWindow { panel: panels.sessionWrapper deformAmount: 0.2 - x: panels.sessionWrapper.x + panels.session.x + bar.implicitWidth + x: panels.sessionWrapper.x + panels.session.x + root.borderThickness implicitWidth: panels.session.width } @@ -199,7 +199,7 @@ StyledWindow { panel: panels.osdWrapper deformAmount: 0.25 - x: panels.osdWrapper.x + panels.osd.x + bar.implicitWidth + x: panels.osdWrapper.x + panels.osd.x + root.borderThickness implicitWidth: panels.osd.width } @@ -226,7 +226,7 @@ StyledWindow { panel: panels.popoutsWrapper deformAmount: panels.popouts.isDetached ? 0.05 : panels.popouts.hasCurrent ? 0.15 : 0.1 - x: panels.popoutsWrapper.x + panels.popouts.x + bar.implicitWidth - panels.popouts.width * extraWidth + x: panels.popoutsWrapper.x + panels.popouts.x + root.borderThickness - panels.popouts.width * extraWidth implicitWidth: panels.popouts.width * (1 + extraWidth) Behavior on extraWidth { @@ -292,8 +292,9 @@ StyledWindow { BarWrapper { id: bar + anchors.left: parent.left + anchors.right: parent.right anchors.top: parent.top - anchors.bottom: parent.bottom screen: root.screen visibilities: visibilities @@ -310,8 +311,8 @@ StyledWindow { property real deformAmount: 0.15 group: blobGroup - x: panel.x + bar.implicitWidth - y: panel.y + root.borderThickness + x: panel.x + root.borderThickness + y: panel.y + bar.implicitHeight implicitWidth: panel.width implicitHeight: panel.height radius: Tokens.rounding.extraLarge diff --git a/modules/drawers/Exclusions.qml b/modules/drawers/Exclusions.qml index fe72730c..4005613c 100644 --- a/modules/drawers/Exclusions.qml +++ b/modules/drawers/Exclusions.qml @@ -14,11 +14,11 @@ Scope { ExclusionZone { anchors.left: true - exclusiveZone: root.bar.exclusiveZone } ExclusionZone { anchors.top: true + exclusiveZone: root.bar.exclusiveZone } ExclusionZone { diff --git a/modules/drawers/Interactions.qml b/modules/drawers/Interactions.qml index b89cb007..50193615 100644 --- a/modules/drawers/Interactions.qml +++ b/modules/drawers/Interactions.qml @@ -23,27 +23,29 @@ CustomMouseArea { property bool osdShortcutActive property bool utilitiesShortcutActive + // NoSignal top bar: the bar's thickness now insets the TOP, so panel Y-origins + // are offset by bar.implicitHeight; the left inset is just the border thickness. function withinPanelHeight(panel: Item, x: real, y: real): bool { - const panelY = root.borderThickness + panel.y; + const panelY = root.bar.implicitHeight + panel.y; return y >= panelY - Config.border.rounding && y <= panelY + panel.height + Config.border.rounding; } function withinPanelWidth(panel: Item, x: real, y: real): bool { - const panelX = bar.implicitWidth + panel.x; + const panelX = root.borderThickness + panel.x; return x >= panelX - Config.border.rounding && x <= panelX + panel.width + Config.border.rounding; } function inLeftPanel(panel: Item, x: real, y: real): bool { - return x < bar.implicitWidth + panel.x + panel.width && withinPanelHeight(panel, x, y); + return x < root.borderThickness + panel.x + panel.width && withinPanelHeight(panel, x, y); } function inRightPanel(panel: Item, x: real, y: real): bool { - return x > Math.min(width - Config.border.minThickness, bar.implicitWidth + panel.x) && withinPanelHeight(panel, x, y); + return x > Math.min(width - Config.border.minThickness, root.borderThickness + panel.x) && withinPanelHeight(panel, x, y); } function inTopPanel(panel: Item, x: real, y: real): bool { const panelHeight = panel.height * (1 - (panel.offsetScale ?? 0)); // qmllint disable missing-property - return y < Math.max(Config.border.minThickness, Config.border.thickness + panelHeight) && withinPanelWidth(panel, x, y); + return y < Math.max(Config.border.minThickness, root.bar.implicitHeight + panelHeight) && withinPanelWidth(panel, x, y); } function inBottomPanel(panel: Item, x: real, y: real, isCorner = false): bool { @@ -54,8 +56,8 @@ CustomMouseArea { function onWheel(event: WheelEvent): void { if (fullscreen) return; - if (event.x < bar.implicitWidth) { - bar.handleWheel(event.y, event.angleDelta); + if (event.y < bar.implicitHeight) { + bar.handleWheel(event.x, event.angleDelta); } } @@ -102,15 +104,15 @@ CustomMouseArea { return; } - // Show bar in non-exclusive mode on hover - if (!visibilities.bar && Config.bar.showOnHover && x < bar.clampedWidth) + // Show bar in non-exclusive mode on hover (top edge) + if (!visibilities.bar && Config.bar.showOnHover && y < bar.clampedHeight) bar.isHovered = true; - // Show/hide bar on drag - if (pressed && dragStart.x < bar.clampedWidth) { - if (dragX > Config.bar.dragThreshold) + // Show/hide bar on drag (vertical, from the top edge) + if (pressed && dragStart.y < bar.clampedHeight) { + if (dragY > Config.bar.dragThreshold) visibilities.bar = true; - else if (dragX < -Config.bar.dragThreshold) + else if (dragY < -Config.bar.dragThreshold) visibilities.bar = false; } @@ -128,7 +130,7 @@ CustomMouseArea { root.panels.osd.hovered = true; } - const showSidebar = pressed && dragStart.x > Math.min(width - Config.border.minThickness, bar.implicitWidth + panels.sidebar.x); + const showSidebar = pressed && dragStart.x > Math.min(width - Config.border.minThickness, root.borderThickness + panels.sidebar.x); // Show/hide session on drag if (pressed && inRightPanel(panels.sessionWrapper, dragStart.x, dragStart.y) && withinPanelHeight(panels.sessionWrapper, x, y)) { @@ -213,9 +215,9 @@ CustomMouseArea { utilitiesShortcutActive = false; } - // Show popouts on hover - if (x < bar.implicitWidth) { - bar.checkPopout(y); + // Show popouts on hover (top bar) + if (y < bar.implicitHeight) { + bar.checkPopout(x); } else if ((!popouts.currentName.startsWith("traymenu") || ((popouts.current as StackView)?.depth ?? 0) <= 1) && !inLeftPanel(panels.popoutsWrapper, x, y)) { popouts.hasCurrent = false; bar.closeTray(); diff --git a/modules/drawers/Panels.qml b/modules/drawers/Panels.qml index eaeb4538..1f104de0 100644 --- a/modules/drawers/Panels.qml +++ b/modules/drawers/Panels.qml @@ -36,7 +36,7 @@ Item { anchors.fill: parent anchors.margins: borderThickness - anchors.leftMargin: bar.implicitWidth + anchors.topMargin: bar.implicitHeight Item { id: osdWrapper diff --git a/modules/drawers/Regions.qml b/modules/drawers/Regions.qml index 47ad0680..06491a3b 100644 --- a/modules/drawers/Regions.qml +++ b/modules/drawers/Regions.qml @@ -15,10 +15,10 @@ Region { readonly property real borderThickness: win.contentItem.Config.border.thickness readonly property real clampedThickness: win.contentItem.Config.border.clampedThickness - x: bar.clampedWidth + win.dragMaskPadding - y: clampedThickness + win.dragMaskPadding - width: win.width - bar.clampedWidth - clampedThickness - win.dragMaskPadding * 2 - height: win.height - clampedThickness * 2 - win.dragMaskPadding * 2 + x: clampedThickness + win.dragMaskPadding + y: bar.clampedHeight + win.dragMaskPadding + width: win.width - clampedThickness * 2 - win.dragMaskPadding * 2 + height: win.height - bar.clampedHeight - clampedThickness - win.dragMaskPadding * 2 intersection: Intersection.Xor R { @@ -75,8 +75,8 @@ Region { component R: Region { required property Item panel - x: panel.x + root.bar.implicitWidth - y: panel.y + root.borderThickness + x: panel.x + root.borderThickness + y: panel.y + root.bar.implicitHeight width: panel.width height: panel.height intersection: Intersection.Subtract