bug#4892: compute_motion, mouse_position

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

bug#4892: compute_motion, mouse_position

David Reitter-6
I've run into problems with mouse-position and compute-motion while  
debugging the broken drag&drop mechanism for faces in the NS port.
These problems are probably not specific to NS.

1. (mouse-position) does not return the selected frame when several  
frames overlap (partially).  To reproduce, I arrange the frames on the  
screen, then select the lower one by clicking with the mouse, then the  
one that's supposed to go on top.  With the mouse cursor still over  
the intersecting section (on top of the upper frame), I do M-: (mouse-
position).  This will then return the wrong frame.  Reproducible with  
Emacs -Q (NS port with NS frames)

2. (compute-motion) does not correspond to what's shown on the screen  
when word-wrap is turned on.

3. (mouse-position) is incorrect when face-remapping-alist is used,  
enlarging the default face, for example.


I hope these are sufficiently specific to understand and identify the  
code, if not reproduce.  Let me know if not, and I can elaborate.




In GNU Emacs 23.1.50.1 (i386-apple-darwin10.0.0, NS apple-
appkit-1038.11)
  of 2009-10-08 on scarlett.local
Windowing system distributor `Apple', version 10.3.1038
configured using `configure  '--with-ns' '--without-x' 'CC=gcc -arch  
i386''

Important settings:
   value of $LC_ALL: nil
   value of $LC_COLLATE: nil
   value of $LC_CTYPE: nil
   value of $LC_MESSAGES: nil
   value of $LC_MONETARY: nil
   value of $LC_NUMERIC: nil
   value of $LC_TIME: nil
   value of $LANG: nil
   value of $XMODIFIERS: nil
   locale-coding-system: nil
   default enable-multibyte-characters: t

Major mode: Fundamental

Minor modes in effect:
   which-function-mode: t
   tooltip-mode: t
   mouse-wheel-mode: t
   menu-bar-mode: t
   file-name-shadow-mode: t
   global-font-lock-mode: t
   font-lock-mode: t
   global-auto-composition-mode: t
   auto-composition-mode: t
   auto-encryption-mode: t
   auto-compression-mode: t
   line-number-mode: t
   transient-mark-mode: t

Recent input:
<help-echo> C-x 5 2 <help-echo> <switch-frame> <help-echo>
<help-echo> <escape> : ( m o u s e - p o s i t i o
n ) <return> <help-echo> <down-mouse-1> <help-echo>
<mouse-1> <help-echo> <down-mouse-1> <mouse-1> <help-echo>
<down-mouse-1> <mouse-1> <help-echo> <escape> : <up>
<return> <help-echo> <help-echo> <switch-frame> <help-echo>
<help-echo> <help-echo> <escape> : <up> <return> <help-echo>
<down-mouse-1> <help-echo> <mouse-1> <help-echo> <down-mouse-1>
<mouse-1> <help-echo> <down-mouse-1> <mouse-1> <escape>
: <up> <return> <help-echo> <down-mouse-1> <mouse-1>
s-n C-x k <return> s-v C-x C-e <switch-frame> C-x C-f
<backspace> <backspace> t e s t <return> <help-echo>
C-y <down-mouse-1> <mouse-1> <escape> x n s - s h o
w - c o l o <tab> <return> <backspace> <backspace>
<backspace> <backspace> <backspace> <backspace> <backspace>
<backspace> <backspace> c o l o <tab> <return> <ns-drag-color>
<ns-drag-color> <down-mouse-1> <mouse-1> <down-mouse-1>
<mouse-1> <down-mouse-1> <mouse-1> <escape> x e n l
a r <tab> <tab> C-g <escape> x z o o m <tab> <tab>
C-g <escape> x g r o w <tab> <tab> C-g <menu-bar> <help-menu>
<send-emacs-bug-report>

Recent messages:
Mark set

#<frame /Users/dr/test 0x7d5900>

Auto-saving...

#<frame /Users/dr/test 0x7d5900>

Making completion list...
Quit [2 times]
Quit

Load-path shadows:
None found.




Reply | Threaded
Open this post in threaded view
|

bug#4892: compute_motion, mouse_position

Stefan Monnier
> I've run into problems with mouse-position and compute-motion while
> debugging the broken drag&drop mechanism for faces in the NS port.
> These problems are probably not specific to NS.

Both sound like generic bugs, indeed.

Until they get fixed, I recommend you try and use posn-at-point and
posn-at-x-y rather than compute-motion, whenever possible.
For mouse-position, try to use the position info included in input
(mouse) events instead.


        Stefan



Reply | Threaded
Open this post in threaded view
|

bug#4892: compute_motion, mouse_position

Alan Third
In reply to this post by David Reitter-6
David Reitter <[hidden email]> writes:

> 1. (mouse-position) does not return the selected frame when several
> frames overlap (partially).  To reproduce, I arrange the frames on the
> screen, then select the lower one by clicking with the mouse, then the
> one that's supposed to go on top.  With the mouse cursor still over
> the intersecting section (on top of the upper frame), I do M-: (mouse-
> position).  This will then return the wrong frame.  Reproducible with
> Emacs -Q (NS port with NS frames)

It looks to me like it returns the last frame that an Emacs mouse event
was generated on. That's not necessarily the last frame clicked as the
standard behaviour on macOS is to NOT generate application events when
an OS window is selected.

It's unclear to me exactly what ns_mouse_position should be doing here.
I've had a look at the documentation and other terminal's
implementations and I'm none the wiser as there seem to be many
exceptions.

--
Alan Third



Reply | Threaded
Open this post in threaded view
|

bug#4892: [PATCH] Fix mouse-position on macOS (bug#4892)

Alan Third
* src/nsterm.m (ns_mouse_position): Implement a search for the frame
under the mouse pointer.
---
 src/nsterm.m | 52 ++++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 38 insertions(+), 14 deletions(-)

diff --git a/src/nsterm.m b/src/nsterm.m
index 52a9830be8..71234ac783 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -2475,7 +2475,7 @@ so some key presses (TAB) are swallowed by the system.  */
    -------------------------------------------------------------------------- */
 {
   id view;
-  NSPoint position;
+  NSPoint view_position;
   Lisp_Object frame, tail;
   struct frame *f;
   struct ns_display_info *dpyinfo;
@@ -2498,31 +2498,55 @@ so some key presses (TAB) are swallowed by the system.  */
       XFRAME (frame)->mouse_moved = 0;
 
   dpyinfo->last_mouse_scroll_bar = nil;
-  f = dpyinfo->ns_focus_frame ? dpyinfo->ns_focus_frame : SELECTED_FRAME ();
-  if (dpyinfo->last_mouse_frame
-      /* While dropping, use the last mouse frame only if there is no
- currently focused frame.  */
-      && (!EQ (track_mouse, Qdropping) || !f)
+
+#ifdef NS_IMPL_COCOA
+  /* Find the uppermost Emacs frame under the mouse pointer.
+
+     This doesn't work on GNUstep, although in recent versions there
+     is compatibility code that makes it a noop.  */
+
+  NSPoint screen_position = [NSEvent mouseLocation];
+  NSInteger window_number = 0;
+  do
+    {
+      NSWindow *w;
+
+      window_number = [NSWindow windowNumberAtPoint:screen_position
+                        belowWindowWithWindowNumber:window_number];
+      w = [NSApp windowWithWindowNumber:window_number];
+
+      if (w && [[w delegate] isKindOfClass:[EmacsView class]])
+        f = ((EmacsView *)[w delegate])->emacsframe;
+    }
+  while (window_number > 0 && !f);
+#endif
+
+  if (!f)
+    f = dpyinfo->ns_focus_frame ? dpyinfo->ns_focus_frame : SELECTED_FRAME ();
+
+  /* While dropping, use the last mouse frame only if there is no
+     currently focused frame.  */
+  if (!f
+      && EQ (track_mouse, Qdropping)
+      && dpyinfo->last_mouse_frame
       && FRAME_LIVE_P (dpyinfo->last_mouse_frame))
     f = dpyinfo->last_mouse_frame;
-  else
-    f = dpyinfo->ns_focus_frame ? dpyinfo->ns_focus_frame : SELECTED_FRAME ();
 
   if (f && FRAME_NS_P (f))
     {
       view = FRAME_NS_VIEW (f);
 
-      position = [[view window] mouseLocationOutsideOfEventStream];
-      position = [view convertPoint: position fromView: nil];
-      remember_mouse_glyph (f, position.x, position.y,
+      view_position = [[view window] mouseLocationOutsideOfEventStream];
+      view_position = [view convertPoint: view_position fromView: nil];
+      remember_mouse_glyph (f, view_position.x, view_position.y,
                             &dpyinfo->last_mouse_glyph);
-      NSTRACE_POINT ("position", position);
+      NSTRACE_POINT ("view_position", view_position);
 
       if (bar_window) *bar_window = Qnil;
       if (part) *part = scroll_bar_above_handle;
 
-      if (x) XSETINT (*x, lrint (position.x));
-      if (y) XSETINT (*y, lrint (position.y));
+      if (x) XSETINT (*x, lrint (view_position.x));
+      if (y) XSETINT (*y, lrint (view_position.y));
       if (time)
         *time = dpyinfo->last_mouse_movement_time;
       *fp = f;
--
2.21.0


--
Alan Third



Reply | Threaded
Open this post in threaded view
|

bug#4892: [PATCH] Fix mouse-position on macOS (bug#4892)

David Reitter-6
Looks good to me (but haven’t tried). Thanks for working on this!
DR
On Dec 4, 2019, 07:44 -0500, Alan Third <[hidden email]>, wrote:
* src/nsterm.m (ns_mouse_position): Implement a search for the frame
under the mouse pointer.
---
src/nsterm.m | 52 ++++++++++++++++++++++++++++++++++++++--------------
1 file changed, 38 insertions(+), 14 deletions(-)

diff --git a/src/nsterm.m b/src/nsterm.m
index 52a9830be8..71234ac783 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -2475,7 +2475,7 @@ so some key presses (TAB) are swallowed by the system. */
-------------------------------------------------------------------------- */
{
id view;
- NSPoint position;
+ NSPoint view_position;
Lisp_Object frame, tail;
struct frame *f;
struct ns_display_info *dpyinfo;
@@ -2498,31 +2498,55 @@ so some key presses (TAB) are swallowed by the system. */
XFRAME (frame)->mouse_moved = 0;

dpyinfo->last_mouse_scroll_bar = nil;
- f = dpyinfo->ns_focus_frame ? dpyinfo->ns_focus_frame : SELECTED_FRAME ();
- if (dpyinfo->last_mouse_frame
- /* While dropping, use the last mouse frame only if there is no
- currently focused frame. */
- && (!EQ (track_mouse, Qdropping) || !f)
+
+#ifdef NS_IMPL_COCOA
+ /* Find the uppermost Emacs frame under the mouse pointer.
+
+ This doesn't work on GNUstep, although in recent versions there
+ is compatibility code that makes it a noop. */
+
+ NSPoint screen_position = [NSEvent mouseLocation];
+ NSInteger window_number = 0;
+ do
+ {
+ NSWindow *w;
+
+ window_number = [NSWindow windowNumberAtPoint:screen_position
+ belowWindowWithWindowNumber:window_number];
+ w = [NSApp windowWithWindowNumber:window_number];
+
+ if (w && [[w delegate] isKindOfClass:[EmacsView class]])
+ f = ((EmacsView *)[w delegate])->emacsframe;
+ }
+ while (window_number > 0 && !f);
+#endif
+
+ if (!f)
+ f = dpyinfo->ns_focus_frame ? dpyinfo->ns_focus_frame : SELECTED_FRAME ();
+
+ /* While dropping, use the last mouse frame only if there is no
+ currently focused frame. */
+ if (!f
+ && EQ (track_mouse, Qdropping)
+ && dpyinfo->last_mouse_frame
&& FRAME_LIVE_P (dpyinfo->last_mouse_frame))
f = dpyinfo->last_mouse_frame;
- else
- f = dpyinfo->ns_focus_frame ? dpyinfo->ns_focus_frame : SELECTED_FRAME ();

if (f && FRAME_NS_P (f))
{
view = FRAME_NS_VIEW (f);

- position = [[view window] mouseLocationOutsideOfEventStream];
- position = [view convertPoint: position fromView: nil];
- remember_mouse_glyph (f, position.x, position.y,
+ view_position = [[view window] mouseLocationOutsideOfEventStream];
+ view_position = [view convertPoint: view_position fromView: nil];
+ remember_mouse_glyph (f, view_position.x, view_position.y,
&dpyinfo->last_mouse_glyph);
- NSTRACE_POINT ("position", position);
+ NSTRACE_POINT ("view_position", view_position);

if (bar_window) *bar_window = Qnil;
if (part) *part = scroll_bar_above_handle;

- if (x) XSETINT (*x, lrint (position.x));
- if (y) XSETINT (*y, lrint (position.y));
+ if (x) XSETINT (*x, lrint (view_position.x));
+ if (y) XSETINT (*y, lrint (view_position.y));
if (time)
*time = dpyinfo->last_mouse_movement_time;
*fp = f;
--
2.21.0


--
Alan Third