]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix macOS mouse movement
authorCharles A. Roelli <charles@aurox.ch>
Thu, 18 May 2017 19:31:46 +0000 (21:31 +0200)
committerAlan Third <alan@idiocy.org>
Sat, 20 May 2017 23:09:41 +0000 (00:09 +0100)
* lisp/frame.el (ns-set-mouse-absolute-pixel-position): New
function (Lisp).
(set-mouse-absolute-pixel-position): Change it to call
`ns-set-mouse-absolute-pixel-position' on macOS.
* src/nsfns.m (Fns_set_mouse_absolute_pixel_position): New
function.
* src/nsterm.h (NS_PARENT_WINDOW_TOP_POS): Use the primary
screen's height as a base for calculating global coordinates.
* src/nsterm.m (frame_set_mouse_pixel_position): Fix it in macOS.
* test/lisp/mouse-tests.el (bug26816-mouse-frame-movement): Test
movement of mouse relative to frame.

etc/NEWS
lisp/frame.el
src/nsfns.m
src/nsterm.h
src/nsterm.m
test/lisp/mouse-tests.el

index eeb7c773acccd0828481e2bd14e40615880f3024..1b1fec3e9141198f2abec5461f4530b02fa6ad79 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1321,6 +1321,9 @@ This is in contrast to the default action on POSIX Systems, where it
 causes the receiving process to terminate with a core dump if no
 debugger has been attached to it.
 
+** `set-mouse-position' and `set-mouse-absolute-pixel-position' work
+on macOS.
+
 \f
 ----------------------------------------------------------------------
 This file is part of GNU Emacs.
index 05db8cf6fd472abedeff9545b141c254360cfd8a..02871e0551d5582d16f956514c27f8003d0cce1e 100644 (file)
@@ -1465,6 +1465,7 @@ position (0, 0) of the selected frame's terminal."
      (t
       (cons 0 0)))))
 
+(declare-function ns-set-mouse-absolute-pixel-position "nsfns.m" (x y))
 (declare-function w32-set-mouse-absolute-pixel-position "w32fns.c" (x y))
 (declare-function x-set-mouse-absolute-pixel-position "xfns.c" (x y))
 
@@ -1474,6 +1475,8 @@ The coordinates X and Y are interpreted in pixels relative to a
 position (0, 0) of the selected frame's terminal."
   (let ((frame-type (framep-on-display)))
     (cond
+     ((eq frame-type 'ns)
+      (ns-set-mouse-absolute-pixel-position x y))
      ((eq frame-type 'x)
       (x-set-mouse-absolute-pixel-position x y))
      ((eq frame-type 'w32)
index 04565a99bb73461ec767fb8d3c4f6d5ee575ccfb..a815ce656cbe68c4d81914b0b146f8a86873bc25 100644 (file)
@@ -3066,6 +3066,44 @@ menu bar or tool bar of FRAME.  */)
                                 : Qnative_edges));
 }
 
+DEFUN ("ns-set-mouse-absolute-pixel-position",
+       Fns_set_mouse_absolute_pixel_position,
+       Sns_set_mouse_absolute_pixel_position, 2, 2, 0,
+       doc: /* Move mouse pointer to absolute pixel position (X, Y).
+The coordinates X and Y are interpreted in pixels relative to a position
+\(0, 0) of the selected frame's display.  */)
+       (Lisp_Object x, Lisp_Object y)
+{
+  struct frame *f = SELECTED_FRAME ();
+  EmacsView *view = FRAME_NS_VIEW (f);
+  NSScreen *screen = [[view window] screen];
+  NSRect screen_frame = [screen frame];
+  int mouse_x, mouse_y;
+
+  NSScreen *primary_screen = [[NSScreen screens] objectAtIndex:0];
+  NSRect primary_screen_frame = [primary_screen frame];
+  CGFloat primary_screen_height = primary_screen_frame.size.height;
+
+  if (FRAME_INITIAL_P (f) || !FRAME_NS_P (f))
+    return Qnil;
+
+  CHECK_TYPE_RANGED_INTEGER (int, x);
+  CHECK_TYPE_RANGED_INTEGER (int, y);
+
+  mouse_x = screen_frame.origin.x + XINT (x);
+
+  if (screen == primary_screen)
+    mouse_y = screen_frame.origin.y + XINT (y);
+  else
+    mouse_y = (primary_screen_height - screen_frame.size.height
+               - screen_frame.origin.y) + XINT (y);
+
+  CGPoint mouse_pos = CGPointMake(mouse_x, mouse_y);
+  CGWarpMouseCursorPosition (mouse_pos);
+
+  return Qnil;
+}
+
 /* ==========================================================================
 
     Class implementations
@@ -3254,6 +3292,7 @@ be used as the image of the icon representing the frame.  */);
   defsubr (&Sns_frame_edges);
   defsubr (&Sns_frame_list_z_order);
   defsubr (&Sns_frame_restack);
+  defsubr (&Sns_set_mouse_absolute_pixel_position);
   defsubr (&Sx_display_mm_width);
   defsubr (&Sx_display_mm_height);
   defsubr (&Sx_display_screens);
index 9285178d190ca73e649ce73cf038adccfc499603..ac339bf479289c844598fe01e0b56ade23b125eb 100644 (file)
@@ -1087,7 +1087,7 @@ struct x_output
    ? ([[FRAME_NS_VIEW (f) window] parentWindow].frame.origin.y          \
       + [[FRAME_NS_VIEW (f) window] parentWindow].frame.size.height     \
       - FRAME_NS_TITLEBAR_HEIGHT (FRAME_PARENT_FRAME (f)))              \
-   : [[[FRAME_NS_VIEW (f) window] screen] frame].size.height)
+   : [[[NSScreen screens] objectAtIndex: 0] frame].size.height)
 
 #define FRAME_NS_FONT_TABLE(f) (FRAME_DISPLAY_INFO (f)->font_table)
 
index c22c5a70baa8b7e10b01eb1608aee0344c3887cb..a7ab73b63e3cb9e50ec209056951ca2bd2a0c8e7 100644 (file)
@@ -2321,14 +2321,14 @@ frame_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y)
    -------------------------------------------------------------------------- */
 {
   NSTRACE ("frame_set_mouse_pixel_position");
-  ns_raise_frame (f);
-#if 0
-  /* FIXME: this does not work, and what about GNUstep? */
+
+  /* FIXME: what about GNUstep? */
 #ifdef NS_IMPL_COCOA
-  [FRAME_NS_VIEW (f) lockFocus];
-  PSsetmouse ((float)pix_x, (float)pix_y);
-  [FRAME_NS_VIEW (f) unlockFocus];
-#endif
+  CGPoint mouse_pos =
+    CGPointMake(f->left_pos + pix_x,
+                f->top_pos + pix_y +
+                FRAME_NS_TITLEBAR_HEIGHT(f) + FRAME_TOOLBAR_HEIGHT(f));
+  CGWarpMouseCursorPosition (mouse_pos);
 #endif
 }
 
index fffaa2fa53d1c8a350e3b04c05792ab60502e65c..a8eca28365e7ad9a8861c80cbd772feae6eaea21 100644 (file)
@@ -47,4 +47,13 @@ translate ‘mouse-1’ events into ‘mouse-2’ events."
     (should-not (mouse--down-1-maybe-follows-link))
     (should (equal unread-command-events '((mouse-2 nil 1))))))
 
+(ert-deftest bug26816-mouse-frame-movement ()
+  "Mouse moves relative to frame."
+  (skip-unless (display-graphic-p))
+  (let ((frame (selected-frame)))
+    (set-mouse-position frame 0 0)
+    (should (equal (mouse-position)
+                   (cons frame (cons 0 0))))))
+
+
 ;;; mouse-tests.el ends here