unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
From: "Charles A. Roelli" <charles@aurox.ch>
To: Eli Zaretskii <eliz@gnu.org>, Alan Third <alan@idiocy.org>
Cc: 26816@debbugs.gnu.org
Subject: bug#26816: mouse movement support for OS X
Date: Mon, 15 May 2017 20:23:27 +0200	[thread overview]
Message-ID: <76527b19-1f31-0642-ac3a-8e55fd9b0a90@aurox.ch> (raw)
In-Reply-To: <83y3tz7bcp.fsf@gnu.org>

[-- Attachment #1: Type: text/plain, Size: 1338 bytes --]

I've added a `skip-unless' form to the beginning of the test:


(skip-unless (display-graphic-p))


Seems to take care of the issue.  Patch is attached, with a commit message.


On 14/05/2017 16:37, Eli Zaretskii wrote:
>> Date: Sun, 14 May 2017 14:59:10 +0100
>> From: Alan Third <alan@idiocy.org>
>> Cc: 26816@debbugs.gnu.org, martin rudalics <rudalics@gmx.at>,
>> 	Eli Zaretskii <eliz@gnu.org>
>>
>> On Sun, May 14, 2017 at 03:29:57PM +0200, Charles A. Roelli wrote:
>>> Attached is a patch now working with multiple monitors.  I also added
>>> `ns-set-mouse-absolute-pixel-position', a test and a NEWS entry.  The test
>>> works interactively, but it requires a frame to run and I'm not sure whether
>>> tests run with them by default.
>> Usually you run tests with ’make check’, and there’s no frame
>> available.
> There's always a frame, even in batch sessions.  Observe:
>
>    emacs -batch --eval "(message \"%s\" (selected-frame))"
>      => #<frame F1 017b9d08>
>
> It's just that it's not a frame which this feature could use.
>
>> I’ve just checked and it does throw up an error for that
>> test. I’m not sure how that should be handled.
> You could explicitly test for non-interactive sessions, and skip the
> test, or display a message that this test can only be run
> interactively.  Would that be good enough?


[-- Attachment #2: 0001-Fix-macOS-mouse-movement.patch --]
[-- Type: text/x-patch, Size: 6311 bytes --]

From 66c9d13f9709d11dd06cf640a5873d39a8fb952c Mon Sep 17 00:00:00 2001
From: Charles A. Roelli <charles@aurox.ch>
Date: Mon, 15 May 2017 20:18:21 +0200
Subject: [PATCH] Fix macOS mouse movement

* 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                 |    3 +++
 lisp/frame.el            |    3 +++
 src/nsfns.m              |   39 +++++++++++++++++++++++++++++++++++++++
 src/nsterm.h             |    2 +-
 src/nsterm.m             |   14 +++++++-------
 test/lisp/mouse-tests.el |    9 +++++++++
 6 files changed, 62 insertions(+), 8 deletions(-)

diff --git a/etc/NEWS b/etc/NEWS
index 6667a44..25f0f18 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1292,6 +1292,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.
diff --git a/lisp/frame.el b/lisp/frame.el
index 05db8cf..02871e0 100644
--- a/lisp/frame.el
+++ b/lisp/frame.el
@@ -1465,6 +1465,7 @@ mouse-absolute-pixel-position
      (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 @@ set-mouse-absolute-pixel-position
 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)
diff --git a/src/nsfns.m b/src/nsfns.m
index cbe0ffb..e916f6a 100644
--- a/src/nsfns.m
+++ b/src/nsfns.m
@@ -3053,6 +3053,44 @@ value is a list of the form (LEFT, TOP, RIGHT, BOTTOM).  All values are
 				 : 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
@@ -3241,6 +3279,7 @@ - (NSString *)panel: (id)sender userEnteredFilename: (NSString *)filename
   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);
diff --git a/src/nsterm.h b/src/nsterm.h
index 9285178..ac339bf 100644
--- a/src/nsterm.h
+++ b/src/nsterm.h
@@ -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)
 
diff --git a/src/nsterm.m b/src/nsterm.m
index c22c5a7..a7ab73b 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -2321,14 +2321,14 @@ so some key presses (TAB) are swallowed by the system. */
    -------------------------------------------------------------------------- */
 {
   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
 }
 
diff --git a/test/lisp/mouse-tests.el b/test/lisp/mouse-tests.el
index fffaa2f..70e932b 100644
--- a/test/lisp/mouse-tests.el
+++ b/test/lisp/mouse-tests.el
@@ -47,5 +47,13 @@
     (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
-- 
1.7.4.4


  reply	other threads:[~2017-05-15 18:23 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-05-07 15:11 bug#26816: mouse movement support for OS X Charles A. Roelli
2017-05-07 16:51 ` Eli Zaretskii
2017-05-08 18:34   ` Charles A. Roelli
2017-05-08 18:54     ` Eli Zaretskii
2017-05-07 18:07 ` martin rudalics
2017-05-07 20:00 ` Alan Third
2017-05-09 19:09   ` Charles A. Roelli
2017-05-09 22:44     ` Alan Third
2017-05-11 18:06       ` Charles A. Roelli
2017-05-11 21:43         ` Alan Third
2017-05-14 13:29           ` Charles A. Roelli
2017-05-14 13:59             ` Alan Third
2017-05-14 14:37               ` Eli Zaretskii
2017-05-15 18:23                 ` Charles A. Roelli [this message]
2017-05-16 22:53                   ` Alan Third
2017-05-17  8:36                     ` Andreas Schwab
2017-05-18 19:43                       ` Charles A. Roelli

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=76527b19-1f31-0642-ac3a-8e55fd9b0a90@aurox.ch \
    --to=charles@aurox.ch \
    --cc=26816@debbugs.gnu.org \
    --cc=alan@idiocy.org \
    --cc=eliz@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).