summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms
diff options
context:
space:
mode:
authorMorten Johan Sørvig <morten.sorvig@digia.com>2013-02-27 10:27:20 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-03-26 19:21:38 +0100
commitb2c73c73cd0a68aae0586cf447c2612c13aeb52c (patch)
tree35c387cf8f14240e4cc3c5f10fa0acacfe27cdc7 /src/plugins/platforms
parenta2fc37044ce3e7a51317a6528d121df632df5d68 (diff)
Cocoa: Correct enter/leave event handling.
Make top-level windows generate enter/leave events for sub-windows. Keep track of the current "under mouse" window in mouseMoved and send EnterLeave events when it changes. mouseEntered/mouseExited handles enters and leaves from the top-level window. Add tests/manual/cocoa/nativewidgets. Task-number: QTBUG-27550 Task-number: QTBUG-29751 Change-Id: If4b9f9e0f39d9fb05fdab45a100ffdcf107965ad Reviewed-by: Gabriel de Dietrich <gabriel.dedietrich@digia.com>
Diffstat (limited to 'src/plugins/platforms')
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.h2
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm15
-rw-r--r--src/plugins/platforms/cocoa/qnsview.mm44
3 files changed, 57 insertions, 4 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h
index c19017166b..5029321247 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.h
+++ b/src/plugins/platforms/cocoa/qcocoawindow.h
@@ -150,6 +150,7 @@ public:
qreal devicePixelRatio() const;
void exposeWindow();
void obscureWindow();
+ QWindow *childWindowAt(QPoint windowPoint);
protected:
// NSWindow handling. The QCocoaWindow/QNSView can either be displayed
// in an existing NSWindow or in one created by Qt.
@@ -177,6 +178,7 @@ public: // for QNSView
Qt::WindowState m_synchedWindowState;
Qt::WindowModality m_windowModality;
QPointer<QWindow> m_activePopupWindow;
+ QPointer<QWindow> m_underMouseWindow;
bool m_inConstructor;
QCocoaGLContext *m_glContext;
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index a7e75480ea..9988cea597 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -927,6 +927,21 @@ void QCocoaWindow::obscureWindow()
}
}
+QWindow *QCocoaWindow::childWindowAt(QPoint windowPoint)
+{
+ QWindow *targetWindow = window();
+ foreach (QObject *child, targetWindow->children()) {
+ if (QWindow *childWindow = qobject_cast<QWindow *>(child)) {
+ if (childWindow->geometry().contains(windowPoint)) {
+ QCocoaWindow* platformWindow = static_cast<QCocoaWindow*>(childWindow->handle());
+ targetWindow = platformWindow->childWindowAt(windowPoint - childWindow->position());
+ }
+ }
+ }
+
+ return targetWindow;
+}
+
QMargins QCocoaWindow::frameMargins() const
{
NSRect frameW = [m_nsWindow frame];
diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm
index 12a6bb9e69..3046b898df 100644
--- a/src/plugins/platforms/cocoa/qnsview.mm
+++ b/src/plugins/platforms/cocoa/qnsview.mm
@@ -599,6 +599,7 @@ static QTouchDevice *touchDevice = 0;
if (NSIsEmptyRect([self visibleRect]))
return;
+ // Remove current trakcing areas:
QCocoaAutoReleasePool pool;
if (NSArray *trackingArray = [self trackingAreas]) {
NSUInteger size = [trackingArray count];
@@ -611,7 +612,7 @@ static QTouchDevice *touchDevice = 0;
// Ideally, we shouldn't have NSTrackingMouseMoved events included below, it should
// only be turned on if mouseTracking, hover is on or a tool tip is set.
// Unfortunately, Qt will send "tooltip" events on mouse moves, so we need to
- // turn it on in ALL case. That means EVERY QCocoaView gets to pay the cost of
+ // turn it on in ALL case. That means EVERY QWindow gets to pay the cost of
// mouse moves delivered to it (Apple recommends keeping it OFF because there
// is a performance hit). So it goes.
NSUInteger trackingOptions = NSTrackingMouseEnteredAndExited | NSTrackingActiveInActiveApp
@@ -628,23 +629,58 @@ static QTouchDevice *touchDevice = 0;
{
if (m_window->flags() & Qt::WindowTransparentForInput)
return [super mouseMoved:theEvent];
- [self handleMouseEvent:theEvent];
+
+ QPoint windowPoint, screenPoint;
+ [self convertFromEvent:theEvent toWindowPoint:&windowPoint andScreenPoint:&screenPoint];
+ QWindow *childWindow = m_platformWindow->childWindowAt(windowPoint);
+
+ // Top-level windows generate enter-leave events for sub-windows.
+ // Qt wants to know which window (if any) will be entered at the
+ // the time of the leave. This is dificult to accomplish by
+ // handling mouseEnter and mouseLeave envents, since they are sent
+ // individually to different views.
+ if (m_platformWindow->m_nsWindow && childWindow) {
+ if (childWindow != m_platformWindow->m_underMouseWindow) {
+ QWindowSystemInterface::handleEnterLeaveEvent(childWindow, m_platformWindow->m_underMouseWindow, windowPoint, screenPoint);
+ m_platformWindow->m_underMouseWindow = childWindow;
+ }
+ }
+
+ // Cocoa keeps firing mouse move events for obscured parent views. Qt should not
+ // send those events so filter them out here.
+ if (childWindow != m_window)
+ return;
+
+ [self handleMouseEvent: theEvent];
}
- (void)mouseEntered:(NSEvent *)theEvent
{
if (m_window->flags() & Qt::WindowTransparentForInput)
return [super mouseEntered:theEvent];
+
+ // Top-level windows generate enter events for sub-windows.
+ if (!m_platformWindow->m_nsWindow)
+ return;
+
QPoint windowPoint, screenPoint;
[self convertFromEvent:theEvent toWindowPoint:&windowPoint andScreenPoint:&screenPoint];
- QWindowSystemInterface::handleEnterEvent(m_window, windowPoint, screenPoint);
+ m_platformWindow->m_underMouseWindow = m_platformWindow->childWindowAt(windowPoint);
+ QWindowSystemInterface::handleEnterEvent(m_platformWindow->m_underMouseWindow, windowPoint, screenPoint);
}
- (void)mouseExited:(NSEvent *)theEvent
{
if (m_window->flags() & Qt::WindowTransparentForInput)
return [super mouseExited:theEvent];
- QWindowSystemInterface::handleLeaveEvent(m_window);
+ Q_UNUSED(theEvent);
+
+ // Top-level windows generate leave events for sub-windows.
+ if (!m_platformWindow->m_nsWindow)
+ return;
+
+ QWindowSystemInterface::handleLeaveEvent(m_platformWindow->m_underMouseWindow);
+ m_platformWindow->m_underMouseWindow = 0;
}
- (void)rightMouseDown:(NSEvent *)theEvent