From 3af42e04f227aa5ab3462bd468509056cfcd2e1b Mon Sep 17 00:00:00 2001 From: Debian Qt/KDE Maintainers Date: Thu, 13 Apr 2023 00:24:34 +0100 Subject: [PATCH] xcb: recreate xcb window under some conditions Origin: upstream, https://code.qt.io/cgit/qt/qtbase.git/commit/?id=f9e4402ffeef791e Last-Update: 2022-11-24 Some netWmState needs to be set during unmap/hide(), which is too difficult to follow, and causes m_mapped status out of sync very easily sometimes, which we had tried in e946e6895a8517a887ac246905e0769edd766fcc . Destroy the xcb window and recreate new could make the thing much easier. This practice is also used in other platforms, such as cocoa plugin. In Qt 4, the platform window was destroyed and re-created in this situation on all platforms, which was not ported into Qt5. See also the code between setWinId(0) and createWinId() in QWidgetPrivate::setParent_sys() in qwidget_x11.cpp/qwidget_win.cpp/ qwidget_mac.mm. Gbp-Pq: Name recreate_xcb_window.diff --- src/plugins/platforms/xcb/qxcbwindow.cpp | 14 ++++++++++++++ src/plugins/platforms/xcb/qxcbwindow.h | 9 +++++++++ 2 files changed, 23 insertions(+) diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 1c947f348..609e8ac56 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -93,6 +93,8 @@ enum { QT_BEGIN_NAMESPACE +Q_LOGGING_CATEGORY(lcQpaWindow, "qt.qpa.window"); + Q_DECLARE_TYPEINFO(xcb_rectangle_t, Q_PRIMITIVE_TYPE); #undef FocusIn @@ -555,6 +557,7 @@ void QXcbWindow::destroy() } m_mapped = false; + m_recreationReasons = RecreationNotNeeded; if (m_pendingSyncRequest) m_pendingSyncRequest->invalidate(); @@ -689,6 +692,11 @@ void QXcbWindow::setVisible(bool visible) void QXcbWindow::show() { if (window()->isTopLevel()) { + if (m_recreationReasons != RecreationNotNeeded) { + qCDebug(lcQpaWindow) << "QXcbWindow: need to recreate window" << window() << m_recreationReasons; + create(); + m_recreationReasons = RecreationNotNeeded; + } // update WM_NORMAL_HINTS propagateSizeHints(); @@ -904,6 +912,12 @@ void QXcbWindow::setWindowFlags(Qt::WindowFlags flags) if (type == Qt::Popup) flags |= Qt::X11BypassWindowManagerHint; + Qt::WindowFlags oldflags = window()->flags(); + if ((oldflags & Qt::WindowStaysOnTopHint) != (flags & Qt::WindowStaysOnTopHint)) + m_recreationReasons |= WindowStaysOnTopHintChanged; + if ((oldflags & Qt::WindowStaysOnBottomHint) != (flags & Qt::WindowStaysOnBottomHint)) + m_recreationReasons |= WindowStaysOnBottomHintChanged; + const quint32 mask = XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK; const quint32 values[] = { // XCB_CW_OVERRIDE_REDIRECT diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h index 6f5c1f5ed..8de486c6d 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.h +++ b/src/plugins/platforms/xcb/qxcbwindow.h @@ -74,6 +74,13 @@ public: Q_DECLARE_FLAGS(NetWmStates, NetWmState) + enum RecreationReason { + RecreationNotNeeded = 0, + WindowStaysOnTopHintChanged = 0x1, + WindowStaysOnBottomHintChanged = 0x2 + }; + Q_DECLARE_FLAGS(RecreationReasons, RecreationReason) + QXcbWindow(QWindow *window); ~QXcbWindow(); @@ -281,6 +288,8 @@ protected: int m_swapInterval = -1; qreal m_sizeHintsScaleFactor = 1.0; + + RecreationReasons m_recreationReasons = RecreationNotNeeded; }; class QXcbForeignWindow : public QXcbWindow -- 2.30.2