summaryrefslogtreecommitdiffstats
path: root/src/widgets/kernel/qwidgetwindow.cpp
diff options
context:
space:
mode:
authorShawn Rutledge <[email protected]>2024-11-12 10:04:31 +0100
committerShawn Rutledge <[email protected]>2024-12-07 08:27:51 +0100
commit84a5f50c7766c99f62b22bb4388137e0aa8dd13d (patch)
tree5bfba5ae3ef25ea8cd8ab0d039521d155477aa32 /src/widgets/kernel/qwidgetwindow.cpp
parent953b7aaddc7579a253cd15562de6eec9476245e4 (diff)
Move QContextMenuEvent synthesis from QWidgetWindow to QWindow
...and only if the original mouse event is not accepted. To that end, QGraphicsView must setAccepted(false) if the graphics scene did not accept the QGraphicsSceneMouseEvent. So a widget or a Qt Quick item or handler can handle the mouse events directly, to provide a consistent context-menu experience across platforms (for example to handle the press-drag-release gesture), but the fallback pattern follows the platform behavior. QWidgetWindow::handleMouseEvent() picks the receiver in its own way: often a leaf widget. It sets qt_last_mouse_receiver, so QWidgetWindow::handleContextMenuEvent() can deliver a mouse-originating QContextMenuEvent to the same receiver. A keyboard-originating QContextMenuEvent is delivered to the focus widget instead, as before. As a drive-by: fix an awkward word in qCDebug output. Task-number: QTBUG-93486 Change-Id: I4c1499120851a899acf2d7d4adaedaf9f42c3126 Reviewed-by: Mitch Curtis <[email protected]> Reviewed-by: Jan Arve Sæther <[email protected]>
Diffstat (limited to 'src/widgets/kernel/qwidgetwindow.cpp')
-rw-r--r--src/widgets/kernel/qwidgetwindow.cpp63
1 files changed, 32 insertions, 31 deletions
diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp
index 9b2d6ca31d4..d337679fb2d 100644
--- a/src/widgets/kernel/qwidgetwindow.cpp
+++ b/src/widgets/kernel/qwidgetwindow.cpp
@@ -505,6 +505,7 @@ void QWidgetWindow::handleNonClientAreaMouseEvent(QMouseEvent *e)
void QWidgetWindow::handleMouseEvent(QMouseEvent *event)
{
+ Q_D(QWidgetWindow);
if (auto *activePopupWidget = QApplication::activePopupWidget()) {
QPointF mapped = event->position();
if (activePopupWidget != m_widget)
@@ -647,7 +648,7 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event)
if (!receiver)
return;
- if (d_func()->isPopup() && receiver->window()->windowHandle() != this) {
+ if (d->isPopup() && receiver->window()->windowHandle() != this) {
receiver = widget;
mapped = event->position().toPoint();
}
@@ -664,16 +665,8 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event)
&qt_button_down, qt_last_mouse_receiver);
event->setAccepted(translated.isAccepted());
}
-#ifndef QT_NO_CONTEXTMENU
- if (event->type() == QGuiApplicationPrivate::contextMenuEventType()
- && event->button() == Qt::RightButton
- && m_widget->rect().contains(event->position().toPoint())) {
- QContextMenuEvent e(QContextMenuEvent::Mouse, mapped.toPoint(), event->globalPosition().toPoint(), event->modifiers());
- QGuiApplication::forwardEvent(receiver, &e, event);
- if (e.isAccepted())
- event->accept();
- }
-#endif
+
+ d->maybeSynthesizeContextMenuEvent(event);
}
void QWidgetWindow::handleTouchEvent(QTouchEvent *event)
@@ -1165,28 +1158,36 @@ void QWidgetWindow::handleGestureEvent(QNativeGestureEvent *e)
#ifndef QT_NO_CONTEXTMENU
void QWidgetWindow::handleContextMenuEvent(QContextMenuEvent *e)
{
- // We are only interested in keyboard originating context menu events here,
- // mouse originated context menu events for widgets are generated in mouse handling methods.
- if (e->reason() != QContextMenuEvent::Keyboard)
- return;
-
- QWidget *fw = QWidget::keyboardGrabber();
- if (!fw) {
- if (QApplication::activePopupWidget()) {
- fw = (QApplication::activePopupWidget()->focusWidget()
- ? QApplication::activePopupWidget()->focusWidget()
- : QApplication::activePopupWidget());
- } else if (QApplication::focusWidget()) {
- fw = QApplication::focusWidget();
- } else {
- fw = m_widget;
+ QWidget *receiver = qt_last_mouse_receiver.get();
+ QPoint pos = e->pos();
+ QPoint globalPos = e->globalPos();
+
+ // Keyboard-originating context menu events are delivered to the focus widget,
+ // independently of event position.
+ if (e->reason() == QContextMenuEvent::Keyboard) {
+ receiver = QWidget::keyboardGrabber();
+ if (!receiver) {
+ if (QApplication::activePopupWidget()) {
+ receiver = (QApplication::activePopupWidget()->focusWidget()
+ ? QApplication::activePopupWidget()->focusWidget()
+ : QApplication::activePopupWidget());
+ } else if (QApplication::focusWidget()) {
+ receiver = QApplication::focusWidget();
+ } else {
+ receiver = m_widget;
+ }
}
+ if (Q_LIKELY(receiver)) {
+ pos = receiver->inputMethodQuery(Qt::ImCursorRectangle).toRect().center();
+ globalPos = receiver->mapToGlobal(pos);
+ }
+ } else if (Q_LIKELY(receiver)) {
+ pos = receiver->mapFromGlobal(e->globalPos());
}
- if (fw && fw->isEnabled()) {
- QPoint pos = fw->inputMethodQuery(Qt::ImCursorRectangle).toRect().center();
- QContextMenuEvent widgetEvent(QContextMenuEvent::Keyboard, pos, fw->mapToGlobal(pos),
- e->modifiers());
- QGuiApplication::forwardEvent(fw, &widgetEvent, e);
+
+ if (receiver && receiver->isEnabled()) {
+ QContextMenuEvent widgetEvent(e->reason(), pos, globalPos, e->modifiers());
+ QGuiApplication::forwardEvent(receiver, &widgetEvent, e);
}
}
#endif // QT_NO_CONTEXTMENU