get native gtk widgets in sidebars working

Change-Id: If65aef1249f54a87d7854c3fa2db4319a24a5a05
Reviewed-on: https://gerrit.libreoffice.org/85326
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Tested-by: Caolán McNamara <caolanm@redhat.com>
diff --git a/extensions/source/propctrlr/browserline.cxx b/extensions/source/propctrlr/browserline.cxx
index 10beadb..9b45c0c 100644
--- a/extensions/source/propctrlr/browserline.cxx
+++ b/extensions/source/propctrlr/browserline.cxx
@@ -52,11 +52,9 @@ namespace pcr
    namespace PropertyLineElement = ::com::sun::star::inspection::PropertyLineElement;

    OBrowserLine::OBrowserLine(const OUString& rEntryName, weld::Container* pParent, weld::SizeGroup* pLabelGroup,
                               weld::Container* pInitialControlParent, bool bInterimBuilder)
                               weld::Container* pInitialControlParent)
        : m_sEntryName(rEntryName)
        , m_xBuilder(bInterimBuilder
                     ? Application::CreateInterimBuilder(pParent, "modules/spropctrlr/ui/browserline.ui")
                     : Application::CreateBuilder(pParent, "modules/spropctrlr/ui/browserline.ui"))
        , m_xBuilder(Application::CreateBuilder(pParent, "modules/spropctrlr/ui/browserline.ui"))
        , m_xContainer(m_xBuilder->weld_container("BrowserLine"))
        , m_xFtTitle(m_xBuilder->weld_label("label"))
        , m_xBrowseButton(m_xBuilder->weld_button("browse"))
diff --git a/extensions/source/propctrlr/browserline.hxx b/extensions/source/propctrlr/browserline.hxx
index e3e668a..cbe577e 100644
--- a/extensions/source/propctrlr/browserline.hxx
+++ b/extensions/source/propctrlr/browserline.hxx
@@ -70,7 +70,7 @@ namespace pcr

    public:
        OBrowserLine(const OUString& rEntryName, weld::Container* pParent, weld::SizeGroup* pLabelGroup,
                     weld::Container* pInitialControlParent, bool bInterimBuilder);
                     weld::Container* pInitialControlParent);
        ~OBrowserLine();

        void setControl( const css::uno::Reference< css::inspection::XPropertyControl >& rxControl );
diff --git a/extensions/source/propctrlr/browserlistbox.cxx b/extensions/source/propctrlr/browserlistbox.cxx
index b626731..a50d93c 100644
--- a/extensions/source/propctrlr/browserlistbox.cxx
+++ b/extensions/source/propctrlr/browserlistbox.cxx
@@ -298,7 +298,7 @@ namespace pcr
        }
    }

    OBrowserListBox::OBrowserListBox(weld::Builder& rBuilder, weld::Container* pContainer, bool bInterimBuilder)
    OBrowserListBox::OBrowserListBox(weld::Builder& rBuilder, weld::Container* pContainer)
        : m_xScrolledWindow(rBuilder.weld_scrolled_window("scrolledwindow"))
        , m_xLinesPlayground(rBuilder.weld_container("playground"))
        , m_xSizeGroup(rBuilder.create_size_group())
@@ -308,7 +308,6 @@ namespace pcr
        , m_pControlObserver( nullptr )
        , m_nTheNameSize(0)
        , m_nRowHeight(0)
        , m_bInterimBuilder(bInterimBuilder)
        , m_pControlContextImpl( new PropertyControlContext_Impl( *this ) )
    {
        m_xScrolledWindow->set_size_request(-1, m_xScrolledWindow->get_text_height() * 20);
@@ -465,8 +464,7 @@ namespace pcr
    {
        // create a new line
        BrowserLinePointer pBrowserLine(new OBrowserLine(rPropertyData.sName, m_xLinesPlayground.get(),
                                                         m_xSizeGroup.get(), m_pInitialControlParent,
                                                         m_bInterimBuilder));
                                                         m_xSizeGroup.get(), m_pInitialControlParent));

        // check that the name is unique
        for (auto const& line : m_aLines)
diff --git a/extensions/source/propctrlr/browserlistbox.hxx b/extensions/source/propctrlr/browserlistbox.hxx
index 1a1b63a..ad0a3aa 100644
--- a/extensions/source/propctrlr/browserlistbox.hxx
+++ b/extensions/source/propctrlr/browserlistbox.hxx
@@ -84,7 +84,6 @@ namespace pcr
                                    m_xActiveControl;
        sal_uInt16                  m_nTheNameSize;
        int                         m_nRowHeight;
        bool                        m_bInterimBuilder;
        ::rtl::Reference< PropertyControlContext_Impl >
                                    m_pControlContextImpl;

@@ -92,7 +91,7 @@ namespace pcr
        void    ShowEntry(sal_uInt16 nPos);

    public:
        explicit OBrowserListBox(weld::Builder& rBuilder, weld::Container* pContainer, bool bInterimBuilder);
        explicit OBrowserListBox(weld::Builder& rBuilder, weld::Container* pContainer);
        ~OBrowserListBox();

        void                        SetListener( IPropertyLineListener* _pListener );
diff --git a/extensions/source/propctrlr/browserpage.cxx b/extensions/source/propctrlr/browserpage.cxx
index 9bba600..183743e 100644
--- a/extensions/source/propctrlr/browserpage.cxx
+++ b/extensions/source/propctrlr/browserpage.cxx
@@ -22,13 +22,11 @@

namespace pcr
{
    OBrowserPage::OBrowserPage(weld::Container* pParent, weld::Container* pInitialControlContainer, bool bInterimBuilder)
    OBrowserPage::OBrowserPage(weld::Container* pParent, weld::Container* pInitialControlContainer)
        : m_pParent(pParent)
        , m_xBuilder(bInterimBuilder
                     ? Application::CreateInterimBuilder(pParent, "modules/spropctrlr/ui/browserpage.ui")
                     : Application::CreateBuilder(pParent, "modules/spropctrlr/ui/browserpage.ui"))
        , m_xBuilder(Application::CreateBuilder(pParent, "modules/spropctrlr/ui/browserpage.ui"))
        , m_xContainer(m_xBuilder->weld_container("BrowserPage"))
        , m_xListBox(std::make_unique<OBrowserListBox>(*m_xBuilder, pInitialControlContainer, bInterimBuilder))
        , m_xListBox(std::make_unique<OBrowserListBox>(*m_xBuilder, pInitialControlContainer))
    {
    }

diff --git a/extensions/source/propctrlr/browserpage.hxx b/extensions/source/propctrlr/browserpage.hxx
index 4018a6b..8ab95cb 100644
--- a/extensions/source/propctrlr/browserpage.hxx
+++ b/extensions/source/propctrlr/browserpage.hxx
@@ -36,8 +36,8 @@ namespace pcr
        OUString m_aPageTitle;

    public:
        // if bInterimBuilder wasn't needed this could inherit from BuilderPage
        explicit OBrowserPage(weld::Container* pParent, weld::Container* pContainer, bool bInterimBuilder);
        // TODO inherit from BuilderPage
        explicit OBrowserPage(weld::Container* pParent, weld::Container* pContainer);
        ~OBrowserPage();

        void SetPageTitle(const OUString& rPageTitle) { m_aPageTitle = rPageTitle; }
diff --git a/extensions/source/propctrlr/browserview.cxx b/extensions/source/propctrlr/browserview.cxx
index 35d0626..fb4c28d 100644
--- a/extensions/source/propctrlr/browserview.cxx
+++ b/extensions/source/propctrlr/browserview.cxx
@@ -29,8 +29,8 @@ namespace pcr
    using namespace ::com::sun::star::uno;
    using namespace ::com::sun::star::lang;

    OPropertyBrowserView::OPropertyBrowserView(css::uno::Reference<css::uno::XComponentContext>& rContext, weld::Builder& rBuilder, bool bInterimBuilder)
        : m_xPropBox(new OPropertyEditor(rContext, rBuilder, bInterimBuilder))
    OPropertyBrowserView::OPropertyBrowserView(css::uno::Reference<css::uno::XComponentContext>& rContext, weld::Builder& rBuilder)
        : m_xPropBox(new OPropertyEditor(rContext, rBuilder))
        , m_nActivePage(0)
    {
        m_xPropBox->SetHelpId(HID_FM_PROPDLG_TABCTR);
diff --git a/extensions/source/propctrlr/browserview.hxx b/extensions/source/propctrlr/browserview.hxx
index c26f57d..22f8971 100644
--- a/extensions/source/propctrlr/browserview.hxx
+++ b/extensions/source/propctrlr/browserview.hxx
@@ -35,7 +35,7 @@ namespace pcr
        Link<LinkParamNone*,void>   m_aPageActivationHandler;

    public:
        explicit OPropertyBrowserView(css::uno::Reference<css::uno::XComponentContext>& rContext, weld::Builder& rBuilder, bool bInterimBuilder);
        explicit OPropertyBrowserView(css::uno::Reference<css::uno::XComponentContext>& rContext, weld::Builder& rBuilder);
        ~OPropertyBrowserView();

        OPropertyEditor&    getPropertyBox() { return *m_xPropBox; }
diff --git a/extensions/source/propctrlr/handlerhelper.cxx b/extensions/source/propctrlr/handlerhelper.cxx
index 0f29819..18a575d 100644
--- a/extensions/source/propctrlr/handlerhelper.cxx
+++ b/extensions/source/propctrlr/handlerhelper.cxx
@@ -296,23 +296,14 @@ namespace pcr

    std::unique_ptr<weld::Builder> PropertyHandlerHelper::makeBuilder(const OUString& rUIFile, const Reference<XComponentContext>& rContext)
    {
        bool bInterimBuilder(true);
        Any aReturn = rContext->getValueByName("InterimBuilder");
        aReturn >>= bInterimBuilder;

        Reference<XWindow> xWindow(rContext->getValueByName("BuilderParent"), UNO_QUERY_THROW);
        weld::TransportAsXWindow& rTunnel = dynamic_cast<weld::TransportAsXWindow&>(*xWindow);

        // bInterimBuilder for the hosted in sidebar in basic IDE case
        if (!bInterimBuilder)
            return std::unique_ptr<weld::Builder>(Application::CreateBuilder(rTunnel.getWidget(), rUIFile));
        return std::unique_ptr<weld::Builder>(Application::CreateInterimBuilder(rTunnel.getWidget(), rUIFile));
        return std::unique_ptr<weld::Builder>(Application::CreateBuilder(rTunnel.getWidget(), rUIFile));
    }

    void PropertyHandlerHelper::setBuilderParent(css::uno::Reference<css::uno::XComponentContext>& rContext, weld::Widget* pParent, bool bInterimBuilder)
    void PropertyHandlerHelper::setBuilderParent(css::uno::Reference<css::uno::XComponentContext>& rContext, weld::Widget* pParent)
    {
        Reference<css::container::XNameContainer> xName(rContext, UNO_QUERY_THROW);
        xName->insertByName("InterimBuilder", makeAny(bInterimBuilder));
        Reference<XWindow> xWindow(new weld::TransportAsXWindow(pParent));
        xName->insertByName("BuilderParent", makeAny(xWindow));
    }
@@ -320,7 +311,6 @@ namespace pcr
    void PropertyHandlerHelper::clearBuilderParent(css::uno::Reference<css::uno::XComponentContext>& rContext)
    {
        Reference<css::container::XNameContainer> xName(rContext, UNO_QUERY_THROW);
        xName->removeByName("InterimBuilder");
        xName->removeByName("BuilderParent");
    }

diff --git a/extensions/source/propctrlr/handlerhelper.hxx b/extensions/source/propctrlr/handlerhelper.hxx
index c170538..bf2aec5 100644
--- a/extensions/source/propctrlr/handlerhelper.hxx
+++ b/extensions/source/propctrlr/handlerhelper.hxx
@@ -215,7 +215,7 @@ namespace pcr

        static std::unique_ptr<weld::Builder> makeBuilder(const OUString& rUIFile, const css::uno::Reference<css::uno::XComponentContext>& rContext);

        static void setBuilderParent(css::uno::Reference<css::uno::XComponentContext>& rContext, weld::Widget* pParent, bool bInterim);
        static void setBuilderParent(css::uno::Reference<css::uno::XComponentContext>& rContext, weld::Widget* pParent);

        static void clearBuilderParent(css::uno::Reference<css::uno::XComponentContext>& rContext);

diff --git a/extensions/source/propctrlr/propcontroller.cxx b/extensions/source/propctrlr/propcontroller.cxx
index 885e7ef..88b38e2 100644
--- a/extensions/source/propctrlr/propcontroller.cxx
+++ b/extensions/source/propctrlr/propcontroller.cxx
@@ -90,7 +90,6 @@ namespace pcr
            ,m_bSuspendingPropertyHandlers( false )
            ,m_bConstructed( false )
            ,m_bBindingIntrospectee( false )
            ,m_bInterimBuilder( false )
    {
    }

@@ -360,7 +359,6 @@ namespace pcr
        if (weld::TransportAsXWindow* pTunnel = dynamic_cast<weld::TransportAsXWindow*>(xContainerWindow.get()))
        {
            xBuilder.reset(Application::CreateBuilder(pTunnel->getWidget(), sUIFile));
            m_bInterimBuilder = false;
        }
        else
        {
@@ -369,7 +367,6 @@ namespace pcr
            if (!pParentWin)
                throw RuntimeException("The frame is invalid. Unable to extract the container window.",*this);
            xBuilder.reset(Application::CreateInterimBuilder(pParentWin, sUIFile));
            m_bInterimBuilder = true;
        }

        Construct(xContainerWindow, std::move(xBuilder));
@@ -658,7 +655,7 @@ namespace pcr

        m_xBuilder = std::move(xBuilder);

        m_xPropView.reset(new OPropertyBrowserView(m_xContext, *m_xBuilder, m_bInterimBuilder));
        m_xPropView.reset(new OPropertyBrowserView(m_xContext, *m_xBuilder));
        m_xPropView->setPageActivationHandler(LINK(this, OPropertyBrowserController, OnPageActivation));

        // add as dispose listener for our view. The view is disposed by the frame we're plugged into,
diff --git a/extensions/source/propctrlr/propcontroller.hxx b/extensions/source/propctrlr/propcontroller.hxx
index ee35d79..7cfeba9 100644
--- a/extensions/source/propctrlr/propcontroller.hxx
+++ b/extensions/source/propctrlr/propcontroller.hxx
@@ -134,7 +134,6 @@ namespace pcr
        bool        m_bSuspendingPropertyHandlers;
        bool        m_bConstructed;
        bool        m_bBindingIntrospectee;
        bool        m_bInterimBuilder;

    protected:
        DECLARE_XINTERFACE()
diff --git a/extensions/source/propctrlr/propertyeditor.cxx b/extensions/source/propctrlr/propertyeditor.cxx
index 41a7be1..e102a4d 100644
--- a/extensions/source/propctrlr/propertyeditor.cxx
+++ b/extensions/source/propctrlr/propertyeditor.cxx
@@ -31,7 +31,7 @@ namespace pcr
    using ::com::sun::star::inspection::XPropertyControl;
    using ::com::sun::star::uno::Reference;

    OPropertyEditor::OPropertyEditor(css::uno::Reference<css::uno::XComponentContext>& rContext, weld::Builder& rBuilder, bool bInterimBuilder)
    OPropertyEditor::OPropertyEditor(css::uno::Reference<css::uno::XComponentContext>& rContext, weld::Builder& rBuilder)
        : m_xContainer(rBuilder.weld_container("box"))
        , m_xTabControl(rBuilder.weld_notebook("tabcontrol"))
        , m_xControlHoldingParent(rBuilder.weld_container("controlparent")) // controls initially have this parent before they are moved
@@ -40,11 +40,10 @@ namespace pcr
        , m_pObserver(nullptr)
        , m_nNextId(1)
        , m_bHasHelpSection(false)
        , m_bInterimBuilder(bInterimBuilder)
        , m_nMinHelpLines(0)
        , m_nMaxHelpLines(0)
    {
        PropertyHandlerHelper::setBuilderParent(rContext, m_xControlHoldingParent.get(), bInterimBuilder);
        PropertyHandlerHelper::setBuilderParent(rContext, m_xControlHoldingParent.get());

        m_xTabControl->connect_leave_page(LINK(this, OPropertyEditor, OnPageDeactivate));
        m_xTabControl->connect_enter_page(LINK(this, OPropertyEditor, OnPageActivate));
@@ -127,7 +126,7 @@ namespace pcr
        m_xTabControl->append_page(sIdent, rText);

        // create a new page
        auto xPage = std::make_unique<OBrowserPage>(m_xTabControl->get_page(sIdent), m_xControlHoldingParent.get(), m_bInterimBuilder);
        auto xPage = std::make_unique<OBrowserPage>(m_xTabControl->get_page(sIdent), m_xControlHoldingParent.get());
        xPage->SetPageTitle(rText);
        // some knittings
        xPage->getListBox().SetListener(m_pListener);
diff --git a/extensions/source/propctrlr/propertyeditor.hxx b/extensions/source/propctrlr/propertyeditor.hxx
index d04ab25..f0e1b99 100644
--- a/extensions/source/propctrlr/propertyeditor.hxx
+++ b/extensions/source/propctrlr/propertyeditor.hxx
@@ -59,7 +59,6 @@ namespace pcr
        sal_uInt16                  m_nNextId;
        Link<LinkParamNone*,void>   m_aPageActivationHandler;
        bool                        m_bHasHelpSection;
        bool                        m_bInterimBuilder;
        sal_Int32                   m_nMinHelpLines;
        sal_Int32                   m_nMaxHelpLines;

@@ -68,7 +67,7 @@ namespace pcr
        std::map<sal_uInt16, PropertyPage> m_aHiddenPages;

    public:
        explicit OPropertyEditor(css::uno::Reference<css::uno::XComponentContext>& rContext, weld::Builder& rBuilder, bool bInterimBuilder);
        explicit OPropertyEditor(css::uno::Reference<css::uno::XComponentContext>& rContext, weld::Builder& rBuilder);
        ~OPropertyEditor();

        void                        SetLineListener( IPropertyLineListener* );
diff --git a/include/svx/sidebar/PanelLayout.hxx b/include/svx/sidebar/PanelLayout.hxx
index 6439ed5..01cb0ff 100644
--- a/include/svx/sidebar/PanelLayout.hxx
+++ b/include/svx/sidebar/PanelLayout.hxx
@@ -14,6 +14,7 @@

#include <vcl/builder.hxx>
#include <vcl/ctrl.hxx>
#include <vcl/layout.hxx>
#include <vcl/timer.hxx>
#include <vcl/idle.hxx>
#include <vcl/weld.hxx>
@@ -25,6 +26,7 @@ class SVX_DLLPUBLIC PanelLayout : public Control, public VclBuilderContainer
{
protected:
    std::unique_ptr<weld::Builder> m_xBuilder;
    VclPtr<VclVBox> m_xVclContentArea;
    std::unique_ptr<weld::Container> m_xContainer;

private:
diff --git a/include/vcl/svapp.hxx b/include/vcl/svapp.hxx
index b36c22e..8b79031 100644
--- a/include/vcl/svapp.hxx
+++ b/include/vcl/svapp.hxx
@@ -1341,8 +1341,7 @@ public:
    static void setDeInitHook(Link<LinkParamNone*,void> const & hook);

    static weld::Builder* CreateBuilder(weld::Widget* pParent, const OUString &rUIFile);
    static weld::Builder* CreateInterimBuilder(vcl::Window* pParent, const OUString &rUIFile); //for the duration of same SfxTabPages in mixed parent types
    static weld::Builder* CreateInterimBuilder(weld::Widget* pParent, const OUString &rUIFile); //for the duration of same SfxTabPages in mixed parent types
    static weld::Builder* CreateInterimBuilder(vcl::Window* pParent, const OUString &rUIFile); //for the duration of vcl parent windows

    static weld::MessageDialog* CreateMessageDialog(weld::Widget* pParent, VclMessageType eMessageType,
                                                    VclButtonsType eButtonType, const OUString& rPrimaryMessage);
diff --git a/include/vcl/sysdata.hxx b/include/vcl/sysdata.hxx
index 393116d..41277c5 100644
--- a/include/vcl/sysdata.hxx
+++ b/include/vcl/sysdata.hxx
@@ -181,6 +181,7 @@ struct SystemWindowData
    // Nothing
#elif defined( UNX )
    void*           pVisual;        // the visual to be used
    bool            bClipUsingNativeWidget; // default is false, true will attempt to clip the childwindow with a native widget
#endif
};

diff --git a/svx/source/sidebar/PanelLayout.cxx b/svx/source/sidebar/PanelLayout.cxx
index 105bb1c..e82c03f 100644
--- a/svx/source/sidebar/PanelLayout.cxx
+++ b/svx/source/sidebar/PanelLayout.cxx
@@ -30,11 +30,18 @@ PanelLayout::PanelLayout(vcl::Window* pParent, const OString& rID, const OUStrin

    // VclBuilder will trigger resize and start Idle
    if (!bInterimBuilder)
    {
        m_pUIBuilder.reset(new VclBuilder(this, getUIRootDir(), rUIXMLDescription, rID, rFrame));
        if (GetSettings().GetStyleSettings().GetAutoMnemonic())
           Accelerator::GenerateAutoMnemonicsOnHierarchy(this);
    }
    else
        m_xBuilder.reset(Application::CreateInterimBuilder(this, rUIXMLDescription));
    if (GetSettings().GetStyleSettings().GetAutoMnemonic())
       Accelerator::GenerateAutoMnemonicsOnHierarchy(this);
    {
        m_xVclContentArea = VclPtr<VclVBox>::Create(this);
        m_xVclContentArea->Show();
        m_xBuilder.reset(Application::CreateInterimBuilder(m_xVclContentArea, rUIXMLDescription));
        m_xContainer = m_xBuilder->weld_container(rID);
    }
}

PanelLayout::~PanelLayout()
@@ -46,7 +53,9 @@ void PanelLayout::dispose()
{
    m_bInClose = true;
    m_aPanelLayoutIdle.Stop();
    m_xContainer.reset();
    m_xBuilder.reset();
    m_xVclContentArea.disposeAndClear();
    disposeBuilder();
    Control::dispose();
}
diff --git a/vcl/inc/salinst.hxx b/vcl/inc/salinst.hxx
index d47fb63..6213436 100644
--- a/vcl/inc/salinst.hxx
+++ b/vcl/inc/salinst.hxx
@@ -164,7 +164,7 @@ public:
    virtual OpenGLContext*  CreateOpenGLContext() = 0;

    virtual weld::Builder* CreateBuilder(weld::Widget* pParent, const OUString& rUIRoot, const OUString& rUIFile);
    static  weld::Builder* CreateInterimBuilder(vcl::Window* pParent, const OUString& rUIRoot, const OUString& rUIFile);
    virtual weld::Builder* CreateInterimBuilder(vcl::Window* pParent, const OUString& rUIRoot, const OUString& rUIFile);
    virtual weld::MessageDialog* CreateMessageDialog(weld::Widget* pParent, VclMessageType eMessageType,
                                                     VclButtonsType eButtonType, const OUString& rPrimaryMessage);
    virtual weld::Window* GetFrameWeld(const css::uno::Reference<css::awt::XWindow>& rWindow);
diff --git a/vcl/inc/salobj.hxx b/vcl/inc/salobj.hxx
index 90ef3ae5..6e79e49 100644
--- a/vcl/inc/salobj.hxx
+++ b/vcl/inc/salobj.hxx
@@ -48,6 +48,7 @@ public:
    virtual void                    Show( bool bVisible ) = 0;
    virtual void                    Enable( bool /* nEnable */ ) {} // overridden by WinSalObject
    virtual void                    GrabFocus() {}
    virtual void                    Reparent(SalFrame* /*pFrame*/) {}

    virtual void                    SetForwardKey( bool /* bEnable */ ) {}

diff --git a/vcl/inc/unx/gtk/gtkframe.hxx b/vcl/inc/unx/gtk/gtkframe.hxx
index 0955a1d..033ee93 100644
--- a/vcl/inc/unx/gtk/gtkframe.hxx
+++ b/vcl/inc/unx/gtk/gtkframe.hxx
@@ -162,6 +162,8 @@ class GtkSalFrame final : public SalFrame
    };
    friend struct IMHandler;

    friend class GtkSalObjectWidgetClip;

    SalX11Screen                    m_nXScreen;
    GtkWidget*                      m_pWindow;
    GtkHeaderBar*                   m_pHeaderBar;
diff --git a/vcl/inc/unx/gtk/gtkinst.hxx b/vcl/inc/unx/gtk/gtkinst.hxx
index 1e0f86c..d1d624b 100644
--- a/vcl/inc/unx/gtk/gtkinst.hxx
+++ b/vcl/inc/unx/gtk/gtkinst.hxx
@@ -236,6 +236,7 @@ public:
    virtual css::uno::Reference< css::uno::XInterface > CreateDropTarget() override;
    virtual OpenGLContext* CreateOpenGLContext() override;
    virtual weld::Builder* CreateBuilder(weld::Widget* pParent, const OUString& rUIRoot, const OUString& rUIFile) override;
    virtual weld::Builder* CreateInterimBuilder(vcl::Window* pParent, const OUString& rUIRoot, const OUString& rUIFile) override;
    virtual weld::MessageDialog* CreateMessageDialog(weld::Widget* pParent, VclMessageType eMessageType, VclButtonsType eButtonType, const OUString &rPrimaryMessage) override;
    virtual weld::Window* GetFrameWeld(const css::uno::Reference<css::awt::XWindow>& rWindow) override;

diff --git a/vcl/inc/unx/gtk/gtkobject.hxx b/vcl/inc/unx/gtk/gtkobject.hxx
index 7ff9e49..d1a5226 100644
--- a/vcl/inc/unx/gtk/gtkobject.hxx
+++ b/vcl/inc/unx/gtk/gtkobject.hxx
@@ -25,37 +25,83 @@
#include <salobj.hxx>
#include <unx/gtk/gtkframe.hxx>

class GtkSalObject final : public SalObject
class GtkSalObjectBase : public SalObject
{
    SystemEnvData     m_aSystemData;
protected:
    SystemEnvData       m_aSystemData;
    GtkWidget*          m_pSocket;
    GtkSalFrame*        m_pParent;
    cairo_region_t*     m_pRegion;

    // signals
    static gboolean     signalButton( GtkWidget*, GdkEventButton*, gpointer );
    static gboolean     signalFocus( GtkWidget*, GdkEventFocus*, gpointer );
    static void         signalDestroy( GtkWidget*, gpointer );
public:
    GtkSalObject( GtkSalFrame* pParent, bool bShow );
    virtual ~GtkSalObject() override;
    void Init();

    // override all pure virtual methods
    virtual void                    ResetClipRegion() override;
public:
    GtkSalObjectBase(GtkSalFrame* pParent);
    virtual ~GtkSalObjectBase() override;

    virtual void                    BeginSetClipRegion( sal_uInt32 nRects ) override;
    virtual void                    UnionClipRegion( long nX, long nY, long nWidth, long nHeight ) override;
    virtual void                    EndSetClipRegion() override;

    virtual void                    SetPosSize( long nX, long nY, long nWidth, long nHeight ) override;
    virtual void                    Show( bool bVisible ) override;

    virtual void                    SetForwardKey( bool bEnable ) override;

    virtual const SystemEnvData*    GetSystemData() const override;

    virtual Size                    GetOptimalSize() const override;

private:
    // signals
    static gboolean     signalButton( GtkWidget*, GdkEventButton*, gpointer );
    static gboolean     signalFocus( GtkWidget*, GdkEventFocus*, gpointer );
};

// this attempts to clip the hosted native window using gdk_window_shape_combine_region
class GtkSalObject final : public GtkSalObjectBase
{
    // signals
    static void         signalDestroy( GtkWidget*, gpointer );

public:
    GtkSalObject(GtkSalFrame* pParent, bool bShow);
    virtual ~GtkSalObject() override;

    // override all pure virtual methods
    virtual void                    ResetClipRegion() override;
    virtual void                    EndSetClipRegion() override;

    virtual void                    SetPosSize( long nX, long nY, long nWidth, long nHeight ) override;
    virtual void                    Show( bool bVisible ) override;
    virtual void                    Reparent(SalFrame* pFrame) override;
};

// this attempts to clip the hosted native GtkWidget by using a GtkScrolledWindow as a viewport
// only a rectangular area is going to work
class GtkSalObjectWidgetClip final : public GtkSalObjectBase
{
    tools::Rectangle m_aRect;
    tools::Rectangle m_aClipRect;
    GtkWidget* m_pScrolledWindow;

    // signals
    static gboolean     signalScroll( GtkWidget*, GdkEvent*, gpointer );
    static void         signalDestroy( GtkWidget*, gpointer );

    bool signal_scroll(GtkWidget* pScrolledWindow, GdkEvent* pEvent);

    void ApplyClipRegion();
public:
    GtkSalObjectWidgetClip(GtkSalFrame* pParent, bool bShow);
    virtual ~GtkSalObjectWidgetClip() override;

    // override all pure virtual methods
    virtual void                    ResetClipRegion() override;
    virtual void                    EndSetClipRegion() override;

    virtual void                    SetPosSize( long nX, long nY, long nWidth, long nHeight ) override;
    virtual void                    Show( bool bVisible ) override;
    virtual void                    Reparent(SalFrame* pFrame) override;
};


#endif // INCLUDED_VCL_INC_UNX_GTK_GTKOBJECT_HXX

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx
index 1d49f77..7e56847 100644
--- a/vcl/source/app/salvtables.cxx
+++ b/vcl/source/app/salvtables.cxx
@@ -6611,13 +6611,6 @@ weld::Builder* SalInstance::CreateInterimBuilder(vcl::Window* pParent, const OUS
    return new SalInstanceBuilder(pParent, rUIRoot, rUIFile);
}

weld::Builder* Application::CreateInterimBuilder(weld::Widget* pParent, const OUString &rUIFile)
{
    SalInstanceWidget* pParentInstance = dynamic_cast<SalInstanceWidget*>(pParent);
    vcl::Window* pParentWidget = pParentInstance ? pParentInstance->getWidget() : nullptr;
    return Application::CreateInterimBuilder(pParentWidget, rUIFile);
}

void SalInstanceWindow::help()
{
    //show help for widget with keyboard focus
diff --git a/vcl/source/window/builder.cxx b/vcl/source/window/builder.cxx
index b47ad02..91e30d1 100644
--- a/vcl/source/window/builder.cxx
+++ b/vcl/source/window/builder.cxx
@@ -154,7 +154,7 @@ weld::Builder* Application::CreateBuilder(weld::Widget* pParent, const OUString 

weld::Builder* Application::CreateInterimBuilder(vcl::Window* pParent, const OUString &rUIFile)
{
    return SalInstance::CreateInterimBuilder(pParent, VclBuilderContainer::getUIRootDir(), rUIFile);
    return ImplGetSVData()->mpDefInst->CreateInterimBuilder(pParent, VclBuilderContainer::getUIRootDir(), rUIFile);
}

weld::MessageDialog* Application::CreateMessageDialog(weld::Widget* pParent, VclMessageType eMessageType,
diff --git a/vcl/source/window/stacking.cxx b/vcl/source/window/stacking.cxx
index 718ce76..08b6cba 100644
--- a/vcl/source/window/stacking.cxx
+++ b/vcl/source/window/stacking.cxx
@@ -23,6 +23,7 @@
#include <sal/log.hxx>

#include <salframe.hxx>
#include <salobj.hxx>
#include <svdata.hxx>
#include <window.h>
#include <brdwin.hxx>
@@ -63,8 +64,13 @@ void Window::ImplInsertWindow( vcl::Window* pParent )
    {
        // search frame window and set window frame data
        vcl::Window* pFrameParent = pParent->mpWindowImpl->mpFrameWindow;
        mpWindowImpl->mpFrameData     = pFrameParent->mpWindowImpl->mpFrameData;
        mpWindowImpl->mpFrame         = pFrameParent->mpWindowImpl->mpFrame;
        mpWindowImpl->mpFrameData = pFrameParent->mpWindowImpl->mpFrameData;
        if (mpWindowImpl->mpFrame != pFrameParent->mpWindowImpl->mpFrame)
        {
            mpWindowImpl->mpFrame = pFrameParent->mpWindowImpl->mpFrame;
            if (mpWindowImpl->mpSysObj)
                mpWindowImpl->mpSysObj->Reparent(mpWindowImpl->mpFrame);
        }
        mpWindowImpl->mpFrameWindow   = pFrameParent;
        mpWindowImpl->mbFrame         = false;

@@ -751,7 +757,12 @@ void Window::ImplUpdateWindowPtr( vcl::Window* pWindow )
    }

    mpWindowImpl->mpFrameData     = pWindow->mpWindowImpl->mpFrameData;
    mpWindowImpl->mpFrame         = pWindow->mpWindowImpl->mpFrame;
    if (mpWindowImpl->mpFrame != pWindow->mpWindowImpl->mpFrame)
    {
        mpWindowImpl->mpFrame = pWindow->mpWindowImpl->mpFrame;
        if (mpWindowImpl->mpSysObj)
            mpWindowImpl->mpSysObj->Reparent(mpWindowImpl->mpFrame);
    }
    mpWindowImpl->mpFrameWindow   = pWindow->mpWindowImpl->mpFrameWindow;
    if ( pWindow->ImplIsOverlapWindow() )
        mpWindowImpl->mpOverlapWindow = pWindow;
diff --git a/vcl/unx/gtk3/gtk3gtkinst.cxx b/vcl/unx/gtk3/gtk3gtkinst.cxx
index d4842bea..0df4459 100644
--- a/vcl/unx/gtk3/gtk3gtkinst.cxx
+++ b/vcl/unx/gtk3/gtk3gtkinst.cxx
@@ -241,11 +241,13 @@ SalFrame* GtkInstance::CreateChildFrame( SystemParentData* pParentData, SalFrame
    return new GtkSalFrame( pParentData );
}

SalObject* GtkInstance::CreateObject( SalFrame* pParent, SystemWindowData* /*pWindowData*/, bool bShow )
SalObject* GtkInstance::CreateObject( SalFrame* pParent, SystemWindowData* pWindowData, bool bShow )
{
    EnsureInit();
    //FIXME: Missing CreateObject functionality ...
    return new GtkSalObject( static_cast<GtkSalFrame*>(pParent), bShow );
    if (pWindowData && pWindowData->bClipUsingNativeWidget)
        return new GtkSalObjectWidgetClip(static_cast<GtkSalFrame*>(pParent), bShow);
    return new GtkSalObject(static_cast<GtkSalFrame*>(pParent), bShow);
}

extern "C"
@@ -13277,6 +13279,27 @@ weld::Builder* GtkInstance::CreateBuilder(weld::Widget* pParent, const OUString&
    return new GtkInstanceBuilder(pBuilderParent, rUIRoot, rUIFile);
}

weld::Builder* GtkInstance::CreateInterimBuilder(vcl::Window* pParent, const OUString& rUIRoot, const OUString& rUIFile)
{
    // Create a foreign window which we know is a GtkGrid and make the native widgets a child of that, so we can
    // support GtkWidgets within a vcl::Window
    SystemWindowData winData = {};
    winData.bClipUsingNativeWidget = true;
    auto xEmbedWindow = VclPtr<SystemChildWindow>::Create(pParent, 0, &winData, true);
    xEmbedWindow->Show();
    xEmbedWindow->set_expand(true);

    const SystemEnvData* pEnvData = xEmbedWindow->GetSystemData();
    if (!pEnvData)
        return nullptr;

    GtkWidget *pWindow = static_cast<GtkWidget*>(pEnvData->pWidget);
    gtk_widget_show_all(pWindow);

    // build the widget tree as a child of the GtkEventBox GtkGrid parent
    return new GtkInstanceBuilder(pWindow, rUIRoot, rUIFile);
}

weld::MessageDialog* GtkInstance::CreateMessageDialog(weld::Widget* pParent, VclMessageType eMessageType, VclButtonsType eButtonsType, const OUString &rPrimaryMessage)
{
    GtkInstanceWidget* pParentInstance = dynamic_cast<GtkInstanceWidget*>(pParent);
diff --git a/vcl/unx/gtk3/gtk3gtkobject.cxx b/vcl/unx/gtk3/gtk3gtkobject.cxx
index 3079fdb..93db53a 100644
--- a/vcl/unx/gtk3/gtk3gtkobject.cxx
+++ b/vcl/unx/gtk3/gtk3gtkobject.cxx
@@ -28,12 +28,19 @@
#include <unx/gtk/gtkframe.hxx>
#include <unx/gtk/gtkdata.hxx>

GtkSalObject::GtkSalObject( GtkSalFrame* pParent, bool bShow )
        : m_pSocket(nullptr)
        , m_pParent(pParent)
        , m_pRegion(nullptr)
GtkSalObjectBase::GtkSalObjectBase(GtkSalFrame* pParent)
    : m_pSocket(nullptr)
    , m_pParent(pParent)
    , m_pRegion(nullptr)
{
    if( !pParent )
    if (!m_pParent)
        return;
}

GtkSalObject::GtkSalObject(GtkSalFrame* pParent, bool bShow)
    : GtkSalObjectBase(pParent)
{
    if (!m_pParent)
        return;

    // our plug window
@@ -43,17 +50,28 @@ GtkSalObject::GtkSalObject( GtkSalFrame* pParent, bool bShow )
    gtk_fixed_put( pParent->getFixedContainer(),
                   m_pSocket,
                   0, 0 );

    Init();

    g_signal_connect( G_OBJECT(m_pSocket), "destroy", G_CALLBACK(signalDestroy), this );

    // #i59255# necessary due to sync effects with java child windows
    pParent->Flush();
}

void GtkSalObjectBase::Init()
{
    // realize so we can get a window id
    gtk_widget_realize( m_pSocket );

    // system data
    m_aSystemData.aWindow       = pParent->GetNativeWindowHandle(m_pSocket);
    m_aSystemData.aWindow       = m_pParent->GetNativeWindowHandle(m_pSocket);
    m_aSystemData.aShellWindow  = reinterpret_cast<sal_IntPtr>(this);
    m_aSystemData.pSalFrame     = nullptr;
    m_aSystemData.pWidget       = m_pSocket;
    m_aSystemData.nScreen       = pParent->getXScreenNumber().getXScreen();
    m_aSystemData.nScreen       = m_pParent->getXScreenNumber().getXScreen();
    m_aSystemData.toolkit       = SystemEnvData::Toolkit::Gtk3;
    GdkScreen* pScreen = gtk_window_get_screen(GTK_WINDOW(pParent->getWindow()));
    GdkScreen* pScreen = gtk_window_get_screen(GTK_WINDOW(m_pParent->getWindow()));
    GdkVisual* pVisual = gdk_screen_get_system_visual(pScreen);

#if defined(GDK_WINDOWING_X11)
@@ -77,19 +95,18 @@ GtkSalObject::GtkSalObject( GtkSalFrame* pParent, bool bShow )
    g_signal_connect( G_OBJECT(m_pSocket), "button-release-event", G_CALLBACK(signalButton), this );
    g_signal_connect( G_OBJECT(m_pSocket), "focus-in-event", G_CALLBACK(signalFocus), this );
    g_signal_connect( G_OBJECT(m_pSocket), "focus-out-event", G_CALLBACK(signalFocus), this );
    g_signal_connect( G_OBJECT(m_pSocket), "destroy", G_CALLBACK(signalDestroy), this );

    // #i59255# necessary due to sync effects with java child windows
    pParent->Flush();

}

GtkSalObject::~GtkSalObject()
GtkSalObjectBase::~GtkSalObjectBase()
{
    if( m_pRegion )
    {
        cairo_region_destroy( m_pRegion );
    }
}

GtkSalObject::~GtkSalObject()
{
    if( m_pSocket )
    {
        // remove socket from parent frame's fixed container
@@ -110,14 +127,14 @@ void GtkSalObject::ResetClipRegion()
        gdk_window_shape_combine_region( gtk_widget_get_window(m_pSocket), nullptr, 0, 0 );
}

void GtkSalObject::BeginSetClipRegion( sal_uInt32 )
void GtkSalObjectBase::BeginSetClipRegion( sal_uInt32 )
{
    if( m_pRegion )
        cairo_region_destroy( m_pRegion );
    if (m_pRegion)
        cairo_region_destroy(m_pRegion);
    m_pRegion = cairo_region_create();
}

void GtkSalObject::UnionClipRegion( long nX, long nY, long nWidth, long nHeight )
void GtkSalObjectBase::UnionClipRegion( long nX, long nY, long nWidth, long nHeight )
{
    GdkRectangle aRect;
    aRect.x         = nX;
@@ -134,9 +151,9 @@ void GtkSalObject::EndSetClipRegion()
        gdk_window_shape_combine_region( gtk_widget_get_window(m_pSocket), m_pRegion, 0, 0 );
}

void GtkSalObject::SetPosSize( long nX, long nY, long nWidth, long nHeight )
void GtkSalObject::SetPosSize(long nX, long nY, long nWidth, long nHeight)
{
    if( m_pSocket )
    if (m_pSocket)
    {
        GtkFixed* pContainer = GTK_FIXED(gtk_widget_get_parent(m_pSocket));
        gtk_fixed_move( pContainer, m_pSocket, nX, nY );
@@ -145,18 +162,43 @@ void GtkSalObject::SetPosSize( long nX, long nY, long nWidth, long nHeight )
    }
}

void GtkSalObject::Reparent(SalFrame* pFrame)
{
    GtkSalFrame* pNewParent = static_cast<GtkSalFrame*>(pFrame);
    if (m_pSocket)
    {
        GtkFixed* pContainer = GTK_FIXED(gtk_widget_get_parent(m_pSocket));

        gint nX(0), nY(0);
        gtk_container_child_get(GTK_CONTAINER(pContainer), m_pSocket,
                "x", &nX,
                "y", &nY,
                nullptr);

        g_object_ref(m_pSocket);
        gtk_container_remove(GTK_CONTAINER(pContainer), m_pSocket);

        gtk_fixed_put(pNewParent->getFixedContainer(),
                      m_pSocket,
                      nX, nY);

        g_object_unref(m_pSocket);
    }
    m_pParent = pNewParent;
}

void GtkSalObject::Show( bool bVisible )
{
    if( m_pSocket )
    {
        if( bVisible )
            gtk_widget_show( m_pSocket );
            gtk_widget_show(m_pSocket);
        else
            gtk_widget_hide( m_pSocket );
            gtk_widget_hide(m_pSocket);
    }
}

Size GtkSalObject::GetOptimalSize() const
Size GtkSalObjectBase::GetOptimalSize() const
{
    if (m_pSocket)
    {
@@ -172,14 +214,14 @@ Size GtkSalObject::GetOptimalSize() const
    return Size();
}

const SystemEnvData* GtkSalObject::GetSystemData() const
const SystemEnvData* GtkSalObjectBase::GetSystemData() const
{
    return &m_aSystemData;
}

gboolean GtkSalObject::signalButton( GtkWidget*, GdkEventButton* pEvent, gpointer object )
gboolean GtkSalObjectBase::signalButton( GtkWidget*, GdkEventButton* pEvent, gpointer object )
{
    GtkSalObject* pThis = static_cast<GtkSalObject*>(object);
    GtkSalObjectBase* pThis = static_cast<GtkSalObject*>(object);

    if( pEvent->type == GDK_BUTTON_PRESS )
    {
@@ -189,9 +231,9 @@ gboolean GtkSalObject::signalButton( GtkWidget*, GdkEventButton* pEvent, gpointe
    return FALSE;
}

gboolean GtkSalObject::signalFocus( GtkWidget*, GdkEventFocus* pEvent, gpointer object )
gboolean GtkSalObjectBase::signalFocus( GtkWidget*, GdkEventFocus* pEvent, gpointer object )
{
    GtkSalObject* pThis = static_cast<GtkSalObject*>(object);
    GtkSalObjectBase* pThis = static_cast<GtkSalObject*>(object);

    pThis->CallCallback( pEvent->in ? SalObjEvent::GetFocus : SalObjEvent::LoseFocus );

@@ -207,7 +249,7 @@ void GtkSalObject::signalDestroy( GtkWidget* pObj, gpointer object )
    }
}

void GtkSalObject::SetForwardKey( bool bEnable )
void GtkSalObjectBase::SetForwardKey( bool bEnable )
{
    if( bEnable )
        gtk_widget_add_events( GTK_WIDGET( m_pSocket ), GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE );
@@ -215,4 +257,186 @@ void GtkSalObject::SetForwardKey( bool bEnable )
        gtk_widget_set_events( GTK_WIDGET( m_pSocket ), ~(GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE) & gtk_widget_get_events( GTK_WIDGET( m_pSocket ) ) );
}

GtkSalObjectWidgetClip::GtkSalObjectWidgetClip(GtkSalFrame* pParent, bool bShow)
    : GtkSalObjectBase(pParent)
    , m_pScrolledWindow(nullptr)
{
    if( !pParent )
        return;

    m_pScrolledWindow = gtk_scrolled_window_new(nullptr, nullptr);
    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(m_pScrolledWindow),
                                   GTK_POLICY_EXTERNAL, GTK_POLICY_EXTERNAL);
    g_signal_connect(m_pScrolledWindow, "scroll-event", G_CALLBACK(signalScroll), this);

    // insert into container
    gtk_fixed_put( pParent->getFixedContainer(),
                   m_pScrolledWindow,
                   0, 0 );

    // deliberately without adjustments to avoid gtk's auto adjustment on changing focus
    GtkWidget* pViewPort = gtk_viewport_new(nullptr, nullptr);

    // force in a fake background of a suitable color
    GtkStyleContext *pWidgetContext = gtk_widget_get_style_context(pViewPort);
    GtkCssProvider* pBgCssProvider = gtk_css_provider_new();
    OUString sColor = Application::GetSettings().GetStyleSettings().GetDialogColor().AsRGBHexString();
    OUString aBuffer = "* { background-color: #" + sColor + "; }";
    OString aResult = OUStringToOString(aBuffer, RTL_TEXTENCODING_UTF8);
    gtk_css_provider_load_from_data(pBgCssProvider, aResult.getStr(), aResult.getLength(), nullptr);
    gtk_style_context_add_provider(pWidgetContext, GTK_STYLE_PROVIDER(pBgCssProvider),
                                   GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);

    gtk_container_add(GTK_CONTAINER(m_pScrolledWindow), pViewPort);
    gtk_widget_show(pViewPort);

    // our plug window
    m_pSocket = gtk_grid_new();
    gtk_container_add(GTK_CONTAINER(pViewPort), m_pSocket);
    gtk_widget_show(m_pSocket);

    Show(bShow);

    Init();

    g_signal_connect( G_OBJECT(m_pSocket), "destroy", G_CALLBACK(signalDestroy), this );
}

GtkSalObjectWidgetClip::~GtkSalObjectWidgetClip()
{
    if( m_pSocket )
    {
        // remove socket from parent frame's fixed container
        gtk_container_remove( GTK_CONTAINER(gtk_widget_get_parent(m_pScrolledWindow)),
                              m_pScrolledWindow );
        // get rid of the socket
        // actually the gtk_container_remove should let the ref count
        // of the socket sink to 0 and destroy it (see signalDestroy)
        // this is just a sanity check
        if( m_pScrolledWindow )
            gtk_widget_destroy( m_pScrolledWindow );
    }
}

void GtkSalObjectWidgetClip::ResetClipRegion()
{
    m_aClipRect = tools::Rectangle();
    ApplyClipRegion();
}

void GtkSalObjectWidgetClip::EndSetClipRegion()
{
    int nRects = cairo_region_num_rectangles(m_pRegion);
    assert(nRects == 0 || nRects == 1);
    if (nRects == 0)
        m_aClipRect = tools::Rectangle();
    else
    {
        cairo_rectangle_int_t rectangle;
        cairo_region_get_rectangle(m_pRegion, 0, &rectangle);
        m_aClipRect = tools::Rectangle(Point(rectangle.x, rectangle.y), Size(rectangle.width, rectangle.height));
    }
    ApplyClipRegion();
}

void GtkSalObjectWidgetClip::ApplyClipRegion()
{
    if( m_pSocket )
    {
        GtkFixed* pContainer = GTK_FIXED(gtk_widget_get_parent(m_pScrolledWindow));
        gtk_fixed_move(pContainer, m_pScrolledWindow, m_aRect.Left() + m_aClipRect.Left(), m_aRect.Top() + m_aClipRect.Top());
        if (m_aClipRect.IsEmpty())
            gtk_widget_set_size_request(m_pScrolledWindow, m_aRect.GetWidth(), m_aRect.GetHeight());
        else
            gtk_widget_set_size_request(m_pScrolledWindow, m_aClipRect.GetWidth(), m_aClipRect.GetHeight());
        gtk_adjustment_set_value(gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(m_pScrolledWindow)), m_aClipRect.Left());
        gtk_adjustment_set_value(gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(m_pScrolledWindow)), m_aClipRect.Top());
    }
}

void GtkSalObjectWidgetClip::SetPosSize(long nX, long nY, long nWidth, long nHeight)
{
    m_aRect = tools::Rectangle(Point(nX, nY), Size(nWidth, nHeight));
    if (m_pSocket)
    {
        GtkFixed* pContainer = GTK_FIXED(gtk_widget_get_parent(m_pScrolledWindow));
        gtk_widget_set_size_request(m_pSocket, nWidth, nHeight);
        ApplyClipRegion();
        m_pParent->nopaint_container_resize_children(GTK_CONTAINER(pContainer));
    }
}

void GtkSalObjectWidgetClip::Reparent(SalFrame* pFrame)
{
    GtkSalFrame* pNewParent = static_cast<GtkSalFrame*>(pFrame);
    if (m_pSocket)
    {
        GtkFixed* pContainer = GTK_FIXED(gtk_widget_get_parent(m_pScrolledWindow));

        gint nX(0), nY(0);
        gtk_container_child_get(GTK_CONTAINER(pContainer), m_pScrolledWindow,
                "x", &nX,
                "y", &nY,
                nullptr);

        g_object_ref(m_pScrolledWindow);
        gtk_container_remove(GTK_CONTAINER(pContainer), m_pScrolledWindow);

        gtk_fixed_put(pNewParent->getFixedContainer(),
                      m_pScrolledWindow,
                      nX, nY);

        g_object_unref(m_pScrolledWindow);
    }
    m_pParent = pNewParent;
}

void GtkSalObjectWidgetClip::Show( bool bVisible )
{
    if( m_pSocket )
    {
        if( bVisible )
            gtk_widget_show(m_pScrolledWindow);
        else
            gtk_widget_hide(m_pScrolledWindow);
    }
}

void GtkSalObjectWidgetClip::signalDestroy( GtkWidget* pObj, gpointer object )
{
    GtkSalObjectWidgetClip* pThis = static_cast<GtkSalObjectWidgetClip*>(object);
    if( pObj == pThis->m_pSocket )
    {
        pThis->m_pSocket = nullptr;
        pThis->m_pScrolledWindow = nullptr;
    }
}

gboolean GtkSalObjectWidgetClip::signalScroll(GtkWidget* pScrolledWindow, GdkEvent* pEvent, gpointer object)
{
    GtkSalObjectWidgetClip* pThis = static_cast<GtkSalObjectWidgetClip*>(object);
    return pThis->signal_scroll(pScrolledWindow, pEvent);
}

// forward the wheel scroll events onto the main window instead
bool GtkSalObjectWidgetClip::signal_scroll(GtkWidget*, GdkEvent* pEvent)
{
    GtkWidget* pEventWidget = gtk_get_event_widget(pEvent);

    GtkWidget* pMouseEventWidget = m_pParent->getMouseEventWidget();

    gint dest_x, dest_y;
    gtk_widget_translate_coordinates(pEventWidget,
                                     pMouseEventWidget,
                                     pEvent->scroll.x,
                                     pEvent->scroll.y,
                                     &dest_x,
                                     &dest_y);
    pEvent->scroll.x = dest_x;
    pEvent->scroll.y = dest_y;

    GtkSalFrame::signalScroll(pMouseEventWidget, pEvent, m_pParent);
    return true;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */