Skip to content

Commit

Permalink
Send events as spontaneous in QWindowPrivate::forwardToPopup()
Browse files Browse the repository at this point in the history
QWindowPrivate::forwardToPopup() sends key events with
QCoreApplication::sendEvent(), which sets QEvent::m_spont to false.
That makes key and pointer events sent to popups appear synthetic,
while they are sponaneous if sent to other widgets.

The method has been newly implemented in the course of moving
popup handling from QApplication to QGuiApplication.

Make current behavior consistent to the behavior prior to
e4ef0f0.
Since events are always spontaneous, use
QCoreApplication::sendSpontaneousEvent() instead.

Add a test function to tst_QComboBox to Verify, that key events
- are sent directly to the popup
- not seen by the window
- appear as spontaneous.

This amends e4ef0f0.

Fixes: QTBUG-129258
Change-Id: Iff61b98b290f6483948007b5f12b19393759d9db
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
(cherry picked from commit 3fbae61)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
(cherry picked from commit c20a382)
  • Loading branch information
ASpoerl authored and Qt Cherry-pick Bot committed Sep 26, 2024
1 parent d39c9d3 commit 6f48162
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 2 deletions.
1 change: 1 addition & 0 deletions src/corelib/kernel/qcoreapplication.h
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ public Q_SLOTS:
friend class QWidget;
friend class QWidgetWindow;
friend class QWidgetPrivate;
friend class QWindowPrivate;
#ifndef QT_NO_QOBJECT
friend class QEventDispatcherUNIXPrivate;
friend class QCocoaEventDispatcherPrivate;
Expand Down
4 changes: 2 additions & 2 deletions src/gui/kernel/qwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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();
Expand Down
49 changes: 49 additions & 0 deletions tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ private slots:
void mouseWheel();
void popupWheelHandling();
#endif // QT_CONFIG(wheelevent)
void sendKeyEventToPopup();
void layoutDirection();
void itemListPosition();
void separatorItem_data();
Expand Down Expand Up @@ -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<QWindow *>(obj))
++countWindow;

if (qobject_cast<QAbstractItemView *>(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<QAbstractItemView *>();
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;
Expand Down

0 comments on commit 6f48162

Please sign in to comment.