tdf#123864 a11y: Add new AccessibleStateType::CHECKABLE

Both, AT-SPI and IAccessible2 have a CHECKABLE state
that describes whether an item is checkable, i.e.
whether it can be checked, i.e. whether it is possible
that this object can have the CHECKED state.

So far, LibreOffice didn't have any equivalent, and
e.g. a checkbox that is ticked would report state
CHECKED but not CHECKABLE, which is inconsistent.
("How can an object that is not checkable be checked?")

For an unchecked object, the fact that it can be checked
is unclear since that one will just have the CHECKED state
not being present.

Introduce a new a11y state, `AccessibleStateType::CHECKABLE`
with the same semantics as in AT-SPI and IAccessible2 to
bridge the gap.

Map the state in winaccessibility (to IAccessible2),
gtk3 and an the Qt-based VCL plugins, which are
responsible for mapping to AT-SPI.

While Qt has an equivalent state flag, it currently
doesn't map that to AT-SPI yet.
Pending upstream Gerrit change to implement that: [1]

The gtk4 a11y API doesn't have a direct equivalent and will
be handled separately in a following commit.

Reporting the new state where applicable will be
implemented in following commits.

[1] https://codereview.qt-project.org/c/qt/qtbase/+/517844

Change-Id: I6aa7fec3b3bd728a5cfedcdc8d6b66f06337f7ce
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/159382
Tested-by: Jenkins
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
This commit is contained in:
Michael Weghorn
2023-11-13 15:53:44 +01:00
parent 74c1e23c80
commit d6c6472bbe
4 changed files with 18 additions and 2 deletions

View File

@@ -239,6 +239,12 @@ constants AccessibleStateType
*/
const hyper COLLAPSE = 8589934592;
/** Indicates this object is checkable, i.e. it has the potential
to be checked.
See also the CHECKED state.
*/
const hyper CHECKABLE = 17179869184;
};
}; }; }; };

View File

@@ -578,6 +578,9 @@ void lcl_addState(QAccessible::State* state, sal_Int64 nState)
case AccessibleStateType::BUSY:
state->busy = true;
break;
case AccessibleStateType::CHECKABLE:
state->checkable = true;
break;
case AccessibleStateType::CHECKED:
state->checked = true;
break;

View File

@@ -125,6 +125,7 @@ AtkStateType mapAtkState( sal_Int64 nState )
MAP_DIRECT( ACTIVE );
MAP_DIRECT( ARMED );
MAP_DIRECT( BUSY );
MAP_DIRECT( CHECKABLE );
MAP_DIRECT( CHECKED );
MAP_DIRECT( EDITABLE );
MAP_DIRECT( ENABLED );

View File

@@ -128,7 +128,7 @@ bool queryTableCell(XAccessible* pXAcc, XInterface** ppXI)
}
void lcl_addIA2State(AccessibleStates& rStates, sal_Int64 nUnoState)
void lcl_addIA2State(AccessibleStates& rStates, sal_Int64 nUnoState, sal_Int16 nRole)
{
switch (nUnoState)
{
@@ -138,6 +138,12 @@ void lcl_addIA2State(AccessibleStates& rStates, sal_Int64 nUnoState)
case css::accessibility::AccessibleStateType::ARMED:
rStates |= IA2_STATE_ARMED;
break;
case css::accessibility::AccessibleStateType::CHECKABLE:
// STATE_SYSTEM_PRESSED is used instead of STATE_SYSTEM_CHECKED for these button
// roles (s. AccObject::GetMSAAStateFromUNO), so don't set CHECKABLE state for them
if (nRole != AccessibleRole::PUSH_BUTTON && nRole != AccessibleRole::TOGGLE_BUTTON)
rStates |= IA2_STATE_CHECKABLE;
break;
case css::accessibility::AccessibleStateType::DEFUNC:
rStates |= IA2_STATE_DEFUNCT;
break;
@@ -2592,7 +2598,7 @@ COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::get_states(AccessibleStates __RP
{
sal_Int64 nUnoState = sal_Int64(1) << i;
if (nRStateSet & nUnoState)
lcl_addIA2State(*states, nUnoState);
lcl_addIA2State(*states, nUnoState, m_xContext->getAccessibleRole());
}
return S_OK;