<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;"><div class="">When I started working with Qt Quick in 2011, it wasn't too</div><div class="">long before I began to notice that our vaunted support for multitouch (which</div><div class="">still felt like an innovative new feature at the time, even though it had</div><div class="">already been 5 years since the introduction of the iPhone) was quite flawed.</div><div class="">Everyone was using MouseArea and Flickable, and those were not very good</div><div class="">companions for the only components that actually supported multitouch:</div><div class="">MultiPointTouchArea and PinchArea.  At some point someone had made the decision</div><div class="">that touch is enough like mouse, that it would simplify things if we just</div><div class="">convert touch events to synthetic mouse events and reuse the same logic for</div><div class="">both.  Maybe that was decided before multi-touch screens were invented; it</div><div class="">would have been ok for the resistive ones from the QTopia days, for example.</div><div class="">But I thought that Qt Quick was newer than that, so it was an immediate</div><div class="">facepalm moment when I realized that mistake was perpetuated there.  Finding</div><div class="">ways to work around it has dominated a lot of my time working on Qt Quick ever</div><div class="">since.  But Qt 5 has had such a long lifespan, and it wasn't possible to fix it</div><div class="">in a fundamental way, without increasing complexity in ways that you might have</div><div class="">noticed.</div><div class=""><br class=""></div><div class="">First, I did some patches to handle actual QTouchEvents in Flickable and</div><div class="">MouseArea.  This naturally increases the code size quite dramatically, because</div><div class="">QMouseEvent and QTouchEvent have too little in common, and the delivery</div><div class="">strategy needs to be different.  QTouchEvents are broken up according to item</div><div class="">boundaries, so that you can touch multiple Items at the same time with</div><div class="">different fingers.  This complexity was already there in QQuickWindow, but I</div><div class="">had to add a lot more code to Flickable and MouseArea.  It took a really long</div><div class="">time to get all the tests to pass again.  Frederik was supportive, understood</div><div class="">the point of what I was doing, and helped with it.  Finally this work was ready</div><div class="">to go into 5.5, but then reviewers still had too many doubts.  From one side it</div><div class="">doesn't make a lot of sense to take a component called MouseArea, with all the</div><div class="">limitations that name implies, and try to make it do the right things with</div><div class="">touch events too.  (Even though users already expected it to handle taps and</div><div class="">drags on touchscreens, because the touch->mouse synthesis had always been</div><div class="">there.)  It was a lot of code to read and understand.  So we left it broken.</div><div class="">And customers keep asking for those patches, so they still exist on a personal</div><div class="">branch somewhere, which I haven't updated for quite a while.  To this day, if</div><div class="">you use any touch-handling Item or pointer handler inside a Flickable, the</div><div class="">results are often not very satisfying.  If you turn on pressDelay, it gets</div><div class="">worse.  (Flickable never saw the touch press, only a synth-mouse press.  So it</div><div class="">cannot replay a touch press either.  So the children will see a synthetic mouse</div><div class="">press followed by a series of touch events, and will be required to see through</div><div class="">the synth-mouse crap and treat the whole series as if the press had been a</div><div class="">touch event too.  But… should filtering events that would otherwise go to the</div><div class="">children really be Flickable’s responsibility?  What about replaying events</div><div class="">after a press delay: monolithic Flickable should really do that too?) And </div><div class="">because of another architectural abomination, making Item Views inherit </div><div class="">Flickable, that affects even more use cases with ListView and TableView </div><div class="">delegates.  (I have some hope of eventually rewriting Flickable using </div><div class="">Pointer Handlers (that’s what FakeFlickable.qml demonstrates), but </div><div class="">keeping it working the same both for subclasses and for end-users is quite</div><div class="">a high bar.)</div><div class=""><br class=""></div><div class="">That experience taught me that we can only fix touch and mouse and Wacom tablet</div><div class="">event delivery by making it the same for all of them.  That means we must make</div><div class="">the events look enough alike that the same delivery code will work for all of</div><div class="">them.  It's not possible with the leftover QInputEvent hierarchy from Qt 4 and</div><div class="">earlier.  There is not even a consistently-named set of accessors for getting</div><div class="">the coordinates from the various event types.</div><div class=""><br class=""></div><div class="">Continuing with the touch->mouse synthesis approach could maybe have been</div><div class="">justified if we had support for multiple mice in Qt (so that there could be a</div><div class="">virtual mouse for each touchpoint), and if we could agree that it's ok to</div><div class="">disassociate touchpoints from each other and deliver them as separate events.</div><div class="">I had a series of patches to deliver touch events that way.  It worked fine in</div><div class="">practice, but for that prototype I had done some non-BC modifications in</div><div class="">qevent.h (which could have been mitigated with differently-designed wrapper</div><div class="">events).  But when we discussed it with Lars, he was very much against the idea</div><div class="">of disassociating touchpoints, feeling strongly that points which belong to the</div><div class="">same gesture need to be kept together.  As said, touch events get broken up</div><div class="">during delivery in QQuickWindow; but if PinchHandler for example received</div><div class="">multiple events, one for each finger involved in the pinch, it would have to</div><div class="">update the gesture each time.  We could have mitigated that by adding an</div><div class="">incrementing frame counter so that touchpoints could be re-associated.</div><div class=""><br class=""></div><div class="">But at that time, we concluded that we will go the other way in Qt Quick: every</div><div class="">"pointer event" will have API appropriate for multiple points.  QMouseEvent can</div><div class="">have hard-coded accessors for the single point that it carries; but touch</div><div class="">events carry multiple points.  This is how we can eventually refactor the</div><div class="">delivery code so that mouse and touch events are delivered the same way.  And</div><div class="">we agreed to make the Qt Quick events a prototype of how we would refactor the</div><div class="">QEvents in Qt 6.  So since Qt 5.8, Qt Quick has been delivering wrapper events</div><div class="">instead: QQuickPointerEvent which contains instances of QQuickEventPoint.  Some</div><div class="">of the delivery refactoring has been done: conservatively, because although few</div><div class="">are willing to help, a lot more complain loudly when any existing usecase</div><div class="">breaks.  And there are so many applications already.  But the wrapper events</div><div class="">made it possible to develop Pointer Handlers; and the goal has always been that</div><div class="">those would retain QML source compatibility in Qt 6.  The delivery mechanism</div><div class="">for those adds a lot of flexibility.  After enough use cases have been ported</div><div class="">over to using them, maybe we can eventually deprecate some of the most</div><div class="">pernicious features that depend on complex delivery code that I'd like to get</div><div class="">rid of in QQuickWindow; but progress has been so slow in other modules outside</div><div class="">of Qt Quick itself, that it still seems too early to consider doing that in Qt</div><div class="">6, because it would require heroic effort by a number of people over a short</div><div class="">time period.</div><div class=""><br class=""></div><div class="">Anyway, the time has come to at least get the QEvent refactoring done, so that</div><div class="">Qt Quick can go back to delivering them without wrappers, and so that Items can</div><div class="">receive pointer events directly.  We have discussed this a few times already at</div><div class="">various events.  At one QtCS Qt 6 planning session, I think in 2018 (or was it</div><div class="">earlier?), I promised to do the refactoring for Qt 6.  The goal is to break</div><div class="">nothing in widgets: that is, QMouseEvent needs to keep its existing accessors.</div><div class="">We will add new ones, and deprecate the ones that are named inconsistently and</div><div class="">the ones that provide integer coordinates.  The same for the other event types.</div><div class=""> QTouchEvent::TouchPoint is a bit special: it will be replaced by the</div><div class="">QEventPoint that every QPointerEvent contains at least one of.  So far it looks</div><div class="">like I can use "using" to make QTouchEvent::TouchPoint an alias of QEventPoint,</div><div class="">for the sake of source compatibility.</div><div class=""><br class=""></div><div class="">I think the result will look something like this:</div><div class=""><br class=""></div><div class=""><img apple-inline="yes" id="4B81B323-AB51-4D9D-8C3B-E9D1AD187F96" src="cid:C1AA75CA-B900-4C5E-B058-555CA8D4527D@lan" class=""></div><div class=""><br class=""></div><div class="">What I started with a few months ago was adding const QInputDevice *device() to</div><div class="">QInputEvent.  We have seen that the MouseEventSource enum does not provide</div><div class="">enough information.  E.g. in Controls we had to assume in some places that if a</div><div class="">mouse event is SynthesizedByQt, then it's synthesized from a touchscreen by</div><div class="">QQuickWindow during delivery of the original QTouchEvent.  That's not always</div><div class="">true (there are other places where synthesis occurs), and resulted in some</div><div class="">bugs.  Now that we're trying to fully support Wacom tablets in Qt Quick, a</div><div class="">synth-mouse event could come from that.  So I want to completely replace</div><div class="">MouseEventSource with the device pointer, so that the event consumer can see</div><div class="">specifically which device the event came from, and thus can adjust behavior</div><div class="">depending on the specific type of device, its capabilities, the screen area</div><div class="">that the device can access (e.g. a touchscreen input device or Wacom tablet is</div><div class="">probably mapped to a specific QScreen or QWindow), etc.  This way we can also</div><div class="">begin to support multiple mice and multiple "seats" (in the Wayland sense) at</div><div class="">the same time.  But it imposes a new requirement on platform plugins: to create</div><div class="">the QInputDevice instances.  The plugins that I know about all do device</div><div class="">discovery anyway, though; they have just been using internal ad-hoc data</div><div class="">structures of their own, and not exposing those devices to</div><div class="">QWindowSystemInterface.  I've been working on the xcb plugin so far, since I</div><div class="">understand that one the best, and it already supports multiple seats after a</div><div class="">fashion (there can be multiple core pointers and core keyboards, and they can</div><div class="">be associated with each other; there just isn't a seat name, but I can make one</div><div class="">up).</div><div class=""><br class=""></div><div class="">The fantastic result of that should be that event delivery code can finally be</div><div class="">device-agnostic!  QQuickWindow and QQuickFlickable will no longer need to treat</div><div class="">mouse and touch events differently, and Wacom tablet events will go through the</div><div class="">same way too.  Flickable should be able to blindly replay a copy of whatever event</div><div class="">it got when the pressDelay timer fires, without caring about every piece of data </div><div class="">inside. Only the final event consumer (QQuickItem or Pointer Handler or even</div><div class="">a QWidget subclass) will need to care about the device-specific details, and it</div><div class="">will have all the information necessary for very finely-tuned behavior.  Now we</div><div class="">can finally add virtual functions to QQuickItem to handle pointer events, so</div><div class="">not only Pointer Handlers will be able to do that.  And we will open the</div><div class="">possibility to refactor event delivery code in other parts of Qt later on.  It</div><div class="">should become possible to fix most of the open bugs related to handling mouse</div><div class="">and touch events in Qt Quick and Controls during the Qt 6 series.</div><div class=""><br class=""></div><div class="">Because we will make QPointerEvent look as much as possible like</div><div class="">QQuickPointerEvent, we will maintain QML source compatibility for anyone who</div><div class="">just started using pointer handlers.  Of course the goal is for older stuff</div><div class="">like MouseArea and Flickable and Controls that we can choose appropriate API</div><div class="">changes, not be required to make them because of event changes.  QPointerEvent</div><div class="">will be a gadget instead of a QObject wrapper, but it will have the same</div><div class="">properties, so to the extent that it's exposed in QML API (which is not much),</div><div class="">it will look the same.  It will also look enough like a QMouseEvent and enough</div><div class="">like a QTouchEvent that we will have source compatibility in virtual functions</div><div class="">that handle those, too.  Hopefully.</div><div class=""><br class=""></div><div class="">After proving that we have also maintained source compatibility as much as</div><div class="">possible (including in the great heap of widget code in the world), we still</div><div class="">end up with a lot of deprecated methods that should be replaced over time</div><div class="">(QPoint pos() -> QPointF position() and such).  For that purpose I want to add</div><div class="">a feature to clazy or develop some other clang-based tooling which can fix all</div><div class="">of our modules, and also be available to customers to make the same</div><div class="">replacements in their code bases.  If we end up with any SC breaks, it's a</div><div class="">possible fallback position that at least we can deliver a tool to fix them.</div><div class=""><br class=""></div><div class="">Beyond that, we probably ought to do something about native gestures.  Another</div><div class="">reason Qt Quick is so complex is that it started out assuming it will be given</div><div class="">only raw touch events and needs to do gesture recognition itself; but now</div><div class="">gestures have gone mainstream on most platforms, so we could be getting</div><div class="">QNativeGestureEvents from most of them, especially from touchpads.  But I</div><div class="">didn't get as far as I should have over the last couple of years just exploring</div><div class="">how to improve that aspect of Qt, and the platform plugin maintainers</div><div class="">have not gotten around to adding support for native gestures to all the</div><div class="">platforms that could have them, either.  I wish we could get rid of the gesture</div><div class="">recognizer in the widgets module completely; but customers will not be</div><div class="">satisfied unless we then have native gesture recognition on all platforms where</div><div class="">it's possible.  Some of them want to continue doing custom gesture recognition,</div><div class="">too.  But we have QGestureEvent (for the widget gesture recognizer) and</div><div class="">QNativeGestureEvent (for gesture events that come from the QPA plugin) as</div><div class="">separate types.  We're running out of time to figure out whether we can unify</div><div class="">those two, just to make it less confusing for applications.  I guess it's not</div><div class="">so terrible to keep the events separate if we still have to keep the old</div><div class="">gesture framework intact; but do we?</div><div class=""><br class=""></div><div class="">So that's the status of pointer event handling.  And I'm still working mostly</div><div class="">alone on it.  It seems with our schedule that the QEvent API, and all other</div><div class="">APIs that need to change as a result of that, need to be stabilized by the end</div><div class="">of June.  I still think I can get the broad strokes done if nobody and no</div><div class="">unexpected bugs get in the way this time, and the +2's come quickly (keeping in</div><div class="">mind that the perfect is the enemy of the good, and every change is subject to</div><div class="">ongoing incremental changes later).  (It looks like my time is limited to make</div><div class="">other API changes in Qt Quick, since this is taking most of it.)  Is anyone</div><div class="">interested in helping?</div><div class=""><br class=""></div></body></html>