summaryrefslogtreecommitdiff
path: root/src/window.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/window.c')
-rw-r--r--src/window.c151
1 files changed, 86 insertions, 65 deletions
diff --git a/src/window.c b/src/window.c
index eb16e2a4338..a6e8ee0d534 100644
--- a/src/window.c
+++ b/src/window.c
@@ -215,20 +215,6 @@ wset_combination (struct window *w, bool horflag, Lisp_Object val)
w->horizontal = horflag;
}
-static void
-wset_update_mode_line (struct window *w)
-{
- /* If this window is the selected window on its frame, set the
- global variable update_mode_lines, so that gui_consider_frame_title
- will consider this frame's title for redisplay. */
- Lisp_Object fselected_window = XFRAME (WINDOW_FRAME (w))->selected_window;
-
- if (WINDOWP (fselected_window) && XWINDOW (fselected_window) == w)
- update_mode_lines = 42;
- else
- w->update_mode_line = true;
-}
-
/* True if leaf window W doesn't reflect the actual state
of displayed buffer due to its text or overlays change. */
@@ -482,6 +468,7 @@ Return WINDOW. */)
else
{
fset_selected_window (XFRAME (frame), window);
+ /* Don't clear FRAME's select_mini_window_flag here. */
return window;
}
}
@@ -518,10 +505,21 @@ select_window (Lisp_Object window, Lisp_Object norecord,
{
struct window *w;
struct frame *sf;
+ Lisp_Object frame;
+ struct frame *f;
CHECK_LIVE_WINDOW (window);
w = XWINDOW (window);
+ frame = WINDOW_FRAME (w);
+ f = XFRAME (frame);
+
+ if (FRAME_TOOLTIP_P (f))
+ /* Do not select a tooltip window (Bug#47207). */
+ error ("Cannot select a tooltip window");
+
+ /* We deinitely want to select WINDOW, not the mini-window. */
+ f->select_mini_window_flag = false;
/* Make the selected window's buffer current. */
Fset_buffer (w->contents);
@@ -542,14 +540,14 @@ select_window (Lisp_Object window, Lisp_Object norecord,
redisplay_other_windows ();
sf = SELECTED_FRAME ();
- if (XFRAME (WINDOW_FRAME (w)) != sf)
+ if (f != sf)
{
- fset_selected_window (XFRAME (WINDOW_FRAME (w)), window);
+ fset_selected_window (f, window);
/* Use this rather than Fhandle_switch_frame
so that FRAME_FOCUS_FRAME is moved appropriately as we
move around in the state where a minibuffer in a separate
frame is active. */
- Fselect_frame (WINDOW_FRAME (w), norecord);
+ Fselect_frame (frame, norecord);
/* Fselect_frame called us back so we've done all the work already. */
eassert (EQ (window, selected_window));
return window;
@@ -1725,14 +1723,16 @@ have been if redisplay had finished, do this:
DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 2, 0,
doc: /* Return position at which display currently ends in WINDOW.
-WINDOW must be a live window and defaults to the selected one.
-This is updated by redisplay, when it runs to completion.
-Simply changing the buffer text or setting `window-start'
-does not update this value.
+This is the position after the final character in WINDOW.
+
+WINDOW must be a live window and defaults to the selected one. This
+is updated by redisplay, when it runs to completion. Simply changing
+the buffer text or setting `window-start' does not update this value.
+
Return nil if there is no recorded value. (This can happen if the
-last redisplay of WINDOW was preempted, and did not finish.)
-If UPDATE is non-nil, compute the up-to-date position
-if it isn't already recorded. */)
+last redisplay of WINDOW was preempted, and did not finish.) If
+UPDATE is non-nil, compute the up-to-date position if it isn't already
+recorded. */)
(Lisp_Object window, Lisp_Object update)
{
Lisp_Object value;
@@ -2556,8 +2556,13 @@ window_list (void)
if (!CONSP (Vwindow_list))
{
Lisp_Object tail, frame;
+ ptrdiff_t count = SPECPDL_INDEX ();
Vwindow_list = Qnil;
+ /* Don't allow quitting in Fnconc. Otherwise we might end up
+ with a too short Vwindow_list and Fkill_buffer not being able
+ to replace a buffer in all windows showing it (Bug#47244). */
+ specbind (Qinhibit_quit, Qt);
FOR_EACH_FRAME (tail, frame)
{
Lisp_Object arglist = Qnil;
@@ -2569,6 +2574,8 @@ window_list (void)
arglist = Fnreverse (arglist);
Vwindow_list = nconc2 (Vwindow_list, arglist);
}
+
+ unbind_to (count, Qnil);
}
return Vwindow_list;
@@ -2603,7 +2610,7 @@ candidate_window_p (Lisp_Object window, Lisp_Object owindow,
candidate_p = false;
else if (MINI_WINDOW_P (w)
&& (EQ (minibuf, Qlambda)
- || (WINDOWP (minibuf) && !EQ (minibuf, window))))
+ || (WINDOW_LIVE_P (minibuf) && !EQ (minibuf, window))))
{
/* If MINIBUF is `lambda' don't consider any mini-windows.
If it is a window, consider only that one. */
@@ -2647,7 +2654,8 @@ candidate_window_p (Lisp_Object window, Lisp_Object owindow,
candidate_p = ((EQ (XWINDOW (all_frames)->frame, w->frame)
|| (EQ (f->minibuffer_window, all_frames)
&& EQ (XWINDOW (all_frames)->frame, FRAME_FOCUS_FRAME (f))))
- && !is_minibuffer (0, XWINDOW (all_frames)->contents));
+ && (EQ (minibuf, Qt)
+ || !is_minibuffer (0, XWINDOW (all_frames)->contents)));
else if (FRAMEP (all_frames))
candidate_p = EQ (all_frames, w->frame);
@@ -2666,12 +2674,12 @@ decode_next_window_args (Lisp_Object *window, Lisp_Object *minibuf, Lisp_Object
Lisp_Object miniwin = XFRAME (w->frame)->minibuffer_window;
XSETWINDOW (*window, w);
- /* MINIBUF nil may or may not include minibuffers. Decide if it
- does. */
- if (NILP (*minibuf))
- *minibuf = this_minibuffer_depth (XWINDOW (miniwin)->contents)
- ? miniwin
- : Qlambda;
+ /* MINIBUF nil may or may not include minibuffer windows. Decide if
+ it does. But first make sure that this frame's minibuffer window
+ is live (Bug#47207). */
+ if (WINDOW_LIVE_P (miniwin) && NILP (*minibuf))
+ *minibuf = (this_minibuffer_depth (XWINDOW (miniwin)->contents)
+ ? miniwin : Qlambda);
else if (!EQ (*minibuf, Qt))
*minibuf = Qlambda;
@@ -2682,9 +2690,10 @@ decode_next_window_args (Lisp_Object *window, Lisp_Object *minibuf, Lisp_Object
/* ALL_FRAMES nil doesn't specify which frames to include. */
if (NILP (*all_frames))
*all_frames
- = (!EQ (*minibuf, Qlambda)
- ? FRAME_MINIBUF_WINDOW (XFRAME (w->frame))
- : Qnil);
+ /* Once more make sure that this frame's minibuffer window is live
+ before including it (Bug#47207). */
+ = ((WINDOW_LIVE_P (miniwin) && !EQ (*minibuf, Qlambda))
+ ? miniwin : Qnil);
else if (EQ (*all_frames, Qvisible))
;
else if (EQ (*all_frames, make_fixnum (0)))
@@ -2705,6 +2714,8 @@ static Lisp_Object
next_window (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames,
bool next_p)
{
+ ptrdiff_t count = SPECPDL_INDEX ();
+
decode_next_window_args (&window, &minibuf, &all_frames);
/* If ALL_FRAMES is a frame, and WINDOW isn't on that frame, just
@@ -2713,6 +2724,9 @@ next_window (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames,
&& !EQ (all_frames, XWINDOW (window)->frame))
return Fframe_first_window (all_frames);
+ /* Don't allow quitting in Fmemq. */
+ specbind (Qinhibit_quit, Qt);
+
if (next_p)
{
Lisp_Object list;
@@ -2762,6 +2776,8 @@ next_window (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames,
window = candidate;
}
+ unbind_to (count, Qnil);
+
return window;
}
@@ -2852,10 +2868,14 @@ static Lisp_Object
window_list_1 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
{
Lisp_Object tail, list, rest;
+ ptrdiff_t count = SPECPDL_INDEX ();
decode_next_window_args (&window, &minibuf, &all_frames);
list = Qnil;
+ /* Don't allow quitting in Fmemq and Fnconc. */
+ specbind (Qinhibit_quit, Qt);
+
for (tail = window_list (); CONSP (tail); tail = XCDR (tail))
if (candidate_window_p (XCAR (tail), window, minibuf, all_frames))
list = Fcons (XCAR (tail), list);
@@ -2870,6 +2890,9 @@ window_list_1 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
XSETCDR (tail, Qnil);
list = nconc2 (rest, list);
}
+
+ unbind_to (count, Qnil);
+
return list;
}
@@ -3225,6 +3248,9 @@ window-start value is reasonable when this function is called. */)
if (EQ (selected_frame, w->frame))
Fselect_window (window, Qnil);
else
+ /* Do not clear f->select_mini_window_flag here. If the
+ last selected window on F was an active minibuffer, we
+ want to return to it on a later Fselect_frame. */
fset_selected_window (f, window);
}
}
@@ -5124,37 +5150,23 @@ Signal an error when WINDOW is the only window on its frame. */)
adjust_frame_glyphs (f);
if (!WINDOW_LIVE_P (FRAME_SELECTED_WINDOW (f)))
- /* We deleted the frame's selected window. */
+ /* We apparently deleted the frame's selected window; use the
+ frame's first window as substitute but don't record it yet.
+ `delete-window' may have something better up its sleeves. */
{
/* Use the frame's first window as fallback ... */
Lisp_Object new_selected_window = Fframe_first_window (frame);
- /* ... but preferably use its most recently used window. */
- Lisp_Object mru_window;
- /* `get-mru-window' might fail for some reason so play it safe
- - promote the first window _without recording it_ first. */
if (EQ (FRAME_SELECTED_WINDOW (f), selected_window))
Fselect_window (new_selected_window, Qt);
else
- fset_selected_window (f, new_selected_window);
-
- unblock_input ();
-
- /* Now look whether `get-mru-window' gets us something. */
- mru_window = call1 (Qget_mru_window, frame);
- if (WINDOW_LIVE_P (mru_window)
- && EQ (XWINDOW (mru_window)->frame, frame))
- new_selected_window = mru_window;
-
- /* If all ended up well, we now promote the mru window. */
- if (EQ (FRAME_SELECTED_WINDOW (f), selected_window))
- Fselect_window (new_selected_window, Qnil);
- else
+ /* Do not clear f->select_mini_window_flag here. If the
+ last selected window on F was an active minibuffer, we
+ want to return to it on a later Fselect_frame. */
fset_selected_window (f, new_selected_window);
}
- else
- unblock_input ();
+ unblock_input ();
FRAME_WINDOW_CHANGE (f) = true;
}
else
@@ -6864,19 +6876,22 @@ DEFUN ("window-configuration-frame", Fwindow_configuration_frame, Swindow_config
}
DEFUN ("set-window-configuration", Fset_window_configuration,
- Sset_window_configuration, 1, 2, 0,
+ Sset_window_configuration, 1, 3, 0,
doc: /* Set the configuration of windows and buffers as specified by CONFIGURATION.
CONFIGURATION must be a value previously returned
by `current-window-configuration' (which see).
Normally, this function selects the frame of the CONFIGURATION, but if
DONT-SET-FRAME is non-nil, it leaves selected the frame which was
-current at the start of the function.
+current at the start of the function. If DONT-SET-MINIWINDOW is non-nil,
+the mini-window of the frame doesn't get set to the corresponding element
+of CONFIGURATION.
If CONFIGURATION was made from a frame that is now deleted,
only frame-independent values can be restored. In this case,
the return value is nil. Otherwise the value is t. */)
- (Lisp_Object configuration, Lisp_Object dont_set_frame)
+ (Lisp_Object configuration, Lisp_Object dont_set_frame,
+ Lisp_Object dont_set_miniwindow)
{
register struct save_window_data *data;
struct Lisp_Vector *saved_windows;
@@ -6958,7 +6973,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);
@@ -7086,8 +7102,10 @@ the return value is nil. Otherwise the value is t. */)
}
}
- if (BUFFERP (p->buffer) && BUFFER_LIVE_P (XBUFFER (p->buffer)))
- /* If saved buffer is alive, install it. */
+ if ((NILP (dont_set_miniwindow) || !MINI_WINDOW_P (w))
+ && BUFFERP (p->buffer) && BUFFER_LIVE_P (XBUFFER (p->buffer)))
+ /* If saved buffer is alive, install it, unless it's a
+ minibuffer we explicitly prohibit. */
{
wset_buffer (w, p->buffer);
w->start_at_line_beg = !NILP (p->start_at_line_beg);
@@ -7240,9 +7258,11 @@ void
restore_window_configuration (Lisp_Object configuration)
{
if (CONSP (configuration))
- Fset_window_configuration (XCDR (configuration), XCAR (configuration));
+ Fset_window_configuration (XCAR (configuration),
+ Fcar_safe (XCDR (configuration)),
+ Fcar_safe (Fcdr_safe (XCDR (configuration))));
else
- Fset_window_configuration (configuration, Qnil);
+ Fset_window_configuration (configuration, Qnil, Qnil);
}
@@ -8134,7 +8154,7 @@ init_window_once (void)
minibuf_selected_window = Qnil;
staticpro (&minibuf_selected_window);
- pdumper_do_now_and_after_load (init_window_once_for_pdumper);
+ pdumper_do_now_and_after_late_load (init_window_once_for_pdumper);
}
static void init_window_once_for_pdumper (void)
@@ -8224,6 +8244,7 @@ syms_of_window (void)
DEFSYM (Qmode_line_format, "mode-line-format");
DEFSYM (Qheader_line_format, "header-line-format");
DEFSYM (Qtab_line_format, "tab-line-format");
+ DEFSYM (Qno_other_window, "no-other-window");
DEFVAR_LISP ("temp-buffer-show-function", Vtemp_buffer_show_function,
doc: /* Non-nil means call as function to display a help buffer.