summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
authorDenis Dzyubenko <denis.dzyubenko@nokia.com>2009-11-26 16:32:51 (GMT)
committerDenis Dzyubenko <denis.dzyubenko@nokia.com>2009-12-02 16:10:55 (GMT)
commit0b2eab87ad3bd73a0744469a45c29ca098649c9b (patch)
treed5b26bc05eaf96c3b665aaf750135c7676db6002 /src/gui
parent271936b063fb261293e3f77f7a2273e3a4dbb5d6 (diff)
downloadQt-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.mm25
-rw-r--r--src/gui/kernel/qcocoaview_mac.mm15
-rw-r--r--src/gui/kernel/qcocoawindow_mac.mm26
-rw-r--r--src/gui/kernel/qt_cocoa_helpers_mac.mm45
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
}