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

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