From 8b37ea31d322a002ecd56a0e751a11804a4d1d06 Mon Sep 17 00:00:00 2001 From: mdheller <21163552+mdheller@users.noreply.github.com> Date: Thu, 23 Apr 2026 22:04:59 -0400 Subject: [PATCH 1/9] workstation-v0: add mac-style screenshot helper --- .../workstation-v0/bin/mac-screenshot.sh | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 profiles/linux-dev/workstation-v0/bin/mac-screenshot.sh diff --git a/profiles/linux-dev/workstation-v0/bin/mac-screenshot.sh b/profiles/linux-dev/workstation-v0/bin/mac-screenshot.sh new file mode 100644 index 0000000..68b3801 --- /dev/null +++ b/profiles/linux-dev/workstation-v0/bin/mac-screenshot.sh @@ -0,0 +1,84 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Mac-style screenshot helper for SourceOS workstation-v0. +# Intended GNOME bindings: +# - Super+Shift+3 -> full screen +# - Super+Shift+4 -> area selection +# - Super+Shift+5 -> interactive screenshot UI + +err(){ printf "ERROR: %s\n" "$*" >&2; } +info(){ printf "INFO: %s\n" "$*" >&2; } +have(){ command -v "$1" >/dev/null 2>&1; } + +screenshot_dir(){ + printf '%s\n' "${SOURCEOS_SCREENSHOT_DIR:-$HOME/Pictures/Screenshots}" +} + +stamp(){ date +%Y-%m-%d-%H%M%S; } + +open_dir(){ + local d=$1 + if have xdg-open; then + xdg-open "$d" >/dev/null 2>&1 || true + elif have open; then + open "$d" >/dev/null 2>&1 || true + fi +} + +shot(){ + local mode=$1 + local d out + d="$(screenshot_dir)" + mkdir -p "$d" + out="$d/Screenshot-$(stamp).png" + + if ! have gnome-screenshot; then + err "gnome-screenshot is not installed" + exit 127 + fi + + case "$mode" in + screen) + gnome-screenshot -f "$out" + ;; + area) + gnome-screenshot -a -f "$out" + ;; + window) + gnome-screenshot -w -f "$out" + ;; + interactive) + gnome-screenshot -i + exit 0 + ;; + *) + err "unknown screenshot mode: $mode (use screen|area|window|interactive|open-dir)" + exit 2 + ;; + esac + + info "wrote: $out" +} + +main(){ + case "${1:-screen}" in + screen|area|window|interactive) + shot "$1" + ;; + open-dir) + mkdir -p "$(screenshot_dir)" + open_dir "$(screenshot_dir)" + ;; + -h|--help|help) + cat <<'EOF' +Usage: mac-screenshot.sh [screen|area|window|interactive|open-dir] +EOF + ;; + *) + shot "$1" + ;; + esac +} + +main "$@" From 5be8972fbcf5367597d4b6e332d9ac088350df5d Mon Sep 17 00:00:00 2001 From: mdheller <21163552+mdheller@users.noreply.github.com> Date: Thu, 23 Apr 2026 22:07:12 -0400 Subject: [PATCH 2/9] ci(workstation): add GNOME Mac polish smoke workflow --- .github/workflows/workstation-mac-polish.yml | 47 ++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 .github/workflows/workstation-mac-polish.yml diff --git a/.github/workflows/workstation-mac-polish.yml b/.github/workflows/workstation-mac-polish.yml new file mode 100644 index 0000000..3e21ae4 --- /dev/null +++ b/.github/workflows/workstation-mac-polish.yml @@ -0,0 +1,47 @@ +name: workstation-mac-polish + +on: + pull_request: + paths: + - 'profiles/linux-dev/workstation-v0/bin/mac-screenshot.sh' + - 'profiles/linux-dev/workstation-v0/bin/install-sourceos-cli.sh' + - 'profiles/linux-dev/workstation-v0/gnome/mac-defaults.sh' + - 'profiles/linux-dev/workstation-v0/gnome/README.md' + - 'profiles/linux-dev/workstation-v0/manifest.yaml' + - 'docs/workstation/**' + - '.github/workflows/workstation-mac-polish.yml' + push: + branches: + - main + paths: + - 'profiles/linux-dev/workstation-v0/bin/mac-screenshot.sh' + - 'profiles/linux-dev/workstation-v0/bin/install-sourceos-cli.sh' + - 'profiles/linux-dev/workstation-v0/gnome/mac-defaults.sh' + - 'profiles/linux-dev/workstation-v0/gnome/README.md' + - 'profiles/linux-dev/workstation-v0/manifest.yaml' + - 'docs/workstation/**' + - '.github/workflows/workstation-mac-polish.yml' + +jobs: + mac-polish-smoke: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Syntax check Mac polish scripts + run: | + set -euo pipefail + bash -n profiles/linux-dev/workstation-v0/bin/mac-screenshot.sh + bash -n profiles/linux-dev/workstation-v0/bin/install-sourceos-cli.sh + bash -n profiles/linux-dev/workstation-v0/gnome/mac-defaults.sh + + - name: Smoke: installer writes user wrappers + run: | + set -euo pipefail + installer='profiles/linux-dev/workstation-v0/bin/install-sourceos-cli.sh' + tmp_home=$(mktemp -d) + HOME="$tmp_home" bash "$installer" + test -x "$tmp_home/.local/bin/sourceos" + test -x "$tmp_home/.local/bin/mac-screenshot.sh" + test -s "$tmp_home/.config/sourceos/profile.path" From 8deb18c5dbf8bd4df33739fc8b2543435c589b0a Mon Sep 17 00:00:00 2001 From: mdheller <21163552+mdheller@users.noreply.github.com> Date: Thu, 23 Apr 2026 22:09:34 -0400 Subject: [PATCH 3/9] workstation-v0: declare GNOME quicklook and screenshot polish --- profiles/linux-dev/workstation-v0/manifest.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/profiles/linux-dev/workstation-v0/manifest.yaml b/profiles/linux-dev/workstation-v0/manifest.yaml index 6a1a89b..2310bbc 100644 --- a/profiles/linux-dev/workstation-v0/manifest.yaml +++ b/profiles/linux-dev/workstation-v0/manifest.yaml @@ -16,6 +16,8 @@ spec: - xclip - fuzzel - input-remapper + - sushi + - gnome-screenshot dnf: - git - openssh-clients @@ -26,6 +28,8 @@ spec: - xclip - fuzzel - input-remapper + - sushi + - gnome-screenshot user: brew: - fzf @@ -83,6 +87,10 @@ spec: name: fusuma enabled: true rationale: "MIT multitouch gesture recognizer using libinput" + mac_polish: + quicklook: sushi + screenshots: gnome-screenshot + screenshot_dir: "~/Pictures/Screenshots" launcher: palette: primary: fuzzel From ddb5d907cb9b55203aaa5a9a7258e3dee8b93ef1 Mon Sep 17 00:00:00 2001 From: mdheller <21163552+mdheller@users.noreply.github.com> Date: Thu, 23 Apr 2026 22:12:34 -0400 Subject: [PATCH 4/9] workstation-v0: install mac screenshot helper wrapper --- .../bin/install-sourceos-cli.sh | 70 ++++++++++++------- 1 file changed, 44 insertions(+), 26 deletions(-) diff --git a/profiles/linux-dev/workstation-v0/bin/install-sourceos-cli.sh b/profiles/linux-dev/workstation-v0/bin/install-sourceos-cli.sh index fc9b1ef..4576662 100644 --- a/profiles/linux-dev/workstation-v0/bin/install-sourceos-cli.sh +++ b/profiles/linux-dev/workstation-v0/bin/install-sourceos-cli.sh @@ -1,23 +1,18 @@ #!/usr/bin/env bash set -euo pipefail -# Install the profile-local `sourceos` helper CLI to user scope. -# Target: ~/.local/bin/sourceos -# -# IMPORTANT: -# - We do NOT copy the helper script itself into ~/.local/bin. -# - Instead we install a small wrapper that pins the profile directory in -# $XDG_CONFIG_HOME/sourceos/profile.path and execs the profile-local helper. -# -# Rationale: -# - The helper CLI is profile-scoped (linux-dev/workstation-v0). Copying it out of -# the profile directory breaks relative-path assumptions and can drift. +# Install profile-local workstation helper CLIs to user scope. +# Targets: +# - ~/.local/bin/sourceos +# - ~/.local/bin/mac-screenshot.sh PROFILE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" -IMPL="$PROFILE_DIR/bin/sourceos" +SOURCEOS_IMPL="$PROFILE_DIR/bin/sourceos" +SCREENSHOT_IMPL="$PROFILE_DIR/bin/mac-screenshot.sh" DEST_DIR="${HOME}/.local/bin" -DEST="$DEST_DIR/sourceos" +SOURCEOS_DEST="$DEST_DIR/sourceos" +SCREENSHOT_DEST="$DEST_DIR/mac-screenshot.sh" CFG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/sourceos" PROFILE_FILE="$CFG_DIR/profile.path" @@ -26,17 +21,28 @@ info(){ printf "INFO: %s\n" "$*" >&2; } warn(){ printf "WARN: %s\n" "$*" >&2; } err(){ printf "ERROR: %s\n" "$*" >&2; } -main(){ - [[ -x "$IMPL" ]] || { err "sourceos helper missing: $IMPL"; exit 2; } +install_sourceos_wrapper(){ + cat > "$SOURCEOS_DEST" <<'EOF' +#!/usr/bin/env bash +set -euo pipefail - mkdir -p "$DEST_DIR" - mkdir -p "$CFG_DIR" +PROFILE_FILE="${XDG_CONFIG_HOME:-$HOME/.config}/sourceos/profile.path" +PROFILE_DIR="$(cat "$PROFILE_FILE" 2>/dev/null || true)" - # Persist the profile dir - printf '%s\n' "$PROFILE_DIR" > "$PROFILE_FILE" +if [[ -z "$PROFILE_DIR" ]]; then + echo "ERROR: SourceOS profile path file missing or empty: $PROFILE_FILE" >&2 + echo "Re-run the workstation profile installer to regenerate it." >&2 + exit 2 +fi + +export SOURCEOS_PROFILE_DIR="$PROFILE_DIR" +exec "$PROFILE_DIR/bin/sourceos" "$@" +EOF + chmod +x "$SOURCEOS_DEST" +} - # Install wrapper - cat > "$DEST" <<'EOF' +install_screenshot_wrapper(){ + cat > "$SCREENSHOT_DEST" <<'EOF' #!/usr/bin/env bash set -euo pipefail @@ -49,17 +55,29 @@ if [[ -z "$PROFILE_DIR" ]]; then exit 2 fi -export SOURCEOS_PROFILE_DIR="$PROFILE_DIR" -exec "$PROFILE_DIR/bin/sourceos" "$@" +exec "$PROFILE_DIR/bin/mac-screenshot.sh" "$@" EOF + chmod +x "$SCREENSHOT_DEST" +} + +main(){ + [[ -x "$SOURCEOS_IMPL" ]] || { err "sourceos helper missing: $SOURCEOS_IMPL"; exit 2; } + [[ -f "$SCREENSHOT_IMPL" ]] || { err "screenshot helper missing: $SCREENSHOT_IMPL"; exit 2; } + + mkdir -p "$DEST_DIR" + mkdir -p "$CFG_DIR" + + printf '%s\n' "$PROFILE_DIR" > "$PROFILE_FILE" - chmod +x "$DEST" + install_sourceos_wrapper + install_screenshot_wrapper - info "installed wrapper: $DEST" + info "installed wrapper: $SOURCEOS_DEST" + info "installed wrapper: $SCREENSHOT_DEST" info "pinned profile dir: $PROFILE_FILE" if [[ ":$PATH:" != *":$DEST_DIR:"* ]]; then - warn "$DEST_DIR is not on PATH. Add it to your shell rc before using sourceos." + warn "$DEST_DIR is not on PATH. Add it to your shell rc before using sourceos or mac-screenshot.sh." fi } From 6dee30d3434aa062728e3b22fbb16a309d950365 Mon Sep 17 00:00:00 2001 From: mdheller <21163552+mdheller@users.noreply.github.com> Date: Fri, 24 Apr 2026 07:01:53 -0400 Subject: [PATCH 5/9] gnome: add mac-style screenshot bindings --- .../workstation-v0/gnome/mac-defaults.sh | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/profiles/linux-dev/workstation-v0/gnome/mac-defaults.sh b/profiles/linux-dev/workstation-v0/gnome/mac-defaults.sh index 08ec164..9b543ea 100644 --- a/profiles/linux-dev/workstation-v0/gnome/mac-defaults.sh +++ b/profiles/linux-dev/workstation-v0/gnome/mac-defaults.sh @@ -62,18 +62,29 @@ main(){ set_key org.gnome.nautilus.preferences click-policy 'double' set_key org.gnome.nautilus.preferences show-delete-permanently true + # Screenshots + mkdir -p "$HOME/Pictures/Screenshots" + # Favorites / dock seed (best-effort) set_key org.gnome.shell favorite-apps "['org.gnome.Nautilus.desktop', 'org.gnome.Terminal.desktop', 'firefox.desktop', 'org.gnome.Settings.desktop']" - # Preserve palette hotkey in custom0, then add Finder/Terminal-like bindings. + # Preserve palette hotkey in custom0, then add Finder/Terminal/screenshot bindings. local base="/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/" local custom0="${base}custom0/" local custom1="${base}custom1/" local custom2="${base}custom2/" - gsettings set org.gnome.settings-daemon.plugins.media-keys custom-keybindings "['${custom0}', '${custom1}', '${custom2}']" || true + local custom3="${base}custom3/" + local custom4="${base}custom4/" + local custom5="${base}custom5/" + local custom6="${base}custom6/" + gsettings set org.gnome.settings-daemon.plugins.media-keys custom-keybindings "['${custom0}', '${custom1}', '${custom2}', '${custom3}', '${custom4}', '${custom5}', '${custom6}']" || true set_custom_binding custom1 "SourceOS Files" "nautilus --new-window" "e" set_custom_binding custom2 "SourceOS Terminal" "gnome-terminal" "Return" + set_custom_binding custom3 "SourceOS Screenshot Screen" "mac-screenshot.sh screen" "3" + set_custom_binding custom4 "SourceOS Screenshot Area" "mac-screenshot.sh area" "4" + set_custom_binding custom5 "SourceOS Screenshot Interactive" "mac-screenshot.sh interactive" "5" + set_custom_binding custom6 "SourceOS Screenshots Folder" "mac-screenshot.sh open-dir" "6" info "Mac-like GNOME defaults pack applied" } From f2c2d6fd09366b8d3b2634b34bcd6336d258013a Mon Sep 17 00:00:00 2001 From: mdheller <21163552+mdheller@users.noreply.github.com> Date: Fri, 24 Apr 2026 07:03:28 -0400 Subject: [PATCH 6/9] workstation-v0: install GNOME quicklook and screenshot packages --- profiles/linux-dev/workstation-v0/install.sh | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/profiles/linux-dev/workstation-v0/install.sh b/profiles/linux-dev/workstation-v0/install.sh index e29c2b3..ee2eec4 100644 --- a/profiles/linux-dev/workstation-v0/install.sh +++ b/profiles/linux-dev/workstation-v0/install.sh @@ -18,15 +18,16 @@ autopatch_enabled(){ } install_system(){ + local packages=(git openssh-clients podman toolbox wl-clipboard jq xclip sushi gnome-screenshot) if have rpm-ostree; then - info "rpm-ostree detected: installing minimal SYSTEM layer (may require reboot)" - sudo rpm-ostree install git openssh-clients podman toolbox wl-clipboard jq xclip || true + info "rpm-ostree detected: installing SYSTEM layer (may require reboot)" + sudo rpm-ostree install "${packages[@]}" || true info "If new packages were layered, reboot before continuing." return fi if have dnf; then - info "dnf detected: installing minimal SYSTEM layer" - sudo dnf install -y git openssh-clients podman toolbox wl-clipboard jq xclip || true + info "dnf detected: installing SYSTEM layer" + sudo dnf install -y "${packages[@]}" || true return fi err "No rpm-ostree/dnf found; cannot apply SYSTEM layer" From c66dfc99772c5ee07a812a9ddd776eb5089e77c6 Mon Sep 17 00:00:00 2001 From: mdheller <21163552+mdheller@users.noreply.github.com> Date: Fri, 24 Apr 2026 08:12:05 -0400 Subject: [PATCH 7/9] docs(gnome): document Mac polish v1 behavior --- .../linux-dev/workstation-v0/gnome/README.md | 33 ++++++++++++++----- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/profiles/linux-dev/workstation-v0/gnome/README.md b/profiles/linux-dev/workstation-v0/gnome/README.md index f3f3075..c163f52 100644 --- a/profiles/linux-dev/workstation-v0/gnome/README.md +++ b/profiles/linux-dev/workstation-v0/gnome/README.md @@ -4,14 +4,17 @@ This directory contains a **minimal GNOME baseline** for the workstation profile Principles: -- Behavioral configuration via **GSettings** (no GNOME core forks). +- Behavioral configuration via **GSettings**. - Conservative defaults that are stable across GNOME upgrades. - Avoid invasive keybinding rewrites until we pin and validate a full shortcut map. +- Mac-like behavior is implemented as bounded GNOME defaults, helper scripts, and packaged GNOME components. ## Apply ```bash ./apply.sh +./extensions-install.sh +./mac-defaults.sh ``` ## Current baseline (v0) @@ -19,11 +22,25 @@ Principles: - Enable window buttons: close/minimize/maximize (left) - Touchpad: tap-to-click + natural scrolling - Show battery percentage -- Show weekday in clock +- Show weekday/date in clock - Enable dynamic workspaces - -Future work: - -- Extension pinset (dash-to-dock, appindicator, etc.) -- Albert hotkey binding (Super+Space) once the command surface is confirmed -- Wayland-safe keyboard remap lane (keyd/xremap) in addition to Kinto +- Dash-to-Dock and AppIndicator extension pinset +- SourceOS palette on `Super+Space` +- Files on `Super+E` +- Terminal on `Super+Return` + +## Mac polish v1 + +- Quick preview through Fedora's `sushi` package +- Screenshot helper wrapper installed as `~/.local/bin/mac-screenshot.sh` +- Screenshot output directory at `~/Pictures/Screenshots` +- `Super+Shift+3` full-screen screenshot +- `Super+Shift+4` area screenshot +- `Super+Shift+5` interactive screenshot UI +- `Super+Shift+6` open screenshot directory + +## Follow-on work + +- Wayland-safe keyboard remap lane expansion +- Optional bounded icon/cursor/font appearance pack +- More complete macOS-style shortcut map after validation From bd160030b17a0587ef0acd28d72a1bf801953e79 Mon Sep 17 00:00:00 2001 From: mdheller <21163552+mdheller@users.noreply.github.com> Date: Fri, 24 Apr 2026 08:19:04 -0400 Subject: [PATCH 8/9] workstation-v0: invoke screenshot helper wrapper via bash --- profiles/linux-dev/workstation-v0/bin/install-sourceos-cli.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/profiles/linux-dev/workstation-v0/bin/install-sourceos-cli.sh b/profiles/linux-dev/workstation-v0/bin/install-sourceos-cli.sh index 4576662..ee54383 100644 --- a/profiles/linux-dev/workstation-v0/bin/install-sourceos-cli.sh +++ b/profiles/linux-dev/workstation-v0/bin/install-sourceos-cli.sh @@ -55,7 +55,7 @@ if [[ -z "$PROFILE_DIR" ]]; then exit 2 fi -exec "$PROFILE_DIR/bin/mac-screenshot.sh" "$@" +exec bash "$PROFILE_DIR/bin/mac-screenshot.sh" "$@" EOF chmod +x "$SCREENSHOT_DEST" } From 61a8b1b8015a0e5aa00c027ebbf9df9156e94d48 Mon Sep 17 00:00:00 2001 From: mdheller <21163552+mdheller@users.noreply.github.com> Date: Fri, 24 Apr 2026 08:41:15 -0400 Subject: [PATCH 9/9] docs(workstation): document GNOME Mac polish v1 --- docs/workstation/README.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/docs/workstation/README.md b/docs/workstation/README.md index 0d671a1..2c6a68c 100644 --- a/docs/workstation/README.md +++ b/docs/workstation/README.md @@ -35,6 +35,7 @@ It triggers on PRs and main pushes touching: Workflow files: - `.github/workflows/workstation-scripts.yml` - `.github/workflows/workstation-lampstand.yml` +- `.github/workflows/workstation-mac-polish.yml` ## Workstation v0 goals @@ -46,6 +47,7 @@ Workflow files: - Compatibility remap lanes: `xremap` and `kinto` (explicit compatibility path, not default). - Touchpad gesture lane: `fusuma`. - Mac-like GNOME behavior pack: left-side window controls, hot corners off, 12h clock, Files on `Super+E`, Terminal on `Super+Return`, dock favorites seeded. +- Mac polish v1: Sushi quick preview, macOS-style screenshot helper, `Super+Shift+3/4/5/6` screenshot bindings, and `~/Pictures/Screenshots` output lane. - Local status/doctor surfaces that can be opened from the launcher (`sourceos status --open`, `sourceos doctor --open`). ## Apply @@ -74,6 +76,31 @@ Or via the installed helper: sourceos status --json sourceos search 'report OR invoice' --snippet +## GNOME Mac polish commands + +The profile installs `mac-screenshot.sh` into `~/.local/bin` as a wrapper around the profile-local helper. + +Screenshot commands: + + mac-screenshot.sh screen + mac-screenshot.sh area + mac-screenshot.sh window + mac-screenshot.sh interactive + mac-screenshot.sh open-dir + +Default screenshot output path: + + ~/Pictures/Screenshots + +GNOME keybindings applied by `gnome/mac-defaults.sh`: + + Super+Shift+3 full-screen screenshot + Super+Shift+4 area screenshot + Super+Shift+5 interactive screenshot UI + Super+Shift+6 open screenshots folder + +Quick preview behavior uses Fedora's `sushi` package, GNOME's Quick Look-style previewer for Nautilus. + ## Lampstand runtime commands Search and runtime inspection are exposed through the same workstation helper so the launcher remains an action bus and Lampstand remains the file-search authority: @@ -112,6 +139,7 @@ Notes: - Kinto is treated as an explicit compatibility lane rather than the default Wayland-first path. - File search should resolve through Lampstand when available; the launcher must not run a redundant second file-search pass. - Lampstand is installed in user space and exposed through a user service, not as a mandatory host-system package. +- Mac polish v1 stays inside bounded GNOME defaults and package installs; it does not fork GNOME Shell or replace libadwaita. ## Related docs