diff --git a/common.nix b/common.nix index 2608eb7..c544812 100644 --- a/common.nix +++ b/common.nix @@ -58,7 +58,7 @@ let } ''; - post = "nvd diff $OLD_SYSTEM /run/current-system && (command -v record-update &>/dev/null && record-update $OLD_SYSTEM /run/current-system || true); rm -f \"$HOME\"/Pictures/Screenshots/*"; + post = "nvd diff $OLD_SYSTEM /run/current-system && (command -v record-update &>/dev/null && record-update $OLD_SYSTEM /run/current-system || true)"; # The server evaluates and builds for itself. localUpdate = "bash -c 'set -o pipefail && OLD_SYSTEM=$(readlink /run/current-system) && sudo nixos-rebuild switch $@ --refresh --flake ${flake} -L${buildLog} && ${post}' --"; diff --git a/settings/hyprland.nix b/settings/hyprland.nix index 133df50..1ec16e3 100644 --- a/settings/hyprland.nix +++ b/settings/hyprland.nix @@ -263,8 +263,6 @@ in hl.env("QT_QPA_PLATFORM", "wayland;xcb") hl.env("SDL_VIDEODRIVER", "wayland") hl.env("_JAVA_AWT_WM_NONREPARENTING", "1") - -- hyprshot save dir; it mkdir -p's this itself. `update` wipes it. - hl.env("HYPRSHOT_DIR", "/home/fred/Pictures/Screenshots") ${lib.optionalString isGaming '' -- GPU pinning — Navi 22 is card1 on the dual-GPU gaming box. hl.env("AQ_DRM_DEVICES", "/dev/dri/card1") @@ -524,8 +522,11 @@ in -- Screenshots — Shift+Super+S matches GNOME binding -- Pin/unpin quickshell's focus grab around the region select so an -- open menu survives slurp's input grab (no-ops if qs isn't up). - hl.bind(mod .. " + SHIFT + S", hl.dsp.exec_cmd("sh -c 'qs ipc call screenshot pin; hyprshot -m region; qs ipc call screenshot unpin'")) - hl.bind("Print", hl.dsp.exec_cmd("hyprshot -m output")) + -- --clipboard-only: nothing hits the disk, so there is no folder to + -- fill and no file for the notification to thumbnail. The bar draws + -- a camera glyph instead of holding a decoded screen-sized texture. + hl.bind(mod .. " + SHIFT + S", hl.dsp.exec_cmd("sh -c 'qs ipc call screenshot pin; hyprshot -m region --clipboard-only; qs ipc call screenshot unpin'")) + hl.bind("Print", hl.dsp.exec_cmd("hyprshot -m output --clipboard-only")) -- Settings shortcut — Super+I matches GNOME binding hl.bind(mod .. " + I", hl.dsp.exec_cmd("pavucontrol")) diff --git a/settings/quickshell.nix b/settings/quickshell.nix index 57a88cc..504b9ff 100644 --- a/settings/quickshell.nix +++ b/settings/quickshell.nix @@ -2119,9 +2119,11 @@ in elide: Text.ElideRight maximumLineCount: _nc.bodyLines wrapMode: Text.Wrap - // ponytail: hyprshot's body is a noisy file path; the - // "Screenshot saved" summary + the preview say enough. - visible: text !== "" && !(_nc.notif && _nc.notif.appName === "Hyprshot") + // hyprshot's body used to be a noisy save path and was + // hidden. Under --clipboard-only it reads "Image copied + // to the clipboard", which is the only thing correcting + // its own "Screenshot saved" summary — nothing is saved. + visible: text !== "" } Row { spacing: 4 @@ -3888,7 +3890,7 @@ in } // Preview image for a notification: its image hint, else a - // file-path appIcon (e.g. hyprshot's saved shot). "" = none. + // file-path appIcon (e.g. album art on disk). "" = none. function notifPreviewSource(notif) { if (!notif) return ""; if (notif.image && notif.image !== "") return notif.image; @@ -3897,6 +3899,15 @@ in if (a.startsWith("/")) return "file://" + a; return ""; } + + // Glyph to fill the preview slot when there is no image to put + // there. Screenshots run --clipboard-only, so nothing is written + // to disk and there is no thumbnail to load — which is the point: + // a decoded 3440x1440 texture cost ~19MB per retained shot. + function notifPreviewIcon(notif) { + if (!notif) return ""; + return notif.appName === "Hyprshot" ? "camera" : ""; + } // Jump to the window that sent a notification. Toplevel.activate() // goes over wlr-foreign-toplevel — the same path a taskbar uses — // so Hyprland follows it across workspaces. The app raising @@ -6969,6 +6980,7 @@ in id: notifItem required property var modelData readonly property string previewSource: bar.notifPreviewSource(notifItem.modelData) + readonly property string previewIcon: bar.notifPreviewIcon(notifItem.modelData) width: parent.width Item { @@ -6994,10 +7006,11 @@ in } } - // Image preview (album art, screenshot thumb…) + // Image preview (album art…), or a glyph for + // senders that have no image worth loading. ClippingRectangle { id: notifPreview - visible: notifItem.previewSource !== "" + visible: notifItem.previewSource !== "" || notifItem.previewIcon !== "" anchors.left: parent.left anchors.top: parent.top width: 48; height: 48 @@ -7006,14 +7019,19 @@ in Image { anchors.fill: parent fillMode: Image.PreserveAspectCrop - // Decode to thumbnail height: without this a - // screenshot notification keeps a full-resolution - // 3440x1440 texture (~19MB) resident for as long - // as it is tracked — 30 retained notifications is + // Decode to thumbnail height: a full-resolution + // 3440x1440 texture is ~19MB resident for as long + // as the notification is tracked — 30 retained is // half a gigabyte of VRAM for 48px previews. sourceSize.height: 96 source: notifItem.previewSource } + SIcon { + anchors.centerIn: parent + visible: notifItem.previewSource === "" + text: notifItem.previewIcon + font.pixelSize: 22 + } } NotifContent { @@ -7330,6 +7348,7 @@ in color: Theme.cardBg property string previewSource: bar.notifPreviewSource(toastItem.currentNotif) + property string previewIcon: bar.notifPreviewIcon(toastItem.currentNotif) // First child, so the action chips and the dismiss // button still take their own clicks. @@ -7343,10 +7362,10 @@ in } } - // Image preview (screenshot thumb, album art…) + // Image preview (album art…), else the sender's glyph. ClippingRectangle { id: toastPreview - visible: toastCard.previewSource !== "" + visible: toastCard.previewSource !== "" || toastCard.previewIcon !== "" anchors.left: parent.left anchors.top: parent.top anchors.margins: 8 @@ -7360,6 +7379,12 @@ in sourceSize.height: 96 source: toastCard.previewSource } + SIcon { + anchors.centerIn: parent + visible: toastCard.previewSource === "" + text: toastCard.previewIcon + font.pixelSize: 22 + } } NotifContent {