Support resizing frames and windows pixelwise.
[bpt/emacs.git] / src / dispnew.c
index b68cc2e..9492960 100644 (file)
@@ -72,7 +72,7 @@ struct dim
 static void update_frame_line (struct frame *, int);
 static int required_matrix_height (struct window *);
 static int required_matrix_width (struct window *);
-static void change_frame_size_1 (struct frame *, int, int, bool, bool, bool);
+static void change_frame_size_1 (struct frame *, int, int, bool, bool, bool, bool);
 static void increment_row_positions (struct glyph_row *, ptrdiff_t, ptrdiff_t);
 static void build_frame_matrix_from_window_tree (struct glyph_matrix *,
                                                  struct window *);
@@ -401,8 +401,8 @@ adjust_glyph_matrix (struct window *w, struct glyph_matrix *matrix, int x, int y
       if (!marginal_areas_changed_p
          && !XFRAME (w->frame)->fonts_changed
          && !header_line_changed_p
-         && matrix->window_left_col == WINDOW_LEFT_EDGE_COL (w)
-         && matrix->window_top_line == WINDOW_TOP_EDGE_LINE (w)
+         && matrix->window_pixel_left == WINDOW_LEFT_PIXEL_EDGE (w)
+         && matrix->window_pixel_top == WINDOW_TOP_PIXEL_EDGE (w)
          && matrix->window_height == window_height
          && matrix->window_vscroll == w->vscroll
          && matrix->window_width == window_width)
@@ -543,8 +543,8 @@ adjust_glyph_matrix (struct window *w, struct glyph_matrix *matrix, int x, int y
              && !header_line_changed_p
              && new_rows == 0
              && dim.width == matrix->matrix_w
-             && matrix->window_left_col == WINDOW_LEFT_EDGE_COL (w)
-             && matrix->window_top_line == WINDOW_TOP_EDGE_LINE (w)
+             && matrix->window_pixel_left == WINDOW_LEFT_PIXEL_EDGE (w)
+             && matrix->window_pixel_top == WINDOW_TOP_PIXEL_EDGE (w)
              && matrix->window_width == window_width)
            {
              /* Find the last row in the window.  */
@@ -591,8 +591,8 @@ adjust_glyph_matrix (struct window *w, struct glyph_matrix *matrix, int x, int y
      was last adjusted.  This is used to optimize redisplay above.  */
   if (w)
     {
-      matrix->window_left_col = WINDOW_LEFT_EDGE_COL (w);
-      matrix->window_top_line = WINDOW_TOP_EDGE_LINE (w);
+      matrix->window_pixel_left = WINDOW_LEFT_PIXEL_EDGE (w);
+      matrix->window_pixel_top = WINDOW_TOP_PIXEL_EDGE (w);
       matrix->window_height = window_height;
       matrix->window_width = window_width;
       matrix->window_vscroll = w->vscroll;
@@ -1661,6 +1661,7 @@ required_matrix_height (struct window *w)
     {
       int ch_height = FRAME_SMALLEST_FONT_HEIGHT (f);
       int window_pixel_height = window_box_height (w) + eabs (w->vscroll);
+
       return (((window_pixel_height + ch_height - 1)
               / ch_height) * w->nrows_scale_factor
              /* One partially visible line at the top and
@@ -1685,10 +1686,9 @@ required_matrix_width (struct window *w)
   if (FRAME_WINDOW_P (f))
     {
       int ch_width = FRAME_SMALLEST_CHAR_WIDTH (f);
-      int window_pixel_width = WINDOW_TOTAL_WIDTH (w);
 
       /* Compute number of glyphs needed in a glyph row.  */
-      return (((window_pixel_width + ch_width - 1)
+      return (((WINDOW_PIXEL_WIDTH (w) + ch_width - 1)
               / ch_width) * w->ncols_scale_factor
              /* 2 partially visible columns in the text area.  */
              + 2
@@ -1978,6 +1978,10 @@ adjust_frame_glyphs_for_frame_redisplay (struct frame *f)
       /* Size of frame matrices must equal size of frame.  Note
         that we are called for X frames with window widths NOT equal
         to the frame width (from CHANGE_FRAME_SIZE_1).  */
+      if (matrix_dim.width != FRAME_COLS (f)
+         || matrix_dim.height != FRAME_LINES (f))
+       return;
+
       eassert (matrix_dim.width == FRAME_COLS (f)
               && matrix_dim.height == FRAME_LINES (f));
 
@@ -2047,10 +2051,14 @@ adjust_frame_glyphs_for_window_redisplay (struct frame *f)
 
     /* Set window dimensions to frame dimensions and allocate or
        adjust glyph matrices of W.  */
-    w->top_line = 0;
+    w->pixel_left = 0;
     w->left_col = 0;
-    w->total_lines = FRAME_MENU_BAR_LINES (f);
+    w->pixel_top = 0;
+    w->top_line = 0;
+    w->pixel_width = FRAME_PIXEL_WIDTH (f);
     w->total_cols = FRAME_TOTAL_COLS (f);
+    w->pixel_height = FRAME_MENU_BAR_HEIGHT (f);
+    w->total_lines = FRAME_MENU_BAR_LINES (f);
     allocate_matrices_for_window_redisplay (w);
   }
 #endif
@@ -2072,10 +2080,15 @@ adjust_frame_glyphs_for_window_redisplay (struct frame *f)
     else
       w = XWINDOW (f->tool_bar_window);
 
-    w->top_line = FRAME_MENU_BAR_LINES (f);
+    w->pixel_left = 0;
     w->left_col = 0;
-    w->total_lines = FRAME_TOOL_BAR_LINES (f);
+    w->pixel_top = FRAME_MENU_BAR_HEIGHT (f);
+    w->top_line = FRAME_MENU_BAR_LINES (f);
+    w->pixel_width = (FRAME_PIXEL_WIDTH (f)
+                      - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
     w->total_cols = FRAME_TOTAL_COLS (f);
+    w->pixel_height = FRAME_TOOL_BAR_HEIGHT (f);
+    w->total_lines = FRAME_TOOL_BAR_LINES (f);
     allocate_matrices_for_window_redisplay (w);
   }
 #endif
@@ -5275,7 +5288,7 @@ marginal_area_string (struct window *w, enum window_part part,
       if (area == RIGHT_MARGIN_AREA)
        x0 = ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
               ? WINDOW_LEFT_FRINGE_WIDTH (w)
-              : WINDOW_TOTAL_FRINGE_WIDTH (w))
+              : WINDOW_FRINGES_WIDTH (w))
              + window_box_width (w, LEFT_MARGIN_AREA)
              + window_box_width (w, TEXT_AREA));
       else
@@ -5367,7 +5380,7 @@ handle_window_change_signal (int sig)
           /* Record the new sizes, but don't reallocate the data
              structures now.  Let that be done later outside of the
              signal handler.  */
-          change_frame_size (XFRAME (frame), height, width, 0, 1, 0);
+          change_frame_size (XFRAME (frame), width, height, 0, 1, 0, 0);
     }
   }
 }
@@ -5401,17 +5414,21 @@ do_pending_window_change (bool safe)
        {
          struct frame *f = XFRAME (frame);
 
-         if (f->new_text_lines != 0 || f->new_text_cols != 0)
-           change_frame_size (f, f->new_text_lines, f->new_text_cols,
-                              0, 0, safe);
+         if (f->new_height != 0 || f->new_width != 0)
+           change_frame_size (f, f->new_width, f->new_height,
+                              0, 0, safe, f->new_pixelwise);
        }
     }
 }
 
-
 /* Change the frame height and/or width.  Values may be given as zero to
    indicate no change is to take place.
 
+   new_height and new_width refer to the text portion of the frame.  It
+   doesn't matter for new_height, since text and total portion are the
+   same in that case.  But new_width must be enlarged to get the total
+   width of the frame.
+
    If DELAY, assume we're being called from a signal handler, and
    queue the change for later - perhaps the next redisplay.
    Since this tries to resize windows, we can't call it
@@ -5421,8 +5438,8 @@ do_pending_window_change (bool safe)
    safe to change frame sizes while a redisplay is in progress.  */
 
 void
-change_frame_size (struct frame *f, int newheight, int newwidth,
-                  bool pretend, bool delay, bool safe)
+change_frame_size (struct frame *f, int new_width, int new_height,
+                  bool pretend, bool delay, bool safe, bool pixelwise)
 {
   Lisp_Object tail, frame;
 
@@ -5433,55 +5450,72 @@ change_frame_size (struct frame *f, int newheight, int newwidth,
          ttys. */
       FOR_EACH_FRAME (tail, frame)
        if (! FRAME_WINDOW_P (XFRAME (frame)))
-         change_frame_size_1 (XFRAME (frame), newheight, newwidth,
-                              pretend, delay, safe);
+         change_frame_size_1 (XFRAME (frame), new_width, new_height,
+                              pretend, delay, safe, pixelwise);
     }
   else
-    change_frame_size_1 (f, newheight, newwidth, pretend, delay, safe);
+    change_frame_size_1 (f, new_width, new_height, pretend, delay, safe,
+                        pixelwise);
 }
 
 static void
-change_frame_size_1 (struct frame *f, int newheight, int newwidth,
-                    bool pretend, bool delay, bool safe)
+change_frame_size_1 (struct frame *f, int new_width, int new_height,
+                    bool pretend, bool delay, bool safe, bool pixelwise)
 {
-  int new_frame_total_cols;
+  int new_text_width, new_text_height, new_root_width;
+  int old_root_width = (FRAME_PIXEL_WIDTH (f)
+                       - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
+  int new_cols, new_lines;
   ptrdiff_t count = SPECPDL_INDEX ();
 
   /* If we can't deal with the change now, queue it for later.  */
   if (delay || (redisplaying_p && !safe))
     {
-      f->new_text_lines = newheight;
-      f->new_text_cols = newwidth;
+      f->new_width = new_width;
+      f->new_height = new_height;
+      f->new_pixelwise = pixelwise;
       delayed_size_change = 1;
       return;
     }
 
   /* This size-change overrides any pending one for this frame.  */
-  f->new_text_lines = 0;
-  f->new_text_cols = 0;
+  f->new_height = 0;
+  f->new_width = 0;
+  f->new_pixelwise = 0;
 
   /* If an argument is zero, set it to the current value.  */
-  if (newheight == 0)
-    newheight = FRAME_LINES (f);
-  if (newwidth == 0)
-    newwidth  = FRAME_COLS  (f);
+  if (pixelwise)
+    {
+      new_text_width = (new_width == 0) ? FRAME_TEXT_WIDTH (f) : new_width;
+      new_text_height = (new_height == 0) ? FRAME_TEXT_HEIGHT (f) : new_height;
+      new_cols = new_text_width / FRAME_COLUMN_WIDTH (f);
+      new_lines = new_text_height / FRAME_LINE_HEIGHT (f);
+    }
+  else
+    {
+      new_cols = (new_width == 0) ? FRAME_COLS (f) : new_width;
+      new_lines = (new_height == 0) ? FRAME_LINES (f) : new_height;
+      new_text_width = new_cols * FRAME_COLUMN_WIDTH (f);
+      new_text_height = new_lines * FRAME_LINE_HEIGHT (f);
+    }
 
   /* Compute width of windows in F.  */
   /* Round up to the smallest acceptable size.  */
-  check_frame_size (f, &newheight, &newwidth);
-
-  /* This is the width of the frame with vertical scroll bars and fringe
-     columns.  Do this after rounding - see discussion of bug#9723.  */
-  new_frame_total_cols = FRAME_TOTAL_COLS_ARG (f, newwidth);
-
+  check_frame_size (f, &new_text_width, &new_text_height, 1);
+
+  /* This is the width of the frame without vertical scroll bars and
+     fringe columns.  Do this after rounding - see discussion of
+     bug#9723.  */
+  new_root_width = (new_text_width
+                   /* PXM: Use the configured scrollbar width !??  */
+                   + FRAME_SCROLL_BAR_AREA_WIDTH (f)
+                   + FRAME_TOTAL_FRINGE_WIDTH (f));
   /* If we're not changing the frame size, quit now.  */
   /* Frame width may be unchanged but the text portion may change, for
      example, fullscreen and remove/add scroll bar.  */
-  if (newheight == FRAME_LINES (f)
-      /* Text portion unchanged?  */
-      && newwidth == FRAME_COLS  (f)
-      /* Frame width unchanged?  */
-      && new_frame_total_cols == FRAME_TOTAL_COLS (f))
+  if (new_text_height == FRAME_TEXT_HEIGHT (f)
+      && new_text_width == FRAME_TEXT_WIDTH (f)
+      && new_root_width == old_root_width)
     return;
 
   block_input ();
@@ -5490,36 +5524,44 @@ change_frame_size_1 (struct frame *f, int newheight, int newwidth,
   /* We only can set screen dimensions to certain values supported
      by our video hardware.  Try to find the smallest size greater
      or equal to the requested dimensions.  */
-  dos_set_window_size (&newheight, &newwidth);
+  dos_set_window_size (&new_lines, &new_cols);
 #endif
 
-  if (newheight != FRAME_LINES (f))
+  if (new_text_height != FRAME_TEXT_HEIGHT (f))
     {
-      resize_frame_windows (f, newheight, 0);
+      resize_frame_windows (f, new_text_height, 0, 1);
 
       /* MSDOS frames cannot PRETEND, as they change frame size by
         manipulating video hardware.  */
       if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f))
-       FrameRows (FRAME_TTY (f)) = newheight;
+       FrameRows (FRAME_TTY (f)) = new_height;
     }
 
-  if (new_frame_total_cols != FRAME_TOTAL_COLS (f))
+  if (new_text_width != FRAME_TEXT_WIDTH (f)
+      || new_root_width != old_root_width)
     {
-      resize_frame_windows (f, new_frame_total_cols, 1);
+      resize_frame_windows (f, new_root_width, 1, 1);
 
       /* MSDOS frames cannot PRETEND, as they change frame size by
         manipulating video hardware.  */
       if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f))
-       FrameCols (FRAME_TTY (f)) = newwidth;
+       FrameCols (FRAME_TTY (f)) = new_cols;
 
 #if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
       if (WINDOWP (f->tool_bar_window))
-       XWINDOW (f->tool_bar_window)->total_cols = newwidth;
+       {
+         XWINDOW (f->tool_bar_window)->total_cols = new_cols;
+         XWINDOW (f->tool_bar_window)->pixel_width = new_root_width;
+       }
 #endif
     }
 
-  FRAME_LINES (f) = newheight;
-  SET_FRAME_COLS (f, newwidth);
+  SET_FRAME_COLS (f, new_cols);
+  FRAME_LINES (f) = new_lines;
+  FRAME_TEXT_WIDTH (f) = new_text_width;
+  FRAME_TEXT_HEIGHT (f) = new_text_height;
+  FRAME_PIXEL_WIDTH (f) = FRAME_TEXT_TO_PIXEL_WIDTH (f, new_text_width);
+  FRAME_PIXEL_HEIGHT (f) = FRAME_TEXT_TO_PIXEL_HEIGHT (f, new_text_height);
 
   {
     struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
@@ -5546,8 +5588,6 @@ change_frame_size_1 (struct frame *f, int newheight, int newwidth,
 
   unbind_to (count, Qnil);
 }
-
-
 \f
 /***********************************************************************
                   Terminal Related Lisp Functions
@@ -6076,8 +6116,8 @@ init_display (void)
 #endif
     t->display_info.tty->top_frame = selected_frame;
     change_frame_size (XFRAME (selected_frame),
-                       FrameRows (t->display_info.tty),
-                       FrameCols (t->display_info.tty), 0, 0, 1);
+                       FrameCols (t->display_info.tty),
+                       FrameRows (t->display_info.tty), 0, 0, 1, 0);
 
     /* Delete the initial terminal. */
     if (--initial_terminal->reference_count == 0