emacs-diffs
[Top][All Lists]
Advanced

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

master 7c2ebf6: Prevent open minibuffers getting lost when their frame g


From: Alan Mackenzie
Subject: master 7c2ebf6: Prevent open minibuffers getting lost when their frame gets deleted
Date: Sun, 21 Mar 2021 12:57:50 -0400 (EDT)

branch: master
commit 7c2ebf6e23663fdc7b1880a4d7caeadc8c47c00e
Author: Alan Mackenzie <acm@muc.de>
Commit: Alan Mackenzie <acm@muc.de>

    Prevent open minibuffers getting lost when their frame gets deleted
    
    This happened with minibuffer-follows-selected-frame set to t.
    
    * doc/emacs/mini.texi (Basic Minibuffer): State where a command's action 
takes
    place when a minibuffer's frame has been deleted.
    
    * lisp/window.el (window--before-delete-windows, record-window-buffer): Take
    into account that minibuffers are now recorded on w->prev_buffers field.
    
    * src/fns.c (merge_c): New version of `merge' taking a C function, rather 
than
    a Lisp function as the comparison function.
    
    * src/frame.c (do_switch_frame): Pass arguments sf and for_deletion to
    move_minibuffers_onnto_frame.
    
    * src/lisp.h (top level): Declare merge_c and
    move_minibuffers_onto_selected_frame.
    
    * src/minibuf.c (MB_frame): New Lisp_Object recording the minibuffer's 
frame.
    (choose_minibuf_frame): Remove all code except that which sets 
minibuf_window
    to the current frame's minibuffer.
    (minibuffer_ent_greater): New comparison function, passed to merge_c.
    (zip_minibuffer_stacks): New function.
    (move_minibuffers_onto_frame): Renamed from `move_minibuffer_onto_frame' 
given
    two arguments, the old frame and for_deletion, and simplified.  Minibuffers
    are now stacked in the mini-window's ->prev_buffers field.
    (read_minibuf): Several detailed amendments.
    (exp_MB_frame): New Lisp_Object, the expired minibuffer's frame.
    (read_minibuf_unwind): Search for the expired minibuffer's frame, rather 
than
    taking it from (unreliable) variables.  Switch temporarily to this frame for
    tidying up operations.
    (minibuffer_unwind): New function which pops a stacked minibuffer.
    (syms_of_minibuf): Call staticpro for the two new Lisp variables.
    
    * src/window.c (Fset_window_configuration): Don't record minibuffers with
    record-window-buffer.
    
    * src/xdisp.c (gui_consider_frame_title): Remove redundant Fselect_window,
    which caused an unwanted frame switch.  Amend the arguments to
    format_mode_line_unwind_data to match.
---
 doc/emacs/mini.texi |   4 +-
 lisp/window.el      |   5 +-
 src/fns.c           |  46 +++++++++
 src/frame.c         |   2 +-
 src/lisp.h          |   3 +-
 src/minibuf.c       | 292 +++++++++++++++++++++++++++++++++-------------------
 src/window.c        |   3 +-
 src/xdisp.c         |   3 +-
 8 files changed, 242 insertions(+), 116 deletions(-)

diff --git a/doc/emacs/mini.texi b/doc/emacs/mini.texi
index 9c1b975..d0865c5 100644
--- a/doc/emacs/mini.texi
+++ b/doc/emacs/mini.texi
@@ -82,7 +82,9 @@ after a recursive minibuffer has been opened in the current 
command
 (@pxref{Recursive Mini,,, elisp}).  This option is mainly to retain
 (approximately) the behavior prior to Emacs 28.1.  Note that the
 effect of the command, when you finally finish using the minibuffer,
-always takes place in the frame where you first opened it.
+always takes place in the frame where you first opened it.  The sole
+exception is that when that frame no longer exists, the action takes
+place in the currently selected frame.
 
 @node Minibuffer File
 @section Minibuffers for File Names
diff --git a/lisp/window.el b/lisp/window.el
index cfd9876..f27631b 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -4158,7 +4158,7 @@ returned by `window-start' and `window-point' 
respectively.
 
 This function is called only if `switch-to-buffer-preserve-window-point'
 evaluates non-nil."
-  (dolist (win (window-list))
+  (dolist (win (window-list nil 'no-minibuf))
     (let* ((buf   (window-buffer (or window win)))
            (start (window-start win))
            (pos   (window-point win))
@@ -4416,7 +4416,8 @@ WINDOW must be a live window and defaults to the selected 
one."
        window (assq-delete-all buffer (window-prev-buffers window))))
 
     ;; Don't record insignificant buffers.
-    (unless (eq (aref (buffer-name buffer) 0) ?\s)
+    (when (or (not (eq (aref (buffer-name buffer) 0) ?\s))
+              (minibufferp buffer))
       ;; Add an entry for buffer to WINDOW's previous buffers.
       (with-current-buffer buffer
        (let ((start (window-start window))
diff --git a/src/fns.c b/src/fns.c
index 766e767..2cd59c8 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -2279,6 +2279,52 @@ merge (Lisp_Object org_l1, Lisp_Object org_l2, 
Lisp_Object pred)
     }
 }
 
+Lisp_Object
+merge_c (Lisp_Object org_l1, Lisp_Object org_l2, bool (*less) (Lisp_Object, 
Lisp_Object))
+{
+  Lisp_Object l1 = org_l1;
+  Lisp_Object l2 = org_l2;
+  Lisp_Object tail = Qnil;
+  Lisp_Object value = Qnil;
+
+  while (1)
+    {
+      if (NILP (l1))
+       {
+         if (NILP (tail))
+           return l2;
+         Fsetcdr (tail, l2);
+         return value;
+       }
+      if (NILP (l2))
+       {
+         if (NILP (tail))
+           return l1;
+         Fsetcdr (tail, l1);
+         return value;
+       }
+
+      Lisp_Object tem;
+      if (less (Fcar (l1), Fcar (l2)))
+       {
+         tem = l1;
+         l1 = Fcdr (l1);
+         org_l1 = l1;
+       }
+      else
+       {
+         tem = l2;
+         l2 = Fcdr (l2);
+         org_l2 = l2;
+       }
+      if (NILP (tail))
+       value = tem;
+      else
+       Fsetcdr (tail, tem);
+      tail = tem;
+    }
+}
+
 
 /* This does not check for quits.  That is safe since it must terminate.  */
 
diff --git a/src/frame.c b/src/frame.c
index cfdf3b6..66ae494 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -1487,7 +1487,7 @@ do_switch_frame (Lisp_Object frame, int track, int 
for_deletion, Lisp_Object nor
 #endif
     internal_last_event_frame = Qnil;
 
-  move_minibuffer_onto_frame ();
+  move_minibuffers_onto_frame (sf, for_deletion);
   return frame;
 }
 
diff --git a/src/lisp.h b/src/lisp.h
index b95f389..c67c8b0 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -3610,6 +3610,7 @@ extern void validate_subarray (Lisp_Object, Lisp_Object, 
Lisp_Object,
 extern Lisp_Object substring_both (Lisp_Object, ptrdiff_t, ptrdiff_t,
                                   ptrdiff_t, ptrdiff_t);
 extern Lisp_Object merge (Lisp_Object, Lisp_Object, Lisp_Object);
+extern Lisp_Object merge_c (Lisp_Object, Lisp_Object, bool (*) (Lisp_Object, 
Lisp_Object));
 extern Lisp_Object do_yes_or_no_p (Lisp_Object);
 extern int string_version_cmp (Lisp_Object, Lisp_Object);
 extern Lisp_Object concat2 (Lisp_Object, Lisp_Object);
@@ -4348,7 +4349,7 @@ extern void clear_regexp_cache (void);
 
 extern Lisp_Object Vminibuffer_list;
 extern Lisp_Object last_minibuf_string;
-extern void move_minibuffer_onto_frame (void);
+extern void move_minibuffers_onto_frame (struct frame *, bool);
 extern bool is_minibuffer (EMACS_INT, Lisp_Object);
 extern EMACS_INT this_minibuffer_depth (Lisp_Object);
 extern EMACS_INT minibuf_level;
diff --git a/src/minibuf.c b/src/minibuf.c
index 4b1f4b1..d58924a 100644
--- a/src/minibuf.c
+++ b/src/minibuf.c
@@ -59,6 +59,12 @@ Lisp_Object last_minibuf_string;
 
 static Lisp_Object minibuf_prompt;
 
+/* The frame containinug the most recently opened Minibuffer.  This is
+   used only when `minibuffer-follows-selected-frame' is neither nil
+   nor t.  */
+
+static Lisp_Object MB_frame;
+
 /* Width of current mini-buffer prompt.  Only set after display_line
    of the line that contains the prompt.  */
 
@@ -67,6 +73,7 @@ static ptrdiff_t minibuf_prompt_width;
 static Lisp_Object nth_minibuffer (EMACS_INT depth);
 static EMACS_INT minibuf_c_loop_level (EMACS_INT depth);
 static void set_minibuffer_mode (Lisp_Object buf, EMACS_INT depth);
+static bool live_minibuffer_p (Lisp_Object);
 
 
 /* Return TRUE when a frame switch causes a minibuffer on the old
@@ -78,6 +85,7 @@ minibuf_follows_frame (void)
              Qt);
 }
 
+#if 0
 /* Return TRUE when a minibuffer always remains on the frame where it
    was first invoked. */
 static bool
@@ -85,6 +93,7 @@ minibuf_stays_put (void)
 {
   return NILP (Fdefault_toplevel_value (Qminibuffer_follows_selected_frame));
 }
+#endif
 
 /* Return TRUE when opening a (recursive) minibuffer causes
    minibuffers on other frames to move to the selected frame.  */
@@ -112,84 +121,85 @@ choose_minibuf_frame (void)
        emacs_abort ();
 
       minibuf_window = sf->minibuffer_window;
-      /* If we've still got another minibuffer open, use its mini-window
-         instead.  */
-      if (minibuf_level > 1 && minibuf_stays_put ())
-        {
-          Lisp_Object buffer = get_minibuffer (minibuf_level);
-          Lisp_Object tail, frame;
-
-          FOR_EACH_FRAME (tail, frame)
-            if (EQ (XWINDOW (XFRAME (frame)->minibuffer_window)->contents,
-                    buffer))
-              {
-                minibuf_window = XFRAME (frame)->minibuffer_window;
-                break;
-              }
-        }
     }
+}
 
-  if (minibuf_moves_frame_when_opened ()
-      && FRAMEP (selected_frame)
-      && FRAME_LIVE_P (XFRAME (selected_frame)))
-    /* Make sure no other frame has a minibuffer as its selected window,
-       because the text would not be displayed in it, and that would be
-       confusing.  Only allow the selected frame to do this,
-       and that only if the minibuffer is active.  */
-  {
-    Lisp_Object tail, frame;
-    struct frame *of;
-
-    FOR_EACH_FRAME (tail, frame)
-      if (!EQ (frame, selected_frame)
-          && minibuf_level > 1
-         /* The frame's minibuffer can be on a different frame.  */
-         && ! EQ (XWINDOW ((of = XFRAME (frame))->minibuffer_window)->frame,
-                  selected_frame))
-        {
-          if (MINI_WINDOW_P (XWINDOW (FRAME_SELECTED_WINDOW (of))))
-            Fset_frame_selected_window (frame, Fframe_first_window (frame),
-                                        Qnil);
-
-          if (!EQ (XWINDOW (of->minibuffer_window)->contents,
-                   nth_minibuffer (0)))
-            set_window_buffer (of->minibuffer_window,
-                               nth_minibuffer (0), 0, 0);
-        }
-  }
+/* If ENT1 has a higher minibuffer index than ENT2, return true.  More
+precisely, compare the buffer components of each window->prev_buffers
+entry.  */
+static bool
+minibuffer_ent_greater (Lisp_Object ent1, Lisp_Object ent2)
+{
+  return this_minibuffer_depth (Fcar (ent1))
+    > this_minibuffer_depth (Fcar (ent2)) ;
 }
 
-/* If `minibuffer_follows_selected_frame' is t and we have a
-   minibuffer, move it from its current frame to the selected frame.
-   This function is intended to be called from `do_switch_frame' in
-   frame.c.  */
-void move_minibuffer_onto_frame (void)
+/* Move the ordered "stack" of minibuffers from SOURCE_WINDOW to
+   DEST_WINDOW, interleaving those minibuffers with any in DEST_WINDOW
+   to produce an ordered combination.  The ordering is by minibuffer
+   depth.  A stack of minibuffers consists of the minibuffer currently
+   in DEST/SOURCE_WINDOW together with any recorded in the
+   ->prev_buffers field of the struct window.  */
+static void
+zip_minibuffer_stacks (Lisp_Object dest_window, Lisp_Object source_window)
 {
-  if (!minibuf_level)
-    return;
-  if (!minibuf_follows_frame ())
-    return;
-  if (FRAMEP (selected_frame)
-      && FRAME_LIVE_P (XFRAME (selected_frame))
-      && !EQ (minibuf_window, XFRAME (selected_frame)->minibuffer_window))
+  struct window *dw = XWINDOW (dest_window);
+  struct window *sw = XWINDOW (source_window);
+  Lisp_Object acc;
+  Lisp_Object d_ent;   /* Entry from dw->prev_buffers */
+
+  if (!live_minibuffer_p (dw->contents)
+      && NILP (dw->prev_buffers))
     {
-      EMACS_INT i;
-      struct frame *sf = XFRAME (selected_frame);
-      Lisp_Object old_frame = XWINDOW (minibuf_window)->frame;
-      struct frame *of = XFRAME (old_frame);
+      set_window_buffer (dest_window, sw->contents, 0, 0);
+      Fset_window_start (dest_window, Fwindow_start (source_window), Qnil);
+      Fset_window_point (dest_window, Fwindow_point (source_window));
+      dw->prev_buffers = sw->prev_buffers;
+      set_window_buffer (source_window, get_minibuffer (0), 0, 0);
+      sw->prev_buffers = Qnil;
+      return;
+    }
 
-      /* Stack up all the (recursively) open minibuffers on the selected
-         mini_window.  */
-      for (i = 1; i <= minibuf_level; i++)
-       set_window_buffer (sf->minibuffer_window, nth_minibuffer (i), 0, 0);
-      minibuf_window = sf->minibuffer_window;
-      if (of != sf)
-       {
-         Lisp_Object temp = get_minibuffer (0);
+  if (live_minibuffer_p (dw->contents))
+    call1 (Qrecord_window_buffer, dest_window);
+  if (live_minibuffer_p (sw->contents))
+    call1 (Qrecord_window_buffer, source_window);
 
-         set_window_buffer (of->minibuffer_window, temp, 0, 0);
-         set_minibuffer_mode (temp, 0);
-       }
+  acc = merge_c (dw->prev_buffers, sw->prev_buffers, minibuffer_ent_greater);
+
+  if (!NILP (acc))
+    {
+      d_ent = Fcar (acc);
+      acc = Fcdr (acc);
+      set_window_buffer (dest_window, Fcar (d_ent), 0, 0);
+      Fset_window_start (dest_window, Fcar (Fcdr (d_ent)), Qnil);
+      Fset_window_point (dest_window, Fcar (Fcdr (Fcdr (d_ent))));
+    }
+  dw->prev_buffers = acc;
+  sw->prev_buffers = Qnil;
+  set_window_buffer (source_window, get_minibuffer (0), 0, 0);
+}
+
+/* If `minibuffer_follows_selected_frame' is t, or we're about to
+   delete a frame which potentially "contains" minibuffers, move them
+   from the old frame to the selected frame.  This function is
+   intended to be called from `do_switch_frame' in frame.c.  OF is the
+   old frame, FOR_DELETION is true if OF is about to be deleted.  */
+void
+move_minibuffers_onto_frame (struct frame *of, bool for_deletion)
+{
+  struct frame *f = XFRAME (selected_frame);
+
+  minibuf_window = f->minibuffer_window;
+  if (!(minibuf_level
+       && (for_deletion || minibuf_follows_frame () || FRAME_INITIAL_P (of))))
+    return;
+  if (FRAME_LIVE_P (f)
+      && !EQ (f->minibuffer_window, of->minibuffer_window))
+    {
+      zip_minibuffer_stacks (f->minibuffer_window, of->minibuffer_window);
+      if (for_deletion && XFRAME (MB_frame) != of)
+       MB_frame = selected_frame;
     }
 }
 
@@ -221,6 +231,7 @@ without invoking the usual minibuffer commands.  */)
 /* Actual minibuffer invocation.  */
 
 static void read_minibuf_unwind (void);
+static void minibuffer_unwind (void);
 static void run_exit_minibuf_hook (void);
 
 
@@ -544,7 +555,6 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, 
Lisp_Object prompt,
   Lisp_Object histval;
 
   Lisp_Object empty_minibuf;
-  Lisp_Object dummy, frame;
 
   specbind (Qminibuffer_default, defalt);
   specbind (Qinhibit_read_only, Qnil);
@@ -626,17 +636,24 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, 
Lisp_Object prompt,
   mini_frame = WINDOW_FRAME (XWINDOW (minibuf_window));
 
   if (minibuf_level > 1
+      && !EQ (XWINDOW (XFRAME (selected_frame)->minibuffer_window)->frame,
+             MB_frame)
       && minibuf_moves_frame_when_opened ()
-      && (!minibuf_follows_frame ()
-         || (!EQ (mini_frame, selected_frame))))
+      && (!minibuf_follows_frame ()))
     {
-      EMACS_INT i;
+      struct frame *of = XFRAME (MB_frame);
 
-      /* Stack up the existing minibuffers on the current mini-window */
-      for (i = 1; i < minibuf_level; i++)
-       set_window_buffer (minibuf_window, nth_minibuffer (i), 0, 0);
+      zip_minibuffer_stacks (minibuf_window, of->minibuffer_window);
+      /* MB_frame's minibuffer can be on a different frame.  */
+      if (MINI_WINDOW_P (XWINDOW (FRAME_SELECTED_WINDOW (of))))
+       Fset_frame_selected_window (MB_frame,
+                                   Fframe_first_window (MB_frame), Qnil);
     }
+  MB_frame = XWINDOW (XFRAME (selected_frame)->minibuffer_window)->frame;
+  if (live_minibuffer_p (XWINDOW (minibuf_window)->contents))
+    call1 (Qrecord_window_buffer, minibuf_window);
 
+  record_unwind_protect_void (minibuffer_unwind);
   record_unwind_protect (restore_window_configuration,
                          Fcons (Qt, Fcurrent_window_configuration (Qnil)));
 
@@ -771,23 +788,6 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, 
Lisp_Object prompt,
   empty_minibuf = get_minibuffer (0);
   set_minibuffer_mode (empty_minibuf, 0);
 
-  FOR_EACH_FRAME (dummy, frame)
-    {
-      Lisp_Object root_window = Fframe_root_window (frame);
-      Lisp_Object mini_window = XWINDOW (root_window)->next;
-      Lisp_Object buffer;
-
-      if (!NILP (mini_window) && !EQ (mini_window, minibuf_window)
-          && !NILP (Fwindow_minibuffer_p (mini_window)))
-        {
-          buffer = XWINDOW (mini_window)->contents;
-          if (!live_minibuffer_p (buffer))
-            /* Use set_window_buffer instead of Fset_window_buffer (see
-               discussion of bug#11984, bug#12025, bug#12026).  */
-            set_window_buffer (mini_window, empty_minibuf, 0, 0);
-        }
-    }
-
   /* Display this minibuffer in the proper window.  */
   /* Use set_window_buffer instead of Fset_window_buffer (see
      discussion of bug#11984, bug#12025, bug#12026).  */
@@ -908,7 +908,9 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, 
Lisp_Object prompt,
   unbind_to (count, Qnil);
 
   /* Switch the frame back to the calling frame.  */
-  if (!EQ (selected_frame, calling_frame)
+  if ((!EQ (selected_frame, calling_frame)
+       || !EQ (XWINDOW (XFRAME (calling_frame)->minibuffer_window)->frame,
+              calling_frame))
       && FRAMEP (calling_frame)
       && FRAME_LIVE_P (XFRAME (calling_frame)))
     call2 (intern ("select-frame-set-input-focus"), calling_frame, Qnil);
@@ -1026,6 +1028,14 @@ run_exit_minibuf_hook (void)
   safe_run_hooks (Qminibuffer_exit_hook);
 }
 
+/* This variable records the expired minibuffer's frame between the
+   calls of `read_minibuf_unwind' and `minibuffer_unwind'.  It should
+   be used only by these two functions.  Note that the same search
+   method for the MB's frame won't always work in `minibuffer_unwind'
+   because the intervening `restore-window-configuration' will have
+   changed the buffer in the mini-window.  */
+static Lisp_Object exp_MB_frame;
+
 /* This function is called on exiting minibuffer, whether normally or
    not, and it restores the current window, buffer, etc.  */
 
@@ -1036,6 +1046,28 @@ read_minibuf_unwind (void)
   Lisp_Object calling_frame;
   Lisp_Object calling_window;
   Lisp_Object future_mini_window;
+  Lisp_Object saved_selected_frame = selected_frame;
+  Lisp_Object window, frames;
+  struct window *w;
+  struct frame *f;
+
+  /* Locate the expired minibuffer.  */
+  FOR_EACH_FRAME (frames, exp_MB_frame)
+    {
+      f = XFRAME (exp_MB_frame);
+      window = f->minibuffer_window;
+      w = XWINDOW (window);
+      if (EQ (w->frame, exp_MB_frame)
+         && EQ (w->contents, nth_minibuffer (minibuf_level)))
+       goto found;
+    }
+  return; /* expired minibuffer not found.  Maybe we should output an
+            error, here. */
+
+ found:
+  if (!EQ (exp_MB_frame, saved_selected_frame))
+    do_switch_frame (exp_MB_frame, 0, 0, Qt); /* This also sets
+                                            minibuff_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
@@ -1127,20 +1159,61 @@ read_minibuf_unwind (void)
      away from the expired minibuffer window, both in the current
      minibuffer's frame and the original calling frame.  */
   choose_minibuf_frame ();
-  if (!EQ (WINDOW_FRAME (XWINDOW (minibuf_window)), calling_frame))
-  {
-    Lisp_Object prev = Fprevious_window (minibuf_window, Qnil, Qnil);
-    /* PREV can be on a different frame when we have a minibuffer only
-       frame, the other frame's minibuffer window is MINIBUF_WINDOW,
-       and its "focus window" is also MINIBUF_WINDOW.  */
-    if (!EQ (prev, minibuf_window)
-       && EQ (WINDOW_FRAME (XWINDOW (prev)),
-              WINDOW_FRAME (XWINDOW (minibuf_window))))
-      Fset_frame_selected_window (selected_frame, prev, Qnil);
-  }
-  else
-    Fset_frame_selected_window (calling_frame, calling_window, Qnil);
+  if (NILP (XWINDOW (minibuf_window)->prev_buffers))
+    {
+      if (!EQ (WINDOW_FRAME (XWINDOW (minibuf_window)), calling_frame))
+       {
+         Lisp_Object prev = Fprevious_window (minibuf_window, Qnil, Qnil);
+         /* PREV can be on a different frame when we have a minibuffer only
+            frame, the other frame's minibuffer window is MINIBUF_WINDOW,
+            and its "focus window" is also MINIBUF_WINDOW.  */
+         if (!EQ (prev, minibuf_window)
+             && EQ (WINDOW_FRAME (XWINDOW (prev)),
+                    WINDOW_FRAME (XWINDOW (minibuf_window))))
+           Fset_frame_selected_window (selected_frame, prev, Qnil);
+       }
+      else
+       Fset_frame_selected_window (calling_frame, calling_window, Qnil);
+    }
+
+  /* Restore the selected frame. */
+  if (!EQ (exp_MB_frame, saved_selected_frame))
+    do_switch_frame (saved_selected_frame, 0, 0, Qt);
+}
+
+/* Replace the expired minibuffer in frame exp_MB_frame with the next less
+   nested minibuffer in that frame, if any.  Otherwise, replace it
+   with the null minibuffer.  MINIBUF_WINDOW is not changed.  */
+static void
+minibuffer_unwind (void)
+{
+  struct frame *f;
+  struct window *w;
+  Lisp_Object window;
+  Lisp_Object entry;
+
+  f = XFRAME (exp_MB_frame);
+  window = f->minibuffer_window;
+  w = XWINDOW (window);
+  if (FRAME_LIVE_P (f))
+    {
+      /* minibuf_window = sf->minibuffer_window; */
+      if (!NILP (w->prev_buffers))
+       {
+         entry = Fcar (w->prev_buffers);
+         w->prev_buffers = Fcdr (w->prev_buffers);
+         set_window_buffer (window, Fcar (entry), 0, 0);
+         Fset_window_start (window, Fcar (Fcdr (entry)), Qnil);
+         Fset_window_point (window, Fcar (Fcdr (Fcdr (entry))));
+         /* set-window-configuration may/will have unselected the
+            mini-window as the selected window.  Restore it. */
+         Fset_frame_selected_window (exp_MB_frame, window, Qnil);
+       }
+      else
+       set_window_buffer (window, nth_minibuffer (0), 0, 0);
+    }
 }
+
 
 
 void
@@ -2213,6 +2286,9 @@ syms_of_minibuf (void)
 {
   staticpro (&minibuf_prompt);
   staticpro (&minibuf_save_list);
+  staticpro (&MB_frame);
+  MB_frame = Qnil;
+  staticpro (&exp_MB_frame);
 
   DEFSYM (Qminibuffer_follows_selected_frame,
           "minibuffer-follows-selected-frame");
diff --git a/src/window.c b/src/window.c
index eb16e2a..4d5c7e7 100644
--- a/src/window.c
+++ b/src/window.c
@@ -6958,7 +6958,8 @@ the return value is nil.  Otherwise the value is t.  */)
 
          if (BUFFERP (w->contents)
              && !EQ (w->contents, p->buffer)
-             && BUFFER_LIVE_P (XBUFFER (p->buffer)))
+             && BUFFER_LIVE_P (XBUFFER (p->buffer))
+             && (NILP (Fminibufferp (p->buffer, Qnil))))
            /* If a window we restore gets another buffer, record the
               window's old buffer.  */
            call1 (Qrecord_window_buffer, window);
diff --git a/src/xdisp.c b/src/xdisp.c
index cc0a689..a405d51 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -12650,9 +12650,8 @@ gui_consider_frame_title (Lisp_Object frame)
         mode_line_noprop_buf; then display the title.  */
       record_unwind_protect (unwind_format_mode_line,
                             format_mode_line_unwind_data
-                              (f, current_buffer, selected_window, false));
+                            (NULL, current_buffer, Qnil, false));
 
-      Fselect_window (f->selected_window, Qt);
       set_buffer_internal_1
        (XBUFFER (XWINDOW (f->selected_window)->contents));
       fmt = FRAME_ICONIFIED_P (f) ? Vicon_title_format : Vframe_title_format;



reply via email to

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