316QGestureRecognizer::Result QFlickGestureRecognizer::recognize(QGesture *state,
322 Q_CONSTINIT
static QElapsedTimer monotonicTimer;
323 if (!monotonicTimer.isValid())
324 monotonicTimer.start();
326 QFlickGesture *q =
static_cast<QFlickGesture *>(state);
327 QFlickGesturePrivate *d = q->d_func();
329 QScroller *scroller = d->receiverScroller;
333 QWidget *receiverWidget = qobject_cast<QWidget *>(d->receiver);
334#if QT_CONFIG(graphicsview)
335 QGraphicsObject *receiverGraphicsObject = qobject_cast<QGraphicsObject *>(d->receiver);
339 if (PressDelayHandler::instance()->shouldEventBeIgnored(event)) {
344 const QMouseEvent *me =
nullptr;
345#if QT_CONFIG(graphicsview)
346 const QGraphicsSceneMouseEvent *gsme =
nullptr;
348 const QTouchEvent *te =
nullptr;
353 Qt::KeyboardModifiers keyboardModifiers = Qt::NoModifier;
354 Qt::MouseButtons mouseButtons = Qt::NoButton;
355 switch (event->type()) {
356 case QEvent::MouseButtonPress:
357 case QEvent::MouseButtonRelease:
358 case QEvent::MouseMove:
361 if (button != Qt::NoButton) {
362 me =
static_cast<
const QMouseEvent *>(event);
363 keyboardModifiers = me->modifiers();
364 mouseButtons = me->buttons();
365 globalPos = me->globalPosition().toPoint();
368#if QT_CONFIG(graphicsview)
369 case QEvent::GraphicsSceneMousePress:
370 case QEvent::GraphicsSceneMouseRelease:
371 case QEvent::GraphicsSceneMouseMove:
372 if (!receiverGraphicsObject)
374 if (button != Qt::NoButton) {
375 gsme =
static_cast<
const QGraphicsSceneMouseEvent *>(event);
376 keyboardModifiers = gsme->modifiers();
377 mouseButtons = gsme->buttons();
378 globalPos = gsme->screenPos();
382 case QEvent::TouchBegin:
383 case QEvent::TouchEnd:
384 case QEvent::TouchUpdate:
385 if (button == Qt::NoButton) {
386 te =
static_cast<
const QTouchEvent *>(event);
387 keyboardModifiers = te->modifiers();
388 if (!te->points().isEmpty())
389 globalPos = te->points().at(0).globalPosition().toPoint();
395 if (d->macIgnoreWheel || (scroller->state() != QScroller::Inactive))
396 return Ignore | ConsumeEventHint;
400 case QEvent::MouseButtonDblClick:
401 if (scroller->state() != QScroller::Inactive)
402 return Ignore | ConsumeEventHint;
410#if QT_CONFIG(graphicsview)
418 QScroller::Input inputType = (QScroller::Input) 0;
420 switch (event->type()) {
421 case QEvent::MouseButtonPress:
422 if (me && me->button() == button && me->buttons() == button) {
423 point = me->globalPosition().toPoint();
424 inputType = QScroller::InputPress;
427 return CancelGesture;
430 case QEvent::MouseButtonRelease:
431 if (me && me->button() == button) {
432 point = me->globalPosition().toPoint();
433 inputType = QScroller::InputRelease;
436 case QEvent::MouseMove:
437 if (me && me->buttons() == button) {
438 point = me->globalPosition().toPoint();
439 inputType = QScroller::InputMove;
443#if QT_CONFIG(graphicsview)
444 case QEvent::GraphicsSceneMousePress:
445 if (gsme && gsme->button() == button && gsme->buttons() == button) {
446 point = gsme->scenePos();
447 inputType = QScroller::InputPress;
450 return CancelGesture;
453 case QEvent::GraphicsSceneMouseRelease:
454 if (gsme && gsme->button() == button) {
455 point = gsme->scenePos();
456 inputType = QScroller::InputRelease;
459 case QEvent::GraphicsSceneMouseMove:
460 if (gsme && gsme->buttons() == button) {
461 point = gsme->scenePos();
462 inputType = QScroller::InputMove;
467 case QEvent::TouchBegin:
468 inputType = QScroller::InputPress;
470 case QEvent::TouchEnd:
472 inputType = QScroller::InputRelease;
474 case QEvent::TouchUpdate:
476 inputType = QScroller::InputMove;
478 if (te->pointingDevice()->type() == QInputDevice::DeviceType::TouchPad) {
479 if (te->points().size() != 2)
482 point = te->points().at(0).scenePressPosition() +
483 ((te->points().at(0).scenePosition() - te->points().at(0).scenePressPosition()) +
484 (te->points().at(1).scenePosition() - te->points().at(1).scenePressPosition())) / 2;
486 if (te->points().size() != 1)
489 point = te->points().at(0).scenePosition();
498 if (inputType == QScroller::InputPress) {
499 const auto activeScrollers = QScroller::activeScrollers();
500 for (QScroller *as : activeScrollers) {
501 if (as != scroller) {
502 QRegion scrollerRegion;
504 if (QWidget *w = qobject_cast<QWidget *>(as->target())) {
505 scrollerRegion = QRect(w->mapToGlobal(QPoint(0, 0)), w->size());
506#if QT_CONFIG(graphicsview)
507 }
else if (QGraphicsObject *go = qobject_cast<QGraphicsObject *>(as->target())) {
508 if (
const auto *scene = go->scene()) {
509 const auto goBoundingRectMappedToScene = go->mapToScene(go->boundingRect());
510 const auto views = scene->views();
511 for (QGraphicsView *gv : views) {
512 scrollerRegion |= gv->mapFromScene(goBoundingRectMappedToScene)
513 .translated(gv->mapToGlobal(QPoint(0, 0)));
519 if (scrollerRegion.contains(globalPos))
525 bool scrollerWasDragging = (scroller->state() == QScroller::Dragging);
526 bool scrollerWasScrolling = (scroller->state() == QScroller::Scrolling);
529 if (QWidget *w = qobject_cast<QWidget *>(d->receiver))
530 point = w->mapFromGlobal(point.toPoint());
531#if QT_CONFIG(graphicsview)
532 else if (QGraphicsObject *go = qobject_cast<QGraphicsObject *>(d->receiver))
533 point = go->mapFromScene(point);
537 scroller->handleInput(inputType, point, monotonicTimer.elapsed());
542 bool scrollerIsActive = (scroller->state() == QScroller::Dragging ||
543 scroller->state() == QScroller::Scrolling);
548#if QT_CONFIG(graphicsview)
551 ) && scrollerIsActive)
552 result |= ConsumeEventHint;
560#if QT_CONFIG(graphicsview)
564 if (!scrollerWasDragging && !scrollerWasScrolling && scrollerIsActive)
565 PressDelayHandler::instance()->scrollerBecameActive(keyboardModifiers, mouseButtons);
566 else if (scrollerWasScrolling && (scroller->state() == QScroller::Dragging || scroller->state() == QScroller::Inactive))
567 PressDelayHandler::instance()->scrollerWasIntercepted();
573 switch (event->type()) {
574 case QEvent::MouseButtonPress:
575#if QT_CONFIG(graphicsview)
576 case QEvent::GraphicsSceneMousePress:
578 if (scroller->state() == QScroller::Pressed) {
579 int pressDelay =
int(1000 * scroller->scrollerProperties().scrollMetric(QScrollerProperties::MousePressEventDelay).toReal());
580 if (pressDelay > 0) {
581 result |= ConsumeEventHint;
583 PressDelayHandler::instance()->pressed(event, pressDelay);
588 case QEvent::TouchBegin:
589 q->setHotSpot(globalPos);
590 result |= scrollerIsActive ? TriggerGesture : MayBeGesture;
593 case QEvent::MouseMove:
594#if QT_CONFIG(graphicsview)
595 case QEvent::GraphicsSceneMouseMove:
597 if (PressDelayHandler::instance()->isDelaying())
598 result |= ConsumeEventHint;
600 case QEvent::TouchUpdate:
601 result |= scrollerIsActive ? TriggerGesture : Ignore;
604#if QT_CONFIG(graphicsview)
605 case QEvent::GraphicsSceneMouseRelease:
607 case QEvent::MouseButtonRelease:
608 if (PressDelayHandler::instance()->released(event, scrollerWasDragging || scrollerWasScrolling, scrollerIsActive))
609 result |= ConsumeEventHint;
611 case QEvent::TouchEnd:
612 result |= scrollerIsActive ? FinishGesture : CancelGesture;