Always send QContextMenuEvent after the contextMenuEventType event

Both widgets and Qt Quick Controls are unable to avoid accepting the
right-click events (press and/or release) in at least some cases.
In the Windows UI pattern of allowing the user to select something by
pressing (and maybe dragging) with the right button and then getting
a QContextMenuEvent afterwards, it's sensible for the code that does
the selection to accept the mouse events, because that code is only
concerned with selection, not the context menu. And in Controls,
Pane is accepting all mouse events just to prevent propagation to
other controls underneath. (That might not be so great, but we don't
have a better way yet.) In legacy Qt Quick, accepting the event results
in an exclusive grab; so in fact, Pane gets the grab, so we can't use
that either, as a way to distinguish "stop propagation" from "this item
is handling it completely, nothing more needs to be done". So it
doesn't make sense for QWindowPrivate::maybeSynthesizeContextMenuEvent
to check the grabber either.

Amends 357c64a99607456133bfabf86d6b67162717cb29 and
84a5f50c7766c99f62b22bb4388137e0aa8dd13d

Task-number: QTBUG-67331
Task-number: QTBUG-93486
Task-number: QTBUG-132066
Fixes: QTBUG-132073
Change-Id: I822cada05cfef27afe6a44faf170585f027061f7
Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
Reviewed-by: Jan Arve Sæther <jan-arve.saether@qt.io>
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
(cherry picked from commit 70c61b12efe9d1faf24063b63cf5a69414d45cea)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Shawn Rutledge 2024-12-11 13:08:33 +01:00 committed by Qt Cherry-pick Bot
parent 835475873b
commit 019feea9b1

View File

@ -2750,21 +2750,27 @@ bool QWindow::event(QEvent *ev)
}
/*! \internal
Synthesize and send a QContextMenuEvent if the given \a event is a
suitable mouse event (a right-button press or release, depending on
QStyleHints::contextMenuTrigger()) that *isn't* exclusively grabbed.
On most platforms, it's done on mouse release; on
Windows, it's done on press, because of the potential to support
right-button clicks and drags to select or lasso items, and then still
getting a context menu at the end of that gesture. (That is in conflict
with supporting the press-drag-release gesture to select menu items on the
context menus themselves. Context menus can be implemented that way by
handling the separate press, move and release events.) Any time the
\a event was already handled in some way, it *should* be accepted, to
indicate that it's not necessary to synthesize a QContextMenuEvent here.
However, there's enough legacy widget code that doesn't call ignore()
on unhandled mouse events, that in QWidgetWindow, we put off requiring
the event to be ignored. Hopefully we can begin requiring it in Qt 7.
Synthesize and send a QContextMenuEvent if the given \a event is a suitable
mouse event (a right-button press or release, depending on
QStyleHints::contextMenuTrigger()). On most platforms, it's done on mouse
press; on Windows, it's done on release, because of the potential to
support right-button clicks and drags to select or lasso items, and then
still getting a context menu at the end of that gesture. (That is in
conflict with supporting the press-drag-release gesture to select menu
items on the context menus themselves. Context menus can be implemented
that way by handling the separate press, move and release events.)
Any time the \a event was already handled in some way, it *should* be
accepted, but mere acceptance of the mouse event cannot be taken to
indicate that it's not necessary to synthesize a QContextMenuEvent here,
because the Windows use case requires doing one thing (selecting items)
with the mouse events, and then doing something completely different with
the QContextMenuEvent. In other words, QContextMenuEvent is very different
from other kinds of optional followup events synthesized from unhandled
events (like the way we synthesize a QMouseEvent only if a QTabletEvent was
not handled). Furthermore, there's enough legacy widget code that doesn't
call ignore() on unhandled mouse events. So it's uncertain whether this can
change in Qt 7.
The QContextMenuEvent occurs at the scenePosition(). The position()
was likely already "localized" during the previous delivery.
@ -2784,7 +2790,7 @@ bool QWindow::event(QEvent *ev)
void QWindowPrivate::maybeSynthesizeContextMenuEvent(QMouseEvent *event)
{
#ifndef QT_NO_CONTEXTMENU
if (!event->exclusivePointGrabber() && event->button() == Qt::RightButton
if (event->button() == Qt::RightButton
&& event->type() == QGuiApplicationPrivate::contextMenuEventType()) {
QContextMenuEvent e(QContextMenuEvent::Mouse, event->scenePosition().toPoint(),
event->globalPosition().toPoint(), event->modifiers());