Proxy mouse/touch events



  • There has been some prior discussion, e.g.

    "fake events":http://stackoverflow.com/questions/18849663/generating-simulating-fake-mouse-events-in-qt

    but I am trying to get this working correctly with Qt5.4 and QQuickView. The simple project below demonstrates. A remote or proxy cursor moves within the main window and if it coincides with an UI element such as a button, a MouseEvent is generated that fakes a users action. The position of the proxy click can be anywhere but the event generated uses the position of the proxy cursor. So the button gets pressed.

    The ClickSimulator class creates an event and sends it to an UI element. This appears to work but the event is never received by the QML id realbutton.

    I am using prebuilt Qt5.4 and I am targeting multiple platforms. This is a genrally useful utility so I hope someone has done this and can spot some problem in my code.

    main.cpp
    @#include <QApplication>
    #include <QQmlApplicationEngine>
    #include <QQuickView>
    #include "clicksimulator.h"

    int main(int argc, char *argv[])
    {
    QApplication app(argc, argv);

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    
    QObject *topLevel = engine.rootObjects().value(0);
    QQuickWindow *window = qobject_cast<QQuickWindow *>(topLevel);
    
    QQuickView *view = new QQuickView;
    view->setParent(window);
    
    // Setup the finger click handler
    ClickSimulator sim(window);
    sim.connect(window, SIGNAL(newfingerpos(int, int)),  SLOT(proxyClick(int, int)));
    QObject::connect(view->engine(), SIGNAL(quit()), view, SLOT(close()));
    
    return app.exec();
    

    }
    @

    main.qml
    @import QtQuick 2.4
    import QtQuick.Controls 1.3
    import QtQuick.Window 2.2
    import QtQuick.Dialogs 1.2

    ApplicationWindow {
    title: qsTr("Hello World")
    width: 640
    height: 480
    visible: true

    signal newfingerpos(int x, int y)
    
    // This is the overlay that catches the finger clicks
    Button {
        objectName: "overlaybutton"
        anchors.fill: parent
        opacity: 0.3
        z: 2
    
        MouseArea {
            anchors.fill: parent
            propagateComposedEvents: false
            onClicked: {
                mouse.accepted = true
                console.log("overlay tapped")
                newfingerpos(50, 50)
            }
        }
    }
    
    // This is the 'real' button but it will only be pressed from the newfingerpos signal
    Button {
        id: button
        objectName: "realbutton"
        width: 100; height: 100
        x:25; y:25
        text: qsTr("Press Me")
        z: 1
    
        MouseArea {
            anchors.fill: parent
            onClicked: {
                console.log("button pressed by proxy event")
                console.log("Mouse x: ", mouseX, "Mouse y: ", mouseY)
            }
        }
    }
    

    }
    @

    clicksimulator.h
    @#pragma once

    #include <QObject>
    #include <QQuickView>

    class ClickSimulator : public QObject
    {
    Q_OBJECT

    public:
    explicit ClickSimulator(QQuickWindow* viewer, QObject *parent = 0);

    public slots:
    void proxyClick(int, int);

    private:
    QQuickWindow* _viewport;

    };
    @

    clicksimulator.cpp
    @#include "clicksimulator.h"

    #include <QMouseEvent>
    #include <QQuickItem>

    ClickSimulator::ClickSimulator(QQuickWindow* viewport, QObject *parent) :
    QObject(parent),
    _viewport(viewport)
    {
    }

    void ClickSimulator::proxyClick(int x, int y)
    {
    if (_viewport != NULL) {
    QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(x, y), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
    QQuickItem* controlarea = _viewport->findChild<QQuickItem*>("realbutton");
    const bool isSent = _viewport->sendEvent(controlarea, &pressEvent);
    qDebug() << "'Press' at (" << x << "," << y << ") successful? " << isSent;

        QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(x, y), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
        const bool isRlseSent = _viewport->sendEvent(controlarea, &releaseEvent);
        qDebug() << "'Release' at (" << x << "," << y << ") successful? " << isRlseSent;
    
        _viewport->update();
    }
    

    }
    @

    mousetest.pro
    @TEMPLATE = app

    QT += qml quick widgets

    SOURCES += main.cpp
    clicksimulator.cpp

    RESOURCES += qml.qrc

    Additional import path used to resolve QML modules in Qt Creator's code model

    QML_IMPORT_PATH =

    Default rules for deployment.

    include(deployment.pri)

    HEADERS +=
    clicksimulator.h
    @


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.