aboutsummaryrefslogtreecommitdiffstats
path: root/src/quickwidgets/qquickwidget.cpp
diff options
context:
space:
mode:
authorPaul Olav Tvete <paul.tvete@qt.io>2021-11-29 17:23:18 +0100
committerPaul Olav Tvete <paul.tvete@qt.io>2021-12-07 02:40:56 +0100
commit8c0b1e06d9679676d12ff92db981198077eeda76 (patch)
treed908b91d72bded41cdbfce88cd6d099d48da898a /src/quickwidgets/qquickwidget.cpp
parent61e325460ce810b645fc3595ae38a86468c289a3 (diff)
Fix focus for items inside a QQuickWidget in a QGraphicsProxyWidget
QQuickWidgetRenderControl::renderWindowFor() did not take the proxy widget into account, making it impossible to give focus to items inside a QGraphicsProxyWidget by clicking on the item. This patch is based on a patch by Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>, which fixed renderWindowFor(), but did not handle the case where a proxy widget was in multiple views. This version of the patch adds QQuickRenderControlPrivate::isRenderWindowFor(), which allows all the views of the proxy widget to handle focus. This patch also carefully preserves the non-obvious feature of the previous implementation where all windows are considered to have focus if QGuiApplication::focusWindow() == nullptr. [ChangeLog][QuickWidget][Quick items inside a QuickWidget that is inside a QGraphicsProxyWidget can now get focus by clicking.] Fixes: QTBUG-91479 Pick-to: 6.2 Change-Id: I4a6fbbbeda2d14b5a6d8eb8218d5b14a3404d9c3 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Diffstat (limited to 'src/quickwidgets/qquickwidget.cpp')
-rw-r--r--src/quickwidgets/qquickwidget.cpp78
1 files changed, 72 insertions, 6 deletions
diff --git a/src/quickwidgets/qquickwidget.cpp b/src/quickwidgets/qquickwidget.cpp
index d0cc6f9048..37b3823bde 100644
--- a/src/quickwidgets/qquickwidget.cpp
+++ b/src/quickwidgets/qquickwidget.cpp
@@ -83,6 +83,11 @@
#include <QtQuick/qquickgraphicsdevice.h>
#include <QtQuick/qquickrendertarget.h>
+#include "private/qwidget_p.h"
+
+#include <QtWidgets/qgraphicsscene.h>
+#include <QtWidgets/qgraphicsview.h>
+
QT_BEGIN_NAMESPACE
QQuickWidgetOffscreenWindow::QQuickWidgetOffscreenWindow(QQuickWindowPrivate &dd, QQuickRenderControl *control)
@@ -104,19 +109,80 @@ public:
}
};
+class QQuickWidgetRenderControlPrivate;
+
class QQuickWidgetRenderControl : public QQuickRenderControl
{
+ Q_DECLARE_PRIVATE(QQuickWidgetRenderControl)
+public:
+ QQuickWidgetRenderControl(QQuickWidget *quickwidget);
+ QWindow *renderWindow(QPoint *offset) override;
+
+};
+
+class QQuickWidgetRenderControlPrivate : public QQuickRenderControlPrivate
+{
public:
- QQuickWidgetRenderControl(QQuickWidget *quickwidget) : m_quickWidget(quickwidget) {}
- QWindow *renderWindow(QPoint *offset) override {
- if (offset)
- *offset = m_quickWidget->mapTo(m_quickWidget->window(), QPoint());
- return m_quickWidget->window()->windowHandle();
+ Q_DECLARE_PUBLIC(QQuickWidgetRenderControl)
+ QQuickWidgetRenderControlPrivate(QQuickWidgetRenderControl *renderControl, QQuickWidget *qqw)
+ : QQuickRenderControlPrivate(renderControl)
+ , m_quickWidget(qqw)
+ {
+ }
+
+ bool isRenderWindow(const QWindow *w) override {
+#if QT_CONFIG(graphicsview)
+ QWidgetPrivate *widgetd = QWidgetPrivate::get(m_quickWidget);
+ auto *proxy = (widgetd && widgetd->extra) ? widgetd->extra->proxyWidget : nullptr;
+ auto *scene = proxy ? proxy->scene() : nullptr;
+ if (scene) {
+ for (const auto &view : scene->views()) {
+ if (view->window()->windowHandle() == w)
+ return true;
+ }
+ }
+
+ return m_quickWidget->window()->windowHandle() == w;
+#endif
}
-private:
QQuickWidget *m_quickWidget;
};
+QQuickWidgetRenderControl::QQuickWidgetRenderControl(QQuickWidget *quickWidget)
+ : QQuickRenderControl(*(new QQuickWidgetRenderControlPrivate(this, quickWidget)), nullptr)
+{
+}
+
+QWindow *QQuickWidgetRenderControl::renderWindow(QPoint *offset)
+{
+ Q_D(QQuickWidgetRenderControl);
+ if (offset)
+ *offset = d->m_quickWidget->mapTo(d->m_quickWidget->window(), QPoint());
+
+ QWindow *result = nullptr;
+#if QT_CONFIG(graphicsview)
+ QWidgetPrivate *widgetd = QWidgetPrivate::get(d->m_quickWidget);
+ if (widgetd->extra) {
+ if (auto proxy = widgetd->extra->proxyWidget) {
+ auto scene = proxy->scene();
+ if (scene) {
+ const auto views = scene->views();
+ if (!views.isEmpty()) {
+ // Get the first QGV containing the proxy. Not ideal, but the callers
+ // of this function aren't prepared to handle more than one render window.
+ auto candidateView = views.first();
+ result = candidateView->window()->windowHandle();
+ }
+ }
+ }
+ }
+#endif
+ if (!result)
+ result = d->m_quickWidget->window()->windowHandle();
+
+ return result;
+}
+
void QQuickWidgetPrivate::initOffscreenWindow()
{
Q_Q(QQuickWidget);