QWidgetWindow: use sendEvent to forward events to the wrapped QWidget

The fallback code for unhandled event types in QWidgetWindow::event
directly called event() on the underlying QWidget (i.e. m_widget->event(e)).

The problem with that approach is that it does not activate any
event filters that can have been installed on the top level widget.
Instead, let's use sendEvent to forward the event to the widget.

An extra modification becomes necessary:
the events received when creating/showing/etc. a widget change,
hence the corresponding test needs to be tuned. On the other hand,
apparently this fixes a long time XFAIL in that test.

Task-number: QTBUG-42281
Task-number: QTBUG-26424
Change-Id: I237bbbc301e3e9e10f071589629c71343a600ef9
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
This commit is contained in:
Giuseppe D'Angelo 2014-12-19 12:34:45 +01:00
parent d59638f21d
commit 51af196ba0
4 changed files with 64 additions and 15 deletions

View File

@ -6116,8 +6116,15 @@ QIcon QWidget::windowIcon() const
void QWidgetPrivate::setWindowIcon_helper()
{
Q_Q(QWidget);
QEvent e(QEvent::WindowIconChange);
QApplication::sendEvent(q_func(), &e);
// Do not send the event if the widget is a top level.
// In that case, setWindowIcon_sys does it, and event propagation from
// QWidgetWindow to the top level QWidget ensures that the event reaches
// the top level anyhow
if (!q->windowHandle())
QApplication::sendEvent(q, &e);
for (int i = 0; i < children.size(); ++i) {
QWidget *w = qobject_cast<QWidget *>(children.at(i));
if (w && !w->isWindow())

View File

@ -161,7 +161,7 @@ bool QWidgetWindow::event(QEvent *event)
if (m_widget->testAttribute(Qt::WA_DontShowOnScreen)) {
// \a event is uninteresting for QWidgetWindow, the event was probably
// generated before WA_DontShowOnScreen was set
return m_widget->event(event);
return QCoreApplication::sendEvent(m_widget, event);
}
switch (event->type()) {
@ -303,7 +303,7 @@ bool QWidgetWindow::event(QEvent *event)
break;
}
if (m_widget->event(event) && event->type() != QEvent::Timer)
if (QCoreApplication::sendEvent(m_widget, event) && event->type() != QEvent::Timer)
return true;
return QWindow::event(event);

View File

@ -6010,10 +6010,13 @@ void tst_QWidget::childEvents()
expected =
EventRecorder::EventList()
<< qMakePair(&widget, QEvent::Polish)
<< qMakePair(&widget, QEvent::PlatformSurface)
<< qMakePair(&widget, QEvent::WinIdChange)
<< qMakePair(&widget, QEvent::WindowIconChange)
<< qMakePair(&widget, QEvent::Move)
<< qMakePair(&widget, QEvent::Resize)
<< qMakePair(&widget, QEvent::Show)
<< qMakePair(&widget, QEvent::CursorChange)
<< qMakePair(&widget, QEvent::ShowToParent);
QVERIFY2(spy.eventList() == expected,
@ -6025,13 +6028,9 @@ void tst_QWidget::childEvents()
EventRecorder::EventList()
<< qMakePair(&widget, QEvent::PolishRequest)
<< qMakePair(&widget, QEvent::Type(QEvent::User + 1))
#if defined(Q_OS_OSX) || defined(Q_OS_QNX)
<< qMakePair(&widget, QEvent::UpdateLater)
#endif
<< qMakePair(&widget, QEvent::UpdateRequest);
if (m_platform == QStringLiteral("windows") || m_platform == QStringLiteral("xcb"))
QEXPECT_FAIL("", EventRecorder::msgExpectFailQtBug26424(expected, spy.eventList()).constData(), Continue);
QVERIFY2(spy.eventList() == expected,
EventRecorder::msgEventListMismatch(expected, spy.eventList()).constData());
}
@ -6100,10 +6099,13 @@ void tst_QWidget::childEvents()
<< qMakePair(&widget, QEvent::Polish)
<< qMakePair(&widget, QEvent::ChildPolished)
<< qMakePair(&widget, QEvent::ChildPolished)
<< qMakePair(&widget, QEvent::PlatformSurface)
<< qMakePair(&widget, QEvent::WinIdChange)
<< qMakePair(&widget, QEvent::WindowIconChange)
<< qMakePair(&widget, QEvent::Move)
<< qMakePair(&widget, QEvent::Resize)
<< qMakePair(&widget, QEvent::Show)
<< qMakePair(&widget, QEvent::CursorChange)
<< qMakePair(&widget, QEvent::ShowToParent);
QVERIFY2(spy.eventList() == expected,
@ -6116,13 +6118,9 @@ void tst_QWidget::childEvents()
<< qMakePair(&widget, QEvent::PolishRequest)
<< qMakePair(&widget, QEvent::Type(QEvent::User + 1))
<< qMakePair(&widget, QEvent::Type(QEvent::User + 2))
#if defined(Q_OS_OSX) || defined(Q_OS_QNX)
<< qMakePair(&widget, QEvent::UpdateLater)
#endif
<< qMakePair(&widget, QEvent::UpdateRequest);
if (m_platform == QStringLiteral("windows") || m_platform == QStringLiteral("xcb"))
QEXPECT_FAIL("", EventRecorder::msgExpectFailQtBug26424(expected, spy.eventList()).constData(), Continue);
QVERIFY2(spy.eventList() == expected,
EventRecorder::msgEventListMismatch(expected, spy.eventList()).constData());
}
@ -6193,10 +6191,13 @@ void tst_QWidget::childEvents()
EventRecorder::EventList()
<< qMakePair(&widget, QEvent::Polish)
<< qMakePair(&widget, QEvent::ChildPolished)
<< qMakePair(&widget, QEvent::PlatformSurface)
<< qMakePair(&widget, QEvent::WinIdChange)
<< qMakePair(&widget, QEvent::WindowIconChange)
<< qMakePair(&widget, QEvent::Move)
<< qMakePair(&widget, QEvent::Resize)
<< qMakePair(&widget, QEvent::Show)
<< qMakePair(&widget, QEvent::CursorChange)
<< qMakePair(&widget, QEvent::ShowToParent);
QVERIFY2(spy.eventList() == expected,
@ -6209,13 +6210,9 @@ void tst_QWidget::childEvents()
<< qMakePair(&widget, QEvent::PolishRequest)
<< qMakePair(&widget, QEvent::Type(QEvent::User + 1))
<< qMakePair(&widget, QEvent::Type(QEvent::User + 2))
#if defined(Q_OS_OSX) || defined(Q_OS_QNX)
<< qMakePair(&widget, QEvent::UpdateLater)
#endif
<< qMakePair(&widget, QEvent::UpdateRequest);
if (m_platform == QStringLiteral("windows") || m_platform == QStringLiteral("xcb"))
QEXPECT_FAIL("", EventRecorder::msgExpectFailQtBug26424(expected, spy.eventList()).constData(), Continue);
QVERIFY2(spy.eventList() == expected,
EventRecorder::msgEventListMismatch(expected, spy.eventList()).constData());
}

View File

@ -97,6 +97,8 @@ private slots:
void tst_resize_count();
void tst_move_count();
void tst_eventfilter_on_toplevel();
};
void tst_QWidget_window::initTestCase()
@ -762,5 +764,48 @@ void tst_QWidget_window::tst_move_count()
QTRY_VERIFY(move.moveCount >= 1);
}
class EventFilter : public QObject
{
public:
int eventCount;
EventFilter()
: QObject(),
eventCount(0)
{
}
static QEvent::Type filterEventType()
{
static int type = QEvent::registerEventType();
return static_cast<QEvent::Type>(type);
}
protected:
bool eventFilter(QObject *o, QEvent *e) Q_DECL_OVERRIDE
{
if (e->type() == filterEventType())
++eventCount;
return QObject::eventFilter(o, e);
}
};
void tst_QWidget_window::tst_eventfilter_on_toplevel()
{
QWidget w;
EventFilter filter;
w.installEventFilter(&filter);
w.show();
QVERIFY(QTest::qWaitForWindowActive(&w));
QVERIFY(w.isWindow());
QCOMPARE(filter.eventCount, 0);
// send an event not handled in a special way by QWidgetWindow::event,
// and check that it's received by the event filter
QCoreApplication::postEvent(w.windowHandle(), new QEvent(EventFilter::filterEventType()));
QTRY_COMPARE(filter.eventCount, 1);
}
QTEST_MAIN(tst_QWidget_window)
#include "tst_qwidget_window.moc"