True Emacs Transparency

Transparency in Emacs isn’t that great. Every source I find regarding transparency of Emacs (as of writing this) points to setting the alpha frame parameter. For instance:

  1. EmacsWiki: Transparent Emacs
  2. How can transparency be toggled? - Emacs Stack Exchange
  3. How to set a key binding to make Emacs as transparent/opaque
  4. Any Advice On Getting Transparency To Work In Emacs Window Manager

The issue with alpha is that it sets the transparency of the entire window; what this means is that text and background become transparent together. Clearly this is undesirable for some: the alpha parameter needs to be near 100, otherwise the text becomes illegible. Ideally, the text remains opaque while the background becomes transparent.1

The solution came from a patched version of Emacs made by Håkon Flatval back in November 2021—his announcement that month on Reddit received some attention. The patch adds the alpha-background frame parameter which makes only the background of a frame transparent:

Figure 1: alpha-background set to 75.

Figure 1: alpha-background set to 75.

You can set the alpha-background of a particular frame with the set-frame-parameter function, and the default value for frames by adding to default-frame-alist.2 For example:

1
2
(set-frame-parameter nil 'alpha-background 100) ; For current frame
(add-to-list 'default-frame-alist '(alpha-background . 100)) ; For all new frames henceforth

I’ve also defined my own command for toggling between a frame having alpha-background values of 100 and 75:3

1
2
3
4
5
6
7
(defun kb/toggle-window-transparency ()
  "Toggle transparency."
  (interactive)
  (let ((alpha-transparency 75))
    (pcase (frame-parameter nil 'alpha-background)
      (alpha-transparency (set-frame-parameter nil 'alpha-background 100))
      (t (set-frame-parameter nil 'alpha-background alpha-transparency)))))

In practice, this is what toggling transparency looks like:

Figure 2: Live-toggling of the alpha-background parameter.

Figure 2: Live-toggling of the alpha-background parameter.

I had been using Håkon’s patched version since becoming aware of it, and it’s been perfect for me. My only gripe was that without the expertise of patching future releases of Emacs (Håkon wasn’t updating his repository), I would inevitably be using an increasingly out-of-date version of Emacs.

However, I recently returned to check if there had been any updates to the repo. Though there were no new commits to the repository, I decided to check if there was work on mainline Emacs yet. I searched the repo for matches of alpha-background, and sure enough, I found a hit! On January 30, 2022, Po Lu silently announced the merging of the patch. Accordingly, this means that the alpha-background frame parameter is available to all builds after January 30, 2022. I’ll also note that do not know what went on behind-the-scenes to get this merged, so I’ll make it clear that I am not attributing the development of this feature to only Håkon and Po Lu.

Of course, transparency in Emacs (alongside any other application on your system) is only possible if you are using a compositor (e.g. Picom). Regarding build flags, Håkon’s patch supported transparency only with Emacs compiled with GTK3 and cairo support. I do not know for certain if this is still the case. If it is, then an Emacs built with the --with-cairo and --with-x-toolkit=gtk3 flags is necessary (meaning this feature is only available on machines using X Window). However, according to this Reddit comment thread, it seems like only cairo is necessary, while GTK3 is not necessary. That is, --with-x-toolkit=no works as well.

Changelog

  • June 8, 2022
    • Note that a compositor is necessary for transparency.
    • Added statement about GTK3 perhaps not being necessary that links to a corresponding Reddit comment thread.

  1. I work exclusively on a 14-inch laptop, so screen real-estate is valuable. I often use transparency to watch videos (e.g. YouTube, Netflix, lecture) while working on something in Emacs—I benefit from having the space of my entire screen. ↩︎

  2. The behavior of alpha-background matches that of alpha; that is, 100 is fully opaque while 0 is fully transparent. ↩︎

  3. The reason why my frame is not fully opaque when alpha-background is 100 is because I’ve additionally set alpha to 98. ↩︎