Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-57910

Missing touchUngrabEvent callback when Flickable steals press

    XMLWordPrintable

Details

    • Bug
    • Resolution: Done
    • P1: Critical
    • 5.9.0 Beta 1
    • 5.9
    • None
    • Latest qtdeclarative dev on any touch device
    • 71a2dbed467be0041b6793dda868655b2632e830

    Description

      Steps to reproce:

      • press and drag the blue button

      Expected result:

      • the button receives an ungrab event when the Flickable steals press

      Actual result:

      • the button stays pressed since it does not receive an ungrab event

      main.cpp:

      #include <QGuiApplication>
      #include <QQmlApplicationEngine>
      #include <QQuickPaintedItem>
      #include <QPainter>
      
      class TouchButton : public QQuickPaintedItem
      {
          Q_OBJECT
      public:
          TouchButton(QQuickItem *parent = nullptr)
              : QQuickPaintedItem(parent) , m_pressed(false), m_touchId(-1)
          {
          }
      
          void paint(QPainter *painter) override
          {
              painter->setOpacity(0.75);
              painter->setRenderHint(QPainter::Antialiasing);
      
              painter->setBrush(m_pressed ? Qt::darkBlue : Qt::blue);
              painter->drawRoundedRect(boundingRect(), width() / 10, width() / 10);
      
              painter->setPen(Qt::white);
              painter->drawText(boundingRect(), Qt::AlignCenter, "Press\nand\ndrag");
          }
      
      protected:
          bool event(QEvent *event) override
          {
              qDebug() << event;
              return QQuickPaintedItem::event(event);
          }
      
          void touchEvent(QTouchEvent *event) override
          {
              switch (event->type()) {
              case QEvent::TouchBegin:
                  if (m_touchId == -1) {
                      m_pressed = true;
                      m_touchId = event->touchPoints().first().id();
                      update();
                  }
                  break;
      
              case QEvent::TouchUpdate:
                  for (const QTouchEvent::TouchPoint &point : event->touchPoints()) {
                      if (point.id() != m_touchId)
                          continue;
      
                      switch (point.state()) {
                      case Qt::TouchPointPressed:
                          m_pressed = true;
                          update();
                          break;
                      case Qt::TouchPointReleased:
                          m_pressed = false;
                          update();
                          break;
                      default:
                          break;
                      }
                  }
                  break;
      
              case QEvent::TouchEnd:
                  for (const QTouchEvent::TouchPoint &point : event->touchPoints()) {
                      if (point.id() == m_touchId) {
                          m_pressed = false;
                          m_touchId = -1;
                          update();
                      }
                  }
                  break;
      
              case QEvent::TouchCancel:
                  m_pressed = false;
                  m_touchId = -1;
                  update();
                  break;
      
              default:
                  QQuickPaintedItem::touchEvent(event);
                  break;
              }
          }
      
          void touchUngrabEvent() override
          {
              m_pressed = false;
              m_touchId = -1;
              update();
          }
      
      private:
          bool m_pressed;
          int m_touchId;
      };
      
      int main(int argc, char *argv[])
      {
          QGuiApplication app(argc, argv);
      
          qmlRegisterType<TouchButton>("TouchButton", 1, 0, "TouchButton");
      
          QQmlApplicationEngine engine;
          engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
      
          return app.exec();
      }
      
      #include "main.moc"
      

      main.qml:

      import QtQuick 2.5
      import QtQuick.Window 2.2
      import TouchButton 1.0
      
      Window {
          id: window
          width: 640
          height: 480
          visible: true
      
          Flickable {
              anchors.fill: parent
              contentWidth: parent.width * 1.5
              contentHeight: parent.height * 1.5
      
              TouchButton {
                  width: parent.width / 4
                  height: parent.height / 4
                  anchors.centerIn: parent
              }
          }
      }
      

      Output on Android:

      D libuntitled603.so: ../untitled603/main.cpp:30 (virtual bool TouchButton::event(QEvent*)): QTouchEvent(TouchBegin device: "" states: TouchPointPressed, 1 points: (TouchPoint(2000001 (340,411) TouchPointPressed pressure 0.9125 ellipse (179.745 x 222.809 angle 0) vel (0,0) start (340,411) last (340,411) delta (0,0)))
      D libuntitled603.so: ../untitled603/main.cpp:30 (virtual bool TouchButton::event(QEvent*)): QTouchEvent(TouchUpdate device: "" states: TouchPointMoved, 1 points: (TouchPoint(2000001 (340,411) TouchPointMoved pressure 1.0625 ellipse (179.745 x 222.809 angle 0) vel (0,0) start (340,411) last (340,411) delta (0,0)))
      D libuntitled603.so: ../untitled603/main.cpp:30 (virtual bool TouchButton::event(QEvent*)): QTouchEvent(TouchUpdate device: "" states: TouchPointMoved, 1 points: (TouchPoint(2000001 (332,399) TouchPointMoved pressure 0.95 ellipse (196.085 x 243.064 angle 0) vel (0,0) start (340,411) last (340,411) delta (-8,-12)))

      The button receives only touch press and move events.

      Attachments

        Issue Links

          No reviews matched the request. Check your Options in the drop-down menu of this sections header.

          Activity

            People

              frederik Frederik Gladhorn
              jpnurmi J-P Nurmi
              Votes:
              1 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Gerrit Reviews

                  There are no open Gerrit changes