refactor(dock): restore launcher removal in apps dock widget, unify config & visual effects options

This commit is contained in:
purian23 committed 2026-10-13 18:22:45 -04:00
1 parent 39b41fb880
commit c18d989fc5
14 files changed
+228 -87

No files matched your search

+1 -1
View File
@@ -23,7 +23,7 @@ Singleton {
id: root
readonly property var log: Log.scoped("SettingsData")
readonly property int settingsConfigVersion: 41
readonly property int settingsConfigVersion: 42
readonly property bool isGreeterMode: Quickshell.env("DMS_RUN_GREETER") === "1" || Quickshell.env("DMS_RUN_GREETER") === "true"
@@ -151,6 +151,13 @@ var DEFAULTS = {
barMaxVisibleApps: 0,
barMaxVisibleRunningApps: 0,
barShowOverflowBadge: true,
launcherEnabled: false,
launcherLogoMode: "os",
launcherLogoCustomPath: "",
launcherLogoColorOverride: "",
launcherLogoSizeOffset: 0,
launcherLogoBrightness: 0.5,
launcherLogoContrast: 1,
runningAppsCompactMode: true,
runningAppsCurrentWorkspace: true,
appsDockHideIndicators: true,
@@ -747,9 +747,36 @@ function migrateToVersion(obj, targetVersion) {
settings.configVersion = 41;
}
if (currentVersion < 42 && targetVersion >= 42) {
migrateDockAppsSizing(settings);
settings.configVersion = 42;
}
return settings;
}
// v42: dock apps follow the dock's icon size and magnification instead of their own copies
function migrateDockAppsSizing(settings) {
if (!Array.isArray(settings.dockConfigs))
return;
for (const dock of settings.dockConfigs) {
for (const widget of Array.isArray(dock?.widgets) ? dock.widgets : []) {
if (!widget || typeof widget !== "object")
continue;
if (widget.appsDockEnlargeOnHover === true && dock.magnification !== true) {
dock.magnification = true;
dock.magnificationScale = Math.max(105, Math.min(160, Number(widget.appsDockEnlargePercentage) || 125));
}
const percentage = Number(widget.appsDockIconSizePercentage);
if (percentage > 0 && percentage !== 100)
dock.iconSize = Math.round((Number(dock.iconSize) || DockConfig.create("", "").iconSize) * percentage / 100);
delete widget.appsDockEnlargeOnHover;
delete widget.appsDockEnlargePercentage;
delete widget.appsDockIconSizePercentage;
}
}
}
// v41: footer entries became a grid row under the rest, keeping their order and widths
function migrateControlCenterFooter(settings) {
delete settings.controlCenterFooterPosition;
+11 -4
View File
@@ -30,7 +30,16 @@ BasePill {
itemSpacing: appOption("appsDockSpacing", 4),
maxVisibleApps: appOption("barMaxVisibleApps", defaults.maxVisibleApps),
maxVisibleRunningApps: appOption("barMaxVisibleRunningApps", defaults.maxVisibleRunningApps),
showOverflowBadge: appOption("barShowOverflowBadge", defaults.showOverflowBadge)
showOverflowBadge: appOption("barShowOverflowBadge", defaults.showOverflowBadge),
launcherEnabled: appOption("launcherEnabled"),
launcherLogoMode: appOption("launcherLogoMode"),
launcherLogoCustomPath: appOption("launcherLogoCustomPath"),
launcherLogoColorOverride: appOption("launcherLogoColorOverride"),
launcherLogoSizeOffset: appOption("launcherLogoSizeOffset"),
launcherLogoBrightness: appOption("launcherLogoBrightness"),
launcherLogoContrast: appOption("launcherLogoContrast"),
enlargeOnHover: appOption("appsDockEnlargeOnHover"),
enlargePercentage: appOption("appsDockEnlargePercentage")
});
return Object.assign(options, {
iconSize: Math.min(options.iconSize, surfaceContext?.widgetThickness ?? options.iconSize),
@@ -39,13 +48,11 @@ BasePill {
hideIndicators: appOption("appsDockHideIndicators", false),
colorizeActive: appOption("appsDockColorizeActive", false),
activeColorMode: appOption("appsDockActiveColorMode", "primary"),
enlargeOnHover: appOption("appsDockEnlargeOnHover", false),
enlargePercentage: appOption("appsDockEnlargePercentage", 125),
magnification: dockHosted && (surfaceContext?.config?.magnification ?? false),
magnificationScale: dockHosted ? (surfaceContext?.config?.magnificationScale ?? 130) : 130,
magnificationProfile: dockHosted ? (surfaceContext?.config?.magnificationProfile ?? "parabolic") : "parabolic",
magnificationExpand: dockHosted && (surfaceContext?.config?.magnificationExpand ?? false),
iconSizePercentage: appOption("appsDockIconSizePercentage", 100)
iconSizePercentage: dockHosted ? 100 : appOption("appsDockIconSizePercentage")
});
}
property bool renderItems: true
+1 -1
View File
@@ -447,7 +447,7 @@ Item {
id: iconSlot
anchors.fill: parent
scale: !root.options?.magnification && root.options?.enlargeOnHover && root.isHovered ? (root.options?.enlargePercentage ?? 125) / 100 : 1
scale: root.options?.enlargeOnHover && root.isHovered ? (root.options?.enlargePercentage ?? 125) / 100 : 1
AppIconRenderer {
id: coreIcon
@@ -64,7 +64,7 @@ Item {
anchors.centerIn: parent
width: actualIconSize
height: actualIconSize
scale: !root.options?.magnification && root.options?.enlargeOnHover && root.isHovered ? (root.options?.enlargePercentage ?? 125) / 100 : 1
scale: root.options?.enlargeOnHover && root.isHovered ? (root.options?.enlargePercentage ?? 125) / 100 : 1
LauncherLogo {
anchors.centerIn: parent
+1 -1
View File
@@ -67,7 +67,7 @@ Item {
anchors.centerIn: parent
width: actualIconSize - 4
height: actualIconSize - 4
scale: !root.options?.magnification && root.options?.enlargeOnHover && root.isHovered ? (root.options?.enlargePercentage ?? 125) / 100 : 1
scale: root.options?.enlargeOnHover && root.isHovered ? (root.options?.enlargePercentage ?? 125) / 100 : 1
readonly property string iconPath: Paths.resolveIconPath(TrashService.isEmpty ? "user-trash" : "user-trash-full")
@@ -119,7 +119,6 @@ Column {
SettingsCard {
title: I18n.tr("Launcher button")
settingKey: "dockLauncher"
visible: root.dockHosted
SettingsToggleRow {
text: I18n.tr("Show")
@@ -268,6 +267,7 @@ Column {
SettingsCard {
title: I18n.tr("Visual effects")
settingKey: "barWidgetAppsDockEffects"
visible: !root.dockHosted
SettingsToggleRow {
text: I18n.tr("Indicators")
@@ -275,22 +275,6 @@ Column {
onToggled: checked => root.page.set("appsDockHideIndicators", !checked)
}
SettingsButtonGroupRow {
resetStore: root.apps
resetKeys: ["indicatorStyle"]
text: I18n.tr("Indicator style")
visible: root.dockHosted
enabled: !root.page.value("appsDockHideIndicators")
model: [I18n.tr("Circle", "dock indicator style option"), I18n.tr("Line", "dock indicator style option")]
buttonPadding: Theme.spacingS
currentIndex: root.apps.get("indicatorStyle") === "circle" ? 0 : 1
onSelectionChanged: (index, selected) => {
if (!selected)
return;
root.apps.set("indicatorStyle", index === 0 ? "circle" : "line");
}
}
SettingsToggleRow {
text: I18n.tr("Colorize active")
checked: root.page.value("appsDockColorizeActive")
@@ -310,7 +294,7 @@ Column {
SettingsToggleSliderRow {
resetStore: root.page
valueKeys: ["appsDockEnlargePercentage"]
text: I18n.tr("Enlarge on hover")
text: I18n.tr("Magnification", "dock setting: enlarge icons near the cursor")
checked: root.page.value("appsDockEnlargeOnHover")
value: root.page.value("appsDockEnlargePercentage")
minimum: 100
@@ -336,7 +320,6 @@ Column {
resetStore: root.page
resetKeys: ["appsDockSpacing"]
text: I18n.tr("Spacing")
visible: !root.dockHosted
value: root.page.value("appsDockSpacing")
minimum: 0
maximum: 32
+1 -2
View File
@@ -77,8 +77,7 @@ Item {
}
readonly property var _dockAppsDefaults: ({
"appsDockHideIndicators": false,
"appsDockIconSizePercentage": 100
"appsDockHideIndicators": false
})
function defaultOption(key) {
@@ -135,12 +135,65 @@ Item {
}
}
SettingsControlledBy {
visible: dock.hasConfig && !dock.connectedFrameModeActive
target: "surfaces"
parentModal: root.parentModal
section: "surfaceOpacity_dock_" + dock.selectedDockId
settingLabel: I18n.tr("Opacity")
SettingsCard {
width: parent.width
visible: dock.appsEntry !== null
iconName: "auto_awesome"
title: I18n.tr("Visual effects")
settingKey: "dockVisualEffects"
tags: ["dock", "indicator", "running", "active", "colorize", "highlight"]
SettingsToggleRow {
text: I18n.tr("Indicators")
checked: !dock.appsValue("appsDockHideIndicators")
onToggled: checked => dock.setAppsOption("appsDockHideIndicators", !checked)
}
SettingsButtonGroupRow {
resetStore: dock
resetKeys: ["indicatorStyle"]
text: I18n.tr("Indicator style")
enabled: !dock.appsValue("appsDockHideIndicators")
model: [I18n.tr("Circle", "dock indicator style option"), I18n.tr("Line", "dock indicator style option")]
buttonPadding: Theme.spacingS
currentIndex: dock.config?.indicatorStyle === "circle" ? 0 : 1
onSelectionChanged: (index, selected) => {
if (!selected)
return;
dock.setOption("indicatorStyle", index === 0 ? "circle" : "line");
}
}
SettingsToggleRow {
text: I18n.tr("Colorize active")
checked: dock.appsValue("appsDockColorizeActive")
onToggled: checked => dock.setAppsOption("appsDockColorizeActive", checked)
}
ColorDropdownRow {
resetStore: dock.apps
resetKeys: ["appsDockActiveColorMode"]
text: I18n.tr("Active color")
enabled: dock.appsValue("appsDockColorizeActive")
options: [({
"value": "primary",
"label": I18n.tr("Primary")
}), ({
"value": "secondary",
"label": I18n.tr("Secondary")
}), ({
"value": "primaryContainer",
"label": I18n.tr("Primary Container")
}), ({
"value": "error",
"label": I18n.tr("Error")
}), ({
"value": "success",
"label": I18n.tr("Success", "noun, theme color name in active color dropdown")
})]
currentMode: dock.appsValue("appsDockActiveColorMode")
onModeSelected: mode => dock.setAppsOption("appsDockActiveColorMode", mode)
}
}
SettingsToggleCard {
@@ -193,6 +246,14 @@ Item {
}
}
SettingsControlledBy {
visible: dock.hasConfig && !dock.connectedFrameModeActive
target: "surfaces"
parentModal: root.parentModal
section: "surfaceOpacity_dock_" + dock.selectedDockId
settingLabel: I18n.tr("Opacity")
}
SettingsControlledBy {
visible: dock.connectedFrameModeActive
parentModal: root.parentModal
+11 -32
View File
@@ -13,49 +13,28 @@ Item {
property int catalogRevision: 0
readonly property bool dockHosted: true
readonly property var appsEntry: dock.config?.widgets.find(item => item.widgetId === "appsDock") ?? null
readonly property var appsEntry: dock.appsEntry
readonly property var appStore: ({
"get": key => dock.config?.[key],
"set": (key, value) => dock.setOption(key, value),
"isDefault": keys => dock.isDefault(keys),
"resetToDefault": keys => dock.resetToDefault(keys)
})
readonly property var _dockAppsDefaults: ({
"appsDockHideIndicators": false,
"appsDockIconSizePercentage": 100,
"runningAppsCurrentWorkspace": false
})
function defaultOption(key) {
if (key in _dockAppsDefaults)
return _dockAppsDefaults[key];
return SettingsData.widgetDefaults("appsDock")[key];
}
function value(key) {
if (key in _dockAppsDefaults)
return appsEntry?.[key] ?? _dockAppsDefaults[key];
return SettingsData.widgetOption("appsDock", appsEntry, key);
}
function isDefault(keys) {
return keys.every(key => defaultOption(key) === undefined || JSON.stringify(value(key)) === JSON.stringify(defaultOption(key)));
}
function resetToDefault(keys) {
for (const key of keys) {
const fallback = defaultOption(key);
if (fallback !== undefined)
set(key, fallback);
}
return dock.appsValue(key);
}
function set(key, value) {
if (!appsEntry)
return;
SettingsData.updateDockWidget(dock.selectedDockId, appsEntry.id, {
[key]: value
});
dock.setAppsOption(key, value);
}
function isDefault(keys) {
return dock.apps.isDefault(keys);
}
function resetToDefault(keys) {
dock.apps.resetToDefault(keys);
}
DockSelectionState {
@@ -105,6 +105,39 @@ Item {
return SettingsData.dockAssignmentConflict(selectedDockId, screenPreferences, config.position);
}
// The apps strip keeps its own options on its widget entry rather than on the dock.
readonly property var appsEntry: config?.widgets.find(item => item.widgetId === "appsDock") ?? null
readonly property var _appsDefaults: ({
"appsDockHideIndicators": false,
"runningAppsCurrentWorkspace": false
})
readonly property var apps: ({
"get": key => root.appsValue(key),
"set": (key, value) => root.setAppsOption(key, value),
"isDefault": keys => keys.every(key => root.appsDefault(key) === undefined || JSON.stringify(root.appsValue(key)) === JSON.stringify(root.appsDefault(key))),
"resetToDefault": keys => keys.filter(key => root.appsDefault(key) !== undefined).forEach(key => root.setAppsOption(key, root.appsDefault(key)))
})
function appsDefault(key) {
if (key in _appsDefaults)
return _appsDefaults[key];
return SettingsData.widgetDefaults("appsDock")[key];
}
function appsValue(key) {
if (key in _appsDefaults)
return appsEntry?.[key] ?? _appsDefaults[key];
return SettingsData.widgetOption("appsDock", appsEntry, key);
}
function setAppsOption(key, value) {
if (!appsEntry)
return;
SettingsData.updateDockWidget(selectedDockId, appsEntry.id, {
[key]: value
});
}
function isDefault(keys) {
if (!config)
return true;
@@ -0,0 +1,31 @@
import assert from "node:assert/strict";
import test from "node:test";
import { loadScript } from "./qml-script.mjs";
const store = loadScript(new URL("../Common/settings/SettingsStore.js", import.meta.url));
function migrate(dock, widget) {
const settings = { configVersion: 41, dockConfigs: [Object.assign({ id: "dock", widgets: [Object.assign({ id: "dock_apps", widgetId: "appsDock" }, widget)] }, dock)] };
return JSON.parse(JSON.stringify(store.migrateToVersion(settings, 42))).dockConfigs[0];
}
test("dock apps sizing folds into the dock and the widget copies are dropped", () => {
const cases = [
{ dock: {}, widget: { appsDockEnlargeOnHover: true, appsDockEnlargePercentage: 140 }, magnification: true, scale: 140 },
{ dock: {}, widget: { appsDockEnlargeOnHover: true, appsDockEnlargePercentage: 100 }, magnification: true, scale: 105 },
{ dock: { magnification: true, magnificationScale: 150 }, widget: { appsDockEnlargeOnHover: true, appsDockEnlargePercentage: 110 }, magnification: true, scale: 150 },
{ dock: { magnification: false, magnificationScale: 130 }, widget: { appsDockEnlargeOnHover: false, appsDockEnlargePercentage: 140 }, magnification: false, scale: 130 },
{ dock: { iconSize: 40 }, widget: { appsDockIconSizePercentage: 150 }, iconSize: 60 },
{ dock: { iconSize: 48 }, widget: { appsDockIconSizePercentage: 100 }, iconSize: 48 }
];
for (const { dock, widget, magnification, scale, iconSize } of cases) {
const migrated = migrate(dock, widget);
if (magnification !== undefined) {
assert.equal(migrated.magnification === true, magnification);
assert.equal(migrated.magnificationScale, scale);
}
if (iconSize !== undefined)
assert.equal(migrated.iconSize, iconSize);
assert.deepEqual(migrated.widgets, [{ id: "dock_apps", widgetId: "appsDock" }]);
}
});
@@ -9753,7 +9753,7 @@
"parentLabel": "Power & battery"
},
{
"section": "barWidgetOption:AppsDockOptions.qml:24",
"section": "barWidgetOption:AppsDockOptions.qml:23",
"label": "Active color",
"tabIndex": 22,
"keywords": [],
@@ -9936,7 +9936,7 @@
"optionFile": "LauncherButtonOptions.qml"
},
{
"section": "barWidgetOption:AppsDockOptions.qml:23",
"section": "barWidgetOption:AppsDockOptions.qml:22",
"label": "Colorize active",
"tabIndex": 22,
"keywords": [],
@@ -10103,14 +10103,6 @@
"runtimeType": "barWidgetOption",
"optionFile": "WorkspaceSwitcherOptions.qml"
},
{
"section": "barWidgetOption:AppsDockOptions.qml:25",
"label": "Enlarge on hover",
"tabIndex": 22,
"keywords": [],
"runtimeType": "barWidgetOption",
"optionFile": "AppsDockOptions.qml"
},
{
"section": "barWidgetOption:IslandOptions.qml:28",
"label": "Expand by default",
@@ -10256,7 +10248,7 @@
"optionFile": "LauncherButtonOptions.qml"
},
{
"section": "barWidgetOption:AppsDockOptions.qml:26",
"section": "barWidgetOption:AppsDockOptions.qml:25",
"label": "Icon size",
"tabIndex": 22,
"keywords": [],
@@ -10287,14 +10279,6 @@
"runtimeType": "barWidgetOption",
"optionFile": "WorkspaceSwitcherOptions.qml"
},
{
"section": "barWidgetOption:AppsDockOptions.qml:22",
"label": "Indicator style",
"tabIndex": 22,
"keywords": [],
"runtimeType": "barWidgetOption",
"optionFile": "AppsDockOptions.qml"
},
{
"section": "barWidgetOption:AppsDockOptions.qml:21",
"label": "Indicators",
@@ -10351,6 +10335,14 @@
"runtimeType": "barWidgetOption",
"optionFile": "MusicOptions.qml"
},
{
"section": "barWidgetOption:AppsDockOptions.qml:24",
"label": "Magnification",
"tabIndex": 22,
"keywords": [],
"runtimeType": "barWidgetOption",
"optionFile": "AppsDockOptions.qml"
},
{
"section": "barWidgetOption:WorkspaceSwitcherOptions.qml:8",
"label": "Max apps to show",
@@ -10736,7 +10728,7 @@
"optionFile": "SystemUpdateOptions.qml"
},
{
"section": "barWidgetOption:AppsDockOptions.qml:27",
"section": "barWidgetOption:AppsDockOptions.qml:26",
"label": "Spacing",
"tabIndex": 22,
"keywords": [],
@@ -17044,6 +17036,28 @@
],
"parentLabel": "Dock"
},
{
"section": "dockVisualEffects",
"label": "Visual effects",
"tabIndex": 58,
"category": "Appearance",
"keywords": [
"active",
"appearance",
"colorize",
"dock",
"effects",
"highlight",
"indicator",
"launcher bar",
"panel",
"running",
"taskbar",
"visual"
],
"parentLabel": "Dock",
"icon": "auto_awesome"
},
{
"section": "_tab_59",
"label": "Advanced",