vcl/unx/gtk3/a11y/atkselection.cxx |    8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

New commits:
commit eec233bf33ac0d9ac1ba0ecc669a5ecf58626ef2
Author:     Michael Weghorn <m.wegh...@posteo.de>
AuthorDate: Tue Oct 26 16:51:35 2021 +0200
Commit:     Michael Weghorn <m.wegh...@posteo.de>
CommitDate: Thu Oct 28 20:36:14 2021 +0200

    gtk3 a11y: Use correct index when deselecting child
    
    The AT-SPI selection interface provides two functions
    to unselect:
    
         gboolean atspi_selection_deselect_selected_child (AtspiSelection *obj, 
gint selected_child_index, GError **error);
         gboolean atspi_selection_deselect_child (AtspiSelection *obj, gint 
child_index, GError **error);
    
    For the first one, 'atspi_selection_deselect_selected_child',
    "child_index is the index in the selected-children list,
    not the index in the parent container." [1]
    
    For the second one, 'atspi_selection_deselect_child',
    "child_index is the index of the child in the parent container". [2]
    
    ATKSelection, on the other hand, only has
    
        gboolean
        atk_selection_remove_selection (AtkSelection *selection,
                                        gint i);
    
    where the index 'i' is "a gint specifying the index in the selection set.
    (e.g. the ith selection as opposed to the ith child)." [3]
    
    That means, the meaning of the index in
    'atk_selection_remove_selection' is the same as in
    'atspi_selection_deselect_selected_child', while
    'XAccessibleSelection::deselectAccessibleChild' expects
    an index in the parent container, not in the selection
    set.
    
    Therefore, convert the index from an index in the
    selection to a child index first before passing
    it into 'XAccessibleSelection::deselectAccessibleChild'.
    
    (For ATK, the mapping from the two AT-SPI to the
    ATK function is done in libatk-bridge.)
    
    Example to reproduce wrong behaviour without this
    change in place:
    
    1) select cells B1 to E5 in Calc
    2) start Accerciser
    3) select the Calc table in Accerciser
    4) get AT-SPI selection interface for the table by typing the following
       in the IPython Console in Accerciser:
    
        sel = acc.querySelection()
    
    5) check whether child 0 (i.e. cell A1) is selected
    
        In : sel.isChildSelected(0)
        Out: False
    
    -> OK
    
    6) check whether child 1 (i.e. cell B1) is selected:
    
        In : sel.isChildSelected(1)
        Out: True
    
    -> OK
    
    7a) try to unselect cell B1:
        In : sel.deselectChild(1)
        Out: True
    
    -> NOK: selection remains unchanged, cell B1 is still selected
    
    Alternatively, intead of step 7a:
    7b) try to unselect cell C1 (2nd item in the selection):
    
        In : sel.deselectSelectedChild(1)
        Out: True
    
    -> NOK: cell B1 gets unselected instead of C1
    
    [1] 
https://developer-old.gnome.org/libatspi/unstable/libatspi-atspi-selection.html#atspi-selection-deselect-selected-child
    [2] 
https://developer-old.gnome.org/libatspi/unstable/libatspi-atspi-selection.html#atspi-selection-deselect-child
    [3] 
https://gnome.pages.gitlab.gnome.org/atk/AtkSelection.html#atk-selection-remove-selection
    
    Change-Id: I3c63c647e61baaa6288ffd545d8d89d8b94231de
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/124329
    Tested-by: Jenkins
    Reviewed-by: Michael Weghorn <m.wegh...@posteo.de>

diff --git a/vcl/unx/gtk3/a11y/atkselection.cxx 
b/vcl/unx/gtk3/a11y/atkselection.cxx
index 91759e8d0b21..22d515f1b6fa 100644
--- a/vcl/unx/gtk3/a11y/atkselection.cxx
+++ b/vcl/unx/gtk3/a11y/atkselection.cxx
@@ -141,7 +141,13 @@ selection_remove_selection( AtkSelection *selection,
             = getSelection( selection );
         if( pSelection.is() )
         {
-            pSelection->deselectAccessibleChild( i );
+            css::uno::Reference<css::accessibility::XAccessible> xAcc = 
pSelection->getSelectedAccessibleChild(i);
+            if (!xAcc.is())
+                return false;
+
+            css::uno::Reference<css::accessibility::XAccessibleContext> 
xAccContext = xAcc->getAccessibleContext();
+            const sal_Int32 nChildIndex = 
xAccContext->getAccessibleIndexInParent();
+            pSelection->deselectAccessibleChild(nChildIndex);
             return true;
         }
     }

Reply via email to