From ec23228a3a2fc4e8868f7f04b838313be59ad719 Mon Sep 17 00:00:00 2001
From: Jan-Marek Glogowski <glogow@fbihome.de>
Date: Sun, 11 Apr 2021 17:40:26 +0200
Subject: tdf#143796 Qt5/KF5 fix double-buffer graphics

This is a squashed commit for:

"Qt5/KF5 get rid of unneeded own grahics handling"
"tdf#143334 Qt5 don't reset buffer on style change"
"tdf#144008 Qt5/Kf5 create frames in the GUI thread"

commit 963f252cd1ea9c268a6ced68a3454b10cbee1a89
commit ec77a2ed0283cb3446f6e352fc329afd3dfb785c
commit 923b30aa27ceb377d6a540c012000e89ce5db31e

The first commit exposed the same problem to kf5, the 2nd patch is
the real fix and the 3rd partly a regression for kf5 from the 1st
commit but also an additional bugfix for qt5.

Change-Id: I84b8dd106a35a5c2fda08a525f657b0b733a5cb7
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/121795
Tested-by: Jenkins
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
Reviewed-by: Jan-Marek Glogowski <glogow@fbihome.de>
Reviewed-by: Adolfo Jayme Barrientos <fitojb@ubuntu.com>
---
 vcl/inc/qt5/Qt5Frame.hxx       |  8 +-------
 vcl/inc/qt5/Qt5Instance.hxx    |  1 +
 vcl/qt5/Qt5Frame.cxx           | 34 ++++++++++++----------------------
 vcl/qt5/Qt5Instance.cxx        | 18 +++++++++++++++---
 vcl/unx/kf5/KF5SalFrame.cxx    | 24 ------------------------
 vcl/unx/kf5/KF5SalFrame.hxx    |  6 ------
 vcl/unx/kf5/KF5SalInstance.cxx | 16 +++++++++++++---
 vcl/unx/kf5/KF5SalInstance.hxx |  1 +
 8 files changed, 43 insertions(+), 65 deletions(-)

diff --git a/vcl/inc/qt5/Qt5Frame.hxx b/vcl/inc/qt5/Qt5Frame.hxx
index 54a721e03730..9b6e3811c3bb 100644
--- a/vcl/inc/qt5/Qt5Frame.hxx
+++ b/vcl/inc/qt5/Qt5Frame.hxx
@@ -77,17 +77,12 @@ class VCLPLUG_QT5_PUBLIC Qt5Frame : public QObject, public SalFrame
     std::unique_ptr<QImage> m_pQImage;
     std::unique_ptr<Qt5Graphics> m_pQt5Graphics;
     UniqueCairoSurface m_pSurface;
-    std::unique_ptr<Qt5SvpGraphics> m_pOurSvpGraphics;
-    // in base class, this ptr is the same as m_pOurSvpGraphic
-    // in derived class, it can point to a derivative
-    // of Qt5SvpGraphics (which the derived class then owns)
-    Qt5SvpGraphics* m_pSvpGraphics;
+    std::unique_ptr<Qt5SvpGraphics> m_pSvpGraphics;
     DamageHandler m_aDamageHandler;
     QRegion m_aRegion;
     bool m_bNullRegion;
 
     bool m_bGraphicsInUse;
-    bool m_bGraphicsInvalid;
     SalFrameStyleFlags m_nStyle;
     Qt5Frame* m_pParent;
     PointerStyle m_ePointerStyle;
@@ -144,7 +139,6 @@ public:
     void Damage(sal_Int32 nExtentsX, sal_Int32 nExtentsY, sal_Int32 nExtentsWidth,
                 sal_Int32 nExtentsHeight) const;
 
-    void InitQt5SvpGraphics(Qt5SvpGraphics* pQt5SvpGraphics);
     virtual SalGraphics* AcquireGraphics() override;
     virtual void ReleaseGraphics(SalGraphics* pGraphics) override;
 
diff --git a/vcl/inc/qt5/Qt5Instance.hxx b/vcl/inc/qt5/Qt5Instance.hxx
index d73a59de51c1..a2372e58f8c9 100644
--- a/vcl/inc/qt5/Qt5Instance.hxx
+++ b/vcl/inc/qt5/Qt5Instance.hxx
@@ -82,6 +82,7 @@ protected:
     virtual Qt5FilePicker*
     createPicker(css::uno::Reference<css::uno::XComponentContext> const& context,
                  QFileDialog::FileMode);
+    bool useCairo() const { return m_bUseCairo; }
 
 public:
     explicit Qt5Instance(std::unique_ptr<QApplication>& pQApp, bool bUseCairo = false);
diff --git a/vcl/qt5/Qt5Frame.cxx b/vcl/qt5/Qt5Frame.cxx
index b398e9a5cf3b..d39d1729c812 100644
--- a/vcl/qt5/Qt5Frame.cxx
+++ b/vcl/qt5/Qt5Frame.cxx
@@ -104,10 +104,8 @@ sal_Int32 screenNumber(const QScreen* pScreen)
 Qt5Frame::Qt5Frame(Qt5Frame* pParent, SalFrameStyleFlags nStyle, bool bUseCairo)
     : m_pTopLevel(nullptr)
     , m_bUseCairo(bUseCairo)
-    , m_pSvpGraphics(nullptr)
     , m_bNullRegion(true)
     , m_bGraphicsInUse(false)
-    , m_bGraphicsInvalid(false)
     , m_ePointerStyle(PointerStyle::Arrow)
     , m_pDragSource(nullptr)
     , m_pDropTarget(nullptr)
@@ -288,17 +286,6 @@ void Qt5Frame::Damage(sal_Int32 nExtentsX, sal_Int32 nExtentsY, sal_Int32 nExten
                                    1 / devicePixelRatioF()));
 }
 
-void Qt5Frame::InitQt5SvpGraphics(Qt5SvpGraphics* pQt5SvpGraphics)
-{
-    QSize aSize = m_pQWidget->size() * devicePixelRatioF();
-    m_pSvpGraphics = pQt5SvpGraphics;
-    m_pSurface.reset(
-        cairo_image_surface_create(CAIRO_FORMAT_ARGB32, aSize.width(), aSize.height()));
-    m_pSvpGraphics->setSurface(m_pSurface.get(), basegfx::B2IVector(aSize.width(), aSize.height()));
-    cairo_surface_set_user_data(m_pSurface.get(), Qt5SvpGraphics::getDamageKey(), &m_aDamageHandler,
-                                nullptr);
-}
-
 SalGraphics* Qt5Frame::AcquireGraphics()
 {
     if (m_bGraphicsInUse)
@@ -308,24 +295,28 @@ SalGraphics* Qt5Frame::AcquireGraphics()
 
     if (m_bUseCairo)
     {
-        if (!m_pOurSvpGraphics || m_bGraphicsInvalid)
+        if (!m_pSvpGraphics)
         {
-            m_pOurSvpGraphics.reset(new Qt5SvpGraphics(this));
-            InitQt5SvpGraphics(m_pOurSvpGraphics.get());
-            m_bGraphicsInvalid = false;
+            QSize aSize = m_pQWidget->size() * devicePixelRatioF();
+            m_pSvpGraphics.reset(new Qt5SvpGraphics(this));
+            m_pSurface.reset(
+                cairo_image_surface_create(CAIRO_FORMAT_ARGB32, aSize.width(), aSize.height()));
+            m_pSvpGraphics->setSurface(m_pSurface.get(),
+                                       basegfx::B2IVector(aSize.width(), aSize.height()));
+            cairo_surface_set_user_data(m_pSurface.get(), Qt5SvpGraphics::getDamageKey(),
+                                        &m_aDamageHandler, nullptr);
         }
-        return m_pOurSvpGraphics.get();
+        return m_pSvpGraphics.get();
     }
     else
     {
-        if (!m_pQt5Graphics || m_bGraphicsInvalid)
+        if (!m_pQt5Graphics)
         {
             m_pQt5Graphics.reset(new Qt5Graphics(this));
             m_pQImage.reset(
                 new QImage(m_pQWidget->size() * devicePixelRatioF(), Qt5_DefaultFormat32));
             m_pQImage->fill(Qt::transparent);
             m_pQt5Graphics->ChangeQImage(m_pQImage.get());
-            m_bGraphicsInvalid = false;
         }
         return m_pQt5Graphics.get();
     }
@@ -335,7 +326,7 @@ void Qt5Frame::ReleaseGraphics(SalGraphics* pSalGraph)
 {
     (void)pSalGraph;
     if (m_bUseCairo)
-        assert(pSalGraph == m_pOurSvpGraphics.get());
+        assert(pSalGraph == m_pSvpGraphics.get());
     else
         assert(pSalGraph == m_pQt5Graphics.get());
     m_bGraphicsInUse = false;
@@ -1145,7 +1136,6 @@ void Qt5Frame::UpdateSettings(AllSettings& rSettings)
     style.SetShadowColor(toColor(pal.color(QPalette::Disabled, QPalette::WindowText)));
     style.SetDarkShadowColor(toColor(pal.color(QPalette::Inactive, QPalette::WindowText)));
 
-    m_bGraphicsInvalid = true;
     rSettings.SetStyleSettings(style);
 }
 
diff --git a/vcl/qt5/Qt5Instance.cxx b/vcl/qt5/Qt5Instance.cxx
index ca1f914dd707..bceae35e9016 100644
--- a/vcl/qt5/Qt5Instance.cxx
+++ b/vcl/qt5/Qt5Instance.cxx
@@ -252,13 +252,21 @@ void Qt5Instance::deleteObjectLater(QObject* pObject) { pObject->deleteLater();
 
 SalFrame* Qt5Instance::CreateChildFrame(SystemParentData* /*pParent*/, SalFrameStyleFlags nStyle)
 {
-    return new Qt5Frame(nullptr, nStyle, m_bUseCairo);
+    SalFrame* pRet(nullptr);
+    RunInMainThread([&, this]() { pRet = new Qt5Frame(nullptr, nStyle, useCairo()); });
+    assert(pRet);
+    return pRet;
 }
 
 SalFrame* Qt5Instance::CreateFrame(SalFrame* pParent, SalFrameStyleFlags nStyle)
 {
     assert(!pParent || dynamic_cast<Qt5Frame*>(pParent));
-    return new Qt5Frame(static_cast<Qt5Frame*>(pParent), nStyle, m_bUseCairo);
+
+    SalFrame* pRet(nullptr);
+    RunInMainThread(
+        [&, this]() { pRet = new Qt5Frame(static_cast<Qt5Frame*>(pParent), nStyle, useCairo()); });
+    assert(pRet);
+    return pRet;
 }
 
 void Qt5Instance::DestroyFrame(SalFrame* pFrame)
@@ -273,7 +281,11 @@ void Qt5Instance::DestroyFrame(SalFrame* pFrame)
 SalObject* Qt5Instance::CreateObject(SalFrame* pParent, SystemWindowData*, bool bShow)
 {
     assert(!pParent || dynamic_cast<Qt5Frame*>(pParent));
-    return new Qt5Object(static_cast<Qt5Frame*>(pParent), bShow);
+
+    SalObject* pRet(nullptr);
+    RunInMainThread([&]() { pRet = new Qt5Object(static_cast<Qt5Frame*>(pParent), bShow); });
+    assert(pRet);
+    return pRet;
 }
 
 void Qt5Instance::DestroyObject(SalObject* pObject)
diff --git a/vcl/unx/kf5/KF5SalFrame.cxx b/vcl/unx/kf5/KF5SalFrame.cxx
index 1aa0b9008de7..8f14594586d2 100644
--- a/vcl/unx/kf5/KF5SalFrame.cxx
+++ b/vcl/unx/kf5/KF5SalFrame.cxx
@@ -45,7 +45,6 @@
 
 KF5SalFrame::KF5SalFrame(KF5SalFrame* pParent, SalFrameStyleFlags nState, bool bUseCairo)
     : Qt5Frame(pParent, nState, bUseCairo)
-    , m_bGraphicsInUse(false)
 {
 }
 
@@ -162,27 +161,4 @@ void KF5SalFrame::UpdateSettings(AllSettings& rSettings)
     rSettings.SetStyleSettings(style);
 }
 
-SalGraphics* KF5SalFrame::AcquireGraphics()
-{
-    if (m_bGraphicsInUse)
-        return nullptr;
-
-    m_bGraphicsInUse = true;
-
-    if (!m_pKF5Graphics)
-    {
-        m_pKF5Graphics.reset(new Qt5SvpGraphics(this));
-        Qt5Frame::InitQt5SvpGraphics(m_pKF5Graphics.get());
-    }
-
-    return m_pKF5Graphics.get();
-}
-
-void KF5SalFrame::ReleaseGraphics(SalGraphics* pSalGraph)
-{
-    (void)pSalGraph;
-    assert(pSalGraph == m_pKF5Graphics.get());
-    m_bGraphicsInUse = false;
-}
-
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/kf5/KF5SalFrame.hxx b/vcl/unx/kf5/KF5SalFrame.hxx
index f757535c2f35..d0fdd91978e6 100644
--- a/vcl/unx/kf5/KF5SalFrame.hxx
+++ b/vcl/unx/kf5/KF5SalFrame.hxx
@@ -28,15 +28,9 @@ class QWidget;
 
 class KF5SalFrame : public Qt5Frame
 {
-private:
-    std::unique_ptr<Qt5SvpGraphics> m_pKF5Graphics;
-    bool m_bGraphicsInUse;
-
 public:
     KF5SalFrame(KF5SalFrame* pParent, SalFrameStyleFlags nStyle, bool bUseCairo);
 
-    virtual SalGraphics* AcquireGraphics() override;
-    virtual void ReleaseGraphics(SalGraphics* pGraphics) override;
     virtual void UpdateSettings(AllSettings& rSettings) override;
 };
 
diff --git a/vcl/unx/kf5/KF5SalInstance.cxx b/vcl/unx/kf5/KF5SalInstance.cxx
index 5b95ff8df572..d9d7747fe647 100644
--- a/vcl/unx/kf5/KF5SalInstance.cxx
+++ b/vcl/unx/kf5/KF5SalInstance.cxx
@@ -40,11 +40,21 @@ KF5SalInstance::KF5SalInstance(std::unique_ptr<QApplication>& pQApp)
     pSVData->maAppData.mxToolkitName = OUString("kf5");
 }
 
-SalFrame* KF5SalInstance::CreateFrame(SalFrame* pParent, SalFrameStyleFlags nState)
+SalFrame* KF5SalInstance::CreateChildFrame(SystemParentData* /*pParent*/, SalFrameStyleFlags nStyle)
 {
     SalFrame* pRet(nullptr);
-    RunInMainThread([&pRet, pParent, nState]() {
-        pRet = new KF5SalFrame(static_cast<KF5SalFrame*>(pParent), nState, true);
+    RunInMainThread([&, this]() { pRet = new KF5SalFrame(nullptr, nStyle, useCairo()); });
+    assert(pRet);
+    return pRet;
+}
+
+SalFrame* KF5SalInstance::CreateFrame(SalFrame* pParent, SalFrameStyleFlags nStyle)
+{
+    assert(!pParent || dynamic_cast<KF5SalFrame*>(pParent));
+
+    SalFrame* pRet(nullptr);
+    RunInMainThread([&, this]() {
+        pRet = new KF5SalFrame(static_cast<KF5SalFrame*>(pParent), nStyle, useCairo());
     });
     assert(pRet);
     return pRet;
diff --git a/vcl/unx/kf5/KF5SalInstance.hxx b/vcl/unx/kf5/KF5SalInstance.hxx
index 5dd306da5231..b951df59ab33 100644
--- a/vcl/unx/kf5/KF5SalInstance.hxx
+++ b/vcl/unx/kf5/KF5SalInstance.hxx
@@ -28,6 +28,7 @@ class KF5SalInstance final : public Qt5Instance
                                 QFileDialog::FileMode) override;
 
     SalFrame* CreateFrame(SalFrame* pParent, SalFrameStyleFlags nStyle) override;
+    SalFrame* CreateChildFrame(SystemParentData* pParent, SalFrameStyleFlags nStyle) override;
 
 public:
     explicit KF5SalInstance(std::unique_ptr<QApplication>& pQApp);
-- 
cgit v1.2.1

