aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/util/qquickdeliveryagent_p_p.h
Commit message (Collapse)AuthorAgeFilesLines
* Add QQDAPriv::allPointsGrabbed() and stop using QPointerEvent::apg()Shawn Rutledge2022-07-131-0/+1
| | | | | | | | | | | | | | | | QPointerEvent::allPointsGrabbed() was implemented wrong in qtbase 8932e80d0c8879a1e720fef825ed0d9c4e384a01. Fixing it has ramifications for event delivery; so it's easier to take care of that in one patch in qtdeclarative first, rather than causing a submodule update crisis, and then fix the public QPointerEvent version afterwards. It fits nicely alongside anyPointGrabbed() anyway. Task-number: QTBUG-101932 Change-Id: I4141a492c941963e5eb716b63d3e09f9ae165c57 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io> (cherry picked from commit 42eddf0743e09f5b751a68555dba045c17cf8520) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
* QQuickItem: ignore double-clicks by default; remove allowDoubleClickShawn Rutledge2022-06-081-1/+0
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Because Qt has a pattern that events arrive pre-accepted, most event-handling functions in QQuickItem call ignore(), and it's up to subclasses to override those functions to allow the event to remain accepted, if they choose to handle it. So it was odd that QQuickItem::mouseDoubleClickEvent() did not call ignore(). Pointer handlers don't handle MouseButtonDblClick events, so QQuickDeliveryAgent does not send those events to handlers. Since 0e3adb65b0e9c44fa6e202630ff57c907ecf0820 though, we disallowed delivery of double-click events to Items after any handler has already accepted the single point in a mouse event. This caused some inconsistencies; in fact the allowDoubleClick variable was getting thrashed a lot, making it hard to reason about the logic. Items that contained handlers behaved differently than items that did not. One scenario being fixed here was absurd: a parent Rectangle (which never handles pointer events on its own) got an implicit grab in deliverMatchingPointsToItem() and thus stole the grab from a handler (!), during delivery of a MouseButtonDblClick (!!), just because the event happened to remain accepted, even though no item or handler reacted to it directly. The Rectangle needs to ignore() the event to avoid that, just as all Items now do by default. Then it turns out that we don't need a stateful allowDoubleClick anymore: the logic is more consistent without it. Items can handle double-clicks, but they don't by default, as with any other pointer event. Pointer handlers don't handle MouseButtonDblClick because they detect double-clicks in their own way, and that's enforced by simply not sending those events to handlers. Passive grabs should be retained regardless of the interloper MouseButtonDblClick event: items that handle it cannot cancel a handler's passive grab. They can steal a handler's exclusive grab, but that should be prevented in other ways, such as ignoring the event so that there is no accidental implicit grab. Reverts 0e3adb65b0e9c44fa6e202630ff57c907ecf0820. DeliveryAgent no longer calls clearPassiveGrabbers() directly as QQuickWindow did then; and it also no longer delivers MouseButtonDblClick the same as a press event. QSinglePointEvent::isBeginEvent() returns false in that case, so deliverPressOrReleaseEvent() is not called. A couple of existing tests now need to avoid generating double-clicks, but they were not trying to test that anyway. New tests are added (test coverage of double-clicks has been unfortunately sparse so far). Fixes: QTBUG-102625 Change-Id: If74baff68ffc46b8b403d37f4e10ddf6b159d40c Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Doris Verria <doris.verria@qt.io> Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io> (cherry picked from commit 72651a50f83aa72998822312c7b5c6235d28978f) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
* QQuickDeliverAgent: don't propagate hover to siblingsRichard Moe Gustavsen2022-03-271-0/+1
| | | | | | | | | | | | | | From testing Qt 6.1, hover events should not propagate between siblings. As soon as a leaf item is found that receives a hover events, the event should only propagate up the parent chain starting from the leaf item. Change-Id: I7448f5322f529addb2260b0ee2b02d2cfadb55e1 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Mitch Curtis <mitch.curtis@qt.io> Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io> (cherry picked from commit 499828b855d125ac236917f6ed01d8f1e7d88505) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
* Detach QEventPoint instances during touch compression; test & docsShawn Rutledge2022-02-041-0/+1
| | | | | | | | | | | | | | | | | | | | If we don't detach, they could be modified between the time that the event is stored (delayed) until it's delivered. QQuickDeliveryAgentPrivate::compressTouchEvent() had no explicit test coverage until now; in fact, most tests call QQuickTouchUtils::flush() after every touch event to ensure that it gets delivered immediately. Also add internal docs. Fixes: QTBUG-97185 Fixes: QTBUG-98486 Fixes: QTBUG-98543 Change-Id: I6fd76651ca6fbf15169c44d4d9dbbeb7dc7e3a71 Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io> Reviewed-by: Jan Arve Sæther <jan-arve.saether@qt.io> (cherry picked from commit d08038ba7015dc681c95654f7fe5e54b60c2e55c) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
* Fix setting the focus reason in Qt Quick ControlsVolker Hilsheimer2021-12-041-1/+1
| | | | | | | | | | | | | | | | | | | | | | | Focus might go to the content item, which is a QQuickItem that has no concept of either focusPolicy or focusReason. For Qt Quick Controls to update the focusReason property when an item in it's item tree receives or loses focus, it has to install itself as a notification listener on the item. However, QQuickItemChangeListener didn't have any notification type for focus changes. Add the new change type, and notify listeners whenever the an item's focus changes. Focus scoping might mean that an item never loses focus, but nevertheless loses active focus. To be able to update items recursively with the correct focusReason, add the reason parameter to the QQuickDeliveryAgent helper function. Fixes: QTBUG-75862 Pick-to: 6.2 Change-Id: I3d19b722bb07b55416b8cfbb4a9cdb0edd0da3ec Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
* qquickdeliveryagent: Fix drag events being sent in the wrong orderMaximilian Goldstein2021-12-021-1/+3
| | | | | | | | | | | | When a former drag event target is on a higher or the same z-level as the new target, send the QDragLeaveEvent before the QDragEnterEvent. [ChangeLog][Quick][Fix] Now sends DragArea leave events before enter events when appropriate (QTBUG-82263) Pick-to: 6.2 Fixes: QTBUG-82263 Change-Id: Ibe76000cbe76748ee8928e4b98a92c38eff5b59c Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
* Move Q_DECLARE_PUBLIC to the public sectionThiago Macieira2021-11-271-1/+1
| | | | | | | This is now required to use QObjectPrivate::connect. Change-Id: Iccb47e5527544b6fbd75fffd16b8bd87f0818ad5 Reviewed-by: Marc Mutz <marc.mutz@qt.io>
* QQuickHoverHandler: don't use passive grabsRichard Moe Gustavsen2021-07-011-2/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | QQuickDeliveryAgent will clear the list of passive grabbers when we deliver: 1. a QPointerEvent::isEndEvent() from deliverPointerEvent() 2. a QEventPoint::Pressed event from deliverPressOrReleaseEvent() In other words, QQuickDeliveryAgent will clear the list of grabbers whenever it receives a mouse press or release. This doesn't work well with hover handlers, which were using passive grabs to ensure receiving updates: they also lost their grabs on press and release. This has some implications: 1. the list of hover items (QQuickDeliveryAgentPrivate::hoverItems) will no longer be in sync with the items we deliver events to. 2. a hover handler stacked underneath another hover handler will stop working. The reason is that QQuickDeliveryAgent detects that hoverItems is not empty, and as such, assumes that all handlers will receive events from their passive grabs. (which is no longer the case after the clear) So letting hover handlers rely on passive grabbing currently fails. It was also confusing that we delivered some of the hover events from deliverHoverEvent(), and others from passive grabs in deliverPointerEvent(). In Qt Quick 3D, when the hover is delivered because of a passive grab, we need to use sceneTransform; but when picking is done, the transform was already done at the same time. But hover events that come from flushFrameSynchronousEvents() always need to go through picking, and that happens frequently, so it's more consistent if we just rely on it all the time. In addition, the previous solution was assuming that only one leaf item would be under the mouse. This fails when you have siblings that overlap (and each sibling has HoverHandlers). While we could try to be more careful about when, and which, grabbers we clear here and there from QQuickDeliveryAgent, it seems better to dodge the whole passive grabber logic for hover handlers, and instead send all hover events directly from deliverHoverEvent(). This because we anyway need to traverse all the items in the application on each pointer move to check if new items are being hovered. So we might as well send out hover events in the same go. That way the logic becomes a bit easier to follow, and don't need to worry about keeping the hoveredItems list in sync with passive grabbing. tst_qquickhoverhandler: hoverHandlerAndUnderlyingMouseArea: - HoverHandlers have (conceptually) never stopped hover events from propagating to the parent. Still, this test checks that a MouseArea underneath a HoverHandler is not hovered. Since this now actually works, the test is changed. mouseAreaAndUnderlyingHoverHandler: - MouseArea now accepts hover events, which will stop propagation. This is done to preserve the same behavior as before. But this also means that a MouseArea that has another MouseArea as a direct child (which was a special case from before) will no longer get hover events after the child has accepted them. For the same reason, an item's HoverHandlers will also not get hover events if there is a child that is accepting them, as in this test case. Fixes: QTBUG-34882 Fixes: QTBUG-63670 Pick-to: 6.2 Change-Id: Id38042bcbd1c3ca5403b4b81b875b84196fcfc76 Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
* Use QQDeliveryAgent::sceneTransform, if set, in QQuickItem::mapFromGlobalShawn Rutledge2021-05-051-0/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | During dragging of a QEventPoint, Flickable computes the drag delta as pos - mapFromGlobal(point.globalPressPosition()) We cannot use only the global position delta, because the Flickable might be transformed in 2D (by setting rotation on it or in a parent, as in tst_qquickflickable::clickAndDragWhenTransformed) or in 3D (by mapping it onto a Model object). So we really need QQuickItem::mapFromGlobal() to actually work regardless how many of these transformations are in place. This is just the beginning: we have a lot of these mapFrom/To functions; but it's enough for the Flickable in the quick3d/dynamictexture example to work better. Without this fix, if you tried to drag a yellow note on the door panel, at the very first drag ListView saw a large delta and considered its drag threshold exceeded immediately, whereas the DragHandler on the note saw a very small delta; so ListView grabbed and DragHandler did not steal it: it relies on having "first dibs". When the drag threshold is exceeded, Flickable merely plans to grab on the next event rather than grabbing immediately, and therefore a child has a chance to grab first. Therefore it's normally OK for DragHandler to simply become the first exclusive grabber when the drag threshold is exceeded, and not steal the grab from another item (although grabPermissions can be changed to allow stealing if necessary). However this means that we continue to enforce the drag threshold in local (transformed) coordinates: if Flickable should wait until the user drags 10 pixels, but it's scaled to half-size, it will start dragging after only 5 pixels of movement, for example. Pick-to: 6.1 Task-number: QTBUG-92944 Change-Id: Id01cc833ca80850ca18a965adf47f435e43e20ed Reviewed-by: Andy Nichols <andy.nichols@qt.io>
* Store memory of grabbing agents in EventPointDataShawn Rutledge2021-05-051-3/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | QQuickDeliveryAgentPrivate::grabberAgent(event, point) was too naive: it's not only that each point could be delivered by a different agent, but also each point could have an exclusive grab in the context of one agent and multiple passive grabs in the contexts of different agents. E.g. in qtquick3d/examples/quick3d/dynamictexture, many grabs can occur if you press on a door: the View3D has a TapHandler to pick the door, so that you can click to open; each Panel has a TapHandler to defocus whichever TextArea has focus; there is a ListView for dragging through the panel delegates sideways; if you press on a yellow note, its DragHandler prepares to start dragging; etc. So at least, a TapHandler in the subscene and the other one in the View3D need to get passive grabs, and need to receive the release event in the correct coordinate system, to detect taps. When we apply the sceneTransform of a particular agent before re-delivering an update or a release, based on the grab, it has to be in the correct coordinate system for that grabber. So on grab, we use EventPointData::exclusiveGrabberContext or passiveGrabbersContext to store the pointer to the QQDeliveryAgent that was doing the delivery when the grab occurred. When we deliver the next event to a grabber, we also look up the correct DA to do the delivery. This gets done twice: once in QQuickWindow::event() to find the DAs that need to handle the event, and in QQDeliveryAgentPriv::deliverUpdatedPoints() to ignore passive grabbers for which a different DA is responsible. The failsafe "never allow any kind of grab to persist after release" is moved to QQuickWindow::event because we don't want to do it prematurely in a subscene agent, and ATM we don't require the main DA to deliver last: it depends on the order in EventPointData::passiveGrabbersContext. QQuickPointerHandler::onGrabChanged() should only be called from the relevant DA, to avoid overreaction: that is, the DA that is delivering an event at the time the grab occurs. QQDelAgentPrivate::onGrabChanged() gets called on all DA instances, but only one of them is supposed to store itself as the assigned DA for handling a particular point ID. It's not always the same as QQuickItemPrivate::deliveryAgent(): that goes astray when the same 2D subscene is mapped to the main scene and also onto multiple QQ3D models. In that case, if the user interacts directly with the 2D scene, the main DA should be assigned; or if the user interacts with one of the mapped subscenes, its DA should be assigned. We have to stop delivering to subscenes when the event is accepted, at least, because of the usual convention that delivery is done when the event remains accepted rather than being purposely ignored. So in the dynamictexture example, if you click on a TextEdit on one of the doors, it receives the event first (because it's on top) and accepts it; that stops delivery in QQuickDeliveryAgentPrivate::deliverPressOrReleaseEvent(), and now also stops QQuickWindow::event() from visiting the next subscene, or the main scene, so that the TapHandler in the View3D doesn't get clicked, and the doors don't open. Task-number: QTBUG-92944 Pick-to: 6.1 Change-Id: I1b4520b665e58874d17a936024cf62e4c7175d8e Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Andy Nichols <andy.nichols@qt.io>
* Fix build without features.wheeleventTasuku Suzuki2021-04-231-0/+2
| | | | | Change-Id: I03320c39431d49456e8baba66609e4e9c8850587 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* Add QQuickDeliveryAgentPrivate::isHoverEvent()Shawn Rutledge2021-03-111-0/+1
| | | | | | | It's just another type-switching function, needed in QtQuick3D now. Change-Id: I6ecc6d82177368556cbab1b3fd038ce325f39496 Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
* QQuickDeliverAgent: change sendHoverEvent signatureRichard Moe Gustavsen2021-03-091-1/+1
| | | | | | | | | | Now we intend to always send pre-accepted hover events, for consistency with event delivery in the rest of Qt. This is mostly done as a preparation for later patches. Change-Id: I5833b5ed9971057ace272a7bfc390fd336cc2e7d Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
* Move event delivery from QQWindow to QQuickDeliveryAgentShawn Rutledge2021-02-241-0/+209
QQuickWindow owns QQuickRootItem which owns QQuickDeliveryAgent, so for every window there's an object responsible for event delivery, while the window itself is mainly responsible for rendering (separation of concerns). However, QQuickRootItem and QQuickDeliveryAgent can now be used in cases where the scene doesn't directly belong to a window, such as when a Qt Quick sub-scene is mapped somewhere into a Qt Quick 3D scene. In that case, we must remember which delivery agent was in use at the time when a QEventPoint is grabbed and deliver subsequent updates via the same DA. There's also a QQuickDeliveryAgent::Transform abstraction which subscene-management code (such as QQuick3DViewport) can implement, to provide a formula to map the window's scene coordinates to subscene coordinates; if defined, it will be used during delivery of subsequent updates to existing grabbers. Task-number: QTBUG-84870 Change-Id: I70b433f7ebb05d2e60214ff3192e05da0aa84a42 Reviewed-by: Andy Nichols <andy.nichols@qt.io>