From 7d6f2e71e374b95d600467602b770a8c8cf85d07 Mon Sep 17 00:00:00 2001 From: Kristian Bendiksen Date: Fri, 11 Sep 2026 10:05:31 +0200 Subject: [PATCH] Preserve dock parents to avoid black QOpenGLWidget views Switching dock tabs reparents inactive non-native widgets to nullptr, temporarily turning them into top-level windows. For QOpenGLWidget children, these transitions can invalidate Qt composition resources even when shared OpenGL contexts remain alive, leading to black frames or views that recover only after another repaint. The internalWinId() condition restricted parent preservation to dock widgets with an existing native window handle. A non-native dock can also contain a QOpenGLWidget, which normally renders into an offscreen framebuffer that Qt composites into the containing window. Such docks need protection from temporary top-level transitions too, so native-window status is not an appropriate condition for preserving their parent. Remove the internalWinId() condition and keep detached widgets parented to the dock manager regardless of whether they are native. This neither creates nor removes native window handles. Explicitly hide detached widgets before reparenting because setParent() may be a no-op. Retain the null-parent fallback when no dock manager is available and update the layout ownership documentation. This avoids forcing native windows or adding extra repaint requests. No application-specific environment variable is required. Related ResInsight issue: https://github.com/OPM/ResInsight/issues/14708 --- src/DockAreaWidget.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/DockAreaWidget.cpp b/src/DockAreaWidget.cpp index ff40aa5f..7b0e2f3b 100644 --- a/src/DockAreaWidget.cpp +++ b/src/DockAreaWidget.cpp @@ -72,9 +72,8 @@ static bool isAutoHideFeatureEnabled() /** * Internal dock area layout mimics stack layout but only inserts the current * widget into the internal QLayout object. - * \warning Only the current widget has a parent. All other widgets - * do not have a parent. That means, a widget that is in this layout may - * return nullptr for its parent() function if it is not the current widget. + * Inactive widgets are hidden and parented to the dock manager when available, + * rather than becoming temporary top-level windows. */ class CDockAreaLayout { @@ -85,12 +84,14 @@ class CDockAreaLayout QWidget* m_CurrentWidget = nullptr; /** - * Detaches a widget without turning an existing native window into a top-level window. + * Detaches a widget while keeping it hidden and parented to the dock manager. */ void detachWidget(QWidget* Widget) { + // setParent() may be a no-op; keep inactive docks hidden explicitly. + Widget->hide(); CDockAreaWidget* DockArea = qobject_cast(m_ParentLayout->parentWidget()); - if (Widget->internalWinId() && DockArea && DockArea->dockManager()) + if (DockArea && DockArea->dockManager()) { Widget->setParent(DockArea->dockManager()); }