qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH v2] ui/cocoa: Fix absolute input device grabbing iss


From: Chen Zhang
Subject: [Qemu-devel] [PATCH v2] ui/cocoa: Fix absolute input device grabbing issues on Mojave
Date: Tue, 19 Mar 2019 11:51:48 +0800

On Mojave, absolute input device, i.e. tablet, had trouble re-grabbing
the cursor in re-entry into the virtual screen area. In some cases,
the `window` property of NSEvent object is nil, after exit of cursor,
meaning that the `-locationInWindow` method would return value in screen
coordinates. Current implementation used raw locations from NSEvent
without considering whether the value was for the window coordinates or
the macOS screen coordinates, nor was the zooming factor for Zoom-to-Fit
included for fullscreen mode.

In fullscreen mode, the fullscreen cocoa window might not be the key 
window, therefore location of event in virtual coordinates should suffice
for the condition of grabbing.

This patch fixed boundary check methods for cursor in normal and fullscreen
with/without Zoom-to-Fit on macOS Mojave.

Signed-off-by: Chen Zhang <address@hidden>
---
 ui/cocoa.m | 39 +++++++++++++++++++++++++++++++++++++--
 1 file changed, 37 insertions(+), 2 deletions(-)

diff --git a/ui/cocoa.m b/ui/cocoa.m
index 420b2411c1..21c20e8dd9 100644
--- a/ui/cocoa.m
+++ b/ui/cocoa.m
@@ -405,6 +405,37 @@ QemuCocoaView *cocoaView;
     return (p.x > -1 && p.x < screen.width && p.y > -1 && p.y < screen.height);
 }
 
+/* Get location of event and convert to virtual screen coordinate */
+- (CGPoint) screenLocationOfEvent:(NSEvent *)ev
+{
+    NSWindow *eventWindow = [ev window];
+    if (!eventWindow) {
+        if (!isFullscreen) {
+            return [[self window] convertPointFromScreen:[ev 
locationInWindow]];
+        } else {
+            CGPoint loc = [self convertPoint:[[self window] 
convertPointFromScreen:[ev locationInWindow]] fromView:nil];
+            if (stretch_video) {
+                loc.x /= cdx;
+                loc.y /= cdy;
+            }
+            return loc;
+        }
+    } else if ([[self window] isEqual:eventWindow]) {
+        if (!isFullscreen) {
+            return [ev locationInWindow];
+        } else {
+            CGPoint loc = [self convertPoint:[ev locationInWindow] 
fromView:nil];
+            if (stretch_video) {
+                loc.x /= cdx;
+                loc.y /= cdy;
+            }
+            return loc;
+        }
+    } else {
+        return [[self window] convertPointFromScreen:[eventWindow 
convertPointToScreen:[ev locationInWindow]]];
+    }
+}
+
 - (void) hideCursor
 {
     if (!cursor_hide) {
@@ -704,7 +735,8 @@ QemuCocoaView *cocoaView;
     int keycode = 0;
     bool mouse_event = false;
     static bool switched_to_fullscreen = false;
-    NSPoint p = [event locationInWindow];
+    // Location of event in virtual screen coordinates
+    NSPoint p = [self screenLocationOfEvent:event];
 
     switch ([event type]) {
         case NSEventTypeFlagsChanged:
@@ -815,7 +847,10 @@ QemuCocoaView *cocoaView;
             break;
         case NSEventTypeMouseMoved:
             if (isAbsoluteEnabled) {
-                if (![self screenContainsPoint:p] || ![[self window] 
isKeyWindow]) {
+                // Cursor re-entered into a window may generate events in 
screen coordinates
+                // and `nil` window property, and in full screen mode, current 
window may not be
+                // key window, where event location alone should suffice.
+                if (![self screenContainsPoint:p] || !([[self window] 
isKeyWindow] || isFullscreen)) {
                     if (isMouseGrabbed) {
                         [self ungrabMouse];
                     }
-- 
2.19.2




reply via email to

[Prev in Thread] Current Thread [Next in Thread]