]> code.delx.au - gnu-emacs/blobdiff - src/window.c
Port USE_STACK_LISP_OBJECTS fix to Clang
[gnu-emacs] / src / window.c
index 461bb627df768b9b8322783dbde35ca47a88b5c3..8953d3cec00299c9bd2db6ce6b28b888a0ffa04d 100644 (file)
@@ -1,6 +1,6 @@
 /* Window creation, deletion and examination for GNU Emacs.
    Does not include redisplay.
 /* Window creation, deletion and examination for GNU Emacs.
    Does not include redisplay.
-   Copyright (C) 1985-1987, 1993-1998, 2000-2015 Free Software
+   Copyright (C) 1985-1987, 1993-1998, 2000-2016 Free Software
    Foundation, Inc.
 
 This file is part of GNU Emacs.
    Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -23,11 +23,9 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <stdio.h>
 
 #include "lisp.h"
 #include <stdio.h>
 
 #include "lisp.h"
-#include "character.h"
 #include "buffer.h"
 #include "keyboard.h"
 #include "keymap.h"
 #include "buffer.h"
 #include "keyboard.h"
 #include "keymap.h"
-#include "menu.h"
 #include "frame.h"
 #include "window.h"
 #include "commands.h"
 #include "frame.h"
 #include "window.h"
 #include "commands.h"
@@ -36,8 +34,8 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "disptab.h"
 #include "dispextern.h"
 #include "blockinput.h"
 #include "disptab.h"
 #include "dispextern.h"
 #include "blockinput.h"
-#include "intervals.h"
 #include "termhooks.h"         /* For FRAME_TERMINAL.  */
 #include "termhooks.h"         /* For FRAME_TERMINAL.  */
+#include "xwidget.h"
 #ifdef HAVE_WINDOW_SYSTEM
 #include TERM_HEADER
 #endif /* HAVE_WINDOW_SYSTEM */
 #ifdef HAVE_WINDOW_SYSTEM
 #include TERM_HEADER
 #endif /* HAVE_WINDOW_SYSTEM */
@@ -208,6 +206,20 @@ wset_combination (struct window *w, bool horflag, Lisp_Object val)
     w->horizontal = horflag;
 }
 
     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 x_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.  */
 
 /* True if leaf window W doesn't reflect the actual state
    of displayed buffer due to its text or overlays change.  */
 
@@ -641,7 +653,7 @@ DEFUN ("window-combination-limit", Fwindow_combination_limit, Swindow_combinatio
 WINDOW must be a valid window used in horizontal or vertical combination.
 If the return value is nil, child windows of WINDOW can be recombined with
 WINDOW's siblings.  A return value of t means that child windows of
 WINDOW must be a valid window used in horizontal or vertical combination.
 If the return value is nil, child windows of WINDOW can be recombined with
 WINDOW's siblings.  A return value of t means that child windows of
-WINDOW are never \(re-)combined with WINDOW's siblings.  */)
+WINDOW are never (re-)combined with WINDOW's siblings.  */)
   (Lisp_Object window)
 {
   struct window *w;
   (Lisp_Object window)
 {
   struct window *w;
@@ -658,7 +670,7 @@ DEFUN ("set-window-combination-limit", Fset_window_combination_limit, Sset_windo
 WINDOW must be a valid window used in horizontal or vertical combination.
 If LIMIT is nil, child windows of WINDOW can be recombined with WINDOW's
 siblings.  LIMIT t means that child windows of WINDOW are never
 WINDOW must be a valid window used in horizontal or vertical combination.
 If LIMIT is nil, child windows of WINDOW can be recombined with WINDOW's
 siblings.  LIMIT t means that child windows of WINDOW are never
-\(re-)combined with WINDOW's siblings.  Other values are reserved for
+(re-)combined with WINDOW's siblings.  Other values are reserved for
 future use.  */)
   (Lisp_Object window, Lisp_Object limit)
 {
 future use.  */)
   (Lisp_Object window, Lisp_Object limit)
 {
@@ -1101,186 +1113,6 @@ end-trigger value is reset to nil.  */)
   return value;
 }
 
   return value;
 }
 
-DEFUN ("window-edges", Fwindow_edges, Swindow_edges, 0, 1, 0,
-       doc: /* Return a list of the edge coordinates of WINDOW.
-WINDOW must be a valid window and defaults to the selected one.
-
-The returned list has the form (LEFT TOP RIGHT BOTTOM).  TOP and BOTTOM
-count by lines, and LEFT and RIGHT count by columns, all relative to 0,
-0 at top left corner of frame.
-
-RIGHT is one more than the rightmost column occupied by WINDOW.  BOTTOM
-is one more than the bottommost row occupied by WINDOW.  The edges
-include the space used by WINDOW's scroll bar, display margins, fringes,
-header line, and/or mode line.  For the edges of just the text area, use
-`window-inside-edges'.  */)
-  (Lisp_Object window)
-{
-  register struct window *w = decode_valid_window (window);
-
-  return list4i (WINDOW_LEFT_EDGE_COL (w), WINDOW_TOP_EDGE_LINE (w),
-                WINDOW_RIGHT_EDGE_COL (w), WINDOW_BOTTOM_EDGE_LINE (w));
-}
-
-DEFUN ("window-pixel-edges", Fwindow_pixel_edges, Swindow_pixel_edges, 0, 1, 0,
-       doc: /* Return a list of the edge pixel coordinates of WINDOW.
-WINDOW must be a valid window and defaults to the selected one.
-
-The returned list has the form (LEFT TOP RIGHT BOTTOM), all relative to
-0, 0 at the top left corner of the frame.
-
-RIGHT is one more than the rightmost x position occupied by WINDOW.
-BOTTOM is one more than the bottommost y position occupied by WINDOW.
-The pixel edges include the space used by WINDOW's scroll bar, display
-margins, fringes, header line, and/or mode line.  For the pixel edges
-of just the text area, use `window-inside-pixel-edges'.  */)
-  (Lisp_Object window)
-{
-  register struct window *w = decode_valid_window (window);
-
-  return list4i (WINDOW_LEFT_EDGE_X (w), WINDOW_TOP_EDGE_Y (w),
-                WINDOW_RIGHT_EDGE_X (w), WINDOW_BOTTOM_EDGE_Y (w));
-}
-
-static void
-calc_absolute_offset (struct window *w, int *add_x, int *add_y)
-{
-  struct frame *f = XFRAME (w->frame);
-  *add_y = f->top_pos;
-#ifdef FRAME_MENUBAR_HEIGHT
-  *add_y += FRAME_MENUBAR_HEIGHT (f);
-#endif
-#ifdef FRAME_TOOLBAR_TOP_HEIGHT
-  *add_y += FRAME_TOOLBAR_TOP_HEIGHT (f);
-#elif defined (FRAME_TOOLBAR_HEIGHT)
-  *add_y += FRAME_TOOLBAR_HEIGHT (f);
-#endif
-#ifdef FRAME_NS_TITLEBAR_HEIGHT
-  *add_y += FRAME_NS_TITLEBAR_HEIGHT (f);
-#endif
-  *add_x = f->left_pos;
-#ifdef FRAME_TOOLBAR_LEFT_WIDTH
-  *add_x += FRAME_TOOLBAR_LEFT_WIDTH (f);
-#endif
-}
-
-DEFUN ("window-absolute-pixel-edges", Fwindow_absolute_pixel_edges,
-       Swindow_absolute_pixel_edges, 0, 1, 0,
-       doc: /* Return a list of the edge pixel coordinates of WINDOW.
-WINDOW must be a valid window and defaults to the selected one.
-
-The returned list has the form (LEFT TOP RIGHT BOTTOM), all relative to
-0, 0 at the top left corner of the display.
-
-RIGHT is one more than the rightmost x position occupied by WINDOW.
-BOTTOM is one more than the bottommost y position occupied by WINDOW.
-The pixel edges include the space used by WINDOW's scroll bar, display
-margins, fringes, header line, and/or mode line.  For the pixel edges
-of just the text area, use `window-inside-absolute-pixel-edges'.  */)
-  (Lisp_Object window)
-{
-  register struct window *w = decode_valid_window (window);
-  int add_x, add_y;
-
-  calc_absolute_offset (w, &add_x, &add_y);
-
-  return list4i (WINDOW_LEFT_EDGE_X (w) + add_x,
-                WINDOW_TOP_EDGE_Y (w) + add_y,
-                WINDOW_RIGHT_EDGE_X (w) + add_x,
-                WINDOW_BOTTOM_EDGE_Y (w) + add_y);
-}
-
-DEFUN ("window-inside-edges", Fwindow_inside_edges, Swindow_inside_edges, 0, 1, 0,
-       doc: /* Return a list of the edge coordinates of WINDOW.
-WINDOW must be a live window and defaults to the selected one.
-
-The returned list has the form (LEFT TOP RIGHT BOTTOM).  TOP and BOTTOM
-count by lines, and LEFT and RIGHT count by columns, all relative to 0,
-0 at top left corner of frame.
-
-RIGHT is one more than the rightmost column of WINDOW's text area.
-BOTTOM is one more than the bottommost row of WINDOW's text area.  The
-inside edges do not include the space used by the WINDOW's scroll bar,
-display margins, fringes, header line, and/or mode line.  */)
-  (Lisp_Object window)
-{
-  register struct window *w = decode_live_window (window);
-
-  return list4i ((WINDOW_BOX_LEFT_EDGE_COL (w)
-                 + WINDOW_LEFT_MARGIN_COLS (w)
-                 + ((WINDOW_LEFT_FRINGE_WIDTH (w)
-                     + WINDOW_FRAME_COLUMN_WIDTH (w) - 1)
-                    / WINDOW_FRAME_COLUMN_WIDTH (w))),
-                (WINDOW_TOP_EDGE_LINE (w)
-                 + WINDOW_HEADER_LINE_LINES (w)),
-                (WINDOW_BOX_RIGHT_EDGE_COL (w)
-                 - WINDOW_RIGHT_MARGIN_COLS (w)
-                 - ((WINDOW_RIGHT_FRINGE_WIDTH (w)
-                     + WINDOW_FRAME_COLUMN_WIDTH (w) - 1)
-                    / WINDOW_FRAME_COLUMN_WIDTH (w))),
-                (WINDOW_BOTTOM_EDGE_LINE (w)
-                 - WINDOW_MODE_LINE_LINES (w)));
-}
-
-DEFUN ("window-inside-pixel-edges", Fwindow_inside_pixel_edges, Swindow_inside_pixel_edges, 0, 1, 0,
-       doc: /* Return a list of the edge pixel coordinates of WINDOW's text area.
-WINDOW must be a live window and defaults to the selected one.
-
-The returned list has the form (LEFT TOP RIGHT BOTTOM), all relative to
-(0,0) at the top left corner of the frame's window area.
-
-RIGHT is one more than the rightmost x position of WINDOW's text area.
-BOTTOM is one more than the bottommost y position of WINDOW's text area.
-The inside edges do not include the space used by WINDOW's scroll bar,
-display margins, fringes, header line, and/or mode line.  */)
-  (Lisp_Object window)
-{
-  register struct window *w = decode_live_window (window);
-
-  return list4i ((WINDOW_BOX_LEFT_EDGE_X (w)
-                 + WINDOW_LEFT_MARGIN_WIDTH (w)
-                 + WINDOW_LEFT_FRINGE_WIDTH (w)),
-                (WINDOW_TOP_EDGE_Y (w)
-                 + WINDOW_HEADER_LINE_HEIGHT (w)),
-                (WINDOW_BOX_RIGHT_EDGE_X (w)
-                 - WINDOW_RIGHT_MARGIN_WIDTH (w)
-                 - WINDOW_RIGHT_FRINGE_WIDTH (w)),
-                (WINDOW_BOTTOM_EDGE_Y (w)
-                 - WINDOW_MODE_LINE_HEIGHT (w)));
-}
-
-DEFUN ("window-inside-absolute-pixel-edges",
-       Fwindow_inside_absolute_pixel_edges,
-       Swindow_inside_absolute_pixel_edges, 0, 1, 0,
-       doc: /* Return a list of the edge pixel coordinates of WINDOW's text area.
-WINDOW must be a live window and defaults to the selected one.
-
-The returned list has the form (LEFT TOP RIGHT BOTTOM), all relative to
-(0,0) at the top left corner of the frame's window area.
-
-RIGHT is one more than the rightmost x position of WINDOW's text area.
-BOTTOM is one more than the bottommost y position of WINDOW's text area.
-The inside edges do not include the space used by WINDOW's scroll bar,
-display margins, fringes, header line, and/or mode line.  */)
-  (Lisp_Object window)
-{
-  register struct window *w = decode_live_window (window);
-  int add_x, add_y;
-
-  calc_absolute_offset (w, &add_x, &add_y);
-
-  return list4i ((WINDOW_BOX_LEFT_EDGE_X (w)
-                 + WINDOW_LEFT_MARGIN_WIDTH (w)
-                 + WINDOW_LEFT_FRINGE_WIDTH (w) + add_x),
-                (WINDOW_TOP_EDGE_Y (w)
-                 + WINDOW_HEADER_LINE_HEIGHT (w) + add_y),
-                (WINDOW_BOX_RIGHT_EDGE_X (w)
-                 - WINDOW_RIGHT_MARGIN_WIDTH (w)
-                 - WINDOW_RIGHT_FRINGE_WIDTH (w) + add_x),
-                (WINDOW_BOTTOM_EDGE_Y (w)
-                 - WINDOW_MODE_LINE_HEIGHT (w) + add_y));
-}
-
 /* Test if the character at column X, row Y is within window W.
    If it is not, return ON_NOTHING;
    if it is on the window's vertical divider, return
 /* Test if the character at column X, row Y is within window W.
    If it is not, return ON_NOTHING;
    if it is on the window's vertical divider, return
@@ -1471,10 +1303,18 @@ window_relative_x_coord (struct window *w, enum window_part part, int x)
              + window_box_width (w, RIGHT_MARGIN_AREA)
              + ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
                 ? WINDOW_RIGHT_FRINGE_WIDTH (w) : 0));
              + window_box_width (w, RIGHT_MARGIN_AREA)
              + ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
                 ? WINDOW_RIGHT_FRINGE_WIDTH (w) : 0));
-    }
 
 
-  /* ON_SCROLL_BAR, ON_NOTHING, and ON_VERTICAL_BORDER:  */
-  return 0;
+    case ON_NOTHING:
+    case ON_VERTICAL_BORDER:
+    case ON_VERTICAL_SCROLL_BAR:
+    case ON_HORIZONTAL_SCROLL_BAR:
+    case ON_RIGHT_DIVIDER:
+    case ON_BOTTOM_DIVIDER:
+      return 0;
+
+    default:
+      emacs_abort ();
+    }
 }
 
 
 }
 
 
@@ -1484,7 +1324,7 @@ DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
 WINDOW must be a live window and defaults to the selected one.
 COORDINATES is a cons of the form (X . Y), X and Y being distances
 measured in characters from the upper-left corner of the frame.
 WINDOW must be a live window and defaults to the selected one.
 COORDINATES is a cons of the form (X . Y), X and Y being distances
 measured in characters from the upper-left corner of the frame.
-\(0 . 0) denotes the character in the upper left corner of the
+(0 . 0) denotes the character in the upper left corner of the
 frame.
 If COORDINATES are in the text portion of WINDOW,
    the coordinates relative to the window are returned.
 frame.
 If COORDINATES are in the text portion of WINDOW,
    the coordinates relative to the window are returned.
@@ -1748,7 +1588,11 @@ if it isn't already recorded.  */)
          || b->clip_changed
          || b->prevent_redisplay_optimizations_p
          || window_outdated (w))
          || b->clip_changed
          || b->prevent_redisplay_optimizations_p
          || window_outdated (w))
-      && !noninteractive)
+      /* Don't call display routines if we didn't yet create any real
+        frames, because the glyph matrices are not yet allocated in
+        that case.  This could happen in some code that runs in the
+        daemon during initialization (e.g., see bug#20565).  */
+      && !(noninteractive || FRAME_INITIAL_P (WINDOW_XFRAME (w))))
     {
       struct text_pos startp;
       struct it it;
     {
       struct text_pos startp;
       struct it it;
@@ -1837,7 +1681,7 @@ overriding motion of point in order to display at this exact start.  */)
   w->start_at_line_beg = false;
   if (NILP (noforce))
     w->force_start = true;
   w->start_at_line_beg = false;
   if (NILP (noforce))
     w->force_start = true;
-  w->update_mode_line = true;
+  wset_update_mode_line (w);
   /* Bug#15957.  */
   w->window_end_valid = false;
   wset_redisplay (w);
   /* Bug#15957.  */
   w->window_end_valid = false;
   wset_redisplay (w);
@@ -1854,8 +1698,10 @@ Return nil if that position is scrolled vertically out of view.  If a
 character is only partially visible, nil is returned, unless the
 optional argument PARTIALLY is non-nil.  If POS is only out of view
 because of horizontal scrolling, return non-nil.  If POS is t, it
 character is only partially visible, nil is returned, unless the
 optional argument PARTIALLY is non-nil.  If POS is only out of view
 because of horizontal scrolling, return non-nil.  If POS is t, it
-specifies the position of the last visible glyph in WINDOW.  POS
-defaults to point in WINDOW; WINDOW defaults to the selected window.
+specifies either the first position displayed on the last visible
+screen line in WINDOW, or the end-of-buffer position, whichever comes
+first.  POS defaults to point in WINDOW; WINDOW defaults to the
+selected window.
 
 If POS is visible, return t if PARTIALLY is nil; if PARTIALLY is non-nil,
 the return value is a list of 2 or 6 elements (X Y [RTOP RBOT ROWH VPOS]),
 
 If POS is visible, return t if PARTIALLY is nil; if PARTIALLY is non-nil,
 the return value is a list of 2 or 6 elements (X Y [RTOP RBOT ROWH VPOS]),
@@ -1864,7 +1710,7 @@ of the window.  The remaining elements are omitted if the character after
 POS is fully visible; otherwise, RTOP and RBOT are the number of pixels
 off-window at the top and bottom of the screen line ("row") containing
 POS, ROWH is the visible height of that row, and VPOS is the row number
 POS is fully visible; otherwise, RTOP and RBOT are the number of pixels
 off-window at the top and bottom of the screen line ("row") containing
 POS, ROWH is the visible height of that row, and VPOS is the row number
-\(zero-based).  */)
+(zero-based).  */)
   (Lisp_Object pos, Lisp_Object window, Lisp_Object partially)
 {
   struct window *w;
   (Lisp_Object pos, Lisp_Object window, Lisp_Object partially)
 {
   struct window *w;
@@ -2809,7 +2655,6 @@ window_loop (enum window_loop type, Lisp_Object obj, bool mini,
   Lisp_Object window, windows, best_window, frame_arg;
   bool frame_best_window_flag = false;
   struct frame *f;
   Lisp_Object window, windows, best_window, frame_arg;
   bool frame_best_window_flag = false;
   struct frame *f;
-  struct gcpro gcpro1;
 
   /* If we're only looping through windows on a particular frame,
      frame points to that frame.  If we're looping through windows
 
   /* If we're only looping through windows on a particular frame,
      frame points to that frame.  If we're looping through windows
@@ -2843,7 +2688,6 @@ window_loop (enum window_loop type, Lisp_Object obj, bool mini,
     window = FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
 
   windows = window_list_1 (window, mini ? Qt : Qnil, frame_arg);
     window = FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
 
   windows = window_list_1 (window, mini ? Qt : Qnil, frame_arg);
-  GCPRO1 (windows);
   best_window = Qnil;
 
   for (; CONSP (windows); windows = XCDR (windows))
   best_window = Qnil;
 
   for (; CONSP (windows); windows = XCDR (windows))
@@ -2871,7 +2715,7 @@ window_loop (enum window_loop type, Lisp_Object obj, bool mini,
              {
                if (EQ (window, selected_window))
                  /* Preferably return the selected window.  */
              {
                if (EQ (window, selected_window))
                  /* Preferably return the selected window.  */
-                 RETURN_UNGCPRO (window);
+                 return window;
                else if (EQ (XWINDOW (window)->frame, selected_frame)
                         && !frame_best_window_flag)
                  /* Prefer windows on the current frame (but don't
                else if (EQ (XWINDOW (window)->frame, selected_frame)
                         && !frame_best_window_flag)
                  /* Prefer windows on the current frame (but don't
@@ -2937,7 +2781,6 @@ window_loop (enum window_loop type, Lisp_Object obj, bool mini,
          }
     }
 
          }
     }
 
-  UNGCPRO;
   return best_window;
 }
 
   return best_window;
 }
 
@@ -3443,7 +3286,8 @@ set_window_buffer (Lisp_Object window, Lisp_Object buffer,
   /* Maybe we could move this into the `if' but it's not obviously safe and
      I doubt it's worth the trouble.  */
   wset_redisplay (w);
   /* Maybe we could move this into the `if' but it's not obviously safe and
      I doubt it's worth the trouble.  */
   wset_redisplay (w);
-  w->update_mode_line = true;
+
+  wset_update_mode_line (w);
 
   /* We must select BUFFER to run the window-scroll-functions and to look up
      the buffer-local value of Vwindow_point_insertion_type.  */
 
   /* We must select BUFFER to run the window-scroll-functions and to look up
      the buffer-local value of Vwindow_point_insertion_type.  */
@@ -4127,9 +3971,11 @@ values.  */)
 }
 
 
 }
 
 
-/* Resize frame F's windows when number of lines of F is set to SIZE.
-   HORFLAG means resize windows when number of columns of F is set to
-   SIZE.  PIXELWISE means to interpret SIZE as pixels.  */
+/* Resize frame F's windows when F's width or height is set to SIZE.
+   If HORFLAG is zero, F's width was set to SIZE, otherwise its height
+   was set.  SIZE is interpreted in F's canonical character units
+   (a.k.a. "columns" or "lines"), unless PIXELWISE is non-zero, which
+   means to interpret SIZE in pixel units.  */
 void
 resize_frame_windows (struct frame *f, int size, bool horflag, bool pixelwise)
 {
 void
 resize_frame_windows (struct frame *f, int size, bool horflag, bool pixelwise)
 {
@@ -4140,7 +3986,6 @@ resize_frame_windows (struct frame *f, int size, bool horflag, bool pixelwise)
   /* old_size is the old size of the frame's root window.  */
   int old_size = horflag ? r->total_cols : r->total_lines;
   int old_pixel_size = horflag ? r->pixel_width : r->pixel_height;
   /* old_size is the old size of the frame's root window.  */
   int old_size = horflag ? r->total_cols : r->total_lines;
   int old_pixel_size = horflag ? r->pixel_width : r->pixel_height;
-  int old_pixel_top = r->pixel_top;
   /* new_size is the new size of the frame's root window.  */
   int new_size, new_pixel_size;
   int unit = horflag ? FRAME_COLUMN_WIDTH (f) : FRAME_LINE_HEIGHT (f);
   /* new_size is the new size of the frame's root window.  */
   int new_size, new_pixel_size;
   int unit = horflag ? FRAME_COLUMN_WIDTH (f) : FRAME_LINE_HEIGHT (f);
@@ -4170,11 +4015,8 @@ resize_frame_windows (struct frame *f, int size, bool horflag, bool pixelwise)
       new_pixel_size = new_size * unit;
     }
 
       new_pixel_size = new_size * unit;
     }
 
-  r->top_line = FRAME_TOP_MARGIN (f);
-  r->pixel_top = FRAME_TOP_MARGIN_HEIGHT (f);
-
   if (new_pixel_size == old_pixel_size
   if (new_pixel_size == old_pixel_size
-      && r->pixel_top == old_pixel_top)
+      && (horflag || r->pixel_top == FRAME_TOP_MARGIN_HEIGHT (f)))
     ;
   else if (WINDOW_LEAF_P (r))
     /* For a leaf root window just set the size.  */
     ;
   else if (WINDOW_LEAF_P (r))
     /* For a leaf root window just set the size.  */
@@ -4185,6 +4027,9 @@ resize_frame_windows (struct frame *f, int size, bool horflag, bool pixelwise)
       }
     else
       {
       }
     else
       {
+       r->top_line = FRAME_TOP_MARGIN (f);
+       r->pixel_top = FRAME_TOP_MARGIN_HEIGHT (f);
+
        r->total_lines = new_size;
        r->pixel_height = new_pixel_size;
       }
        r->total_lines = new_size;
        r->pixel_height = new_pixel_size;
       }
@@ -4192,6 +4037,12 @@ resize_frame_windows (struct frame *f, int size, bool horflag, bool pixelwise)
     {
       Lisp_Object delta;
 
     {
       Lisp_Object delta;
 
+      if (!horflag)
+       {
+         r->top_line = FRAME_TOP_MARGIN (f);
+         r->pixel_top = FRAME_TOP_MARGIN_HEIGHT (f);
+       }
+
       if (pixelwise)
        XSETINT (delta, new_pixel_size - old_pixel_size);
       else
       if (pixelwise)
        XSETINT (delta, new_pixel_size - old_pixel_size);
       else
@@ -4216,37 +4067,6 @@ resize_frame_windows (struct frame *f, int size, bool horflag, bool pixelwise)
            {
              window_resize_apply (r, horflag);
              window_pixel_to_total (r->frame, horflag ? Qt : Qnil);
            {
              window_resize_apply (r, horflag);
              window_pixel_to_total (r->frame, horflag ? Qt : Qnil);
-#if false /* Let's try without safe sizes and/or killing other windows.  */
-           }
-         else
-           {
-             /* Finally, try with "safe" minimum sizes.  */
-             resize_root_window (root, delta, horflag ? Qt : Qnil, Qsafe,
-                                 pixelwise ? Qt : Qnil);
-             if (window_resize_check (r, horflag)
-                 && new_pixel_size == XINT (r->new_pixel))
-               {
-                 window_resize_apply (r, horflag);
-                 window_pixel_to_total (r->frame, horflag ? Qt : Qnil);
-               }
-             else
-               {
-                 /* We lost.  Delete all windows but the frame's
-                    selected one.  */
-                 root = f->selected_window;
-                 Fdelete_other_windows_internal (root, Qnil);
-                 if (horflag)
-                   {
-                     XWINDOW (root)->total_cols = new_size;
-                     XWINDOW (root)->pixel_width = new_pixel_size;
-                   }
-                 else
-                   {
-                     XWINDOW (root)->total_lines = new_size;
-                     XWINDOW (root)->pixel_height = new_pixel_size;
-                   }
-               }
-#endif /* false */
            }
        }
     }
            }
        }
     }
@@ -4256,7 +4076,7 @@ resize_frame_windows (struct frame *f, int size, bool horflag, bool pixelwise)
       m = XWINDOW (mini);
       if (horflag)
        {
       m = XWINDOW (mini);
       if (horflag)
        {
-         m->total_cols = size;
+         m->total_cols = new_size;
          m->pixel_width = new_pixel_size;
        }
       else
          m->pixel_width = new_pixel_size;
        }
       else
@@ -4269,6 +4089,7 @@ resize_frame_windows (struct frame *f, int size, bool horflag, bool pixelwise)
        }
     }
 
        }
     }
 
+  FRAME_WINDOW_SIZES_CHANGED (f) = true;
   fset_redisplay (f);
 }
 
   fset_redisplay (f);
 }
 
@@ -4550,6 +4371,7 @@ Signal an error when WINDOW is the only window on its frame.  */)
 
       /* Block input.  */
       block_input ();
 
       /* Block input.  */
       block_input ();
+      xwidget_view_delete_all_in_window (w);
       window_resize_apply (p, horflag);
       /* If this window is referred to by the dpyinfo's mouse
         highlight, invalidate that slot to be safe (Bug#9904).  */
       window_resize_apply (p, horflag);
       /* If this window is referred to by the dpyinfo's mouse
         highlight, invalidate that slot to be safe (Bug#9904).  */
@@ -4707,6 +4529,7 @@ grow_mini_window (struct window *w, int delta, bool pixelwise)
          /* Enforce full redisplay of the frame.  */
          /* FIXME: Shouldn't window--resize-root-window-vertically do it?  */
          fset_redisplay (f);
          /* Enforce full redisplay of the frame.  */
          /* FIXME: Shouldn't window--resize-root-window-vertically do it?  */
          fset_redisplay (f);
+         FRAME_WINDOW_SIZES_CHANGED (f) = true;
          adjust_frame_glyphs (f);
          unblock_input ();
        }
          adjust_frame_glyphs (f);
          unblock_input ();
        }
@@ -4746,6 +4569,7 @@ shrink_mini_window (struct window *w, bool pixelwise)
          /* Enforce full redisplay of the frame.  */
          /* FIXME: Shouldn't window--resize-root-window-vertically do it?  */
          fset_redisplay (f);
          /* Enforce full redisplay of the frame.  */
          /* FIXME: Shouldn't window--resize-root-window-vertically do it?  */
          fset_redisplay (f);
+         FRAME_WINDOW_SIZES_CHANGED (f) = true;
          adjust_frame_glyphs (f);
          unblock_input ();
        }
          adjust_frame_glyphs (f);
          unblock_input ();
        }
@@ -4989,7 +4813,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, bool noerror)
                  set_marker_restricted (w->start, make_number (spos),
                                         w->contents);
                  w->start_at_line_beg = true;
                  set_marker_restricted (w->start, make_number (spos),
                                         w->contents);
                  w->start_at_line_beg = true;
-                 w->update_mode_line = true;
+                 wset_update_mode_line (w);
                  /* Set force_start so that redisplay_window will run the
                     window-scroll-functions.  */
                  w->force_start = true;
                  /* Set force_start so that redisplay_window will run the
                     window-scroll-functions.  */
                  w->force_start = true;
@@ -5137,7 +4961,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, bool noerror)
                                  IT_BYTEPOS (it));
       bytepos = marker_byte_position (w->start);
       w->start_at_line_beg = (pos == BEGV || FETCH_BYTE (bytepos - 1) == '\n');
                                  IT_BYTEPOS (it));
       bytepos = marker_byte_position (w->start);
       w->start_at_line_beg = (pos == BEGV || FETCH_BYTE (bytepos - 1) == '\n');
-      w->update_mode_line = true;
+      wset_update_mode_line (w);
       /* Set force_start so that redisplay_window will run the
         window-scroll-functions.  */
       w->force_start = true;
       /* Set force_start so that redisplay_window will run the
         window-scroll-functions.  */
       w->force_start = true;
@@ -5159,27 +4983,34 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, bool noerror)
 
   if (n > 0)
     {
 
   if (n > 0)
     {
+      int last_y = it.last_visible_y - this_scroll_margin - 1;
+
       /* We moved the window start towards ZV, so PT may be now
         in the scroll margin at the top.  */
       move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
       /* We moved the window start towards ZV, so PT may be now
         in the scroll margin at the top.  */
       move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
-      if (IT_CHARPOS (it) == PT && it.current_y >= this_scroll_margin
+      if (IT_CHARPOS (it) == PT
+         && it.current_y >= this_scroll_margin
+         && it.current_y <= last_y - WINDOW_HEADER_LINE_HEIGHT (w)
           && (NILP (Vscroll_preserve_screen_position)
              || EQ (Vscroll_preserve_screen_position, Qt)))
        /* We found PT at a legitimate height.  Leave it alone.  */
        ;
           && (NILP (Vscroll_preserve_screen_position)
              || EQ (Vscroll_preserve_screen_position, Qt)))
        /* We found PT at a legitimate height.  Leave it alone.  */
        ;
-      else if (window_scroll_pixel_based_preserve_y >= 0)
-       {
-         /* If we have a header line, take account of it.
-            This is necessary because we set it.current_y to 0, above.  */
-         move_it_to (&it, -1,
-                     window_scroll_pixel_based_preserve_x,
-                     (window_scroll_pixel_based_preserve_y
-                      - WINDOW_WANTS_HEADER_LINE_P (w)),
-                     -1, MOVE_TO_Y | MOVE_TO_X);
-         SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
-       }
       else
        {
       else
        {
+         if (window_scroll_pixel_based_preserve_y >= 0)
+           {
+             /* Don't enter the scroll margin at the end of the window.  */
+             int goal_y = min (last_y, window_scroll_pixel_based_preserve_y);
+
+             /* If we have a header line, take account of it.  This
+                is necessary because we set it.current_y to 0, above.  */
+             move_it_to (&it, -1,
+                         window_scroll_pixel_based_preserve_x,
+                         goal_y - WINDOW_HEADER_LINE_HEIGHT (w),
+                         -1, MOVE_TO_Y | MOVE_TO_X);
+           }
+
+         /* Get out of the scroll margin at the top of the window.  */
          while (it.current_y < this_scroll_margin)
            {
              int prev = it.current_y;
          while (it.current_y < this_scroll_margin)
            {
              int prev = it.current_y;
@@ -5203,7 +5034,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, bool noerror)
       /* We moved the window start towards BEGV, so PT may be now
         in the scroll margin at the bottom.  */
       move_it_to (&it, PT, -1,
       /* We moved the window start towards BEGV, so PT may be now
         in the scroll margin at the bottom.  */
       move_it_to (&it, PT, -1,
-                 (it.last_visible_y - CURRENT_HEADER_LINE_HEIGHT (w)
+                 (it.last_visible_y - WINDOW_HEADER_LINE_HEIGHT (w)
                   - this_scroll_margin - 1),
                  -1,
                  MOVE_TO_POS | MOVE_TO_Y);
                   - this_scroll_margin - 1),
                  -1,
                  MOVE_TO_POS | MOVE_TO_Y);
@@ -5254,14 +5085,20 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, bool noerror)
        ;
       else if (window_scroll_pixel_based_preserve_y >= 0)
        {
        ;
       else if (window_scroll_pixel_based_preserve_y >= 0)
        {
+         int goal_y = min (it.last_visible_y - this_scroll_margin - 1,
+                           window_scroll_pixel_based_preserve_y);
+
+         /* Don't let the preserved screen Y coordinate put us inside
+            any of the two margins.  */
+         if (goal_y < this_scroll_margin)
+           goal_y = this_scroll_margin;
          SET_TEXT_POS_FROM_MARKER (start, w->start);
          start_display (&it, w, start);
          /* It would be wrong to subtract CURRENT_HEADER_LINE_HEIGHT
             here because we called start_display again and did not
             alter it.current_y this time.  */
          move_it_to (&it, -1, window_scroll_pixel_based_preserve_x,
          SET_TEXT_POS_FROM_MARKER (start, w->start);
          start_display (&it, w, start);
          /* It would be wrong to subtract CURRENT_HEADER_LINE_HEIGHT
             here because we called start_display again and did not
             alter it.current_y this time.  */
          move_it_to (&it, -1, window_scroll_pixel_based_preserve_x,
-                     window_scroll_pixel_based_preserve_y, -1,
-                     MOVE_TO_Y | MOVE_TO_X);
+                     goal_y, -1, MOVE_TO_Y | MOVE_TO_X);
          SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
        }
       else
          SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
        }
       else
@@ -5371,12 +5208,13 @@ window_scroll_line_based (Lisp_Object window, int n, bool whole, bool noerror)
 
       set_marker_restricted_both (w->start, w->contents, pos, pos_byte);
       w->start_at_line_beg = !NILP (bolp);
 
       set_marker_restricted_both (w->start, w->contents, pos, pos_byte);
       w->start_at_line_beg = !NILP (bolp);
-      w->update_mode_line = true;
+      wset_update_mode_line (w);
       /* Set force_start so that redisplay_window will run
         the window-scroll-functions.  */
       w->force_start = true;
 
       if (!NILP (Vscroll_preserve_screen_position)
       /* Set force_start so that redisplay_window will run
         the window-scroll-functions.  */
       w->force_start = true;
 
       if (!NILP (Vscroll_preserve_screen_position)
+         && this_scroll_margin == 0
          && (whole || !EQ (Vscroll_preserve_screen_position, Qt)))
        {
          SET_PT_BOTH (pos, pos_byte);
          && (whole || !EQ (Vscroll_preserve_screen_position, Qt)))
        {
          SET_PT_BOTH (pos, pos_byte);
@@ -5402,8 +5240,16 @@ window_scroll_line_based (Lisp_Object window, int n, bool whole, bool noerror)
                         marker_byte_position (opoint_marker));
          else if (!NILP (Vscroll_preserve_screen_position))
            {
                         marker_byte_position (opoint_marker));
          else if (!NILP (Vscroll_preserve_screen_position))
            {
+             int nlines = window_scroll_preserve_vpos;
+
              SET_PT_BOTH (pos, pos_byte);
              SET_PT_BOTH (pos, pos_byte);
-             Fvertical_motion (original_pos, window, Qnil);
+             if (window_scroll_preserve_vpos < this_scroll_margin)
+               nlines = this_scroll_margin;
+             else if (window_scroll_preserve_vpos
+                      >= w->total_lines - this_scroll_margin)
+               nlines = w->total_lines - this_scroll_margin - 1;
+             Fvertical_motion (Fcons (make_number (window_scroll_preserve_hpos),
+                                      make_number (nlines)), window, Qnil);
            }
          else
            SET_PT (top_margin);
            }
          else
            SET_PT (top_margin);
@@ -5429,8 +5275,16 @@ window_scroll_line_based (Lisp_Object window, int n, bool whole, bool noerror)
            {
              if (!NILP (Vscroll_preserve_screen_position))
                {
            {
              if (!NILP (Vscroll_preserve_screen_position))
                {
+                 int nlines = window_scroll_preserve_vpos;
+
                  SET_PT_BOTH (pos, pos_byte);
                  SET_PT_BOTH (pos, pos_byte);
-                 Fvertical_motion (original_pos, window, Qnil);
+                 if (window_scroll_preserve_vpos < this_scroll_margin)
+                   nlines = this_scroll_margin;
+                 else if (window_scroll_preserve_vpos
+                          >= ht - this_scroll_margin)
+                   nlines = ht - this_scroll_margin - 1;
+                 Fvertical_motion (Fcons (make_number (window_scroll_preserve_hpos),
+                                          make_number (nlines)), window, Qnil);
                }
              else
                Fvertical_motion (make_number (-1), window, Qnil);
                }
              else
                Fvertical_motion (make_number (-1), window, Qnil);
@@ -6527,11 +6381,17 @@ delete_all_child_windows (Lisp_Object window)
 static ptrdiff_t
 count_windows (struct window *window)
 {
 static ptrdiff_t
 count_windows (struct window *window)
 {
-  return get_leaf_windows (window, NULL, 0);
+  ptrdiff_t count = 1;
+  if (!NILP (window->next))
+    count += count_windows (XWINDOW (window->next));
+  if (WINDOWP (window->contents))
+    count += count_windows (XWINDOW (window->contents));
+  return count;
 }
 
 }
 
-/* If vector FLAT is non-null, fill it with leaf windows under W,
-   starting at index I.  Value is last index + 1.  */
+
+/* Fill vector FLAT with leaf windows under W, starting at index I.
+   Value is last index + 1.  */
 static ptrdiff_t
 get_leaf_windows (struct window *w, struct window **flat, ptrdiff_t i)
 {
 static ptrdiff_t
 get_leaf_windows (struct window *w, struct window **flat, ptrdiff_t i)
 {
@@ -6540,11 +6400,7 @@ get_leaf_windows (struct window *w, struct window **flat, ptrdiff_t i)
       if (WINDOWP (w->contents))
        i = get_leaf_windows (XWINDOW (w->contents), flat, i);
       else
       if (WINDOWP (w->contents))
        i = get_leaf_windows (XWINDOW (w->contents), flat, i);
       else
-       {
-         if (flat)
-           flat[i] = w;
-         i++;
-       }
+       flat[i++] = w;
 
       w = NILP (w->next) ? 0 : XWINDOW (w->next);
     }
 
       w = NILP (w->next) ? 0 : XWINDOW (w->next);
     }
@@ -6776,7 +6632,6 @@ apply_window_adjustment (struct window *w)
   eassert (w);
   clear_glyph_matrix (w->current_matrix);
   w->window_end_valid = false;
   eassert (w);
   clear_glyph_matrix (w->current_matrix);
   w->window_end_valid = false;
-  windows_or_buffers_changed = 30;
   wset_redisplay (w);
   adjust_frame_glyphs (XFRAME (WINDOW_FRAME (w)));
 }
   wset_redisplay (w);
   adjust_frame_glyphs (XFRAME (WINDOW_FRAME (w)));
 }
@@ -7323,7 +7178,6 @@ syms_of_window (void)
   DEFSYM (Qwindow_size, "window-size");
   DEFSYM (Qtemp_buffer_show_hook, "temp-buffer-show-hook");
   DEFSYM (Qabove, "above");
   DEFSYM (Qwindow_size, "window-size");
   DEFSYM (Qtemp_buffer_show_hook, "temp-buffer-show-hook");
   DEFSYM (Qabove, "above");
-  DEFSYM (Qbelow, "below");
   DEFSYM (Qclone_of, "clone-of");
   DEFSYM (Qfloor, "floor");
   DEFSYM (Qceiling, "ceiling");
   DEFSYM (Qclone_of, "clone-of");
   DEFSYM (Qfloor, "floor");
   DEFSYM (Qceiling, "ceiling");
@@ -7409,7 +7263,7 @@ resizing a window preferably resizes one adjacent window only.
 
 If this variable is t, splitting a window tries to get the space
 proportionally from all windows in the same combination.  This also
 
 If this variable is t, splitting a window tries to get the space
 proportionally from all windows in the same combination.  This also
-allows to split a window that is otherwise too small or of fixed size.
+allows splitting a window that is otherwise too small or of fixed size.
 Resizing and deleting a window proportionally resize all windows in the
 same combination.
 
 Resizing and deleting a window proportionally resize all windows in the
 same combination.
 
@@ -7543,18 +7397,12 @@ displayed after a scrolling operation to be somewhat inaccurate.  */);
   defsubr (&Sset_window_hscroll);
   defsubr (&Swindow_redisplay_end_trigger);
   defsubr (&Sset_window_redisplay_end_trigger);
   defsubr (&Sset_window_hscroll);
   defsubr (&Swindow_redisplay_end_trigger);
   defsubr (&Sset_window_redisplay_end_trigger);
-  defsubr (&Swindow_edges);
-  defsubr (&Swindow_pixel_edges);
-  defsubr (&Swindow_absolute_pixel_edges);
   defsubr (&Swindow_mode_line_height);
   defsubr (&Swindow_header_line_height);
   defsubr (&Swindow_right_divider_width);
   defsubr (&Swindow_bottom_divider_width);
   defsubr (&Swindow_scroll_bar_width);
   defsubr (&Swindow_scroll_bar_height);
   defsubr (&Swindow_mode_line_height);
   defsubr (&Swindow_header_line_height);
   defsubr (&Swindow_right_divider_width);
   defsubr (&Swindow_bottom_divider_width);
   defsubr (&Swindow_scroll_bar_width);
   defsubr (&Swindow_scroll_bar_height);
-  defsubr (&Swindow_inside_edges);
-  defsubr (&Swindow_inside_pixel_edges);
-  defsubr (&Swindow_inside_absolute_pixel_edges);
   defsubr (&Scoordinates_in_window_p);
   defsubr (&Swindow_at);
   defsubr (&Swindow_point);
   defsubr (&Scoordinates_in_window_p);
   defsubr (&Swindow_at);
   defsubr (&Swindow_point);