Preserve tty top-frames under various window-changing operations.
* subr.el (with-selected-window): Preserve the selected window's terminal's top-frame. * window.el (save-selected-window): Likewise. * frame.c (delete_frame): When selecting a frame on a different text terminal, do not alter the terminal's top-frame. * term.c (Ftty_top_frame): New function. * xdisp.c (format_mode_line_unwind_data): Record the target frame's selected window and its terminal's top-frame. (unwind_format_mode_line): Restore them. (x_consider_frame_title, display_mode_line, Fformat_mode_line): Callers changed. (x_consider_frame_title): Do not condition on HAVE_WINDOW_SYSTEM, since tty frames can be explicitly named. (prepare_menu_bars): Likewise. Fixes: debbugs:4702
This commit is contained in:
parent
4e2cc2f31f
commit
c6bf302224
8 changed files with 140 additions and 54 deletions
2
etc/NEWS
2
etc/NEWS
|
@ -473,6 +473,8 @@ is detected.
|
|||
Emacs now supports mouse highlight, help-echo (in the echo area), and
|
||||
mouse-autoselect-window.
|
||||
|
||||
** New function `tty-top-frame' returns the topmost frame of a text terminal.
|
||||
|
||||
|
||||
* Installation Changes in Emacs 24.1
|
||||
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
2012-06-19 Chong Yidong <cyd@gnu.org>
|
||||
|
||||
* subr.el (with-selected-window): Preserve the selected window's
|
||||
terminal's top-frame (Bug#4702).
|
||||
|
||||
* window.el (save-selected-window): Likewise.
|
||||
|
||||
2012-06-18 Stefan Monnier <monnier@iro.umontreal.ca>
|
||||
|
||||
* progmodes/python.el (python-rx-constituents): Move backquote.
|
||||
|
|
27
lisp/subr.el
27
lisp/subr.el
|
@ -3011,24 +3011,29 @@ the buffer list ordering."
|
|||
(declare (indent 1) (debug t))
|
||||
;; Most of this code is a copy of save-selected-window.
|
||||
`(let* ((save-selected-window-destination ,window)
|
||||
(save-selected-window-frame
|
||||
(window-frame save-selected-window-destination))
|
||||
(save-selected-window-window (selected-window))
|
||||
;; Selecting a window on another frame changes not only the
|
||||
;; selected-window but also the frame-selected-window of the
|
||||
;; destination frame. So we need to save&restore it.
|
||||
;; Selecting a window on another frame also changes that
|
||||
;; frame's frame-selected-window. We must save&restore it.
|
||||
(save-selected-window-other-frame
|
||||
(unless (eq (selected-frame)
|
||||
(window-frame save-selected-window-destination))
|
||||
(frame-selected-window
|
||||
(window-frame save-selected-window-destination)))))
|
||||
(unless (eq (selected-frame) save-selected-window-frame)
|
||||
(frame-selected-window save-selected-window-frame)))
|
||||
(save-selected-window-top-frame
|
||||
(unless (eq (selected-frame) save-selected-window-frame)
|
||||
(tty-top-frame save-selected-window-frame))))
|
||||
(save-current-buffer
|
||||
(unwind-protect
|
||||
(progn (select-window save-selected-window-destination 'norecord)
|
||||
,@body)
|
||||
;; First reset frame-selected-window.
|
||||
(if (window-live-p save-selected-window-other-frame)
|
||||
;; We don't use set-frame-selected-window because it does not
|
||||
;; pass the `norecord' argument to Fselect_window.
|
||||
(select-window save-selected-window-other-frame 'norecord))
|
||||
(when (window-live-p save-selected-window-other-frame)
|
||||
;; We don't use set-frame-selected-window because it does not
|
||||
;; pass the `norecord' argument to Fselect_window.
|
||||
(select-window save-selected-window-other-frame 'norecord)
|
||||
(and (frame-live-p save-selected-window-top-frame)
|
||||
(not (eq (tty-top-frame) save-selected-window-top-frame))
|
||||
(select-frame save-selected-window-top-frame 'norecord)))
|
||||
;; Then reset the actual selected-window.
|
||||
(when (window-live-p save-selected-window-window)
|
||||
(select-window save-selected-window-window 'norecord))))))
|
||||
|
|
|
@ -47,12 +47,24 @@ order of recently selected windows and the buffer list ordering
|
|||
are not altered by this macro (unless they are altered in BODY)."
|
||||
(declare (indent 0) (debug t))
|
||||
`(let ((save-selected-window-window (selected-window))
|
||||
;; It is necessary to save all of these, because calling
|
||||
;; select-window changes frame-selected-window for whatever
|
||||
;; frame that window is in.
|
||||
;; We save and restore all frames' selected windows, because
|
||||
;; `select-window' can change the frame-selected-window of
|
||||
;; whatever frame that window is in. Each text terminal's
|
||||
;; top-frame is preserved by putting it last in the list.
|
||||
(save-selected-window-alist
|
||||
(mapcar (lambda (frame) (cons frame (frame-selected-window frame)))
|
||||
(frame-list))))
|
||||
(apply 'append
|
||||
(mapcar (lambda (terminal)
|
||||
(let ((frames (frames-on-display-list terminal))
|
||||
(top-frame (tty-top-frame terminal))
|
||||
alist)
|
||||
(if top-frame
|
||||
(setq frames
|
||||
(cons top-frame
|
||||
(delq top-frame frames))))
|
||||
(dolist (f frames)
|
||||
(push (cons f (frame-selected-window f))
|
||||
alist))))
|
||||
(terminal-list)))))
|
||||
(save-current-buffer
|
||||
(unwind-protect
|
||||
(progn ,@body)
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
2012-06-19 Chong Yidong <cyd@gnu.org>
|
||||
|
||||
* frame.c (delete_frame): When selecting a frame on a different
|
||||
text terminal, do not alter the terminal's top-frame.
|
||||
|
||||
* xdisp.c (format_mode_line_unwind_data): Record the target
|
||||
frame's selected window and its terminal's top-frame.
|
||||
(unwind_format_mode_line): Restore them.
|
||||
(x_consider_frame_title, display_mode_line, Fformat_mode_line):
|
||||
Callers changed.
|
||||
(x_consider_frame_title): Do not condition on HAVE_WINDOW_SYSTEM,
|
||||
since tty frames can be explicitly named.
|
||||
(prepare_menu_bars): Likewise.
|
||||
|
||||
* term.c (Ftty_top_frame): New function.
|
||||
|
||||
2012-06-18 Paul Eggert <eggert@cs.ucla.edu>
|
||||
|
||||
Port byte-code-meter to modern targets.
|
||||
|
|
36
src/frame.c
36
src/frame.c
|
@ -630,8 +630,8 @@ DEFUN ("make-terminal-frame", Fmake_terminal_frame, Smake_terminal_frame,
|
|||
doc: /* Create an additional terminal frame, possibly on another terminal.
|
||||
This function takes one argument, an alist specifying frame parameters.
|
||||
|
||||
You can create multiple frames on a single text-only terminal, but
|
||||
only one of them (the selected terminal frame) is actually displayed.
|
||||
You can create multiple frames on a single text terminal, but only one
|
||||
of them (the selected terminal frame) is actually displayed.
|
||||
|
||||
In practice, generally you don't need to specify any parameters,
|
||||
except when you want to create a new frame on another terminal.
|
||||
|
@ -865,8 +865,8 @@ something to select a different frame, or until the next time
|
|||
this function is called. If you are using a window system, the
|
||||
previously selected frame may be restored as the selected frame
|
||||
when returning to the command loop, because it still may have
|
||||
the window system's input focus. On a text-only terminal, the
|
||||
next redisplay will display FRAME.
|
||||
the window system's input focus. On a text terminal, the next
|
||||
redisplay will display FRAME.
|
||||
|
||||
This function returns FRAME, or nil if FRAME has been deleted. */)
|
||||
(Lisp_Object frame, Lisp_Object norecord)
|
||||
|
@ -1254,7 +1254,17 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
|
|||
FOR_EACH_FRAME (tail, frame1)
|
||||
{
|
||||
if (! EQ (frame, frame1) && FRAME_LIVE_P (XFRAME (frame1)))
|
||||
break;
|
||||
{
|
||||
/* Do not change a text terminal's top-frame. */
|
||||
struct frame *f1 = XFRAME (frame1);
|
||||
if (FRAME_TERMCAP_P (f1) || FRAME_MSDOS_P (f1))
|
||||
{
|
||||
Lisp_Object top_frame = FRAME_TTY (f1)->top_frame;
|
||||
if (!EQ (top_frame, frame))
|
||||
frame1 = top_frame;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef NS_IMPL_COCOA
|
||||
|
@ -1730,8 +1740,8 @@ usually not displayed at all, even in a window system's \"taskbar\".
|
|||
Normally you may not make FRAME invisible if all other frames are invisible,
|
||||
but if the second optional argument FORCE is non-nil, you may do so.
|
||||
|
||||
This function has no effect on text-only terminal frames. Such frames
|
||||
are always considered visible, whether or not they are currently being
|
||||
This function has no effect on text terminal frames. Such frames are
|
||||
always considered visible, whether or not they are currently being
|
||||
displayed in the terminal. */)
|
||||
(Lisp_Object frame, Lisp_Object force)
|
||||
{
|
||||
|
@ -1743,12 +1753,6 @@ displayed in the terminal. */)
|
|||
if (NILP (force) && !other_visible_frames (XFRAME (frame)))
|
||||
error ("Attempt to make invisible the sole visible or iconified frame");
|
||||
|
||||
#if 0 /* This isn't logically necessary, and it can do GC. */
|
||||
/* Don't let the frame remain selected. */
|
||||
if (EQ (frame, selected_frame))
|
||||
do_switch_frame (next_frame (frame, Qt), 0, 0, Qnil)
|
||||
#endif
|
||||
|
||||
/* Don't allow minibuf_window to remain on a deleted frame. */
|
||||
if (EQ (XFRAME (frame)->minibuffer_window, minibuf_window))
|
||||
{
|
||||
|
@ -1816,7 +1820,7 @@ Return nil if FRAME was made invisible, via `make-frame-invisible'.
|
|||
On graphical displays, invisible frames are not updated and are
|
||||
usually not displayed at all, even in a window system's \"taskbar\".
|
||||
|
||||
If FRAME is a text-only terminal frame, this always returns t.
|
||||
If FRAME is a text terminal frame, this always returns t.
|
||||
Such frames are always considered visible, whether or not they are
|
||||
currently being displayed on the terminal. */)
|
||||
(Lisp_Object frame)
|
||||
|
@ -1872,7 +1876,7 @@ doesn't support multiple overlapping frames, this function selects FRAME. */)
|
|||
f = XFRAME (frame);
|
||||
|
||||
if (FRAME_TERMCAP_P (f))
|
||||
/* On a text-only terminal select FRAME. */
|
||||
/* On a text terminal select FRAME. */
|
||||
Fselect_frame (frame, Qnil);
|
||||
else
|
||||
/* Do like the documentation says. */
|
||||
|
@ -2493,7 +2497,7 @@ not the menu bar).
|
|||
In a graphical version with no toolkit, it includes both the tool bar
|
||||
and menu bar.
|
||||
|
||||
For a text-only terminal, it includes the menu bar. In this case, the
|
||||
For a text terminal, it includes the menu bar. In this case, the
|
||||
result is really in characters rather than pixels (i.e., is identical
|
||||
to `frame-height'). */)
|
||||
(Lisp_Object frame)
|
||||
|
|
22
src/term.c
22
src/term.c
|
@ -2132,7 +2132,7 @@ DEFUN ("tty-display-color-p", Ftty_display_color_p, Stty_display_color_p,
|
|||
|
||||
TERMINAL can be a terminal object, a frame, or nil (meaning the
|
||||
selected frame's terminal). This function always returns nil if
|
||||
TERMINAL does not refer to a text-only terminal. */)
|
||||
TERMINAL does not refer to a text terminal. */)
|
||||
(Lisp_Object terminal)
|
||||
{
|
||||
struct terminal *t = get_tty_terminal (terminal, 0);
|
||||
|
@ -2149,7 +2149,7 @@ DEFUN ("tty-display-color-cells", Ftty_display_color_cells,
|
|||
|
||||
TERMINAL can be a terminal object, a frame, or nil (meaning the
|
||||
selected frame's terminal). This function always returns 0 if
|
||||
TERMINAL does not refer to a text-only terminal. */)
|
||||
TERMINAL does not refer to a text terminal. */)
|
||||
(Lisp_Object terminal)
|
||||
{
|
||||
struct terminal *t = get_tty_terminal (terminal, 0);
|
||||
|
@ -2371,7 +2371,7 @@ no effect if used on a non-tty terminal.
|
|||
|
||||
TERMINAL can be a terminal object, a frame or nil (meaning the
|
||||
selected frame's terminal). This function always returns nil if
|
||||
TERMINAL does not refer to a text-only terminal. */)
|
||||
TERMINAL does not refer to a text terminal. */)
|
||||
(Lisp_Object terminal)
|
||||
{
|
||||
struct terminal *t = get_terminal (terminal, 1);
|
||||
|
@ -2381,6 +2381,21 @@ TERMINAL does not refer to a text-only terminal. */)
|
|||
return Qnil;
|
||||
}
|
||||
|
||||
DEFUN ("tty-top-frame", Ftty_top_frame, Stty_top_frame, 0, 1, 0,
|
||||
doc: /* Return the topmost terminal frame on TERMINAL.
|
||||
TERMINAL can be a terminal object, a frame or nil (meaning the
|
||||
selected frame's terminal). This function returns nil if TERMINAL
|
||||
does not refer to a text terminal. Otherwise, it returns the
|
||||
top-most frame on the text terminal. */)
|
||||
(Lisp_Object terminal)
|
||||
{
|
||||
struct terminal *t = get_terminal (terminal, 1);
|
||||
|
||||
if (t->type == output_termcap)
|
||||
return t->display_info.tty->top_frame;
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
|
||||
|
||||
DEFUN ("suspend-tty", Fsuspend_tty, Ssuspend_tty, 0, 1, 0,
|
||||
|
@ -3638,6 +3653,7 @@ bigger, or it may make it blink, or it may do nothing at all. */);
|
|||
defsubr (&Stty_no_underline);
|
||||
defsubr (&Stty_type);
|
||||
defsubr (&Scontrolling_tty_p);
|
||||
defsubr (&Stty_top_frame);
|
||||
defsubr (&Ssuspend_tty);
|
||||
defsubr (&Sresume_tty);
|
||||
#ifdef HAVE_GPM
|
||||
|
|
62
src/xdisp.c
62
src/xdisp.c
|
@ -8356,9 +8356,9 @@ move_it_in_display_line_to (struct it *it,
|
|||
/* On graphical terminals, newlines may
|
||||
"overflow" into the fringe if
|
||||
overflow-newline-into-fringe is non-nil.
|
||||
On text-only terminals, newlines may
|
||||
overflow into the last glyph on the
|
||||
display line.*/
|
||||
On text terminals, newlines may overflow
|
||||
into the last glyph on the display
|
||||
line.*/
|
||||
if (!FRAME_WINDOW_P (it->f)
|
||||
|| IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
|
||||
{
|
||||
|
@ -10821,7 +10821,8 @@ static Lisp_Object mode_line_string_face_prop;
|
|||
static Lisp_Object Vmode_line_unwind_vector;
|
||||
|
||||
static Lisp_Object
|
||||
format_mode_line_unwind_data (struct buffer *obuf,
|
||||
format_mode_line_unwind_data (struct frame *target_frame,
|
||||
struct buffer *obuf,
|
||||
Lisp_Object owin,
|
||||
int save_proptrans)
|
||||
{
|
||||
|
@ -10833,7 +10834,7 @@ format_mode_line_unwind_data (struct buffer *obuf,
|
|||
Vmode_line_unwind_vector = Qnil;
|
||||
|
||||
if (NILP (vector))
|
||||
vector = Fmake_vector (make_number (8), Qnil);
|
||||
vector = Fmake_vector (make_number (10), Qnil);
|
||||
|
||||
ASET (vector, 0, make_number (mode_line_target));
|
||||
ASET (vector, 1, make_number (MODE_LINE_NOPROP_LEN (0)));
|
||||
|
@ -10848,6 +10849,15 @@ format_mode_line_unwind_data (struct buffer *obuf,
|
|||
tmp = Qnil;
|
||||
ASET (vector, 6, tmp);
|
||||
ASET (vector, 7, owin);
|
||||
if (target_frame)
|
||||
{
|
||||
/* Similarly to `with-selected-window', if the operation selects
|
||||
a window on another frame, we must restore that frame's
|
||||
selected window, and (for a tty) the top-frame. */
|
||||
ASET (vector, 8, target_frame->selected_window);
|
||||
if (FRAME_TERMCAP_P (target_frame))
|
||||
ASET (vector, 9, FRAME_TTY (target_frame)->top_frame);
|
||||
}
|
||||
|
||||
return vector;
|
||||
}
|
||||
|
@ -10855,6 +10865,10 @@ format_mode_line_unwind_data (struct buffer *obuf,
|
|||
static Lisp_Object
|
||||
unwind_format_mode_line (Lisp_Object vector)
|
||||
{
|
||||
Lisp_Object old_window = AREF (vector, 7);
|
||||
Lisp_Object target_frame_window = AREF (vector, 8);
|
||||
Lisp_Object old_top_frame = AREF (vector, 9);
|
||||
|
||||
mode_line_target = XINT (AREF (vector, 0));
|
||||
mode_line_noprop_ptr = mode_line_noprop_buf + XINT (AREF (vector, 1));
|
||||
mode_line_string_list = AREF (vector, 2);
|
||||
|
@ -10863,9 +10877,26 @@ unwind_format_mode_line (Lisp_Object vector)
|
|||
mode_line_string_face = AREF (vector, 4);
|
||||
mode_line_string_face_prop = AREF (vector, 5);
|
||||
|
||||
if (!NILP (AREF (vector, 7)))
|
||||
/* Select window before buffer, since it may change the buffer. */
|
||||
Fselect_window (AREF (vector, 7), Qt);
|
||||
/* Select window before buffer, since it may change the buffer. */
|
||||
if (!NILP (old_window))
|
||||
{
|
||||
/* If the operation that we are unwinding had selected a window
|
||||
on a different frame, reset its frame-selected-window. For a
|
||||
text terminal, reset its top-frame if necessary. */
|
||||
if (!NILP (target_frame_window))
|
||||
{
|
||||
Lisp_Object frame
|
||||
= WINDOW_FRAME (XWINDOW (target_frame_window));
|
||||
|
||||
if (!EQ (frame, WINDOW_FRAME (XWINDOW (old_window))))
|
||||
Fselect_window (target_frame_window, Qt);
|
||||
|
||||
if (!NILP (old_top_frame) && !EQ (old_top_frame, frame))
|
||||
Fselect_frame (old_top_frame, Qt);
|
||||
}
|
||||
|
||||
Fselect_window (old_window, Qt);
|
||||
}
|
||||
|
||||
if (!NILP (AREF (vector, 6)))
|
||||
{
|
||||
|
@ -10936,8 +10967,6 @@ store_mode_line_noprop (const char *string, int field_width, int precision)
|
|||
Frame Titles
|
||||
***********************************************************************/
|
||||
|
||||
#ifdef HAVE_WINDOW_SYSTEM
|
||||
|
||||
/* Set the title of FRAME, if it has changed. The title format is
|
||||
Vicon_title_format if FRAME is iconified, otherwise it is
|
||||
frame_title_format. */
|
||||
|
@ -10981,7 +11010,7 @@ x_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
|
||||
(current_buffer, selected_window, 0));
|
||||
(f, current_buffer, selected_window, 0));
|
||||
|
||||
Fselect_window (f->selected_window, Qt);
|
||||
set_buffer_internal_1 (XBUFFER (XWINDOW (f->selected_window)->buffer));
|
||||
|
@ -11008,10 +11037,6 @@ x_consider_frame_title (Lisp_Object frame)
|
|||
}
|
||||
}
|
||||
|
||||
#endif /* not HAVE_WINDOW_SYSTEM */
|
||||
|
||||
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
Menu Bars
|
||||
|
@ -11038,7 +11063,6 @@ prepare_menu_bars (void)
|
|||
/* Update all frame titles based on their buffer names, etc. We do
|
||||
this before the menu bars so that the buffer-menu will show the
|
||||
up-to-date frame titles. */
|
||||
#ifdef HAVE_WINDOW_SYSTEM
|
||||
if (windows_or_buffers_changed || update_mode_lines)
|
||||
{
|
||||
Lisp_Object tail, frame;
|
||||
|
@ -11051,7 +11075,6 @@ prepare_menu_bars (void)
|
|||
x_consider_frame_title (frame);
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_WINDOW_SYSTEM */
|
||||
|
||||
/* Update the menu bar item lists, if appropriate. This has to be
|
||||
done before any actual redisplay or generation of display lines. */
|
||||
|
@ -20125,7 +20148,7 @@ display_mode_line (struct window *w, enum face_id face_id, Lisp_Object format)
|
|||
it.paragraph_embedding = L2R;
|
||||
|
||||
record_unwind_protect (unwind_format_mode_line,
|
||||
format_mode_line_unwind_data (NULL, Qnil, 0));
|
||||
format_mode_line_unwind_data (NULL, NULL, Qnil, 0));
|
||||
|
||||
mode_line_target = MODE_LINE_DISPLAY;
|
||||
|
||||
|
@ -20826,7 +20849,8 @@ are the selected window and the WINDOW's buffer). */)
|
|||
and set that to nil so that we don't alter the outer value. */
|
||||
record_unwind_protect (unwind_format_mode_line,
|
||||
format_mode_line_unwind_data
|
||||
(old_buffer, selected_window, 1));
|
||||
(XFRAME (WINDOW_FRAME (XWINDOW (window))),
|
||||
old_buffer, selected_window, 1));
|
||||
mode_line_proptrans_alist = Qnil;
|
||||
|
||||
Fselect_window (window, Qt);
|
||||
|
|
Loading…
Add table
Reference in a new issue