Faster and smoother theme changes
This commit is contained in:
+36
-4
@@ -12,6 +12,7 @@ fi
|
|||||||
CURRENT_THEME_PATH="$HOME/.config/omarchy/current/theme"
|
CURRENT_THEME_PATH="$HOME/.config/omarchy/current/theme"
|
||||||
NEXT_THEME_PATH="$HOME/.config/omarchy/current/next-theme"
|
NEXT_THEME_PATH="$HOME/.config/omarchy/current/next-theme"
|
||||||
CURRENT_BACKGROUND_LINK="$HOME/.config/omarchy/current/background"
|
CURRENT_BACKGROUND_LINK="$HOME/.config/omarchy/current/background"
|
||||||
|
BACKGROUND_TRANSITION_CACHE="$HOME/.cache/omarchy/background-transitions"
|
||||||
USER_THEMES_PATH="$HOME/.config/omarchy/themes"
|
USER_THEMES_PATH="$HOME/.config/omarchy/themes"
|
||||||
OMARCHY_THEMES_PATH="$OMARCHY_PATH/themes"
|
OMARCHY_THEMES_PATH="$OMARCHY_PATH/themes"
|
||||||
|
|
||||||
@@ -29,6 +30,19 @@ run_parallel() {
|
|||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
snapshot_current_background() {
|
||||||
|
local current_background snapshot extension
|
||||||
|
|
||||||
|
current_background=$(readlink -f "$CURRENT_BACKGROUND_LINK" 2>/dev/null || true)
|
||||||
|
[[ -f $current_background ]] || return
|
||||||
|
|
||||||
|
mkdir -p "$BACKGROUND_TRANSITION_CACHE"
|
||||||
|
extension=${current_background##*.}
|
||||||
|
snapshot="$BACKGROUND_TRANSITION_CACHE/previous-$$.$extension"
|
||||||
|
ln "$current_background" "$snapshot" 2>/dev/null || cp "$current_background" "$snapshot"
|
||||||
|
echo "$snapshot"
|
||||||
|
}
|
||||||
|
|
||||||
set_theme_background() {
|
set_theme_background() {
|
||||||
local backgrounds=()
|
local backgrounds=()
|
||||||
local current_background index new_background next_index
|
local current_background index new_background next_index
|
||||||
@@ -41,6 +55,7 @@ set_theme_background() {
|
|||||||
|
|
||||||
if (( ${#backgrounds[@]} == 0 )); then
|
if (( ${#backgrounds[@]} == 0 )); then
|
||||||
omarchy-notification-send "No background was found for theme" -t 2000
|
omarchy-notification-send "No background was found for theme" -t 2000
|
||||||
|
omarchy-shell-ipc-fast shell applyTheme "$colors_payload" "$shell_payload" >/dev/null 2>&1 || true
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -61,7 +76,15 @@ set_theme_background() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
ln -nsf "$new_background" "$CURRENT_BACKGROUND_LINK"
|
ln -nsf "$new_background" "$CURRENT_BACKGROUND_LINK"
|
||||||
omarchy-shell-ipc-fast background setInstant "$new_background" >/dev/null 2>&1 || true
|
|
||||||
|
if [[ -f $OLD_BACKGROUND_SNAPSHOT ]]; then
|
||||||
|
omarchy-shell-ipc-fast background themeTransition "$OLD_BACKGROUND_SNAPSHOT" "$new_background" "$colors_payload" "$shell_payload" >/dev/null 2>&1 || \
|
||||||
|
omarchy-shell-ipc-fast shell applyTheme "$colors_payload" "$shell_payload" >/dev/null 2>&1 || true
|
||||||
|
(sleep 3; rm -f "$OLD_BACKGROUND_SNAPSHOT") &
|
||||||
|
else
|
||||||
|
omarchy-shell-ipc-fast background themeTransition "" "$new_background" "$colors_payload" "$shell_payload" >/dev/null 2>&1 || \
|
||||||
|
omarchy-shell-ipc-fast shell applyTheme "$colors_payload" "$shell_payload" >/dev/null 2>&1 || true
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
THEME_NAME=$(echo "$1" | sed -E 's/<[^>]+>//g' | tr '[:upper:]' '[:lower:]' | tr ' ' '-')
|
THEME_NAME=$(echo "$1" | sed -E 's/<[^>]+>//g' | tr '[:upper:]' '[:lower:]' | tr ' ' '-')
|
||||||
@@ -71,6 +94,10 @@ if [[ ! -d $OMARCHY_THEMES_PATH/$THEME_NAME ]] && [[ ! -d $USER_THEMES_PATH/$THE
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Prevent file-watch reloads from changing shell colors before the background
|
||||||
|
# reveal is ready. The theme IPC below resumes reloads as it applies colors.
|
||||||
|
omarchy-shell-ipc --if-running shell suspendThemeReloads >/dev/null 2>&1 || true
|
||||||
|
|
||||||
# Setup clean next theme directory (for atomic theme config swapping)
|
# Setup clean next theme directory (for atomic theme config swapping)
|
||||||
rm -rf "$NEXT_THEME_PATH"
|
rm -rf "$NEXT_THEME_PATH"
|
||||||
mkdir -p "$NEXT_THEME_PATH"
|
mkdir -p "$NEXT_THEME_PATH"
|
||||||
@@ -87,6 +114,11 @@ fi
|
|||||||
# Generate dynamic configs
|
# Generate dynamic configs
|
||||||
omarchy-theme-set-templates
|
omarchy-theme-set-templates
|
||||||
|
|
||||||
|
OLD_BACKGROUND_SNAPSHOT=""
|
||||||
|
if [[ $OMARCHY_THEME_SKIP_BACKGROUND != "1" ]]; then
|
||||||
|
OLD_BACKGROUND_SNAPSHOT=$(snapshot_current_background)
|
||||||
|
fi
|
||||||
|
|
||||||
# Swap next theme in as current
|
# Swap next theme in as current
|
||||||
rm -rf "$CURRENT_THEME_PATH"
|
rm -rf "$CURRENT_THEME_PATH"
|
||||||
mv "$NEXT_THEME_PATH" "$CURRENT_THEME_PATH"
|
mv "$NEXT_THEME_PATH" "$CURRENT_THEME_PATH"
|
||||||
@@ -98,9 +130,9 @@ echo "$THEME_NAME" >"$HOME/.config/omarchy/current/theme.name"
|
|||||||
# for file-watch debounce while the rest of the theme hooks run.
|
# for file-watch debounce while the rest of the theme hooks run.
|
||||||
colors_payload=$([[ -f $CURRENT_THEME_PATH/colors.toml ]] && base64 -w 0 "$CURRENT_THEME_PATH/colors.toml")
|
colors_payload=$([[ -f $CURRENT_THEME_PATH/colors.toml ]] && base64 -w 0 "$CURRENT_THEME_PATH/colors.toml")
|
||||||
shell_payload=$([[ -f $CURRENT_THEME_PATH/shell.toml ]] && base64 -w 0 "$CURRENT_THEME_PATH/shell.toml")
|
shell_payload=$([[ -f $CURRENT_THEME_PATH/shell.toml ]] && base64 -w 0 "$CURRENT_THEME_PATH/shell.toml")
|
||||||
omarchy-shell-ipc-fast shell applyTheme "$colors_payload" "$shell_payload" >/dev/null 2>&1 || true
|
if [[ $OMARCHY_THEME_SKIP_BACKGROUND == "1" ]]; then
|
||||||
|
omarchy-shell-ipc-fast shell applyTheme "$colors_payload" "$shell_payload" >/dev/null 2>&1 || true
|
||||||
if [[ $OMARCHY_THEME_SKIP_BACKGROUND != "1" ]]; then
|
else
|
||||||
set_theme_background
|
set_theme_background
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
@@ -170,7 +170,18 @@ QtObject {
|
|||||||
shellValues = parsed
|
shellValues = parsed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
property bool themeReloadSuspended: false
|
||||||
|
|
||||||
|
function suspendThemeReloads() {
|
||||||
|
themeReloadSuspended = true
|
||||||
|
}
|
||||||
|
|
||||||
|
function resumeThemeReloads() {
|
||||||
|
themeReloadSuspended = false
|
||||||
|
}
|
||||||
|
|
||||||
function reloadTheme() {
|
function reloadTheme() {
|
||||||
|
if (themeReloadSuspended) return
|
||||||
colorsFile.reload()
|
colorsFile.reload()
|
||||||
shellFile.reload()
|
shellFile.reload()
|
||||||
}
|
}
|
||||||
@@ -184,7 +195,7 @@ QtObject {
|
|||||||
watchChanges: true
|
watchChanges: true
|
||||||
printErrors: false
|
printErrors: false
|
||||||
onLoaded: root.loadColors(text())
|
onLoaded: root.loadColors(text())
|
||||||
onFileChanged: reload()
|
onFileChanged: root.reloadTheme()
|
||||||
}
|
}
|
||||||
property FileView shellFile: FileView {
|
property FileView shellFile: FileView {
|
||||||
id: shellFile
|
id: shellFile
|
||||||
@@ -193,7 +204,7 @@ QtObject {
|
|||||||
printErrors: false
|
printErrors: false
|
||||||
onLoaded: root.loadShell(text())
|
onLoaded: root.loadShell(text())
|
||||||
onLoadFailed: root.loadShell("")
|
onLoadFailed: root.loadShell("")
|
||||||
onFileChanged: reload()
|
onFileChanged: root.reloadTheme()
|
||||||
}
|
}
|
||||||
property FileView themeNameFile: FileView {
|
property FileView themeNameFile: FileView {
|
||||||
path: Quickshell.env("HOME") + "/.config/omarchy/current/theme.name"
|
path: Quickshell.env("HOME") + "/.config/omarchy/current/theme.name"
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import Quickshell
|
|||||||
import Quickshell.Io
|
import Quickshell.Io
|
||||||
import Quickshell.Wayland
|
import Quickshell.Wayland
|
||||||
import QtQuick
|
import QtQuick
|
||||||
|
import qs.Commons as NoctaliaCommons
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
@@ -19,6 +20,10 @@ Item {
|
|||||||
property string oldBackground: ""
|
property string oldBackground: ""
|
||||||
property bool finishingTransition: false
|
property bool finishingTransition: false
|
||||||
property int backgroundVersion: 0
|
property int backgroundVersion: 0
|
||||||
|
property int revealStartedVersion: -1
|
||||||
|
property int pendingThemeVersion: -1
|
||||||
|
property string pendingColorsRaw: ""
|
||||||
|
property string pendingShellRaw: ""
|
||||||
property real revealProgress: 1
|
property real revealProgress: 1
|
||||||
|
|
||||||
function imageUrl(path) {
|
function imageUrl(path) {
|
||||||
@@ -31,10 +36,16 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function setBackground(path, instant) {
|
function setBackground(path, instant) {
|
||||||
|
transitionBackground("", path, instant)
|
||||||
|
}
|
||||||
|
|
||||||
|
function transitionBackground(fromPath, path, instant) {
|
||||||
path = String(path || "").trim()
|
path = String(path || "").trim()
|
||||||
|
fromPath = String(fromPath || "").trim()
|
||||||
if (!path || path === currentBackground) return
|
if (!path || path === currentBackground) return
|
||||||
currentBackground = path
|
currentBackground = path
|
||||||
backgroundVersion += 1
|
backgroundVersion += 1
|
||||||
|
revealStartedVersion = -1
|
||||||
|
|
||||||
revealAnimation.stop()
|
revealAnimation.stop()
|
||||||
finishingTransition = false
|
finishingTransition = false
|
||||||
@@ -47,11 +58,46 @@ Item {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
oldBackground = displayedBackground
|
oldBackground = fromPath || displayedBackground
|
||||||
incomingBackground = path
|
incomingBackground = path
|
||||||
revealProgress = 0
|
revealProgress = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function decodePayload(payload) {
|
||||||
|
try { return Qt.atob(String(payload || "")) } catch (e) { return "" }
|
||||||
|
}
|
||||||
|
|
||||||
|
function setPendingTheme(colorsB64, shellB64) {
|
||||||
|
pendingColorsRaw = decodePayload(colorsB64)
|
||||||
|
pendingShellRaw = decodePayload(shellB64)
|
||||||
|
pendingThemeVersion = backgroundVersion
|
||||||
|
}
|
||||||
|
|
||||||
|
function applyPendingTheme() {
|
||||||
|
if (pendingThemeVersion !== backgroundVersion) return
|
||||||
|
NoctaliaCommons.Color.resumeThemeReloads()
|
||||||
|
NoctaliaCommons.Color.loadColors(pendingColorsRaw)
|
||||||
|
NoctaliaCommons.Color.loadShell(pendingShellRaw)
|
||||||
|
pendingThemeVersion = -1
|
||||||
|
pendingColorsRaw = ""
|
||||||
|
pendingShellRaw = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
function transitionBackgroundWithTheme(fromPath, path, colorsB64, shellB64) {
|
||||||
|
transitionBackground(fromPath, path, false)
|
||||||
|
setPendingTheme(colorsB64, shellB64)
|
||||||
|
if (!incomingBackground || revealProgress >= 1) applyPendingTheme()
|
||||||
|
}
|
||||||
|
|
||||||
|
function startReveal(panel) {
|
||||||
|
if (!incomingBackground) return
|
||||||
|
panel.maskReady = true
|
||||||
|
if (revealStartedVersion === backgroundVersion) return
|
||||||
|
revealStartedVersion = backgroundVersion
|
||||||
|
applyPendingTheme()
|
||||||
|
revealAnimation.restart()
|
||||||
|
}
|
||||||
|
|
||||||
function openSelector() {
|
function openSelector() {
|
||||||
if (!bgSwitchProc.running) bgSwitchProc.running = true
|
if (!bgSwitchProc.running) bgSwitchProc.running = true
|
||||||
}
|
}
|
||||||
@@ -94,6 +140,14 @@ Item {
|
|||||||
function setInstant(path: string): void {
|
function setInstant(path: string): void {
|
||||||
root.setBackground(path, true)
|
root.setBackground(path, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function transition(fromPath: string, path: string): void {
|
||||||
|
root.transitionBackground(fromPath, path, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
function themeTransition(fromPath: string, path: string, colorsB64: string, shellB64: string): void {
|
||||||
|
root.transitionBackgroundWithTheme(fromPath, path, colorsB64, shellB64)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Timer {
|
Timer {
|
||||||
@@ -230,41 +284,28 @@ Item {
|
|||||||
sy = (ih - sh) / 2
|
sy = (ih - sh) / 2
|
||||||
}
|
}
|
||||||
|
|
||||||
var center = width / 2
|
var centerTop = width / 2 - slant * height / 2
|
||||||
var reach = width / 2 + Math.abs(slant) * height + 4
|
var centerBottom = width / 2 + slant * height / 2
|
||||||
|
var reach = width / 2 + Math.abs(slant) * height / 2 + 4
|
||||||
var spread = reach * root.revealProgress
|
var spread = reach * root.revealProgress
|
||||||
var leftTop = center - spread
|
var leftTop = centerTop - spread
|
||||||
var leftBottom = center - spread + slant * height
|
var leftBottom = centerBottom - spread
|
||||||
var rightTop = center + spread
|
var rightTop = centerTop + spread
|
||||||
var rightBottom = center + spread + slant * height
|
var rightBottom = centerBottom + spread
|
||||||
|
|
||||||
ctx.save()
|
ctx.save()
|
||||||
ctx.beginPath()
|
ctx.beginPath()
|
||||||
ctx.moveTo(center, 0)
|
ctx.moveTo(leftTop, 0)
|
||||||
ctx.lineTo(leftTop, 0)
|
|
||||||
ctx.lineTo(leftBottom, height)
|
|
||||||
ctx.lineTo(center, height)
|
|
||||||
ctx.closePath()
|
|
||||||
ctx.clip()
|
|
||||||
ctx.drawImage(src, sx, sy, sw, sh, 0, 0, width, height)
|
|
||||||
ctx.restore()
|
|
||||||
|
|
||||||
ctx.save()
|
|
||||||
ctx.beginPath()
|
|
||||||
ctx.moveTo(center, 0)
|
|
||||||
ctx.lineTo(rightTop, 0)
|
ctx.lineTo(rightTop, 0)
|
||||||
ctx.lineTo(rightBottom, height)
|
ctx.lineTo(rightBottom, height)
|
||||||
ctx.lineTo(center, height)
|
ctx.lineTo(leftBottom, height)
|
||||||
ctx.closePath()
|
ctx.closePath()
|
||||||
ctx.clip()
|
ctx.clip()
|
||||||
ctx.drawImage(src, sx, sy, sw, sh, 0, 0, width, height)
|
ctx.drawImage(src, sx, sy, sw, sh, 0, 0, width, height)
|
||||||
ctx.restore()
|
ctx.restore()
|
||||||
|
|
||||||
if (!panel.maskReady && root.incomingBackground && root.revealProgress === 0) {
|
if (!panel.maskReady && root.incomingBackground && root.revealProgress === 0) {
|
||||||
Qt.callLater(function() {
|
Qt.callLater(function() { root.startReveal(panel) })
|
||||||
panel.maskReady = true
|
|
||||||
revealAnimation.restart()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -792,11 +792,17 @@ ShellRoot {
|
|||||||
var shellRaw = ""
|
var shellRaw = ""
|
||||||
try { colorsRaw = Qt.atob(String(colorsB64 || "")) } catch (e) { colorsRaw = "" }
|
try { colorsRaw = Qt.atob(String(colorsB64 || "")) } catch (e) { colorsRaw = "" }
|
||||||
try { shellRaw = Qt.atob(String(shellB64 || "")) } catch (e2) { shellRaw = "" }
|
try { shellRaw = Qt.atob(String(shellB64 || "")) } catch (e2) { shellRaw = "" }
|
||||||
|
NoctaliaCommons.Color.resumeThemeReloads()
|
||||||
NoctaliaCommons.Color.loadColors(colorsRaw)
|
NoctaliaCommons.Color.loadColors(colorsRaw)
|
||||||
NoctaliaCommons.Color.loadShell(shellRaw)
|
NoctaliaCommons.Color.loadShell(shellRaw)
|
||||||
return "ok"
|
return "ok"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function suspendThemeReloads(): string {
|
||||||
|
NoctaliaCommons.Color.suspendThemeReloads()
|
||||||
|
return "ok"
|
||||||
|
}
|
||||||
|
|
||||||
function reloadTheme(): string {
|
function reloadTheme(): string {
|
||||||
NoctaliaCommons.Color.reloadTheme()
|
NoctaliaCommons.Color.reloadTheme()
|
||||||
return "ok"
|
return "ok"
|
||||||
|
|||||||
Reference in New Issue
Block a user