Subject: bug#22466: 25.0.50; disable-theme apparently forces a redisplay and causes a screen flash

From: Mauro Aranda <[email-masked]>
Date: Fri, 7 Mar 2025 09:26:14 -0300

On 7/3/25 09:06, Eli Zaretskii wrote:
 >> Date: Fri, 7 Mar 2025 08:53:25 -0300
 >> Cc: Eli Zaretskii <[email-masked]>, Artur Malabarba 
<[email-masked]>
 >> From: Mauro Aranda <[email-masked]>
 >>
 >>
 >> Eli Zaretskii <[email-masked]> writes:
 >>
 >>  >> From: Artur Malabarba <[email-masked]>
 >>  >> Cc: [email-masked]
 >>  >> Date: Wed, 27 Jan 2016 20:20:43 +0000
 >>  >>
 >>  >> > Then it would make sense to find a way of switching a theme 
without
 >>  >> > changing the frame's background color, if that's possible 
(i.e. if the
 >>  >> > new theme keeps the same background color).  If there's a function
 >>  >> > missing for that, I'd suggest to add one.
 >>  >>
 >>  >> How about just running that form only when necessary (i.e., only 
if the
 >>  >> disabled theme actually sets the frame `background-color')?
 >>  >
 >>  > Yes, something like that.  Or maybe add a new switch-theme API that
 >>  > receives both the old and a new theme, and changes the background
 >>  > color only if the new theme sets a different one.
 >>
 >> With the provided recipe, I only see a flash at the scroll-bar
 >> position, unlike in older versions.
 >>
 >> I'll be testing the attached patch for a while, which introduces a
 >> new switch-theme command.
 >
 > Thanks.
 >
 > Would it be a better UI if instead of prompting with
 >
 >   Enable custom theme:
 >   Disable custom theme:
 >
 > we would prompt like this:
 >
 >   Switch off theme (default none):
 >   Switch on theme:
 >
 > I think this order is preferable, since "switch-SOMETHING"
 > conceptually means turn off OLD, then turn on NEW, not the other way
 > around, even if the implementation does it in the reverse order for
 > some technical reasons.

Thank you Eli, that does indeed look better for the UI.

Updated patch attached.  If it works fine, I'll add a NEWS entry.

From bf3c271313eb20a5bd8342a3a84d823274dfce07 Mon Sep 17 00:00:00 2001
From: Mauro Aranda <[email-masked]>
Date: Tue, 4 Mar 2025 10:04:22 -0300
Subject: [PATCH] New command switch-theme

* lisp/custom.el (switch-theme): New command.  Avoids screen
flashing when switching themes, or reenabling one.  (Bug#22466)
---
 lisp/custom.el | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/lisp/custom.el b/lisp/custom.el
index 5360c397c59..e59ddd4d097 100644
--- a/lisp/custom.el
+++ b/lisp/custom.el
@@ -1441,6 +1441,28 @@ theme-choose-variant
 
 (defalias 'toggle-theme #'theme-choose-variant)
 
+(defun switch-theme (old new)
+  "Disable theme OLD and enable theme NEW.
+
+Both themes should be known themes, but OLD might be nil, in which
+case this is equivalent to executing `enable-theme'."
+  (interactive (list (intern
+                      (completing-read
+                       "Switch off theme (default none): "
+                       custom-enabled-themes nil nil nil nil "nil"))
+                     (intern
+                      (completing-read
+                       "Switch on theme: "
+                       obarray (lambda (sym)
+                                 (and (get sym 'theme-settings)
+                                      (not (eq sym 'user))))
+                       t))))
+  ;; Enable and then disable, to avoid an intermediate step where
+  ;; we switch back to the frame's default foreground and background.
+  (enable-theme new)
+  (when old
+    (disable-theme old)))
+
 (defun custom-theme-load-confirm (hash)
   "Query the user about loading a Custom theme that may not be safe.
 The theme should be in the current buffer.  If the user agrees,
-- 
2.34.1