Blame SOURCES/0020-Client-Announce-an-output-after-receiving-more-compl.patch

6f97c1
From d5186701e27ad6f09f3944809cec2a25c5328026 Mon Sep 17 00:00:00 2001
6f97c1
From: Vlad Zahorodnii <vlad.zahorodnii@kde.org>
6f97c1
Date: Wed, 5 May 2021 20:49:26 +0300
147f94
Subject: [PATCH 20/36] Client: Announce an output after receiving more
6f97c1
 complete state
6f97c1
6f97c1
Output initialization is not atomic, meaning that the compositor may
6f97c1
process a wl_output bind request in one event loop cycle, and the
6f97c1
xdg_output_manager.get_xdg_output in another event loop cycle.
6f97c1
6f97c1
This means that xdg_output properties may arrive in another wl_output
6f97c1
done frame. Prior to xdg-output v3, that wasn't an issue because the
6f97c1
compositor is required to send an xdg_output.done event after sending
6f97c1
xdg_output properties.
6f97c1
6f97c1
Starting with v3, the compositor may choose not to send an
6f97c1
xdg_output.done event after sending xdg_output properties. Therefore,
6f97c1
as is, QtWayland may announce an output with bad logical geometry or
6f97c1
even worse without name assigned by the compositor.
6f97c1
6f97c1
Unfortunately, that breaks applications such as plasmashell. Plasma uses
6f97c1
output names as a criterion to determine what kind of contents should be
6f97c1
displayed on a particular output.
6f97c1
6f97c1
In order to fix the initialization sequence, this change makes every
6f97c1
QWaylandScreen track processed events. After all required events have
6f97c1
been received, the screen can be announced to the rest of Qt.
6f97c1
6f97c1
Change-Id: If5da747edd7af277ec1364cbea105c6994f47402
6f97c1
Reviewed-by: David Edmundson <davidedmundson@kde.org>
6f97c1
(cherry picked from commit 69ea480f2e53ad4a5bbca78cde044eb8d4c48896)
6f97c1
6f97c1
Original Ticket: https://codereview.qt-project.org/c/qt/qtwayland/+/347774
6f97c1
CCBUG: 435124
6f97c1
---
6f97c1
 src/client/qwaylandscreen.cpp | 32 +++++++++++++++++++++++---------
6f97c1
 src/client/qwaylandscreen_p.h | 10 ++++++++--
6f97c1
 2 files changed, 31 insertions(+), 11 deletions(-)
6f97c1
6f97c1
diff --git a/src/client/qwaylandscreen.cpp b/src/client/qwaylandscreen.cpp
6f97c1
index 6cb337de..7c2d9be3 100644
6f97c1
--- a/src/client/qwaylandscreen.cpp
6f97c1
+++ b/src/client/qwaylandscreen.cpp
6f97c1
@@ -72,7 +72,7 @@ QWaylandScreen::QWaylandScreen(QWaylandDisplay *waylandDisplay, int version, uin
6f97c1
         qCWarning(lcQpaWayland) << "wl_output done event not supported by compositor,"
6f97c1
                                 << "QScreen may not work correctly";
6f97c1
         mWaylandDisplay->forceRoundTrip(); // Give the compositor a chance to send geometry etc.
6f97c1
-        mOutputDone = true; // Fake the done event
6f97c1
+        mProcessedEvents |= OutputDoneEvent; // Fake the done event
6f97c1
         maybeInitialize();
6f97c1
     }
6f97c1
 }
6f97c1
@@ -83,14 +83,25 @@ QWaylandScreen::~QWaylandScreen()
6f97c1
         zxdg_output_v1::destroy();
6f97c1
 }
6f97c1
 
6f97c1
+uint QWaylandScreen::requiredEvents() const
6f97c1
+{
6f97c1
+    uint ret = OutputDoneEvent;
6f97c1
+
6f97c1
+    if (mWaylandDisplay->xdgOutputManager()) {
6f97c1
+        ret |= XdgOutputNameEvent;
6f97c1
+
6f97c1
+        if (mWaylandDisplay->xdgOutputManager()->version() < 3)
6f97c1
+            ret |= XdgOutputDoneEvent;
6f97c1
+    }
6f97c1
+    return ret;
6f97c1
+}
6f97c1
+
6f97c1
 void QWaylandScreen::maybeInitialize()
6f97c1
 {
6f97c1
     Q_ASSERT(!mInitialized);
6f97c1
 
6f97c1
-    if (!mOutputDone)
6f97c1
-        return;
6f97c1
-
6f97c1
-    if (mWaylandDisplay->xdgOutputManager() && !mXdgOutputDone)
6f97c1
+    const uint requiredEvents = this->requiredEvents();
6f97c1
+    if ((mProcessedEvents & requiredEvents) != requiredEvents)
6f97c1
         return;
6f97c1
 
6f97c1
     mInitialized = true;
6f97c1
@@ -276,9 +287,8 @@ void QWaylandScreen::output_scale(int32_t factor)
6f97c1
 
6f97c1
 void QWaylandScreen::output_done()
6f97c1
 {
6f97c1
-    mOutputDone = true;
6f97c1
-    if (zxdg_output_v1::isInitialized() && mWaylandDisplay->xdgOutputManager()->version() >= 3)
6f97c1
-        mXdgOutputDone = true;
6f97c1
+    mProcessedEvents |= OutputDoneEvent;
6f97c1
+
6f97c1
     if (mInitialized) {
6f97c1
         updateOutputProperties();
6f97c1
         if (zxdg_output_v1::isInitialized())
6f97c1
@@ -339,7 +349,7 @@ void QWaylandScreen::zxdg_output_v1_done()
6f97c1
     if (Q_UNLIKELY(mWaylandDisplay->xdgOutputManager()->version() >= 3))
6f97c1
         qWarning(lcQpaWayland) << "zxdg_output_v1.done received on version 3 or newer, this is most likely a bug in the compositor";
6f97c1
 
6f97c1
-    mXdgOutputDone = true;
6f97c1
+    mProcessedEvents |= XdgOutputDoneEvent;
6f97c1
     if (mInitialized)
6f97c1
         updateXdgOutputProperties();
6f97c1
     else
6f97c1
@@ -348,7 +358,11 @@ void QWaylandScreen::zxdg_output_v1_done()
6f97c1
 
6f97c1
 void QWaylandScreen::zxdg_output_v1_name(const QString &name)
6f97c1
 {
6f97c1
+    if (Q_UNLIKELY(mInitialized))
6f97c1
+        qWarning(lcQpaWayland) << "zxdg_output_v1.name received after output has been initialized, this is most likely a bug in the compositor";
6f97c1
+
6f97c1
     mOutputName = name;
6f97c1
+    mProcessedEvents |= XdgOutputNameEvent;
6f97c1
 }
6f97c1
 
6f97c1
 void QWaylandScreen::updateXdgOutputProperties()
6f97c1
diff --git a/src/client/qwaylandscreen_p.h b/src/client/qwaylandscreen_p.h
6f97c1
index df1c94f2..050cfdc0 100644
6f97c1
--- a/src/client/qwaylandscreen_p.h
6f97c1
+++ b/src/client/qwaylandscreen_p.h
6f97c1
@@ -116,6 +116,13 @@ public:
6f97c1
     static QWaylandScreen *fromWlOutput(::wl_output *output);
6f97c1
 
6f97c1
 private:
6f97c1
+    enum Event : uint {
6f97c1
+        XdgOutputDoneEvent = 0x1,
6f97c1
+        OutputDoneEvent = 0x2,
6f97c1
+        XdgOutputNameEvent = 0x4,
6f97c1
+    };
6f97c1
+    uint requiredEvents() const;
6f97c1
+
6f97c1
     void output_mode(uint32_t flags, int width, int height, int refresh) override;
6f97c1
     void output_geometry(int32_t x, int32_t y,
6f97c1
                          int32_t width, int32_t height,
6f97c1
@@ -148,8 +155,7 @@ private:
6f97c1
     QSize mPhysicalSize;
6f97c1
     QString mOutputName;
6f97c1
     Qt::ScreenOrientation m_orientation = Qt::PrimaryOrientation;
6f97c1
-    bool mOutputDone = false;
6f97c1
-    bool mXdgOutputDone = false;
6f97c1
+    uint mProcessedEvents = 0;
6f97c1
     bool mInitialized = false;
6f97c1
 
6f97c1
 #if QT_CONFIG(cursor)
6f97c1
-- 
147f94
2.33.1
6f97c1