[Development] Pointer Handlers will be Tech Preview in 5.10

Shawn Rutledge Shawn.Rutledge at qt.io
Wed Aug 9 14:10:27 CEST 2017

We just finally got the wip/pointerhandler branch merged to dev branch (yes it’s a couple of days past the feature freeze, but has been in the works for years, and we really planned to get it in 5.10).

A PointerHandler is a QObject which can be declared as a child of an Item in Qt Quick, which will handle events from pointing devices (mouse, keyboard, or stylus) on behalf of that Item.  An Item can have multiple handlers.  So, handlers are intended to be smaller and more specific in implementation, compared to the existing Areas such as MouseArea which try to do everything you could ever want to do with the mouse (and then get used for handling touch events in practice besides); and also somewhat smaller in memory, not being full-fledged Items themselves.

It’s going to be Tech Preview because of still being incomplete.  So far we only have

TapHandler - the one you need to build a button, it handles press and release, tapping (clicking), long-press and multi-tapping (the most common use cases for MouseArea).  There are improvements like being able to constrain it to react only to certain device types, certain mouse buttons, or while holding down a modifier key; being able to count taps rather than only supporting single and double click; and being able to tap or press multiple Items with TapHandlers at the same time (which until now has required that you switch from MouseArea to MultiPointTouchArea).

DragHandler - declare one of these inside an Item and suddenly you can drag it.  It has some properties too.

PinchHandler - to enable 2-finger pinch gestures for rotation, scaling and dragging.  The major improvements over PinchArea are that you can zoom into any point (the point which is the centroid of your finger positions) rather than only zooming into the center or corner of an Item; and, you can require more than two fingers if you like, so it’s possible to have a 2-finger pinch which does one thing and a 3-finger pinch which does something else, for example.

So what have we left out? everything else that you could do with a mouse: for example hovering, and use of the mouse wheel, at least.  Scrolling via a 2-finger flick gesture on a touch pad (which is implemented via fake mouse wheel events on most platforms… but that’s not always good enough).  We need to write a few more handlers I think.

Handling of QTabletEvents (from a stylus on a Wacom tablet, Tablet PC or a Galaxy Note) is also not implemented yet (although I have had patches to get started with that for a long time now).  And I think we need another handler for the stylus anyway.  Now that we have path rendering in Qt Quick, maybe the next step is to be able to draw paths with a stylus; but we didn’t flesh out the mechanism for doing that yet.

DragHandler drags items around the scene, but we have made no attempt at proper DnD support yet.

Another reason is that we hope to have public C++ API eventually, so that you can subclass one of the pointer handler abstract classes and handle the kinds of gestures that we don’t already support, to do whatever you like.  But we have not yet made it suitable for that: it needs more API review, the classes need refactoring to follow the PIMPL pattern, more docs, etc.

So for 5.10 you will only be able to do

import Qt.labs.handlers 1.0

and instantiate those three types in QML; and you can play with the private API in C++, with the expectation that some of it will probably be public later on.

There is a prototype FakeFlickable which we have as a manual test so far, which shows how you can use two Items plus a DragHandler to implement something which behaves like Flickable, in pure QML.  Maybe we will re-implement Flickable itself that way, under the covers, which should result in some code de-duplication and more flexible event handling; but we haven’t gotten to that yet, and the behavior isn’t perfect yet anyway.  But it’s very difficult to fix Flickable to handle multi-touch properly: you can’t flick two of them at once with two fingers, and it only knows how to steal the grab from a mouse event, so there are some problems with stealing synthetic mouse events from handlers or items which are grabbing touchpoints already.  So we think that replacing it might streamline the code while also enabling more kinds of interaction.  But can we keep the API the same while totally replacing the implementation?  (or should we?)  won’t know until we try…

We still need to do a lot more dogfooding: for example try to replace all the custom C++ event handling code in qtlocation with pointer handlers.  We can’t say it’s ready to use if we don’t succeed with that.  Likewise, sets of controls such as QtQuick.Controls could make use of handlers… but we’ll see how that goes.  From one side, we need to do something like that in order to validate more of the possible use cases.  From another side, the total QObject count would go up (which means instantiation time and memory usage would probably increase), compared to the Controls 2.0 implementation with its monolithic base classes.  So we’ll see about that.  Maybe we can find some sort of middle ground which gives us code reuse without bloating the object count, somehow.  Such an approach amounts to having a different kind of C++ API.

The original idea was more about using attached properties, rather than having to declare the handlers.  We are still playing with some ideas there.

And actually, there are still known bugs we are fixing.  We will keep trying to get more of them fixed before 5.10 ships. But now is the chance for some early feedback.  After talking about this at the contributors’ summit for 3 years straight, we think it’s about time that we shipped something.

Sorry for getting it in at the last minute like this.  (It could have been a couple of months ago.  I was on vacation, and little has changed since this spring, except for some bug fixes which finally enabled integration.)  But if you don’t do the import, you can ignore it.  We kept all the old autotests passing, so we expect that the existence of this new stuff won’t impact existing QML.  And during the big event-delivery refactoring (some of which was in 5.9 already), we have tried to make event delivery more efficient for all use cases, so it will be interesting to get some feedback about that too.

Later on, it may be part of Qt Quick, not requiring a separate import anymore.  And then if it all goes really well, at some point maybe we should deprecate the old Areas (not sure when that will be).  And in Qt 6 I hope we can broaden the scope of the event delivery refactoring: promote the pointer event concept to qtbase, instead of just having it be a wrapper around the existing QInputEvents in qtdeclarative, as it is now.  I even hope we can go as far as to remove the one-mouse limitation eventually.  QtQuick will be ready for that by the time it’s possible in qtbase, anyway.

The main thrust of this gambit is to unify the delivery and handling of all pointer events instead of needing separate delivery paths for QMouseEvent, QTouchEvent and QTabletEvent (with their own behavioral idioscynrasies and bugs), and to enable proper multi-touch support such that we can some day stop relying on the synthesis of mouse events from touch events (because the delivery process is now agnostic about the type of event, even though an individual handler may care about some device-specific event details).

More information about the Development mailing list