I've been looking for faster ways to include screenshots and other media in org mode.
With 0 keystrokes in emacs:
The video sequence:
- I press the Print Screen key, bound on my desktop to call
flameshot gui
. - I confirm the area selection looks good to me with
Ctrl + C
. - Flameshot sends a method call over dbus after it records the bytes of the image into the system clipboard.
- Emacs has been monitoring for that specific method call, and
(yank-media)
is called automatically in the(current-buffer)
. - Due to a quirk in the clipboard not being ready when this notification fires,
(yank-media)
thinks we're pasting plain text, and fails. - The quirk is a nonissue if existing image data exists in the clipboard, so the second time I do steps 1 - 4, it works, with the newest image.
- Finally I call
org-toggle-inline-images
(ok, 1 keystroke, but it was for the demo).
So there's a quirk, but I hope the folks at flameshot will continue to iterate on it. Or maybe it's an issue with Wayland + Gnome interaction?
Jump to Code to steal this.
Update 2025-01-09 I find that flameshot is really finicky if it will work outside of being called within Gnome terminal on wayland. Sometimes it works if I restart my computer.
Desired Workflow
- Take a screenshot
- Emacs should immediately either
- add a link to the media in kill-ring so I can decide what to do with it later.
- auto insert into the org doc in
(current-buffer)
, allowing me to take a bunch of screenshots and then I can just rearrange them as I like, like a scrapbook.
- add a link to the media in kill-ring so I can decide what to do with it later.
In the video, you see me take option 2. But hopefully after reading this, you'll realize option 1 is a piece of cake too.
Tradeoffs Made
Other Approaches
Other non-dbus options exist, and they look complicated.
- https://github.com/bburns/clipmon polls the system clipboard.
- Works for text and images in system clipboard.
- Only works on X.
- Works for text and images in system clipboard.
- https://github.com/cdown/clipnotify is properly evented and I experimented with calling dbus commands to send signals to emacs
- It's not as easy to package a solution using it for various reasons1.
- Also only works on X.
- Works for text and images in system clipboard.
- It's not as easy to package a solution using it for various reasons1.
- Use the elisp#File Notifications api, by listening to changes in the file system. For this, configure the screenshot tool to always save to a file.
- Probably the most robust, cross platform solution. I did not choose this, partially because of fashion.
- I would have to save a file first, before likely moving it.
- Probably the most robust, cross platform solution. I did not choose this, partially because of fashion.
DBUS + Flameshot approach
You might be wondering why I didn't use a DBUS event for when the system clipboard changes. It's because I couldn't find one.
Pros:
- Should work on Wayland and X.
- Is event-based, no polling required
- Uses native emacs DBUS API
- No integration layer to set up in Flameshot–it has native dbus support.
Cons:
- Has 2 hard dependencies: dbus and flameshot.
- Doesn't work with text, I've only supported images since I'm focusing on flameshot.
- DBUS support in Flameshot could be improved.
So I've settled on flameshot
flameshot --version
Flameshot v12.1.0 (-) Compiled with Qt 5.15.14
If you're on wayland, there's scattered help online, but see if https://flameshot.org/docs/guide/wayland helps.
Flameshot settings
I like the "Use last region" option, which you can access by running
flameshot config

Then running
flameshot gui
brings up a screen where you can select your region. (Shown in demo video). Hover over icons to learn the shortcuts.
One thing I love in emacs is browsing man pages with (woman)
, where you can learn more about flameshot.
(woman "flameshot")

Code
There are only two components:
- Monitor: gets notified of events in dbus. You specify fields to filter only the events you want.
- Handler: handles the event. Call arbitrary code.
(defun jwow/dbus-flameshot-handler (&rest _args) "A dbus event handler that adds picture attachments. Forces a selection of media type as \"image/png\" to speed up workflow" (let ((completing-read-function (lambda (&rest _) ;; customize a variable for this instead to your liking "image/png"))) (yank-media)) (insert "\n")) ;; Save the dbus object, which is a monitor, so we can unregister it if needed ;; This invocation can be derived by watching dbus-monito messages (setq jwow/dbus-flameshot-monitor (dbus-register-monitor :session ; bus #'jwow/dbus-flameshot-handler :sender "org.flameshot.Flameshot" :path "/org/freedesktop/Notifications" :interface "org.freedesktop.Notifications" :member "Notify")) ;; To disable the auto yank-media behavior, unregister the monitor (dbus-unregister-object jwow/dbus-flameshot-monitor)
Quirks
Notify?
Yes, I waited for Notify
to get called, which populates system notifications:

I did this in part because there weren't many identifiable events from flameshot. I was a little sad about that.
method call time=1736280897.494725 sender=:1.229 -> destination=org.freedesktop.Notifications serial=111 path=/org/freedesktop/Notifications; interface=org.freedesktop.Notifications; member=Notify string "flameshot" uint32 0 string "flameshot" string "Flameshot Info" string "Capture saved to clipboard." array [ ] array [ ] int32 5000
No Signals?
At this point, it's a bit weird IMO, that Flameshot doesn't have any signals (for broadcasting) in its DBUS interface. I think it should. That way, emacs can register itself as a proper service and get notified that way.
Emacs registering a monitor might be hacky (I don't know, I'm not a heavy dbus user) and I cannot comment on its performance. Creating a monitor is based on dbus-monitor
, a shell command (and elisp command).

Flameshot sends an incorrect DBUS message?
In the shell command I get something like this:
method call time=1736280897.456930 sender=:1.460 -> destination=org.flameshot.Flameshot serial=9 path=/; interface=(null); member=attachScreenshotToClipboard array of bytes [ 00 00 00 01 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 00 00 02 90 00 00 01 ec 0 ...
In emacs's code path for dbus events:
dbus-event-bus-name: D-Bus error: "Not a valid D-Bus event", (dbus-event :session-private 1 9 ":1.576" "org.flameshot.Flameshot" "/" nil " attachScreenshotToClipboard" jwow/dbus-flameshot-handler ...)
The interfaces is missing; seems like a bug. In any case, it doesn't avoid the issues of text being in the clipboard, and (yank-media)
having no idea how to handle it.
Emacs (dbus-monitor)
, funnels all events
If you set up a monitor, unfortunately calling (dbus-monitor)
will make your previously defined handler handle all events.
I think this is a flaw in the emacs dbus api. dbus-monitor
should call a built-in handler.
At this point, unregister the dbus monitor to get back to normal.
(dbus-unregister-object jwow/dbus-flameshot-monitor)
Explore More
- See dbus#Top for an overview of the dbus api.
- Ian Eure's informative and concise presentation at https://emacsconf.org/2022/talks/dbus/. He shows off an interface where he uses DBUS to detect if a usb drive connects to the computer.
- Think about things you could do with the handler:
- Save the data to a file and save the file name to kill-ring
- experiment with
(gui-get-selection 'CLIPBOARD 'TARGETS)
- pipe the screenshot to a program to resize it
- get auto-ocr, and yank the text from the image to kill-ring
- Save the data to a file and save the file name to kill-ring
Thanks for supporting my work. Turning into an unstoppable space god wouldn't be possible without your help!
For one, you have to create a loop in bash to keep it listening. Which isn't bad. It notifies whenever text is selected, not even copied, as well. To change that, you have to change the C code and recompile the binary.