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>
This commit is contained in:
parent
a2fc37044c
commit
b2c73c73cd
@ -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;
|
||||
|
@ -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];
|
||||
|
@ -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
|
||||
|
147
tests/manual/cocoa/nativewidgets/main.cpp
Normal file
147
tests/manual/cocoa/nativewidgets/main.cpp
Normal file
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
7
tests/manual/cocoa/nativewidgets/nativewigets.pro
Normal file
7
tests/manual/cocoa/nativewidgets/nativewigets.pro
Normal file
@ -0,0 +1,7 @@
|
||||
TEMPLATE = app
|
||||
|
||||
HEADERS +=
|
||||
SOURCES += main.cpp
|
||||
|
||||
QT += core widgets
|
||||
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
|
Loading…
x
Reference in New Issue
Block a user