unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
From: martin rudalics <rudalics@gmx.at>
To: ynyaaa@gmail.com
Cc: 38705@debbugs.gnu.org
Subject: bug#38705: 26.3; set-frame-size pixelwise makes frame larger
Date: Wed, 25 Dec 2019 10:49:34 +0100	[thread overview]
Message-ID: <dcbecb80-5eb5-0e8d-3817-594a3dce20ee@gmx.at> (raw)
In-Reply-To: <86lfr1al4s.fsf@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 4677 bytes --]

 > I tried to set up the frame outer size like below.
 >    ;;; sample ~/.emacs.d/init.el
 >    (defun test-set-frame-outer-size (frame width height)
 >      (set-frame-size frame width height t)
 >      (set-frame-size frame
 >                      (- width  (- (frame-outer-width  frame) width))
 >                      (- height (- (frame-outer-height frame) height))
 >                      t))
 >    (setq frame-inhibit-implied-resize t)
 >    (test-set-frame-outer-size nil 500 500)
 >    ;;; sample ~/.emacs.d/init.el end
 >
 > But the function does not work well inside init.el.
 > After emacs started, the size is:
 >    (list (frame-outer-width) (frame-outer-height))
 >    =>(500 502)
 > When user input is allowed, evaluating
 >    (test-set-frame-outer-size nil 500 500)
 > works as expected.

Look up the function 'frame-geometry'.  If its return value for
something like the 'external-border-size' differs for a frame before
and after "user input is allowed" then it's because that something has
not been specified before the frame was "mapped" and so Emacs won't
know it.

If you are sure that your decorations won't change from one emacs
session to the next, you can try to remember them from the last
session and apply them manually.  However, in general, calling
'frame-outer-width/-height' from init.el is not a good idea.

 > About another point.
 > If the frame has no menu-bar, tool-bar, scroll-bar nor fringes,
 > frame-pixel-width and frame-pixel-height can be set by set-frame-size.
 > But if the frame is undecorated, the outer size is as large as the size
 > of non-undecorated frame regardless of the value of
 > frame-inhibit-implied-resize.
 > The inner size is enlarged to the outer size after redisplay.
 > The size can not be set as expected.
 >    (let ((width 500) (height 500)
 >          (params '((undecorated . t)
 >                    (menu-bar-lines . 0)
 >                    (tool-bar-lines . 0)
 >                    (horizontal-scroll-bars . nil)
 >                    (vertical-scroll-bars . nil)
 >                    (left-fringe . 0)
 >                    (right-fringe . 0)))
 >          (f (lambda () (list (list (frame-outer-width)
 >                                    (frame-inner-width))
 >                              (list (frame-outer-height)
 >                                    (frame-inner-height))))))
 >      (setq frame-inhibit-implied-resize t)
 >      (modify-frame-parameters nil params)
 >      (set-frame-size nil width height t)
 >      (list (funcall f)
 >            (progn (redisplay) (funcall f))))
 >    =>(((516 500) (539 500)) ((516 516) (539 539)))
 >
 > If the form above is evaluated twice, the frame outer size stays
 > 516x539 pixels and the inner size shrinks to 500x500 pixels.

Please note again that the values you pass to 'set-frame-size' are the
values later reported by 'frame-text-width' and 'frame-text-height'.
These are fictive values and neither inner, nor outer or native sizes
might match these.

 > The inner text area is displayed at the top-left,
 > and there are blank areas at the right and the bottom.

This is the result of a bug that made frame resizing incorrect for
undecorated frames on Windows ever since.  To explain why this bug
usually goes unnoticed note that 'set-frame-size' causes three things
to happen: (1) it asks the window manager to resize the frame's
(window system) window.  (2) it "prematurely" resizes the frame's
windows because in their code some users want to know the new window
sizes right away.

Now if (1) eventually results in a frame size different from the one
expected in (2), the corresponding message from the window manager
will cause Emacs to (3) re-resize the frame's windows if they don't
match and everything should go well.  Usually, the sizes returned by
the window manager match those expected by (2) and in (3) no such
re-resizing is needed.

But in your scenario the first

(set-frame-size nil 500 500 t)

call will, due to the bug, pass incorrect values to the window
manager, which makes the values eventually returned by the window
manager differ from those calculated in (2).  (3) will fix this.  But
the subsequent calls will cause the window manager do nothing in (1)
because it is supplied the old values again and thus will decide that
no resizing is needed.  Yet Emacs will perform (2) with the values it
expects and these values will never be corrected because (3) will
never happen.

Please try the attached patch.  I will install it on Emacs-27 as soon
as I have upgraded my working environment, something which may happen
in a couple of days only.

Many thanks again for reporting these obscure behaviors, martin

[-- Attachment #2: w32fns.c.diffs --]
[-- Type: text/plain, Size: 388 bytes --]

diff --git a/src/w32fns.c b/src/w32fns.c
index bf2a7a3e54..8145b82416 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -2146,6 +2146,9 @@ w32_set_undecorated (struct frame *f, Lisp_Object new_value, Lisp_Object old_val
 		    | SWP_FRAMECHANGED);
       FRAME_UNDECORATED (f) = false;
     }
+
+  f->output_data.w32->dwStyle = GetWindowLong (hwnd, GWL_STYLE);
+
   unblock_input ();
 }
 


  reply	other threads:[~2019-12-25  9:49 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-12-22 12:36 bug#38705: 26.3; set-frame-size pixelwise makes frame larger ynyaaa
2019-12-23 10:08 ` martin rudalics
2019-12-24 13:49   ` ynyaaa
2019-12-25  9:49     ` martin rudalics [this message]
2020-01-02  8:52       ` martin rudalics

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=dcbecb80-5eb5-0e8d-3817-594a3dce20ee@gmx.at \
    --to=rudalics@gmx.at \
    --cc=38705@debbugs.gnu.org \
    --cc=ynyaaa@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).