Visitar URL original
macOS a11y: let other apps set values on accessibility elements by kayakthedev · Pull Request #69 · LibreOffice/core · GitHub
Skip to content

macOS a11y: let other apps set values on accessibility elements - #69

Open
kayakthedev wants to merge 1 commit into
LibreOffice:masterfrom
kayakthedev:macos-a11y-setters
Open

kayakthedev wants to merge 1 commit into
LibreOffice:masterfrom
kayakthedev:macos-a11y-setters

Conversation

@kayakthedev

Copy link
Copy Markdown

AquaA11yWrapper is an NSAccessibilityElement and overrides the
NSAccessibility protocol's getters (accessibilityValue etc.), but none
of its setters. When another process sets an attribute with
AXUIElementSetAttributeValue(), AppKit calls the protocol setter, e.g.
-setAccessibilityValue:, and NSAccessibilityElement's own implementation
drops the value. -accessibilitySetValue:forAttribute:, which dispatches
to the component, text, selection and value wrappers, is never reached.
Since isAccessibilitySelectorAllowed: allows the setters for settable
attributes, the caller is told the attribute is settable and the write
succeeds, but nothing changes.

Measured on macOS 26 with Calc: setting a cell's AXValue to a string,
to 42 and to 3.5, and setting its AXSelectedText, all returned
kAXErrorSuccess, and the cell stayed empty. A standalone
NSAccessibilityElement subclass built the same way shows the same on
macOS 26: AXValue reported settable, the write returned success, and
-accessibilitySetValue:forAttribute: was not called until
-setAccessibilityValue: was overridden to forward to it.

So:

  • Add the setters for the attributes the wrappers can set (AXValue,
    AXFocused, AXSelectedText, AXSelectedTextRange, AXSelectedChildren),
    each forwarding to -accessibilitySetValue:forAttribute:.

  • AquaA11yValueWrapper passed Any( [ number longValue ] ). long is 64
    bit on macOS, so that Any is a hyper, from which neither a sal_Int32
    (scroll bars, check boxes, ...) nor a double (Calc and Writer cells,
    numeric fields) can be extracted, so setCurrentValue() never took it.
    Use the type of the current value instead, as the Qt backend does in
    QtAccessibleWidget::setCurrentValue(), and double otherwise. A number
    set as a Calc cell's AXValue then reaches
    ScAccessibleCellBase::setCurrentValue().

  • AquaA11yTextWrapper's AXValue setter was an empty TODO, while
    isAttributeSettable: reports AXValue settable for every non static
    text element. Implement it with XAccessibleEditableText::setText()
    when the element has editable text, like the AXSelectedText setter
    next to it does with replaceText().

Elements without XAccessibleEditableText (e.g. Calc cells, whose text
is AccessibleStaticTextBase) still report AXValue and AXSelectedText
settable through the text wrapper and ignore a string; that is left
as it is here.


This repository is a read-only mirror, so this is also ready for Gerrit as one commit (Change-Id I32ea2c26baa6afe4bb77ac7f7bbc0e18462b8ebe); a maintainer is welcome to carry it there. Not built inside a full LibreOffice build: the cause was confirmed with a standalone NSAccessibilityElement probe on macOS 26, and the new setters compile against the macOS SDK with -Werror.

🤖 Generated with Claude Code

AquaA11yWrapper is an NSAccessibilityElement and overrides the
NSAccessibility protocol's getters (accessibilityValue etc.), but none
of its setters. When another process sets an attribute with
AXUIElementSetAttributeValue(), AppKit calls the protocol setter, e.g.
-setAccessibilityValue:, and NSAccessibilityElement's own implementation
drops the value. -accessibilitySetValue:forAttribute:, which dispatches
to the component, text, selection and value wrappers, is never reached.
Since isAccessibilitySelectorAllowed: allows the setters for settable
attributes, the caller is told the attribute is settable and the write
succeeds, but nothing changes.

Measured on macOS 26 with Calc: setting a cell's AXValue to a string,
to 42 and to 3.5, and setting its AXSelectedText, all returned
kAXErrorSuccess, and the cell stayed empty. A standalone
NSAccessibilityElement subclass built the same way shows the same on
macOS 26: AXValue reported settable, the write returned success, and
-accessibilitySetValue:forAttribute: was not called until
-setAccessibilityValue: was overridden to forward to it.

So:

- Add the setters for the attributes the wrappers can set (AXValue,
  AXFocused, AXSelectedText, AXSelectedTextRange, AXSelectedChildren),
  each forwarding to -accessibilitySetValue:forAttribute:.

- AquaA11yValueWrapper passed Any( [ number longValue ] ). long is 64
  bit on macOS, so that Any is a hyper, from which neither a sal_Int32
  (scroll bars, check boxes, ...) nor a double (Calc and Writer cells,
  numeric fields) can be extracted, so setCurrentValue() never took it.
  Use the type of the current value instead, as the Qt backend does in
  QtAccessibleWidget::setCurrentValue(), and double otherwise. A number
  set as a Calc cell's AXValue then reaches
  ScAccessibleCellBase::setCurrentValue().

- AquaA11yTextWrapper's AXValue setter was an empty TODO, while
  isAttributeSettable: reports AXValue settable for every non static
  text element. Implement it with XAccessibleEditableText::setText()
  when the element has editable text, like the AXSelectedText setter
  next to it does with replaceText().

Elements without XAccessibleEditableText (e.g. Calc cells, whose text
is AccessibleStaticTextBase) still report AXValue and AXSelectedText
settable through the text wrapper and ignore a string; that is left
as it is here.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: I32ea2c26baa6afe4bb77ac7f7bbc0e18462b8ebe
@tooclassyforthisworld

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants