changeset 5045:c3cc3fa503a2

more frame-sizing cleanups -------------------- ChangeLog entries follow: -------------------- man/ChangeLog addition: 2010-02-16 Ben Wing <ben@xemacs.org> * internals/internals.texi (Top): * internals/internals.texi (Modules for the Basic Displayable Lisp Objects): * internals/internals.texi (Creating a Window-System Type): * internals/internals.texi (Window and Frame Geometry): * internals/internals.texi (Intro to Window and Frame Geometry): * internals/internals.texi (The Frame): * internals/internals.texi (The Non-Client Area): * internals/internals.texi (The Client Area): * internals/internals.texi (The Paned Area): * internals/internals.texi (Text Areas): * internals/internals.texi (The Displayable Area): * internals/internals.texi (Which Functions Use Which?): * internals/internals.texi (The Redisplay Mechanism): Integrate the long comment in frame.c into the internals manual. src/ChangeLog addition: 2010-02-16 Ben Wing <ben@xemacs.org> * frame-impl.h: * frame-impl.h (FRAME_INTERNAL_BORDER_WIDTH): * frame-impl.h (FRAME_REAL_TOOLBAR_BOUNDS): * frame-impl.h (FRAME_REAL_TOP_TOOLBAR_BOUNDS): * frame-impl.h (FRAME_BOTTOM_BORDER_START): * frame-impl.h (FRAME_LEFT_BORDER_START): * frame-impl.h (FRAME_RIGHT_BORDER_START): * frame.c (frame_conversion_internal_1): * frame.c (change_frame_size_1): * redisplay-output.c (clear_left_border): * redisplay-output.c (clear_right_border): * redisplay-output.c (redisplay_clear_top_of_window): * redisplay-output.c (redisplay_clear_to_window_end): * redisplay-output.c (redisplay_clear_bottom_of_window): Rename FRAME_BORDER_* to FRAME_INTERNAL_BORDER_*. Add general FRAME_INTERNAL_BORDER_SIZE(). Add FRAME_REAL_TOOLBAR_BOUNDS() to encompass the entire size of the toolbar including its border. Add specific top/left/bottom/right versions of this macro. Rewrite FRAME_*_BORDER_START and FRAME_*_BORDER_END to take into use FRAME_REAL_*_TOOLBAR_BOUNDS(). Add some comments about existing problems in frame sizing and how they might be fixed. Simplify change_frame_size_1() using the macros just created.
author Ben Wing <ben@xemacs.org>
date Tue, 16 Feb 2010 01:21:32 -0600
parents e84a30b0e4a2
children d4f666cda5e6
files man/ChangeLog man/internals/internals.texi src/ChangeLog src/frame-impl.h src/frame.c src/redisplay-output.c
diffstat 6 files changed, 447 insertions(+), 59 deletions(-) [+]
line wrap: on
line diff
--- a/man/ChangeLog	Mon Feb 15 22:58:10 2010 -0600
+++ b/man/ChangeLog	Tue Feb 16 01:21:32 2010 -0600
@@ -1,3 +1,20 @@
+2010-02-16  Ben Wing  <ben@xemacs.org>
+
+	* internals/internals.texi (Top):
+	* internals/internals.texi (Modules for the Basic Displayable Lisp Objects):
+	* internals/internals.texi (Creating a Window-System Type):
+	* internals/internals.texi (Window and Frame Geometry):
+	* internals/internals.texi (Intro to Window and Frame Geometry):
+	* internals/internals.texi (The Frame):
+	* internals/internals.texi (The Non-Client Area):
+	* internals/internals.texi (The Client Area):
+	* internals/internals.texi (The Paned Area):
+	* internals/internals.texi (Text Areas):
+	* internals/internals.texi (The Displayable Area):
+	* internals/internals.texi (Which Functions Use Which?):
+	* internals/internals.texi (The Redisplay Mechanism):
+	Integrate the long comment in frame.c into the internals manual.
+
 2010-02-08  Ben Wing  <ben@xemacs.org>
 
 	* internals/internals.texi (How Lisp Objects Are Represented in C):
--- a/man/internals/internals.texi	Mon Feb 15 22:58:10 2010 -0600
+++ b/man/internals/internals.texi	Tue Feb 16 01:21:32 2010 -0600
@@ -360,6 +360,7 @@
 * Multilingual Support::        
 * Consoles; Devices; Frames; Windows::  
 * Window-System Support::       
+* Window and Frame Geometry::   
 * The Redisplay Mechanism::     
 * Extents::                     
 * Faces::                       
@@ -596,6 +597,17 @@
 
 * Creating a Window-System Type::  
 
+Window and Frame Geometry
+
+* Intro to Window and Frame Geometry::  
+* The Frame::                   
+* The Non-Client Area::         
+* The Client Area::             
+* The Paned Area::              
+* Text Areas::                  
+* The Displayable Area::        
+* Which Functions Use Which?::  
+
 The Redisplay Mechanism
 
 * Critical Redisplay Sections::  
@@ -17668,7 +17680,7 @@
 types such as scrollbars.
 
 
-@node Window-System Support, The Redisplay Mechanism, Consoles; Devices; Frames; Windows, Top
+@node Window-System Support, Window and Frame Geometry, Consoles; Devices; Frames; Windows, Top
 @chapter Window-System Support
 @cindex window-system support
 @cindex window systems
@@ -17851,7 +17863,324 @@
 
 
 
-@node The Redisplay Mechanism, Extents, Window-System Support, Top
+@node Window and Frame Geometry, The Redisplay Mechanism, Window-System Support, Top
+@chapter Window and Frame Geometry
+
+@menu
+* Intro to Window and Frame Geometry::  
+* The Frame::                   
+* The Non-Client Area::         
+* The Client Area::             
+* The Paned Area::              
+* Text Areas::                  
+* The Displayable Area::        
+* Which Functions Use Which?::  
+@end menu
+
+@node Intro to Window and Frame Geometry, The Frame, Window and Frame Geometry, Window and Frame Geometry
+@section Intro to Window and Frame Geometry
+
+Here is an ASCII diagram:
+
+@example
++-----------------------------------------------------------------------------|
+|                          window-manager decoration                          |
+| +-------------------------------------------------------------------------+ |
+| |                                menubar                                  | |
+| ########################################################################### |
+| #                                toolbar                                  # |
+| #-------------------------------------------------------------------------# |
+| #  |                             gutter                                |  # |
+| #  |-------------------------------------------------------------------|  # |
+| #  | |                   internal border width                       | |  # |
+| #  | |-*************************************************************-| |  # |
+|w#  | | *                          |s|v*                          |s* | |  #w|
+|i#  | | *                          |c|e*                          |c* | |  #i|
+|n#  | | *                          |r|r*                          |r* | |  #n|
+|d#  | | *                          |o|t*                          |o* | |  #d|
+|o#  | | *         text area        |l|.*        text area         |l* | |  #o|
+|w#  | |i*                          |l| *                          |l*i| |  #w|
+|-#  | |n*                          |b|d*                          |b*n| |  #-|
+|m#  | |t*                          |a|i*                          |a*t| |  #m|
+|a#  | |.*                          |r|v*                          |r*.| |  #a|
+|n# t| | *--------------------------+-|i*--------------------------+-* | |t #n|
+|a# o|g|b*         scrollbar        | |d*        scrollbar         | *b|g|o #a|
+|g# o|u|o*--------------------------+-|e*--------------------------+-*o|u|o #g|
+|e# l|t|r*         modeline           |r*        modeline            *r|t|l #e|
+|r# b|t|d*************************************************************d|t|b #r|
+| # a|e|e*   =...texttexttex....=   |s|v*                          |s*e|e|a # |
+|d# r|r|r*o m=...texttexttextt..=o m|c|e*                          |c*r|r|r #d|
+|e#  | | *u a=.texttexttextte...=u a|r|r*                          |r* | |  #e|
+|c#  | |w*t r=.....texttexttex..=t r|o|t*                          |o*w| |  #c|
+|o#  | |i*s g=         etc.     =s g|l|.*        text area         |l*i| |  #o|
+|r#  | |d*i i=                  =i i|l| *                          |l*d| |  #r|
+|a#  | |t*d n=                  =d n|b|d*                          |b*t| |  #a|
+|t#  | |h*e  =  inner text area =e  |a|i*                          |a*h| |  #t|
+|i#  | | *   =                  =   |r|v*                          |r* | |  #i|
+|o#  | | *---====================---+-|i*--------------------------+-* | |  #o|
+|n#  | | *         scrollbar        | |d*        scrollbar         | * | |  #n|
+| #  | | *--------------------------+-|e*--------------------------+-* | |  # |
+| #  | | *         modeline           |r*        modeline            * | |  # |
+| #  | | ************************************************************* | |  # |
+| #  | | *                         minibuffer                        * | |  # |
+| #  | | ************************************************************* | |  # |
+| #  | |                    internal border width                      | |  # |
+| #  |-------------------------------------------------------------------|  # |
+| #  |                              gutter                               |  # |
+| #-------------------------------------------------------------------------# |
+| #                                 toolbar                                 # |
+| ########################################################################### |
+|                           window manager decoration                         |
++-----------------------------------------------------------------------------+
+
+   # = boundary of client area; * = window boundaries, boundary of paned area
+   = = boundary of inner text area; . = inside margin area
+@end example
+
+Note in particular what happens at the corners, where a "corner box"
+occurs.  Top and bottom toolbars take precedence over left and right
+toolbars, extending out horizontally into the corner boxes.  Gutters
+work the same way.  The corner box where the scrollbars meet, however,
+is assigned to neither scrollbar, and is known as the "dead box"; it is
+an area that must be cleared specially.
+
+@node The Frame, The Non-Client Area, Intro to Window and Frame Geometry, Window and Frame Geometry
+@section The Frame
+
+The "top-level window area" is the entire area of a top-level window (or
+"frame").  The "client area" (a term from MS Windows) is the area of a
+top-level window that XEmacs draws into and manages with redisplay.
+This includes the toolbar, scrollbars, gutters, dividers, text area,
+modeline and minibuffer.  It does not include the menubar, title or
+outer borders.  The "non-client area" is the area of a top-level window
+outside of the client area and includes the menubar, title and outer
+borders.  Internally, all frame coordinates are relative to the client
+area.
+
+
+@node The Non-Client Area, The Client Area, The Frame, Window and Frame Geometry
+@section The Non-Client Area
+
+Under X, the non-client area is split into two parts:
+
+@enumerate
+@item
+The outer layer is the window-manager decorations: The title and
+borders.  These are controlled by the window manager, a separate process
+that controls the desktop, the location of icons, etc.  When a process
+tries to create a window, the window manager intercepts this action and
+"reparents" the window, placing another window around it which contains
+the window decorations, including the title bar, outer borders used for
+resizing, etc.  The window manager also implements any actions involving
+the decorations, such as the ability to resize a window by dragging its
+borders, move a window by dragging its title bar, etc.  If there is no
+window manager or you kill it, windows will have no decorations (and
+will lose them if they previously had any) and you will not be able to
+move or resize them.
+
+@item
+Inside of the window-manager decorations is the "shell", which is
+managed by the toolkit and widget libraries your program is linked with.
+The code in @file{*-x.c} uses the Xt toolkit and various possible widget
+libraries built on top of Xt, such as Motif, Athena, the "Lucid"
+widgets, etc.  Another possibility is GTK (@file{*-gtk.c}), which implements
+both the toolkit and widgets.  Under Xt, the "shell" window is an
+EmacsShell widget, containing an EmacsManager widget of the same size,
+which in turn contains a menubar widget and an EmacsFrame widget, inside
+of which is the client area. (The division into EmacsShell and
+EmacsManager is due to the complex and screwy geometry-management system
+in Xt [and X more generally].  The EmacsShell handles negotation with
+the window manager; the place of the EmacsManager widget is normally
+assumed by a widget that manages the geometry of its child widgets, but
+the EmacsManager widget just lets the XEmacs redisplay mechanism do the
+positioning.)
+@end enumerate
+
+Under Windows, the non-client area is managed by the window system.
+There is no division such as under X.  Part of the window-system API
+(@file{USER.DLL}) of Win32 includes functions to control the menubars, title,
+etc. and implements the move and resize behavior.  There @strong{is} an
+equivalent of the window manager, called the "shell", but it manages
+only the desktop, not the windows themselves.  The normal shell under
+Windows is @file{EXPLORER.EXE}; if you kill this, you will lose the bar
+containing the "Start" menu and tray and such, but the windows
+themselves will not be affected or lose their decorations.
+
+
+@node The Client Area, The Paned Area, The Non-Client Area, Window and Frame Geometry
+@section The Client Area
+
+Inside of the client area is the toolbars, the gutters (where the buffer
+tabs are displayed), the minibuffer, the internal border width, and one
+or more non-overlapping "windows" (this is old Emacs terminology, from
+before the time when frames existed at all; the standard terminology for
+this would be "pane").  Each window can contain a modeline, horizontal
+and/or vertical scrollbars, and (for non-rightmost windows) a vertical
+divider, surrounding a text area.
+
+The dimensions of the toolbars and gutters are determined by the formula
+(THICKNESS + 2 * BORDER-THICKNESS), where "thickness" is a cover term
+for height or width, as appropriate.  The height and width come from
+@code{default-toolbar-height} and @code{default-toolbar-width} and the specific
+versions of these (@code{top-toolbar-height}, @code{left-toolbar-width}, etc.).
+The border thickness comes from @code{default-toolbar-border-height} and
+@code{default-toolbar-border-width}, and the specific versions of these.  The
+gutter works exactly equivalently.
+
+Note that for any particular toolbar or gutter, it will only be
+displayed if [a] its visibility specifier (@code{default-toolbar-visible-p}
+etc.) is non-nil; [b] its thickness (@code{default-toolbar-height} etc.)  is
+greater than 0; [c] its contents (@code{default-toolbar} etc.) are non-nil.
+
+The position-specific toolbars interact with the default specifications
+as follows: If the value for a position-specific specifier is not
+defined in a particular domain (usually a window), and the position of
+that specifier is set as the default position (using
+@code{default-toolbar-position}), then the value from the corresponding
+default specifier in that domain will be used.  The gutters work the
+same.
+
+
+@node The Paned Area, Text Areas, The Client Area, Window and Frame Geometry
+@section The Paned Area
+
+The area occupied by the "windows" is called the paned area.  Note that
+this includes the minibuffer, which is just another window but is
+special-cased in XEmacs.  Each window can include a horizontal and/or
+vertical scrollbar, a modeline and a vertical divider to its right, as
+well as the text area.  Only non-rightmost windows can include a
+vertical divider. (The minibuffer normally does not include either
+modeline or scrollbars.)
+
+Note that, because the toolbars and gutters are controlled by
+specifiers, and specifiers can have window-specific and buffer-specific
+values, the size of the paned area can change depending on which window
+is selected: In other words, if the selected window or buffer changes,
+the entire paned area for the frame may change.
+
+
+@node Text Areas, The Displayable Area, The Paned Area, Window and Frame Geometry
+@section Text Areas, Fringes, Margins
+
+The space occupied by a window can be divided into the text area and the
+fringes.  The fringes include the modeline, scrollbars and vertical
+divider on the right side (if any); inside of this is the text area,
+where the text actually occurs.  Note that a window may or may not
+contain any of the elements that are part of the fringe -- this is
+controlled by specifiers, e.g. @code{has-modeline-p},
+@code{horizontal-scrollbar-visible-p}, @code{vertical-scrollbar-visible-p},
+@code{vertical-divider-always-visible-p}, etc.
+
+In addition, it is possible to set margins in the text area using the
+specifiers @code{left-margin-width} and @code{right-margin-width}.  When this is
+done, only the "inner text area" (the area inside of the margins) will
+be used for normal display of text; the margins will be used for glyphs
+with a layout policy of @code{outside-margin} (as set on an extent containing
+the glyph by @code{set-extent-begin-glyph-layout} or
+@code{set-extent-end-glyph-layout}).  However, the calculation of the text
+area size (e.g. in the function @code{window-text-area-width}) includes the
+margins.  Which margin is used depends on whether a glyph has been set
+as the begin-glyph or end-glyph of an extent (@code{set-extent-begin-glyph}
+etc.), using the left and right margins, respectively.
+
+Technically, the margins outside of the inner text area are known as the
+"outside margins".  The "inside margins" are in the inner text area and
+constitute the whitespace between the outside margins and the first or
+last non-whitespace character in a line; their width can vary from line
+to line.  Glyphs will be placed in the inside margin if their layout
+policy is @code{inside-margin} or @code{whitespace}, with @code{whitespace} glyphs on
+the inside and @code{inside-margin} glyphs on the outside.  Inside-margin
+glyphs can spill over into the outside margin if @code{use-left-overflow} or
+@code{use-right-overflow}, respectively, is non-nil.
+
+See the Lisp Reference manual, under Annotations, for more details.
+
+
+@node The Displayable Area, Which Functions Use Which?, Text Areas, Window and Frame Geometry
+@section The Displayable Area
+
+The "displayable area" is not so much an actual area as a convenient
+fiction.  It is the area used to convert between pixel and character
+dimensions for frames.  The character dimensions for a frame (e.g. as
+returned by @code{frame-width} and @code{frame-height} and set by
+@code{set-frame-width} and @code{set-frame-height}) are determined from the
+displayable area by dividing by the pixel size of the default font as
+instantiated in the frame. (For proportional fonts, the "average" width
+is used.  Under Windows, this is a built-in property of the fonts.
+Under X, this is based on the width of the lowercase 'n', or if this is
+zero then the width of the default character. [We prefer 'n' to the
+specified default character because many X fonts have a default
+character with a zero or otherwise non-representative width.])
+
+The displayable area is essentially the "theoretical" paned area of the
+frame excluding the rightmost and bottom-most scrollbars.  In this
+context, "theoretical" means that all calculations on based on
+frame-level values for toolbar, gutter and scrollbar thicknesses.
+Because these thicknesses are controlled by specifiers, and specifiers
+can have window-specific and buffer-specific values, these calculations
+may or may not reflect the actual size of the paned area or of the
+scrollbars when any particular window is selected.  Note also that the
+"displayable area" may not even be contiguous!  In particular, if the
+frame-level value of the horizontal scrollbar height is non-zero, then
+the displayable area includes the paned area above and below the bottom
+horizontal scrollbar but not the scrollbar itself.
+
+As a further twist, the character-dimension calculations are adjusted so
+that the truncation and continuation glyphs (see @code{truncation-glyph} and
+@code{continuation-glyph}) count as a single character even if they are wider
+than the default font width. (Technically, the character width is
+computed from the displayable-area width by subtracting the maximum of
+the truncation-glyph width, continuation-glyph width and default-font
+width before dividing by the default-font width, and then adding 1 to
+the result.) (The ultimate motivation for this kludge as well as the
+subtraction of the scrollbars, but not the minibuffer or bottom-most
+modeline, is to maintain compatibility with TTY's.)
+
+Despite all these concerns and kludges, however, the "displayable area"
+concept works well in practice and mostly ensures that by default the
+frame will actually fit 79 characters + continuation/truncation glyph.
+
+
+@node Which Functions Use Which?,  , The Displayable Area, Window and Frame Geometry
+@section Which Functions Use Which?
+
+@enumerate
+@item
+Top-level window area:
+
+@example
+set-frame-position
+@code{left} and @code{top} frame properties
+@end example
+
+@item
+Client area:
+
+@example
+frame-pixel-*, set-frame-pixel-*
+@end example
+
+@item
+Paned area:
+
+@example
+window-pixel-edges
+event-x-pixel, event-y-pixel, event-properties, make-event
+@end example
+
+@item
+Displayable area:
+
+@example
+frame-width, frame-height and other all functions specifying frame size
+  in characters
+frame-displayable-pixel-*
+@end example
+@end enumerate
+
+
+
+@node The Redisplay Mechanism, Extents, Window and Frame Geometry, Top
 @chapter The Redisplay Mechanism
 @cindex redisplay mechanism, the
 
--- a/src/ChangeLog	Mon Feb 15 22:58:10 2010 -0600
+++ b/src/ChangeLog	Tue Feb 16 01:21:32 2010 -0600
@@ -1,3 +1,28 @@
+2010-02-16  Ben Wing  <ben@xemacs.org>
+
+	* frame-impl.h:
+	* frame-impl.h (FRAME_INTERNAL_BORDER_WIDTH):
+	* frame-impl.h (FRAME_REAL_TOOLBAR_BOUNDS):
+	* frame-impl.h (FRAME_REAL_TOP_TOOLBAR_BOUNDS):
+	* frame-impl.h (FRAME_BOTTOM_BORDER_START):
+	* frame-impl.h (FRAME_LEFT_BORDER_START):
+	* frame-impl.h (FRAME_RIGHT_BORDER_START):
+	* frame.c (frame_conversion_internal_1):
+	* frame.c (change_frame_size_1):
+	* redisplay-output.c (clear_left_border):
+	* redisplay-output.c (clear_right_border):
+	* redisplay-output.c (redisplay_clear_top_of_window):
+	* redisplay-output.c (redisplay_clear_to_window_end):
+	* redisplay-output.c (redisplay_clear_bottom_of_window):
+	Rename FRAME_BORDER_* to FRAME_INTERNAL_BORDER_*.  Add
+	general FRAME_INTERNAL_BORDER_SIZE().  Add FRAME_REAL_TOOLBAR_BOUNDS()
+	to encompass the entire size of the toolbar including its border.
+	Add specific top/left/bottom/right versions of this macro.
+	Rewrite FRAME_*_BORDER_START and FRAME_*_BORDER_END to take into use
+	FRAME_REAL_*_TOOLBAR_BOUNDS().  Add some comments about existing
+	problems in frame sizing and how they might be fixed.  Simplify
+	change_frame_size_1() using the macros just created.
+
 2010-02-15  Ben Wing  <ben@xemacs.org>
 
 	* frame.c (change_frame_size_1):
--- a/src/frame-impl.h	Mon Feb 15 22:58:10 2010 -0600
+++ b/src/frame-impl.h	Tue Feb 16 01:21:32 2010 -0600
@@ -1,6 +1,6 @@
 /* Define frame-object for XEmacs.
    Copyright (C) 1988, 1992, 1993, 1994 Free Software Foundation, Inc.
-   Copyright (C) 1995 Ben Wing.
+   Copyright (C) 1995, 2010 Ben Wing.
 
 This file is part of XEmacs.
 
@@ -543,8 +543,16 @@
 
 #endif /* FSFmacs */
 
-#define FRAME_BORDER_WIDTH(f) ((f)->internal_border_width)
-#define FRAME_BORDER_HEIGHT(f) ((f)->internal_border_width)
+#define FRAME_INTERNAL_BORDER_WIDTH(f) ((f)->internal_border_width)
+#define FRAME_INTERNAL_BORDER_HEIGHT(f) ((f)->internal_border_width)
+#define FRAME_INTERNAL_BORDER_SIZE(f, pos) ((f)->internal_border_width)
+
+/************************************************************************/
+/*	                        toolbars      				*/
+/************************************************************************/
+
+/*---------------- Theoretical and real toolbar values ----------------*/
+
 
 /* This returns the frame-local value; that tells you what you should
    use when computing the frame size.  It is *not* the actual toolbar
@@ -657,6 +665,10 @@
    ? FRAME_RAW_REAL_TOOLBAR_BORDER_WIDTH (f, pos)	\
    : 0)
 
+#define FRAME_REAL_TOOLBAR_BOUNDS(f, pos)		\
+  (FRAME_REAL_TOOLBAR_SIZE (f, pos) +			\
+   2 * FRAME_REAL_TOOLBAR_BORDER_WIDTH (f, pos))
+
 #define FRAME_REAL_TOP_TOOLBAR_HEIGHT(f) \
   FRAME_REAL_TOOLBAR_SIZE (f, TOP_TOOLBAR)
 #define FRAME_REAL_BOTTOM_TOOLBAR_HEIGHT(f) \
@@ -684,32 +696,39 @@
 #define FRAME_REAL_RIGHT_TOOLBAR_VISIBLE(f) \
   FRAME_REAL_TOOLBAR_VISIBLE (f, RIGHT_TOOLBAR)
 
+#define FRAME_REAL_TOP_TOOLBAR_BOUNDS(f) \
+  FRAME_REAL_TOOLBAR_BOUNDS (f, TOP_TOOLBAR)
+#define FRAME_REAL_BOTTOM_TOOLBAR_BOUNDS(f) \
+  FRAME_REAL_TOOLBAR_BOUNDS (f, BOTTOM_TOOLBAR)
+#define FRAME_REAL_LEFT_TOOLBAR_BOUNDS(f) \
+  FRAME_REAL_TOOLBAR_BOUNDS (f, LEFT_TOOLBAR)
+#define FRAME_REAL_RIGHT_TOOLBAR_BOUNDS(f) \
+  FRAME_REAL_TOOLBAR_BOUNDS (f, RIGHT_TOOLBAR)
+
+/************************************************************************/
+/*         frame dimensions defined using toolbars and gutters          */
+/************************************************************************/
+
+/* #### These should be using the gutter sizes, but aren't yet */
+
 #define FRAME_TOP_BORDER_START(f)				\
-  (FRAME_REAL_TOP_TOOLBAR_HEIGHT (f) +				\
-   2 * FRAME_REAL_TOP_TOOLBAR_BORDER_WIDTH (f))
+  FRAME_REAL_TOP_TOOLBAR_BOUNDS (f)
 #define FRAME_TOP_BORDER_END(f)					\
-  (FRAME_TOP_BORDER_START (f) + FRAME_BORDER_HEIGHT (f))
+  (FRAME_TOP_BORDER_START (f) + FRAME_INTERNAL_BORDER_HEIGHT (f))
 
 #define FRAME_BOTTOM_BORDER_START(f)				\
-  (FRAME_PIXHEIGHT (f) - FRAME_BORDER_HEIGHT (f) -		\
-   FRAME_REAL_BOTTOM_TOOLBAR_HEIGHT (f) -			\
-   2 * FRAME_REAL_BOTTOM_TOOLBAR_BORDER_WIDTH (f))
+  (FRAME_BOTTOM_BORDER_END (f) - FRAME_INTERNAL_BORDER_HEIGHT (f))
 #define FRAME_BOTTOM_BORDER_END(f)				\
-  (FRAME_PIXHEIGHT (f) - FRAME_REAL_BOTTOM_TOOLBAR_HEIGHT (f) -	\
-   2 * FRAME_REAL_BOTTOM_TOOLBAR_BORDER_WIDTH (f))
+  (FRAME_PIXHEIGHT (f) - FRAME_REAL_BOTTOM_TOOLBAR_BOUNDS (f))
 
 #define FRAME_LEFT_BORDER_START(f)				\
-  (FRAME_REAL_LEFT_TOOLBAR_WIDTH (f) +				\
-   2 * FRAME_REAL_LEFT_TOOLBAR_BORDER_WIDTH (f))
+  FRAME_REAL_LEFT_TOOLBAR_BOUNDS (f)
 #define FRAME_LEFT_BORDER_END(f)				\
-  (FRAME_LEFT_BORDER_START (f) + FRAME_BORDER_WIDTH (f))
+  (FRAME_LEFT_BORDER_START (f) + FRAME_INTERNAL_BORDER_WIDTH (f))
 
 #define FRAME_RIGHT_BORDER_START(f)				\
-  (FRAME_PIXWIDTH (f) - FRAME_BORDER_WIDTH (f) -		\
-   FRAME_REAL_RIGHT_TOOLBAR_WIDTH(f) -                          \
-   2 * FRAME_REAL_RIGHT_TOOLBAR_BORDER_WIDTH (f))
+  (FRAME_RIGHT_BORDER_END (f) - FRAME_INTERNAL_BORDER_WIDTH (f))
 #define FRAME_RIGHT_BORDER_END(f)				\
-  (FRAME_PIXWIDTH (f) - FRAME_REAL_RIGHT_TOOLBAR_WIDTH (f) -	\
-   2 * FRAME_REAL_RIGHT_TOOLBAR_BORDER_WIDTH(f))
+  (FRAME_PIXWIDTH (f) - FRAME_REAL_RIGHT_TOOLBAR_BOUNDS (f))
 
 #endif /* INCLUDED_frame_impl_h_ */
--- a/src/frame.c	Mon Feb 15 22:58:10 2010 -0600
+++ b/src/frame.c	Tue Feb 16 01:21:32 2010 -0600
@@ -3318,6 +3318,14 @@
 
   window = FRAME_SELECTED_WINDOW (f);
 
+  /* #### It really seems like we should also be subtracting out the
+     theoretical gutter width and height, just like we do for toolbars.
+     There is currently a bug where if you call `set-frame-pixel-width'
+     on MS Windows (at least, possibly also X) things get confused and
+     the top of the root window overlaps the top gutter instead of being
+     below it.  This gets fixed next time you resize the frame using the
+     mouse.  Possibly this is caused by not handling the gutter height
+     here? */
   egw = max (glyph_width (Vcontinuation_glyph, window),
 	     glyph_width (Vtruncation_glyph, window));
   egw = max (egw, cpw);
@@ -3554,8 +3562,9 @@
 			     out_width, out_height);
 }
 
-/* Change the frame height and/or width.  Values may be given as zero to
-   indicate no change is to take place. */
+/* Change the frame height and/or width.  Values passed in are in
+   frame units (character cells on X/GTK, displayable-area pixels
+   on MS Windows or generally on pixelated-geometry window systems). */
 static void
 change_frame_size_1 (struct frame *f, int newwidth, int newheight)
 {
@@ -3586,37 +3595,20 @@
   FRAME_NEW_HEIGHT (f) = 0;
   FRAME_NEW_WIDTH (f) = 0;
 
-  /* when frame_conversion_internal() calculated the number of rows/cols
-     in the frame, the theoretical toolbar sizes were subtracted out.
-     The calculations below adjust for real toolbar height/width in
-     frame, which may be different from frame spec, taking the above
-     fact into account */
-  new_pixheight +=
-    - FRAME_REAL_TOP_TOOLBAR_HEIGHT (f)
-    - 2 * FRAME_REAL_TOP_TOOLBAR_BORDER_WIDTH (f);
-
-  new_pixheight +=
-    - FRAME_REAL_BOTTOM_TOOLBAR_HEIGHT (f)
-    - 2 * FRAME_REAL_BOTTOM_TOOLBAR_BORDER_WIDTH (f);
-
-  new_pixwidth +=
-    - FRAME_REAL_LEFT_TOOLBAR_WIDTH (f)
-    - 2 * FRAME_REAL_LEFT_TOOLBAR_BORDER_WIDTH (f);
-
-  new_pixwidth +=
-    - FRAME_REAL_RIGHT_TOOLBAR_WIDTH (f)
-    - 2 * FRAME_REAL_RIGHT_TOOLBAR_BORDER_WIDTH (f);
-
-  /* Adjust for gutters here so that we always get set
-     properly. */
+  /* We need to remove the boundaries of the paned area (see top of file)
+     from the total-area pixel size, which is what we have now.
+
+     #### We should also be subtracting the internal borders. */
   new_pixheight -=
-    (FRAME_TOP_GUTTER_BOUNDS (f)
+    (FRAME_REAL_TOP_TOOLBAR_BOUNDS (f)
+     + FRAME_REAL_BOTTOM_TOOLBAR_BOUNDS (f)
+     + FRAME_TOP_GUTTER_BOUNDS (f)
      + FRAME_BOTTOM_GUTTER_BOUNDS (f));
 
-  /* Adjust for gutters here so that we always get set
-     properly. */
   new_pixwidth -=
-    (FRAME_LEFT_GUTTER_BOUNDS (f)
+    (FRAME_REAL_LEFT_TOOLBAR_BOUNDS (f)
+     + FRAME_REAL_RIGHT_TOOLBAR_BOUNDS (f)
+     + FRAME_LEFT_GUTTER_BOUNDS (f)
      + FRAME_RIGHT_GUTTER_BOUNDS (f));
 
   XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_top
@@ -3676,6 +3668,12 @@
   if (FRAME_TTY_P (f))
     f->pixwidth = newwidth;
 
+  /* #### On MS Windows, this references FRAME_PIXWIDTH() and FRAME_PIXHEIGHT().
+     I'm not sure we can count on those values being set.  Instead we should
+     use the total pixel size we got near the top by calling
+     frame_conversion_internal().  We should inline the logic in
+     get_frame_char_size() here and change that function so it just looks
+     at FRAME_CHARWIDTH() and FRAME_CHARHEIGHT(). */
   get_frame_char_size (f, &FRAME_CHARWIDTH (f), &FRAME_CHARHEIGHT (f));
 
   MARK_FRAME_TOOLBARS_CHANGED (f);
--- a/src/redisplay-output.c	Mon Feb 15 22:58:10 2010 -0600
+++ b/src/redisplay-output.c	Tue Feb 16 01:21:32 2010 -0600
@@ -638,7 +638,7 @@
 
   redisplay_clear_region (window, DEFAULT_INDEX,
 		FRAME_LEFT_BORDER_START (f), y,
-		FRAME_BORDER_WIDTH (f), height);
+		FRAME_INTERNAL_BORDER_WIDTH (f), height);
 }
 
 /*****************************************************************************
@@ -654,7 +654,7 @@
 
   redisplay_clear_region (window, DEFAULT_INDEX,
 		FRAME_RIGHT_BORDER_START (f),
-		y, FRAME_BORDER_WIDTH (f), height);
+		y, FRAME_INTERNAL_BORDER_WIDTH (f), height);
 }
 
 /*****************************************************************************
@@ -2102,14 +2102,14 @@
 
       if (window_is_leftmost (w))
 	{
-	  x -= FRAME_BORDER_WIDTH (f);
-	  width += FRAME_BORDER_WIDTH (f);
+	  x -= FRAME_INTERNAL_BORDER_WIDTH (f);
+	  width += FRAME_INTERNAL_BORDER_WIDTH (f);
 	}
       if (window_is_rightmost (w))
-	width += FRAME_BORDER_WIDTH (f);
+	width += FRAME_INTERNAL_BORDER_WIDTH (f);
 
       y = FRAME_TOP_BORDER_START (f) - 1;
-      height = FRAME_BORDER_HEIGHT (f) + 1;
+      height = FRAME_INTERNAL_BORDER_HEIGHT (f) + 1;
 
       redisplay_clear_region (window, DEFAULT_INDEX, x, y, width, height);
     }
@@ -2145,7 +2145,7 @@
 
 	  if (window_is_leftmost (w))
 	    redisplay_clear_region (window, DEFAULT_INDEX, FRAME_LEFT_BORDER_START (f),
-				    ypos1, FRAME_BORDER_WIDTH (f), height);
+				    ypos1, FRAME_INTERNAL_BORDER_WIDTH (f), height);
 
 	  if (bounds.left_in - bounds.left_out > 0)
 	    redisplay_clear_region (window,
@@ -2167,7 +2167,7 @@
 
 	  if (window_is_rightmost (w))
 	    redisplay_clear_region (window, DEFAULT_INDEX, FRAME_RIGHT_BORDER_START (f),
-				    ypos1, FRAME_BORDER_WIDTH (f), height);
+				    ypos1, FRAME_INTERNAL_BORDER_WIDTH (f), height);
 	}
     }
 }
@@ -2217,7 +2217,7 @@
   /* #### See if this can be made conditional on the frame
      changing size. */
   if (MINI_WINDOW_P (w))
-    ypos2 += FRAME_BORDER_HEIGHT (f);
+    ypos2 += FRAME_INTERNAL_BORDER_HEIGHT (f);
 
   if (min_start >= 0 && ypos1 < min_start)
     ypos1 = min_start;