From patchwork Mon Jun 23 09:35:24 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 32341 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-pb0-f70.google.com (mail-pb0-f70.google.com [209.85.160.70]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id C807620540 for ; Mon, 23 Jun 2014 09:36:36 +0000 (UTC) Received: by mail-pb0-f70.google.com with SMTP id rp16sf24983215pbb.1 for ; Mon, 23 Jun 2014 02:36:36 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:date :message-id:in-reply-to:references:cc:subject:precedence:list-id :list-unsubscribe:list-archive:list-post:list-help:list-subscribe :errors-to:sender:x-original-sender :x-original-authentication-results:mailing-list; bh=ZOEA74cIiyn9cUrWFzmEU1+wlP2/h3RHI4zhnpTJIOk=; b=PANo8Ca9mlOkx1nZoRXinzn+JU7pN9hq3wew8ZI3+b+yt3YdlVfQySvM1g9kbvGlDt /iKLTuTV+1M0Kg4p7VankN/Lmbx08csh3Y2ZTo4oZeD6V43t3bJmFKrL6zTJv/iXYrW1 59zCMvbzldojJLbvBH6CMb5HpXz5lQKExzaf44Wi4ohbuePs5GsN6yME9BwcvK6zHodn r7jqZ+xX2NlqvPaeNcLBGIc8NEFVps2LhZGYNJcha8DSpeoxD/xqayH8snLJgl0jk7vs QetSqkE3NbOvSjrPi1I7C3pjp/Rs3rGngKP2+h3RC7zpQibfD7r4eVdx+K3QCJi52Opv I3xQ== X-Gm-Message-State: ALoCoQkjtMV2vq/kE2bgzpzinP85o8YBYW2SsZt5gnLisQbcF5sizrWute549MufluFacELVcL7f X-Received: by 10.66.169.79 with SMTP id ac15mr2977567pac.48.1403516196134; Mon, 23 Jun 2014 02:36:36 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.27.131 with SMTP id 3ls1813626qgx.9.gmail; Mon, 23 Jun 2014 02:36:36 -0700 (PDT) X-Received: by 10.52.138.14 with SMTP id qm14mr431499vdb.49.1403516196017; Mon, 23 Jun 2014 02:36:36 -0700 (PDT) Received: from mail-vc0-f182.google.com (mail-vc0-f182.google.com [209.85.220.182]) by mx.google.com with ESMTPS id nh6si8664921vec.57.2014.06.23.02.36.36 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 23 Jun 2014 02:36:36 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.182 as permitted sender) client-ip=209.85.220.182; Received: by mail-vc0-f182.google.com with SMTP id il7so5807655vcb.27 for ; Mon, 23 Jun 2014 02:36:35 -0700 (PDT) X-Received: by 10.58.187.19 with SMTP id fo19mr192485vec.45.1403516195944; Mon, 23 Jun 2014 02:36:35 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.221.37.5 with SMTP id tc5csp117435vcb; Mon, 23 Jun 2014 02:36:35 -0700 (PDT) X-Received: by 10.224.3.8 with SMTP id 8mr30702248qal.58.1403516195575; Mon, 23 Jun 2014 02:36:35 -0700 (PDT) Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id a9si21925197qaj.70.2014.06.23.02.36.35 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Mon, 23 Jun 2014 02:36:35 -0700 (PDT) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Received: from localhost ([::1]:52332 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Wz0fz-0007rZ-2m for patch@linaro.org; Mon, 23 Jun 2014 05:36:35 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:60141) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Wz0f3-0006zw-S9 for qemu-devel@nongnu.org; Mon, 23 Jun 2014 05:35:38 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Wz0f1-00062n-6g for qemu-devel@nongnu.org; Mon, 23 Jun 2014 05:35:37 -0400 Received: from mnementh.archaic.org.uk ([2001:8b0:1d0::1]:48670) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Wz0f0-00061e-Pv for qemu-devel@nongnu.org; Mon, 23 Jun 2014 05:35:35 -0400 Received: from pm215 by mnementh.archaic.org.uk with local (Exim 4.80) (envelope-from ) id 1Wz0er-0003nc-7m; Mon, 23 Jun 2014 10:35:25 +0100 From: Peter Maydell To: qemu-devel@nongnu.org Date: Mon, 23 Jun 2014 10:35:24 +0100 Message-Id: <1403516125-14568-4-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1403516125-14568-1-git-send-email-peter.maydell@linaro.org> References: <1403516125-14568-1-git-send-email-peter.maydell@linaro.org> X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2001:8b0:1d0::1 Cc: =?UTF-8?q?Andreas=20F=C3=A4rber?= , Gerd Hoffmann Subject: [Qemu-devel] [PATCH 3/4] ui/cocoa: Fix handling of absolute positioning devices X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: , List-Help: , List-Subscribe: , Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: qemu-devel-bounces+patch=linaro.org@nongnu.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: peter.maydell@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.182 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 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 --- (Note that the GTK UI backend behaves differently from SDL; I picked the SDL one to follow as it is older and less experimental, and also because the GTK behaviour of "grab-on-click and then never let go until ungrab keycombo" is problematic for Cocoa because AFAICT there's no way to get absolute mouse coordinates and still trap the mouse within our window.) --- 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;}