James
James

Reputation: 2834

Sending Key Events to a Qt QML WebEngineView

I have a Qt QML WebEngineView that I want to send key press events to from a custom keyboard. Is there a way to programmatically send keypress events to the view? To be clear, I'm only having trouble with WebEngineViews, and not other QML elements.

Theres some discussion online on how to do this with QWidgets, but I'm trying to get things working with Qt Quick/QML.

[1] https://forum.qt.io/topic/69439/how-do-you-send-key-events-to-qwebengineview-if-sendkey-doesn-t-work

Upvotes: 3

Views: 1734

Answers (2)

Mohammad Kanan
Mohammad Kanan

Reputation: 4582

Observing QTBUG-46251 and QTBUG-43602, WebEngineView does its own key handling for scrolling content.

They suggest work-around with Action

ApplicationWindow {
    width: 1280
    height: 720
    visible: true
    WebEngineView {
        id: webview
        url: "http://www.qt-project.org"
        anchors.fill: parent
        focus: true;
    }

    Action {
        shortcut: "Escape"
        onTriggered: {
            console.log("Escape pressed.");
            Qt.quit();
        }
    }
}

Upvotes: 2

talamaki
talamaki

Reputation: 5472

You can't do it purely in QML side but you can write your own QObject and register it as a context property.

KeyEventSender class

#include <QObject>
#include <QGuiApplication>
#include <QQuickItem>
#include <QQuickWindow>

class KeyEventSender : public QObject
{
    Q_OBJECT
public:
    explicit KeyEventSender(QObject *parent = nullptr) : QObject(parent) {}
    Q_INVOKABLE void simulateKey(int key, Qt::KeyboardModifiers modifiers, const QString &text) {
        QQuickItem *r = qobject_cast<QQuickItem *>(QGuiApplication::focusObject());
        if (r) {
            bool autorep = false;
            QKeyEvent press = QKeyEvent(QKeyEvent::KeyPress, key, modifiers, text, autorep);
            r->window()->sendEvent(r, &press);
            QKeyEvent release = QKeyEvent(QKeyEvent::KeyRelease, key, modifiers, text, autorep);
            r->window()->sendEvent(r, &release);
        }
    }
};

Register it in main()

#include "keyeventsender.h"

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);
    QQmlApplicationEngine engine;
    KeyEventSender k;
    engine.rootContext()->setContextProperty("keyEventSender",&k);

Use it in QML:

    TextField {
        id: text
        anchors.centerIn: parent
        focus: true
    }

    Timer {
        interval: 2000; running: true; repeat: true
        property bool capital: false
        onTriggered: {
            if (!capital)
                keyEventSender.simulateKey(Qt.Key_K, Qt.NoModifier,"k")
            else
                keyEventSender.simulateKey(Qt.Key_K, Qt.ShiftModifier,"K")

            capital = !capital
        }
    }

Notice that the focused item gets the key events. TextField will update like "kKkKkK" when timer triggers.

Upvotes: 2

Related Questions