Merge upstream quattro for the Qt 6.12 palette fix (#14553)
Qt 6.12 shadows the bare Color singleton, so the bar and every Color role read undefined on fresh installs. Keep our I18n text in the four conflicting files, qualify #14433's notification button color, give the new dictation menu rows and notifications Chinese, and drop table entries for the removed Voxtype and FIDO2 texts.
This commit is contained in:
commit
fcd681c099
239 files changed
+3996
-616
No files matched your search
@@ -49,3 +49,7 @@ unicode characters. Agent file-editing tools can strip multi-byte codepoints
|
||||
in some positions — do **not** rewrite widget files wholesale through those
|
||||
tools. For glyph fixes, make a targeted edit with the surrounding context, or
|
||||
use a Python script that inserts codepoints via `chr(0xXXXXX)`.
|
||||
|
||||
## Palette references
|
||||
|
||||
Import `qs.Commons as Commons` and use `Commons.Color` for the palette singleton, including `Connections.target`. Qt 6.12 introduces a `Color` type in `QtQuick` that shadows unqualified palette references. This applies to first-party components and third-party plugin QML alike. Keep the unqualified `qs.Commons` import when the file also uses `Style`, `Util`, or `Border`.
|
||||
@@ -46,6 +46,7 @@ GROUP_DESCRIPTIONS[finalize]="Finalize user setup"
|
||||
GROUP_DESCRIPTIONS[default]="Default application selection"
|
||||
GROUP_DESCRIPTIONS[dev]="Omarchy development tools"
|
||||
GROUP_DESCRIPTIONS[disk]="Disk performance helpers"
|
||||
GROUP_DESCRIPTIONS[dictation]="Dictation recording"
|
||||
GROUP_DESCRIPTIONS[display]="Display and text scaling"
|
||||
GROUP_DESCRIPTIONS[dns]="DNS resolver configuration"
|
||||
GROUP_DESCRIPTIONS[drive]="Drive selection and encryption"
|
||||
|
||||
Executable
+37
@@ -0,0 +1,37 @@
|
||||
#!/bin/bash
|
||||
|
||||
# omarchy:summary=Get or set the default dictation backend
|
||||
# omarchy:args=[backend]
|
||||
# omarchy:examples=omarchy default dictation | omarchy default dictation superwhisper
|
||||
|
||||
if (($# > 1)); then
|
||||
echo "Usage: omarchy default dictation [backend]" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if (($# == 0)); then
|
||||
config="${XDG_CONFIG_HOME:-$HOME/.config}/omarchy/defaults/dictation"
|
||||
if [[ ! -s $config ]]; then
|
||||
echo "No dictation backend configured. Select one in Setup > Defaults > Dictation." >&2
|
||||
exit 1
|
||||
fi
|
||||
read -r backend < "$config"
|
||||
else
|
||||
backend=$1
|
||||
fi
|
||||
|
||||
if [[ ! $backend =~ ^[a-z0-9][a-z0-9-]*$ ]]; then
|
||||
echo "Invalid dictation backend: $backend" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if (($# == 0)); then
|
||||
echo "$backend"
|
||||
else
|
||||
installer="omarchy-install-dictation-$backend"
|
||||
if omarchy-cmd-missing "$installer"; then
|
||||
echo "No installer available for dictation backend: $backend" >&2
|
||||
exit 1
|
||||
fi
|
||||
omarchy-launch-floating-terminal-with-presentation "$installer"
|
||||
fi
|
||||
Executable
+26
@@ -0,0 +1,26 @@
|
||||
#!/bin/bash
|
||||
|
||||
# omarchy:summary=Record dictation with the configured backend
|
||||
# omarchy:args=<start|stop|toggle>
|
||||
# omarchy:examples=omarchy dictation start | omarchy dictation toggle
|
||||
|
||||
if (($# != 1)) || [[ $1 != "start" && $1 != "stop" && $1 != "toggle" ]]; then
|
||||
echo "Usage: omarchy dictation <start|stop|toggle>" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
config="${XDG_CONFIG_HOME:-$HOME/.config}/omarchy/defaults/dictation"
|
||||
mkdir -p "${config%/*}"
|
||||
exec 9> "$config.lock"
|
||||
if ! flock -w 5 9; then
|
||||
echo "Dictation is busy; try again." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
backend=$(omarchy-default-dictation) || exit 1
|
||||
adapter="omarchy-dictation-$backend"
|
||||
if omarchy-cmd-missing "$adapter"; then
|
||||
echo "The selected dictation backend ($backend) is not installed." >&2
|
||||
exit 1
|
||||
fi
|
||||
"$adapter" "$1" 9>&-
|
||||
Executable
+17
@@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
|
||||
# omarchy:summary=Record dictation using Superwhisper
|
||||
# omarchy:args=<start|stop|toggle>
|
||||
|
||||
case "${1:-}" in
|
||||
start) superwhisper start ;;
|
||||
stop)
|
||||
if omarchy-cmd-missing superwhisper || ! systemctl --user is-active --quiet superwhisper.service; then
|
||||
exit 0
|
||||
else
|
||||
superwhisper stop
|
||||
fi
|
||||
;;
|
||||
toggle) superwhisper record ;;
|
||||
*) echo "Usage: omarchy dictation superwhisper <start|stop|toggle>" >&2; exit 1 ;;
|
||||
esac
|
||||
Executable
+33
@@ -0,0 +1,33 @@
|
||||
#!/bin/bash
|
||||
|
||||
# omarchy:hidden=true
|
||||
# omarchy:summary=Save a configured dictation backend after stopping the previous backend
|
||||
# omarchy:args=<backend>
|
||||
|
||||
set -e
|
||||
|
||||
if (($# != 1)) || [[ ! $1 =~ ^[a-z0-9][a-z0-9-]*$ ]]; then
|
||||
echo "Usage: omarchy-dictation-use <backend>" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
config="${XDG_CONFIG_HOME:-$HOME/.config}/omarchy/defaults/dictation"
|
||||
mkdir -p "${config%/*}"
|
||||
exec 9> "$config.lock"
|
||||
if ! flock -w 5 9; then
|
||||
echo "Dictation is busy; try again." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
previous=$(omarchy-default-dictation 2>/dev/null) || previous=""
|
||||
if [[ -n $previous && $previous != "$1" ]] && omarchy-cmd-present "omarchy-dictation-$previous"; then
|
||||
if ! "omarchy-dictation-$previous" stop 9>&-; then
|
||||
echo "Could not stop $previous; keeping the existing dictation backend." >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
temporary=$(mktemp "$config.XXXXXX")
|
||||
trap 'rm -f "$temporary"' EXIT
|
||||
printf '%s\n' "$1" > "$temporary"
|
||||
mv -f "$temporary" "$config"
|
||||
Executable
+16
@@ -0,0 +1,16 @@
|
||||
#!/bin/bash
|
||||
|
||||
# omarchy:summary=Record dictation using Voxtype
|
||||
# omarchy:args=<start|stop|toggle>
|
||||
|
||||
case "${1:-}" in
|
||||
start|toggle) voxtype record "$1" ;;
|
||||
stop)
|
||||
if omarchy-cmd-missing voxtype || [[ $(voxtype status) == "stopped" ]]; then
|
||||
exit 0
|
||||
else
|
||||
voxtype record stop
|
||||
fi
|
||||
;;
|
||||
*) echo "Usage: omarchy dictation voxtype <start|stop|toggle>" >&2; exit 1 ;;
|
||||
esac
|
||||
Executable
+27
@@ -0,0 +1,27 @@
|
||||
#!/bin/bash
|
||||
|
||||
# omarchy:summary=Install and configure Superwhisper dictation
|
||||
# omarchy:requires-sudo=true
|
||||
|
||||
set -e
|
||||
|
||||
omarchy-pkg-add superwhisper-bin
|
||||
bash /usr/share/superwhisper/setup-user
|
||||
# Existing profiles may still use Right Alt, which conflicts with Omarchy.
|
||||
# Keep a recording shortcut active while moving away from that binding.
|
||||
shortcuts=$(superwhisper shortcuts show)
|
||||
if [[ $(jq -r '.shortcuts.hold' <<< "$shortcuts") == "RightAlt" ]]; then
|
||||
if [[ -z $(jq -r '.shortcuts.toggle' <<< "$shortcuts") ]]; then
|
||||
superwhisper shortcuts set hold "RightSuper" >/dev/null
|
||||
else
|
||||
superwhisper shortcuts set hold none >/dev/null
|
||||
fi
|
||||
fi
|
||||
# Superwhisper requires a native recording shortcut; keep it separate from
|
||||
# Omarchy's push-to-talk keys.
|
||||
superwhisper shortcuts set toggle "Alt+Space" >/dev/null
|
||||
superwhisper shortcuts set hold none >/dev/null
|
||||
omarchy-dictation-use superwhisper
|
||||
hyprctl reload >/dev/null
|
||||
omarchy-notification-send -g "$(omarchy-text "Superwhisper Dictation Ready")" "$(omarchy-text "Hold Right Alt or F9 to dictate (or toggle with Super + Ctrl + X).")" -t 10000
|
||||
superwhisper settings
|
||||
Executable
+33
@@ -0,0 +1,33 @@
|
||||
#!/bin/bash
|
||||
|
||||
# omarchy:summary=Install and configure Voxtype dictation
|
||||
# omarchy:requires-sudo=true
|
||||
|
||||
set -e
|
||||
|
||||
if omarchy-cmd-missing voxtype; then
|
||||
if gum confirm "Install Voxtype + AI model (~150MB) to enable dictation?"; then
|
||||
omarchy-pkg-add wtype voxtype-bin
|
||||
else
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
config_home="${XDG_CONFIG_HOME:-$HOME/.config}"
|
||||
mkdir -p "$config_home/voxtype"
|
||||
if [[ ! -e $config_home/voxtype/config.toml ]]; then
|
||||
cp "$OMARCHY_PATH/default/voxtype/config.toml" "$config_home/voxtype/"
|
||||
if omarchy-hw-vulkan; then
|
||||
voxtype setup gpu --enable || true
|
||||
fi
|
||||
fi
|
||||
|
||||
# Setup reuses the configured model and downloads it only when missing.
|
||||
# Retry these steps even when an earlier attempt already installed the binary.
|
||||
voxtype setup --download --no-post-install
|
||||
voxtype setup systemd
|
||||
systemctl --user enable --now voxtype.service
|
||||
|
||||
omarchy-dictation-use voxtype
|
||||
hyprctl reload >/dev/null
|
||||
omarchy-notification-send -g "$(omarchy-text "Voxtype Dictation Ready")" "$(omarchy-text "Hold Right Alt or F9 to dictate (or toggle with Super + Ctrl + X).")" -t 10000
|
||||
@@ -15,7 +15,9 @@
|
||||
# against a half-written tree, and that failed reload leaves a second engine
|
||||
# generation behind that turns the next restart's IPC kill into a crash.
|
||||
run_shell() {
|
||||
QS_DISABLE_FILE_WATCHER=1 QS_NO_RELOAD_POPUP=1 \
|
||||
local startup_background
|
||||
startup_background=$(readlink -f "$HOME/.local/state/omarchy/current/background" 2>/dev/null)
|
||||
OMARCHY_STARTUP_BACKGROUND="$startup_background" QS_DISABLE_FILE_WATCHER=1 QS_NO_RELOAD_POPUP=1 \
|
||||
systemd-cat -t omarchy-shell -- quickshell -n -p "$OMARCHY_PATH/shell" &
|
||||
shell_pid=$!
|
||||
|
||||
|
||||
@@ -68,8 +68,6 @@ run_first_run_step() {
|
||||
fi
|
||||
}
|
||||
|
||||
run_first_run_step "install Voxtype post-update hook" \
|
||||
omarchy-hook-install post-update "$OMARCHY_PATH/install/user/first-run/install-voxtype.hook"
|
||||
run_first_run_step "install fingerprint setup post-update hook" \
|
||||
omarchy-hook-install post-update "$OMARCHY_PATH/install/user/first-run/setup-fingerprint.hook"
|
||||
run_first_run_step "install agent setup post-update hook" \
|
||||
|
||||
Executable
+40
@@ -0,0 +1,40 @@
|
||||
#!/bin/bash
|
||||
|
||||
# omarchy:summary=Remove Superwhisper dictation and its desktop integration
|
||||
# omarchy:requires-sudo=true
|
||||
|
||||
set -e
|
||||
|
||||
config_home="${XDG_CONFIG_HOME:-$HOME/.config}"
|
||||
data_home="${XDG_DATA_HOME:-$HOME/.local/share}"
|
||||
|
||||
systemctl --user disable --now superwhisper.service 2>/dev/null || true
|
||||
omarchy-shell -q shell setPluginEnabled superwhisper.panel false >/dev/null
|
||||
omarchy-pkg-drop superwhisper-bin
|
||||
systemctl --user daemon-reload
|
||||
|
||||
# Remove the package setup's links, preserving independently installed copies
|
||||
# and the user's preferences, history, and models.
|
||||
unlink_package_link() {
|
||||
if [[ -L $1 && $(readlink "$1") == "$2" ]]; then
|
||||
rm "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
unlink_package_link "$HOME/.local/bin/superwhisper" /usr/bin/superwhisper
|
||||
unlink_package_link "$data_home/superwhisper/app/current" /opt/superwhisper
|
||||
unlink_package_link "$config_home/omarchy/plugins/superwhisper-panel" /opt/superwhisper/assets/omarchy-plugin/superwhisper-panel
|
||||
for agent in .agents .claude .codex .pi/agent; do
|
||||
unlink_package_link "$HOME/$agent/skills/superwhisper" /opt/superwhisper/assets/agent-skill/superwhisper
|
||||
done
|
||||
|
||||
backend_config="$config_home/omarchy/defaults/dictation"
|
||||
if [[ -f $backend_config && $(< "$backend_config") == "superwhisper" ]]; then
|
||||
rm "$backend_config"
|
||||
fi
|
||||
|
||||
omarchy-shell -q shell rescanPlugins
|
||||
hyprctl reload >/dev/null
|
||||
if systemctl --user -q is-active omarchy-fcitx5.service; then
|
||||
systemctl --user restart omarchy-fcitx5.service
|
||||
fi
|
||||
@@ -18,6 +18,10 @@ if omarchy-cmd-present voxtype; then
|
||||
omarchy-pkg-drop voxtype-bin
|
||||
rm -rf ~/.config/voxtype
|
||||
rm -rf ~/.local/share/voxtype
|
||||
backend_config="${XDG_CONFIG_HOME:-$HOME/.config}/omarchy/defaults/dictation"
|
||||
if [[ -f $backend_config && $(< "$backend_config") == "voxtype" ]]; then
|
||||
rm "$backend_config"
|
||||
fi
|
||||
hyprctl reload >/dev/null
|
||||
else
|
||||
echo "Voxtype was not installed."
|
||||
Executable
+201
@@ -0,0 +1,201 @@
|
||||
#!/bin/bash
|
||||
|
||||
# omarchy:summary=Play the current background's matching theme intro
|
||||
# omarchy:hidden=true
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
state_home="$HOME/.local/state"
|
||||
current_dir="$state_home/omarchy/current"
|
||||
current_background_link="$current_dir/background"
|
||||
marker="$state_home/omarchy/background-intro.session-id"
|
||||
toggle="$state_home/omarchy/toggles/background-intros-off"
|
||||
video_extensions=(mp4 m4v mov webm mkv avi)
|
||||
|
||||
resolve_intro() {
|
||||
local background
|
||||
local stem
|
||||
local extension
|
||||
local intro
|
||||
|
||||
background=$(readlink -f "${1:-$current_background_link}" 2>/dev/null) || return 1
|
||||
[[ -f $background ]] || return 1
|
||||
case ${background,,} in
|
||||
*.jpg | *.jpeg | *.png | *.bmp | *.webp) ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
|
||||
stem=${background##*/}
|
||||
stem=${stem%.*}
|
||||
for extension in "${video_extensions[@]}"; do
|
||||
intro="${background%/*}/intros/$stem.$extension"
|
||||
if [[ -f $intro ]]; then
|
||||
printf '%s\n' "$intro"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
# Preparation is speculative: the selected staged clip is compared again by OWE.
|
||||
prepare_theme_intro() {
|
||||
local theme="$1" background remembered name source intro
|
||||
local -a names=()
|
||||
[[ -n $theme && $theme != .* && $theme != */* ]] || return 0
|
||||
[[ ! -f $toggle ]] && ! animations_off || return 0
|
||||
owe warm >/dev/null 2>&1 || return 0
|
||||
[[ $(cat "$current_dir/theme.name" 2>/dev/null) != "$theme" ]] || return 0
|
||||
remembered=$(cat "$state_home/omarchy/theme-backgrounds/$theme" 2>/dev/null || true)
|
||||
if [[ ${remembered%/*} == "$current_dir/theme/backgrounds" ]]; then
|
||||
name=${remembered##*/}
|
||||
elif [[ -f $remembered ]]; then
|
||||
background="$remembered"
|
||||
else
|
||||
mapfile -d '' -t names < <(
|
||||
find -L "$HOME/.config/omarchy/backgrounds/$theme" -maxdepth 1 -type f -print0 2>/dev/null | sort -z
|
||||
)
|
||||
if (( ${#names[@]} > 0 )); then
|
||||
background=${names[0]}
|
||||
else
|
||||
mapfile -d '' -t names < <(
|
||||
find -L "$OMARCHY_PATH/themes/$theme/backgrounds" "$HOME/.config/omarchy/themes/$theme/backgrounds" -maxdepth 1 -type f \
|
||||
\( -iname '*.jpg' -o -iname '*.jpeg' -o -iname '*.png' -o -iname '*.bmp' -o -iname '*.webp' \) -printf '%f\0' 2>/dev/null | sort -zu
|
||||
)
|
||||
(( ${#names[@]} > 0 )) || return 0
|
||||
name=${names[0]}
|
||||
fi
|
||||
fi
|
||||
if [[ -n ${name:-} ]]; then
|
||||
for source in "$HOME/.config/omarchy/themes/$theme" "$OMARCHY_PATH/themes/$theme"; do
|
||||
if [[ -f $source/backgrounds/$name ]]; then
|
||||
background="$source/backgrounds/$name"
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
[[ -n ${background:-} ]] || return 0
|
||||
intro=$(resolve_intro "$background" || true)
|
||||
[[ -z $intro ]] || owe intro-prepare "$intro" >/dev/null 2>&1 || true
|
||||
}
|
||||
|
||||
animations_off() {
|
||||
[[ $(hyprctl -j getoption animations:enabled 2>/dev/null | jq -r '.bool' 2>/dev/null) == "false" ]]
|
||||
}
|
||||
|
||||
theme_switch=false
|
||||
intro_prepared=false
|
||||
expected_background=""
|
||||
expected_theme=""
|
||||
case ${1:-} in
|
||||
"") ;;
|
||||
--prepare-theme)
|
||||
prepare_theme_intro "${2:-}"
|
||||
exit 0
|
||||
;;
|
||||
--resolve-only)
|
||||
resolve_intro "${2:-}" || true
|
||||
exit 0
|
||||
;;
|
||||
--resolve-startup)
|
||||
if [[ ! -f $toggle ]] && ! animations_off; then
|
||||
resolve_intro || true
|
||||
fi
|
||||
exit 0
|
||||
;;
|
||||
--theme-switch)
|
||||
theme_switch=true
|
||||
expected_background=$(readlink -f "${2:-}" 2>/dev/null) || exit 1
|
||||
expected_theme=${3:-}
|
||||
intro_prepared=${4:-false}
|
||||
[[ -n $expected_theme ]] || exit 1
|
||||
;;
|
||||
*)
|
||||
echo "Usage: omarchy-theme-bg-boot-intro [--resolve-only [background]|--resolve-startup|--prepare-theme theme|--theme-switch background theme-id [prepared]]" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
if [[ $theme_switch == false ]]; then
|
||||
mkdir -p "$(dirname "$marker")"
|
||||
exec 9>"$state_home/omarchy/background-intro.lock"
|
||||
flock 9
|
||||
|
||||
session_id=${OMARCHY_SESSION_ID:-${HYPRLAND_INSTANCE_SIGNATURE:-}}
|
||||
[[ -n $session_id ]] || exit 0
|
||||
if [[ -f $marker && $(<"$marker") == "$session_id" ]]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
marker_staged=$(mktemp "$state_home/omarchy/.background-intro.session-id.XXXXXX")
|
||||
trap 'rm -f "$marker_staged"' EXIT
|
||||
printf '%s\n' "$session_id" >"$marker_staged"
|
||||
mv -f "$marker_staged" "$marker"
|
||||
trap - EXIT
|
||||
exec 9>&-
|
||||
fi
|
||||
|
||||
selection_current() {
|
||||
[[ $(readlink -f "$current_background_link") == "$expected_background" &&
|
||||
$(stat -Lc '%d:%i' "$current_dir/theme" 2>/dev/null) == "$expected_theme" ]]
|
||||
}
|
||||
|
||||
if [[ $theme_switch == true ]] && ! selection_current; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ -f $toggle ]] || animations_off; then
|
||||
[[ $theme_switch == false ]] || exit 1
|
||||
exit 0
|
||||
fi
|
||||
|
||||
intro=$(resolve_intro || true)
|
||||
if [[ -z $intro ]]; then
|
||||
[[ $theme_switch == false ]] || exit 1
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ $theme_switch == true && $intro_prepared != "true" ]]; then
|
||||
owe refresh >/dev/null || exit 1
|
||||
elif [[ $theme_switch == false ]]; then
|
||||
deadline=$((SECONDS + 5))
|
||||
while ! timeout 1 owe status >/dev/null 2>&1; do
|
||||
if (( SECONDS >= deadline )); then
|
||||
exit 0
|
||||
fi
|
||||
sleep 0.2
|
||||
done
|
||||
(( SECONDS < deadline )) || exit 0
|
||||
fi
|
||||
|
||||
# The asynchronous outgoing cover must reach the compositor before playback
|
||||
# can hide the shell background. Older shells have no readiness method.
|
||||
if [[ $theme_switch == true ]]; then
|
||||
deadline=$((SECONDS + 3))
|
||||
while true; do
|
||||
cover_status=$(omarchy-shell shell themeIntroCoverStatus "$expected_theme" 2>/dev/null || true)
|
||||
case $cover_status in
|
||||
loading)
|
||||
(( SECONDS < deadline )) || exit 1
|
||||
sleep 0.01
|
||||
;;
|
||||
error) exit 1 ;;
|
||||
superseded) exit 0 ;;
|
||||
*) break ;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
|
||||
if [[ $theme_switch == true ]] && ! selection_current; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# A selection or setting changed while OWE was starting no longer permits this intro.
|
||||
if [[ ! -f $toggle && $intro == "$(resolve_intro || true)" ]] && ! animations_off; then
|
||||
if [[ $theme_switch == true && $intro_prepared == "true" ]]; then
|
||||
owe intro --start first-frame --refresh "$intro"
|
||||
else
|
||||
owe intro --start first-frame "$intro"
|
||||
fi
|
||||
elif [[ $theme_switch == true ]]; then
|
||||
exit 1
|
||||
fi
|
||||
Executable
+34
@@ -0,0 +1,34 @@
|
||||
#!/bin/bash
|
||||
|
||||
# omarchy:summary=Enable or disable background intros
|
||||
# omarchy:args=<enable|disable|toggle|status>
|
||||
# omarchy:examples=omarchy theme bg intro toggle | omarchy theme bg intro disable
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
toggle="$HOME/.local/state/omarchy/toggles/background-intros-off"
|
||||
case ${1:-} in
|
||||
enable)
|
||||
rm -f "$toggle"
|
||||
omarchy-notification-send "$(omarchy-text "Background Intros")" "$(omarchy-text "Enabled")"
|
||||
;;
|
||||
disable)
|
||||
mkdir -p "$(dirname "$toggle")"
|
||||
touch "$toggle"
|
||||
omarchy-notification-send "$(omarchy-text "Background Intros")" "$(omarchy-text "Disabled")"
|
||||
;;
|
||||
toggle)
|
||||
if [[ -f $toggle ]]; then
|
||||
omarchy-theme-bg-intro enable
|
||||
else
|
||||
omarchy-theme-bg-intro disable
|
||||
fi
|
||||
;;
|
||||
status)
|
||||
[[ ! -f $toggle ]]
|
||||
;;
|
||||
*)
|
||||
echo "Usage: omarchy-theme-bg-intro <enable|disable|toggle|status>" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
+84
-6
@@ -50,6 +50,13 @@ shell_ipc() {
|
||||
timeout 2 omarchy-shell "$@" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
wait_for_theme_intro() {
|
||||
local method="$1" token="$2" pending="$3" deadline=$((SECONDS + 3))
|
||||
while (( SECONDS < deadline )) && [[ $(omarchy-shell shell "$method" "$token" 2>/dev/null) == "$pending" ]]; do
|
||||
sleep 0.02
|
||||
done
|
||||
}
|
||||
|
||||
is_video_path() {
|
||||
[[ ${1,,} =~ \.(mp4|m4v|mov|webm|mkv|avi)$ ]]
|
||||
}
|
||||
@@ -70,10 +77,18 @@ snapshot_background_path() {
|
||||
}
|
||||
|
||||
snapshot_current_background() {
|
||||
local current_background
|
||||
local current_background snapshot
|
||||
|
||||
current_background=$(readlink -f "$CURRENT_BACKGROUND_LINK" 2>/dev/null || true)
|
||||
snapshot_background_path "$current_background" "previous"
|
||||
# An interrupted intro is still moving; its final still would flash as a
|
||||
# cover. Capture the frame already playing instead, when OWE supports it.
|
||||
mkdir -p "$BACKGROUND_TRANSITION_CACHE"
|
||||
snapshot="$BACKGROUND_TRANSITION_CACHE/previous-$$.ppm"
|
||||
if owe render "$(jq -nc --arg path "$snapshot" '{cmd: "snapshot", path: $path}')" >/dev/null 2>&1; then
|
||||
echo "$snapshot"
|
||||
else
|
||||
current_background=$(readlink -f "$CURRENT_BACKGROUND_LINK" 2>/dev/null || true)
|
||||
snapshot_background_path "$current_background" "previous"
|
||||
fi
|
||||
}
|
||||
|
||||
theme_background_state_file() {
|
||||
@@ -171,7 +186,7 @@ set_theme_background_link() {
|
||||
}
|
||||
|
||||
set_theme_background() {
|
||||
local new_background new_background_snapshot
|
||||
local new_background new_background_snapshot theme_id intro_prepared=false
|
||||
|
||||
if [[ -z $CHOSEN_THEME_BACKGROUND || ! -f $CHOSEN_THEME_BACKGROUND ]]; then
|
||||
if ! choose_theme_background; then
|
||||
@@ -182,6 +197,37 @@ set_theme_background() {
|
||||
fi
|
||||
|
||||
new_background="$CHOSEN_THEME_BACKGROUND"
|
||||
if [[ -n $THEME_BACKGROUND_INTRO ]]; then
|
||||
if [[ -n $INTRO_PREPARE_PID ]] && wait "$INTRO_PREPARE_PID"; then
|
||||
intro_prepared=true
|
||||
fi
|
||||
theme_id=$(stat -Lc '%d:%i' "$CURRENT_THEME_PATH")
|
||||
THEME_INTRO_TOKEN="$theme_id"
|
||||
shell_ipc shell prepareThemeIntro "$OLD_BACKGROUND_SNAPSHOT" "$theme_id" "$colors_payload" "$shell_payload" || \
|
||||
shell_ipc shell applyTheme "$colors_payload" "$shell_payload" || true
|
||||
ln -nsf "$new_background" "$CURRENT_BACKGROUND_LINK"
|
||||
(
|
||||
if ! omarchy-theme-bg-boot-intro --theme-switch "$new_background" "$theme_id" "$intro_prepared"; then
|
||||
if [[ $(readlink -f "$CURRENT_BACKGROUND_LINK") == "$(readlink -f "$new_background")" &&
|
||||
$(stat -Lc '%d:%i' "$CURRENT_THEME_PATH" 2>/dev/null) == "$theme_id" ]]; then
|
||||
shell_ipc background setInstant "$new_background" || true
|
||||
fi
|
||||
fi
|
||||
shell_ipc shell finishThemeIntro "$theme_id" || true
|
||||
wait_for_theme_intro themeIntroStatus "$theme_id" "pending"
|
||||
# Reloading Hyprland interrupts video presentation. Wait for playback,
|
||||
# then serialize with theme selection so an old intro cannot reload
|
||||
# the compositor during the next theme's video.
|
||||
(
|
||||
flock 9
|
||||
if [[ $(stat -Lc '%d:%i' "$CURRENT_THEME_PATH" 2>/dev/null) == "$theme_id" ]]; then
|
||||
omarchy-restart-hyprctl
|
||||
fi
|
||||
) 9>"$THEME_SET_LOCK"
|
||||
[[ -z $OLD_BACKGROUND_SNAPSHOT ]] || rm -f "$OLD_BACKGROUND_SNAPSHOT"
|
||||
) 9>&- &
|
||||
return
|
||||
fi
|
||||
new_background_snapshot=""
|
||||
if [[ -n $PREPARED_BACKGROUND_SNAPSHOT && $PREPARED_BACKGROUND == "$new_background" ]]; then
|
||||
new_background_snapshot="$PREPARED_BACKGROUND_SNAPSHOT"
|
||||
@@ -337,6 +383,12 @@ fi
|
||||
exec 9>"$THEME_SET_LOCK"
|
||||
flock 9
|
||||
|
||||
# A current video frame only represents the screen after its opening fade.
|
||||
# Finish that short reveal before capturing the next outgoing cover.
|
||||
if [[ $THEME_HEADLESS != "1" && $OMARCHY_THEME_SKIP_BACKGROUND != "1" ]]; then
|
||||
wait_for_theme_intro themeIntroStatus "$(stat -Lc '%d:%i' "$CURRENT_THEME_PATH" 2>/dev/null)" "pending"
|
||||
fi
|
||||
|
||||
PREVIOUS_THEME_NAME=$(cat "$CURRENT_THEME_NAME_PATH" 2>/dev/null || true)
|
||||
remember_current_theme_background
|
||||
|
||||
@@ -365,11 +417,24 @@ OLD_BACKGROUND_SNAPSHOT=""
|
||||
PREPARED_BACKGROUND=""
|
||||
PREPARED_BACKGROUND_SNAPSHOT=""
|
||||
BACKGROUND_TRANSITION_SNAPSHOTS=true
|
||||
THEME_BACKGROUND_INTRO=""
|
||||
INTRO_PREPARE_PID=""
|
||||
THEME_INTRO_TOKEN=""
|
||||
if [[ $THEME_HEADLESS != "1" && $OMARCHY_THEME_SKIP_BACKGROUND != "1" ]]; then
|
||||
# Resolve the staged choice while the old theme still exists. Video changes
|
||||
# switch directly to the durable path in QML, so neither side needs a copy.
|
||||
if choose_staged_theme_background; then
|
||||
if background_transition_uses_snapshots "$CHOSEN_THEME_BACKGROUND"; then
|
||||
if [[ $PREVIOUS_THEME_NAME != "$THEME_NAME" && ! -f $HOME/.local/state/omarchy/toggles/background-intros-off ]] &&
|
||||
[[ $(hyprctl -j getoption animations:enabled 2>/dev/null | jq -r '.bool') == "true" ]]; then
|
||||
THEME_BACKGROUND_INTRO=$(omarchy-theme-bg-boot-intro --resolve-only "$STAGED_THEME_BACKGROUND")
|
||||
fi
|
||||
if [[ -n $THEME_BACKGROUND_INTRO ]]; then
|
||||
OLD_BACKGROUND_SNAPSHOT=$(snapshot_current_background)
|
||||
# OWE retains the opened clip across the staged directory's rename.
|
||||
owe intro-prepare "$THEME_BACKGROUND_INTRO" >/dev/null 2>&1 9>&- &
|
||||
INTRO_PREPARE_PID=$!
|
||||
shell_ipc shell prepareThemeIntro "$OLD_BACKGROUND_SNAPSHOT" "$(stat -Lc '%d:%i' "$NEXT_THEME_PATH")" "" "" || true
|
||||
elif background_transition_uses_snapshots "$CHOSEN_THEME_BACKGROUND"; then
|
||||
OLD_BACKGROUND_SNAPSHOT=$(snapshot_current_background)
|
||||
|
||||
# Hand the shell the next background now, so it decodes while the
|
||||
@@ -389,6 +454,12 @@ fi
|
||||
# Generate dynamic configs
|
||||
omarchy-theme-set-templates
|
||||
|
||||
# Replacing the theme's still can cancel an active OWE intro even before the
|
||||
# background link changes. Present its cover before replacing either path.
|
||||
if [[ -n $THEME_BACKGROUND_INTRO ]]; then
|
||||
wait_for_theme_intro themeIntroCoverStatus "$(stat -Lc '%d:%i' "$NEXT_THEME_PATH")" "loading"
|
||||
fi
|
||||
|
||||
# Swap next theme in as current
|
||||
rm -rf "$CURRENT_THEME_PATH"
|
||||
mv "$NEXT_THEME_PATH" "$CURRENT_THEME_PATH"
|
||||
@@ -418,7 +489,6 @@ flock -u 9
|
||||
|
||||
post_theme_commands=(
|
||||
omarchy-restart-terminal
|
||||
omarchy-restart-hyprctl
|
||||
omarchy-restart-btop
|
||||
omarchy-restart-opencode
|
||||
omarchy-restart-helix
|
||||
@@ -437,6 +507,14 @@ post_theme_commands=(
|
||||
)
|
||||
|
||||
if [[ $THEME_HEADLESS != "1" ]]; then
|
||||
# Let the wallpaper and bar finish their reveal before app retints compete
|
||||
# with decoding and the shell's frame rendering. An intro reloads Hyprland
|
||||
# after playback; ordinary theme changes reload it with the app retints.
|
||||
if [[ -n $THEME_INTRO_TOKEN ]]; then
|
||||
wait_for_theme_intro themeIntroStatus "$THEME_INTRO_TOKEN" "pending"
|
||||
else
|
||||
post_theme_commands+=(omarchy-restart-hyprctl)
|
||||
fi
|
||||
run_parallel "${post_theme_commands[@]}"
|
||||
|
||||
# Call hook on theme set
|
||||
|
||||
@@ -29,6 +29,8 @@ if [[ -n $OMARCHY_THEME_SYNC_FROM ]] || ! omarchy-toggle-enabled herdr-theme-syn
|
||||
fi
|
||||
|
||||
theme=$(cat "$HOME/.local/state/omarchy/current/theme.name" 2>/dev/null)
|
||||
control_dir="$XDG_RUNTIME_DIR/omarchy-theme-sync"
|
||||
mkdir -m 700 -p "$control_dir"
|
||||
|
||||
# Runs on the remote machine under a login shell, so OMARCHY_PATH and PATH are set there.
|
||||
# SSH carries no desktop session, so the environment comes from the live Hyprland instance.
|
||||
@@ -66,10 +68,13 @@ read -r -d '' REMOTE_SCRIPT <<'EOF'
|
||||
} </dev/null
|
||||
EOF
|
||||
|
||||
# One machine at a time, so an SSH agent like 1Password asks for approval at most once.
|
||||
# Reuse each authenticated connection for ten idle minutes, so an SSH agent like
|
||||
# 1Password does not need to approve every theme change. Connect one machine at a time.
|
||||
# SSH joins its arguments into a shell command, so the theme travels on stdin as a quoted assignment.
|
||||
for target in $targets; do
|
||||
result=$(printf 'theme=%q from=%q\n%s\n' "$theme" "$(hostname)" "$REMOTE_SCRIPT" |
|
||||
timeout 60 ssh -o BatchMode=yes -o ConnectTimeout=5 "$target" bash -l -s 2>&1 | tail -n 1)
|
||||
timeout 60 ssh -o BatchMode=yes -o ConnectTimeout=5 \
|
||||
-o ControlMaster=auto -o ControlPersist=600 -o "ControlPath=$control_dir/%C" \
|
||||
"$target" bash -l -s 2>&1 | tail -n 1)
|
||||
echo "$(date '+%F %T') $target: ${result:-unreachable}"
|
||||
done
|
||||
@@ -1,26 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# omarchy:summary=Install and configure Voxtype dictation
|
||||
# omarchy:requires-sudo=true
|
||||
|
||||
set -e
|
||||
|
||||
# Install voxtype and configure it for use.
|
||||
|
||||
if gum confirm "Install Voxtype + AI model (~150MB) to enable dictation?"; then
|
||||
omarchy-pkg-add wtype voxtype-bin
|
||||
|
||||
# Setup voxtype
|
||||
mkdir -p ~/.config/voxtype
|
||||
cp "$OMARCHY_PATH/default/voxtype/config.toml" ~/.config/voxtype/
|
||||
|
||||
voxtype setup --download --no-post-install
|
||||
if omarchy-hw-vulkan; then
|
||||
voxtype setup gpu --enable || true
|
||||
fi
|
||||
voxtype setup systemd
|
||||
|
||||
hyprctl reload >/dev/null
|
||||
omarchy-restart-shell
|
||||
omarchy-notification-send -g "$(omarchy-text "Voxtype Dictation Ready")" "$(omarchy-text "Hold F9 to dictate (or toggle with Super + Ctrl + X).")" -t 10000
|
||||
fi
|
||||
@@ -1,13 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# omarchy:summary=Stream voxtype --follow status as bar-friendly JSON
|
||||
|
||||
if omarchy-cmd-missing voxtype; then
|
||||
echo '{"alt": "", "class": "idle", "tooltip": ""}'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Keep the status follower as the direct child of the bar. Quickshell
|
||||
# clean up their direct child when they restart; a shell pipeline/coproc would
|
||||
# leave `voxtype status --follow` orphaned under the user systemd instance.
|
||||
exec setpriv --pdeathsig TERM voxtype status --follow --extended --format json
|
||||
@@ -1,5 +1,5 @@
|
||||
--ozone-platform=wayland
|
||||
--ozone-platform-hint=wayland
|
||||
--password-store=gnome-libsecret
|
||||
--enable-features=TouchpadOverscrollHistoryNavigation
|
||||
--enable-features=TouchpadOverscrollHistoryNavigation,OverlayScrollbar
|
||||
--load-extension=/usr/share/omarchy/default/chromium/extensions/copy-url,/usr/share/omarchy/default/chromium/extensions/yt-dlp,/usr/share/omarchy/default/chromium/extensions/whatsapp-slim
|
||||
@@ -0,0 +1 @@
|
||||
superwhisper
|
||||
@@ -11,7 +11,7 @@
|
||||
#
|
||||
# To put it into use, remove .sample from this file name.
|
||||
|
||||
# Example: add an Include line above [core].
|
||||
# Example: add an Include line above the first repository, [omarchy].
|
||||
# Maintain the repo entries in /etc/pacman.d/custom-repos.conf yourself.
|
||||
|
||||
CONF=/etc/pacman.conf
|
||||
@@ -21,4 +21,4 @@ MARKER="Include = $SNIPPET"
|
||||
[[ -r $SNIPPET ]] || exit 0
|
||||
grep -qxF "$MARKER" "$CONF" && exit 0
|
||||
|
||||
sudo sed -i "0,/^\[core\]/s||$MARKER\n\n[core]|" "$CONF"
|
||||
sudo sed -i "0,/^\[omarchy\]/s||$MARKER\n\n[omarchy]|" "$CONF"
|
||||
@@ -6,12 +6,16 @@ hl.layer_rule({ match = { namespace = "omarchy-bar" }, no_anim = true, animation
|
||||
|
||||
-- Launcher, image selector, emojis, clipboard overlays, the OSD, reminders, the
|
||||
-- Wi-Fi QR code and keyboard-driven panels should pop without compositor layer
|
||||
-- animations. The overlays stay mapped between opens and grow from a parked
|
||||
-- 1x1 when shown, which Hyprland would otherwise animate as a slide in from
|
||||
-- the corner. Panels keep their own QML opacity transition for normal
|
||||
-- open/close, and skip it for panel handoff.
|
||||
-- animations. Overlays open as soon as their scale is ready, without a
|
||||
-- compositor fade or slide. Panels keep their own QML opacity transition
|
||||
-- for normal open/close, and skip it for panel handoff.
|
||||
hl.layer_rule({ match = { namespace = "^(omarchy-menu|omarchy-image-selector|omarchy-emojis|omarchy-clipboard|omarchy-keyboard-panel|omarchy-osd|omarchy-reminders|omarchy-network-qr)$" }, no_anim = true, animation = "none" })
|
||||
|
||||
-- A boot intro hands the desktop between OWE's video layer and the shell's
|
||||
-- background layer. The media fades itself, so a compositor fade on either
|
||||
-- layer only dips the screen toward the empty desktop during the handoff.
|
||||
hl.layer_rule({ match = { namespace = "^(omarchy-background|owe-background)$" }, no_anim = true, animation = "none" })
|
||||
|
||||
-- Dev gallery is the main shell workbench; open it maximized like
|
||||
-- SUPER+ALT+F so component previews have the whole workspace.
|
||||
o.window({ class = "^org.quickshell$", title = "^Omarchy shell – dev gallery$" }, { maximize = true })
|
||||
@@ -1,4 +1,12 @@
|
||||
require("default.hypr.startup-cursor")
|
||||
|
||||
hl.on("hyprland.start", function()
|
||||
-- Applications inherit the user's cursor; only the compositor starts blank.
|
||||
if omarchy_startup_cursor_pending then
|
||||
hl.env("XCURSOR_PATH", omarchy_startup_cursor.path)
|
||||
hl.env("XCURSOR_THEME", omarchy_startup_cursor.xcursor)
|
||||
end
|
||||
|
||||
-- Slow app launch fix -- set systemd vars before starting session services.
|
||||
hl.exec_cmd("systemctl --user import-environment $(env | cut -d'=' -f 1)")
|
||||
hl.exec_cmd("dbus-update-activation-environment --systemd --all")
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
if o.shell_succeeds("omarchy-default-dictation") then
|
||||
o.bind("SUPER + CTRL + X", "Toggle dictation", "omarchy-dictation toggle")
|
||||
o.bind("F9", "Start dictation (push-to-talk)", "omarchy-dictation start")
|
||||
o.bind("F9", "Stop dictation (push-to-talk)", "omarchy-dictation stop", { release = true })
|
||||
-- A modifier's mask changes between its press and release. Match the keysym
|
||||
-- independently of that mask; AltGr layouts use a different keysym.
|
||||
o.bind("ALT + Alt_R", "Start dictation (push-to-talk)", "omarchy-dictation start", { ignore_mods = true })
|
||||
o.bind("ALT + Alt_R", "Stop dictation (push-to-talk)", "omarchy-dictation stop", { release = true, ignore_mods = true })
|
||||
end
|
||||
@@ -1,5 +0,0 @@
|
||||
if o.cmd_present("voxtype") then
|
||||
o.bind("SUPER + CTRL + X", "Toggle dictation", "voxtype record toggle")
|
||||
o.bind("F9", "Start dictation (push-to-talk)", "voxtype record start")
|
||||
o.bind("F9", "Stop dictation (push-to-talk)", "voxtype record stop", { release = true })
|
||||
end
|
||||
Binary file not shown.
@@ -0,0 +1,24 @@
|
||||
-- Backends may supply their own desktop integration without editing the
|
||||
-- user's Hyprland config. Recording bindings remain owned by Omarchy.
|
||||
local paths = require("default.hypr.paths")
|
||||
local pipe = io.popen("omarchy-default-dictation 2>/dev/null", "r")
|
||||
if not pipe then
|
||||
return
|
||||
end
|
||||
|
||||
local backend = pipe:read("*l")
|
||||
pipe:close()
|
||||
|
||||
if not backend or not backend:match("^[%w%-]+$") or o.cmd_missing("omarchy-dictation-" .. backend) then
|
||||
return
|
||||
end
|
||||
|
||||
local integration = paths.config_home .. "/" .. backend .. "/shortcuts.lua"
|
||||
local file = io.open(integration, "r")
|
||||
if file then
|
||||
file:close()
|
||||
local ok, error = pcall(dofile, integration)
|
||||
if not ok then
|
||||
print("Could not load dictation backend " .. backend .. ": " .. tostring(error))
|
||||
end
|
||||
end
|
||||
@@ -104,6 +104,7 @@ hl.config({
|
||||
misc = {
|
||||
disable_hyprland_logo = true,
|
||||
disable_splash_rendering = true,
|
||||
background_color = "rgb(000000)",
|
||||
disable_scale_notification = true,
|
||||
focus_on_activate = true,
|
||||
anr_missed_pings = 3,
|
||||
|
||||
@@ -12,7 +12,7 @@ if _G.omarchy_default_bindings ~= false then
|
||||
require("default.hypr.bindings.jis")
|
||||
require("default.hypr.bindings.tiling")
|
||||
require("default.hypr.bindings.utilities")
|
||||
require("default.hypr.bindings.voxtype")
|
||||
require("default.hypr.bindings.dictation")
|
||||
require_optional.module("default.hypr.bindings.applications")
|
||||
end
|
||||
require("default.hypr.envs")
|
||||
@@ -20,6 +20,7 @@ require("default.hypr.looknfeel")
|
||||
require("default.hypr.qconsole")
|
||||
require("default.hypr.input")
|
||||
require("default.hypr.windows")
|
||||
require("default.hypr.dictation-backend")
|
||||
|
||||
-- Current theme overrides.
|
||||
require_optional.module("omarchy.current.theme.hyprland")
|
||||
@@ -0,0 +1,46 @@
|
||||
-- Hyprland polls cursor.invisible, so its first frames need a blank cursor too.
|
||||
function omarchy_startup_cursor_restore(loaded)
|
||||
if not omarchy_startup_cursor_pending then return end
|
||||
local cursor = omarchy_startup_cursor
|
||||
if loaded then
|
||||
omarchy_startup_cursor_pending = false
|
||||
hl.config({ cursor = cursor.config })
|
||||
if cursor.config.enable_hyprcursor and cursor.hyprcursor then
|
||||
hl.exec_cmd("hyprctl setcursor " .. o.shell_quote(cursor.hyprcursor) .. " " .. cursor.size)
|
||||
end
|
||||
elseif not cursor.restoring then
|
||||
-- Reload the normal Xcursor fallback before enabling Hyprcursor or GSettings.
|
||||
cursor.restoring = true
|
||||
hl.exec_cmd("hyprctl setcursor " .. o.shell_quote(cursor.xcursor) .. " " .. cursor.size
|
||||
.. " && hyprctl eval 'omarchy_startup_cursor_restore(true)'")
|
||||
end
|
||||
end
|
||||
|
||||
hl.on("config.reloaded", function()
|
||||
if omarchy_startup_cursor_pending == nil then
|
||||
-- Config updates in an existing compositor must not hide its pointer.
|
||||
omarchy_startup_cursor_pending = #hl.get_monitors() == 0
|
||||
if omarchy_startup_cursor_pending then
|
||||
local hyprcursor = hl.get_config("cursor.enable_hyprcursor")
|
||||
omarchy_startup_cursor = {
|
||||
config = {
|
||||
invisible = hl.get_config("cursor.invisible"),
|
||||
enable_hyprcursor = hyprcursor,
|
||||
sync_gsettings_theme = hl.get_config("cursor.sync_gsettings_theme"),
|
||||
},
|
||||
hyprcursor = os.getenv("HYPRCURSOR_THEME"),
|
||||
size = tonumber((hyprcursor and os.getenv("HYPRCURSOR_SIZE")) or os.getenv("XCURSOR_SIZE")) or 24,
|
||||
path = os.getenv("XCURSOR_PATH") or "~/.local/share/icons:~/.icons:/usr/share/icons:/usr/share/pixmaps",
|
||||
xcursor = os.getenv("XCURSOR_THEME") or "default",
|
||||
}
|
||||
if omarchy_startup_cursor.size <= 0 then omarchy_startup_cursor.size = 24 end
|
||||
hl.env("XCURSOR_PATH", os.getenv("OMARCHY_PATH") .. "/default/hypr/cursors:" .. omarchy_startup_cursor.path)
|
||||
hl.env("XCURSOR_THEME", "omarchy-startup")
|
||||
end
|
||||
end
|
||||
if omarchy_startup_cursor_pending then
|
||||
-- Keep the temporary cursor private to the compositor, including GSettings.
|
||||
hl.config({ cursor = { invisible = true, enable_hyprcursor = false, sync_gsettings_theme = false } })
|
||||
hl.timer(function() omarchy_startup_cursor_restore() end, { timeout = 15000, type = "oneshot" })
|
||||
end
|
||||
end)
|
||||
@@ -163,6 +163,9 @@
|
||||
"setup.default.browser.edge": {"icon":"","label":"Edge","checked":"[[ \"$(omarchy-default-browser)\" == \"edge\" ]]","action":"omarchy-default-browser edge"},
|
||||
"setup.default.browser.firefox": {"icon":"","label":"Firefox","checked":"[[ \"$(omarchy-default-browser)\" == \"firefox\" ]]","action":"omarchy-default-browser firefox"},
|
||||
"setup.default.browser.zen": {"icon":"","label":"Zen","checked":"[[ \"$(omarchy-default-browser)\" == \"zen\" ]]","action":"omarchy-default-browser zen"},
|
||||
"setup.default.dictation": {"icon":"","label":"Dictation","title":"Default Dictation"},
|
||||
"setup.default.dictation.superwhisper": {"icon":"","label":"Superwhisper","checked":"[[ \"$(omarchy-default-dictation)\" == \"superwhisper\" ]]","action":"omarchy-default-dictation superwhisper"},
|
||||
"setup.default.dictation.voxtype": {"icon":"","label":"Voxtype","checked":"[[ \"$(omarchy-default-dictation)\" == \"voxtype\" ]]","action":"omarchy-default-dictation voxtype"},
|
||||
"setup.default.terminal": {"icon":"","label":"Terminal","title":"Default Terminal"},
|
||||
"setup.default.terminal.alacritty": {"icon":"","label":"Alacritty","checked":"[[ \"$(omarchy-default-terminal)\" == \"alacritty\" ]]","action":"omarchy-default-terminal alacritty"},
|
||||
"setup.default.terminal.foot": {"icon":"","label":"Foot","checked":"[[ \"$(omarchy-default-terminal)\" == \"foot\" ]]","action":"omarchy-default-terminal foot"},
|
||||
@@ -267,7 +270,6 @@
|
||||
"install.terminal.kitty": {"icon":"","label":"Kitty","disabled":"omarchy-pkg-present kitty","action":"omarchy-launch-floating-terminal-with-presentation 'omarchy-install-terminal kitty'"},
|
||||
"install.ai.chatgpt": {"icon":"","iconFont":"omarchy","label":"ChatGPT Desktop","disabled":"omarchy-pkg-present openai-codex-desktop","action":"omarchy-launch-floating-terminal-with-presentation omarchy-install-ai-chatgpt"},
|
||||
"install.ai.claude": {"icon":"","iconFont":"omarchy","label":"Claude Desktop","disabled":"omarchy-pkg-present claude-desktop","action":"omarchy-launch-floating-terminal-with-presentation omarchy-install-ai-claude"},
|
||||
"install.ai.dictation": {"icon":"","label":"Dictation","disabled":"omarchy-pkg-present voxtype-bin","action":"omarchy-launch-floating-terminal-with-presentation omarchy-voxtype-install"},
|
||||
"install.ai.grok-bot": {"icon":"","iconFont":"omarchy","label":"Grok Bot","disabled":"omarchy-pkg-present grok-bot","action":"omarchy-install-and-launch 'Grok Bot' grok-bot grok-bot"},
|
||||
"install.ai.hermes": {"icon":"","iconFont":"omarchy","label":"Hermes Desktop","disabled":"omarchy-pkg-present hermes-desktop","action":"omarchy-launch-floating-terminal-with-presentation omarchy-install-ai-hermes"},
|
||||
"install.ai.lm-studio": {"icon":"","iconFont":"omarchy","label":"LM Studio","disabled":"omarchy-pkg-present lmstudio-bin","action":"omarchy-install-app 'LM Studio' lmstudio-bin"},
|
||||
@@ -311,6 +313,7 @@
|
||||
// Remove
|
||||
"remove.package": {"icon":"","label":"Package","action":"xdg-terminal-exec --app-id=org.omarchy.terminal omarchy-pkg-remove"},
|
||||
"remove.ai": {"icon":"","label":"AI","title":"Remove"},
|
||||
"remove.dictation": {"icon":"","label":"Dictation","when":"omarchy-pkg-present voxtype-bin || omarchy-pkg-present superwhisper-bin"},
|
||||
"remove.service": {"icon":"","label":"Services","title":"Remove"},
|
||||
"remove.development": {"icon":"","label":"Development","title":"Remove"},
|
||||
"remove.theme": {"icon":"","label":"Theme","action":"omarchy-theme-remove"},
|
||||
@@ -338,7 +341,8 @@
|
||||
"remove.service.ssh-agent": {"icon":"","label":"SSH Agent","when":"systemctl --user -q is-enabled gcr-ssh-agent.socket","action":"omarchy-launch-floating-terminal-with-presentation omarchy-remove-service-ssh-agent"},
|
||||
"remove.ai.chatgpt": {"icon":"","iconFont":"omarchy","label":"ChatGPT Desktop","when":"omarchy-pkg-present openai-codex-desktop","action":"omarchy-launch-floating-terminal-with-presentation omarchy-remove-ai-chatgpt"},
|
||||
"remove.ai.claude": {"icon":"","iconFont":"omarchy","label":"Claude Desktop","when":"omarchy-pkg-present claude-desktop","action":"omarchy-launch-floating-terminal-with-presentation omarchy-remove-ai-claude"},
|
||||
"remove.ai.dictation": {"icon":"","label":"Dictation","when":"omarchy-pkg-present voxtype-bin","action":"omarchy-launch-floating-terminal-with-presentation omarchy-voxtype-remove"},
|
||||
"remove.dictation.superwhisper": {"icon":"","label":"Superwhisper","when":"omarchy-pkg-present superwhisper-bin","action":"omarchy-launch-floating-terminal-with-presentation omarchy-remove-dictation-superwhisper"},
|
||||
"remove.dictation.voxtype": {"icon":"","label":"Voxtype","when":"omarchy-pkg-present voxtype-bin","action":"omarchy-launch-floating-terminal-with-presentation omarchy-remove-dictation-voxtype"},
|
||||
"remove.ai.grok-bot": {"icon":"","iconFont":"omarchy","label":"Grok Bot","when":"omarchy-pkg-present grok-bot","action":"omarchy-launch-floating-terminal-with-presentation omarchy-remove-ai-grok-bot"},
|
||||
"remove.ai.lm-studio": {"icon":"","iconFont":"omarchy","label":"LM Studio","when":"omarchy-pkg-present lmstudio-bin","action":"omarchy-launch-floating-terminal-with-presentation omarchy-remove-ai-lm-studio"},
|
||||
"remove.ai.ollama": {"icon":"","iconFont":"omarchy","label":"Ollama","when":"omarchy-pkg-present ollama","action":"omarchy-launch-floating-terminal-with-presentation omarchy-remove-ai-ollama"},
|
||||
|
||||
@@ -95,6 +95,7 @@
|
||||
"setup.network.qr": {"label":"二维码"},
|
||||
"setup.default": {"label":"默认程序"},
|
||||
"setup.default.agent": {"title":"默认 Agent"},
|
||||
"setup.default.dictation": {"label":"语音听写","title":"默认语音听写"},
|
||||
"setup.default.browser": {"label":"浏览器","title":"默认浏览器"},
|
||||
"setup.default.terminal": {"label":"终端","title":"默认终端"},
|
||||
"setup.default.editor": {"label":"编辑器","title":"默认编辑器"},
|
||||
@@ -125,7 +126,6 @@
|
||||
"install.terminal": {"label":"终端"},
|
||||
"install.preinstalls": {"label":"预装应用"},
|
||||
"install.service.chromium-account": {"label":"Chromium 账号"},
|
||||
"install.ai.dictation": {"label":"语音听写"},
|
||||
"install.gaming.xbox-cloud": {"label":"Xbox 云游戏"},
|
||||
"install.gaming.xbox-controllers": {"label":"Xbox 手柄"},
|
||||
"install.gaming.retro-launcher": {"label":"RetroArch 启动器"},
|
||||
@@ -142,7 +142,7 @@
|
||||
"remove.security": {"label":"安全","title":"移除"},
|
||||
"remove.security.fingerprint": {"label":"指纹"},
|
||||
"remove.security.sudoless-docker": {"label":"免 sudo Docker"},
|
||||
"remove.ai.dictation": {"label":"语音听写"},
|
||||
"remove.dictation": {"label":"语音听写"},
|
||||
"remove.gaming.xbox-cloud": {"label":"Xbox 云游戏"},
|
||||
"remove.gaming.xbox-controllers": {"label":"Xbox 手柄 ()"},
|
||||
"remove.development.javascript": {"title":"移除"},
|
||||
|
||||
@@ -16,6 +16,9 @@ SigLevel = Required DatabaseOptional
|
||||
LocalFileSigLevel = Optional
|
||||
|
||||
# pacman searches repositories in the order defined here
|
||||
[omarchy]
|
||||
Server = https://pkgs.omarchy.org/edge/$arch
|
||||
|
||||
[core]
|
||||
Include = /etc/pacman.d/mirrorlist
|
||||
|
||||
@@ -25,9 +28,6 @@ Include = /etc/pacman.d/mirrorlist
|
||||
[multilib]
|
||||
Include = /etc/pacman.d/mirrorlist
|
||||
|
||||
[omarchy]
|
||||
Server = https://pkgs.omarchy.org/edge/$arch
|
||||
|
||||
# Repositories for debug symbol packages.
|
||||
#
|
||||
# These upstream debug packages will only match core/extra/multilib packages from the Omarchy edge
|
||||
|
||||
@@ -16,6 +16,9 @@ SigLevel = Required DatabaseOptional
|
||||
LocalFileSigLevel = Optional
|
||||
|
||||
# pacman searches repositories in the order defined here
|
||||
[omarchy]
|
||||
Server = https://pkgs.omarchy.org/rc/$arch
|
||||
|
||||
[core]
|
||||
Include = /etc/pacman.d/mirrorlist
|
||||
|
||||
@@ -24,6 +27,3 @@ Include = /etc/pacman.d/mirrorlist
|
||||
|
||||
[multilib]
|
||||
Include = /etc/pacman.d/mirrorlist
|
||||
|
||||
[omarchy]
|
||||
Server = https://pkgs.omarchy.org/rc/$arch
|
||||
@@ -16,6 +16,9 @@ SigLevel = Required DatabaseOptional
|
||||
LocalFileSigLevel = Optional
|
||||
|
||||
# pacman searches repositories in the order defined here
|
||||
[omarchy]
|
||||
Server = https://pkgs.omarchy.org/stable/$arch
|
||||
|
||||
[core]
|
||||
Include = /etc/pacman.d/mirrorlist
|
||||
|
||||
@@ -24,6 +27,3 @@ Include = /etc/pacman.d/mirrorlist
|
||||
|
||||
[multilib]
|
||||
Include = /etc/pacman.d/mirrorlist
|
||||
|
||||
[omarchy]
|
||||
Server = https://pkgs.omarchy.org/stable/$arch
|
||||
@@ -53,6 +53,7 @@ hl.config({
|
||||
misc = {
|
||||
disable_hyprland_logo = true,
|
||||
disable_splash_rendering = true,
|
||||
background_color = "rgb(000000)",
|
||||
force_default_wallpaper = 0,
|
||||
},
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
state_file = "auto"
|
||||
|
||||
[hotkey]
|
||||
# Hotkey is configured in Hyprland. Default is Super + Ctrl + X
|
||||
# Hotkeys are configured in Hyprland: hold Right Alt or F9, or toggle with Super + Ctrl + X.
|
||||
enabled = false
|
||||
|
||||
[audio]
|
||||
|
||||
+2
-2
@@ -267,8 +267,8 @@ first runs `omarchy-provision-user || true` so finalize catches up if it
|
||||
never ran, then handles the steps that need a running graphical session
|
||||
and/or a working user systemd instance:
|
||||
|
||||
- `omarchy-hook-install post-update` for the three shipped hooks
|
||||
(`install-voxtype.hook`, `setup-fingerprint.hook`, `setup-agent.hook`).
|
||||
- `omarchy-hook-install post-update` for the two shipped hooks
|
||||
(`setup-fingerprint.hook`, `setup-agent.hook`).
|
||||
- `install/user/first-run/enable-user-units.sh` — daemon-reload, then
|
||||
`systemctl --user enable --now` the shipped user units (`bt-agent`,
|
||||
`omarchy-sleep-lock`, `omarchy-recover-internal-monitor`,
|
||||
|
||||
+21
-7
@@ -189,6 +189,20 @@ overrides like `omarchy display text size` survive theme switches.
|
||||
|
||||
## Theme tokens
|
||||
|
||||
Shell and plugin QML must qualify the palette singleton because Qt 6.12 introduces its own `Color` type. Import `qs.Commons` with an alias and use `Commons.Color` for palette properties and signal connections:
|
||||
|
||||
```qml
|
||||
import QtQuick
|
||||
import qs.Commons
|
||||
import qs.Commons as Commons
|
||||
|
||||
Rectangle {
|
||||
color: Commons.Color.background
|
||||
}
|
||||
```
|
||||
|
||||
The unqualified import can remain for `Style`, `Util`, and `Border`. Existing third-party plugins that use bare `Color` must make the same change; fixing the host shell does not change a plugin's import scope.
|
||||
|
||||
See [`theming.md`](theming.md) for the full theme/template workflow,
|
||||
including generated `*.tpl` files, gradient helpers, and shell border syntax.
|
||||
|
||||
@@ -200,17 +214,17 @@ or override a single section with `shell.<section>.toml`, merged in by
|
||||
`omarchy-theme-set-templates` (see [`theming.md`](theming.md)).
|
||||
|
||||
`colors.toml` uses `foreground` and `background` for the foundational
|
||||
text/background palette, exposed to QML as `Color.foreground` and
|
||||
`Color.background`.
|
||||
text/background palette, exposed to QML as `Commons.Color.foreground` and
|
||||
`Commons.Color.background`.
|
||||
|
||||
The shell exposes these tokens to QML via three singletons in
|
||||
`qs.Commons`:
|
||||
|
||||
- `Color` — palette (`foreground`, `background`, `accent`, `urgent`)
|
||||
and per-surface roles (`Color.bar.*`, `Color.popups.*`,
|
||||
`Color.tooltip.*`, `Color.notifications.*`, `Color.menu.*`,
|
||||
`Color.polkit.*`, `Color.lock.*`, `Color.imagePicker.*`). Clipboard
|
||||
and emojis share `Color.menu.*`; the `[launcher]` section is consumed
|
||||
and per-surface roles (`Commons.Color.bar.*`, `Commons.Color.popups.*`,
|
||||
`Commons.Color.tooltip.*`, `Commons.Color.notifications.*`, `Commons.Color.menu.*`,
|
||||
`Commons.Color.polkit.*`, `Commons.Color.lock.*`, `Commons.Color.imagePicker.*`). Clipboard
|
||||
and emojis share `Commons.Color.menu.*`; the `[launcher]` section is consumed
|
||||
by the launcher outside shell QML.
|
||||
- `Style` — structural tokens (`cornerRadius`), shared interactive
|
||||
state tokens/helpers, spacing (`Style.spacing.*` / `Style.space(px)`),
|
||||
@@ -218,7 +232,7 @@ The shell exposes these tokens to QML via three singletons in
|
||||
(`Style.bar.sizeHorizontal` / `Style.bar.sizeVertical`).
|
||||
- `Border` — border-spec helpers for QML surfaces. Use with
|
||||
`BorderSurface` from `qs.Ui` when a border should honor shell theme
|
||||
gradients or per-side widths. `Color.<section>.border` is only the
|
||||
gradients or per-side widths. `Commons.Color.<section>.border` is only the
|
||||
flat-color fallback for code that cannot render a real border.
|
||||
|
||||
### Interactive states
|
||||
|
||||
+10
-10
@@ -6,12 +6,11 @@ Omarchy themes live under `themes/<name>/` in the source tree (installed at
|
||||
`colors.toml`; Omarchy generates the active theme files from
|
||||
`default/themed/*.tpl` when `omarchy-theme-set <name>` runs.
|
||||
|
||||
Beyond `colors.toml` and hand-written config overrides, a first-party theme can
|
||||
ship `backgrounds/` (users overlay their own via
|
||||
`~/.config/omarchy/backgrounds/<name>/`; the active image is the
|
||||
`~/.local/state/omarchy/current/background` symlink), `preview.png` and
|
||||
`preview-unlock.png` for the theme switcher, `icons.theme`, `keyboard.rgb`,
|
||||
`unlock.png`, and a `light.mode` marker file.
|
||||
Beyond `colors.toml` and hand-written config overrides, a first-party theme can ship `backgrounds/` (users overlay their own via `~/.config/omarchy/backgrounds/<name>/`; the active image is the `~/.local/state/omarchy/current/background` symlink), `preview.png` and `preview-unlock.png` for the theme switcher, `icons.theme`, `keyboard.rgb`, `unlock.png`, and a `light.mode` marker file.
|
||||
|
||||
A theme can pair a still background with a silent intro video using matching filenames: `backgrounds/0-winding-road.webp` and `backgrounds/intros/0-winding-road.mp4`. The video plays automatically at login and when switching to that theme with this background selected. No registration, checksum file or manual setting is needed. Supported video extensions are `mp4`, `m4v`, `mov`, `webm`, `mkv` and `avi`. Intro videos stay inside the nested `intros/` directory so the background picker does not list them as looping wallpapers. An image selected from another directory looks for its intro in that directory's own `intros/`, so a same-named custom image cannot inherit a theme's video.
|
||||
|
||||
Aim for a video between five and seven seconds long that opens on its scene setup and ends on the matching still. The shell provides the opening crossfade, so an added fade from black is unnecessary. OWE owns decoding, mute and the handoff back to that image. The theme picker prepares the highlighted theme's remembered intro offscreen, paused at its opening frame. OWE keeps one prepared clip and an idle renderer for up to one minute, then releases them. A theme switch also starts preparation while its templates render; OWE compares the selected video with the prepared clip before resuming it. Older OWE versions use the ordinary startup path. Hyprland and the SDDM greeter use a black compositor background. On a fresh login, the persistent shell host keeps an opaque black cover above the bar and wallpaper until the bar has loaded and OWE has a moving video frame, then fades both in together over 420 ms. Hyprland initializes with a transparent cursor so its visibility polling cannot expose a pointer in the first frames. The temporary Xcursor theme stays private to the compositor; applications inherit the normal cursor environment. The opening fade restores the selected cursor and settings. Shell restarts and a fifteen-second compositor timeout recover a cursor left hidden by an interrupted startup. With intros disabled or unavailable, it waits for the still to be ready instead. A ten-second deadline releases the cover if a missing wallpaper or failed plugin never becomes ready. Ordinary shell restarts preload the selected still alongside the bar without mapping that login cover. Login intros use the Hyprland instance signature, so logging out and back in plays the intro again. The launcher consumes the current session before waiting up to five seconds for OWE. Shell restarts and a daemon starting after that window cannot play a delayed intro. Theme switches synchronize OWE with the selected image and use its first-frame start mode. An interrupted video supplies its currently playing frame as the outgoing snapshot. Rapid selections wait for the previous opening fade to finish before capturing it. Theme replacement and playback wait for the outgoing cover to decode and reach the compositor on every screen. A persistent layer holds that outgoing wallpaper until OWE hides the shell background and reports a ready video with an advancing playback position and no outgoing still transition, then crossfades it over 420 ms while applying the new bar palette. The shell retains its background service and decoded wallpaper while it is hidden, so handing the still back does not recreate them. App retints wait until the opening crossfade completes, with a three-second bound, so they do not compete with its first frames. The compositor reload waits until playback finishes because reloading Hyprland pauses video presentation. A superseded intro skips that reload. Failed playback releases the pending palette, and a newer theme invalidates the older handoff. Refreshing a theme, headless setup, and cycling backgrounds within the same theme do not trigger intros. Toggle > Animations suppresses playback along with the other animations. The `omarchy theme bg intro toggle` command can toggle intros separately.
|
||||
|
||||
A theme installed from a git repo is held to a much shorter list; see [What an installed theme may not ship](#what-an-installed-theme-may-not-ship).
|
||||
|
||||
@@ -198,7 +197,7 @@ The filename decides the target section, so the `[lock]` header is optional.
|
||||
|
||||
The running shell reads `shell.toml` into two QML singletons:
|
||||
|
||||
- `Color` for palette and surface roles like `Color.menu.border`.
|
||||
- `Color` for palette and surface roles like `Commons.Color.menu.border`.
|
||||
- `Style` for controls, spacing, font scale, corner radius, and bar sizing.
|
||||
|
||||
### Borders
|
||||
@@ -327,11 +326,12 @@ Plugin and shell QML should use `BorderSurface` for theme-aware borders:
|
||||
|
||||
```qml
|
||||
import qs.Commons
|
||||
import qs.Commons as Commons
|
||||
import qs.Ui
|
||||
|
||||
BorderSurface {
|
||||
color: Color.popups.background
|
||||
borderSpec: Border.surfaceSpec("popups", "border", Color.popups.border, 2)
|
||||
color: Commons.Color.popups.background
|
||||
borderSpec: Border.surfaceSpec("popups", "border", Commons.Color.popups.border, 2)
|
||||
padding: Style.spacing.popupPadding
|
||||
|
||||
Item {
|
||||
@@ -348,7 +348,7 @@ Use `Border.surfaceSpec(section, token, fallbackColor, fallbackWidth, alphaKey)`
|
||||
for shell theme tokens (the optional `alphaKey` names the alpha token, e.g.
|
||||
`"border-alpha"`), `Border.controlSpec(state, foreground, accent, urgent)` for
|
||||
shared controls, and `Border.flat(color, width)` for a deliberate local border
|
||||
that should not be overridden by the active theme. `Color.<section>.border` is the
|
||||
that should not be overridden by the active theme. `Commons.Color.<section>.border` is the
|
||||
flat first-stop color for consumers that cannot render full border specs.
|
||||
|
||||
## Hyprland templates
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
[Service]
|
||||
# Let start-hyprland stop the compositor before killing its shell clients.
|
||||
# Sending SIGTERM to the whole group removes the wallpaper during teardown.
|
||||
KillMode=mixed
|
||||
@@ -131,6 +131,7 @@ sddm
|
||||
slurp
|
||||
socat
|
||||
starship
|
||||
superwhisper-bin
|
||||
sushi
|
||||
system-config-printer
|
||||
tesseract
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
if omarchy-done ensure voxtype-install-invitation; then
|
||||
omarchy-notification-send -u critical -g "$(omarchy-text "Install Dictation with Voxtype")" \
|
||||
"$(omarchy-text "Click to install voice dictation for Omarchy.")" \
|
||||
--exec omarchy-launch-floating-terminal-with-presentation omarchy-voxtype-install
|
||||
fi
|
||||
@@ -12,7 +12,12 @@ case ${OMARCHY_SETUP_CONTEXT:-runtime} in
|
||||
esac
|
||||
|
||||
if [[ -n $NODE_PACKAGE_DIR ]]; then
|
||||
NODE_TARBALL=$(find "$NODE_PACKAGE_DIR" -name "node-v*-linux-x64.tar.gz" -type f 2>/dev/null | head -n1)
|
||||
# The ISO bundles the tarball for its own architecture.
|
||||
case $(uname -m) in
|
||||
aarch64) NODE_PLATFORM=linux-arm64 ;;
|
||||
*) NODE_PLATFORM=linux-x64 ;;
|
||||
esac
|
||||
NODE_TARBALL=$(find "$NODE_PACKAGE_DIR" -name "node-v*-$NODE_PLATFORM.tar.gz" -type f 2>/dev/null | head -n1)
|
||||
if [[ -z $NODE_TARBALL ]]; then
|
||||
if [[ ${OMARCHY_SETUP_CONTEXT:-} == "provision-owner" ]]; then
|
||||
# A factory snapshot predating the bundled tarball may not have it staged.
|
||||
@@ -24,7 +29,7 @@ if [[ -n $NODE_PACKAGE_DIR ]]; then
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
NODE_VERSION=$(basename "$NODE_TARBALL" | sed 's/node-v\(.*\)-linux-x64.tar.gz/\1/')
|
||||
NODE_VERSION=$(basename "$NODE_TARBALL" | sed "s/node-v\(.*\)-$NODE_PLATFORM.tar.gz/\1/")
|
||||
NODE_INSTALL_DIR="$HOME/.local/share/mise/installs/node/$NODE_VERSION"
|
||||
|
||||
mkdir -p "$NODE_INSTALL_DIR"
|
||||
|
||||
@@ -150,8 +150,8 @@ Usually on Linux, you need `Ctrl + Shift + C/V` to copy'n'paste in the terminal
|
||||
| `Super + Alt + ]` | Make webcam overlay larger while recording |
|
||||
| `Alt + Shift + L` | Copy current URL from webapp or Chromium |
|
||||
| `Alt + Shift + D` | Download the video on the current page to `~/Videos` |
|
||||
| `Super + Ctrl + X` | Start/stop dictation (requires _Install > AI > Dictation_) |
|
||||
| `F9` | Push-to-talk dictation (requires _Install > AI > Dictation_) |
|
||||
| `Super + Ctrl + X` | Start/stop dictation (requires _Setup > Defaults > Dictation_) |
|
||||
| `Right Alt` / `F9` | Push-to-talk dictation (requires Voxtype or Superwhisper) |
|
||||
|
||||
With screenrecordings, the hotkey first asks which audio you want, then starts recording. Hit it again to stop. See [screenshots and recording](12-screenshots-recording.md) for the details.
|
||||
|
||||
|
||||
@@ -10,6 +10,14 @@ This is very helpful for grabbing addresses out of image footers or phone number
|
||||
|
||||
### Dictation
|
||||
|
||||
Omarchy offers AI dictation via [Voxtype](https://voxtype.io/). You install it via _Install > AI > Dictation_ through the Omarchy menu. By default, it'll load a base English model that takes up 150MB. But you can tweak which model you'd like to use by running `voxtype setup model` in the terminal. And you can tweak all the settings via `~/.config/voxtype/config.toml`.
|
||||
On fresh installs, [Superwhisper](https://superwhisper.com/) is the default dictation backend, using cloud processing without offline model downloads. Choose Superwhisper or [Voxtype](https://voxtype.io/) through _Setup > Defaults > Dictation_ in the Omarchy menu. Selecting a backend installs it if needed and makes it the default for dictation. Voxtype loads a base English model that takes up 150MB; change the model with `voxtype setup model` and other settings through `~/.config/voxtype/config.toml`. Superwhisper opens its settings to choose cloud or local processing, and OPR keeps the application updated.
|
||||
|
||||
Once installed, you dictate by holding down `F9` or by toggling with `Super + Ctrl + X`, and the dictated text will appear in the focused input area.
|
||||
You dictate by holding down `Right Alt` or `F9`, or by toggling with `Super + Ctrl + X`, and the dictated text will appear in the focused input area. These shortcuts use the selected backend. Right Alt also starts dictation when used in a modifier chord; use Left Alt for those chords. On keyboard layouts where Right Alt is AltGr, use `F9` to keep AltGr available for typing.
|
||||
|
||||
The same shortcuts work with either backend. Select your backend through Setup > Defaults > Dictation. The backend installer configures it and saves the selection. Run `omarchy default dictation` to see which one is selected. The selection is saved in `~/.config/omarchy/defaults/dictation`. Fresh installs select Superwhisper automatically.
|
||||
|
||||
Omarchy loads the selected backend's desktop integration automatically. No Superwhisper configuration is needed in `~/.config/hypr/`.
|
||||
|
||||
Custom bindings and scripts can use `omarchy dictation start`, `omarchy dictation stop`, and `omarchy dictation toggle`. The selected backend handles the recording and transcription. Selecting Superwhisper disables its native hold shortcut and sets its native toggle to `Alt + Space`, keeping it separate from Omarchy's recording keys. Superwhisper requires at least one native recording shortcut, and its cancellation shortcut stays available.
|
||||
|
||||
Additional backends can integrate without changing Omarchy. Provide an executable named `omarchy-dictation-<backend>` on PATH that accepts `start`, `stop`, and `toggle` and returns promptly, with a nonzero status on failure. Its installer configures the provider and calls `omarchy-dictation-use <backend>` after successful setup. This stops the previous backend and saves the selection atomically; `stop` must succeed when the provider is idle or unavailable. Backend names use lowercase letters, digits, and hyphens. Provide `omarchy-install-dictation-<backend>` for setup; `omarchy default dictation <backend>` launches it. Add a Defaults menu entry through an Omarchy menu extension to call that selector. Optional desktop integration can live in `${XDG_CONFIG_HOME:-$HOME/.config}/<backend>/shortcuts.lua`.
|
||||
@@ -6,6 +6,10 @@ You can do this most easily by going to _Install > Style > Background_ in the Om
|
||||
|
||||
Backgrounds can be videos as well as stills. Drop an `mp4`, `m4v`, `mov`, `webm`, `mkv`, or `avi` file in the same folder and it appears alongside the images. Videos are played by the OWE wallpaper engine. It decodes the video once for all monitors and plays its sound through the default audio output, and it stops playback whenever nothing can see it. The lock screen draws the same decode, muted, through OWE. A video wallpaper still costs far more power than a still one.
|
||||
|
||||
Themes can include a short intro for a still background. For `backgrounds/road.webp`, the matching video lives at `backgrounds/intros/road.mp4`. It plays automatically at boot and when switching to a theme with that background selected, then returns to the still. Intro videos stay out of the background picker and never loop.
|
||||
|
||||
Turning off _Toggle > Animations_ also turns off background intros. Omarchy does this by default in a virtual machine. The `omarchy theme bg intro toggle` command can toggle intros separately. Refreshing a theme or choosing another background within the same theme does not play an intro.
|
||||
|
||||
You can find a huge collection of cool curated backgrounds on https://github.com/dharmx/walls.
|
||||
|
||||
Video backgrounds keep a cached still on the lock screen while playback is paused or unavailable. Animated GIFs play on the desktop and show a still frame on the lock screen.
|
||||
@@ -0,0 +1,26 @@
|
||||
echo "Re-stage the active theme with packaged intro videos"
|
||||
|
||||
theme_name_path="$HOME/.local/state/omarchy/current/theme.name"
|
||||
|
||||
[[ -s $theme_name_path ]] || exit 0
|
||||
|
||||
theme_name=$(<"$theme_name_path")
|
||||
[[ $theme_name =~ ^[[:alnum:]_][[:alnum:].+_-]*$ ]] || exit 0
|
||||
[[ -d $OMARCHY_PATH/themes/$theme_name/backgrounds/intros ]] || exit 0
|
||||
|
||||
omarchy-theme-refresh
|
||||
|
||||
state_dir="$HOME/.local/state/omarchy"
|
||||
marker="$state_dir/background-intro.session-id"
|
||||
session_id=${OMARCHY_SESSION_ID:-${HYPRLAND_INSTANCE_SIGNATURE:-}}
|
||||
if [[ -z $session_id ]]; then
|
||||
hypr_dir=$(find "${XDG_RUNTIME_DIR:-/run/user/$UID}/hypr" -mindepth 1 -maxdepth 1 -type d -printf '%T@ %p\n' 2>/dev/null | sort -n | tail -n 1 | cut -d' ' -f2- || true)
|
||||
session_id=${hypr_dir##*/}
|
||||
fi
|
||||
[[ -n $session_id ]] || exit 0
|
||||
mkdir -p "$state_dir"
|
||||
marker_staged=$(mktemp "$state_dir/.background-intro.session-id.XXXXXX")
|
||||
trap 'rm -f "$marker_staged"' EXIT
|
||||
printf '%s\n' "$session_id" >"$marker_staged"
|
||||
mv -f "$marker_staged" "$marker"
|
||||
trap - EXIT
|
||||
@@ -0,0 +1,15 @@
|
||||
echo "Enable overlay scrollbars in Chromium-based browsers"
|
||||
|
||||
for flags_file in "$HOME"/.config/{chromium,chrome,microsoft-edge-stable,brave,brave-origin}-flags.conf; do
|
||||
[[ -f $flags_file ]] || continue
|
||||
grep -Eq -- '^--enable-features=([^,]+,)*OverlayScrollbar([,:]|$)' "$flags_file" && continue
|
||||
|
||||
if grep -q -- '^--enable-features=' "$flags_file"; then
|
||||
sed -i --follow-symlinks \
|
||||
-e '/^--enable-features=/ s/$/,OverlayScrollbar/' \
|
||||
-e '/^--enable-features=/ s/=,/=/' "$flags_file"
|
||||
else
|
||||
[[ -n $(tail -c1 "$flags_file") ]] && echo >>"$flags_file"
|
||||
echo '--enable-features=OverlayScrollbar' >>"$flags_file"
|
||||
fi
|
||||
done
|
||||
@@ -0,0 +1,28 @@
|
||||
echo "Prioritize the Omarchy package repository over Arch repositories"
|
||||
|
||||
# Move the existing section rather than replacing pacman.conf so channel URLs,
|
||||
# custom repositories, and administrator options survive the migration.
|
||||
pacman_config=$(mktemp)
|
||||
trap 'rm -f "$pacman_config"' EXIT
|
||||
|
||||
awk '
|
||||
/^[[:space:]]*\[[^]]+\]/ {
|
||||
section = $0
|
||||
sub(/^[[:space:]]*\[/, "", section)
|
||||
sub(/\].*$/, "", section)
|
||||
if (section != "options") repositories = 1
|
||||
}
|
||||
!repositories { prefix = prefix $0 "\n"; next }
|
||||
section == "omarchy" { omarchy = omarchy $0 "\n"; next }
|
||||
{ others = others $0 "\n" }
|
||||
END { printf "%s%s%s", prefix, omarchy, others }
|
||||
' /etc/pacman.conf >"$pacman_config"
|
||||
|
||||
if ! cmp -s /etc/pacman.conf "$pacman_config"; then
|
||||
sudo cp -a /etc/pacman.conf /etc/pacman.conf.bak
|
||||
sudo install -m 644 -o root -g root "$pacman_config" /etc/pacman.conf
|
||||
fi
|
||||
|
||||
# Refresh databases and upgrade against the new repository priority. Run this
|
||||
# even when the config is already ordered so a failed upgrade can be retried.
|
||||
omarchy-update-system-pkgs
|
||||
@@ -0,0 +1,9 @@
|
||||
echo "Preserve Voxtype as the default for existing dictation users"
|
||||
|
||||
backend_config="${XDG_CONFIG_HOME:-$HOME/.config}/omarchy/defaults/dictation"
|
||||
if [[ ! -e $backend_config ]] && omarchy-pkg-present voxtype-bin; then
|
||||
mkdir -p "${backend_config%/*}"
|
||||
temporary=$(mktemp "$backend_config.XXXXXX")
|
||||
printf '%s\n' voxtype > "$temporary"
|
||||
mv -f "$temporary" "$backend_config"
|
||||
fi
|
||||
@@ -1,5 +1,6 @@
|
||||
pragma Singleton
|
||||
import QtQuick
|
||||
import qs.Commons as Commons
|
||||
import "BorderGeometry.js" as Geometry
|
||||
|
||||
// Central border-spec factory for shell surfaces and controls. A spec carries
|
||||
@@ -22,7 +23,7 @@ QtObject {
|
||||
}
|
||||
|
||||
function value(section, key) {
|
||||
var v = Color.shellValues[section + "." + key]
|
||||
var v = Commons.Color.shellValues[section + "." + key]
|
||||
return (v === undefined || v === null) ? "" : v
|
||||
}
|
||||
|
||||
@@ -39,7 +40,7 @@ QtObject {
|
||||
var seen = {}
|
||||
while (s.match(/^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/) && !seen[s]) {
|
||||
seen[s] = true
|
||||
var next = Color.shellValues[s]
|
||||
var next = Commons.Color.shellValues[s]
|
||||
if (next === undefined || next === null || String(next).length === 0) break
|
||||
s = String(next).replace(/^\s+|\s+$/g, "")
|
||||
}
|
||||
@@ -68,10 +69,10 @@ QtObject {
|
||||
|
||||
var s = String(color || "").replace(/^\s+|\s+$/g, "")
|
||||
var role = s.toLowerCase()
|
||||
if (role === "foreground" || role === "text") return cssColor(Color.foreground, a)
|
||||
if (role === "accent") return cssColor(Color.accent, a)
|
||||
if (role === "urgent") return cssColor(Color.urgent, a)
|
||||
if (role === "background") return cssColor(Color.background, a)
|
||||
if (role === "foreground" || role === "text") return cssColor(Commons.Color.foreground, a)
|
||||
if (role === "accent") return cssColor(Commons.Color.accent, a)
|
||||
if (role === "urgent") return cssColor(Commons.Color.urgent, a)
|
||||
if (role === "background") return cssColor(Commons.Color.background, a)
|
||||
if (role === "transparent") return "transparent"
|
||||
return Geometry.canonicalColor(s, a)
|
||||
}
|
||||
|
||||
@@ -396,7 +396,6 @@ var table = {
|
||||
"Pin": "固定",
|
||||
"Show": "显示",
|
||||
"Hide": "隐藏",
|
||||
"Dictate": "语音输入",
|
||||
"Allow Notifications": "允许通知",
|
||||
"Silence Notifications": "静默通知",
|
||||
"Day Light": "日间光线",
|
||||
@@ -434,11 +433,9 @@ var table = {
|
||||
"Download failed": "下载失败",
|
||||
"Editing config file": "正在编辑配置文件",
|
||||
"Extended mode restored": "已恢复扩展模式",
|
||||
"FIDO2 authfile needs attention": "FIDO2 认证文件需要处理",
|
||||
"Failed to start Windows VM": "无法启动 Windows 虚拟机",
|
||||
"Herdr theme sync disabled": "Herdr 主题同步已关闭",
|
||||
"Herdr theme sync enabled": "Herdr 主题同步已开启",
|
||||
"Hold F9 to dictate (or toggle with Super + Ctrl + X).": "按住 F9 语音输入(或用 Super + Ctrl + X 切换)。",
|
||||
"Laptop display disabled": "笔记本屏幕已关闭",
|
||||
"Laptop display enabled": "笔记本屏幕已开启",
|
||||
"Logging out": "正在注销",
|
||||
@@ -514,8 +511,6 @@ var table = {
|
||||
"Enable sudo and unlocking with your fingerprint.": "用指纹进行 sudo 和解锁。",
|
||||
"Set your default agent": "设置默认 AI 代理",
|
||||
"Let your favorite agent help with Omarchy.": "让你喜欢的 AI 代理帮你使用 Omarchy。",
|
||||
"Install Dictation with Voxtype": "安装 Voxtype 语音输入",
|
||||
"Click to install voice dictation for Omarchy.": "点击为 Omarchy 安装语音输入。",
|
||||
"All %1 accounts are over %2%": "所有 %1 账户都超过 %2%",
|
||||
"Staying on %1. %2 resets in %3.": "继续使用 %1。%2 将在 %3 后重置。",
|
||||
"Staying on %1.": "继续使用 %1。",
|
||||
@@ -616,5 +611,10 @@ var table = {
|
||||
"Log out now to switch the language?": "立即注销以切换语言?",
|
||||
"Log back in to switch the language.": "重新登录后切换语言。",
|
||||
"Log out now to switch the developer mirrors?": "立即注销以切换开发工具镜像?",
|
||||
"Log back in to switch the developer mirrors.": "重新登录后切换开发工具镜像。"
|
||||
"Log back in to switch the developer mirrors.": "重新登录后切换开发工具镜像。",
|
||||
"Superwhisper Dictation Ready": "Superwhisper 语音输入就绪",
|
||||
"Hold Right Alt or F9 to dictate (or toggle with Super + Ctrl + X).": "按住右 Alt 或 F9 说话(或用 Super + Ctrl + X 切换)。",
|
||||
"Background Intros": "背景开场动画",
|
||||
"Enabled": "已开启",
|
||||
"Disabled": "已关闭"
|
||||
}
|
||||
+22
-21
@@ -1,5 +1,6 @@
|
||||
pragma Singleton
|
||||
import QtQuick
|
||||
import qs.Commons as Commons
|
||||
import Quickshell
|
||||
import Quickshell.Hyprland
|
||||
import Quickshell.Io
|
||||
@@ -114,27 +115,27 @@ QtObject {
|
||||
}
|
||||
|
||||
function resolveStateColor(token, foreground, accent, urgent, fallback) {
|
||||
var fb = fallback || foreground || Color.foreground
|
||||
var fb = fallback || foreground || Commons.Color.foreground
|
||||
var s = String(token || "").replace(/^\s+|\s+$/g, "")
|
||||
var role = s.toLowerCase()
|
||||
if (role === "foreground" || role === "text") return foreground || Color.foreground
|
||||
if (role === "accent") return accent || Color.accent
|
||||
if (role === "urgent") return urgent || Color.urgent
|
||||
if (role === "background") return Color.background
|
||||
if (role === "foreground" || role === "text") return foreground || Commons.Color.foreground
|
||||
if (role === "accent") return accent || Commons.Color.accent
|
||||
if (role === "urgent") return urgent || Commons.Color.urgent
|
||||
if (role === "background") return Commons.Color.background
|
||||
if (role === "transparent") return Qt.rgba(0, 0, 0, 0)
|
||||
return colorFromHex(s, fb)
|
||||
}
|
||||
|
||||
function normalStateColor(foreground, accent, urgent) {
|
||||
return resolveStateColor(normalColorToken, foreground, accent, urgent, foreground || Color.foreground)
|
||||
return resolveStateColor(normalColorToken, foreground, accent, urgent, foreground || Commons.Color.foreground)
|
||||
}
|
||||
|
||||
function hoverStateColor(foreground, accent, urgent) {
|
||||
return resolveStateColor(hoverColorToken, foreground, accent, urgent, foreground || Color.foreground)
|
||||
return resolveStateColor(hoverColorToken, foreground, accent, urgent, foreground || Commons.Color.foreground)
|
||||
}
|
||||
|
||||
function selectedStateColor(foreground, accent, urgent) {
|
||||
return resolveStateColor(selectedColorToken, foreground, accent, urgent, foreground || Color.foreground)
|
||||
return resolveStateColor(selectedColorToken, foreground, accent, urgent, foreground || Commons.Color.foreground)
|
||||
}
|
||||
|
||||
function pressedStateColor(foreground, accent, urgent) {
|
||||
@@ -149,7 +150,7 @@ QtObject {
|
||||
}
|
||||
|
||||
function selectionStateColor(foreground, accent, urgent) {
|
||||
return resolveStateColor(selectionColorToken, foreground, accent, urgent, foreground || Color.foreground)
|
||||
return resolveStateColor(selectionColorToken, foreground, accent, urgent, foreground || Commons.Color.foreground)
|
||||
}
|
||||
|
||||
function normalFillFor(foreground, accent, urgent) { return Util.alpha(normalStateColor(foreground, accent, urgent), normalFillAlpha) }
|
||||
@@ -187,17 +188,17 @@ QtObject {
|
||||
}
|
||||
|
||||
// Convenience colors resolved against the foundational palette.
|
||||
readonly property color normalFill: normalFillFor(Color.foreground, Color.accent, Color.urgent)
|
||||
readonly property color hoverFill: hoverFillFor(Color.foreground, Color.accent, Color.urgent)
|
||||
readonly property color selectedFill: selectedFillFor(Color.foreground, Color.accent, Color.urgent)
|
||||
readonly property color pressedFill: pressedFillFor(Color.foreground, Color.accent, Color.urgent)
|
||||
readonly property color focusFillColor: focusFillFor(Color.foreground, Color.accent, Color.urgent)
|
||||
readonly property color normalBorderColor: normalBorderFor(Color.foreground, Color.accent, Color.urgent)
|
||||
readonly property color hoverBorderColor: hoverBorderFor(Color.foreground, Color.accent, Color.urgent)
|
||||
readonly property color selectedBorderColor: selectedBorderFor(Color.foreground, Color.accent, Color.urgent)
|
||||
readonly property color focusBorderColor: focusBorderFor(Color.foreground, Color.accent, Color.urgent)
|
||||
readonly property color selectedAccentFill: Util.alpha(Color.accent, selectedFillAlpha)
|
||||
readonly property color selectionFill: selectionFillFor(Color.foreground, Color.accent, Color.urgent)
|
||||
readonly property color normalFill: normalFillFor(Commons.Color.foreground, Commons.Color.accent, Commons.Color.urgent)
|
||||
readonly property color hoverFill: hoverFillFor(Commons.Color.foreground, Commons.Color.accent, Commons.Color.urgent)
|
||||
readonly property color selectedFill: selectedFillFor(Commons.Color.foreground, Commons.Color.accent, Commons.Color.urgent)
|
||||
readonly property color pressedFill: pressedFillFor(Commons.Color.foreground, Commons.Color.accent, Commons.Color.urgent)
|
||||
readonly property color focusFillColor: focusFillFor(Commons.Color.foreground, Commons.Color.accent, Commons.Color.urgent)
|
||||
readonly property color normalBorderColor: normalBorderFor(Commons.Color.foreground, Commons.Color.accent, Commons.Color.urgent)
|
||||
readonly property color hoverBorderColor: hoverBorderFor(Commons.Color.foreground, Commons.Color.accent, Commons.Color.urgent)
|
||||
readonly property color selectedBorderColor: selectedBorderFor(Commons.Color.foreground, Commons.Color.accent, Commons.Color.urgent)
|
||||
readonly property color focusBorderColor: focusBorderFor(Commons.Color.foreground, Commons.Color.accent, Commons.Color.urgent)
|
||||
readonly property color selectedAccentFill: Util.alpha(Commons.Color.accent, selectedFillAlpha)
|
||||
readonly property color selectionFill: selectionFillFor(Commons.Color.foreground, Commons.Color.accent, Commons.Color.urgent)
|
||||
|
||||
// ---------------------------------------------------------- spacing
|
||||
//
|
||||
@@ -390,7 +391,7 @@ QtObject {
|
||||
}
|
||||
|
||||
// Pull typography, bar dimensions, state tokens, and spacing out of the
|
||||
// shell.toml dict that Color already parsed. Called by Color.loadShell so
|
||||
// shell.toml dict that Color already parsed. Called by Commons.Color.loadShell so
|
||||
// a single parse pass feeds both singletons.
|
||||
function applyShellValues(values) {
|
||||
var fontOut = {}
|
||||
|
||||
+7
-6
@@ -1,6 +1,7 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import qs.Commons
|
||||
import qs.Commons as Commons
|
||||
|
||||
// The button. One component for every clickable thing in the kit.
|
||||
// States compose independently and are applied in priority order:
|
||||
@@ -32,9 +33,9 @@ BorderSurface {
|
||||
property bool bordered: false
|
||||
|
||||
// Colors. Defaults track the theme; per-instance overrides are honored.
|
||||
property color foreground: Color.foreground
|
||||
property color foreground: Commons.Color.foreground
|
||||
property color background: "transparent"
|
||||
property color accent: Color.accent
|
||||
property color accent: Commons.Color.accent
|
||||
|
||||
// Sizing.
|
||||
property string fontFamily: Style.font.family
|
||||
@@ -54,9 +55,9 @@ BorderSurface {
|
||||
// Tooltip palette. Auto-rendered if tooltipText is set. Defaults pull
|
||||
// from [tooltip] in shell.toml; override per-instance only when a button
|
||||
// intentionally wants a tooltip that diverges from the theme.
|
||||
property color tooltipBackground: Color.tooltip.background
|
||||
property color tooltipForeground: Color.tooltip.text
|
||||
property color tooltipBorder: Color.tooltip.border
|
||||
property color tooltipBackground: Commons.Color.tooltip.background
|
||||
property color tooltipForeground: Commons.Color.tooltip.text
|
||||
property color tooltipBorder: Commons.Color.tooltip.border
|
||||
|
||||
signal clicked()
|
||||
signal rightClicked()
|
||||
@@ -77,7 +78,7 @@ BorderSurface {
|
||||
readonly property bool hot: mouseArea.containsMouse || hasCursor
|
||||
readonly property bool _showFocusRing: focusable && activeFocus
|
||||
readonly property color _selectedColor: Style.selectedStateColor(root.foreground, root.accent)
|
||||
readonly property var _tooltipBorderSpec: Border.localOrSurfaceSpec("tooltip", "border", root.tooltipBorder, Color.tooltip.border, Math.max(1, Style.normalBorderWidth))
|
||||
readonly property var _tooltipBorderSpec: Border.localOrSurfaceSpec("tooltip", "border", root.tooltipBorder, Commons.Color.tooltip.border, Math.max(1, Style.normalBorderWidth))
|
||||
readonly property var _focusBorderSpec: Border.controlSpec("focus", root.foreground, root.accent)
|
||||
readonly property var _hoverBorderSpec: Border.controlSpec("hover-cursor", root.foreground, root.accent)
|
||||
readonly property var _selectedBorderSpec: Border.controlSpec("selected", root.foreground, root.accent)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import QtQuick
|
||||
import qs.Commons
|
||||
import qs.Commons as Commons
|
||||
|
||||
// Mutually-exclusive row of Buttons — the form-style "pick one of N"
|
||||
// pattern (bar position top/right/bottom/left, theme preset chips, etc.).
|
||||
@@ -25,9 +26,9 @@ Row {
|
||||
|
||||
property var options: []
|
||||
property string value: ""
|
||||
property color foreground: Color.foreground
|
||||
property color background: Color.background
|
||||
property color accent: Color.accent
|
||||
property color foreground: Commons.Color.foreground
|
||||
property color background: Commons.Color.background
|
||||
property color accent: Commons.Color.accent
|
||||
property string fontFamily: Style.font.family
|
||||
property real fontSize: Style.font.body
|
||||
property bool focusable: true
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import QtQuick
|
||||
import qs.Commons
|
||||
import qs.Commons as Commons
|
||||
|
||||
Item {
|
||||
id: root
|
||||
@@ -9,11 +10,11 @@ Item {
|
||||
property string cancelText: I18n.tr("Cancel")
|
||||
property string confirmText: I18n.tr("Confirm")
|
||||
property int selectedIndex: 1
|
||||
property color background: Color.background
|
||||
property color foreground: Color.foreground
|
||||
property color scrim: Util.alpha(Color.background, 0.7)
|
||||
property color selectedBackground: Util.alpha(Color.foreground, 0.08)
|
||||
property color selectedText: Color.accent
|
||||
property color background: Commons.Color.background
|
||||
property color foreground: Commons.Color.foreground
|
||||
property color scrim: Util.alpha(Commons.Color.background, 0.7)
|
||||
property color selectedBackground: Util.alpha(Commons.Color.foreground, 0.08)
|
||||
property color selectedText: Commons.Color.accent
|
||||
property string fontFamily: Style.font.family
|
||||
property int cornerRadius: Style.cornerRadius
|
||||
|
||||
@@ -98,10 +99,10 @@ Item {
|
||||
width: Style.space(88)
|
||||
height: Style.space(34)
|
||||
color: selected
|
||||
? (destructive ? Util.alpha(Color.urgent, 0.22) : root.selectedBackground)
|
||||
? (destructive ? Util.alpha(Commons.Color.urgent, 0.22) : root.selectedBackground)
|
||||
: "transparent"
|
||||
borderSpec: Border.flat(destructive
|
||||
? (selected ? Color.urgent : Util.alpha(Color.urgent, 0.56))
|
||||
? (selected ? Commons.Color.urgent : Util.alpha(Commons.Color.urgent, 0.56))
|
||||
: (selected ? root.selectedText : Util.alpha(root.foreground, 0.38)), Style.normalBorderWidth)
|
||||
radius: 0
|
||||
|
||||
@@ -109,7 +110,7 @@ Item {
|
||||
textFormat: Text.PlainText
|
||||
anchors.centerIn: parent
|
||||
text: modelData
|
||||
color: destructive ? (selected ? Color.urgent : root.foreground) : (selected ? root.selectedText : root.foreground)
|
||||
color: destructive ? (selected ? Commons.Color.urgent : root.foreground) : (selected ? root.selectedText : root.foreground)
|
||||
font.family: root.fontFamily
|
||||
font.pixelSize: Style.font.caption
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import QtQuick
|
||||
import qs.Commons
|
||||
import qs.Commons as Commons
|
||||
|
||||
// Shared visual chrome for keyboard-and-mouse-navigable items inside a panel.
|
||||
// Contract: items must NOT read `containsMouse` for color/border. Mouse
|
||||
@@ -19,8 +20,8 @@ BorderSurface {
|
||||
property bool outline: false
|
||||
property bool bordered: false
|
||||
|
||||
property color foreground: Color.foreground
|
||||
property color accent: Color.accent
|
||||
property color foreground: Commons.Color.foreground
|
||||
property color accent: Commons.Color.accent
|
||||
property color fill: Style.hoverFillFor(foreground, accent)
|
||||
property color currentFill: Style.selectedFillFor(foreground, accent)
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import qs.Commons
|
||||
import qs.Commons as Commons
|
||||
|
||||
// Themed single-select dropdown. Trigger row paints with the kit's focus
|
||||
// chrome; the popup anchors below and uses Color.popups.background +
|
||||
// Color.popups.border so it reads as a panel surface rather than the
|
||||
// chrome; the popup anchors below and uses Commons.Color.popups.background +
|
||||
// Commons.Color.popups.border so it reads as a panel surface rather than the
|
||||
// platform-native ComboBox look.
|
||||
//
|
||||
// `options` accepts either a plain string[] or an array of
|
||||
@@ -22,11 +23,11 @@ Item {
|
||||
property string value: ""
|
||||
property var options: []
|
||||
|
||||
property color foreground: Color.popups.text
|
||||
property color background: Color.popups.background
|
||||
property color popupBorder: Color.popups.border
|
||||
property color accent: Color.accent
|
||||
readonly property var popupBorderSpec: Border.localOrSurfaceSpec("popups", "border", popupBorder, Color.popups.border, Style.normalBorderWidth)
|
||||
property color foreground: Commons.Color.popups.text
|
||||
property color background: Commons.Color.popups.background
|
||||
property color popupBorder: Commons.Color.popups.border
|
||||
property color accent: Commons.Color.accent
|
||||
readonly property var popupBorderSpec: Border.localOrSurfaceSpec("popups", "border", popupBorder, Commons.Color.popups.border, Style.normalBorderWidth)
|
||||
property string fontFamily: Style.font.family
|
||||
property int rowHeight: Style.spacing.controlHeight
|
||||
property int popupRowHeight: Style.spacing.popupRowHeight
|
||||
|
||||
@@ -2,6 +2,7 @@ import QtQuick
|
||||
import Quickshell
|
||||
import Quickshell.Wayland
|
||||
import qs.Commons
|
||||
import qs.Commons as Commons
|
||||
|
||||
// Layer-shell popup attached to a bar widget icon, designed for
|
||||
// click-driven AND keyboard-driven panels (e.g. SUPER+CTRL+W summon).
|
||||
@@ -44,7 +45,7 @@ PanelWindow {
|
||||
property int padding: Style.spacing.popupPadding
|
||||
property int contentWidth: Style.space(280)
|
||||
property int contentHeight: Style.space(200)
|
||||
property var borderSpec: Border.surfaceSpec("popups", "border", Color.popups.border, Math.max(1, Style.space(2)))
|
||||
property var borderSpec: Border.surfaceSpec("popups", "border", Commons.Color.popups.border, Math.max(1, Style.space(2)))
|
||||
property bool centerOnBar: false
|
||||
property bool open: false
|
||||
property int gap: Style.gapsOut // distance between bar edge and panel
|
||||
@@ -382,7 +383,7 @@ PanelWindow {
|
||||
y: root.cardOrigin.y
|
||||
width: root.contentWidth
|
||||
height: root.contentHeight
|
||||
color: Color.popups.background
|
||||
color: Commons.Color.popups.background
|
||||
borderSpec: root.borderSpec
|
||||
padding: root.padding
|
||||
radius: Style.cornerRadius
|
||||
|
||||
@@ -3,6 +3,7 @@ import QtQuick.Controls as QQC
|
||||
import QtQuick.Window
|
||||
import Quickshell.Io
|
||||
import qs.Commons
|
||||
import qs.Commons as Commons
|
||||
|
||||
// Searchable multi-select dropdown. Trigger shape matches Dropdown /
|
||||
// SearchableDropdown; the popup shows a search field, an optional refresh
|
||||
@@ -33,11 +34,11 @@ Item {
|
||||
property string triggerLabel: ""
|
||||
property bool showLabel: true
|
||||
|
||||
property color foreground: Color.popups.text
|
||||
property color background: Color.popups.background
|
||||
property color popupBorder: Color.popups.border
|
||||
property color accent: Color.accent
|
||||
readonly property var popupBorderSpec: Border.localOrSurfaceSpec("popups", "border", popupBorder, Color.popups.border, Style.normalBorderWidth)
|
||||
property color foreground: Commons.Color.popups.text
|
||||
property color background: Commons.Color.popups.background
|
||||
property color popupBorder: Commons.Color.popups.border
|
||||
property color accent: Commons.Color.accent
|
||||
readonly property var popupBorderSpec: Border.localOrSurfaceSpec("popups", "border", popupBorder, Commons.Color.popups.border, Style.normalBorderWidth)
|
||||
property string fontFamily: Style.font.family
|
||||
property int rowHeight: Style.spacing.controlHeight
|
||||
property int popupRowHeight: Style.spacing.popupRowHeight
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls as QQC
|
||||
import qs.Commons
|
||||
import qs.Commons as Commons
|
||||
|
||||
Column {
|
||||
id: root
|
||||
@@ -10,8 +11,8 @@ Column {
|
||||
property int from: 0
|
||||
property int to: 100
|
||||
property int stepSize: 1
|
||||
property color foreground: Color.foreground
|
||||
property color accent: Color.accent
|
||||
property color foreground: Commons.Color.foreground
|
||||
property color accent: Commons.Color.accent
|
||||
property string fontFamily: Style.font.family
|
||||
property real fontSize: Style.font.body
|
||||
property real fieldWidth: Style.spacing.numberFieldWidth
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import QtQuick
|
||||
import qs.Commons
|
||||
import qs.Commons as Commons
|
||||
|
||||
Item {
|
||||
id: root
|
||||
@@ -7,7 +8,7 @@ Item {
|
||||
property string text: ""
|
||||
property string fontFamily: Style.font.family
|
||||
property real fontSize: Style.font.body
|
||||
property color color: Color.foreground
|
||||
property color color: Commons.Color.foreground
|
||||
property bool debugBounds: false
|
||||
|
||||
readonly property int renderedFontSize: Math.max(1, Math.round(fontSize))
|
||||
|
||||
+57
-24
@@ -3,12 +3,9 @@ import Quickshell
|
||||
import Quickshell.Hyprland
|
||||
import Quickshell.Wayland
|
||||
|
||||
// A fullscreen overlay whose surface outlives each open. A fresh surface draws
|
||||
// its first frames before the compositor sends its fractional scale, so an
|
||||
// overlay mapped per open flashed blurry until the scale arrived. Closed, the
|
||||
// surface parks as a 1x1, input-less, content-less layer below windows: small
|
||||
// enough to cost nothing, off the overlay layer so it never blocks direct
|
||||
// scanout for fullscreen apps. Opening only resizes and raises it.
|
||||
// Map a fresh fullscreen surface on each open. Keep its first frames
|
||||
// transparent until Qt receives the output's scale, so it opens sharp without
|
||||
// retaining a parked surface that can be closed when a monitor disconnects.
|
||||
PanelWindow {
|
||||
id: window
|
||||
|
||||
@@ -17,11 +14,31 @@ PanelWindow {
|
||||
property int shownLayer: WlrLayer.Overlay
|
||||
property int shownKeyboardFocus: WlrKeyboardFocus.Exclusive
|
||||
|
||||
// The surface no longer lands on the focused output by being mapped there,
|
||||
// so it follows the focused monitor each time it is shown. Unset until the
|
||||
// first show lets the compositor choose.
|
||||
property var targetScreen: null
|
||||
property Region emptyRegion: Region {}
|
||||
readonly property var targetMonitor: {
|
||||
var monitors = Hyprland.monitors.values
|
||||
for (var i = 0; i < monitors.length; i++) {
|
||||
if (targetScreen && monitors[i].name === targetScreen.name) return monitors[i]
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
// Wait for fullscreen geometry as well as scale so no smaller opening frame
|
||||
// is stretched across the output. Fractional scale uses units of 1/120;
|
||||
// compare in those units to tolerate floating point rounding.
|
||||
readonly property bool contentReady: shown && backingWindowVisible && !!targetScreen
|
||||
&& width === targetScreen.width && height === targetScreen.height
|
||||
&& !!targetMonitor && Math.round(devicePixelRatio * 120) === Math.round(targetMonitor.scale * 120)
|
||||
property bool contentRevealed: false
|
||||
|
||||
onContentReadyChanged: {
|
||||
contentRevealed = false
|
||||
// Resize and scale notifications arrive while Qt is still updating the
|
||||
// window. Reveal on the next turn, once its content layout has caught up.
|
||||
if (contentReady) Qt.callLater(function() {
|
||||
if (window.contentReady) window.contentRevealed = true
|
||||
})
|
||||
}
|
||||
|
||||
function focusedScreen() {
|
||||
var monitor = Hyprland.focusedMonitor
|
||||
@@ -29,28 +46,44 @@ PanelWindow {
|
||||
for (var i = 0; i < Quickshell.screens.length; i++) {
|
||||
if (Quickshell.screens[i].name === name) return Quickshell.screens[i]
|
||||
}
|
||||
return null
|
||||
return Quickshell.screens.length > 0 ? Quickshell.screens[0] : null
|
||||
}
|
||||
|
||||
onShownChanged: if (shown) targetScreen = focusedScreen() || targetScreen
|
||||
// Live monitor scaling does not emit a Hyprland monitor event, so its cached
|
||||
// scale can lag behind Qt. Refresh on opening and on scale changes while open.
|
||||
onShownChanged: {
|
||||
targetScreen = shown ? focusedScreen() : null
|
||||
if (shown) Hyprland.refreshMonitors()
|
||||
}
|
||||
onDevicePixelRatioChanged: if (shown) Hyprland.refreshMonitors()
|
||||
|
||||
visible: true
|
||||
Connections {
|
||||
target: Quickshell
|
||||
function onScreensChanged() {
|
||||
if (window.shown && Quickshell.screens.indexOf(window.targetScreen) < 0) {
|
||||
window.targetScreen = null
|
||||
// Let the removed output finish closing its old window before mapping
|
||||
// a replacement, rather than recreating it during Qt's teardown.
|
||||
Qt.callLater(function() {
|
||||
if (window.shown && !window.targetScreen) window.targetScreen = window.focusedScreen()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
visible: shown && !!targetScreen && !!targetMonitor
|
||||
screen: targetScreen
|
||||
anchors { top: true; left: true; bottom: shown; right: shown }
|
||||
implicitWidth: 1
|
||||
implicitHeight: 1
|
||||
mask: shown ? null : emptyRegion
|
||||
anchors { top: true; left: true; bottom: true; right: true }
|
||||
color: "transparent"
|
||||
exclusionMode: ExclusionMode.Ignore
|
||||
WlrLayershell.layer: shown ? shownLayer : WlrLayer.Bottom
|
||||
WlrLayershell.keyboardFocus: shown ? shownKeyboardFocus : WlrKeyboardFocus.None
|
||||
WlrLayershell.layer: shownLayer
|
||||
WlrLayershell.keyboardFocus: shownKeyboardFocus
|
||||
|
||||
// Draw nothing until the surface has actually grown. A frame drawn while it
|
||||
// is still 1x1 holds only the scrim's color, which the compositor would
|
||||
// stretch across the whole screen until the fullscreen frame arrives.
|
||||
// Opacity preserves keyboard handling while the scale arrives, including
|
||||
// search keystrokes and Escape pressed immediately after opening.
|
||||
Binding {
|
||||
target: window.contentItem
|
||||
property: "visible"
|
||||
value: window.shown && window.width > 1 && window.height > 1
|
||||
property: "opacity"
|
||||
value: window.contentRevealed ? 1 : 0
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -1,6 +1,7 @@
|
||||
import QtQuick
|
||||
import Quickshell.Io
|
||||
import qs.Commons
|
||||
import qs.Commons as Commons
|
||||
|
||||
// Base item for plugin popup widgets. Many first-party plugins expose a bar
|
||||
// button plus a popup from one QML entry point; this base owns the shared
|
||||
@@ -19,7 +20,7 @@ Item {
|
||||
property bool popoutSwitchClosing: false
|
||||
|
||||
readonly property bool opened: panelController.open
|
||||
readonly property color barForeground: bar ? bar.barForeground : Color.foreground
|
||||
readonly property color barForeground: bar ? bar.barForeground : Commons.Color.foreground
|
||||
|
||||
function open() { panelController.show() }
|
||||
function close() { panelController.hide() }
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import QtQuick
|
||||
import qs.Commons
|
||||
import qs.Commons as Commons
|
||||
|
||||
// Small (22×22 by default) icon button used at the right edge of panel rows
|
||||
// for inline actions — forget network, confirm passphrase, unpair device,
|
||||
@@ -29,7 +30,7 @@ BorderSurface {
|
||||
|
||||
property string iconText: ""
|
||||
property string tooltipText: ""
|
||||
property color foreground: Color.foreground
|
||||
property color foreground: Commons.Color.foreground
|
||||
property color hoverColor: foreground
|
||||
property string fontFamily: Style.font.family
|
||||
property real fontSize: Style.font.icon
|
||||
@@ -57,7 +58,7 @@ BorderSurface {
|
||||
? Border.controlSpec("focus", hoverColor, hoverColor)
|
||||
: (_hot && bordered
|
||||
? Border.controlSpec("hover-cursor", hoverColor, hoverColor)
|
||||
: (bordered ? Border.controlSpec("normal", foreground, Color.accent) : Border.none()))
|
||||
: (bordered ? Border.controlSpec("normal", foreground, Commons.Color.accent) : Border.none()))
|
||||
|
||||
color: _showFocusRing
|
||||
? Style.focusFillFor(hoverColor, hoverColor)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import QtQuick
|
||||
import qs.Commons
|
||||
import qs.Commons as Commons
|
||||
|
||||
Item {
|
||||
id: root
|
||||
@@ -8,7 +9,7 @@ Item {
|
||||
property string title: ""
|
||||
property string meta: ""
|
||||
property string detail: ""
|
||||
property color foreground: Color.foreground
|
||||
property color foreground: Commons.Color.foreground
|
||||
property string fontFamily: Style.font.family
|
||||
property real iconSize: Style.font.display
|
||||
property real iconOpacity: 1.0
|
||||
@@ -71,7 +72,7 @@ Item {
|
||||
implicitHeight: detailText.implicitHeight + Style.space(4)
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
color: "transparent"
|
||||
borderSpec: Border.controlSpec("normal", root.foreground, Color.accent)
|
||||
borderSpec: Border.controlSpec("normal", root.foreground, Commons.Color.accent)
|
||||
radius: Style.cornerRadius
|
||||
|
||||
Text {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import QtQuick
|
||||
import qs.Commons
|
||||
import qs.Commons as Commons
|
||||
|
||||
// Small-caps-style label that introduces a panel section ("DNS provider",
|
||||
// "Wi-Fi networks", "Output device", "Paired devices"). Sits between a
|
||||
@@ -7,7 +8,7 @@ import qs.Commons
|
||||
Text {
|
||||
id: root
|
||||
|
||||
property color foreground: Color.foreground
|
||||
property color foreground: Commons.Color.foreground
|
||||
property string fontFamily: Style.font.family
|
||||
property real fontSize: Style.font.caption
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import QtQuick
|
||||
import qs.Commons
|
||||
import qs.Commons as Commons
|
||||
|
||||
// 1px horizontal divider for panel sections. The alpha-on-foreground tint
|
||||
// keeps the rule legible against the panel background without competing
|
||||
@@ -7,7 +8,7 @@ import qs.Commons
|
||||
Rectangle {
|
||||
id: root
|
||||
|
||||
property color foreground: Color.foreground
|
||||
property color foreground: Commons.Color.foreground
|
||||
property real strength: 0.12
|
||||
|
||||
width: parent ? parent.width : implicitWidth
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import QtQuick
|
||||
import qs.Commons
|
||||
import qs.Commons as Commons
|
||||
|
||||
Item {
|
||||
id: root
|
||||
@@ -10,9 +11,9 @@ Item {
|
||||
property real maximum: 1
|
||||
property real step: 0.05
|
||||
property bool integer: false
|
||||
property color trackColor: bar ? Style.selectedFillFor(bar.foreground, Color.accent) : "#333"
|
||||
property color fillColor: bar ? bar.foreground : Color.foreground
|
||||
property color knobColor: bar ? bar.foreground : Color.foreground
|
||||
property color trackColor: bar ? Style.selectedFillFor(bar.foreground, Commons.Color.accent) : "#333"
|
||||
property color fillColor: bar ? bar.foreground : Commons.Color.foreground
|
||||
property color knobColor: bar ? bar.foreground : Commons.Color.foreground
|
||||
property bool dragging: false
|
||||
property real trackHeight: Math.max(4, Math.round(Style.spacing.controlHeight * 0.11))
|
||||
property real knobSize: Math.max(14, Math.round(Style.spacing.controlHeight * 0.38))
|
||||
@@ -23,7 +24,7 @@ Item {
|
||||
// crossing the track shows). Purely visual — snapping is the caller's job via
|
||||
// `integer`/`step` or an index-based value. Default 0 leaves the track plain.
|
||||
property int tickCount: 0
|
||||
property color tickColor: bar ? bar.background : Color.background
|
||||
property color tickColor: bar ? bar.background : Commons.Color.background
|
||||
|
||||
onValueChanged: if (!dragging) liveValue = value
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import qs.Commons
|
||||
import qs.Commons as Commons
|
||||
|
||||
// Styled wrapper around Qt Quick Controls ToolTip. Drop-in: declare inside
|
||||
// the hovered item and bind `visible` to the hover state, e.g.
|
||||
@@ -9,7 +10,7 @@ import qs.Commons
|
||||
// text: "Forget network"
|
||||
// }
|
||||
//
|
||||
// Defaults pull from [tooltip] in shell.toml via Color.tooltip.*. Override
|
||||
// Defaults pull from [tooltip] in shell.toml via Commons.Color.tooltip.*. Override
|
||||
// the panel* properties per-instance only when you need a tooltip that
|
||||
// intentionally diverges from the theme.
|
||||
//
|
||||
@@ -18,13 +19,13 @@ import qs.Commons
|
||||
ToolTip {
|
||||
id: root
|
||||
|
||||
property color panelForeground: Color.tooltip.text
|
||||
property color panelBackground: Color.tooltip.background
|
||||
property color panelBorder: Color.tooltip.border
|
||||
property color panelForeground: Commons.Color.tooltip.text
|
||||
property color panelBackground: Commons.Color.tooltip.background
|
||||
property color panelBorder: Commons.Color.tooltip.border
|
||||
property string fontFamily: Style.font.family
|
||||
property real fontSize: Style.font.bodySmall
|
||||
|
||||
readonly property var panelBorderSpec: Border.localOrSurfaceSpec("tooltip", "border", panelBorder, Color.tooltip.border, Style.normalBorderWidth)
|
||||
readonly property var panelBorderSpec: Border.localOrSurfaceSpec("tooltip", "border", panelBorder, Commons.Color.tooltip.border, Style.normalBorderWidth)
|
||||
|
||||
delay: 400
|
||||
padding: 0
|
||||
|
||||
@@ -2,6 +2,7 @@ import QtQuick
|
||||
import Quickshell
|
||||
import Quickshell.Hyprland
|
||||
import qs.Commons
|
||||
import qs.Commons as Commons
|
||||
|
||||
PopupWindow {
|
||||
id: root
|
||||
@@ -13,8 +14,8 @@ PopupWindow {
|
||||
property int padding: Style.spacing.popupPadding
|
||||
property int contentWidth: Style.space(280)
|
||||
property int contentHeight: Style.space(200)
|
||||
property color borderColor: Color.popups.border
|
||||
property var borderSpec: Border.localOrSurfaceSpec("popups", "border", borderColor, Color.popups.border, Math.max(1, Style.space(2)))
|
||||
property color borderColor: Commons.Color.popups.border
|
||||
property var borderSpec: Border.localOrSurfaceSpec("popups", "border", borderColor, Commons.Color.popups.border, Math.max(1, Style.space(2)))
|
||||
property bool open: false
|
||||
property bool centerOnBar: false
|
||||
// "click" — uses HyprlandFocusGrab so clicking outside dismisses the popup.
|
||||
@@ -150,7 +151,7 @@ PopupWindow {
|
||||
BorderSurface {
|
||||
id: card
|
||||
anchors.fill: parent
|
||||
color: Color.popups.background
|
||||
color: Commons.Color.popups.background
|
||||
borderSpec: root.borderSpec
|
||||
padding: root.padding
|
||||
radius: Style.cornerRadius
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls as QQC
|
||||
import qs.Commons
|
||||
import qs.Commons as Commons
|
||||
|
||||
// Searchable single-select dropdown. Same trigger shape as Dropdown, but
|
||||
// the popup leads with an embedded TextField that filters the option
|
||||
@@ -25,11 +26,11 @@ Item {
|
||||
property string emptyText: I18n.tr("No matches")
|
||||
property string triggerLabel: ""
|
||||
|
||||
property color foreground: Color.popups.text
|
||||
property color background: Color.popups.background
|
||||
property color popupBorder: Color.popups.border
|
||||
property color accent: Color.accent
|
||||
readonly property var popupBorderSpec: Border.localOrSurfaceSpec("popups", "border", popupBorder, Color.popups.border, Style.normalBorderWidth)
|
||||
property color foreground: Commons.Color.popups.text
|
||||
property color background: Commons.Color.popups.background
|
||||
property color popupBorder: Commons.Color.popups.border
|
||||
property color accent: Commons.Color.accent
|
||||
readonly property var popupBorderSpec: Border.localOrSurfaceSpec("popups", "border", popupBorder, Commons.Color.popups.border, Style.normalBorderWidth)
|
||||
property string fontFamily: Style.font.family
|
||||
property int rowHeight: Style.spacing.controlHeight
|
||||
property int popupRowHeight: Style.spacing.popupRowHeight
|
||||
|
||||
@@ -4,6 +4,7 @@ import QtQuick.Shapes
|
||||
import Quickshell
|
||||
import Quickshell.Wayland
|
||||
import qs.Commons
|
||||
import qs.Commons as Commons
|
||||
import qs.Ui
|
||||
|
||||
// Centered speed test overlay shared by the network and disk speed tests. No
|
||||
@@ -288,7 +289,7 @@ PanelWindow {
|
||||
// round caps would leave a stray dot at the foot of the scale.
|
||||
ShapePath {
|
||||
strokeWidth: dial.arcWidth * 3
|
||||
strokeColor: dial.arcVisible ? Qt.rgba(Color.accent.r, Color.accent.g, Color.accent.b, 0.18) : "transparent"
|
||||
strokeColor: dial.arcVisible ? Qt.rgba(Commons.Color.accent.r, Commons.Color.accent.g, Commons.Color.accent.b, 0.18) : "transparent"
|
||||
fillColor: "transparent"
|
||||
capStyle: ShapePath.RoundCap
|
||||
|
||||
@@ -305,7 +306,7 @@ PanelWindow {
|
||||
// Value: fills behind the needle.
|
||||
ShapePath {
|
||||
strokeWidth: dial.arcWidth
|
||||
strokeColor: dial.arcVisible ? Color.accent : "transparent"
|
||||
strokeColor: dial.arcVisible ? Commons.Color.accent : "transparent"
|
||||
fillColor: "transparent"
|
||||
capStyle: ShapePath.RoundCap
|
||||
|
||||
@@ -356,8 +357,8 @@ PanelWindow {
|
||||
radius: width / 2
|
||||
|
||||
gradient: Gradient {
|
||||
GradientStop { position: 0.0; color: Color.accent }
|
||||
GradientStop { position: 0.55; color: Color.accent }
|
||||
GradientStop { position: 0.0; color: Commons.Color.accent }
|
||||
GradientStop { position: 0.55; color: Commons.Color.accent }
|
||||
GradientStop { position: 1.0; color: "transparent" }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import qs.Commons
|
||||
import qs.Commons as Commons
|
||||
|
||||
// Single-line text input with the kit's focus + selection styling. Inherits
|
||||
// from Qt Quick Controls TextField so the underlying type's API (text,
|
||||
@@ -18,8 +19,8 @@ import qs.Commons
|
||||
TextField {
|
||||
id: root
|
||||
|
||||
property color foreground: Color.foreground
|
||||
property color accent: Color.accent
|
||||
property color foreground: Commons.Color.foreground
|
||||
property color accent: Commons.Color.accent
|
||||
property color selectionTint: Style.selectionFillFor(foreground, accent)
|
||||
property bool password: false
|
||||
property real horizontalPadding: Style.spacing.controlPaddingX
|
||||
|
||||
+3
-2
@@ -1,5 +1,6 @@
|
||||
import QtQuick
|
||||
import qs.Commons
|
||||
import qs.Commons as Commons
|
||||
|
||||
// Labeled toggle row: title + optional description on the left, a
|
||||
// `ToggleSwitch` on the right. Clicking anywhere on the row emits `clicked()`;
|
||||
@@ -28,8 +29,8 @@ BorderSurface {
|
||||
// Override per-instance if a caller wants the opposite.
|
||||
property bool rounded: Style.cornerRadius > 0
|
||||
|
||||
property color foreground: Color.foreground
|
||||
property color accent: Color.accent
|
||||
property color foreground: Commons.Color.foreground
|
||||
property color accent: Commons.Color.accent
|
||||
property string fontFamily: Style.font.family
|
||||
property real titleSize: Style.font.subtitle
|
||||
property real descriptionSize: Style.font.caption
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import QtQuick
|
||||
import qs.Commons
|
||||
import qs.Commons as Commons
|
||||
|
||||
// Bare on/off switch: a track with a sliding knob and no label. This is the
|
||||
// switch `Toggle` parks at the end of its labeled row, factored out so panel
|
||||
@@ -40,8 +41,8 @@ Item {
|
||||
property bool cursorRing: interactive
|
||||
property int cursorPad: Style.space(6)
|
||||
property bool rounded: Style.cornerRadius > 0
|
||||
property color foreground: Color.foreground
|
||||
property color accent: Color.accent
|
||||
property color foreground: Commons.Color.foreground
|
||||
property color accent: Commons.Color.accent
|
||||
|
||||
signal toggled()
|
||||
signal hovered(bool isHovered)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import QtQuick
|
||||
import qs.Commons
|
||||
import qs.Commons as Commons
|
||||
|
||||
Item {
|
||||
id: root
|
||||
@@ -8,8 +9,8 @@ Item {
|
||||
property string text: ""
|
||||
property string fontFamily: bar ? bar.fontFamily : Style.font.family
|
||||
property real fontSize: Style.font.body
|
||||
property color foreground: bar ? bar.barForeground : Color.foreground
|
||||
property color activeColor: bar ? bar.urgent : Color.urgent
|
||||
property color foreground: bar ? bar.barForeground : Commons.Color.foreground
|
||||
property color activeColor: bar ? bar.urgent : Commons.Color.urgent
|
||||
property bool active: false
|
||||
property real horizontalMargin: 8.5
|
||||
property real verticalPadding: 6
|
||||
|
||||
@@ -3,6 +3,7 @@ import QtQuick.Controls
|
||||
import Quickshell
|
||||
import Quickshell.Io
|
||||
import qs.Commons
|
||||
import qs.Commons as Commons
|
||||
import qs.Ui
|
||||
|
||||
Panel {
|
||||
@@ -11,11 +12,11 @@ Panel {
|
||||
ipcTarget: "omarchy.agents"
|
||||
manageIpc: false
|
||||
|
||||
readonly property color foreground: bar ? bar.foreground : Color.foreground
|
||||
readonly property color urgent: bar ? bar.urgent : Color.urgent
|
||||
readonly property color foreground: bar ? bar.foreground : Commons.Color.foreground
|
||||
readonly property color urgent: bar ? bar.urgent : Commons.Color.urgent
|
||||
readonly property color dim: Qt.darker(foreground, 1.55)
|
||||
readonly property color surface: Color.popups.background
|
||||
readonly property color track: Style.selectedFillFor(foreground, Color.accent)
|
||||
readonly property color surface: Commons.Color.popups.background
|
||||
readonly property color track: Style.selectedFillFor(foreground, Commons.Color.accent)
|
||||
readonly property string fontFamily: bar ? bar.fontFamily : Style.font.family
|
||||
|
||||
// Every subscription on one page, limits first: the question this panel
|
||||
@@ -725,7 +726,7 @@ Panel {
|
||||
function iconCandidatesForProvider(p, surfaceColor) {
|
||||
if (!p) return []
|
||||
var candidates = []
|
||||
if (colorLuminance(surfaceColor || Color.background) >= 0.5)
|
||||
if (colorLuminance(surfaceColor || Commons.Color.background) >= 0.5)
|
||||
candidates.push(Qt.resolvedUrl("assets/" + p.providerId + "-light.svg"))
|
||||
candidates.push(Qt.resolvedUrl("assets/" + p.providerId + ".svg"))
|
||||
return candidates
|
||||
@@ -1116,7 +1117,7 @@ Panel {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
textFormat: Text.PlainText
|
||||
text: choice.modelData.providerName
|
||||
color: choice.hasCursor ? Color.accent : root.foreground
|
||||
color: choice.hasCursor ? Commons.Color.accent : root.foreground
|
||||
font.family: root.fontFamily
|
||||
font.pixelSize: Style.font.body
|
||||
font.bold: true
|
||||
@@ -1196,7 +1197,7 @@ Panel {
|
||||
Text {
|
||||
textFormat: Text.PlainText
|
||||
text: root.addCode
|
||||
color: Color.accent
|
||||
color: Commons.Color.accent
|
||||
font.family: root.fontFamily
|
||||
font.pixelSize: Style.font.display
|
||||
font.bold: true
|
||||
@@ -1538,7 +1539,7 @@ Panel {
|
||||
property bool hasCursor: false
|
||||
implicitHeight: tileBody.implicitHeight + Style.space(20)
|
||||
radius: Style.cornerRadius
|
||||
color: hasCursor ? root.alpha(Color.accent, 0.14) : root.alpha(root.foreground, 0.05)
|
||||
color: hasCursor ? root.alpha(Commons.Color.accent, 0.14) : root.alpha(root.foreground, 0.05)
|
||||
onHasCursorChanged: if (hasCursor) root.revealItem(tile)
|
||||
|
||||
Row {
|
||||
@@ -1550,7 +1551,7 @@ Panel {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
textFormat: Text.PlainText
|
||||
text: tile.glyph
|
||||
color: Color.accent
|
||||
color: Commons.Color.accent
|
||||
font.family: root.fontFamily
|
||||
font.pixelSize: Style.font.heading
|
||||
}
|
||||
@@ -1559,7 +1560,7 @@ Panel {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
textFormat: Text.PlainText
|
||||
text: tile.title
|
||||
color: tile.hasCursor ? Color.accent : root.foreground
|
||||
color: tile.hasCursor ? Commons.Color.accent : root.foreground
|
||||
font.family: root.fontFamily
|
||||
font.pixelSize: Style.font.body
|
||||
font.bold: true
|
||||
@@ -1593,16 +1594,16 @@ Panel {
|
||||
implicitHeight: implicitWidth
|
||||
radius: Style.cornerRadius
|
||||
// The cursor needs more than a shade deeper to read on a tinted square.
|
||||
color: root.alpha(Color.accent, hasCursor ? 0.3 : 0.12)
|
||||
color: root.alpha(Commons.Color.accent, hasCursor ? 0.3 : 0.12)
|
||||
border.width: hasCursor ? Math.max(1, Style.hoverBorderWidth) : 0
|
||||
border.color: Color.accent
|
||||
border.color: Commons.Color.accent
|
||||
onHasCursorChanged: if (hasCursor) root.revealItem(heroButton)
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
textFormat: Text.PlainText
|
||||
text: heroButton.glyph
|
||||
color: Color.accent
|
||||
color: Commons.Color.accent
|
||||
font.family: root.fontFamily
|
||||
font.pixelSize: Style.font.heading
|
||||
}
|
||||
@@ -1634,7 +1635,7 @@ Panel {
|
||||
readonly property bool hot: linkMouse.containsMouse || picked
|
||||
onPickedChanged: if (picked) root.revealItem(link)
|
||||
textFormat: Text.PlainText
|
||||
color: current ? Color.accent : (hot ? root.foreground : idleColor)
|
||||
color: current ? Commons.Color.accent : (hot ? root.foreground : idleColor)
|
||||
font.family: root.fontFamily
|
||||
font.pixelSize: Style.font.caption
|
||||
font.bold: current
|
||||
@@ -1715,7 +1716,7 @@ Panel {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: Math.min(implicitWidth, parent.width * 0.6)
|
||||
text: head.label
|
||||
color: head.picked ? Color.accent : root.foreground
|
||||
color: head.picked ? Commons.Color.accent : root.foreground
|
||||
font.family: root.fontFamily
|
||||
font.pixelSize: Style.font.body
|
||||
font.bold: head.isActive
|
||||
@@ -1821,7 +1822,7 @@ Panel {
|
||||
anchors.right: parent.right
|
||||
textFormat: Text.PlainText
|
||||
text: I18n.tr("ACTIVE")
|
||||
color: Color.accent
|
||||
color: Commons.Color.accent
|
||||
font.family: root.fontFamily
|
||||
font.pixelSize: Style.font.caption
|
||||
font.bold: true
|
||||
|
||||
@@ -5,12 +5,14 @@ import QtQuick
|
||||
import QtQuick.Effects
|
||||
import QtQuick.Shapes
|
||||
import qs.Commons
|
||||
import qs.Commons as Commons
|
||||
import qs.Ui
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
property var shell: null
|
||||
property bool suspended: false
|
||||
readonly property string home: Quickshell.env("HOME")
|
||||
readonly property string stateHome: home + "/.local/state"
|
||||
readonly property string currentBackgroundLink: stateHome + "/omarchy/current/background"
|
||||
@@ -37,11 +39,20 @@ Item {
|
||||
property var sizeQueue: []
|
||||
property bool finishingTransition: false
|
||||
property int backgroundVersion: 0
|
||||
property int reloadVersion: 0
|
||||
property int revealStartedVersion: -1
|
||||
property int pendingThemeVersion: -1
|
||||
property string pendingColorsRaw: ""
|
||||
property string pendingShellRaw: ""
|
||||
property real revealProgress: 1
|
||||
readonly property bool ready: {
|
||||
if (isVideo(displayedBackground)) return true
|
||||
if (backgrounds.instances.length === 0) return false
|
||||
for (var panel of backgrounds.instances) {
|
||||
if (!panel.backgroundReady) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
function isVideo(path) {
|
||||
return Util.isVideoPath(path)
|
||||
@@ -56,7 +67,8 @@ Item {
|
||||
}
|
||||
|
||||
function setBackground(path, instant) {
|
||||
transitionBackground("", path, path, instant, false)
|
||||
if (instant) reloadVersion += 1
|
||||
transitionBackground("", path, path, instant, instant)
|
||||
}
|
||||
|
||||
function transitionBackground(fromPath, path, finalPath, instant, force) {
|
||||
@@ -106,10 +118,10 @@ Item {
|
||||
// pending; the latest theme payload should still apply.
|
||||
if (pendingThemeVersion < 0) return
|
||||
pendingThemeFallbackTimer.stop()
|
||||
Color.loadColors(pendingColorsRaw)
|
||||
// Color.loadShell also refreshes Style so the type scale flips with the
|
||||
Commons.Color.loadColors(pendingColorsRaw)
|
||||
// Commons.Color.loadShell also refreshes Style so the type scale flips with the
|
||||
// background reveal instead of waiting for a separate reload path.
|
||||
Color.loadShell(pendingShellRaw)
|
||||
Commons.Color.loadShell(pendingShellRaw)
|
||||
Style.scheduleRefresh()
|
||||
pendingThemeVersion = -1
|
||||
pendingColorsRaw = ""
|
||||
@@ -223,6 +235,10 @@ Item {
|
||||
root.setBackground(path, true)
|
||||
}
|
||||
|
||||
function setSuspended(value: string): void {
|
||||
root.suspended = value === "true"
|
||||
}
|
||||
|
||||
function transition(fromPath: string, path: string): void {
|
||||
root.transitionBackground(fromPath, path, path, false, false)
|
||||
}
|
||||
@@ -259,7 +275,7 @@ Item {
|
||||
from: 0
|
||||
to: 1
|
||||
duration: Style.duration(420)
|
||||
easing.type: Easing.InOutCubic
|
||||
easing.type: Easing.OutCubic
|
||||
onFinished: {
|
||||
if (root.incomingBackground) {
|
||||
root.displayedBackground = root.currentBackground || root.incomingBackground
|
||||
@@ -272,6 +288,7 @@ Item {
|
||||
Component.onCompleted: refreshBackground()
|
||||
|
||||
Variants {
|
||||
id: backgrounds
|
||||
model: Quickshell.screens
|
||||
|
||||
PanelWindow {
|
||||
@@ -279,7 +296,7 @@ Item {
|
||||
required property var modelData
|
||||
|
||||
screen: modelData
|
||||
visible: !remapGuard.remapping
|
||||
visible: !remapGuard.remapping && !root.suspended
|
||||
anchors { top: true; bottom: true; left: true; right: true }
|
||||
|
||||
ScreenMoveRemap {
|
||||
@@ -294,6 +311,13 @@ Item {
|
||||
updatesEnabled: true
|
||||
|
||||
property bool maskReady: false
|
||||
property int readyFrames: 0
|
||||
readonly property bool backgroundReady: base.ready && readyFrames >= 2
|
||||
|
||||
FrameAnimation {
|
||||
running: base.ready && panel.readyFrames < 2
|
||||
onTriggered: panel.readyFrames += 1
|
||||
}
|
||||
|
||||
// Decode the wallpaper at the size this screen can show, not the size
|
||||
// it was shipped at. With PreserveAspectCrop Qt takes sourceSize as the
|
||||
@@ -337,9 +361,12 @@ Item {
|
||||
id: base
|
||||
anchors.fill: parent
|
||||
path: root.displayedBackground
|
||||
version: root.reloadVersion
|
||||
cached: true
|
||||
constrainDecode: true
|
||||
decodeSize: panel.decodeSize(root.displayedBackground)
|
||||
onReadyChanged: {
|
||||
panel.readyFrames = 0
|
||||
if (ready && root.finishingTransition) {
|
||||
root.incomingBackground = ""
|
||||
root.oldBackground = ""
|
||||
|
||||
+14
-13
@@ -5,6 +5,7 @@ import Quickshell.Wayland
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import qs.Commons
|
||||
import qs.Commons as Commons
|
||||
import qs.Ui
|
||||
import "BarModel.js" as BarModel
|
||||
|
||||
@@ -71,18 +72,18 @@ Item {
|
||||
property string fontFamily: Style.font.family
|
||||
// Bound to the central Color singleton so the bar tracks shell.toml's
|
||||
// [bar] section. Property names kept for the rest of this file's bindings.
|
||||
property color themeForeground: Color.bar.text
|
||||
property color themeContrastForeground: Color.background
|
||||
property color transparentForeground: Color.bar.text
|
||||
property color themeForeground: Commons.Color.bar.text
|
||||
property color themeContrastForeground: Commons.Color.background
|
||||
property color transparentForeground: Commons.Color.bar.text
|
||||
property color foreground: themeForeground
|
||||
property color barForeground: useTransparentForeground ? transparentForeground : themeForeground
|
||||
property bool foregroundAnimationEnabled: true
|
||||
property color background: Color.bar.background
|
||||
property color urgent: Color.bar.active
|
||||
property color background: Commons.Color.bar.background
|
||||
property color urgent: Commons.Color.bar.active
|
||||
|
||||
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 } }
|
||||
Behavior on barForeground { enabled: root.foregroundAnimationEnabled; ColorAnimation { duration: Style.duration(420); easing.type: Easing.OutCubic } }
|
||||
Behavior on background { ColorAnimation { duration: Style.duration(420); easing.type: Easing.OutCubic } }
|
||||
Behavior on urgent { ColorAnimation { duration: Style.duration(420); easing.type: Easing.OutCubic } }
|
||||
property var tooltipTarget: null
|
||||
property var pendingTooltipTarget: null
|
||||
property string tooltipText: ""
|
||||
@@ -1342,8 +1343,8 @@ Item {
|
||||
id: tooltipBubble
|
||||
implicitWidth: tooltipLabel.implicitWidth + 20
|
||||
implicitHeight: tooltipLabel.implicitHeight + 14
|
||||
color: Color.tooltip.background
|
||||
borderSpec: Border.surfaceSpec("tooltip", "border", Color.tooltip.border, 1)
|
||||
color: Commons.Color.tooltip.background
|
||||
borderSpec: Border.surfaceSpec("tooltip", "border", Commons.Color.tooltip.border, 1)
|
||||
radius: Style.cornerRadius
|
||||
|
||||
Text {
|
||||
@@ -1351,7 +1352,7 @@ Item {
|
||||
textFormat: Text.PlainText
|
||||
anchors.centerIn: parent
|
||||
text: root.tooltipText
|
||||
color: Color.tooltip.text
|
||||
color: Commons.Color.tooltip.text
|
||||
font.family: root.fontFamily
|
||||
font.pixelSize: Style.font.body
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
@@ -1470,7 +1471,7 @@ Item {
|
||||
y: targetRect ? Math.round(targetRect.y) : 0
|
||||
width: targetRect ? targetRect.width : 0
|
||||
height: targetRect ? targetRect.height : 0
|
||||
color: Color.accent
|
||||
color: Commons.Color.accent
|
||||
radius: Math.min(width, height) / 2
|
||||
}
|
||||
}
|
||||
@@ -1905,7 +1906,7 @@ Item {
|
||||
|
||||
visible: opacity > 0
|
||||
opacity: slot.panelOpen && !slot.dragSource ? 0.9 : 0
|
||||
color: Color.accent
|
||||
color: Commons.Color.accent
|
||||
radius: Math.min(width, height) / 2
|
||||
width: root.vertical ? Style.space(2) : slot.panelIndicatorExtent
|
||||
height: root.vertical ? slot.panelIndicatorExtent : Style.space(2)
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
import QtQuick
|
||||
import Quickshell.Io
|
||||
import qs.Commons
|
||||
import qs.Ui
|
||||
|
||||
BarIndicator {
|
||||
id: root
|
||||
|
||||
property string state: "idle"
|
||||
property string icon: ""
|
||||
|
||||
active: state === "recording"
|
||||
activeText: icon
|
||||
inactiveText: ""
|
||||
activeTooltipText: state
|
||||
inactiveTooltipText: I18n.tr("Dictate")
|
||||
|
||||
function update(raw) {
|
||||
var data = extractData(raw)
|
||||
|
||||
state = String(data.alt || data.class || "idle")
|
||||
if (state === "recording") icon = ""
|
||||
else if (state === "transcribing") icon = ""
|
||||
else icon = ""
|
||||
}
|
||||
|
||||
Process {
|
||||
command: ["bash", "-c", "omarchy-voxtype-status"]
|
||||
running: true
|
||||
stdout: SplitParser {
|
||||
onRead: function(data) { root.update(data) }
|
||||
}
|
||||
}
|
||||
|
||||
onPressed: function() {
|
||||
if (!root.bar) return
|
||||
root.bar.run("omarchy-voxtype-config")
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ import QtQuick
|
||||
import Quickshell
|
||||
import Quickshell.Io
|
||||
import qs.Commons
|
||||
import qs.Commons as Commons
|
||||
import qs.Ui
|
||||
|
||||
BarIndicator {
|
||||
@@ -16,7 +17,7 @@ BarIndicator {
|
||||
activeTooltipText: I18n.tr("Disable Passwordless Sudo")
|
||||
inactiveTooltipText: I18n.tr("Passwordless Sudo")
|
||||
useActiveColor: true
|
||||
activeColor: Color.urgent
|
||||
activeColor: Commons.Color.urgent
|
||||
|
||||
function refresh() {
|
||||
if (!root.bar) return
|
||||
|
||||
@@ -2,6 +2,7 @@ import QtQuick
|
||||
import Quickshell
|
||||
import Quickshell.Wayland
|
||||
import qs.Commons
|
||||
import qs.Commons as Commons
|
||||
import qs.Ui
|
||||
|
||||
BarWidget {
|
||||
@@ -34,7 +35,7 @@ BarWidget {
|
||||
anchors.left: parent.left
|
||||
width: parent.width
|
||||
text: root.title
|
||||
color: root.bar ? root.bar.barForeground : Color.foreground
|
||||
color: root.bar ? root.bar.barForeground : Commons.Color.foreground
|
||||
font.family: root.bar ? root.bar.fontFamily : Style.font.family
|
||||
font.pixelSize: Style.font.body
|
||||
elide: Text.ElideRight
|
||||
|
||||
@@ -31,11 +31,6 @@
|
||||
"label": "Passwordless sudo",
|
||||
"description": "Warning while passwordless root access is enabled"
|
||||
},
|
||||
{
|
||||
"value": "Dictation",
|
||||
"label": "Dictation",
|
||||
"description": "Voice typing status"
|
||||
},
|
||||
{
|
||||
"value": "ScreenRecording",
|
||||
"label": "Screen recording",
|
||||
|
||||
@@ -8,7 +8,7 @@ BarWidget {
|
||||
id: root
|
||||
moduleName: "omarchy.indicators"
|
||||
|
||||
readonly property var defaultIndicatorEntries: [ "PasswordlessSudo", "Dictation", "ScreenRecording", "Reminder", "NightLight", "Dnd", "StayAwake" ]
|
||||
readonly property var defaultIndicatorEntries: [ "PasswordlessSudo", "ScreenRecording", "Reminder", "NightLight", "Dnd", "StayAwake" ]
|
||||
readonly property var indicatorEntries: indicatorEntriesFromSettings(settings)
|
||||
property var activeIndicatorIds: []
|
||||
property var indicatorActiveStates: ({})
|
||||
|
||||
@@ -4,6 +4,7 @@ import QtQuick.Controls
|
||||
import QtQuick.Effects
|
||||
import Quickshell.Services.SystemTray
|
||||
import qs.Commons
|
||||
import qs.Commons as Commons
|
||||
import qs.Ui
|
||||
import "TrayModel.js" as TrayModel
|
||||
|
||||
@@ -16,7 +17,7 @@ BarWidget {
|
||||
property bool trayMenuOpen: false
|
||||
property var activeTrayItem: null
|
||||
property var activeTrayAnchor: null
|
||||
readonly property color foreground: bar ? bar.foreground : Color.foreground
|
||||
readonly property color foreground: bar ? bar.foreground : Commons.Color.foreground
|
||||
readonly property string fontFamily: bar ? bar.fontFamily : Style.font.family
|
||||
readonly property var pinnedIds: settings.pinned instanceof Array ? settings.pinned : []
|
||||
readonly property var hiddenIds: settings.hidden instanceof Array ? settings.hidden : []
|
||||
@@ -620,7 +621,7 @@ BarWidget {
|
||||
anchors.rightMargin: Style.space(10)
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
height: 1
|
||||
color: Color.popups.border
|
||||
color: Commons.Color.popups.border
|
||||
opacity: 0.45
|
||||
}
|
||||
}
|
||||
@@ -674,7 +675,7 @@ BarWidget {
|
||||
anchors.rightMargin: Style.space(10)
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
height: 1
|
||||
color: Color.popups.border
|
||||
color: Commons.Color.popups.border
|
||||
opacity: 0.45
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import Quickshell.Io
|
||||
import Quickshell.Wayland
|
||||
import QtQuick
|
||||
import qs.Commons
|
||||
import qs.Commons as Commons
|
||||
import qs.Ui
|
||||
import "ClipboardHistory.js" as ClipboardHistory
|
||||
|
||||
@@ -22,13 +23,13 @@ Item {
|
||||
// Shares the [menu] surface tokens — themes that style the menu also
|
||||
// style the clipboard. Selected-row colors composed in the
|
||||
// singleton so consumers drop them straight into Rectangle bindings.
|
||||
property color background: Color.menu.background
|
||||
property color foreground: Color.menu.text
|
||||
property color border: Color.menu.border
|
||||
property color background: Commons.Color.menu.background
|
||||
property color foreground: Commons.Color.menu.text
|
||||
property color border: Commons.Color.menu.border
|
||||
property var borderSpec: Border.surfaceSpec("menu", "border", border, Math.max(1, Style.space(2)))
|
||||
property color scrim: Color.menu.scrim
|
||||
property color selectedBackground: Color.menu.selectedBackground
|
||||
property color selectedText: Color.menu.selectedText
|
||||
property color scrim: Commons.Color.menu.scrim
|
||||
property color selectedBackground: Commons.Color.menu.selectedBackground
|
||||
property color selectedText: Commons.Color.menu.selectedText
|
||||
readonly property int cornerRadius: Style.cornerRadius
|
||||
property string fontFamily: Style.font.menuFamily
|
||||
property int contentMargin: Style.spacing.panelPadding
|
||||
|
||||
@@ -3,6 +3,7 @@ import QtQuick.Controls
|
||||
import Quickshell
|
||||
import qs.Ui
|
||||
import qs.Commons
|
||||
import qs.Commons as Commons
|
||||
|
||||
// Visual reference + live playground for omarchy-shell's common UI
|
||||
// components. Summon with `omarchy dev ui-preview`, or directly via:
|
||||
@@ -66,10 +67,10 @@ Item {
|
||||
property var shell: null
|
||||
|
||||
// ---- theme --------------------------------------------------------------
|
||||
readonly property color foreground: Color.foreground
|
||||
readonly property color background: Color.background
|
||||
readonly property color accent: Color.accent
|
||||
readonly property color urgent: Color.urgent
|
||||
readonly property color foreground: Commons.Color.foreground
|
||||
readonly property color background: Commons.Color.background
|
||||
readonly property color accent: Commons.Color.accent
|
||||
readonly property color urgent: Commons.Color.urgent
|
||||
readonly property string fontFamily: "monospace"
|
||||
|
||||
// Fake `bar` for components that take a whole bar object (e.g. Slider).
|
||||
|
||||
@@ -3,6 +3,7 @@ import Quickshell.Io
|
||||
import Quickshell.Wayland
|
||||
import QtQuick
|
||||
import qs.Commons
|
||||
import qs.Commons as Commons
|
||||
import qs.Ui
|
||||
import "EmojiSearch.js" as EmojiSearch
|
||||
|
||||
@@ -23,13 +24,13 @@ Item {
|
||||
// Shares the [menu] surface tokens — themes that style the menu also
|
||||
// style emojis. Selected-cell colors composed in the
|
||||
// singleton so consumers drop them straight into Rectangle bindings.
|
||||
property color background: Color.menu.background
|
||||
property color foreground: Color.menu.text
|
||||
property color border: Color.menu.border
|
||||
property color background: Commons.Color.menu.background
|
||||
property color foreground: Commons.Color.menu.text
|
||||
property color border: Commons.Color.menu.border
|
||||
property var borderSpec: Border.surfaceSpec("menu", "border", border, Math.max(1, Style.space(2)))
|
||||
property color scrim: Color.menu.scrim
|
||||
property color selectedBackground: Color.menu.selectedBackground
|
||||
property color selectedText: Color.menu.selectedText
|
||||
property color scrim: Commons.Color.menu.scrim
|
||||
property color selectedBackground: Commons.Color.menu.selectedBackground
|
||||
property color selectedText: Commons.Color.menu.selectedText
|
||||
readonly property int cornerRadius: Style.cornerRadius
|
||||
property string fontFamily: Style.font.menuFamily
|
||||
property int contentMargin: Style.spacing.panelPadding
|
||||
|
||||
@@ -5,6 +5,7 @@ import QtQuick
|
||||
import QtQuick.Effects
|
||||
import QtQuick.Shapes
|
||||
import qs.Commons
|
||||
import qs.Commons as Commons
|
||||
import qs.Ui
|
||||
import "ImagePickerModel.js" as ImagePickerModel
|
||||
|
||||
@@ -37,14 +38,14 @@ Item {
|
||||
property string themeRows: ""
|
||||
property bool themeMode: false
|
||||
property bool themeOpenPending: false
|
||||
// Bound to the central [image-picker] section in shell.toml via Color.qml.
|
||||
// Bound to the central [image-picker] section in shell.toml via Commons.Color.qml.
|
||||
// `dimColor` tints unselected slices and text outlines on top of the scrim;
|
||||
// it intentionally tracks the foundational background, not a surface role.
|
||||
property color dimColor: Color.background
|
||||
property color foreground: Color.imagePicker.text
|
||||
property color scrim: Color.imagePicker.scrim
|
||||
property color selectedBorder: Color.imagePicker.selectedBorder
|
||||
property color unselectedBorder: Color.imagePicker.unselectedBorder
|
||||
property color dimColor: Commons.Color.background
|
||||
property color foreground: Commons.Color.imagePicker.text
|
||||
property color scrim: Commons.Color.imagePicker.scrim
|
||||
property color selectedBorder: Commons.Color.imagePicker.selectedBorder
|
||||
property color unselectedBorder: Commons.Color.imagePicker.unselectedBorder
|
||||
property int expandedWidth: 768
|
||||
property int expandedHeight: 475
|
||||
property int sliceWidth: 108
|
||||
@@ -274,7 +275,29 @@ Item {
|
||||
property var imageArray: []
|
||||
readonly property var matchingImageIndices: ImagePickerModel.matchingIndices(imageArray, filterText)
|
||||
onMatchingImageIndicesChanged: updateVisibleItems()
|
||||
onSelectedIndexChanged: updateVisibleItems()
|
||||
onSelectedIndexChanged: {
|
||||
updateVisibleItems()
|
||||
introPrepareTimer.restart()
|
||||
}
|
||||
onThemeModeChanged: if (themeMode) introPrepareTimer.restart()
|
||||
|
||||
Timer {
|
||||
id: introPrepareTimer
|
||||
interval: 75
|
||||
onTriggered: {
|
||||
if (root.opened && root.themeMode && !introPrepare.running) {
|
||||
introPrepare.theme = root.nameForPath(root.currentPath())
|
||||
introPrepare.command = ["omarchy-theme-bg-boot-intro", "--prepare-theme", root.nameForPath(root.currentPath())]
|
||||
introPrepare.running = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Process {
|
||||
id: introPrepare
|
||||
property string theme: ""
|
||||
onExited: if (root.opened && root.themeMode && theme !== root.nameForPath(root.currentPath())) introPrepareTimer.restart()
|
||||
}
|
||||
|
||||
function updateVisibleItems() {
|
||||
ImagePickerModel.syncWindow(visibleImages, ImagePickerModel.visibleWindow(matchingImageIndices, selectedIndex, previewRadius))
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import QtQuick
|
||||
import QtQuick.Effects
|
||||
import qs.Commons
|
||||
import qs.Commons as Commons
|
||||
import qs.Ui
|
||||
|
||||
Item {
|
||||
@@ -42,8 +43,8 @@ Item {
|
||||
readonly property bool showPasswordCursor: inputEnabled && !authenticatingPassword && failureMessage.length === 0
|
||||
readonly property bool errorState: failureMessage.length > 0
|
||||
readonly property var inputBorderSpec: errorState
|
||||
? Border.surfaceSpec("lock", "border-error", Color.lock.borderError, root.outlineThickness, "border-alpha")
|
||||
: Border.surfaceSpec("lock", "border-active", Color.lock.borderActive, root.outlineThickness, "border-alpha")
|
||||
? Border.surfaceSpec("lock", "border-error", Commons.Color.lock.borderError, root.outlineThickness, "border-alpha")
|
||||
: Border.surfaceSpec("lock", "border-active", Commons.Color.lock.borderActive, root.outlineThickness, "border-alpha")
|
||||
|
||||
readonly property bool video: Util.isVideoPath(root.backgroundPath)
|
||||
readonly property bool feedActive: root.video && root.loadBackground && !root.displaysBlank && !root.powerSaverActive
|
||||
@@ -97,7 +98,7 @@ Item {
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: Color.background
|
||||
color: Commons.Color.background
|
||||
|
||||
BackgroundMedia {
|
||||
id: wallpaper
|
||||
@@ -156,7 +157,7 @@ Item {
|
||||
width: root.fieldWidth
|
||||
height: root.fieldHeight
|
||||
anchors.centerIn: parent
|
||||
color: Color.lock.background
|
||||
color: Commons.Color.lock.background
|
||||
borderSpec: root.inputBorderSpec
|
||||
radius: Style.cornerRadius
|
||||
clip: true
|
||||
@@ -179,16 +180,16 @@ Item {
|
||||
echoMode: TextInput.Password
|
||||
passwordCharacter: "\u25CF"
|
||||
passwordMaskDelay: 0
|
||||
color: Color.lock.text
|
||||
selectionColor: Color.lock.selection
|
||||
selectedTextColor: Color.lock.text
|
||||
color: Commons.Color.lock.text
|
||||
selectionColor: Commons.Color.lock.selection
|
||||
selectedTextColor: Commons.Color.lock.text
|
||||
font.family: Style.font.family
|
||||
font.pixelSize: text.length > 0 ? Math.max(1, Math.floor(root.passwordDotFontSize * root.passwordDotScale)) : root.fieldFontSize
|
||||
font.letterSpacing: text.length > 0 ? root.passwordDotLetterSpacing * root.passwordDotScale : 0
|
||||
cursorVisible: activeFocus && root.showPasswordCursor && text.length > 0
|
||||
cursorDelegate: Rectangle {
|
||||
width: 2
|
||||
color: Color.lock.text
|
||||
color: Commons.Color.lock.text
|
||||
visible: passwordInput.cursorVisible
|
||||
}
|
||||
|
||||
@@ -224,7 +225,7 @@ Item {
|
||||
anchors.fill: passwordInput
|
||||
text: root.authenticatingPassword ? I18n.tr("Checking…") : (root.failureMessage.length > 0 ? root.failureMessage : root.placeholderText)
|
||||
visible: passwordInput.text.length === 0
|
||||
color: root.authenticatingPassword ? Color.lock.text : (root.failureMessage.length > 0 ? Color.lock.textError : Color.lock.placeholder)
|
||||
color: root.authenticatingPassword ? Commons.Color.lock.text : (root.failureMessage.length > 0 ? Commons.Color.lock.textError : Commons.Color.lock.placeholder)
|
||||
font.family: Style.font.family
|
||||
font.pixelSize: root.fieldFontSize
|
||||
font.italic: !root.authenticatingPassword && root.failureMessage.length > 0
|
||||
@@ -247,7 +248,7 @@ Item {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
visible: root.fingerprintConfigured
|
||||
text: root.fingerprintUnavailable ? "" : ""
|
||||
color: root.fingerprintUnavailable ? Color.lock.textError : Color.lock.placeholder
|
||||
color: root.fingerprintUnavailable ? Commons.Color.lock.textError : Commons.Color.lock.placeholder
|
||||
font.family: Style.font.family
|
||||
font.pixelSize: Math.round(root.fieldFontSize * 1.1)
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
@@ -266,7 +267,7 @@ Item {
|
||||
anchors.horizontalCenter: inputField.horizontalCenter
|
||||
visible: root.fingerprintConfigured && root.fingerprintUnavailable
|
||||
text: I18n.tr("Fingerprint reader unavailable")
|
||||
color: Color.lock.textError
|
||||
color: Commons.Color.lock.textError
|
||||
font.family: Style.font.family
|
||||
font.pixelSize: Style.font.heading
|
||||
font.italic: true
|
||||
|
||||
@@ -4,6 +4,7 @@ import Quickshell.Io
|
||||
import Quickshell.Services.Pam
|
||||
import Quickshell.Wayland
|
||||
import qs.Commons
|
||||
import qs.Commons as Commons
|
||||
import "FingerprintModel.js" as FingerprintModel
|
||||
|
||||
Item {
|
||||
@@ -467,7 +468,7 @@ Item {
|
||||
|
||||
WlSessionLockSurface {
|
||||
id: lockSurface
|
||||
color: Color.background
|
||||
color: Commons.Color.background
|
||||
|
||||
LockView {
|
||||
id: lockView
|
||||
|
||||
+11
-10
@@ -3,6 +3,7 @@ import Quickshell.Io
|
||||
import Quickshell.Wayland
|
||||
import QtQuick
|
||||
import qs.Commons
|
||||
import qs.Commons as Commons
|
||||
import qs.Ui
|
||||
import "MenuModel.js" as MenuModel
|
||||
|
||||
@@ -84,17 +85,17 @@ Item {
|
||||
property bool deleteConfirmOpen: false
|
||||
property var deleteTarget: null
|
||||
onOpenedChanged: if (!opened) { deleteConfirmOpen = false; deleteTarget = null }
|
||||
// Bound to the central [menu] section in shell.toml via Color.qml.
|
||||
// Bound to the central [menu] section in shell.toml via Commons.Color.qml.
|
||||
// Each color already includes its alpha companion (composed in the
|
||||
// singleton), so consumers can drop them straight into a Rectangle.
|
||||
property color background: Color.menu.background
|
||||
property color foreground: Color.menu.text
|
||||
property color border: Color.menu.border
|
||||
property color background: Commons.Color.menu.background
|
||||
property color foreground: Commons.Color.menu.text
|
||||
property color border: Commons.Color.menu.border
|
||||
property var borderSpec: Border.surfaceSpec("menu", "border", border, Math.max(1, Style.space(2)))
|
||||
property color scrim: Color.menu.scrim
|
||||
property color selectedBackground: Color.menu.selectedBackground
|
||||
property color selectedText: Color.menu.selectedText
|
||||
property color selectedBorder: Color.menu.selectedBorder
|
||||
property color scrim: Commons.Color.menu.scrim
|
||||
property color selectedBackground: Commons.Color.menu.selectedBackground
|
||||
property color selectedText: Commons.Color.menu.selectedText
|
||||
property color selectedBorder: Commons.Color.menu.selectedBorder
|
||||
property var selectedBorderSpec: Border.surfaceSpec("menu", "selected-border", selectedBorder, 0)
|
||||
readonly property real rowReservedBorderLeft: Border.left(selectedBorderSpec)
|
||||
readonly property real rowReservedBorderRight: Border.right(selectedBorderSpec)
|
||||
@@ -1088,7 +1089,7 @@ Item {
|
||||
// then on the card grows and shrinks downward instead of re-centering
|
||||
// on every resize, which made the menu jump around. The rows height is
|
||||
// frozen at the same moment, so the starting menu also caps how tall the
|
||||
// card may grow from there. Closing unfreezes both.
|
||||
// card may grow from there. Closing or changing screens unfreezes both.
|
||||
property int cardTop: -1
|
||||
property int maxRowsHeight: -1
|
||||
readonly property int centeredTop: Math.max(Style.gapsOut, Math.round((height - root.cardHeight) / 2))
|
||||
@@ -1099,8 +1100,8 @@ Item {
|
||||
maxRowsHeight = root.visibleRowsHeight
|
||||
}
|
||||
}
|
||||
// The surface stays mapped between opens, so closing is shown going false.
|
||||
onShownChanged: if (!shown) { cardTop = -1; maxRowsHeight = -1 }
|
||||
onTargetScreenChanged: { cardTop = -1; maxRowsHeight = -1 }
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
|
||||
@@ -413,6 +413,7 @@ var GUARD_READERS = [
|
||||
"omarchy-default-browser",
|
||||
"omarchy-default-editor",
|
||||
"omarchy-default-terminal",
|
||||
"omarchy-default-dictation",
|
||||
"omarchy-dns",
|
||||
"omarchy-region",
|
||||
"omarchy-language"
|
||||
|
||||
@@ -6,6 +6,7 @@ import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import Quickshell
|
||||
import qs.Commons
|
||||
import qs.Commons as Commons
|
||||
import qs.Ui
|
||||
import "../NotificationLogic.js" as NotificationLogic
|
||||
|
||||
@@ -48,10 +49,10 @@ BorderSurface {
|
||||
readonly property string sanitizedBody: sanitizeBody(body)
|
||||
readonly property string styledBody: NotificationLogic.styledBody(body, app, appIcon)
|
||||
|
||||
readonly property color dimColor: Qt.darker(Color.notifications.text, 1.4)
|
||||
readonly property color bodyColor: Qt.darker(Color.notifications.text, 1.15)
|
||||
readonly property color accentColor: urgency === 2 ? Color.urgent : (urgency === 0 ? dimColor : Color.notifications.countdown)
|
||||
readonly property var cardBorderSpec: Border.surfaceSpec("notifications", "border", Color.notifications.border, Math.max(1, Style.space(2)))
|
||||
readonly property color dimColor: Qt.darker(Commons.Color.notifications.text, 1.4)
|
||||
readonly property color bodyColor: Qt.darker(Commons.Color.notifications.text, 1.15)
|
||||
readonly property color accentColor: urgency === 2 ? Commons.Color.urgent : (urgency === 0 ? dimColor : Commons.Color.notifications.countdown)
|
||||
readonly property var cardBorderSpec: Border.surfaceSpec("notifications", "border", Commons.Color.notifications.border, Math.max(1, Style.space(2)))
|
||||
|
||||
function sanitizeBody(s) {
|
||||
return NotificationLogic.sanitizeBody(s, app, appIcon)
|
||||
@@ -70,7 +71,7 @@ BorderSurface {
|
||||
// doesn't push content under the bottom edge.
|
||||
implicitHeight: mainColumn.implicitHeight + borderTop + borderBottom
|
||||
radius: cornerRadius
|
||||
color: Color.notifications.background
|
||||
color: Commons.Color.notifications.background
|
||||
borderSpec: cardBorderSpec
|
||||
clip: true
|
||||
|
||||
@@ -139,7 +140,7 @@ BorderSurface {
|
||||
anchors.centerIn: parent
|
||||
visible: root.hasGlyph && smallIconImage.status !== Image.Ready
|
||||
text: root.glyph
|
||||
color: Color.notifications.text
|
||||
color: Commons.Color.notifications.text
|
||||
font.family: root.fontFamily
|
||||
font.pixelSize: Style.font.displayLarge
|
||||
}
|
||||
@@ -150,7 +151,7 @@ BorderSurface {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
visible: root.compactGlyph
|
||||
text: root.glyph
|
||||
color: Color.notifications.text
|
||||
color: Commons.Color.notifications.text
|
||||
font.family: root.fontFamily
|
||||
font.pixelSize: Style.font.icon
|
||||
}
|
||||
@@ -172,7 +173,7 @@ BorderSurface {
|
||||
visible: root.summary.length > 0
|
||||
text: root.summary
|
||||
font.family: "Liberation Sans"
|
||||
color: Color.notifications.text
|
||||
color: Commons.Color.notifications.text
|
||||
font.pixelSize: Style.font.title
|
||||
font.bold: true
|
||||
wrapMode: Text.WordWrap
|
||||
@@ -210,7 +211,7 @@ BorderSurface {
|
||||
required property var modelData
|
||||
text: modelData.text
|
||||
bordered: true
|
||||
foreground: Color.notifications.text
|
||||
foreground: Commons.Color.notifications.text
|
||||
fontFamily: root.fontFamily
|
||||
onClicked: root.actionClicked(modelData.identifier)
|
||||
}
|
||||
@@ -235,7 +236,7 @@ BorderSurface {
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "✕"
|
||||
color: closeArea.containsMouse ? Color.notifications.text : root.dimColor
|
||||
color: closeArea.containsMouse ? Commons.Color.notifications.text : root.dimColor
|
||||
font.pixelSize: Math.round(Style.font.caption * 1.44)
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import Quickshell
|
||||
import Quickshell.Io
|
||||
import Quickshell.Wayland
|
||||
import qs.Commons
|
||||
import qs.Commons as Commons
|
||||
import qs.Ui
|
||||
import "OsdModel.js" as OsdModel
|
||||
|
||||
@@ -139,8 +140,8 @@ Item {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: Style.space(67)
|
||||
color: Util.alpha(Color.background, 0.97)
|
||||
borderSpec: Border.surfaceSpec("popups", "border", Color.popups.border, Math.max(1, Style.space(2)))
|
||||
color: Util.alpha(Commons.Color.background, 0.97)
|
||||
borderSpec: Border.surfaceSpec("popups", "border", Commons.Color.popups.border, Math.max(1, Style.space(2)))
|
||||
radius: Style.cornerRadius
|
||||
opacity: root.opened ? 1 : 0
|
||||
|
||||
@@ -162,7 +163,7 @@ Item {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: root.icon
|
||||
font: iconMetrics.font
|
||||
color: Color.popups.text
|
||||
color: Commons.Color.popups.text
|
||||
}
|
||||
}
|
||||
Rectangle {
|
||||
@@ -170,11 +171,11 @@ Item {
|
||||
width: root.barWidth
|
||||
height: Math.max(Style.space(6), Style.spacing.sm)
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
color: Util.alpha(Color.popups.text, 0.45)
|
||||
color: Util.alpha(Commons.Color.popups.text, 0.45)
|
||||
Rectangle {
|
||||
height: parent.height
|
||||
width: parent.width * (root.hasProgress ? root.value / root.maxValue : 0)
|
||||
color: Color.accent
|
||||
color: Commons.Color.accent
|
||||
|
||||
Behavior on width {
|
||||
enabled: root.opened
|
||||
@@ -192,7 +193,7 @@ Item {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: root.message
|
||||
font: messageMetrics.font
|
||||
color: Color.popups.text
|
||||
color: Commons.Color.popups.text
|
||||
elide: Text.ElideRight
|
||||
maximumLineCount: 1
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import Quickshell.Services.Mpris
|
||||
import Quickshell.Services.Pipewire
|
||||
import qs.Ui
|
||||
import qs.Commons
|
||||
import qs.Commons as Commons
|
||||
import "Model.js" as Model
|
||||
|
||||
Panel {
|
||||
@@ -179,10 +180,10 @@ Panel {
|
||||
readonly property string toggleHint: anyAudible ? I18n.tr("Mute") : I18n.tr("Unmute")
|
||||
|
||||
readonly property color hoverFill: bar
|
||||
? Style.hoverFillFor(bar.foreground, Color.accent)
|
||||
? Style.hoverFillFor(bar.foreground, Commons.Color.accent)
|
||||
: "transparent"
|
||||
readonly property color selectedFill: bar
|
||||
? Style.selectedFillFor(bar.foreground, Color.accent)
|
||||
? Style.selectedFillFor(bar.foreground, Commons.Color.accent)
|
||||
: "transparent"
|
||||
|
||||
function sectionCount(section) {
|
||||
|
||||
@@ -6,6 +6,7 @@ import Quickshell.Bluetooth
|
||||
import Quickshell.Services.Pipewire
|
||||
import qs.Ui
|
||||
import qs.Commons
|
||||
import qs.Commons as Commons
|
||||
import "Model.js" as Model
|
||||
|
||||
Panel {
|
||||
@@ -104,10 +105,10 @@ Panel {
|
||||
readonly property string toggleHint: root.adapter && root.adapter.enabled ? I18n.tr("Turn Bluetooth off") : I18n.tr("Turn Bluetooth on")
|
||||
|
||||
readonly property color hoverFill: bar
|
||||
? Style.hoverFillFor(bar.foreground, Color.accent)
|
||||
? Style.hoverFillFor(bar.foreground, Commons.Color.accent)
|
||||
: "transparent"
|
||||
readonly property color selectedFill: bar
|
||||
? Style.selectedFillFor(bar.foreground, Color.accent)
|
||||
? Style.selectedFillFor(bar.foreground, Commons.Color.accent)
|
||||
: "transparent"
|
||||
|
||||
function sectionCount(section) {
|
||||
|
||||
Loaded 100 of 239 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user