include/test/screenshot_test.hxx    |   15 -
 include/vcl/dialog.hxx              |   18 -
 include/vcl/syswin.hxx              |   18 +
 include/vcl/weld.hxx                |   57 +++--
 test/source/screenshot_test.cxx     |  106 +++++-----
 vcl/UIConfig_vcl.mk                 |    1 
 vcl/source/app/salvtables.cxx       |  124 +++++++----
 vcl/source/window/dialog.cxx        |   53 -----
 vcl/source/window/syswin.cxx        |   54 +++++
 vcl/uiconfig/ui/screenshotparent.ui |   54 +++++
 vcl/unx/gtk3/gtk3gtkinst.cxx        |  377 +++++++++++++++++++-----------------
 11 files changed, 511 insertions(+), 366 deletions(-)

New commits:
commit bb6bcabda53dbd64dda43f09fab9f4ad6f34eba6
Author:     Caolán McNamara <caol...@redhat.com>
AuthorDate: Wed Oct 9 13:55:46 2019 +0100
Commit:     Caolán McNamara <caol...@redhat.com>
CommitDate: Thu Oct 10 20:25:07 2019 +0200

    support screenshotting .ui files with GtkBuilder
    
    so...
    
    SAL_USE_VCLPLUGIN=gtk3 make screenshot
    
    for the "unknown dialog" cases of make screenshot, which loads .ui files and
    tries to render them, will render them with the native gtk infrastructure
    
    Change-Id: Ifc8fe264155887c4d01b7ce0e2aa53e12acbfcb0
    Reviewed-on: https://gerrit.libreoffice.org/80545
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caol...@redhat.com>
    Tested-by: Caolán McNamara <caol...@redhat.com>

diff --git a/include/test/screenshot_test.hxx b/include/test/screenshot_test.hxx
index 74bcfc721d53..3e1f3f84a06f 100644
--- a/include/test/screenshot_test.hxx
+++ b/include/test/screenshot_test.hxx
@@ -15,7 +15,8 @@
 #include <unotest/macros_test.hxx>
 #include <com/sun/star/lang/XComponent.hpp>
 #include <osl/file.hxx>
-#include <vcl/dialog.hxx>
+#include <vcl/vclptr.hxx>
+#include <vcl/weld.hxx>
 #include <map>
 
 class VclAbstractDialog;
@@ -30,11 +31,18 @@ private:
     /// the set of known dialogs and their ID for usage in createDialogByID
     mapType     maKnownDialogs;
 
+    /// parent for non-dialog buildables
+    weld::GenericDialogController maParent;
+    std::unique_ptr<weld::Container> mxParentWidget;
+
 private:
     /// helpers
     void implSaveScreenshot(const BitmapEx& rScreenshot, const OString& 
rScreenshotId);
     void saveScreenshot(VclAbstractDialog const & rDialog);
-    void saveScreenshot(Dialog& rDialog);
+    void saveScreenshot(weld::Window& rDialog);
+
+    /// helper method to create and dump a dialog based on Builder contents.
+    void dumpDialogToPath(weld::Builder& rDialog);
 
     /// helper method to populate maKnownDialogs, called in setUp(). Needs to 
be
     /// written and has to add entries to maKnownDialogs
@@ -58,9 +66,6 @@ public:
     /// version for AbstractDialogs, the ones created in 
AbstractDialogFactories
     void dumpDialogToPath(VclAbstractDialog& rDialog);
 
-    /// version for pure vcl-based dialogs
-    void dumpDialogToPath(Dialog& rDialog);
-
     /// fallback version for dialogs for which only the UXMLDescription is 
known.
     /// This should be used with care - no active layouting will be done, only 
the
     /// VclBuilder will be activated for layouting. Result can thus vary 
drastically
diff --git a/include/vcl/dialog.hxx b/include/vcl/dialog.hxx
index cc5355d58132..ee2560abc475 100644
--- a/include/vcl/dialog.hxx
+++ b/include/vcl/dialog.hxx
@@ -50,7 +50,6 @@ private:
     bool            mbInSyncExecute;
     bool            mbInClose;
     bool            mbModalMode;
-    bool            mbPaintComplete;
     bool const      mbForceBorderWindow;
     InitFlag const  mnInitFlag; // used for deferred init
 
@@ -70,11 +69,6 @@ private:
     DECL_DLLPRIVATE_LINK(ImplAsyncCloseHdl, void*, void);
     DECL_DLLPRIVATE_LINK(ResponseHdl, Button*, void);
 
-    // ensureRepaint - triggers Application::Yield until the dialog is
-    // completely repainted. Sometimes needed for dialogs showing progress
-    // during actions
-    void ensureRepaint();
-
 protected:
     using Window::ImplInit;
     void    ImplInit( vcl::Window* pParent, WinBits nStyle, InitFlag eFlag = 
InitFlag::Default );
@@ -95,6 +89,7 @@ protected:
 
 protected:
     friend class VclBuilder;
+    friend class SalInstanceBuilder;
     void set_action_area(VclButtonBox* pBox);
     virtual void set_content_area(VclBox* pBox);
 
@@ -119,17 +114,6 @@ public:
 
     virtual bool    Close() override;
 
-    // try to extract content and return as Bitmap. To do that reliably, a 
Yield-loop
-    // like in Execute() has to be executed and it is necessary to detect when 
the
-    // paint is finished
-    virtual void PrePaint(vcl::RenderContext& rRenderContext) override;
-    virtual void PostPaint(vcl::RenderContext& rRenderContext) override;
-
-    // Screenshot interface
-    virtual std::vector<OString> getAllPageUIXMLDescriptions() const;
-    virtual bool selectPageByUIXMLDescription(const OString& 
rUIXMLDescription);
-    void createScreenshot(VirtualDevice& rOutput);
-
     virtual short   Execute();
     bool            IsInExecute() const { return mbInExecute; }
     // Return true when dialog is synchronously executed (calling ::Execute())
diff --git a/include/vcl/syswin.hxx b/include/vcl/syswin.hxx
index 402aebeb381e..cb6d15d27ead 100644
--- a/include/vcl/syswin.hxx
+++ b/include/vcl/syswin.hxx
@@ -141,6 +141,7 @@ private:
     bool            mbHideBtn;
     bool            mbSysChild;
     bool            mbIsCalculatingInitialLayoutSize;
+    bool            mbPaintComplete;
     MenuBarMode     mnMenuBarMode;
     sal_uInt16      mnIcon;
     std::unique_ptr<ImplData> mpImplData;
@@ -159,6 +160,17 @@ private:
     SAL_DLLPRIVATE void setPosSizeOnContainee(Size aSize, Window &rBox);
     DECL_DLLPRIVATE_LINK( ImplHandleLayoutTimerHdl, Timer*, void );
 
+    // try to extract content and return as Bitmap. To do that reliably, a 
Yield-loop
+    // like in Execute() has to be executed and it is necessary to detect when 
the
+    // paint is finished
+    virtual void PrePaint(vcl::RenderContext& rRenderContext) override;
+    virtual void PostPaint(vcl::RenderContext& rRenderContext) override;
+
+    // ensureRepaint - triggers Application::Yield until the dialog is
+    // completely repainted. Sometimes needed for dialogs showing progress
+    // during actions
+    SAL_DLLPRIVATE void ensureRepaint();
+
 protected:
     // Single argument ctors shall be explicit.
     explicit SystemWindow(WindowType nType);
@@ -171,6 +183,7 @@ protected:
     SAL_DLLPRIVATE void DoInitialLayout();
 
     SAL_DLLPRIVATE void SetIdleDebugName( const sal_Char *pDebugName );
+
 public:
     virtual         ~SystemWindow() override;
     virtual void    dispose() override;
@@ -270,6 +283,11 @@ public:
     SAL_DLLPRIVATE bool hasPendingLayout() const { return 
maLayoutIdle.IsActive(); }
 
     virtual        void    doDeferredInit(WinBits nBits);
+
+    // Screenshot interface
+    virtual std::vector<OString> getAllPageUIXMLDescriptions() const;
+    virtual bool selectPageByUIXMLDescription(const OString& 
rUIXMLDescription);
+    void createScreenshot(VirtualDevice& rOutput);
 };
 
 inline void SystemWindow::SetIdleDebugName( const sal_Char *pDebugName )
diff --git a/include/vcl/weld.hxx b/include/vcl/weld.hxx
index 20c8d9e5751e..be9cf23f0779 100644
--- a/include/vcl/weld.hxx
+++ b/include/vcl/weld.hxx
@@ -351,6 +351,26 @@ public:
     void connect_enter_page(const Link<const OString&, void>& rLink) { 
m_aEnterPageHdl = rLink; }
 };
 
+class VCL_DLLPUBLIC ScreenShotEntry
+{
+public:
+    ScreenShotEntry(const OString& rHelpId, const basegfx::B2IRange& rB2IRange)
+        : msHelpId(rHelpId)
+        , maB2IRange(rB2IRange)
+    {
+    }
+
+    const basegfx::B2IRange& getB2IRange() const { return maB2IRange; }
+
+    const OString& GetHelpId() const { return msHelpId; }
+
+private:
+    OString msHelpId;
+    basegfx::B2IRange maB2IRange;
+};
+
+typedef std::vector<ScreenShotEntry> ScreenShotCollection;
+
 class VCL_DLLPUBLIC Window : virtual public Container
 {
 protected:
@@ -397,6 +417,11 @@ public:
     virtual SystemEnvData get_system_data() const = 0;
 
     virtual void resize_to_request() = 0;
+
+    // render the dialog for a screenshot
+    virtual void draw(VirtualDevice& rOutput) = 0;
+    // collect positions of widgets and their help ids for screenshot purposes
+    virtual ScreenShotCollection collect_screenshot_data() = 0;
 };
 
 class VCL_DLLPUBLIC WaitObject
@@ -420,26 +445,6 @@ public:
 
 class Button;
 
-class VCL_DLLPUBLIC ScreenShotEntry
-{
-public:
-    ScreenShotEntry(const OString& rHelpId, const basegfx::B2IRange& rB2IRange)
-        : msHelpId(rHelpId)
-        , maB2IRange(rB2IRange)
-    {
-    }
-
-    const basegfx::B2IRange& getB2IRange() const { return maB2IRange; }
-
-    const OString& GetHelpId() const { return msHelpId; }
-
-private:
-    OString msHelpId;
-    basegfx::B2IRange maB2IRange;
-};
-
-typedef std::vector<ScreenShotEntry> ScreenShotCollection;
-
 class VCL_DLLPUBLIC Dialog : virtual public Window
 {
 private:
@@ -467,11 +472,6 @@ public:
     // undo previous dialog collapse
     virtual void undo_collapse() = 0;
 
-    // render the dialog for a screenshot
-    virtual void draw(VirtualDevice& rOutput) = 0;
-    // collect positions of widgets and their help ids for screenshot purposes
-    virtual ScreenShotCollection collect_screenshot_data() = 0;
-
     virtual void SetInstallLOKNotifierHdl(const Link<void*, 
vcl::ILibreOfficeKitNotifier*>& rLink)
         = 0;
 };
@@ -1937,6 +1937,13 @@ public:
     virtual std::unique_ptr<Toolbar> weld_toolbar(const OString& id, bool 
bTakeOwnership = true)
         = 0;
     virtual std::unique_ptr<SizeGroup> create_size_group() = 0;
+    /* return a Dialog suitable to take a screenshot of containing the 
contents of the .ui file.
+
+       If the toplevel element is a dialog, that will be returned
+       If the toplevel is not a dialog, a dialog will be created and the 
contents of the .ui
+       inserted into it
+    */
+    virtual std::unique_ptr<Window> create_screenshot_window() = 0;
     virtual ~Builder() {}
 };
 
diff --git a/test/source/screenshot_test.cxx b/test/source/screenshot_test.cxx
index 42dd194d6fe1..6f4d49cc88bd 100644
--- a/test/source/screenshot_test.cxx
+++ b/test/source/screenshot_test.cxx
@@ -20,6 +20,7 @@
 #include <vcl/pngwrite.hxx>
 #include <vcl/svapp.hxx>
 #include <vcl/virdev.hxx>
+#include <vcl/weld.hxx>
 #include <unotools/configmgr.hxx>
 #include <tools/stream.hxx>
 
@@ -45,6 +46,8 @@ static constexpr OUStringLiteral 
g_aScreenshotDirectory("screenshots");
 
 ScreenshotTest::ScreenshotTest()
     : maKnownDialogs()
+    , maParent(nullptr, "vcl/ui/screenshotparent.ui", "ScreenShot")
+    , mxParentWidget(maParent.getDialog()->weld_content_area())
 {
     maCurrentLanguage = OUString::fromUtf8(getenv("LO_TEST_LOCALE"));
 }
@@ -109,20 +112,17 @@ void ScreenshotTest::saveScreenshot(VclAbstractDialog 
const & rDialog)
     }
 }
 
-void ScreenshotTest::saveScreenshot(Dialog& rDialog)
+void ScreenshotTest::saveScreenshot(weld::Window& rDialog)
 {
     VclPtr<VirtualDevice> 
xDialogSurface(VclPtr<VirtualDevice>::Create(DeviceFormat::DEFAULT));
-    rDialog.createScreenshot(*xDialogSurface);
+    rDialog.draw(*xDialogSurface);
     const BitmapEx aScreenshot(xDialogSurface->GetBitmapEx(Point(), 
xDialogSurface->GetOutputSizePixel()));
 
     if (!aScreenshot.IsEmpty())
     {
-        const OString aScreenshotId = rDialog.GetScreenshotId();
-
-        if (!aScreenshotId.isEmpty())
-        {
-            implSaveScreenshot(aScreenshot, aScreenshotId);
-        }
+        const OString aScreenshotId = rDialog.get_help_id();
+        assert(!aScreenshotId.isEmpty());
+        implSaveScreenshot(aScreenshot, aScreenshotId);
     }
 }
 
@@ -162,17 +162,29 @@ void ScreenshotTest::dumpDialogToPath(VclAbstractDialog& 
rDialog)
     }
 }
 
-void ScreenshotTest::dumpDialogToPath(Dialog& rDialog)
+void ScreenshotTest::dumpDialogToPath(weld::Builder& rBuilder)
 {
-    const std::vector<OString> 
aPageDescriptions(rDialog.getAllPageUIXMLDescriptions());
+    std::unique_ptr<weld::Window> xDialog(rBuilder.create_screenshot_window());
 
-    if (!aPageDescriptions.empty())
+    auto xTabCtrl = rBuilder.weld_notebook("tabcontrol");
+
+    int nPages = xTabCtrl ? xTabCtrl->get_n_pages() : 0;
+    if (nPages)
     {
-        for (size_t a(0); a < aPageDescriptions.size(); a++)
+        for (int i = 0; i < nPages; ++i)
         {
-            if (rDialog.selectPageByUIXMLDescription(aPageDescriptions[a]))
+            OString sIdent(xTabCtrl->get_page_ident(i));
+            xTabCtrl->set_current_page(sIdent);
+            if (xTabCtrl->get_current_page_ident() == sIdent)
             {
-                saveScreenshot(rDialog);
+                OString sOrigHelpId(xDialog->get_help_id());
+                // skip empty pages
+                weld::Container* pPage = xTabCtrl->get_page(sIdent);
+                OString sBuildableName(pPage->get_buildable_name());
+                if (!sBuildableName.isEmpty() && 
!sBuildableName.startsWith("__"))
+                    xDialog->set_help_id(pPage->get_help_id());
+                saveScreenshot(*xDialog);
+                xDialog->set_help_id(sOrigHelpId);
             }
             else
             {
@@ -182,7 +194,7 @@ void ScreenshotTest::dumpDialogToPath(Dialog& rDialog)
     }
     else
     {
-        saveScreenshot(rDialog);
+        saveScreenshot(*xDialog);
     }
 }
 
@@ -190,41 +202,33 @@ void ScreenshotTest::dumpDialogToPath(const OString& 
rUIXMLDescription)
 {
     if (!rUIXMLDescription.isEmpty())
     {
-        VclPtrInstance<Dialog> pDialog(Application::GetDefDialogParent(), 
WB_STDDIALOG | WB_SIZEABLE, Dialog::InitFlag::NoParent);
-
-        {
-            VclPtr<vcl::Window> aOwnedToplevel;
-
-            bool bLegacy = rUIXMLDescription == "fps/ui/remotefilesdialog.ui" 
||
-                           rUIXMLDescription == 
"modules/swriter/ui/sidebarstylepresets.ui" ||
-                           rUIXMLDescription == 
"modules/swriter/ui/sidebartheme.ui" ||
-                           rUIXMLDescription == "sfx/ui/startcenter.ui" ||
-                           rUIXMLDescription == "svx/ui/datanavigator.ui";
-            std::unique_ptr<VclBuilder> xBuilder(new VclBuilder(pDialog, 
VclBuilderContainer::getUIRootDir(), OStringToOUString(rUIXMLDescription, 
RTL_TEXTENCODING_UTF8), OString(), css::uno::Reference<css::frame::XFrame>(), 
bLegacy));
-            vcl::Window *pRoot = xBuilder->get_widget_root();
-            Dialog *pRealDialog = dynamic_cast<Dialog*>(pRoot);
-
-            if (!pRealDialog)
-            {
-                pRealDialog = pDialog;
-            }
-            else
-            {
-                aOwnedToplevel.set(pRoot);
-                xBuilder->drop_ownership(pRoot);
-            }
-
-            pRealDialog->SetText(utl::ConfigManager::getProductName());
-            pRealDialog->SetStyle(pDialog->GetStyle() | WB_CLOSEABLE);
-
-            dumpDialogToPath(*pRealDialog);
-
-            if (VclBuilderContainer* pOwnedToplevel = 
dynamic_cast<VclBuilderContainer*>(aOwnedToplevel.get()))
-                pOwnedToplevel->m_pUIBuilder = std::move(xBuilder);
-            aOwnedToplevel.disposeAndClear();
-        }
-
-        pDialog.disposeAndClear();
+        bool bNonConforming = rUIXMLDescription == 
"modules/swriter/ui/sidebarstylepresets.ui" ||
+                              rUIXMLDescription == 
"modules/swriter/ui/sidebarpage.ui" ||
+                              rUIXMLDescription == 
"modules/swriter/ui/sidebartheme.ui" ||
+                              rUIXMLDescription == 
"modules/swriter/ui/sidebarwrap.ui" ||
+                              rUIXMLDescription == 
"modules/swriter/ui/notebookbar.ui" ||
+                              rUIXMLDescription == 
"modules/scalc/ui/sidebaralignment.ui" ||
+                              rUIXMLDescription == 
"modules/scalc/ui/sidebarcellappearance.ui" ||
+                              rUIXMLDescription == 
"modules/scalc/ui/sidebarnumberformat.ui" ||
+                              rUIXMLDescription == 
"sfx/ui/helpbookmarkpage.ui" ||
+                              rUIXMLDescription == "sfx/ui/helpcontentpage.ui" 
||
+                              rUIXMLDescription == "sfx/ui/helpindexpage.ui" ||
+                              rUIXMLDescription == "sfx/ui/helpsearchpage.ui" 
||
+                              rUIXMLDescription == "sfx/ui/startcenter.ui" ||
+                              rUIXMLDescription == "svx/ui/datanavigator.ui" ||
+                              rUIXMLDescription == "svx/ui/xformspage.ui" ||
+                              rUIXMLDescription == 
"modules/dbreport/ui/conditionwin.ui";
+        if (bNonConforming) // skip these broken ones
+            return;
+        bool bLegacy = rUIXMLDescription == "fps/ui/explorerfiledialog.ui" ||
+                       rUIXMLDescription == "fps/ui/remotefilesdialog.ui" ||
+                       rUIXMLDescription == "sfx/ui/floatingrecord.ui";
+        std::unique_ptr<weld::Builder> xBuilder;
+        if (bLegacy)
+            
xBuilder.reset(Application::CreateInterimBuilder(mxParentWidget.get(), 
OStringToOUString(rUIXMLDescription, RTL_TEXTENCODING_UTF8)));
+        else
+            xBuilder.reset(Application::CreateBuilder(mxParentWidget.get(), 
OStringToOUString(rUIXMLDescription, RTL_TEXTENCODING_UTF8)));
+        dumpDialogToPath(*xBuilder);
     }
 }
 
@@ -273,7 +277,7 @@ void ScreenshotTest::processDialogBatchFile(const OUString& 
rFile)
             else
             {
                 // unknown dialog, try fallback to generic created
-                // VclBuilder-generated instance. Keep in mind that Dialogs
+                // Builder-generated instance. Keep in mind that Dialogs
                 // using this mechanism will probably not be layouted well
                 // since the setup/initialization part is missing. Thus,
                 // only use for fallback when only the UI file is available.
diff --git a/vcl/UIConfig_vcl.mk b/vcl/UIConfig_vcl.mk
index 638fc9a537ae..c00d0d461f23 100644
--- a/vcl/UIConfig_vcl.mk
+++ b/vcl/UIConfig_vcl.mk
@@ -23,6 +23,7 @@ $(eval $(call gb_UIConfig_add_uifiles,vcl,\
        vcl/uiconfig/ui/printerpropertiesdialog \
        vcl/uiconfig/ui/printprogressdialog \
        vcl/uiconfig/ui/querydialog \
+       vcl/uiconfig/ui/screenshotparent \
 ))
 
 $(eval $(call gb_UIConfig_add_a11yerrors_uifiles,vcl,\
diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx
index 416f81071e93..d12c3464c75d 100644
--- a/vcl/source/app/salvtables.cxx
+++ b/vcl/source/app/salvtables.cxx
@@ -35,6 +35,7 @@
 #include <messagedialog.hxx>
 #include <treeglue.hxx>
 #include <unotools/accessiblerelationsethelper.hxx>
+#include <unotools/configmgr.hxx>
 #include <utility>
 #include <tools/helpers.hxx>
 #include <vcl/abstdlg.hxx>
@@ -1059,6 +1060,34 @@ std::unique_ptr<weld::Container> 
SalInstanceWidget::weld_parent() const
     return std::make_unique<SalInstanceContainer>(pParent, m_pBuilder, false);
 }
 
+namespace
+{
+    void CollectChildren(const vcl::Window& rCurrent, const basegfx::B2IPoint& 
rTopLeft, weld::ScreenShotCollection& rControlDataCollection)
+    {
+        if (rCurrent.IsVisible())
+        {
+            const Point aCurrentPos(rCurrent.GetPosPixel());
+            const Size aCurrentSize(rCurrent.GetSizePixel());
+            const basegfx::B2IPoint aCurrentTopLeft(rTopLeft.getX() + 
aCurrentPos.X(), rTopLeft.getY() + aCurrentPos.Y());
+            const basegfx::B2IRange aCurrentRange(aCurrentTopLeft, 
aCurrentTopLeft + basegfx::B2IPoint(aCurrentSize.Width(), 
aCurrentSize.Height()));
+
+            if (!aCurrentRange.isEmpty())
+            {
+                rControlDataCollection.emplace_back(rCurrent.GetHelpId(), 
aCurrentRange);
+            }
+
+            for (sal_uInt16 a(0); a < rCurrent.GetChildCount(); a++)
+            {
+                vcl::Window* pChild = rCurrent.GetChild(a);
+                if (nullptr != pChild)
+                {
+                    CollectChildren(*pChild, aCurrentTopLeft, 
rControlDataCollection);
+                }
+            }
+        }
+    }
+}
+
 class SalInstanceWindow : public SalInstanceContainer, public virtual 
weld::Window
 {
 private:
@@ -1221,6 +1250,26 @@ public:
         SalInstanceContainer::HandleEventListener(rEvent);
     }
 
+    virtual void draw(VirtualDevice& rOutput) override
+    {
+        SystemWindow* pSysWin = dynamic_cast<SystemWindow*>(m_xWindow.get());
+        assert(pSysWin);
+        pSysWin->createScreenshot(rOutput);
+    }
+
+    virtual weld::ScreenShotCollection collect_screenshot_data() override
+    {
+        weld::ScreenShotCollection aRet;
+
+        // collect all children. Choose start pos to be negative
+        // of target dialog's position to get all positions relative to (0,0)
+        const Point aParentPos(m_xWindow->GetPosPixel());
+        const basegfx::B2IPoint aTopLeft(-aParentPos.X(), -aParentPos.Y());
+        CollectChildren(*m_xWindow, aTopLeft, aRet);
+
+        return aRet;
+    }
+
     virtual ~SalInstanceWindow() override
     {
         clear_child_help(m_xWindow);
@@ -1258,34 +1307,6 @@ namespace
     }
 }
 
-namespace
-{
-    void CollectChildren(const vcl::Window& rCurrent, const basegfx::B2IPoint& 
rTopLeft, weld::ScreenShotCollection& rControlDataCollection)
-    {
-        if (rCurrent.IsVisible())
-        {
-            const Point aCurrentPos(rCurrent.GetPosPixel());
-            const Size aCurrentSize(rCurrent.GetSizePixel());
-            const basegfx::B2IPoint aCurrentTopLeft(rTopLeft.getX() + 
aCurrentPos.X(), rTopLeft.getY() + aCurrentPos.Y());
-            const basegfx::B2IRange aCurrentRange(aCurrentTopLeft, 
aCurrentTopLeft + basegfx::B2IPoint(aCurrentSize.Width(), 
aCurrentSize.Height()));
-
-            if (!aCurrentRange.isEmpty())
-            {
-                rControlDataCollection.emplace_back(rCurrent.GetHelpId(), 
aCurrentRange);
-            }
-
-            for (sal_uInt16 a(0); a < rCurrent.GetChildCount(); a++)
-            {
-                vcl::Window* pChild = rCurrent.GetChild(a);
-                if (nullptr != pChild)
-                {
-                    CollectChildren(*pChild, aCurrentTopLeft, 
rControlDataCollection);
-                }
-            }
-        }
-    }
-}
-
 class SalInstanceDialog : public SalInstanceWindow, public virtual weld::Dialog
 {
 private:
@@ -1474,23 +1495,6 @@ public:
         return new SalInstanceContainer(m_xDialog->get_content_area(), 
m_pBuilder, false);
     }
 
-    virtual void draw(VirtualDevice& rOutput) override
-    {
-        m_xDialog->createScreenshot(rOutput);
-    }
-
-    virtual weld::ScreenShotCollection collect_screenshot_data() override
-    {
-        weld::ScreenShotCollection aRet;
-
-        // collect all children. Choose start pos to be negative
-        // of target dialog's position to get all positions relative to (0,0)
-        const Point aParentPos(m_xDialog->GetPosPixel());
-        const basegfx::B2IPoint aTopLeft(-aParentPos.X(), -aParentPos.Y());
-        CollectChildren(*m_xDialog, aTopLeft, aRet);
-
-        return aRet;
-    }
 };
 
 IMPL_LINK(SalInstanceDialog, PopupScreenShotMenuHdl, const CommandEvent&, 
rCEvt, bool)
@@ -5759,6 +5763,34 @@ public:
         return pRet;
     }
 
+    virtual std::unique_ptr<weld::Window> create_screenshot_window() override
+    {
+        assert(!m_aOwnedToplevel && "only one toplevel per .ui allowed");
+
+        vcl::Window *pRoot = m_xBuilder->get_widget_root();
+        if (SystemWindow *pWindow = dynamic_cast<SystemWindow*>(pRoot))
+        {
+            std::unique_ptr<weld::Window> xRet(new SalInstanceWindow(pWindow, 
this, false));
+            m_aOwnedToplevel.set(pWindow);
+            m_xBuilder->drop_ownership(pWindow);
+            return xRet;
+        }
+
+        VclPtrInstance<Dialog> xDialog(nullptr, WB_HIDE | WB_STDDIALOG | 
WB_SIZEABLE | WB_CLOSEABLE, Dialog::InitFlag::NoParent);
+        xDialog->SetText(utl::ConfigManager::getProductName());
+
+        auto xContentArea = VclPtr<VclVBox>::Create(xDialog, false, 12);
+        pRoot->SetParent(xContentArea);
+        assert(pRoot == xContentArea->GetWindow(GetWindowType::FirstChild));
+        xContentArea->Show();
+        pRoot->Show();
+        xDialog->SetHelpId(pRoot->GetHelpId());
+
+        m_aOwnedToplevel.set(xDialog);
+
+        return std::unique_ptr<weld::Dialog>(new SalInstanceDialog(xDialog, 
this, false));
+    }
+
     virtual std::unique_ptr<weld::Window> weld_window(const OString &id, bool 
bTakeOwnership) override
     {
         SystemWindow* pWindow = m_xBuilder->get<SystemWindow>(id);
@@ -5799,6 +5831,8 @@ public:
     virtual std::unique_ptr<weld::Notebook> weld_notebook(const OString &id, 
bool bTakeOwnership) override
     {
         vcl::Window* pNotebook = m_xBuilder->get<vcl::Window>(id);
+        if (!pNotebook)
+            return nullptr;
         if (pNotebook->GetType() == WindowType::TABCONTROL)
             return 
std::make_unique<SalInstanceNotebook>(static_cast<TabControl*>(pNotebook), 
this, bTakeOwnership);
         if (pNotebook->GetType() == WindowType::VERTICALTABCONTROL)
diff --git a/vcl/source/window/dialog.cxx b/vcl/source/window/dialog.cxx
index 679403c9efbc..714141ea8131 100644
--- a/vcl/source/window/dialog.cxx
+++ b/vcl/source/window/dialog.cxx
@@ -386,7 +386,6 @@ void Dialog::ImplInitDialogData()
     mbInSyncExecute         = false;
     mbInClose               = false;
     mbModalMode             = false;
-    mbPaintComplete         = false;
     mpContentArea.clear();
     mpActionArea.clear();
     mnMousePositioned       = 0;
@@ -1013,58 +1012,6 @@ void Dialog::ImplEndExecuteModal()
     pSVData->maAppData.mnModalMode--;
 }
 
-void Dialog::PrePaint(vcl::RenderContext& rRenderContext)
-{
-    SystemWindow::PrePaint(rRenderContext);
-    mbPaintComplete = false;
-}
-
-void Dialog::PostPaint(vcl::RenderContext& rRenderContext)
-{
-    SystemWindow::PostPaint(rRenderContext);
-    mbPaintComplete = true;
-}
-
-std::vector<OString> Dialog::getAllPageUIXMLDescriptions() const
-{
-    // default has no pages
-    return std::vector<OString>();
-}
-
-bool Dialog::selectPageByUIXMLDescription(const OString& /*rUIXMLDescription*/)
-{
-    // default cannot select anything (which is okay, return true)
-    return true;
-}
-
-void Dialog::ensureRepaint()
-{
-    // ensure repaint
-    Invalidate();
-    mbPaintComplete = false;
-
-    while (!mbPaintComplete)
-    {
-        Application::Yield();
-    }
-}
-
-void Dialog::createScreenshot(VirtualDevice& rOutput)
-{
-    // same prerequisites as in Execute()
-    setDeferredProperties();
-    ImplAdjustNWFSizes();
-    Show();
-    ToTop();
-    ensureRepaint();
-
-    Point aPos;
-    Size aSize(GetOutputSizePixel());
-
-    rOutput.SetOutputSizePixel(aSize);
-    rOutput.DrawOutDev(aPos, aSize, aPos, aSize, *this);
-}
-
 short Dialog::Execute()
 {
 // Once the Android app is based on same idea as the iOS one currently
diff --git a/vcl/source/window/syswin.cxx b/vcl/source/window/syswin.cxx
index aa0964524e35..c6ecb2109a74 100644
--- a/vcl/source/window/syswin.cxx
+++ b/vcl/source/window/syswin.cxx
@@ -31,6 +31,7 @@
 #include <vcl/taskpanelist.hxx>
 #include <vcl/tabctrl.hxx>
 #include <vcl/tabpage.hxx>
+#include <vcl/virdev.hxx>
 
 #include <rtl/strbuf.hxx>
 
@@ -67,6 +68,7 @@ SystemWindow::SystemWindow(WindowType nType)
     , mbHideBtn(false)
     , mbSysChild(false)
     , mbIsCalculatingInitialLayoutSize(false)
+    , mbPaintComplete(false)
     , mnMenuBarMode(MenuBarMode::Normal)
     , mnIcon(0)
     , mpImplData(new ImplData)
@@ -1152,4 +1154,56 @@ void SystemWindow::doDeferredInit(WinBits /*nBits*/)
     SAL_WARN("vcl.layout", "SystemWindow in layout without doDeferredInit 
impl");
 }
 
+std::vector<OString> SystemWindow::getAllPageUIXMLDescriptions() const
+{
+    // default has no pages
+    return std::vector<OString>();
+}
+
+bool SystemWindow::selectPageByUIXMLDescription(const OString& 
/*rUIXMLDescription*/)
+{
+    // default cannot select anything (which is okay, return true)
+    return true;
+}
+
+void SystemWindow::createScreenshot(VirtualDevice& rOutput)
+{
+    // same prerequisites as in Execute()
+    setDeferredProperties();
+    ImplAdjustNWFSizes();
+    Show();
+    ToTop();
+    ensureRepaint();
+
+    Point aPos;
+    Size aSize(GetOutputSizePixel());
+
+    rOutput.SetOutputSizePixel(aSize);
+    rOutput.DrawOutDev(aPos, aSize, aPos, aSize, *this);
+}
+
+void SystemWindow::PrePaint(vcl::RenderContext& rRenderContext)
+{
+    Window::PrePaint(rRenderContext);
+    mbPaintComplete = false;
+}
+
+void SystemWindow::PostPaint(vcl::RenderContext& rRenderContext)
+{
+    Window::PostPaint(rRenderContext);
+    mbPaintComplete = true;
+}
+
+void SystemWindow::ensureRepaint()
+{
+    // ensure repaint
+    Invalidate();
+    mbPaintComplete = false;
+
+    while (!mbPaintComplete)
+    {
+        Application::Yield();
+    }
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/uiconfig/ui/screenshotparent.ui 
b/vcl/uiconfig/ui/screenshotparent.ui
new file mode 100644
index 000000000000..722a1e810839
--- /dev/null
+++ b/vcl/uiconfig/ui/screenshotparent.ui
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="vcl">
+  <requires lib="gtk+" version="3.18"/>
+  <object class="GtkDialog" id="ScreenShot">
+    <property name="can_focus">False</property>
+    <property name="border_width">6</property>
+    <property name="modal">True</property>
+    <property name="default_width">0</property>
+    <property name="default_height">0</property>
+    <property name="type_hint">dialog</property>
+    <child>
+      <placeholder/>
+    </child>
+    <child internal-child="vbox">
+      <object class="GtkBox" id="ScreenShotBox">
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">12</property>
+        <child internal-child="action_area">
+          <object class="GtkButtonBox" id="internalarea">
+            <property name="can_focus">False</property>
+            <property name="layout_style">end</property>
+            <child>
+              <object class="GtkButton" id="cancel">
+                <property name="label">gtk-close</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_stock">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">3</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child>
+          <placeholder/>
+        </child>
+      </object>
+    </child>
+    <action-widgets>
+      <action-widget response="-6">cancel</action-widget>
+    </action-widgets>
+  </object>
+</interface>
diff --git a/vcl/unx/gtk3/gtk3gtkinst.cxx b/vcl/unx/gtk3/gtk3gtkinst.cxx
index 1ddbc7f0b180..9dd62384c2da 100644
--- a/vcl/unx/gtk3/gtk3gtkinst.cxx
+++ b/vcl/unx/gtk3/gtk3gtkinst.cxx
@@ -3223,6 +3223,126 @@ namespace
     }
 }
 
+namespace
+{
+    struct ButtonOrder
+    {
+        const char * m_aType;
+        int m_nPriority;
+    };
+
+    int getButtonPriority(const OString &rType)
+    {
+        static const size_t N_TYPES = 6;
+        static const ButtonOrder aDiscardCancelSave[N_TYPES] =
+        {
+            { "/discard", 0 },
+            { "/cancel", 1 },
+            { "/no", 2 },
+            { "/save", 3 },
+            { "/yes", 3 },
+            { "/ok", 3 }
+        };
+
+        static const ButtonOrder aSaveDiscardCancel[N_TYPES] =
+        {
+            { "/save", 0 },
+            { "/yes", 0 },
+            { "/ok", 0 },
+            { "/discard", 1 },
+            { "/no", 1 },
+            { "/cancel", 2 }
+        };
+
+        const ButtonOrder* pOrder = &aDiscardCancelSave[0];
+
+        const OUString &rEnv = Application::GetDesktopEnvironment();
+
+        if (rEnv.equalsIgnoreAsciiCase("windows") ||
+            rEnv.equalsIgnoreAsciiCase("tde") ||
+            rEnv.startsWithIgnoreAsciiCase("kde"))
+        {
+            pOrder = &aSaveDiscardCancel[0];
+        }
+
+        for (size_t i = 0; i < N_TYPES; ++i, ++pOrder)
+        {
+            if (rType.endsWith(pOrder->m_aType))
+                return pOrder->m_nPriority;
+        }
+
+        return -1;
+    }
+
+    bool sortButtons(const GtkWidget* pA, const GtkWidget* pB)
+    {
+        //order within groups according to platform rules
+        return getButtonPriority(::get_help_id(pA)) < 
getButtonPriority(::get_help_id(pB));
+    }
+
+    void sort_native_button_order(GtkBox* pContainer)
+    {
+        std::vector<GtkWidget*> aChildren;
+        GList* pChildren = 
gtk_container_get_children(GTK_CONTAINER(pContainer));
+        for (GList* pChild = g_list_first(pChildren); pChild; pChild = 
g_list_next(pChild))
+            aChildren.push_back(static_cast<GtkWidget*>(pChild->data));
+        g_list_free(pChildren);
+
+        //sort child order within parent so that we match the platform button 
order
+        std::stable_sort(aChildren.begin(), aChildren.end(), sortButtons);
+
+        for (size_t pos = 0; pos < aChildren.size(); ++pos)
+            gtk_box_reorder_child(pContainer, aChildren[pos], pos);
+    }
+
+    Point get_csd_offset(GtkWidget* pTopLevel)
+    {
+        // try and omit drawing CSD under wayland
+        GList* pChildren = 
gtk_container_get_children(GTK_CONTAINER(pTopLevel));
+        GList* pChild = g_list_first(pChildren);
+
+        int x, y;
+        gtk_widget_translate_coordinates(GTK_WIDGET(pChild->data),
+                                         GTK_WIDGET(pTopLevel),
+                                         0, 0, &x, &y);
+
+        int innerborder = 
gtk_container_get_border_width(GTK_CONTAINER(pChild->data));
+        g_list_free(pChildren);
+
+        int outerborder = 
gtk_container_get_border_width(GTK_CONTAINER(pTopLevel));
+        int totalborder = outerborder + innerborder;
+        x -= totalborder;
+        y -= totalborder;
+
+        return Point(x, y);
+    }
+
+    void do_collect_screenshot_data(GtkWidget* pItem, gpointer data)
+    {
+        GtkWidget* pTopLevel = gtk_widget_get_toplevel(pItem);
+
+        int x, y;
+        gtk_widget_translate_coordinates(pItem, pTopLevel, 0, 0, &x, &y);
+
+        Point aOffset = get_csd_offset(pTopLevel);
+
+        GtkAllocation alloc;
+        gtk_widget_get_allocation(pItem, &alloc);
+
+        const basegfx::B2IPoint aCurrentTopLeft(x - aOffset.X(), y - 
aOffset.Y());
+        const basegfx::B2IRange aCurrentRange(aCurrentTopLeft, aCurrentTopLeft 
+ basegfx::B2IPoint(alloc.width, alloc.height));
+
+        if (!aCurrentRange.isEmpty())
+        {
+            weld::ScreenShotCollection* pCollection = 
static_cast<weld::ScreenShotCollection*>(data);
+            pCollection->emplace_back(::get_help_id(pItem), aCurrentRange);
+        }
+
+        if (GTK_IS_CONTAINER(pItem))
+            gtk_container_forall(GTK_CONTAINER(pItem), 
do_collect_screenshot_data, data);
+    }
+}
+
 class GtkInstanceWindow : public GtkInstanceContainer, public virtual 
weld::Window
 {
 private:
@@ -3434,87 +3554,68 @@ public:
             g_signal_handler_unblock(m_pWidget, 
m_nToplevelFocusChangedSignalId);
     }
 
-    virtual ~GtkInstanceWindow() override
-    {
-        if (m_nToplevelFocusChangedSignalId)
-            g_signal_handler_disconnect(m_pWindow, 
m_nToplevelFocusChangedSignalId);
-        if (m_xWindow.is())
-            m_xWindow->clear();
-    }
-};
-
-namespace
-{
-    struct ButtonOrder
-    {
-        const char * m_aType;
-        int m_nPriority;
-    };
-
-    int getButtonPriority(const OString &rType)
+    virtual void draw(VirtualDevice& rOutput) override
     {
-        static const size_t N_TYPES = 6;
-        static const ButtonOrder aDiscardCancelSave[N_TYPES] =
+        // detect if we have to manually setup its size
+        bool bAlreadyRealized = gtk_widget_get_realized(GTK_WIDGET(m_pWindow));
+        // has to be visible for draw to work
+        bool bAlreadyVisible = gtk_widget_get_visible(GTK_WIDGET(m_pWindow));
+        if (!bAlreadyVisible)
         {
-            { "/discard", 0 },
-            { "/cancel", 1 },
-            { "/no", 2 },
-            { "/save", 3 },
-            { "/yes", 3 },
-            { "/ok", 3 }
-        };
+            if (GTK_IS_DIALOG(m_pWindow))
+                
sort_native_button_order(GTK_BOX(gtk_dialog_get_action_area(GTK_DIALOG(m_pWindow))));
+            gtk_widget_show(GTK_WIDGET(m_pWindow));
+        }
 
-        static const ButtonOrder aSaveDiscardCancel[N_TYPES] =
+        if (!bAlreadyRealized)
         {
-            { "/save", 0 },
-            { "/yes", 0 },
-            { "/ok", 0 },
-            { "/discard", 1 },
-            { "/no", 1 },
-            { "/cancel", 2 }
-        };
+            GtkAllocation allocation;
+            gtk_widget_realize(GTK_WIDGET(m_pWindow));
+            gtk_widget_get_allocation(GTK_WIDGET(m_pWindow), &allocation);
+            gtk_widget_size_allocate(GTK_WIDGET(m_pWindow), &allocation);
+        }
 
-        const ButtonOrder* pOrder = &aDiscardCancelSave[0];
+        rOutput.SetOutputSizePixel(get_size());
+        cairo_surface_t* pSurface = get_underlying_cairo_surface(rOutput);
+        cairo_t* cr = cairo_create(pSurface);
 
-        const OUString &rEnv = Application::GetDesktopEnvironment();
+        Point aOffset = get_csd_offset(GTK_WIDGET(m_pWindow));
 
-        if (rEnv.equalsIgnoreAsciiCase("windows") ||
-            rEnv.equalsIgnoreAsciiCase("tde") ||
-            rEnv.startsWithIgnoreAsciiCase("kde"))
-        {
-            pOrder = &aSaveDiscardCancel[0];
-        }
+#if defined(GDK_WINDOWING_X11)
+        GdkDisplay *pDisplay = gtk_widget_get_display(GTK_WIDGET(m_pWindow));
+        if (DLSYM_GDK_IS_X11_DISPLAY(pDisplay))
+            assert(aOffset.X() == 0 && aOffset.Y() == 0 && "expected offset of 
0 under X");
+#endif
 
-        for (size_t i = 0; i < N_TYPES; ++i, ++pOrder)
-        {
-            if (rType.endsWith(pOrder->m_aType))
-                return pOrder->m_nPriority;
-        }
+        cairo_translate(cr, -aOffset.X(), -aOffset.Y());
 
-        return -1;
-    }
+        gtk_widget_draw(GTK_WIDGET(m_pWindow), cr);
 
-    bool sortButtons(const GtkWidget* pA, const GtkWidget* pB)
-    {
-        //order within groups according to platform rules
-        return getButtonPriority(::get_help_id(pA)) < 
getButtonPriority(::get_help_id(pB));
+        cairo_destroy(cr);
+
+        if (!bAlreadyVisible)
+            gtk_widget_hide(GTK_WIDGET(m_pWindow));
+        if (!bAlreadyRealized)
+            gtk_widget_unrealize(GTK_WIDGET(m_pWindow));
     }
 
-    void sort_native_button_order(GtkBox* pContainer)
+    virtual weld::ScreenShotCollection collect_screenshot_data() override
     {
-        std::vector<GtkWidget*> aChildren;
-        GList* pChildren = 
gtk_container_get_children(GTK_CONTAINER(pContainer));
-        for (GList* pChild = g_list_first(pChildren); pChild; pChild = 
g_list_next(pChild))
-            aChildren.push_back(static_cast<GtkWidget*>(pChild->data));
-        g_list_free(pChildren);
+        weld::ScreenShotCollection aRet;
 
-        //sort child order within parent so that we match the platform button 
order
-        std::stable_sort(aChildren.begin(), aChildren.end(), sortButtons);
+        gtk_container_foreach(GTK_CONTAINER(m_pWindow), 
do_collect_screenshot_data, &aRet);
 
-        for (size_t pos = 0; pos < aChildren.size(); ++pos)
-            gtk_box_reorder_child(pContainer, aChildren[pos], pos);
+        return aRet;
     }
-}
+
+    virtual ~GtkInstanceWindow() override
+    {
+        if (m_nToplevelFocusChangedSignalId)
+            g_signal_handler_disconnect(m_pWindow, 
m_nToplevelFocusChangedSignalId);
+        if (m_xWindow.is())
+            m_xWindow->clear();
+    }
+};
 
 class GtkInstanceDialog;
 
@@ -3861,54 +3962,6 @@ private:
         return false;
     }
 
-    static Point get_csd_offset(GtkWidget* pTopLevel)
-    {
-        // try and omit drawing CSD under wayland
-        GList* pChildren = 
gtk_container_get_children(GTK_CONTAINER(pTopLevel));
-        GList* pChild = g_list_first(pChildren);
-
-        int x, y;
-        gtk_widget_translate_coordinates(GTK_WIDGET(pChild->data),
-                                         GTK_WIDGET(pTopLevel),
-                                         0, 0, &x, &y);
-
-        int innerborder = 
gtk_container_get_border_width(GTK_CONTAINER(pChild->data));
-        g_list_free(pChildren);
-
-        int outerborder = 
gtk_container_get_border_width(GTK_CONTAINER(pTopLevel));
-        int totalborder = outerborder + innerborder;
-        x -= totalborder;
-        y -= totalborder;
-
-        return Point(x, y);
-    }
-
-    static void do_collect_screenshot_data(GtkWidget* pItem, gpointer data)
-    {
-        GtkWidget* pTopLevel = gtk_widget_get_toplevel(pItem);
-
-        int x, y;
-        gtk_widget_translate_coordinates(pItem, pTopLevel, 0, 0, &x, &y);
-
-        Point aOffset = get_csd_offset(pTopLevel);
-
-        GtkAllocation alloc;
-        gtk_widget_get_allocation(pItem, &alloc);
-
-        const basegfx::B2IPoint aCurrentTopLeft(x - aOffset.X(), y - 
aOffset.Y());
-        const basegfx::B2IRange aCurrentRange(aCurrentTopLeft, aCurrentTopLeft 
+ basegfx::B2IPoint(alloc.width, alloc.height));
-
-        if (!aCurrentRange.isEmpty())
-        {
-            weld::ScreenShotCollection* pCollection = 
static_cast<weld::ScreenShotCollection*>(data);
-            pCollection->emplace_back(::get_help_id(pItem), aCurrentRange);
-        }
-
-        if (GTK_IS_CONTAINER(pItem))
-            gtk_container_forall(GTK_CONTAINER(pItem), 
do_collect_screenshot_data, data);
-    }
-
-
 public:
     GtkInstanceDialog(GtkWindow* pDialog, GtkInstanceBuilder* pBuilder, bool 
bTakeOwnership)
         : GtkInstanceWindow(pDialog, pBuilder, bTakeOwnership)
@@ -4125,59 +4178,6 @@ public:
         //not implemented for the gtk variant
     }
 
-    virtual void draw(VirtualDevice& rOutput) override
-    {
-        // detect if we have to manually setup its size
-        bool bAlreadyRealized = gtk_widget_get_realized(GTK_WIDGET(m_pDialog));
-        // has to be visible for draw to work
-        bool bAlreadyVisible = gtk_widget_get_visible(GTK_WIDGET(m_pDialog));
-        if (!bAlreadyVisible)
-        {
-            
sort_native_button_order(GTK_BOX(gtk_dialog_get_action_area(GTK_DIALOG(m_pDialog))));
-            gtk_widget_show(GTK_WIDGET(m_pDialog));
-        }
-
-        if (!bAlreadyRealized)
-        {
-            GtkAllocation allocation;
-            gtk_widget_realize(GTK_WIDGET(m_pDialog));
-            gtk_widget_get_allocation(GTK_WIDGET(m_pDialog), &allocation);
-            gtk_widget_size_allocate(GTK_WIDGET(m_pDialog), &allocation);
-        }
-
-        rOutput.SetOutputSizePixel(get_size());
-        cairo_surface_t* pSurface = get_underlying_cairo_surface(rOutput);
-        cairo_t* cr = cairo_create(pSurface);
-
-        Point aOffset = get_csd_offset(GTK_WIDGET(m_pDialog));
-
-#if defined(GDK_WINDOWING_X11)
-        GdkDisplay *pDisplay = gtk_widget_get_display(GTK_WIDGET(m_pDialog));
-        if (DLSYM_GDK_IS_X11_DISPLAY(pDisplay))
-            assert(aOffset.X() == 0 && aOffset.Y() == 0 && "expected offset of 
0 under X");
-#endif
-
-        cairo_translate(cr, -aOffset.X(), -aOffset.Y());
-
-        gtk_widget_draw(GTK_WIDGET(m_pDialog), cr);
-
-        cairo_destroy(cr);
-
-        if (!bAlreadyVisible)
-            gtk_widget_hide(GTK_WIDGET(m_pDialog));
-        if (!bAlreadyRealized)
-            gtk_widget_unrealize(GTK_WIDGET(m_pDialog));
-    }
-
-    virtual weld::ScreenShotCollection collect_screenshot_data() override
-    {
-        weld::ScreenShotCollection aRet;
-
-        gtk_container_foreach(GTK_CONTAINER(m_pDialog), 
do_collect_screenshot_data, &aRet);
-
-        return aRet;
-    }
-
     virtual ~GtkInstanceDialog() override
     {
         if (!m_aHiddenWidgets.empty())
@@ -11748,7 +11748,6 @@ public:
         return sPageHelpId;
     }
 
-
     virtual ~GtkInstanceBuilder() override
     {
         g_slist_free(m_pObjectList);
@@ -11795,12 +11794,50 @@ public:
 
     virtual std::unique_ptr<weld::Dialog> weld_dialog(const OString &id, bool 
bTakeOwnership) override
     {
-        GtkDialog* pDialog = GTK_DIALOG(gtk_builder_get_object(m_pBuilder, 
id.getStr()));
+        GtkWindow* pDialog = GTK_WINDOW(gtk_builder_get_object(m_pBuilder, 
id.getStr()));
         if (!pDialog)
             return nullptr;
         if (m_pParentWidget)
-            gtk_window_set_transient_for(GTK_WINDOW(pDialog), 
GTK_WINDOW(gtk_widget_get_toplevel(m_pParentWidget)));
-        return std::make_unique<GtkInstanceDialog>(GTK_WINDOW(pDialog), this, 
bTakeOwnership);
+            gtk_window_set_transient_for(pDialog, 
GTK_WINDOW(gtk_widget_get_toplevel(m_pParentWidget)));
+        return std::make_unique<GtkInstanceDialog>(pDialog, this, 
bTakeOwnership);
+    }
+
+    virtual std::unique_ptr<weld::Window> create_screenshot_window() override
+    {
+        GtkWidget* pTopLevel = nullptr;
+
+        for (GSList* l = m_pObjectList; l; l = g_slist_next(l))
+        {
+            GObject* pObj = static_cast<GObject*>(l->data);
+
+            if (!GTK_IS_WIDGET(pObj) || 
gtk_widget_get_parent(GTK_WIDGET(pObj)))
+                continue;
+
+            if (!pTopLevel)
+                pTopLevel = GTK_WIDGET(pObj);
+            else if (GTK_IS_WINDOW(pObj))
+                pTopLevel = GTK_WIDGET(pObj);
+        }
+
+        if (!pTopLevel)
+            return nullptr;
+
+        GtkWindow* pDialog;
+        if (GTK_IS_WINDOW(pTopLevel))
+            pDialog = GTK_WINDOW(pTopLevel);
+        else
+        {
+            pDialog = GTK_WINDOW(gtk_dialog_new());
+            ::set_help_id(GTK_WIDGET(pDialog), ::get_help_id(pTopLevel));
+
+            GtkWidget* pContentArea = 
gtk_dialog_get_content_area(GTK_DIALOG(pDialog));
+            gtk_container_add(GTK_CONTAINER(pContentArea), pTopLevel);
+            gtk_widget_show_all(pTopLevel);
+        }
+
+        if (m_pParentWidget)
+            gtk_window_set_transient_for(pDialog, 
GTK_WINDOW(gtk_widget_get_toplevel(m_pParentWidget)));
+        return std::make_unique<GtkInstanceDialog>(pDialog, this, true);
     }
 
     virtual std::unique_ptr<weld::Window> weld_window(const OString &id, bool 
bTakeOwnership) override
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to