diff --git a/install_gnome_extension b/install_gnome_extension new file mode 100755 index 0000000..fad96f2 --- /dev/null +++ b/install_gnome_extension @@ -0,0 +1,107 @@ +#!/bin/bash +# Install/update a gnome-shell extension from the shared applications +# directory into the user's local extensions dir, and enable it. Shared by +# install_gtile and install_tactile -- see those for which UUID/build was +# vetted compatible with this rhel9 / gnome-shell 40 desktop. +# +# Usage: install_gnome_extension + +UUID="${1:?Usage: $(basename "$0") }" +SRC="/sf/bernina/applications/${UUID}" +EXT_DIR="${HOME}/.local/share/gnome-shell/extensions" +DEST="${EXT_DIR}/${UUID}" + +log() { echo "$(date '+%F %T') install_gnome_extension(${UUID}): $*"; } + +# This runs at login via autostart, right when /sf/bernina (a Kerberos-secured +# NFS4 mount, sec=krb5) may still be settling its GSS context for this brand +# new session -- retry briefly instead of permanently giving up on a +# transient "not there yet" (confirmed intermittent gTile failures previously +# had no logging at all here, so a one-shot failure like this could never be +# told apart from a real missing-source case; see gtile_link_migration memory). +tries=0 +until [ -d "$SRC" ]; do + tries=$((tries + 1)) + if [ "$tries" -ge 10 ]; then + log "source $SRC still not found after ${tries}s, giving up" + exit 0 + fi + sleep 1 +done +[ "$tries" -gt 0 ] && log "source $SRC took ${tries}s to become available" + +# PSI's home-sync (linux_home_links.yaml) links this dir to the SMB network +# drive, but a known depth-nesting bug in that tool leaves it a broken +# symlink (missing a "../../../" prefix) -- fall back to a plain local +# directory rather than failing the install. +if [ -L "$EXT_DIR" ] && [ ! -e "$EXT_DIR" ]; then + log "$EXT_DIR is a broken symlink ($(readlink "$EXT_DIR")), replacing with a local directory" + rm -f "$EXT_DIR" +fi + +# Clear anything GNOME Shell's own extensions.gnome.org auto-update check +# may have already staged here before allow-extension-installation (set by +# the main startup script) had a chance to stop it -- a stale staged build +# would otherwise still be sitting here ready to silently swap in on some +# future shell restart, superseding the pinned version reinstalled below. +rm -rf "${HOME}/.local/share/gnome-shell/extension-updates/${UUID}" + +src_version=$(sed -n 's/.*"version": *\([0-9]*\).*/\1/p' "$SRC/metadata.json") +dest_version="" +[ -f "$DEST/metadata.json" ] && dest_version=$(sed -n 's/.*"version": *\([0-9]*\).*/\1/p' "$DEST/metadata.json") + +reinstalled=false +if [ ! -d "$DEST" ] || [ "$src_version" != "$dest_version" ]; then + mkdir -p "$(dirname "$DEST")" + rsync -a --delete "$SRC/" "$DEST/" + glib-compile-schemas "$DEST/schemas" 2>/dev/null + log "installed version $src_version to $DEST (was: ${dest_version:-none})" + reinstalled=true +fi + +# A plain `enable` is a no-op if the extension is already enabled -- the +# normal case every login -- so it does NOT make gnome-shell pick up a +# version this script just rsynced onto disk above (extensions aren't +# hot-reloaded on file change). Force a disable/enable cycle whenever we +# actually changed what's on disk, so the running session matches disk +# immediately instead of only from the next full login onward (confirmed: +# this exact gap is what left saresb-cons-05 running a stale in-memory gTile +# version even after the rsync above had already put the correct one back +# on disk). +if $reinstalled && gnome-extensions list --enabled 2>/dev/null | grep -qx "$UUID"; then + gnome-extensions disable "$UUID" 2>/dev/null +fi + +# enable the extension (needs a live gnome-shell D-Bus session, i.e. +# org.gnome.Shell.Extensions already registered -- also not guaranteed yet +# this early at login, so retry briefly before falling back). +enabled=false +tries=0 +until gnome-extensions enable "$UUID" 2>/dev/null; do + tries=$((tries + 1)) + if [ "$tries" -ge 5 ]; then + break + fi + sleep 1 +done +if [ "$tries" -lt 5 ] || gnome-extensions list --enabled 2>/dev/null | grep -qx "$UUID"; then + enabled=true + [ "$tries" -gt 0 ] && log "gnome-extensions enable succeeded after ${tries}s" +fi + +if ! $enabled; then + # shell D-Bus interface still not reachable -- fall back to writing the + # enabled-extensions list directly; gnome-shell picks this up itself once + # it (or its extension-directory file monitor) is ready. + log "gnome-extensions enable unreachable after ${tries}s, falling back to gsettings" + python3 - "$UUID" <<'EOF' +import subprocess, sys +uuid = sys.argv[1] +current = eval(subprocess.check_output( + ["gsettings", "get", "org.gnome.shell", "enabled-extensions"]).decode()) +if uuid not in current: + current.append(uuid) + subprocess.call(["gsettings", "set", "org.gnome.shell", + "enabled-extensions", str(current)]) +EOF +fi diff --git a/install_gtile b/install_gtile index 7aa2534..cc405e1 100755 --- a/install_gtile +++ b/install_gtile @@ -1,73 +1,4 @@ #!/bin/bash -# Install/update the gTile gnome-shell extension from the shared applications -# directory into the user's local extensions dir, and enable it. # Compatible gTile build for this rhel9 / gnome-shell 40 desktop lives in -# /sf/bernina/applications/gTile@vibou. - -UUID="gTile@vibou" -SRC="/sf/bernina/applications/${UUID}" -EXT_DIR="${HOME}/.local/share/gnome-shell/extensions" -DEST="${EXT_DIR}/${UUID}" - -if [ ! -d "$SRC" ]; then - echo "install_gtile: source $SRC not found, skipping" >&2 - exit 0 -fi - -# PSI's home-sync (linux_home_links.yaml) links this dir to the SMB network -# drive, but a known depth-nesting bug in that tool leaves it a broken -# symlink (missing a "../../../" prefix) -- fall back to a plain local -# directory rather than failing the install. -if [ -L "$EXT_DIR" ] && [ ! -e "$EXT_DIR" ]; then - echo "install_gtile: $EXT_DIR is a broken symlink ($(readlink "$EXT_DIR")), replacing with a local directory" >&2 - rm -f "$EXT_DIR" -fi - -# Clear anything GNOME Shell's own extensions.gnome.org auto-update check -# may have already staged here before allow-extension-installation (set by -# the main startup script) had a chance to stop it -- a stale staged build -# would otherwise still be sitting here ready to silently swap in on some -# future shell restart, superseding the pinned version reinstalled below. -rm -rf "${HOME}/.local/share/gnome-shell/extension-updates/${UUID}" - -src_version=$(sed -n 's/.*"version": *\([0-9]*\).*/\1/p' "$SRC/metadata.json") -dest_version="" -[ -f "$DEST/metadata.json" ] && dest_version=$(sed -n 's/.*"version": *\([0-9]*\).*/\1/p' "$DEST/metadata.json") - -reinstalled=false -if [ ! -d "$DEST" ] || [ "$src_version" != "$dest_version" ]; then - mkdir -p "$(dirname "$DEST")" - rsync -a --delete "$SRC/" "$DEST/" - glib-compile-schemas "$DEST/schemas" 2>/dev/null - echo "install_gtile: installed gTile version $src_version to $DEST" - reinstalled=true -fi - -# A plain `enable` is a no-op if the extension is already enabled -- the -# normal case every login -- so it does NOT make gnome-shell pick up a -# version this script just rsynced onto disk above (extensions aren't -# hot-reloaded on file change). Force a disable/enable cycle whenever we -# actually changed what's on disk, so the running session matches disk -# immediately instead of only from the next full login onward (confirmed: -# this exact gap is what left saresb-cons-05 running a stale in-memory -# version even after the rsync above had already put the correct one back -# on disk). -if $reinstalled && gnome-extensions list --enabled 2>/dev/null | grep -qx "$UUID"; then - gnome-extensions disable "$UUID" 2>/dev/null -fi - -# enable the extension (needs a live gnome-shell D-Bus session) -if ! gnome-extensions enable "$UUID" 2>/dev/null; then - # shell D-Bus interface not reachable yet (e.g. very early in session - # startup) -- fall back to writing the enabled-extensions list directly - python3 - "$UUID" <<'EOF' -import subprocess, sys -uuid = sys.argv[1] -current = eval(subprocess.check_output( - ["gsettings", "get", "org.gnome.shell", "enabled-extensions"]).decode()) -if uuid not in current: - current.append(uuid) - subprocess.call(["gsettings", "set", "org.gnome.shell", - "enabled-extensions", str(current)]) -EOF -fi +# /sf/bernina/applications/gTile@vibou (shell-version includes "40"). +exec /sf/bernina/bin/install_gnome_extension "gTile@vibou" diff --git a/install_tactile b/install_tactile new file mode 100755 index 0000000..d8cee8e --- /dev/null +++ b/install_tactile @@ -0,0 +1,6 @@ +#!/bin/bash +# Compatible Tactile build for this rhel9 / gnome-shell 40 desktop lives in +# /sf/bernina/applications/tactile@lundal.io -- version 27 (extensions.gnome.org +# package 40260), whose shell-version list covers 3.32 through 44, including +# this desktop's 40.10. +exec /sf/bernina/bin/install_gnome_extension "tactile@lundal.io" diff --git a/startup_bernina_terminal b/startup_bernina_terminal index 6c80204..a8ad878 100755 --- a/startup_bernina_terminal +++ b/startup_bernina_terminal @@ -203,7 +203,12 @@ set_gnome_keyboard_shortcut 'dark screens' 'xset dpms force off' 'd' # reason for it to be on when every extension this desktop uses is already # managed by hand. gsettings set org.gnome.shell allow-extension-installation false -install_gtile +# Logged (unlike a bare call) so an intermittent skip/fallback here -- e.g. +# /sf/bernina (Kerberos NFS4) not yet reachable this early at login, or +# gnome-shell's D-Bus Extensions interface not registered yet -- leaves a +# trace instead of silently vanishing, since this runs unattended via +# autostart with no terminal to watch. +install_gtile >> "$HOME/.install_gtile.log" 2>&1 dconf write /org/gnome/shell/extensions/gtile/resize21 "'3x3 0:2 0:2, 0:1 0:2, 0:2 1:2, 0:1 1:2'" dconf write /org/gnome/shell/extensions/gtile/resize22 "'3x3 1:2 1:2, 1:1 1:2, 0:2 2:2, 0:1 2:2'" dconf write /org/gnome/shell/extensions/gtile/resize23 "'3x3 2:2 2:2, 2:1 2:2, 1:2 2:2, 1:1 2:2'" @@ -219,7 +224,15 @@ dconf write /org/gnome/shell/extensions/gtile/resize29 "'3x3 2:0 2:0, 2:0 2:1, 1 # every other preset-resize-2N sibling was untouched and still works fine) # -- reset it back to gTile's own default rather than hardcoding a value # here, so this self-heals regardless of what that default actually is. -gsettings reset org.gnome.shell.extensions.gtile preset-resize-21 +# NOTE: `dconf reset`, not `gsettings reset` -- gTile's schema is a +# relocatable one bundled inside the extension itself and never registered +# system-wide, so plain `gsettings` (run outside gnome-shell's own process, +# which loads it internally) can't see it at all ("No such schema", +# confirmed by hand -- this line was silently failing every single run). +# `dconf reset` only touches the raw key/value store, no schema needed -- +# gnome-shell's own GSettings wrapper then falls back to the compiled-in +# default the next time it reads the now-unset key. +dconf reset /org/gnome/shell/extensions/gtile/preset-resize-21 # Second gTile preset set: a 4x4 grid on + the right-hand # key block, laid out to spatially match the keyboard (row of keys top to @@ -260,22 +273,52 @@ dconf write /org/gnome/shell/extensions/gtile/resize13 "'4x4 0:0 3:3, 0:1 2:3, 0 dconf write /org/gnome/shell/extensions/gtile/resize14 "'4x4 1:1 3:3, 0:1 2:3, 0:1 0:3, 0:3 0:3'" dconf write /org/gnome/shell/extensions/gtile/resize15 "'4x4 2:2 3:3, 2:3 2:3, 2:3 0:3, 0:3 0:3'" dconf write /org/gnome/shell/extensions/gtile/resize16 "'4x4 3:3 3:3, 2:3 2:3, 2:3 0:3, 0:3 0:3'" -gsettings set org.gnome.shell.extensions.gtile preset-resize-1 "['7']" -gsettings set org.gnome.shell.extensions.gtile preset-resize-2 "['8']" -gsettings set org.gnome.shell.extensions.gtile preset-resize-3 "['9']" -gsettings set org.gnome.shell.extensions.gtile preset-resize-4 "['0']" -gsettings set org.gnome.shell.extensions.gtile preset-resize-5 "['u']" -gsettings set org.gnome.shell.extensions.gtile preset-resize-6 "['i']" -gsettings set org.gnome.shell.extensions.gtile preset-resize-7 "['o']" -gsettings set org.gnome.shell.extensions.gtile preset-resize-8 "['p']" -gsettings set org.gnome.shell.extensions.gtile preset-resize-9 "['j']" -gsettings set org.gnome.shell.extensions.gtile preset-resize-10 "['k']" -gsettings set org.gnome.shell.extensions.gtile preset-resize-11 "['l']" -gsettings set org.gnome.shell.extensions.gtile preset-resize-12 "['semicolon']" -gsettings set org.gnome.shell.extensions.gtile preset-resize-13 "['m']" -gsettings set org.gnome.shell.extensions.gtile preset-resize-14 "['comma']" -gsettings set org.gnome.shell.extensions.gtile preset-resize-15 "['period']" -gsettings set org.gnome.shell.extensions.gtile preset-resize-16 "['slash']" +# NOTE: `dconf write`, not `gsettings set` -- gTile's schema is bundled +# inside the extension and never registered system-wide, so plain +# `gsettings` (run outside gnome-shell's own process) can't see it at all +# ("No such schema", confirmed by hand). These 16 lines used to be +# `gsettings set` and were therefore silently failing every single run -- +# the resize1-16 grid layouts above were being written fine (dconf write +# never needed the schema), but the keybindings meant to trigger them never +# actually got assigned, leaving preset-resize-1..16 at gTile's factory +# defaults (KP_N / KP_N) instead of this +# right-hand block. This is almost certainly why this second preset set +# looked like it "didn't work" while the numpad set above (which only ever +# needed dconf write, no keybinding reassignment) did. +dconf write /org/gnome/shell/extensions/gtile/preset-resize-1 "['7']" +dconf write /org/gnome/shell/extensions/gtile/preset-resize-2 "['8']" +dconf write /org/gnome/shell/extensions/gtile/preset-resize-3 "['9']" +dconf write /org/gnome/shell/extensions/gtile/preset-resize-4 "['0']" +dconf write /org/gnome/shell/extensions/gtile/preset-resize-5 "['u']" +dconf write /org/gnome/shell/extensions/gtile/preset-resize-6 "['i']" +dconf write /org/gnome/shell/extensions/gtile/preset-resize-7 "['o']" +dconf write /org/gnome/shell/extensions/gtile/preset-resize-8 "['p']" +dconf write /org/gnome/shell/extensions/gtile/preset-resize-9 "['j']" +dconf write /org/gnome/shell/extensions/gtile/preset-resize-10 "['k']" +dconf write /org/gnome/shell/extensions/gtile/preset-resize-11 "['l']" +dconf write /org/gnome/shell/extensions/gtile/preset-resize-12 "['semicolon']" +dconf write /org/gnome/shell/extensions/gtile/preset-resize-13 "['m']" +dconf write /org/gnome/shell/extensions/gtile/preset-resize-14 "['comma']" +dconf write /org/gnome/shell/extensions/gtile/preset-resize-15 "['period']" +dconf write /org/gnome/shell/extensions/gtile/preset-resize-16 "['slash']" + +#install/update and enable the tactile extension (a second, simpler +#grid-tiling extension alongside gTile above), then pin its keyboard +#shortcuts to its own shipped defaults so they self-heal against the same +#kind of stray-override drift documented for gTile's preset-resize-21. +# `dconf reset`, not `gsettings reset` -- see the note on gTile's +# preset-resize-21 above: tactile's schema is bundled inside the extension +# and never registered system-wide, so plain `gsettings` can't see it. +install_tactile >> "$HOME/.install_tactile.log" 2>&1 +dconf reset /org/gnome/shell/extensions/tactile/show-tiles +dconf reset /org/gnome/shell/extensions/tactile/hide-tiles +dconf reset /org/gnome/shell/extensions/tactile/show-settings +dconf reset /org/gnome/shell/extensions/tactile/next-monitor +dconf reset /org/gnome/shell/extensions/tactile/prev-monitor +dconf reset /org/gnome/shell/extensions/tactile/layout-1 +dconf reset /org/gnome/shell/extensions/tactile/layout-2 +dconf reset /org/gnome/shell/extensions/tactile/layout-3 +dconf reset /org/gnome/shell/extensions/tactile/layout-4 # gnome terminal color profiles: install Solarized Dark/Light and Spacedust # (plus a "1-Spacedust" copy that sorts to the top of the profile menu) if @@ -337,5 +380,5 @@ command -v notify-send >/dev/null 2>&1 && notify-send -u low "Bernina Terminal" # make rhel9 text larger and rely on default dash, no extra cluttering dock. dconf write /org/gnome/desktop/interface/text-scaling-factor 1.25 -dconf write /org/gnome/shell/enabled-extensions "['appindicatorsupport@rgcjonas.gmail.com', 'gTile@vibou']" +dconf write /org/gnome/shell/enabled-extensions "['appindicatorsupport@rgcjonas.gmail.com', 'gTile@vibou', 'tactile@lundal.io']" dconf write /org/gnome/shell/disabled-extensions "['dash-to-dock@gnome-shell-extensions.gcampax.github.com']"