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

Auto-scrolling a ListView breaks drag operation

    XMLWordPrintable

Details

    • Bug
    • Resolution: Unresolved
    • P1: Critical
    • None
    • 6.6.2
    • Quick: Other
    • None
    • Ubuntu 22.04
    • Linux/Wayland

    Description

      I'm trying to drag & drop into a ListView, to move its items around. I've added automatic scrolling when drag position is on top or bottom of the list.

      Problem faced: after a few auto-scrolling iterations, the drag operation seems to enter an invalid state: I lose visual feedback, but internally it seems to still be active. I get a "exited" event on the DropArea, as if the mouse cursor had left the ListView (which it didn't), but the drag is still active. I cannot do anything until I release the drag and start a new one.

      A proof that something's going wrong internally: later when I quit the app, I get a crash related to what looks like a drag operation that was stuck.

      I've attached a video that shows the problem.

      Here is a minimal code that reproduces it:

      Rectangle {
          anchors.fill: parent
          color: "black"
      
          DropArea {
              id: dropArea
              anchors.fill: parent
      
              onPositionChanged: drag => {
                  const itemHeight = 50;
                  if (drag.y < itemHeight && !list.moving) {
                      scrollbar.decrease()
                  } else if (drag.y > list.height - itemHeight && !list.moving) {
                      scrollbar.increase()
                  }
              }
      
              onEntered: status.text = "DropArea.onEntered"
              onExited: status.text = "DropArea.onExited"
          }
      
          ColumnLayout {
              anchors.fill: parent
      
              ListView {
                  id: list
                  Layout.fillWidth: true
                  Layout.fillHeight: true
                  spacing: 1
                  model: 200
                  boundsBehavior: Flickable.StopAtBounds
                  clip: true
      
                  ScrollBar.vertical: ScrollBar {
                      id: scrollbar
                      stepSize: 1. / list.count
                  }
      
                  delegate: Rectangle {
                      id: listItem
                      width: list.width
                      height: 50
                      color: "white"
      
                      Text {
                          anchors.centerIn: parent; text: index; color: "black"
                      }
      
                      Drag.dragType: Drag.Automatic
                      Drag.supportedActions: Qt.MoveAction
      
                      DragHandler {
                          id: dragHandler
                          target: null
      
                          onActiveChanged: {
                              if (active) {
                                  listItem.grabToImage(function (result) {
                                      if (active) {
                                          listItem.Drag.imageSource = result.url;
                                          listItem.Drag.active = true;
                                      }
                                  });
                              } else {
                                  listItem.Drag.active = false;
                              }
                          }
                      }
                  }
              }
      
              Text {
                  id: status
                  Layout.fillWidth: true
                  Layout.fillHeight: false
                  color: "white"
              }
          }
      } 

      And the stack trace of the crash that occurs on exit (differs sometimes, but always related to drag):

       1# 0x0000702AA1C42520 in /lib/x86_64-linux-gnu/libc.so.6
       2# QQmlData::isSignalConnected(QAbstractDeclarativeData*, QObject const*, int) at /home/qt/work/qt/qtdeclarative/src/qml/qml/qqmlengine.cpp:373
       3# void doActivate<false>(QObject*, int, void**) at /home/qt/work/qt/qtbase/src/corelib/kernel/qobject.cpp:3928
       4# QQuickDragAttached::dragFinished(Qt::DropAction) at /home/qt/work/build/qtdeclarative/src/quick/Quick_autogen/include/moc_qquickdrag_p.cpp:1185
       5# QQuickDragAttachedPrivate::startDrag(QFlags<Qt::DropAction>) at /home/qt/work/qt/qtdeclarative/src/quick/items/qquickdrag.cpp:790
       6# QQuickDragAttached::qt_metacall(QMetaObject::Call, int, void**) at /home/qt/work/build/qtdeclarative/src/quick/Quick_autogen/include/moc_qquickdrag_p.cpp:1169
       7# QQmlPropertyData::writeProperty(QObject*, void*, QFlags<QQmlPropertyData::WriteFlag>) const at /home/qt/work/qt/qtdeclarative/src/qml/qml/qqmlpropertydata_p.h:340
       8# QQmlPropertyPrivate::write(QObject*, QQmlPropertyData const&, QVariant const&, QQmlRefPointer<QQmlContextData> const&, QFlags<QQmlPropertyData::WriteFlag>) at /home/qt/work/qt/qtdeclarative/src/qml/qml/qqmlproperty.cpp:1555
       9# QV4::QObjectWrapper::setProperty(QV4::ExecutionEngine*, QObject*, QQmlPropertyData const*, QV4::Value const&) at /home/qt/work/qt/qtdeclarative/src/qml/jsruntime/qv4qobjectwrapper.cpp:650
      10# QV4::QObjectWrapper::setQmlProperty(QV4::ExecutionEngine*, QQmlRefPointer<QQmlContextData> const&, QObject*, QV4::String*, QFlags<QV4::QObjectWrapper::Flag>, QV4::Value const&) at /home/qt/work/qt/qtdeclarative/src/qml/jsruntime/qv4qobjectwrapper.cpp:466
      11# QV4::QQmlTypeWrapper::virtualPut(QV4::Managed*, QV4::PropertyKey, QV4::Value const&, QV4::Value*) at /home/qt/work/qt/qtdeclarative/src/qml/qml/qqmltypewrapper.cpp:334
      12# QV4::Object::virtualResolveLookupSetter(QV4::Object*, QV4::ExecutionEngine*, QV4::Lookup*, QV4::Value const&) at /home/qt/work/qt/qtdeclarative/src/qml/jsruntime/qv4object.cpp:813
      13# QV4::Moth::VME::interpret(QV4::JSTypesStackFrame*, QV4::ExecutionEngine*, char const*) at /home/qt/work/qt/qtdeclarative/src/qml/jsruntime/qv4vme_moth.cpp:801
      14# QV4::Moth::VME::exec(QV4::JSTypesStackFrame*, QV4::ExecutionEngine*) at /home/qt/work/qt/qtdeclarative/src/qml/jsruntime/qv4vme_moth.cpp:584
      15# qfoDoCall(QV4::FunctionObject const*, QV4::Value const*, QV4::Value const*, int) at /home/qt/work/qt/qtdeclarative/src/qml/jsruntime/qv4functionobject.cpp:528
      16# QJSValue::call(QList<QJSValue> const&) const at /home/qt/work/qt/qtdeclarative/src/qml/jsapi/qjsvalue.cpp:707
      17# QQuickItemGrabResult::event(QEvent*) at /home/qt/work/qt/qtdeclarative/src/quick/items/qquickitemgrabresult.cpp:217
      18# QApplicationPrivate::notify_helper(QObject*, QEvent*) at /home/qt/work/qt/qtbase/src/widgets/kernel/qapplication.cpp:3298
      19# QCoreApplication::notifyInternal2(QObject*, QEvent*) at /home/qt/work/qt/qtbase/src/corelib/kernel/qcoreapplication.cpp:1121
      20# QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) at /home/qt/work/qt/qtbase/src/corelib/kernel/qcoreapplication.cpp:1906
      21# postEventSourceDispatch(_GSource*, int (*)(void*), void*) at /home/qt/work/qt/qtbase/src/corelib/kernel/qeventdispatcher_glib.cpp:244
      22# g_main_context_dispatch in /lib/x86_64-linux-gnu/libglib-2.0.so.0
      23# 0x0000702AA1708258 in /lib/x86_64-linux-gnu/libglib-2.0.so.0
      24# g_main_context_iteration in /lib/x86_64-linux-gnu/libglib-2.0.so.0
      25# QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) at /home/qt/work/qt/qtbase/src/corelib/kernel/qeventdispatcher_glib.cpp:394
      26# QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) at /home/qt/work/qt/qtbase/src/corelib/kernel/qeventloop.cpp:181
      27# QCoreApplication::exec() at /home/qt/work/qt/qtbase/src/corelib/kernel/qcoreapplication.cpp:1442 

      Attachments

        For Gerrit Dashboard: QTBUG-124663
        # Subject Branch Project Status CR V

        Activity

          People

            piwierci Piotr Wierciński
            laurentgom Laurent
            Votes:
            1 Vote for this issue
            Watchers:
            4 Start watching this issue

            Dates

              Created:
              Updated:

              Gerrit Reviews

                There are 2 open Gerrit changes