provide a route to weld accessibility

Change-Id: I92e88a4356cb8e4bd958fd86d33c52f5be82be54
Reviewed-on: https://gerrit.libreoffice.org/51787
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Tested-by: Caolán McNamara <caolanm@redhat.com>
diff --git a/include/vcl/weld.hxx b/include/vcl/weld.hxx
index d623427..4a8340e 100644
--- a/include/vcl/weld.hxx
+++ b/include/vcl/weld.hxx
@@ -17,6 +17,8 @@
#include <vcl/field.hxx>
#include <vcl/virdev.hxx>

typedef css::uno::Reference<css::accessibility::XAccessible> a11yref;

namespace weld
{
class Container;
@@ -595,7 +597,9 @@ public:
    virtual TextView* weld_text_view(const OString& id, bool bTakeOwnership = false) = 0;
    virtual Expander* weld_expander(const OString& id, bool bTakeOwnership = false) = 0;
    virtual Entry* weld_entry(const OString& id, bool bTakeOwnership = false) = 0;
    virtual DrawingArea* weld_drawing_area(const OString& id, bool bTakeOwnership = false) = 0;
    virtual DrawingArea* weld_drawing_area(const OString& id, const a11yref& rA11yImpl = nullptr,
                                           bool bTakeOwnership = false)
        = 0;
    virtual ~Builder() {}
};

diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx
index 9cfe42e..9e0b4eb 100644
--- a/vcl/source/app/salvtables.cxx
+++ b/vcl/source/app/salvtables.cxx
@@ -1224,10 +1224,11 @@ private:
    DECL_LINK(MouseReleaseHdl, const Point&, void);

public:
    SalInstanceDrawingArea(VclDrawingArea* pDrawingArea, bool bTakeOwnership)
    SalInstanceDrawingArea(VclDrawingArea* pDrawingArea, const a11yref& rAlly, bool bTakeOwnership)
        : SalInstanceWidget(pDrawingArea, bTakeOwnership)
        , m_xDrawingArea(pDrawingArea)
    {
        m_xDrawingArea->SetAccessible(rAlly);
        m_xDrawingArea->SetPaintHdl(LINK(this, SalInstanceDrawingArea, PaintHdl));
        m_xDrawingArea->SetResizeHdl(LINK(this, SalInstanceDrawingArea, ResizeHdl));
        m_xDrawingArea->SetMousePressHdl(LINK(this, SalInstanceDrawingArea, MousePressHdl));
@@ -1601,10 +1602,10 @@ public:
        return pExpander ? new SalInstanceExpander(pExpander, bTakeOwnership) : nullptr;
    }

    virtual weld::DrawingArea* weld_drawing_area(const OString &id, bool bTakeOwnership) override
    virtual weld::DrawingArea* weld_drawing_area(const OString &id, const a11yref& rA11yImpl, bool bTakeOwnership) override
    {
        VclDrawingArea* pDrawingArea = m_xBuilder->get<VclDrawingArea>(id);
        return pDrawingArea ? new SalInstanceDrawingArea(pDrawingArea, bTakeOwnership) : nullptr;
        return pDrawingArea ? new SalInstanceDrawingArea(pDrawingArea, rA11yImpl, bTakeOwnership) : nullptr;
    }

    virtual ~SalInstanceBuilder() override
diff --git a/vcl/unx/gtk3/gtk3gtkinst.cxx b/vcl/unx/gtk3/gtk3gtkinst.cxx
index 947d1cc..c5ba7be 100644
--- a/vcl/unx/gtk3/gtk3gtkinst.cxx
+++ b/vcl/unx/gtk3/gtk3gtkinst.cxx
@@ -8,7 +8,7 @@
 */

#include "../gtk/gtkinst.cxx"

#include "../gtk/a11y/atkwrapper.hxx"
#include <com/sun/star/lang/IllegalArgumentException.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/lang/XServiceInfo.hpp>
@@ -2615,6 +2615,8 @@ class GtkInstanceDrawingArea : public GtkInstanceWidget, public virtual weld::Dr
{
private:
    GtkDrawingArea* m_pDrawingArea;
    a11yref m_xAccessible;
    AtkObject *m_pAccessible;
    ScopedVclPtrInstance<VirtualDevice> m_xDevice;
    std::vector<unsigned char> m_aBuffer;
    cairo_surface_t* m_pSurface;
@@ -2699,9 +2701,11 @@ private:
    }

public:
    GtkInstanceDrawingArea(GtkDrawingArea* pDrawingArea, bool bTakeOwnership)
    GtkInstanceDrawingArea(GtkDrawingArea* pDrawingArea, const a11yref& rA11y, bool bTakeOwnership)
        : GtkInstanceWidget(GTK_WIDGET(pDrawingArea), bTakeOwnership)
        , m_pDrawingArea(pDrawingArea)
        , m_xAccessible(rA11y)
        , m_pAccessible(nullptr)
        , m_xDevice(nullptr, Size(1, 1), DeviceFormat::DEFAULT)
        , m_pSurface(nullptr)
        , m_nDrawSignalId(g_signal_connect(m_pDrawingArea, "draw", G_CALLBACK(signalDraw), this))
@@ -2710,6 +2714,14 @@ public:
        , m_nMotionSignalId(g_signal_connect(m_pDrawingArea, "motion-notify-event", G_CALLBACK(signalMotion), this))
        , m_nButtonReleaseSignalId(g_signal_connect(m_pDrawingArea, "button-release-event", G_CALLBACK(signalButton), this))
    {
        g_object_set_data(G_OBJECT(m_pDrawingArea), "g-lo-GtkInstanceDrawingArea", this);
    }

    AtkObject* GetAtkObject()
    {
        if (!m_pAccessible && m_xAccessible.is())
            m_pAccessible = atk_object_wrapper_new(m_xAccessible);
        return m_pAccessible;
    }

    virtual void queue_draw() override
@@ -2724,6 +2736,9 @@ public:

    virtual ~GtkInstanceDrawingArea() override
    {
        g_object_steal_data(G_OBJECT(m_pDrawingArea), "g-lo-GtkInstanceDrawingArea");
        if (m_pAccessible)
            g_object_unref(m_pAccessible);
        if (m_pSurface)
            cairo_surface_destroy(m_pSurface);
        g_signal_handler_disconnect(m_pDrawingArea, m_nButtonPressSignalId);
@@ -3107,6 +3122,37 @@ namespace
    }
}

namespace
{

AtkObject* (*default_drawing_area_get_accessible)(GtkWidget *widget);

AtkObject* drawing_area_get_accessibity(GtkWidget *pWidget)
{
    void* pData = g_object_get_data(G_OBJECT(pWidget), "g-lo-GtkInstanceDrawingArea");
    GtkInstanceDrawingArea* pDrawingArea = static_cast<GtkInstanceDrawingArea*>(pData);
    AtkObject *pAtkObj = pDrawingArea ? pDrawingArea->GetAtkObject() : nullptr;
    if (pAtkObj)
        return pAtkObj;
    return default_drawing_area_get_accessible(pWidget);
}

void ensure_intercept_drawing_area_accessibility()
{
    static bool bDone;
    if (!bDone)
    {
        gpointer pClass = g_type_class_ref(GTK_TYPE_DRAWING_AREA);
        GtkWidgetClass* pWidgetClass = GTK_WIDGET_CLASS(pClass);
        default_drawing_area_get_accessible = pWidgetClass->get_accessible;
        pWidgetClass->get_accessible = drawing_area_get_accessibity;
        g_type_class_unref(pClass);
        bDone = true;
    }
}

}

class GtkInstanceBuilder : public weld::Builder
{
private:
@@ -3120,6 +3166,8 @@ public:
        , m_sHelpRoot(rUIFile)
        , m_pParentWidget(pParent)
    {
        ensure_intercept_drawing_area_accessibility();

        OUString aUri(rUIRoot + rUIFile);
        OUString aPath;
        osl::FileBase::getSystemPathFromFileURL(aUri, aPath);
@@ -3301,13 +3349,13 @@ public:
        return new GtkInstanceExpander(pExpander, bTakeOwnership);
    }

    virtual weld::DrawingArea* weld_drawing_area(const OString &id, bool bTakeOwnership) override
    virtual weld::DrawingArea* weld_drawing_area(const OString &id, const a11yref& rA11y, bool bTakeOwnership) override
    {
        GtkDrawingArea* pDrawingArea = GTK_DRAWING_AREA(gtk_builder_get_object(m_pBuilder, id.getStr()));
        if (!pDrawingArea)
            return nullptr;
        auto_add_parentless_widgets_to_container(GTK_WIDGET(pDrawingArea));
        return new GtkInstanceDrawingArea(pDrawingArea, bTakeOwnership);
        return new GtkInstanceDrawingArea(pDrawingArea, rA11y, bTakeOwnership);
    }
};