Cocoa: Make QScreen::topLevelAt() work correctly

The QPlatformScreen::topLevelAt() default implementation
is flawed in that it does not check z-ordering but
simply returns the first window in the window list
that contains the test point.

Add QCocoaScreen::topLevelAt(). Use [NSApp orderedWindows]
to iterate through the window list in z order. Add
a NSWindow->QCococaWindow mapping hash to QCocoaIntegration
for getting the corresponding QWindow once a NSWindow
is found.

Task-number: QTBUG-37597
Change-Id: I7af70163a32528cb56f8d6caa037b98f580ee191
Reviewed-by: Gabriel de Dietrich <gabriel.dedietrich@digia.com>
This commit is contained in:
Morten Johan Sørvig 2014-04-02 12:35:09 +02:00 committed by The Qt Project
parent bb73d8d070
commit bd2ec12a7b
3 changed files with 37 additions and 0 deletions

View File

@ -80,6 +80,7 @@ public:
qreal refreshRate() const { return m_refreshRate; } qreal refreshRate() const { return m_refreshRate; }
QString name() const { return m_name; } QString name() const { return m_name; }
QPlatformCursor *cursor() const { return m_cursor; } QPlatformCursor *cursor() const { return m_cursor; }
QWindow *topLevelAt(const QPoint &point) const;
QList<QPlatformScreen *> virtualSiblings() const { return m_siblings; } QList<QPlatformScreen *> virtualSiblings() const { return m_siblings; }
// ---------------------------------------------------- // ----------------------------------------------------
@ -138,6 +139,8 @@ public:
void setToolbar(QWindow *window, NSToolbar *toolbar); void setToolbar(QWindow *window, NSToolbar *toolbar);
NSToolbar *toolbar(QWindow *window) const; NSToolbar *toolbar(QWindow *window) const;
void clearToolbars(); void clearToolbars();
void setWindow(NSWindow* nsWindow, QCocoaWindow *window);
QCocoaWindow *window(NSWindow *window);
private: private:
static QCocoaIntegration *mInstance; static QCocoaIntegration *mInstance;
@ -156,6 +159,7 @@ private:
QScopedPointer<QCocoaKeyMapper> mKeyboardMapper; QScopedPointer<QCocoaKeyMapper> mKeyboardMapper;
QHash<QWindow *, NSToolbar *> mToolbars; QHash<QWindow *, NSToolbar *> mToolbars;
QHash<NSWindow *, QCocoaWindow*> mWindows;
}; };
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@ -156,6 +156,24 @@ qreal QCocoaScreen::devicePixelRatio() const
} }
} }
QWindow *QCocoaScreen::topLevelAt(const QPoint &point) const
{
// Get a z-ordered list of windows. Iterate through it until
// we find a window which contains the point.
for (NSWindow *nsWindow in [NSApp orderedWindows]) {
QCocoaWindow *cocoaWindow = QCocoaIntegration::instance()->window(nsWindow);
if (!cocoaWindow)
continue;
QWindow *window = cocoaWindow->window();
if (!window->isTopLevel())
continue;
if (window->geometry().contains(point))
return window;
}
return QPlatformScreen::topLevelAt(point);
}
extern CGContextRef qt_mac_cg_context(const QPaintDevice *pdev); extern CGContextRef qt_mac_cg_context(const QPaintDevice *pdev);
QPixmap QCocoaScreen::grabWindow(WId window, int x, int y, int width, int height) const QPixmap QCocoaScreen::grabWindow(WId window, int x, int y, int width, int height) const
@ -500,6 +518,16 @@ NSToolbar *QCocoaIntegration::toolbar(QWindow *window) const
return mToolbars.value(window); return mToolbars.value(window);
} }
void QCocoaIntegration::setWindow(NSWindow* nsWindow, QCocoaWindow *window)
{
mWindows.insert(nsWindow, window);
}
QCocoaWindow *QCocoaIntegration::window(NSWindow *window)
{
return mWindows.value(window);
}
void QCocoaIntegration::clearToolbars() void QCocoaIntegration::clearToolbars()
{ {
QHash<QWindow *, NSToolbar *>::const_iterator it = mToolbars.constBegin(); QHash<QWindow *, NSToolbar *>::const_iterator it = mToolbars.constBegin();

View File

@ -261,6 +261,8 @@ static bool isMouseEvent(NSEvent *ev)
{ {
[self close]; [self close];
QCocoaIntegration::instance()->setWindow(self, 0);
if (self.helper.grabbingMouse) { if (self.helper.grabbingMouse) {
self.helper.releaseOnMouseUp = YES; self.helper.releaseOnMouseUp = YES;
} else { } else {
@ -327,6 +329,7 @@ static bool isMouseEvent(NSEvent *ev)
{ {
[self.helper detachFromPlatformWindow]; [self.helper detachFromPlatformWindow];
[self close]; [self close];
QCocoaIntegration::instance()->setWindow(self, 0);
[self release]; [self release];
} }
@ -1402,6 +1405,8 @@ QCocoaNSWindow * QCocoaWindow::createNSWindow()
applyContentBorderThickness(createdWindow); applyContentBorderThickness(createdWindow);
QCocoaIntegration::instance()->setWindow(createdWindow, this);
return createdWindow; return createdWindow;
} }