[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
night-mode?
From: |
Stefan Monnier |
Subject: |
night-mode? |
Date: |
Fri, 20 Nov 2020 16:25:35 -0500 |
User-agent: |
Gnus/5.13 (Gnus v5.13) Emacs/28.0.50 (gnu/linux) |
Based on previous discussions, I think we should add some way to toggle
the dark/light mode. I'm not completely sure what the interface should
look like, nor what'd be the better implementation, but see the patch
below for a first cut to add a `night-mode` command, which does
basically the "inverse video" by swapping the foreground and the
background of the default face (and then resetting the background-mode
accordingly, of course).
Stefan
Along the way I saw a few other issues:
- `frame-set-background-mode` currently doesn't use `color-dark-p`, and
the code it uses for that uses a different algorithm, AFAICT.
- The only current use of `color-dark-p`, as well as the potential new
use of it in `frame-set-background-mode` both have an RGB in form
[0,65535] and need to scale it to p0,1] before calling `color-dark-p`,
so maybe `color-dark-p` should be changed to accept colors using the
[0,65535] scale.
diff --git a/lisp/faces.el b/lisp/faces.el
index 7355e1dd0a..a417979547 100644
--- a/lisp/faces.el
+++ b/lisp/faces.el
@@ -1798,6 +1798,9 @@ color-luminance-dark-limit
This value was determined experimentally.")
(defun color-dark-p (rgb)
+ ;; FIXME: The only 2 uses of this function I can find both need to
+ ;; (mapcar (lambda (c) (/ c 65535.0)) because they have RGB on
+ ;; [0,65535] instead of [0,1]!
"Whether RGB is more readable against white than black.
RGB is a 3-element list (R G B), each component in the range [0,1].
This predicate can be used both for determining a suitable (black or white)
diff --git a/lisp/frame.el b/lisp/frame.el
index 772ba3d8c4..57ffb8bee9 100644
--- a/lisp/frame.el
+++ b/lisp/frame.el
@@ -1159,8 +1159,8 @@ frame-background-mode
:group 'faces
:set #'(lambda (var value)
(set-default var value)
- (mapc 'frame-set-background-mode (frame-list)))
- :initialize 'custom-initialize-changed
+ (mapc #'frame-set-background-mode (frame-list)))
+ :initialize #'custom-initialize-changed
:type '(choice (const dark)
(const light)
(const :tag "automatic" nil)))
@@ -1173,6 +1173,27 @@ frame-background-mode
(defvar inhibit-frame-set-background-mode nil)
+(defun frame--current-backround-mode (frame)
+ (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)))
+ (cond (frame-default-bg-mode)
+ ((equal bg-color "unspecified-fg") ; inverted colors
+ (if (eq default-bg-mode 'light) 'dark 'light))
+ ((not (color-values bg-color frame))
+ default-bg-mode)
+ ((color-dark-p (mapcar (lambda (c) (/ c 65535.0))
+ (color-values bg-color frame)))
+ 'dark)
+ (t 'light))))
+
(defun frame-set-background-mode (frame &optional keep-face-specs)
"Set up display-dependent faces on FRAME.
Display-dependent faces are those which have different definitions
@@ -1181,30 +1202,8 @@ frame-set-background-mode
If optional arg KEEP-FACE-SPECS is non-nil, don't recalculate
face specs for the new background mode."
(unless inhibit-frame-set-background-mode
- (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)))
+ (let* ((bg-mode
+ (frame--current-backround-mode frame))
(display-type
(cond ((null (window-system frame))
(if (tty-display-color-p frame) 'color 'mono))
@@ -1270,6 +1269,18 @@ frame-terminal-default-bg-mode
(intern (downcase bg-resource))))
(terminal-parameter frame 'background-mode)))
+(define-minor-mode night-mode
+ "Use light text on dark background."
+ :global t
+ ;; FIXME: The code below is partly per-frame and partly all-frames :-(
+ (when (eq night-mode
+ (eq 'light (frame--current-backround-mode (selected-frame))))
+ ;; FIXME: Change the face's SPEC instead?
+ (set-face-attribute 'default nil
+ :foreground (face-attribute 'default :background)
+ :background (face-attribute 'default :foreground))
+ (frame-set-background-mode (selected-frame))))
+
;;;; Frame configurations
- night-mode?,
Stefan Monnier <=
- Re: night-mode?, Pankaj Jangid, 2020/11/20
- Re: night-mode?, Juri Linkov, 2020/11/21
- Re: night-mode?, Stefan Monnier, 2020/11/21
- Re: night-mode?, Juri Linkov, 2020/11/22
- Re: night-mode?, Stefan Monnier, 2020/11/22
- Re: night-mode?, Eli Zaretskii, 2020/11/22
- Re: night-mode?, Arthur Miller, 2020/11/22
- Re: night-mode?, Jean Louis, 2020/11/22