Subject: Re: 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 08:53:25 -0300

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.

From 7410f0b45a595495c3c87862fecb2efb2ff5eab4 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..f773dfa5071 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 (new &optional old)
+  "Enable theme NEW and disable theme OLD.
+
+Both NEW and OLD should be known themes but OLD might be omitted, in which
+case, this is equivalent to executing `enable-theme'."
+  (interactive (list (intern
+                      (completing-read
+                       "Enable custom theme: "
+                       obarray (lambda (sym)
+                                 (and (get sym 'theme-settings)
+                                      (not (eq sym 'user))))
+                       t))
+                     (intern
+                      (completing-read
+                       "Disable custom theme: "
+                       custom-enabled-themes nil nil nil nil "nil"))))
+  ;; 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