qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Peter Maydell <peter.maydell@linaro.org>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] [PULL 3/4] ui/cocoa: Fix handling of absolute positioning devices
Date: Mon, 30 Jun 2014 13:49:54 +0100	[thread overview]
Message-ID: <1404132595-32651-4-git-send-email-peter.maydell@linaro.org> (raw)
In-Reply-To: <1404132595-32651-1-git-send-email-peter.maydell@linaro.org>

Fix handling of absolute positioning devices, which were basically
unusable for two separate reasons:
 (1) as soon as you pressed the left mouse button we would call
     CGAssociateMouseAndMouseCursorPosition(FALSE), which means that
     the absolute coordinates of the mouse events are never updated
 (2) we didn't account for MacOSX coordinate origin being bottom left
     rather than top right, and so all the Y values sent to the guest
     were inverted

We fix (1) by aligning our behaviour with the SDL UI backend for
absolute devices:
 * when the mouse moves into the window we do a grab (which means
   hiding the host cursor and sending special keys to the guest)
 * when the mouse moves out of the window we un-grab
and fix (2) by doing the correct transformation in the call to
qemu_input_queue_abs().

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1403516125-14568-4-git-send-email-peter.maydell@linaro.org
---
 ui/cocoa.m | 75 ++++++++++++++++++++++++++++++++++++++------------------------
 1 file changed, 46 insertions(+), 29 deletions(-)

diff --git a/ui/cocoa.m b/ui/cocoa.m
index 1a626e2..06951d0 100644
--- a/ui/cocoa.m
+++ b/ui/cocoa.m
@@ -256,7 +256,7 @@ static int cocoa_keycode_to_qemu(int keycode)
     BOOL isMouseGrabbed;
     BOOL isFullscreen;
     BOOL isAbsoluteEnabled;
-    BOOL isTabletEnabled;
+    BOOL isMouseDeassociated;
 }
 - (void) switchSurface:(DisplaySurface *)surface;
 - (void) grabMouse;
@@ -264,8 +264,21 @@ static int cocoa_keycode_to_qemu(int keycode)
 - (void) toggleFullScreen:(id)sender;
 - (void) handleEvent:(NSEvent *)event;
 - (void) setAbsoluteEnabled:(BOOL)tIsAbsoluteEnabled;
+/* The state surrounding mouse grabbing is potentially confusing.
+ * isAbsoluteEnabled tracks qemu_input_is_absolute() [ie "is the emulated
+ *   pointing device an absolute-position one?"], but is only updated on
+ *   next refresh.
+ * isMouseGrabbed tracks whether GUI events are directed to the guest;
+ *   it controls whether special keys like Cmd get sent to the guest,
+ *   and whether we capture the mouse when in non-absolute mode.
+ * isMouseDeassociated tracks whether we've told MacOSX to disassociate
+ *   the mouse and mouse cursor position by calling
+ *   CGAssociateMouseAndMouseCursorPosition(FALSE)
+ *   (which basically happens if we grab in non-absolute mode).
+ */
 - (BOOL) isMouseGrabbed;
 - (BOOL) isAbsoluteEnabled;
+- (BOOL) isMouseDeassociated;
 - (float) cdx;
 - (float) cdy;
 - (QEMUScreen) gscreen;
@@ -613,14 +626,12 @@ QemuCocoaView *cocoaView;
         case NSMouseMoved:
             if (isAbsoluteEnabled) {
                 if (![self screenContainsPoint:p] || ![[self window] isKeyWindow]) {
-                    if (isTabletEnabled) { // if we leave the window, deactivate the tablet
-                        [NSCursor unhide];
-                        isTabletEnabled = FALSE;
+                    if (isMouseGrabbed) {
+                        [self ungrabMouse];
                     }
                 } else {
-                    if (!isTabletEnabled) { // if we enter the window, activate the tablet
-                        [NSCursor hide];
-                        isTabletEnabled = TRUE;
+                    if (!isMouseGrabbed) {
+                        [self grabMouse];
                     }
                 }
             }
@@ -659,16 +670,9 @@ QemuCocoaView *cocoaView;
             mouse_event = true;
             break;
         case NSLeftMouseUp:
-            if (isTabletEnabled) {
-                    mouse_event = true;
-            } else if (!isMouseGrabbed) {
-                if ([self screenContainsPoint:p]) {
-                    [self grabMouse];
-                } else {
-                    [NSApp sendEvent:event];
-                }
-            } else {
-                mouse_event = true;
+            mouse_event = true;
+            if (!isMouseGrabbed && [self screenContainsPoint:p]) {
+                [self grabMouse];
             }
             break;
         case NSRightMouseUp:
@@ -678,13 +682,11 @@ QemuCocoaView *cocoaView;
             mouse_event = true;
             break;
         case NSScrollWheel:
-            if (isTabletEnabled || isMouseGrabbed) {
+            if (isMouseGrabbed) {
                 buttons |= ([event deltaY] < 0) ?
                     MOUSE_EVENT_WHEELUP : MOUSE_EVENT_WHEELDN;
-                mouse_event = true;
-            } else {
-                [NSApp sendEvent:event];
             }
+            mouse_event = true;
             break;
         default:
             [NSApp sendEvent:event];
@@ -702,12 +704,20 @@ QemuCocoaView *cocoaView;
             qemu_input_update_buttons(dcl->con, bmap, last_buttons, buttons);
             last_buttons = buttons;
         }
-        if (isTabletEnabled) {
-            qemu_input_queue_abs(dcl->con, INPUT_AXIS_X, p.x, screen.width);
-            qemu_input_queue_abs(dcl->con, INPUT_AXIS_Y, p.y, screen.height);
-        } else if (isMouseGrabbed) {
-            qemu_input_queue_rel(dcl->con, INPUT_AXIS_X, (int)[event deltaX]);
-            qemu_input_queue_rel(dcl->con, INPUT_AXIS_Y, (int)[event deltaY]);
+        if (isMouseGrabbed) {
+            if (isAbsoluteEnabled) {
+                /* Note that the origin for Cocoa mouse coords is bottom left, not top left.
+                 * The check on screenContainsPoint is to avoid sending out of range values for
+                 * clicks in the titlebar.
+                 */
+                if ([self screenContainsPoint:p]) {
+                    qemu_input_queue_abs(dcl->con, INPUT_AXIS_X, p.x, screen.width);
+                    qemu_input_queue_abs(dcl->con, INPUT_AXIS_Y, screen.height - p.y, screen.height);
+                }
+            } else {
+                qemu_input_queue_rel(dcl->con, INPUT_AXIS_X, (int)[event deltaX]);
+                qemu_input_queue_rel(dcl->con, INPUT_AXIS_Y, (int)[event deltaY]);
+            }
         } else {
             [NSApp sendEvent:event];
         }
@@ -726,7 +736,10 @@ QemuCocoaView *cocoaView;
             [normalWindow setTitle:@"QEMU - (Press ctrl + alt to release Mouse)"];
     }
     [NSCursor hide];
-    CGAssociateMouseAndMouseCursorPosition(FALSE);
+    if (!isAbsoluteEnabled) {
+        isMouseDeassociated = TRUE;
+        CGAssociateMouseAndMouseCursorPosition(FALSE);
+    }
     isMouseGrabbed = TRUE; // while isMouseGrabbed = TRUE, QemuCocoaApp sends all events to [cocoaView handleEvent:]
 }
 
@@ -741,13 +754,17 @@ QemuCocoaView *cocoaView;
             [normalWindow setTitle:@"QEMU"];
     }
     [NSCursor unhide];
-    CGAssociateMouseAndMouseCursorPosition(TRUE);
+    if (isMouseDeassociated) {
+        CGAssociateMouseAndMouseCursorPosition(TRUE);
+        isMouseDeassociated = FALSE;
+    }
     isMouseGrabbed = FALSE;
 }
 
 - (void) setAbsoluteEnabled:(BOOL)tIsAbsoluteEnabled {isAbsoluteEnabled = tIsAbsoluteEnabled;}
 - (BOOL) isMouseGrabbed {return isMouseGrabbed;}
 - (BOOL) isAbsoluteEnabled {return isAbsoluteEnabled;}
+- (BOOL) isMouseDeassociated {return isMouseDeassociated;}
 - (float) cdx {return cdx;}
 - (float) cdy {return cdy;}
 - (QEMUScreen) gscreen {return screen;}
-- 
1.9.1

  parent reply	other threads:[~2014-06-30 12:49 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-06-30 12:49 [Qemu-devel] [PULL 0/4] cocoa queue Peter Maydell
2014-06-30 12:49 ` [Qemu-devel] [PULL 1/4] ui/cocoa: Cope with first surface being same as initial window size Peter Maydell
2014-06-30 12:49 ` [Qemu-devel] [PULL 2/4] ui/cocoa: Add utility method to check if point is within window Peter Maydell
2014-06-30 12:49 ` Peter Maydell [this message]
2014-06-30 12:49 ` [Qemu-devel] [PULL 4/4] ui/cocoa: Honour -show-cursor command line option Peter Maydell
2014-06-30 14:55 ` [Qemu-devel] [PULL 0/4] cocoa queue Peter Maydell

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

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

  git send-email \
    --in-reply-to=1404132595-32651-4-git-send-email-peter.maydell@linaro.org \
    --to=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.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.
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 NNTP newsgroup(s).