emacs-diffs
[Top][All Lists]
Advanced

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

[Emacs-diffs] /srv/bzr/emacs/trunk r108658: Preserve tty top-frames unde


From: Chong Yidong
Subject: [Emacs-diffs] /srv/bzr/emacs/trunk r108658: Preserve tty top-frames under various window-changing operations.
Date: Tue, 19 Jun 2012 14:49:50 +0800
User-agent: Bazaar (2.5.0)

------------------------------------------------------------
revno: 108658
fixes bug: http://debbugs.gnu.org/4702
committer: Chong Yidong <address@hidden>
branch nick: trunk
timestamp: Tue 2012-06-19 14:49:50 +0800
message:
  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.
modified:
  etc/NEWS
  lisp/ChangeLog
  lisp/subr.el
  lisp/window.el
  src/ChangeLog
  src/frame.c
  src/term.c
  src/xdisp.c
=== modified file 'etc/NEWS'
--- a/etc/NEWS  2012-06-18 15:57:41 +0000
+++ b/etc/NEWS  2012-06-19 06:49:50 +0000
@@ -473,6 +473,8 @@
 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
 

=== modified file 'lisp/ChangeLog'
--- a/lisp/ChangeLog    2012-06-18 20:41:23 +0000
+++ b/lisp/ChangeLog    2012-06-19 06:49:50 +0000
@@ -1,3 +1,10 @@
+2012-06-19  Chong Yidong  <address@hidden>
+
+       * 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  <address@hidden>
 
        * progmodes/python.el (python-rx-constituents): Move backquote.

=== modified file 'lisp/subr.el'
--- a/lisp/subr.el      2012-06-07 16:20:28 +0000
+++ b/lisp/subr.el      2012-06-19 06:49:50 +0000
@@ -3011,24 +3011,29 @@
   (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))))))

=== modified file 'lisp/window.el'
--- a/lisp/window.el    2012-06-18 06:22:22 +0000
+++ b/lisp/window.el    2012-06-19 06:49:50 +0000
@@ -47,12 +47,24 @@
 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)

=== modified file 'src/ChangeLog'
--- a/src/ChangeLog     2012-06-18 22:53:53 +0000
+++ b/src/ChangeLog     2012-06-19 06:49:50 +0000
@@ -1,3 +1,19 @@
+2012-06-19  Chong Yidong  <address@hidden>
+
+       * 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  <address@hidden>
 
        Port byte-code-meter to modern targets.

=== modified file 'src/frame.c'
--- a/src/frame.c       2012-06-13 13:40:48 +0000
+++ b/src/frame.c       2012-06-19 06:49:50 +0000
@@ -630,8 +630,8 @@
        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 @@
 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 @@
          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 @@
 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 @@
   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 @@
 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 @@
   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 @@
 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)

=== modified file 'src/term.c'
--- a/src/term.c        2012-06-16 12:24:15 +0000
+++ b/src/term.c        2012-06-19 06:49:50 +0000
@@ -2132,7 +2132,7 @@
 
 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 @@
 
 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 @@
 
 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 @@
   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 @@
   defsubr (&Stty_no_underline);
   defsubr (&Stty_type);
   defsubr (&Scontrolling_tty_p);
+  defsubr (&Stty_top_frame);
   defsubr (&Ssuspend_tty);
   defsubr (&Sresume_tty);
 #ifdef HAVE_GPM

=== modified file 'src/xdisp.c'
--- a/src/xdisp.c       2012-06-17 10:11:39 +0000
+++ b/src/xdisp.c       2012-06-19 06:49:50 +0000
@@ -8356,9 +8356,9 @@
                          /* 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 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 @@
   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 @@
     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 @@
 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 @@
   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 @@
                             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 @@
         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 @@
     }
 }
 
-#endif /* not HAVE_WINDOW_SYSTEM */
-
-
-
 
 /***********************************************************************
                              Menu Bars
@@ -11038,7 +11063,6 @@
   /* 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 @@
            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 @@
   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 @@
      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);


reply via email to

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