diff options
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoawindow.h | 2 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoawindow.mm | 15 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qnsview.mm | 44 | ||||
-rw-r--r-- | tests/manual/cocoa/nativewidgets/main.cpp | 147 | ||||
-rw-r--r-- | tests/manual/cocoa/nativewidgets/nativewigets.pro | 7 |
5 files changed, 211 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 diff --git a/tests/manual/cocoa/nativewidgets/main.cpp b/tests/manual/cocoa/nativewidgets/main.cpp new file mode 100644 index 0000000000..2ff919b125 --- /dev/null +++ b/tests/manual/cocoa/nativewidgets/main.cpp @@ -0,0 +1,147 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtCore> +#include <QtWidgets> + +class ColorWidget : public QWidget +{ + QColor color; + int s; + int v; + + void changeColor() + { + color.setHsv((qreal(qrand()) / RAND_MAX) * 50 + 200, s, s); + } + +public: + ColorWidget() + { + s = 150; + v = 150; + changeColor(); + setMouseTracking(true); + } + + void mousePressEvent(QMouseEvent *) + { + changeColor(); + update(); + } + + void mouseMoveEvent(QMouseEvent *) + { + changeColor(); + update(); + } + + void enterEvent(QEvent *) + { + s = 200; + v = 200; + changeColor(); + update(); + } + + void leaveEvent(QEvent *) + { + s = 75; + v = 75; + changeColor(); + update(); + } + + void paintEvent(QPaintEvent *){ + QPainter p(this); + p.fillRect(QRect(QPoint(0, 0), size()), QBrush(color)); + } +}; + + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + + ColorWidget window; + + QWidget *w1 = new ColorWidget; + QWidget *w2 = new ColorWidget; + QWidget *w3 = new ColorWidget; + + QHBoxLayout *layout = new QHBoxLayout; + layout->addWidget(w1); + layout->addWidget(w2); + layout->addWidget(w3); + + QWidget *w3_1 = new ColorWidget; + QWidget *w3_2 = new ColorWidget; + QWidget *w3_3 = new ColorWidget; + + QVBoxLayout *layout3 = new QVBoxLayout; + layout3->setMargin(0); + layout3->addWidget(w3_1); + layout3->addWidget(w3_2); + layout3->addWidget(w3_3); + w3->setLayout(layout3); + + window.setLayout(layout); + + bool native = 1; + + if (native) { + w1->winId(); + w2->winId(); + w3->winId(); + + w3_1->winId(); + w3_2->winId(); + w3_3->winId(); + } + + window.resize(640, 480); + window.show(); + + return app.exec(); +} + + + diff --git a/tests/manual/cocoa/nativewidgets/nativewigets.pro b/tests/manual/cocoa/nativewidgets/nativewigets.pro new file mode 100644 index 0000000000..f1b1260688 --- /dev/null +++ b/tests/manual/cocoa/nativewidgets/nativewigets.pro @@ -0,0 +1,7 @@ +TEMPLATE = app + +HEADERS += +SOURCES += main.cpp + +QT += core widgets +DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 |