Subject: Re: bug#28620: Interact directly on Emacs bug#28620: mouse drag event records wrong release window

From: Robert Weiner <[email-masked]>
Date: Wed, 4 Oct 2017 15:30:45 -0400

Hi Alan:

Thanks for your thoughts on this.

On Wed, Oct 4, 2017 at 2:59 PM, Alan Third <[email-masked]> wrote:

> On Wed, Oct 04, 2017 at 01:26:18PM -0400, Robert Weiner wrote:
>
> > ​So how is it that Emacs processes a drag event when the mouse button is
> > released in the new frame if it never sees the mouseUp (drag release)
> > event?​  If I drag across frames, on mouseUp, the key binding associated
> > with mouseUp (mouse-1 as opposed to down-mouse-1 is run).
>
> The NSEvent is delivered to the EmacsView belonging to the frame where
> the drag was initiated. I don’t think there’s anything we can do to
> change that.
>

​So you are saying that only one NSEvent is delivered to Emacs for both the
press and release of a drag that crosses frames?
And that Emacs internally internally recognizes both the press and release
of the mouse button and fires their respective key bindings but they both
share the location from that one NSEvent?

If so, why can't the nsterm.m mouseUp (release) handler synthesize an
NSEvent based on the current mouse position that is run prior to invoking
the keybinding for mouseUp?

​​
>
> ​​
> > > The mouse wheel code is also handled in
> ​​
> mouseDown, the difference is
> ​​
> > > that macOS always sends the mouse whe
> ​​
> el event to the emacs frame under
> ​​
> > > the mouse pointer, whereas the mouse cli
> ​​
> ck event is not sent when the
> ​​
> > > frame is not already key (i.e. selected).
> ​​
>
> ​​
​Ok, I understand that now.​

> ​
> > ​Can you show some sample code that would make macOS send the mouse drag
> ​​
> > release event to the frame under the mouse pointer just as the scroll
> wheel
> ​​
> >
> ​​
> ​​
> c
> ​​
> o
> ​​
> d
> ​​
> e
> ​​
> ​​
> d
> ​​
> o
> ​​
> e
> ​​
> s
> ​​
> .
> ​
>
> ​​
>
> ​​
> I don’t believe it’s possible. As I described before we’d have to do
> ​​
> something like:
> ​​
>
> ​​
>     [...] get a list of NSWindows, iterate over them to find out which
> ​​
>     one the mouse pointer is over, convert that NSWindow back to an Emacs
> ​​
>     frame, and [return it].
> ​​
>
> ​​
> > > AFAICT Emacs does the right thing here, exactly the same thing as
> ​​
> > > every other macOS app.
> ​​
> > >
> ​​
> > ​As Eli noted, this does not happen under MS Windows.

​I just tested under MS Windows 7 with Emacs 25 and saw the same behavior
as on the Mac (mouse-1 drag between frames yields a release event with the
depress frame rather than the release frame).  I'll have to talk to Eli
about this.
​

> ​​
>   I want to have
> ​​
> ​​
> ​​
> ​​
> ​​
> ​​
> ​​
> ​​
> ​​
> ​​
> ​​
>
> ​​
> > behavior that allows for drags across frames.  The present code does not,
> ​​
>
> ​​
> > so whether it is consistent with Mac UI guidelines, it is not useful for
> ​​
>
> ​​
> > that purpose.  I would like your help in figuring out how to enable su
> ​​
> ch
> ​​
> > behavior as you seem to understand the macOS event flow well.
> ​​
>
> ​​
>
> ​​
> But which behaviour? I can’t work out exactly what we’re talking ab
> ​​
> out
> ​​
> here. Are you trying to get cross‐frame dragging working

​Yes.​

​​
> or
> ​​
> are you
> ​​
> ​​
> ​​
> ​​
> ​​
> ​​
> ​​
> ​​
> ​​
> ​​
>
> ​​
> genuinely concerned that Emacs doesn’t receive a click event when the
> ​​
> frame is selected using the mouse? These seem like two different
> ​​
> things to me.
>

​I want to work around that if possible.  The fact that Emacs can dispatch
on the mouseUp​ event tells me that we just need to determine the proper
window of mouse position at that point and use that instead of the frame
the Mac window system provides.

> ​​
>
> ​​
> > > There’s nothing fancy here, emacsframe is an instance variable
> ​​
>
> ​​
> > > associated with the EmacsView that macOS sends the mouse
> ​​
> event to.
> ​​
> >
> ​​
>
> ​​
> >
> ​​
>
> ​​
> >
> ​​
> ​So show me how and where I could set that variable to the frame of the
> ​​
> >
> ​​
> mouse position at the point of mouseUp​ and I will test it and let people
> ​​
> >
> ​​
> know if it works.
> ​​
>
> F
> ​​
> ns_frame_list_z_order in nsfns.m does some of what’s described
> a
> ​​
> bove... But...
> ​​
>
> ​​
> It looks like there’s maybe a neater way to get the current frame
> ​​
> under the mouse...
> ​​
>
> ​​
>     Lisp_Object frame = Qnil;
> ​​
>     NSWindow *w = [NSApp windowWithWindowNumber:
> ​​
>                          [NSWindow windowNumberAtPoint:[NSEvent
> mouseLocation]
> ​​
>                            belowWindowWithWindowNumber:0]];
> ​​
>     if (w != nil)
> ​​
>       XSETFRAME (frame, ((EmacsView *)[w delegate])->emacsframe);
> ​​
>
> ​​
> I’ve not tested this, so it may not work at all. Note that [NSEvent
> ​​
> mouseLocation] returns an NSPoint indicating where the mouse is *right
> ​​
> now*. It would probably be more sensible to use any co‐ordinates
> ​​
> provided by the event itself.
>

If the coordinates represent the location of the mouseUp event rather than
mouseDown (of which I'm not sure), then why couldn't the frame differ as
well when we have the right functionality together?  Let me see if I can
test with mouseLocation first.

I would suggest that the (mouse-position) function should always return the
uppermost Z-ordered frame at point, even though it fails to do that now.

Bob