accessibility/source/standard/vclxaccessibletoolboxitem.cxx |    6 ++
 include/vcl/builder.hxx                                     |   12 +++--
 include/vcl/toolbox.hxx                                     |    4 +
 vcl/inc/toolbox.h                                           |    1 
 vcl/source/window/builder.cxx                               |   25 ++++++++----
 vcl/source/window/toolbox2.cxx                              |   17 ++++++++
 6 files changed, 53 insertions(+), 12 deletions(-)

New commits:
commit ad1167b92b8b8fdabf6b21e945682c0bafc80946
Author:     Michael Weghorn <m.wegh...@posteo.de>
AuthorDate: Tue Feb 27 13:12:43 2024 +0100
Commit:     Michael Weghorn <m.wegh...@posteo.de>
CommitDate: Tue Feb 27 19:34:55 2024 +0100

    tdf#159910 a11y VclBuilder: Apply tool item's a11y name to itself
    
    For the VCL `ToolBox` implementation of a toolbar, the items
    are not represented by own widgets (`vcl::Window`s), but handled
    by the `ToolBox`.
    
    As a consequence, the `vcl::Window` passed to
    `VclBuilder::applyAtkProperties` cannot be the tool item
    itself (e.g. a `GtkToolButton` in the .ui file), but is the
    `ToolBox`, i.e. the (VCL builder implementation of the
    `GtkToolbar` parent widget in the .ui file).
    
    So far, the ATK properties set for the tool item were
    just applied to the parent instead.
    
    For example, with the upcoming
    
        Change-Id: I852503e849651bb7be4daa419ec2379568623f0f
        Author: Michael Weghorn <m.wegh...@posteo.de>
        Date:   Tue Feb 27 11:51:55 2024 +0100
    
            tdf#159910 sw a11y: Set a11y names for Navigator items
    
    , this would result in the toolbars getting the name of their
    last item (one of the toolbars in the Navigator would
    get the a11y name "Show Up to Outline Level") and the
    toolbar items would only have an a11y name set because
    they still fall back to the tooltip text for the a11y name.
    
    Adjust that to set the accessible name for the
    actual toolbar item when a toolbar item is
    processed. (Add a bool param to indicate that).
    
    See also `VclBuilder::applyPackingProperty` which
    already had a similar way to determine and handle that
    case.
    
    With this in place, the accessible name set in the .ui
    file is now applied to the toolbar item as expected.
    
    (The accessible description could be handled similarly,
    but I'm a bit more hesitant to add that right away because
    the accessible description is currently also used for the
    extended tooltip text and the NVDA screen reader on Windows
    announces the description in addition to the name by default.)
    
    Change-Id: I45b87839dda90083ceba1c43fdb4d4ec460fce3d
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/164034
    Tested-by: Jenkins
    Reviewed-by: Michael Weghorn <m.wegh...@posteo.de>

diff --git a/include/vcl/builder.hxx b/include/vcl/builder.hxx
index 37fbfbe97e16..59202ba34062 100644
--- a/include/vcl/builder.hxx
+++ b/include/vcl/builder.hxx
@@ -353,9 +353,12 @@ private:
     void        extractMnemonicWidget(const OUString &id, stringmap &rMap);
 
     // either pParent or pAtkProps must be set, pParent for a child of a 
widget, pAtkProps for
-    // collecting the atk info for a GtkMenuItem
-    void        handleChild(vcl::Window *pParent, stringmap *pAtkProps, 
xmlreader::XmlReader &reader);
-    VclPtr<vcl::Window> handleObject(vcl::Window *pParent, stringmap 
*pAtkProps, xmlreader::XmlReader &reader);
+    // collecting the atk info for a GtkMenuItem,
+    // if bToolbarItem=true, pParent is the ToolBox that the item belongs to, 
since there's no widget for the item itself
+    void        handleChild(vcl::Window *pParent, stringmap *pAtkProps, 
xmlreader::XmlReader &reader, bool bToolbarItem = false);
+    // if bToolbarItem=true, pParent is the ToolBox that the item belongs to, 
since there's no widget for the item itself
+    VclPtr<vcl::Window> handleObject(vcl::Window *pParent, stringmap 
*pAtkProps, xmlreader::XmlReader &reader, bool bToolbarItem);
+
     void        handlePacking(vcl::Window *pCurrent, vcl::Window *pParent, 
xmlreader::XmlReader &reader);
     static std::vector<vcl::EnumContext::Context> 
handleStyle(xmlreader::XmlReader &reader, int &nPriority);
     static OUString getStyleClass(xmlreader::XmlReader &reader);
@@ -385,7 +388,8 @@ private:
 
     stringmap   handleAtkObject(xmlreader::XmlReader &reader) const;
 
-    static void applyAtkProperties(vcl::Window *pWindow, const stringmap& 
rProperties);
+    // if bToolbarItem=true, pParent is the ToolBox that the item belongs to, 
since there's no widget for the item itself
+    void applyAtkProperties(vcl::Window *pWindow, const stringmap& 
rProperties, bool bToolbarItem);
 
     void        handleActionWidget(xmlreader::XmlReader &reader);
 
diff --git a/vcl/source/window/builder.cxx b/vcl/source/window/builder.cxx
index 0fcf7d6b65fd..7c77fad75a53 100644
--- a/vcl/source/window/builder.cxx
+++ b/vcl/source/window/builder.cxx
@@ -2796,7 +2796,7 @@ void VclBuilder::tweakInsertedChild(vcl::Window *pParent, 
vcl::Window* pCurrentC
     }
 }
 
-void VclBuilder::handleChild(vcl::Window *pParent, stringmap* pAtkProps, 
xmlreader::XmlReader &reader)
+void VclBuilder::handleChild(vcl::Window *pParent, stringmap* pAtkProps, 
xmlreader::XmlReader &reader, bool bToolbarItem)
 {
     xmlreader::Span name;
     int nsId;
@@ -2833,7 +2833,7 @@ void VclBuilder::handleChild(vcl::Window *pParent, 
stringmap* pAtkProps, xmlread
         {
             if (name == "object" || name == "placeholder")
             {
-                pCurrentChild = handleObject(pParent, pAtkProps, reader);
+                pCurrentChild = handleObject(pParent, pAtkProps, reader, 
bToolbarItem);
 
                 bool bObjectInserted = pCurrentChild && pParent != 
pCurrentChild;
                 if (bObjectInserted)
@@ -3095,12 +3095,22 @@ VclBuilder::stringmap 
VclBuilder::handleAtkObject(xmlreader::XmlReader &reader)
     return aProperties;
 }
 
-void VclBuilder::applyAtkProperties(vcl::Window *pWindow, const stringmap& 
rProperties)
+void VclBuilder::applyAtkProperties(vcl::Window *pWindow, const stringmap& 
rProperties, bool bToolbarItem)
 {
     assert(pWindow);
     for (auto const& [ rKey, rValue ] : rProperties)
     {
-        if (pWindow && rKey.match("AtkObject::"))
+        if (bToolbarItem)
+        {
+            // apply accessible name to the toolbar item
+            if (rKey == u"AtkObject::accessible-name")
+            {
+                ToolBox* pToolBox = dynamic_cast<ToolBox*>(pWindow);
+                assert(pToolBox);
+                pToolBox->SetAccessibleName(m_pParserState->m_nLastToolbarId, 
rValue);
+            }
+        }
+        else if (pWindow && rKey.match("AtkObject::"))
             
pWindow->set_property(rKey.copy(RTL_CONSTASCII_LENGTH("AtkObject::")), rValue);
         else
             SAL_WARN("vcl.builder", "unhandled atk prop: " << rKey);
@@ -3558,7 +3568,7 @@ template<typename T> static bool insertItems(vcl::Window 
*pWindow, VclBuilder::s
     return true;
 }
 
-VclPtr<vcl::Window> VclBuilder::handleObject(vcl::Window *pParent, stringmap 
*pAtkProps, xmlreader::XmlReader &reader)
+VclPtr<vcl::Window> VclBuilder::handleObject(vcl::Window *pParent, stringmap 
*pAtkProps, xmlreader::XmlReader &reader, bool bToolbarItem)
 {
     OUString sClass;
     OUString sID;
@@ -3616,7 +3626,7 @@ VclPtr<vcl::Window> VclBuilder::handleObject(vcl::Window 
*pParent, stringmap *pA
         assert(!(pParent && pAtkProps) && "must not have both");
         auto aAtkProperties = handleAtkObject(reader);
         if (pParent)
-            applyAtkProperties(pParent, aAtkProperties);
+            applyAtkProperties(pParent, aAtkProperties, bToolbarItem);
         if (pAtkProps)
             *pAtkProps = aAtkProperties;
         return nullptr;
@@ -3649,7 +3659,8 @@ VclPtr<vcl::Window> VclBuilder::handleObject(vcl::Window 
*pParent, stringmap *pA
                     pCurrentChild = insertObject(pParent, sClass, sID,
                         aProperties, aPangoAttributes, aAtkAttributes);
                 }
-                handleChild(pCurrentChild, nullptr, reader);
+                const bool bToolItem = pCurrentChild == pParent && 
pCurrentChild->GetType() == WindowType::TOOLBOX && isToolbarItemClass(sClass);
+                handleChild(pCurrentChild, nullptr, reader, bToolItem);
             }
             else if (name == "items")
                 aItems = handleItems(reader);
commit 8e456d51a48b4d2461634a41a40a5a3b58bfdef3
Author:     Michael Weghorn <m.wegh...@posteo.de>
AuthorDate: Tue Feb 27 12:58:52 2024 +0100
Commit:     Michael Weghorn <m.wegh...@posteo.de>
CommitDate: Tue Feb 27 19:34:47 2024 +0100

    tdf#159910 vcl a11y: Allow explicitly setting toolbar item a11y name
    
    Add `ToolBox::SetAccessibleName` (and corresponding getter)
    to allow explicitly setting an accessible name for a toolbox/toolbar
    item with the VCL toolbar implementation.
    
    In the a11y class for a toolbar item, use any
    explicitly set name if it's non-empty, otherwise
    fall back to the previous logic.
    
    This will be used in an upcoming commit to
    take into account the accessible name set in .ui files
    and align the VCL ToolBox more with the gtk implementation
    using native GtkToolbar and native widgets for the toolbar
    items.
    
    Change-Id: Ib0255e2741a7ab2489a857ac120fb87f680fa775
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/164033
    Tested-by: Jenkins
    Reviewed-by: Michael Weghorn <m.wegh...@posteo.de>

diff --git a/accessibility/source/standard/vclxaccessibletoolboxitem.cxx 
b/accessibility/source/standard/vclxaccessibletoolboxitem.cxx
index 064d2ebb3037..b8e489c9f610 100644
--- a/accessibility/source/standard/vclxaccessibletoolboxitem.cxx
+++ b/accessibility/source/standard/vclxaccessibletoolboxitem.cxx
@@ -340,7 +340,11 @@ OUString SAL_CALL 
VCLXAccessibleToolBoxItem::getAccessibleDescription(  )
 
 OUString VCLXAccessibleToolBoxItem::implGetAccessibleName()
 {
-    OUString sRet = implGetText();
+    OUString sRet = m_pToolBox->GetAccessibleName(m_nItemId);
+    if (!sRet.isEmpty())
+        return sRet;
+
+    sRet = implGetText();
     if (!sRet.isEmpty())
         return sRet;
 
diff --git a/include/vcl/toolbox.hxx b/include/vcl/toolbox.hxx
index 6cf448a30b1d..ead78c715dc9 100644
--- a/include/vcl/toolbox.hxx
+++ b/include/vcl/toolbox.hxx
@@ -412,6 +412,10 @@ public:
 
     void                SetHelpId( ToolBoxItemId nItemId, const OUString& 
rHelpId );
 
+    using DockingWindow::SetAccessibleName;
+    void SetAccessibleName(ToolBoxItemId nItemId, const OUString& rName );
+    OUString GetAccessibleName(ToolBoxItemId nItemId) const;
+
     //  window size according to current alignment, floating state and number 
of lines
     Size                CalcWindowSizePixel();
     //  window size according to current alignment, floating state and a given 
number of lines
diff --git a/vcl/inc/toolbox.h b/vcl/inc/toolbox.h
index bda27560cbd0..3510889d42cb 100644
--- a/vcl/inc/toolbox.h
+++ b/vcl/inc/toolbox.h
@@ -44,6 +44,7 @@ struct ImplToolItem
     OUString            maText;
     OUString            maQuickHelpText;
     OUString            maHelpText;
+    OUString            maAccessibleName;
     OUString            maCommandStr;
     OUString            maHelpId;
     tools::Rectangle           maRect;
diff --git a/vcl/source/window/toolbox2.cxx b/vcl/source/window/toolbox2.cxx
index c799495b9b0a..bbec06228807 100644
--- a/vcl/source/window/toolbox2.cxx
+++ b/vcl/source/window/toolbox2.cxx
@@ -1349,6 +1349,23 @@ const OUString& ToolBox::GetHelpText( ToolBoxItemId 
nItemId ) const
     return ImplGetHelpText( nItemId );
 }
 
+void ToolBox::SetAccessibleName(ToolBoxItemId nItemId, const OUString& rText)
+{
+    ImplToolItem* pItem = ImplGetItem(nItemId);
+
+    if (pItem)
+        pItem->maAccessibleName = rText;
+}
+
+OUString ToolBox::GetAccessibleName(ToolBoxItemId nItemId) const
+{
+    ImplToolItem* pItem = ImplGetItem(nItemId);
+    if (pItem)
+        return pItem->maAccessibleName;
+
+    return OUString();
+}
+
 void ToolBox::SetHelpId( ToolBoxItemId nItemId, const OUString& rHelpId )
 {
     ImplToolItem* pItem = ImplGetItem( nItemId );

Reply via email to