Search code examples
qtevent-handlingqmlmouseevent

QML: acceptedButtons for Flickable


I have a Flickable with some content that has its own DragHandler.
I want all drags with the left mouse button to be handled by the content's drag handler, and drags with the right mouse button should be handled by the Flickable. Is that possible?

Example code:

Flickable {
    id: canvas

    anchors.fill: parent
    contentWidth: 2*parent.width
    contentHeight: 2*parent.height
    // Something like this
    //acceptedButtons: Qt.RightButton

    Rectangle {
        color: "blue"
        width: canvas.width
        height: canvas.height

        DragHandler {
            acceptedButtons: Qt.LeftButton
            target: null
            onActiveChanged: console.log(`content drag active: ${active}`)
            // Some code to do something with the drag...
        }

        Rectangle {
            color: "yellow"
            anchors.centerIn: parent
            width: 50
            height: 50
        }
    }
}

Goal: I want to move the blue Rectangle inside the Flickable by dragging with the right mouse button, while drag events with the left mouse button are handled by the DragHandler of the blue Rectangle


Solution

  • Looking at the QQuickFlickable source code, I found out that the accepted buttons are statically set to the left button:

    272: q->setAcceptedMouseButtons(Qt::LeftButton);

    So I tried to work around it by introducing another DragHandler, which worked for me:

    Flickable {
        id: canvas
    
        anchors.fill: parent
        contentWidth: 2*parent.width
        contentHeight: 2*parent.height
    
        DragHandler {
            property real _startX
            property real _startY
    
            acceptedButtons: Qt.RightButton
            dragThreshold: 0
            target: null
    
            onActiveChanged: {
                if (active) {
                    _startX = canvas.contentX
                    _startY = canvas.contentY
                }
            }
            onTranslationChanged: {
                canvas.contentX = _startX - translation.x
                canvas.contentY = _startY - translation.y
            }
        }
    
        Rectangle {
            color: "blue"
            width: canvas.width
            height: canvas.height
    
            DragHandler {
                acceptedButtons: Qt.LeftButton
                target: null
                onActiveChanged: console.log(`content drag active: ${active}`)
                // Some code to do something with the drag...
            }
    
            Rectangle {
                color: "yellow"
                anchors.centerIn: parent
                width: 50
                height: 50
            }
        }
    }
    

    It simply imitates the standard behaviour, but allows to use the acceptedButtons property of the DragHandler to control the Flickable with the button I want.
    So far I did not notice any other behaviour of Flickable breaking through this workaround.