Add mouse wheel events handler to MouseArea
This patch was based on the attached patch in QTBUG-7369. It basically exposes the wheel events to MouseArea via the onWheel signal. The current API is based on the new QWheelEvent API introduced by this patch: http://codereview.qt-project.org/#change,12532 Task-number: QTBUG-7369 Change-Id: Id58513715c2d0ae81e3a69e9e1ed400bbae07507 Reviewed-by: Michael Brasser <michael.brasser@nokia.com>
This commit is contained in:
parent
78356f6038
commit
f2e1be963f
|
@ -0,0 +1,84 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/
|
||||
**
|
||||
** This file is part of the examples of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:BSD$
|
||||
** You may use this file under the terms of the BSD license as follows:
|
||||
**
|
||||
** "Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions are
|
||||
** met:
|
||||
** * Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** * Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in
|
||||
** the documentation and/or other materials provided with the
|
||||
** distribution.
|
||||
** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
|
||||
** the names of its contributors may be used to endorse or promote
|
||||
** products derived from this software without specific prior written
|
||||
** permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick 2.0
|
||||
|
||||
Rectangle {
|
||||
height: 700
|
||||
width: 485
|
||||
color: "#333333"
|
||||
|
||||
Column {
|
||||
anchors.centerIn: parent
|
||||
spacing: 2
|
||||
|
||||
Repeater {
|
||||
model: ["#9ACD32", "#EEEEEE", "#FFD700", "#87CEEB"]
|
||||
|
||||
Rectangle {
|
||||
property real scaleFactor: 1
|
||||
|
||||
height: 40 * scaleFactor
|
||||
width: 60 * scaleFactor
|
||||
color: modelData
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onWheel: {
|
||||
if (wheel.modifiers & Qt.ControlModifier) {
|
||||
if (wheel.angleDelta.y > 0)
|
||||
parent.scaleFactor += 0.2;
|
||||
else if (parent.scaleFactor - 0.2 >= 0.2)
|
||||
parent.scaleFactor -= 0.2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
color: "#FFD700"
|
||||
text: "Rotate the mouse wheel pressing <Control> to resize the squares."
|
||||
}
|
||||
}
|
|
@ -1185,7 +1185,8 @@ bool QQuickCanvasPrivate::deliverWheelEvent(QQuickItem *item, QWheelEvent *event
|
|||
|
||||
QPointF p = item->mapFromScene(event->posF());
|
||||
if (QRectF(0, 0, item->width(), item->height()).contains(p)) {
|
||||
QWheelEvent wheel(p, event->delta(), event->buttons(), event->modifiers(), event->orientation());
|
||||
QWheelEvent wheel(p, p, event->pixelDelta(), event->angleDelta(), event->delta(),
|
||||
event->orientation(), event->buttons(), event->modifiers());
|
||||
wheel.accept();
|
||||
q->sendEvent(item, &wheel);
|
||||
if (wheel.isAccepted()) {
|
||||
|
|
|
@ -236,4 +236,108 @@ Item {
|
|||
*/
|
||||
|
||||
|
||||
/*!
|
||||
\qmlclass WheelEvent QQuickWheelEvent
|
||||
\inqmlmodule QtQuick 2
|
||||
\ingroup qml-event-elements
|
||||
|
||||
\brief The WheelEvent object provides information about a mouse wheel event.
|
||||
|
||||
The position of the mouse can be found via the \l x and \l y properties.
|
||||
|
||||
\sa MouseArea
|
||||
*/
|
||||
|
||||
/*!
|
||||
\internal
|
||||
\class QQuickWheelEvent
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty int QtQuick2::WheelEvent::x
|
||||
\qmlproperty int QtQuick2::WheelEvent::y
|
||||
|
||||
These properties hold the coordinates of the position supplied by the wheel event.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty bool QtQuick2::WheelEvent::accepted
|
||||
|
||||
Setting \a accepted to true prevents the wheel event from being
|
||||
propagated to items below this item.
|
||||
|
||||
Generally, if the item acts on the wheel event then it should be accepted
|
||||
so that items lower in the stacking order do not also respond to the same event.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty int QtQuick2::WheelEvent::buttons
|
||||
|
||||
This property holds the mouse buttons pressed when the wheel event was generated.
|
||||
|
||||
It contains a bitwise combination of:
|
||||
\list
|
||||
\o Qt.LeftButton
|
||||
\o Qt.RightButton
|
||||
\o Qt.MiddleButton
|
||||
\endlist
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty point QtQuick2::WheelEvent::angleDelta
|
||||
|
||||
This property holds the distance that the wheel is rotated in wheel degrees.
|
||||
The x and y cordinate of this property holds the delta in horizontal and
|
||||
vertical orientation.
|
||||
|
||||
A positive value indicates that the wheel was rotated up/right;
|
||||
a negative value indicates that the wheel was rotated down/left.
|
||||
|
||||
Most mouse types work in steps of 15 degrees, in which case the delta value is a
|
||||
multiple of 120; i.e., 120 units * 1/8 = 15 degrees.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty point QtQuick2::WheelEvent::pixelDelta
|
||||
|
||||
This property holds the delta in screen pixels and is available in plataforms that
|
||||
have high-resolution trackpads, such as Mac OS X.
|
||||
The x and y cordinate of this property holds the delta in horizontal and
|
||||
vertical orientation. The value should be used directly to scroll content on screen.
|
||||
|
||||
For platforms without high-resolution trackpad support, pixelDelta will always be (0,0),
|
||||
and angleDelta should be used instead.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty int QtQuick2::WheelEvent::modifiers
|
||||
|
||||
This property holds the keyboard modifier flags that existed immediately
|
||||
before the event occurred.
|
||||
|
||||
It contains a bitwise combination of:
|
||||
\list
|
||||
\o Qt.NoModifier - No modifier key is pressed.
|
||||
\o Qt.ShiftModifier - A Shift key on the keyboard is pressed.
|
||||
\o Qt.ControlModifier - A Ctrl key on the keyboard is pressed.
|
||||
\o Qt.AltModifier - An Alt key on the keyboard is pressed.
|
||||
\o Qt.MetaModifier - A Meta key on the keyboard is pressed.
|
||||
\o Qt.KeypadModifier - A keypad button is pressed.
|
||||
\endlist
|
||||
|
||||
For example, to react to a Control key pressed during the wheel event:
|
||||
\qml
|
||||
MouseArea {
|
||||
onWheel: {
|
||||
if (wheel.modifiers & Qt.ControlModifier) {
|
||||
if (wheel.angleDelta.y > 0)
|
||||
zoomIn();
|
||||
else
|
||||
zoomOut();
|
||||
}
|
||||
}
|
||||
}
|
||||
\endqml
|
||||
*/
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
@ -201,9 +201,47 @@ private:
|
|||
};
|
||||
|
||||
|
||||
class QQuickWheelEvent : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(qreal x READ x)
|
||||
Q_PROPERTY(qreal y READ y)
|
||||
Q_PROPERTY(QPoint angleDelta READ angleDelta)
|
||||
Q_PROPERTY(QPoint pixelDelta READ pixelDelta)
|
||||
Q_PROPERTY(int buttons READ buttons)
|
||||
Q_PROPERTY(int modifiers READ modifiers)
|
||||
Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted)
|
||||
|
||||
public:
|
||||
QQuickWheelEvent(qreal x, qreal y, const QPoint& angleDelta, const QPoint& pixelDelta,
|
||||
Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers)
|
||||
: _x(x), _y(y), _angleDelta(angleDelta), _pixelDelta(pixelDelta), _buttons(buttons),
|
||||
_modifiers(modifiers), _accepted(true) {}
|
||||
|
||||
qreal x() const { return _x; }
|
||||
qreal y() const { return _y; }
|
||||
QPoint angleDelta() const { return _angleDelta; }
|
||||
QPoint pixelDelta() const { return _pixelDelta; }
|
||||
int buttons() const { return _buttons; }
|
||||
int modifiers() const { return _modifiers; }
|
||||
|
||||
bool isAccepted() { return _accepted; }
|
||||
void setAccepted(bool accepted) { _accepted = accepted; }
|
||||
|
||||
private:
|
||||
qreal _x;
|
||||
qreal _y;
|
||||
QPoint _angleDelta;
|
||||
QPoint _pixelDelta;
|
||||
Qt::MouseButtons _buttons;
|
||||
Qt::KeyboardModifiers _modifiers;
|
||||
bool _accepted;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
QML_DECLARE_TYPE(QQuickKeyEvent)
|
||||
QML_DECLARE_TYPE(QQuickMouseEvent)
|
||||
QML_DECLARE_TYPE(QQuickWheelEvent)
|
||||
|
||||
#endif // QQUICKEVENTS_P_P_H
|
||||
|
|
|
@ -169,6 +169,7 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor)
|
|||
qmlRegisterType<QQuickAnchors>();
|
||||
qmlRegisterType<QQuickKeyEvent>();
|
||||
qmlRegisterType<QQuickMouseEvent>();
|
||||
qmlRegisterType<QQuickWheelEvent>();
|
||||
qmlRegisterType<QQuickTransform>();
|
||||
qmlRegisterType<QQuickPathElement>();
|
||||
qmlRegisterType<QQuickCurve>();
|
||||
|
|
|
@ -236,6 +236,13 @@ bool QQuickMouseAreaPrivate::isClickConnected()
|
|||
return QObjectPrivate::get(q)->isSignalConnected(idx);
|
||||
}
|
||||
|
||||
bool QQuickMouseAreaPrivate::isWheelConnected()
|
||||
{
|
||||
Q_Q(QQuickMouseArea);
|
||||
static int idx = QObjectPrivate::get(q)->signalIndex("wheel(QQuickWheelEvent*)");
|
||||
return QObjectPrivate::get(q)->isSignalConnected(idx);
|
||||
}
|
||||
|
||||
void QQuickMouseAreaPrivate::propagate(QQuickMouseEvent* event, PropagateType t)
|
||||
{
|
||||
Q_Q(QQuickMouseArea);
|
||||
|
@ -331,7 +338,8 @@ bool QQuickMouseAreaPrivate::propagateHelper(QQuickMouseEvent *ev, QQuickItem *i
|
|||
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.
|
||||
onPressed, onReleased and onPressAndHold. It's also possible to handle mouse
|
||||
wheel events via the onWheel signal.
|
||||
|
||||
By default, MouseArea items only report mouse clicks and not changes to the
|
||||
position of the mouse cursor. Setting the hoverEnabled property ensures that
|
||||
|
@ -513,6 +521,17 @@ bool QQuickMouseAreaPrivate::propagateHelper(QQuickMouseEvent *ev, QQuickItem *i
|
|||
the logic when the MouseArea has lost the mouse handling to the \l Flickable,
|
||||
\c onCanceled should be used in addition to onReleased.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlsignal QtQuick2::MouseArea::onWheel(WheelEvent mouse)
|
||||
|
||||
This handler is called 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
|
||||
position, any buttons currently pressed, and information about the wheel movement, including
|
||||
angleDelta and pixelDelta.
|
||||
*/
|
||||
|
||||
QQuickMouseArea::QQuickMouseArea(QQuickItem *parent)
|
||||
: QQuickItem(*(new QQuickMouseAreaPrivate), parent)
|
||||
{
|
||||
|
@ -860,6 +879,22 @@ void QQuickMouseArea::hoverLeaveEvent(QHoverEvent *event)
|
|||
setHovered(false);
|
||||
}
|
||||
|
||||
void QQuickMouseArea::wheelEvent(QWheelEvent *event)
|
||||
{
|
||||
Q_D(QQuickMouseArea);
|
||||
if (!d->absorb) {
|
||||
QQuickItem::wheelEvent(event);
|
||||
return;
|
||||
}
|
||||
|
||||
QQuickWheelEvent we(event->posF().x(), event->posF().y(), event->angleDelta(),
|
||||
event->pixelDelta(), event->buttons(), event->modifiers());
|
||||
we.setAccepted(d->isWheelConnected());
|
||||
emit wheel(&we);
|
||||
if (!we.isAccepted())
|
||||
QQuickItem::wheelEvent(event);
|
||||
}
|
||||
|
||||
void QQuickMouseArea::ungrabMouse()
|
||||
{
|
||||
Q_D(QQuickMouseArea);
|
||||
|
|
|
@ -119,6 +119,7 @@ private:
|
|||
};
|
||||
|
||||
class QQuickMouseAreaPrivate;
|
||||
class QQuickWheelEvent;
|
||||
// used in QtLocation
|
||||
class Q_QUICK_EXPORT QQuickMouseArea : public QQuickItem
|
||||
{
|
||||
|
@ -182,6 +183,7 @@ Q_SIGNALS:
|
|||
void released(QQuickMouseEvent *mouse);
|
||||
void clicked(QQuickMouseEvent *mouse);
|
||||
void doubleClicked(QQuickMouseEvent *mouse);
|
||||
void wheel(QQuickWheelEvent *wheel);
|
||||
void entered();
|
||||
void exited();
|
||||
void canceled();
|
||||
|
@ -199,6 +201,7 @@ protected:
|
|||
virtual void hoverEnterEvent(QHoverEvent *event);
|
||||
virtual void hoverMoveEvent(QHoverEvent *event);
|
||||
virtual void hoverLeaveEvent(QHoverEvent *event);
|
||||
virtual void wheelEvent(QWheelEvent *event);
|
||||
virtual bool childMouseEventFilter(QQuickItem *i, QEvent *e);
|
||||
virtual void timerEvent(QTimerEvent *event);
|
||||
virtual void windowDeactivateEvent();
|
||||
|
|
|
@ -83,6 +83,7 @@ public:
|
|||
bool isPressAndHoldConnected();
|
||||
bool isDoubleClickConnected();
|
||||
bool isClickConnected();
|
||||
bool isWheelConnected();
|
||||
|
||||
bool absorb : 1;
|
||||
bool hovered : 1;
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
import QtQuick 2.0
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
|
||||
property var angleDeltaY
|
||||
property real mouseX
|
||||
property real mouseY
|
||||
property bool controlPressed
|
||||
|
||||
width: 400
|
||||
height: 400
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
|
||||
onWheel: {
|
||||
root.angleDeltaY = wheel.angleDelta.y;
|
||||
root.mouseX = wheel.x;
|
||||
root.mouseY = wheel.y;
|
||||
root.controlPressed = wheel.modifiers & Qt.ControlModifier;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -73,6 +73,7 @@ private slots:
|
|||
void hoverPropagation();
|
||||
void hoverVisible();
|
||||
void disableAfterPress();
|
||||
void onWheel();
|
||||
|
||||
private:
|
||||
QQuickView *createView();
|
||||
|
@ -906,6 +907,26 @@ void tst_QQuickMouseArea::disableAfterPress()
|
|||
delete canvas;
|
||||
}
|
||||
|
||||
void tst_QQuickMouseArea::onWheel()
|
||||
{
|
||||
QQuickView *canvas = createView();
|
||||
canvas->setSource(testFileUrl("wheel.qml"));
|
||||
|
||||
QQuickItem *root = canvas->rootObject();
|
||||
QVERIFY(root != 0);
|
||||
|
||||
QWheelEvent wheelEvent(QPoint(10, 32), QPoint(10, 32), QPoint(60, 20), QPoint(0, 120),
|
||||
0, Qt::Vertical,Qt::NoButton, Qt::ControlModifier);
|
||||
QGuiApplication::sendEvent(canvas, &wheelEvent);
|
||||
|
||||
QCOMPARE(root->property("angleDeltaY").toInt(), 120);
|
||||
QCOMPARE(root->property("mouseX").toReal(), qreal(10));
|
||||
QCOMPARE(root->property("mouseY").toReal(), qreal(32));
|
||||
QCOMPARE(root->property("controlPressed").toBool(), true);
|
||||
|
||||
delete canvas;
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QQuickMouseArea)
|
||||
|
||||
#include "tst_qquickmousearea.moc"
|
||||
|
|
Loading…
Reference in New Issue