Subject: Re: bug#38452: 26.3; set-frame-position is slightly drifted

From: martin rudalics <[email-masked]>
Date: Tue, 3 Dec 2019 16:59:22 +0100

> As you can read in this scratch the behaviour is even more mysterious
 > now. Indeed if I set the parameters and read them back by
 > frame-parameter both evaluated in a enclosing progn then I get the
 > expected values. But if I reread right after the parameters I get
 > different values !?

My guess is that Emacs initially sets the parameter values to the
requested values and asks the window manager to apply them and later
sets the parameters to what the window manager has applied.  If you
retrieve their values in between these two steps, Emacs reports the
requested and not the finally realized values.  BTW, I still don't
know what your window manager is.

 > pl-dock-left’s value is
 > (((name . "eDP-1")
 >    (geometry 0 0 1920 1080)
 >    (workarea 55 27 1865 1053)
 >    (mm-size 309 174)
 >    (frames #<frame  *Minibuf-2* 0x4e723c0> #<frame *unsent mail to martin rudalics* 0x5289930>)
 >    (source . "Gdk")))
 >
 >
 > pl-dock-bottom’s value is
 > (((name . "eDP-1")
 >    (geometry 0 0 1920 1080)
 >    (workarea 0 27 1920 1000)
 >    (mm-size 309 174)
 >    (frames #<frame  *Minibuf-2* 0x4e723c0> #<frame *unsent mail to martin rudalics* 0x5289930>)
 >    (source . "Gdk")))

These values are consistent and make sense.

 > In the first configuration (my laptop screen as a unique scrren) it
 > seems that when the frame is at the top left corner the parameters
 > take values (L=45,T=19) (which probably correspond to the width of the
 > dock and height of the menu line).

Well 55 - 45 gives 10 and 27 - 19 gives 8, the values you reported in
your original report as

   However the frame is slightly drifted by 10 pixel to the left and 8
   pixels to the top.

If we say that the origin for things to display on screen is (-10, -8)
- something you could probably verify by moving the dock to the right
and the menu bar line to the bottom - we have a clue.  Just that it
doesn't make sense to me, yet.

 > If I set-frame-position at (x,y) with 0<=x<=55 and 0<=y<=27 then the
 > frame does not move and the values are reset to (45,19).
 > If I set-frame-position at (60,30) then the frame moved a little bit and
 > the parameters evaluate to (50,22).

These fit into the picture sketched above.

 > Here is a scratch file on which I did some experiment commented.

Fine exercise.  Appreciated!

 > Th function pl-lt is defined to easily show the values of the parameters
 > left/top of the frame:
 >
 > ========================== SCRACTCH INTERACTIVE LISP FILE WITH EXPERMINTS ========================================
 > ;; This buffer is for text that is not saved, and for Lisp evaluation.
 > ;; To create a file, visit it with <open> and enter text in its buffer.
 >
 > ;; Experiments with set-frame-position and the result values of the parameters left and top of the frame
 > ;; Each parenthesis sexp has been evaluated with C-j = eval-print-last-sexp
 > (defun pl-lt ()
 >    "Returns a string giving the left/top positions of the current frame"
 >    (concat " LEFT="
 > 	  (prin1-to-string (frame-parameter nil 'left))
 > 	  "  TOP="
 > 	  (prin1-to-string (frame-parameter nil 'top))))
 >
 >
 > ;; First experiments with the laptop as only display and  the gnome-3 dock on the left:
 > (display-monitor-attributes-list)
 > (((name . "eDP-1") (geometry 0 0 1920 1080) (workarea 55 27 1865 1053) (mm-size 309 174) (frames #<frame *scratch* 0x4e723c0> #<frame *unsent mail to martin rudalics* 0x5289930>) (source . "Gdk")))
 >
 >
 > (set-frame-position nil 0 0)
 > t
 > ;; the frame is immediately below the menu line and on the immediate right of  the left dock
 > (pl-lt)
 > " LEFT=45  TOP=19"
 > (progn (set-frame-position nil 0 0) (pl-lt))
 > " LEFT=0  TOP=0"
 >   (pl-lt)
 > " LEFT=45  TOP=19"
 > (set-frame-position nil 45 19)
 > t
 > ;; this did not move the frame: still at left corner but not overlaping the dock or menu line
 > (pl-lt)
 > " LEFT=45  TOP=19"
 > (progn (set-frame-position nil 45 19) (pl-lt))
 > " LEFT=45  TOP=19"
 > (pl-lt)
 > " LEFT=45  TOP=19"
 > (progn (set-frame-position nil 50 25) (pl-lt))
 > " LEFT=50  TOP=25"
 > ;; this did not move the frame
 > (pl-lt)
 > " LEFT=45  TOP=19"
 > ;; the parameters changed between the (pl-lt) inside the progn and after !!!

Yes.  This is what I mentioned at the top of this manual.

 > (progn (set-frame-position nil 55 27) (pl-lt))
 > " LEFT=55  TOP=27"
 > ;; this did not move the frame
 > (pl-lt)
 > " LEFT=45  TOP=19"

You didn't try (set-frame-position nil 56 28) here, it should move the
frame to (46, 20) IIUC ;-)

 > (progn (set-frame-position nil 60 30) (pl-lt))
 > " LEFT=60  TOP=30"
 > ;; this moved very slight the frame away from the left-top corner
 > (pl-lt)
 > " LEFT=50  TOP=22"
 >
 >
 >
 > (set-frame-position nil 400 100)
 > t
 > ;; this moved the frame sowewhere in the middle of the screen
 > (pl-lt)
 > " LEFT=390  TOP=92"
 > (progn (set-frame-position nil 390 92) (pl-lt))
 > " LEFT=390  TOP=92"
 > ;; this moved a bit the frame towars the top left corner
 > (pl-lt)
 > " LEFT=380  TOP=84"
 >
 > ;; ---------------------------
 > ;; Second experiments with an external screen as single display
 > (display-monitor-attributes-list)
 > (((name . "DP-1-2") (geometry 0 0 1920 1080) (workarea 55 27 1865 1053) (mm-size 598 336) (frames #<frame *scratch* 0x4e723c0> #<frame *unsent mail to martin rudalics* 0x5289930>) (source . "Gdk")))
 >
 > (set-frame-position nil 0 0)
 > ;; the frame is immediately below the menu line and on the immediate right of  the left dock
 > t
 > (pl-lt)
 > " LEFT=45  TOP=19"
 > (progn (set-frame-position nil 0 0) (pl-lt))
 > " LEFT=0  TOP=0"
 > (pl-lt)
 >
 > ;; Third experiment with a double display: internal display of laptop + external display
 > ;; The external display is set as the 'primary' display and is supposed to be on the right
 > ;; of the laptop display. So the menu bar and dock are only on the external display
 > (display-monitor-attributes-list)
 > (((name . "DP-1-2") (geometry 1920 0 1920 1080) (workarea 1920 27 1920 1053) (mm-size 598 336) (frames #<frame *scratch* 0x4e723c0> #<frame *unsent mail to martin rudalics* 0x5289930>) (source . "Gdk")) ((name . "eDP-1") (geometry 0 0 1920 1080) (workarea 0 0 1920 1080) (mm-size 309 174) (frames) (source . "Gdk")))
 > (set-frame-position nil 0 0)
 > t
 > ;; the frame is now in the left-top corner of the laptoop screen (no menu neither dock here)
 > (pl-lt)
 > " LEFT=(+ -10)  TOP=(+ -8)"
 > (progn (set-frame-position nil 0 0) (pl-lt))
 > " LEFT=0  TOP=0"
 > (pl-lt)
 > " LEFT=(+ -10)  TOP=(+ -8)"

So here we see that a frame that should be located at (0, 0) is moved
to (-10, -8).  What does

(modify-frame-parameters nil '((left . 0) (top . 0) (undecorated . t)))

yield (to find out whether these 10/8 are due to the decorations)?

 > (progn (set-frame-position nil (+ -10) (+ -8)) (pl-lt))

The doc-string of 'set-frame-position' says that

   FRAME must be a live frame and defaults to the selected one.  X and Y,
   if positive, specify the coordinate of the left and top edge of FRAME's
   outer frame in pixels relative to an origin (0, 0) of FRAME's display.
   If any of X or Y is negative, it specifies the coordinates of the right
   or bottom edge of the outer frame of FRAME relative to the right or
   bottom edge of FRAME's display.

so you tried to move the frame to some position near the bottom right
corner of the display and these

 > " LEFT=2842  TOP=288"
 > ;; the previous evaluation has moved the frame on the external display close to the right corner
 > (pl-lt)
 > " LEFT=2832  TOP=280"
 > (progn (set-frame-position nil 2832 280) (pl-lt))
 > " LEFT=2832  TOP=280"
 > ;; the previous sexpevaluation has moved the frame slighly to the left and top

will be as expected provided the frame size and the LEFT/TOP values
sum up accordingly.

Does anything change in general when you explicitly request a position
as with

(modify-frame-parameters nil '((user-position . t) (left . 0) (top . 0)))

martin