From a4d4ef9df5a99c0952079972fcd1b14078ede280 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Thu, 12 Dec 2024 09:31:48 +0100 Subject: [PATCH] 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 (cherry picked from commit 6e089a66a4d08a5d788c194560fccdec793e6337) Reviewed-by: Qt Cherry-pick Bot --- src/gui/kernel/qevent.cpp | 68 +++++++++++++++++++++++++++++++++++---- 1 file changed, 61 insertions(+), 7 deletions(-) diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index 5f4daced732..d0c2ddb2b3a 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -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() */