tv pinentry-urxvt: show tinted screenshots

This commit is contained in:
tv 2022-12-08 16:12:00 +01:00
parent d7341bbff6
commit b1d1322e25
1 changed files with 71 additions and 3 deletions

View File

@ -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