Bar: Improve centering by computing pixel perfect coordinates. All basic widgets + workspace.

This commit is contained in:
Lemmy
2025-12-29 22:08:48 -05:00
parent b991feaff0
commit 50685937da
5 changed files with 71 additions and 58 deletions
+6 -1
View File
@@ -90,7 +90,7 @@ Singleton {
let h;
switch (Settings.data.bar.density) {
case "mini":
h = (Settings.data.bar.position === "left" || Settings.data.bar.position === "right") ? 22 : 20;
h = (Settings.data.bar.position === "left" || Settings.data.bar.position === "right") ? 23 : 21;
break;
case "compact":
h = (Settings.data.bar.position === "left" || Settings.data.bar.position === "right") ? 27 : 25;
@@ -136,4 +136,9 @@ Singleton {
function toOdd(n) {
return Math.floor(n / 2) * 2 + 1;
}
// Ensures a number is always even (rounds down to nearest even)
function toEven(n) {
return Math.floor(n / 2) * 2;
}
}
+6 -6
View File
@@ -211,7 +211,7 @@ Item {
// Top section (left widgets)
ColumnLayout {
anchors.horizontalCenter: parent.horizontalCenter
x: Style.pixelAlignCenter(parent.width, width)
anchors.top: parent.top
anchors.topMargin: Style.marginM
spacing: Style.marginS
@@ -238,7 +238,7 @@ Item {
// Center section (center widgets)
ColumnLayout {
anchors.horizontalCenter: parent.horizontalCenter
x: Style.pixelAlignCenter(parent.width, width)
anchors.verticalCenter: parent.verticalCenter
spacing: Style.marginS
@@ -264,7 +264,7 @@ Item {
// Bottom section (right widgets)
ColumnLayout {
anchors.horizontalCenter: parent.horizontalCenter
x: Style.pixelAlignCenter(parent.width, width)
anchors.bottom: parent.bottom
anchors.bottomMargin: Style.marginM
spacing: Style.marginS
@@ -304,7 +304,7 @@ Item {
objectName: "leftSection"
anchors.left: parent.left
anchors.leftMargin: Style.marginS
anchors.verticalCenter: parent.verticalCenter
y: Style.pixelAlignCenter(parent.height, height)
spacing: Style.marginS
Repeater {
@@ -332,7 +332,7 @@ Item {
id: centerSection
objectName: "centerSection"
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
y: Style.pixelAlignCenter(parent.height, height)
spacing: Style.marginS
Repeater {
@@ -361,7 +361,7 @@ Item {
objectName: "rightSection"
anchors.right: parent.right
anchors.rightMargin: Style.marginS
anchors.verticalCenter: parent.verticalCenter
y: Style.pixelAlignCenter(parent.height, height)
spacing: Style.marginS
Repeater {
+22 -25
View File
@@ -58,7 +58,7 @@ Item {
readonly property real groupedBorderOpacity: (widgetSettings.groupedBorderOpacity !== undefined) ? widgetSettings.groupedBorderOpacity : widgetMetadata.groupedBorderOpacity
readonly property bool enableScrollWheel: (widgetSettings.enableScrollWheel !== undefined) ? widgetSettings.enableScrollWheel : widgetMetadata.enableScrollWheel
readonly property int itemSize: Math.round(Style.capsuleHeight * 0.8)
readonly property int itemSize: Style.toOdd(Style.capsuleHeight * 0.8)
// Context menu state for grouped mode - store IDs instead of object references to avoid stale references
property string selectedWindowId: ""
@@ -123,13 +123,13 @@ Item {
const textWidth = displayText.length * (d * 0.4); // Approximate width per character
const padding = d * 0.6;
return Math.round(Math.max(d * factor, textWidth + padding));
return Style.toOdd(Math.max(d * factor, textWidth + padding));
}
function getWorkspaceHeight(ws) {
const d = Math.round(Style.capsuleHeight * root.baseDimensionRatio);
const factor = ws.isActive ? 2.2 : 1;
return Math.round(d * factor);
return Style.toOdd(d * factor);
}
function computeWidth() {
@@ -140,7 +140,7 @@ Item {
}
total += Math.max(localWorkspaces.count - 1, 0) * spacingBetweenPills;
total += horizontalPadding * 2;
return Math.round(total);
return Style.toOdd(total);
}
function computeHeight() {
@@ -151,7 +151,7 @@ Item {
}
total += Math.max(localWorkspaces.count - 1, 0) * spacingBetweenPills;
total += horizontalPadding * 2;
return Math.round(total);
return Style.toOdd(total);
}
function getFocusedLocalIndex() {
@@ -410,8 +410,8 @@ Item {
border.color: Style.capsuleBorderColor
border.width: Style.capsuleBorderWidth
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
x: isVertical ? Style.pixelAlignCenter(parent.width, width) : 0
y: isVertical ? 0 : Style.pixelAlignCenter(parent.height, height)
MouseArea {
anchors.fill: parent
@@ -473,8 +473,8 @@ Item {
Row {
id: pillRow
spacing: spacingBetweenPills
anchors.verticalCenter: workspaceBackground.verticalCenter
x: horizontalPadding
y: workspaceBackground.y + Style.pixelAlignCenter(workspaceBackground.height, height)
visible: !isVertical && !showApplications
Repeater {
@@ -483,7 +483,7 @@ Item {
Item {
id: workspacePillContainer
width: root.getWorkspaceWidth(model)
height: Style.capsuleHeight * root.baseDimensionRatio
height: Style.toOdd(Style.capsuleHeight * root.baseDimensionRatio)
Rectangle {
id: pill
@@ -493,8 +493,8 @@ Item {
active: (labelMode !== "none") && (!root.showLabelsOnlyWhenOccupied || model.isOccupied || model.isFocused)
sourceComponent: Component {
NText {
x: (pill.width - width) / 2
y: (pill.height - height) / 2 + (height - contentHeight) / 2
x: Style.pixelAlignCenter(pill.width, width)
y: Style.pixelAlignCenter(pill.height, height)
text: {
if (model.name && model.name.length > 0) {
if (root.labelMode === "name") {
@@ -621,7 +621,7 @@ Item {
Column {
id: pillColumn
spacing: spacingBetweenPills
anchors.horizontalCenter: workspaceBackground.horizontalCenter
x: workspaceBackground.x + Style.pixelAlignCenter(workspaceBackground.width, width)
y: horizontalPadding
visible: isVertical && !showApplications
@@ -630,7 +630,7 @@ Item {
model: localWorkspaces
Item {
id: workspacePillContainerVertical
width: Style.capsuleHeight * root.baseDimensionRatio
width: Style.toOdd(Style.capsuleHeight * root.baseDimensionRatio)
height: root.getWorkspaceHeight(model)
Rectangle {
@@ -641,8 +641,8 @@ Item {
active: (labelMode !== "none") && (!root.showLabelsOnlyWhenOccupied || model.isOccupied || model.isFocused)
sourceComponent: Component {
NText {
x: (pillVertical.width - width) / 2
y: (pillVertical.height - height) / 2 + (height - contentHeight) / 2
x: Style.pixelAlignCenter(pillVertical.width, width)
y: Style.pixelAlignCenter(pillVertical.height, height)
text: {
if (model.name && model.name.length > 0) {
if (root.labelMode === "name") {
@@ -779,8 +779,8 @@ Item {
property var workspaceModel: model
property bool hasWindows: (workspaceModel?.windows?.count ?? 0) > 0
width: (hasWindows ? groupedIconsFlow.implicitWidth : root.itemSize) + (root.isVertical ? Style.marginXS : Style.marginXL)
height: (hasWindows ? groupedIconsFlow.implicitHeight : root.itemSize) + (root.isVertical ? Style.marginL : Style.marginXS)
width: Style.toOdd((hasWindows ? groupedIconsFlow.implicitWidth : root.itemSize) + (root.isVertical ? Style.marginXS : Style.marginXL))
height: Style.toOdd((hasWindows ? groupedIconsFlow.implicitHeight : root.itemSize) + (root.isVertical ? Style.marginL : Style.marginXS))
color: Style.capsuleColor
radius: Style.radiusS
border.color: Settings.data.bar.showOutline ? Style.capsuleBorderColor : Qt.alpha((workspaceModel.isFocused ? Color.mPrimary : Color.mOutline), root.groupedBorderOpacity)
@@ -812,7 +812,8 @@ Item {
Flow {
id: groupedIconsFlow
anchors.centerIn: parent
x: Style.pixelAlignCenter(parent.width, width)
y: Style.pixelAlignCenter(parent.height, height)
spacing: 4
flow: root.isVertical ? Flow.TopToBottom : Flow.LeftToRight
@@ -1019,15 +1020,11 @@ Item {
id: groupedGrid
visible: showApplications
anchors.verticalCenter: isVertical ? undefined : parent.verticalCenter
anchors.left: isVertical ? undefined : parent.left
anchors.leftMargin: isVertical ? 0 : Style.marginM
anchors.horizontalCenter: isVertical ? parent.horizontalCenter : undefined
anchors.top: isVertical ? parent.top : undefined
anchors.topMargin: isVertical ? Style.marginM : 0
x: root.isVertical ? Style.pixelAlignCenter(parent.width, width) : Style.marginM
y: root.isVertical ? Style.marginM : Style.pixelAlignCenter(parent.height, height)
spacing: Style.marginS
flow: isVertical ? Flow.TopToBottom : Flow.LeftToRight
flow: root.isVertical ? Flow.TopToBottom : Flow.LeftToRight
Repeater {
model: showApplications ? localWorkspaces : null
+6 -7
View File
@@ -294,25 +294,24 @@ PanelWindow {
readonly property string barPosition: Settings.data.bar.position || "top"
readonly property bool barIsVertical: barPosition === "left" || barPosition === "right"
readonly property bool barFloating: Settings.data.bar.floating || false
readonly property real barMarginH: barFloating ? Math.ceil(Settings.data.bar.marginHorizontal * Style.marginXL) : 0
readonly property real barMarginV: barFloating ? Math.ceil(Settings.data.bar.marginVertical * Style.marginXL) : 0
readonly property real attachmentOverlap: 1 // Attachment overlap to fix hairline gap with fractional scaling
readonly property real barMarginH: barFloating ? Math.floor(Settings.data.bar.marginHorizontal * Style.marginXL) : 0
readonly property real barMarginV: barFloating ? Math.floor(Settings.data.bar.marginVertical * Style.marginXL) : 0
// Expose bar dimensions directly on this Item for BarBackground
// Use screen dimensions directly
x: {
if (barPosition === "right")
return screen.width - Style.barHeight - barMarginH - attachmentOverlap; // Extend left towards panels
return screen.width - Style.barHeight - barMarginH;
return barMarginH;
}
y: {
if (barPosition === "bottom")
return screen.height - Style.barHeight - barMarginV - attachmentOverlap;
return screen.height - Style.barHeight - barMarginV;
return barMarginV;
}
width: {
if (barIsVertical) {
return Style.barHeight + attachmentOverlap;
return Style.barHeight;
}
return screen.width - barMarginH * 2;
}
@@ -320,7 +319,7 @@ PanelWindow {
if (barIsVertical) {
return screen.height - barMarginV * 2;
}
return Style.barHeight + attachmentOverlap;
return Style.barHeight;
}
// Corner states (same as Bar.qml)
+31 -19
View File
@@ -93,6 +93,7 @@ Item {
readonly property bool barFloating: Settings.data.bar.floating
readonly property real barMarginH: barFloating ? Math.ceil(Settings.data.bar.marginHorizontal * Style.marginXL) : 0
readonly property real barMarginV: barFloating ? Math.ceil(Settings.data.bar.marginVertical * Style.marginXL) : 0
readonly property real attachmentOverlap: 1 // Panel extends 1px into bar area to fix hairline gap with fractional scaling
// Check if bar should be visible on this screen
readonly property bool barShouldShow: {
@@ -306,12 +307,13 @@ Item {
// For vertical bars
if (panelContent.allowAttach) {
// Attached panels: align with bar edge (left or right side)
// Subtract attachmentOverlap to extend panel 1px into bar area
if (root.barPosition === "left") {
var leftBarEdge = root.barMarginH + Style.barHeight;
var leftBarEdge = root.barMarginH + Style.barHeight - root.attachmentOverlap;
calculatedX = leftBarEdge;
} else {
// right
var rightBarEdge = root.width - root.barMarginH - Style.barHeight;
var rightBarEdge = root.width - root.barMarginH - Style.barHeight + root.attachmentOverlap;
calculatedX = rightBarEdge - panelWidth;
}
} else {
@@ -365,7 +367,8 @@ Item {
if (root.effectivePanelAnchorRight) {
// Attached: snap to edge/bar
if (root.barIsVertical && root.barPosition === "right") {
var rightBarEdge = root.width - root.barMarginH - Style.barHeight;
// Add attachmentOverlap to extend panel 1px into bar area
var rightBarEdge = root.width - root.barMarginH - Style.barHeight + root.attachmentOverlap;
calculatedX = rightBarEdge - panelWidth;
} else {
var panelOnSameEdgeAsBar = (root.barPosition === "top" && root.effectivePanelAnchorTop) || (root.barPosition === "bottom" && root.effectivePanelAnchorBottom);
@@ -385,7 +388,8 @@ Item {
if (root.effectivePanelAnchorLeft) {
// Attached: snap to edge/bar
if (root.barIsVertical && root.barPosition === "left") {
var leftBarEdge = root.barMarginH + Style.barHeight;
// Subtract attachmentOverlap to extend panel 1px into bar area
var leftBarEdge = root.barMarginH + Style.barHeight - root.attachmentOverlap;
calculatedX = leftBarEdge;
} else {
var panelOnSameEdgeAsBar = (root.barPosition === "top" && root.effectivePanelAnchorTop) || (root.barPosition === "bottom" && root.effectivePanelAnchorBottom);
@@ -404,12 +408,12 @@ Item {
// No explicit anchor: attach to bar if allowAttach, otherwise center
if (root.barIsVertical) {
if (panelContent.allowAttach) {
// Attach to the bar edge
// Attach to the bar edge (with overlap into bar area)
if (root.barPosition === "left") {
var leftBarEdge = root.barMarginH + Style.barHeight;
var leftBarEdge = root.barMarginH + Style.barHeight - root.attachmentOverlap;
calculatedX = leftBarEdge;
} else {
var rightBarEdge = root.width - root.barMarginH - Style.barHeight;
var rightBarEdge = root.width - root.barMarginH - Style.barHeight + root.attachmentOverlap;
calculatedX = rightBarEdge - panelWidth;
}
} else {
@@ -466,14 +470,16 @@ Item {
if (root.barPosition === "top") {
var topBarEdge = root.barMarginV + Style.barHeight;
if (panelContent.allowAttach) {
calculatedY = topBarEdge;
// Subtract attachmentOverlap to extend panel 1px into bar area
calculatedY = topBarEdge - root.attachmentOverlap;
} else {
calculatedY = topBarEdge + Style.marginM;
}
} else if (root.barPosition === "bottom") {
var bottomBarEdge = root.height - root.barMarginV - Style.barHeight;
if (panelContent.allowAttach) {
calculatedY = bottomBarEdge - panelHeight;
// Add attachmentOverlap to extend panel 1px into bar area
calculatedY = bottomBarEdge - panelHeight + root.attachmentOverlap;
} else {
calculatedY = bottomBarEdge - panelHeight - Style.marginM;
}
@@ -501,14 +507,18 @@ Item {
}
} else {
if (root.effectivePanelAnchorTop && root.barPosition === "top") {
calculatedY = root.barMarginV + Style.barHeight;
// Subtract attachmentOverlap to extend panel 1px into bar area
calculatedY = root.barMarginV + Style.barHeight - root.attachmentOverlap;
} else if (root.effectivePanelAnchorBottom && root.barPosition === "bottom") {
calculatedY = root.height - root.barMarginV - Style.barHeight - panelHeight;
// Add attachmentOverlap to extend panel 1px into bar area
calculatedY = root.height - root.barMarginV - Style.barHeight - panelHeight + root.attachmentOverlap;
} else if (!root.hasExplicitVerticalAnchor) {
if (root.barPosition === "top") {
calculatedY = root.barMarginV + Style.barHeight;
// Subtract attachmentOverlap to extend panel 1px into bar area
calculatedY = root.barMarginV + Style.barHeight - root.attachmentOverlap;
} else if (root.barPosition === "bottom") {
calculatedY = root.height - root.barMarginV - Style.barHeight - panelHeight;
// Add attachmentOverlap to extend panel 1px into bar area
calculatedY = root.height - root.barMarginV - Style.barHeight - panelHeight + root.attachmentOverlap;
}
}
}
@@ -532,8 +542,8 @@ Item {
} else if (root.panelAnchorTop) {
// Use raw panelAnchorTop for positioning decision
if (root.effectivePanelAnchorTop) {
// Attached: snap to edge/bar
calculatedY = root.barPosition === "top" ? root.barMarginV + Style.barHeight : 0;
// Attached: snap to edge/bar (with overlap into bar area)
calculatedY = root.barPosition === "top" ? root.barMarginV + Style.barHeight - root.attachmentOverlap : 0;
} else {
// Not attached: position at top with margin
var topBarOffset = (root.barPosition === "top") ? barOffset : 0;
@@ -542,8 +552,8 @@ Item {
} else if (root.panelAnchorBottom) {
// Use raw panelAnchorBottom for positioning decision
if (root.effectivePanelAnchorBottom) {
// Attached: snap to edge/bar
calculatedY = root.barPosition === "bottom" ? root.height - root.barMarginV - Style.barHeight - panelHeight : root.height - panelHeight;
// Attached: snap to edge/bar (with overlap into bar area)
calculatedY = root.barPosition === "bottom" ? root.height - root.barMarginV - Style.barHeight - panelHeight + root.attachmentOverlap : root.height - panelHeight;
} else {
// Not attached: position at bottom with margin
var bottomBarOffset = (root.barPosition === "bottom") ? barOffset : 0;
@@ -563,9 +573,11 @@ Item {
} else {
if (panelContent.allowAttach && !root.barIsVertical) {
if (root.barPosition === "top") {
calculatedY = root.barMarginV + Style.barHeight;
// Subtract attachmentOverlap to extend panel 1px into bar area
calculatedY = root.barMarginV + Style.barHeight - root.attachmentOverlap;
} else if (root.barPosition === "bottom") {
calculatedY = root.height - root.barMarginV - Style.barHeight - panelHeight;
// Add attachmentOverlap to extend panel 1px into bar area
calculatedY = root.height - root.barMarginV - Style.barHeight - panelHeight + root.attachmentOverlap;
}
} else {
if (root.barPosition === "top") {