final changes

This commit is contained in:
elwrcl committed 2026-10-09 15:08:50 +03:00
1 parent 42bca37ed8
commit 2028a9aaa7
8 files changed
+24 -91

No files matched your search

-1
View File
@@ -7,7 +7,6 @@
!/Cargo.lock !/Cargo.lock
!/nix/ !/nix/
!/src/ !/src/
!/docs/
!/assets/ !/assets/
!/noctalia-plugin/ !/noctalia-plugin/
!/README.md !/README.md
+13 -4
View File
@@ -2,7 +2,7 @@
name = "valw" name = "valw"
version = "0.1.0" version = "0.1.0"
edition = "2024" edition = "2024"
description = "macOS-style screenshots for niri" description = "desktop helper"
license = "MIT" license = "MIT"
[dependencies] [dependencies]
@@ -10,7 +10,11 @@ ab_glyph = "0.2.32"
anyhow = "1.0.104" anyhow = "1.0.104"
chrono = "0.4.45" chrono = "0.4.45"
clap = { version = "4.6.7", features = ["derive"] } clap = { version = "4.6.7", features = ["derive"] }
eframe = { version = "0.36.2", default-features = false, features = ["default_fonts", "glow", "wayland"] } eframe = { version = "0.36.2", default-features = false, features = [
"default_fonts",
"glow",
"wayland",
] }
glow = "0.18.0" glow = "0.18.0"
image = { version = "0.25.10", default-features = false, features = ["png"] } image = { version = "0.25.10", default-features = false, features = ["png"] }
khronos-egl = { version = "6.0.0", features = ["dynamic"] } khronos-egl = { version = "6.0.0", features = ["dynamic"] }
@@ -18,7 +22,13 @@ libc = "0.2.189"
libloading = "0.8" libloading = "0.8"
resvg = "0.48.1" resvg = "0.48.1"
niri-ipc = "=26.4.0" niri-ipc = "=26.4.0"
rustix = { version = "1.1.5", features = ["event", "fs", "pipe", "process", "stdio"] } rustix = { version = "1.1.5", features = [
"event",
"fs",
"pipe",
"process",
"stdio",
] }
serde = { version = "1.0.229", features = ["derive"] } serde = { version = "1.0.229", features = ["derive"] }
serde_ignored = "0.1.14" serde_ignored = "0.1.14"
serde_json = "1.0.151" serde_json = "1.0.151"
@@ -37,6 +47,5 @@ wl-clipboard-rs = "0.9.4"
[dev-dependencies] [dev-dependencies]
tempfile = "3.27.0" tempfile = "3.27.0"
# Image encoding is painfully slow unoptimised; keep dev builds usable.
[profile.dev.package."*"] [profile.dev.package."*"]
opt-level = 3 opt-level = 3
+9 -55
View File
@@ -1,19 +1,16 @@
# valw # valw
macOS-style screenshots for [niri](https://github.com/YaLTeR/niri) on valw is desktop helper for 3N' [nixos] (https://nixos.org/) [niri](https://github.com/YaLTeR/niri) [noctalia](https://github.com/noctalia-dev/noctalia)
Wayland: the whole screen, a region, a window, a zoomable freeze-frame, a
Cmd+Shift+5-style toolbar, a floating preview you can drag into other apps,
and a built-in markup editor. Written in Rust, packaged with Nix.
## Install ## installation
Run it once: run first:
```sh ```sh
nix run git+https://git.userevolt.app/elars/valw -- doctor nix run git+https://git.userevolt.app/elars/valw -- doctor
``` ```
As a package from the flake (`packages.<system>.default`), or with the use as package from the flake (`packages.<system>.default`), or with the
home-manager module: home-manager module:
```nix ```nix
@@ -35,13 +32,7 @@ inputs.valw.url = "git+https://git.userevolt.app/elars/valw";
}; };
} }
``` ```
## binding on niri
`settings` becomes `~/.config/valw/config.toml`. valw checks it while the
configuration is built, so a typo or a bad value fails the rebuild instead
of surprising you later. The toolbar's remembered choices live in
`~/.local/state/valw/toolbar.toml` and stay writable.
## Bind it in niri
```kdl ```kdl
binds { binds {
@@ -53,7 +44,7 @@ binds {
} }
``` ```
## Commands ## commands
| Command | What it does | | Command | What it does |
|---|---| |---|---|
@@ -69,45 +60,8 @@ binds {
Capture commands take `--clipboard-only`, `-o PATH` (`-` for stdout), Capture commands take `--clipboard-only`, `-o PATH` (`-` for stdout),
`--delay SECS`, `--cursor` and `--no-preview`. `--delay SECS`, `--cursor` and `--no-preview`.
## The overview backdrop
`valw backdrop` draws a slow liquid-paint background, coloured from the ## configuration
wallpaper (via Noctalia, if it runs), behind niri's overview. It only draws
while the overview shows it. Start it with niri and place it in the
backdrop:
```kdl
spawn-at-startup "valw" "backdrop"
layer-rule {
match namespace="^valw-backdrop$"
place-within-backdrop true
}
```
With Noctalia, turn its own backdrop off (`[backdrop] enabled = false`).
Colours elsewhere (the region dim, the window picker's fallback) follow
Noctalia's current community palette when there is one.
## Noctalia
With [Noctalia](https://noctalia.dev), valw comes as a plugin: a camera
button on the bar (left click: the toolbar, right click: a region shot),
the toolbar as a Noctalia panel and a control-center tile. Noctalia draws
them, so they follow your Noctalia theme.
```nix
programs.valw.noctalia.enable = true;
```
Then enable `elars/valw` in Noctalia, add a widget of type `elars/valw:bar`
to a bar, and bind the toolbar:
```kdl
Mod+Shift+T { spawn "noctalia" "msg" "panel-toggle" "elars/valw:toolbar"; }
```
## Configuration
Every key is optional; these are the defaults. Every key is optional; these are the defaults.
@@ -130,7 +84,7 @@ scroll_step = 1.15
flashlight_radius = 180 flashlight_radius = 180
[editor] [editor]
backend = "builtin" # or "satty", or "noctalia" (its annotator) backend = "builtin" # or "satty","noctalia" choose which one is for you.
[sound] [sound]
enabled = true enabled = true
@@ -138,4 +92,4 @@ volume = 0.9
combo_reset_secs = 5 combo_reset_secs = 5
``` ```
Logs are in `~/.local/state/valw/logs/`. logs are in `~/.local/state/valw/logs/`.
+1 -1
View File
@@ -1,5 +1,5 @@
{ {
description = "valw, macOS-style screenshots for niri"; description = "valw desktop helper";
inputs = { inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
-15
View File
@@ -9,9 +9,6 @@
}: }:
let let
valw = self'.packages.default; valw = self'.packages.default;
# The home-manager module, evaluated with stand-ins for the two
# home-manager options it sets (no home-manager input needed).
homeModule = homeModule =
valwConfig: valwConfig:
(lib.evalModules { (lib.evalModules {
@@ -44,7 +41,6 @@
]; ];
}).config; }).config;
# Reuses the package's vendored dependencies, runs `cmd` instead of the build.
cargoCheck = cargoCheck =
name: tools: cmd: name: tools: cmd:
valw.overrideAttrs (old: { valw.overrideAttrs (old: {
@@ -52,7 +48,6 @@
nativeBuildInputs = old.nativeBuildInputs ++ tools; nativeBuildInputs = old.nativeBuildInputs ++ tools;
buildPhase = cmd; buildPhase = cmd;
installPhase = "touch $out"; installPhase = "touch $out";
# The package patches its binary's RUNPATH; a check has no binary.
postFixup = ""; postFixup = "";
}); });
in in
@@ -100,9 +95,6 @@
}/testBuildFailure.log }/testBuildFailure.log
touch $out touch $out
''; '';
# The plugin as packaged: manifest, every entry present, Luau that
# compiles, translations that parse; and its logic against stubbed
# Noctalia globals.
noctalia-plugin = noctalia-plugin =
pkgs.runCommand "valw-noctalia-plugin" pkgs.runCommand "valw-noctalia-plugin"
{ {
@@ -135,8 +127,6 @@
touch $out touch $out
''; '';
# Runs the real screencopy path against a headless sway. This is
# wlroots, not niri, but it catches capture and format bugs on every build.
headless = headless =
pkgs.runCommand "valw-headless" pkgs.runCommand "valw-headless"
{ {
@@ -168,15 +158,10 @@
valw doctor | tee doctor.txt valw doctor | tee doctor.txt
! grep -q '^fail' doctor.txt ! grep -q '^fail' doctor.txt
# Through a pipe: the clipboard child must not keep it open.
# The timeout covers the reader too; the child is in its own
# session, so bounding valw alone would not catch a leak.
timeout 10 sh -c 'valw screen -o - | cat > shot.png' timeout 10 sh -c 'valw screen -o - | cat > shot.png'
file shot.png | tee file.txt file shot.png | tee file.txt
grep -q 'PNG image data, 1280 x 720' file.txt grep -q 'PNG image data, 1280 x 720' file.txt
# Preview. The background is solid black, so a thumbnail in the
# bottom-right corner shows up as more than one colour there.
mkdir -p $HOME/.config/valw mkdir -p $HOME/.config/valw
printf '[preview]\ntimeout_secs = 2\n' > $HOME/.config/valw/config.toml printf '[preview]\ntimeout_secs = 2\n' > $HOME/.config/valw/config.toml
socket=$XDG_RUNTIME_DIR/valw.sock socket=$XDG_RUNTIME_DIR/valw.sock
-4
View File
@@ -16,21 +16,17 @@
clippy clippy
rust-analyzer rust-analyzer
rustfmt rustfmt
# Manual verification: grim is the pixel oracle, magick compares.
grim grim
imagemagick imagemagick
wayland-utils wayland-utils
]; ];
# What the package gets through its RUNPATH, for `cargo run`.
LD_LIBRARY_PATH = lib.makeLibraryPath [ LD_LIBRARY_PATH = lib.makeLibraryPath [
pkgs.wayland pkgs.wayland
pkgs.libxkbcommon pkgs.libxkbcommon
pkgs.libglvnd pkgs.libglvnd
]; ];
# The repo is a path: flake, so Nix copies the whole tree on every
# evaluation. Keep the multi-gigabyte target dir out of it.
shellHook = '' shellHook = ''
export CARGO_TARGET_DIR="''${XDG_CACHE_HOME:-$HOME/.cache}/valw/target" export CARGO_TARGET_DIR="''${XDG_CACHE_HOME:-$HOME/.cache}/valw/target"
''; '';
-1
View File
@@ -10,7 +10,6 @@
let let
cfg = config.programs.valw; cfg = config.programs.valw;
toml = pkgs.formats.toml { }; toml = pkgs.formats.toml { };
# valw checks its own config: a typo or a bad value fails the build.
checked = checked =
settings: settings:
let let
+1 -10
View File
@@ -14,9 +14,7 @@
!(builtins.elem (baseNameOf path) [ !(builtins.elem (baseNameOf path) [
".direnv" ".direnv"
".jj" ".jj"
# Plan ledgers and review notes; not part of the build.
".superpowers" ".superpowers"
# Documentation: a doc change shouldn't rebuild the binary.
"docs" "docs"
"README.md" "README.md"
"result" "result"
@@ -35,11 +33,7 @@
pkgs.wayland pkgs.wayland
]; ];
# Tests run through `nix flake check` instead.
doCheck = false; doCheck = false;
# Clicking a preview opens Satty if configured. --suffix keeps a user's own Satty first.
# The editor embeds DejaVu Sans Bold; its licence wants the notice shipped.
postInstall = '' postInstall = ''
wrapProgram $out/bin/valw --suffix PATH : ${ wrapProgram $out/bin/valw --suffix PATH : ${
lib.makeBinPath [ lib.makeBinPath [
@@ -48,14 +42,11 @@
] ]
} }
install -Dm644 assets/fonts/LICENSE-DejaVu $out/share/licenses/valw/LICENSE-DejaVu install -Dm644 assets/fonts/LICENSE-DejaVu $out/share/licenses/valw/LICENSE-DejaVu
# The Noctalia plugin (programs.valw.noctalia), without its tests.
mkdir -p $out/share/valw mkdir -p $out/share/valw
cp -r noctalia-plugin $out/share/valw/noctalia-plugin cp -r noctalia-plugin $out/share/valw/noctalia-plugin
rm -r $out/share/valw/noctalia-plugin/tests rm -r $out/share/valw/noctalia-plugin/tests
''; '';
# dlopen()ed at run time: libwayland (winit, valw), libxkbcommon (winit),
# libEGL (zoom, editor; Mesa's drivers come from the system).
postFixup = '' postFixup = ''
patchelf --add-rpath ${ patchelf --add-rpath ${
lib.makeLibraryPath [ lib.makeLibraryPath [
@@ -67,7 +58,7 @@
''; '';
meta = { meta = {
description = "macOS-style screenshots for niri"; description = "desktop helper";
mainProgram = "valw"; mainProgram = "valw";
platforms = lib.platforms.linux; platforms = lib.platforms.linux;
}; };