feat: convert bar margins from percentages to pixels

Change bar margin settings from percentage values (0-1) to integer pixel values (0-18). Add migration 38 to convert existing settings. Update all margin calculations to use pixel values directly. Update UI labels to show "px" instead of "%".
This commit is contained in:
anthonyhab
2026-01-07 11:25:43 -05:00
parent 247b1cc8a2
commit f34dcc11b9
17 changed files with 66 additions and 37 deletions
+2 -2
View File
@@ -10,8 +10,8 @@
"backgroundOpacity": 0.93,
"useSeparateOpacity": false,
"floating": false,
"marginVertical": 0.25,
"marginHorizontal": 0.25,
"marginVertical": 4,
"marginHorizontal": 4,
"outerCorners": true,
"exclusive": true,
"widgets": {
+27
View File
@@ -0,0 +1,27 @@
import QtQuick
import qs.Commons
QtObject {
function migrate(adapter, logger, rawJson) {
logger.i("Migration38", "Migrating bar margins from percentages to integers");
// Use rawJson to read original values, adapter to write new values (following migration patterns)
const rawVertical = rawJson?.bar?.marginVertical;
const rawHorizontal = rawJson?.bar?.marginHorizontal;
// Only migrate if values exist and are percentages (<= 1.0)
if (rawVertical !== undefined && typeof rawVertical === 'number' && rawVertical <= 1.0) {
const marginXL = 18; // Standard value of Style.marginXL
adapter.bar.marginVertical = Math.round(rawVertical * marginXL);
logger.d("Migration38", "Converted marginVertical from " + rawVertical + " to " + adapter.bar.marginVertical + "px");
}
if (rawHorizontal !== undefined && typeof rawHorizontal === 'number' && rawHorizontal <= 1.0) {
const marginXL = 18; // Standard value of Style.marginXL
adapter.bar.marginHorizontal = Math.round(rawHorizontal * marginXL);
logger.d("Migration38", "Converted marginHorizontal from " + rawHorizontal + " to " + adapter.bar.marginHorizontal + "px");
}
return true;
}
}
+3 -1
View File
@@ -13,7 +13,8 @@ QtObject {
33: migration33Component,
35: migration35Component,
36: migration36Component,
37: migration37Component
37: migration37Component,
38: migration38Component
})
// Migration components
@@ -24,4 +25,5 @@ QtObject {
property Component migration35Component: Migration35 {}
property Component migration36Component: Migration36 {}
property Component migration37Component: Migration37 {}
property Component migration38Component: Migration38 {}
}
+3 -3
View File
@@ -25,7 +25,7 @@ Singleton {
- Default cache directory: ~/.cache/noctalia
*/
readonly property alias data: adapter // Used to access via Settings.data.xxx.yyy
readonly property int settingsVersion: 37
readonly property int settingsVersion: 38
readonly property bool isDebug: Quickshell.env("NOCTALIA_DEBUG") === "1"
readonly property string shellName: "noctalia"
readonly property string configDir: Quickshell.env("NOCTALIA_CONFIG_DIR") || (Quickshell.env("XDG_CONFIG_HOME") || Quickshell.env("HOME") + "/.config") + "/" + shellName + "/"
@@ -201,8 +201,8 @@ Singleton {
// Floating bar settings
property bool floating: false
property real marginVertical: 0.25
property real marginHorizontal: 0.25
property int marginVertical: 4
property int marginHorizontal: 4
// Bar outer corners (inverted/concave corners at bar edges when not floating)
property bool outerCorners: true
+2 -2
View File
@@ -17,8 +17,8 @@ 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 ? Settings.data.bar.marginHorizontal * Style.marginXL : 0
readonly property real barMarginV: barFloating ? Settings.data.bar.marginVertical * Style.marginXL : 0
readonly property real barMarginH: barFloating ? Settings.data.bar.marginHorizontal : 0
readonly property real barMarginV: barFloating ? Settings.data.bar.marginVertical : 0
// Invisible - just reserves space
color: "transparent"
+1 -1
View File
@@ -49,7 +49,7 @@ Rectangle {
if (!screen || isVerticalBar || !smartWidth || maxTaskbarWidthPercent <= 0)
return 0;
var barFloating = Settings.data.bar.floating || false;
var barMarginH = barFloating ? Math.ceil(Settings.data.bar.marginHorizontal * Style.marginXL) : 0;
var barMarginH = barFloating ? Math.ceil(Settings.data.bar.marginHorizontal) : 0;
var availableWidth = screen.width - (barMarginH * 2);
return Math.round(availableWidth * (maxTaskbarWidthPercent / 100));
}
+2 -2
View File
@@ -313,13 +313,13 @@ Variants {
readonly property int barOffsetTop: {
if (barPos !== "top")
return Style.marginM;
const floatMarginV = barFloating ? Math.ceil(Settings.data.bar.marginVertical * Style.marginXL) : 0;
const floatMarginV = barFloating ? Math.ceil(Settings.data.bar.marginVertical) : 0;
return Style.barHeight + floatMarginV + Style.marginM;
}
readonly property int barOffsetRight: {
if (barPos !== "right")
return Style.marginM;
const floatMarginH = barFloating ? Math.ceil(Settings.data.bar.marginHorizontal * Style.marginXL) : 0;
const floatMarginH = barFloating ? Math.ceil(Settings.data.bar.marginHorizontal) : 0;
return Style.barHeight + floatMarginH + Style.marginM;
}
+1 -1
View File
@@ -358,7 +358,7 @@ Loader {
margins.bottom: {
switch (Settings.data.bar.position) {
case "bottom":
return (Style.barHeight + Style.marginM) + (Settings.data.bar.floating ? Settings.data.bar.marginVertical * Style.marginXL + floatingMargin : floatingMargin);
return (Style.barHeight + Style.marginM) + (Settings.data.bar.floating ? Settings.data.bar.marginVertical + floatingMargin : floatingMargin);
default:
return floatingMargin;
}
+2 -2
View File
@@ -33,8 +33,8 @@ 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: Math.ceil(barFloating ? Settings.data.bar.marginHorizontal * Style.marginXL : 0)
readonly property real barMarginV: Math.ceil(barFloating ? Settings.data.bar.marginVertical * Style.marginXL : 0)
readonly property real barMarginH: Math.ceil(barFloating ? Settings.data.bar.marginHorizontal : 0)
readonly property real barMarginV: Math.ceil(barFloating ? Settings.data.bar.marginVertical : 0)
// Anchor to the bar's edge
anchors {
+2 -2
View File
@@ -17,8 +17,8 @@ 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 barMarginH: barFloating ? Math.ceil(Settings.data.bar.marginHorizontal) : 0
readonly property real barMarginV: barFloating ? Math.ceil(Settings.data.bar.marginVertical) : 0
readonly property real fractOffset: CompositorService.getDisplayScale(screen?.name) % 1.0
// Invisible - just reserves space
+2 -2
View File
@@ -324,8 +324,8 @@ 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.floor(Settings.data.bar.marginHorizontal * Style.marginXL) : 0
readonly property real barMarginV: barFloating ? Math.floor(Settings.data.bar.marginVertical * Style.marginXL) : 0
readonly property real barMarginH: barFloating ? Math.floor(Settings.data.bar.marginHorizontal) : 0
readonly property real barMarginV: barFloating ? Math.floor(Settings.data.bar.marginVertical) : 0
// Expose bar dimensions directly on this Item for BarBackground
// Use screen dimensions directly
+2 -2
View File
@@ -91,8 +91,8 @@ Item {
readonly property string barPosition: Settings.data.bar.position
readonly property bool barIsVertical: barPosition === "left" || barPosition === "right"
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 barMarginH: barFloating ? Math.ceil(Settings.data.bar.marginHorizontal) : 0
readonly property real barMarginV: barFloating ? Math.ceil(Settings.data.bar.marginVertical) : 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
+4 -4
View File
@@ -86,28 +86,28 @@ Variants {
readonly property int barOffsetTop: {
if (barPos !== "top")
return 0;
const floatMarginV = isFloating ? Math.ceil(Settings.data.bar.marginVertical * Style.marginXL) : 0;
const floatMarginV = isFloating ? Math.ceil(Settings.data.bar.marginVertical) : 0;
return Style.barHeight + floatMarginV;
}
readonly property int barOffsetBottom: {
if (barPos !== "bottom")
return 0;
const floatMarginV = isFloating ? Math.ceil(Settings.data.bar.marginVertical * Style.marginXL) : 0;
const floatMarginV = isFloating ? Math.ceil(Settings.data.bar.marginVertical) : 0;
return Style.barHeight + floatMarginV;
}
readonly property int barOffsetLeft: {
if (barPos !== "left")
return 0;
const floatMarginH = isFloating ? Math.ceil(Settings.data.bar.marginHorizontal * Style.marginXL) : 0;
const floatMarginH = isFloating ? Math.ceil(Settings.data.bar.marginHorizontal) : 0;
return Style.barHeight + floatMarginH;
}
readonly property int barOffsetRight: {
if (barPos !== "right")
return 0;
const floatMarginH = isFloating ? Math.ceil(Settings.data.bar.marginHorizontal * Style.marginXL) : 0;
const floatMarginH = isFloating ? Math.ceil(Settings.data.bar.marginHorizontal) : 0;
return Style.barHeight + floatMarginH;
}
+1 -1
View File
@@ -510,7 +510,7 @@ Variants {
let base = Style.marginM;
if (Settings.data.bar.position === position) {
const isVertical = position === "top" || position === "bottom";
const floatExtra = Math.ceil(Settings.data.bar.floating ? (isVertical ? Settings.data.bar.marginVertical : Settings.data.bar.marginHorizontal) * Style.marginXL : 0);
const floatExtra = Math.ceil(Settings.data.bar.floating ? (isVertical ? Settings.data.bar.marginVertical : Settings.data.bar.marginHorizontal) : 0);
return Style.barHeight + base + floatExtra;
}
return base;
+2 -2
View File
@@ -21,8 +21,8 @@ SmartPanel {
readonly property string barDensity: Settings.data.bar.density
readonly property string barPosition: Settings.data.bar.position
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 barMarginH: barFloating ? Math.ceil(Settings.data.bar.marginHorizontal) : 0
readonly property real barMarginV: barFloating ? Math.ceil(Settings.data.bar.marginVertical) : 0
forceAttachToBar: attachToBar
panelAnchorHorizontalCenter: attachToBar ? (barPosition === "top" || barPosition === "bottom") : true
@@ -168,12 +168,12 @@ ColumnLayout {
Layout.fillWidth: true
label: I18n.tr("panels.bar.appearance-margins-vertical")
from: 0
to: 1
stepSize: 0.01
to: 18
stepSize: 1
value: Settings.data.bar.marginVertical
defaultValue: Settings.getDefaultValue("bar.marginVertical")
onMoved: value => Settings.data.bar.marginVertical = value
text: Math.round(Settings.data.bar.marginVertical * 100) + "%"
text: Settings.data.bar.marginVertical + "px"
}
}
@@ -184,12 +184,12 @@ ColumnLayout {
Layout.fillWidth: true
label: I18n.tr("panels.bar.appearance-margins-horizontal")
from: 0
to: 1
stepSize: 0.01
to: 18
stepSize: 1
value: Settings.data.bar.marginHorizontal
defaultValue: Settings.getDefaultValue("bar.marginHorizontal")
onMoved: value => Settings.data.bar.marginHorizontal = value
text: Math.ceil(Settings.data.bar.marginHorizontal * 100) + "%"
text: Settings.data.bar.marginHorizontal + "px"
}
}
}
+4 -4
View File
@@ -150,28 +150,28 @@ Item {
readonly property int barOffsetTop: {
if (barPos !== "top")
return 0;
const floatMarginV = isFloating ? Math.ceil(Settings.data.bar.marginVertical * Style.marginXL) : 0;
const floatMarginV = isFloating ? Math.ceil(Settings.data.bar.marginVertical) : 0;
return Style.barHeight + floatMarginV;
}
readonly property int barOffsetBottom: {
if (barPos !== "bottom")
return 0;
const floatMarginV = isFloating ? Math.ceil(Settings.data.bar.marginVertical * Style.marginXL) : 0;
const floatMarginV = isFloating ? Math.ceil(Settings.data.bar.marginVertical) : 0;
return Style.barHeight + floatMarginV;
}
readonly property int barOffsetLeft: {
if (barPos !== "left")
return 0;
const floatMarginH = isFloating ? Math.ceil(Settings.data.bar.marginHorizontal * Style.marginXL) : 0;
const floatMarginH = isFloating ? Math.ceil(Settings.data.bar.marginHorizontal) : 0;
return Style.barHeight + floatMarginH;
}
readonly property int barOffsetRight: {
if (barPos !== "right")
return 0;
const floatMarginH = isFloating ? Math.ceil(Settings.data.bar.marginHorizontal * Style.marginXL) : 0;
const floatMarginH = isFloating ? Math.ceil(Settings.data.bar.marginHorizontal) : 0;
return Style.barHeight + floatMarginH;
}