An image sharing menu for swaywm with imv
Recreating the share menu from iOS in Sway
📅 7 Aug 2023 | ~3 min readTags: #linux
Recently, I have been wanting to include more images within the notes that I take in Emacs org-mode. Previously I had been using this script to take screenshots, but it was something that I never really used it to its full potential. I bound the script in my sway config as below:
bindsym print exec ~/bin/screenshot.sh
I had the idea to implement a photo sharing menu similar to what you get on an iPhone. I wanted to be able to see the image and take actions on it with a single key-press. I knew that my current image viewer imv
could be configured with custom key-bindings, so I decided that this would be the best way to approach the problem.
A quick reference to the imv
manpage revealed that running the program with the -w
flag allows for a custom window title which made it trivial to run custom window rules and enable a centred floating window.
for_window [title="imv floating"] {
floating enable}
For my use case, I realised that it was better for me to save all files to disk and remove the option of copying images directly to the clipboard, so I removed all the necessary options from the file that Robbie wrote above.
shotdir=$HOME/screenshots
filename="${shotdir}/screenshot-$(date +'%Y-%m-%d-%H%M%S.png')"
screenshot_area_to_file="Screenshot area to file"
screenshot_window_to_file="Screenshot focused window to file"
screenshot_monitor_to_file="Screenshot focused monitor to file"
# Store each option in a single string seperated by newlines.
options="$screenshot_window_to_file\n"
options+="$screenshot_area_to_file\n"
options+="$screenshot_monitor_to_file"
# Prompt the user with tofi.
choice="$(echo -e "$options" | tofi)"
case $choice in
$screenshot_area_to_file)
grim -g "$(slurp)" "$filename"
imv -w "imv floating" "$filename"
;;
$screenshot_window_to_file)
grim -g "$(swaymsg -t get_tree | jq -j '.. | select(.type?) | select(.focused).rect | "\(.x),\(.y) \(.width)x\(.height)"')" "$filename"
imv -w "imv floating" "$filename"
;;
$screenshot_monitor_to_file)
grim -o $(swaymsg -t get_outputs | jq -r '.[] | select(.focused) | .name') "$filename"
imv -w "imv floating" "$filename"
;;
esac
With this done, I could now start defining the commands that I want to use from my menu.
The commands
At the moment, I only have three commands, and I have been using the first two on a daily basis.
[binds]
# Rotate the currently open image by 90 degrees by pressing 'R'
<Shift+R> = exec mogrify -rotate 90 "$imv_current_file"
# Delete and then close an open image by pressing 'X'
<Shift+X> = exec rm "$imv_current_file"; quit
f = fullscreen
y = exec wl-copy "[[""$imv_current_file""]]"
e = exec sh ~/bin/imv-dired-jump.sh
t = exec tesseract "$imv_current_file" - | wl-copy
- The first command simply copies a link to the file’s location in an org-mode format
- The second runs a script that shows the image in
dired
mode in emacs as it is my preferred file manager
#!/bin/sh
#
# Proxy the `swaymsg` command to the focused window.
imv "$@" &
imv_pid = $!
file="$imv_current_file"
emacsclient -e -c "(dired-jump nil \"""$file""\")" &
killall imv-wayland
Future ideas
A script for taking an image containing hard coded Chinese subtitles and performing image optimizations with
imagemagick
before running running OCR withtesseract
Write an emacs lisp function that automatically an image inline when a link to a buffer is pasted into the buffer
If you have any further ideas, please let me know by email or on Mastodon.
✉️ Respond by Email.