emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

emacs-29 4ca371e9cc7: Fix bug#64152 (Minibuffer sometimes goes "modal")


From: Alan Mackenzie
Subject: emacs-29 4ca371e9cc7: Fix bug#64152 (Minibuffer sometimes goes "modal")
Date: Wed, 21 Jun 2023 10:26:06 -0400 (EDT)

branch: emacs-29
commit 4ca371e9cc7178572cc25cbe47371c0075405ff7
Author: Alan Mackenzie <acm@muc.de>
Commit: Alan Mackenzie <acm@muc.de>

    Fix bug#64152 (Minibuffer sometimes goes "modal")
    
    In particular, when a frame has no minibuffer and is using that
    of a different "normal" frame, C-x 5 o, etc., and GUI
    operations fail.
    
    Fix by partially reverting the commit from 2022-07-07 15:38:09
    +0000 "Remove obscure, obsolete code from do_switch_frame".  As
    a consequent change, also revert the commit from 2022-07-08
    20:19:03 +0000 "Remove now unused parameter TRACK from
    do_switch_frame".
    
    * src/frame.c (do_switch_frame): Restore the TRACK parameter.
    Restore the code which redirects the frame focus when a new
    frame gets selected.
    
    * src/frame.c (Fselect_frame, Fhandle_switch_frame)
    (delete_frame)
    * src/keyboard.c (quit_throw_to_read_char)
    * src/lisp.h (do_switch_frame prototype)
    * src/minibuf.c (read_minibuf_unwind)
    * src/window.c (Fset_window_configuration): Restore the TRACK
    argument to do_switch_frame.
    
    * src/xterm.c (x_try_restore_frame): Add a zero TRACK argument
    to do_switch_frame.
---
 src/frame.c    | 50 ++++++++++++++++++++++++++++++++++++++++++++++----
 src/keyboard.c |  2 +-
 src/lisp.h     |  2 +-
 src/minibuf.c  |  6 +++---
 src/window.c   |  2 +-
 src/xterm.c    |  2 +-
 6 files changed, 53 insertions(+), 11 deletions(-)

diff --git a/src/frame.c b/src/frame.c
index 38a6583605c..fc6a3459482 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -1444,6 +1444,10 @@ affects all frames on the same terminal device.  */)
    If FRAME is a switch-frame event `(switch-frame FRAME1)', use
    FRAME1 as frame.
 
+   If TRACK is non-zero and the frame that currently has the focus
+   redirects its focus to the selected frame, redirect that focused
+   frame's focus to FRAME instead.
+
    FOR_DELETION non-zero means that the selected frame is being
    deleted, which includes the possibility that the frame's terminal
    is dead.
@@ -1451,7 +1455,7 @@ affects all frames on the same terminal device.  */)
    The value of NORECORD is passed as argument to Fselect_window.  */
 
 Lisp_Object
-do_switch_frame (Lisp_Object frame, int for_deletion, Lisp_Object norecord)
+do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object 
norecord)
 {
   struct frame *sf = SELECTED_FRAME (), *f;
 
@@ -1473,6 +1477,44 @@ do_switch_frame (Lisp_Object frame, int for_deletion, 
Lisp_Object norecord)
   else if (f == sf)
     return frame;
 
+  /* If the frame with GUI focus has had it's Emacs focus redirected
+     toward the currently selected frame, we should change the
+     redirection to point to the newly selected frame.  This means
+     that if the focus is redirected from a minibufferless frame to a
+     surrogate minibuffer frame, we can use `other-window' to switch
+     between all the frames using that minibuffer frame, and the focus
+     redirection will follow us around.  This code is necessary when
+     we have a minibufferless frame using the MB in another (normal)
+     frame (bug#64152) (ACM, 2023-06-20).  */
+#ifdef HAVE_WINDOW_SYSTEM
+  if (track && FRAME_WINDOW_P (f) && FRAME_TERMINAL (f)->get_focus_frame)
+    {
+      Lisp_Object gfocus; /* The frame which still has focus on the
+                            current terminal, according to the GUI
+                            system. */
+      Lisp_Object focus;  /* The frame to which Emacs has redirected
+                            the focus from `gfocus'.  This might be a
+                            frame with a minibuffer when `gfocus'
+                            doesn't have a MB.  */
+
+      gfocus = FRAME_TERMINAL (f)->get_focus_frame (f);
+      if (FRAMEP (gfocus))
+       {
+         focus = FRAME_FOCUS_FRAME (XFRAME (gfocus));
+         if (FRAMEP (focus) && XFRAME (focus) == SELECTED_FRAME ())
+             /* Redirect frame focus also when FRAME has its minibuffer
+                window on the selected frame (see Bug#24500).
+
+                Don't do that: It causes redirection problem with a
+                separate minibuffer frame (Bug#24803) and problems
+                when updating the cursor on such frames.
+             || (NILP (focus)
+                 && EQ (FRAME_MINIBUF_WINDOW (f), sf->selected_window)))  */
+           Fredirect_frame_focus (gfocus, frame);
+       }
+    }
+#endif /* HAVE_X_WINDOWS */
+
   if (!for_deletion && FRAME_HAS_MINIBUF_P (sf))
     resize_mini_window (XWINDOW (FRAME_MINIBUF_WINDOW (sf)), 1);
 
@@ -1574,7 +1616,7 @@ This function returns FRAME, or nil if FRAME has been 
deleted.  */)
     /* Do not select a tooltip frame (Bug#47207).  */
     error ("Cannot select a tooltip frame");
   else
-    return do_switch_frame (frame, 0, norecord);
+    return do_switch_frame (frame, 1, 0, norecord);
 }
 
 DEFUN ("handle-switch-frame", Fhandle_switch_frame,
@@ -1590,7 +1632,7 @@ necessarily represent user-visible input focus.  */)
   kset_prefix_arg (current_kboard, Vcurrent_prefix_arg);
   run_hook (Qmouse_leave_buffer_hook);
 
-  return do_switch_frame (event, 0, Qnil);
+  return do_switch_frame (event, 0, 0, Qnil);
 }
 
 DEFUN ("selected-frame", Fselected_frame, Sselected_frame, 0, 0, 0,
@@ -2108,7 +2150,7 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
        Fraise_frame (frame1);
 #endif
 
-      do_switch_frame (frame1, 1, Qnil);
+      do_switch_frame (frame1, 0, 1, Qnil);
       sf = SELECTED_FRAME ();
     }
   else
diff --git a/src/keyboard.c b/src/keyboard.c
index b1ccf4acde4..99f886821e2 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -11561,7 +11561,7 @@ quit_throw_to_read_char (bool from_signal)
   if (FRAMEP (internal_last_event_frame)
       && !EQ (internal_last_event_frame, selected_frame))
     do_switch_frame (make_lispy_switch_frame (internal_last_event_frame),
-                    0, Qnil);
+                    0, 0, Qnil);
 
   sys_longjmp (getcjmp, 1);
 }
diff --git a/src/lisp.h b/src/lisp.h
index 9c02d975a74..bf91a1559bf 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -4878,7 +4878,7 @@ extern void syms_of_indent (void);
 /* Defined in frame.c.  */
 extern void store_frame_param (struct frame *, Lisp_Object, Lisp_Object);
 extern void store_in_alist (Lisp_Object *, Lisp_Object, Lisp_Object);
-extern Lisp_Object do_switch_frame (Lisp_Object, int, Lisp_Object);
+extern Lisp_Object do_switch_frame (Lisp_Object, int, int, Lisp_Object);
 extern Lisp_Object get_frame_param (struct frame *, Lisp_Object);
 extern void frames_discard_buffer (Lisp_Object);
 extern void init_frame_once (void);
diff --git a/src/minibuf.c b/src/minibuf.c
index bcb7eb9375d..6e54d8c3ba5 100644
--- a/src/minibuf.c
+++ b/src/minibuf.c
@@ -1125,8 +1125,8 @@ read_minibuf_unwind (void)
  found:
   if (!EQ (exp_MB_frame, saved_selected_frame)
       && !NILP (exp_MB_frame))
-    do_switch_frame (exp_MB_frame, 0, Qt); /* This also sets
-                                             minibuf_window */
+    do_switch_frame (exp_MB_frame, 0, 0, Qt); /* This also sets
+                                            minibuf_window */
 
   /* To keep things predictable, in case it matters, let's be in the
      minibuffer when we reset the relevant variables.  Don't depend on
@@ -1238,7 +1238,7 @@ read_minibuf_unwind (void)
   /* Restore the selected frame. */
   if (!EQ (exp_MB_frame, saved_selected_frame)
       && !NILP (exp_MB_frame))
-    do_switch_frame (saved_selected_frame, 0, Qt);
+    do_switch_frame (saved_selected_frame, 0, 0, Qt);
 }
 
 /* Replace the expired minibuffer in frame exp_MB_frame with the next less
diff --git a/src/window.c b/src/window.c
index 0efd6813f8d..1dc977626b3 100644
--- a/src/window.c
+++ b/src/window.c
@@ -7399,7 +7399,7 @@ the return value is nil.  Otherwise the value is t.  */)
        do_switch_frame (NILP (dont_set_frame)
                          ? data->selected_frame
                          : old_frame
-                         , 0, Qnil);
+                         , 0, 0, Qnil);
     }
 
   FRAME_WINDOW_CHANGE (f) = true;
diff --git a/src/xterm.c b/src/xterm.c
index e981a36fa9c..5840b15bcb7 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -25792,7 +25792,7 @@ x_try_restore_frame (void)
 
   FOR_EACH_FRAME (tail, frame)
     {
-      if (!NILP (do_switch_frame (frame, 1, Qnil)))
+      if (!NILP (do_switch_frame (frame, 0, 1, Qnil)))
        return;
     }
 }



reply via email to

[Prev in Thread] Current Thread [Next in Thread]