Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-101398

grabPermissions cannot prevent an Item stealing grab from a handler in Qt 6

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Reported
    • Priority: P1: Critical
    • Resolution: Unresolved
    • Affects Version/s: 6.0, 6.3.0 Beta2
    • Fix Version/s: None
    • Labels:
      None

      Description

      In Qt 5 we had this code:

      void QQuickEventPoint::setGrabberItem(QQuickItem *grabber)
      {
          if (grabber != m_exclusiveGrabber.data()) {
              QQuickPointerHandler *oldGrabberHandler = grabberPointerHandler();
              if (oldGrabberHandler && !oldGrabberHandler->approveGrabTransition(this, grabber))
                  return;
              if (Q_UNLIKELY(lcPointerGrab().isDebugEnabled())) {
                  qCDebug(lcPointerGrab) << pointDeviceName(this) << "point" << Qt::hex << m_pointId << pointStateString(this) << "@" << m_scenePos
                                         << ": grab" << m_exclusiveGrabber << "->" << grabber;
              }
      

      In Qt 6, we have QPointerEvent::setExclusiveGrabber() and we're using it directly. It's in QtGui, and knows nothing about how to get approval for a grab transition. So it seems we will need to write a wrapper function in Qt Quick to restore this feature, or else come up with some sort of callback mechanism so that Qt Quick can provide an approver function that QtGui can call. And the nice thing about an approver function would be that even if e.g. a QWidget or something in Qt Quick 3D tries to take the grab from a handler, it would have a chance to say no (in case of hybrid applications); whereas with a wrapper function just for Qt Quick, we'd have to remember to use it everywhere (add a note to QPointerEvent::setExclusiveGrabber() that it should never be called directly from Qt Quick).

      It comes up when trying to use a TapHandler to open a context menu on a TextArea, for example:

      import QtQuick
      import QtQuick.Controls
      
      TextArea {
          id: textArea
          focus: true
          text: "test message"
          TapHandler {
              acceptedButtons: Qt.RightButton
              gesturePolicy: TapHandler.ReleaseWithinBounds
              grabPermissions: PointerHandler.CanTakeOverFromAnything
              onTapped: contextMenu.popup(point.position)
          }
          Menu {
              id: contextMenu
              MenuItem { text: "Cut" }
              MenuItem { text: "Copy" }
              MenuItem { text: "Paste" }
          }
      }
      

      When pressing the right mouse button, TapHandler gets a grab first (gesturePolicy makes it an exclusive grab), and TextArea gets to take over the grab without even asking, merely by accepting the event. That is because QQuickDeliveryAgentPrivate::deliverMatchingPointsToItem() calls pointerEvent->setExclusiveGrabber() directly. But we have many such places in Qt Quick.

        Attachments

        1. textAreaTapHandler.qml
          0.5 kB
          Shawn Rutledge

          Issue Links

          For Gerrit Dashboard: QTBUG-101398
          # Subject Branch Project Status CR V

            Activity

              People

              Assignee:
              srutledg Shawn Rutledge
              Reporter:
              srutledg Shawn Rutledge
              Votes:
              1 Vote for this issue
              Watchers:
              3 Start watching this issue

                Dates

                Created:
                Updated:

                  Gerrit Reviews