Subject: bug#24085: 25.1.50; `make-frame' given `top' param creates frame with ~10x smaller `top'

From: Drew Adams <[email-masked]>
Date: Wed, 27 Jul 2016 13:55:33 -0700 (PDT)

> > > Reverting the change will reintroduce the bug it fixed
> >
> > Obviously, as I indicated in my earlier message, I meant that the
> > bug that it fixed should be fixed properly, without treading on
> > `make-frame'.  If on MS Windows you think the first Emacs frame
> > should be positioned so that it does not overlap the task bar,
> > then do that.  But do it without affecting what `make-frame' does.
> >
> > > so doing that is out of the question.
> >
> > What _is_ in the question, then?
> 
> Anything else.

Good!

> > If you are unwilling to fix the code, will you fix the doc?
> 
> If that's the best we can do, yes.

Also good - better than nothing.

> > Just what bug did this change seek to fix?  Wasn't it only the default,
> > initial behavior of Emacs for the initial frame?  If so, how is this
> > general change to `make-frame' the right fix for that bug?
> 
> Please re-read the discussion, the answers are there.
> 
> > And how would it hurt for `make-frame' to at least respect an _explicit_
> > frame alist argument, which is, after all, optional?  Why does it have
> > such an argument, if it no longer respects it?
> 
> The code that bothers you is not in make-frame.

What bothers me is the effect on `make-frame', regardless of where
the culprit code may be.

> > But why take over the single, general-purpose frame-creation Lisp
> > function we have, changing its behavior to ignore parts of optional
> > arg PARAMETERS (on one platform, no less), just to accommodate the
> > special case of the initial frame?
> 
> No one took over any Lisp function.

The behavior of `make-frame' (this bug) was altered drastically, so
that its optional PARAMETERS argument is at best problematic, and at
worst nearly useless.  The intention of the fix might not have been
to do that, but that was the effect on `make-frame', which is what
this bug report is about.

> The code in question is deep in
> the low-level support for creating frames on Windows.  What it does is
> make sure a frame, any frame, is not displayed with its echo area's
> view obstructed by the task bar.

That's a mistake (misguided), I think.  Why was that the solution
(or is the solution) to the problem reported, which was about the
initial frame?

As I said, it is entirely possible (and thank goodness) for either a
user or Lisp code to _move_ a frame into positions that you want to
avoid for the initial frame.  Not just positions that don't show the
echo area, but positions that can place any part - or all - of a frame
off screen. 

Can we not fix Emacs so that its avoidance of such positions is for
the initial frame only?  And if we can, let's please do that.  The
initial-frame case is a special (unique) case in this and other ways.
Why should the behavior of a general function such as `make-frame'
need to be sacrificed to fix that unique use case?

And if there _were_ a good reason for `make-frame' to avoid such
positions in a general, default case (which I would disagree with,
FWIW), why would that be the case also for the non-default cases
where you pass an explicit PARAMETERS list to `make-frame'?  Surely,
at least in that case the coder's intention should be respected.
And a fortiori if (user-position . t) is in PARAMETERS.  I cannot
see any argument for _never_ being able to have `make-frame' respect
PARAMETERS.

I think (hope) you are saying that there is no good argument for
not respecting PARAMETERS, but because of the previous, low-level fix,
that's unfortunately where we are today.  In that case, let's please
try to do better.  If `set-frame-parameter' can in a sense "override"
or work around that low-level dictation of frame positioning, then
I imagine it should be possible for `make-frame' to do the same.

If nothing else, if PARAMETERS is present, shouldn't `make-frame' be
able to at least update the frame parameters, respecting PARAMETERS,
immediately after the low-level code creates it in the (wrong) position
that it uses to avoid hiding the echo area?

> > This makes no sense to me.  And I find it hard to believe that you
> > would not consider fixing that bug properly and restoring `make-frame'
> > to a general-purpose function that respects whatever optional frame
> > parameters are specified.
> 
> You put in my mouth things I didn't say.

I'm glad to hear that, and I apologize if I misunderstood you.
It must be said that you did not say much - hardly much to go on,
to decipher your meaning or intention.

Anyway, I take it now that you will seriously consider trying to
fix this problem for `make-frame'?  That would be great, and all
that anyone could ask.

I'll say again that this is not something that annoys me in my own
use of Emacs, in general.  I stumbled on it now, with emacs -Q,
after it having been introduced 10 years ago apparently.  But I
think that Emacs's `make-frame' should behave as it did before,
even if something should be done to ensure that the initial frame
is not occluded.

---

Since I have your attention, and if it doesn't take too much of
your time, could you or Martin perhaps please recommend a way of
getting the screen-relative pixel coordinates of a given buffer
position in a given window of a given Emacs frame?

I've been fiddling a bit with test code like this, but haven't
really found anything reasonable yet:

;; Try to get screen-relative X, Y (pixels) for current point
(let* ((posn-at-pt  (posn-at-point))
       (x-y         (and posn-at-pt  (posn-x-y posn-at-pt)))
       (win-edges   (and x-y  (window-inside-absolute-pixel-edges)))
	(x           (and x-y  (+ (car x-y) (car win-edges))))
	(y           (and x-y  (+ (cdr x-y) (cadr win-edges))))
	(y           (and y  (top-fudge-pixels y))))
  ...)

(defun top-fudge-pixels (y)
  (let ((y2  y))
    (when tool-bar-mode (setq y2  (+ 40 tp)))
    (when menu-bar-mode (setq y2  (+ 25 tp)))
    (setq y2  (+ y2 28))  ; Frame title bar
    y2))

Just hoping I'm missing something simple, like a function
`screen-relative-x-y-pixels-at-point'...  Thanks, if you can
point the way.