[Interest] QML Pointer Handlers: how to use 'GrabPermissions'

Shawn Rutledge Shawn.Rutledge at qt.io
Tue Sep 18 18:48:27 CEST 2018


> On 18 Sep 2018, at 14:36, Alexander Ivash <elderorb at gmail.com> wrote:
> 
> Hi Shawn,
> 
> I'm still curious about best practices on implementing use case I
> mentioned previously: To refresh memory I need a 'canvas' with some
> 'items' inside. Simplified version looks like this:
> 
> ApplicationWindow {
>    visible: true
>    width: 640
>    height: 480
> 
>    ScrollView {
>        anchors.fill: parent
> 
>        Flickable {
>            Rectangle {
>                anchors.fill: parent
>                color: 'yellow'
> 
>                TapHandler {
>                    onTapped: {
>                        console.debug('item deselected');
>                    }
>                }
>            }
> 
>            Rectangle {
>                width: 50
>                height: 50
>                color: 'green'
> 
>                TapHandler {
>                    onTapped: {
>                        console.debug('item selected');
>                    }
>                }
>            }
>        }
>    }
> }
> 
> Tapping canvas should result in item de-selection, tapping item should
> result in item selection. So I need item's tap handler to do not
> propagate tap (although maybe wouldn't mind propagating long presses).

I tried: if you change the small green rectangle's TapHandler to have either gesturePolicy: TapHandler.ReleaseWithinBounds, or TapHandler.WithinBounds, it works.  Because it accepts the point, that means the event will not propagate to the other TapHandler.  But that’s unintuitive API for this use case.  So we should try to come up with something more sensible I suppose.

There is https://codereview.qt-project.org/#/c/227659 which proposed to add a TapHandler property called blocksTaps.  I didn’t think that was the right name for it.  But I think it was intended to solve the opposite problem: a TapHandler is somehow on top of a MouseArea, and we want both of them to get the event.  If you have set gesturePolicy: TapHandler.ReleaseWithinBounds, and that stops propagation, maybe you need a way to continue propagation instead.

An Item can either accept or reject an entire event.  When multiple touchpoints are pressed, we deliver a custom event to each Item, an event that has only the touchpoints that are inside the Item’s bounds.  So accepting that custom event means accept all the touchpoints, excluding the touchpoints which are not part of that event.  But for Handlers, we want to deliver the entire event to each handler, because that improves flexibility (PinchHandler can react to points slightly outside the item bounds, for example); therefore Handlers accept individual points, not the whole event.  In general, accepting all points _implies_ accepting the entire event, but it may be that one handler accepts some points while another accepts other points.  This is how it’s now possible to interact with multiple handlers at the same time, but delivery is not “done” until all the points are accepted.

So if we add another property to QQuickPointerHandler, it would be to control whether a particular handler instance will accept the subset of points that it determined were relevant to it.  What should it be named then?  acceptPoints?  greedy?  stopPropagation?  Do any of those make sense to designers, or to anyone who doesn’t understand event delivery?  I suppose changing gesturePolicy should automatically change the default value of that property too (because otherwise people will complain that changing gesturePolicy does not change behavior), while setting both properties could be allowed, but some combinations might be dysfunctional.

Also, we have properties like acceptedMouseButtons, acceptedModifiers and so on, but there “accept” means “react to an event”, not “stop propagation”.



More information about the Interest mailing list