From 4d0531f351978c71d769e70efa16b9fc57339a71 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Tue, 11 Aug 2026 13:56:09 +0200 Subject: [PATCH] Add QR code capture (#6705) Select a screen region and decode the QR code in it to the clipboard, so an otpauth:// setup code shown on screen no longer needs a phone. The decoded value is only ever placed on the clipboard, and marked sensitive so clipboard history skips it. Decoding is restricted to QR so a stray barcode elsewhere on screen can't take the clipboard instead. Co-authored-by: Hlib Kanunnikov Co-authored-by: Claude Opus 5 (1M context) --- bin/omarchy-capture-qr | 36 ++++++++++++++++++++++++++++++ default/omarchy/omarchy-menu.jsonc | 1 + install/omarchy-base.packages | 1 + migrations/1786447584.sh | 3 +++ 4 files changed, 41 insertions(+) create mode 100755 bin/omarchy-capture-qr create mode 100644 migrations/1786447584.sh diff --git a/bin/omarchy-capture-qr b/bin/omarchy-capture-qr new file mode 100755 index 00000000..17897387 --- /dev/null +++ b/bin/omarchy-capture-qr @@ -0,0 +1,36 @@ +#!/bin/bash + +# omarchy:summary=Decode a QR code from a screenshot region +# omarchy:group=capture +# omarchy:examples=omarchy capture qr + +# Keep hyprpicker alive until after grim captures so the screenshot sees the +# frozen overlay rather than live content shifting during teardown. +cleanup_freeze() { + [[ -n $PID ]] && kill $PID 2>/dev/null +} +trap cleanup_freeze EXIT + +hyprpicker -r -z >/dev/null 2>&1 & +PID=$! +sleep .1 +SELECTION=$(slurp 2>/dev/null) + +[[ -z $SELECTION ]] && exit 0 + +# Decode QR codes only. Leaving the other symbologies enabled lets dense screen +# content false-positive as an EAN or Code 39 barcode and take over the clipboard. +RESULT=$(grim -g "$SELECTION" - | zbarimg -q --raw -Sdisable -Sqrcode.enable - 2>/dev/null) + +if [[ -z $RESULT ]]; then + omarchy-notification-send -g 󰐲 -u critical "No QR code found" "Select a region containing a QR code" + exit 1 +fi + +# QR codes routinely carry secrets, like the otpauth:// URIs behind 2FA setup +# codes, so the decoded value goes to the clipboard and nowhere else. Printing it +# or putting it in the notification would leak it to the session journal and to +# the notification history, and an unmarked copy would be retained by clipboard +# history. Pasting still works; only the recorded copy is given up. +printf '%s' "$RESULT" | wl-copy --sensitive +omarchy-notification-send -g 󰐲 "QR code copied to clipboard" diff --git a/default/omarchy/omarchy-menu.jsonc b/default/omarchy/omarchy-menu.jsonc index e582e4ca..b397820c 100644 --- a/default/omarchy/omarchy-menu.jsonc +++ b/default/omarchy/omarchy-menu.jsonc @@ -53,6 +53,7 @@ "trigger.capture.screenrecord.stop": {"icon":"","label":"Stop Screenrecording","when":"pgrep -f '^gpu-screen-recorder'","action":"omarchy-capture-screenrecording --stop-recording"}, "trigger.capture.screenrecord": {"icon":"","label":"Screenrecord"}, "trigger.capture.text": {"icon":"󰴑","label":"Text","action":"omarchy-capture-text"}, + "trigger.capture.qr": {"icon":"󰐲","label":"QR Code","action":"omarchy-capture-qr"}, "trigger.capture.color": {"icon":"󰃉","label":"Color","action":"pkill hyprpicker || hyprpicker -a"}, "trigger.capture.screenrecord.no-audio": {"icon":"","label":"With no audio","action":"omarchy-capture-screenrecording"}, "trigger.capture.screenrecord.desktop-audio": {"icon":"","label":"With desktop audio","action":"omarchy-capture-screenrecording --with-desktop-audio"}, diff --git a/install/omarchy-base.packages b/install/omarchy-base.packages index 5f4a35d8..08968b2d 100644 --- a/install/omarchy-base.packages +++ b/install/omarchy-base.packages @@ -146,4 +146,5 @@ xournalpp yaru-icon-theme yay yt-dlp +zbar zoxide diff --git a/migrations/1786447584.sh b/migrations/1786447584.sh new file mode 100644 index 00000000..77bfd681 --- /dev/null +++ b/migrations/1786447584.sh @@ -0,0 +1,3 @@ +echo "Install QR code scanning support" + +omarchy-pkg-add zbar