| /**************************************************************************** |
| ** |
| ** 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$ |
| ** |
| ****************************************************************************/ |
| |
| #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> |
| |
| #include <QtGui/private/qguiapplication_p.h> |
| #include <QtGui/qevent.h> |
| #include <QtGui/qstylehints.h> |
| |
| #include <float.h> |
| |
| QT_BEGIN_NAMESPACE |
| |
| DEFINE_BOOL_CONFIG_OPTION(qmlVisualTouchDebugging, QML_VISUAL_TOUCH_DEBUGGING) |
| |
| Q_DECLARE_LOGGING_CATEGORY(DBG_HOVER_TRACE) |
| |
| QQuickMouseAreaPrivate::QQuickMouseAreaPrivate() |
| : enabled(true), scrollGestureEnabled(true), hovered(false), longPress(false), |
| moved(false), stealMouse(false), doubleClick(false), preventStealing(false), |
| propagateComposedEvents(false), overThreshold(false), pressed(nullptr), |
| pressAndHoldInterval(-1) |
| #if QT_CONFIG(quick_draganddrop) |
| , drag(nullptr) |
| #endif |
| #if QT_CONFIG(cursor) |
| , cursor(nullptr) |
| #endif |
| { |
| } |
| |
| QQuickMouseAreaPrivate::~QQuickMouseAreaPrivate() |
| { |
| #if QT_CONFIG(quick_draganddrop) |
| delete drag; |
| #endif |
| #if QT_CONFIG(cursor) |
| delete cursor; |
| #endif |
| } |
| |
| void QQuickMouseAreaPrivate::init() |
| { |
| Q_Q(QQuickMouseArea); |
| q->setAcceptedMouseButtons(Qt::LeftButton); |
| q->setAcceptTouchEvents(false); // rely on mouse events synthesized from touch |
| q->setFiltersChildMouseEvents(true); |
| if (qmlVisualTouchDebugging()) { |
| q->setFlag(QQuickItem::ItemHasContents); |
| } |
| } |
| |
| void QQuickMouseAreaPrivate::saveEvent(QMouseEvent *event) |
| { |
| lastPos = event->localPos(); |
| lastScenePos = event->windowPos(); |
| lastButton = event->button(); |
| lastButtons = event->buttons(); |
| lastModifiers = event->modifiers(); |
| lastFlags = event->flags(); |
| } |
| |
| bool QQuickMouseAreaPrivate::isPressAndHoldConnected() |
| { |
| Q_Q(QQuickMouseArea); |
| IS_SIGNAL_CONNECTED(q, QQuickMouseArea, pressAndHold, (QQuickMouseEvent *)); |
| } |
| |
| bool QQuickMouseAreaPrivate::isDoubleClickConnected() |
| { |
| Q_Q(QQuickMouseArea); |
| IS_SIGNAL_CONNECTED(q, QQuickMouseArea, doubleClicked, (QQuickMouseEvent *)); |
| } |
| |
| bool QQuickMouseAreaPrivate::isClickConnected() |
| { |
| Q_Q(QQuickMouseArea); |
| IS_SIGNAL_CONNECTED(q, QQuickMouseArea, clicked, (QQuickMouseEvent *)); |
| } |
| |
| bool QQuickMouseAreaPrivate::isWheelConnected() |
| { |
| Q_Q(QQuickMouseArea); |
| IS_SIGNAL_CONNECTED(q, QQuickMouseArea, wheel, (QQuickWheelEvent *)); |
| } |
| |
| void QQuickMouseAreaPrivate::propagate(QQuickMouseEvent* event, PropagateType t) |
| { |
| Q_Q(QQuickMouseArea); |
| if (!window || !propagateComposedEvents) |
| return; |
| QPointF scenePos = q->mapToScene(QPointF(event->x(), event->y())); |
| propagateHelper(event, window->contentItem(), scenePos, t); |
| } |
| |
| bool QQuickMouseAreaPrivate::propagateHelper(QQuickMouseEvent *ev, QQuickItem *item,const QPointF &sp, PropagateType sig) |
| { |
| //Based off of QQuickWindow::deliverInitialMousePressEvent |
| //But specific to MouseArea, so doesn't belong in window |
| Q_Q(const QQuickMouseArea); |
| QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item); |
| |
| if (itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) { |
| QPointF p = item->mapFromScene(sp); |
| if (!item->contains(p)) |
| return false; |
| } |
| |
| QList<QQuickItem *> children = itemPrivate->paintOrderChildItems(); |
| for (int ii = children.count() - 1; ii >= 0; --ii) { |
| QQuickItem *child = children.at(ii); |
| if (!child->isVisible() || !child->isEnabled()) |
| continue; |
| if (propagateHelper(ev, child, sp, sig)) |
| return true; |
| } |
| |
| QQuickMouseArea* ma = qobject_cast<QQuickMouseArea*>(item); |
| if (ma && ma != q && ma->isEnabled() && itemPrivate->acceptedMouseButtons() & ev->button()) { |
| switch (sig) { |
| case Click: |
| if (!ma->d_func()->isClickConnected()) |
| return false; |
| break; |
| case DoubleClick: |
| if (!ma->d_func()->isDoubleClickConnected()) |
| return false; |
| break; |
| case PressAndHold: |
| if (!ma->d_func()->isPressAndHoldConnected()) |
| return false; |
| break; |
| } |
| QPointF p = item->mapFromScene(sp); |
| if (item->contains(p)) { |
| ev->setX(p.x()); |
| ev->setY(p.y()); |
| ev->setAccepted(true);//It is connected, they have to explicitly ignore to let it slide |
| switch (sig) { |
| case Click: emit ma->clicked(ev); break; |
| case DoubleClick: emit ma->doubleClicked(ev); break; |
| case PressAndHold: emit ma->pressAndHold(ev); break; |
| } |
| if (ev->isAccepted()) |
| return true; |
| } |
| } |
| return false; |
| |
| } |
| |
| /*! |
| \qmltype MouseArea |
| \instantiates QQuickMouseArea |
| \inqmlmodule QtQuick |
| \ingroup qtquick-input |
| \brief Enables simple mouse handling. |
| \inherits Item |
| |
| A MouseArea is an invisible item that is typically used in conjunction with |
| a visible item in order to provide mouse handling for that item. |
| By effectively acting as a proxy, the logic for mouse handling can be |
| contained within a MouseArea item. |
| |
| The \l enabled property is used to enable and disable mouse handling for |
| the proxied item. When disabled, the mouse area becomes transparent to |
| mouse events. |
| |
| MouseArea is an invisible Item, but it has a visible property. |
| When set to false, the mouse area becomes transparent to mouse events. |
| |
| The \l pressed read-only property indicates whether or not the user is |
| holding down a mouse button over the mouse area. This property is often |
| used in bindings between properties in a user interface. The containsMouse |
| read-only property indicates the presence of the mouse cursor over the |
| mouse area but, by default, only when a mouse button is held down; see |
| the containsMouse documentation for details. |
| |
| Information about the mouse position and button clicks are provided via |
| signals for which event handler properties are defined. The most commonly |
| used involved handling mouse presses and clicks: onClicked, onDoubleClicked, |
| onPressed, onReleased and onPressAndHold. It's also possible to handle mouse |
| wheel events via the onWheel signal. |
| |
| If a MouseArea overlaps with the area of other MouseArea items, you can choose |
| to propagate \c clicked, \c doubleClicked and \c pressAndHold events to these |
| other items by setting propagateComposedEvents to true and rejecting events |
| that should be propagated. See the propagateComposedEvents documentation for |
| details. |
| |
| By default, MouseArea items only report mouse clicks and not changes to the |
| position of the mouse cursor. Setting the hoverEnabled property ensures that |
| handlers defined for onPositionChanged, onEntered and onExited are used and |
| that the containsMouse property is updated even when no mouse buttons are |
| pressed. |
| |
| \section1 Example Usage |
| |
| \div {class="float-right"} |
| \inlineimage qml-mousearea-snippet.png |
| \enddiv |
| |
| The following example uses a MouseArea in a \l Rectangle that changes |
| the \l Rectangle color to red when clicked: |
| |
| \snippet qml/mousearea/mousearea.qml import |
| \codeline |
| \snippet qml/mousearea/mousearea.qml intro |
| |
| \clearfloat |
| Many MouseArea signals pass a \l{MouseEvent}{mouse} parameter that contains |
| additional information about the mouse event, such as the position, button, |
| and any key modifiers. |
| |
| Here is an extension of the previous example that produces a different |
| color when the area is right clicked: |
| |
| \snippet qml/mousearea/mousearea.qml intro-extended |
| |
| \sa MouseEvent, {mousearea}{MouseArea example}, |
| {Important Concepts In Qt Quick - User Input} |
| */ |
| |
| /*! |
| \qmlsignal QtQuick::MouseArea::entered() |
| |
| This signal is emitted when the mouse enters the mouse area. |
| |
| By default this signal is only emitted if a button is currently |
| pressed. Set \l hoverEnabled to true to emit this signal |
| even when no mouse button is pressed. |
| |
| \sa hoverEnabled |
| |
| The corresponding handler is \c onEntered. |
| */ |
| |
| /*! |
| \qmlsignal QtQuick::MouseArea::exited() |
| |
| This signal is emitted when the mouse exits the mouse area. |
| |
| By default this signal is only emitted if a button is currently |
| pressed. Set \l hoverEnabled to true to emit this signal |
| even when no mouse button is pressed. |
| |
| The example below shows a fairly typical relationship between |
| two MouseAreas, with \c mouseArea2 on top of \c mouseArea1. Moving the |
| mouse into \c mouseArea2 from \c mouseArea1 will cause \c mouseArea1 |
| to emit the \c exited signal. |
| \qml |
| Rectangle { |
| width: 400; height: 400 |
| MouseArea { |
| id: mouseArea1 |
| anchors.fill: parent |
| hoverEnabled: true |
| } |
| MouseArea { |
| id: mouseArea2 |
| width: 100; height: 100 |
| anchors.centerIn: parent |
| hoverEnabled: true |
| } |
| } |
| \endqml |
| |
| If instead you give the two MouseAreas a parent-child relationship, |
| moving the mouse into \c mouseArea2 from \c mouseArea1 will \b not |
| cause \c mouseArea1 to emit \c exited. Instead, they will |
| both be considered to be simultaneously hovered. |
| |
| \sa hoverEnabled |
| |
| The corresponding handler is \c onExited. |
| */ |
| |
| /*! |
| \qmlsignal QtQuick::MouseArea::positionChanged(MouseEvent mouse) |
| |
| This signal is emitted when the mouse position changes. |
| |
| The \l {MouseEvent}{mouse} parameter provides information about the mouse, including the x and y |
| position, and any buttons currently pressed. |
| |
| By default this signal is only emitted if a button is currently |
| pressed. Set \l hoverEnabled to true to emit this signal |
| even when no mouse button is pressed. |
| |
| When handling this signal, changing the \l {MouseEvent::}{accepted} property of the \a mouse |
| parameter has no effect. |
| |
| The corresponding handler is \c onPositionChanged. |
| */ |
| |
| /*! |
| \qmlsignal QtQuick::MouseArea::clicked(MouseEvent mouse) |
| |
| This signal is emitted when there is a click. A click is defined as a press followed by a release, |
| both inside the MouseArea (pressing, moving outside the MouseArea, and then moving back inside and |
| releasing is also considered a click). |
| |
| The \l {MouseEvent}{mouse} parameter provides information about the click, including the x and y |
| position of the release of the click, and whether the click was held. |
| |
| 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. |
| */ |
| |
| /*! |
| \qmlsignal QtQuick::MouseArea::pressed(MouseEvent mouse) |
| |
| This signal is emitted when there is a press. |
| The \l {MouseEvent}{mouse} parameter provides information about the press, including the x and y |
| position and which button was pressed. |
| |
| When handling this signal, use the \l {MouseEvent::}{accepted} property of the \a mouse |
| parameter to control whether this MouseArea handles the press and all future mouse events until |
| 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. |
| */ |
| |
| /*! |
| \qmlsignal QtQuick::MouseArea::released(MouseEvent mouse) |
| |
| This signal is emitted when there is a release. |
| The \l {MouseEvent}{mouse} parameter provides information about the click, including the x and y |
| position of the release of the click, and whether the click was held. |
| |
| 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 |
| */ |
| |
| /*! |
| \qmlsignal QtQuick::MouseArea::pressAndHold(MouseEvent mouse) |
| |
| This signal is emitted when there is a long press (currently 800ms). |
| The \l {MouseEvent}{mouse} parameter provides information about the press, including the x and y |
| position of the press, and which button is pressed. |
| |
| 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. |
| */ |
| |
| /*! |
| \qmlsignal QtQuick::MouseArea::doubleClicked(MouseEvent mouse) |
| |
| This signal is emitted when there is a double-click (a press followed by a release followed by a press). |
| The \l {MouseEvent}{mouse} parameter provides information about the click, including the x and y |
| position of the release of the click, and whether the click was held. |
| |
| 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. |
| */ |
| |
| /*! |
| \qmlsignal QtQuick::MouseArea::canceled() |
| |
| This signal is emitted when mouse events have been canceled, because another item stole the mouse event handling. |
| |
| This signal is for advanced use: it is useful when there is more than one MouseArea |
| that is handling input, or when there is a MouseArea inside a \l Flickable. In the latter |
| case, if you execute some logic in the \c onPressed signal handler and then start dragging, the |
| \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. |
| */ |
| |
| /*! |
| \qmlsignal QtQuick::MouseArea::wheel(WheelEvent wheel) |
| |
| This signal is emitted in response to both mouse wheel and trackpad scroll gestures. |
| |
| 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) |
| : QQuickItem(*(new QQuickMouseAreaPrivate), parent) |
| { |
| Q_D(QQuickMouseArea); |
| d->init(); |
| #if QT_CONFIG(cursor) |
| // Explcitly call setCursor on QQuickItem since |
| // it internally keeps a boolean hasCursor that doesn't |
| // get set to true unless you call setCursor |
| setCursor(Qt::ArrowCursor); |
| #endif |
| } |
| |
| QQuickMouseArea::~QQuickMouseArea() |
| { |
| } |
| |
| /*! |
| \qmlproperty real QtQuick::MouseArea::mouseX |
| \qmlproperty real QtQuick::MouseArea::mouseY |
| These properties hold the coordinates of the mouse cursor. |
| |
| If the hoverEnabled property is false then these properties will only be valid |
| while a button is pressed, and will remain valid as long as the button is held |
| down even if the mouse is moved outside the area. |
| |
| By default, this property is false. |
| |
| If hoverEnabled is true then these properties will be valid when: |
| \list |
| \li no button is pressed, but the mouse is within the MouseArea (containsMouse is true). |
| \li a button is pressed and held, even if it has since moved out of the area. |
| \endlist |
| |
| The coordinates are relative to the MouseArea. |
| */ |
| qreal QQuickMouseArea::mouseX() const |
| { |
| Q_D(const QQuickMouseArea); |
| return d->lastPos.x(); |
| } |
| |
| qreal QQuickMouseArea::mouseY() const |
| { |
| Q_D(const QQuickMouseArea); |
| return d->lastPos.y(); |
| } |
| |
| /*! |
| \qmlproperty bool QtQuick::MouseArea::enabled |
| This property holds whether the item accepts mouse events. |
| |
| \note Due to historical reasons, this property is not equivalent to |
| Item.enabled. It only affects mouse events, and its effect does not |
| propagate to child items. |
| |
| By default, this property is true. |
| */ |
| bool QQuickMouseArea::isEnabled() const |
| { |
| Q_D(const QQuickMouseArea); |
| return d->enabled; |
| } |
| |
| void QQuickMouseArea::setEnabled(bool a) |
| { |
| Q_D(QQuickMouseArea); |
| if (a != d->enabled) { |
| d->enabled = a; |
| emit enabledChanged(); |
| } |
| } |
| |
| /*! |
| \qmlproperty bool QtQuick::MouseArea::scrollGestureEnabled |
| \since 5.5 |
| |
| This property controls whether this MouseArea responds to scroll gestures |
| from non-mouse devices, such as the 2-finger flick gesture on a trackpad. |
| If set to false, the \l wheel signal be emitted only when the wheel event |
| comes from an actual mouse with a wheel, while scroll gesture events will |
| pass through to any other Item that will handle them. For example, the user |
| might perform a flick gesture while the cursor is over an item containing a |
| MouseArea, intending to interact with a Flickable which is underneath. |
| Setting this property to false will allow the PinchArea to handle the mouse |
| wheel or the pinch gesture, while the Flickable handles the flick gesture. |
| |
| By default, this property is true. |
| */ |
| bool QQuickMouseArea::isScrollGestureEnabled() const |
| { |
| Q_D(const QQuickMouseArea); |
| return d->scrollGestureEnabled; |
| } |
| |
| void QQuickMouseArea::setScrollGestureEnabled(bool e) |
| { |
| Q_D(QQuickMouseArea); |
| if (e != d->scrollGestureEnabled) { |
| d->scrollGestureEnabled = e; |
| emit scrollGestureEnabledChanged(); |
| } |
| } |
| |
| /*! |
| \qmlproperty bool QtQuick::MouseArea::preventStealing |
| This property holds whether the mouse events may be stolen from this |
| MouseArea. |
| |
| If a MouseArea is placed within an item that filters child mouse |
| events, such as Flickable, the mouse |
| events may be stolen from the MouseArea if a gesture is recognized |
| by the parent item, e.g. a flick gesture. If preventStealing is |
| set to true, no item will steal the mouse events. |
| |
| Note that setting preventStealing to true once an item has started |
| stealing events will have no effect until the next press event. |
| |
| By default this property is false. |
| */ |
| bool QQuickMouseArea::preventStealing() const |
| { |
| Q_D(const QQuickMouseArea); |
| return d->preventStealing; |
| } |
| |
| void QQuickMouseArea::setPreventStealing(bool prevent) |
| { |
| Q_D(QQuickMouseArea); |
| if (prevent != d->preventStealing) { |
| d->preventStealing = prevent; |
| setKeepMouseGrab(d->preventStealing && d->enabled); |
| emit preventStealingChanged(); |
| } |
| } |
| |
| |
| /*! |
| \qmlproperty bool QtQuick::MouseArea::propagateComposedEvents |
| This property holds whether composed mouse events will automatically propagate to |
| other MouseAreas that overlap with this MouseArea but are lower in the visual stacking order. |
| By default, this property is false. |
| |
| MouseArea contains several composed events: \c clicked, \c doubleClicked and \c pressAndHold. |
| These are composed of basic mouse events, like \c pressed, and can be propagated differently |
| in comparison to basic events. |
| |
| If propagateComposedEvents is set to true, then composed events will be automatically |
| propagated to other MouseAreas in the same location in the scene. Each event is propagated |
| to the next \l enabled MouseArea beneath it in the stacking order, propagating down this visual |
| hierarchy until a MouseArea accepts the event. Unlike \c pressed events, composed events will |
| not be automatically accepted if no handler is present. |
| |
| For example, below is a yellow \l Rectangle that contains a blue \l Rectangle. The blue |
| rectangle is the top-most item in the hierarchy of the visual stacking order; it will |
| visually rendered above the yellow rectangle. Since the blue rectangle sets |
| propagateComposedEvents to true, and also sets \l MouseEvent::accepted to false for all |
| received \c clicked events, any \c clicked events it receives are propagated to the |
| MouseArea of the yellow rectangle beneath it. |
| |
| \qml |
| import QtQuick 2.0 |
| |
| Rectangle { |
| color: "yellow" |
| width: 100; height: 100 |
| |
| MouseArea { |
| anchors.fill: parent |
| onClicked: console.log("clicked yellow") |
| } |
| |
| Rectangle { |
| color: "blue" |
| width: 50; height: 50 |
| |
| MouseArea { |
| anchors.fill: parent |
| propagateComposedEvents: true |
| onClicked: { |
| console.log("clicked blue") |
| mouse.accepted = false |
| } |
| } |
| } |
| } |
| \endqml |
| |
| Clicking on the blue rectangle will cause the \c onClicked handler of its child MouseArea to |
| be invoked; the event will then be propagated to the MouseArea of the yellow rectangle, causing |
| its own \c onClicked handler to be invoked. |
| |
| This property greatly simplifies the usecase of when you want to have overlapping MouseAreas |
| handling the composed events together. For example: if you want one MouseArea to handle \c clicked |
| signals and the other to handle \c pressAndHold, or if you want one MouseArea to handle \c clicked most |
| of the time, but pass it through when certain conditions are met. |
| */ |
| bool QQuickMouseArea::propagateComposedEvents() const |
| { |
| Q_D(const QQuickMouseArea); |
| return d->propagateComposedEvents; |
| } |
| |
| void QQuickMouseArea::setPropagateComposedEvents(bool prevent) |
| { |
| Q_D(QQuickMouseArea); |
| if (prevent != d->propagateComposedEvents) { |
| d->propagateComposedEvents = prevent; |
| setKeepMouseGrab(d->propagateComposedEvents && d->enabled); |
| emit propagateComposedEventsChanged(); |
| } |
| } |
| |
| /*! |
| \qmlproperty MouseButtons QtQuick::MouseArea::pressedButtons |
| This property holds the mouse buttons currently pressed. |
| |
| It contains a bitwise combination of: |
| \list |
| \li Qt.LeftButton |
| \li Qt.RightButton |
| \li Qt.MiddleButton |
| \endlist |
| |
| The code below displays "right" when the right mouse buttons is pressed: |
| |
| \snippet qml/mousearea/mousearea.qml mousebuttons |
| |
| \note this property only handles buttons specified in \l acceptedButtons. |
| |
| \sa acceptedButtons |
| */ |
| Qt::MouseButtons QQuickMouseArea::pressedButtons() const |
| { |
| Q_D(const QQuickMouseArea); |
| return d->pressed; |
| } |
| |
| void QQuickMouseArea::mousePressEvent(QMouseEvent *event) |
| { |
| Q_D(QQuickMouseArea); |
| d->moved = false; |
| d->stealMouse = d->preventStealing; |
| d->overThreshold = false; |
| if (!d->enabled || !(event->button() & acceptedMouseButtons())) { |
| QQuickItem::mousePressEvent(event); |
| } else { |
| d->longPress = false; |
| d->saveEvent(event); |
| #if QT_CONFIG(quick_draganddrop) |
| if (d->drag) |
| d->drag->setActive(false); |
| #endif |
| setHovered(true); |
| d->startScene = event->windowPos(); |
| setKeepMouseGrab(d->stealMouse); |
| event->setAccepted(setPressed(event->button(), true, event->source())); |
| if (event->isAccepted()) |
| d->pressAndHoldTimer.start(pressAndHoldInterval(), this); |
| } |
| } |
| |
| void QQuickMouseArea::mouseMoveEvent(QMouseEvent *event) |
| { |
| Q_D(QQuickMouseArea); |
| if (!d->enabled && !d->pressed) { |
| QQuickItem::mouseMoveEvent(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)); |
| |
| #if QT_CONFIG(quick_draganddrop) |
| if (d->drag && d->drag->target()) { |
| if (!d->moved) { |
| d->targetStartPos = d->drag->target()->parentItem() |
| ? d->drag->target()->parentItem()->mapToScene(d->drag->target()->position()) |
| : d->drag->target()->position(); |
| } |
| |
| QPointF startLocalPos; |
| QPointF curLocalPos; |
| if (drag()->target()->parentItem()) { |
| startLocalPos = drag()->target()->parentItem()->mapFromScene(d->startScene); |
| curLocalPos = drag()->target()->parentItem()->mapFromScene(event->windowPos()); |
| } else { |
| startLocalPos = d->startScene; |
| curLocalPos = event->windowPos(); |
| } |
| |
| if (keepMouseGrab() && d->stealMouse && d->overThreshold && !d->drag->active()) |
| d->drag->setActive(true); |
| |
| QPointF startPos = d->drag->target()->parentItem() |
| ? d->drag->target()->parentItem()->mapFromScene(d->targetStartPos) |
| : d->targetStartPos; |
| |
| bool dragX = drag()->axis() & QQuickDrag::XAxis; |
| bool dragY = drag()->axis() & QQuickDrag::YAxis; |
| |
| QPointF dragPos = d->drag->target()->position(); |
| QPointF boundedDragPos = dragPos; |
| if (dragX) { |
| dragPos.setX(startPos.x() + curLocalPos.x() - startLocalPos.x()); |
| boundedDragPos.setX(qBound( |
| d->drag->xmin(), |
| dragPos.x(), |
| d->drag->xmax())); |
| } |
| if (dragY) { |
| dragPos.setY(startPos.y() + curLocalPos.y() - startLocalPos.y()); |
| boundedDragPos.setY(qBound( |
| d->drag->ymin(), |
| dragPos.y(), |
| d->drag->ymax())); |
| } |
| |
| QPointF targetPos = d->drag->target()->position(); |
| |
| if (d->drag->active()) { |
| d->drag->target()->setPosition(boundedDragPos); |
| d->lastPos = d->lastScenePos - mapToScene(position()); |
| } |
| |
| 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()); |
| |
| if (!d->overThreshold && (((targetPos.x() != boundedDragPos.x()) && dragOverThresholdX) || |
| ((targetPos.y() != boundedDragPos.y()) && dragOverThresholdY))) |
| { |
| d->overThreshold = true; |
| if (d->drag->smoothed()) |
| d->startScene = event->windowPos(); |
| } |
| |
| if (!keepMouseGrab() && d->overThreshold) { |
| setKeepMouseGrab(true); |
| d->stealMouse = true; |
| } |
| |
| d->moved = true; |
| } |
| #endif |
| |
| QQuickMouseEvent &me = d->quickMouseEvent; |
| me.reset(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, false, d->longPress, event->flags()); |
| me.setSource(event->source()); |
| emit mouseXChanged(&me); |
| me.setPosition(d->lastPos); |
| emit mouseYChanged(&me); |
| me.setPosition(d->lastPos); |
| emit positionChanged(&me); |
| } |
| |
| void QQuickMouseArea::mouseReleaseEvent(QMouseEvent *event) |
| { |
| Q_D(QQuickMouseArea); |
| d->stealMouse = false; |
| d->overThreshold = false; |
| if (!d->enabled && !d->pressed) { |
| QQuickItem::mouseReleaseEvent(event); |
| } else { |
| d->saveEvent(event); |
| setPressed(event->button(), false, event->source()); |
| if (!d->pressed) { |
| // no other buttons are pressed |
| #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()) |
| setHovered(false); |
| QQuickWindow *w = window(); |
| if (w && w->mouseGrabberItem() == this) |
| ungrabMouse(); |
| setKeepMouseGrab(false); |
| } |
| } |
| d->doubleClick = false; |
| } |
| |
| void QQuickMouseArea::mouseDoubleClickEvent(QMouseEvent *event) |
| { |
| Q_D(QQuickMouseArea); |
| if (d->enabled) { |
| d->saveEvent(event); |
| QQuickMouseEvent &me = d->quickMouseEvent; |
| me.reset(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, true, |
| false, event->flags()); |
| me.setSource(event->source()); |
| me.setAccepted(d->isDoubleClickConnected()); |
| emit this->doubleClicked(&me); |
| if (!me.isAccepted()) |
| d->propagate(&me, QQuickMouseAreaPrivate::DoubleClick); |
| d->doubleClick = d->isDoubleClickConnected() || me.isAccepted(); |
| } |
| QQuickItem::mouseDoubleClickEvent(event); |
| } |
| |
| void QQuickMouseArea::hoverEnterEvent(QHoverEvent *event) |
| { |
| Q_D(QQuickMouseArea); |
| if (!d->enabled && !d->pressed) { |
| QQuickItem::hoverEnterEvent(event); |
| } else { |
| d->lastPos = event->posF(); |
| d->lastModifiers = event->modifiers(); |
| setHovered(true); |
| QQuickMouseEvent &me = d->quickMouseEvent; |
| me.reset(d->lastPos.x(), d->lastPos.y(), Qt::NoButton, Qt::NoButton, d->lastModifiers, false, false); |
| emit mouseXChanged(&me); |
| me.setPosition(d->lastPos); |
| emit mouseYChanged(&me); |
| me.setPosition(d->lastPos); |
| } |
| } |
| |
| 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(); |
| d->lastModifiers = event->modifiers(); |
| QQuickMouseEvent &me = d->quickMouseEvent; |
| me.reset(d->lastPos.x(), d->lastPos.y(), Qt::NoButton, Qt::NoButton, d->lastModifiers, false, false); |
| emit mouseXChanged(&me); |
| me.setPosition(d->lastPos); |
| emit mouseYChanged(&me); |
| me.setPosition(d->lastPos); |
| emit positionChanged(&me); |
| } |
| } |
| |
| void QQuickMouseArea::hoverLeaveEvent(QHoverEvent *event) |
| { |
| Q_D(QQuickMouseArea); |
| if (!d->enabled && !d->pressed) |
| QQuickItem::hoverLeaveEvent(event); |
| else |
| setHovered(false); |
| } |
| |
| #if QT_CONFIG(wheelevent) |
| void QQuickMouseArea::wheelEvent(QWheelEvent *event) |
| { |
| Q_D(QQuickMouseArea); |
| if (!d->enabled || (!isScrollGestureEnabled() && event->source() != Qt::MouseEventNotSynthesized)) { |
| QQuickItem::wheelEvent(event); |
| return; |
| } |
| |
| QQuickWheelEvent &we = d->quickWheelEvent; |
| we.reset(event->position().x(), event->position().y(), event->angleDelta(), event->pixelDelta(), |
| event->buttons(), event->modifiers(), event->inverted()); |
| we.setAccepted(d->isWheelConnected()); |
| emit wheel(&we); |
| if (!we.isAccepted()) |
| QQuickItem::wheelEvent(event); |
| } |
| #endif |
| |
| void QQuickMouseArea::ungrabMouse() |
| { |
| Q_D(QQuickMouseArea); |
| if (d->pressed) { |
| // if our mouse grab has been removed (probably by Flickable), fix our |
| // state |
| d->pressed = Qt::NoButton; |
| d->stealMouse = false; |
| d->doubleClick = false; |
| d->overThreshold = false; |
| setKeepMouseGrab(false); |
| |
| #if QT_CONFIG(quick_draganddrop) |
| if (d->drag) |
| d->drag->setActive(false); |
| #endif |
| |
| emit canceled(); |
| emit pressedChanged(); |
| emit containsPressChanged(); |
| emit pressedButtonsChanged(); |
| |
| if (d->hovered && !isUnderMouse()) { |
| d->hovered = false; |
| emit hoveredChanged(); |
| } |
| } |
| } |
| |
| 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()); |
| |
| 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(), |
| event->button(), event->buttons(), event->modifiers()); |
| mouseEvent.setAccepted(false); |
| |
| switch (event->type()) { |
| case QEvent::MouseMove: |
| mouseMoveEvent(&mouseEvent); |
| break; |
| case QEvent::MouseButtonPress: |
| mousePressEvent(&mouseEvent); |
| break; |
| case QEvent::MouseButtonRelease: |
| mouseReleaseEvent(&mouseEvent); |
| stealThisEvent = d->stealMouse; |
| break; |
| default: |
| break; |
| } |
| grabber = c ? c->mouseGrabberItem() : nullptr; |
| if (grabber && stealThisEvent && !grabber->keepMouseGrab() && grabber != this) |
| grabMouse(); |
| |
| return stealThisEvent; |
| } |
| if (event->type() == QEvent::MouseButtonRelease) { |
| if (d->pressed) { |
| d->pressed &= ~event->button(); |
| emit pressedButtonsChanged(); |
| if (!d->pressed) { |
| // no other buttons are pressed |
| d->stealMouse = false; |
| d->overThreshold = false; |
| if (c && c->mouseGrabberItem() == this) |
| ungrabMouse(); |
| emit canceled(); |
| emit pressedChanged(); |
| emit containsPressChanged(); |
| if (d->hovered) { |
| d->hovered = false; |
| emit hoveredChanged(); |
| } |
| } |
| } |
| } |
| return false; |
| } |
| |
| bool QQuickMouseArea::childMouseEventFilter(QQuickItem *i, QEvent *e) |
| { |
| Q_D(QQuickMouseArea); |
| if (!d->pressed && |
| (!d->enabled || !isVisible() |
| #if QT_CONFIG(quick_draganddrop) |
| || !d->drag || !d->drag->filterChildren() |
| #endif |
| ) |
| ) |
| return QQuickItem::childMouseEventFilter(i, e); |
| switch (e->type()) { |
| case QEvent::MouseButtonPress: |
| case QEvent::MouseMove: |
| case QEvent::MouseButtonRelease: |
| return sendMouseEvent(static_cast<QMouseEvent *>(e)); |
| default: |
| break; |
| } |
| |
| return QQuickItem::childMouseEventFilter(i, e); |
| } |
| |
| void QQuickMouseArea::timerEvent(QTimerEvent *event) |
| { |
| Q_D(QQuickMouseArea); |
| if (event->timerId() == d->pressAndHoldTimer.timerId()) { |
| d->pressAndHoldTimer.stop(); |
| #if QT_CONFIG(quick_draganddrop) |
| bool dragged = d->drag && d->drag->active(); |
| #else |
| bool dragged = false; |
| #endif |
| if (d->pressed && dragged == false && d->hovered == true) { |
| 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); |
| me.setSource(Qt::MouseEventSynthesizedByQt); |
| me.setAccepted(d->isPressAndHoldConnected()); |
| emit pressAndHold(&me); |
| if (!me.isAccepted()) |
| d->propagate(&me, QQuickMouseAreaPrivate::PressAndHold); |
| if (!me.isAccepted()) // no one handled the long press - allow click |
| d->longPress = false; |
| } |
| } |
| } |
| |
| void QQuickMouseArea::windowDeactivateEvent() |
| { |
| ungrabMouse(); |
| QQuickItem::windowDeactivateEvent(); |
| } |
| |
| void QQuickMouseArea::geometryChanged(const QRectF &newGeometry, |
| const QRectF &oldGeometry) |
| { |
| Q_D(QQuickMouseArea); |
| QQuickItem::geometryChanged(newGeometry, oldGeometry); |
| |
| if (d->lastScenePos.isNull) |
| d->lastScenePos = mapToScene(d->lastPos); |
| else if (newGeometry.x() != oldGeometry.x() || newGeometry.y() != oldGeometry.y()) |
| d->lastPos = mapFromScene(d->lastScenePos); |
| } |
| |
| void QQuickMouseArea::itemChange(ItemChange change, const ItemChangeData &value) |
| { |
| Q_D(QQuickMouseArea); |
| switch (change) { |
| case ItemVisibleHasChanged: |
| if (d->effectiveEnable && d->enabled && acceptHoverEvents() && d->hovered != (isVisible() && isUnderMouse())) { |
| if (!d->hovered) { |
| QPointF cursorPos = QGuiApplicationPrivate::lastCursorPosition; |
| d->lastScenePos = d->window->mapFromGlobal(cursorPos.toPoint()); |
| d->lastPos = mapFromScene(d->lastScenePos); |
| } |
| setHovered(!d->hovered); |
| } |
| break; |
| default: |
| break; |
| } |
| |
| QQuickItem::itemChange(change, value); |
| } |
| |
| /*! |
| \qmlproperty bool QtQuick::MouseArea::hoverEnabled |
| This property holds whether hover events are handled. |
| |
| By default, mouse events are only handled in response to a button event, or when a button is |
| pressed. Hover enables handling of all mouse events even when no mouse button is |
| pressed. |
| |
| This property affects the containsMouse property and the onEntered, onExited and |
| onPositionChanged signals. |
| */ |
| bool QQuickMouseArea::hoverEnabled() const |
| { |
| return acceptHoverEvents(); |
| } |
| |
| void QQuickMouseArea::setHoverEnabled(bool h) |
| { |
| if (h == acceptHoverEvents()) |
| return; |
| |
| setAcceptHoverEvents(h); |
| emit hoverEnabledChanged(); |
| } |
| |
| |
| /*! |
| \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 |
| when the mouse is pressed while the mouse cursor is inside the MouseArea. |
| */ |
| bool QQuickMouseArea::hovered() const |
| { |
| Q_D(const QQuickMouseArea); |
| return d->hovered; |
| } |
| |
| /*! |
| \qmlproperty bool QtQuick::MouseArea::pressed |
| This property holds whether any of the \l acceptedButtons are currently pressed. |
| */ |
| bool QQuickMouseArea::pressed() const |
| { |
| Q_D(const QQuickMouseArea); |
| return d->pressed; |
| } |
| |
| /*! |
| \qmlproperty bool QtQuick::MouseArea::containsPress |
| \since 5.4 |
| This is a convenience property equivalent to \c {pressed && containsMouse}, |
| i.e. it holds whether any of the \l acceptedButtons are currently pressed |
| and the mouse is currently within the MouseArea. |
| |
| This property is particularly useful for highlighting an item while the mouse |
| is pressed within its bounds. |
| |
| \sa pressed, containsMouse |
| */ |
| bool QQuickMouseArea::containsPress() const |
| { |
| Q_D(const QQuickMouseArea); |
| return d->pressed && d->hovered; |
| } |
| |
| void QQuickMouseArea::setHovered(bool h) |
| { |
| Q_D(QQuickMouseArea); |
| if (d->hovered != h) { |
| qCDebug(DBG_HOVER_TRACE) << this << d->hovered << "->" << h; |
| d->hovered = h; |
| emit hoveredChanged(); |
| d->hovered ? emit entered() : emit exited(); |
| if (d->pressed) |
| emit containsPressChanged(); |
| } |
| } |
| |
| /*! |
| \qmlproperty Qt::MouseButtons QtQuick::MouseArea::acceptedButtons |
| This property holds the mouse buttons that the mouse area reacts to. |
| |
| To specify that the MouseArea will react to multiple buttons, |
| Qt::MouseButtons flag values are combined using the "|" (or) operator: |
| |
| \code |
| MouseArea { acceptedButtons: Qt.LeftButton | Qt.RightButton } |
| \endcode |
| |
| To indicate that all possible mouse buttons are to be accepted, |
| the special value 'Qt.AllButtons' may be used: |
| |
| \code |
| MouseArea { acceptedButtons: Qt.AllButtons } |
| \endcode |
| |
| The default value is \c Qt.LeftButton. |
| */ |
| Qt::MouseButtons QQuickMouseArea::acceptedButtons() const |
| { |
| return acceptedMouseButtons(); |
| } |
| |
| void QQuickMouseArea::setAcceptedButtons(Qt::MouseButtons buttons) |
| { |
| if (buttons != acceptedMouseButtons()) { |
| setAcceptedMouseButtons(buttons); |
| emit acceptedButtonsChanged(); |
| } |
| } |
| |
| bool QQuickMouseArea::setPressed(Qt::MouseButton button, bool p, Qt::MouseEventSource source) |
| { |
| Q_D(QQuickMouseArea); |
| |
| #if QT_CONFIG(quick_draganddrop) |
| bool dragged = d->drag && d->drag->active(); |
| #else |
| bool dragged = false; |
| #endif |
| bool wasPressed = d->pressed & button; |
| bool isclick = wasPressed && p == false && dragged == false && d->hovered == true; |
| Qt::MouseButtons oldPressed = d->pressed; |
| |
| 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); |
| me.setSource(source); |
| if (p) { |
| d->pressed |= button; |
| if (!d->doubleClick) |
| emit pressed(&me); |
| me.setPosition(d->lastPos); |
| emit mouseXChanged(&me); |
| me.setPosition(d->lastPos); |
| emit mouseYChanged(&me); |
| |
| if (!me.isAccepted()) { |
| d->pressed = Qt::NoButton; |
| } |
| |
| if (!oldPressed) { |
| emit pressedChanged(); |
| emit containsPressChanged(); |
| } |
| emit pressedButtonsChanged(); |
| } else { |
| d->pressed &= ~button; |
| emit released(&me); |
| me.setPosition(d->lastPos); |
| if (!d->pressed) { |
| emit pressedChanged(); |
| emit containsPressChanged(); |
| } |
| emit pressedButtonsChanged(); |
| if (isclick && !d->longPress && !d->doubleClick){ |
| me.setAccepted(d->isClickConnected()); |
| emit clicked(&me); |
| if (!me.isAccepted()) |
| d->propagate(&me, QQuickMouseAreaPrivate::Click); |
| } |
| } |
| |
| return me.isAccepted(); |
| } |
| return false; |
| } |
| |
| |
| /*! |
| \qmlproperty Qt::CursorShape QtQuick::MouseArea::cursorShape |
| This property holds the cursor shape for this mouse area. |
| Note that on platforms that do not display a mouse cursor this may have |
| no effect. |
| |
| The available cursor shapes are: |
| \list |
| \li Qt.ArrowCursor |
| \li Qt.UpArrowCursor |
| \li Qt.CrossCursor |
| \li Qt.WaitCursor |
| \li Qt.IBeamCursor |
| \li Qt.SizeVerCursor |
| \li Qt.SizeHorCursor |
| \li Qt.SizeBDiagCursor |
| \li Qt.SizeFDiagCursor |
| \li Qt.SizeAllCursor |
| \li Qt.BlankCursor |
| \li Qt.SplitVCursor |
| \li Qt.SplitHCursor |
| \li Qt.PointingHandCursor |
| \li Qt.ForbiddenCursor |
| \li Qt.WhatsThisCursor |
| \li Qt.BusyCursor |
| \li Qt.OpenHandCursor |
| \li Qt.ClosedHandCursor |
| \li Qt.DragCopyCursor |
| \li Qt.DragMoveCursor |
| \li Qt.DragLinkCursor |
| \endlist |
| |
| In order to only set a mouse cursor shape for a region without reacting |
| to mouse events set the acceptedButtons to none: |
| |
| \code |
| MouseArea { cursorShape: Qt.IBeamCursor; acceptedButtons: Qt.NoButton } |
| \endcode |
| |
| The default value is \c Qt.ArrowCursor. |
| \sa Qt::CursorShape |
| */ |
| |
| #if QT_CONFIG(cursor) |
| Qt::CursorShape QQuickMouseArea::cursorShape() const |
| { |
| return cursor().shape(); |
| } |
| |
| void QQuickMouseArea::setCursorShape(Qt::CursorShape shape) |
| { |
| if (cursor().shape() == shape) |
| return; |
| |
| setCursor(shape); |
| |
| emit cursorShapeChanged(); |
| } |
| |
| #endif |
| |
| |
| /*! |
| \qmlproperty int QtQuick::MouseArea::pressAndHoldInterval |
| \since 5.9 |
| |
| This property overrides the elapsed time in milliseconds before |
| \c pressAndHold is emitted. |
| |
| If not explicitly set -- or after reset -- the value follows |
| \c QStyleHints::mousePressAndHoldInterval. |
| |
| Typically it's sufficient to set this property globally using the |
| application style hint. This property should be used when varying intervals |
| are needed for certain MouseAreas. |
| |
| \sa pressAndHold |
| */ |
| int QQuickMouseArea::pressAndHoldInterval() const |
| { |
| Q_D(const QQuickMouseArea); |
| return d->pressAndHoldInterval > -1 ? |
| d->pressAndHoldInterval : QGuiApplication::styleHints()->mousePressAndHoldInterval(); |
| } |
| |
| void QQuickMouseArea::setPressAndHoldInterval(int interval) |
| { |
| Q_D(QQuickMouseArea); |
| if (interval != d->pressAndHoldInterval) { |
| d->pressAndHoldInterval = interval; |
| emit pressAndHoldIntervalChanged(); |
| } |
| } |
| |
| void QQuickMouseArea::resetPressAndHoldInterval() |
| { |
| Q_D(QQuickMouseArea); |
| if (d->pressAndHoldInterval > -1) { |
| d->pressAndHoldInterval = -1; |
| emit pressAndHoldIntervalChanged(); |
| } |
| } |
| |
| /*! |
| \qmlpropertygroup QtQuick::MouseArea::drag |
| \qmlproperty Item QtQuick::MouseArea::drag.target |
| \qmlproperty bool QtQuick::MouseArea::drag.active |
| \qmlproperty enumeration QtQuick::MouseArea::drag.axis |
| \qmlproperty real QtQuick::MouseArea::drag.minimumX |
| \qmlproperty real QtQuick::MouseArea::drag.maximumX |
| \qmlproperty real QtQuick::MouseArea::drag.minimumY |
| \qmlproperty real QtQuick::MouseArea::drag.maximumY |
| \qmlproperty bool QtQuick::MouseArea::drag.filterChildren |
| \qmlproperty real QtQuick::MouseArea::drag.threshold |
| |
| \c drag provides a convenient way to make an item draggable. |
| |
| \list |
| \li \c drag.target specifies the id of the item to drag. |
| \li \c drag.active specifies if the target item is currently being dragged. |
| \li \c drag.axis specifies whether dragging can be done horizontally (\c Drag.XAxis), vertically (\c Drag.YAxis), or both (\c Drag.XAndYAxis) |
| \li \c drag.minimum and \c drag.maximum limit how far the target can be dragged along the corresponding axes. |
| \endlist |
| |
| The following example displays a \l Rectangle that can be dragged along the X-axis. The opacity |
| of the rectangle is reduced when it is dragged to the right. |
| |
| \snippet qml/mousearea/mousearea.qml drag |
| |
| \note Items cannot be dragged if they are anchored for the requested |
| \c drag.axis. For example, if \c anchors.left or \c anchors.right was set |
| for \c rect in the above example, it cannot be dragged along the X-axis. |
| This can be avoided by settng the anchor value to \c undefined in |
| an \l {pressed}{onPressed} handler. |
| |
| 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: |
| |
| \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. |
| |
| If \c drag.smoothed is \c true, the target will be moved only after the drag operation has |
| started. If set to \c false, the target will be moved straight to the current mouse position. |
| 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(quick_draganddrop) |
| QQuickDrag *QQuickMouseArea::drag() |
| { |
| Q_D(QQuickMouseArea); |
| if (!d->drag) |
| d->drag = new QQuickDrag; |
| return d->drag; |
| } |
| #endif |
| |
| QSGNode *QQuickMouseArea::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data) |
| { |
| Q_UNUSED(data); |
| Q_D(QQuickMouseArea); |
| |
| if (!qmlVisualTouchDebugging()) |
| return nullptr; |
| |
| QSGInternalRectangleNode *rectangle = static_cast<QSGInternalRectangleNode *>(oldNode); |
| if (!rectangle) rectangle = d->sceneGraphContext()->createInternalRectangleNode(); |
| |
| rectangle->setRect(QRectF(0, 0, width(), height())); |
| rectangle->setColor(QColor(255, 0, 0, 50)); |
| rectangle->update(); |
| return rectangle; |
| } |
| |
| QT_END_NAMESPACE |
| |
| #include "moc_qquickmousearea_p.cpp" |