Capture the entire screen with Return during a region pick
A previous submap attempt was brittle because the script owned the keyboard state: if it died between enter and exit, the submap stuck. This version lets the compositor own both edges. The Lua config binds plain Return when a layer surface with slurp's "selection" namespace opens and unbinds it when the last one closes, so the bind exists exactly while a pick is on screen. slurp dying for any reason (cancel, crash, pkill, SIGKILL of the picker) fires layer.closed and the bind evaporates — there is no code path where it leaks. Return invokes omarchy-capture-region --take-fullscreen, which flags a marker in XDG_RUNTIME_DIR and dismisses slurp; the picker treats an empty slurp result with a fresh marker as the focused monitor, reusing the existing fullscreen path. Since monitor focus follows the cursor, that is the monitor under the slurp crosshair. The recording flow gets monitor:NAME from the existing match, so Return during a recording pick starts a native full-monitor capture. The signal mode no-ops unless slurp is actually running, and both the signal protocol and the layer-scoped bind lifecycle are verified live: bind present only while slurp is open, real picks resolved by the signal on both the screenshot and recording paths, no leftover binds. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
b72aa8f65e
commit
1e996609a0
@@ -20,6 +20,18 @@
|
|||||||
# --match-monitor print "monitor:NAME" instead when the picked geometry
|
# --match-monitor print "monitor:NAME" instead when the picked geometry
|
||||||
# exactly matches a monitor
|
# exactly matches a monitor
|
||||||
|
|
||||||
|
FULLSCREEN_MARKER="${XDG_RUNTIME_DIR:-/tmp}/omarchy-capture-region-fullscreen"
|
||||||
|
|
||||||
|
# Pressing Return while slurp is open captures the entire focused monitor:
|
||||||
|
# a bind scoped to slurp's layer surface (default/hypr/bindings/utilities.lua)
|
||||||
|
# invokes this mode, which flags the intent and dismisses slurp.
|
||||||
|
if [[ ${1:-} == "--take-fullscreen" ]]; then
|
||||||
|
pgrep -x slurp >/dev/null || exit 0
|
||||||
|
touch "$FULLSCREEN_MARKER"
|
||||||
|
pkill -x slurp
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
MODE=smart
|
MODE=smart
|
||||||
KEEP_FREEZE=false
|
KEEP_FREEZE=false
|
||||||
MATCH_MONITOR=false
|
MATCH_MONITOR=false
|
||||||
@@ -52,6 +64,25 @@ get_rectangles() {
|
|||||||
hyprctl clients -j | jq -r --arg ws "$active_workspace" '.[] | select(.workspace.id == ($ws | tonumber)) | "\(.at[0]),\(.at[1]) \(.size[0])x\(.size[1])"'
|
hyprctl clients -j | jq -r --arg ws "$active_workspace" '.[] | select(.workspace.id == ($ws | tonumber)) | "\(.at[0]),\(.at[1]) \(.size[0])x\(.size[1])"'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
focused_monitor_geo() {
|
||||||
|
hyprctl monitors -j | jq -r "${JQ_MONITOR_GEO} .[] | select(.focused == true) | format_geo"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Runs slurp; an empty result with the fullscreen marker present means Return
|
||||||
|
# was pressed, so the focused monitor is the selection.
|
||||||
|
pick() {
|
||||||
|
local selection
|
||||||
|
rm -f "$FULLSCREEN_MARKER"
|
||||||
|
selection=$(slurp "$@" 2>/dev/null)
|
||||||
|
|
||||||
|
if [[ -z $selection && -e $FULLSCREEN_MARKER ]]; then
|
||||||
|
rm -f "$FULLSCREEN_MARKER"
|
||||||
|
selection=$(focused_monitor_geo)
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf '%s' "$selection"
|
||||||
|
}
|
||||||
|
|
||||||
FREEZE_PID=""
|
FREEZE_PID=""
|
||||||
freeze_screen() {
|
freeze_screen() {
|
||||||
hyprpicker -r -z >/dev/null 2>&1 &
|
hyprpicker -r -z >/dev/null 2>&1 &
|
||||||
@@ -68,19 +99,19 @@ trap cleanup_freeze EXIT
|
|||||||
case "$MODE" in
|
case "$MODE" in
|
||||||
region)
|
region)
|
||||||
freeze_screen
|
freeze_screen
|
||||||
SELECTION=$(slurp 2>/dev/null)
|
SELECTION=$(pick)
|
||||||
;;
|
;;
|
||||||
windows)
|
windows)
|
||||||
freeze_screen
|
freeze_screen
|
||||||
SELECTION=$(get_rectangles | slurp -r 2>/dev/null)
|
SELECTION=$(get_rectangles | pick -r)
|
||||||
;;
|
;;
|
||||||
fullscreen)
|
fullscreen)
|
||||||
SELECTION=$(hyprctl monitors -j | jq -r "${JQ_MONITOR_GEO} .[] | select(.focused == true) | format_geo")
|
SELECTION=$(focused_monitor_geo)
|
||||||
;;
|
;;
|
||||||
smart | *)
|
smart | *)
|
||||||
RECTS=$(get_rectangles)
|
RECTS=$(get_rectangles)
|
||||||
freeze_screen
|
freeze_screen
|
||||||
SELECTION=$(echo "$RECTS" | slurp 2>/dev/null)
|
SELECTION=$(echo "$RECTS" | pick)
|
||||||
|
|
||||||
# A bare click (area < 20px^2) snaps to whichever rectangle it landed in,
|
# A bare click (area < 20px^2) snaps to whichever rectangle it landed in,
|
||||||
# so users don't end up with accidental 2px captures. X and Y can be
|
# so users don't end up with accidental 2px captures. X and Y can be
|
||||||
|
|||||||
@@ -41,6 +41,29 @@ o.bind("ALT + PRINT", "Screenrecording", "omarchy-capture-screenrecording --stop
|
|||||||
o.bind("SUPER + PRINT", "Color picker", "pkill hyprpicker || hyprpicker -a")
|
o.bind("SUPER + PRINT", "Color picker", "pkill hyprpicker || hyprpicker -a")
|
||||||
o.bind("SUPER + CTRL + PRINT", "Extract text (OCR) from screenshot", "omarchy-capture-text-extraction")
|
o.bind("SUPER + CTRL + PRINT", "Extract text (OCR) from screenshot", "omarchy-capture-text-extraction")
|
||||||
|
|
||||||
|
-- While the slurp region picker is open, Return captures the entire focused
|
||||||
|
-- monitor. The bind lives exactly as long as a selection layer is on screen
|
||||||
|
-- (slurp opens one per monitor), so it cannot leak or get stuck.
|
||||||
|
local selection_layers = 0
|
||||||
|
|
||||||
|
hl.on("layer.opened", function(layer)
|
||||||
|
if layer.namespace == "selection" then
|
||||||
|
selection_layers = selection_layers + 1
|
||||||
|
if selection_layers == 1 then
|
||||||
|
hl.bind("RETURN", hl.dsp.exec_cmd("omarchy-capture-region --take-fullscreen"), { description = "Capture entire screen" })
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
hl.on("layer.closed", function(layer)
|
||||||
|
if layer.namespace == "selection" and selection_layers > 0 then
|
||||||
|
selection_layers = selection_layers - 1
|
||||||
|
if selection_layers == 0 then
|
||||||
|
hl.unbind("RETURN")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
o.bind("SUPER + CTRL + S", "Share", "omarchy-menu toggle share")
|
o.bind("SUPER + CTRL + S", "Share", "omarchy-menu toggle share")
|
||||||
|
|
||||||
o.bind("SUPER + CTRL + PERIOD", "Transcode", "omarchy-transcode")
|
o.bind("SUPER + CTRL + PERIOD", "Transcode", "omarchy-transcode")
|
||||||
|
|||||||
Reference in New Issue
Block a user