Package: qtbase-opensource-src / 5.15.8+dfsg-11+deb12u3

recreate_xcb_window.diff Patch series | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
Description: xcb: recreate xcb window under some conditions
 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.
Origin: upstream, https://code.qt.io/cgit/qt/qtbase.git/commit/?id=f9e4402ffeef791e
Last-Update: 2022-11-24

--- 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::Wind
     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
--- 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