Document pixelwise frame resizing and fix related bug on Windows.

* 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'.
This commit is contained in:
Martin Rudalics 2014-03-14 11:38:46 +01:00
parent 56759cf12a
commit cfd5e825ae
5 changed files with 118 additions and 41 deletions

View 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

View 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,

View 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
This function sets the size of @var{frame}, measured in characters;
@var{cols} and @var{rows} specify the new width and height.
@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.
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.
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{width} and @var{height} specify the new width in columns and the
new height in lines.
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?

View 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

View 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.
-----------------------------------------------------------------
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. */
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.
if (w32_enable_frame_resize_hack)
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.
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);
}