mirror of
https://github.com/thesleepingsage/hypr-lens.git
synced 2026-11-01 06:56:42 +01:00
fix(snipCommands): Copy never clobbers the clipboard on failed capture
buildCopyCommand stages the crop to a file and gates wl-copy + the
success notification on magick's exit status AND a non-empty file:
- piping magick straight into wl-copy cleared the clipboard and fired
a false 'Copied to clipboard' whenever the crop failed or was empty
- the save branch's [ -f ] check passed on tee-created empty files
- pre-clean prevents a stale .crop.png from a killed run passing the gate
- wl-copy failure now notifies ('Copy failed' / 'Saved, copy failed')
- cleanup is ;-chained so the source screenshot never leaks on failure
This commit is contained in:
1 parent
2fa907c451
commit
1d785947de
2 files changed
+23
-9
No files matched your search
@@ -22,6 +22,7 @@ and this project adheres to [Conventional Commits](https://www.conventionalcommi
|
||||
### Fixed
|
||||
|
||||
- **Edge-Straddling Window Targeting** - Clicking a window or layer that hangs off the monitor's left/top edge now selects it (matching its hover highlight) instead of dismissing the overlay; validity no longer sign-checks the region's origin. The capture is trimmed to the window's visible on-screen extent — screen clamping used to slide such regions fully on-screen at full size, which would have captured unrelated content beside the window
|
||||
- **Copy Failure Handling** - A failed capture in Copy mode no longer clears the clipboard or reports a false "Copied to clipboard"; failures now show an explicit "Copy failed" notification and leave no zero-byte files behind
|
||||
- **Freehand Closed Loops** - A freehand loop that ends precisely on its starting pixel is now captured as the drawn shape instead of being discarded as a click. Consequence: any Freehand gesture with 2+ motion samples counts as a draw even if it returns to its start pixel — a jittery click there now captures a tiny shape rather than selecting the content region under the cursor (matching how Freehand already treated jitter with any net drift)
|
||||
- **Invisible Region Selection** - Clicks no longer select regions whose highlight type is disabled (`regionSelector.targetRegions.*: false`); hit-testing now follows the same gating as the visuals. Note this also changes Freehand mode: a stationary click on a window (never highlighted there) previously captured that window silently — it now dismisses the overlay unless the click lands inside a highlighted content region, which stays selectable in Freehand, consistent with what's on screen
|
||||
|
||||
|
||||
@@ -63,28 +63,41 @@ Singleton {
|
||||
return `notify-send '${title}' "${body}" -a 'hypr-lens' & disown`;
|
||||
}
|
||||
|
||||
// Copy to clipboard (optionally also saves to disk if copyAlsoSaves is true)
|
||||
// Copy to clipboard (optionally also saves to disk if copyAlsoSaves is true).
|
||||
// The crop is staged to a file and everything downstream is gated on [ -s ]:
|
||||
// piping magick straight into wl-copy would clear the clipboard (and fire a
|
||||
// false success notification) whenever the crop fails or emits nothing.
|
||||
// Cleanup is ;-chained so the source screenshot never leaks on failure.
|
||||
function buildCopyCommand(screenshotPath: string, rx: int, ry: int, rw: int, rh: int, saveDir: string, alsoSave: bool, polygon: string): list<string> {
|
||||
const cropBase = buildCropBase(screenshotPath, rx, ry, rw, rh, polygon, false);
|
||||
const cropToStdout = `${cropBase} -`;
|
||||
const cleanup = buildCleanup(screenshotPath);
|
||||
|
||||
if (!alsoSave) {
|
||||
return ["bash", "-c", `${cropToStdout} | wl-copy && \
|
||||
{ ${buildNotify("Copied to clipboard", "")}; } && \
|
||||
const cropTmp = StringUtils.shellSingleQuoteEscape(screenshotPath + ".crop.png");
|
||||
// Pre-clean guards against a stale crop from a killed prior run satisfying
|
||||
// the gate; the gate itself needs magick's exit status AND a non-empty file
|
||||
// ([ -s ] alone would bless a truncated PNG from a disk-full/killed magick)
|
||||
return ["bash", "-c", `rm -f '${cropTmp}'; \
|
||||
if ${cropBase} '${cropTmp}' && [ -s '${cropTmp}' ]; then \
|
||||
if wl-copy < '${cropTmp}'; then ${buildNotify("Copied to clipboard", "")}; else ${buildNotify("Copy failed", "")}; fi; \
|
||||
else \
|
||||
${buildNotify("Copy failed", "")}; \
|
||||
fi; \
|
||||
rm -f '${cropTmp}'; \
|
||||
${cleanup}`];
|
||||
}
|
||||
|
||||
const expandedSaveDir = resolveSavePath(saveDir);
|
||||
// Saved-but-copy-failed is a reachable state (dead compositor, wl-copy missing)
|
||||
// and must say so — the file exists and the user needs to know where
|
||||
return [
|
||||
"bash", "-c",
|
||||
`${buildSaveSetup(expandedSaveDir)} && \
|
||||
${cropToStdout} | tee >(wl-copy) > "$savePath" && \
|
||||
if [ -f "$savePath" ]; then \
|
||||
${buildNotify("Copied & saved", "$savePath")}; \
|
||||
`if ${buildSaveSetup(expandedSaveDir)} && ${cropBase} "$savePath" && [ -s "$savePath" ]; then \
|
||||
if wl-copy < "$savePath"; then ${buildNotify("Copied & saved", "$savePath")}; else ${buildNotify("Saved, copy failed", "$savePath")}; fi; \
|
||||
else \
|
||||
rm -f "$savePath"; \
|
||||
${buildNotify("Copy failed", "")}; \
|
||||
fi && \
|
||||
fi; \
|
||||
${cleanup}`
|
||||
];
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user