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

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