src/gui/kernel/qt_cocoa_helpers_mac.mm
changeset 3 41300fa6a67c
parent 0 1918ee327afb
child 4 3b1da2848fc7
child 7 f7bc934e204c
--- a/src/gui/kernel/qt_cocoa_helpers_mac.mm	Tue Jan 26 12:42:25 2010 +0200
+++ b/src/gui/kernel/qt_cocoa_helpers_mac.mm	Tue Feb 02 00:43:10 2010 +0200
@@ -139,6 +139,7 @@
 extern bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event); // qapplication.cpp;
 extern Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum); // qcocoaview.mm
 extern QWidget * mac_mouse_grabber;
+extern QPointer<QWidget> qt_button_down; //qapplication_mac.cpp
 
 void macWindowFade(void * /*OSWindowRef*/ window, float durationSeconds)
 {
@@ -748,7 +749,11 @@
             NSRect frameRect = [window frame];
             if (fakeNCEvents || NSMouseInRect(globalPoint, frameRect, NO)) {
                 NSRect contentRect = [window contentRectForFrameRect:frameRect];
-                if (fakeNCEvents || !NSMouseInRect(globalPoint, contentRect, NO)) {
+                qglobalPoint = QPoint(flipPoint(globalPoint).toPoint());
+                QWidget *w = widgetToGetEvent->childAt(widgetToGetEvent->mapFromGlobal(qglobalPoint));
+                // check that the mouse pointer is on the non-client area and
+                // there are not widgets in it.
+                if (fakeNCEvents || (!NSMouseInRect(globalPoint, contentRect, NO) && !w)) {
                     qglobalPoint = QPoint(flipPoint(globalPoint).toPoint());
                     qlocalPoint = widgetToGetEvent->mapFromGlobal(qglobalPoint);
                     processThisEvent = true;
@@ -759,8 +764,11 @@
     // This is not an NC area mouse message.
     if (!processThisEvent)
         return;
+
     // If the window is frame less, generate fake mouse events instead. (floating QToolBar)
-    if (fakeNCEvents && (widgetToGetEvent->window()->windowFlags() & Qt::FramelessWindowHint))
+    // or if someone already got an explicit or implicit grab
+    if (mac_mouse_grabber || qt_button_down ||
+        (fakeNCEvents && (widgetToGetEvent->window()->windowFlags() & Qt::FramelessWindowHint)))
         fakeMouseEvents = true;
 
     Qt::MouseButton button;
@@ -838,8 +846,15 @@
             leftButtonIsRightButton = false;
         }
     }
+
     QMouseEvent qme(eventType, qlocalPoint, qglobalPoint, button, button, keyMods);
     qt_sendSpontaneousEvent(widgetToGetEvent, &qme);
+
+    // We don't need to set the implicit grab widget here because we won't
+    // reach this point if then event type is Press over a Qt widget.
+    // However we might need to unset it if the event is Release.
+    if (eventType == QEvent::MouseButtonRelease)
+        qt_button_down = 0;
 #endif
 }
 
@@ -873,15 +888,12 @@
     // Find the widget that *should* get the event (e.g., maybe it was a pop-up,
     // they always get the mouse event).
     QWidget *qwidget = [theView qt_qwidget];
-    QWidget *widgetToGetMouse = qwidget;
+    QWidget *widgetToGetMouse = 0;
+    NSView *tmpView = 0;
     QWidget *popup = qAppInstance()->activePopupWidget();
-    NSView *tmpView = theView;
-    if (mac_mouse_grabber  && mac_mouse_grabber != widgetToGetMouse) {
-        widgetToGetMouse = mac_mouse_grabber;
-        tmpView = qt_mac_nativeview_for(widgetToGetMouse);
-    }
+    QPoint qglobalPoint(flipPoint(globalPoint).toPoint());
 
-    if (popup && popup != qwidget->window()) {
+    if (popup) {
         widgetToGetMouse = popup;
         tmpView = qt_mac_nativeview_for(popup);
         windowPoint = [[tmpView window] convertScreenToBase:globalPoint];
@@ -899,7 +911,17 @@
             widgetToGetMouse =
                 [static_cast<QT_MANGLE_NAMESPACE(QCocoaView) *>(tmpView) qt_qwidget];
         }
+    } else {
+        extern QPointer<QWidget> qt_button_down; //qapplication_mac.cpp
+        QPoint pos;
+        widgetToGetMouse = QApplicationPrivate::pickMouseReceiver(qwidget, qglobalPoint,
+                                                                  pos, eventType,
+                                                                  button, qt_button_down, 0);
+        if (widgetToGetMouse)
+            tmpView = qt_mac_nativeview_for(widgetToGetMouse);
     }
+    if (!widgetToGetMouse)
+        return false;
 
     NSPoint localPoint = [tmpView convertPoint:windowPoint fromView:nil];
     QPoint qlocalPoint(localPoint.x, localPoint.y);
@@ -945,14 +967,13 @@
         break;
     }
     [QT_MANGLE_NAMESPACE(QCocoaView) currentMouseEvent]->localPoint = localPoint;
-    QPoint qglobalPoint(flipPoint(globalPoint).toPoint());
     QMouseEvent qme(eventType, qlocalPoint, qglobalPoint, button, buttons, keyMods);
     qt_sendSpontaneousEvent(widgetToGetMouse, &qme);
     if (eventType == QEvent::MouseButtonPress && button == Qt::RightButton) {
         QContextMenuEvent qcme(QContextMenuEvent::Mouse, qlocalPoint, qglobalPoint, keyMods);
         qt_sendSpontaneousEvent(widgetToGetMouse, &qcme);
     }
-    return qme.isAccepted();
+    return true;
 #endif
 }
 
@@ -1152,16 +1173,23 @@
 #endif
 }
 
-QString qt_mac_get_pasteboardString()
+QString qt_mac_get_pasteboardString(OSPasteboardRef paste)
 {
     QMacCocoaAutoReleasePool pool;
-    NSPasteboard *pb = [NSPasteboard generalPasteboard];
-    NSString *text = [pb stringForType:NSStringPboardType];
-    if (text) {
-        return qt_mac_NSStringToQString(text);
+    NSPasteboard *pb = nil;
+    CFStringRef pbname;
+    if (PasteboardCopyName (paste, &pbname)) {
+        pb = [NSPasteboard generalPasteboard];
     } else {
-        return QString();
+        pb = [NSPasteboard pasteboardWithName:reinterpret_cast<const NSString *>(pbname)];
+        CFRelease (pbname);
     }
+    if (pb) {
+        NSString *text = [pb stringForType:NSStringPboardType];
+        if (text)
+            return qt_mac_NSStringToQString(text);
+    }
+    return QString();
 }
 
 QPixmap qt_mac_convert_iconref(const IconRef icon, int width, int height)