diff options
author | Doris Verria <doris.verria@qt.io> | 2023-12-13 13:31:13 +0100 |
---|---|---|
committer | Doris Verria <doris.verria@qt.io> | 2023-12-16 02:39:58 +0100 |
commit | a85791ddf5384abd91232a981c8b4aae19ed93da (patch) | |
tree | e904571dff9ad247e2b8929dfc4bed6b60bd1d93 /src/quick/items/qquickitem.cpp | |
parent | c0fc9d8ab828810cdd9fd17626a6a033b1b1e5cc (diff) |
QQuickItem: Respect focusPolicy when delivering events
When delivering events that may potentially transfer focus based on the
focusPolicy of the item, we need to set the focus (if needed) before
letting the item handle the event.
Do this in QQuickItem::event so that the specific event handlers don't
need to deal with setting focus, as well as overrides don't need to
know about those handler's implementations in the base.
Task-number: QTBUG-117596
Pick-to: 6.7
Change-Id: I8223638ce4abf80c212dc63bffdb876254e43442
Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Diffstat (limited to 'src/quick/items/qquickitem.cpp')
-rw-r--r-- | src/quick/items/qquickitem.cpp | 101 |
1 files changed, 85 insertions, 16 deletions
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index 78b14df8f1..44372e8fd6 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -88,6 +88,14 @@ void debugFocusTree(QQuickItem *item, QQuickItem *scope = nullptr, int depth = 1 } } +static void setActiveFocus(QQuickItem *item, Qt::FocusReason reason) +{ + QQuickItemPrivate *d = QQuickItemPrivate::get(item); + if (d->subFocusItem && d->window && d->flags & QQuickItem::ItemIsFocusScope) + QQuickWindowPrivate::get(d->window)->clearFocusInScope(item, d->subFocusItem, reason); + item->forceActiveFocus(reason); +} + /*! \qmltype Transform \instantiates QQuickTransform @@ -1697,6 +1705,40 @@ void QQuickItemPrivate::updateSubFocusItem(QQuickItem *scope, bool focus) } } + +bool QQuickItemPrivate::setFocusIfNeeded(QEvent::Type eventType) +{ + Q_Q(QQuickItem); + const bool setFocusOnRelease = QGuiApplication::styleHints()->setFocusOnTouchRelease(); + Qt::FocusPolicy policy = Qt::ClickFocus; + + switch (eventType) { + case QEvent::MouseButtonPress: + case QEvent::MouseButtonDblClick: + case QEvent::TouchBegin: + if (setFocusOnRelease) + return false; + break; + case QEvent::MouseButtonRelease: + case QEvent::TouchEnd: + if (!setFocusOnRelease) + return false; + break; + case QEvent::Wheel: + policy = Qt::WheelFocus; + break; + default: + break; + } + + if ((focusPolicy & policy) == policy) { + setActiveFocus(q, Qt::MouseFocusReason); + return true; + } + + return false; +} + /*! \class QQuickItem \brief The QQuickItem class provides the most basic of all visual items in \l {Qt Quick}. @@ -5535,6 +5577,41 @@ bool QQuickItemPrivate::filterKeyEvent(QKeyEvent *e, bool post) return e->isAccepted(); } +void QQuickItemPrivate::deliverPointerEvent(QEvent *event) +{ + Q_Q(QQuickItem); + const auto eventType = event->type(); + const bool focusAccepted = setFocusIfNeeded(eventType); + + switch (eventType) { + case QEvent::MouseButtonPress: + q->mousePressEvent(static_cast<QMouseEvent *>(event)); + break; + case QEvent::MouseButtonRelease: + q->mouseReleaseEvent(static_cast<QMouseEvent *>(event)); + break; + case QEvent::MouseButtonDblClick: + q->mouseDoubleClickEvent(static_cast<QMouseEvent *>(event)); + break; +#if QT_CONFIG(wheelevent) + case QEvent::Wheel: + q->wheelEvent(static_cast<QWheelEvent*>(event)); + break; +#endif + case QEvent::TouchBegin: + case QEvent::TouchUpdate: + case QEvent::TouchEnd: + case QEvent::TouchCancel: + q->touchEvent(static_cast<QTouchEvent *>(event)); + break; + default: + break; + } + + if (focusAccepted) + event->accept(); +} + void QQuickItemPrivate::deliverKeyEvent(QKeyEvent *e) { Q_Q(QQuickItem); @@ -8918,8 +8995,14 @@ bool QQuickItem::event(QEvent *ev) case QEvent::TouchUpdate: case QEvent::TouchEnd: case QEvent::TouchCancel: - touchEvent(static_cast<QTouchEvent*>(ev)); - break; + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + case QEvent::MouseButtonDblClick: +#if QT_CONFIG(wheelevent) + case QEvent::Wheel: +#endif + d->deliverPointerEvent(ev); + break; case QEvent::StyleAnimationUpdate: if (isVisible()) { ev->accept(); @@ -8951,20 +9034,6 @@ bool QQuickItem::event(QEvent *ev) case QEvent::MouseMove: mouseMoveEvent(static_cast<QMouseEvent*>(ev)); break; - case QEvent::MouseButtonPress: - mousePressEvent(static_cast<QMouseEvent*>(ev)); - break; - case QEvent::MouseButtonRelease: - mouseReleaseEvent(static_cast<QMouseEvent*>(ev)); - break; - case QEvent::MouseButtonDblClick: - mouseDoubleClickEvent(static_cast<QMouseEvent*>(ev)); - break; -#if QT_CONFIG(wheelevent) - case QEvent::Wheel: - wheelEvent(static_cast<QWheelEvent*>(ev)); - break; -#endif #if QT_CONFIG(quick_draganddrop) case QEvent::DragEnter: dragEnterEvent(static_cast<QDragEnterEvent*>(ev)); |