summaryrefslogtreecommitdiffstats
path: root/tv
diff options
context:
space:
mode:
authortv <tv@krebsco.de>2022-12-08 16:12:00 +0100
committertv <tv@krebsco.de>2022-12-08 16:18:14 +0100
commitb1d1322e25459f1f7c79a866b2abf06fc5535e33 (patch)
tree0db102960826da1189bd81bdaa13f2d3787042f8 /tv
parentd7341bbff6b0b866aa5d8bc9b248e8468fba5952 (diff)
tv pinentry-urxvt: show tinted screenshots
Diffstat (limited to 'tv')
-rw-r--r--tv/5pkgs/simple/pinentry-urxvt/default.nix74
1 files changed, 71 insertions, 3 deletions
diff --git a/tv/5pkgs/simple/pinentry-urxvt/default.nix b/tv/5pkgs/simple/pinentry-urxvt/default.nix
index 65b76c077..6e4f6b002 100644
--- a/tv/5pkgs/simple/pinentry-urxvt/default.nix
+++ b/tv/5pkgs/simple/pinentry-urxvt/default.nix
@@ -20,7 +20,11 @@ let
type = lib.types.str;
};
display = lib.mkOption {
- default = ":0";
+ default = null;
+ type = lib.types.nullOr lib.types.str;
+ };
+ xwud.className = lib.mkOption {
+ default = "PinentryUrxvtXwudFloat";
type = lib.types.str;
};
};
@@ -30,12 +34,76 @@ let
in
+ # pinentry-urxvt - A mechanism for PIN entry utilizing rxvt-unicode
+ #
+ # This spawns a PIN entry terminal on top of a tinted screenshot of the
+ # current display's root window. The display for spawning the terminal can
+ # be predefined, in which case both the current and the predefined display
+ # will show the screenshot.
+ #
+ # The purpose of the screenshot, aside from looking nice, is to prevent entry
+ # of the PIN into the wrong window, e.g. by accidentally moving the cursor
+ # while typing. If necessary, the screenshot can be closed by sending 'q',
+ # 'Q', or ctrl-c while its focused.
+ #
pkgs.write "pinentry-urxvt" {
"/bin/pinentry".link = pkgs.writeDash "pinentry-urxvt-wrapper" ''
set -efu
+
+ trap cleanup EXIT
+
+ cleanup() {
+ rm "$screenshot"
+ # Kill process group in order to kill screenshot windows.
+ ${pkgs.utillinux}/bin/kill 0
+ }
+
+ screenshot=$(${pkgs.coreutils}/bin/mktemp -t pinentry-urxvt.screenshot.XXXXXXXX)
+
+ ${pkgs.xorg.xwd}/bin/xwd -root |
+ ${pkgs.imagemagick}/bin/convert xwd:- -fill \#424242 -colorize 80% xwd:"$screenshot"
+
+ show_screenshot() {
+ ${pkgs.exec "pinentry-urxvt.show_screenshot" {
+ filename = "${pkgs.xorg.xwud}/bin/xwud";
+ argv = [
+ cfg.xwud.className
+ "-noclick"
+ ];
+ }} < "$screenshot" &
+ wait_for_screenshot $!
+ }
+
+ # Wait for the xwud window by trying to intercept the call to munmap().
+ # If it cannot be intercepted within 0.1s, assume that attaching strace
+ # wasn't fast enough or xwud doesn't call munmap() anymore. In either
+ # case fall back to search the window by class name, assuming there can
+ # be only one per display.
+ wait_for_screenshot() {
+ if ! \
+ ${pkgs.coreutils}/bin/timeout 0.1 \
+ ${pkgs.strace}/bin/strace -p "$1" -e munmap 2>&1 |
+ read -r _
+ then
+ until ${pkgs.xdotool}/bin/xdotool search \
+ --classname ${lib.shell.escape cfg.xwud.className}
+ do
+ ${pkgs.coreutils}/bin/sleep 0.1
+ done
+ fi
+ }
+
+ show_screenshot
+
+ ${lib.optionalString (cfg.display != null) /* sh */ ''
+ if test "$DISPLAY" != ${lib.shell.escape cfg.display}; then
+ export DISPLAY=${lib.shell.escape cfg.display}
+ show_screenshot
+ fi
+ ''}
+
exec 3<&0 4>&1 5>&2
- export DISPLAY=${lib.shell.escape cfg.display}
- exec ${pkgs.rxvt_unicode}/bin/urxvt \
+ ${pkgs.rxvt_unicode}/bin/urxvt \
-name ${lib.shell.escape cfg.appName} \
-e ${pkgs.writeDash "pinentry-urxvt-tty" ''
set -efu