diff --git a/src/corelib/kernel/qcoreapplication.h b/src/corelib/kernel/qcoreapplication.h index 0078dc32958..e27086aa052 100644 --- a/src/corelib/kernel/qcoreapplication.h +++ b/src/corelib/kernel/qcoreapplication.h @@ -238,6 +238,7 @@ private: friend class QWidget; friend class QWidgetWindow; friend class QWidgetPrivate; + friend class QWindowPrivate; #ifndef QT_NO_QOBJECT friend class QEventDispatcherUNIXPrivate; friend class QCocoaEventDispatcherPrivate; diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp index f698113ed29..f950ad1d08e 100644 --- a/src/gui/kernel/qwindow.cpp +++ b/src/gui/kernel/qwindow.cpp @@ -2449,7 +2449,7 @@ const QWindow *QWindowPrivate::forwardToPopup(QEvent *event, const QWindow */*ac /* Popups are expected to be able to directly handle the drag-release sequence after pressing to open, as well as any other mouse events that occur within the popup's bounds. */ - if (QCoreApplication::sendEvent(popupWindow, pointerEvent.get())) { + if (QCoreApplication::sendSpontaneousEvent(popupWindow, pointerEvent.get())) { event->setAccepted(pointerEvent->isAccepted()); if (pointerEvent->isAccepted()) ret = popupWindow; @@ -2458,7 +2458,7 @@ const QWindow *QWindowPrivate::forwardToPopup(QEvent *event, const QWindow */*ac << "handled?" << (ret != nullptr) << event->isAccepted(); return ret; } else if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease) { - if (QCoreApplication::sendEvent(popupWindow, event)) + if (QCoreApplication::sendSpontaneousEvent(popupWindow, event)) ret = popupWindow; qCDebug(lcPopup) << q << "forwarded" << event->type() << "to popup" << popupWindow << "handled?" << (ret != nullptr) << event->isAccepted(); diff --git a/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp b/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp index 679b824ce50..7936eb78e4e 100644 --- a/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp +++ b/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp @@ -104,6 +104,7 @@ private slots: void mouseWheel(); void popupWheelHandling(); #endif // QT_CONFIG(wheelevent) + void sendKeyEventToPopup(); void layoutDirection(); void itemListPosition(); void separatorItem_data(); @@ -2185,6 +2186,54 @@ void tst_QComboBox::popupWheelHandling() } #endif // QT_CONFIG(wheelevent) +void tst_QComboBox::sendKeyEventToPopup() +{ + struct KeyEventFilter : public QObject { + uint countWindow = 0; + uint countView = 0; + bool eventFilter(QObject *obj, QEvent *event) override + { + if (event->type() != QEvent::KeyPress) + return false; + + if (qobject_cast(obj)) + ++countWindow; + + if (qobject_cast(obj) && event->spontaneous()) + ++countView; + + return false; + } + }; + + QScrollArea scrollArea; + scrollArea.move(300, 300); + QWidget *widget = new QWidget; + scrollArea.setWidget(widget); + QVBoxLayout *layout = new QVBoxLayout(widget); + layout->setSizeConstraint(QLayout::SetMinAndMaxSize); + QComboBox *comboBox = new QComboBox; + comboBox->addItems(QStringList() << QStringLiteral("Won") << QStringLiteral("Too") + << QStringLiteral("3") << QStringLiteral("fore")); + layout->addWidget(comboBox); + layout->addSpacing(100); + const QPoint sizeP(scrollArea.width(), scrollArea.height()); + scrollArea.move(QGuiApplication::primaryScreen()->availableGeometry().center() - sizeP / 2); + scrollArea.show(); + QVERIFY(QTest::qWaitForWindowExposed(&scrollArea)); + comboBox->showPopup(); + auto *itemView = comboBox->findChild(); + QVERIFY(QTest::qWaitForWindowExposed(itemView)); + KeyEventFilter filter; + itemView->installEventFilter(&filter); + comboBox->window()->windowHandle()->installEventFilter(&filter); + QWindowSystemInterfacePrivate::KeyEvent ke(comboBox->window()->windowHandle(), 0, QEvent::KeyPress, Qt::Key_End, Qt::KeyboardModifiers()); + QGuiApplicationPrivate::processKeyEvent(&ke); + // Make sure that the key event is directly delivered to the popup + QCOMPARE(filter.countWindow, 0); + QCOMPARE(filter.countView, 1); +} + void tst_QComboBox::layoutDirection() { QComboBox box;