Cocoa: Send proper mouse coordinates.
authorMorten Sorvig <morten.sorvig@nokia.com>
Thu, 29 Sep 2011 12:24:59 +0000 (14:24 +0200)
committerQt by Nokia <qt-info@nokia.com>
Mon, 3 Oct 2011 13:31:42 +0000 (15:31 +0200)
Clear up coordinate system confusion. Also change
QApplicationPrivate::pickMouseReceiver to indicate
that, yes, it does modify the 3rd argument in
addition to returning the mouse receiver widget.

Change-Id: If2c44eff65aedfdc78c6da1728f31d6e2db71f9d
Reviewed-on: http://codereview.qt-project.org/5919
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@nokia.com>
src/plugins/platforms/cocoa/qnsview.mm
src/widgets/kernel/qapplication.cpp
src/widgets/kernel/qapplication_p.h
src/widgets/kernel/qwidgetwindow_qpa.cpp

index ea1180f..243cdb8 100644 (file)
 
 - (void)handleMouseEvent:(NSEvent *)theEvent;
 {
-    NSPoint windowPoint = [self convertPoint: [theEvent locationInWindow] fromView: nil];
-    QPoint qt_windowPoint(windowPoint.x, windowPoint.y);
-
-    NSTimeInterval timestamp = [theEvent timestamp];
-    ulong qt_timestamp = timestamp * 1000;
-
-    // ### Should the points be windowPoint and screenPoint?
-    QWindowSystemInterface::handleMouseEvent(m_window, qt_timestamp, qt_windowPoint, qt_windowPoint, m_buttons);
+    // Calculate the mouse position in the QWindow and Qt screen coordinate system,
+    // starting from coordinates in the NSWindow coordinate system.
+    //
+    // This involves translating according to the window location on screen,
+    // as well as inverting the y coordinate due to the origin change.
+    //
+    // Coordinate system overview, outer to innermost:
+    //
+    // Name             Origin
+    //
+    // OS X screen      bottom-left
+    // Qt screen        top-left
+    // NSWindow         bottom-left
+    // NSView/QWindow   top-left
+    //
+    // NSView and QWindow are equal coordinate systems: the QWindow covers the
+    // entire NSView, and we've set the NSView's isFlipped property to true.
+
+    NSPoint nsWindowPoint = [theEvent locationInWindow];                    // NSWindow coordinates
+
+    NSPoint nsViewPoint = [self convertPoint: nsWindowPoint fromView: nil]; // NSView/QWindow coordinates
+    QPoint qtWindowPoint(nsViewPoint.x, nsViewPoint.y);                     // NSView/QWindow coordinates
+
+    NSRect screenRect = [[self window] convertRectToScreen : NSMakeRect(nsWindowPoint.x, nsWindowPoint.y, 0, 0)];  // OS X screen coordinates
+    QPoint qtScreenPoint(screenRect.origin.x, qt_mac_flipYCoordinate(screenRect.origin.y));                        // Qt screen coordinates
+
+    ulong timestamp = [theEvent timestamp] * 1000;
+
+    QWindowSystemInterface::handleMouseEvent(m_window, timestamp, qtWindowPoint, qtScreenPoint, m_buttons);
 }
 
 - (void)mouseDown:(NSEvent *)theEvent
index 07035e9..5d5098c 100644 (file)
@@ -2865,7 +2865,7 @@ bool QApplicationPrivate::tryModalHelper(QWidget *widget, QWidget **rettop)
    \internal
 */
 QWidget *QApplicationPrivate::pickMouseReceiver(QWidget *candidate, const QPoint &globalPos,
-                                                QPoint &pos, QEvent::Type type,
+                                                QPoint *pos, QEvent::Type type,
                                                 Qt::MouseButtons buttons, QWidget *buttonDown,
                                                 QWidget *alienWidget)
 {
@@ -2887,7 +2887,7 @@ QWidget *QApplicationPrivate::pickMouseReceiver(QWidget *candidate, const QPoint
 
     if (mouseGrabber && mouseGrabber != candidate) {
         receiver = mouseGrabber;
-        pos = receiver->mapFromGlobal(globalPos);
+        *pos = receiver->mapFromGlobal(globalPos);
 #ifdef ALIEN_DEBUG
         qDebug() << "  ** receiver adjusted to:" << receiver << "pos:" << pos;
 #endif
index e451a53..2130a97 100644 (file)
@@ -473,7 +473,7 @@ public:
     static QString styleSheet;
 #endif
     static QPointer<QWidget> leaveAfterRelease;
-    static QWidget *pickMouseReceiver(QWidget *candidate, const QPoint &globalPos, QPoint &pos,
+    static QWidget *pickMouseReceiver(QWidget *candidate, const QPoint &globalPos, QPoint *pos,
                                       QEvent::Type type, Qt::MouseButtons buttons,
                                       QWidget *buttonDown, QWidget *alienWidget);
     static bool sendMouseEvent(QWidget *receiver, QMouseEvent *event, QWidget *alienWidget,
index 4488015..ee5cd74 100644 (file)
@@ -251,7 +251,7 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event)
     if (event->type() == QEvent::MouseButtonPress && !qt_button_down)
         qt_button_down = widget;
 
-    QWidget *receiver = QApplicationPrivate::pickMouseReceiver(m_widget, event->globalPos(), mapped, event->type(), event->buttons(),
+    QWidget *receiver = QApplicationPrivate::pickMouseReceiver(m_widget, event->globalPos(), &mapped, event->type(), event->buttons(),
                                                                qt_button_down, widget);
 
     if (!receiver) {