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

QPointerEvent::clone does not do a deep copy, leaving the cloned object partially aliased

    XMLWordPrintable

Details

    • All
    • 12b7eab4d (dev)

    Description

      QPointerEvent has a protected member variable "QList<QEventPoint> m_points". QEventPoint uses QExplicitlySharedDataPointer internally. When you call "clone()" on a QPointerEvent (or any of its subclasses, such as QMouseEvent), the shared data is not detached or otherwise deep-copied. This leaves the cloned object partially aliased to the original object. If the original object changes for whatever reason, such as, as it bubbles up through the stack of parent widgets, the cloned object reflects those changes. Presumably, a cloned object should be insulated entirely from changes to the original object.

       

      Example code

      #include <QMouseEvent>
      #include <QDebug>
      
      int main()
      {
          const QPointF pos(10.0f, 10.0f);
      
          // create a mouse event (call it the original)
          QMouseEvent originalMe(QEvent::MouseButtonPress, pos, pos, pos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
          qDebug() << originalMe.allPointsAccepted(); // starts out false, as expected
          qDebug() << originalMe.points().first().isAccepted(); // starts out false, as expected
      
          // create a clone of the original
          auto clonedMe = originalMe.clone();
          qDebug() << clonedMe->allPointsAccepted(); // expecting false, because it's a clone
          qDebug() << clonedMe->points().first().isAccepted(); // starts out false, as expected
      
          // now we alter originalMe, which should *not* change clonedMe
          originalMe.setAccepted(true);
          qDebug() << clonedMe->allPointsAccepted(); // expecting false, but we get true -- changing originalMe erroneously changed clonedMe
          qDebug() << clonedMe->points().first().isAccepted(); // expecting false, but we get true
      
          // please note that I am using the "accepted" flag because it is available to manipulate via public methods
          // the problem exists for all data in QEventPoint, because QEventPoint is implemented with QExplicitlySharedDataPointer but doesn't do detach() as part of clone()
      }
      

      Attachments

        Issue Links

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

          Activity

            People

              vhilshei Volker Hilsheimer
              psturm_esri Paul Sturm
              Votes:
              1 Vote for this issue
              Watchers:
              7 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Gerrit Reviews

                  There are no open Gerrit changes