Add a no-animations mode, on by default in VMs (#13550)
A machine without a GPU, like most VMs, renders through llvmpipe on the CPU, where every animated frame and every translucent window costs. In a VM, opening and closing a terminal took ~5s of CPU; a panel ~3.4s. omarchy toggle animations (also under Toggle > Animations) places a Hyprland flag that turns off animations, blur and shadows and makes windows opaque. The shell follows Hyprland's animations:enabled, rereading it on every config reload: its one-shot animations run for Style.duration(ms), which is then 0, and its spinners, pulses and title marquee hold still. A new install in a VM starts with the flag in place. Measured in the ISO test VM (llvmpipe), CPU per interaction: terminal open+close 5000ms -> 481ms, workspace switch 1670ms -> 409ms, audio panel 3446ms -> 796ms, volume OSD 2324ms -> 584ms, menu 2028ms -> 1241ms. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
97a9fce54f
commit
b18ab4952b
41 files changed
+201
-79
No files matched your search
Executable
+5
@@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
|
||||
# omarchy:summary=Returns true when running in a virtual machine.
|
||||
|
||||
systemd-detect-virt --vm --quiet
|
||||
Executable
+22
@@ -0,0 +1,22 @@
|
||||
#!/bin/bash
|
||||
|
||||
# omarchy:summary=Toggle animations, transparency and other effects that are slow without a GPU
|
||||
# omarchy:args=[toggle|on|off]
|
||||
# omarchy:examples=omarchy toggle animations | omarchy toggle animations off | omarchy toggle animations on
|
||||
|
||||
# The flag records animations being off, so on and off swap on the way through.
|
||||
case ${1:-toggle} in
|
||||
toggle) omarchy-hyprland-toggle no-animations toggle ;;
|
||||
on) omarchy-hyprland-toggle no-animations off ;;
|
||||
off) omarchy-hyprland-toggle no-animations on ;;
|
||||
*)
|
||||
echo "Usage: omarchy-toggle-animations [toggle|on|off]" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
if omarchy-hyprland-toggle-enabled no-animations; then
|
||||
omarchy-notification-send -g "Animations disabled"
|
||||
else
|
||||
omarchy-notification-send -g "Animations enabled"
|
||||
fi
|
||||
@@ -0,0 +1,20 @@
|
||||
-- Draw nothing just for show, for machines that render on the CPU, like a VM:
|
||||
-- no animations, blur or shadows, and opaque windows, so nothing behind a
|
||||
-- window has to be blended into it.
|
||||
hl.config({
|
||||
animations = {
|
||||
enabled = false,
|
||||
},
|
||||
|
||||
decoration = {
|
||||
blur = {
|
||||
enabled = false,
|
||||
},
|
||||
|
||||
shadow = {
|
||||
enabled = false,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
o.window(".*", { opacity = "1 1" })
|
||||
@@ -97,6 +97,7 @@
|
||||
"trigger.toggle.battery-percentage": {"icon":"","label":"Battery Percentage","when":"omarchy-hw-laptop","action":"omarchy-shell omarchy.power togglePercentage"},
|
||||
"trigger.toggle.workspace-layout": {"icon":"","label":"Workspace Layout","action":"omarchy-hyprland-workspace-layout-toggle"},
|
||||
"trigger.toggle.window-gaps": {"icon":"","label":"Window Gaps","action":"omarchy-hyprland-window-gaps-toggle"},
|
||||
"trigger.toggle.animations": {"icon":"","label":"Animations","action":"omarchy-toggle-animations"},
|
||||
"trigger.toggle.one-window-ratio": {"icon":"","label":"1-Window Ratio","action":"omarchy-hyprland-window-single-square-aspect-toggle"},
|
||||
"trigger.tests.network-speedtest": {"icon":"","label":"Network Speed Test","action":"omarchy-shell shell summon omarchy.speedtest"},
|
||||
"trigger.tests.disk-speedtest": {"icon":"","label":"Disk Speed Test","action":"omarchy-shell shell summon omarchy.disk-speedtest"},
|
||||
|
||||
@@ -9,6 +9,7 @@ run_logged "$OMARCHY_INSTALL/user/hardware/asus/fix-mic.sh"
|
||||
run_logged "$OMARCHY_INSTALL/user/hardware/framework/fix-f13-amd-audio-input.sh"
|
||||
run_logged "$OMARCHY_INSTALL/user/hardware/dell/xps13-text-scaling.sh"
|
||||
run_logged "$OMARCHY_INSTALL/user/hardware/fix-nouveau-cursor.sh"
|
||||
run_logged "$OMARCHY_INSTALL/user/hardware/vm-no-animations.sh"
|
||||
|
||||
run_logged "$OMARCHY_INSTALL/user/default-keyring.sh"
|
||||
run_logged "$OMARCHY_INSTALL/user/mise.sh"
|
||||
@@ -0,0 +1,9 @@
|
||||
# A VM usually renders on the CPU, where animations and transparency cost
|
||||
# every frame, so start it without them. omarchy-toggle-animations brings them
|
||||
# back. This runs before any Hyprland session exists, so place the flag
|
||||
# directly rather than through omarchy-hyprland-toggle, which reloads Hyprland.
|
||||
if omarchy-hw-vm; then
|
||||
echo "Detected a virtual machine. Turning off animations and transparency."
|
||||
mkdir -p "$HOME/.local/state/omarchy/toggles/hypr"
|
||||
cp "$OMARCHY_PATH/default/hypr/toggles/no-animations.lua" "$HOME/.local/state/omarchy/toggles/hypr/"
|
||||
fi
|
||||
@@ -1,6 +1,7 @@
|
||||
pragma Singleton
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import Quickshell.Hyprland
|
||||
import Quickshell.Io
|
||||
|
||||
// Shared structural style tokens for the shell. Color is the palette
|
||||
@@ -347,9 +348,19 @@ QtObject {
|
||||
readonly property int statusSlot: root.barToken("status-slot", 21)
|
||||
}
|
||||
|
||||
// Off with Hyprland's own animations, as `omarchy toggle animations` turns
|
||||
// them off for machines that render on the CPU. Every shell animation runs
|
||||
// for Style.duration(ms), which is then 0, so nothing is drawn in between.
|
||||
property bool reduceMotion: false
|
||||
|
||||
function duration(ms) {
|
||||
return reduceMotion ? 0 : ms
|
||||
}
|
||||
|
||||
function refresh() {
|
||||
hyprctlProc.running = true
|
||||
gapsOutProc.running = true
|
||||
animationsProc.running = true
|
||||
}
|
||||
|
||||
function scheduleRefresh() {
|
||||
@@ -448,6 +459,30 @@ QtObject {
|
||||
}
|
||||
}
|
||||
|
||||
property Process animationsProc: Process {
|
||||
id: animationsProc
|
||||
command: ["hyprctl", "-j", "getoption", "animations:enabled"]
|
||||
stdout: StdioCollector {
|
||||
waitForEnd: true
|
||||
onStreamFinished: {
|
||||
try {
|
||||
root.reduceMotion = JSON.parse(text || "{}").bool === false
|
||||
} catch (e) {
|
||||
// hyprctl missing / Hyprland not running — leave the previous value.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A reload is when the animations toggle, a theme or the user's own config
|
||||
// lands, and Hyprland only announces it once the new values are in effect.
|
||||
property Connections hyprlandEvents: Connections {
|
||||
target: Hyprland
|
||||
function onRawEvent(event) {
|
||||
if (event && String(event.name) === "configreloaded") root.refresh()
|
||||
}
|
||||
}
|
||||
|
||||
property Process gapsOutProc: Process {
|
||||
id: gapsOutProc
|
||||
command: ["hyprctl", "-j", "getoption", "general:gaps_out"]
|
||||
|
||||
+2
-2
@@ -125,7 +125,7 @@ BorderSurface {
|
||||
// dedicated selected border.
|
||||
borderSpec: _borderSpec
|
||||
|
||||
Behavior on color { ColorAnimation { duration: 120 } }
|
||||
Behavior on color { ColorAnimation { duration: Style.duration(120) } }
|
||||
|
||||
ToolTip {
|
||||
visible: root.tooltipText !== "" && mouseArea.containsMouse
|
||||
@@ -174,7 +174,7 @@ BorderSurface {
|
||||
to: 360
|
||||
duration: 900
|
||||
loops: Animation.Infinite
|
||||
running: root.iconSpinning
|
||||
running: root.iconSpinning && !Style.reduceMotion
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -36,6 +36,6 @@ BorderSurface {
|
||||
: Border.none()))
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation { duration: 60 }
|
||||
ColorAnimation { duration: Style.duration(60) }
|
||||
}
|
||||
}
|
||||
@@ -390,7 +390,7 @@ PanelWindow {
|
||||
|
||||
Behavior on opacity {
|
||||
enabled: !root.popoutSwitching && !root.popoutSwitchClosing
|
||||
NumberAnimation { duration: 140; easing.type: Easing.OutCubic }
|
||||
NumberAnimation { duration: Style.duration(140); easing.type: Easing.OutCubic }
|
||||
}
|
||||
|
||||
// Swallow clicks on the card so they don't bubble to the dismissal
|
||||
@@ -411,7 +411,7 @@ PanelWindow {
|
||||
|
||||
Behavior on opacity {
|
||||
enabled: root.popoutSwitching
|
||||
NumberAnimation { duration: 140; easing.type: Easing.OutCubic }
|
||||
NumberAnimation { duration: Style.duration(140); easing.type: Easing.OutCubic }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -461,7 +461,7 @@ Item {
|
||||
font.pixelSize: Style.font.body
|
||||
|
||||
RotationAnimator on rotation {
|
||||
running: root.loadingOptions
|
||||
running: root.loadingOptions && !Style.reduceMotion
|
||||
from: 0; to: 360
|
||||
duration: 800
|
||||
loops: Animation.Infinite
|
||||
|
||||
@@ -66,7 +66,7 @@ BorderSurface {
|
||||
: "transparent")
|
||||
borderSpec: _borderSpec
|
||||
|
||||
Behavior on color { ColorAnimation { duration: 60 } }
|
||||
Behavior on color { ColorAnimation { duration: Style.duration(60) } }
|
||||
|
||||
Text {
|
||||
textFormat: Text.PlainText
|
||||
|
||||
@@ -62,7 +62,7 @@ Item {
|
||||
|
||||
Behavior on width {
|
||||
enabled: !root.dragging
|
||||
NumberAnimation { duration: 140; easing.type: Easing.OutCubic }
|
||||
NumberAnimation { duration: Style.duration(140); easing.type: Easing.OutCubic }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,11 +93,11 @@ Item {
|
||||
|
||||
Behavior on x {
|
||||
enabled: !root.dragging
|
||||
NumberAnimation { duration: 140; easing.type: Easing.OutCubic }
|
||||
NumberAnimation { duration: Style.duration(140); easing.type: Easing.OutCubic }
|
||||
}
|
||||
|
||||
Behavior on scale {
|
||||
NumberAnimation { duration: 110; easing.type: Easing.OutCubic }
|
||||
NumberAnimation { duration: Style.duration(110); easing.type: Easing.OutCubic }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -157,7 +157,7 @@ PopupWindow {
|
||||
opacity: root.open ? 1.0 : 0
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation { duration: 140; easing.type: Easing.OutCubic }
|
||||
NumberAnimation { duration: Style.duration(140); easing.type: Easing.OutCubic }
|
||||
}
|
||||
|
||||
Item {
|
||||
|
||||
@@ -61,7 +61,7 @@ PanelWindow {
|
||||
onRightValueChanged: expandScale(rightValue)
|
||||
|
||||
Behavior on fullScale {
|
||||
NumberAnimation { duration: 400; easing.type: Easing.OutCubic }
|
||||
NumberAnimation { duration: Style.duration(400); easing.type: Easing.OutCubic }
|
||||
}
|
||||
|
||||
// The scrim below is a fixed near-black regardless of theme, so text and
|
||||
@@ -178,7 +178,7 @@ PanelWindow {
|
||||
onClicked: root.runAgainRequested()
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation { duration: 240; easing.type: Easing.OutCubic }
|
||||
NumberAnimation { duration: Style.duration(240); easing.type: Easing.OutCubic }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -236,13 +236,13 @@ PanelWindow {
|
||||
opacity: engaged ? 1 : 0.5
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation { duration: 240; easing.type: Easing.OutCubic }
|
||||
NumberAnimation { duration: Style.duration(240); easing.type: Easing.OutCubic }
|
||||
}
|
||||
|
||||
// Live readings land once a second; glide between them rather than snap.
|
||||
Behavior on shown {
|
||||
enabled: !ignition.running
|
||||
NumberAnimation { duration: 600; easing.type: Easing.OutCubic }
|
||||
NumberAnimation { duration: Style.duration(600); easing.type: Easing.OutCubic }
|
||||
}
|
||||
|
||||
onValueChanged: {
|
||||
@@ -257,8 +257,8 @@ PanelWindow {
|
||||
// the live figures take over.
|
||||
SequentialAnimation {
|
||||
id: ignition
|
||||
NumberAnimation { target: dial; property: "shown"; to: dial.fullScale; duration: 550; easing.type: Easing.InOutCubic }
|
||||
NumberAnimation { target: dial; property: "shown"; to: 0; duration: 650; easing.type: Easing.OutCubic }
|
||||
NumberAnimation { target: dial; property: "shown"; to: dial.fullScale; duration: Style.duration(550); easing.type: Easing.InOutCubic }
|
||||
NumberAnimation { target: dial; property: "shown"; to: 0; duration: Style.duration(650); easing.type: Easing.OutCubic }
|
||||
onFinished: dial.shown = dial.value
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -52,7 +52,7 @@ BorderSurface {
|
||||
color: Style.controlFill(activeFocus, _hot, foreground, accent)
|
||||
borderSpec: _borderSpec
|
||||
|
||||
Behavior on color { ColorAnimation { duration: 100 } }
|
||||
Behavior on color { ColorAnimation { duration: Style.duration(100) } }
|
||||
|
||||
Row {
|
||||
id: content
|
||||
|
||||
@@ -84,7 +84,7 @@ Item {
|
||||
: Style.normalFillFor(root.foreground, root.accent)
|
||||
borderSpec: Border.controlSpec(root.checked ? "selected" : "normal", root.foreground, root.accent)
|
||||
|
||||
Behavior on color { ColorAnimation { duration: 120 } }
|
||||
Behavior on color { ColorAnimation { duration: Style.duration(120) } }
|
||||
|
||||
Rectangle {
|
||||
width: root.knobSize
|
||||
@@ -94,8 +94,8 @@ Item {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
color: root.checked ? Style.selectedStateColor(root.foreground, root.accent) : Qt.darker(root.foreground, 1.25)
|
||||
|
||||
Behavior on x { NumberAnimation { duration: 120; easing.type: Easing.OutCubic } }
|
||||
Behavior on color { ColorAnimation { duration: 120 } }
|
||||
Behavior on x { NumberAnimation { duration: Style.duration(120); easing.type: Easing.OutCubic } }
|
||||
Behavior on color { ColorAnimation { duration: Style.duration(120) } }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ Item {
|
||||
implicitHeight: fixedHeight > 0 ? fixedHeight : (vertical ? Math.max(12, label.implicitHeight + scaledVerticalPadding * 2) : barSize)
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation { duration: 140; easing.type: Easing.OutCubic }
|
||||
NumberAnimation { duration: Style.duration(140); easing.type: Easing.OutCubic }
|
||||
}
|
||||
|
||||
Text {
|
||||
@@ -88,7 +88,7 @@ Item {
|
||||
|
||||
Behavior on color {
|
||||
enabled: !root.bar || root.bar.foregroundAnimationEnabled
|
||||
ColorAnimation { duration: 160 }
|
||||
ColorAnimation { duration: Style.duration(160) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -788,7 +788,7 @@ Panel {
|
||||
color: meter.alarming ? root.urgent : root.foreground
|
||||
|
||||
Behavior on width {
|
||||
NumberAnimation { duration: 160; easing.type: Easing.OutCubic }
|
||||
NumberAnimation { duration: Style.duration(160); easing.type: Easing.OutCubic }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -837,7 +837,7 @@ Panel {
|
||||
color: dayRow.today ? root.foreground : root.alpha(root.foreground, 0.55)
|
||||
|
||||
Behavior on width {
|
||||
NumberAnimation { duration: 160; easing.type: Easing.OutCubic }
|
||||
NumberAnimation { duration: Style.duration(160); easing.type: Easing.OutCubic }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -894,7 +894,7 @@ Panel {
|
||||
color: root.alpha(root.foreground, 0.14)
|
||||
|
||||
Behavior on width {
|
||||
NumberAnimation { duration: 160; easing.type: Easing.OutCubic }
|
||||
NumberAnimation { duration: Style.duration(160); easing.type: Easing.OutCubic }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -258,7 +258,7 @@ Item {
|
||||
property: "revealProgress"
|
||||
from: 0
|
||||
to: 1
|
||||
duration: 420
|
||||
duration: Style.duration(420)
|
||||
easing.type: Easing.InOutCubic
|
||||
onFinished: {
|
||||
if (root.incomingBackground) {
|
||||
|
||||
@@ -80,9 +80,9 @@ Item {
|
||||
property color background: Color.bar.background
|
||||
property color urgent: Color.bar.active
|
||||
|
||||
Behavior on barForeground { enabled: root.foregroundAnimationEnabled; ColorAnimation { duration: 420; easing.type: Easing.InOutCubic } }
|
||||
Behavior on background { ColorAnimation { duration: 420; easing.type: Easing.InOutCubic } }
|
||||
Behavior on urgent { ColorAnimation { duration: 420; easing.type: Easing.InOutCubic } }
|
||||
Behavior on barForeground { enabled: root.foregroundAnimationEnabled; ColorAnimation { duration: Style.duration(420); easing.type: Easing.InOutCubic } }
|
||||
Behavior on background { ColorAnimation { duration: Style.duration(420); easing.type: Easing.InOutCubic } }
|
||||
Behavior on urgent { ColorAnimation { duration: Style.duration(420); easing.type: Easing.InOutCubic } }
|
||||
property var tooltipTarget: null
|
||||
property var pendingTooltipTarget: null
|
||||
property string tooltipText: ""
|
||||
@@ -1509,7 +1509,7 @@ Item {
|
||||
opacity: root.barMoveCandidate === modelData ? (root.transparent ? 0.45 : 0.7) : 0
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation { duration: 140; easing.type: Easing.OutCubic }
|
||||
NumberAnimation { duration: Style.duration(140); easing.type: Easing.OutCubic }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1895,7 +1895,7 @@ Item {
|
||||
z: 50
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation { duration: 120; easing.type: Easing.OutCubic }
|
||||
NumberAnimation { duration: Style.duration(120); easing.type: Easing.OutCubic }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ BarWidget {
|
||||
implicitHeight: barSize
|
||||
|
||||
Behavior on implicitWidth {
|
||||
NumberAnimation { duration: 180; easing.type: Easing.OutCubic }
|
||||
NumberAnimation { duration: Style.duration(180); easing.type: Easing.OutCubic }
|
||||
}
|
||||
|
||||
Item {
|
||||
|
||||
@@ -216,7 +216,7 @@ BarWidget {
|
||||
implicitHeight: root.vertical ? trayContent.implicitHeight : root.barSize
|
||||
|
||||
Behavior on revealProgress {
|
||||
NumberAnimation { duration: root.animationDuration; easing.type: Easing.OutCubic }
|
||||
NumberAnimation { duration: Style.duration(root.animationDuration); easing.type: Easing.OutCubic }
|
||||
}
|
||||
|
||||
Loader {
|
||||
|
||||
@@ -207,7 +207,7 @@ BorderSurface {
|
||||
visible: opacity > 0
|
||||
opacity: root.hovered ? 1 : 0
|
||||
|
||||
Behavior on opacity { NumberAnimation { duration: 100 } }
|
||||
Behavior on opacity { NumberAnimation { duration: Style.duration(100) } }
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
|
||||
@@ -178,7 +178,7 @@ Item {
|
||||
|
||||
Behavior on width {
|
||||
enabled: root.opened
|
||||
NumberAnimation { duration: 140; easing.type: Easing.OutCubic }
|
||||
NumberAnimation { duration: Style.duration(140); easing.type: Easing.OutCubic }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -944,7 +944,7 @@ Panel {
|
||||
height: parent.height
|
||||
width: parent.width * Math.max(0, Math.min(1, inputPeakMonitor.peak))
|
||||
color: root.bar.foreground
|
||||
Behavior on width { NumberAnimation { duration: 70 } }
|
||||
Behavior on width { NumberAnimation { duration: Style.duration(70) } }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -603,14 +603,14 @@ Panel {
|
||||
id: phraseSwap
|
||||
PropertyAnimation {
|
||||
target: heroStatus; property: "opacity"
|
||||
to: 0.0; duration: 180; easing.type: Easing.OutQuad
|
||||
to: 0.0; duration: Style.duration(180); easing.type: Easing.OutQuad
|
||||
}
|
||||
ScriptAction {
|
||||
script: root.phraseIndex = (root.phraseIndex + 1) % root.activePhrases.length
|
||||
}
|
||||
PropertyAnimation {
|
||||
target: heroStatus; property: "opacity"
|
||||
to: 1.0; duration: 260; easing.type: Easing.InQuad
|
||||
to: 1.0; duration: Style.duration(260); easing.type: Easing.InQuad
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -457,7 +457,7 @@ Panel {
|
||||
radius: parent.radius
|
||||
color: Style.selectedStateColor(root.contentForeground, Color.accent)
|
||||
|
||||
Behavior on width { NumberAnimation { duration: 160; easing.type: Easing.OutCubic } }
|
||||
Behavior on width { NumberAnimation { duration: Style.duration(160); easing.type: Easing.OutCubic } }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -515,7 +515,7 @@ Panel {
|
||||
radius: parent.radius
|
||||
color: Style.selectedStateColor(root.contentForeground, Color.accent)
|
||||
|
||||
Behavior on width { NumberAnimation { duration: 160; easing.type: Easing.OutCubic } }
|
||||
Behavior on width { NumberAnimation { duration: Style.duration(160); easing.type: Easing.OutCubic } }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -369,14 +369,14 @@ Panel {
|
||||
id: phraseSwap
|
||||
PropertyAnimation {
|
||||
target: hero; property: "metaOpacity"
|
||||
to: 0.0; duration: 180; easing.type: Easing.OutQuad
|
||||
to: 0.0; duration: Style.duration(180); easing.type: Easing.OutQuad
|
||||
}
|
||||
ScriptAction {
|
||||
script: root.phraseIndex = (root.phraseIndex + 1) % root.activePhrases.length
|
||||
}
|
||||
PropertyAnimation {
|
||||
target: hero; property: "metaOpacity"
|
||||
to: 1.0; duration: 260; easing.type: Easing.InQuad
|
||||
to: 1.0; duration: Style.duration(260); easing.type: Easing.InQuad
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -79,13 +79,13 @@ Rectangle {
|
||||
// The dragged row follows the pointer one-to-one; the others ease aside.
|
||||
Behavior on y {
|
||||
enabled: !row.dragged
|
||||
NumberAnimation { duration: 130; easing.type: Easing.OutCubic }
|
||||
NumberAnimation { duration: Style.duration(130); easing.type: Easing.OutCubic }
|
||||
}
|
||||
}
|
||||
]
|
||||
z: dragged ? 2 : 0
|
||||
opacity: dragged ? 0.9 : 1
|
||||
Behavior on opacity { NumberAnimation { duration: 120 } }
|
||||
Behavior on opacity { NumberAnimation { duration: Style.duration(120) } }
|
||||
|
||||
HoverHandler { id: rowHover }
|
||||
|
||||
@@ -219,7 +219,7 @@ Rectangle {
|
||||
spacing: Style.spacing.sm
|
||||
opacity: parent.greeting ? 0 : 1
|
||||
visible: opacity > 0
|
||||
Behavior on opacity { NumberAnimation { duration: 110 } }
|
||||
Behavior on opacity { NumberAnimation { duration: Style.duration(110) } }
|
||||
|
||||
Caption {
|
||||
text: row.ready ? row.rowData.date : "\u2026"
|
||||
@@ -242,7 +242,7 @@ Rectangle {
|
||||
spacing: Style.space(5)
|
||||
opacity: parent.greeting ? 1 : 0
|
||||
visible: opacity > 0
|
||||
Behavior on opacity { NumberAnimation { duration: 110 } }
|
||||
Behavior on opacity { NumberAnimation { duration: Style.duration(110) } }
|
||||
|
||||
// Non-Latin scripts fall back per character through fontconfig.
|
||||
Caption {
|
||||
@@ -304,7 +304,7 @@ Rectangle {
|
||||
// Shown on the keyboard's pick too, so Delete's target is plain.
|
||||
opacity: row.removable && row.lit ? 1 : 0
|
||||
visible: opacity > 0
|
||||
Behavior on opacity { NumberAnimation { duration: 120 } }
|
||||
Behavior on opacity { NumberAnimation { duration: Style.duration(120) } }
|
||||
onClicked: row.panel.removeCityAt(row.index)
|
||||
}
|
||||
|
||||
|
||||
@@ -115,7 +115,7 @@ Item {
|
||||
color: strip.foreground
|
||||
}
|
||||
|
||||
Behavior on x { NumberAnimation { duration: 400; easing.type: Easing.OutCubic } }
|
||||
Behavior on x { NumberAnimation { duration: Style.duration(400); easing.type: Easing.OutCubic } }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,7 +182,7 @@ Item {
|
||||
// Gone rather than faded, so a hidden arrow is also untappable.
|
||||
opacity: strip.hovered && !arrow.covered ? 1 : 0
|
||||
visible: opacity > 0
|
||||
Behavior on opacity { NumberAnimation { duration: 160 } }
|
||||
Behavior on opacity { NumberAnimation { duration: Style.duration(160) } }
|
||||
|
||||
// Sunrise sits a little high and sunset a little low: a cue that needs no reading.
|
||||
transform: Translate { y: arrow.rising ? -Style.space(2) : Style.space(2) }
|
||||
|
||||
@@ -338,9 +338,9 @@ Item {
|
||||
ParallelAnimation {
|
||||
id: flight
|
||||
NumberAnimation { id: flightSpin; target: root; property: "spin"
|
||||
duration: 800; easing.type: Easing.OutCubic }
|
||||
duration: Style.duration(800); easing.type: Easing.OutCubic }
|
||||
NumberAnimation { id: flightViewLat; target: root; property: "viewLat"
|
||||
duration: 800; easing.type: Easing.OutCubic }
|
||||
duration: Style.duration(800); easing.type: Easing.OutCubic }
|
||||
}
|
||||
|
||||
// The throw: spin keeps going after the drag and eases to a stop.
|
||||
|
||||
@@ -137,7 +137,7 @@ Column {
|
||||
id: globeSpin
|
||||
target: heroIcon
|
||||
property: "spin"
|
||||
duration: 1250
|
||||
duration: Style.duration(1250)
|
||||
easing.type: Easing.OutQuart
|
||||
}
|
||||
|
||||
@@ -145,7 +145,7 @@ Column {
|
||||
id: focusSpin
|
||||
target: heroIcon
|
||||
property: "spin"
|
||||
duration: 700
|
||||
duration: Style.duration(700)
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
}
|
||||
|
||||
@@ -631,7 +631,7 @@ Panel {
|
||||
// Heavy on the way out, brisk on the way back.
|
||||
Behavior on zoom {
|
||||
NumberAnimation {
|
||||
duration: root.zoomDuration
|
||||
duration: Style.duration(root.zoomDuration)
|
||||
easing.type: root.zoomEasing
|
||||
}
|
||||
}
|
||||
@@ -649,14 +649,14 @@ Panel {
|
||||
|
||||
Behavior on moonDemo {
|
||||
enabled: root.moonShowing
|
||||
NumberAnimation { duration: 460; easing.type: Easing.InOutSine }
|
||||
NumberAnimation { duration: Style.duration(460); easing.type: Easing.InOutSine }
|
||||
}
|
||||
|
||||
NumberAnimation {
|
||||
id: dropAnimation
|
||||
target: root
|
||||
property: "dragOffset"
|
||||
duration: 150
|
||||
duration: Style.duration(150)
|
||||
easing.type: Easing.OutCubic
|
||||
onFinished: root.commitRowDrag()
|
||||
}
|
||||
@@ -805,7 +805,7 @@ Panel {
|
||||
id: scrollAnim
|
||||
target: scroller
|
||||
property: "contentY"
|
||||
duration: 160
|
||||
duration: Style.duration(160)
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
|
||||
|
||||
@@ -965,14 +965,14 @@ Panel {
|
||||
id: connectionPhraseSwap
|
||||
PropertyAnimation {
|
||||
target: heroMeta; property: "opacity"
|
||||
to: 0.0; duration: 180; easing.type: Easing.OutQuad
|
||||
to: 0.0; duration: Style.duration(180); easing.type: Easing.OutQuad
|
||||
}
|
||||
ScriptAction {
|
||||
script: root.connectionPhraseIndex = (root.connectionPhraseIndex + 1) % root.connectionPhrases.length
|
||||
}
|
||||
PropertyAnimation {
|
||||
target: heroMeta; property: "opacity"
|
||||
to: 1.0; duration: 260; easing.type: Easing.InQuad
|
||||
to: 1.0; duration: Style.duration(260); easing.type: Easing.InQuad
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1472,10 +1472,10 @@ Panel {
|
||||
opacity: root.bandPillsVisible ? 1 : 0
|
||||
|
||||
Behavior on height {
|
||||
NumberAnimation { duration: 140; easing.type: Easing.OutCubic }
|
||||
NumberAnimation { duration: Style.duration(140); easing.type: Easing.OutCubic }
|
||||
}
|
||||
Behavior on opacity {
|
||||
NumberAnimation { duration: 140; easing.type: Easing.OutCubic }
|
||||
NumberAnimation { duration: Style.duration(140); easing.type: Easing.OutCubic }
|
||||
}
|
||||
|
||||
Row {
|
||||
|
||||
@@ -246,7 +246,7 @@ Panel {
|
||||
id: phraseSwap
|
||||
PropertyAnimation {
|
||||
target: heroStatus; property: "opacity"
|
||||
to: 0.0; duration: 180; easing.type: Easing.OutQuad
|
||||
to: 0.0; duration: Style.duration(180); easing.type: Easing.OutQuad
|
||||
}
|
||||
ScriptAction {
|
||||
script: {
|
||||
@@ -256,7 +256,7 @@ Panel {
|
||||
}
|
||||
PropertyAnimation {
|
||||
target: heroStatus; property: "opacity"
|
||||
to: 1.0; duration: 260; easing.type: Easing.InQuad
|
||||
to: 1.0; duration: Style.duration(260); easing.type: Easing.InQuad
|
||||
}
|
||||
}
|
||||
|
||||
@@ -333,7 +333,7 @@ Panel {
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
Behavior on color { ColorAnimation { duration: 200 } }
|
||||
Behavior on color { ColorAnimation { duration: Style.duration(200) } }
|
||||
}
|
||||
|
||||
Column {
|
||||
@@ -380,7 +380,7 @@ Panel {
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
Behavior on color { ColorAnimation { duration: 200 } }
|
||||
Behavior on color { ColorAnimation { duration: Style.duration(200) } }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -405,12 +405,12 @@ Panel {
|
||||
color: root.batteryFillColor
|
||||
width: Math.max(barTrack.height, barTrack.width * root.batteryFraction)
|
||||
|
||||
Behavior on width { NumberAnimation { duration: 320; easing.type: Easing.OutCubic } }
|
||||
Behavior on color { ColorAnimation { duration: 220 } }
|
||||
Behavior on width { NumberAnimation { duration: Style.duration(320); easing.type: Easing.OutCubic } }
|
||||
Behavior on color { ColorAnimation { duration: Style.duration(220) } }
|
||||
|
||||
// Subtle pulse while charging — visible signal that energy is flowing in.
|
||||
SequentialAnimation on opacity {
|
||||
running: root.charging && !root.fullyCharged && root.opened
|
||||
running: root.charging && !root.fullyCharged && root.opened && !Style.reduceMotion
|
||||
loops: Animation.Infinite
|
||||
alwaysRunToEnd: true
|
||||
NumberAnimation { from: 1.0; to: 0.55; duration: 950; easing.type: Easing.InOutSine }
|
||||
|
||||
@@ -726,14 +726,14 @@ Panel {
|
||||
id: phraseSwap
|
||||
PropertyAnimation {
|
||||
target: hero; property: "metaOpacity"
|
||||
to: 0.0; duration: 180; easing.type: Easing.OutQuad
|
||||
to: 0.0; duration: Style.duration(180); easing.type: Easing.OutQuad
|
||||
}
|
||||
ScriptAction {
|
||||
script: root.phraseIndex = (root.phraseIndex + 1) % root.activePhrases.length
|
||||
}
|
||||
PropertyAnimation {
|
||||
target: hero; property: "metaOpacity"
|
||||
to: 1.0; duration: 260; easing.type: Easing.InQuad
|
||||
to: 1.0; duration: Style.duration(260); easing.type: Easing.InQuad
|
||||
}
|
||||
}
|
||||
|
||||
@@ -834,7 +834,7 @@ Panel {
|
||||
opacity: accountRow.switchingAccount ? 0.45 : 1.0
|
||||
|
||||
SequentialAnimation on opacity {
|
||||
running: accountRow.switchingAccount
|
||||
running: accountRow.switchingAccount && !Style.reduceMotion
|
||||
NumberAnimation { to: 1.0; duration: 420; easing.type: Easing.InOutQuad }
|
||||
NumberAnimation { to: 0.45; duration: 420; easing.type: Easing.InOutQuad }
|
||||
loops: Animation.Infinite
|
||||
@@ -1150,7 +1150,7 @@ Panel {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
NumberAnimation on rotation {
|
||||
running: exitNodeRow.settingExitNode
|
||||
running: exitNodeRow.settingExitNode && !Style.reduceMotion
|
||||
from: 0
|
||||
to: 360
|
||||
duration: 900
|
||||
|
||||
@@ -657,7 +657,7 @@ Panel {
|
||||
font.pixelSize: Style.font.bodySmall
|
||||
|
||||
RotationAnimator on rotation {
|
||||
running: root.savingLocation
|
||||
running: root.savingLocation && !Style.reduceMotion
|
||||
from: 0; to: 360
|
||||
duration: 800
|
||||
loops: Animation.Infinite
|
||||
|
||||
@@ -153,9 +153,9 @@ Item {
|
||||
|
||||
SequentialAnimation {
|
||||
id: shakeAnimation
|
||||
NumberAnimation { target: root; property: "shakeOffset"; to: -8; duration: 35; easing.type: Easing.OutQuad }
|
||||
NumberAnimation { target: root; property: "shakeOffset"; to: 8; duration: 50; easing.type: Easing.InOutQuad }
|
||||
NumberAnimation { target: root; property: "shakeOffset"; to: 0; duration: 55; easing.type: Easing.OutQuad }
|
||||
NumberAnimation { target: root; property: "shakeOffset"; to: -8; duration: Style.duration(35); easing.type: Easing.OutQuad }
|
||||
NumberAnimation { target: root; property: "shakeOffset"; to: 8; duration: Style.duration(50); easing.type: Easing.InOutQuad }
|
||||
NumberAnimation { target: root; property: "shakeOffset"; to: 0; duration: Style.duration(55); easing.type: Easing.OutQuad }
|
||||
}
|
||||
FileView {
|
||||
path: "/etc/pam.d/polkit-1"
|
||||
|
||||
@@ -40,7 +40,7 @@ BarWidget {
|
||||
font.pixelSize: Style.font.body
|
||||
Behavior on color {
|
||||
enabled: !root.bar || root.bar.foregroundAnimationEnabled
|
||||
ColorAnimation { duration: 160 }
|
||||
ColorAnimation { duration: Style.duration(160) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,7 +65,9 @@ BarWidget {
|
||||
|
||||
NumberAnimation on x {
|
||||
id: scrollAnim
|
||||
running: labelText.needsScroll && !root.popupOpen && !root.bar.vertical
|
||||
running: labelText.needsScroll && !root.popupOpen && !root.bar.vertical && !Style.reduceMotion
|
||||
// Stopped for reduced motion, the title reads from its start again.
|
||||
onRunningChanged: if (!running && Style.reduceMotion) labelText.x = 0
|
||||
loops: Animation.Infinite
|
||||
duration: Math.max(6000, labelText.implicitWidth * 25)
|
||||
from: scrollClip.width
|
||||
|
||||
@@ -84,3 +84,30 @@ pass "fullscreen off leaves full screen"
|
||||
HOME="$test_home" omarchy-toggle-fullscreen-desktop on
|
||||
[[ -f $bar_flag && -f $gaps_flag ]] || fail "fullscreen on enters full screen"
|
||||
pass "fullscreen on enters full screen"
|
||||
|
||||
# The flag records animations being off, so on and off are the other way round.
|
||||
printf '#!/bin/bash\nexit 0\n' >"$stub_bin/omarchy-notification-send"
|
||||
chmod +x "$stub_bin/omarchy-notification-send"
|
||||
animations_flag="$test_home/.local/state/omarchy/toggles/hypr/no-animations.lua"
|
||||
|
||||
HOME="$test_home" omarchy-toggle-animations off
|
||||
[[ -f $animations_flag ]] || fail "animations off places the no-animations flag"
|
||||
HOME="$test_home" omarchy-toggle-animations on
|
||||
[[ ! -f $animations_flag ]] || fail "animations on removes the no-animations flag"
|
||||
HOME="$test_home" omarchy-toggle-animations
|
||||
[[ -f $animations_flag ]] || fail "toggling animations flips the flag"
|
||||
pass "animations toggle turns the no-animations flag the right way round"
|
||||
|
||||
# A VM install starts without animations; other machines keep them.
|
||||
for virt in vm none; do
|
||||
rm -rf "$test_home/.local/state/omarchy/toggles/hypr"
|
||||
printf '#!/bin/bash\n[[ %s == vm ]]\n' "$virt" >"$stub_bin/omarchy-hw-vm"
|
||||
chmod +x "$stub_bin/omarchy-hw-vm"
|
||||
HOME="$test_home" OMARCHY_PATH="$ROOT" bash "$ROOT/install/user/hardware/vm-no-animations.sh" >/dev/null
|
||||
if [[ $virt == "vm" ]]; then
|
||||
[[ -f $animations_flag ]] || fail "a VM install turns animations off"
|
||||
else
|
||||
[[ ! -f $animations_flag ]] || fail "a machine that is not a VM keeps its animations"
|
||||
fi
|
||||
done
|
||||
pass "a VM install starts without animations"
|
||||
Reference in new issue
Block a user