diff options
author | Laszlo Agocs <laszlo.agocs@qt.io> | 2021-06-10 17:42:54 +0200 |
---|---|---|
committer | Laszlo Agocs <laszlo.agocs@qt.io> | 2021-06-18 15:14:02 +0200 |
commit | e6a969954a9e6865e5f662acd1d949561f8ef3be (patch) | |
tree | eb0e77db06be3ce75fc90f11fabeeaf389c8dc5e /tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp | |
parent | 29789ff0eabc2ea91a21526c475e5a8c0126a7af (diff) |
Do not alter a widget's backing window's format once created
Changing anything on a QWindow's QSurfaceFormat has zero and null
effects once the underlying native window has been created. Letting
QWidget update the format is wrong in this case, because we always
expect that the value returned from QWindow::format() reflects
reality.
(reality being the settings with which the underlying native resource
was created, which is typically frozen after QWindow::create(), not
the state of some QWidget attribute. There are certain exceptions to
this, such as when preparing to recreate the underlying native window,
in which case one will want to update all relevant fields of the
format based on the current values of the widget attributes, which is
exactly what QWidgetPrivate::create() implements, and that's good.)
Such a mismatch can have fatal consequences when OpenGL and friends
are involved, but this always depends heavily on the platform and
windowing system. For example, claiming that the alpha buffer size is
0 when the native window was created with 8, or vice versa, can break
OpenGL-related code (both in Qt itself and in applications), that
tries to create a QOpengGLContext configured based on what
QWindow::format() returns. If that format describes settings that are
incompatible with the actual underlying native window, we end up with
the classic Invalid pixel format, EGL_BAD_MATCH, and alike errors.
This is exactly what is happening when a QOpenGLWidget (or
QQuickWidget) is placed in a QDockWidget where one of the ancestors is
forced to native (winId() was called or WA_NativeWindow was set). When
undocking, various code paths in QWidget will try to update the opaque
flag of the widget, which in turn calls updateIsTranslucent. Now, if
this function unconditionally changes the alphaBufferSize in the
QWindow's QSurfaceFormat (even though this is completely futile to do,
it has no visible effect in practice), we get the problem described
above: rendering breaking down due to OpenGL contexts created with a
pixel format incompatible with the native window.
Prevent all this by not touching the format once the QWindow has a
QPlatformWindow. This is the right thing to do, regardless of the bug
in question: a window's (or context's or any other native resource
wrapping class's) format must describe the underlying native resource
and must never deviate, unless we are preparing to create a new native
resource underneath.
When it comes to the autotest, this changes the test added in
555661b625c40f21a6a3e4c73e928a6e8a46db20: the autotest logic is
inverted because what we should test for is that the QSurfaceFormat
stays untouched once the application makes a - futile - attribute
change on the widget.
Fixes: QTBUG-85714
Pick-to: 6.2 6.1
Change-Id: I7bf90711867e8a0fd474895625bf9530a7821fd5
Reviewed-by: Paul Olav Tvete <paul.tvete@qt.io>
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
Reviewed-by: Andy Nichols <andy.nichols@qt.io>
Diffstat (limited to 'tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp')
-rw-r--r-- | tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp | 11 |
1 files changed, 8 insertions, 3 deletions
diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp index 8992a0b051..7ca08993ab 100644 --- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp +++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp @@ -9316,10 +9316,15 @@ void tst_QWidget::translucentWidget() QCOMPARE(actual,expected); const QWindow *window = label.windowHandle(); - const QSurfaceFormat translucentFormat = window->requestedFormat(); + const QSurfaceFormat translucentFormat = window->format(); label.setAttribute(Qt::WA_TranslucentBackground, false); - const QSurfaceFormat opaqueFormat = window->requestedFormat(); - QVERIFY(translucentFormat != opaqueFormat); + // Changing WA_TranslucentBackground with an already created native window + // has no effect since Qt 5.0 due to the introduction of QWindow et al. + // This means that the change must *not* be reflected in the + // QSurfaceFormat, because there is no change when it comes to the + // underlying native window. Otherwise the state would no longer + // describe reality (the native window) See QTBUG-85714. + QVERIFY(translucentFormat == window->format()); } class MaskResizeTestWidget : public QWidget |