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

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