Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qquickwheelhandler.cpp
Go to the documentation of this file.
1// Copyright (C) 2020 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
7#include <QtQuick/private/qquickitem_p.h>
8#include <QLoggingCategory>
9#include <QtMath>
10
12
13Q_STATIC_LOGGING_CATEGORY(lcWheelHandler, "qt.quick.handler.wheel")
14
15/*!
16 \qmltype WheelHandler
17 \nativetype QQuickWheelHandler
18 \inherits SinglePointHandler
19 \inqmlmodule QtQuick
20 \ingroup qtquick-input-handlers
21 \brief Handler for the mouse wheel.
22
23 WheelHandler is a handler that is used to interactively manipulate some
24 numeric property of an Item as the user rotates the mouse wheel. Like other
25 Input Handlers, by default it manipulates its \l {PointerHandler::target}
26 {target}. Declare \l property to control which target property will be
27 manipulated:
28
29 \snippet pointerHandlers/wheelHandler.qml 0
30
31 \l BoundaryRule is quite useful in combination with WheelHandler (as well
32 as with other Input Handlers) to declare the allowed range of values that
33 the target property can have. For example it is possible to implement
34 scrolling using a combination of WheelHandler and \l DragHandler to
35 manipulate the scrollable Item's \l{QQuickItem::y}{y} property when the
36 user rotates the wheel or drags the item on a touchscreen, and
37 \l BoundaryRule to limit the range of motion from the top to the bottom:
38
39 \snippet pointerHandlers/handlerFlick.qml 0
40
41 Alternatively, if \l property is not set or \l target is null,
42 WheelHandler will not automatically manipulate anything; but the
43 \l rotation property can be used in a binding to manipulate another
44 property, or you can implement \c onWheel and handle the wheel event
45 directly.
46
47 By default, WheelHandler handles \l {QWheelEvent}{wheel events}
48 from a rotating mouse wheel, or virtual "wheel" events from a touchpad.
49 This can be changed by setting \l acceptedDevices.
50
51 \sa MouseArea, Flickable, {Qt Quick Examples - Pointer Handlers}
52*/
53
54QQuickWheelHandler::QQuickWheelHandler(QQuickItem *parent)
55 : QQuickSinglePointHandler(*(new QQuickWheelHandlerPrivate), parent)
56{
57 setAcceptedDevices(QInputDevice::DeviceType::Mouse | QInputDevice::DeviceType::TouchPad);
58}
59
60/*!
61 \qmlproperty enumeration QtQuick::WheelHandler::orientation
62
63 Which wheel to react to. The default is \c Qt.Vertical.
64
65 Not every mouse has a \c Horizontal wheel; sometimes it is emulated by
66 tilting the wheel sideways. A touchpad can usually generate both vertical
67 and horizontal wheel events.
68*/
69Qt::Orientation QQuickWheelHandler::orientation() const
70{
71 Q_D(const QQuickWheelHandler);
72 return d->orientation;
73}
74
75void QQuickWheelHandler::setOrientation(Qt::Orientation orientation)
76{
77 Q_D(QQuickWheelHandler);
78 if (d->orientation == orientation)
79 return;
80
81 d->orientation = orientation;
82 emit orientationChanged();
83}
84
85/*!
86 \qmlproperty bool QtQuick::WheelHandler::invertible
87
88 Whether or not to reverse the direction of property change if
89 \l QWheelEvent::inverted is \c true. The default is \c true.
90
91 If the operating system has a "natural scrolling" setting that causes
92 scrolling to be in the same direction as the finger movement, then if this
93 property is set to \c true, and WheelHandler is directly setting a property
94 on \l target, the direction of movement will correspond to the system setting.
95 If this property is set to \c false, it will invert the \l rotation so that
96 the direction of motion is always the same as the direction of finger movement.
97*/
98bool QQuickWheelHandler::isInvertible() const
99{
100 Q_D(const QQuickWheelHandler);
101 return d->invertible;
102}
103
104void QQuickWheelHandler::setInvertible(bool invertible)
105{
106 Q_D(QQuickWheelHandler);
107 if (d->invertible == invertible)
108 return;
109
110 d->invertible = invertible;
111 emit invertibleChanged();
112}
113
114/*!
115 \qmlproperty real QtQuick::WheelHandler::activeTimeout
116
117 The amount of time in seconds after which the \l active property will
118 revert to \c false if no more wheel events are received. The default is
119 \c 0.1 (100 ms).
120
121 When WheelHandler handles events that contain
122 \l {Qt::ScrollPhase}{scroll phase} information, such as events from some
123 touchpads, the \l active property will become \c false as soon as an event
124 with phase \l Qt::ScrollEnd is received; in that case the timeout is not
125 necessary. But a conventional mouse with a wheel does not provide a scroll
126 phase: the mouse cannot detect when the user has decided to stop
127 scrolling, so the \l active property transitions to \c false after this
128 much time has elapsed.
129
130 \sa QWheelEvent::phase()
131*/
132qreal QQuickWheelHandler::activeTimeout() const
133{
134 Q_D(const QQuickWheelHandler);
135 return d->activeTimeout;
136}
137
138void QQuickWheelHandler::setActiveTimeout(qreal timeout)
139{
140 Q_D(QQuickWheelHandler);
141 if (qFuzzyCompare(d->activeTimeout, timeout))
142 return;
143
144 if (timeout < 0) {
145 qWarning("activeTimeout must be positive");
146 return;
147 }
148
149 d->activeTimeout = timeout;
150 emit activeTimeoutChanged();
151}
152
153/*!
154 \qmlproperty real QtQuick::WheelHandler::rotation
155
156 The angle through which the mouse wheel has been rotated since the last
157 time this property was set, in wheel degrees.
158
159 A positive value indicates that the wheel was rotated up/right;
160 a negative value indicates that the wheel was rotated down/left.
161
162 A basic mouse click-wheel works in steps of 15 degrees.
163
164 The default is \c 0 at startup. It can be programmatically set to any value
165 at any time. The value will be adjusted from there as the user rotates the
166 mouse wheel.
167
168 \sa orientation
169*/
170qreal QQuickWheelHandler::rotation() const
171{
172 Q_D(const QQuickWheelHandler);
173 return d->rotation * d->rotationScale;
174}
175
176void QQuickWheelHandler::setRotation(qreal rotation)
177{
178 Q_D(QQuickWheelHandler);
179 if (qFuzzyCompare(d->rotation, rotation / d->rotationScale))
180 return;
181
182 d->rotation = rotation / d->rotationScale;
183 emit rotationChanged();
184}
185
186/*!
187 \qmlproperty real QtQuick::WheelHandler::rotationScale
188
189 The scaling to be applied to the \l rotation property, and to the
190 \l property on the \l target item, if any. The default is 1, such that
191 \l rotation will be in units of degrees of rotation. It can be set to a
192 negative number to invert the effect of the direction of mouse wheel
193 rotation.
194*/
195qreal QQuickWheelHandler::rotationScale() const
196{
197 Q_D(const QQuickWheelHandler);
198 return d->rotationScale;
199}
200
201void QQuickWheelHandler::setRotationScale(qreal rotationScale)
202{
203 Q_D(QQuickWheelHandler);
204 if (qFuzzyCompare(d->rotationScale, rotationScale))
205 return;
206 if (qFuzzyIsNull(rotationScale)) {
207 qWarning("rotationScale cannot be set to zero");
208 return;
209 }
210
211 d->rotationScale = rotationScale;
212 emit rotationScaleChanged();
213}
214
215/*!
216 \qmlproperty string QtQuick::WheelHandler::property
217
218 The property to be modified on the \l target when the mouse wheel is rotated.
219
220 The default is no property (empty string). When no target property is being
221 automatically modified, you can use bindings to react to mouse wheel
222 rotation in arbitrary ways.
223
224 You can use the mouse wheel to adjust any numeric property. For example if
225 \c property is set to \c x, the \l target will move horizontally as the
226 wheel is rotated. The following properties have special behavior:
227
228 \value scale
229 \l{QQuickItem::scale}{scale} will be modified in a non-linear fashion
230 as described under \l targetScaleMultiplier. If
231 \l targetTransformAroundCursor is \c true, the \l{QQuickItem::x}{x} and
232 \l{QQuickItem::y}{y} properties will be simultaneously adjusted so that
233 the user will effectively zoom into or out of the point under the mouse
234 cursor.
235 \value rotation
236 \l{QQuickItem::rotation}{rotation} will be set to \l rotation. If
237 \l targetTransformAroundCursor is \c true, the l{QQuickItem::x}{x} and
238 \l{QQuickItem::y}{y} properties will be simultaneously adjusted so
239 that the user will effectively rotate the item around the point under
240 the mouse cursor.
241
242 The adjustment of the given target property is always scaled by \l rotationScale.
243*/
244QString QQuickWheelHandler::property() const
245{
246 Q_D(const QQuickWheelHandler);
247 return d->propertyName;
248}
249
250void QQuickWheelHandler::setProperty(const QString &propertyName)
251{
252 Q_D(QQuickWheelHandler);
253 if (d->propertyName == propertyName)
254 return;
255
256 d->propertyName = propertyName;
257 d->metaPropertyDirty = true;
258 emit propertyChanged();
259}
260
261/*!
262 \qmlproperty real QtQuick::WheelHandler::targetScaleMultiplier
263
264 The amount by which the \l target \l{QQuickItem::scale}{scale} is to be
265 multiplied whenever the \l rotation changes by 15 degrees. This
266 is relevant only when \l property is \c "scale".
267
268 The \c scale will be multiplied by
269 \c targetScaleMultiplier \sup {angleDelta * rotationScale / 15}.
270 The default is \c 2 \sup {1/3}, which means that if \l rotationScale is left
271 at its default value, and the mouse wheel is rotated by one "click"
272 (15 degrees), the \l target will be scaled by approximately 1.25; after
273 three "clicks" its size will be doubled or halved, depending on the
274 direction that the wheel is rotated. If you want to make it double or halve
275 with every 2 clicks of the wheel, set this to \c 2 \sup {1/2} (1.4142).
276 If you want to make it scale the opposite way as the wheel is rotated,
277 set \c rotationScale to a negative value.
278*/
279qreal QQuickWheelHandler::targetScaleMultiplier() const
280{
281 Q_D(const QQuickWheelHandler);
282 return d->targetScaleMultiplier;
283}
284
285void QQuickWheelHandler::setTargetScaleMultiplier(qreal targetScaleMultiplier)
286{
287 Q_D(QQuickWheelHandler);
288 if (qFuzzyCompare(d->targetScaleMultiplier, targetScaleMultiplier))
289 return;
290
291 d->targetScaleMultiplier = targetScaleMultiplier;
292 emit targetScaleMultiplierChanged();
293}
294
295/*!
296 \qmlproperty bool QtQuick::WheelHandler::targetTransformAroundCursor
297
298 Whether the \l target should automatically be repositioned in such a way
299 that it is transformed around the mouse cursor position while the
300 \l property is adjusted. The default is \c true.
301
302 If \l property is set to \c "rotation" and \l targetTransformAroundCursor
303 is \c true, then as the wheel is rotated, the \l target item will rotate in
304 place around the mouse cursor position. If \c targetTransformAroundCursor
305 is \c false, it will rotate around its
306 \l{QQuickItem::transformOrigin}{transformOrigin} instead.
307*/
308bool QQuickWheelHandler::isTargetTransformAroundCursor() const
309{
310 Q_D(const QQuickWheelHandler);
311 return d->targetTransformAroundCursor;
312}
313
314void QQuickWheelHandler::setTargetTransformAroundCursor(bool ttac)
315{
316 Q_D(QQuickWheelHandler);
317 if (d->targetTransformAroundCursor == ttac)
318 return;
319
320 d->targetTransformAroundCursor = ttac;
321 emit targetTransformAroundCursorChanged();
322}
323
324/*!
325 \qmlproperty bool QtQuick::WheelHandler::blocking
326 \since 6.3
327
328 Whether this handler prevents other items or handlers behind it from
329 handling the same wheel event. This property is \c true by default.
330*/
331bool QQuickWheelHandler::isBlocking() const
332{
333 Q_D(const QQuickWheelHandler);
334 return d->blocking;
335}
336
337void QQuickWheelHandler::setBlocking(bool blocking)
338{
339 Q_D(QQuickWheelHandler);
340 if (d->blocking == blocking)
341 return;
342
343 d->blocking = blocking;
344 emit blockingChanged();
345}
346
347bool QQuickWheelHandler::wantsPointerEvent(QPointerEvent *event)
348{
349 if (!event)
350 return false;
351 if (event->type() != QEvent::Wheel)
352 return false;
353 QWheelEvent *we = static_cast<QWheelEvent *>(event);
354 if (!acceptedDevices().testFlag(QPointingDevice::DeviceType::TouchPad)
355 && we->source() != Qt::MouseEventNotSynthesized)
356 return false;
357 if (!active()) {
358 switch (orientation()) {
359 case Qt::Horizontal:
360 if (!(we->angleDelta().x()) && !(we->pixelDelta().x()))
361 return false;
362 break;
363 case Qt::Vertical:
364 if (!(we->angleDelta().y()) && !(we->pixelDelta().y()))
365 return false;
366 break;
367 }
368 }
369 auto &point = event->point(0);
370 if (QQuickPointerDeviceHandler::wantsPointerEvent(event) && wantsEventPoint(event, point) && parentContains(point)) {
371 setPointId(point.id());
372 return true;
373 }
374 return false;
375}
376
377void QQuickWheelHandler::handleEventPoint(QPointerEvent *ev, QEventPoint &point)
378{
379 Q_D(QQuickWheelHandler);
380 QQuickSinglePointHandler::handleEventPoint(ev, point);
381
382 if (ev->type() != QEvent::Wheel)
383 return;
384 const QWheelEvent *event = static_cast<const QWheelEvent *>(ev);
385 setActive(true); // ScrollEnd will not happen unless it was already active (see setActive(false) below)
386 if (d->blocking)
387 point.setAccepted();
388 qreal inversion = !d->invertible && event->isInverted() ? -1 : 1;
389 qreal angleDelta = inversion * qreal(orientation() == Qt::Horizontal ? event->angleDelta().x() :
390 event->angleDelta().y()) / 8;
391 d->rotation += angleDelta;
392 emit rotationChanged();
393
394 d->wheelEvent.reset(event);
395 emit wheel(&d->wheelEvent);
396 if (!d->propertyName.isEmpty() && target()) {
397 QQuickItem *t = target();
398 // writing target()'s property is done via QMetaProperty::write() so that any registered interceptors can react.
399 if (d->propertyName == QLatin1String("scale")) {
400 qreal multiplier = qPow(d->targetScaleMultiplier, angleDelta * d->rotationScale / 15); // wheel "clicks"
401 const QPointF centroidParentPos = t->parentItem()->mapFromScene(point.scenePosition());
402 const QPointF positionWas = t->position();
403 const qreal scaleWas = t->scale();
404 const qreal activePropertyValue = scaleWas * multiplier;
405 qCDebug(lcWheelHandler) << objectName() << "angle delta" << event->angleDelta() << "pixel delta" << event->pixelDelta()
406 << "@" << point.position() << "in parent" << centroidParentPos
407 << "in scene" << point.scenePosition()
408 << "multiplier" << multiplier << "scale" << scaleWas
409 << "->" << activePropertyValue;
410 d->targetMetaProperty().write(t, activePropertyValue);
411 if (d->targetTransformAroundCursor) {
412 // If an interceptor intervened, scale may now be different than we asked for. Adjust accordingly.
413 multiplier = t->scale() / scaleWas;
414 const QPointF adjPos = QQuickItemPrivate::get(t)->adjustedPosForTransform(
415 centroidParentPos, positionWas, QVector2D(), scaleWas, multiplier, t->rotation(), 0);
416 qCDebug(lcWheelHandler) << "adjusting item pos" << adjPos << "in scene" << t->parentItem()->mapToScene(adjPos);
417 t->setPosition(adjPos);
418 }
419 } else if (d->propertyName == QLatin1String("rotation")) {
420 const QPointF positionWas = t->position();
421 const qreal rotationWas = t->rotation();
422 const qreal activePropertyValue = rotationWas + angleDelta * d->rotationScale;
423 const QPointF centroidParentPos = t->parentItem()->mapFromScene(point.scenePosition());
424 qCDebug(lcWheelHandler) << objectName() << "angle delta" << event->angleDelta() << "pixel delta" << event->pixelDelta()
425 << "@" << point.position() << "in parent" << centroidParentPos
426 << "in scene" << point.scenePosition() << "rotation" << t->rotation()
427 << "->" << activePropertyValue;
428 d->targetMetaProperty().write(t, activePropertyValue);
429 if (d->targetTransformAroundCursor) {
430 // If an interceptor intervened, rotation may now be different than we asked for. Adjust accordingly.
431 const QPointF adjPos = QQuickItemPrivate::get(t)->adjustedPosForTransform(
432 centroidParentPos, positionWas, QVector2D(),
433 t->scale(), 1, rotationWas, t->rotation() - rotationWas);
434 qCDebug(lcWheelHandler) << "adjusting item pos" << adjPos << "in scene" << t->parentItem()->mapToScene(adjPos);
435 t->setPosition(adjPos);
436 }
437 } else {
438 qCDebug(lcWheelHandler) << objectName() << "angle delta" << event->angleDelta() << "scaled" << angleDelta
439 << "total" << d->rotation << "pixel delta" << event->pixelDelta()
440 << "@" << point.position() << "in scene" << point.scenePosition() << "rotation" << t->rotation();
441 qreal delta = 0;
442 if (event->hasPixelDelta()) {
443 delta = inversion * d->rotationScale * qreal(orientation() == Qt::Horizontal ? event->pixelDelta().x() : event->pixelDelta().y());
444 qCDebug(lcWheelHandler) << "changing target" << d->propertyName << "by pixel delta" << delta << "from" << event;
445 } else {
446 delta = angleDelta * d->rotationScale;
447 qCDebug(lcWheelHandler) << "changing target" << d->propertyName << "by scaled angle delta" << delta << "from" << event;
448 }
449 bool ok = false;
450 qreal value = d->targetMetaProperty().read(t).toReal(&ok);
451 if (ok)
452 d->targetMetaProperty().write(t, value + qreal(delta));
453 else
454 qWarning() << "failed to read property" << d->propertyName << "of" << t;
455 }
456 }
457 switch (event->phase()) {
458 case Qt::ScrollEnd:
459 qCDebug(lcWheelHandler) << objectName() << "deactivating due to ScrollEnd phase";
460 setActive(false);
461 break;
462 case Qt::NoScrollPhase:
463 d->deactivationTimer.start(qRound(d->activeTimeout * 1000), this);
464 break;
465 case Qt::ScrollBegin:
466 case Qt::ScrollUpdate:
467 case Qt::ScrollMomentum:
468 break;
469 }
470}
471
472void QQuickWheelHandler::onTargetChanged(QQuickItem *oldTarget)
473{
474 Q_UNUSED(oldTarget);
475 Q_D(QQuickWheelHandler);
476 d->metaPropertyDirty = true;
477}
478
479void QQuickWheelHandler::onActiveChanged()
480{
481 Q_D(QQuickWheelHandler);
482 if (!active())
483 d->deactivationTimer.stop();
484}
485
486void QQuickWheelHandler::timerEvent(QTimerEvent *event)
487{
488 Q_D(const QQuickWheelHandler);
489 if (event->timerId() == d->deactivationTimer.timerId()) {
490 qCDebug(lcWheelHandler) << objectName() << "deactivating due to timeout";
491 setActive(false);
492 }
493}
494
495/*!
496 \qmlsignal QtQuick::WheelHandler::wheel(WheelEvent event)
497
498 This signal is emitted every time this handler receives an \a event
499 of type \l QWheelEvent: that is, every time the wheel is moved or the
500 scrolling gesture is updated.
501*/
502
503QQuickWheelHandlerPrivate::QQuickWheelHandlerPrivate()
504 : QQuickSinglePointHandlerPrivate()
505{
506}
507
508QMetaProperty &QQuickWheelHandlerPrivate::targetMetaProperty() const
509{
510 Q_Q(const QQuickWheelHandler);
511 if (metaPropertyDirty && q->target()) {
512 if (!propertyName.isEmpty()) {
513 const QMetaObject *targetMeta = q->target()->metaObject();
514 metaProperty = targetMeta->property(
515 targetMeta->indexOfProperty(propertyName.toLocal8Bit().constData()));
516 }
517 metaPropertyDirty = false;
518 }
519 return metaProperty;
520}
521
522/*! \internal
523 \qmlproperty flags QtQuick::WheelHandler::acceptedButtons
524
525 This overrides QtQuick::PointerDeviceHandler::acceptedButtons
526 and hides it from the documentation as the property is not relevant for
527 WheelHandler.
528*/
529
530/*!
531 \qmlproperty flags QtQuick::WheelHandler::acceptedDevices
532
533 The types of pointing devices that can activate this handler.
534
535 By default, since 6.13 this property is set to
536 \l{QInputDevice::DeviceType}{PointerDevice.Mouse | PointerDevice.TouchPad}.
537
538 \note In prior versions of Qt, the default was
539 \l{QInputDevice::DeviceType}{PointerDevice.Mouse}, so as to react only to
540 events from an actual mouse wheel. Old behavior can be restored by
541 setting it that way again.
542*/
543
544/*!
545 \qmlproperty flags QtQuick::WheelHandler::acceptedModifiers
546
547 If this property is set, it will require the given keyboard modifiers to
548 be pressed in order to react to wheel events, and otherwise ignore them.
549
550 If this property is set to \c Qt.KeyboardModifierMask (the default value),
551 the WheelHandler ignores the modifier keys.
552
553 For example, an \l [QML] Item could have two handlers, one of which is
554 enabled only if the required keyboard modifier is pressed, while the other
555 ignores events if any modifier is pressed:
556
557 \snippet pointerHandlers/wheelHandlerAcceptedModifiers.qml entire
558
559 The available modifiers are as follows:
560
561 \value NoModifier No modifier key is allowed.
562 \value ShiftModifier A Shift key on the keyboard must be pressed.
563 \value ControlModifier A Ctrl key on the keyboard must be pressed.
564 \value AltModifier An Alt key on the keyboard must be pressed.
565 \value MetaModifier A Meta key on the keyboard must be pressed.
566 \value KeypadModifier A keypad button must be pressed.
567 \value GroupSwitchModifier X11 only (unless activated on Windows by a command line argument).
568 A Mode_switch key on the keyboard must be pressed.
569 \value KeyboardModifierMask The handler does not care which modifiers are pressed.
570
571 \sa Qt::KeyboardModifier
572*/
573
574/*! \internal
575 \qmlproperty flags QtQuick::WheelHandler::acceptedPointerTypes
576
577 This overrides QtQuick::PointerDeviceHandler::acceptedPointerTypes
578 and hides it from the documentation as the property is not relevant for
579 WheelHandler.
580*/
581
582/*!
583 \readonly
584 \qmlproperty bool QtQuick::WheelHandler::active
585
586 This holds \c true whenever the WheelHandler has recently seen a
587 QWheelEvent, is keeping its properties up-to-date, and actively manipulating
588 its \l target (if any).
589
590 \sa activeTimeout
591*/
592
593/*! \internal
594 \qmlproperty flags QtQuick::WheelHandler::cursorShape
595
596 This overrides QtQuick::PointerHandler::cursorShape
597 and hides it from the documentation as the property is not relevant for
598 WheelHandler.
599*/
600
601/*! \internal
602 \qmlproperty flags QtQuick::WheelHandler::dragThreshold
603
604 This overrides QtQuick::PointerHandler::dragThreshold
605 and hides it from the documentation as the property is not relevant for
606 WheelHandler.
607*/
608
609/*! \internal
610 \qmlproperty flags QtQuick::WheelHandler::grabPermissions
611
612 This overrides QtQuick::PointerHandler::grabPermissions
613 and hides it from the documentation as the property is not relevant for
614 WheelHandler.
615*/
616
617/*!
618 \qmlproperty real QtQuick::WheelHandler::margin
619
620 The margin beyond the bounds of the \l {PointerHandler::parent}{parent}
621 item within which the WheelHandler can react. For example if \c margin
622 is set to \c 10, you could place the cursor up to 10 pixels outside the
623 visible edge of the item, and it will still react to the wheel:
624
625 \snippet pointerHandlers/wheelHandlerMargin.qml entire
626
627 The default value is \c 0.
628*/
629
630/*! \internal
631 \qmlsignal QtQuick::WheelHandler::grabChanged(PointerDevice::GrabTransition transition, eventPoint point)
632
633 This overrides QtQuick::PointerHandler::grabChanged
634 and hides it from the documentation as the signal is not relevant for
635 WheelHandler.
636*/
637
638/*! \internal
639 \qmlsignal QtQuick::WheelHandler::canceled(eventPoint point)
640
641 This overrides QtQuick::PointerHandler::canceled
642 and hides it from the documentation as the signal is not relevant for
643 WheelHandler.
644*/
645
646QT_END_NAMESPACE
647
648#include "moc_qquickwheelhandler_p.cpp"
Combined button and popup list for selecting options.