3

I'm running GNU Emacs 24.5.4 on Mac OS X 10.10.5 in Terminal.app.

In this (stock) setup, Emacs has a transparent background. With a transparent background, the colors that Emacs uses to display text are auto-adjusted based on the color underneath Emacs. In my case, "underneath Emacs" is a Terminal.app window with an opaque black background.

(In the title I refer to the "effective" theme. I'm using that to mean to the colors that Emacs actually uses to render text - as opposed to the "specified" theme, which is different in this case.)

Here is what the default theme looks like when no background color is specified in Emacs, and Emacs is running in a Terminal.app window with an opaque black background:

enter image description here

And here is the same setup - except with a black background specified in Emacs:

enter image description here

While beauty is certainly in the eye of the beholder, I've gotten used to the colors in the top image.

So I'd like to duplicate those colors in GUI Emacs. But since GUI Emacs isn't a transparent window always running on top of something with a black background and hence having colors auto-adjusted, setting its background to black results in the coloring shown in the bottom screenshot.

How do I duplicate the 'effective' colors used in the top screenshot so that they are used in GUI Emacs as well?

P.S. Here's a video demonstrating the text color adjustments happening in real-time vs. changes to the background color of Terminal.app: vimeo.com/139967912. (I had to use an external camera since QuickTime Player's screen recording didn't work for this purpose.)

4
  • Why don't you just make your own theme with the colors you like and adjust the ones you dislike?
    – wasamasa
    Commented Sep 22, 2015 at 10:56
  • Stock Emacs has a theme I like: the one in the top screenshot. Since I can just use it, why make a theme by hand?
    – WalterGR
    Commented Sep 22, 2015 at 16:57
  • Because this isn't a theme, it's the default face definitions for light backgrounds...
    – wasamasa
    Commented Sep 23, 2015 at 19:01
  • That's a semantic distinction that's irrelevant to the question, right? Stock Emacs has a "default face definition for light backgrounds" that I like. Since I can just use it, why make a theme by hand?
    – WalterGR
    Commented Sep 23, 2015 at 22:14

3 Answers 3

1

This isn't what you think it is. Emacs has hilariously terrible heuristics to determine whether your background in an uncustomized terminal session is dark or light. What you see here is that it has detected your terminal emulator to come with a light background and is therefore using the light faces on a dark background. In a GUI session the heuristics won't fail, so it's showing the dark faces.

As for how to achieve this, feel free to patch frame-set-background-mode or create your own theme that mirrors the aesthetics of this visual glitch...

4
  • Did you write the blog post you linked to? I see that the post is dated today and links to this question. It has more details than in your answer. If those details were included here, it would be easier to comment on your answer.
    – WalterGR
    Commented Sep 21, 2015 at 20:48
  • After much fiddling: Modifying frame-set-background-mode isn't necessary. You only need to override Emacs' detection of the frame color. I added the details to the question.
    – WalterGR
    Commented Sep 22, 2015 at 0:47
  • Yes, I'm its author. I did in fact plan writing it before, but only got to it today after seeing this question pop up. I don't really see how it offers more details than you'd need as I've explained the relevant part of the problem in my answer here.
    – wasamasa
    Commented Sep 22, 2015 at 10:59
  • More details are often better, for example, the code excerpt. "Feel free to patch frame-set-background-mode" is a non sequitur unless a person has already followed the link to your blog post. The web suffers from link rot, and the link to your blog may eventually 404. At that point, the material that the rest of your answer expects that a person has read will be inaccessible. I'll just post the contents of the blog post as a separate answer and then people can vote.
    – WalterGR
    Commented Sep 22, 2015 at 16:59
1

Did you ever wonder how Emacs finds out whether you are using a dark or light background? If you’ve themed it, it can just ask for the current definition of the default face, but if you didn’t do this yet, only GUI Emacs can answer this question truthfully.

So, what does Emacs do for the case of an uncustomized setup in a terminal? Simple, it has a hardcoded list of terminal emulators that use light backgrounds by default and does otherwise assume an unknown one uses a dark background!

Joke’s on you if you’re using any of these with a dark background and wonder why it’s looking so different…

(let* ((frame-default-bg-mode (frame-terminal-default-bg-mode frame))
       (bg-color (frame-parameter frame 'background-color))
       (tty-type (tty-type frame))
       (default-bg-mode
         (if (or (window-system frame)
                 (and tty-type
                      (string-match "^\\(xterm\\|\\rxvt\\|dtterm\\|eterm\\)"
                                    tty-type)))
             'light
           'dark))
       (non-default-bg-mode (if (eq default-bg-mode 'light) 'dark 'light))
       (bg-mode
        (cond (frame-default-bg-mode)
              ((equal bg-color "unspecified-fg") ; inverted colors
               non-default-bg-mode)
              ((not (color-values bg-color frame))
               default-bg-mode)
              ((>= (apply '+ (color-values bg-color frame))
                   ;; Just looking at the screen, colors whose
                   ;; values add up to .6 of the white total
                   ;; still look dark to me.
                   (* (apply '+ (color-values "white" frame)) .6))
               'light)
              (t 'dark)))
       (display-type
        (cond ((null (window-system frame))
               (if (tty-display-color-p frame) 'color 'mono))
              ((display-color-p frame)
               'color)
              ((x-display-grayscale-p frame)
               'grayscale)
              (t 'mono)))
       (old-bg-mode
        (frame-parameter frame 'background-mode))
       (old-display-type
        (frame-parameter frame 'display-type)))
  ...)

From http://emacshorrors.com/posts/come-in-and-find-out.html. Licensed Creative Commons Attribution-NoDerivatives 4.0 International (CC BY-ND 4.0).

1

Modifying frame-set-background-mode (as suggested in @wasamasa's answer) isn't necessary.

You only need to override Emacs' detection of the frame color. In my case, since I like the color scheme when Emacs thinks I have a light-colored frame but I actually have a dark-colored frame, all I need to do is

(setq frame-background-mode 'light)

More here: http://www.gnu.org/software/emacs/manual/html_node/emacs/Faces.html

Tricking Emacs in this way can lead to bad effects: black-on-black text for example.

2
  • 1
    Strangely, black-on-black text appears as white-on-black in Emacs in both Terminal.app and iterm2, but in GUI Emacs it does render as black-on-black. I'm assuming that Terminal.app and iterm2 are handling black-on-black text specially.
    – WalterGR
    Commented Nov 28, 2015 at 17:57
  • Modifying frame-background-mode does not seem to make a difference nowadays, at least for me. Commented Apr 6, 2022 at 14:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.