diff options
author | Denis Dzyubenko <denis.dzyubenko@nokia.com> | 2009-11-26 16:32:51 (GMT) |
---|---|---|
committer | Denis Dzyubenko <denis.dzyubenko@nokia.com> | 2009-12-02 16:10:55 (GMT) |
commit | 0b2eab87ad3bd73a0744469a45c29ca098649c9b (patch) | |
tree | d5b26bc05eaf96c3b665aaf750135c7676db6002 /src/gui | |
parent | 271936b063fb261293e3f77f7a2273e3a4dbb5d6 (diff) | |
download | Qt-0b2eab87ad3bd73a0744469a45c29ca098649c9b.zip Qt-0b2eab87ad3bd73a0744469a45c29ca098649c9b.tar.gz Qt-0b2eab87ad3bd73a0744469a45c29ca098649c9b.tar.bz2 |
Improved implicit mouse grabbing on Cocoa.
This improves 106121a74bca32a6411b9ca968ee415f8bdfbff1 which was incomplete and
didn't work properly for comboboxes (or in general - when a popup window opens
due to a mouse press).
Reviewed-by: Prasanth
Diffstat (limited to 'src/gui')
-rw-r--r-- | src/gui/kernel/qcocoapanel_mac.mm | 25 | ||||
-rw-r--r-- | src/gui/kernel/qcocoaview_mac.mm | 15 | ||||
-rw-r--r-- | src/gui/kernel/qcocoawindow_mac.mm | 26 | ||||
-rw-r--r-- | src/gui/kernel/qt_cocoa_helpers_mac.mm | 45 |
4 files changed, 69 insertions, 42 deletions
diff --git a/src/gui/kernel/qcocoapanel_mac.mm b/src/gui/kernel/qcocoapanel_mac.mm index a26d775..d201653 100644 --- a/src/gui/kernel/qcocoapanel_mac.mm +++ b/src/gui/kernel/qcocoapanel_mac.mm @@ -52,6 +52,7 @@ QT_FORWARD_DECLARE_CLASS(QWidget); QT_BEGIN_NAMESPACE extern Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum); // qcocoaview.mm +extern QPointer<QWidget> qt_button_down; //qapplication_mac.cpp QT_END_NAMESPACE QT_USE_NAMESPACE @@ -132,38 +133,41 @@ QT_USE_NAMESPACE QT_MANGLE_NAMESPACE(QCocoaView) *view = static_cast<QT_MANGLE_NAMESPACE(QCocoaView) *>(qt_mac_nativeview_for(widget)); Qt::MouseButton mouseButton = cocoaButton2QtButton([event buttonNumber]); + bool handled = false; // sometimes need to redirect mouse events to the popup. QWidget *popup = qAppInstance()->activePopupWidget(); - if (popup && popup != widget) { + if (popup) { switch([event type]) { case NSLeftMouseDown: - qt_mac_handleMouseEvent(view, event, QEvent::MouseButtonPress, mouseButton); + if (!qt_button_down) + qt_button_down = widget; + handled = qt_mac_handleMouseEvent(view, event, QEvent::MouseButtonPress, mouseButton); // Don't call super here. This prevents us from getting the mouseUp event, // which we need to send even if the mouseDown event was not accepted. // (this is standard Qt behavior.) break; case NSRightMouseDown: case NSOtherMouseDown: - if (!qt_mac_handleMouseEvent(view, event, QEvent::MouseButtonPress, mouseButton)) - [super sendEvent:event]; + if (!qt_button_down) + qt_button_down = widget; + handled = qt_mac_handleMouseEvent(view, event, QEvent::MouseButtonPress, mouseButton); break; case NSLeftMouseUp: case NSRightMouseUp: case NSOtherMouseUp: - if (!qt_mac_handleMouseEvent(view, event, QEvent::MouseButtonRelease, mouseButton)) - [super sendEvent:event]; + handled = qt_mac_handleMouseEvent(view, event, QEvent::MouseButtonRelease, mouseButton); + qt_button_down = 0; break; case NSMouseMoved: - qt_mac_handleMouseEvent(view, event, QEvent::MouseMove, Qt::NoButton); + handled = qt_mac_handleMouseEvent(view, event, QEvent::MouseMove, Qt::NoButton); break; case NSLeftMouseDragged: case NSRightMouseDragged: case NSOtherMouseDragged: [QT_MANGLE_NAMESPACE(QCocoaView) currentMouseEvent]->view = view; [QT_MANGLE_NAMESPACE(QCocoaView) currentMouseEvent]->theEvent = event; - if (!qt_mac_handleMouseEvent(view, event, QEvent::MouseMove, mouseButton)) - [super sendEvent:event]; + handled = qt_mac_handleMouseEvent(view, event, QEvent::MouseMove, mouseButton); break; default: [super sendEvent:event]; @@ -172,8 +176,9 @@ QT_USE_NAMESPACE } else { [super sendEvent:event]; } - qt_mac_dispatchNCMouseMessage(self, event, [self QT_MANGLE_NAMESPACE(qt_qwidget)], leftButtonIsRightButton); + if (!handled) + qt_mac_dispatchNCMouseMessage(self, event, [self QT_MANGLE_NAMESPACE(qt_qwidget)], leftButtonIsRightButton); [self release]; } diff --git a/src/gui/kernel/qcocoaview_mac.mm b/src/gui/kernel/qcocoaview_mac.mm index 3da783f..a4da25f 100644 --- a/src/gui/kernel/qcocoaview_mac.mm +++ b/src/gui/kernel/qcocoaview_mac.mm @@ -708,9 +708,9 @@ extern "C" { - (void)mouseUp:(NSEvent *)theEvent { - qt_button_down = 0; - qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseButtonRelease, Qt::LeftButton); + + qt_button_down = 0; } - (void)rightMouseDown:(NSEvent *)theEvent @@ -723,9 +723,9 @@ extern "C" { - (void)rightMouseUp:(NSEvent *)theEvent { - qt_button_down = 0; - qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseButtonRelease, Qt::RightButton); + + qt_button_down = 0; } - (void)otherMouseDown:(NSEvent *)theEvent @@ -739,10 +739,10 @@ extern "C" { - (void)otherMouseUp:(NSEvent *)theEvent { - qt_button_down = 0; - Qt::MouseButton mouseButton = cocoaButton2QtButton([theEvent buttonNumber]); qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseButtonRelease, mouseButton); + + qt_button_down = 0; } - (void)mouseDragged:(NSEvent *)theEvent @@ -1442,6 +1442,9 @@ Qt::DropAction QDragManager::drag(QDrag *o) pasteboard:pboard source:dndParams.view slideBack:YES]; + // reset the implicit grab widget when drag ends because we will not + // receive the mouse release event when DND is active. + qt_button_down = 0; [dndParams.view release]; [image release]; dragPrivate()->executed_action = Qt::IgnoreAction; diff --git a/src/gui/kernel/qcocoawindow_mac.mm b/src/gui/kernel/qcocoawindow_mac.mm index 263f0ac..ee5952b 100644 --- a/src/gui/kernel/qcocoawindow_mac.mm +++ b/src/gui/kernel/qcocoawindow_mac.mm @@ -52,6 +52,7 @@ QT_FORWARD_DECLARE_CLASS(QWidget); QT_BEGIN_NAMESPACE extern Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum); // qcocoaview.mm +extern QPointer<QWidget> qt_button_down; //qapplication_mac.cpp QT_END_NAMESPACE QT_USE_NAMESPACE @@ -146,40 +147,44 @@ QT_USE_NAMESPACE } [self retain]; + + bool handled = false; QT_MANGLE_NAMESPACE(QCocoaView) *view = static_cast<QT_MANGLE_NAMESPACE(QCocoaView) *>(qt_mac_nativeview_for(widget)); Qt::MouseButton mouseButton = cocoaButton2QtButton([event buttonNumber]); // sometimes need to redirect mouse events to the popup. QWidget *popup = qAppInstance()->activePopupWidget(); - if (popup && popup != widget) { + if (popup) { switch([event type]) { case NSLeftMouseDown: - qt_mac_handleMouseEvent(view, event, QEvent::MouseButtonPress, mouseButton); + if (!qt_button_down) + qt_button_down = widget; + handled = qt_mac_handleMouseEvent(view, event, QEvent::MouseButtonPress, mouseButton); // Don't call super here. This prevents us from getting the mouseUp event, // which we need to send even if the mouseDown event was not accepted. // (this is standard Qt behavior.) break; case NSRightMouseDown: case NSOtherMouseDown: - if (!qt_mac_handleMouseEvent(view, event, QEvent::MouseButtonPress, mouseButton)) - [super sendEvent:event]; + if (!qt_button_down) + qt_button_down = widget; + handled = qt_mac_handleMouseEvent(view, event, QEvent::MouseButtonPress, mouseButton); break; case NSLeftMouseUp: case NSRightMouseUp: case NSOtherMouseUp: - if (!qt_mac_handleMouseEvent(view, event, QEvent::MouseButtonRelease, mouseButton)) - [super sendEvent:event]; + handled = qt_mac_handleMouseEvent(view, event, QEvent::MouseButtonRelease, mouseButton); + qt_button_down = 0; break; case NSMouseMoved: - qt_mac_handleMouseEvent(view, event, QEvent::MouseMove, Qt::NoButton); + handled = qt_mac_handleMouseEvent(view, event, QEvent::MouseMove, Qt::NoButton); break; case NSLeftMouseDragged: case NSRightMouseDragged: case NSOtherMouseDragged: [QT_MANGLE_NAMESPACE(QCocoaView) currentMouseEvent]->view = view; [QT_MANGLE_NAMESPACE(QCocoaView) currentMouseEvent]->theEvent = event; - if (!qt_mac_handleMouseEvent(view, event, QEvent::MouseMove, mouseButton)) - [super sendEvent:event]; + handled = qt_mac_handleMouseEvent(view, event, QEvent::MouseMove, mouseButton); break; default: [super sendEvent:event]; @@ -188,8 +193,9 @@ QT_USE_NAMESPACE } else { [super sendEvent:event]; } - qt_mac_dispatchNCMouseMessage(self, event, [self QT_MANGLE_NAMESPACE(qt_qwidget)], leftButtonIsRightButton); + if (!handled) + qt_mac_dispatchNCMouseMessage(self, event, [self QT_MANGLE_NAMESPACE(qt_qwidget)], leftButtonIsRightButton); [self release]; } diff --git a/src/gui/kernel/qt_cocoa_helpers_mac.mm b/src/gui/kernel/qt_cocoa_helpers_mac.mm index 2bf1465..ef680a4 100644 --- a/src/gui/kernel/qt_cocoa_helpers_mac.mm +++ b/src/gui/kernel/qt_cocoa_helpers_mac.mm @@ -139,6 +139,7 @@ void QMacWindowFader::performFade() 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 @@ void qt_mac_dispatchNCMouseMessage(void * /* NSWindow* */eventWindow, void * /* 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 @@ void qt_mac_dispatchNCMouseMessage(void * /* NSWindow* */eventWindow, void * /* // 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 @@ void qt_mac_dispatchNCMouseMessage(void * /* NSWindow* */eventWindow, void * /* 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 @@ bool qt_mac_handleMouseEvent(void * /* NSView * */view, void * /* NSEvent * */ev // 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]; @@ -901,13 +913,15 @@ bool qt_mac_handleMouseEvent(void * /* NSView * */view, void * /* NSEvent * */ev } } else { extern QPointer<QWidget> qt_button_down; //qapplication_mac.cpp - if (!mac_mouse_grabber && qt_button_down) { - // if there is no explicit grabber, and the mouse was grabbed - // implicitely (i.e. a mousebutton was pressed) - widgetToGetMouse = qt_button_down; + 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); @@ -953,14 +967,13 @@ bool qt_mac_handleMouseEvent(void * /* NSView * */view, void * /* NSEvent * */ev 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 } |