Refine redisplay optimizations to only redisplay *some* frames/windows
[bpt/emacs.git] / src / window.c
index 560f31e..6c336f6 100644 (file)
@@ -20,8 +20,6 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <config.h>
 
-#define WINDOW_INLINE EXTERN_INLINE
-
 #include <stdio.h>
 
 #include "lisp.h"
@@ -39,19 +37,12 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "blockinput.h"
 #include "intervals.h"
 #include "termhooks.h"         /* For FRAME_TERMINAL.  */
-
-#ifdef HAVE_X_WINDOWS
-#include "xterm.h"
-#endif /* HAVE_X_WINDOWS */
-#ifdef HAVE_NTGUI
-#include "w32term.h"
-#endif
+#ifdef HAVE_WINDOW_SYSTEM
+#include TERM_HEADER
+#endif /* HAVE_WINDOW_SYSTEM */
 #ifdef MSDOS
 #include "msdos.h"
 #endif
-#ifdef HAVE_NS
-#include "nsterm.h"
-#endif
 
 Lisp_Object Qwindowp, Qwindow_live_p;
 static Lisp_Object Qwindow_valid_p;
@@ -69,7 +60,6 @@ static int get_leaf_windows (struct window *, struct window **, int);
 static void window_scroll (Lisp_Object, EMACS_INT, bool, int);
 static void window_scroll_pixel_based (Lisp_Object, int, bool, int);
 static void window_scroll_line_based (Lisp_Object, int, bool, int);
-static Lisp_Object window_list (void);
 static int add_window_to_list (struct window *, void *);
 static Lisp_Object next_window (Lisp_Object, Lisp_Object,
                                 Lisp_Object, int);
@@ -491,6 +481,12 @@ select_window (Lisp_Object window, Lisp_Object norecord, int inhibit_point_swap)
        record_buffer before returning here.  */
     goto record_and_return;
 
+  if (NILP (norecord))
+    /* Mark the window for redisplay since the selected-window has a different
+       mode-line.  */
+    wset_redisplay (XWINDOW (selected_window));
+  else
+    redisplay_other_windows ();
   sf = SELECTED_FRAME ();
   if (XFRAME (WINDOW_FRAME (w)) != sf)
     {
@@ -509,7 +505,8 @@ select_window (Lisp_Object window, Lisp_Object norecord, int inhibit_point_swap)
 
   select_window_1 (window, inhibit_point_swap);
   bset_last_selected_window (XBUFFER (w->contents), window);
-  windows_or_buffers_changed++;
+  if (NILP (norecord))
+    wset_redisplay (w);
 
  record_and_return:
   /* record_buffer can run QUIT, so make sure it is run only after we have
@@ -954,7 +951,7 @@ calc_absolute_offset (struct window *w, int *add_x, int *add_y)
 #endif
 #ifdef FRAME_TOOLBAR_TOP_HEIGHT
   *add_y += FRAME_TOOLBAR_TOP_HEIGHT (f);
-#elif FRAME_TOOLBAR_HEIGHT
+#elif defined (FRAME_TOOLBAR_HEIGHT)
   *add_y += FRAME_TOOLBAR_HEIGHT (f);
 #endif
 #ifdef FRAME_NS_TITLEBAR_HEIGHT
@@ -1386,6 +1383,7 @@ window_from_coordinates (struct frame *f, int x, int y,
   cw.window = &window, cw.x = x, cw.y = y; cw.part = part;
   foreach_window (f, check_window_containing, &cw);
 
+#if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
   /* If not found above, see if it's in the tool bar window, if a tool
      bar exists.  */
   if (NILP (window)
@@ -1398,6 +1396,7 @@ window_from_coordinates (struct frame *f, int x, int y,
       *part = ON_TEXT;
       window = f->tool_bar_window;
     }
+#endif
 
   return window;
 }
@@ -1494,7 +1493,6 @@ if it isn't already recorded.  */)
       && !noninteractive)
     {
       struct text_pos startp;
-      ptrdiff_t charpos = marker_position (w->start);
       struct it it;
       struct buffer *old_buffer = NULL;
       void *itdata = NULL;
@@ -1512,12 +1510,7 @@ if it isn't already recorded.  */)
          `-l' containing a call to `rmail' with subsequent other
          commands.  At the end, W->start happened to be BEG, while
          rmail had already narrowed the buffer.  */
-      if (charpos < BEGV)
-       SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
-      else if (charpos > ZV)
-       SET_TEXT_POS (startp, ZV, ZV_BYTE);
-      else
-       SET_TEXT_POS_FROM_MARKER (startp, w->start);
+      CLIP_TEXT_POS_FROM_MARKER (startp, w->start);
 
       itdata = bidi_shelve_cache ();
       start_display (&it, w, startp);
@@ -1566,7 +1559,7 @@ Return POS.  */)
       set_marker_restricted (w->pointm, pos, w->contents);
       /* We have to make sure that redisplay updates the window to show
         the new value of point.  */
-      ++windows_or_buffers_changed;
+      windows_or_buffers_changed = 25;
     }
 
   return pos;
@@ -1587,9 +1580,10 @@ overriding motion of point in order to display at this exact start.  */)
   if (NILP (noforce))
     w->force_start = 1;
   w->update_mode_line = 1;
+  /* Bug#15957.  */
+  w->window_end_valid = 0;
   if (w != XWINDOW (selected_window))
-    /* Enforce full redisplay.  FIXME: make it more selective.  */
-    windows_or_buffers_changed++;
+    wset_redisplay (w);
 
   return pos;
 }
@@ -2021,8 +2015,10 @@ replace_window (Lisp_Object old, Lisp_Object new, int setflag)
       memset (&n->cursor, 0, sizeof (n->cursor));
       memset (&n->phys_cursor, 0, sizeof (n->phys_cursor));
       n->last_cursor_vpos = 0;
-      n->phys_cursor_type = -1;
+#ifdef HAVE_WINDOW_SYSTEM
+      n->phys_cursor_type = NO_CURSOR;
       n->phys_cursor_width = -1;
+#endif
       n->must_be_updated_p = 0;
       n->pseudo_window_p = 0;
       n->window_end_vpos = 0;
@@ -2148,7 +2144,7 @@ add_window_to_list (struct window *w, void *user_data)
    Vwindow_list is a list, return that list.  Otherwise, build a new
    list, cache it in Vwindow_list, and return that.  */
 
-static Lisp_Object
+Lisp_Object
 window_list (void)
 {
   if (!CONSP (Vwindow_list))
@@ -2650,7 +2646,7 @@ window_loop (enum window_loop type, Lisp_Object obj, int mini, Lisp_Object frame
                mark_window_display_accurate (window, 0);
                w->update_mode_line = 1;
                XBUFFER (obj)->prevent_redisplay_optimizations_p = 1;
-               ++update_mode_lines;
+               update_mode_lines = 27;
                best_window = window;
              }
            break;
@@ -2848,7 +2844,7 @@ window-start value is reasonable when this function is called.  */)
     }
   free_window_matrices (r);
 
-  windows_or_buffers_changed++;
+  windows_or_buffers_changed = 27;
   Vwindow_list = Qnil;
   FRAME_WINDOW_SIZES_CHANGED (f) = 1;
   resize_failed = 0;
@@ -2958,7 +2954,7 @@ window-start value is reasonable when this function is called.  */)
        }
     }
 
-  adjust_glyphs (f);
+  adjust_frame_glyphs (f);
   unblock_input ();
 
   run_window_configuration_change_hook (f);
@@ -3182,7 +3178,7 @@ 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.  */
-  windows_or_buffers_changed++;
+  windows_or_buffers_changed = 28;
 
   /* We must select BUFFER for running the window-scroll-functions.  */
   /* We can't check ! NILP (Vwindow_scroll_functions) here
@@ -3289,8 +3285,8 @@ displaying that buffer.  */)
 {
   if (NILP (object))
     {
-      windows_or_buffers_changed++;
-      update_mode_lines++;
+      windows_or_buffers_changed = 29;
+      update_mode_lines = 28;
       return Qt;
     }
 
@@ -3301,7 +3297,7 @@ displaying that buffer.  */)
       w->update_mode_line = 1;
       if (BUFFERP (w->contents))
        XBUFFER (w->contents)->prevent_redisplay_optimizations_p = 1;
-      ++update_mode_lines;
+      update_mode_lines = 29;
       return Qt;
     }
 
@@ -3432,8 +3428,11 @@ make_window (void)
      non-Lisp data, so do it only for slots which should not be zero.  */
   w->nrows_scale_factor = w->ncols_scale_factor = 1;
   w->left_fringe_width = w->right_fringe_width = -1;
-  w->phys_cursor_type = -1;
+  w->mode_line_height = w->header_line_height = -1;
+#ifdef HAVE_WINDOW_SYSTEM
+  w->phys_cursor_type = NO_CURSOR;
   w->phys_cursor_width = -1;
+#endif
   w->scroll_bar_width = -1;
   w->column_number_displayed = -1;
 
@@ -3623,6 +3622,9 @@ window_resize_apply (struct window *w, bool horflag)
          c = NILP (c->next) ? 0 : XWINDOW (c->next);
        }
     }
+  else
+    /* Bug#15957.  */
+    w->window_end_valid = 0;
 }
 
 
@@ -3654,10 +3656,10 @@ be applied on the Elisp level.  */)
   block_input ();
   window_resize_apply (r, horflag);
 
-  windows_or_buffers_changed++;
+  windows_or_buffers_changed = 30;
   FRAME_WINDOW_SIZES_CHANGED (f) = 1;
 
-  adjust_glyphs (f);
+  adjust_frame_glyphs (f);
   unblock_input ();
 
   run_window_configuration_change_hook (f);
@@ -3749,7 +3751,7 @@ resize_frame_windows (struct frame *f, int size, bool horflag)
        }
     }
 
-  windows_or_buffers_changed++;
+  windows_or_buffers_changed = 31;
 }
 
 
@@ -3870,7 +3872,7 @@ set correctly.  See the code of `split-window' for how this is done.  */)
   else
     p = XWINDOW (o->parent);
 
-  windows_or_buffers_changed++;
+  windows_or_buffers_changed = 32;
   FRAME_WINDOW_SIZES_CHANGED (f) = 1;
   new = make_window ();
   n = XWINDOW (new);
@@ -3927,7 +3929,7 @@ set correctly.  See the code of `split-window' for how this is done.  */)
 
   block_input ();
   window_resize_apply (p, horflag);
-  adjust_glyphs (f);
+  adjust_frame_glyphs (f);
   /* Set buffer of NEW to buffer of reference window.  Don't run
      any hooks.  */
   set_window_buffer (new, r->contents, 0, 1);
@@ -4020,7 +4022,7 @@ Signal an error when WINDOW is the only window on its frame.  */)
            hlinfo->mouse_face_window = Qnil;
        }
 
-      windows_or_buffers_changed++;
+      windows_or_buffers_changed = 33;
       Vwindow_list = Qnil;
       FRAME_WINDOW_SIZES_CHANGED (f) = 1;
 
@@ -4056,7 +4058,7 @@ Signal an error when WINDOW is the only window on its frame.  */)
          recombine_windows (sibling);
        }
 
-      adjust_glyphs (f);
+      adjust_frame_glyphs (f);
 
       if (!WINDOW_LIVE_P (FRAME_SELECTED_WINDOW (f)))
        /* We deleted the frame's selected window.  */
@@ -4141,9 +4143,10 @@ grow_mini_window (struct window *w, int delta)
       /* Grow the mini-window.  */
       w->top_line = r->top_line + r->total_lines;
       w->total_lines -= XINT (value);
-      /* Enforce full redisplay.  FIXME: make it more selective.  */
-      windows_or_buffers_changed++;
-      adjust_glyphs (f);
+      /* Enforce full redisplay of the frame.  */
+      /* FIXME: Shouldn't window--resize-root-window-vertically do it?  */
+      fset_redisplay (f);
+      adjust_frame_glyphs (f);
       unblock_input ();
     }
 }
@@ -4175,9 +4178,10 @@ shrink_mini_window (struct window *w)
          /* Shrink the mini-window.  */
          w->top_line = r->top_line + r->total_lines;
          w->total_lines = 1;
-         /* Enforce full redisplay.  FIXME: make it more selective.  */
-         windows_or_buffers_changed++;
-         adjust_glyphs (f);
+         /* Enforce full redisplay of the frame.  */
+         /* FIXME: Shouldn't window--resize-root-window-vertically do it?  */
+         fset_redisplay (f);
+         adjust_frame_glyphs (f);
          unblock_input ();
        }
       /* If the above failed for whatever strange reason we must make a
@@ -4216,9 +4220,9 @@ DEFUN ("resize-mini-window-internal", Fresize_mini_window_internal, Sresize_mini
       w->total_lines = XFASTINT (w->new_total);
       w->top_line = r->top_line + r->total_lines;
 
-      windows_or_buffers_changed++;
+      windows_or_buffers_changed = 36;
       FRAME_WINDOW_SIZES_CHANGED (f) = 1;
-      adjust_glyphs (f);
+      adjust_frame_glyphs (f);
       unblock_input ();
 
       run_window_configuration_change_hook (f);
@@ -4294,6 +4298,8 @@ window_scroll (Lisp_Object window, EMACS_INT n, bool whole, int noerror)
   else
     window_scroll_line_based (window, n, whole, noerror);
 
+  /* Bug#15957.  */
+  XWINDOW (window)->window_end_valid = 0;
   immediate_quit = 0;
 }
 
@@ -4489,7 +4495,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, int noerror)
                 visible.  */
              w->vscroll = (it.last_visible_y
                            - it.current_y + it.max_ascent + it.max_descent);
-             adjust_glyphs (it.f);
+             adjust_frame_glyphs (it.f);
            }
          else
            {
@@ -4838,7 +4844,7 @@ scroll_command (Lisp_Object n, int direction)
       Fset_buffer (XWINDOW (selected_window)->contents);
 
       /* Make redisplay consider other windows than just selected_window.  */
-      ++windows_or_buffers_changed;
+      windows_or_buffers_changed = 37;
     }
 
   if (NILP (n))
@@ -4948,7 +4954,7 @@ specifies the window to scroll.  This takes precedence over
 
   /* Don't screw up if window_scroll gets an error.  */
   record_unwind_protect (save_excursion_restore, save_excursion_save ());
-  ++windows_or_buffers_changed;
+  windows_or_buffers_changed = 38;
 
   Fset_buffer (w->contents);
   SET_PT_BOTH (marker_position (w->pointm), marker_byte_position (w->pointm));
@@ -5038,7 +5044,6 @@ displayed_window_lines (struct window *w)
 {
   struct it it;
   struct text_pos start;
-  ptrdiff_t charpos = marker_position (w->start);
   int height = window_box_height (w);
   struct buffer *old_buffer;
   int bottom_y;
@@ -5055,12 +5060,7 @@ displayed_window_lines (struct window *w)
   /* In case W->start is out of the accessible range, do something
      reasonable.  This happens in Info mode when Info-scroll-down
      calls (recenter -1) while W->start is 1.  */
-  if (charpos < BEGV)
-    SET_TEXT_POS (start, BEGV, BEGV_BYTE);
-  else if (charpos > ZV)
-    SET_TEXT_POS (start, ZV, ZV_BYTE);
-  else
-    SET_TEXT_POS_FROM_MARKER (start, w->start);
+  CLIP_TEXT_POS_FROM_MARKER (start, w->start);
 
   itdata = bidi_shelve_cache ();
   start_display (&it, w, start);
@@ -5130,9 +5130,9 @@ and redisplay normally--don't erase and redraw the frame.  */)
          /* Invalidate pixel data calculated for all compositions.  */
          for (i = 0; i < n_compositions; i++)
            composition_table[i]->font = NULL;
-
+#if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
          WINDOW_XFRAME (w)->minimize_tool_bar_window_p = 1;
-
+#endif
          Fredraw_frame (WINDOW_FRAME (w));
          SET_FRAME_GARBAGED (WINDOW_XFRAME (w));
        }
@@ -5554,17 +5554,25 @@ the return value is nil.  Otherwise the value is t.  */)
          || data->frame_cols != previous_frame_cols)
        change_frame_size (f, data->frame_lines,
                           data->frame_cols, 0, 0, 0);
-#if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
+#ifdef HAVE_MENUS
       if (data->frame_menu_bar_lines
          != previous_frame_menu_bar_lines)
-       x_set_menu_bar_lines (f, make_number (data->frame_menu_bar_lines),
-                             make_number (0));
+       {
+#ifdef HAVE_WINDOW_SYSTEM
+         if (FRAME_WINDOW_P (f))
+           x_set_menu_bar_lines (f, make_number (data->frame_menu_bar_lines),
+                                 make_number (0));
+         else  /* TTY or MSDOS */
+#endif
+           set_menu_bar_lines (f, make_number (data->frame_menu_bar_lines),
+                               make_number (0));
+       }
+#endif
 #ifdef HAVE_WINDOW_SYSTEM
       if (data->frame_tool_bar_lines
          != previous_frame_tool_bar_lines)
        x_set_tool_bar_lines (f, make_number (data->frame_tool_bar_lines),
                              make_number (0));
-#endif
 #endif
 
       /* "Swap out" point from the selected window's buffer
@@ -5581,7 +5589,7 @@ the return value is nil.  Otherwise the value is t.  */)
                           BUF_PT_BYTE (XBUFFER (w->contents)));
        }
 
-      windows_or_buffers_changed++;
+      windows_or_buffers_changed = 39;
       FRAME_WINDOW_SIZES_CHANGED (f) = 1;
 
       /* Problem: Freeing all matrices and later allocating them again
@@ -5752,15 +5760,24 @@ the return value is nil.  Otherwise the value is t.  */)
          || previous_frame_cols != FRAME_COLS (f))
        change_frame_size (f, previous_frame_lines, previous_frame_cols,
                           0, 0, 0);
-#if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
+#ifdef HAVE_MENUS
       if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
-       x_set_menu_bar_lines (f, make_number (previous_frame_menu_bar_lines),
-                             make_number (0));
+       {
+#ifdef HAVE_WINDOW_SYSTEM
+         if (FRAME_WINDOW_P (f))
+           x_set_menu_bar_lines (f,
+                                 make_number (previous_frame_menu_bar_lines),
+                                 make_number (0));
+         else  /* TTY or MSDOS */
+#endif
+           set_menu_bar_lines (f, make_number (previous_frame_menu_bar_lines),
+                               make_number (0));
+       }
+#endif
 #ifdef HAVE_WINDOW_SYSTEM
       if (previous_frame_tool_bar_lines != FRAME_TOOL_BAR_LINES (f))
        x_set_tool_bar_lines (f, make_number (previous_frame_tool_bar_lines),
                              make_number (0));
-#endif
 #endif
 
       /* Now, free glyph matrices in windows that were not reused.  */
@@ -5772,7 +5789,7 @@ the return value is nil.  Otherwise the value is t.  */)
            ++n;
        }
 
-      adjust_glyphs (f);
+      adjust_frame_glyphs (f);
       unblock_input ();
 
       /* Scan dead buffer windows.  */
@@ -6100,8 +6117,8 @@ apply_window_adjustment (struct window *w)
   adjust_window_margins (w);
   clear_glyph_matrix (w->current_matrix);
   w->window_end_valid = 0;
-  windows_or_buffers_changed++;
-  adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
+  windows_or_buffers_changed = 40;
+  adjust_frame_glyphs (XFRAME (WINDOW_FRAME (w)));
 }
 
 \f
@@ -6367,7 +6384,7 @@ If PIXELS-P is non-nil, the return value is VSCROLL.  */)
          /* Adjust glyph matrix of the frame if the virtual display
             area becomes larger than before.  */
          if (w->vscroll < 0 && w->vscroll < old_dy)
-           adjust_glyphs (f);
+           adjust_frame_glyphs (f);
 
          /* Prevent redisplay shortcuts.  */
          XBUFFER (w->contents)->prevent_redisplay_optimizations_p = 1;
@@ -6523,7 +6540,6 @@ init_window_once (void)
   Vterminal_frame = selected_frame;
   minibuf_window = f->minibuffer_window;
   selected_window = f->selected_window;
-  last_nonminibuf_frame = f;
 
   window_initialized = 1;
 }