adds overview, removes old stuff
This commit is contained in:
@@ -0,0 +1,360 @@
|
||||
pragma Singleton
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import Quickshell.Io
|
||||
import "functions"
|
||||
import "." as Common
|
||||
import ".."
|
||||
|
||||
Singleton {
|
||||
id: root
|
||||
property string colorSource: Common.Config.options.appearance.colorSource
|
||||
property string caelestiaAccentProfile: Common.Config.options.appearance.caelestia.accentProfile
|
||||
property string lastCaelestiaPayload: ""
|
||||
property QtObject m3colors: {
|
||||
if (colorSource === "matugen" && matugenLoader.item)
|
||||
return matugenLoader.item;
|
||||
if (colorSource === "caelestia" && caelestiaPaletteLoaded)
|
||||
return caelestiaColors;
|
||||
return defaultColors;
|
||||
}
|
||||
property QtObject animation
|
||||
property QtObject animationCurves
|
||||
property QtObject colors
|
||||
property QtObject rounding
|
||||
property QtObject font
|
||||
property QtObject sizes
|
||||
property bool caelestiaPaletteLoaded: false
|
||||
|
||||
Loader {
|
||||
id: matugenLoader
|
||||
active: root.colorSource === "matugen"
|
||||
source: "Appearance.colors.qml"
|
||||
}
|
||||
|
||||
// Retuned to pull from this shell's own wallust palette (Theme/Colors) instead of the
|
||||
// upstream stock M3 purple palette, so the overview matches the bar's look. See
|
||||
// ../modules/overview/CREDITS.md.
|
||||
property QtObject defaultColors: QtObject {
|
||||
property bool darkmode: true
|
||||
property color m3primary: Theme.wsActive
|
||||
property color m3onPrimary: Colors.background
|
||||
property color m3primaryContainer: ColorUtils.mix(Theme.wsActive, Colors.background, 0.35)
|
||||
property color m3onPrimaryContainer: Colors.foreground
|
||||
property color m3secondary: Theme.wsActive
|
||||
property color m3onSecondary: Colors.background
|
||||
property color m3secondaryContainer: ColorUtils.mix(Theme.wsActive, Colors.background, 0.55)
|
||||
property color m3onSecondaryContainer: Colors.foreground
|
||||
property color m3background: Colors.background
|
||||
property color m3onBackground: Colors.foreground
|
||||
property color m3surface: Colors.background
|
||||
property color m3surfaceContainerLow: ColorUtils.mix(Colors.foreground, Colors.background, 0.06)
|
||||
property color m3surfaceContainer: ColorUtils.mix(Colors.foreground, Colors.background, 0.10)
|
||||
property color m3surfaceContainerHigh: ColorUtils.mix(Colors.foreground, Colors.background, 0.15)
|
||||
property color m3surfaceContainerHighest: ColorUtils.mix(Colors.foreground, Colors.background, 0.20)
|
||||
property color m3onSurface: Colors.foreground
|
||||
property color m3surfaceVariant: ColorUtils.mix(Colors.foreground, Colors.background, 0.25)
|
||||
property color m3onSurfaceVariant: Colors.foreground
|
||||
property color m3inverseSurface: Colors.foreground
|
||||
property color m3inverseOnSurface: Colors.background
|
||||
property color m3outline: Colors.color8
|
||||
property color m3outlineVariant: ColorUtils.mix(Colors.foreground, Colors.background, 0.30)
|
||||
property color m3shadow: "#000000"
|
||||
}
|
||||
|
||||
property QtObject caelestiaColors: QtObject {
|
||||
property bool darkmode: defaultColors.darkmode
|
||||
property color m3primary: defaultColors.m3primary
|
||||
property color m3onPrimary: defaultColors.m3onPrimary
|
||||
property color m3primaryContainer: defaultColors.m3primaryContainer
|
||||
property color m3onPrimaryContainer: defaultColors.m3onPrimaryContainer
|
||||
property color m3secondary: defaultColors.m3secondary
|
||||
property color m3onSecondary: defaultColors.m3onSecondary
|
||||
property color m3secondaryContainer: defaultColors.m3secondaryContainer
|
||||
property color m3onSecondaryContainer: defaultColors.m3onSecondaryContainer
|
||||
property color m3background: defaultColors.m3background
|
||||
property color m3onBackground: defaultColors.m3onBackground
|
||||
property color m3surface: defaultColors.m3surface
|
||||
property color m3surfaceContainerLow: defaultColors.m3surfaceContainerLow
|
||||
property color m3surfaceContainer: defaultColors.m3surfaceContainer
|
||||
property color m3surfaceContainerHigh: defaultColors.m3surfaceContainerHigh
|
||||
property color m3surfaceContainerHighest: defaultColors.m3surfaceContainerHighest
|
||||
property color m3onSurface: defaultColors.m3onSurface
|
||||
property color m3surfaceVariant: defaultColors.m3surfaceVariant
|
||||
property color m3onSurfaceVariant: defaultColors.m3onSurfaceVariant
|
||||
property color m3inverseSurface: defaultColors.m3inverseSurface
|
||||
property color m3inverseOnSurface: defaultColors.m3inverseOnSurface
|
||||
property color m3outline: defaultColors.m3outline
|
||||
property color m3outlineVariant: defaultColors.m3outlineVariant
|
||||
property color m3shadow: defaultColors.m3shadow
|
||||
}
|
||||
|
||||
function loadCaelestiaPalette() {
|
||||
getCaelestiaScheme.running = true;
|
||||
}
|
||||
|
||||
function relativeLuminance(color) {
|
||||
const c = Qt.color(color);
|
||||
function channel(v) {
|
||||
return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);
|
||||
}
|
||||
return (0.2126 * channel(c.r)) + (0.7152 * channel(c.g)) + (0.0722 * channel(c.b));
|
||||
}
|
||||
|
||||
function bestOnColor(backgroundColor) {
|
||||
return relativeLuminance(backgroundColor) > 0.5 ? "#121212" : "#f5f5f5";
|
||||
}
|
||||
|
||||
function firstColor(palette, keys, fallback) {
|
||||
for (const key of keys) {
|
||||
if (palette[key])
|
||||
return palette[key];
|
||||
}
|
||||
return fallback;
|
||||
}
|
||||
|
||||
function applyCaelestiaPalette(palette, mode) {
|
||||
if (caelestiaAccentProfile === "vibrant") {
|
||||
const primary = firstColor(palette, ["blue", "klink", "term12", "primary"], defaultColors.m3primary);
|
||||
const secondary = firstColor(palette, ["mauve", "lavender", "term13", "secondary"], defaultColors.m3secondary);
|
||||
const tertiary = firstColor(palette, ["pink", "rosewater", "term11", "tertiary"], defaultColors.m3secondaryContainer);
|
||||
const primaryContainer = firstColor(palette, ["sapphire", "klinkSelection", "primaryContainer"], defaultColors.m3primaryContainer);
|
||||
const secondaryContainer = firstColor(palette, ["surface2", "secondaryContainer"], defaultColors.m3secondaryContainer);
|
||||
|
||||
caelestiaColors.m3primary = primary;
|
||||
caelestiaColors.m3onPrimary = bestOnColor(primary);
|
||||
caelestiaColors.m3primaryContainer = primaryContainer;
|
||||
caelestiaColors.m3onPrimaryContainer = bestOnColor(primaryContainer);
|
||||
caelestiaColors.m3secondary = secondary;
|
||||
caelestiaColors.m3onSecondary = bestOnColor(secondary);
|
||||
caelestiaColors.m3secondaryContainer = secondaryContainer;
|
||||
caelestiaColors.m3onSecondaryContainer = bestOnColor(secondaryContainer);
|
||||
// Preserve a stronger accent presence across UI mixes.
|
||||
caelestiaColors.m3surfaceVariant = firstColor(palette, ["surface1", "surfaceVariant"], defaultColors.m3surfaceVariant);
|
||||
caelestiaColors.m3outline = firstColor(palette, ["overlay2", "outline"], defaultColors.m3outline);
|
||||
caelestiaColors.m3outlineVariant = firstColor(palette, ["overlay0", "outlineVariant"], defaultColors.m3outlineVariant);
|
||||
if (tertiary)
|
||||
caelestiaColors.m3secondaryContainer = ColorUtils.mix(secondaryContainer, tertiary, 0.7);
|
||||
} else {
|
||||
const map = {
|
||||
"primary": "m3primary",
|
||||
"onPrimary": "m3onPrimary",
|
||||
"primaryContainer": "m3primaryContainer",
|
||||
"onPrimaryContainer": "m3onPrimaryContainer",
|
||||
"secondary": "m3secondary",
|
||||
"onSecondary": "m3onSecondary",
|
||||
"secondaryContainer": "m3secondaryContainer",
|
||||
"onSecondaryContainer": "m3onSecondaryContainer",
|
||||
"surfaceVariant": "m3surfaceVariant",
|
||||
"outline": "m3outline",
|
||||
"outlineVariant": "m3outlineVariant"
|
||||
};
|
||||
for (const key in map) {
|
||||
if (palette[key])
|
||||
caelestiaColors[map[key]] = palette[key];
|
||||
}
|
||||
}
|
||||
|
||||
// Keep foundational tones from Material keys for readability.
|
||||
const baseMap = {
|
||||
"background": "m3background",
|
||||
"onBackground": "m3onBackground",
|
||||
"surface": "m3surface",
|
||||
"surfaceContainerLow": "m3surfaceContainerLow",
|
||||
"surfaceContainer": "m3surfaceContainer",
|
||||
"surfaceContainerHigh": "m3surfaceContainerHigh",
|
||||
"surfaceContainerHighest": "m3surfaceContainerHighest",
|
||||
"onSurface": "m3onSurface",
|
||||
"inverseSurface": "m3inverseSurface",
|
||||
"inverseOnSurface": "m3inverseOnSurface",
|
||||
"shadow": "m3shadow"
|
||||
};
|
||||
for (const key in baseMap) {
|
||||
if (palette[key])
|
||||
caelestiaColors[baseMap[key]] = palette[key];
|
||||
}
|
||||
|
||||
if (palette["onSurfaceVariant"])
|
||||
caelestiaColors.m3onSurfaceVariant = palette["onSurfaceVariant"];
|
||||
|
||||
if (mode === "light")
|
||||
caelestiaColors.darkmode = false;
|
||||
else if (mode === "dark")
|
||||
caelestiaColors.darkmode = true;
|
||||
}
|
||||
|
||||
Process {
|
||||
id: getCaelestiaScheme
|
||||
command: ["sh", "-lc", "caelestia scheme get 2>/dev/null || true"]
|
||||
stdout: StdioCollector {
|
||||
id: caelestiaCollector
|
||||
onStreamFinished: {
|
||||
const text = caelestiaCollector.text;
|
||||
if (!text || !text.trim()) {
|
||||
root.caelestiaPaletteLoaded = false;
|
||||
return;
|
||||
}
|
||||
|
||||
const ansiPattern = /\x1b\[[0-9;]*m/g;
|
||||
const lines = text.split("\n");
|
||||
let mode = "";
|
||||
const palette = ({});
|
||||
|
||||
for (const rawLine of lines) {
|
||||
const line = rawLine.replace(ansiPattern, "").trim();
|
||||
|
||||
if (line.startsWith("Mode:")) {
|
||||
mode = line.split(":")[1]?.trim()?.toLowerCase() ?? "";
|
||||
continue;
|
||||
}
|
||||
|
||||
const match = line.match(/^([A-Za-z0-9_]+):\s*.*?([0-9a-fA-F]{6})$/);
|
||||
if (!match)
|
||||
continue;
|
||||
|
||||
palette[match[1]] = `#${match[2]}`;
|
||||
}
|
||||
|
||||
const normalized = JSON.stringify({ mode: mode, palette: palette, profile: caelestiaAccentProfile });
|
||||
if (normalized === root.lastCaelestiaPayload)
|
||||
return;
|
||||
|
||||
root.lastCaelestiaPayload = normalized;
|
||||
applyCaelestiaPalette(palette, mode);
|
||||
root.caelestiaPaletteLoaded = Object.keys(palette).length > 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: caelestiaRefreshTimer
|
||||
interval: Math.max(500, Common.Config.options.appearance.caelestia.refreshInterval)
|
||||
running: root.colorSource === "caelestia" && Common.Config.options.appearance.caelestia.autoRefresh
|
||||
repeat: true
|
||||
triggeredOnStart: false
|
||||
onTriggered: root.loadCaelestiaPalette()
|
||||
}
|
||||
|
||||
onColorSourceChanged: {
|
||||
if (colorSource === "caelestia")
|
||||
loadCaelestiaPalette();
|
||||
}
|
||||
|
||||
onCaelestiaAccentProfileChanged: {
|
||||
if (colorSource === "caelestia") {
|
||||
root.lastCaelestiaPayload = "";
|
||||
loadCaelestiaPalette();
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
if (colorSource === "caelestia")
|
||||
loadCaelestiaPalette();
|
||||
}
|
||||
|
||||
colors: QtObject {
|
||||
property color colSubtext: m3colors.m3outline
|
||||
property color colLayer0: m3colors.m3background
|
||||
property color colOnLayer0: m3colors.m3onBackground
|
||||
property color colLayer0Border: ColorUtils.mix(root.m3colors.m3outlineVariant, colLayer0, 0.4)
|
||||
property color colLayer1: m3colors.m3surfaceContainerLow
|
||||
property color colOnLayer1: m3colors.m3onSurfaceVariant
|
||||
property color colOnLayer1Inactive: ColorUtils.mix(colOnLayer1, colLayer1, 0.45)
|
||||
property color colLayer1Hover: ColorUtils.mix(colLayer1, colOnLayer1, 0.92)
|
||||
property color colLayer1Active: ColorUtils.mix(colLayer1, colOnLayer1, 0.85)
|
||||
property color colLayer2: m3colors.m3surfaceContainer
|
||||
property color colOnLayer2: m3colors.m3onSurface
|
||||
property color colLayer2Hover: ColorUtils.mix(colLayer2, colOnLayer2, 0.90)
|
||||
property color colLayer2Active: ColorUtils.mix(colLayer2, colOnLayer2, 0.80)
|
||||
property color colPrimary: m3colors.m3primary
|
||||
property color colOnPrimary: m3colors.m3onPrimary
|
||||
property color colSecondary: m3colors.m3secondary
|
||||
property color colSecondaryContainer: m3colors.m3secondaryContainer
|
||||
property color colOnSecondaryContainer: m3colors.m3onSecondaryContainer
|
||||
property color colTooltip: m3colors.m3inverseSurface
|
||||
property color colOnTooltip: m3colors.m3inverseOnSurface
|
||||
property color colShadow: ColorUtils.transparentize(m3colors.m3shadow, 0.7)
|
||||
property color colOutline: m3colors.m3outline
|
||||
}
|
||||
|
||||
rounding: QtObject {
|
||||
property int unsharpen: Common.Config.options.appearance.rounding.unsharpen
|
||||
property int verysmall: Common.Config.options.appearance.rounding.verysmall
|
||||
property int small: Common.Config.options.appearance.rounding.small
|
||||
property int normal: Common.Config.options.appearance.rounding.normal
|
||||
property int large: Common.Config.options.appearance.rounding.large
|
||||
property int full: Common.Config.options.appearance.rounding.full
|
||||
property int screenRounding: Common.Config.options.appearance.rounding.screenRounding
|
||||
property int windowRounding: Common.Config.options.appearance.rounding.windowRounding
|
||||
}
|
||||
|
||||
font: QtObject {
|
||||
property QtObject family: QtObject {
|
||||
property string main: Common.Config.options.appearance.font.family.main
|
||||
property string title: Common.Config.options.appearance.font.family.title
|
||||
property string expressive: Common.Config.options.appearance.font.family.expressive
|
||||
}
|
||||
property QtObject pixelSize: QtObject {
|
||||
property int smaller: Common.Config.options.appearance.font.pixelSize.smaller
|
||||
property int small: Common.Config.options.appearance.font.pixelSize.small
|
||||
property int normal: Common.Config.options.appearance.font.pixelSize.normal
|
||||
property int larger: Common.Config.options.appearance.font.pixelSize.larger
|
||||
property int huge: Common.Config.options.appearance.font.pixelSize.huge
|
||||
}
|
||||
}
|
||||
|
||||
animationCurves: QtObject {
|
||||
readonly property list<real> expressiveDefaultSpatial: [0.38, 1.21, 0.22, 1.00, 1, 1]
|
||||
readonly property list<real> expressiveEffects: [0.34, 0.80, 0.34, 1.00, 1, 1]
|
||||
readonly property list<real> emphasizedDecel: [0.05, 0.7, 0.1, 1, 1, 1]
|
||||
readonly property real expressiveDefaultSpatialDuration: Common.Config.options.appearance.animation.duration.elementMove
|
||||
readonly property real expressiveEffectsDuration: Common.Config.options.appearance.animation.duration.elementMoveFast
|
||||
}
|
||||
|
||||
animation: QtObject {
|
||||
property QtObject elementMove: QtObject {
|
||||
property int duration: animationCurves.expressiveDefaultSpatialDuration
|
||||
property int type: Easing.BezierSpline
|
||||
property list<real> bezierCurve: animationCurves.expressiveDefaultSpatial
|
||||
property Component numberAnimation: Component {
|
||||
NumberAnimation {
|
||||
duration: root.animation.elementMove.duration
|
||||
easing.type: root.animation.elementMove.type
|
||||
easing.bezierCurve: root.animation.elementMove.bezierCurve
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
property QtObject elementMoveEnter: QtObject {
|
||||
property int duration: Common.Config.options.appearance.animation.duration.elementMoveEnter
|
||||
property int type: Easing.BezierSpline
|
||||
property list<real> bezierCurve: animationCurves.emphasizedDecel
|
||||
property Component numberAnimation: Component {
|
||||
NumberAnimation {
|
||||
duration: root.animation.elementMoveEnter.duration
|
||||
easing.type: root.animation.elementMoveEnter.type
|
||||
easing.bezierCurve: root.animation.elementMoveEnter.bezierCurve
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
property QtObject elementMoveFast: QtObject {
|
||||
property int duration: animationCurves.expressiveEffectsDuration
|
||||
property int type: Easing.BezierSpline
|
||||
property list<real> bezierCurve: animationCurves.expressiveEffects
|
||||
property Component numberAnimation: Component {
|
||||
NumberAnimation {
|
||||
duration: root.animation.elementMoveFast.duration
|
||||
easing.type: root.animation.elementMoveFast.type
|
||||
easing.bezierCurve: root.animation.elementMoveFast.bezierCurve
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sizes: QtObject {
|
||||
property real elevationMargin: Common.Config.options.appearance.sizes.elevationMargin
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
pragma Singleton
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import Quickshell.Io
|
||||
|
||||
Singleton {
|
||||
id: root
|
||||
|
||||
property var userOptions: ({})
|
||||
|
||||
function read(path, fallback) {
|
||||
const parts = path.split(".");
|
||||
let current = userOptions;
|
||||
|
||||
for (const part of parts) {
|
||||
if (current === null || current === undefined || typeof current !== "object" || !(part in current)) {
|
||||
return fallback;
|
||||
}
|
||||
current = current[part];
|
||||
}
|
||||
|
||||
return current === undefined || current === null ? fallback : current;
|
||||
}
|
||||
|
||||
function readInt(path, fallback) {
|
||||
const value = read(path, fallback);
|
||||
const parsed = Number(value);
|
||||
return Number.isInteger(parsed) ? parsed : fallback;
|
||||
}
|
||||
|
||||
function readReal(path, fallback) {
|
||||
const value = read(path, fallback);
|
||||
const parsed = Number(value);
|
||||
return Number.isFinite(parsed) ? parsed : fallback;
|
||||
}
|
||||
|
||||
function readBool(path, fallback) {
|
||||
const value = read(path, fallback);
|
||||
return typeof value === "boolean" ? value : fallback;
|
||||
}
|
||||
|
||||
function readString(path, fallback) {
|
||||
const value = read(path, fallback);
|
||||
if (typeof value !== "string")
|
||||
return fallback;
|
||||
|
||||
const trimmed = value.trim();
|
||||
return trimmed.length > 0 ? trimmed : fallback;
|
||||
}
|
||||
|
||||
property QtObject options: QtObject {
|
||||
property QtObject appearance: QtObject {
|
||||
property string colorSource: root.readString(
|
||||
"appearance.colorSource",
|
||||
root.readBool("appearance.useMatugenColors", false) ? "matugen" : "default"
|
||||
)
|
||||
property bool useMatugenColors: colorSource === "matugen"
|
||||
property QtObject caelestia: QtObject {
|
||||
property bool autoRefresh: root.readBool("appearance.caelestia.autoRefresh", true)
|
||||
property int refreshInterval: root.readInt("appearance.caelestia.refreshInterval", 2000)
|
||||
property string accentProfile: root.readString("appearance.caelestia.accentProfile", "vibrant")
|
||||
}
|
||||
|
||||
property QtObject rounding: QtObject {
|
||||
property int unsharpen: root.readInt("appearance.rounding.unsharpen", 2)
|
||||
property int verysmall: root.readInt("appearance.rounding.verysmall", 8)
|
||||
property int small: root.readInt("appearance.rounding.small", 12)
|
||||
property int normal: root.readInt("appearance.rounding.normal", 17)
|
||||
property int large: root.readInt("appearance.rounding.large", 23)
|
||||
property int full: root.readInt("appearance.rounding.full", 9999)
|
||||
property int screenRounding: root.readInt("appearance.rounding.screenRounding", large)
|
||||
property int windowRounding: root.readInt("appearance.rounding.windowRounding", 18)
|
||||
}
|
||||
|
||||
property QtObject font: QtObject {
|
||||
property QtObject family: QtObject {
|
||||
property string main: root.readString("appearance.font.family.main", "sans-serif")
|
||||
property string title: root.readString("appearance.font.family.title", "sans-serif")
|
||||
property string expressive: root.readString("appearance.font.family.expressive", "sans-serif")
|
||||
}
|
||||
|
||||
property QtObject pixelSize: QtObject {
|
||||
property int smaller: root.readInt("appearance.font.pixelSize.smaller", 12)
|
||||
property int small: root.readInt("appearance.font.pixelSize.small", 15)
|
||||
property int normal: root.readInt("appearance.font.pixelSize.normal", 16)
|
||||
property int larger: root.readInt("appearance.font.pixelSize.larger", 19)
|
||||
property int huge: root.readInt("appearance.font.pixelSize.huge", 22)
|
||||
}
|
||||
}
|
||||
|
||||
property QtObject animation: QtObject {
|
||||
property QtObject duration: QtObject {
|
||||
property int elementMove: root.readInt("appearance.animation.duration.elementMove", 500)
|
||||
property int elementMoveEnter: root.readInt("appearance.animation.duration.elementMoveEnter", 400)
|
||||
property int elementMoveFast: root.readInt("appearance.animation.duration.elementMoveFast", 200)
|
||||
}
|
||||
}
|
||||
|
||||
property QtObject sizes: QtObject {
|
||||
property real elevationMargin: root.readReal("appearance.sizes.elevationMargin", 10)
|
||||
}
|
||||
}
|
||||
|
||||
property QtObject overview: QtObject {
|
||||
property int rows: root.readInt("overview.rows", 2)
|
||||
property int columns: root.readInt("overview.columns", 5)
|
||||
property real scale: root.readReal("overview.scale", 0.16)
|
||||
property bool enable: root.readBool("overview.enable", true)
|
||||
property bool hideEmptyRows: root.readBool("overview.hideEmptyRows", true)
|
||||
property bool closeOnFocusLoss: root.readBool("overview.closeOnFocusLoss", true)
|
||||
property bool useWorkspaceMap: root.readBool("overview.useWorkspaceMap", false)
|
||||
property var workspaceMap: root.read("overview.workspaceMap", [])
|
||||
property bool orderRightLeft: root.readBool("overview.orderRightLeft", false)
|
||||
property bool orderBottomUp: root.readBool("overview.orderBottomUp", false)
|
||||
property bool previewsEnabled: root.readBool("overview.previewsEnabled", true)
|
||||
property string previewMode: root.readString("overview.previewMode", "live")
|
||||
property bool includeInactiveMonitorPreviews: root.readBool("overview.includeInactiveMonitorPreviews", true)
|
||||
property int previewRecaptureDelayMs: root.readInt("overview.previewRecaptureDelayMs", 60)
|
||||
property bool showSpecialWorkspaces: root.readBool("overview.showSpecialWorkspaces", true)
|
||||
property var specialWorkspaces: root.read("overview.specialWorkspaces", [])
|
||||
property int specialWorkspaceColumns: root.readInt("overview.specialWorkspaceColumns", columns)
|
||||
property string emptyWorkspaceWallpaper: root.readString("overview.emptyWorkspaceWallpaper", "")
|
||||
property string specialEmptyWorkspaceWallpaper: root.readString("overview.specialEmptyWorkspaceWallpaper", "")
|
||||
property real workspaceSpacing: root.readReal("overview.workspaceSpacing", 5)
|
||||
property real backgroundPadding: root.readReal("overview.backgroundPadding", 10)
|
||||
property real workspaceNumberBaseSize: root.readReal("overview.workspaceNumberBaseSize", 250)
|
||||
property QtObject effects: QtObject {
|
||||
property bool enableBackdrop: root.readBool("overview.effects.enableBackdrop", false)
|
||||
property real backdropOpacity: root.readReal("overview.effects.backdropOpacity", 0.28)
|
||||
property real panelOpacity: root.readReal("overview.effects.panelOpacity", 0.92)
|
||||
property real workspaceOpacity: root.readReal("overview.effects.workspaceOpacity", 0.86)
|
||||
property real emptyWorkspaceWallpaperOverlayOpacity: root.readReal("overview.effects.emptyWorkspaceWallpaperOverlayOpacity", 0.18)
|
||||
property real windowOverlayOpacity: root.readReal("overview.effects.windowOverlayOpacity", 0.22)
|
||||
property bool enableBlur: root.readBool("overview.effects.enableBlur", false)
|
||||
property bool glassMode: root.readBool("overview.effects.glassMode", false)
|
||||
property real glassTintStrength: root.readReal("overview.effects.glassTintStrength", 0.35)
|
||||
property real glassBorderOpacity: root.readReal("overview.effects.glassBorderOpacity", 0.72)
|
||||
property real glassShineOpacity: root.readReal("overview.effects.glassShineOpacity", 0.14)
|
||||
}
|
||||
}
|
||||
|
||||
property QtObject position: QtObject {
|
||||
property int topMargin: root.readInt("position.topMargin", 100)
|
||||
}
|
||||
|
||||
property QtObject windowPreview: QtObject {
|
||||
property bool showIcons: root.readBool("windowPreview.showIcons", true)
|
||||
property real iconToWindowRatio: root.readReal("windowPreview.iconToWindowRatio", 0.25)
|
||||
property real iconToWindowRatioCompact: root.readReal("windowPreview.iconToWindowRatioCompact", 0.45)
|
||||
property real xwaylandIndicatorToIconRatio: root.readReal("windowPreview.xwaylandIndicatorToIconRatio", 0.35)
|
||||
property real inactiveMonitorOpacity: root.readReal("windowPreview.inactiveMonitorOpacity", 0.4)
|
||||
property bool cropToFill: root.readBool("windowPreview.cropToFill", false)
|
||||
}
|
||||
|
||||
property QtObject hacks: QtObject {
|
||||
property int arbitraryRaceConditionDelay: root.readInt("hacks.arbitraryRaceConditionDelay", 150)
|
||||
property int hyprlandEventDebounceMs: root.readInt("hacks.hyprlandEventDebounceMs", 40)
|
||||
}
|
||||
}
|
||||
|
||||
Process {
|
||||
id: loadUserConfig
|
||||
command: [
|
||||
"sh",
|
||||
"-lc",
|
||||
"cfg=\"${XDG_CONFIG_HOME:-$HOME/.config}/quickshell/overview/config.json\"; [ -r \"$cfg\" ] && cat \"$cfg\""
|
||||
]
|
||||
stdout: StdioCollector {
|
||||
id: configCollector
|
||||
onStreamFinished: {
|
||||
const payload = configCollector.text.trim();
|
||||
if (!payload)
|
||||
return;
|
||||
|
||||
try {
|
||||
const parsed = JSON.parse(payload);
|
||||
if (typeof parsed === "object" && parsed !== null) {
|
||||
root.userOptions = parsed;
|
||||
} else {
|
||||
console.warn("overview: config.json must contain a JSON object; ignoring file");
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn("overview: failed to parse user config.json; using defaults", error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
loadUserConfig.running = true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
pragma Singleton
|
||||
import Quickshell
|
||||
|
||||
Singleton {
|
||||
id: root
|
||||
|
||||
function colorWithHueOf(color1, color2) {
|
||||
var c1 = Qt.color(color1);
|
||||
var c2 = Qt.color(color2);
|
||||
var hue = c2.hsvHue;
|
||||
var sat = c1.hsvSaturation;
|
||||
var val = c1.hsvValue;
|
||||
var alpha = c1.a;
|
||||
return Qt.hsva(hue, sat, val, alpha);
|
||||
}
|
||||
|
||||
function colorWithSaturationOf(color1, color2) {
|
||||
var c1 = Qt.color(color1);
|
||||
var c2 = Qt.color(color2);
|
||||
var hue = c1.hsvHue;
|
||||
var sat = c2.hsvSaturation;
|
||||
var val = c1.hsvValue;
|
||||
var alpha = c1.a;
|
||||
return Qt.hsva(hue, sat, val, alpha);
|
||||
}
|
||||
|
||||
function colorWithLightness(color, lightness) {
|
||||
var c = Qt.color(color);
|
||||
return Qt.hsla(c.hslHue, c.hslSaturation, lightness, c.a);
|
||||
}
|
||||
|
||||
function colorWithLightnessOf(color1, color2) {
|
||||
var c2 = Qt.color(color2);
|
||||
return colorWithLightness(color1, c2.hslLightness);
|
||||
}
|
||||
|
||||
function adaptToAccent(color1, color2) {
|
||||
var c1 = Qt.color(color1);
|
||||
var c2 = Qt.color(color2);
|
||||
var hue = c2.hslHue;
|
||||
var sat = c2.hslSaturation;
|
||||
var light = c1.hslLightness;
|
||||
var alpha = c1.a;
|
||||
return Qt.hsla(hue, sat, light, alpha);
|
||||
}
|
||||
|
||||
function mix(color1, color2, percentage = 0.5) {
|
||||
var c1 = Qt.color(color1);
|
||||
var c2 = Qt.color(color2);
|
||||
return Qt.rgba(
|
||||
percentage * c1.r + (1 - percentage) * c2.r,
|
||||
percentage * c1.g + (1 - percentage) * c2.g,
|
||||
percentage * c1.b + (1 - percentage) * c2.b,
|
||||
percentage * c1.a + (1 - percentage) * c2.a
|
||||
);
|
||||
}
|
||||
|
||||
function transparentize(color, percentage = 1) {
|
||||
var c = Qt.color(color);
|
||||
return Qt.rgba(c.r, c.g, c.b, c.a * (1 - percentage));
|
||||
}
|
||||
|
||||
function applyAlpha(color, alpha) {
|
||||
var c = Qt.color(color);
|
||||
var a = Math.max(0, Math.min(1, alpha));
|
||||
return Qt.rgba(c.r, c.g, c.b, a);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
singleton ColorUtils 1.0 ColorUtils.qml
|
||||
@@ -0,0 +1,7 @@
|
||||
singleton Appearance 1.0 Appearance.qml
|
||||
singleton Config 1.0 Config.qml
|
||||
singleton ColorUtils 1.0 functions/ColorUtils.qml
|
||||
StyledText 1.0 widgets/StyledText.qml
|
||||
StyledRectangularShadow 1.0 widgets/StyledRectangularShadow.qml
|
||||
StyledToolTip 1.0 widgets/StyledToolTip.qml
|
||||
StyledToolTipContent 1.0 widgets/StyledToolTipContent.qml
|
||||
@@ -0,0 +1,14 @@
|
||||
import QtQuick
|
||||
import QtQuick.Effects
|
||||
import ".."
|
||||
|
||||
RectangularShadow {
|
||||
required property var target
|
||||
anchors.fill: target
|
||||
radius: 20
|
||||
blur: 0.9 * Appearance.sizes.elevationMargin
|
||||
offset: Qt.vector2d(0.0, 1.0)
|
||||
spread: 1
|
||||
color: Appearance.colors.colShadow
|
||||
cached: true
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import QtQuick
|
||||
import ".."
|
||||
|
||||
Text {
|
||||
id: root
|
||||
property bool animateChange: false
|
||||
|
||||
renderType: Text.NativeRendering
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
font {
|
||||
hintingPreference: Font.PreferFullHinting
|
||||
family: Appearance?.font.family.main ?? "sans-serif"
|
||||
pixelSize: Appearance?.font.pixelSize.small ?? 15
|
||||
}
|
||||
color: Appearance?.m3colors.m3onBackground ?? "white"
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import "."
|
||||
|
||||
ToolTip {
|
||||
id: root
|
||||
property bool extraVisibleCondition: true
|
||||
property bool alternativeVisibleCondition: false
|
||||
readonly property bool internalVisibleCondition: (extraVisibleCondition && (parent.hovered === undefined || parent?.hovered)) || alternativeVisibleCondition
|
||||
verticalPadding: 5
|
||||
horizontalPadding: 10
|
||||
background: null
|
||||
|
||||
visible: internalVisibleCondition
|
||||
|
||||
contentItem: StyledToolTipContent {
|
||||
id: contentItem
|
||||
text: root.text
|
||||
shown: root.internalVisibleCondition
|
||||
horizontalPadding: root.horizontalPadding
|
||||
verticalPadding: root.verticalPadding
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
import QtQuick
|
||||
import "."
|
||||
import "../"
|
||||
|
||||
Item {
|
||||
id: root
|
||||
required property string text
|
||||
property bool shown: false
|
||||
property real horizontalPadding: 10
|
||||
property real verticalPadding: 5
|
||||
implicitWidth: tooltipTextObject.implicitWidth + 2 * root.horizontalPadding
|
||||
implicitHeight: tooltipTextObject.implicitHeight + 2 * root.verticalPadding
|
||||
|
||||
property bool isVisible: backgroundRectangle.implicitHeight > 0
|
||||
|
||||
Rectangle {
|
||||
id: backgroundRectangle
|
||||
anchors {
|
||||
bottom: root.bottom
|
||||
horizontalCenter: root.horizontalCenter
|
||||
}
|
||||
color: Appearance?.colors.colTooltip ?? "#3C4043"
|
||||
radius: Appearance?.rounding.verysmall ?? 7
|
||||
opacity: shown ? 1 : 0
|
||||
implicitWidth: shown ? (tooltipTextObject.implicitWidth + 2 * root.horizontalPadding) : 0
|
||||
implicitHeight: shown ? (tooltipTextObject.implicitHeight + 2 * root.verticalPadding) : 0
|
||||
clip: true
|
||||
|
||||
Behavior on implicitWidth {
|
||||
animation: Appearance?.animation.elementMoveFast.numberAnimation.createObject(this)
|
||||
}
|
||||
Behavior on implicitHeight {
|
||||
animation: Appearance?.animation.elementMoveFast.numberAnimation.createObject(this)
|
||||
}
|
||||
Behavior on opacity {
|
||||
animation: Appearance?.animation.elementMoveFast.numberAnimation.createObject(this)
|
||||
}
|
||||
|
||||
StyledText {
|
||||
id: tooltipTextObject
|
||||
anchors.centerIn: parent
|
||||
text: root.text
|
||||
font.pixelSize: Appearance?.font.pixelSize.smaller ?? 14
|
||||
font.hintingPreference: Font.PreferNoHinting
|
||||
color: Appearance?.colors.colOnTooltip ?? "#FFFFFF"
|
||||
wrapMode: Text.Wrap
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
StyledText 1.0 StyledText.qml
|
||||
StyledRectangularShadow 1.0 StyledRectangularShadow.qml
|
||||
StyledToolTip 1.0 StyledToolTip.qml
|
||||
StyledToolTipContent 1.0 StyledToolTipContent.qml
|
||||
Reference in New Issue
Block a user