aboutsummaryrefslogtreecommitdiffstats
path: root/desktop/modules
diff options
context:
space:
mode:
Diffstat (limited to 'desktop/modules')
-rw-r--r--desktop/modules/user/README.md5
-rwxr-xr-xdesktop/modules/user/test-userctl.sh19
-rwxr-xr-xdesktop/modules/user/userctl15
3 files changed, 32 insertions, 7 deletions
diff --git a/desktop/modules/user/README.md b/desktop/modules/user/README.md
index 7a09c07..6e67b50 100644
--- a/desktop/modules/user/README.md
+++ b/desktop/modules/user/README.md
@@ -7,7 +7,7 @@ it opens, which edits the user's details where other programs read them.
| --- | --- |
| name | AccountsService `RealName` (which also rewrites the passwd GECOS that LibreOffice prefills from), `~/.config/emaildefaults` `FullName`, git `user.name` with the surname as an initial |
| email | AccountsService `Email`, emaildefaults `EmailAddress`, git `user.email` |
-| avatar | AccountsService `IconFile`; the daemon copies the file in and SDDM shows it |
+| avatar | `~/.user-icon.jpg` (converted to JPEG with `magick`), which hyprlock, the udt SDDM theme and the rofi power menu read; then AccountsService `IconFile`, so its consumers agree |
| language, location | AccountsService |
| signing key | git `user.signingkey`; None unsets it |
@@ -25,6 +25,5 @@ Checks: `./test-userctl.sh` (stubs every store) and
`node desktop/modules/user/test_user.js`.
Not here: the password (`passwd` in a terminal; changing it also leaves the
-login keyring on the old one), `~/.face.icon` (SDDM reads the
-AccountsService icon), social links (nothing reads them). Values are read
+login keyring on the old one), `~/.face.icon` (nothing here reads it), social links (nothing reads them). Values are read
when the page opens, not watched.
diff --git a/desktop/modules/user/test-userctl.sh b/desktop/modules/user/test-userctl.sh
index 02a6e0c..33d50a2 100755
--- a/desktop/modules/user/test-userctl.sh
+++ b/desktop/modules/user/test-userctl.sh
@@ -34,11 +34,12 @@ case "$n" in
busctl) [[ " $* " == *" get-property "* ]] && printf '{"type":"s","data":"%s"}\n' "${@: -1}" ;;
git) [[ " $* " == *" --get "* ]] && { [[ -n "${GIT_VALUE:-}" ]] && echo "$GIT_VALUE" || exit 1; } ;;
gpg) cat "$GPG_FIXTURE" ;;
+ magick) : > "${@: -1}" ;;
esac
exit 0
EOF
chmod +x "$tmp/bin/stub"
-for n in busctl kwriteconfig6 git gpg; do ln -s stub "$tmp/bin/$n"; done
+for n in busctl kwriteconfig6 git gpg magick; do ln -s stub "$tmp/bin/$n"; done
export PATH="$tmp/bin:$PATH" HOME="$tmp" LOG="$tmp/log"
obj="/org/freedesktop/Accounts/User$(id -u)"
@@ -66,6 +67,11 @@ language=Language
location=Location
signingkey=ABCDEF" "$("$ctl" get)"
+# The desktop's avatar file, once it exists, wins over AccountsService's.
+: > "$HOME/.user-icon.jpg"
+check "get prefers ~/.user-icon.jpg" "avatar=$HOME/.user-icon.jpg" "$("$ctl" get | grep '^avatar=')"
+rm "$HOME/.user-icon.jpg"
+
# keys: the primary fingerprint and first uid of each secret key; subkey
# fingerprints and later uids are skipped.
reset
@@ -111,12 +117,21 @@ kwriteconfig6 [--file] [emaildefaults] [--group] [PROFILE_Default] [--key] [Emai
git [config] [--global] [user.email] [jane@example.org]" "$(cat "$LOG")"
# AccountsService only.
-for pair in avatar:SetIconFile language:SetLanguage location:SetLocation; do
+for pair in language:SetLanguage location:SetLocation; do
reset
"$ctl" set "${pair%%:*}" v >/dev/null
check "set ${pair%%:*} writes" "$acc [${pair#*:}] [s] [v]" "$(cat "$LOG")"
done
+# avatar: converted to ~/.user-icon.jpg through a temp file, then handed to
+# AccountsService, so the greeter, hyprlock and the login screen agree.
+reset
+"$ctl" set avatar /pics/me.png >/dev/null
+check "set avatar writes" "magick [/pics/me.png] [-auto-orient] [-strip] [$HOME/.user-icon.jpg.tmp.jpg]
+$acc [SetIconFile] [s] [$HOME/.user-icon.jpg]" "$(cat "$LOG")"
+check "set avatar leaves the file" "yes" "$([[ -e "$HOME/.user-icon.jpg" && ! -e "$HOME/.user-icon.jpg.tmp.jpg" ]] && echo yes)"
+rm -f "$HOME/.user-icon.jpg"
+
# signingkey: a fingerprint is written; empty unsets, but only if one is set.
reset
"$ctl" set signingkey ABCD >/dev/null
diff --git a/desktop/modules/user/userctl b/desktop/modules/user/userctl
index d9720d8..5ad31d1 100755
--- a/desktop/modules/user/userctl
+++ b/desktop/modules/user/userctl
@@ -18,7 +18,9 @@
# userctl set <key> <val> write one field to every store holding it
#
# Stores: AccountsService (and through SetRealName the passwd GECOS that
-# LibreOffice reads), KDE's ~/.config/emaildefaults, the global git config.
+# LibreOffice reads), KDE's ~/.config/emaildefaults, the global git config,
+# and ~/.user-icon.jpg, the avatar hyprlock, the SDDM theme and the rofi
+# power menu read (udt-accent points the greeter at it).
# Polkit lets a user change their own AccountsService entry without a prompt.
#
# set prints nothing on success. On a failing write it prints the command and
@@ -30,6 +32,7 @@ set -u
# Character-wise ${x:0:1}, so an accented initial is not cut in half.
export LC_ALL=C.UTF-8
+AVATAR="$HOME/.user-icon.jpg"
ACC=org.freedesktop.Accounts
OBJ="/org/freedesktop/Accounts/User$(id -u)"
IFACE=org.freedesktop.Accounts.User
@@ -77,6 +80,8 @@ case "$1" in
# Read everything first: one error line and exit 1, never blank fields.
for p in RealName:name Email:email IconFile:avatar Language:language Location:location; do
val="$(prop "${p%%:*}")" || { printf 'error=%s\n' "$val"; exit 1; }
+ # The desktop's avatar wins; AccountsService's is the fallback.
+ [[ "${p#*:}" == avatar && -e "$AVATAR" ]] && val="$AVATAR"
out+="${p#*:}=$val"$'\n'
done
printf '%s' "$out"
@@ -104,7 +109,13 @@ case "$1" in
kde EmailAddress "$v"
run git config --global user.email "$v"
;;
- avatar) acc SetIconFile "$v" ;;
+ avatar)
+ # Converted, so the .jpg name is true whatever was picked;
+ # renamed into place, so no reader sees half a file.
+ run magick "$v" -auto-orient -strip "$AVATAR.tmp.jpg"
+ run mv -f "$AVATAR.tmp.jpg" "$AVATAR"
+ acc SetIconFile "$AVATAR"
+ ;;
language) acc SetLanguage "$v" ;;
location) acc SetLocation "$v" ;;
signingkey)