doc: Explain the use of QContextMenuEvent cross-platform

...and across Qt Quick and Widgets, and somewhat from a usability
perspective.

Task-number: QTBUG-67331
Task-number: QTBUG-93486
Change-Id: I75085f3a7a8e76c3e67ff5864600324faf262a76
Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
(cherry picked from commit 6e089a66a4d08a5d788c194560fccdec793e6337)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Shawn Rutledge 2024-12-12 09:31:48 +01:00 committed by Qt Cherry-pick Bot
parent 9fcce29068
commit a4d4ef9df5

View File

@ -1907,14 +1907,65 @@ Q_IMPL_EVENT_COMMON(QIconDragEvent)
\ingroup events
Context menu events are sent to widgets when a user performs
an action associated with opening a context menu.
The actions required to open context menus vary between platforms;
for example, on Windows, pressing the menu button or clicking the
right mouse button will cause this event to be sent.
A context menu event is sent when a user performs an action that should
open a contextual menu:
\list
\li clicking the right mouse button
\li pressing a dedicated keyboard menu key (if the keyboard has one,
such as the menu key on standard 104-key PC keyboards)
\li pressing some other keyboard shortcut (such as "Ctrl+Return" by
default on macOS 15 and newer)
\endlist
When this event occurs it is customary to show a QMenu with a
context menu, if this is relevant to the context.
The expected context menu should contain \l {QAction}{actions} that are
relevant to some content within the application (the "context"). In Qt, the
context is at least the particular \l {QWidget}{widget} or Qt Quick \l Item
that receives the QContextMenuEvent. If there is a selection, that should
probably be treated as the context. The context can be further refined
using \l QContextMenuEvent::pos() to pinpoint the content within the
widget, item or selection.
Widgets can override \l QWidget::contextMenuEvent() to handle this event.
Many widgets already do that, and have useful context menus by default.
Some widgets have a function such as
\l {QLineEdit::createStandardContextMenu()}{createStandardContextMenu()}
to populate the default set of actions into a \l QMenu, which can be
customized further in your subclass and then shown.
In Qt Quick, the event can be handled via the
\l {QtQuick.Controls::}{ContextMenu} attached property. Some
\l {QtQuick.Controls} Controls already provide context menus by default.
Unlike most synthetic events (such as a QMouseEvent that is sent only after
a QTouchEvent or QTabletEvent was not accepted), QContextMenuEvent is sent
regardless of whether the original mouse or key event was already handled
and \l {QEvent::isAccepted()}{accepted}. This is to accommodate the Windows
UI pattern of selecting some kind of items (icons, drawing elements, or
cells in an Item View) using the right mouse button (clicking or dragging),
and then getting a context menu as soon as you release the right mouse
button. (The actions on the menu are meant to apply to the selection.)
Therefore, on Windows the QContextMenuEvent is sent on mouse release; while
on other platforms, it's sent on press. Qt follows the
\l {QStyleHints::contextMenuTrigger()}{platform convention} by default.
There are also some Qt Quick Controls such as \l {QtQuick.Controls::}{Pane}
that accept mouse events, and nevertheless receive a QContextMenuEvent
after a mouse press or click.
If you prefer to support the press-drag-release UI pattern to open a
context menu on press, and drag over a menu item to select it on release,
you will need to do that by handling \l {QMouseEvent}{QMouseEvents} directly
(by overriding \l {QWidget::mousePressEvent()}{virtual functions} in
QWidget subclasses, or using \l TapHandler to open a \l Menu in Qt Quick);
and then the QContextMenuEvent will be redundant when the \l reason() is
\c Mouse. You should \l ignore() the event in that case; but you should
still ensure that the widget, custom control or application can respond to
a QContextMenuEvent that \l {reason()}{comes from} the platform-specific
keyboard shortcut.
When a QContextMenuEvent is \l {ignore()}{ignored}, Qt attempts to deliver
it to other widgets and/or Items under the \l {pos()}{position} (which
is usually translated from the cursor position).
*/
#ifndef QT_NO_CONTEXTMENU
@ -1968,6 +2019,9 @@ QContextMenuEvent::QContextMenuEvent(Reason reason, const QPoint &pos)
Returns the position of the mouse pointer relative to the widget
that received the event.
\note If the QContextMenuEvent did not come from the right mouse button,
\c pos() may be \l {QPoint::isNull()}{null}.
\sa x(), y(), globalPos()
*/