vcl/unx/gtk4/gtkaccessibletext.cxx |   85 +++++++++++++++++++++++++++++++++----
 1 file changed, 78 insertions(+), 7 deletions(-)

New commits:
commit 5a4c3575945876f90dc2f6d67211107ed3b1de4f
Author:     Michael Weghorn <m.wegh...@posteo.de>
AuthorDate: Fri Mar 15 10:06:49 2024 +0100
Commit:     Michael Weghorn <m.wegh...@posteo.de>
CommitDate: Fri Mar 15 13:59:44 2024 +0100

    gtk4 a11y: Extract helper function for text attr conversion
    
    Extract conversion of LO's text attr representation to the
    one that the GTK implementation in
    `lo_accessible_text_get_attributes` needs to return to
    a new helper function `convertUnoTextAttributesToGtk` that
    will be reused in an upcoming commit to implement handling
    of default text attributes for which API has recently been
    added to GTK.
    
    Change-Id: I01a703012c668149a29c3ce759437a1b716988dc
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/164859
    Tested-by: Jenkins
    Reviewed-by: Michael Weghorn <m.wegh...@posteo.de>

diff --git a/vcl/unx/gtk4/gtkaccessibletext.cxx 
b/vcl/unx/gtk4/gtkaccessibletext.cxx
index ffe4108a1e6f..4d7853c054d4 100644
--- a/vcl/unx/gtk4/gtkaccessibletext.cxx
+++ b/vcl/unx/gtk4/gtkaccessibletext.cxx
@@ -125,6 +125,38 @@ static gboolean 
lo_accessible_text_get_selection(GtkAccessibleText* self, gsize*
     return true;
 }
 
+static int
+convertUnoTextAttributesToGtk(const 
css::uno::Sequence<css::beans::PropertyValue>& rAttribs,
+                              char*** attribute_names, char*** 
attribute_values)
+{
+    std::vector<std::pair<OString, OUString>> aNameValuePairs;
+    for (const css::beans::PropertyValue& rAttribute : rAttribs)
+    {
+        if (rAttribute.Name == "CharFontName")
+        {
+            const OUString sValue = 
*o3tl::doAccess<OUString>(rAttribute.Value);
+            aNameValuePairs.emplace_back(GTK_ACCESSIBLE_ATTRIBUTE_FAMILY, 
sValue);
+        }
+    }
+
+    if (aNameValuePairs.empty())
+        return 0;
+
+    const int nCount = aNameValuePairs.size();
+    *attribute_names = g_new(char*, nCount + 1);
+    *attribute_values = g_new(char*, nCount + 1);
+    for (int i = 0; i < nCount; i++)
+    {
+        (*attribute_names)[i] = g_strdup(aNameValuePairs[i].first.getStr());
+        (*attribute_values)[i] = g_strdup(
+            OUStringToOString(aNameValuePairs[i].second, 
RTL_TEXTENCODING_UTF8).getStr());
+    }
+    (*attribute_names)[nCount] = nullptr;
+    (*attribute_values)[nCount] = nullptr;
+
+    return nCount;
+}
+
 static gboolean lo_accessible_text_get_attributes(GtkAccessibleText* self, 
unsigned int offset,
                                                   gsize* n_ranges, 
GtkAccessibleTextRange** ranges,
                                                   char*** attribute_names, 
char*** attribute_values)
@@ -152,40 +184,20 @@ static gboolean 
lo_accessible_text_get_attributes(GtkAccessibleText* self, unsig
     else
         aAttribs = xText->getCharacterAttributes(offset, 
css::uno::Sequence<OUString>());
 
-    std::vector<std::pair<OString, OUString>> aNameValuePairs;
-    for (const css::beans::PropertyValue& rAttribute : aAttribs)
-    {
-        if (rAttribute.Name == "CharFontName")
-        {
-            const OUString sValue = 
*o3tl::doAccess<OUString>(rAttribute.Value);
-            aNameValuePairs.emplace_back(GTK_ACCESSIBLE_ATTRIBUTE_FAMILY, 
sValue);
-        }
-    }
-
-    if (aNameValuePairs.empty())
+    const int nCount = convertUnoTextAttributesToGtk(aAttribs, 
attribute_names, attribute_values);
+    if (nCount == 0)
         return false;
 
-    const css::accessibility::TextSegment aAttributeRun
-        = xText->getTextAtIndex(offset, 
css::accessibility::AccessibleTextType::ATTRIBUTE_RUN);
-
-    const int nCount = aNameValuePairs.size();
     *n_ranges = nCount;
     *ranges = g_new(GtkAccessibleTextRange, nCount);
-    *attribute_names = g_new(char*, nCount + 1);
-    *attribute_values = g_new(char*, nCount + 1);
-
+    // just use start and end of attribute run for each single attribute
+    const css::accessibility::TextSegment aAttributeRun
+        = xText->getTextAtIndex(offset, 
css::accessibility::AccessibleTextType::ATTRIBUTE_RUN);
     for (int i = 0; i < nCount; i++)
     {
-        // just use start and end of attribute run for each single attribute
         ((*ranges)[i]).start = aAttributeRun.SegmentStart;
         ((*ranges)[i]).length = aAttributeRun.SegmentEnd - 
aAttributeRun.SegmentStart;
-
-        (*attribute_names)[i] = g_strdup(aNameValuePairs[i].first.getStr());
-        (*attribute_values)[i] = g_strdup(
-            OUStringToOString(aNameValuePairs[i].second, 
RTL_TEXTENCODING_UTF8).getStr());
     }
-    (*attribute_names)[nCount] = nullptr;
-    (*attribute_values)[nCount] = nullptr;
 
     return true;
 }
commit ae00b39c43b7c767d7f0eea78eb104b983799265
Author:     Michael Weghorn <m.wegh...@posteo.de>
AuthorDate: Fri Mar 15 09:40:31 2024 +0100
Commit:     Michael Weghorn <m.wegh...@posteo.de>
CommitDate: Fri Mar 15 13:59:36 2024 +0100

    gtk4 a11y: Add initial text attribute handling
    
    Implement initial handling for reporting text
    attributes in `lo_accessible_text_get_attributes`.
    
    Initially, only the font family attribute is
    handled, but more can be added in the future
    (s.a. the gtk3/atk and Qt implementations).
    
    With this in place, formatting some text in a
    Writer paragraph with font "Linux Libertine G"
    now shows the "family-name" text attribute with
    a value of "Linux Libertine G" as expected in
    Accerciser when selecting the paragraph object
    in Accerciser's treeview of the LO a11y tree and
    choosing an appropriate offset when using the gtk4 VCL
    plugin, just as with the gtk3 or qt6 VCL plugins.
    
    (Implementation inspired by GTK's internal
    `gtk_text_view_accessible_text_get_attributes` [1])
    
    [1] 
https://gitlab.gnome.org/GNOME/gtk/-/blob/fe4cd7cf0f497ace134a39243b0a44ef09e181be/gtk/gtktextview.c#L10459
    
    Change-Id: Iba565753b3143548492ccc817a159ebfb92a8c88
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/164858
    Tested-by: Jenkins
    Reviewed-by: Michael Weghorn <m.wegh...@posteo.de>

diff --git a/vcl/unx/gtk4/gtkaccessibletext.cxx 
b/vcl/unx/gtk4/gtkaccessibletext.cxx
index c98275468408..ffe4108a1e6f 100644
--- a/vcl/unx/gtk4/gtkaccessibletext.cxx
+++ b/vcl/unx/gtk4/gtkaccessibletext.cxx
@@ -7,9 +7,13 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
+#include <vector>
+
 #include <com/sun/star/accessibility/AccessibleTextType.hpp>
 #include <com/sun/star/accessibility/TextSegment.hpp>
 #include <com/sun/star/accessibility/XAccessibleText.hpp>
+#include <com/sun/star/accessibility/XAccessibleTextAttributes.hpp>
+#include <o3tl/any.hxx>
 #include <sal/log.hxx>
 
 #include "a11y.hxx"
@@ -121,14 +125,69 @@ static gboolean 
lo_accessible_text_get_selection(GtkAccessibleText* self, gsize*
     return true;
 }
 
-static gboolean lo_accessible_text_get_attributes(GtkAccessibleText* /* self 
*/,
-                                                  unsigned int /* offset */, 
gsize* /* n_ranges */,
-                                                  GtkAccessibleTextRange** /* 
ranges */,
-                                                  char*** /* attribute_names 
*/,
-                                                  char*** /* attribute_values 
*/)
+static gboolean lo_accessible_text_get_attributes(GtkAccessibleText* self, 
unsigned int offset,
+                                                  gsize* n_ranges, 
GtkAccessibleTextRange** ranges,
+                                                  char*** attribute_names, 
char*** attribute_values)
 {
-    // TODO: implement
-    return false;
+    css::uno::Reference<css::accessibility::XAccessibleText> xText = 
getXText(self);
+    if (!xText.is())
+        return false;
+
+    const unsigned int nTextLength = 
o3tl::make_unsigned(xText->getCharacterCount());
+    if (offset == nTextLength)
+        offset = nTextLength - 1;
+
+    if (offset >= nTextLength)
+    {
+        SAL_WARN("vcl.gtk",
+                 "lo_accessible_text_get_attributes called with invalid 
offset: " << offset);
+        return false;
+    }
+
+    css::uno::Sequence<css::beans::PropertyValue> aAttribs;
+    css::uno::Reference<css::accessibility::XAccessibleTextAttributes> 
xAttributes(
+        xText, com::sun::star::uno::UNO_QUERY);
+    if (xAttributes.is())
+        aAttribs = xAttributes->getRunAttributes(offset, 
css::uno::Sequence<OUString>());
+    else
+        aAttribs = xText->getCharacterAttributes(offset, 
css::uno::Sequence<OUString>());
+
+    std::vector<std::pair<OString, OUString>> aNameValuePairs;
+    for (const css::beans::PropertyValue& rAttribute : aAttribs)
+    {
+        if (rAttribute.Name == "CharFontName")
+        {
+            const OUString sValue = 
*o3tl::doAccess<OUString>(rAttribute.Value);
+            aNameValuePairs.emplace_back(GTK_ACCESSIBLE_ATTRIBUTE_FAMILY, 
sValue);
+        }
+    }
+
+    if (aNameValuePairs.empty())
+        return false;
+
+    const css::accessibility::TextSegment aAttributeRun
+        = xText->getTextAtIndex(offset, 
css::accessibility::AccessibleTextType::ATTRIBUTE_RUN);
+
+    const int nCount = aNameValuePairs.size();
+    *n_ranges = nCount;
+    *ranges = g_new(GtkAccessibleTextRange, nCount);
+    *attribute_names = g_new(char*, nCount + 1);
+    *attribute_values = g_new(char*, nCount + 1);
+
+    for (int i = 0; i < nCount; i++)
+    {
+        // just use start and end of attribute run for each single attribute
+        ((*ranges)[i]).start = aAttributeRun.SegmentStart;
+        ((*ranges)[i]).length = aAttributeRun.SegmentEnd - 
aAttributeRun.SegmentStart;
+
+        (*attribute_names)[i] = g_strdup(aNameValuePairs[i].first.getStr());
+        (*attribute_values)[i] = g_strdup(
+            OUStringToOString(aNameValuePairs[i].second, 
RTL_TEXTENCODING_UTF8).getStr());
+    }
+    (*attribute_names)[nCount] = nullptr;
+    (*attribute_values)[nCount] = nullptr;
+
+    return true;
 }
 
 void lo_accessible_text_init(GtkAccessibleTextInterface* iface)

Reply via email to