aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/items/qquickmousearea.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/quick/items/qquickmousearea.cpp')
-rw-r--r--src/quick/items/qquickmousearea.cpp291
1 files changed, 163 insertions, 128 deletions
diff --git a/src/quick/items/qquickmousearea.cpp b/src/quick/items/qquickmousearea.cpp
index 0b345697ec..7e68dd8be3 100644
--- a/src/quick/items/qquickmousearea.cpp
+++ b/src/quick/items/qquickmousearea.cpp
@@ -1,46 +1,12 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQuick module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qquickmousearea_p.h"
#include "qquickmousearea_p_p.h"
#include "qquickwindow.h"
+#if QT_CONFIG(quick_draganddrop)
#include "qquickdrag_p.h"
+#endif
#include <private/qqmldata_p.h>
#include <private/qsgadaptationlayer_p.h>
@@ -53,16 +19,14 @@
QT_BEGIN_NAMESPACE
-DEFINE_BOOL_CONFIG_OPTION(qmlVisualTouchDebugging, QML_VISUAL_TOUCH_DEBUGGING)
-
-Q_DECLARE_LOGGING_CATEGORY(DBG_HOVER_TRACE)
+DEFINE_BOOL_CONFIG_OPTION(qmlMaVisualTouchDebugging, QML_VISUAL_TOUCH_DEBUGGING)
QQuickMouseAreaPrivate::QQuickMouseAreaPrivate()
-: enabled(true), scrollGestureEnabled(true), hovered(false), longPress(false),
+: enabled(true), hoverEnabled(false), scrollGestureEnabled(true), hovered(false), longPress(false),
moved(false), stealMouse(false), doubleClick(false), preventStealing(false),
- propagateComposedEvents(false), overThreshold(false), pressed(nullptr),
+ propagateComposedEvents(false), overThreshold(false),
pressAndHoldInterval(-1)
-#if QT_CONFIG(draganddrop)
+#if QT_CONFIG(quick_draganddrop)
, drag(nullptr)
#endif
#if QT_CONFIG(cursor)
@@ -73,7 +37,7 @@ QQuickMouseAreaPrivate::QQuickMouseAreaPrivate()
QQuickMouseAreaPrivate::~QQuickMouseAreaPrivate()
{
-#if QT_CONFIG(draganddrop)
+#if QT_CONFIG(quick_draganddrop)
delete drag;
#endif
#if QT_CONFIG(cursor)
@@ -87,15 +51,15 @@ void QQuickMouseAreaPrivate::init()
q->setAcceptedMouseButtons(Qt::LeftButton);
q->setAcceptTouchEvents(false); // rely on mouse events synthesized from touch
q->setFiltersChildMouseEvents(true);
- if (qmlVisualTouchDebugging()) {
+ if (qmlMaVisualTouchDebugging()) {
q->setFlag(QQuickItem::ItemHasContents);
}
}
void QQuickMouseAreaPrivate::saveEvent(QMouseEvent *event)
{
- lastPos = event->localPos();
- lastScenePos = event->windowPos();
+ lastPos = event->position();
+ lastScenePos = event->scenePosition();
lastButton = event->button();
lastButtons = event->buttons();
lastModifiers = event->modifiers();
@@ -120,11 +84,13 @@ bool QQuickMouseAreaPrivate::isClickConnected()
IS_SIGNAL_CONNECTED(q, QQuickMouseArea, clicked, (QQuickMouseEvent *));
}
+#if QT_CONFIG(wheelevent)
bool QQuickMouseAreaPrivate::isWheelConnected()
{
Q_Q(QQuickMouseArea);
IS_SIGNAL_CONNECTED(q, QQuickMouseArea, wheel, (QQuickWheelEvent *));
}
+#endif
void QQuickMouseAreaPrivate::propagate(QQuickMouseEvent* event, PropagateType t)
{
@@ -149,7 +115,7 @@ bool QQuickMouseAreaPrivate::propagateHelper(QQuickMouseEvent *ev, QQuickItem *i
}
QList<QQuickItem *> children = itemPrivate->paintOrderChildItems();
- for (int ii = children.count() - 1; ii >= 0; --ii) {
+ for (int ii = children.size() - 1; ii >= 0; --ii) {
QQuickItem *child = children.at(ii);
if (!child->isVisible() || !child->isEnabled())
continue;
@@ -273,8 +239,6 @@ bool QQuickMouseAreaPrivate::propagateHelper(QQuickMouseEvent *ev, QQuickItem *i
even when no mouse button is pressed.
\sa hoverEnabled
-
- The corresponding handler is \c onEntered.
*/
/*!
@@ -313,8 +277,6 @@ bool QQuickMouseAreaPrivate::propagateHelper(QQuickMouseEvent *ev, QQuickItem *i
both be considered to be simultaneously hovered.
\sa hoverEnabled
-
- The corresponding handler is \c onExited.
*/
/*!
@@ -331,8 +293,6 @@ bool QQuickMouseAreaPrivate::propagateHelper(QQuickMouseEvent *ev, QQuickItem *i
When handling this signal, changing the \l {MouseEvent::}{accepted} property of the \a mouse
parameter has no effect.
-
- The corresponding handler is \c onPositionChanged.
*/
/*!
@@ -347,8 +307,6 @@ bool QQuickMouseAreaPrivate::propagateHelper(QQuickMouseEvent *ev, QQuickItem *i
When handling this signal, changing the \l {MouseEvent::}{accepted} property of the \a mouse
parameter has no effect, unless the \l propagateComposedEvents property is \c true.
-
- The corresponding handler is \c onClicked.
*/
/*!
@@ -363,8 +321,6 @@ bool QQuickMouseAreaPrivate::propagateHelper(QQuickMouseEvent *ev, QQuickItem *i
release. The default is to accept the event and not allow other MouseAreas beneath this one to
handle the event. If \e accepted is set to false, no further events will be sent to this MouseArea
until the button is next pressed.
-
- The corresponding handler is \c onPressed.
*/
/*!
@@ -377,8 +333,6 @@ bool QQuickMouseAreaPrivate::propagateHelper(QQuickMouseEvent *ev, QQuickItem *i
When handling this signal, changing the \l {MouseEvent::}{accepted} property of the \a mouse
parameter has no effect.
- The corresponding handler is \c onReleased.
-
\sa canceled
*/
@@ -391,8 +345,6 @@ bool QQuickMouseAreaPrivate::propagateHelper(QQuickMouseEvent *ev, QQuickItem *i
When handling this signal, changing the \l {MouseEvent::}{accepted} property of the \a mouse
parameter has no effect, unless the \l propagateComposedEvents property is \c true.
-
- The corresponding handler is \c onPressAndHold.
*/
/*!
@@ -405,8 +357,6 @@ bool QQuickMouseAreaPrivate::propagateHelper(QQuickMouseEvent *ev, QQuickItem *i
When handling this signal, if the \l {MouseEvent::}{accepted} property of the \a mouse
parameter is set to false, the pressed/released/clicked signals will be emitted for the second
click; otherwise they are suppressed. The \c accepted property defaults to true.
-
- The corresponding handler is \c onDoubleClicked.
*/
/*!
@@ -420,8 +370,6 @@ bool QQuickMouseAreaPrivate::propagateHelper(QQuickMouseEvent *ev, QQuickItem *i
\l Flickable will steal the mouse handling from the MouseArea. In these cases, to reset
the logic when the MouseArea has lost the mouse handling to the \l Flickable,
\c canceled should be handled in addition to \l released.
-
- The corresponding handler is \c onCanceled.
*/
/*!
@@ -429,11 +377,9 @@ bool QQuickMouseAreaPrivate::propagateHelper(QQuickMouseEvent *ev, QQuickItem *i
This signal is emitted in response to both mouse wheel and trackpad scroll gestures.
- The \l {WheelEvent}{wheel} parameter provides information about the event, including the x and y
+ The \a wheel parameter provides information about the event, including the x and y
position, any buttons currently pressed, and information about the wheel movement, including
angleDelta and pixelDelta.
-
- The corresponding handler is \c onWheel.
*/
QQuickMouseArea::QQuickMouseArea(QQuickItem *parent)
@@ -505,6 +451,7 @@ void QQuickMouseArea::setEnabled(bool a)
Q_D(QQuickMouseArea);
if (a != d->enabled) {
d->enabled = a;
+ setAcceptHoverEvents(a && d->hoverEnabled);
emit enabledChanged();
}
}
@@ -615,7 +562,7 @@ void QQuickMouseArea::setPreventStealing(bool prevent)
MouseArea {
anchors.fill: parent
propagateComposedEvents: true
- onClicked: {
+ onClicked: (mouse)=> {
console.log("clicked blue")
mouse.accepted = false
}
@@ -685,12 +632,12 @@ void QQuickMouseArea::mousePressEvent(QMouseEvent *event)
} else {
d->longPress = false;
d->saveEvent(event);
-#if QT_CONFIG(draganddrop)
+#if QT_CONFIG(quick_draganddrop)
if (d->drag)
d->drag->setActive(false);
#endif
setHovered(true);
- d->startScene = event->windowPos();
+ d->startScene = event->scenePosition();
setKeepMouseGrab(d->stealMouse);
event->setAccepted(setPressed(event->button(), true, event->source()));
if (event->isAccepted())
@@ -706,13 +653,19 @@ void QQuickMouseArea::mouseMoveEvent(QMouseEvent *event)
return;
}
- d->saveEvent(event);
-
// ### we should skip this if these signals aren't used
// ### can GV handle this for us?
- setHovered(contains(d->lastPos));
+ setHovered(contains(event->position()));
+
+ if ((event->buttons() & acceptedMouseButtons()) == 0) {
+ QQuickItem::mouseMoveEvent(event);
+ return;
+ }
+
+ d->saveEvent(event);
+
-#if QT_CONFIG(draganddrop)
+#if QT_CONFIG(quick_draganddrop)
if (d->drag && d->drag->target()) {
if (!d->moved) {
d->targetStartPos = d->drag->target()->parentItem()
@@ -724,10 +677,10 @@ void QQuickMouseArea::mouseMoveEvent(QMouseEvent *event)
QPointF curLocalPos;
if (drag()->target()->parentItem()) {
startLocalPos = drag()->target()->parentItem()->mapFromScene(d->startScene);
- curLocalPos = drag()->target()->parentItem()->mapFromScene(event->windowPos());
+ curLocalPos = drag()->target()->parentItem()->mapFromScene(event->scenePosition());
} else {
startLocalPos = d->startScene;
- curLocalPos = event->windowPos();
+ curLocalPos = event->scenePosition();
}
if (keepMouseGrab() && d->stealMouse && d->overThreshold && !d->drag->active())
@@ -759,20 +712,22 @@ void QQuickMouseArea::mouseMoveEvent(QMouseEvent *event)
QPointF targetPos = d->drag->target()->position();
- if (d->drag->active())
+ if (d->drag->active()) {
d->drag->target()->setPosition(boundedDragPos);
+ d->lastPos = mapFromScene(d->lastScenePos);
+ }
- bool dragOverThresholdX = QQuickWindowPrivate::dragOverThreshold(dragPos.x() - startPos.x(),
- Qt::XAxis, event, d->drag->threshold());
- bool dragOverThresholdY = QQuickWindowPrivate::dragOverThreshold(dragPos.y() - startPos.y(),
- Qt::YAxis, event, d->drag->threshold());
+ bool dragOverThresholdX = QQuickDeliveryAgentPrivate::dragOverThreshold(dragPos.x() - startPos.x(),
+ Qt::XAxis, event, d->drag->threshold());
+ bool dragOverThresholdY = QQuickDeliveryAgentPrivate::dragOverThreshold(dragPos.y() - startPos.y(),
+ Qt::YAxis, event, d->drag->threshold());
if (!d->overThreshold && (((targetPos.x() != boundedDragPos.x()) && dragOverThresholdX) ||
((targetPos.y() != boundedDragPos.y()) && dragOverThresholdY)))
{
d->overThreshold = true;
if (d->drag->smoothed())
- d->startScene = event->windowPos();
+ d->startScene = event->scenePosition();
}
if (!keepMouseGrab() && d->overThreshold) {
@@ -786,7 +741,9 @@ void QQuickMouseArea::mouseMoveEvent(QMouseEvent *event)
QQuickMouseEvent &me = d->quickMouseEvent;
me.reset(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, false, d->longPress, event->flags());
+#if QT_DEPRECATED_SINCE(6, 6)
me.setSource(event->source());
+#endif
emit mouseXChanged(&me);
me.setPosition(d->lastPos);
emit mouseYChanged(&me);
@@ -806,17 +763,18 @@ void QQuickMouseArea::mouseReleaseEvent(QMouseEvent *event)
setPressed(event->button(), false, event->source());
if (!d->pressed) {
// no other buttons are pressed
-#if QT_CONFIG(draganddrop)
+#if QT_CONFIG(quick_draganddrop)
if (d->drag)
d->drag->setActive(false);
#endif
// If we don't accept hover, we need to reset containsMouse.
- if (!acceptHoverEvents())
+ if (!hoverEnabled())
setHovered(false);
QQuickWindow *w = window();
if (w && w->mouseGrabberItem() == this)
ungrabMouse();
- setKeepMouseGrab(false);
+ if (!d->preventStealing)
+ setKeepMouseGrab(false);
}
}
d->doubleClick = false;
@@ -830,12 +788,18 @@ void QQuickMouseArea::mouseDoubleClickEvent(QMouseEvent *event)
QQuickMouseEvent &me = d->quickMouseEvent;
me.reset(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, true,
false, event->flags());
+#if QT_DEPRECATED_SINCE(6, 6)
me.setSource(event->source());
+#endif
me.setAccepted(d->isDoubleClickConnected());
emit this->doubleClicked(&me);
if (!me.isAccepted())
d->propagate(&me, QQuickMouseAreaPrivate::DoubleClick);
- d->doubleClick = d->isDoubleClickConnected() || me.isAccepted();
+ if (d->pressed)
+ d->doubleClick = d->isDoubleClickConnected() || me.isAccepted();
+
+ // Do not call the base implementation: we don't want to call event->ignore().
+ return;
}
QQuickItem::mouseDoubleClickEvent(event);
}
@@ -844,9 +808,17 @@ void QQuickMouseArea::hoverEnterEvent(QHoverEvent *event)
{
Q_D(QQuickMouseArea);
if (!d->enabled && !d->pressed) {
+ // Note: The fact that MouseArea doesn't update 'containsMouse' when it's disabled, is a
+ // legacy behavior that is different from how hover events are supposed to work; Hover
+ // events are always delivered to both enabled and disabled items (when they explicitly
+ // subscribe for them), to open up for hover effects, like showing tooltips. Because of
+ // this difference, you cannot use a MouseArea to e.g trigger a tooltop on a parent that
+ // is disabled. But since MouseArea has always worked this way, it should (probably) stay
+ // that way to avoid regressions. HoverHandlers do not suffer from this limitation, and
+ // can therefore be used as a replacement to solve such cases.
QQuickItem::hoverEnterEvent(event);
} else {
- d->lastPos = event->posF();
+ d->lastPos = event->position();
d->lastModifiers = event->modifiers();
setHovered(true);
QQuickMouseEvent &me = d->quickMouseEvent;
@@ -856,6 +828,9 @@ void QQuickMouseArea::hoverEnterEvent(QHoverEvent *event)
emit mouseYChanged(&me);
me.setPosition(d->lastPos);
}
+
+ // A MouseArea should not block hover events
+ event->ignore();
}
void QQuickMouseArea::hoverMoveEvent(QHoverEvent *event)
@@ -863,8 +838,8 @@ void QQuickMouseArea::hoverMoveEvent(QHoverEvent *event)
Q_D(QQuickMouseArea);
if (!d->enabled && !d->pressed) {
QQuickItem::hoverMoveEvent(event);
- } else if (d->lastPos != event->posF()) {
- d->lastPos = event->posF();
+ } else if (d->lastPos != event->position()) {
+ d->lastPos = event->position();
d->lastModifiers = event->modifiers();
QQuickMouseEvent &me = d->quickMouseEvent;
me.reset(d->lastPos.x(), d->lastPos.y(), Qt::NoButton, Qt::NoButton, d->lastModifiers, false, false);
@@ -874,15 +849,21 @@ void QQuickMouseArea::hoverMoveEvent(QHoverEvent *event)
me.setPosition(d->lastPos);
emit positionChanged(&me);
}
+
+ // A MouseArea should not block hover events
+ event->ignore();
}
void QQuickMouseArea::hoverLeaveEvent(QHoverEvent *event)
{
Q_D(QQuickMouseArea);
- if (!d->enabled && !d->pressed)
+ if (!d->enabled && !d->pressed && !d->hovered)
QQuickItem::hoverLeaveEvent(event);
else
setHovered(false);
+
+ // A MouseArea should not block hover events
+ event->ignore();
}
#if QT_CONFIG(wheelevent)
@@ -895,8 +876,7 @@ void QQuickMouseArea::wheelEvent(QWheelEvent *event)
}
QQuickWheelEvent &we = d->quickWheelEvent;
- we.reset(event->posF().x(), event->posF().y(), event->angleDelta(), event->pixelDelta(),
- event->buttons(), event->modifiers(), event->inverted());
+ we.reset(event);
we.setAccepted(d->isWheelConnected());
emit wheel(&we);
if (!we.isAccepted())
@@ -916,7 +896,7 @@ void QQuickMouseArea::ungrabMouse()
d->overThreshold = false;
setKeepMouseGrab(false);
-#if QT_CONFIG(draganddrop)
+#if QT_CONFIG(quick_draganddrop)
if (d->drag)
d->drag->setActive(false);
#endif
@@ -927,6 +907,7 @@ void QQuickMouseArea::ungrabMouse()
emit pressedButtonsChanged();
if (d->hovered && !isUnderMouse()) {
+ qCDebug(lcHoverTrace) << "losing hover: not under the mouse";
d->hovered = false;
emit hoveredChanged();
}
@@ -938,16 +919,22 @@ void QQuickMouseArea::mouseUngrabEvent()
ungrabMouse();
}
+void QQuickMouseArea::touchUngrabEvent()
+{
+ // allow a Pointer Handler to steal the grab from MouseArea
+ ungrabMouse();
+}
+
bool QQuickMouseArea::sendMouseEvent(QMouseEvent *event)
{
Q_D(QQuickMouseArea);
- QPointF localPos = mapFromScene(event->windowPos());
+ QPointF localPos = mapFromScene(event->scenePosition());
QQuickWindow *c = window();
QQuickItem *grabber = c ? c->mouseGrabberItem() : nullptr;
bool stealThisEvent = d->stealMouse;
if ((stealThisEvent || contains(localPos)) && (!grabber || !grabber->keepMouseGrab())) {
- QMouseEvent mouseEvent(event->type(), localPos, event->windowPos(), event->screenPos(),
+ QMouseEvent mouseEvent(event->type(), localPos, event->scenePosition(), event->globalPosition(),
event->button(), event->buttons(), event->modifiers());
mouseEvent.setAccepted(false);
@@ -985,6 +972,7 @@ bool QQuickMouseArea::sendMouseEvent(QMouseEvent *event)
emit pressedChanged();
emit containsPressChanged();
if (d->hovered) {
+ qCDebug(lcHoverTrace) << "losing hover: button released";
d->hovered = false;
emit hoveredChanged();
}
@@ -999,7 +987,7 @@ bool QQuickMouseArea::childMouseEventFilter(QQuickItem *i, QEvent *e)
Q_D(QQuickMouseArea);
if (!d->pressed &&
(!d->enabled || !isVisible()
-#if QT_CONFIG(draganddrop)
+#if QT_CONFIG(quick_draganddrop)
|| !d->drag || !d->drag->filterChildren()
#endif
)
@@ -1022,7 +1010,7 @@ void QQuickMouseArea::timerEvent(QTimerEvent *event)
Q_D(QQuickMouseArea);
if (event->timerId() == d->pressAndHoldTimer.timerId()) {
d->pressAndHoldTimer.stop();
-#if QT_CONFIG(draganddrop)
+#if QT_CONFIG(quick_draganddrop)
bool dragged = d->drag && d->drag->active();
#else
bool dragged = false;
@@ -1031,7 +1019,9 @@ void QQuickMouseArea::timerEvent(QTimerEvent *event)
d->longPress = true;
QQuickMouseEvent &me = d->quickMouseEvent;
me.reset(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, false, d->longPress, d->lastFlags);
+#if QT_DEPRECATED_SINCE(6, 6)
me.setSource(Qt::MouseEventSynthesizedByQt);
+#endif
me.setAccepted(d->isPressAndHoldConnected());
emit pressAndHold(&me);
if (!me.isAccepted())
@@ -1042,19 +1032,12 @@ void QQuickMouseArea::timerEvent(QTimerEvent *event)
}
}
-void QQuickMouseArea::windowDeactivateEvent()
-{
- ungrabMouse();
- QQuickItem::windowDeactivateEvent();
-}
-
-void QQuickMouseArea::geometryChanged(const QRectF &newGeometry,
- const QRectF &oldGeometry)
+void QQuickMouseArea::geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry)
{
Q_D(QQuickMouseArea);
- QQuickItem::geometryChanged(newGeometry, oldGeometry);
+ QQuickItem::geometryChange(newGeometry, oldGeometry);
- if (d->lastScenePos.isNull)
+ if (!d->lastScenePos.isValid())
d->lastScenePos = mapToScene(d->lastPos);
else if (newGeometry.x() != oldGeometry.x() || newGeometry.y() != oldGeometry.y())
d->lastPos = mapFromScene(d->lastScenePos);
@@ -1064,14 +1047,56 @@ void QQuickMouseArea::itemChange(ItemChange change, const ItemChangeData &value)
{
Q_D(QQuickMouseArea);
switch (change) {
+ case ItemEnabledHasChanged:
+ // If MouseArea becomes effectively disabled by disabling a parent
+ // (for example, onPressed: parent.enabled = false), cancel the pressed state.
+ if (d->pressed && !d->effectiveEnable)
+ ungrabMouse();
+ break;
case ItemVisibleHasChanged:
- if (acceptHoverEvents() && d->hovered != (isVisible() && isUnderMouse())) {
- if (!d->hovered) {
- QPointF cursorPos = QGuiApplicationPrivate::lastCursorPosition;
- d->lastScenePos = d->window->mapFromGlobal(cursorPos.toPoint());
- d->lastPos = mapFromScene(d->lastScenePos);
+ if (d->effectiveEnable && d->enabled && hoverEnabled()
+ && d->hovered != (isVisible() && isUnderMouse())) {
+ if (d->hovered) {
+ // If hovered but no longer under the mouse then un-hover.
+ setHovered(false);
+ } else {
+ // If under the mouse but not hovered then hover the QQuickMouseArea if it is
+ // marked as a hovered item under the windows QQuickDeliveryAgentPrivate instance.
+ // This is required as this QQuickMouseArea may be masked by another hoverable
+ // QQuickMouseArea higher up in the scenes z-index ordering.
+ QPointF globalPos{ QGuiApplicationPrivate::lastCursorPosition.toPoint() };
+ QPointF scenePos{ d->window->mapFromGlobal(globalPos) };
+
+ QQuickWindowPrivate *wd = QQuickWindowPrivate::get(d->window);
+ QQuickDeliveryAgentPrivate *dap = wd->deliveryAgentPrivate();
+
+ // If the QQuickDeliveryAgentPrivate has not already found a hovered leaf
+ // item then attempt to find one.
+ if (!dap->hoveredLeafItemFound) {
+ dap->deliverHoverEvent(scenePos, scenePos, Qt::NoModifier,
+ QDateTime::currentSecsSinceEpoch());
+ }
+
+ // Now if the QQuickDeliveryAgentPrivate has found a hovered leaf item check
+ // that this QQuickMouseArea item was one of the hovered items.
+ if (dap->hoveredLeafItemFound) {
+ for (auto hoverItem : dap->hoverItems) {
+ if (hoverItem.first == this) {
+ // Found a match so update the hover state.
+ d->lastScenePos = scenePos;
+ d->lastPos = mapFromScene(d->lastScenePos);
+ setHovered(true);
+ break;
+ }
+ }
+ }
}
- setHovered(!d->hovered);
+ }
+ if (d->pressed && (!isVisible())) {
+ // This happens when the mouse area hides itself
+ // inside the press handler. In that case we should not keep the internal
+ // state as pressed, since we never became the mouse grabber.
+ ungrabMouse();
}
break;
default:
@@ -1094,15 +1119,18 @@ void QQuickMouseArea::itemChange(ItemChange change, const ItemChangeData &value)
*/
bool QQuickMouseArea::hoverEnabled() const
{
- return acceptHoverEvents();
+ return d_func()->hoverEnabled;
}
void QQuickMouseArea::setHoverEnabled(bool h)
{
- if (h == acceptHoverEvents())
+ Q_D(QQuickMouseArea);
+ if (h == d->hoverEnabled)
return;
- setAcceptHoverEvents(h);
+ d->hoverEnabled = h;
+ setAcceptHoverEvents(h && d->enabled);
+
emit hoverEnabledChanged();
}
@@ -1111,8 +1139,10 @@ void QQuickMouseArea::setHoverEnabled(bool h)
\qmlproperty bool QtQuick::MouseArea::containsMouse
This property holds whether the mouse is currently inside the mouse area.
- \warning If hoverEnabled is false, containsMouse will only be valid
+ \warning If hoverEnabled is \c false, \c containsMouse will be \c true
when the mouse is pressed while the mouse cursor is inside the MouseArea.
+ But if you set \c {mouse.accepted = false} in an \c onPressed handler,
+ \c containsMouse will remain \c false because the press was rejected.
*/
bool QQuickMouseArea::hovered() const
{
@@ -1124,7 +1154,7 @@ bool QQuickMouseArea::hovered() const
\qmlproperty bool QtQuick::MouseArea::pressed
This property holds whether any of the \l acceptedButtons are currently pressed.
*/
-bool QQuickMouseArea::pressed() const
+bool QQuickMouseArea::isPressed() const
{
Q_D(const QQuickMouseArea);
return d->pressed;
@@ -1152,7 +1182,7 @@ void QQuickMouseArea::setHovered(bool h)
{
Q_D(QQuickMouseArea);
if (d->hovered != h) {
- qCDebug(DBG_HOVER_TRACE) << this << d->hovered << "->" << h;
+ qCDebug(lcHoverTrace) << this << d->hovered << "->" << h;
d->hovered = h;
emit hoveredChanged();
d->hovered ? emit entered() : emit exited();
@@ -1198,7 +1228,7 @@ bool QQuickMouseArea::setPressed(Qt::MouseButton button, bool p, Qt::MouseEventS
{
Q_D(QQuickMouseArea);
-#if QT_CONFIG(draganddrop)
+#if QT_CONFIG(quick_draganddrop)
bool dragged = d->drag && d->drag->active();
#else
bool dragged = false;
@@ -1210,7 +1240,9 @@ bool QQuickMouseArea::setPressed(Qt::MouseButton button, bool p, Qt::MouseEventS
if (wasPressed != p) {
QQuickMouseEvent &me = d->quickMouseEvent;
me.reset(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, isclick, d->longPress, d->lastFlags);
+#if QT_DEPRECATED_SINCE(6, 6)
me.setSource(source);
+#endif
if (p) {
d->pressed |= button;
if (!d->doubleClick)
@@ -1222,6 +1254,8 @@ bool QQuickMouseArea::setPressed(Qt::MouseButton button, bool p, Qt::MouseEventS
if (!me.isAccepted()) {
d->pressed = Qt::NoButton;
+ if (!hoverEnabled())
+ setHovered(false);
}
if (!oldPressed) {
@@ -1248,6 +1282,7 @@ bool QQuickMouseArea::setPressed(Qt::MouseButton button, bool p, Qt::MouseEventS
return me.isAccepted();
}
+ Q_UNUSED(source)
return false;
}
@@ -1366,6 +1401,7 @@ void QQuickMouseArea::resetPressAndHoldInterval()
\qmlproperty real QtQuick::MouseArea::drag.maximumY
\qmlproperty bool QtQuick::MouseArea::drag.filterChildren
\qmlproperty real QtQuick::MouseArea::drag.threshold
+ \qmlproperty bool QtQuick::MouseArea::drag.smoothed
\c drag provides a convenient way to make an item draggable.
@@ -1390,6 +1426,8 @@ void QQuickMouseArea::resetPressAndHoldInterval()
If \c drag.filterChildren is set to true, a drag can override descendant MouseAreas. This
enables a parent MouseArea to handle drags, for example, while descendants handle clicks:
+ \snippet qml/mousearea/mouseareadragfilter.qml dragfilter
+
\c drag.threshold determines the threshold in pixels of when the drag operation should
start. By default this is bound to a platform dependent value. This property was added in
Qt Quick 2.2.
@@ -1399,12 +1437,9 @@ void QQuickMouseArea::resetPressAndHoldInterval()
By default, this property is \c true. This property was added in Qt Quick 2.4
See the \l Drag attached property and \l DropArea if you want to make a drop.
-
- \snippet qml/mousearea/mouseareadragfilter.qml dragfilter
-
*/
-#if QT_CONFIG(draganddrop)
+#if QT_CONFIG(quick_draganddrop)
QQuickDrag *QQuickMouseArea::drag()
{
Q_D(QQuickMouseArea);
@@ -1419,7 +1454,7 @@ QSGNode *QQuickMouseArea::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData
Q_UNUSED(data);
Q_D(QQuickMouseArea);
- if (!qmlVisualTouchDebugging())
+ if (!qmlMaVisualTouchDebugging())
return nullptr;
QSGInternalRectangleNode *rectangle = static_cast<QSGInternalRectangleNode *>(oldNode);