Make keyboard events work in QQuickWidget

Right now many cases outside of text input fields are simply broken,
e.g. one cannot use a TableView or other controls with the keyboard.

Removing the seemingly unnecessary focusObject() solves all problems
since this way key events get delivered to the QQuickWidget which in
turn forwards to the QQuickWindow.

Directly routing into the QQuickWindow's focusObject(), which can be
any item in the scene is wrong since it skips a big part of
QQuickWindow's event handling logic.

Task-number: QTBUG-45757
Change-Id: Ie53b9003d156ab019fa4b9cf461e209990e738f7
Reviewed-by: Paul Olav Tvete <paul.tvete@qt.io>
This commit is contained in:
Laszlo Agocs 2017-02-22 16:16:14 +01:00 committed by Simon Hausmann
parent b82d5bb418
commit 0dbc575c1a
3 changed files with 31 additions and 6 deletions

View File

@ -353,10 +353,9 @@ QImage QQuickWidgetPrivate::grabFramebuffer()
return renderControl->grab();
}
QObject *QQuickWidgetPrivate::focusObject()
{
return offscreenWindow ? offscreenWindow->focusObject() : 0;
}
// Intentionally not overriding the QQuickWindow's focusObject.
// Key events should go to our key event handlers, and then to the
// QQuickWindow, not any in-scene item.
/*!
\module QtQuickWidgets

View File

@ -99,8 +99,6 @@ public:
void destroyContext();
void handleContextCreationFailure(const QSurfaceFormat &format, bool isEs);
QObject *focusObject() Q_DECL_OVERRIDE;
#if QT_CONFIG(opengl)
GLuint textureId() const Q_DECL_OVERRIDE;
QImage grabFramebuffer() Q_DECL_OVERRIDE;

View File

@ -58,6 +58,7 @@ private slots:
void grabBeforeShow();
void reparentToNewWindow();
void nullEngine();
void keyEvents();
};
@ -337,6 +338,33 @@ void tst_qquickwidget::nullEngine()
QVERIFY(widget.engine());
}
class KeyHandlingWidget : public QQuickWidget
{
public:
void keyPressEvent(QKeyEvent *e) override {
if (e->key() == Qt::Key_A)
ok = true;
}
bool ok = false;
};
void tst_qquickwidget::keyEvents()
{
// A QQuickWidget should behave like a normal widget when it comes to event handling.
// Verify that key events actually reach the widget. (QTBUG-45757)
KeyHandlingWidget widget;
widget.setSource(testFileUrl("rectangle.qml"));
widget.show();
QVERIFY(QTest::qWaitForWindowExposed(widget.window(), 5000));
// Note: send the event to the QWindow, not the QWidget, in order
// to simulate the full event processing chain.
QTest::keyClick(widget.window()->windowHandle(), Qt::Key_A);
QTRY_VERIFY(widget.ok);
}
QTEST_MAIN(tst_qquickwidget)
#include "tst_qquickwidget.moc"