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)