<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">
<div class="">(The TLDR for this is <a href="https://bugreports.qt.io/browse/QTBUG-94168" class="">https://bugreports.qt.io/browse/QTBUG-94168</a>)</div>
<div class=""><br class="">
</div>
When working on pointer handlers a few years ago, I was mainly thinking of the primary use cases where the target property points to an Item to be manipulated, and when the handler is active, it changes the appropriate properties for you.  (I.e. you can just
 declare a DragHandler inside an Item, and it becomes draggable.  If you want to drag something else instead, you can set the target.)  But there are some use cases where the target is or should be null, and you use ordinary bindings to make the handler manipulate
 arbitrary numeric properties.  QTBUG-68941 was the first (if memory serves) to point out that it’s an API mistake to have the main "value property", like PinchHandler.scale, resetting to the default value (1) when the gesture ends: the result is whatever you
 bound it to will jump back; so you need conditional bindings, or imperative onValueChanged and/or onActiveChanged code blocks to work around that.  So we made PinchHandler.scale “persistent” or “accumulated” so that you can bind it directly to an Item’s scale,
 and the item will scale smoothly when you do a sequence of pinches.  And then I thought "But I suppose we need to do the same with rotation.” But didn’t do it.  A couple of years went by… and now we are afraid to repeat that sort of behavior change, for example
 in 6.2, for fear that too many users might be using those existing properties, and will see breakage when they port their Qt 5 apps to Qt 6.  I’m thinking of PinchHandler.rotation, PinchHandler.translation and DragHandler.translation (I wonder if I missed
 any more).
<div class=""><br class="">
</div>
<div class="">Also, DragHandler and PinchHandler have the centroid property.  The gesture-scoped translation should be the same as centroid.scenePosition - centroid.scenePressPosition I think.  Binding to centroid properties can be useful, but they also change
 abruptly between gestures.<br class="">
<br class="">
Working with Qt Quick 3D reminded me of this problem.  I want to make pointer handlers work in 3D.  (Not start over again with all-new objects for event handling: maybe that’s been done enough times now.)  But a pointer handler’s target property is a QQuickItem*,
 so it cannot be a QQuick3DModel* (so far… but it’s still C++-private, so maybe we can still change it to QObject*, as long as it doesn’t affect the QML API for the 2D use cases; I didn’t try that yet).  I have patches that make it possible to declare the handler
 in the Model, and do event delivery so that it becomes interactive; but DragHandler cannot of its own accord know exactly how to drag a 3D model, because the units are different, and you probably want to drag on a 2D plane, which there is no API to define.
  So it seems that the value properties like DragHandler.translation are going to be more important, because you will more likely need to make bindings to them:</div>
<div class=""><br class="">
</div>
<div class="">     Model {<br class="">
        source: "#Sphere"<br class="">
        pickable: true<br class="">
        materials: DefaultMaterial { diffuseColor: "beige" }<br class="">
        x: dh.translation.x<br class="">
        y: -dh.translation.y<br class="">
        z: 400<br class="">
        DragHandler { id: dh }<br class="">
    }<br class="">
<br class="">
</div>
<div class="">The translation should “pick up where it left off” when you start dragging the second time, to make that work.  But currently it has the same problem as PinchHandler.scale did: it’s just the distance you have dragged within one drag gesture, and
 jumps back to 0,0 on release.  A workaround could be like this:</div>
<div class=""><br class="">
</div>
<div class="">
<div class="">    DragHandler {</div>
<div class=""><span class="Apple-tab-span" style="white-space: pre;"></span>property point startDrag</div>
<div class=""><span class="Apple-tab-span" style="white-space:pre"></span>onActiveChanged: {</div>
<div class=""><span class="Apple-tab-span" style="white-space:pre"></span>   if (active)</div>
<div class=""><span class="Apple-tab-span" style="white-space:pre"></span>startDrag = Qt.point(sphere.x, sphere.y)</div>
<div class=""><span class="Apple-tab-span" style="white-space:pre"></span>}</div>
<div class=""><span class="Apple-tab-span" style="white-space:pre"></span>onTranslationChanged: {</div>
<div class="">            // replace bindings with imperative code, yuck</div>
<div class=""><span class="Apple-tab-span" style="white-space:pre"></span>    sphere.x = startDrag.x + translation.x </div>
<div class=""><span class="Apple-tab-span" style="white-space: pre;"></span>    sphere.y = startDrag.y - translation.y</div>
<div class=""><span class="Apple-tab-span" style="white-space:pre"></span>}</div>
<div class="">    }</div>
</div>
<div class=""><br class="">
</div>
<div class="">(It would be nice if DragHandler “just works”: declare it in a Model and it’s draggable.  But how?  We’d maybe need to teach DragHandler to use some sort of callback to transform pixel deltas to 3D deltas, where the callback is defined by some
 Qt Quick 3D API which we haven’t put any thought into yet; and then perhaps use QMetaProperty’s to set the position of the 3D object, because Qt Quick can’t link directly to Qt Quick 3D.  Using metaproperties is a good idea anyway, for another reason: so that
 property interceptors like Behavior and BoundaryRule will work.  (Every time a handler calls setSomething() on an Item directly, it means those cannot intercept it.)  I don’t know if we will succeed in making binding-free DragHandler possible in 3D or not;
 but making plain old bindings is simple enough, and ought to work.)</div>
<div class=""><br class="">
</div>
<div class="">So I want to make translation persistent, but that’s likely to break someone else’s QML code.  I don’t know how widely-used that property is.</div>
<div class="">
<div class=""><br class="">
</div>
<div class="">So now we are going towards the convention that there is activeTranslation and persistentTranslation, and the same for the other “value properties” like that, in pointer handlers.  That makes translation redundant, so it should be deprecated.
  In order to avoid breaking <i class="">some</i> use cases unexpectedly, we will cause intentional trouble for
<i class="">more</i> of the users (replacing deprecated properties), if we go ahead and repeat that pattern on the rest of the handlers.  It implies that even PinchHandler.scale should be deprecated, because we should call it persistentScale now.  But this
 is what we do in Qt: we always worry about backwards compatibility, and it’s often a hassle.  In the end I’d rather have the shorter property names, actually.  What do you think?</div>
<div class=""><br class="">
</div>
<div class="">Should we stick to the rule that we always deprecate and replace, rather than taking a risk?</div>
<div class=""><br class="">
</div>
<div class="">Any other ideas?</div>
<div class=""><br class="">
</div>
<div class="">If only I’d thought of doing this a few months ago for 6.0, or 5.12 even…</div>
<div class=""><br class="">
</div>
</div>
<div class="">Anyway <a href="https://codereview.qt-project.org/c/qt/qtdeclarative/+/352432" class="">https://codereview.qt-project.org/c/qt/qtdeclarative/+/352432</a> went in for 6.2 today.  Changing the other properties would be past the feature freeze now,
 so I guess it will be later.</div>
<div class=""><br class="">
</div>
<div class="">A couple of grinding follow-up patches are <a href="https://codereview.qt-project.org/c/qt/qtdeclarative/+/352811" class="">https://codereview.qt-project.org/c/qt/qtdeclarative/+/352811</a> and <a href="https://codereview.qt-project.org/c/qt/qtdeclarative/+/352812" class="">https://codereview.qt-project.org/c/qt/qtdeclarative/+/352812</a></div>
<div class=""><br class="">
</div>
</body>
</html>