]> code.delx.au - gnu-emacs/commitdiff
Document pixelwise frame resizing and fix related bug on Windows.
authorMartin Rudalics <rudalics@gmx.at>
Fri, 14 Mar 2014 10:38:46 +0000 (11:38 +0100)
committerMartin Rudalics <rudalics@gmx.at>
Fri, 14 Mar 2014 10:38:46 +0000 (11:38 +0100)
* w32term.c (x_set_window_size): When frame-resize-pixelwise is
nil, always resize character wise to avoid potential loss of the
mode line (Bug#16923 related).
* display.texi (Temporary Displays): Say that
with-temp-buffer-window makes its buffer current.
* frames.texi (Size and Position): Describe new option
`frame-resize-pixelwise'.  Rewrite descriptions of
`set-frame-size', `set-frame-height' and `set-frame-width'.

doc/lispref/ChangeLog
doc/lispref/display.texi
doc/lispref/frames.texi
src/ChangeLog
src/w32term.c

index 274d9fa4fea1de3fcc80c602f19060fab5035f89..047a7c6f3b701aa599423224b8fc8c7d62ca3456 100644 (file)
@@ -1,3 +1,11 @@
+2014-03-14  Martin Rudalics  <rudalics@gmx.at>
+
+       * display.texi (Temporary Displays): Say that
+       with-temp-buffer-window makes its buffer current.
+       * frames.texi (Size and Position): Describe new option
+       `frame-resize-pixelwise'.  Rewrite descriptions of
+       `set-frame-size', `set-frame-height' and `set-frame-width'.
+
 2014-03-09  Martin Rudalics  <rudalics@gmx.at>
 
        * elisp.texi (Top): Rename section "Width" to "Size of Displayed
index bffb840bfeb34678a1156f90a3b5604a4666aa36..5037f0c9032a3970fe194575207833ef82ec0087 100644 (file)
@@ -1175,12 +1175,11 @@ is current, and the window it was displayed in is selected.
 @end defvar
 
 @defmac with-temp-buffer-window buffer-or-name action quit-function forms@dots{}
-This macro is similar to @code{with-output-to-temp-buffer}.
-Like that construct, it executes @var{forms} while arranging to insert
-any output they print into the buffer named @var{buffer-or-name}.
-Finally, the buffer is displayed in some window, but not selected.
-Unlike @code{with-output-to-temp-buffer}, this does not switch to Help
-mode.
+This macro is similar to @code{with-output-to-temp-buffer}.  Like that
+construct, it executes @var{forms} while arranging to insert any output
+they print into the buffer named @var{buffer-or-name} and displays the
+buffer in some window.  Unlike @code{with-output-to-temp-buffer},
+however, this makes the buffer current and does not switch to Help mode.
 
 The argument @var{buffer-or-name} specifies the temporary buffer.
 It can be either a buffer, which must already exist, or a string,
index 206f14e751ee6f2fa62f5ac602d56d98b77ba143..59881afb9037dde8f9d891ca000dd5322e19a58d 100644 (file)
@@ -1147,21 +1147,46 @@ font.  If you don't supply @var{frame}, these functions use the selected
 frame.
 @end defun
 
-@defun set-frame-size frame cols rows
+@defopt frame-resize-pixelwise
+If this option is @code{nil}, a frame's size is usually rounded to a
+multiple of the current values of that frame's @code{frame-char-height}
+and @code{frame-char-width}.  If this is non-@code{nil}, no rounding
+occurs, hence frame sizes can increase/decrease by one pixel.
+
+Setting this causes the next resize operation to pass the corresponding
+size hints to the window manager.  This means that this variable should
+be set only in a user's initial file; applications should never bind it
+temporarily.
+
+The precise semantics of a value of @code{nil} for this option depends
+on the toolkit used: Dragging the frame border with the mouse is usually
+always done character-wise.  Calling @code{set-frame-size} (see below)
+with arguments that do not specify the frame size as an integer multiple
+of its character size may be, however, either ignored or cause a
+rounding (GTK+, Windows) or get accepted (Lucid, Motif).  This also
+means that with some toolkits and a display whose size is not an
+integral multiple of your default font, you may have to set this to
+non-@code{nil} in order to fully maximize a frame.
+@end defopt
+
+@defun set-frame-size frame width height pixelwise
 This function sets the size of @var{frame}, measured in characters;
-@var{cols} and @var{rows} specify the new width and height.
+@var{width} and @var{height} specify the new width in columns and the
+new height in lines.
 
-To set the size based on values measured in pixels, use
-@code{frame-char-height} and @code{frame-char-width} to convert
-them to units of characters.
+The optional argument @var{pixelwise} non-@code{nil} means to measure
+the new width and height in units of pixels instead.  Note that if
+@code{frame-resize-pixelwise} is @code{nil}, some toolkits may refuse to
+fully honor the request if it does not increase/decrease the frame size
+to a multiple of its character size.
 @end defun
 
-@defun set-frame-height frame lines &optional pretend
-This function resizes @var{frame} to a height of @var{lines} lines.  The
+@defun set-frame-height frame height &optional pretend pixelwise
+This function resizes @var{frame} to a height of @var{height} lines.  The
 sizes of existing windows in @var{frame} are altered proportionally to
 fit.
 
-If @var{pretend} is non-@code{nil}, then Emacs displays @var{lines}
+If @var{pretend} is non-@code{nil}, then Emacs displays @var{height}
 lines of output in @var{frame}, but does not change its value for the
 actual height of the frame.  This is only useful on text terminals.
 Using a smaller height than the terminal actually implements may be
@@ -1170,12 +1195,24 @@ terminal malfunctions when using its whole screen.  Setting the frame
 height ``for real'' does not always work, because knowing the correct
 actual size may be necessary for correct cursor positioning on
 text terminals.
+
+The optional fourth argument @var{pixelwise} non-@code{nil} means that
+@var{frame} should be @var{height} pixels high.  Note that if
+@code{frame-resize-pixelwise} is @code{nil}, some toolkits may refuse to
+fully honor the request if it does not increase/decrease the frame
+height to a multiple of its character height.
 @end defun
 
-@defun set-frame-width frame width &optional pretend
+@defun set-frame-width frame width &optional pretend pixelwise
 This function sets the width of @var{frame}, measured in characters.
 The argument @var{pretend} has the same meaning as in
 @code{set-frame-height}.
+
+The optional fourth argument @var{pixelwise} non-@code{nil} means that
+@var{frame} should be @var{width} pixels wide.  Note that if
+@code{frame-resize-pixelwise} is @code{nil}, some toolkits may refuse to
+fully honor the request if it does not increase/decrease the frame width
+to a multiple of its character width.
 @end defun
 
 @c FIXME?  Belongs more in Emacs manual than here?
index 013409ff40684de24ca7434e8153367dd5413e53..0512b0d9b68c242bed80103813de41109798e67a 100644 (file)
@@ -1,3 +1,9 @@
+2014-03-14  Martin Rudalics  <rudalics@gmx.at>
+
+       * w32term.c (x_set_window_size): When frame-resize-pixelwise is
+       nil, always resize character wise to avoid potential loss of the
+       mode line (Bug#16923 related).
+
 2014-03-12  Martin Rudalics  <rudalics@gmx.at>
 
        * frame.c (x_set_frame_parameters): Always calculate new sizes
index 5c93103f2c5ab61b9e3a6a97ddb14247a7650c34..2981320e13630e59f36d38df1272ce76c42d9201 100644 (file)
@@ -5648,6 +5648,31 @@ x_set_window_size (struct frame *f, int change_gravity, int width, int height, b
       pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, height);
     }
 
+  if (!frame_resize_pixelwise)
+    {
+      /* If we don't resize frames pixelwise, round sizes to multiples
+        of character sizes.  Otherwise, Windows may clip our frame
+        rectangle at a character size boundary and we risk losing our
+        mode line.  Bug#16923 might be a consequence of this.
+
+        So far, this is a Windows specific problem; other toolkits may
+        prefer to not resize the frame if the delta is not large enough
+        (GTK) or resize the frame pixelwise as requested (Lucid,
+        Motif).  Windows just doesn't call us back (probably because of
+        the size hint settings which it apparently interprets strictly)
+        neither when the user tries to mouse-drag a frame border by,
+        nor when calling `set-frame-size' with a delta of less than the
+        canonical character size.  If w32_enable_frame_resize_hack is
+        enabled (which it now is by default) we'd then below resize the
+        frame's root window in preparation of a WM_SIZE message to come
+        which, however, is not going to happen. */
+      int unit_width = FRAME_COLUMN_WIDTH (f);
+      int unit_height = FRAME_LINE_HEIGHT (f);
+
+      pixelwidth = (pixelwidth / unit_width) * unit_width;
+      pixelheight = (pixelheight / unit_height) * unit_height;
+    }
+
   f->win_gravity = NorthWestGravity;
   x_wm_set_size_hint (f, (long) 0, 0);
 
@@ -5670,39 +5695,40 @@ x_set_window_size (struct frame *f, int change_gravity, int width, int height, b
   }
 
   /* If w32_enable_frame_resize_hack is non-nil, immediately apply the
-     new pixel sizes to the frame and its subwindows.  See discussion
-     of Bug#16028 for why we need this.  */
+     new pixel sizes to the frame and its subwindows.  This approach is
+     fragile because Windows might not honor the resize request issued
+     by my_set_window_pos with a WM_SIZE message (see previous comment).
 
-  if (w32_enable_frame_resize_hack)
-    /* The following mirrors what is done in xterm.c. It appears to be
-     for informing lisp of the new size immediately, while the actual
-     resize will happen asynchronously. But on Windows, the menu bar
-     automatically wraps when the frame is too narrow to contain it,
-     and that causes any calculations made here to come out wrong. The
-     end is some nasty buggy behavior, including the potential loss
-     of the minibuffer.
+     Jason Rumney earlier refused to call change_frame_size right here
+     with the following argument:
+
+     The following mirrors what is done in xterm.c. It appears to be for
+     informing lisp of the new size immediately, while the actual resize
+     will happen asynchronously. But on Windows, the menu bar
+     automatically wraps when the frame is too narrow to contain it, and
+     that causes any calculations made here to come out wrong.  The end
+     is some nasty buggy behavior, including the potential loss of the
+     minibuffer.
 
      Disabling this code is either not sufficient to fix the problems
      completely, or it causes fresh problems, but at least it removes
      the most problematic symptom of the minibuffer becoming unusable.
 
-     -----------------------------------------------------------------
-
-     Now, strictly speaking, we can't be sure that this is accurate,
-     but the window manager will get around to dealing with the size
-     change request eventually, and we'll hear how it went when the
-     ConfigureNotify event gets here.
+     However, as the discussion about how to handle frame size
+     parameters on Windows (Bug#1348, Bug#16028) shows, that cure seems
+     worse than the disease.  In particular, menu bar wrapping looks
+     like a non-issue - maybe so because Windows eventually gets back to
+     us with the correct client rectangle anyway.  But we have to avoid
+     calling change_frame_size with a delta of less than one canoncial
+     character size when frame_resize_pixelwise is nil, as explained in
+     the comment above.  */
 
-     We could just not bother storing any of this information here,
-     and let the ConfigureNotify event set everything up, but that
-     might be kind of confusing to the Lisp code, since size changes
-     wouldn't be reported in the frame parameters until some random
-     point in the future when the ConfigureNotify event arrives.
+  if (w32_enable_frame_resize_hack)
 
-     We pass 1 for DELAY since we can't run Lisp code inside of
-     a BLOCK_INPUT.  */
     {
-      change_frame_size (f, width, height, 0, 1, 0, pixelwise);
+      change_frame_size (f, FRAME_PIXEL_TO_TEXT_WIDTH (f, pixelwidth),
+                        FRAME_PIXEL_TO_TEXT_HEIGHT (f, pixelheight),
+                        0, 1, 0, 1);
       SET_FRAME_GARBAGED (f);
 
       /* If cursor was outside the new size, mark it as off.  */
@@ -5711,7 +5737,8 @@ x_set_window_size (struct frame *f, int change_gravity, int width, int height, b
       /* Clear out any recollection of where the mouse highlighting was,
         since it might be in a place that's outside the new frame size.
         Actually checking whether it is outside is a pain in the neck,
-        so don't try--just let the highlighting be done afresh with new size.  */
+        so don't try--just let the highlighting be done afresh with new
+        size.  */
       cancel_mouse_face (f);
     }