Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
build/
stage/
*.tar.gz
.superpowers/
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ change that touches the principle, not just this summary.
| `src/stitch-replay.cpp` | Standalone tool: replay a dumped frame directory through the stitcher with no compositor |
| `src/surface-capture.cpp` | In-process output/window capture via `ext-image-copy-capture` |
| `src/cut.cpp/.hpp` | Cut-band tool: remove a strip and collapse the gap |
| `src/clip.cpp/.hpp` | Clip-out: copy a path (rect/ellipse/lasso), punch a hole, lift as a layer |
| `src/recent-snaps.cpp/.hpp` | The recents shelf: shelving/reopening working documents |
| `src/output-config.cpp/.hpp`, `src/palette-config.cpp/.hpp` | The optional `omasnap.conf` INI: output destination/filename, color presets |
| `src/pin.cpp/.hpp`, `src/pin-file.cpp/.hpp`, `src/pin-layout.cpp/.hpp` | Pinned-capture layer-shell surfaces (bottom-right, all workspaces) |
Expand Down
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ add_library(omasnap-core STATIC
src/capture.hpp
src/cut.cpp
src/cut.hpp
src/clip.cpp
src/clip.hpp
src/palette-config.cpp
src/palette-config.hpp
src/background-config.cpp
Expand Down Expand Up @@ -147,6 +149,10 @@ qt_add_executable(omasnap-smoke
tests/cut-smoke.hpp
tests/cut-mapping-smoke.cpp
tests/cut-mapping-smoke.hpp
tests/clip-smoke.cpp
tests/clip-smoke.hpp
tests/clip-mapping-smoke.cpp
tests/clip-mapping-smoke.hpp
tests/palette-config-smoke.cpp
tests/palette-config-smoke.hpp
src/cli-path.cpp
Expand Down
26 changes: 23 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,24 @@ resizable vector layers and preserves the monitor's native pixels on scaled disp
mesh-gradient backdrops, and rendered drop shadows on standard backdrop cards.
- Cut tool: drag across a band of the image to remove it and collapse the gap, with a
live preview and dashed seam marker while dragging; annotations shift to follow.
- Clip-out: in Select, `V` cycles clip shape (rectangle, ellipse, lasso) and a
strip under the toolbar shows those chips plus a Snap toggle. A large enough
empty drag that hits no layers locks a pixel mask of the current shape
(lasso keeps the traced path even if you close back near the start). Snap
is **on by default**: drag a box around the object (leave a little
background in the corners) then Snap reads what is connected under the
pointer inside that box. Toggle the Snap chip to draw a free mask. A scan-dot traces the outline (OCR-style) then the mask locks. Rect
keeps gray chrome, not just the colourful bits. Ellipse fits a circle that
covers protrusions (a pin on a badge). Lasso follows the silhouette.
Click Snap again with a mask locked to refine it. Rect + Snap uses the
object's corner radius so the overlay matches a rounded card, not a
sharp box. Crop handles hide while that mask is locked. A fly-out picks the
hole infill (match surroundings by default; `T` cycles surroundings →
Sample from image → transparent; `1`–`8` / `I` / `#` while the mask is
locked). Drag inside to lift a layer with alpha outside the path.
Release near the hole to snap back; elsewhere to commit. Esc / Ctrl+Z
during a lift cancels only the lift. Distinct from Cut, which collapses a
band. `R` / `E` / `F` still arm the drawing tools.
- Pin a finished capture as a bottom-right always-on-top layer surface, launched
from the same `omasnap` executable and visible on every workspace.
- Crash-resistant working documents under `/run/user/<UID>/omasnap/` (falling back to
Expand Down Expand Up @@ -265,8 +283,10 @@ of a new screenshot. Finishing a reopened capture replaces its shelf entry.

### Configuration (optional)

Omasnap has no settings UI and runs fine with no config at all. If you want to
change where screenshots land or what they are called, create
Omasnap has no settings UI and runs fine with no config at all. Clip-out
defaults (Snap on, hole fill match-surroundings, `T` to cycle fill) are the
product, not INI keys. If you want to change where screenshots land or what
they are called, create
`~/.config/omasnap/omasnap.conf` (INI format); every key is optional:

```ini
Expand Down Expand Up @@ -350,7 +370,7 @@ without reaching for the pointer.

| Input | Action |
|---|---|
| `V` | Select/move/resize layers; carrying one past the source grows the canvas; drag empty canvas for a marquee; multi-select outlines each layer without treating the canvas as one layer; wheel scales the selected layer |
| `V` | Select/move/resize layers; carrying one past the source grows the canvas; press again to cycle clip shape (rectangle, ellipse, lasso); Snap is a strip toggle (Rect snaps to a square/rounded rectangle, Ellipse/Lasso to a circle); drag empty canvas for a marquee; a large enough empty drag that hits no layers locks a pixel mask of the current shape (lasso uses the traced path unless Snap magnets to a circle; crop handles hide while that mask is locked) with a hole-fill fly-out (match surroundings by default; `T` cycles fill; `1`–`8` / Sample from image / `#` hex while locked) — drag inside to lift it out as a new layer (repeat); multi-select outlines each layer without treating the canvas as one layer; wheel scales the selected layer (ignored on a clip) |
| `A` | Arrow |
| `S` | Spotlight/loupe; press again to cycle ellipse, rectangle, rounded |
| `L` | Straight line |
Expand Down
Binary file added docs/clip-out.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
18 changes: 17 additions & 1 deletion docs/editing-model.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
The image on screen while editing is not the working state — the operation
log (`ops_` in `CaptureEditor`, an ordered `QVector<Operation>` with an
`opIndex_` cursor) is. Every action that changes the picture — a crop, a
background choice, adding/patching/deleting an annotation, a cut — appends
background choice, adding/patching/deleting an annotation, a cut, a clip — appends
one `Operation`. Undo moves `opIndex_` back; redo moves it forward.
`CaptureEditor::replayLog()` rebuilds the entire visible state (selection,
background, annotation list, cuts) by replaying the log from empty up to
Expand Down Expand Up @@ -47,6 +47,22 @@ still fully undoable because of how they're kept in the log:
original plus the list of cut ops every time the list changes
(`CaptureEditor::refreshComposedCapture()`). Undo a cut and the composed
image is rebuilt without it; `pristineSource_` was never modified.
- **Clip** (`Operation::Type::Clip`) copies a **path** of native pixels
(rectangle, ellipse, or lasso polygon) and fills that hole — transparent by
default, or a solid colour from the selection fly-out — then adds those
pixels as a `Annotation::Kind::Clip` layer at the drop location. Pixels
outside the path on the lifted tile are alpha 0. The hole does **not**
collapse the image (that is Cut). The torn-off tile is kept on the Clip
annotation (and in JSON). Replay applies cuts and clip fills in order and
recopies from the composed image only when that tile is missing or the
cut/clip prefix before the op changed, so later cuts cannot rewrite an
already-torn piece. `refreshComposedCapture()` uses the same path fill.
Undo a clip and both the hole and the layer disappear together. Live drag is
editor-only preview; the log is touched only on release. Shape is stored as
`shape` (`rect` omitted, `ellipse`, `lasso` plus `points`); fill as HexArgb
when opaque. Click-to-snap / Snap-on drag fits the current clip shape
(rounded rect, ellipse, or silhouette) with a one-lap scan-dot, then the
mask locks. Rect stores optional `radius`.
- **Redaction** exists to permanently destroy sensitive content, so it is
the one place where "non-destructive until export" would be a bug, not a
feature: `renderCapture` applies redactions to the cropped pixels
Expand Down
Loading