vcl/unx/gtk3/a11y/atklistener.cxx |   27 ++++++++++-----------------
 vcl/unx/gtk3/a11y/atktext.cxx     |   18 ------------------
 2 files changed, 10 insertions(+), 35 deletions(-)

New commits:
commit 4162feb37109d4e9da44933831e10b5732721c72
Author:     Michael Weghorn <m.wegh...@posteo.de>
AuthorDate: Tue Feb 22 13:39:56 2022 +0100
Commit:     Michael Weghorn <m.wegh...@posteo.de>
CommitDate: Wed Feb 23 06:26:32 2022 +0100

    gtk3 a11y: Migrate from deprecated "text-changed" ATK signal
    
    The "text-changed" ATK signal (which has a detail of "insert"
    or "delete" to indicate what type of change happened) is
    deprecated since ATK 2.9.4 and "text-insert" or "text-remove"
    should be used instead [1], so do this.
    Those have the inserted/removed text as a third argument,
    so this also obsoletes the workaround to remember the deleted text
    under the "ooo::text_changed::delete" key for the ATK object
    in the "text-changed:delete" case. (See inline comments
    dropped in this commit for more details on how that was
    used, by now "appropriate API exists in atk to pass
    the string value directly".)
    
    Note that this only changes the signal on the ATK layer,
    the corresponding signal on the (underlying) AT-SPI layer
    is still "object::text-changed::inserted" or
    "object::text-changed::deleted", but other than the
    ATK signal of the same name, this event already has
    the inserted/deleted text as extra data. [2]
    
    (The conversion from the ATK signal to the AT-SPI one
    happens in at-spi2-atk. [3]).
    
    I used this script to check the emitted AT-SPI events:
    
        #!/usr/bin/python3
        import pyatspi
        def listener(e):
            try:
                if e.host_application.name != 'soffice':
                    return
                if e.source.role != pyatspi.role.ROLE_PARAGRAPH:
                    return
            except:
                return
            print(e)
        pyatspi.Registry.registerEventListener(listener, "object:text-changed")
        pyatspi.Registry.start()
    
    Pasting the Chinese sample text from tdf#147285 into
    an empty Writer document, removing the third character
    and typing "a" instead resulted in the expected output:
    
    > object:text-changed:insert(0, 12, 维基百科,自由的百科全书)
    >         source: [paragraph | ]
    >         host_application: [application | soffice]
    >         sender: [application | soffice]
    > object:text-changed:delete(2, 1, 百)
    >         source: [paragraph | ]
    >         host_application: [application | soffice]
    >         sender: [application | soffice]
    > object:text-changed:insert(2, 1, a)
    >         source: [paragraph | ]
    >         host_application: [application | soffice]
    >         sender: [application | soffice]
    
    Given this test worked, drop the old
    
    > // TESTME: and remove this comment:
    
    comment as well, and also drop the
    
    > // TODO: when GNOME starts to send "update" kind of events, change
    > // we need to re-think this implementation as well
    
    comment. From what I can see this is still the way to handle
    events using ATK (i.e. for Gtk 3 at least, Gtk 4 has a new a11y
    implementation [4], but that will have to be looked at separately
    anyway).
    
    [1] https://docs.gtk.org/atk/signal.Text.text-changed.html
    [2] 
https://accessibility.linuxfoundation.org/a11yspecs/atspi/adoc/atspi-events.html
    [3] 
https://gitlab.gnome.org/GNOME/at-spi2-atk/-/blob/0af3f73b/atk-adaptor/event.c#L962
    [4] https://blog.gtk.org/2020/10/21/accessibility-in-gtk-4/
    
    Change-Id: Ibcae27ecfccf41a909e06d01ce681e4b7b97eb25
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/130352
    Tested-by: Jenkins
    Reviewed-by: Michael Weghorn <m.wegh...@posteo.de>

diff --git a/vcl/unx/gtk3/a11y/atklistener.cxx 
b/vcl/unx/gtk3/a11y/atklistener.cxx
index 2ef96be4616e..6d81a9a60531 100644
--- a/vcl/unx/gtk3/a11y/atklistener.cxx
+++ b/vcl/unx/gtk3/a11y/atklistener.cxx
@@ -566,34 +566,27 @@ void AtkListener::notifyEvent( const 
accessibility::AccessibleEventObject& aEven
         }
         case accessibility::AccessibleEventId::TEXT_CHANGED:
         {
-            // TESTME: and remove this comment:
             // cf. comphelper/source/misc/accessibletexthelper.cxx 
(implInitTextChangedEvent)
             accessibility::TextSegment aDeletedText;
             accessibility::TextSegment aInsertedText;
 
-            // TODO: when GNOME starts to send "update" kind of events, change
-            // we need to re-think this implementation as well
             if( aEvent.OldValue >>= aDeletedText )
             {
-                /* Remember the text segment here to be able to return removed 
text in get_text().
-                 * This is clearly a hack to be used until appropriate API 
exists in atk to pass
-                 * the string value directly or we find a compelling reason to 
start caching the
-                 * UTF-8 converted strings in the atk wrapper object.
-                 */
-
-                g_object_set_data( G_OBJECT(atk_obj), 
"ooo::text_changed::delete", &aDeletedText);
-
-                g_signal_emit_by_name( atk_obj, "text_changed::delete",
+                const OString aDeletedTextUtf8 = 
OUStringToOString(aDeletedText.SegmentText, RTL_TEXTENCODING_UTF8);
+                g_signal_emit_by_name( atk_obj, "text-remove",
                                        
static_cast<gint>(aDeletedText.SegmentStart),
-                                       static_cast<gint>( 
aDeletedText.SegmentEnd - aDeletedText.SegmentStart ) );
+                                       
static_cast<gint>(aDeletedText.SegmentEnd - aDeletedText.SegmentStart),
+                                       g_strdup(aDeletedTextUtf8.getStr()));
 
-                g_object_steal_data( G_OBJECT(atk_obj), 
"ooo::text_changed::delete" );
             }
-
             if( aEvent.NewValue >>= aInsertedText )
-                g_signal_emit_by_name( atk_obj, "text_changed::insert",
+            {
+                const OString aInsertedTextUtf8 = 
OUStringToOString(aInsertedText.SegmentText, RTL_TEXTENCODING_UTF8);
+                g_signal_emit_by_name( atk_obj, "text-insert",
                                        
static_cast<gint>(aInsertedText.SegmentStart),
-                                       static_cast<gint>( 
aInsertedText.SegmentEnd - aInsertedText.SegmentStart ) );
+                                       
static_cast<gint>(aInsertedText.SegmentEnd - aInsertedText.SegmentStart),
+                                       g_strdup(aInsertedTextUtf8.getStr()));
+            }
             break;
         }
 
diff --git a/vcl/unx/gtk3/a11y/atktext.cxx b/vcl/unx/gtk3/a11y/atktext.cxx
index 8fc773224768..aee5c5ef5db0 100644
--- a/vcl/unx/gtk3/a11y/atktext.cxx
+++ b/vcl/unx/gtk3/a11y/atktext.cxx
@@ -254,24 +254,6 @@ text_wrapper_get_text (AtkText *text,
 
     g_return_val_if_fail( (end_offset == -1) || (end_offset >= start_offset), 
nullptr );
 
-    /* at-spi expects the delete event to be send before the deletion happened
-     * so we save the deleted string object in the UNO event notification and
-     * fool libatk-bridge.so here ..
-     */
-    void * pData = g_object_get_data( G_OBJECT(text), 
"ooo::text_changed::delete" );
-    if( pData != nullptr )
-    {
-        accessibility::TextSegment * pTextSegment =
-            static_cast <accessibility::TextSegment *> (pData);
-
-        if( pTextSegment->SegmentStart == start_offset &&
-            pTextSegment->SegmentEnd == end_offset )
-        {
-            OString aUtf8 = OUStringToOString( pTextSegment->SegmentText, 
RTL_TEXTENCODING_UTF8 );
-            return g_strdup( aUtf8.getStr() );
-        }
-    }
-
     try {
         css::uno::Reference<css::accessibility::XAccessibleText> pText
             = getText( text );

Reply via email to