]> git.eshelyaron.com Git - emacs.git/commitdiff
Improve inhibiting of implied frame resizes.
authorMartin Rudalics <rudalics@gmx.at>
Fri, 7 Nov 2014 10:49:22 +0000 (11:49 +0100)
committerMartin Rudalics <rudalics@gmx.at>
Fri, 7 Nov 2014 10:49:22 +0000 (11:49 +0100)
* frames.texi (Size and Position): Rewrite description of
`frame-inhibit-implied-resize'.
* cus-start.el (frame-resize-pixelwise): Fix group.
(frame-inhibit-implied-resize): Add entry.
* dispnew.c (change_frame_size_1): Fix call of
adjust_frame_size.
* frame.c (Qsize, Qframe_position, Qframe_outer_size)
(Qframe_inner_size, Qexternal_border_size, Qtitle_height)
(Qmenu_bar_external, Qmenu_bar_size, Qtool_bar_external)
(Qtool_bar_size): New constants.
(frame_inhibit_resize, adjust_frame_size): New argument to
handle case where frame_inhibit_implied_resize is a list.
(Fmake_terminal_frame, Fset_frame_height, Fset_frame_width)
(Fset_frame_size, x_set_left_fringe, x_set_right_fringe)
(x_set_right_divider_width, x_set_bottom_divider_width)
(x_set_vertical_scroll_bars, x_set_horizontal_scroll_bars)
(x_set_scroll_bar_width, x_set_scroll_bar_height): Update
callers.
(frame-inhibit-implied-resize): Rewrite doc-string.
* frame.h (frame_inhibit_resize, adjust_frame_size): Fix
external declarations.
(Qframe_position, Qframe_outer_size)
(Qframe_inner_size, Qexternal_border_size, Qtitle_height)
(Qmenu_bar_external, Qmenu_bar_size, Qtool_bar_external)
(Qtool_bar_size): Extern them.
* gtkutil.c (FRAME_TOTAL_PIXEL_HEIGHT, FRAME_TOTAL_PIXEL_WIDTH)
(xg_height_or_width_changed): Remove.
(xg_frame_set_char_size): Adjust adjust_frame_size calls.
(menubar_map_cb, xg_update_frame_menubar, free_frame_menubar)
(tb_size_cb, update_frame_tool_bar, free_frame_tool_bar)
(xg_change_toolbar_position): Call adjust_frame_size directly.
* nsfns.m (x_set_internal_border_width, Fx_create_frame): Fix
calls of adjust_frame_size.
* w32fns.c (x_set_internal_border_width, x_set_menu_bar_lines)
(Fx_create_frame, x_create_tip_frame): Adjust adjust_frame_size
calls.
(x_set_tool_bar_lines, x_change_tool_bar_height): Make sure that
frame can get resized when tool-bar-lines parameter changes from
or to zero.
(Fw32_frame_menu_bar_size): Return fourth value.
(Fw32_frame_rect): Block input around system calls
(Fx_frame_geometry): New function.
* w32menu.c (set_frame_menubar): Adjust adjust_frame_size call.
* w32term.c (x_new_font): Adjust adjust_frame_size call.
* widget.c (EmacsFrameSetCharSize): Adjust frame_inhibit_resize
call.
* window.c (Fset_window_configuration): Adjust adjust_frame_size
call.
* xfns.c (x_set_menu_bar_lines, x_set_internal_border_width)
(Fx_create_frame): Adjust adjust_frame_size calls.
(x_set_tool_bar_lines, x_change_tool_bar_height): Make sure that
frame can get resized when tool-bar-lines parameter changes from
or to zero.
(Fx_frame_geometry): New function.
* xmenu.c (update_frame_menubar): On Lucid call
adjust_frame_size with one pixel less height to avoid that
repeatedly adding/removing the menu bar grows the frame.
(free_frame_menubar): On Motif arrange to optionally preserve
the old frame height when removing the menu bar.
* xterm.c (x_new_font): Adjust adjust_frame_size call.

18 files changed:
doc/lispref/ChangeLog
doc/lispref/frames.texi
lisp/ChangeLog
lisp/cus-start.el
src/ChangeLog
src/dispnew.c
src/frame.c
src/frame.h
src/gtkutil.c
src/nsfns.m
src/w32fns.c
src/w32menu.c
src/w32term.c
src/widget.c
src/window.c
src/xfns.c
src/xmenu.c
src/xterm.c

index 356560f2576b706666de55b265cdb16815d3e28e..9a7a6c8c8a6049f71e80c430cc26582f88049465 100644 (file)
@@ -1,3 +1,8 @@
+2014-11-07  Martin Rudalics  <rudalics@gmx.at>
+
+       * frames.texi (Size and Position): Rewrite description of
+       `frame-inhibit-implied-resize'.
+
 2014-10-22  Martin Rudalics  <rudalics@gmx.at>
 
        * frames.texi (Size Parameters): Replace "frame contents" by
index 146170a967caad750254c6a9816219541f2db2f2..0bded22eade5cc97ce79cbb00db72a93141f999a 100644 (file)
@@ -1350,10 +1350,9 @@ frame's text area unaltered when, for example, adding or removing a menu
 bar, changing the default font or setting the width of the frame's
 scroll bars.  This means, however, that in such case Emacs must ask the
 window manager to resize the display area of the frame in order to
-accommodate the size change.  (Note that with the exception of GTK+
-builds, adding, removing or wrapping the tool bar usually do not resize
-the frame's display area, hence these may alter the number of displayed
-lines.)
+accommodate the size change.  Note that wrapping a menu or tool bar
+usually does not resize the frame's display area, hence this will alter
+the number of displayed lines.
 
    Occasionally, such implied resizing of the display area may be
 unwanted, for example, when the frame is maximized or made fullscreen
@@ -1361,15 +1360,40 @@ where it's turned off by default.  In other cases you can disable
 implied resizing with the following option:
 
 @defopt frame-inhibit-implied-resize
-If this option is @code{nil}, changing default font, menu bar mode,
-fringe width, or scroll bars of a specific frame may resize the frame's
-display area in order to preserve the number of columns or lines the
-frame displays.  If this option is non-@code{nil}, no such resizing is
-done.
-
-When you add a tool bar or scroll bar to a frame that is not large
-enough to accommodate one, Emacs will try to enlarge the frame even if
-this option is non-@code{nil}.
+If this option is @code{nil}, changing font, menu bar, tool bar,
+internal borders, fringes or scroll bars of a specific frame may
+implicitly resize the frame's display area in order to preserve the
+number of columns or lines the frame displays.  If this option is
+non-@code{nil}, no implied resizing is done.
+
+The value of this option can be also be a list of frame parameters.  In
+that case, implied resizing is inhibited when changing a parameter that
+appears in this list.  The frame parameters currently handled by this
+option are: @code{font}, @code{font-backend},
+@code{internal-border-width}, @code{menu-bar-lines} and
+@code{tool-bar-lines}.
+
+Changing any of the @code{scroll-bar-width}, @code{scroll-bar-height},
+@code{vertical-scroll-bars}, @code{horizontal-scroll-bars},
+@code{left-fringe} and @code{right-fringe} frame parameters is handled
+as if the frame contained just one live window.  This means, for
+example, that removing vertical scroll bars on a frame containing
+several side by side windows will shrink the frame width by the width of
+one scroll bar provided this option is @code{nil} and keep it unchanged
+if this option is either @code{t} or a list containing
+@code{vertical-scroll-bars}.
+
+The default value is @code{'(tool-bar-lines)} for Lucid, Motif and
+Windows (which means that adding/removing a tool bar there does not
+change the frame height), @code{nil} on all other window systems
+including GTK+ (which means that changing any of the parameters listed
+above may change the size of the frame), and @code{t} otherwise (which
+means the frame size never changes implicitly when there's no window
+system support).
+
+Note that when a frame is not large enough to accommodate a change of
+any of the parameters listed above, Emacs may try to enlarge the frame
+even if this option is non-@code{nil}.
 @end defopt
 
 @c FIXME?  Belongs more in Emacs manual than here?
index e3b453edc09dd522a7308065a71919493f95f60b..f242386215a1c2031df86a487379a7a7d0ed7347 100644 (file)
@@ -1,3 +1,8 @@
+2014-11-07  Martin Rudalics  <rudalics@gmx.at>
+
+       * cus-start.el (frame-resize-pixelwise): Fix group.
+       (frame-inhibit-implied-resize): Add entry.
+
 2014-11-07  Daiki Ueno  <ueno@gnu.org>
 
        * epa.el (epa-pinentry-mode): New user option.
index e0c1b73a4650ffc152a49f8a827fa93e26fa01fd..3b8885a8717e240bced42a70df8203914ba13911 100644 (file)
@@ -274,7 +274,13 @@ Leaving \"Default\" unchecked is equivalent with specifying a default of
             (tool-bar-mode (frames mouse) boolean nil
 ;                          :initialize custom-initialize-default
                            :set custom-set-minor-mode)
-            (frame-resize-pixelwise windows boolean "24.4")
+            (frame-resize-pixelwise frames boolean "24.4")
+            (frame-inhibit-implied-resize frames
+                                          (choice
+                                           (const :tag "Never" nil)
+                                           (const :tag "Always" t)
+                                           (repeat (symbol :tag "Parameter")))
+                                          "25.1")
             ;; fringe.c
             (overflow-newline-into-fringe fringe boolean)
             ;; image.c
index 6b62a60f7b0e179df49d7a61561542d225c17037..c46d23dd82e765352c22259c1f1b9693d5d86186 100644 (file)
@@ -1,3 +1,62 @@
+2014-11-07  Martin Rudalics  <rudalics@gmx.at>
+
+       * dispnew.c (change_frame_size_1): Fix call of
+       adjust_frame_size.
+       * frame.c (Qsize, Qframe_position, Qframe_outer_size)
+       (Qframe_inner_size, Qexternal_border_size, Qtitle_height)
+       (Qmenu_bar_external, Qmenu_bar_size, Qtool_bar_external)
+       (Qtool_bar_size): New constants.
+       (frame_inhibit_resize, adjust_frame_size): New argument to
+       handle case where frame_inhibit_implied_resize is a list.
+       (Fmake_terminal_frame, Fset_frame_height, Fset_frame_width)
+       (Fset_frame_size, x_set_left_fringe, x_set_right_fringe)
+       (x_set_right_divider_width, x_set_bottom_divider_width)
+       (x_set_vertical_scroll_bars, x_set_horizontal_scroll_bars)
+       (x_set_scroll_bar_width, x_set_scroll_bar_height): Update
+       callers.
+       (frame-inhibit-implied-resize): Rewrite doc-string.
+       * frame.h (frame_inhibit_resize, adjust_frame_size): Fix
+       external declarations.
+       (Qframe_position, Qframe_outer_size)
+       (Qframe_inner_size, Qexternal_border_size, Qtitle_height)
+       (Qmenu_bar_external, Qmenu_bar_size, Qtool_bar_external)
+       (Qtool_bar_size): Extern them.
+       * gtkutil.c (FRAME_TOTAL_PIXEL_HEIGHT, FRAME_TOTAL_PIXEL_WIDTH)
+       (xg_height_or_width_changed): Remove.
+       (xg_frame_set_char_size): Adjust adjust_frame_size calls.
+       (menubar_map_cb, xg_update_frame_menubar, free_frame_menubar)
+       (tb_size_cb, update_frame_tool_bar, free_frame_tool_bar)
+       (xg_change_toolbar_position): Call adjust_frame_size directly.
+       * nsfns.m (x_set_internal_border_width, Fx_create_frame): Fix
+       calls of adjust_frame_size.
+       * w32fns.c (x_set_internal_border_width, x_set_menu_bar_lines)
+       (Fx_create_frame, x_create_tip_frame): Adjust adjust_frame_size
+       calls.
+       (x_set_tool_bar_lines, x_change_tool_bar_height): Make sure that
+       frame can get resized when tool-bar-lines parameter changes from
+       or to zero.
+       (Fw32_frame_menu_bar_size): Return fourth value.
+       (Fw32_frame_rect): Block input around system calls
+       (Fx_frame_geometry): New function.
+       * w32menu.c (set_frame_menubar): Adjust adjust_frame_size call.
+       * w32term.c (x_new_font): Adjust adjust_frame_size call.
+       * widget.c (EmacsFrameSetCharSize): Adjust frame_inhibit_resize
+       call.
+       * window.c (Fset_window_configuration): Adjust adjust_frame_size
+       call.
+       * xfns.c (x_set_menu_bar_lines, x_set_internal_border_width)
+       (Fx_create_frame): Adjust adjust_frame_size calls.
+       (x_set_tool_bar_lines, x_change_tool_bar_height): Make sure that
+       frame can get resized when tool-bar-lines parameter changes from
+       or to zero.
+       (Fx_frame_geometry): New function.
+       * xmenu.c (update_frame_menubar): On Lucid call
+       adjust_frame_size with one pixel less height to avoid that
+       repeatedly adding/removing the menu bar grows the frame.
+       (free_frame_menubar): On Motif arrange to optionally preserve
+       the old frame height when removing the menu bar.
+       * xterm.c (x_new_font): Adjust adjust_frame_size call.
+
 2014-11-03  Eli Zaretskii  <eliz@gnu.org>
 
        * xdisp.c (Fdump_glyph_matrix, Fdump_frame_glyph_matrix): Doc fix.
index 900912d9d97510b25431c7b5353da57f14eaf245..d50d06f2d47ebcead996b4bf891f54010d72ab69 100644 (file)
@@ -5528,7 +5528,7 @@ change_frame_size_1 (struct frame *f, int new_width, int new_height,
 
       /* Adjust frame size but make sure x_set_window_size does not
         get called.  */
-      adjust_frame_size (f, new_width, new_height, 5, pretend);
+      adjust_frame_size (f, new_width, new_height, 5, pretend, Qnil);
     }
 }
 
index d1acb73b926a0ebd0d9f8bca59d0d4916ea7555e..5bb2c831c20a935d251dfdc3f7d4f06b9b307bae 100644 (file)
@@ -77,7 +77,7 @@ Lisp_Object Qterminal;
 Lisp_Object Qauto_raise, Qauto_lower;
 Lisp_Object Qborder_color, Qborder_width;
 Lisp_Object Qcursor_color, Qcursor_type;
-Lisp_Object Qheight, Qwidth;
+Lisp_Object Qheight, Qwidth, Qsize;
 Lisp_Object Qicon_left, Qicon_top, Qicon_type, Qicon_name;
 Lisp_Object Qtooltip;
 Lisp_Object Qinternal_border_width;
@@ -120,6 +120,11 @@ static Lisp_Object Qdelete_frame_functions;
 static Lisp_Object Qframe_windows_min_size;
 static Lisp_Object Qgeometry, Qworkarea, Qmm_size, Qframes, Qsource;
 
+Lisp_Object Qframe_position, Qframe_outer_size, Qframe_inner_size;
+Lisp_Object Qexternal_border_size, Qtitle_height;
+Lisp_Object Qmenu_bar_external, Qmenu_bar_size;
+Lisp_Object Qtool_bar_external, Qtool_bar_size;
+
 /* The currently selected frame.  */
 
 Lisp_Object selected_frame;
@@ -209,12 +214,14 @@ get_frame_param (register struct frame *frame, Lisp_Object prop)
 
 /* Return 1 if `frame-inhibit-implied-resize' is non-nil or fullscreen
    state of frame F would be affected by a vertical (horizontal if
-   HORIZONTAL is true) resize.  */
+   HORIZONTAL is true) resize.  PARAMETER is the symbol of the frame
+   parameter that is changed.  */
 bool
-frame_inhibit_resize (struct frame *f, bool horizontal)
+frame_inhibit_resize (struct frame *f, bool horizontal, Lisp_Object parameter)
 {
-
-  return (frame_inhibit_implied_resize
+  return (EQ (frame_inhibit_implied_resize, Qt)
+         || (CONSP (frame_inhibit_implied_resize)
+             && !NILP (Fmemq (parameter, frame_inhibit_implied_resize)))
          || !NILP (get_frame_param (f, Qfullscreen))
          || FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f));
 }
@@ -337,40 +344,46 @@ frame_windows_min_size (Lisp_Object frame, Lisp_Object horizontal, Lisp_Object p
 /* Make sure windows sizes of frame F are OK.  new_width and new_height
    are in pixels.  A value of -1 means no change is requested for that
    size (but the frame may still have to be resized to accommodate
-   windows with their minimum sizes.
+   windows with their minimum sizes).  This can either issue a request
+   to resize the frame externally (via x_set_window_size), to resize the
+   frame internally (via resize_frame_windows) or do nothing at all.
 
    The argument INHIBIT can assume the following values:
 
    0 means to unconditionally call x_set_window_size even if sizes
-   apparently do not change.  Fx_create_frame uses this to pass the
-   initial size to the window manager.
+     apparently do not change.  Fx_create_frame uses this to pass the
+     initial size to the window manager.
 
-   1 means to call x_set_window_size iff the pixel size really changes.
-   Fset_frame_size, Fset_frame_height, ... use this.
+   1 means to call x_set_window_size if the outer frame size really
+     changes.  Fset_frame_size, Fset_frame_height, ... use this.
 
-   2 means to unconditionally call x_set_window_size provided
-   frame_inhibit_resize allows it.  The menu bar code uses this.
+   2 means to call x_set_window_size provided frame_inhibit_resize
+     allows it.  The menu and tool bar code use this ("3" won't work
+     here in general because menu and tool bar are often not counted in
+     the frame's text height).
 
-   3 means call x_set_window_size iff window minimum sizes must be
-   preserved or frame_inhibit_resize allows it, x_set_left_fringe,
-   x_set_scroll_bar_width, ... use this.
+   3 means call x_set_window_size if window minimum sizes must be
+     preserved or frame_inhibit_resize allows it.  x_set_left_fringe,
+     x_set_scroll_bar_width, x_new_font ... use (or should use) this.
 
-   4 means call x_set_window_size iff window minimum sizes must be
-   preserved.  x_set_tool_bar_lines, x_set_right_divider_width, ... use
-   this.  BUT maybe the toolbar code shouldn't ....
+   4 means call x_set_window_size only if window minimum sizes must be
+     preserved.  x_set_right_divider_width, x_set_border_width and the
+     code responsible for wrapping the tool bar use this.
 
    5 means to never call x_set_window_size.  change_frame_size uses
-   this.
+     this.
 
-   For 2 and 3 note that if frame_inhibit_resize inhibits resizing and
-   minimum sizes are not violated no internal resizing takes place
-   either.  For 2, 3, 4 and 5 note that even if no x_set_window_size
-   call is issued, window sizes may have to be adjusted in order to
-   support minimum size constraints for the frame's windows.
+   Note that even when x_set_window_size is not called, individual
+   windows may have to be resized (via `window--sanitize-window-sizes')
+   in order to support minimum size constraints.
 
-   PRETEND is as for change_frame_size.  */
+   PRETEND is as for change_frame_size.  PARAMETER, if non-nil, is the
+   symbol of the parameter changed (like `menu-bar-lines', `font', ...).
+   This is passed on to frame_inhibit_resize to let the latter decide on
+   a case-by-case basis whether the frame may be resized externally.  */
 void
-adjust_frame_size (struct frame *f, int new_width, int new_height, int inhibit, bool pretend)
+adjust_frame_size (struct frame *f, int new_width, int new_height, int inhibit,
+                  bool pretend, Lisp_Object parameter)
 {
   int unit_width = FRAME_COLUMN_WIDTH (f);
   int unit_height = FRAME_LINE_HEIGHT (f);
@@ -415,10 +428,12 @@ adjust_frame_size (struct frame *f, int new_width, int new_height, int inhibit,
        so or INHIBIT equals 4.  */
     {
       inhibit_horizontal = ((windows_width >= min_windows_width
-                            && (inhibit == 4 || frame_inhibit_resize (f, true)))
+                            && (inhibit == 4
+                                || frame_inhibit_resize (f, true, parameter)))
                            ? true : false);
       inhibit_vertical = ((windows_height >= min_windows_height
-                          && (inhibit == 4 || frame_inhibit_resize (f, false)))
+                          && (inhibit == 4
+                              || frame_inhibit_resize (f, false, parameter)))
                          ? true : false);
     }
   else
@@ -1004,7 +1019,7 @@ affects all frames on the same terminal device.  */)
   {
     int width, height;
     get_tty_size (fileno (FRAME_TTY (f)->input), &width, &height);
-    adjust_frame_size (f, width, height - FRAME_MENU_BAR_LINES (f), 5, 0);
+    adjust_frame_size (f, width, height - FRAME_MENU_BAR_LINES (f), 5, 0, Qnil);
   }
 
   adjust_frame_glyphs (f);
@@ -2848,7 +2863,7 @@ multiple of the default frame font height.  */)
                  ? XINT (height)
                  : XINT (height) * FRAME_LINE_HEIGHT (f));
   if (pixel_height != FRAME_TEXT_HEIGHT (f))
-    adjust_frame_size (f, -1, pixel_height, 1, !NILP (pretend));
+    adjust_frame_size (f, -1, pixel_height, 1, !NILP (pretend), Qheight);
 
   return Qnil;
 }
@@ -2874,7 +2889,7 @@ multiple of the default frame font width.  */)
                 ? XINT (width)
                 : XINT (width) * FRAME_COLUMN_WIDTH (f));
   if (pixel_width != FRAME_TEXT_WIDTH (f))
-    adjust_frame_size (f, pixel_width, -1, 1, !NILP (pretend));
+    adjust_frame_size (f, pixel_width, -1, 1, !NILP (pretend), Qwidth);
 
   return Qnil;
 }
@@ -2903,7 +2918,7 @@ font height.  */)
 
   if (pixel_width != FRAME_TEXT_WIDTH (f)
       || pixel_height != FRAME_TEXT_HEIGHT (f))
-    adjust_frame_size (f, pixel_width, pixel_height, 1, 0);
+    adjust_frame_size (f, pixel_width, pixel_height, 1, 0, Qsize);
 
   return Qnil;
 }
@@ -3627,7 +3642,7 @@ x_set_left_fringe (struct frame *f, Lisp_Object new_value, Lisp_Object old_value
        = (new_width + FRAME_RIGHT_FRINGE_WIDTH (f) + unit - 1) / unit;
 
       if (FRAME_X_WINDOW (f) != 0)
-       adjust_frame_size (f, -1, -1, 3, 0);
+       adjust_frame_size (f, -1, -1, 3, 0, Qleft_fringe);
 
       SET_FRAME_GARBAGED (f);
     }
@@ -3651,7 +3666,7 @@ x_set_right_fringe (struct frame *f, Lisp_Object new_value, Lisp_Object old_valu
        = (new_width + FRAME_LEFT_FRINGE_WIDTH (f) + unit - 1) / unit;
 
       if (FRAME_X_WINDOW (f) != 0)
-       adjust_frame_size (f, -1, -1, 3, 0);
+       adjust_frame_size (f, -1, -1, 3, 0, Qright_fringe);
 
       SET_FRAME_GARBAGED (f);
     }
@@ -3683,7 +3698,7 @@ x_set_right_divider_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
     FRAME_RIGHT_DIVIDER_WIDTH (f) = 0;
   if (FRAME_RIGHT_DIVIDER_WIDTH (f) != old)
     {
-      adjust_frame_size (f, -1, -1, 4, 0);
+      adjust_frame_size (f, -1, -1, 4, 0, Qright_divider_width);
       adjust_frame_glyphs (f);
       SET_FRAME_GARBAGED (f);
     }
@@ -3701,7 +3716,7 @@ x_set_bottom_divider_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval
     FRAME_BOTTOM_DIVIDER_WIDTH (f) = 0;
   if (FRAME_BOTTOM_DIVIDER_WIDTH (f) != old)
     {
-      adjust_frame_size (f, -1, -1, 4, 0);
+      adjust_frame_size (f, -1, -1, 4, 0, Qbottom_divider_width);
       adjust_frame_glyphs (f);
       SET_FRAME_GARBAGED (f);
     }
@@ -3765,7 +3780,7 @@ x_set_vertical_scroll_bars (struct frame *f, Lisp_Object arg, Lisp_Object oldval
         However, if the window hasn't been created yet, we shouldn't
         call x_set_window_size.  */
       if (FRAME_X_WINDOW (f))
-       adjust_frame_size (f, -1, -1, 3, 0);
+       adjust_frame_size (f, -1, -1, 3, 0, Qvertical_scroll_bars);
 
       SET_FRAME_GARBAGED (f);
     }
@@ -3785,7 +3800,7 @@ x_set_horizontal_scroll_bars (struct frame *f, Lisp_Object arg, Lisp_Object oldv
         However, if the window hasn't been created yet, we shouldn't
         call x_set_window_size.  */
       if (FRAME_X_WINDOW (f))
-       adjust_frame_size (f, -1, -1, 3, 0);
+       adjust_frame_size (f, -1, -1, 3, 0, Qhorizontal_scroll_bars);
 
       SET_FRAME_GARBAGED (f);
     }
@@ -3802,7 +3817,7 @@ x_set_scroll_bar_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
       x_set_scroll_bar_default_width (f);
 
       if (FRAME_X_WINDOW (f))
-       adjust_frame_size (f, -1, -1, 3, 0);
+       adjust_frame_size (f, -1, -1, 3, 0, Qscroll_bar_width);
 
       SET_FRAME_GARBAGED (f);
     }
@@ -3812,7 +3827,7 @@ x_set_scroll_bar_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
       FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = XFASTINT (arg);
       FRAME_CONFIG_SCROLL_BAR_COLS (f) = (XFASTINT (arg) + unit - 1) / unit;
       if (FRAME_X_WINDOW (f))
-       adjust_frame_size (f, -1, -1, 3, 0);
+       adjust_frame_size (f, -1, -1, 3, 0, Qscroll_bar_width);
 
       SET_FRAME_GARBAGED (f);
     }
@@ -3832,7 +3847,7 @@ x_set_scroll_bar_height (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
       x_set_scroll_bar_default_height (f);
 
       if (FRAME_X_WINDOW (f))
-       adjust_frame_size (f, -1, -1, 3, 0);
+       adjust_frame_size (f, -1, -1, 3, 0, Qscroll_bar_height);
 
       SET_FRAME_GARBAGED (f);
     }
@@ -3842,7 +3857,7 @@ x_set_scroll_bar_height (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
       FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = XFASTINT (arg);
       FRAME_CONFIG_SCROLL_BAR_LINES (f) = (XFASTINT (arg) + unit - 1) / unit;
       if (FRAME_X_WINDOW (f))
-       adjust_frame_size (f, -1, -1, 3, 0);
+       adjust_frame_size (f, -1, -1, 3, 0, Qscroll_bar_height);
 
       SET_FRAME_GARBAGED (f);
     }
@@ -4785,12 +4800,21 @@ syms_of_frame (void)
 
   DEFSYM (Qterminal, "terminal");
 
-  DEFSYM (Qgeometry, "geometry");
   DEFSYM (Qworkarea, "workarea");
   DEFSYM (Qmm_size, "mm-size");
   DEFSYM (Qframes, "frames");
   DEFSYM (Qsource, "source");
 
+  DEFSYM (Qframe_position, "frame-position");
+  DEFSYM (Qframe_outer_size, "frame-outer-size");
+  DEFSYM (Qexternal_border_size, "external-border-size");
+  DEFSYM (Qtitle_height, "title-height");
+  DEFSYM (Qmenu_bar_external, "menu-bar-external");
+  DEFSYM (Qmenu_bar_size, "menu-bar-size");
+  DEFSYM (Qtool_bar_external, "tool-bar-external");
+  DEFSYM (Qtool_bar_size, "tool-bar-size");
+  DEFSYM (Qframe_inner_size, "frame-inner-size");
+
 #ifdef HAVE_NS
   DEFSYM (Qns_parse_geometry, "ns-parse-geometry");
 #endif
@@ -4985,13 +5009,49 @@ fullscreen.  To resize your initial frame pixelwise, set this option to
 a non-nil value in your init file.  */);
   frame_resize_pixelwise = 0;
 
-  DEFVAR_BOOL ("frame-inhibit-implied-resize", frame_inhibit_implied_resize,
-              doc: /* Non-nil means do not resize frames implicitly.
-If this option is nil, setting default font, menubar mode, fringe width,
-or scroll bar mode of a specific frame may resize the frame in order to
-preserve the number of columns or lines it displays.  If this option is
-non-nil, no such resizing is done.  */);
-  frame_inhibit_implied_resize = 0;
+  DEFVAR_LISP ("frame-inhibit-implied-resize", frame_inhibit_implied_resize,
+              doc: /* Whether frames should be resized implicitly.
+If this option is nil, setting font, menu bar, tool bar, internal
+borders, fringes or scroll bars of a specific frame may resize the frame
+in order to preserve the number of columns or lines it displays.  If
+this option is `t', no such resizing is done.  Note that the size of
+fullscreen and maximized frames, the height of fullheight frames and the
+width of fullwidth frames never change implicitly.
+
+The value of this option can be also be a list of frame parameters.  In
+this case, resizing is inhibited when changing a parameter that appears
+in that list.  The parameters currently handled by this option include
+`font', `font-backend', `internal-border-width', `menu-bar-lines' and
+`tool-bar-lines'.
+
+Changing any of the parameters `scroll-bar-width', `scroll-bar-height',
+`vertical-scroll-bars', `horizontal-scroll-bars', `left-fringe' and
+`right-fringe' is handled as if the frame contained just one live
+window.  This means, for example, that removing vertical scroll bars on
+a frame containing several side by side windows will shrink the frame
+width by the width of one scroll bar provided this option is nil and
+keep it unchanged if this option is either `t' or a list containing
+`vertical-scroll-bars'.
+
+The default value is '(tool-bar-lines) on Lucid, Motif and Windows
+(which means that adding/removing a tool bar does not change the frame
+height), nil on all other window systems including GTK+ (which means
+that changing any of the parameters listed above may change the size of
+the frame), and `t' otherwise (which means the frame size never changes
+implicitly when there's no window system support).
+
+Note that when a frame is not large enough to accommodate a change of
+any of the parameters listed above, Emacs may try to enlarge the frame
+even if this option is non-nil.  */);
+#if defined (HAVE_WINDOW_SYSTEM)
+#if defined (USE_LUCID) || defined (USE_MOTIF) || defined (HAVE_NTGUI)
+  frame_inhibit_implied_resize = list1 (Qtool_bar_lines);
+#else
+  frame_inhibit_implied_resize = Qnil;
+#endif
+#else
+  frame_inhibit_implied_resize = Qt;
+#endif
 
   staticpro (&Vframe_list);
 
index 22f2fa7a24c35d196d68c3fe435674109867434e..b5d3bbb5b119e7ae7807101af5395fc2527d88f3 100644 (file)
@@ -1117,8 +1117,8 @@ extern void check_window_system (struct frame *);
 extern void frame_make_pointer_invisible (struct frame *);
 extern void frame_make_pointer_visible (struct frame *);
 extern Lisp_Object delete_frame (Lisp_Object, Lisp_Object);
-extern bool frame_inhibit_resize (struct frame *, bool);
-extern void adjust_frame_size (struct frame *, int, int, int, bool);
+extern bool frame_inhibit_resize (struct frame *, bool, Lisp_Object);
+extern void adjust_frame_size (struct frame *, int, int, int, bool, Lisp_Object);
 
 extern Lisp_Object Vframe_list;
 
@@ -1380,6 +1380,11 @@ extern Lisp_Object Qx_resource_name;
 extern Lisp_Object Qtop, Qbox, Qbottom;
 extern Lisp_Object Qdisplay;
 
+extern Lisp_Object Qframe_position, Qframe_outer_size, Qframe_inner_size;
+extern Lisp_Object Qexternal_border_size, Qtitle_height;
+extern Lisp_Object Qmenu_bar_external, Qmenu_bar_size;
+extern Lisp_Object Qtool_bar_external, Qtool_bar_size;
+
 extern Lisp_Object Qrun_hook_with_args;
 
 #ifdef HAVE_WINDOW_SYSTEM
index 01360244c2e42031abb96c506af3b69bbd0e187d..6db8858923d9d7bfa9147edcba52ef40b5ea1971 100644 (file)
@@ -50,11 +50,11 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "emacsgtkfixed.h"
 #endif
 
-#define FRAME_TOTAL_PIXEL_HEIGHT(f) \
-  (FRAME_PIXEL_HEIGHT (f) + FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f))
+/** #define FRAME_TOTAL_PIXEL_HEIGHT(f) \ **/
+/**   (FRAME_PIXEL_HEIGHT (f) + FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f)) **/
 
-#define FRAME_TOTAL_PIXEL_WIDTH(f) \
-  (FRAME_PIXEL_WIDTH (f) + FRAME_TOOLBAR_WIDTH (f))
+/** #define FRAME_TOTAL_PIXEL_WIDTH(f) \ **/
+/**   (FRAME_PIXEL_WIDTH (f) + FRAME_TOOLBAR_WIDTH (f)) **/
 
 #ifndef HAVE_GTK_WIDGET_SET_HAS_WINDOW
 #define gtk_widget_set_has_window(w, b) \
@@ -940,12 +940,13 @@ xg_frame_set_char_size (struct frame *f, int width, int height)
       x_wait_for_event (f, ConfigureNotify);
     }
   else
-    adjust_frame_size (f, -1, -1, 5, 0);
+    adjust_frame_size (f, -1, -1, 5, 0, Qnil);
 }
 
 /* Handle height/width changes (i.e. add/remove/move menu/toolbar).
    The policy is to keep the number of editable lines.  */
 
+#if 0
 static void
 xg_height_or_width_changed (struct frame *f)
 {
@@ -955,6 +956,7 @@ xg_height_or_width_changed (struct frame *f)
   f->output_data.x->hint_flags = 0;
   x_wm_set_size_hint (f, 0, 0);
 }
+#endif
 
 /* Convert an X Window WSESC on display DPY to its corresponding GtkWidget.
    Must be done like this, because GtkWidget:s can have "hidden"
@@ -3241,7 +3243,7 @@ menubar_map_cb (GtkWidget *w, gpointer user_data)
   if (FRAME_MENUBAR_HEIGHT (f) != req.height)
     {
       FRAME_MENUBAR_HEIGHT (f) = req.height;
-      xg_height_or_width_changed (f);
+      adjust_frame_size (f, -1, -1, 2, 0, Qmenu_bar_lines);
     }
 }
 
@@ -3273,7 +3275,7 @@ xg_update_frame_menubar (struct frame *f)
   if (FRAME_MENUBAR_HEIGHT (f) != req.height)
     {
       FRAME_MENUBAR_HEIGHT (f) = req.height;
-      xg_height_or_width_changed (f);
+      adjust_frame_size (f, -1, -1, 2, 0, Qmenu_bar_lines);
     }
   unblock_input ();
 }
@@ -3295,7 +3297,7 @@ free_frame_menubar (struct frame *f)
           the container.  */
       x->menubar_widget = 0;
       FRAME_MENUBAR_HEIGHT (f) = 0;
-      xg_height_or_width_changed (f);
+      adjust_frame_size (f, -1, -1, 2, 0, Qmenu_bar_lines);
       unblock_input ();
     }
 }
@@ -4219,7 +4221,7 @@ tb_size_cb (GtkWidget    *widget,
      size hints if tool bar size changes.  Seen on Fedora 18 at least.  */
   struct frame *f = user_data;
   if (xg_update_tool_bar_sizes (f))
-    xg_height_or_width_changed (f);
+    adjust_frame_size (f, -1, -1, 2, 0, Qtool_bar_lines);
 }
 
 /* Create a tool bar for frame F.  */
@@ -4819,7 +4821,7 @@ update_frame_tool_bar (struct frame *f)
         xg_pack_tool_bar (f, FRAME_TOOL_BAR_POSITION (f));
       gtk_widget_show_all (x->toolbar_widget);
       if (xg_update_tool_bar_sizes (f))
-        xg_height_or_width_changed (f);
+       adjust_frame_size (f, -1, -1, 2, 0, Qtool_bar_lines);
     }
 
   unblock_input ();
@@ -4867,7 +4869,7 @@ free_frame_tool_bar (struct frame *f)
                              NULL);
         }
 
-      xg_height_or_width_changed (f);
+      adjust_frame_size (f, -1, -1, 2, 0, Qtool_bar_lines);
 
       unblock_input ();
     }
@@ -4897,7 +4899,7 @@ xg_change_toolbar_position (struct frame *f, Lisp_Object pos)
   xg_pack_tool_bar (f, pos);
   g_object_unref (top_widget);
   if (xg_update_tool_bar_sizes (f))
-    xg_height_or_width_changed (f);
+    adjust_frame_size (f, -1, -1, 2, 0, Qtool_bar_lines);
 
   unblock_input ();
 }
index 1537adbc56d6cef914d9730842060f7660576824..16f4ba3b579f2a62c022b84caa023b9db0e44af3 100644 (file)
@@ -731,7 +731,7 @@ x_set_internal_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldva
     return;
 
   if (FRAME_X_WINDOW (f) != 0)
-    adjust_frame_size (f, -1, -1, 3, 0);
+    adjust_frame_size (f, -1, -1, 3, 0, Qinternal_border_width);
 
   SET_FRAME_GARBAGED (f);
 }
@@ -1275,7 +1275,7 @@ This function is an internal primitive--use `make-frame' instead.  */)
 
   /* Read comment about this code in corresponding place in xfns.c.  */
   adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
-                    FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 5, 1);
+                    FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 5, 1, Qnil);
 
   /* The resources controlling the menu-bar and tool-bar are
      processed specially at startup, and reflected in the mode
@@ -1349,7 +1349,7 @@ This function is an internal primitive--use `make-frame' instead.  */)
   /* Consider frame official, now.  */
   f->official = true;
 
-  adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 0, 1);
+  adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 0, 1, Qnil);
 
   if (! f->output_data.ns->explicit_parent)
     {
index 829347b2c6cc059e0dca03e1bc90770618d46cbf..95821df6c61bf64bfc554e3dde44fa2be48f9213 100644 (file)
@@ -1645,7 +1645,7 @@ x_set_internal_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldva
 
       if (FRAME_X_WINDOW (f) != 0)
        {
-         adjust_frame_size (f, -1, -1, 3, 0);
+         adjust_frame_size (f, -1, -1, 3, 0, Qinternal_border_width);
 
          if (FRAME_VISIBLE_P (f))
            x_clear_under_internal_border (f);
@@ -1691,7 +1691,7 @@ x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
         of the outer rectangle (including decorations) unchanged, and a
         second time because we want to keep the height of the inner
         rectangle (without the decorations unchanged).  */
-      adjust_frame_size (f, -1, -1, 2, 1);
+      adjust_frame_size (f, -1, -1, 2, 1, Qmenu_bar_lines);
 
       /* Not sure whether this is needed.  */
       x_clear_under_internal_border (f);
@@ -1721,7 +1721,15 @@ x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
   else
     nlines = 0;
 
-  x_change_tool_bar_height (f, nlines * FRAME_LINE_HEIGHT (f));
+  if (nlines == 0)
+    x_change_tool_bar_height (f, nlines * FRAME_LINE_HEIGHT (f));
+  else
+    {
+      f->n_tool_bar_rows = 0;
+      FRAME_TOOL_BAR_LINES (f) = nlines;
+      adjust_frame_glyphs (f);
+      SET_FRAME_GARBAGED (f);
+    }
 }
 
 
@@ -1741,10 +1749,10 @@ x_change_tool_bar_height (struct frame *f, int height)
   /* Recalculate tool bar and frame text sizes.  */
   FRAME_TOOL_BAR_HEIGHT (f) = height;
   FRAME_TOOL_BAR_LINES (f) = lines;
-  FRAME_TEXT_HEIGHT (f)
-    = FRAME_PIXEL_TO_TEXT_HEIGHT (f, FRAME_PIXEL_HEIGHT (f));
-  FRAME_LINES (f)
-    = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, FRAME_PIXEL_HEIGHT (f));
+/**   FRAME_TEXT_HEIGHT (f) **/
+/**     = FRAME_PIXEL_TO_TEXT_HEIGHT (f, FRAME_PIXEL_HEIGHT (f)); **/
+/**   FRAME_LINES (f) **/
+/**     = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, FRAME_PIXEL_HEIGHT (f)); **/
   /* Store the `tool-bar-lines' and `height' frame parameters.  */
   store_frame_param (f, Qtool_bar_lines, make_number (lines));
   store_frame_param (f, Qheight, make_number (FRAME_LINES (f)));
@@ -1761,7 +1769,8 @@ x_change_tool_bar_height (struct frame *f, int height)
   /* Recalculate toolbar height.  */
   f->n_tool_bar_rows = 0;
 
-  adjust_frame_size (f, -1, -1, 4, 0);
+  adjust_frame_size (f, -1, -1, (old_height == 0 || height == 0) ? 2 : 4, 0,
+                    Qtool_bar_lines);
 
   if (FRAME_X_WINDOW (f))
     x_clear_under_internal_border (f);
@@ -4629,7 +4638,7 @@ This function is an internal primitive--use `make-frame' instead.  */)
      had one frame line vs one toolbar line which left us with a zero
      root window height which was obviously wrong as well ...  */
   adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
-                    FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 5, 1);
+                    FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 5, 1, Qnil);
 
   /* The X resources controlling the menu-bar and tool-bar are
      processed specially at startup, and reflected in the mode
@@ -4697,7 +4706,7 @@ This function is an internal primitive--use `make-frame' instead.  */)
   /* Consider frame official, now.  */
   f->official = true;
 
-  adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 0, 1);
+  adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 0, 1, Qnil);
 
   /* Tell the server what size and position, etc, we want, and how
      badly we want them.  This should be done after we have the menu
@@ -5797,7 +5806,7 @@ x_create_tip_frame (struct w32_display_info *dpyinfo,
   SET_FRAME_COLS (f, 0);
   SET_FRAME_LINES (f, 0);
   adjust_frame_size (f, width * FRAME_COLUMN_WIDTH (f),
-                    height * FRAME_LINE_HEIGHT (f), 0, 1);
+                    height * FRAME_LINE_HEIGHT (f), 0, 1, Qnil);
 
   /* Add `tooltip' frame parameter's default value. */
   if (NILP (Fframe_parameter (frame, Qtooltip)))
@@ -7368,30 +7377,33 @@ This is a direct interface to the Windows API FindWindow function.  */)
 
 DEFUN ("w32-frame-menu-bar-size", Fw32_frame_menu_bar_size, Sw32_frame_menu_bar_size, 0, 1, 0,
        doc: /* Return sizes of menu bar on frame FRAME.
-The return value is a list of three elements: The current width and
-height of FRAME's menu bar in pixels and the default height of the menu
-bar in pixels.  If FRAME is omitted or nil, the selected frame is
-used.  */)
+The return value is a list of four elements: The current width and
+height of FRAME's menu bar in pixels, the height of one menu bar line in
+a wrapped menu bar in pixels, and the height of a single line menu bar
+in pixels.
+
+If FRAME is omitted or nil, the selected frame is used.  */)
   (Lisp_Object frame)
 {
   struct frame *f = decode_any_frame (frame);
-  MENUBARINFO info;
-  int width, height, default_height;
+  MENUBARINFO menu_bar;
+  int width, height, single_height, wrapped_height;
 
   block_input ();
 
-  default_height = GetSystemMetrics (SM_CYMENUSIZE);
-  info.cbSize = sizeof (info);
-  info.rcBar.right = info.rcBar.left = 0;
-  info.rcBar.top = info.rcBar.bottom = 0;
-  GetMenuBarInfo (FRAME_W32_WINDOW (f), 0xFFFFFFFD, 0, &info);
-  width = info.rcBar.right - info.rcBar.left;
-  height = info.rcBar.bottom - info.rcBar.top;
+  single_height = GetSystemMetrics (SM_CYMENU);
+  wrapped_height = GetSystemMetrics (SM_CYMENUSIZE);
+  menu_bar.cbSize = sizeof (menu_bar);
+  menu_bar.rcBar.right = menu_bar.rcBar.left = 0;
+  menu_bar.rcBar.top = menu_bar.rcBar.bottom = 0;
+  GetMenuBarInfo (FRAME_W32_WINDOW (f), 0xFFFFFFFD, 0, &menu_bar);
+  width = menu_bar.rcBar.right - menu_bar.rcBar.left;
+  height = menu_bar.rcBar.bottom - menu_bar.rcBar.top;
 
   unblock_input ();
 
-  return list3 (make_number (width), make_number (height),
-               make_number (default_height));
+  return list4 (make_number (width), make_number (height),
+               make_number (wrapped_height), make_number (single_height));
 }
 
 DEFUN ("w32-frame-rect", Fw32_frame_rect, Sw32_frame_rect, 0, 2, 0,
@@ -7408,15 +7420,131 @@ title bar and decorations.  */)
   struct frame *f = decode_live_frame (frame);
   RECT rect;
 
+  block_input ();
+
   if (!NILP (client))
     GetClientRect (FRAME_W32_WINDOW (f), &rect);
   else
     GetWindowRect (FRAME_W32_WINDOW (f), &rect);
 
+  unblock_input ();
+
   return list4 (make_number (rect.left), make_number (rect.top),
                make_number (rect.right), make_number (rect.bottom));
 }
 
+DEFUN ("x-frame-geometry", Fx_frame_geometry, Sx_frame_geometry, 0, 1, 0,
+       doc: /* Return geometric atributes of frame FRAME.
+FRAME must be a live frame and defaults to the selected one.
+
+The return value is an association list containing the following
+elements (all size values are in pixels).
+
+- `frame-outer-size' is a cons of the outer width and height of FRAME.
+  The outer size includes the title bar and the external borders as well
+  as any menu and/or tool bar of frame.
+
+- `border' is a cons of the horizontal and vertical width of FRAME's
+  external borders.
+
+- `title-bar-height' is the height of the title bar of FRAME.
+
+- `menu-bar-external' if `t' means the menu bar is by default external
+  (not included in the inner size of FRAME).
+
+- `menu-bar-size' is a cons of the width and height of the menu bar of
+  FRAME.
+
+- `tool-bar-external' if `t' means the tool bar is by default external
+  (not included in the inner size of FRAME).
+
+- `tool-bar-side' tells tells on which side the tool bar on FRAME is by
+  default and can be one of `left', `top', `right' or `bottom'.
+
+- `tool-bar-size' is a cons of the width and height of the tool bar of
+  FRAME.
+
+- `frame-inner-size' is a cons of the inner width and height of FRAME.
+  This excludes FRAME's title bar and external border as well as any
+  external menu and/or tool bar.  */)
+  (Lisp_Object frame)
+{
+  struct frame *f = decode_live_frame (frame);
+  Lisp_Object geometry = Qnil;
+  RECT frame_outer_edges, frame_inner_edges;
+  MENUBARINFO menu_bar;
+  int  border_width, border_height, title_height;
+  int single_bar_height, wrapped_bar_height, menu_bar_height;
+  Lisp_Object fullscreen = Fframe_parameter (frame, Qfullscreen);
+
+  block_input ();
+
+  /* Outer frame rectangle, including outer borders and title bar. */
+  GetWindowRect (FRAME_W32_WINDOW (f), &frame_outer_edges);
+  /* Inner frame rectangle, excluding borders and title bar.  */
+  GetClientRect (FRAME_W32_WINDOW (f), &frame_inner_edges);
+  /* Outer border.  */
+  border_width = GetSystemMetrics (SM_CXFRAME);
+  border_height = GetSystemMetrics (SM_CYFRAME);
+  /* Title bar.  */
+  title_height = GetSystemMetrics (SM_CYCAPTION);
+  /* Menu bar.  */
+  menu_bar.cbSize = sizeof (menu_bar);
+  menu_bar.rcBar.right = menu_bar.rcBar.left = 0;
+  menu_bar.rcBar.top = menu_bar.rcBar.bottom = 0;
+  GetMenuBarInfo (FRAME_W32_WINDOW (f), 0xFFFFFFFD, 0, &menu_bar);
+  single_bar_height = GetSystemMetrics (SM_CYMENU);
+  wrapped_bar_height = GetSystemMetrics (SM_CYMENUSIZE);
+  unblock_input ();
+
+  menu_bar_height = menu_bar.rcBar.bottom - menu_bar.rcBar.top;
+  /* Fix menu bar height reported by GetMenuBarInfo.  */
+  if (menu_bar_height > single_bar_height)
+    /* A wrapped menu bar.  */
+    menu_bar_height += single_bar_height - wrapped_bar_height;
+  else if (menu_bar_height > 0)
+    /* A single line menu bar.  */
+    menu_bar_height = single_bar_height;
+
+  return
+    listn (CONSTYPE_PURE, 10,
+          Fcons (Qframe_position,
+                 Fcons (make_number (frame_outer_edges.left),
+                        make_number (frame_outer_edges.top))),
+          Fcons (Qframe_outer_size,
+                 Fcons (make_number
+                        (frame_outer_edges.right - frame_outer_edges.left),
+                        make_number
+                        (frame_outer_edges.bottom - frame_outer_edges.top))),
+          Fcons (Qexternal_border_size,
+                 ((EQ (fullscreen, Qfullboth) || EQ (fullscreen, Qfullscreen))
+                  ? Fcons (make_number (0), make_number (0))
+                  : Fcons (make_number (border_width),
+                           make_number (border_height)))),
+          Fcons (Qtitle_height,
+                 ((EQ (fullscreen, Qfullboth) || EQ (fullscreen, Qfullscreen))
+                  ? make_number (0)
+                  : make_number (title_height))),
+          Fcons (Qmenu_bar_external, Qt),
+          Fcons (Qmenu_bar_size,
+                 Fcons (make_number
+                        (menu_bar.rcBar.right - menu_bar.rcBar.left),
+                        make_number (menu_bar_height))),
+          Fcons (Qtool_bar_external, Qnil),
+          Fcons (Qtool_bar_position, Qtop),
+          Fcons (Qtool_bar_size,
+                 Fcons (make_number (FRAME_TOOL_BAR_LINES (f)
+                                     ? (FRAME_PIXEL_WIDTH (f)
+                                        - 2 * FRAME_INTERNAL_BORDER_WIDTH (f))
+                                     : 0),
+                        make_number (FRAME_TOOL_BAR_HEIGHT (f)))),
+          Fcons (Qframe_inner_size,
+                 Fcons (make_number
+                        (frame_inner_edges.right - frame_inner_edges.left),
+                        make_number
+                        (frame_inner_edges.bottom - frame_inner_edges.top))));
+}
+
 DEFUN ("w32-battery-status", Fw32_battery_status, Sw32_battery_status, 0, 0, 0,
        doc: /* Get power status information from Windows system.
 
@@ -8411,6 +8539,7 @@ only be necessary if the default setting causes problems.  */);
   defsubr (&Sx_open_connection);
   defsubr (&Sx_close_connection);
   defsubr (&Sx_display_list);
+  defsubr (&Sx_frame_geometry);
   defsubr (&Sx_synchronize);
 
   /* W32 specific functions */
index 9f777167bf07298a76acda014d1639ba383b236c..6633ffddbcf0eb6866d99ab5fc3651f01d1cbfcb 100644 (file)
@@ -504,7 +504,7 @@ set_frame_menubar (struct frame *f, bool first_time, bool deep_p)
        area remains the same, if menubar has just been created.  */
     if (old_widget == NULL)
       adjust_frame_size (f, FRAME_TEXT_WIDTH (f),
-                        FRAME_TEXT_HEIGHT (f), 2, 0);
+                        FRAME_TEXT_HEIGHT (f), 2, 0, Qmenu_bar_lines);
   }
 
   unblock_input ();
index 4cffa3818cef27b67e0072a432e7e503b2a9c6b9..c2a37d078a82f900db8e49a25cb7a8d3d56a8a38 100644 (file)
@@ -5843,7 +5843,7 @@ x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
         problems because the tip frame has no widget.  */
       if (NILP (tip_frame) || XFRAME (tip_frame) != f)
        adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
-                          FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 3, 0);
+                          FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 3, 0, Qfont);
     }
 
   /* X version sets font of input methods here also.  */
index baa6a2ab9174daeb9b8673879fbe604325b2e9fd..ecf145199f2c42c71e1c79893e74031dd55d5ff8 100644 (file)
@@ -644,7 +644,8 @@ EmacsFrameSetCharSize (Widget widget, int columns, int rows)
   EmacsFrame ew = (EmacsFrame) widget;
   struct frame *f = ew->emacs_frame.frame;
 
-  if (!frame_inhibit_resize (f, 0) && !frame_inhibit_resize (f, 1))
+  if (!frame_inhibit_resize (f, 0, Qfont)
+      && !frame_inhibit_resize (f, 1, Qfont))
     x_set_window_size (f, 0, columns, rows, 0);
 }
 
index 2c9292d5b02de5f0f5d91370659401ea0255d59d..168ef1e3b9d99ff7c6d881cfc349d07f83b07980 100644 (file)
@@ -6417,7 +6417,7 @@ the return value is nil.  Otherwise the value is t.  */)
       /* Make frame official again and apply frame size changes if
         needed.  */
       f->official = true;
-      adjust_frame_size (f, -1, -1, 1, 0);
+      adjust_frame_size (f, -1, -1, 1, 0, Qnil);
 
       adjust_frame_glyphs (f);
       unblock_input ();
index 8f5a06c0330705970694fb9b5bf9f5df3fe06518..10eb3336fad6531b9ba8e7860e617ee48b8d2b3e 100644 (file)
@@ -1009,7 +1009,7 @@ x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
 #else /* not USE_X_TOOLKIT && not USE_GTK */
   FRAME_MENU_BAR_LINES (f) = nlines;
   FRAME_MENU_BAR_HEIGHT (f) = nlines * FRAME_LINE_HEIGHT (f);
-  adjust_frame_size (f, -1, -1, 2, 1);
+  adjust_frame_size (f, -1, -1, 2, 1, Qmenu_bar_lines);
   if (FRAME_X_WINDOW (f))
     x_clear_under_internal_border (f);
 
@@ -1075,7 +1075,19 @@ x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
   else
     nlines = 0;
 
+#ifdef USE_GTK
   x_change_tool_bar_height (f, nlines * FRAME_LINE_HEIGHT (f));
+#else /* !USE_GTK */
+  if (nlines == 0)
+    x_change_tool_bar_height (f, nlines * FRAME_LINE_HEIGHT (f));
+  else
+    {
+      f->n_tool_bar_rows = 0;
+      FRAME_TOOL_BAR_LINES (f) = nlines;
+      adjust_frame_glyphs (f);
+      SET_FRAME_GARBAGED (f);
+    }
+#endif /* USE_GTK */
 }
 
 
@@ -1112,10 +1124,10 @@ x_change_tool_bar_height (struct frame *f, int height)
   /* Recalculate tool bar and frame text sizes.  */
   FRAME_TOOL_BAR_HEIGHT (f) = height;
   FRAME_TOOL_BAR_LINES (f) = lines;
-  FRAME_TEXT_HEIGHT (f)
-    = FRAME_PIXEL_TO_TEXT_HEIGHT (f, FRAME_PIXEL_HEIGHT (f));
-  FRAME_LINES (f)
-    = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, FRAME_PIXEL_HEIGHT (f));
+/**   FRAME_TEXT_HEIGHT (f) **/
+/**     = FRAME_PIXEL_TO_TEXT_HEIGHT (f, FRAME_PIXEL_HEIGHT (f)); **/
+/**   FRAME_LINES (f) **/
+/**     = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, FRAME_PIXEL_HEIGHT (f)); **/
   /* Store the `tool-bar-lines' and `height' frame parameters.  */
   store_frame_param (f, Qtool_bar_lines, make_number (lines));
   store_frame_param (f, Qheight, make_number (FRAME_LINES (f)));
@@ -1138,7 +1150,8 @@ x_change_tool_bar_height (struct frame *f, int height)
   /* Recalculate toolbar height.  */
   f->n_tool_bar_rows = 0;
 
-  adjust_frame_size (f, -1, -1, 4, 0);
+  adjust_frame_size (f, -1, -1, (old_height == 0 || height == 0) ? 2 : 4, 0,
+                    Qtool_bar_lines);
 
   if (FRAME_X_WINDOW (f))
     x_clear_under_internal_border (f);
@@ -1166,7 +1179,7 @@ x_set_internal_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldva
 
       if (FRAME_X_WINDOW (f) != 0)
        {
-         adjust_frame_size (f, -1, -1, 3, 0);
+         adjust_frame_size (f, -1, -1, 3, 0, Qinternal_border_width);
 
 #ifdef USE_GTK
          xg_clear_under_internal_border (f);
@@ -3163,7 +3176,7 @@ This function is an internal primitive--use `make-frame' instead.  */)
      had one frame line vs one toolbar line which left us with a zero
      root window height which was obviously wrong as well ...  */
   adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
-                    FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 5, 1);
+                    FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 5, 1, Qnil);
 
   /* Set the menu-bar-lines and tool-bar-lines parameters.  We don't
      look up the X resources controlling the menu-bar and tool-bar
@@ -3237,7 +3250,7 @@ This function is an internal primitive--use `make-frame' instead.  */)
   /* Consider frame official, now.  */
   f->official = true;
 
-  adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 0, 1);
+  adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 0, 1, Qnil);
 
 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
   /* Create the menu bar.  */
@@ -4221,6 +4234,124 @@ Internal use only, use `display-monitor-attributes-list' instead.  */)
   return attributes_list;
 }
 
+DEFUN ("x-frame-geometry", Fx_frame_geometry, Sx_frame_geometry, 0, 1, 0,
+       doc: /* Return geometric atributes of frame FRAME.
+
+FRAME must be a live frame and defaults to the selected one.
+
+The return value is an association list containing the following
+elements (all size values are in pixels).
+
+- `frame-outer-size' is a cons of the outer width and height of FRAME.
+  The outer size include the title bar and the external borders as well
+  as any menu and/or tool bar of frame.
+
+- `border' is a cons of the horizontal and vertical width of FRAME's
+  external borders.
+
+- `title-bar-height' is the height of the title bar of FRAME.
+
+- `menu-bar-external' if `t' means the menu bar is external (not
+  included in the inner edges of FRAME).
+
+- `menu-bar-size' is a cons of the width and height of the menu bar of
+  FRAME.
+
+- `tool-bar-external' if `t' means the tool bar is external (not
+  included in the inner edges of FRAME).
+
+- `tool-bar-side' tells tells on which side the tool bar on FRAME is and
+  can be one of `left', `top', `right' or `bottom'.
+
+- `tool-bar-size' is a cons of the width and height of the tool bar of
+  FRAME.
+
+- `frame-inner-size' is a cons of the inner width and height of FRAME.
+  This excludes FRAME's title bar and external border as well as any
+  external menu and/or tool bar.  */)
+  (Lisp_Object frame)
+{
+  struct frame *f = decode_live_frame (frame);
+  int inner_width = FRAME_PIXEL_WIDTH (f);
+  int inner_height = FRAME_PIXEL_HEIGHT (f);
+  int outer_width, outer_height, border, title;
+  Lisp_Object fullscreen = Fframe_parameter (frame, Qfullscreen);
+  int menu_bar_height, menu_bar_width, tool_bar_height, tool_bar_width;
+
+  border = FRAME_OUTER_TO_INNER_DIFF_X (f);
+  title = FRAME_X_OUTPUT (f)->y_pixels_outer_diff - border;
+
+  outer_width = FRAME_PIXEL_WIDTH (f) + 2 * border;
+  outer_height = (FRAME_PIXEL_HEIGHT (f)
+                 + FRAME_OUTER_TO_INNER_DIFF_Y (f)
+                 + FRAME_OUTER_TO_INNER_DIFF_X (f));
+
+#if defined (USE_GTK)
+  {
+    bool tool_bar_left_right = (EQ (FRAME_TOOL_BAR_POSITION (f), Qleft)
+                               || EQ (FRAME_TOOL_BAR_POSITION (f), Qright));
+
+    tool_bar_width = (tool_bar_left_right
+                     ? FRAME_TOOLBAR_WIDTH (f)
+                     : FRAME_PIXEL_WIDTH (f));
+    tool_bar_height = (tool_bar_left_right
+                      ? FRAME_PIXEL_HEIGHT (f)
+                      : FRAME_TOOLBAR_HEIGHT (f));
+    if (tool_bar_left_right)
+      /* For some reason FRAME_OUTER_TO_INNER_DIFF_X does not count the
+        width of a tool bar.  */
+      outer_width += FRAME_TOOLBAR_WIDTH (f);
+  }
+#else
+  tool_bar_height = FRAME_TOOL_BAR_HEIGHT (f);
+  tool_bar_width = ((tool_bar_height > 0)
+                   ? outer_width - 2 * FRAME_INTERNAL_BORDER_WIDTH (f)
+                   : 0);
+#endif
+
+#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
+  menu_bar_height = FRAME_MENUBAR_HEIGHT (f);
+#else
+  menu_bar_height = FRAME_MENU_BAR_HEIGHT (f);
+#endif
+
+  menu_bar_width = ((menu_bar_height > 0)
+                   ? outer_width - 2 * border
+                   : 0);
+
+  if (!FRAME_EXTERNAL_MENU_BAR (f))
+    inner_height -= menu_bar_height;
+  if (!FRAME_EXTERNAL_TOOL_BAR (f))
+    inner_height -= tool_bar_height;
+
+  return
+    listn (CONSTYPE_PURE, 10,
+          Fcons (Qframe_position,
+                 Fcons (make_number (f->left_pos), make_number (f->top_pos))),
+          Fcons (Qframe_outer_size,
+                 Fcons (make_number (outer_width), make_number (outer_height))),
+          Fcons (Qexternal_border_size,
+                 ((EQ (fullscreen, Qfullboth) || EQ (fullscreen, Qfullscreen))
+                  ? Fcons (make_number (0), make_number (0))
+                  : Fcons (make_number (border), make_number (border)))),
+          Fcons (Qtitle_height,
+                 ((EQ (fullscreen, Qfullboth) || EQ (fullscreen, Qfullscreen))
+                  ? make_number (0)
+                  : make_number (title))),
+          Fcons (Qmenu_bar_external, FRAME_EXTERNAL_MENU_BAR (f) ? Qt : Qnil),
+          Fcons (Qmenu_bar_size,
+                 Fcons (make_number (menu_bar_width),
+                        make_number (menu_bar_height))),
+          Fcons (Qtool_bar_external, FRAME_EXTERNAL_TOOL_BAR (f) ? Qt : Qnil),
+          Fcons (Qtool_bar_position, FRAME_TOOL_BAR_POSITION (f)),
+          Fcons (Qtool_bar_size,
+                 Fcons (make_number (tool_bar_width),
+                        make_number (tool_bar_height))),
+          Fcons (Qframe_inner_size,
+                 Fcons (make_number (inner_width),
+                        make_number (inner_height))));
+}
+
 /************************************************************************
                              X Displays
  ************************************************************************/
@@ -6224,6 +6355,7 @@ When using Gtk+ tooltips, the tooltip face is not used.  */);
   defsubr (&Sx_display_backing_store);
   defsubr (&Sx_display_save_under);
   defsubr (&Sx_display_monitor_attributes_list);
+  defsubr (&Sx_frame_geometry);
   defsubr (&Sx_wm_set_size_hint);
   defsubr (&Sx_create_frame);
   defsubr (&Sx_open_connection);
index eb783fe5070871d7b5e2e99bc13c7d794038cc90..0f69ee28e847dc307d45ba7362ea9e5c5b539379 100644 (file)
@@ -657,9 +657,15 @@ update_frame_menubar (struct frame *f)
   lw_refigure_widget (x->column_widget, True);
 
   /* Force the pane widget to resize itself.  */
-  adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 2, 0);
+#ifdef USE_LUCID
+  /* For reasons I don't know Lucid wants to add one pixel to the frame
+     height when adding the menu bar.  Compensate that here.  */
+  adjust_frame_size (f, -1, FRAME_TEXT_HEIGHT (f) - 1, 2, 0, Qmenu_bar_lines);
+#else
+  adjust_frame_size (f, -1, -1, 2, 0, Qmenu_bar_lines);
+#endif /* USE_LUCID */
   unblock_input ();
-#endif
+#endif /* USE_GTK */
 }
 
 #ifdef USE_LUCID
@@ -1050,6 +1056,12 @@ void
 free_frame_menubar (struct frame *f)
 {
   Widget menubar_widget;
+#ifdef USE_MOTIF
+  /* Motif automatically shrinks the frame in lw_destroy_all_widgets.
+     If we want to preserve the old height, calculate it now so we can
+     restore it below.  */
+  int old_height = FRAME_TEXT_HEIGHT (f) + FRAME_MENUBAR_HEIGHT (f);
+#endif
 
   eassert (FRAME_X_P (f));
 
@@ -1087,17 +1099,20 @@ free_frame_menubar (struct frame *f)
          XtVaGetValues (f->output_data.x->widget, XtNx, &x1, XtNy, &y1, NULL);
          if (x1 == 0 && y1 == 0)
            XtVaSetValues (f->output_data.x->widget, XtNx, x0, XtNy, y0, NULL);
-#endif
-         adjust_frame_size (f, FRAME_TEXT_WIDTH (f),
-                            FRAME_TEXT_HEIGHT (f), 2, 0);
-         /*
-           if (frame_inhibit_resize (f, 0))
-           change_frame_size (f, 0, 0, 0, 0, 0, 1);
+         if (frame_inhibit_resize (f, 0, Qmenu_bar_lines))
+           adjust_frame_size (f, -1, old_height, 1, 0, Qmenu_bar_lines);
          else
-           x_set_window_size (f, 0, FRAME_TEXT_WIDTH (f),
-           FRAME_TEXT_HEIGHT (f), 1);
-         */
+#endif /* USE_MOTIF */
+           adjust_frame_size (f, -1, -1, 2, 0, Qmenu_bar_lines);
        }
+      else
+       {
+#ifdef USE_MOTIF
+         if (frame_inhibit_resize (f, 0, Qmenu_bar_lines))
+           adjust_frame_size (f, -1, old_height, 1, 0, Qmenu_bar_lines);
+#endif
+       }
+
       unblock_input ();
     }
 }
index 53eb7b3625d8a1e372e34aa4e0ab99cf84447fa4..98f2a27c1ce63bc7ca07cbbab85519531fe3e3d6 100644 (file)
@@ -8662,8 +8662,9 @@ x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
         doing it because it's done in Fx_show_tip, and it leads to
         problems because the tip frame has no widget.  */
       if (NILP (tip_frame) || XFRAME (tip_frame) != f)
-       x_set_window_size (f, 0, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
-                          FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 1);
+         adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
+                            FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 3,
+                            0, Qfont);
     }
 
 #ifdef HAVE_X_I18N