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
diredmode 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
imagemagickbefore running running OCR withtesseractWrite 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.