1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qquickmousearea_p.h"
43 #include "qquickmousearea_p_p.h"
44 #include "qquickcanvas.h"
45 #include "qquickevents_p_p.h"
46 #include "qquickdrag_p.h"
48 #include <QtGui/qevent.h>
49 #include <QtGui/qguiapplication.h>
50 #include <QtGui/qstylehints.h>
55 static const int PressAndHoldDelay = 800;
57 QQuickDrag::QQuickDrag(QObject *parent)
58 : QObject(parent), _target(0), _axis(XandYAxis), _xmin(-FLT_MAX),
59 _xmax(FLT_MAX), _ymin(-FLT_MAX), _ymax(FLT_MAX), _active(false), _filterChildren(false)
63 QQuickDrag::~QQuickDrag()
67 QQuickItem *QQuickDrag::target() const
72 void QQuickDrag::setTarget(QQuickItem *t)
80 void QQuickDrag::resetTarget()
88 QQuickDrag::Axis QQuickDrag::axis() const
93 void QQuickDrag::setAxis(QQuickDrag::Axis a)
101 qreal QQuickDrag::xmin() const
106 void QQuickDrag::setXmin(qreal m)
111 emit minimumXChanged();
114 qreal QQuickDrag::xmax() const
119 void QQuickDrag::setXmax(qreal m)
124 emit maximumXChanged();
127 qreal QQuickDrag::ymin() const
132 void QQuickDrag::setYmin(qreal m)
137 emit minimumYChanged();
140 qreal QQuickDrag::ymax() const
145 void QQuickDrag::setYmax(qreal m)
150 emit maximumYChanged();
153 bool QQuickDrag::active() const
158 void QQuickDrag::setActive(bool drag)
163 emit activeChanged();
166 bool QQuickDrag::filterChildren() const
168 return _filterChildren;
171 void QQuickDrag::setFilterChildren(bool filter)
173 if (_filterChildren == filter)
175 _filterChildren = filter;
176 emit filterChildrenChanged();
179 QQuickDragAttached *QQuickDrag::qmlAttachedProperties(QObject *obj)
181 return new QQuickDragAttached(obj);
184 QQuickMouseAreaPrivate::QQuickMouseAreaPrivate()
185 : absorb(true), hovered(false), pressed(false), longPress(false),
186 moved(false), stealMouse(false), doubleClick(false), preventStealing(false),
191 QQuickMouseAreaPrivate::~QQuickMouseAreaPrivate()
196 void QQuickMouseAreaPrivate::init()
198 Q_Q(QQuickMouseArea);
199 q->setAcceptedMouseButtons(Qt::LeftButton);
200 q->setFiltersChildMouseEvents(true);
203 void QQuickMouseAreaPrivate::saveEvent(QMouseEvent *event)
205 lastPos = event->localPos();
206 lastScenePos = event->windowPos();
207 lastButton = event->button();
208 lastButtons = event->buttons();
209 lastModifiers = event->modifiers();
212 bool QQuickMouseAreaPrivate::isPressAndHoldConnected()
214 Q_Q(QQuickMouseArea);
215 static int idx = QObjectPrivate::get(q)->signalIndex("pressAndHold(QQuickMouseEvent*)");
216 return QObjectPrivate::get(q)->isSignalConnected(idx);
219 bool QQuickMouseAreaPrivate::isDoubleClickConnected()
221 Q_Q(QQuickMouseArea);
222 static int idx = QObjectPrivate::get(q)->signalIndex("doubleClicked(QQuickMouseEvent*)");
223 return QObjectPrivate::get(q)->isSignalConnected(idx);
226 bool QQuickMouseAreaPrivate::isClickConnected()
228 Q_Q(QQuickMouseArea);
229 static int idx = QObjectPrivate::get(q)->signalIndex("clicked(QQuickMouseEvent*)");
230 return QObjectPrivate::get(q)->isSignalConnected(idx);
233 void QQuickMouseAreaPrivate::propagate(QQuickMouseEvent* event, PropagateType t)
235 Q_Q(QQuickMouseArea);
236 QPointF scenePos = q->mapToScene(QPointF(event->x(), event->y()));
237 propagateHelper(event, canvas->rootItem(), scenePos, t);
240 bool QQuickMouseAreaPrivate::propagateHelper(QQuickMouseEvent *ev, QQuickItem *item,const QPointF &sp, PropagateType sig)
242 //Based off of QQuickCanvas::deliverInitialMousePressEvent
243 //But specific to MouseArea, so doesn't belong in canvas
244 Q_Q(const QQuickMouseArea);
245 QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
246 if (itemPrivate->opacity == 0.0)
249 if (itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) {
250 QPointF p = item->mapFromScene(sp);
251 if (!QRectF(0, 0, item->width(), item->height()).contains(p))
255 QList<QQuickItem *> children = itemPrivate->paintOrderChildItems();
256 for (int ii = children.count() - 1; ii >= 0; --ii) {
257 QQuickItem *child = children.at(ii);
258 if (!child->isVisible() || !child->isEnabled())
260 if (propagateHelper(ev, child, sp, sig))
264 QQuickMouseArea* ma = qobject_cast<QQuickMouseArea*>(item);
265 if (ma && ma != q && itemPrivate->acceptedMouseButtons & ev->button()) {
268 if (!ma->d_func()->isClickConnected())
272 if (!ma->d_func()->isDoubleClickConnected())
276 if (!ma->d_func()->isPressAndHoldConnected())
280 QPointF p = item->mapFromScene(sp);
281 if (QRectF(0, 0, item->width(), item->height()).contains(p)) {
284 ev->setAccepted(true);//It is connected, they have to explicitly ignore to let it slide
286 case Click: emit ma->clicked(ev); break;
287 case DoubleClick: emit ma->doubleClicked(ev); break;
288 case PressAndHold: emit ma->pressAndHold(ev); break;
290 if (ev->isAccepted())
299 \qmlclass MouseArea QQuickMouseArea
300 \inqmlmodule QtQuick 2
301 \ingroup qml-basic-interaction-elements
302 \brief The MouseArea item enables simple mouse handling.
305 A MouseArea is an invisible item that is typically used in conjunction with
306 a visible item in order to provide mouse handling for that item.
307 By effectively acting as a proxy, the logic for mouse handling can be
308 contained within a MouseArea item.
310 For basic key handling, see the \l{Keys}{Keys attached property}.
312 The \l enabled property is used to enable and disable mouse handling for
313 the proxied item. When disabled, the mouse area becomes transparent to
316 The \l pressed read-only property indicates whether or not the user is
317 holding down a mouse button over the mouse area. This property is often
318 used in bindings between properties in a user interface. The containsMouse
319 read-only property indicates the presence of the mouse cursor over the
320 mouse area but, by default, only when a mouse button is held down; see below
323 Information about the mouse position and button clicks are provided via
324 signals for which event handler properties are defined. The most commonly
325 used involved handling mouse presses and clicks: onClicked, onDoubleClicked,
326 onPressed, onReleased and onPressAndHold.
328 By default, MouseArea items only report mouse clicks and not changes to the
329 position of the mouse cursor. Setting the hoverEnabled property ensures that
330 handlers defined for onPositionChanged, onEntered and onExited are used and
331 that the containsMouse property is updated even when no mouse buttons are
334 \section1 Example Usage
336 \div {class="float-right"}
337 \inlineimage qml-mousearea-snippet.png
340 The following example uses a MouseArea in a \l Rectangle that changes
341 the \l Rectangle color to red when clicked:
343 \snippet doc/src/snippets/declarative/mousearea/mousearea.qml import
345 \snippet doc/src/snippets/declarative/mousearea/mousearea.qml intro
348 Many MouseArea signals pass a \l{MouseEvent}{mouse} parameter that contains
349 additional information about the mouse event, such as the position, button,
350 and any key modifiers.
352 Here is an extension of the previous example that produces a different
353 color when the area is right clicked:
355 \snippet doc/src/snippets/declarative/mousearea/mousearea.qml intro-extended
357 Behavioral Change in QtQuick 2.0
359 From QtQuick 2.0, the signals clicked, doubleClicked and pressAndHold have a different interaction
360 model with regards to the delivery of events to multiple overlapping MouseAreas. These signals will now propagate
361 to all MouseAreas in the area, in painting order, until accepted by one of them. A signal is accepted by
362 default if there is a signal handler for it, use mouse.accepted = false; to ignore. This propagation
363 can send the signal to MouseAreas other than the one which accepted the press event, although that MouseArea
364 will receive the signal first.
366 Note that to get the same behavior as a QtQuick 1.0 MouseArea{} with regard to absorbing all mouse events, you will
367 now need to add empty signal handlers for these three signals.
369 \sa MouseEvent, {declarative/touchinteraction/mousearea}{MouseArea example}
373 \qmlsignal QtQuick2::MouseArea::onEntered()
375 This handler is called when the mouse enters the mouse area.
377 By default the onEntered handler is only called while a button is
378 pressed. Setting hoverEnabled to true enables handling of
379 onEntered when no mouse button is pressed.
385 \qmlsignal QtQuick2::MouseArea::onExited()
387 This handler is called when the mouse exits the mouse area.
389 By default the onExited handler is only called while a button is
390 pressed. Setting hoverEnabled to true enables handling of
391 onExited when no mouse button is pressed.
393 The example below shows a fairly typical relationship between
394 two MouseAreas, with \c mouseArea2 on top of \c mouseArea1. Moving the
395 mouse into \c mouseArea2 from \c mouseArea1 will cause \c onExited
396 to be called for \c mouseArea1.
399 width: 400; height: 400
407 width: 100; height: 100
408 anchors.centerIn: parent
414 If instead you give the two mouseAreas a parent-child relationship,
415 moving the mouse into \c mouseArea2 from \c mouseArea1 will \b not
416 cause \c onExited to be called for \c mouseArea1. Instead, they will
417 both be considered to be simultaneously hovered.
423 \qmlsignal QtQuick2::MouseArea::onPositionChanged(MouseEvent mouse)
425 This handler is called when the mouse position changes.
427 The \l {MouseEvent}{mouse} parameter provides information about the mouse, including the x and y
428 position, and any buttons currently pressed.
430 The \e accepted property of the MouseEvent parameter is ignored in this handler.
432 By default the onPositionChanged handler is only called while a button is
433 pressed. Setting hoverEnabled to true enables handling of
434 onPositionChanged when no mouse button is pressed.
438 \qmlsignal QtQuick2::MouseArea::onClicked(MouseEvent mouse)
440 This handler is called when there is a click. A click is defined as a press followed by a release,
441 both inside the MouseArea (pressing, moving outside the MouseArea, and then moving back inside and
442 releasing is also considered a click).
444 The \l {MouseEvent}{mouse} parameter provides information about the click, including the x and y
445 position of the release of the click, and whether the click was held.
447 The \e accepted property of the MouseEvent parameter is ignored in this handler.
451 \qmlsignal QtQuick2::MouseArea::onPressed(MouseEvent mouse)
453 This handler is called when there is a press.
454 The \l {MouseEvent}{mouse} parameter provides information about the press, including the x and y
455 position and which button was pressed.
457 The \e accepted property of the MouseEvent parameter determines whether this MouseArea
458 will handle the press and all future mouse events until release. The default is to accept
459 the event and not allow other MouseArea beneath this one to handle the event. If \e accepted
460 is set to false, no further events will be sent to this MouseArea until the button is next
465 \qmlsignal QtQuick2::MouseArea::onReleased(MouseEvent mouse)
467 This handler is called when there is a release.
468 The \l {MouseEvent}{mouse} parameter provides information about the click, including the x and y
469 position of the release of the click, and whether the click was held.
471 The \e accepted property of the MouseEvent parameter is ignored in this handler.
477 \qmlsignal QtQuick2::MouseArea::onPressAndHold(MouseEvent mouse)
479 This handler is called when there is a long press (currently 800ms).
480 The \l {MouseEvent}{mouse} parameter provides information about the press, including the x and y
481 position of the press, and which button is pressed.
483 The \e accepted property of the MouseEvent parameter is ignored in this handler.
487 \qmlsignal QtQuick2::MouseArea::onDoubleClicked(MouseEvent mouse)
489 This handler is called when there is a double-click (a press followed by a release followed by a press).
490 The \l {MouseEvent}{mouse} parameter provides information about the click, including the x and y
491 position of the release of the click, and whether the click was held.
493 If the \e accepted property of the \l {MouseEvent}{mouse} parameter is set to false
494 in the handler, the onPressed/onReleased/onClicked handlers will be called for the second
495 click; otherwise they are suppressed. The accepted property defaults to true.
499 \qmlsignal QtQuick2::MouseArea::onCanceled()
501 This handler is called when mouse events have been canceled, either because an event was not accepted, or
502 because another element stole the mouse event handling.
504 This signal is for advanced use: it is useful when there is more than one MouseArea
505 that is handling input, or when there is a MouseArea inside a \l Flickable. In the latter
506 case, if you execute some logic on the pressed signal and then start dragging, the
507 \l Flickable will steal the mouse handling from the MouseArea. In these cases, to reset
508 the logic when the MouseArea has lost the mouse handling to the \l Flickable,
509 \c onCanceled should be used in addition to onReleased.
511 QQuickMouseArea::QQuickMouseArea(QQuickItem *parent)
512 : QQuickItem(*(new QQuickMouseAreaPrivate), parent)
514 Q_D(QQuickMouseArea);
518 QQuickMouseArea::~QQuickMouseArea()
523 \qmlproperty real QtQuick2::MouseArea::mouseX
524 \qmlproperty real QtQuick2::MouseArea::mouseY
525 These properties hold the coordinates of the mouse cursor.
527 If the hoverEnabled property is false then these properties will only be valid
528 while a button is pressed, and will remain valid as long as the button is held
529 down even if the mouse is moved outside the area.
531 By default, this property is false.
533 If hoverEnabled is true then these properties will be valid when:
535 \i no button is pressed, but the mouse is within the MouseArea (containsMouse is true).
536 \i a button is pressed and held, even if it has since moved out of the area.
539 The coordinates are relative to the MouseArea.
541 qreal QQuickMouseArea::mouseX() const
543 Q_D(const QQuickMouseArea);
544 return d->lastPos.x();
547 qreal QQuickMouseArea::mouseY() const
549 Q_D(const QQuickMouseArea);
550 return d->lastPos.y();
554 \qmlproperty bool QtQuick2::MouseArea::enabled
555 This property holds whether the item accepts mouse events.
557 By default, this property is true.
559 bool QQuickMouseArea::isEnabled() const
561 Q_D(const QQuickMouseArea);
565 void QQuickMouseArea::setEnabled(bool a)
567 Q_D(QQuickMouseArea);
568 if (a != d->absorb) {
570 emit enabledChanged();
575 \qmlproperty bool QtQuick2::MouseArea::preventStealing
576 This property holds whether the mouse events may be stolen from this
579 If a MouseArea is placed within an item that filters child mouse
580 events, such as Flickable, the mouse
581 events may be stolen from the MouseArea if a gesture is recognized
582 by the parent element, e.g. a flick gesture. If preventStealing is
583 set to true, no element will steal the mouse events.
585 Note that setting preventStealing to true once an element has started
586 stealing events will have no effect until the next press event.
588 By default this property is false.
590 bool QQuickMouseArea::preventStealing() const
592 Q_D(const QQuickMouseArea);
593 return d->preventStealing;
596 void QQuickMouseArea::setPreventStealing(bool prevent)
598 Q_D(QQuickMouseArea);
599 if (prevent != d->preventStealing) {
600 d->preventStealing = prevent;
601 setKeepMouseGrab(d->preventStealing && d->absorb);
602 emit preventStealingChanged();
607 \qmlproperty MouseButtons QtQuick2::MouseArea::pressedButtons
608 This property holds the mouse buttons currently pressed.
610 It contains a bitwise combination of:
617 The code below displays "right" when the right mouse buttons is pressed:
619 \snippet doc/src/snippets/declarative/mousearea/mousearea.qml mousebuttons
623 Qt::MouseButtons QQuickMouseArea::pressedButtons() const
625 Q_D(const QQuickMouseArea);
626 return d->lastButtons;
629 void QQuickMouseArea::mousePressEvent(QMouseEvent *event)
631 Q_D(QQuickMouseArea);
633 d->stealMouse = d->preventStealing;
635 QQuickItem::mousePressEvent(event);
637 d->longPress = false;
640 d->dragX = drag()->axis() & QQuickDrag::XAxis;
641 d->dragY = drag()->axis() & QQuickDrag::YAxis;
644 d->drag->setActive(false);
646 d->startScene = event->windowPos();
647 d->pressAndHoldTimer.start(PressAndHoldDelay, this);
648 setKeepMouseGrab(d->stealMouse);
649 event->setAccepted(setPressed(true));
654 void QQuickMouseArea::mouseMoveEvent(QMouseEvent *event)
656 Q_D(QQuickMouseArea);
658 QQuickItem::mouseMoveEvent(event);
664 // ### we should skip this if these signals aren't used
665 // ### can GV handle this for us?
666 bool contains = boundingRect().contains(d->lastPos);
667 if (d->hovered && !contains)
669 else if (!d->hovered && contains)
672 if (d->drag && d->drag->target()) {
674 d->targetStartPos = d->drag->target()->parentItem()
675 ? d->drag->target()->parentItem()->mapToScene(d->drag->target()->pos())
676 : d->drag->target()->pos();
679 QPointF startLocalPos;
681 if (drag()->target()->parentItem()) {
682 startLocalPos = drag()->target()->parentItem()->mapFromScene(d->startScene);
683 curLocalPos = drag()->target()->parentItem()->mapFromScene(event->windowPos());
685 startLocalPos = d->startScene;
686 curLocalPos = event->windowPos();
689 const int dragThreshold = qApp->styleHints()->startDragDistance();
690 qreal dx = qAbs(curLocalPos.x() - startLocalPos.x());
691 qreal dy = qAbs(curLocalPos.y() - startLocalPos.y());
693 if (keepMouseGrab() && d->stealMouse && !d->drag->active())
694 d->drag->setActive(true);
696 QPointF startPos = d->drag->target()->parentItem()
697 ? d->drag->target()->parentItem()->mapFromScene(d->targetStartPos)
700 QPointF dragPos = d->drag->target()->pos();
702 if (d->dragX && d->drag->active()) {
703 qreal x = (curLocalPos.x() - startLocalPos.x()) + startPos.x();
704 if (x < drag()->xmin())
706 else if (x > drag()->xmax())
710 if (d->dragY && d->drag->active()) {
711 qreal y = (curLocalPos.y() - startLocalPos.y()) + startPos.y();
712 if (y < drag()->ymin())
714 else if (y > drag()->ymax())
718 d->drag->target()->setPos(dragPos);
720 if (!keepMouseGrab()) {
721 if ((!d->dragY && dy < dragThreshold && d->dragX && dx > dragThreshold)
722 || (!d->dragX && dx < dragThreshold && d->dragY && dy > dragThreshold)
723 || (d->dragX && d->dragY && (dx > dragThreshold || dy > dragThreshold))) {
724 setKeepMouseGrab(true);
725 d->stealMouse = true;
731 QQuickMouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, false, d->longPress);
732 emit mouseXChanged(&me);
733 me.setPosition(d->lastPos);
734 emit mouseYChanged(&me);
735 me.setPosition(d->lastPos);
736 emit positionChanged(&me);
739 void QQuickMouseArea::mouseReleaseEvent(QMouseEvent *event)
741 Q_D(QQuickMouseArea);
742 d->stealMouse = false;
744 QQuickItem::mouseReleaseEvent(event);
749 d->drag->setActive(false);
750 // If we don't accept hover, we need to reset containsMouse.
751 if (!acceptHoverEvents())
753 QQuickCanvas *c = canvas();
754 if (c && c->mouseGrabberItem() == this)
756 setKeepMouseGrab(false);
759 d->doubleClick = false;
762 void QQuickMouseArea::mouseDoubleClickEvent(QMouseEvent *event)
764 Q_D(QQuickMouseArea);
767 QQuickMouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, true, false);
768 me.setAccepted(d->isDoubleClickConnected());
769 emit this->doubleClicked(&me);
770 if (!me.isAccepted())
771 d->propagate(&me, QQuickMouseAreaPrivate::DoubleClick);
772 d->doubleClick = d->isDoubleClickConnected() || me.isAccepted();
774 QQuickItem::mouseDoubleClickEvent(event);
777 void QQuickMouseArea::hoverEnterEvent(QHoverEvent *event)
779 Q_D(QQuickMouseArea);
781 QQuickItem::hoverEnterEvent(event);
783 d->lastPos = event->posF();
784 d->lastModifiers = event->modifiers();
786 QQuickMouseEvent me(d->lastPos.x(), d->lastPos.y(), Qt::NoButton, Qt::NoButton, d->lastModifiers, false, false);
787 emit mouseXChanged(&me);
788 me.setPosition(d->lastPos);
789 emit mouseYChanged(&me);
790 me.setPosition(d->lastPos);
794 void QQuickMouseArea::hoverMoveEvent(QHoverEvent *event)
796 Q_D(QQuickMouseArea);
798 QQuickItem::hoverMoveEvent(event);
800 d->lastPos = event->posF();
801 d->lastModifiers = event->modifiers();
802 QQuickMouseEvent me(d->lastPos.x(), d->lastPos.y(), Qt::NoButton, Qt::NoButton, d->lastModifiers, false, false);
803 emit mouseXChanged(&me);
804 me.setPosition(d->lastPos);
805 emit mouseYChanged(&me);
806 me.setPosition(d->lastPos);
807 emit positionChanged(&me);
811 void QQuickMouseArea::hoverLeaveEvent(QHoverEvent *event)
813 Q_D(QQuickMouseArea);
815 QQuickItem::hoverLeaveEvent(event);
820 void QQuickMouseArea::ungrabMouse()
822 Q_D(QQuickMouseArea);
824 // if our mouse grab has been removed (probably by Flickable), fix our
827 d->stealMouse = false;
828 setKeepMouseGrab(false);
830 emit pressedChanged();
833 emit hoveredChanged();
838 void QQuickMouseArea::mouseUngrabEvent()
843 bool QQuickMouseArea::sendMouseEvent(QMouseEvent *event)
845 Q_D(QQuickMouseArea);
846 QRectF myRect = mapRectToScene(QRectF(0, 0, width(), height()));
848 QQuickCanvas *c = canvas();
849 QQuickItem *grabber = c ? c->mouseGrabberItem() : 0;
850 bool stealThisEvent = d->stealMouse;
851 if ((stealThisEvent || myRect.contains(event->windowPos())) && (!grabber || !grabber->keepMouseGrab())) {
852 QMouseEvent mouseEvent(event->type(), mapFromScene(event->windowPos()), event->windowPos(), event->screenPos(),
853 event->button(), event->buttons(), event->modifiers());
854 mouseEvent.setAccepted(false);
856 switch (event->type()) {
857 case QEvent::MouseMove:
858 mouseMoveEvent(&mouseEvent);
860 case QEvent::MouseButtonPress:
861 mousePressEvent(&mouseEvent);
863 case QEvent::MouseButtonRelease:
864 mouseReleaseEvent(&mouseEvent);
869 grabber = c->mouseGrabberItem();
870 if (grabber && stealThisEvent && !grabber->keepMouseGrab() && grabber != this)
873 return stealThisEvent;
875 if (event->type() == QEvent::MouseButtonRelease) {
878 d->stealMouse = false;
879 if (c && c->mouseGrabberItem() == this)
882 emit pressedChanged();
885 emit hoveredChanged();
892 bool QQuickMouseArea::childMouseEventFilter(QQuickItem *i, QEvent *e)
894 Q_D(QQuickMouseArea);
895 if (!d->absorb || !isVisible() || !d->drag || !d->drag->filterChildren())
896 return QQuickItem::childMouseEventFilter(i, e);
898 case QEvent::MouseButtonPress:
899 case QEvent::MouseMove:
900 case QEvent::MouseButtonRelease:
901 return sendMouseEvent(static_cast<QMouseEvent *>(e));
906 return QQuickItem::childMouseEventFilter(i, e);
909 void QQuickMouseArea::timerEvent(QTimerEvent *event)
911 Q_D(QQuickMouseArea);
912 if (event->timerId() == d->pressAndHoldTimer.timerId()) {
913 d->pressAndHoldTimer.stop();
914 bool dragged = d->drag && d->drag->active();
915 if (d->pressed && dragged == false && d->hovered == true) {
917 QQuickMouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, false, d->longPress);
918 me.setAccepted(d->isPressAndHoldConnected());
919 emit pressAndHold(&me);
920 if (!me.isAccepted())
921 d->propagate(&me, QQuickMouseAreaPrivate::PressAndHold);
922 if (!me.isAccepted()) // no one handled the long press - allow click
923 d->longPress = false;
928 void QQuickMouseArea::windowDeactivateEvent()
931 QQuickItem::windowDeactivateEvent();
934 void QQuickMouseArea::geometryChanged(const QRectF &newGeometry,
935 const QRectF &oldGeometry)
937 Q_D(QQuickMouseArea);
938 QQuickItem::geometryChanged(newGeometry, oldGeometry);
940 if (d->lastScenePos.isNull)
941 d->lastScenePos = mapToScene(d->lastPos);
942 else if (newGeometry.x() != oldGeometry.x() || newGeometry.y() != oldGeometry.y())
943 d->lastPos = mapFromScene(d->lastScenePos);
946 void QQuickMouseArea::itemChange(ItemChange change, const ItemChangeData &value)
948 Q_D(QQuickMouseArea);
950 case ItemVisibleHasChanged:
951 if (acceptHoverEvents() && d->hovered != (isVisible() && isUnderMouse()))
952 setHovered(!d->hovered);
958 QQuickItem::itemChange(change, value);
962 \qmlproperty bool QtQuick2::MouseArea::hoverEnabled
963 This property holds whether hover events are handled.
965 By default, mouse events are only handled in response to a button event, or when a button is
966 pressed. Hover enables handling of all mouse events even when no mouse button is
969 This property affects the containsMouse property and the onEntered, onExited and
970 onPositionChanged signals.
972 bool QQuickMouseArea::hoverEnabled() const
974 return acceptHoverEvents();
977 void QQuickMouseArea::setHoverEnabled(bool h)
979 if (h == acceptHoverEvents())
982 setAcceptHoverEvents(h);
983 emit hoverEnabledChanged();
988 \qmlproperty bool QtQuick2::MouseArea::containsMouse
989 This property holds whether the mouse is currently inside the mouse area.
991 \warning This property is not updated if the area moves under the mouse: \e containsMouse will not change.
992 In addition, if hoverEnabled is false, containsMouse will only be valid when the mouse is pressed.
994 bool QQuickMouseArea::hovered() const
996 Q_D(const QQuickMouseArea);
1001 \qmlproperty bool QtQuick2::MouseArea::pressed
1002 This property holds whether the mouse area is currently pressed.
1004 bool QQuickMouseArea::pressed() const
1006 Q_D(const QQuickMouseArea);
1010 void QQuickMouseArea::setHovered(bool h)
1012 Q_D(QQuickMouseArea);
1013 if (d->hovered != h) {
1015 emit hoveredChanged();
1016 d->hovered ? emit entered() : emit exited();
1020 \qmlproperty QtQuick2::Qt::MouseButtons MouseArea::acceptedButtons
1021 This property holds the mouse buttons that the mouse area reacts to.
1023 The available buttons are:
1030 To accept more than one button the flags can be combined with the
1034 MouseArea { acceptedButtons: Qt.LeftButton | Qt.RightButton }
1037 The default value is \c Qt.LeftButton.
1039 Qt::MouseButtons QQuickMouseArea::acceptedButtons() const
1041 return acceptedMouseButtons();
1044 void QQuickMouseArea::setAcceptedButtons(Qt::MouseButtons buttons)
1046 if (buttons != acceptedMouseButtons()) {
1047 setAcceptedMouseButtons(buttons);
1048 emit acceptedButtonsChanged();
1052 bool QQuickMouseArea::setPressed(bool p)
1054 Q_D(QQuickMouseArea);
1055 bool dragged = d->drag && d->drag->active();
1056 bool isclick = d->pressed == true && p == false && dragged == false && d->hovered == true;
1058 if (d->pressed != p) {
1060 QQuickMouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, isclick, d->longPress);
1062 if (!d->doubleClick)
1064 me.setPosition(d->lastPos);
1065 emit mouseXChanged(&me);
1066 me.setPosition(d->lastPos);
1067 emit mouseYChanged(&me);
1068 emit pressedChanged();
1071 me.setPosition(d->lastPos);
1072 emit pressedChanged();
1073 if (isclick && !d->longPress && !d->doubleClick){
1074 me.setAccepted(d->isClickConnected());
1076 if (!me.isAccepted())
1077 d->propagate(&me, QQuickMouseAreaPrivate::Click);
1081 return me.isAccepted();
1087 \qmlproperty Item QtQuick2::MouseArea::drag.target
1088 \qmlproperty bool QtQuick2::MouseArea::drag.active
1089 \qmlproperty enumeration QtQuick2::MouseArea::drag.axis
1090 \qmlproperty real QtQuick2::MouseArea::drag.minimumX
1091 \qmlproperty real QtQuick2::MouseArea::drag.maximumX
1092 \qmlproperty real QtQuick2::MouseArea::drag.minimumY
1093 \qmlproperty real QtQuick2::MouseArea::drag.maximumY
1094 \qmlproperty bool QtQuick2::MouseArea::drag.filterChildren
1096 \c drag provides a convenient way to make an item draggable.
1099 \i \c drag.target specifies the id of the item to drag.
1100 \i \c drag.active specifies if the target item is currently being dragged.
1101 \i \c drag.axis specifies whether dragging can be done horizontally (\c Drag.XAxis), vertically (\c Drag.YAxis), or both (\c Drag.XandYAxis)
1102 \i \c drag.minimum and \c drag.maximum limit how far the target can be dragged along the corresponding axes.
1105 The following example displays a \l Rectangle that can be dragged along the X-axis. The opacity
1106 of the rectangle is reduced when it is dragged to the right.
1108 \snippet doc/src/snippets/declarative/mousearea/mousearea.qml drag
1110 \note Items cannot be dragged if they are anchored for the requested
1111 \c drag.axis. For example, if \c anchors.left or \c anchors.right was set
1112 for \c rect in the above example, it cannot be dragged along the X-axis.
1113 This can be avoided by settng the anchor value to \c undefined in
1114 an \l onPressed handler.
1116 If \c drag.filterChildren is set to true, a drag can override descendant MouseAreas. This
1117 enables a parent MouseArea to handle drags, for example, while descendants handle clicks:
1119 \snippet doc/src/snippets/declarative/mousearea/mouseareadragfilter.qml dragfilter
1123 QQuickDrag *QQuickMouseArea::drag()
1125 Q_D(QQuickMouseArea);
1127 d->drag = new QQuickDrag;