Reputation: 2834
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
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
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