feat(desktop): add screenshot capture (task 0028)
Add a screenshot module wiring grimblast (grim + slurp) through the satty annotation editor, enabled by the desktop aggregator. Region, active-window, and full-screen captures each open in satty and, on confirm, land in both the clipboard and a dated file under ~/Pictures/Screenshots. Bound to Print / Shift+Print / Ctrl+Print rather than the spec's Super+L family, whose keys task 0021 already holds for hjkl focus and window movement.
This commit is contained in:
@@ -13,7 +13,23 @@ Bind region on `Super+L`, active window on `Super+Shift+L`, and full screen on `
|
||||
|
||||
## Acceptance criteria
|
||||
|
||||
- [ ] A screenshot module exists in the desktop group and is enabled by the aggregator.
|
||||
- [ ] Region, active-window, and full-screen captures work, each opening in satty and exporting to both clipboard and file.
|
||||
- [ ] Captures are bound on `Super+L`, `Super+Shift+L`, and `Super+Ctrl+L`.
|
||||
- [ ] neogaia builds green under `nix flake check`.
|
||||
- [x] A screenshot module exists in the desktop group and is enabled by the aggregator.
|
||||
- [x] Region, active-window, and full-screen captures work, each opening in satty and exporting to both clipboard and file.
|
||||
- [-] Captures are bound on `Super+L`, `Super+Shift+L`, and `Super+Ctrl+L`.
|
||||
- [x] neogaia builds green under `nix flake check`.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
- **Screenshot binds moved off `Super+L` to the Print key family.**
|
||||
Task 0021 already binds `Super+L`, `Super+Shift+L`, and `Super+Alt+L` to the `hjkl` focus, window-move, and resize actions for the right direction, so the spec's literal `Super+L` / `Super+Shift+L` / `Super+Ctrl+L` screenshot binds are a direct three-way collision with core navigation.
|
||||
Two `bind=` lines for one combo don't coexist in Hyprland (one silently shadows the other, and the winner across modules isn't even deterministic), so the collision had to be broken.
|
||||
With the operator's confirmation, the region/window/full captures are bound to `Print` / `Shift+Print` / `Ctrl+Print`, preserving the plain/Shift/Ctrl modifier pattern while leaving the `hjkl` scheme intact.
|
||||
The spec's own keybind table is internally inconsistent here (it lists `Super+L` for both movement and screenshots), so this resolves a contradiction in the source rather than departing from a settled design.
|
||||
|
||||
- **Capture pipeline.**
|
||||
`grimblast save <area|active|screen> -` captures to stdout and pipes into satty, whose copy action is configured with `--copy-command wl-copy --save-after-copy`, so one confirmation lands the shot in both the clipboard and a dated file under `~/Pictures/Screenshots`.
|
||||
`--actions-on-enter save-to-clipboard` makes Enter trigger that path and `--early-exit` closes satty afterwards.
|
||||
The full end-to-end capture is the irreducible manual step the spec calls out (exercised in a live session); the module builds green and the pipeline and flags are verified against satty 0.21.1.
|
||||
|
||||
- **No waybar icon for satty.**
|
||||
The repo convention adds a `window-rewrite` mapping for each graphical application, but satty is a transient floating annotation window rather than a window that lives on a workspace, so at the operator's direction it gets no workspace glyph.
|
||||
|
||||
@@ -16,6 +16,7 @@ in
|
||||
modules.desktop.login.enable = lib.mkDefault true;
|
||||
modules.desktop.mako.enable = lib.mkDefault true;
|
||||
modules.desktop.rofi.enable = lib.mkDefault true;
|
||||
modules.desktop.screenshot.enable = lib.mkDefault true;
|
||||
modules.desktop.terminal.enable = lib.mkDefault true;
|
||||
modules.desktop.theming.enable = lib.mkDefault true;
|
||||
modules.desktop.waybar.enable = lib.mkDefault true;
|
||||
|
||||
50
modules/desktop/screenshot.nix
Normal file
50
modules/desktop/screenshot.nix
Normal file
@@ -0,0 +1,50 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
# Keyboard-driven screenshots that open in satty for annotation, then land in
|
||||
# both the clipboard and a dated file.
|
||||
let
|
||||
cfg = config.modules.desktop.screenshot;
|
||||
user = config.user.name;
|
||||
|
||||
grimblast = "${pkgs.grimblast}/bin/grimblast";
|
||||
satty = "${pkgs.satty}/bin/satty";
|
||||
wl-copy = "${pkgs.wl-clipboard}/bin/wl-copy";
|
||||
|
||||
shotDir = "$HOME/Pictures/Screenshots";
|
||||
|
||||
# satty is the annotation step, and its copy action is set to save as well,
|
||||
# so a single keystroke through it lands the shot in both the clipboard and a
|
||||
# file.
|
||||
capture =
|
||||
target:
|
||||
pkgs.writeShellScript "screenshot-${target}" ''
|
||||
mkdir -p ${shotDir}
|
||||
${grimblast} save ${target} - \
|
||||
| ${satty} --filename - \
|
||||
--output-filename "${shotDir}/screenshot-%Y%m%d-%H%M%S.png" \
|
||||
--copy-command ${wl-copy} \
|
||||
--save-after-copy \
|
||||
--early-exit \
|
||||
--actions-on-enter save-to-clipboard
|
||||
'';
|
||||
in
|
||||
{
|
||||
options.modules.desktop.screenshot.enable = lib.mkEnableOption "screenshots via grimblast and satty";
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
home-manager.users.${user} = {
|
||||
# Print with plain/Shift/Ctrl for region/window/full.
|
||||
# Super+L, the spec's chosen key, is already the hjkl focus and movement
|
||||
# bind, so screenshots take the Print key instead.
|
||||
wayland.windowManager.hyprland.settings.bind = [
|
||||
", Print, exec, ${capture "area"}"
|
||||
"SHIFT, Print, exec, ${capture "active"}"
|
||||
"CTRL, Print, exec, ${capture "screen"}"
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user