From 0e451d3452bdaf013304190eb6c42c21235b6713 Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Sat, 11 Jul 2026 16:50:24 +0300 Subject: [PATCH 01/15] Add portable accessibility semantics --- .../impl/CodenameOneImplementation.java | 23 + CodenameOne/src/com/codename1/ui/Button.java | 5 + .../src/com/codename1/ui/CheckBox.java | 1 + .../src/com/codename1/ui/Component.java | 82 ++- CodenameOne/src/com/codename1/ui/Display.java | 19 + CodenameOne/src/com/codename1/ui/Label.java | 4 + CodenameOne/src/com/codename1/ui/List.java | 36 + .../src/com/codename1/ui/RadioButton.java | 1 + CodenameOne/src/com/codename1/ui/Slider.java | 4 + CodenameOne/src/com/codename1/ui/Tabs.java | 2 + .../src/com/codename1/ui/TextArea.java | 2 + .../ui/accessibility/AccessibilityAction.java | 63 ++ .../AccessibilityAssertions.java | 150 ++++ .../AccessibilityCheckedState.java | 12 + .../AccessibilityChildProvider.java | 13 + .../AccessibilityCollectionInfo.java | 43 ++ .../AccessibilityCollectionItemInfo.java | 41 ++ .../accessibility/AccessibilityGrouping.java | 20 + .../accessibility/AccessibilityInspector.java | 20 + .../ui/accessibility/AccessibilityIssue.java | 31 + .../AccessibilityLiveRegion.java | 11 + .../accessibility/AccessibilityManager.java | 669 ++++++++++++++++++ .../ui/accessibility/AccessibilityNode.java | 197 ++++++ .../AccessibilityNodeSnapshot.java | 176 +++++ .../ui/accessibility/AccessibilityRange.java | 55 ++ .../ui/accessibility/AccessibilityRole.java | 48 ++ .../AccessibilityTreeSnapshot.java | 166 +++++ .../android/AndroidAccessibilityProvider.java | 361 ++++++++++ .../impl/android/AndroidImplementation.java | 36 +- .../impl/javase/ComponentTreeInspector.java | 54 ++ .../impl/javase/JavaSEAccessibility.java | 290 ++++++++ .../com/codename1/impl/javase/JavaSEPort.java | 27 + .../impl/html5/HTML5Implementation.java | 201 ++++++ Ports/LinuxPort/nativeSources/cn1_linux.h | 3 +- .../nativeSources/cn1_linux_window.c | 222 ++++++ .../impl/linux/LinuxImplementation.java | 51 ++ .../com/codename1/impl/linux/LinuxNative.java | 7 + Ports/WindowsPort/nativeSources/cn1_windows.h | 4 +- .../cn1_windows_accessibility.cpp | 266 +++++++ .../nativeSources/cn1_windows_window.cpp | 2 + .../impl/windows/WindowsImplementation.java | 51 ++ .../codename1/impl/windows/WindowsNative.java | 7 + Ports/iOSPort/nativeSources/IOSNative.m | 211 ++++++ .../codename1/impl/ios/IOSImplementation.java | 16 + .../src/com/codename1/impl/ios/IOSNative.java | 2 + .../Accessibility-Semantics.asciidoc | 218 ++++++ docs/developer-guide/developer-guide.asciidoc | 2 + .../AccessibilitySemanticsTest.java | 182 +++++ .../accessibility/AccessibilityTest.java | 235 +++++- 49 files changed, 4330 insertions(+), 12 deletions(-) create mode 100644 CodenameOne/src/com/codename1/ui/accessibility/AccessibilityAction.java create mode 100644 CodenameOne/src/com/codename1/ui/accessibility/AccessibilityAssertions.java create mode 100644 CodenameOne/src/com/codename1/ui/accessibility/AccessibilityCheckedState.java create mode 100644 CodenameOne/src/com/codename1/ui/accessibility/AccessibilityChildProvider.java create mode 100644 CodenameOne/src/com/codename1/ui/accessibility/AccessibilityCollectionInfo.java create mode 100644 CodenameOne/src/com/codename1/ui/accessibility/AccessibilityCollectionItemInfo.java create mode 100644 CodenameOne/src/com/codename1/ui/accessibility/AccessibilityGrouping.java create mode 100644 CodenameOne/src/com/codename1/ui/accessibility/AccessibilityInspector.java create mode 100644 CodenameOne/src/com/codename1/ui/accessibility/AccessibilityIssue.java create mode 100644 CodenameOne/src/com/codename1/ui/accessibility/AccessibilityLiveRegion.java create mode 100644 CodenameOne/src/com/codename1/ui/accessibility/AccessibilityManager.java create mode 100644 CodenameOne/src/com/codename1/ui/accessibility/AccessibilityNode.java create mode 100644 CodenameOne/src/com/codename1/ui/accessibility/AccessibilityNodeSnapshot.java create mode 100644 CodenameOne/src/com/codename1/ui/accessibility/AccessibilityRange.java create mode 100644 CodenameOne/src/com/codename1/ui/accessibility/AccessibilityRole.java create mode 100644 CodenameOne/src/com/codename1/ui/accessibility/AccessibilityTreeSnapshot.java create mode 100644 Ports/Android/src/com/codename1/impl/android/AndroidAccessibilityProvider.java create mode 100644 Ports/JavaSE/src/com/codename1/impl/javase/JavaSEAccessibility.java create mode 100644 Ports/WindowsPort/nativeSources/cn1_windows_accessibility.cpp create mode 100644 docs/developer-guide/Accessibility-Semantics.asciidoc create mode 100644 maven/core-unittests/src/test/java/com/codename1/ui/accessibility/AccessibilitySemanticsTest.java diff --git a/CodenameOne/src/com/codename1/impl/CodenameOneImplementation.java b/CodenameOne/src/com/codename1/impl/CodenameOneImplementation.java index e2be5e7049e..70b3886b129 100644 --- a/CodenameOne/src/com/codename1/impl/CodenameOneImplementation.java +++ b/CodenameOne/src/com/codename1/impl/CodenameOneImplementation.java @@ -91,6 +91,8 @@ import com.codename1.ui.TextArea; import com.codename1.ui.TextSelection; import com.codename1.ui.Transform; +import com.codename1.ui.accessibility.AccessibilityManager; +import com.codename1.ui.accessibility.AccessibilityTreeSnapshot; import com.codename1.ui.animations.Animation; import com.codename1.ui.animations.Transition; import com.codename1.ui.events.ActionEvent; @@ -11132,6 +11134,27 @@ public void announceForAccessibility(Component cmp, String text) { // should override this method. } + /// Called after the portable semantic tree changes. Platform ports should + /// invalidate their native virtual accessibility roots and request the latest + /// immutable snapshot with {@link #getAccessibilityTreeSnapshot()}. + public void accessibilityTreeChanged(int changeType) { + } + + /// Returns the latest immutable semantic tree for the current form. + public AccessibilityTreeSnapshot getAccessibilityTreeSnapshot() { + return AccessibilityManager.getInstance().getCurrentSnapshot(); + } + + /// Dispatches an action from a native virtual accessibility node onto the EDT. + public boolean performAccessibilityAction(long nodeId, String actionId, Object argument) { + return AccessibilityManager.getInstance().performAction(nodeId, actionId, argument); + } + + /// Returns true when this port exposes the portable virtual semantic tree. + public boolean isAccessibilityTreeSupported() { + return false; + } + /// Returns true if the user has selected larger type fonts in the system settings. /// Default implementation returns false. /// diff --git a/CodenameOne/src/com/codename1/ui/Button.java b/CodenameOne/src/com/codename1/ui/Button.java index 3d1549f9a3f..33b0f255c62 100644 --- a/CodenameOne/src/com/codename1/ui/Button.java +++ b/CodenameOne/src/com/codename1/ui/Button.java @@ -992,7 +992,12 @@ public boolean isToggle() { /// /// - `toggle`: the toggle to set public void setToggle(boolean toggle) { + if (this.toggle == toggle) { + return; + } this.toggle = toggle; + accessibilityChanged(com.codename1.ui.accessibility.AccessibilityManager.CHANGE_STRUCTURE + | com.codename1.ui.accessibility.AccessibilityManager.CHANGE_STATE); if (toggle && "CheckBox".equals(getUIID()) || "RadioButton".equals(getUIID())) { setUIID("ToggleButton"); } diff --git a/CodenameOne/src/com/codename1/ui/CheckBox.java b/CodenameOne/src/com/codename1/ui/CheckBox.java index 5144a89f09f..90c2cd94e46 100644 --- a/CodenameOne/src/com/codename1/ui/CheckBox.java +++ b/CodenameOne/src/com/codename1/ui/CheckBox.java @@ -173,6 +173,7 @@ public void setSelected(boolean selected) { this.selected = selected; if (changed) { fireChangeEvent(); + accessibilityChanged(com.codename1.ui.accessibility.AccessibilityManager.CHANGE_STATE); } repaint(); } diff --git a/CodenameOne/src/com/codename1/ui/Component.java b/CodenameOne/src/com/codename1/ui/Component.java index 91e8f48fa9f..2b0aa338db5 100644 --- a/CodenameOne/src/com/codename1/ui/Component.java +++ b/CodenameOne/src/com/codename1/ui/Component.java @@ -40,6 +40,8 @@ import com.codename1.ui.events.StyleListener; import com.codename1.ui.geom.Dimension; import com.codename1.ui.geom.Rectangle; +import com.codename1.ui.accessibility.AccessibilityManager; +import com.codename1.ui.accessibility.AccessibilityNode; import com.codename1.ui.layouts.FlowLayout; import com.codename1.ui.plaf.Border; import com.codename1.ui.plaf.LookAndFeel; @@ -424,6 +426,7 @@ static int rubberBandDecompress(int compressed, int dim) { private EventDispatcher stateChangeListeners; private String tooltip; private String accessibilityText; + private AccessibilityNode semantics; /// The native overlay object. Used in Javascript port for some components so that there is /// an inivisible "native" peer overlaid on the component itself to catch events. E.g. /// TextFields on iOS can't be programmatically focused except through a user-initiated event - @@ -1089,7 +1092,11 @@ public int getX() { /// /// - `x`: the current x coordinate of the components origin public void setX(int x) { + if (bounds.getX() == x) { + return; + } bounds.setX(x); + accessibilityChanged(AccessibilityManager.CHANGE_BOUNDS); if (Form.activePeerCount > 0) { onParentPositionChange(); } @@ -1132,7 +1139,11 @@ public int getY() { /// /// - `y`: the current y coordinate of the components origin public void setY(int y) { + if (bounds.getY() == y) { + return; + } bounds.setY(y); + accessibilityChanged(AccessibilityManager.CHANGE_BOUNDS); if (Form.activePeerCount > 0) { onParentPositionChange(); } @@ -1173,7 +1184,11 @@ public boolean isVisible() { /// /// - `visible`: true if component is visible; otherwise false public void setVisible(boolean visible) { + if (this.visible == visible) { + return; + } this.visible = visible; + accessibilityChanged(AccessibilityManager.CHANGE_STRUCTURE); } void getVisibleRect(Rectangle r, boolean init) { @@ -1363,7 +1378,11 @@ public int getWidth() { /// /// - #setPreferredSize public void setWidth(int width) { + if (bounds.getSize().getWidth() == width) { + return; + } bounds.getSize().setWidth(width); + accessibilityChanged(AccessibilityManager.CHANGE_BOUNDS); } /// Gets the outer width of this component. This is the width of the component including horizontal margins. @@ -1407,7 +1426,11 @@ public int getHeight() { /// /// - #setPreferredSize public void setHeight(int height) { + if (bounds.getSize().getHeight() == height) { + return; + } bounds.getSize().setHeight(height); + accessibilityChanged(AccessibilityManager.CHANGE_BOUNDS); } /// Gets the outer height of this component. This is the height of the component including vertical margins. @@ -2038,6 +2061,7 @@ void setParent(Container parent) { throw new IllegalArgumentException("Attempt to add self as parent"); } this.parent = parent; + accessibilityChanged(AccessibilityManager.CHANGE_STRUCTURE); } /// Gets the "owner" of this component as set by `#setOwner(com.codename1.ui.Component)`. @@ -2329,7 +2353,8 @@ public void setLabelForComponent(Label componentLabel) { void focusGainedInternal() { startComponentLableTicker(); String text = getAccessibilityText(); - if (text != null && text.length() > 0) { + if (text != null && text.length() > 0 + && !Display.getInstance().isAccessibilityTreeSupported()) { announceForAccessibility(text); } } @@ -3556,6 +3581,9 @@ protected void setScrollX(int scrollX) { // component back into view can't recurse infinitely (issue #5305). int oldScrollX = this.scrollX; this.scrollX = scrollXtmp; + if (oldScrollX != scrollXtmp) { + accessibilityChanged(AccessibilityManager.CHANGE_BOUNDS); + } if (scrollListeners != null && oldScrollX != scrollXtmp) { scrollListeners.fireScrollEvent(scrollXtmp, this.scrollY, oldScrollX, this.scrollY); } @@ -3581,6 +3609,7 @@ public int getScrollY() { /// /// - `scrollY`: the Y position of the scrolling protected void setScrollY(int scrollY) { + int oldAccessibilityScrollY = this.scrollY; if (this.scrollY != scrollY) { CodenameOneImplementation ci = Display.impl; @@ -3599,6 +3628,9 @@ protected void setScrollY(int scrollY) { scrollYtmp = Math.min(scrollYtmp, h); scrollYtmp = Math.max(scrollYtmp, 0); } + if (oldAccessibilityScrollY != scrollYtmp) { + accessibilityChanged(AccessibilityManager.CHANGE_BOUNDS); + } if (isScrollableY()) { if (Form.activePeerCount > 0) { onParentPositionChange(); @@ -4188,7 +4220,11 @@ public boolean hasFocus() { /// /// - #requestFocus public void setFocus(boolean focused) { + if (this.focused == focused) { + return; + } this.focused = focused; + accessibilityChanged(AccessibilityManager.CHANGE_FOCUS); } /// Returns the Component Form or null if this Component @@ -8125,6 +8161,7 @@ public void setEnabled(boolean enabled) { return; } this.enabled = enabled; + accessibilityChanged(AccessibilityManager.CHANGE_STATE); repaint(); } @@ -8964,6 +9001,9 @@ public void announceForAccessibility(String text) { /// /// accessibility description or `null` if none public String getAccessibilityText() { + if (semantics != null && semantics.getLabel() != null) { + return semantics.getLabel(); + } if (accessibilityText != null) { return accessibilityText; } @@ -8991,6 +9031,46 @@ public String getAccessibilityText() { /// - `text`: accessibility description public void setAccessibilityText(String text) { this.accessibilityText = text; + if (semantics != null) { + semantics.setLabel(text); + } else { + accessibilityChanged(AccessibilityManager.CHANGE_CONTENT); + } + } + + /// Returns the portable semantic configuration for this component. The same + /// instance is retained for the lifetime of the component. Mutating it updates + /// VoiceOver, TalkBack, UI Automation, AT-SPI, Java accessibility, and web ARIA + /// through the active platform adapter. + /// + /// #### Returns + /// + /// this component's semantic node + public AccessibilityNode getSemantics() { + if (semantics == null) { + semantics = new AccessibilityNode(this); + if (accessibilityText != null) { + semantics.setLabel(accessibilityText); + } + } + return semantics; + } + + /// Alias for {@link #getSemantics()} for APIs that use accessibility-node terminology. + public AccessibilityNode getAccessibilityNode() { + return getSemantics(); + } + + /// Marks this component's semantic representation dirty. Custom components + /// whose accessible value is computed dynamically can call this after state + /// changes that do not pass through a semantic setter. + public void accessibilityChanged() { + accessibilityChanged(AccessibilityManager.CHANGE_ALL); + } + + /// Marks a specific portion of this component's semantic representation dirty. + public void accessibilityChanged(int changeType) { + AccessibilityManager.getInstance().invalidate(this, changeType); } /// #### Returns diff --git a/CodenameOne/src/com/codename1/ui/Display.java b/CodenameOne/src/com/codename1/ui/Display.java index 2960da32e62..8cdce2cf3ec 100644 --- a/CodenameOne/src/com/codename1/ui/Display.java +++ b/CodenameOne/src/com/codename1/ui/Display.java @@ -633,6 +633,22 @@ public void announceForAccessibility(String text) { announceForAccessibility(null, text); } + /// Notifies the native port that the portable semantic tree changed. This is + /// primarily an internal bridge used by the accessibility subsystem. + /// + /// #### Parameters + /// + /// - `changeType`: bit mask of `AccessibilityManager.CHANGE_*` constants + public void accessibilityTreeChanged(int changeType) { + impl.accessibilityTreeChanged(changeType); + } + + /// Returns true when the active port exposes lightweight components through + /// a native virtual accessibility tree. + public boolean isAccessibilityTreeSupported() { + return impl.isAccessibilityTreeSupported(); + } + /// Returns the status of the show during edit flag /// /// #### Returns @@ -1730,6 +1746,9 @@ void setCurrentForm(Form newForm) { lastKeyPressed = 0; previousKeyPressed = 0; newForm.onShowCompletedImpl(); + com.codename1.ui.accessibility.AccessibilityManager.getInstance().invalidate( + newForm, com.codename1.ui.accessibility.AccessibilityManager.CHANGE_STRUCTURE + | com.codename1.ui.accessibility.AccessibilityManager.CHANGE_PANE); } private boolean applyInitialWindowSize(Form form) { diff --git a/CodenameOne/src/com/codename1/ui/Label.java b/CodenameOne/src/com/codename1/ui/Label.java index 4ba6fd7b390..72e6e84cfe2 100644 --- a/CodenameOne/src/com/codename1/ui/Label.java +++ b/CodenameOne/src/com/codename1/ui/Label.java @@ -639,11 +639,15 @@ public String getText() { /// - `text`: the string that the label presents. @Override public void setText(String text) { + String oldText = this.text; widthAtLastCheck = -1; this.text = text; localize(); stringWidthUnselected = -1; setShouldCalcPreferredSize(true); + if (oldText == null ? this.text != null : !oldText.equals(this.text)) { + accessibilityChanged(com.codename1.ui.accessibility.AccessibilityManager.CHANGE_CONTENT); + } repaint(); } diff --git a/CodenameOne/src/com/codename1/ui/List.java b/CodenameOne/src/com/codename1/ui/List.java index 0467aa680da..5980b92ca6c 100644 --- a/CodenameOne/src/com/codename1/ui/List.java +++ b/CodenameOne/src/com/codename1/ui/List.java @@ -447,6 +447,37 @@ public int size() { return model.getSize(); } + /// Returns the bounds of a renderer-backed row for the portable virtual + /// accessibility tree. Bounds are relative to this list. + public Rectangle getAccessibilityItemBounds(int index, Rectangle out) { + if (out == null) { + throw new NullPointerException("out"); + } + if (index < 0 || index >= size()) { + out.setBounds(0, 0, 0, 0); + return out; + } + int width = getWidth() - getStyle().getHorizontalPadding() - getSideGap(); + calculateComponentPosition(index, width, out, getElementSize(false, true), + getElementSize(true, true), index <= getCurrentSelected()); + return out; + } + + /// Returns the accessible name produced by the list renderer for an item. + public String getAccessibilityItemText(int index) { + if (index < 0 || index >= size()) { + return null; + } + T value = model.getItemAt(index); + Component rendererComponent = renderer.getListCellRendererComponent(this, value, index, + index == getSelectedIndex()); + String text = rendererComponent == null ? null : rendererComponent.getAccessibilityText(); + if (text == null || text.length() == 0) { + text = value == null ? null : String.valueOf(value); + } + return text; + } + /// Returns the visual selection during a drag operation, otherwise equivalent to model.getSelectedIndex /// /// #### Returns @@ -515,7 +546,12 @@ public void setSelectedIndex(int index, boolean scrollToSelection) { if (index < 0) { throw new IllegalArgumentException("Selection index is negative:" + index); } + int oldIndex = model.getSelectedIndex(); model.setSelectedIndex(index); + if (oldIndex != index) { + accessibilityChanged(com.codename1.ui.accessibility.AccessibilityManager.CHANGE_STATE + | com.codename1.ui.accessibility.AccessibilityManager.CHANGE_VALUE); + } if (!isInitialized()) { Form f = getComponentForm(); if (f == null) { diff --git a/CodenameOne/src/com/codename1/ui/RadioButton.java b/CodenameOne/src/com/codename1/ui/RadioButton.java index 0b341d68492..07cb36793ed 100644 --- a/CodenameOne/src/com/codename1/ui/RadioButton.java +++ b/CodenameOne/src/com/codename1/ui/RadioButton.java @@ -255,6 +255,7 @@ void setSelectedImpl(boolean selected) { this.selected = selected; if (changed) { fireChangeEvent(); + accessibilityChanged(com.codename1.ui.accessibility.AccessibilityManager.CHANGE_STATE); } repaint(); } diff --git a/CodenameOne/src/com/codename1/ui/Slider.java b/CodenameOne/src/com/codename1/ui/Slider.java index 488b0c8cf20..0ff06ff30f5 100644 --- a/CodenameOne/src/com/codename1/ui/Slider.java +++ b/CodenameOne/src/com/codename1/ui/Slider.java @@ -304,7 +304,11 @@ public int getProgress(ActionEvent evt) { /// thumb sliders) can route their own input through the same value-set + /// repaint pipeline as the built-in handlers. See #1523. protected void setProgressInternal(int value) { + int oldValue = this.value; this.value = value; + if (oldValue != value) { + accessibilityChanged(com.codename1.ui.accessibility.AccessibilityManager.CHANGE_VALUE); + } if (renderValueOnTop || renderPercentageOnTop) { super.setText(formattedValue(value)); } else { diff --git a/CodenameOne/src/com/codename1/ui/Tabs.java b/CodenameOne/src/com/codename1/ui/Tabs.java index e939fff6495..a43c9cf0f9d 100644 --- a/CodenameOne/src/com/codename1/ui/Tabs.java +++ b/CodenameOne/src/com/codename1/ui/Tabs.java @@ -1300,6 +1300,8 @@ public void setSelectedIndex(int index, boolean slideToSelected) { if (index == activeComponent) { return; } + accessibilityChanged(com.codename1.ui.accessibility.AccessibilityManager.CHANGE_STATE + | com.codename1.ui.accessibility.AccessibilityManager.CHANGE_PANE); // Snapshot the current tab bounds *before* we mutate state, so the // animated indicator can tween from where it visibly is to the new // selection's bounds. diff --git a/CodenameOne/src/com/codename1/ui/TextArea.java b/CodenameOne/src/com/codename1/ui/TextArea.java index bebfe7ec53b..aea2cdee7b8 100644 --- a/CodenameOne/src/com/codename1/ui/TextArea.java +++ b/CodenameOne/src/com/codename1/ui/TextArea.java @@ -609,6 +609,8 @@ && textMightGrowByContent(old, text)) { } if (!Objects.equals(text, old)) { fireDataChanged(DataChangedListener.CHANGED, -1); + accessibilityChanged(com.codename1.ui.accessibility.AccessibilityManager.CHANGE_VALUE + | com.codename1.ui.accessibility.AccessibilityManager.CHANGE_CONTENT); } // while native editing we don't need the cursor animations if (Display.getInstance().isNativeInputSupported() && Display.getInstance().isTextEditing(this)) { diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityAction.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityAction.java new file mode 100644 index 00000000000..a0bb01d945d --- /dev/null +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityAction.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2026 Codename One and contributors. All rights reserved. + */ +package com.codename1.ui.accessibility; + +import com.codename1.ui.Component; + +/// An action that assistive technology can invoke on a semantic node. +public final class AccessibilityAction { + public static final String ACTIVATE = "activate"; + public static final String LONG_PRESS = "longPress"; + public static final String INCREMENT = "increment"; + public static final String DECREMENT = "decrement"; + public static final String SET_VALUE = "setValue"; + public static final String SET_TEXT = "setText"; + public static final String FOCUS = "focus"; + public static final String DISMISS = "dismiss"; + public static final String EXPAND = "expand"; + public static final String COLLAPSE = "collapse"; + public static final String SCROLL_FORWARD = "scrollForward"; + public static final String SCROLL_BACKWARD = "scrollBackward"; + public static final String COPY = "copy"; + public static final String CUT = "cut"; + public static final String PASTE = "paste"; + public static final String SHOW_ON_SCREEN = "showOnScreen"; + public static final String SET_SELECTION = "setSelection"; + public static final String MOVE_CURSOR_FORWARD_BY_CHARACTER = "moveCursorForwardByCharacter"; + public static final String MOVE_CURSOR_BACKWARD_BY_CHARACTER = "moveCursorBackwardByCharacter"; + public static final String MOVE_CURSOR_FORWARD_BY_WORD = "moveCursorForwardByWord"; + public static final String MOVE_CURSOR_BACKWARD_BY_WORD = "moveCursorBackwardByWord"; + + /// Handles an accessibility action on the Codename One EDT. + public interface Handler { + boolean perform(Component component, Object argument); + } + + private final String id; + private final String label; + private final Handler handler; + private final boolean enabled; + + public AccessibilityAction(String id, String label, Handler handler) { + this(id, label, handler, true); + } + + public AccessibilityAction(String id, String label, Handler handler, boolean enabled) { + if (id == null || id.length() == 0) { + throw new IllegalArgumentException("Accessibility action id must not be empty"); + } + this.id = id; + this.label = label; + this.handler = handler; + this.enabled = enabled; + } + + public String getId() { return id; } + public String getLabel() { return label; } + public boolean isEnabled() { return enabled; } + + public boolean perform(Component component, Object argument) { + return enabled && handler != null && handler.perform(component, argument); + } +} diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityAssertions.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityAssertions.java new file mode 100644 index 00000000000..139dab70908 --- /dev/null +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityAssertions.java @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2026 Codename One and contributors. All rights reserved. + */ +package com.codename1.ui.accessibility; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/// Automated semantic-tree assertions suitable for unit tests and CI. +public final class AccessibilityAssertions { + private AccessibilityAssertions() { + } + + public static List audit(AccessibilityTreeSnapshot tree) { + List issues = new ArrayList(); + Set identifiers = new HashSet(); + for (AccessibilityNodeSnapshot node : tree.getNodes().values()) { + auditNode(tree, node, identifiers, issues); + } + for (Long root : tree.getRootIds()) { + detectCycle(tree, root.longValue(), new HashSet(), new HashSet(), issues); + } + return issues; + } + + public static void assertNoErrors(AccessibilityTreeSnapshot tree) { + List issues = audit(tree); + StringBuilder errors = new StringBuilder(); + for (AccessibilityIssue issue : issues) { + if (issue.getSeverity() == AccessibilityIssue.Severity.ERROR) { + if (errors.length() > 0) errors.append('\n'); + errors.append(issue.toString()); + } + } + if (errors.length() > 0) throw new AssertionError(errors.toString()); + } + + public static void assertNoUnlabeledInteractiveNodes(AccessibilityTreeSnapshot tree) { + StringBuilder errors = new StringBuilder(); + for (AccessibilityNodeSnapshot node : tree.getNodes().values()) { + if (node.isFocusable() && empty(node.getLabel()) && empty(node.getValue())) { + if (errors.length() > 0) errors.append('\n'); + errors.append("Interactive node ").append(node.getId()).append(" (") + .append(node.getRole()).append(") has no accessible name"); + } + } + if (errors.length() > 0) throw new AssertionError(errors.toString()); + } + + private static void auditNode(AccessibilityTreeSnapshot tree, AccessibilityNodeSnapshot node, + Set identifiers, List issues) { + if (node.isFocusable() && empty(node.getLabel()) && empty(node.getValue())) { + error(issues, "unlabeled-interactive", "Interactive nodes require a label or value", node); + } + if (node.getRange() != null && !node.getRange().isValid()) { + error(issues, "invalid-range", "Range must satisfy min <= current <= max and step >= 0", node); + } + if (node.getRole() == AccessibilityRole.HEADING && node.getHeadingLevel() == 0) { + error(issues, "invalid-heading-level", "Heading levels are 1-based", node); + } + if (node.getChecked() != AccessibilityCheckedState.UNSPECIFIED + && node.getRole() != AccessibilityRole.CHECKBOX + && node.getRole() != AccessibilityRole.RADIO_BUTTON + && node.getRole() != AccessibilityRole.SWITCH + && node.getRole() != AccessibilityRole.TREE_ITEM + && node.getRole() != AccessibilityRole.MENU_ITEM) { + warning(issues, "checked-role", "Checked state is unusual for this role", node); + } + if (node.getExpanded() != null && node.getRole() != AccessibilityRole.TREE_ITEM + && node.getRole() != AccessibilityRole.BUTTON && node.getRole() != AccessibilityRole.MENU_ITEM + && node.getRole() != AccessibilityRole.COMBO_BOX && node.getRole() != AccessibilityRole.GENERIC) { + warning(issues, "expanded-role", "Expanded state is unusual for this role", node); + } + if (node.getCollectionItemInfo() != null) { + AccessibilityCollectionItemInfo item = node.getCollectionItemInfo(); + if (item.getPositionInSet() == 0 || item.getSetSize() == 0 + || item.getPositionInSet() > 0 && item.getSetSize() > 0 + && item.getPositionInSet() > item.getSetSize()) { + error(issues, "invalid-collection-position", "Collection position and size must be 1-based and consistent", node); + } + } + if (node.getParentId() >= 0 && tree.getNode(node.getParentId()) == null) { + error(issues, "missing-parent", "Semantic parent does not exist", node); + } + if (node.getIdentifier() != null && !identifiers.add(node.getIdentifier())) { + error(issues, "duplicate-identifier", "Accessibility identifiers must be unique", node); + } + if (node.getBounds().getWidth() <= 0 || node.getBounds().getHeight() <= 0) { + warning(issues, "empty-bounds", "Node is fully clipped or has empty bounds", node); + } + Set actions = new HashSet(); + for (AccessibilityAction action : node.getActions()) { + if (!actions.add(action.getId())) error(issues, "duplicate-action", "Action ids must be unique per node", node); + if (!isStandardAction(action.getId()) && empty(action.getLabel())) { + error(issues, "unlabeled-custom-action", "Custom accessibility actions require localized labels", node); + } + } + if ((node.getRole() == AccessibilityRole.DIALOG || node.getRole() == AccessibilityRole.ALERT) + && empty(node.getLabel()) && empty(node.getPaneTitle())) { + error(issues, "unnamed-dialog", "Dialogs require a label or pane title", node); + } + } + + private static void detectCycle(AccessibilityTreeSnapshot tree, long id, Set visiting, + Set visited, List issues) { + Long boxed = Long.valueOf(id); + if (visited.contains(boxed)) return; + if (!visiting.add(boxed)) { + AccessibilityNodeSnapshot node = tree.getNode(id); + if (node != null) error(issues, "tree-cycle", "Semantic tree contains a cycle", node); + return; + } + AccessibilityNodeSnapshot node = tree.getNode(id); + if (node != null) { + for (Long child : node.getChildIds()) detectCycle(tree, child.longValue(), visiting, visited, issues); + } + visiting.remove(boxed); + visited.add(boxed); + } + + private static boolean isStandardAction(String id) { + return AccessibilityAction.ACTIVATE.equals(id) || AccessibilityAction.LONG_PRESS.equals(id) + || AccessibilityAction.INCREMENT.equals(id) || AccessibilityAction.DECREMENT.equals(id) + || AccessibilityAction.SET_VALUE.equals(id) || AccessibilityAction.SET_TEXT.equals(id) + || AccessibilityAction.FOCUS.equals(id) || AccessibilityAction.DISMISS.equals(id) + || AccessibilityAction.EXPAND.equals(id) || AccessibilityAction.COLLAPSE.equals(id) + || AccessibilityAction.SCROLL_FORWARD.equals(id) || AccessibilityAction.SCROLL_BACKWARD.equals(id) + || AccessibilityAction.COPY.equals(id) || AccessibilityAction.CUT.equals(id) + || AccessibilityAction.PASTE.equals(id) || AccessibilityAction.SHOW_ON_SCREEN.equals(id) + || AccessibilityAction.SET_SELECTION.equals(id) + || AccessibilityAction.MOVE_CURSOR_FORWARD_BY_CHARACTER.equals(id) + || AccessibilityAction.MOVE_CURSOR_BACKWARD_BY_CHARACTER.equals(id) + || AccessibilityAction.MOVE_CURSOR_FORWARD_BY_WORD.equals(id) + || AccessibilityAction.MOVE_CURSOR_BACKWARD_BY_WORD.equals(id); + } + + private static void error(List issues, String code, String message, + AccessibilityNodeSnapshot node) { + issues.add(new AccessibilityIssue(AccessibilityIssue.Severity.ERROR, code, message, node.getId())); + } + + private static void warning(List issues, String code, String message, + AccessibilityNodeSnapshot node) { + issues.add(new AccessibilityIssue(AccessibilityIssue.Severity.WARNING, code, message, node.getId())); + } + + private static boolean empty(String value) { return value == null || value.length() == 0; } +} diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityCheckedState.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityCheckedState.java new file mode 100644 index 00000000000..4b99c355b7a --- /dev/null +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityCheckedState.java @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2026 Codename One and contributors. All rights reserved. + */ +package com.codename1.ui.accessibility; + +/// Checked state for checkable semantic nodes. +public enum AccessibilityCheckedState { + UNSPECIFIED, + UNCHECKED, + CHECKED, + MIXED +} diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityChildProvider.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityChildProvider.java new file mode 100644 index 00000000000..a4cea03e026 --- /dev/null +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityChildProvider.java @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2026 Codename One and contributors. All rights reserved. + */ +package com.codename1.ui.accessibility; + +import com.codename1.ui.Component; +import java.util.List; + +/// Supplies semantic children that are not represented by persistent lightweight +/// components, such as renderer-backed list rows and table cells. +public interface AccessibilityChildProvider { + List getAccessibilityChildren(Component host); +} diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityCollectionInfo.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityCollectionInfo.java new file mode 100644 index 00000000000..e5d4b221a38 --- /dev/null +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityCollectionInfo.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2026 Codename One and contributors. All rights reserved. + */ +package com.codename1.ui.accessibility; + +/// Metadata describing a list, grid, table, or other collection. +public final class AccessibilityCollectionInfo { + public static final int SELECTION_NONE = 0; + public static final int SELECTION_SINGLE = 1; + public static final int SELECTION_MULTIPLE = 2; + + private final int rowCount; + private final int columnCount; + private final boolean hierarchical; + private final int selectionMode; + + public AccessibilityCollectionInfo(int rowCount, int columnCount) { + this(rowCount, columnCount, false, SELECTION_NONE); + } + + public AccessibilityCollectionInfo(int rowCount, int columnCount, boolean hierarchical, int selectionMode) { + this.rowCount = rowCount; + this.columnCount = columnCount; + this.hierarchical = hierarchical; + this.selectionMode = selectionMode; + } + + public int getRowCount() { + return rowCount; + } + + public int getColumnCount() { + return columnCount; + } + + public boolean isHierarchical() { + return hierarchical; + } + + public int getSelectionMode() { + return selectionMode; + } +} diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityCollectionItemInfo.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityCollectionItemInfo.java new file mode 100644 index 00000000000..0ea48ccfbbc --- /dev/null +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityCollectionItemInfo.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2026 Codename One and contributors. All rights reserved. + */ +package com.codename1.ui.accessibility; + +/// Position and span metadata for an item in a semantic collection. +public final class AccessibilityCollectionItemInfo { + private final int rowIndex; + private final int rowSpan; + private final int columnIndex; + private final int columnSpan; + private final int positionInSet; + private final int setSize; + private final int level; + private final boolean heading; + + public AccessibilityCollectionItemInfo(int rowIndex, int columnIndex) { + this(rowIndex, 1, columnIndex, 1, -1, -1, -1, false); + } + + public AccessibilityCollectionItemInfo(int rowIndex, int rowSpan, int columnIndex, int columnSpan, + int positionInSet, int setSize, int level, boolean heading) { + this.rowIndex = rowIndex; + this.rowSpan = rowSpan; + this.columnIndex = columnIndex; + this.columnSpan = columnSpan; + this.positionInSet = positionInSet; + this.setSize = setSize; + this.level = level; + this.heading = heading; + } + + public int getRowIndex() { return rowIndex; } + public int getRowSpan() { return rowSpan; } + public int getColumnIndex() { return columnIndex; } + public int getColumnSpan() { return columnSpan; } + public int getPositionInSet() { return positionInSet; } + public int getSetSize() { return setSize; } + public int getLevel() { return level; } + public boolean isHeading() { return heading; } +} diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityGrouping.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityGrouping.java new file mode 100644 index 00000000000..96c767ea489 --- /dev/null +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityGrouping.java @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2026 Codename One and contributors. All rights reserved. + */ +package com.codename1.ui.accessibility; + +/// Controls how a component and its descendants participate in the semantic tree. +public enum AccessibilityGrouping { + /// Infer exposure from the role, content, actions, and component type. + AUTO, + /// Expose this node and omit all semantic descendants. + LEAF, + /// Expose this node and its semantic descendants. + GROUP, + /// Expose a single node whose label and description include its descendants. + MERGE_DESCENDANTS, + /// Omit this node but promote its semantic children. + EXCLUDE, + /// Omit this node and its entire semantic subtree. + EXCLUDE_SUBTREE +} diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityInspector.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityInspector.java new file mode 100644 index 00000000000..cea6ae8c0fb --- /dev/null +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityInspector.java @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2026 Codename One and contributors. All rights reserved. + */ +package com.codename1.ui.accessibility; + +import com.codename1.ui.Form; + +/// Read-only semantic-tree inspection entry point for tests and developer tools. +public final class AccessibilityInspector { + private AccessibilityInspector() { + } + + public static AccessibilityTreeSnapshot snapshot(Form form) { + return AccessibilityManager.getInstance().getSnapshot(form); + } + + public static AccessibilityTreeSnapshot currentSnapshot() { + return AccessibilityManager.getInstance().getCurrentSnapshot(); + } +} diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityIssue.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityIssue.java new file mode 100644 index 00000000000..6251e00703b --- /dev/null +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityIssue.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2026 Codename One and contributors. All rights reserved. + */ +package com.codename1.ui.accessibility; + +/// A deterministic accessibility audit finding. +public final class AccessibilityIssue { + public enum Severity { ERROR, WARNING } + + private final Severity severity; + private final String code; + private final String message; + private final long nodeId; + + public AccessibilityIssue(Severity severity, String code, String message, long nodeId) { + this.severity = severity; + this.code = code; + this.message = message; + this.nodeId = nodeId; + } + + public Severity getSeverity() { return severity; } + public String getCode() { return code; } + public String getMessage() { return message; } + public long getNodeId() { return nodeId; } + + @Override + public String toString() { + return severity + " " + code + " [node " + nodeId + "]: " + message; + } +} diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityLiveRegion.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityLiveRegion.java new file mode 100644 index 00000000000..46ac6b73350 --- /dev/null +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityLiveRegion.java @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2026 Codename One and contributors. All rights reserved. + */ +package com.codename1.ui.accessibility; + +/// How changes to a semantic node should be announced without moving focus. +public enum AccessibilityLiveRegion { + OFF, + POLITE, + ASSERTIVE +} diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityManager.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityManager.java new file mode 100644 index 00000000000..476e826c801 --- /dev/null +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityManager.java @@ -0,0 +1,669 @@ +/* + * Copyright (c) 2026 Codename One and contributors. All rights reserved. + */ +package com.codename1.ui.accessibility; + +import com.codename1.ui.Button; +import com.codename1.ui.CheckBox; +import com.codename1.ui.Component; +import com.codename1.ui.Container; +import com.codename1.ui.Dialog; +import com.codename1.ui.Display; +import com.codename1.ui.Form; +import com.codename1.ui.Label; +import com.codename1.ui.RadioButton; +import com.codename1.ui.Slider; +import com.codename1.ui.Tabs; +import com.codename1.ui.TextArea; +import com.codename1.ui.TextField; +import com.codename1.ui.geom.Rectangle; +import com.codename1.ui.table.Table; +import com.codename1.ui.util.WeakHashMap; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +/// Builds, caches, diffs, and dispatches actions for the portable semantic tree. +/// +/// The tree is always constructed on the Codename One EDT. Native ports read the +/// last immutable snapshot and post actions through {@link #performAction(long, String, Object)}, +/// so native accessibility threads never synchronously enter application code. +public final class AccessibilityManager { + public static final int CHANGE_STRUCTURE = 1; + public static final int CHANGE_CONTENT = 2; + public static final int CHANGE_STATE = 4; + public static final int CHANGE_VALUE = 8; + public static final int CHANGE_BOUNDS = 16; + public static final int CHANGE_FOCUS = 32; + public static final int CHANGE_ACTIONS = 64; + public static final int CHANGE_LIVE_REGION = 128; + public static final int CHANGE_PANE = 256; + public static final int CHANGE_ALL = 0x7fffffff; + + private static final AccessibilityManager INSTANCE = new AccessibilityManager(); + private final Map componentIds = new WeakHashMap(); + private final Map virtualIds = new HashMap(); + private long nextId = 1; + private long generation; + private boolean dirty = true; + private boolean refreshScheduled; + private int pendingChanges = CHANGE_ALL; + private Form snapshotForm; + private AccessibilityTreeSnapshot snapshot = new AccessibilityTreeSnapshot(0, + Collections.emptyList(), Collections.emptyMap()); + + private AccessibilityManager() { + } + + public static AccessibilityManager getInstance() { + return INSTANCE; + } + + public synchronized void invalidate(Component component, int changeType) { + dirty = true; + pendingChanges |= changeType; + try { + if (!refreshScheduled) { + refreshScheduled = true; + Display.getInstance().callSerially(new Runnable() { + public void run() { + int changes; + synchronized (AccessibilityManager.this) { + changes = pendingChanges; + } + getSnapshot(Display.getInstance().getCurrent()); + synchronized (AccessibilityManager.this) { + refreshScheduled = false; + } + Display.getInstance().accessibilityTreeChanged(changes); + } + }); + } + } catch (Throwable ignored) { + // Display may not be initialized yet while an application constructs its first form. + refreshScheduled = false; + } + } + + public void invalidateAll() { + invalidate(null, CHANGE_ALL); + } + + public AccessibilityTreeSnapshot getCurrentSnapshot() { + synchronized (this) { + if (dirty && !Display.getInstance().isEdt()) return snapshot; + } + return getSnapshot(Display.getInstance().getCurrent()); + } + + public synchronized AccessibilityTreeSnapshot getSnapshot(Form form) { + if (!dirty && form == snapshotForm) return snapshot; + if (form == null) { + snapshot = new AccessibilityTreeSnapshot(++generation, Collections.emptyList(), + Collections.emptyMap()); + snapshotForm = null; + dirty = false; + pendingChanges = 0; + return snapshot; + } + + List roots = new ArrayList(); + resolveComponent(form, roots); + sortTree(roots); + List rootIds = new ArrayList(); + LinkedHashMap nodes = new LinkedHashMap(); + freeze(roots, -1, rootIds, nodes); + snapshot = new AccessibilityTreeSnapshot(++generation, rootIds, nodes); + snapshotForm = form; + dirty = false; + pendingChanges = 0; + return snapshot; + } + + public synchronized int getPendingChanges() { + return pendingChanges; + } + + public boolean performAction(long nodeId, String actionId, final Object argument) { + final AccessibilityNodeSnapshot node; + final AccessibilityAction action; + synchronized (this) { + node = snapshot.getNode(nodeId); + action = node == null ? null : node.getAction(actionId); + } + if (node == null || action == null || !action.isEnabled()) return false; + Display.getInstance().callSerially(new Runnable() { + public void run() { + action.perform(node.getComponent(), argument); + invalidate(node.getComponent(), CHANGE_STATE | CHANGE_VALUE | CHANGE_CONTENT); + } + }); + return true; + } + + /// Dispatches an action selected by a native bridge that can transport only an integer token. + public boolean performActionByHash(long nodeId, int actionIdHash, Object argument) { + AccessibilityNodeSnapshot node; + synchronized (this) { + node = snapshot.getNode(nodeId); + } + if (node == null) return false; + for (AccessibilityAction action : node.getActions()) { + if (action.getId().hashCode() == actionIdHash) { + return performAction(nodeId, action.getId(), argument); + } + } + return false; + } + + private long idFor(Component component) { + Long id = componentIds.get(component); + if (id == null) { + id = Long.valueOf(nextId++); + componentIds.put(component, id); + } + return id.longValue(); + } + + private long idForVirtual(Component host, String path) { + String key = idFor(host) + ":" + path; + Long id = virtualIds.get(key); + if (id == null) { + id = Long.valueOf(nextId++); + virtualIds.put(key, id); + } + return id.longValue(); + } + + private void resolveComponent(Component component, List destination) { + if (component == null || (!(component instanceof Form) && !component.isVisible()) + || component.isHidden(true)) return; + AccessibilityNode config = component.getSemantics(); + AccessibilityGrouping grouping = config.getGrouping(); + if (grouping == AccessibilityGrouping.EXCLUDE_SUBTREE) return; + + BuildNode node = buildComponentNode(component, config); + List children = new ArrayList(); + if (grouping != AccessibilityGrouping.LEAF && component instanceof Container) { + Container container = (Container)component; + for (int i = 0; i < container.getComponentCount(); i++) { + resolveComponent(container.getComponentAt(i), children); + } + } + if (grouping != AccessibilityGrouping.LEAF) { + addVirtualChildren(component, config, node.id, "custom", children); + if (component instanceof com.codename1.ui.List) { + addListChildren((com.codename1.ui.List)component, node.id, children); + } + } + + boolean expose = shouldExpose(component, config, node); + if (grouping == AccessibilityGrouping.EXCLUDE) expose = false; + if (grouping == AccessibilityGrouping.MERGE_DESCENDANTS) { + String merged = collectLabels(children); + if (isEmpty(node.builder.label)) node.builder.label = merged; + else if (!isEmpty(merged)) node.builder.description = join(node.builder.description, merged); + children.clear(); + expose = true; + } + if (grouping == AccessibilityGrouping.LEAF || grouping == AccessibilityGrouping.GROUP) expose = true; + + if (expose) { + node.children.addAll(children); + destination.add(node); + } else { + destination.addAll(children); + } + } + + private BuildNode buildComponentNode(final Component component, AccessibilityNode config) { + BuildNode out = new BuildNode(); + out.id = idFor(component); + out.builder.id = out.id; + out.builder.component = component; + out.builder.identifier = config.getIdentifier(); + out.builder.label = firstNonEmpty(config.getLabel(), component.getAccessibilityText()); + out.builder.hint = config.getHint(); + out.builder.description = config.getDescription(); + out.builder.value = config.getValue(); + out.builder.validationError = config.getValidationError(); + out.builder.paneTitle = config.getPaneTitle(); + out.builder.roleDescription = config.getRoleDescription(); + out.builder.role = config.getRole() == AccessibilityRole.NONE ? inferRole(component) : config.getRole(); + out.builder.checked = inferChecked(component, config); + out.builder.liveRegion = config.getLiveRegion(); + out.builder.range = config.getRange() == null ? inferRange(component) : config.getRange(); + out.builder.collectionInfo = config.getCollectionInfo() == null ? inferCollection(component) : config.getCollectionInfo(); + out.builder.collectionItemInfo = config.getCollectionItemInfo() == null + ? inferCollectionItem(component) : config.getCollectionItemInfo(); + out.builder.bounds = componentBounds(component); + out.builder.selected = config.getSelected() == null ? inferSelected(component) : config.getSelected(); + out.builder.expanded = config.getExpanded(); + out.builder.enabled = config.getEnabled() == null ? Boolean.valueOf(component.isEnabled()) : config.getEnabled(); + out.builder.invalid = config.getInvalid(); + out.builder.busy = config.getBusy(); + out.builder.readOnly = config.getReadOnly() == null ? inferReadOnly(component) : config.getReadOnly(); + out.builder.required = config.getRequired(); + out.builder.multiline = config.getMultiline() == null ? inferMultiline(component) : config.getMultiline(); + out.builder.obscured = config.getObscured() == null ? inferObscured(component) : config.getObscured(); + out.builder.pressed = config.getPressed(); + out.builder.current = config.getCurrent(); + out.builder.modal = config.isModal() || component instanceof Dialog; + out.builder.focusable = component.isFocusable() || isInteractiveRole(out.builder.role); + out.builder.focused = component.hasFocus(); + out.builder.headingLevel = config.getHeadingLevel(); + out.builder.sortKey = config.getSortKey(); + out.builder.traversalBefore = config.getTraversalBefore(); + out.builder.traversalAfter = config.getTraversalAfter(); + out.builder.actions.addAll(config.getActions()); + addDefaultActions(component, out.builder); + if (component instanceof Form && isEmpty(out.builder.paneTitle)) { + out.builder.paneTitle = ((Form)component).getTitle(); + } + out.component = component; + return out; + } + + private void addVirtualChildren(Component host, AccessibilityNode config, long hostId, + String path, List destination) { + List virtual = new ArrayList(); + virtual.addAll(config.getChildren()); + if (config.getChildProvider() != null) { + List provided = config.getChildProvider().getAccessibilityChildren(host); + if (provided != null) virtual.addAll(provided); + } + for (int i = 0; i < virtual.size(); i++) { + AccessibilityNode child = virtual.get(i); + String key = child.getVirtualKey(); + if (isEmpty(key)) key = "index-" + i; + BuildNode resolved = buildVirtualNode(host, child, path + "/" + key); + addVirtualChildren(host, child, resolved.id, path + "/" + key, resolved.children); + destination.add(resolved); + } + } + + private BuildNode buildVirtualNode(Component host, AccessibilityNode config, String path) { + BuildNode out = new BuildNode(); + out.id = idForVirtual(host, path); + out.builder.id = out.id; + out.builder.component = host; + out.builder.virtualKey = config.getVirtualKey(); + out.builder.identifier = config.getIdentifier(); + out.builder.label = config.getLabel(); + out.builder.hint = config.getHint(); + out.builder.description = config.getDescription(); + out.builder.value = config.getValue(); + out.builder.validationError = config.getValidationError(); + out.builder.paneTitle = config.getPaneTitle(); + out.builder.roleDescription = config.getRoleDescription(); + out.builder.role = config.getRole() == AccessibilityRole.NONE ? AccessibilityRole.GENERIC : config.getRole(); + out.builder.checked = config.getChecked(); + out.builder.liveRegion = config.getLiveRegion(); + out.builder.range = config.getRange(); + out.builder.collectionInfo = config.getCollectionInfo(); + out.builder.collectionItemInfo = config.getCollectionItemInfo(); + out.builder.bounds = virtualBounds(host, config.getBounds()); + out.builder.selected = config.getSelected(); + out.builder.expanded = config.getExpanded(); + out.builder.enabled = config.getEnabled() == null ? Boolean.valueOf(host.isEnabled()) : config.getEnabled(); + out.builder.invalid = config.getInvalid(); + out.builder.busy = config.getBusy(); + out.builder.readOnly = config.getReadOnly(); + out.builder.required = config.getRequired(); + out.builder.multiline = config.getMultiline(); + out.builder.obscured = config.getObscured(); + out.builder.pressed = config.getPressed(); + out.builder.current = config.getCurrent(); + out.builder.modal = config.isModal(); + out.builder.focusable = !config.getActions().isEmpty() || isInteractiveRole(out.builder.role); + out.builder.headingLevel = config.getHeadingLevel(); + out.builder.sortKey = config.getSortKey(); + out.builder.actions.addAll(config.getActions()); + out.component = host; + return out; + } + + private void addListChildren(final com.codename1.ui.List list, long hostId, List destination) { + int size = list.size(); + for (int i = 0; i < size; i++) { + final int index = i; + AccessibilityNode item = new AccessibilityNode("item-" + i) + .setRole(AccessibilityRole.LIST_ITEM) + .setLabel(list.getAccessibilityItemText(i)) + .setSelected(Boolean.valueOf(i == list.getSelectedIndex())) + .setCollectionItemInfo(new AccessibilityCollectionItemInfo(i, 1, 0, 1, + i + 1, size, 1, false)) + .setBounds(list.getAccessibilityItemBounds(i, new Rectangle())) + .addAction(new AccessibilityAction(AccessibilityAction.ACTIVATE, null, + new AccessibilityAction.Handler() { + public boolean perform(Component component, Object argument) { + if (!list.isEnabled()) return false; + list.setSelectedIndex(index); + list.keyReleased(Display.getInstance().getKeyCode(Display.GAME_FIRE)); + return true; + } + })); + destination.add(buildVirtualNode(list, item, "list/item-" + i)); + } + } + + private void addDefaultActions(final Component component, AccessibilityNodeSnapshot.Builder builder) { + if (component.isFocusable() && !hasAction(builder.actions, AccessibilityAction.FOCUS)) { + builder.actions.add(new AccessibilityAction(AccessibilityAction.FOCUS, null, + new AccessibilityAction.Handler() { + public boolean perform(Component source, Object argument) { + if (!source.isEnabled()) return false; + source.requestFocus(); + return true; + } + })); + } + if (component instanceof Button && !hasAction(builder.actions, AccessibilityAction.ACTIVATE)) { + builder.actions.add(new AccessibilityAction(AccessibilityAction.ACTIVATE, null, + new AccessibilityAction.Handler() { + public boolean perform(Component source, Object argument) { + if (!source.isEnabled()) return false; + source.keyReleased(Display.getInstance().getKeyCode(Display.GAME_FIRE)); + return true; + } + })); + } + if (component instanceof Slider) { + final Slider slider = (Slider)component; + if (slider.isEditable() && !hasAction(builder.actions, AccessibilityAction.INCREMENT)) { + builder.actions.add(new AccessibilityAction(AccessibilityAction.INCREMENT, null, + new AccessibilityAction.Handler() { + public boolean perform(Component source, Object argument) { + slider.setProgress(Math.min(slider.getMaxValue(), slider.getProgress() + Math.max(1, slider.getIncrements()))); + return true; + } + })); + } + if (slider.isEditable() && !hasAction(builder.actions, AccessibilityAction.DECREMENT)) { + builder.actions.add(new AccessibilityAction(AccessibilityAction.DECREMENT, null, + new AccessibilityAction.Handler() { + public boolean perform(Component source, Object argument) { + slider.setProgress(Math.max(slider.getMinValue(), slider.getProgress() - Math.max(1, slider.getIncrements()))); + return true; + } + })); + } + } + if (component instanceof TextArea) { + final TextArea text = (TextArea)component; + if (!hasAction(builder.actions, AccessibilityAction.FOCUS)) { + builder.actions.add(new AccessibilityAction(AccessibilityAction.FOCUS, null, + new AccessibilityAction.Handler() { + public boolean perform(Component source, Object argument) { + source.requestFocus(); + return true; + } + })); + } + if (text.isEditable() && !hasAction(builder.actions, AccessibilityAction.SET_TEXT)) { + builder.actions.add(new AccessibilityAction(AccessibilityAction.SET_TEXT, null, + new AccessibilityAction.Handler() { + public boolean perform(Component source, Object argument) { + if (!(argument instanceof String)) return false; + text.setText((String)argument); + return true; + } + })); + } + } + } + + private AccessibilityRole inferRole(Component component) { + if (component.getParent() instanceof Table) { + return ((Table)component.getParent()).getCellRow(component) < 0 + ? AccessibilityRole.COLUMN_HEADER : AccessibilityRole.CELL; + } + Tabs tabOwner = tabPanelOwner(component); + if (tabOwner != null) return AccessibilityRole.TAB_PANEL; + if (component instanceof Dialog) return AccessibilityRole.DIALOG; + if (component instanceof RadioButton) return AccessibilityRole.RADIO_BUTTON; + if (component instanceof CheckBox) return AccessibilityRole.CHECKBOX; + if (component instanceof Button) { + if (isTabButton((Button)component)) return AccessibilityRole.TAB; + return ((Button)component).isToggle() ? AccessibilityRole.TOGGLE_BUTTON : AccessibilityRole.BUTTON; + } + if (component instanceof Slider) return ((Slider)component).isEditable() ? AccessibilityRole.SLIDER : AccessibilityRole.PROGRESS_BAR; + if (component instanceof TextField) return AccessibilityRole.TEXT_FIELD; + if (component instanceof TextArea) return AccessibilityRole.TEXT_FIELD; + if (component instanceof com.codename1.ui.List) return AccessibilityRole.LIST; + if (component instanceof Table) return AccessibilityRole.GRID; + if (component instanceof Tabs) return AccessibilityRole.TAB_LIST; + if (component instanceof Form) return AccessibilityRole.GENERIC; + if (component instanceof Label) return AccessibilityRole.STATIC_TEXT; + return AccessibilityRole.NONE; + } + + private boolean isTabButton(Button button) { + Container parent = button.getParent(); + while (parent != null) { + Container owner = parent.getParent(); + if (owner instanceof Tabs && ((Tabs)owner).getTabsContainer() == parent) return true; + parent = parent.getParent(); + } + return false; + } + + private AccessibilityCheckedState inferChecked(Component component, AccessibilityNode config) { + if (config.getChecked() != AccessibilityCheckedState.UNSPECIFIED) return config.getChecked(); + if (component instanceof CheckBox || component instanceof RadioButton) { + return ((Button)component).isSelected() ? AccessibilityCheckedState.CHECKED : AccessibilityCheckedState.UNCHECKED; + } + return AccessibilityCheckedState.UNSPECIFIED; + } + + private Boolean inferSelected(Component component) { + if (component instanceof Button && (((Button)component).isToggle() || isTabButton((Button)component))) { + return Boolean.valueOf(((Button)component).isSelected()); + } + Tabs tabOwner = tabPanelOwner(component); + if (tabOwner != null) return Boolean.valueOf(tabOwner.getSelectedComponent() == component); + return null; + } + + private Tabs tabPanelOwner(Component component) { + Container parent = component.getParent(); + if (parent != null && parent.getParent() instanceof Tabs) { + Tabs tabs = (Tabs)parent.getParent(); + if (tabs.getContentPane() == parent) return tabs; + } + return null; + } + + private AccessibilityRange inferRange(Component component) { + if (component instanceof Slider) { + Slider slider = (Slider)component; + return new AccessibilityRange(slider.getMinValue(), slider.getMaxValue(), slider.getProgress(), slider.getIncrements(), null); + } + return null; + } + + private AccessibilityCollectionInfo inferCollection(Component component) { + if (component instanceof com.codename1.ui.List) { + return new AccessibilityCollectionInfo(((com.codename1.ui.List)component).size(), 1, + false, AccessibilityCollectionInfo.SELECTION_SINGLE); + } + if (component instanceof Table) { + Table table = (Table)component; + return new AccessibilityCollectionInfo(table.getModel().getRowCount(), table.getModel().getColumnCount(), + false, AccessibilityCollectionInfo.SELECTION_SINGLE); + } + if (component instanceof Tabs) { + return new AccessibilityCollectionInfo(1, ((Tabs)component).getTabCount(), false, + AccessibilityCollectionInfo.SELECTION_SINGLE); + } + return null; + } + + private AccessibilityCollectionItemInfo inferCollectionItem(Component component) { + if (component.getParent() instanceof Table) { + Table table = (Table)component.getParent(); + int sourceRow = table.getCellRow(component); + int row = sourceRow < 0 ? 0 : sourceRow + (table.isIncludeHeader() ? 1 : 0); + int column = table.getCellColumn(component); + return new AccessibilityCollectionItemInfo(row, 1, column, 1, column + 1, + table.getModel().getColumnCount(), 1, sourceRow < 0); + } + return null; + } + + private Boolean inferReadOnly(Component component) { + return component instanceof TextArea ? Boolean.valueOf(!((TextArea)component).isEditable()) : null; + } + + private Boolean inferMultiline(Component component) { + return component instanceof TextArea ? Boolean.valueOf(!(component instanceof TextField) || ((TextArea)component).getRows() > 1) : null; + } + + private Boolean inferObscured(Component component) { + return component instanceof TextArea ? Boolean.valueOf((((TextArea)component).getConstraint() & TextArea.PASSWORD) != 0) : null; + } + + private boolean shouldExpose(Component component, AccessibilityNode config, BuildNode node) { + if (component instanceof Form) return true; + if (config.hasExplicitConfiguration()) return true; + return node.builder.role != AccessibilityRole.NONE && (!isEmpty(node.builder.label) + || !isEmpty(node.builder.value) || node.builder.focusable || !node.builder.actions.isEmpty() + || node.builder.collectionInfo != null || node.builder.range != null); + } + + private Rectangle componentBounds(Component component) { + Rectangle bounds = new Rectangle(component.getAbsoluteX() + component.getScrollX(), + component.getAbsoluteY() + component.getScrollY(), component.getWidth(), component.getHeight()); + Container parent = component.getParent(); + while (parent != null && bounds.getWidth() > 0 && bounds.getHeight() > 0) { + Rectangle clip = new Rectangle(parent.getAbsoluteX() + parent.getScrollX(), + parent.getAbsoluteY() + parent.getScrollY(), parent.getWidth(), parent.getHeight()); + intersect(bounds, clip); + parent = parent.getParent(); + } + return bounds; + } + + private Rectangle virtualBounds(Component host, Rectangle relative) { + if (relative == null) return componentBounds(host); + Rectangle bounds = new Rectangle(host.getAbsoluteX() + host.getScrollX() + relative.getX(), + host.getAbsoluteY() + host.getScrollY() + relative.getY(), relative.getWidth(), relative.getHeight()); + intersect(bounds, componentBounds(host)); + return bounds; + } + + private void intersect(Rectangle target, Rectangle clip) { + int x1 = Math.max(target.getX(), clip.getX()); + int y1 = Math.max(target.getY(), clip.getY()); + int x2 = Math.min(target.getX() + target.getWidth(), clip.getX() + clip.getWidth()); + int y2 = Math.min(target.getY() + target.getHeight(), clip.getY() + clip.getHeight()); + target.setBounds(x1, y1, Math.max(0, x2 - x1), Math.max(0, y2 - y1)); + } + + private void sortTree(List nodes) { + Collections.sort(nodes, new Comparator() { + public int compare(BuildNode a, BuildNode b) { + boolean an = Double.isNaN(a.builder.sortKey); + boolean bn = Double.isNaN(b.builder.sortKey); + if (an && bn) return 0; + if (an) return 1; + if (bn) return -1; + return a.builder.sortKey < b.builder.sortKey ? -1 : a.builder.sortKey == b.builder.sortKey ? 0 : 1; + } + }); + applyRelativeOrder(nodes); + for (BuildNode node : nodes) sortTree(node.children); + } + + private void applyRelativeOrder(List nodes) { + for (int pass = 0; pass < nodes.size(); pass++) { + boolean changed = false; + for (int i = 0; i < nodes.size(); i++) { + BuildNode node = nodes.get(i); + int target = indexOf(nodes, node.builder.traversalBefore); + if (target >= 0 && i > target) { + nodes.remove(i); + nodes.add(target, node); + changed = true; + break; + } + target = indexOf(nodes, node.builder.traversalAfter); + if (target >= 0 && i < target) { + nodes.remove(i); + nodes.add(Math.min(target, nodes.size()), node); + changed = true; + break; + } + } + if (!changed) return; + } + } + + private int indexOf(List nodes, Component component) { + if (component == null) return -1; + for (int i = 0; i < nodes.size(); i++) if (nodes.get(i).component == component) return i; + return -1; + } + + private void freeze(List source, long parentId, List childIds, + LinkedHashMap nodes) { + for (BuildNode node : source) { + node.builder.parentId = parentId; + for (BuildNode child : node.children) node.builder.childIds.add(Long.valueOf(child.id)); + AccessibilityNodeSnapshot frozen = new AccessibilityNodeSnapshot(node.builder); + nodes.put(Long.valueOf(node.id), frozen); + childIds.add(Long.valueOf(node.id)); + List ignored = new ArrayList(); + freeze(node.children, node.id, ignored, nodes); + } + } + + private String collectLabels(List nodes) { + String value = null; + for (BuildNode node : nodes) { + value = join(value, node.builder.label); + value = join(value, collectLabels(node.children)); + } + return value; + } + + private static boolean hasAction(List actions, String id) { + for (AccessibilityAction action : actions) if (id.equals(action.getId())) return true; + return false; + } + + private static boolean isInteractiveRole(AccessibilityRole role) { + return role == AccessibilityRole.BUTTON || role == AccessibilityRole.TOGGLE_BUTTON + || role == AccessibilityRole.CHECKBOX || role == AccessibilityRole.RADIO_BUTTON + || role == AccessibilityRole.SWITCH || role == AccessibilityRole.LINK + || role == AccessibilityRole.TEXT_FIELD || role == AccessibilityRole.SEARCH_FIELD + || role == AccessibilityRole.SLIDER || role == AccessibilityRole.TAB + || role == AccessibilityRole.MENU_ITEM || role == AccessibilityRole.SPIN_BUTTON + || role == AccessibilityRole.COMBO_BOX || role == AccessibilityRole.TREE_ITEM; + } + + private static String firstNonEmpty(String first, String second) { + return !isEmpty(first) ? first : second; + } + + private static String join(String first, String second) { + if (isEmpty(first)) return second; + if (isEmpty(second)) return first; + return first + ", " + second; + } + + private static boolean isEmpty(String value) { + return value == null || value.length() == 0; + } + + private static final class BuildNode { + long id; + Component component; + AccessibilityNodeSnapshot.Builder builder = new AccessibilityNodeSnapshot.Builder(); + List children = new ArrayList(); + } +} diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityNode.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityNode.java new file mode 100644 index 00000000000..282fa251282 --- /dev/null +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityNode.java @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2026 Codename One and contributors. All rights reserved. + */ +package com.codename1.ui.accessibility; + +import com.codename1.ui.Component; +import com.codename1.ui.geom.Rectangle; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/// Mutable semantic configuration for a lightweight component or virtual child. +/// +/// Component-owned nodes are obtained with {@link Component#getSemantics()}. +/// Applications can create standalone nodes for an {@link AccessibilityChildProvider}; +/// virtual nodes must have a stable {@link #setVirtualKey(java.lang.String) virtual key}. +public class AccessibilityNode { + private Component owner; + private String virtualKey; + private String identifier; + private String label; + private String hint; + private String description; + private String value; + private String validationError; + private String paneTitle; + private String roleDescription; + private AccessibilityRole role = AccessibilityRole.NONE; + private AccessibilityCheckedState checked = AccessibilityCheckedState.UNSPECIFIED; + private AccessibilityLiveRegion liveRegion = AccessibilityLiveRegion.OFF; + private AccessibilityGrouping grouping = AccessibilityGrouping.AUTO; + private AccessibilityRange range; + private AccessibilityCollectionInfo collectionInfo; + private AccessibilityCollectionItemInfo collectionItemInfo; + private AccessibilityChildProvider childProvider; + private Rectangle bounds; + private Boolean selected; + private Boolean expanded; + private Boolean enabled; + private Boolean invalid; + private Boolean busy; + private Boolean readOnly; + private Boolean required; + private Boolean multiline; + private Boolean obscured; + private Boolean pressed; + private Boolean current; + private boolean modal; + private int headingLevel = -1; + private double sortKey = Double.NaN; + private Component traversalBefore; + private Component traversalAfter; + private final List actions = new ArrayList(); + private final List children = new ArrayList(); + + public AccessibilityNode() { + } + + public AccessibilityNode(String virtualKey) { + setVirtualKey(virtualKey); + } + + /// Internal constructor used by {@link Component}. + public AccessibilityNode(Component owner) { + this.owner = owner; + } + + private AccessibilityNode changed(int type) { + if (owner != null) { + AccessibilityManager.getInstance().invalidate(owner, type); + } + return this; + } + + public Component getOwner() { return owner; } + public String getVirtualKey() { return virtualKey; } + public AccessibilityNode setVirtualKey(String virtualKey) { + if (virtualKey == null || virtualKey.length() == 0) { + throw new IllegalArgumentException("Virtual accessibility nodes require a non-empty stable key"); + } + this.virtualKey = virtualKey; + return changed(AccessibilityManager.CHANGE_STRUCTURE); + } + public String getIdentifier() { return identifier; } + public AccessibilityNode setIdentifier(String identifier) { this.identifier = identifier; return changed(AccessibilityManager.CHANGE_CONTENT); } + public String getLabel() { return label; } + public AccessibilityNode setLabel(String label) { this.label = label; return changed(AccessibilityManager.CHANGE_CONTENT); } + public String getHint() { return hint; } + public AccessibilityNode setHint(String hint) { this.hint = hint; return changed(AccessibilityManager.CHANGE_CONTENT); } + public String getDescription() { return description; } + public AccessibilityNode setDescription(String description) { this.description = description; return changed(AccessibilityManager.CHANGE_CONTENT); } + public String getValue() { return value; } + public AccessibilityNode setValue(String value) { this.value = value; return changed(AccessibilityManager.CHANGE_VALUE); } + public String getValidationError() { return validationError; } + public AccessibilityNode setValidationError(String error) { this.validationError = error; this.invalid = error == null ? invalid : Boolean.TRUE; return changed(AccessibilityManager.CHANGE_STATE); } + public String getPaneTitle() { return paneTitle; } + public AccessibilityNode setPaneTitle(String paneTitle) { this.paneTitle = paneTitle; return changed(AccessibilityManager.CHANGE_PANE); } + public String getRoleDescription() { return roleDescription; } + public AccessibilityNode setRoleDescription(String roleDescription) { this.roleDescription = roleDescription; return changed(AccessibilityManager.CHANGE_CONTENT); } + public AccessibilityRole getRole() { return role; } + public AccessibilityNode setRole(AccessibilityRole role) { this.role = role == null ? AccessibilityRole.NONE : role; return changed(AccessibilityManager.CHANGE_STRUCTURE); } + public AccessibilityCheckedState getChecked() { return checked; } + public AccessibilityNode setChecked(AccessibilityCheckedState checked) { this.checked = checked == null ? AccessibilityCheckedState.UNSPECIFIED : checked; return changed(AccessibilityManager.CHANGE_STATE); } + public AccessibilityLiveRegion getLiveRegion() { return liveRegion; } + public AccessibilityNode setLiveRegion(AccessibilityLiveRegion liveRegion) { this.liveRegion = liveRegion == null ? AccessibilityLiveRegion.OFF : liveRegion; return changed(AccessibilityManager.CHANGE_LIVE_REGION); } + public AccessibilityGrouping getGrouping() { return grouping; } + public AccessibilityNode setGrouping(AccessibilityGrouping grouping) { this.grouping = grouping == null ? AccessibilityGrouping.AUTO : grouping; return changed(AccessibilityManager.CHANGE_STRUCTURE); } + public AccessibilityRange getRange() { return range; } + public AccessibilityNode setRange(AccessibilityRange range) { this.range = range; return changed(AccessibilityManager.CHANGE_VALUE); } + public AccessibilityCollectionInfo getCollectionInfo() { return collectionInfo; } + public AccessibilityNode setCollectionInfo(AccessibilityCollectionInfo info) { this.collectionInfo = info; return changed(AccessibilityManager.CHANGE_STRUCTURE); } + public AccessibilityCollectionItemInfo getCollectionItemInfo() { return collectionItemInfo; } + public AccessibilityNode setCollectionItemInfo(AccessibilityCollectionItemInfo info) { this.collectionItemInfo = info; return changed(AccessibilityManager.CHANGE_STRUCTURE); } + public AccessibilityChildProvider getChildProvider() { return childProvider; } + public AccessibilityNode setChildProvider(AccessibilityChildProvider provider) { this.childProvider = provider; return changed(AccessibilityManager.CHANGE_STRUCTURE); } + public Rectangle getBounds() { return bounds == null ? null : new Rectangle(bounds); } + public AccessibilityNode setBounds(Rectangle bounds) { this.bounds = bounds == null ? null : new Rectangle(bounds); return changed(AccessibilityManager.CHANGE_BOUNDS); } + public Boolean getSelected() { return selected; } + public AccessibilityNode setSelected(Boolean selected) { this.selected = selected; return changed(AccessibilityManager.CHANGE_STATE); } + public Boolean getExpanded() { return expanded; } + public AccessibilityNode setExpanded(Boolean expanded) { this.expanded = expanded; return changed(AccessibilityManager.CHANGE_STATE); } + public Boolean getEnabled() { return enabled; } + public AccessibilityNode setEnabled(Boolean enabled) { this.enabled = enabled; return changed(AccessibilityManager.CHANGE_STATE); } + public Boolean getInvalid() { return invalid; } + public AccessibilityNode setInvalid(Boolean invalid) { this.invalid = invalid; return changed(AccessibilityManager.CHANGE_STATE); } + public Boolean getBusy() { return busy; } + public AccessibilityNode setBusy(Boolean busy) { this.busy = busy; return changed(AccessibilityManager.CHANGE_STATE); } + public Boolean getReadOnly() { return readOnly; } + public AccessibilityNode setReadOnly(Boolean readOnly) { this.readOnly = readOnly; return changed(AccessibilityManager.CHANGE_STATE); } + public Boolean getRequired() { return required; } + public AccessibilityNode setRequired(Boolean required) { this.required = required; return changed(AccessibilityManager.CHANGE_STATE); } + public Boolean getMultiline() { return multiline; } + public AccessibilityNode setMultiline(Boolean multiline) { this.multiline = multiline; return changed(AccessibilityManager.CHANGE_STATE); } + public Boolean getObscured() { return obscured; } + public AccessibilityNode setObscured(Boolean obscured) { this.obscured = obscured; return changed(AccessibilityManager.CHANGE_STATE); } + public Boolean getPressed() { return pressed; } + public AccessibilityNode setPressed(Boolean pressed) { this.pressed = pressed; return changed(AccessibilityManager.CHANGE_STATE); } + public Boolean getCurrent() { return current; } + public AccessibilityNode setCurrent(Boolean current) { this.current = current; return changed(AccessibilityManager.CHANGE_STATE); } + public boolean isModal() { return modal; } + public AccessibilityNode setModal(boolean modal) { this.modal = modal; return changed(AccessibilityManager.CHANGE_PANE); } + public int getHeadingLevel() { return headingLevel; } + public AccessibilityNode setHeadingLevel(int level) { this.headingLevel = level; if (level > 0 && role == AccessibilityRole.NONE) role = AccessibilityRole.HEADING; return changed(AccessibilityManager.CHANGE_STRUCTURE); } + public double getSortKey() { return sortKey; } + public AccessibilityNode setSortKey(double sortKey) { this.sortKey = sortKey; return changed(AccessibilityManager.CHANGE_STRUCTURE); } + public Component getTraversalBefore() { return traversalBefore; } + public AccessibilityNode setTraversalBefore(Component component) { this.traversalBefore = component; return changed(AccessibilityManager.CHANGE_STRUCTURE); } + public Component getTraversalAfter() { return traversalAfter; } + public AccessibilityNode setTraversalAfter(Component component) { this.traversalAfter = component; return changed(AccessibilityManager.CHANGE_STRUCTURE); } + + public AccessibilityNode addAction(AccessibilityAction action) { + if (action == null) throw new NullPointerException("action"); + for (int i = actions.size() - 1; i >= 0; i--) { + if (actions.get(i).getId().equals(action.getId())) actions.remove(i); + } + actions.add(action); + return changed(AccessibilityManager.CHANGE_ACTIONS); + } + + public AccessibilityNode removeAction(String id) { + for (int i = actions.size() - 1; i >= 0; i--) { + if (actions.get(i).getId().equals(id)) actions.remove(i); + } + return changed(AccessibilityManager.CHANGE_ACTIONS); + } + + public List getActions() { + return Collections.unmodifiableList(actions); + } + + public AccessibilityNode addChild(AccessibilityNode child) { + if (child == null) throw new NullPointerException("child"); + children.add(child); + return changed(AccessibilityManager.CHANGE_STRUCTURE); + } + + public AccessibilityNode clearChildren() { + children.clear(); + return changed(AccessibilityManager.CHANGE_STRUCTURE); + } + + public List getChildren() { + return Collections.unmodifiableList(children); + } + + public boolean hasExplicitConfiguration() { + return role != AccessibilityRole.NONE || label != null || hint != null || description != null + || value != null || validationError != null || paneTitle != null || roleDescription != null + || checked != AccessibilityCheckedState.UNSPECIFIED || liveRegion != AccessibilityLiveRegion.OFF + || grouping != AccessibilityGrouping.AUTO || range != null || collectionInfo != null + || collectionItemInfo != null || childProvider != null || bounds != null || selected != null + || expanded != null || enabled != null || invalid != null || busy != null || readOnly != null + || required != null || multiline != null || obscured != null || pressed != null || current != null + || modal || headingLevel > 0 || !Double.isNaN(sortKey) || traversalBefore != null + || traversalAfter != null || !actions.isEmpty() || !children.isEmpty(); + } +} diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityNodeSnapshot.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityNodeSnapshot.java new file mode 100644 index 00000000000..a60f35a51e4 --- /dev/null +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityNodeSnapshot.java @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2026 Codename One and contributors. All rights reserved. + */ +package com.codename1.ui.accessibility; + +import com.codename1.ui.Component; +import com.codename1.ui.geom.Rectangle; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/// Immutable resolved node exported to platform accessibility adapters and test tooling. +public final class AccessibilityNodeSnapshot { + private final long id; + private final long parentId; + private final Component component; + private final String virtualKey; + private final String identifier; + private final String label; + private final String hint; + private final String description; + private final String value; + private final String validationError; + private final String paneTitle; + private final String roleDescription; + private final AccessibilityRole role; + private final AccessibilityCheckedState checked; + private final AccessibilityLiveRegion liveRegion; + private final AccessibilityRange range; + private final AccessibilityCollectionInfo collectionInfo; + private final AccessibilityCollectionItemInfo collectionItemInfo; + private final Rectangle bounds; + private final Boolean selected; + private final Boolean expanded; + private final Boolean enabled; + private final Boolean invalid; + private final Boolean busy; + private final Boolean readOnly; + private final Boolean required; + private final Boolean multiline; + private final Boolean obscured; + private final Boolean pressed; + private final Boolean current; + private final boolean modal; + private final boolean focusable; + private final boolean focused; + private final int headingLevel; + private final List childIds; + private final List actions; + + AccessibilityNodeSnapshot(Builder b) { + id = b.id; + parentId = b.parentId; + component = b.component; + virtualKey = b.virtualKey; + identifier = b.identifier; + label = b.label; + hint = b.hint; + description = b.description; + value = b.value; + validationError = b.validationError; + paneTitle = b.paneTitle; + roleDescription = b.roleDescription; + role = b.role; + checked = b.checked; + liveRegion = b.liveRegion; + range = b.range; + collectionInfo = b.collectionInfo; + collectionItemInfo = b.collectionItemInfo; + bounds = b.bounds == null ? new Rectangle() : new Rectangle(b.bounds); + selected = b.selected; + expanded = b.expanded; + enabled = b.enabled; + invalid = b.invalid; + busy = b.busy; + readOnly = b.readOnly; + required = b.required; + multiline = b.multiline; + obscured = b.obscured; + pressed = b.pressed; + current = b.current; + modal = b.modal; + focusable = b.focusable; + focused = b.focused; + headingLevel = b.headingLevel; + childIds = Collections.unmodifiableList(new ArrayList(b.childIds)); + actions = Collections.unmodifiableList(new ArrayList(b.actions)); + } + + public long getId() { return id; } + public long getParentId() { return parentId; } + public Component getComponent() { return component; } + public String getVirtualKey() { return virtualKey; } + public String getIdentifier() { return identifier; } + public String getLabel() { return label; } + public String getHint() { return hint; } + public String getDescription() { return description; } + public String getValue() { return value; } + public String getValidationError() { return validationError; } + public String getPaneTitle() { return paneTitle; } + public String getRoleDescription() { return roleDescription; } + public AccessibilityRole getRole() { return role; } + public AccessibilityCheckedState getChecked() { return checked; } + public AccessibilityLiveRegion getLiveRegion() { return liveRegion; } + public AccessibilityRange getRange() { return range; } + public AccessibilityCollectionInfo getCollectionInfo() { return collectionInfo; } + public AccessibilityCollectionItemInfo getCollectionItemInfo() { return collectionItemInfo; } + public Rectangle getBounds() { return new Rectangle(bounds); } + public Boolean getSelected() { return selected; } + public Boolean getExpanded() { return expanded; } + public Boolean getEnabled() { return enabled; } + public Boolean getInvalid() { return invalid; } + public Boolean getBusy() { return busy; } + public Boolean getReadOnly() { return readOnly; } + public Boolean getRequired() { return required; } + public Boolean getMultiline() { return multiline; } + public Boolean getObscured() { return obscured; } + public Boolean getPressed() { return pressed; } + public Boolean getCurrent() { return current; } + public boolean isModal() { return modal; } + public boolean isFocusable() { return focusable; } + public boolean isFocused() { return focused; } + public int getHeadingLevel() { return headingLevel; } + public List getChildIds() { return childIds; } + public List getActions() { return actions; } + + public AccessibilityAction getAction(String id) { + if (id == null) return null; + for (AccessibilityAction action : actions) { + if (id.equals(action.getId())) return action; + } + return null; + } + + static final class Builder { + long id; + long parentId = -1; + Component component; + String virtualKey; + String identifier; + String label; + String hint; + String description; + String value; + String validationError; + String paneTitle; + String roleDescription; + AccessibilityRole role = AccessibilityRole.GENERIC; + AccessibilityCheckedState checked = AccessibilityCheckedState.UNSPECIFIED; + AccessibilityLiveRegion liveRegion = AccessibilityLiveRegion.OFF; + AccessibilityRange range; + AccessibilityCollectionInfo collectionInfo; + AccessibilityCollectionItemInfo collectionItemInfo; + Rectangle bounds; + Boolean selected; + Boolean expanded; + Boolean enabled; + Boolean invalid; + Boolean busy; + Boolean readOnly; + Boolean required; + Boolean multiline; + Boolean obscured; + Boolean pressed; + Boolean current; + boolean modal; + boolean focusable; + boolean focused; + int headingLevel = -1; + double sortKey = Double.NaN; + Component traversalBefore; + Component traversalAfter; + List childIds = new ArrayList(); + List actions = new ArrayList(); + } +} diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityRange.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityRange.java new file mode 100644 index 00000000000..5a6abbe34fb --- /dev/null +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityRange.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2026 Codename One and contributors. All rights reserved. + */ +package com.codename1.ui.accessibility; + +/// Numeric value metadata for sliders, progress indicators, spin buttons, and +/// other adjustable controls. +public final class AccessibilityRange { + private final double minimum; + private final double maximum; + private final double current; + private final double step; + private final String text; + + public AccessibilityRange(double minimum, double maximum, double current) { + this(minimum, maximum, current, 0, null); + } + + public AccessibilityRange(double minimum, double maximum, double current, double step) { + this(minimum, maximum, current, step, null); + } + + public AccessibilityRange(double minimum, double maximum, double current, double step, String text) { + this.minimum = minimum; + this.maximum = maximum; + this.current = current; + this.step = step; + this.text = text; + } + + public double getMinimum() { + return minimum; + } + + public double getMaximum() { + return maximum; + } + + public double getCurrent() { + return current; + } + + public double getStep() { + return step; + } + + public String getText() { + return text; + } + + public boolean isValid() { + return !Double.isNaN(minimum) && !Double.isNaN(maximum) && !Double.isNaN(current) + && minimum <= maximum && current >= minimum && current <= maximum && step >= 0; + } +} diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityRole.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityRole.java new file mode 100644 index 00000000000..7dffde79736 --- /dev/null +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityRole.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2026 Codename One and contributors. All rights reserved. + */ +package com.codename1.ui.accessibility; + +/// The semantic role of a lightweight component or virtual accessibility node. +/// +/// Roles are intentionally portable. Platform ports map them to native control +/// types, traits, patterns, or ARIA roles and fall back to {@link #GENERIC} when +/// a platform has no exact equivalent. +public enum AccessibilityRole { + NONE, + GENERIC, + BUTTON, + TOGGLE_BUTTON, + CHECKBOX, + RADIO_BUTTON, + SWITCH, + HEADING, + LINK, + IMAGE, + STATIC_TEXT, + TEXT_FIELD, + SEARCH_FIELD, + SLIDER, + PROGRESS_BAR, + LIST, + LIST_ITEM, + GRID, + ROW, + CELL, + COLUMN_HEADER, + ROW_HEADER, + TAB_LIST, + TAB, + TAB_PANEL, + DIALOG, + ALERT, + MENU, + MENU_ITEM, + TOOLBAR, + SCROLL_BAR, + SPIN_BUTTON, + COMBO_BOX, + TREE, + TREE_ITEM, + SEPARATOR +} diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityTreeSnapshot.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityTreeSnapshot.java new file mode 100644 index 00000000000..a252a59cf16 --- /dev/null +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityTreeSnapshot.java @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2026 Codename One and contributors. All rights reserved. + */ +package com.codename1.ui.accessibility; + +import com.codename1.ui.geom.Rectangle; +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +/// Immutable accessibility tree for the current form. +public final class AccessibilityTreeSnapshot { + private final long generation; + private final List rootIds; + private final Map nodes; + + AccessibilityTreeSnapshot(long generation, List rootIds, Map nodes) { + this.generation = generation; + this.rootIds = Collections.unmodifiableList(new ArrayList(rootIds)); + this.nodes = Collections.unmodifiableMap(new LinkedHashMap(nodes)); + } + + public long getGeneration() { return generation; } + public List getRootIds() { return rootIds; } + public Map getNodes() { return nodes; } + public AccessibilityNodeSnapshot getNode(long id) { return nodes.get(Long.valueOf(id)); } + + /// Returns the deepest semantic node containing the screen coordinate. + public AccessibilityNodeSnapshot getNodeAt(int x, int y) { + AccessibilityNodeSnapshot best = null; + for (AccessibilityNodeSnapshot node : nodes.values()) { + Rectangle r = node.getBounds(); + if (r.getWidth() > 0 && r.getHeight() > 0 && r.contains(x, y)) { + if (best == null || isDescendant(node, best)) best = node; + } + } + return best; + } + + private boolean isDescendant(AccessibilityNodeSnapshot possibleChild, AccessibilityNodeSnapshot possibleParent) { + long parent = possibleChild.getParentId(); + while (parent >= 0) { + if (parent == possibleParent.getId()) return true; + AccessibilityNodeSnapshot node = getNode(parent); + if (node == null) return false; + parent = node.getParentId(); + } + return false; + } + + public String toJson() { + StringBuilder out = new StringBuilder(); + out.append("{\"generation\":").append(generation).append(",\"roots\":["); + for (int i = 0; i < rootIds.size(); i++) { + if (i > 0) out.append(','); + out.append(rootIds.get(i)); + } + out.append("],\"nodes\":["); + int index = 0; + for (AccessibilityNodeSnapshot node : nodes.values()) { + if (index++ > 0) out.append(','); + out.append('{'); + out.append("\"id\":").append(node.getId()); + out.append(",\"parent\":").append(node.getParentId()); + out.append(",\"role\":"); appendJson(out, node.getRole().name()); + out.append(",\"label\":"); appendJson(out, node.getLabel()); + out.append(",\"value\":"); appendJson(out, node.getValue()); + out.append(",\"hint\":"); appendJson(out, node.getHint()); + out.append(",\"description\":"); appendJson(out, node.getDescription()); + out.append(",\"error\":"); appendJson(out, node.getValidationError()); + out.append(",\"paneTitle\":"); appendJson(out, node.getPaneTitle()); + out.append(",\"identifier\":"); appendJson(out, node.getIdentifier()); + out.append(",\"roleDescription\":"); appendJson(out, node.getRoleDescription()); + out.append(",\"checked\":"); appendJson(out, node.getChecked().name()); + out.append(",\"liveRegion\":"); appendJson(out, node.getLiveRegion().name()); + out.append(",\"selected\":"); appendBoolean(out, node.getSelected()); + out.append(",\"expanded\":"); appendBoolean(out, node.getExpanded()); + out.append(",\"enabled\":"); appendBoolean(out, node.getEnabled()); + out.append(",\"invalid\":"); appendBoolean(out, node.getInvalid()); + out.append(",\"busy\":"); appendBoolean(out, node.getBusy()); + out.append(",\"readOnly\":"); appendBoolean(out, node.getReadOnly()); + out.append(",\"required\":"); appendBoolean(out, node.getRequired()); + out.append(",\"multiline\":"); appendBoolean(out, node.getMultiline()); + out.append(",\"obscured\":"); appendBoolean(out, node.getObscured()); + out.append(",\"pressed\":"); appendBoolean(out, node.getPressed()); + out.append(",\"current\":"); appendBoolean(out, node.getCurrent()); + out.append(",\"modal\":").append(node.isModal()); + out.append(",\"focusable\":").append(node.isFocusable()); + out.append(",\"focused\":").append(node.isFocused()); + out.append(",\"headingLevel\":").append(node.getHeadingLevel()); + if (node.getRange() != null) { + AccessibilityRange range = node.getRange(); + out.append(",\"range\":{"); + out.append("\"min\":").append(range.getMinimum()); + out.append(",\"max\":").append(range.getMaximum()); + out.append(",\"current\":").append(range.getCurrent()); + out.append(",\"step\":").append(range.getStep()); + out.append(",\"text\":"); appendJson(out, range.getText()); + out.append('}'); + } + if (node.getCollectionInfo() != null) { + AccessibilityCollectionInfo collection = node.getCollectionInfo(); + out.append(",\"collection\":{"); + out.append("\"rows\":").append(collection.getRowCount()); + out.append(",\"columns\":").append(collection.getColumnCount()); + out.append(",\"hierarchical\":").append(collection.isHierarchical()); + out.append(",\"selectionMode\":").append(collection.getSelectionMode()).append('}'); + } + if (node.getCollectionItemInfo() != null) { + AccessibilityCollectionItemInfo item = node.getCollectionItemInfo(); + out.append(",\"collectionItem\":{"); + out.append("\"row\":").append(item.getRowIndex()); + out.append(",\"rowSpan\":").append(item.getRowSpan()); + out.append(",\"column\":").append(item.getColumnIndex()); + out.append(",\"columnSpan\":").append(item.getColumnSpan()); + out.append(",\"position\":").append(item.getPositionInSet()); + out.append(",\"setSize\":").append(item.getSetSize()); + out.append(",\"level\":").append(item.getLevel()); + out.append(",\"heading\":").append(item.isHeading()).append('}'); + } + Rectangle bounds = node.getBounds(); + out.append(",\"bounds\":[").append(bounds.getX()).append(',').append(bounds.getY()) + .append(',').append(bounds.getWidth()).append(',').append(bounds.getHeight()).append(']'); + out.append(",\"children\":["); + for (int i = 0; i < node.getChildIds().size(); i++) { + if (i > 0) out.append(','); + out.append(node.getChildIds().get(i)); + } + out.append("],\"actions\":["); + for (int i = 0; i < node.getActions().size(); i++) { + if (i > 0) out.append(','); + AccessibilityAction action = node.getActions().get(i); + out.append('{').append("\"id\":"); appendJson(out, action.getId()); + out.append(",\"label\":"); appendJson(out, action.getLabel()); + out.append(",\"enabled\":").append(action.isEnabled()).append('}'); + } + out.append("]}"); + } + out.append("]}"); + return out.toString(); + } + + private static void appendJson(StringBuilder out, String value) { + if (value == null) { + out.append("null"); + return; + } + out.append('"'); + for (int i = 0; i < value.length(); i++) { + char c = value.charAt(i); + if (c == '"' || c == '\\') out.append('\\'); + if (c == '\n') out.append("\\n"); + else if (c == '\r') out.append("\\r"); + else if (c == '\t') out.append("\\t"); + else out.append(c); + } + out.append('"'); + } + + private static void appendBoolean(StringBuilder out, Boolean value) { + if (value == null) out.append("null"); + else out.append(value.booleanValue()); + } +} diff --git a/Ports/Android/src/com/codename1/impl/android/AndroidAccessibilityProvider.java b/Ports/Android/src/com/codename1/impl/android/AndroidAccessibilityProvider.java new file mode 100644 index 00000000000..045eb526df1 --- /dev/null +++ b/Ports/Android/src/com/codename1/impl/android/AndroidAccessibilityProvider.java @@ -0,0 +1,361 @@ +/* + * Copyright (c) 2026 Codename One and contributors. All rights reserved. + */ +package com.codename1.impl.android; + +import android.graphics.Rect; +import android.os.Build; +import android.os.Bundle; +import android.view.View; +import android.view.ViewParent; +import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityNodeInfo; +import android.view.accessibility.AccessibilityNodeProvider; +import com.codename1.ui.accessibility.AccessibilityAction; +import com.codename1.ui.accessibility.AccessibilityCheckedState; +import com.codename1.ui.accessibility.AccessibilityCollectionInfo; +import com.codename1.ui.accessibility.AccessibilityCollectionItemInfo; +import com.codename1.ui.accessibility.AccessibilityLiveRegion; +import com.codename1.ui.accessibility.AccessibilityManager; +import com.codename1.ui.accessibility.AccessibilityNodeSnapshot; +import com.codename1.ui.accessibility.AccessibilityRange; +import com.codename1.ui.accessibility.AccessibilityRole; +import com.codename1.ui.accessibility.AccessibilityTreeSnapshot; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** Android virtual-view adapter for Codename One's lightweight semantic tree. */ +final class AndroidAccessibilityProvider extends AccessibilityNodeProvider { + private static final int CUSTOM_ACTION_BASE = 0x01000000; + private static final String ROLE_DESCRIPTION_KEY = "AccessibilityNodeInfo.roleDescription"; + private final View host; + private final AndroidImplementation implementation; + private int accessibilityFocusedId = Integer.MIN_VALUE; + + AndroidAccessibilityProvider(View host, AndroidImplementation implementation) { + this.host = host; + this.implementation = implementation; + host.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES); + } + + @Override + public AccessibilityNodeInfo createAccessibilityNodeInfo(int virtualViewId) { + AccessibilityTreeSnapshot tree = implementation.getAccessibilityTreeSnapshot(); + if (virtualViewId == View.NO_ID || virtualViewId == AccessibilityNodeProvider.HOST_VIEW_ID) { + return createHostNode(tree); + } + AccessibilityNodeSnapshot node = tree.getNode(virtualViewId); + return node == null ? null : createVirtualNode(tree, node, virtualViewId); + } + + private AccessibilityNodeInfo createHostNode(AccessibilityTreeSnapshot tree) { + AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(host); + host.onInitializeAccessibilityNodeInfo(info); + info.setClassName("com.codename1.ui.Form"); + info.setPackageName(host.getContext().getPackageName()); + info.setScrollable(false); + for (Long rootId : tree.getRootIds()) { + info.addChild(host, toVirtualId(rootId.longValue())); + } + return info; + } + + private AccessibilityNodeInfo createVirtualNode(AccessibilityTreeSnapshot tree, + AccessibilityNodeSnapshot node, int virtualViewId) { + AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(); + info.setPackageName(host.getContext().getPackageName()); + info.setClassName(className(node.getRole())); + info.setSource(host, virtualViewId); + if (node.getParentId() < 0) info.setParent(host); + else info.setParent(host, toVirtualId(node.getParentId())); + for (Long childId : node.getChildIds()) info.addChild(host, toVirtualId(childId.longValue())); + + String label = node.getLabel(); + if (usesText(node.getRole())) info.setText(label); + else info.setContentDescription(label); + if (Build.VERSION.SDK_INT >= 26 && node.getHint() != null) info.setHintText(node.getHint()); + if (Build.VERSION.SDK_INT >= 19 && node.getRoleDescription() != null) { + info.getExtras().putCharSequence(ROLE_DESCRIPTION_KEY, node.getRoleDescription()); + } + if (Build.VERSION.SDK_INT >= 18 && node.getIdentifier() != null) { + info.setViewIdResourceName(host.getContext().getPackageName() + ":id/" + node.getIdentifier()); + } + + boolean enabled = node.getEnabled() == null || node.getEnabled().booleanValue(); + info.setEnabled(enabled); + info.setVisibleToUser(isVisible(node)); + info.setFocusable(node.isFocusable()); + info.setFocused(node.isFocused()); + info.setAccessibilityFocused(virtualViewId == accessibilityFocusedId); + info.setSelected(Boolean.TRUE.equals(node.getSelected())); + info.setClickable(hasAction(node, AccessibilityAction.ACTIVATE)); + info.setLongClickable(hasAction(node, AccessibilityAction.LONG_PRESS)); + info.setScrollable(hasAction(node, AccessibilityAction.SCROLL_FORWARD) + || hasAction(node, AccessibilityAction.SCROLL_BACKWARD)); + + AccessibilityCheckedState checked = node.getChecked(); + if (checked != AccessibilityCheckedState.UNSPECIFIED) { + info.setCheckable(true); + info.setChecked(checked == AccessibilityCheckedState.CHECKED || checked == AccessibilityCheckedState.MIXED); + if (checked == AccessibilityCheckedState.MIXED && Build.VERSION.SDK_INT >= 19) { + info.getExtras().putCharSequence("com.codename1.accessibility.checkedState", "mixed"); + } + } + if (Build.VERSION.SDK_INT >= 19) { + info.setContentInvalid(Boolean.TRUE.equals(node.getInvalid())); + if (node.getCollectionInfo() != null) info.setCollectionInfo(collection(node.getCollectionInfo())); + if (node.getCollectionItemInfo() != null) info.setCollectionItemInfo(collectionItem(node.getCollectionItemInfo(), node)); + if (node.getRange() != null) info.setRangeInfo(range(node.getRange())); + if (node.getExpanded() != null) { + info.getExtras().putBoolean("com.codename1.accessibility.expanded", node.getExpanded().booleanValue()); + } + } + if (Build.VERSION.SDK_INT >= 21 && node.getValidationError() != null) info.setError(node.getValidationError()); + if (Build.VERSION.SDK_INT >= 28) { + info.setHeading(node.getHeadingLevel() > 0 + || node.getRole() == AccessibilityRole.HEADING + || node.getCollectionItemInfo() != null && node.getCollectionItemInfo().isHeading()); + info.setScreenReaderFocusable(node.isFocusable() || label != null); + if (node.getPaneTitle() != null) info.setPaneTitle(node.getPaneTitle()); + } + if (Build.VERSION.SDK_INT >= 19) { + info.setLiveRegion(node.getLiveRegion() == AccessibilityLiveRegion.ASSERTIVE + ? View.ACCESSIBILITY_LIVE_REGION_ASSERTIVE + : node.getLiveRegion() == AccessibilityLiveRegion.POLITE + ? View.ACCESSIBILITY_LIVE_REGION_POLITE : View.ACCESSIBILITY_LIVE_REGION_NONE); + } + + addActions(info, node); + setBounds(info, node); + return info; + } + + private void addActions(AccessibilityNodeInfo info, AccessibilityNodeSnapshot node) { + if (node.isFocusable()) info.addAction(AccessibilityNodeInfo.ACTION_FOCUS); + if (hasAction(node, AccessibilityAction.ACTIVATE)) info.addAction(AccessibilityNodeInfo.ACTION_CLICK); + if (hasAction(node, AccessibilityAction.LONG_PRESS)) info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK); + if (hasAction(node, AccessibilityAction.INCREMENT)) info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD); + if (hasAction(node, AccessibilityAction.DECREMENT)) info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD); + if (hasAction(node, AccessibilityAction.SCROLL_FORWARD)) info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD); + if (hasAction(node, AccessibilityAction.SCROLL_BACKWARD)) info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD); + info.addAction(accessibilityFocusedId == toVirtualId(node.getId()) + ? AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS + : AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS); + if (Build.VERSION.SDK_INT >= 21) { + for (AccessibilityAction action : node.getActions()) { + if (isStandard(action.getId())) continue; + info.addAction(new AccessibilityNodeInfo.AccessibilityAction(customActionId(action.getId()), + action.getLabel() == null ? action.getId() : action.getLabel())); + } + if (hasAction(node, AccessibilityAction.SET_TEXT)) { + info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SET_TEXT); + } + } + } + + @Override + public boolean performAction(int virtualViewId, int action, Bundle arguments) { + if (virtualViewId == AccessibilityNodeProvider.HOST_VIEW_ID) { + return host.performAccessibilityAction(action, arguments); + } + AccessibilityNodeSnapshot node = implementation.getAccessibilityTreeSnapshot().getNode(virtualViewId); + if (node == null) return false; + if (action == AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS) { + if (accessibilityFocusedId == virtualViewId) return false; + int previous = accessibilityFocusedId; + accessibilityFocusedId = virtualViewId; + if (previous != Integer.MIN_VALUE) sendEvent(previous, AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED); + sendEvent(virtualViewId, AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED); + return true; + } + if (action == AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS) { + if (accessibilityFocusedId != virtualViewId) return false; + accessibilityFocusedId = Integer.MIN_VALUE; + sendEvent(virtualViewId, AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED); + return true; + } + String actionId = null; + Object argument = null; + if (action == AccessibilityNodeInfo.ACTION_CLICK) actionId = AccessibilityAction.ACTIVATE; + else if (action == AccessibilityNodeInfo.ACTION_LONG_CLICK) actionId = AccessibilityAction.LONG_PRESS; + else if (action == AccessibilityNodeInfo.ACTION_FOCUS) actionId = AccessibilityAction.FOCUS; + else if (action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD) { + actionId = hasAction(node, AccessibilityAction.INCREMENT) + ? AccessibilityAction.INCREMENT : AccessibilityAction.SCROLL_FORWARD; + } else if (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD) { + actionId = hasAction(node, AccessibilityAction.DECREMENT) + ? AccessibilityAction.DECREMENT : AccessibilityAction.SCROLL_BACKWARD; + } else if (Build.VERSION.SDK_INT >= 21 && action == AccessibilityNodeInfo.ACTION_SET_TEXT) { + actionId = AccessibilityAction.SET_TEXT; + argument = arguments == null ? null : arguments.getCharSequence( + AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE); + if (argument != null) argument = argument.toString(); + } else { + for (AccessibilityAction candidate : node.getActions()) { + if (customActionId(candidate.getId()) == action) { + actionId = candidate.getId(); + break; + } + } + } + return actionId != null && implementation.performAccessibilityAction(node.getId(), actionId, argument); + } + + @Override + public List findAccessibilityNodeInfosByText(String searched, int virtualViewId) { + if (searched == null) return Collections.emptyList(); + String lower = searched.toLowerCase(); + List result = new ArrayList(); + AccessibilityTreeSnapshot tree = implementation.getAccessibilityTreeSnapshot(); + for (AccessibilityNodeSnapshot node : tree.getNodes().values()) { + if (contains(node.getLabel(), lower) || contains(node.getValue(), lower) + || contains(node.getDescription(), lower)) { + result.add(createVirtualNode(tree, node, toVirtualId(node.getId()))); + } + } + return result; + } + + @Override + public AccessibilityNodeInfo findFocus(int focus) { + AccessibilityTreeSnapshot tree = implementation.getAccessibilityTreeSnapshot(); + if (focus == AccessibilityNodeInfo.FOCUS_ACCESSIBILITY && accessibilityFocusedId != Integer.MIN_VALUE) { + AccessibilityNodeSnapshot node = tree.getNode(accessibilityFocusedId); + return node == null ? null : createVirtualNode(tree, node, accessibilityFocusedId); + } + if (focus == AccessibilityNodeInfo.FOCUS_INPUT) { + for (AccessibilityNodeSnapshot node : tree.getNodes().values()) { + if (node.isFocused()) return createVirtualNode(tree, node, toVirtualId(node.getId())); + } + } + return null; + } + + void invalidate(int changes) { + if ((changes & AccessibilityManager.CHANGE_STRUCTURE) != 0 + || (changes & AccessibilityManager.CHANGE_PANE) != 0) { + sendHostEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED); + } else if ((changes & AccessibilityManager.CHANGE_FOCUS) != 0) { + sendHostEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED); + } else { + sendHostEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED); + } + } + + private void sendHostEvent(int type) { + AccessibilityEvent event = AccessibilityEvent.obtain(type); + event.setPackageName(host.getContext().getPackageName()); + event.setClassName("com.codename1.ui.Form"); + event.setSource(host); + send(event); + } + + private void sendEvent(int virtualId, int type) { + AccessibilityEvent event = AccessibilityEvent.obtain(type); + event.setPackageName(host.getContext().getPackageName()); + event.setClassName("com.codename1.ui.Component"); + event.setSource(host, virtualId); + send(event); + } + + private void send(AccessibilityEvent event) { + ViewParent parent = host.getParent(); + if (parent != null) parent.requestSendAccessibilityEvent(host, event); + } + + private void setBounds(AccessibilityNodeInfo info, AccessibilityNodeSnapshot node) { + com.codename1.ui.geom.Rectangle b = node.getBounds(); + Rect parent = new Rect(b.getX(), b.getY(), b.getX() + b.getWidth(), b.getY() + b.getHeight()); + info.setBoundsInParent(parent); + int[] location = new int[2]; + host.getLocationOnScreen(location); + Rect screen = new Rect(parent); + screen.offset(location[0], location[1]); + info.setBoundsInScreen(screen); + } + + private boolean isVisible(AccessibilityNodeSnapshot node) { + com.codename1.ui.geom.Rectangle b = node.getBounds(); + return host.isShown() && b.getWidth() > 0 && b.getHeight() > 0; + } + + private AccessibilityNodeInfo.CollectionInfo collection(AccessibilityCollectionInfo info) { + int mode = info.getSelectionMode() == AccessibilityCollectionInfo.SELECTION_MULTIPLE + ? AccessibilityNodeInfo.CollectionInfo.SELECTION_MODE_MULTIPLE + : info.getSelectionMode() == AccessibilityCollectionInfo.SELECTION_SINGLE + ? AccessibilityNodeInfo.CollectionInfo.SELECTION_MODE_SINGLE + : AccessibilityNodeInfo.CollectionInfo.SELECTION_MODE_NONE; + if (Build.VERSION.SDK_INT >= 21) { + return AccessibilityNodeInfo.CollectionInfo.obtain(info.getRowCount(), info.getColumnCount(), + info.isHierarchical(), mode); + } + return AccessibilityNodeInfo.CollectionInfo.obtain(info.getRowCount(), info.getColumnCount(), + info.isHierarchical()); + } + + private AccessibilityNodeInfo.CollectionItemInfo collectionItem(AccessibilityCollectionItemInfo item, + AccessibilityNodeSnapshot node) { + if (Build.VERSION.SDK_INT >= 21) { + return AccessibilityNodeInfo.CollectionItemInfo.obtain(item.getRowIndex(), Math.max(1, item.getRowSpan()), + item.getColumnIndex(), Math.max(1, item.getColumnSpan()), item.isHeading(), + Boolean.TRUE.equals(node.getSelected())); + } + return AccessibilityNodeInfo.CollectionItemInfo.obtain(item.getRowIndex(), Math.max(1, item.getRowSpan()), + item.getColumnIndex(), Math.max(1, item.getColumnSpan()), item.isHeading()); + } + + private AccessibilityNodeInfo.RangeInfo range(AccessibilityRange range) { + return AccessibilityNodeInfo.RangeInfo.obtain(AccessibilityNodeInfo.RangeInfo.RANGE_TYPE_FLOAT, + (float)range.getMinimum(), (float)range.getMaximum(), (float)range.getCurrent()); + } + + private String className(AccessibilityRole role) { + switch (role) { + case BUTTON: return "android.widget.Button"; + case TOGGLE_BUTTON: return "android.widget.ToggleButton"; + case CHECKBOX: return "android.widget.CheckBox"; + case RADIO_BUTTON: return "android.widget.RadioButton"; + case SWITCH: return "android.widget.Switch"; + case TEXT_FIELD: + case SEARCH_FIELD: return "android.widget.EditText"; + case SLIDER: return "android.widget.SeekBar"; + case PROGRESS_BAR: return "android.widget.ProgressBar"; + case LIST: return "android.widget.ListView"; + case GRID: return "android.widget.GridView"; + case IMAGE: return "android.widget.ImageView"; + case TAB: return "android.app.ActionBar$Tab"; + case DIALOG: + case ALERT: return "android.app.Dialog"; + default: return "android.view.View"; + } + } + + private boolean usesText(AccessibilityRole role) { + return role == AccessibilityRole.STATIC_TEXT || role == AccessibilityRole.TEXT_FIELD + || role == AccessibilityRole.SEARCH_FIELD || role == AccessibilityRole.HEADING; + } + + private boolean contains(String value, String searchedLower) { + return value != null && value.toLowerCase().contains(searchedLower); + } + + private boolean hasAction(AccessibilityNodeSnapshot node, String id) { + return node.getAction(id) != null; + } + + private boolean isStandard(String id) { + return AccessibilityAction.ACTIVATE.equals(id) || AccessibilityAction.LONG_PRESS.equals(id) + || AccessibilityAction.INCREMENT.equals(id) || AccessibilityAction.DECREMENT.equals(id) + || AccessibilityAction.FOCUS.equals(id) || AccessibilityAction.SET_TEXT.equals(id) + || AccessibilityAction.SCROLL_FORWARD.equals(id) || AccessibilityAction.SCROLL_BACKWARD.equals(id); + } + + private int customActionId(String id) { + return CUSTOM_ACTION_BASE | (id.hashCode() & 0x00ffffff); + } + + private int toVirtualId(long id) { + return (int)id; + } +} diff --git a/Ports/Android/src/com/codename1/impl/android/AndroidImplementation.java b/Ports/Android/src/com/codename1/impl/android/AndroidImplementation.java index 1b26a84c9cc..17feb3e03ab 100644 --- a/Ports/Android/src/com/codename1/impl/android/AndroidImplementation.java +++ b/Ports/Android/src/com/codename1/impl/android/AndroidImplementation.java @@ -317,7 +317,8 @@ public static void setActivity(CodenameOneActivity aActivity) { } } - CodenameOneSurface myView = null; + CodenameOneSurface myView = null; + private AndroidAccessibilityProvider accessibilityProvider; CodenameOneTextPaint defaultFont; private final char[] tmpchar = new char[1]; private final Rect tmprect = new Rect(); @@ -1628,7 +1629,18 @@ private void initSurface() { superPeerMode = true; myView = new AndroidAsyncView(getActivity(), AndroidImplementation.this); } - myView.getAndroidView().setVisibility(View.VISIBLE); + myView.getAndroidView().setVisibility(View.VISIBLE); + + if (Build.VERSION.SDK_INT >= 16) { + final View semanticHost = myView.getAndroidView(); + accessibilityProvider = new AndroidAccessibilityProvider(semanticHost, this); + semanticHost.setAccessibilityDelegate(new View.AccessibilityDelegate() { + @Override + public android.view.accessibility.AccessibilityNodeProvider getAccessibilityNodeProvider(View host) { + return accessibilityProvider; + } + }); + } relativeLayout.addView(myView.getAndroidView()); myView.getAndroidView().setVisibility(View.VISIBLE); @@ -12891,7 +12903,7 @@ public void run() { } @Override - public void announceForAccessibility(final Component cmp, final String text) { + public void announceForAccessibility(final Component cmp, final String text) { final Activity act = getActivity(); if (act == null) { return; @@ -12925,7 +12937,23 @@ public void run() { } } }); - } + } + + @Override + public void accessibilityTreeChanged(final int changeType) { + final Activity act = getActivity(); + if (act == null || accessibilityProvider == null) return; + act.runOnUiThread(new Runnable() { + public void run() { + if (accessibilityProvider != null) accessibilityProvider.invalidate(changeType); + } + }); + } + + @Override + public boolean isAccessibilityTreeSupported() { + return Build.VERSION.SDK_INT >= 16; + } // ================================================================ // Crypto bridge -- routes com.codename1.security onto the standard diff --git a/Ports/JavaSE/src/com/codename1/impl/javase/ComponentTreeInspector.java b/Ports/JavaSE/src/com/codename1/impl/javase/ComponentTreeInspector.java index e2463f15ceb..4cd8bbcfad2 100644 --- a/Ports/JavaSE/src/com/codename1/impl/javase/ComponentTreeInspector.java +++ b/Ports/JavaSE/src/com/codename1/impl/javase/ComponentTreeInspector.java @@ -22,8 +22,14 @@ import com.codename1.ui.list.ContainerList; import com.codename1.ui.plaf.UIManager; import com.codename1.ui.util.Resources; +import com.codename1.ui.accessibility.AccessibilityAssertions; +import com.codename1.ui.accessibility.AccessibilityInspector; +import com.codename1.ui.accessibility.AccessibilityIssue; +import com.codename1.ui.accessibility.AccessibilityTreeSnapshot; import java.awt.BorderLayout; import java.awt.Desktop; +import java.awt.Toolkit; +import java.awt.datatransfer.StringSelection; import java.awt.event.ActionEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; @@ -179,6 +185,54 @@ public void run() { }); contextMenu.add(printComponent); + JMenuItem copyAccessibilityTree = new JMenuItem("Copy Accessibility Tree JSON"); + copyAccessibilityTree.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + com.codename1.ui.CN.callSerially(new Runnable() { + public void run() { + Form form = Display.getInstance().getCurrent(); + if (form == null) return; + final String json = AccessibilityInspector.snapshot(form).toJson(); + SwingUtilities.invokeLater(new Runnable() { + public void run() { + Toolkit.getDefaultToolkit().getSystemClipboard().setContents( + new StringSelection(json), null); + } + }); + } + }); + } + }); + contextMenu.add(copyAccessibilityTree); + + JMenuItem auditAccessibilityTree = new JMenuItem("Audit Accessibility Tree"); + auditAccessibilityTree.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + com.codename1.ui.CN.callSerially(new Runnable() { + public void run() { + Form form = Display.getInstance().getCurrent(); + if (form == null) return; + AccessibilityTreeSnapshot snapshot = AccessibilityInspector.snapshot(form); + final List issues = AccessibilityAssertions.audit(snapshot); + final StringBuilder message = new StringBuilder(); + for (AccessibilityIssue issue : issues) { + if (message.length() > 0) message.append('\n'); + message.append(issue.toString()); + } + SwingUtilities.invokeLater(new Runnable() { + public void run() { + JOptionPane.showMessageDialog(ComponentTreeInspector.this, + issues.isEmpty() ? "No accessibility issues found" : message.toString(), + "Accessibility Audit", issues.isEmpty() + ? JOptionPane.INFORMATION_MESSAGE : JOptionPane.WARNING_MESSAGE); + } + }); + } + }); + } + }); + contextMenu.add(auditAccessibilityTree); + //if (currentComponent instanceof Container) { JMenuItem revalidate = new JMenuItem("Revalidate"); revalidate.addActionListener(new java.awt.event.ActionListener() { diff --git a/Ports/JavaSE/src/com/codename1/impl/javase/JavaSEAccessibility.java b/Ports/JavaSE/src/com/codename1/impl/javase/JavaSEAccessibility.java new file mode 100644 index 00000000000..14b60cf0e62 --- /dev/null +++ b/Ports/JavaSE/src/com/codename1/impl/javase/JavaSEAccessibility.java @@ -0,0 +1,290 @@ +/* + * Copyright (c) 2026 Codename One and contributors. All rights reserved. + */ +package com.codename1.impl.javase; + +import com.codename1.ui.accessibility.AccessibilityAction; +import com.codename1.ui.accessibility.AccessibilityCheckedState; +import com.codename1.ui.accessibility.AccessibilityNodeSnapshot; +import com.codename1.ui.accessibility.AccessibilityRange; +import com.codename1.ui.accessibility.AccessibilityRole; +import com.codename1.ui.accessibility.AccessibilityTreeSnapshot; +import java.awt.Color; +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.event.FocusListener; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleAction; +import javax.accessibility.AccessibleComponent; +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; +import javax.accessibility.AccessibleState; +import javax.accessibility.AccessibleStateSet; +import javax.accessibility.AccessibleValue; +import javax.swing.JPanel; + +/** Swing/Java Access Bridge projection of the lightweight semantic tree. */ +final class JavaSEAccessibility { + private final JPanel canvas; + private final JavaSEPort implementation; + private final RootContext root = new RootContext(); + private final Map cache = new HashMap(); + + JavaSEAccessibility(JPanel canvas, JavaSEPort implementation) { + this.canvas = canvas; + this.implementation = implementation; + } + + AccessibleContext getContext() { + return root; + } + + void changed(int changeType) { + root.firePropertyChange(AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY, null, + Integer.valueOf(changeType)); + } + + private AccessibilityTreeSnapshot tree() { + return implementation.getAccessibilityTreeSnapshot(); + } + + private VirtualAccessible accessible(long id) { + VirtualAccessible value = cache.get(Long.valueOf(id)); + if (value == null) { + value = new VirtualAccessible(id); + cache.put(Long.valueOf(id), value); + } + return value; + } + + private final class RootContext extends AccessibleContext implements AccessibleComponent { + RootContext() { + setAccessibleParent(canvas); + } + + public String getAccessibleName() { return "Codename One application"; } + public String getAccessibleDescription() { return "Lightweight component accessibility tree"; } + public AccessibleRole getAccessibleRole() { return AccessibleRole.PANEL; } + public AccessibleStateSet getAccessibleStateSet() { + AccessibleStateSet states = new AccessibleStateSet(); + if (canvas.isEnabled()) states.add(AccessibleState.ENABLED); + if (canvas.isVisible()) states.add(AccessibleState.VISIBLE); + if (canvas.isShowing()) states.add(AccessibleState.SHOWING); + states.add(AccessibleState.FOCUSABLE); + if (canvas.hasFocus()) states.add(AccessibleState.FOCUSED); + return states; + } + public int getAccessibleIndexInParent() { return -1; } + public int getAccessibleChildrenCount() { return tree().getRootIds().size(); } + public Accessible getAccessibleChild(int i) { + List roots = tree().getRootIds(); + return i < 0 || i >= roots.size() ? null : accessible(roots.get(i).longValue()); + } + public Locale getLocale() { return Locale.getDefault(); } + public AccessibleComponent getAccessibleComponent() { return this; } + public Color getBackground() { return canvas.getBackground(); } + public void setBackground(Color c) { canvas.setBackground(c); } + public Color getForeground() { return canvas.getForeground(); } + public void setForeground(Color c) { canvas.setForeground(c); } + public Cursor getCursor() { return canvas.getCursor(); } + public void setCursor(Cursor c) { canvas.setCursor(c); } + public Font getFont() { return canvas.getFont(); } + public void setFont(Font f) { canvas.setFont(f); } + public FontMetrics getFontMetrics(Font f) { return canvas.getFontMetrics(f); } + public boolean isEnabled() { return canvas.isEnabled(); } + public void setEnabled(boolean b) { canvas.setEnabled(b); } + public boolean isVisible() { return canvas.isVisible(); } + public void setVisible(boolean b) { canvas.setVisible(b); } + public boolean isShowing() { return canvas.isShowing(); } + public boolean contains(Point p) { return canvas.contains(p); } + public Point getLocationOnScreen() { return canvas.getLocationOnScreen(); } + public Point getLocation() { return canvas.getLocation(); } + public void setLocation(Point p) { canvas.setLocation(p); } + public Rectangle getBounds() { return canvas.getBounds(); } + public void setBounds(Rectangle r) { canvas.setBounds(r); } + public Dimension getSize() { return canvas.getSize(); } + public void setSize(Dimension d) { canvas.setSize(d); } + public Accessible getAccessibleAt(Point p) { + Point local = new Point(p); + AccessibilityNodeSnapshot node = tree().getNodeAt(local.x, local.y); + return node == null ? null : accessible(node.getId()); + } + public boolean isFocusTraversable() { return true; } + public void requestFocus() { canvas.requestFocus(); } + public void addFocusListener(FocusListener l) { canvas.addFocusListener(l); } + public void removeFocusListener(FocusListener l) { canvas.removeFocusListener(l); } + } + + private final class VirtualAccessible implements Accessible { + private final long id; + private final NodeContext context; + + VirtualAccessible(long id) { + this.id = id; + context = new NodeContext(); + } + + public AccessibleContext getAccessibleContext() { return context; } + + private AccessibilityNodeSnapshot node() { return tree().getNode(id); } + + private final class NodeContext extends AccessibleContext + implements AccessibleComponent, AccessibleAction, AccessibleValue { + NodeContext() { + setAccessibleParent(canvas); + } + + public String getAccessibleName() { return node() == null ? null : node().getLabel(); } + public void setAccessibleName(String name) { } + public String getAccessibleDescription() { + AccessibilityNodeSnapshot n = node(); + if (n == null) return null; + String value = n.getDescription(); + if (n.getHint() != null) value = value == null ? n.getHint() : value + ". " + n.getHint(); + if (n.getValidationError() != null) value = value == null ? n.getValidationError() : value + ". " + n.getValidationError(); + return value; + } + public void setAccessibleDescription(String description) { } + public AccessibleRole getAccessibleRole() { return role(node() == null ? AccessibilityRole.GENERIC : node().getRole()); } + public AccessibleStateSet getAccessibleStateSet() { return states(node()); } + public Accessible getAccessibleParent() { + AccessibilityNodeSnapshot n = node(); + return n == null || n.getParentId() < 0 ? canvas : accessible(n.getParentId()); + } + public int getAccessibleIndexInParent() { + AccessibilityNodeSnapshot n = node(); + if (n == null) return -1; + List siblings = n.getParentId() < 0 ? tree().getRootIds() + : tree().getNode(n.getParentId()).getChildIds(); + return siblings.indexOf(Long.valueOf(id)); + } + public int getAccessibleChildrenCount() { return node() == null ? 0 : node().getChildIds().size(); } + public Accessible getAccessibleChild(int i) { + AccessibilityNodeSnapshot n = node(); + if (n == null || i < 0 || i >= n.getChildIds().size()) return null; + return accessible(n.getChildIds().get(i).longValue()); + } + public Locale getLocale() { return Locale.getDefault(); } + public AccessibleComponent getAccessibleComponent() { return this; } + public AccessibleAction getAccessibleAction() { return node() != null && !node().getActions().isEmpty() ? this : null; } + public AccessibleValue getAccessibleValue() { return node() != null && node().getRange() != null ? this : null; } + public int getAccessibleActionCount() { return node() == null ? 0 : node().getActions().size(); } + public String getAccessibleActionDescription(int i) { + if (node() == null || i < 0 || i >= node().getActions().size()) return null; + AccessibilityAction action = node().getActions().get(i); + return action.getLabel() == null ? action.getId() : action.getLabel(); + } + public boolean doAccessibleAction(int i) { + if (node() == null || i < 0 || i >= node().getActions().size()) return false; + return implementation.performAccessibilityAction(id, node().getActions().get(i).getId(), null); + } + public Number getCurrentAccessibleValue() { return node() == null || node().getRange() == null ? null : Double.valueOf(node().getRange().getCurrent()); } + public boolean setCurrentAccessibleValue(Number value) { + return value != null && implementation.performAccessibilityAction(id, AccessibilityAction.SET_VALUE, value); + } + public Number getMinimumAccessibleValue() { return node() == null || node().getRange() == null ? null : Double.valueOf(node().getRange().getMinimum()); } + public Number getMaximumAccessibleValue() { return node() == null || node().getRange() == null ? null : Double.valueOf(node().getRange().getMaximum()); } + public Color getBackground() { return canvas.getBackground(); } + public void setBackground(Color c) { } + public Color getForeground() { return canvas.getForeground(); } + public void setForeground(Color c) { } + public Cursor getCursor() { return canvas.getCursor(); } + public void setCursor(Cursor c) { } + public Font getFont() { return canvas.getFont(); } + public void setFont(Font f) { } + public FontMetrics getFontMetrics(Font f) { return canvas.getFontMetrics(f); } + public boolean isEnabled() { return node() != null && !Boolean.FALSE.equals(node().getEnabled()); } + public void setEnabled(boolean b) { } + public boolean isVisible() { return node() != null && node().getBounds().getWidth() > 0 && node().getBounds().getHeight() > 0; } + public void setVisible(boolean b) { } + public boolean isShowing() { return canvas.isShowing() && isVisible(); } + public boolean contains(Point p) { return getBounds().contains(p); } + public Point getLocationOnScreen() { + Point rootLocation = canvas.getLocationOnScreen(); + Rectangle bounds = getBounds(); + return new Point(rootLocation.x + bounds.x, rootLocation.y + bounds.y); + } + public Point getLocation() { Rectangle b = getBounds(); return new Point(b.x, b.y); } + public void setLocation(Point p) { } + public Rectangle getBounds() { + if (node() == null) return new Rectangle(); + com.codename1.ui.geom.Rectangle b = node().getBounds(); + return new Rectangle(b.getX(), b.getY(), b.getWidth(), b.getHeight()); + } + public void setBounds(Rectangle r) { } + public Dimension getSize() { Rectangle b = getBounds(); return new Dimension(b.width, b.height); } + public void setSize(Dimension d) { } + public Accessible getAccessibleAt(Point p) { + AccessibilityNodeSnapshot n = tree().getNodeAt(p.x, p.y); + return n == null ? null : accessible(n.getId()); + } + public boolean isFocusTraversable() { return node() != null && node().isFocusable(); } + public void requestFocus() { implementation.performAccessibilityAction(id, AccessibilityAction.FOCUS, null); } + public void addFocusListener(FocusListener l) { canvas.addFocusListener(l); } + public void removeFocusListener(FocusListener l) { canvas.removeFocusListener(l); } + } + } + + private AccessibleStateSet states(AccessibilityNodeSnapshot node) { + AccessibleStateSet states = new AccessibleStateSet(); + if (node == null) return states; + if (!Boolean.FALSE.equals(node.getEnabled())) states.add(AccessibleState.ENABLED); + if (node.getBounds().getWidth() > 0 && node.getBounds().getHeight() > 0) { + states.add(AccessibleState.VISIBLE); + if (canvas.isShowing()) states.add(AccessibleState.SHOWING); + } + if (node.isFocusable()) states.add(AccessibleState.FOCUSABLE); + if (node.isFocused()) states.add(AccessibleState.FOCUSED); + if (Boolean.TRUE.equals(node.getSelected())) states.add(AccessibleState.SELECTED); + if (node.getChecked() == AccessibilityCheckedState.CHECKED) states.add(AccessibleState.CHECKED); + if (Boolean.TRUE.equals(node.getExpanded())) states.add(AccessibleState.EXPANDED); + if (Boolean.FALSE.equals(node.getExpanded())) states.add(AccessibleState.COLLAPSED); + if (Boolean.TRUE.equals(node.getBusy())) states.add(AccessibleState.BUSY); + if (!Boolean.TRUE.equals(node.getReadOnly()) && (node.getRole() == AccessibilityRole.TEXT_FIELD + || node.getRole() == AccessibilityRole.SEARCH_FIELD)) states.add(AccessibleState.EDITABLE); + if (Boolean.TRUE.equals(node.getMultiline())) states.add(AccessibleState.MULTI_LINE); + return states; + } + + private AccessibleRole role(AccessibilityRole role) { + switch (role) { + case BUTTON: return AccessibleRole.PUSH_BUTTON; + case TOGGLE_BUTTON: return AccessibleRole.TOGGLE_BUTTON; + case CHECKBOX: return AccessibleRole.CHECK_BOX; + case RADIO_BUTTON: return AccessibleRole.RADIO_BUTTON; + case SWITCH: return AccessibleRole.TOGGLE_BUTTON; + case HEADING: + case STATIC_TEXT: return AccessibleRole.LABEL; + case LINK: return AccessibleRole.HYPERLINK; + case IMAGE: return AccessibleRole.ICON; + case TEXT_FIELD: + case SEARCH_FIELD: return AccessibleRole.TEXT; + case SLIDER: return AccessibleRole.SLIDER; + case PROGRESS_BAR: return AccessibleRole.PROGRESS_BAR; + case LIST: return AccessibleRole.LIST; + case LIST_ITEM: return AccessibleRole.LIST_ITEM; + case GRID: return AccessibleRole.TABLE; + case CELL: return AccessibleRole.UNKNOWN; + case TAB_LIST: return AccessibleRole.PAGE_TAB_LIST; + case TAB: return AccessibleRole.PAGE_TAB; + case DIALOG: return AccessibleRole.DIALOG; + case ALERT: return AccessibleRole.ALERT; + case MENU: return AccessibleRole.MENU; + case MENU_ITEM: return AccessibleRole.MENU_ITEM; + case TOOLBAR: return AccessibleRole.TOOL_BAR; + case SCROLL_BAR: return AccessibleRole.SCROLL_BAR; + case COMBO_BOX: return AccessibleRole.COMBO_BOX; + case TREE: return AccessibleRole.TREE; + case SEPARATOR: return AccessibleRole.SEPARATOR; + default: return AccessibleRole.PANEL; + } + } +} diff --git a/Ports/JavaSE/src/com/codename1/impl/javase/JavaSEPort.java b/Ports/JavaSE/src/com/codename1/impl/javase/JavaSEPort.java index cd310f49673..e9572232cfd 100644 --- a/Ports/JavaSE/src/com/codename1/impl/javase/JavaSEPort.java +++ b/Ports/JavaSE/src/com/codename1/impl/javase/JavaSEPort.java @@ -2456,6 +2456,7 @@ public int getCanvasY() { } protected class C extends JPanel implements KeyListener, MouseListener, MouseMotionListener, HierarchyBoundsListener, AdjustmentListener, MouseWheelListener { + private JavaSEAccessibility cn1Accessibility; private BufferedImage buffer; boolean painted; private Graphics2D g2dInstance; @@ -2490,6 +2491,18 @@ public void hierarchyChanged(HierarchyEvent e) { requestFocus(); } + @Override + public javax.accessibility.AccessibleContext getAccessibleContext() { + if (cn1Accessibility == null) { + cn1Accessibility = new JavaSEAccessibility(this, JavaSEPort.this); + } + return cn1Accessibility.getContext(); + } + + void accessibilityChanged(int changeType) { + if (cn1Accessibility != null) cn1Accessibility.changed(changeType); + } + private void installNativeMagnificationListeners() { installMagnificationWheelFallbackListener(); installNativeMagnificationListener(this); @@ -3767,6 +3780,20 @@ public JavaSEPort() { instance = this; } + @Override + public void accessibilityTreeChanged(final int changeType) { + EventQueue.invokeLater(new Runnable() { + public void run() { + if (canvas != null) canvas.accessibilityChanged(changeType); + } + }); + } + + @Override + public boolean isAccessibilityTreeSupported() { + return true; + } + public void paintDirty() { super.paintDirty(); } diff --git a/Ports/JavaScriptPort/src/main/java/com/codename1/impl/html5/HTML5Implementation.java b/Ports/JavaScriptPort/src/main/java/com/codename1/impl/html5/HTML5Implementation.java index 4048f72fce7..9fb7ee00561 100644 --- a/Ports/JavaScriptPort/src/main/java/com/codename1/impl/html5/HTML5Implementation.java +++ b/Ports/JavaScriptPort/src/main/java/com/codename1/impl/html5/HTML5Implementation.java @@ -87,6 +87,14 @@ import com.codename1.ui.events.FocusListener; import com.codename1.ui.events.MessageEvent; import com.codename1.ui.geom.Rectangle; +import com.codename1.ui.accessibility.AccessibilityAction; +import com.codename1.ui.accessibility.AccessibilityCheckedState; +import com.codename1.ui.accessibility.AccessibilityCollectionItemInfo; +import com.codename1.ui.accessibility.AccessibilityLiveRegion; +import com.codename1.ui.accessibility.AccessibilityNodeSnapshot; +import com.codename1.ui.accessibility.AccessibilityRange; +import com.codename1.ui.accessibility.AccessibilityRole; +import com.codename1.ui.accessibility.AccessibilityTreeSnapshot; import com.codename1.ui.geom.Shape; import com.codename1.ui.layouts.BorderLayout; import com.codename1.ui.layouts.BoxLayout; @@ -571,6 +579,7 @@ private boolean hitTest(int x, int y) { * Container for all peer components. */ HTMLElement peersContainer; + private HTMLElement accessibilityContainer; /** @@ -1255,6 +1264,13 @@ private void __init() { peersContainer = (HTMLElement)document.createElement("div"); peersContainer.setAttribute("id", "cn1-peers-container"); outputCanvas.getParentNode().insertBefore(peersContainer, outputCanvas); + accessibilityContainer = (HTMLElement)document.createElement("div"); + accessibilityContainer.setAttribute("id", "cn1-accessibility-tree"); + accessibilityContainer.setAttribute("role", "application"); + accessibilityContainer.getStyle().setCssText("position:absolute;left:0;top:0;width:100%;height:100%;overflow:hidden;pointer-events:none;z-index:2147483646;"); + outputCanvas.getParentNode().insertBefore(accessibilityContainer, outputCanvas); + outputCanvas.setAttribute("role", "presentation"); + outputCanvas.setAttribute("aria-hidden", "true"); nativeEdt = EasyThread.start("NativeEDT"); @@ -2854,6 +2870,191 @@ public void revalidate() { } } + + @Override + public void accessibilityTreeChanged(int changeType) { + if (accessibilityContainer == null) return; + AccessibilityTreeSnapshot tree = getAccessibilityTreeSnapshot(); + accessibilityContainer.setInnerHTML(""); + final Map elements = new HashMap(); + for (AccessibilityNodeSnapshot node : tree.getNodes().values()) { + final long nodeId = node.getId(); + final HTMLElement element = (HTMLElement)document.createElement("div"); + elements.put(Long.valueOf(nodeId), element); + element.setAttribute("data-cn1-accessibility-id", String.valueOf(nodeId)); + applyAria(element, node); + if (node.getParentId() >= 0 && elements.get(Long.valueOf(node.getParentId())) != null) { + elements.get(Long.valueOf(node.getParentId())).appendChild(element); + } else { + accessibilityContainer.appendChild(element); + } + final AccessibilityAction activate = node.getAction(AccessibilityAction.ACTIVATE); + if (activate != null && activate.isEnabled()) { + element.addEventListener("click", new EventListener() { + public void handleEvent(Event event) { + event.preventDefault(); + event.stopPropagation(); + performAccessibilityAction(nodeId, AccessibilityAction.ACTIVATE, null); + } + }); + } + final AccessibilityAction focus = node.getAction(AccessibilityAction.FOCUS); + if (focus != null && focus.isEnabled()) { + element.addEventListener("focus", new EventListener() { + public void handleEvent(Event event) { + performAccessibilityAction(nodeId, AccessibilityAction.FOCUS, null); + } + }); + } + element.addEventListener("keydown", new EventListener() { + public void handleEvent(Event event) { + JSOImplementations.KeyEvent key = (JSOImplementations.KeyEvent)event; + int code = key.getKeyCode(); + if ((code == 13 || code == 32) && activate != null) { + event.preventDefault(); + performAccessibilityAction(nodeId, AccessibilityAction.ACTIVATE, null); + } else if (code == 38 || code == 39) { + performAccessibilityAction(nodeId, AccessibilityAction.INCREMENT, null); + } else if (code == 37 || code == 40) { + performAccessibilityAction(nodeId, AccessibilityAction.DECREMENT, null); + } + } + }); + addWebCustomActions(element, node); + } + } + + @Override + public boolean isAccessibilityTreeSupported() { + return true; + } + + private void applyAria(HTMLElement element, AccessibilityNodeSnapshot node) { + String role = ariaRole(node.getRole()); + if (role != null) element.setAttribute("role", role); + if (node.getLabel() != null) element.setAttribute("aria-label", node.getLabel()); + String description = node.getDescription(); + if (node.getHint() != null) description = description == null ? node.getHint() : description + ". " + node.getHint(); + if (node.getValidationError() != null) description = description == null ? node.getValidationError() : description + ". " + node.getValidationError(); + if (description != null) element.setAttribute("aria-description", description); + if (node.getIdentifier() != null) element.setAttribute("id", node.getIdentifier()); + if (node.getRoleDescription() != null) element.setAttribute("aria-roledescription", node.getRoleDescription()); + if (node.getValue() != null) element.setAttribute("aria-valuetext", node.getValue()); + if (node.getSelected() != null) element.setAttribute("aria-selected", String.valueOf(node.getSelected())); + if (node.getExpanded() != null) element.setAttribute("aria-expanded", String.valueOf(node.getExpanded())); + if (node.getEnabled() != null && !node.getEnabled().booleanValue()) element.setAttribute("aria-disabled", "true"); + if (node.getInvalid() != null) element.setAttribute("aria-invalid", String.valueOf(node.getInvalid())); + if (node.getBusy() != null) element.setAttribute("aria-busy", String.valueOf(node.getBusy())); + if (node.getReadOnly() != null) element.setAttribute("aria-readonly", String.valueOf(node.getReadOnly())); + if (node.getRequired() != null) element.setAttribute("aria-required", String.valueOf(node.getRequired())); + if (node.getMultiline() != null) element.setAttribute("aria-multiline", String.valueOf(node.getMultiline())); + if (node.getCurrent() != null && node.getCurrent().booleanValue()) element.setAttribute("aria-current", "true"); + if (node.isModal()) element.setAttribute("aria-modal", "true"); + if (node.getHeadingLevel() > 0) element.setAttribute("aria-level", String.valueOf(node.getHeadingLevel())); + if (node.getChecked() != AccessibilityCheckedState.UNSPECIFIED) { + element.setAttribute("aria-checked", node.getChecked() == AccessibilityCheckedState.MIXED + ? "mixed" : String.valueOf(node.getChecked() == AccessibilityCheckedState.CHECKED)); + } + if (node.getPressed() != null) element.setAttribute("aria-pressed", String.valueOf(node.getPressed())); + if (node.getLiveRegion() != AccessibilityLiveRegion.OFF) { + element.setAttribute("aria-live", node.getLiveRegion() == AccessibilityLiveRegion.ASSERTIVE ? "assertive" : "polite"); + element.setAttribute("aria-atomic", "true"); + } + AccessibilityRange range = node.getRange(); + if (range != null) { + element.setAttribute("aria-valuemin", String.valueOf(range.getMinimum())); + element.setAttribute("aria-valuemax", String.valueOf(range.getMaximum())); + element.setAttribute("aria-valuenow", String.valueOf(range.getCurrent())); + if (range.getText() != null) element.setAttribute("aria-valuetext", range.getText()); + } + AccessibilityCollectionItemInfo item = node.getCollectionItemInfo(); + if (item != null) { + if (item.getPositionInSet() > 0) element.setAttribute("aria-posinset", String.valueOf(item.getPositionInSet())); + if (item.getSetSize() != 0) element.setAttribute("aria-setsize", String.valueOf(item.getSetSize())); + if (item.getLevel() > 0) element.setAttribute("aria-level", String.valueOf(item.getLevel())); + if (item.getRowIndex() >= 0) element.setAttribute("aria-rowindex", String.valueOf(item.getRowIndex() + 1)); + if (item.getColumnIndex() >= 0) element.setAttribute("aria-colindex", String.valueOf(item.getColumnIndex() + 1)); + if (item.getRowSpan() > 1) element.setAttribute("aria-rowspan", String.valueOf(item.getRowSpan())); + if (item.getColumnSpan() > 1) element.setAttribute("aria-colspan", String.valueOf(item.getColumnSpan())); + } + Rectangle bounds = node.getBounds(); + double ratio = getDevicePixelRatio(); + element.getStyle().setCssText("position:absolute;opacity:0.001;pointer-events:none;overflow:hidden;" + + "left:" + bounds.getX() / ratio + "px;top:" + bounds.getY() / ratio + "px;" + + "width:" + Math.max(1, bounds.getWidth()) / ratio + "px;height:" + + Math.max(1, bounds.getHeight()) / ratio + "px;"); + if (node.isFocusable()) element.setTabIndex(0); + else element.setTabIndex(-1); + if (node.getRole() == AccessibilityRole.STATIC_TEXT || node.getRole() == AccessibilityRole.HEADING) { + element.setTextContent(node.getLabel() == null ? "" : node.getLabel()); + } + } + + private void addWebCustomActions(HTMLElement parent, AccessibilityNodeSnapshot node) { + for (final AccessibilityAction action : node.getActions()) { + if (!action.isEnabled() || isStandardWebAction(action.getId())) continue; + final long nodeId = node.getId(); + HTMLElement button = (HTMLElement)document.createElement("button"); + button.setAttribute("type", "button"); + button.setAttribute("aria-label", action.getLabel() == null ? action.getId() : action.getLabel()); + button.setTextContent(action.getLabel() == null ? action.getId() : action.getLabel()); + button.getStyle().setCssText("position:absolute;opacity:0.001;pointer-events:none;width:1px;height:1px;"); + button.addEventListener("click", new EventListener() { + public void handleEvent(Event event) { + event.preventDefault(); + performAccessibilityAction(nodeId, action.getId(), null); + } + }); + parent.appendChild(button); + } + } + + private boolean isStandardWebAction(String id) { + return AccessibilityAction.ACTIVATE.equals(id) || AccessibilityAction.FOCUS.equals(id) + || AccessibilityAction.INCREMENT.equals(id) || AccessibilityAction.DECREMENT.equals(id) + || AccessibilityAction.SET_TEXT.equals(id) || AccessibilityAction.SCROLL_FORWARD.equals(id) + || AccessibilityAction.SCROLL_BACKWARD.equals(id); + } + + private String ariaRole(AccessibilityRole role) { + switch (role) { + case BUTTON: + case TOGGLE_BUTTON: return "button"; + case CHECKBOX: return "checkbox"; + case RADIO_BUTTON: return "radio"; + case SWITCH: return "switch"; + case HEADING: return "heading"; + case LINK: return "link"; + case IMAGE: return "img"; + case TEXT_FIELD: return "textbox"; + case SEARCH_FIELD: return "searchbox"; + case SLIDER: return "slider"; + case PROGRESS_BAR: return "progressbar"; + case LIST: return "list"; + case LIST_ITEM: return "listitem"; + case GRID: return "grid"; + case ROW: return "row"; + case CELL: return "gridcell"; + case COLUMN_HEADER: return "columnheader"; + case ROW_HEADER: return "rowheader"; + case TAB_LIST: return "tablist"; + case TAB: return "tab"; + case TAB_PANEL: return "tabpanel"; + case DIALOG: return "dialog"; + case ALERT: return "alert"; + case MENU: return "menu"; + case MENU_ITEM: return "menuitem"; + case TOOLBAR: return "toolbar"; + case SCROLL_BAR: return "scrollbar"; + case SPIN_BUTTON: return "spinbutton"; + case COMBO_BOX: return "combobox"; + case TREE: return "tree"; + case TREE_ITEM: return "treeitem"; + case SEPARATOR: return "separator"; + case GENERIC: return "group"; + default: return null; + } + } public static void setMainClass(Object main) { JavaScriptBootstrapCoordinator.bindMainClass(main, diff --git a/Ports/LinuxPort/nativeSources/cn1_linux.h b/Ports/LinuxPort/nativeSources/cn1_linux.h index 97aa5f4a8a7..7a1de5a5268 100644 --- a/Ports/LinuxPort/nativeSources/cn1_linux.h +++ b/Ports/LinuxPort/nativeSources/cn1_linux.h @@ -69,7 +69,8 @@ typedef enum { * ROTATE. drainInput decodes these into Display.fireMagnifyGesture / * fireRotationGesture, the same hooks the macOS trackpad drives. */ CN1_EVENT_PINCH = 10, - CN1_EVENT_ROTATE = 11 + CN1_EVENT_ROTATE = 11, + CN1_EVENT_ACCESSIBILITY_ACTION = 12 } CN1EventType; /* Fixed-point scale for the gesture keyCode field (see CN1_EVENT_PINCH). */ diff --git a/Ports/LinuxPort/nativeSources/cn1_linux_window.c b/Ports/LinuxPort/nativeSources/cn1_linux_window.c index 8e5d032e3bd..b21b0a0c3a4 100644 --- a/Ports/LinuxPort/nativeSources/cn1_linux_window.c +++ b/Ports/LinuxPort/nativeSources/cn1_linux_window.c @@ -95,6 +95,7 @@ static GtkWidget* cn1Window = 0; static GtkWidget* cn1DrawingArea = 0; static GtkWidget* cn1Overlay = 0; /* GtkOverlay: drawing area + native widget layer */ static GtkWidget* cn1Fixed = 0; /* GtkFixed overlay hosting positioned native peers */ +static GtkWidget* cn1AccessibilityFixed = 0; /* transparent GTK/ATK semantic hierarchy */ static CN1Graphics cn1WindowG; /* the on-screen / headless back buffer */ static int cn1DisplayWidth = 800; static int cn1DisplayHeight = 600; @@ -602,6 +603,10 @@ JAVA_VOID com_codename1_impl_linux_LinuxNative_initDisplay___java_lang_String_in cn1Fixed = gtk_fixed_new(); gtk_overlay_add_overlay(GTK_OVERLAY(cn1Overlay), cn1Fixed); gtk_overlay_set_overlay_pass_through(GTK_OVERLAY(cn1Overlay), cn1Fixed, TRUE); + cn1AccessibilityFixed = gtk_fixed_new(); + gtk_widget_set_opacity(cn1AccessibilityFixed, 0.01); + gtk_overlay_add_overlay(GTK_OVERLAY(cn1Overlay), cn1AccessibilityFixed); + gtk_overlay_set_overlay_pass_through(GTK_OVERLAY(cn1Overlay), cn1AccessibilityFixed, TRUE); gtk_container_add(GTK_CONTAINER(cn1Window), cn1Overlay); g_signal_connect(cn1DrawingArea, "draw", G_CALLBACK(cn1OnDraw), 0); @@ -714,6 +719,223 @@ JAVA_BOOLEAN com_codename1_impl_linux_LinuxNative_pollEvent___int_1ARRAY_R_boole return JAVA_FALSE; } +/* ------------------------------------------------ accessibility / AT-SPI */ + +typedef struct CN1A11yEntry { + long long id; + long long parentId; + GtkWidget* widget; + int x, y; + struct CN1A11yEntry* next; +} CN1A11yEntry; + +typedef struct { + long long nodeId; + int actionHash; + char* actionId; + char* label; +} CN1A11yAction; + +static CN1A11yEntry* cn1A11yEntries = 0; + +static void cn1A11yFreeEntries(void) { + CN1A11yEntry* entry = cn1A11yEntries; + while (entry) { + CN1A11yEntry* next = entry->next; + free(entry); + entry = next; + } + cn1A11yEntries = 0; +} + +static CN1A11yEntry* cn1A11yFind(long long id) { + CN1A11yEntry* entry; + for (entry = cn1A11yEntries; entry; entry = entry->next) { + if (entry->id == id) return entry; + } + return 0; +} + +static AtkRole cn1A11yRole(const char* role) { + if (!role) return ATK_ROLE_PANEL; + if (!strcmp(role, "BUTTON") || !strcmp(role, "TOGGLE_BUTTON")) return ATK_ROLE_PUSH_BUTTON; + if (!strcmp(role, "CHECKBOX")) return ATK_ROLE_CHECK_BOX; + if (!strcmp(role, "RADIO_BUTTON")) return ATK_ROLE_RADIO_BUTTON; + if (!strcmp(role, "SWITCH")) return ATK_ROLE_TOGGLE_BUTTON; + if (!strcmp(role, "HEADING")) return ATK_ROLE_HEADING; + if (!strcmp(role, "LINK")) return ATK_ROLE_LINK; + if (!strcmp(role, "IMAGE")) return ATK_ROLE_IMAGE; + if (!strcmp(role, "STATIC_TEXT")) return ATK_ROLE_LABEL; + if (!strcmp(role, "TEXT_FIELD") || !strcmp(role, "SEARCH_FIELD")) return ATK_ROLE_ENTRY; + if (!strcmp(role, "SLIDER")) return ATK_ROLE_SLIDER; + if (!strcmp(role, "PROGRESS_BAR")) return ATK_ROLE_PROGRESS_BAR; + if (!strcmp(role, "LIST")) return ATK_ROLE_LIST; + if (!strcmp(role, "LIST_ITEM")) return ATK_ROLE_LIST_ITEM; + if (!strcmp(role, "GRID")) return ATK_ROLE_TABLE; + if (!strcmp(role, "ROW")) return ATK_ROLE_TABLE_ROW; + if (!strcmp(role, "CELL")) return ATK_ROLE_TABLE_CELL; + if (!strcmp(role, "COLUMN_HEADER")) return ATK_ROLE_COLUMN_HEADER; + if (!strcmp(role, "ROW_HEADER")) return ATK_ROLE_ROW_HEADER; + if (!strcmp(role, "TAB_LIST")) return ATK_ROLE_PAGE_TAB_LIST; + if (!strcmp(role, "TAB")) return ATK_ROLE_PAGE_TAB; + if (!strcmp(role, "DIALOG")) return ATK_ROLE_DIALOG; + if (!strcmp(role, "ALERT")) return ATK_ROLE_ALERT; + if (!strcmp(role, "MENU")) return ATK_ROLE_MENU; + if (!strcmp(role, "MENU_ITEM")) return ATK_ROLE_MENU_ITEM; + if (!strcmp(role, "TOOLBAR")) return ATK_ROLE_TOOL_BAR; + if (!strcmp(role, "SCROLL_BAR")) return ATK_ROLE_SCROLL_BAR; + if (!strcmp(role, "COMBO_BOX")) return ATK_ROLE_COMBO_BOX; + if (!strcmp(role, "TREE")) return ATK_ROLE_TREE; + if (!strcmp(role, "TREE_ITEM")) return ATK_ROLE_TREE_ITEM; + if (!strcmp(role, "SEPARATOR")) return ATK_ROLE_SEPARATOR; + return ATK_ROLE_PANEL; +} + +static void cn1A11yBeginMain(void* ignored) { + (void) ignored; + cn1A11yFreeEntries(); + if (cn1AccessibilityFixed) { + GList* children = gtk_container_get_children(GTK_CONTAINER(cn1AccessibilityFixed)); + GList* item; + for (item = children; item; item = item->next) { + gtk_widget_destroy(GTK_WIDGET(item->data)); + } + g_list_free(children); + } +} + +JAVA_VOID com_codename1_impl_linux_LinuxNative_accessibilityBegin__(CODENAME_ONE_THREAD_STATE) { + cn1LinuxRunOnMainAndWait(cn1A11yBeginMain, 0); +} + +typedef struct { + long long id, parentId; + char *role, *label, *description, *value; + int x, y, width, height, flags; +} CN1A11yNodeCall; + +static GtkWidget* cn1A11yWidget(const char* role, const char* label, const char* value, int flags) { + GtkWidget* widget; + if (role && (!strcmp(role, "BUTTON") || !strcmp(role, "TOGGLE_BUTTON") || !strcmp(role, "SWITCH"))) { + widget = gtk_toggle_button_new_with_label(label ? label : ""); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), (flags & 0x30) == 0x20); + gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(widget), (flags & 0x30) == 0x30); + } else if (role && (!strcmp(role, "CHECKBOX") || !strcmp(role, "RADIO_BUTTON"))) { + widget = gtk_check_button_new_with_label(label ? label : ""); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), (flags & 0x30) == 0x20); + gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(widget), (flags & 0x30) == 0x30); + } else if (role && (!strcmp(role, "TEXT_FIELD") || !strcmp(role, "SEARCH_FIELD"))) { + widget = gtk_entry_new(); + if (value) gtk_entry_set_text(GTK_ENTRY(widget), value); + } else if (role && (!strcmp(role, "SLIDER") || !strcmp(role, "PROGRESS_BAR"))) { + widget = gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, 0, 100, 1); + if (value) gtk_range_set_value(GTK_RANGE(widget), atof(value)); + } else { + widget = gtk_fixed_new(); + } + return widget; +} + +static void cn1A11yNodeMain(void* pointer) { + CN1A11yNodeCall* call = (CN1A11yNodeCall*) pointer; + CN1A11yEntry* parent = cn1A11yFind(call->parentId); + GtkWidget* host = parent ? parent->widget : cn1AccessibilityFixed; + GtkWidget* widget = cn1A11yWidget(call->role, call->label, call->value, call->flags); + AtkObject* accessible = gtk_widget_get_accessible(widget); + atk_object_set_role(accessible, cn1A11yRole(call->role)); + if (call->label) atk_object_set_name(accessible, call->label); + if (call->description) atk_object_set_description(accessible, call->description); + gtk_widget_set_can_focus(widget, (call->flags & 1) != 0); + gtk_widget_set_sensitive(widget, (call->flags & 4) != 0); + gtk_widget_set_size_request(widget, call->width > 0 ? call->width : 1, + call->height > 0 ? call->height : 1); + if (host && GTK_IS_FIXED(host)) { + int px = parent ? call->x - parent->x : call->x; + int py = parent ? call->y - parent->y : call->y; + gtk_fixed_put(GTK_FIXED(host), widget, px, py); + } else if (host && GTK_IS_CONTAINER(host)) { + gtk_container_add(GTK_CONTAINER(host), widget); + } + gtk_widget_show_all(widget); + CN1A11yEntry* entry = (CN1A11yEntry*) calloc(1, sizeof(CN1A11yEntry)); + entry->id = call->id; entry->parentId = call->parentId; entry->widget = widget; + entry->x = call->x; entry->y = call->y; entry->next = cn1A11yEntries; cn1A11yEntries = entry; + free(call->role); free(call->label); free(call->description); free(call->value); free(call); +} + +JAVA_VOID com_codename1_impl_linux_LinuxNative_accessibilityNode___long_long_java_lang_String_java_lang_String_java_lang_String_java_lang_String_int_int_int_int_int( + CODENAME_ONE_THREAD_STATE, JAVA_LONG id, JAVA_LONG parentId, JAVA_OBJECT role, JAVA_OBJECT label, + JAVA_OBJECT description, JAVA_OBJECT value, JAVA_INT x, JAVA_INT y, JAVA_INT width, JAVA_INT height, + JAVA_INT flags) { + extern const char* stringToUTF8(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT); + CN1A11yNodeCall* call = (CN1A11yNodeCall*) calloc(1, sizeof(CN1A11yNodeCall)); + call->id = id; call->parentId = parentId; call->x = x; call->y = y; + call->width = width; call->height = height; call->flags = flags; + call->role = role == JAVA_NULL ? 0 : strdup(stringToUTF8(threadStateData, role)); + call->label = label == JAVA_NULL ? 0 : strdup(stringToUTF8(threadStateData, label)); + call->description = description == JAVA_NULL ? 0 : strdup(stringToUTF8(threadStateData, description)); + call->value = value == JAVA_NULL ? 0 : strdup(stringToUTF8(threadStateData, value)); + cn1LinuxRunOnMainAndWait(cn1A11yNodeMain, call); +} + +static void cn1A11yActionActivated(GtkWidget* widget, gpointer pointer) { + CN1A11yAction* action = (CN1A11yAction*) pointer; + (void) widget; + cn1LinuxPushEvent(CN1_EVENT_ACCESSIBILITY_ACTION, (int) action->nodeId, 0, action->actionHash); +} + +static void cn1A11yActionFree(gpointer pointer, GClosure* closure) { + CN1A11yAction* action = (CN1A11yAction*) pointer; + (void) closure; + free(action->actionId); free(action->label); free(action); +} + +static void cn1A11yActionMain(void* pointer) { + CN1A11yAction* action = (CN1A11yAction*) pointer; + CN1A11yEntry* entry = cn1A11yFind(action->nodeId); + if (!entry) { cn1A11yActionFree(action, 0); return; } + if (!strcmp(action->actionId, "activate") || !strcmp(action->actionId, "focus")) { + if (GTK_IS_BUTTON(entry->widget)) { + g_signal_connect_data(entry->widget, "clicked", G_CALLBACK(cn1A11yActionActivated), action, + cn1A11yActionFree, 0); + return; + } + } else { + GtkWidget* custom = gtk_button_new_with_label(action->label ? action->label : action->actionId); + AtkObject* accessible = gtk_widget_get_accessible(custom); + atk_object_set_name(accessible, action->label ? action->label : action->actionId); + atk_object_set_description(accessible, "Custom accessibility action"); + gtk_widget_set_size_request(custom, entry->widget ? gtk_widget_get_allocated_width(entry->widget) : 1, + entry->widget ? gtk_widget_get_allocated_height(entry->widget) : 1); + gtk_fixed_put(GTK_FIXED(cn1AccessibilityFixed), custom, entry->x, entry->y); + gtk_widget_show(custom); + g_signal_connect_data(custom, "clicked", G_CALLBACK(cn1A11yActionActivated), action, + cn1A11yActionFree, 0); + return; + } + cn1A11yActionFree(action, 0); +} + +JAVA_VOID com_codename1_impl_linux_LinuxNative_accessibilityAction___long_java_lang_String_int_java_lang_String( + CODENAME_ONE_THREAD_STATE, JAVA_LONG nodeId, JAVA_OBJECT actionId, JAVA_INT actionHash, JAVA_OBJECT label) { + extern const char* stringToUTF8(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT); + CN1A11yAction* action = (CN1A11yAction*) calloc(1, sizeof(CN1A11yAction)); + action->nodeId = nodeId; action->actionHash = actionHash; + action->actionId = actionId == JAVA_NULL ? strdup("") : strdup(stringToUTF8(threadStateData, actionId)); + action->label = label == JAVA_NULL ? 0 : strdup(stringToUTF8(threadStateData, label)); + cn1LinuxRunOnMainAndWait(cn1A11yActionMain, action); +} + +static void cn1A11yEndMain(void* pointer) { + (void) pointer; + if (cn1AccessibilityFixed) gtk_widget_show_all(cn1AccessibilityFixed); +} + +JAVA_VOID com_codename1_impl_linux_LinuxNative_accessibilityEnd___int(CODENAME_ONE_THREAD_STATE, JAVA_INT changeType) { + (void) changeType; + cn1LinuxRunOnMainAndWait(cn1A11yEndMain, 0); +} + JAVA_BOOLEAN com_codename1_impl_linux_LinuxNative_pumpMessages___R_boolean(CODENAME_ONE_THREAD_STATE) { /* Process all pending GTK events, then block briefly for the next one so the * loop yields the CPU. Returns false once the window has been closed. */ diff --git a/Ports/LinuxPort/src/com/codename1/impl/linux/LinuxImplementation.java b/Ports/LinuxPort/src/com/codename1/impl/linux/LinuxImplementation.java index 0ad7ab4eda3..53a4fc02dcb 100644 --- a/Ports/LinuxPort/src/com/codename1/impl/linux/LinuxImplementation.java +++ b/Ports/LinuxPort/src/com/codename1/impl/linux/LinuxImplementation.java @@ -35,6 +35,10 @@ import com.codename1.ui.Stroke; import com.codename1.ui.geom.PathIterator; import com.codename1.ui.geom.Shape; +import com.codename1.ui.accessibility.AccessibilityAction; +import com.codename1.ui.accessibility.AccessibilityManager; +import com.codename1.ui.accessibility.AccessibilityNodeSnapshot; +import com.codename1.ui.accessibility.AccessibilityTreeSnapshot; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ByteArrayInputStream; @@ -80,6 +84,7 @@ public class LinuxImplementation extends CodenameOneImplementation { private static final int EVENT_MOUSE_HWHEEL = 9; private static final int EVENT_PINCH = 10; private static final int EVENT_ROTATE = 11; + private static final int EVENT_ACCESSIBILITY_ACTION = 12; // The native gesture events encode their float (incremental scale / radians) as // an int in 1/10000 units; see CN1_GESTURE_FIXED in cn1_linux.h. @@ -681,6 +686,9 @@ private void drainInput() { case EVENT_CLOSE: Display.getInstance().exitApplication(); break; + case EVENT_ACCESSIBILITY_ACTION: + AccessibilityManager.getInstance().performActionByHash(x & 0xffffffffL, key, null); + break; default: break; } @@ -693,6 +701,49 @@ private void drainInput() { } } + @Override + public void accessibilityTreeChanged(int changeType) { + AccessibilityTreeSnapshot tree = getAccessibilityTreeSnapshot(); + LinuxNative.accessibilityBegin(); + for (AccessibilityNodeSnapshot node : tree.getNodes().values()) { + int flags = (node.isFocusable() ? 1 : 0) | (node.isFocused() ? 2 : 0) + | (Boolean.TRUE.equals(node.getEnabled()) ? 4 : 0) + | (Boolean.TRUE.equals(node.getSelected()) ? 8 : 0) + | (node.getChecked().ordinal() << 4) + | (Boolean.TRUE.equals(node.getExpanded()) ? 64 : 0) + | (Boolean.TRUE.equals(node.getInvalid()) ? 128 : 0); + com.codename1.ui.geom.Rectangle b = node.getBounds(); + LinuxNative.accessibilityNode(node.getId(), node.getParentId(), node.getRole().name(), node.getLabel(), + joinDescription(node), node.getValue(), b.getX(), b.getY(), b.getWidth(), b.getHeight(), flags); + for (AccessibilityAction action : node.getActions()) { + if (action.isEnabled()) { + LinuxNative.accessibilityAction(node.getId(), action.getId(), action.getId().hashCode(), + action.getLabel() == null ? action.getId() : action.getLabel()); + } + } + } + LinuxNative.accessibilityEnd(changeType); + } + + private String joinDescription(AccessibilityNodeSnapshot node) { + StringBuilder out = new StringBuilder(); + if (node.getHint() != null) out.append(node.getHint()); + if (node.getDescription() != null) { + if (out.length() > 0) out.append(". "); + out.append(node.getDescription()); + } + if (node.getValidationError() != null) { + if (out.length() > 0) out.append(". "); + out.append(node.getValidationError()); + } + return out.length() == 0 ? null : out.toString(); + } + + @Override + public boolean isAccessibilityTreeSupported() { + return true; + } + /* --------------------------------------------------- local notifications * Desktop semantic (mirrors the JavaSE port): while the app runs, a Timer * fires the notification at its scheduled time and Shell_NotifyIcon shows a diff --git a/Ports/LinuxPort/src/com/codename1/impl/linux/LinuxNative.java b/Ports/LinuxPort/src/com/codename1/impl/linux/LinuxNative.java index dd4d719d858..820bc659a3a 100644 --- a/Ports/LinuxPort/src/com/codename1/impl/linux/LinuxNative.java +++ b/Ports/LinuxPort/src/com/codename1/impl/linux/LinuxNative.java @@ -145,6 +145,13 @@ public static native void setTransform(long graphics, float m00, float m10, floa */ public static native boolean pollEvent(int[] out); + /** Rebuilds the GTK/ATK virtual accessibility hierarchy. */ + public static native void accessibilityBegin(); + public static native void accessibilityNode(long id, long parentId, String role, String label, + String description, String value, int x, int y, int width, int height, int stateFlags); + public static native void accessibilityAction(long nodeId, String actionId, int actionHash, String label); + public static native void accessibilityEnd(int changeType); + /** * True when the default seat has a touchscreen device, used for * {@code Display.isTouchScreen()}. diff --git a/Ports/WindowsPort/nativeSources/cn1_windows.h b/Ports/WindowsPort/nativeSources/cn1_windows.h index f044e2a0611..b576c550cc7 100644 --- a/Ports/WindowsPort/nativeSources/cn1_windows.h +++ b/Ports/WindowsPort/nativeSources/cn1_windows.h @@ -101,7 +101,8 @@ typedef enum { * ROTATE. drainInput decodes these into Display.fireMagnifyGesture / * fireRotationGesture, the same hooks the macOS trackpad drives. */ CN1_EVENT_PINCH = 10, - CN1_EVENT_ROTATE = 11 + CN1_EVENT_ROTATE = 11, + CN1_EVENT_ACCESSIBILITY_ACTION = 12 } CN1EventType; /* Fixed-point scale for the gesture keyCode field (see CN1_EVENT_PINCH). */ @@ -255,6 +256,7 @@ int cn1WinCreateWindow(const char* utf8Title, int width, int height); void cn1WinPushEvent(CN1EventType type, int x, int y, int keyCode); int cn1WinPollEvent(CN1Event* out); LRESULT CALLBACK cn1WinWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); +LRESULT cn1WinAccessibilityObject(HWND hwnd, WPARAM wParam, LPARAM lParam); /* BrowserComponent / WebView2 peer (cn1_windows_browser.cpp). The EDT-facing * native methods marshal each WebView2 operation to the main (pump) thread by diff --git a/Ports/WindowsPort/nativeSources/cn1_windows_accessibility.cpp b/Ports/WindowsPort/nativeSources/cn1_windows_accessibility.cpp new file mode 100644 index 00000000000..d70bb3d7976 --- /dev/null +++ b/Ports/WindowsPort/nativeSources/cn1_windows_accessibility.cpp @@ -0,0 +1,266 @@ +/* Native virtual accessibility tree for the lightweight Win32 port. */ +#ifdef _WIN32 + +#include "cn1_windows.h" +#include +#include +#include +#include +#include +#include + +#pragma comment(lib, "uiautomationcore.lib") +#pragma comment(lib, "oleaut32.lib") + +struct CN1UiaNode { + long long id, parent; + long long actionTarget; + std::wstring role, label, description, value; + int x, y, width, height, flags; + std::vector > actions; +}; + +static SRWLOCK cn1UiaLock = SRWLOCK_INIT; +static std::vector cn1UiaNodes; +static std::vector cn1UiaPending; + +static std::wstring cn1UiaWide(const char* value) { + if (!value) return std::wstring(); + int length = MultiByteToWideChar(CP_UTF8, 0, value, -1, NULL, 0); + if (length <= 1) return std::wstring(); + std::vector buffer((size_t) length); + MultiByteToWideChar(CP_UTF8, 0, value, -1, &buffer[0], length); + return std::wstring(&buffer[0]); +} + +static bool cn1UiaGet(long long id, CN1UiaNode& out) { + bool found = false; + AcquireSRWLockShared(&cn1UiaLock); + for (size_t i = 0; i < cn1UiaNodes.size(); ++i) { + if (cn1UiaNodes[i].id == id) { out = cn1UiaNodes[i]; found = true; break; } + } + ReleaseSRWLockShared(&cn1UiaLock); + return found; +} + +static long long cn1UiaNavigate(long long id, NavigateDirection direction) { + long long result = 0; + AcquireSRWLockShared(&cn1UiaLock); + if (id == 0) { + if (direction == NavigateDirection_FirstChild || direction == NavigateDirection_LastChild) { + for (size_t i = 0; i < cn1UiaNodes.size(); ++i) { + size_t index = direction == NavigateDirection_FirstChild ? i : cn1UiaNodes.size() - 1 - i; + if (cn1UiaNodes[index].parent < 0) { result = cn1UiaNodes[index].id; break; } + } + } + } else { + size_t current = cn1UiaNodes.size(); + for (size_t i = 0; i < cn1UiaNodes.size(); ++i) if (cn1UiaNodes[i].id == id) { current = i; break; } + if (current < cn1UiaNodes.size()) { + const CN1UiaNode& node = cn1UiaNodes[current]; + if (direction == NavigateDirection_Parent) result = node.parent < 0 ? 0 : node.parent; + if (direction == NavigateDirection_FirstChild || direction == NavigateDirection_LastChild) { + for (size_t i = 0; i < cn1UiaNodes.size(); ++i) { + size_t index = direction == NavigateDirection_FirstChild ? i : cn1UiaNodes.size() - 1 - i; + if (cn1UiaNodes[index].parent == id) { result = cn1UiaNodes[index].id; break; } + } + } + if (direction == NavigateDirection_NextSibling) { + for (size_t i = current + 1; i < cn1UiaNodes.size(); ++i) + if (cn1UiaNodes[i].parent == node.parent) { result = cn1UiaNodes[i].id; break; } + } + if (direction == NavigateDirection_PreviousSibling && current > 0) { + for (size_t i = current; i-- > 0; ) + if (cn1UiaNodes[i].parent == node.parent) { result = cn1UiaNodes[i].id; break; } + } + } + } + ReleaseSRWLockShared(&cn1UiaLock); + return result; +} + +static CONTROLTYPEID cn1UiaControlType(const std::wstring& role) { + if (role == L"BUTTON" || role == L"TOGGLE_BUTTON") return UIA_ButtonControlTypeId; + if (role == L"CHECKBOX" || role == L"SWITCH") return UIA_CheckBoxControlTypeId; + if (role == L"RADIO_BUTTON") return UIA_RadioButtonControlTypeId; + if (role == L"TEXT_FIELD" || role == L"SEARCH_FIELD") return UIA_EditControlTypeId; + if (role == L"SLIDER") return UIA_SliderControlTypeId; + if (role == L"PROGRESS_BAR") return UIA_ProgressBarControlTypeId; + if (role == L"LIST") return UIA_ListControlTypeId; + if (role == L"LIST_ITEM") return UIA_ListItemControlTypeId; + if (role == L"GRID") return UIA_DataGridControlTypeId; + if (role == L"ROW" || role == L"CELL") return UIA_DataItemControlTypeId; + if (role == L"TAB_LIST") return UIA_TabControlTypeId; + if (role == L"TAB") return UIA_TabItemControlTypeId; + if (role == L"DIALOG" || role == L"ALERT") return UIA_WindowControlTypeId; + if (role == L"MENU") return UIA_MenuControlTypeId; + if (role == L"MENU_ITEM") return UIA_MenuItemControlTypeId; + if (role == L"TOOLBAR") return UIA_ToolBarControlTypeId; + if (role == L"SCROLL_BAR") return UIA_ScrollBarControlTypeId; + if (role == L"COMBO_BOX") return UIA_ComboBoxControlTypeId; + if (role == L"TREE") return UIA_TreeControlTypeId; + if (role == L"TREE_ITEM") return UIA_TreeItemControlTypeId; + if (role == L"IMAGE") return UIA_ImageControlTypeId; + if (role == L"LINK") return UIA_HyperlinkControlTypeId; + if (role == L"STATIC_TEXT" || role == L"HEADING") return UIA_TextControlTypeId; + if (role == L"SEPARATOR") return UIA_SeparatorControlTypeId; + return UIA_GroupControlTypeId; +} + +class CN1UiaProvider : public IRawElementProviderSimple, public IRawElementProviderFragment, + public IRawElementProviderFragmentRoot, public IInvokeProvider { + LONG refs; + long long id; +public: + explicit CN1UiaProvider(long long nodeId) : refs(1), id(nodeId) {} + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** object) { + if (!object) return E_INVALIDARG; + *object = NULL; + if (iid == __uuidof(IUnknown) || iid == __uuidof(IRawElementProviderSimple)) + *object = static_cast(this); + else if (iid == __uuidof(IRawElementProviderFragment)) + *object = static_cast(this); + else if (iid == __uuidof(IRawElementProviderFragmentRoot) && id == 0) + *object = static_cast(this); + else if (iid == __uuidof(IInvokeProvider)) + *object = static_cast(this); + if (!*object) return E_NOINTERFACE; + AddRef(); return S_OK; + } + ULONG STDMETHODCALLTYPE AddRef() { return (ULONG) InterlockedIncrement(&refs); } + ULONG STDMETHODCALLTYPE Release() { ULONG value = (ULONG) InterlockedDecrement(&refs); if (!value) delete this; return value; } + + HRESULT STDMETHODCALLTYPE get_ProviderOptions(ProviderOptions* options) { + if (!options) return E_INVALIDARG; *options = ProviderOptions_ServerSideProvider; return S_OK; + } + HRESULT STDMETHODCALLTYPE GetPatternProvider(PATTERNID pattern, IUnknown** provider) { + if (!provider) return E_INVALIDARG; *provider = NULL; + CN1UiaNode node; + if (pattern == UIA_InvokePatternId && id != 0 && cn1UiaGet(id, node) && !node.actions.empty()) { + *provider = static_cast(this); AddRef(); + } + return S_OK; + } + HRESULT STDMETHODCALLTYPE GetPropertyValue(PROPERTYID property, VARIANT* value) { + if (!value) return E_INVALIDARG; + VariantInit(value); + if (id == 0) { + if (property == UIA_NamePropertyId) { value->vt = VT_BSTR; value->bstrVal = SysAllocString(L"Codename One"); } + else if (property == UIA_ControlTypePropertyId) { value->vt = VT_I4; value->lVal = UIA_WindowControlTypeId; } + else if (property == UIA_IsControlElementPropertyId || property == UIA_IsContentElementPropertyId) { value->vt = VT_BOOL; value->boolVal = VARIANT_TRUE; } + return S_OK; + } + CN1UiaNode node; if (!cn1UiaGet(id, node)) return UIA_E_ELEMENTNOTAVAILABLE; + if (property == UIA_NamePropertyId) { value->vt = VT_BSTR; value->bstrVal = SysAllocString(node.label.c_str()); } + else if (property == UIA_HelpTextPropertyId) { value->vt = VT_BSTR; value->bstrVal = SysAllocString(node.description.c_str()); } + else if (property == UIA_ValueValuePropertyId) { value->vt = VT_BSTR; value->bstrVal = SysAllocString(node.value.c_str()); } + else if (property == UIA_ControlTypePropertyId) { value->vt = VT_I4; value->lVal = cn1UiaControlType(node.role); } + else if (property == UIA_LocalizedControlTypePropertyId) { value->vt = VT_BSTR; value->bstrVal = SysAllocString(node.role.c_str()); } + else if (property == UIA_IsEnabledPropertyId) { value->vt = VT_BOOL; value->boolVal = (node.flags & 4) ? VARIANT_TRUE : VARIANT_FALSE; } + else if (property == UIA_HasKeyboardFocusPropertyId) { value->vt = VT_BOOL; value->boolVal = (node.flags & 2) ? VARIANT_TRUE : VARIANT_FALSE; } + else if (property == UIA_IsKeyboardFocusablePropertyId) { value->vt = VT_BOOL; value->boolVal = (node.flags & 1) ? VARIANT_TRUE : VARIANT_FALSE; } + else if (property == UIA_IsControlElementPropertyId || property == UIA_IsContentElementPropertyId) { value->vt = VT_BOOL; value->boolVal = VARIANT_TRUE; } + return S_OK; + } + HRESULT STDMETHODCALLTYPE get_HostRawElementProvider(IRawElementProviderSimple** provider) { + if (!provider) return E_INVALIDARG; *provider = NULL; + return id == 0 && cn1Win.hwnd ? UiaHostProviderFromHwnd(cn1Win.hwnd, provider) : S_OK; + } + HRESULT STDMETHODCALLTYPE Navigate(NavigateDirection direction, IRawElementProviderFragment** result) { + if (!result) return E_INVALIDARG; *result = NULL; + long long target = cn1UiaNavigate(id, direction); + if (target || (direction == NavigateDirection_Parent && id != 0)) *result = new CN1UiaProvider(target); + return S_OK; + } + HRESULT STDMETHODCALLTYPE GetRuntimeId(SAFEARRAY** runtimeId) { + if (!runtimeId) return E_INVALIDARG; *runtimeId = NULL; + if (id == 0) return S_OK; + SAFEARRAY* array = SafeArrayCreateVector(VT_I4, 0, 3); if (!array) return E_OUTOFMEMORY; + LONG indexes[] = {0, 1, 2}; int values[] = {UiaAppendRuntimeId, (int)(id >> 32), (int)id}; + for (int i = 0; i < 3; ++i) SafeArrayPutElement(array, &indexes[i], &values[i]); + *runtimeId = array; return S_OK; + } + HRESULT STDMETHODCALLTYPE get_BoundingRectangle(UiaRect* rectangle) { + if (!rectangle) return E_INVALIDARG; + if (id == 0) { RECT r; GetWindowRect(cn1Win.hwnd, &r); rectangle->left=r.left; rectangle->top=r.top; rectangle->width=r.right-r.left; rectangle->height=r.bottom-r.top; return S_OK; } + CN1UiaNode node; if (!cn1UiaGet(id, node)) return UIA_E_ELEMENTNOTAVAILABLE; + POINT point = {node.x, node.y}; ClientToScreen(cn1Win.hwnd, &point); + rectangle->left=point.x; rectangle->top=point.y; rectangle->width=node.width; rectangle->height=node.height; return S_OK; + } + HRESULT STDMETHODCALLTYPE GetEmbeddedFragmentRoots(SAFEARRAY** roots) { if (!roots) return E_INVALIDARG; *roots=NULL; return S_OK; } + HRESULT STDMETHODCALLTYPE SetFocus() { return S_OK; } + HRESULT STDMETHODCALLTYPE get_FragmentRoot(IRawElementProviderFragmentRoot** root) { + if (!root) return E_INVALIDARG; *root = new CN1UiaProvider(0); return S_OK; + } + HRESULT STDMETHODCALLTYPE ElementProviderFromPoint(double x, double y, IRawElementProviderFragment** result) { + if (!result) return E_INVALIDARG; *result=NULL; POINT p={(LONG)x,(LONG)y}; ScreenToClient(cn1Win.hwnd,&p); + long long found=0; AcquireSRWLockShared(&cn1UiaLock); + for (size_t i=0;i=n.x&&p.y>=n.y&&p.xRelease(); return result; +} + +extern "C" { +JAVA_VOID com_codename1_impl_windows_WindowsNative_accessibilityBegin__(CODENAME_ONE_THREAD_STATE) { + AcquireSRWLockExclusive(&cn1UiaLock); cn1UiaPending.clear(); ReleaseSRWLockExclusive(&cn1UiaLock); +} +JAVA_VOID com_codename1_impl_windows_WindowsNative_accessibilityNode___long_long_java_lang_String_java_lang_String_java_lang_String_java_lang_String_int_int_int_int_int( + CODENAME_ONE_THREAD_STATE, JAVA_LONG id, JAVA_LONG parent, JAVA_OBJECT role, JAVA_OBJECT label, + JAVA_OBJECT description, JAVA_OBJECT value, JAVA_INT x, JAVA_INT y, JAVA_INT width, JAVA_INT height, JAVA_INT flags) { + extern const char* stringToUTF8(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT); + CN1UiaNode node; node.id=id; node.parent=parent; node.actionTarget=id; node.x=x; node.y=y; node.width=width; node.height=height; node.flags=flags; + node.role=role==JAVA_NULL?L"":cn1UiaWide(stringToUTF8(threadStateData,role)); + node.label=label==JAVA_NULL?L"":cn1UiaWide(stringToUTF8(threadStateData,label)); + node.description=description==JAVA_NULL?L"":cn1UiaWide(stringToUTF8(threadStateData,description)); + node.value=value==JAVA_NULL?L"":cn1UiaWide(stringToUTF8(threadStateData,value)); + AcquireSRWLockExclusive(&cn1UiaLock); cn1UiaPending.push_back(node); ReleaseSRWLockExclusive(&cn1UiaLock); +} +JAVA_VOID com_codename1_impl_windows_WindowsNative_accessibilityAction___long_java_lang_String_int_java_lang_String( + CODENAME_ONE_THREAD_STATE, JAVA_LONG nodeId, JAVA_OBJECT actionId, JAVA_INT actionHash, JAVA_OBJECT label) { + extern const char* stringToUTF8(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT); + std::wstring idText=actionId==JAVA_NULL?L"":cn1UiaWide(stringToUTF8(threadStateData,actionId)); + std::wstring text=label==JAVA_NULL?L"":cn1UiaWide(stringToUTF8(threadStateData,label)); + AcquireSRWLockExclusive(&cn1UiaLock); + for(size_t i=0;iRelease(); +} +} + +#endif diff --git a/Ports/WindowsPort/nativeSources/cn1_windows_window.cpp b/Ports/WindowsPort/nativeSources/cn1_windows_window.cpp index a474397b938..94dd27557e2 100644 --- a/Ports/WindowsPort/nativeSources/cn1_windows_window.cpp +++ b/Ports/WindowsPort/nativeSources/cn1_windows_window.cpp @@ -471,6 +471,8 @@ static int cn1WinHandleGesture(HWND hwnd, LPARAM lParam) { LRESULT CALLBACK cn1WinWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { + case WM_GETOBJECT: + return cn1WinAccessibilityObject(hwnd, wParam, lParam); case WM_LBUTTONDOWN: cn1WinButtonDown(hwnd, CN1_PE_MASK_PRIMARY); cn1WinPushEvent(CN1_EVENT_POINTER_PRESSED, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), diff --git a/Ports/WindowsPort/src/com/codename1/impl/windows/WindowsImplementation.java b/Ports/WindowsPort/src/com/codename1/impl/windows/WindowsImplementation.java index 11e73024e38..763515be459 100644 --- a/Ports/WindowsPort/src/com/codename1/impl/windows/WindowsImplementation.java +++ b/Ports/WindowsPort/src/com/codename1/impl/windows/WindowsImplementation.java @@ -35,6 +35,10 @@ import com.codename1.ui.Stroke; import com.codename1.ui.geom.PathIterator; import com.codename1.ui.geom.Shape; +import com.codename1.ui.accessibility.AccessibilityAction; +import com.codename1.ui.accessibility.AccessibilityManager; +import com.codename1.ui.accessibility.AccessibilityNodeSnapshot; +import com.codename1.ui.accessibility.AccessibilityTreeSnapshot; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ByteArrayInputStream; @@ -71,6 +75,7 @@ public class WindowsImplementation extends CodenameOneImplementation { private static final int EVENT_MOUSE_HWHEEL = 9; private static final int EVENT_PINCH = 10; private static final int EVENT_ROTATE = 11; + private static final int EVENT_ACCESSIBILITY_ACTION = 12; // The native gesture events encode their float (incremental scale / radians) as // an int in 1/10000 units; see CN1_GESTURE_FIXED in cn1_windows.h. @@ -680,6 +685,9 @@ private void drainInput() { case EVENT_CLOSE: Display.getInstance().exitApplication(); break; + case EVENT_ACCESSIBILITY_ACTION: + AccessibilityManager.getInstance().performActionByHash(x & 0xffffffffL, key, null); + break; default: break; } @@ -692,6 +700,49 @@ private void drainInput() { } } + @Override + public void accessibilityTreeChanged(int changeType) { + AccessibilityTreeSnapshot tree = getAccessibilityTreeSnapshot(); + WindowsNative.accessibilityBegin(); + for (AccessibilityNodeSnapshot node : tree.getNodes().values()) { + int flags = (node.isFocusable() ? 1 : 0) | (node.isFocused() ? 2 : 0) + | (Boolean.TRUE.equals(node.getEnabled()) ? 4 : 0) + | (Boolean.TRUE.equals(node.getSelected()) ? 8 : 0) + | (node.getChecked().ordinal() << 4) + | (Boolean.TRUE.equals(node.getExpanded()) ? 64 : 0) + | (Boolean.TRUE.equals(node.getInvalid()) ? 128 : 0); + com.codename1.ui.geom.Rectangle b = node.getBounds(); + WindowsNative.accessibilityNode(node.getId(), node.getParentId(), node.getRole().name(), node.getLabel(), + accessibilityDescription(node), node.getValue(), b.getX(), b.getY(), b.getWidth(), b.getHeight(), flags); + for (AccessibilityAction action : node.getActions()) { + if (action.isEnabled()) { + WindowsNative.accessibilityAction(node.getId(), action.getId(), action.getId().hashCode(), + action.getLabel() == null ? action.getId() : action.getLabel()); + } + } + } + WindowsNative.accessibilityEnd(changeType); + } + + private String accessibilityDescription(AccessibilityNodeSnapshot node) { + StringBuilder out = new StringBuilder(); + if (node.getHint() != null) out.append(node.getHint()); + if (node.getDescription() != null) { + if (out.length() > 0) out.append(". "); + out.append(node.getDescription()); + } + if (node.getValidationError() != null) { + if (out.length() > 0) out.append(". "); + out.append(node.getValidationError()); + } + return out.length() == 0 ? null : out.toString(); + } + + @Override + public boolean isAccessibilityTreeSupported() { + return true; + } + /* --------------------------------------------------- local notifications * Desktop semantic (mirrors the JavaSE port): while the app runs, a Timer * fires the notification at its scheduled time and Shell_NotifyIcon shows a diff --git a/Ports/WindowsPort/src/com/codename1/impl/windows/WindowsNative.java b/Ports/WindowsPort/src/com/codename1/impl/windows/WindowsNative.java index c0bc766ff92..8d6d1d041e9 100644 --- a/Ports/WindowsPort/src/com/codename1/impl/windows/WindowsNative.java +++ b/Ports/WindowsPort/src/com/codename1/impl/windows/WindowsNative.java @@ -143,6 +143,13 @@ public static native void setTransform(long graphics, float m00, float m10, floa */ public static native boolean pollEvent(int[] out); + /** Rebuilds the Windows UI Automation virtual fragment tree. */ + public static native void accessibilityBegin(); + public static native void accessibilityNode(long id, long parentId, String role, String label, + String description, String value, int x, int y, int width, int height, int stateFlags); + public static native void accessibilityAction(long nodeId, String actionId, int actionHash, String label); + public static native void accessibilityEnd(int changeType); + /** * True when an integrated or external touch digitizer is present, used for * {@code Display.isTouchScreen()} (queries GetSystemMetrics(SM_DIGITIZER)). diff --git a/Ports/iOSPort/nativeSources/IOSNative.m b/Ports/iOSPort/nativeSources/IOSNative.m index 422bf34b4af..90a482a0573 100644 --- a/Ports/iOSPort/nativeSources/IOSNative.m +++ b/Ports/iOSPort/nativeSources/IOSNative.m @@ -13481,6 +13481,217 @@ void com_codename1_impl_ios_IOSNative_announceForAccessibility___java_lang_Strin #endif // !TARGET_OS_WATCH } +#if !TARGET_OS_WATCH +@interface CN1AccessibilityCustomAction : UIAccessibilityCustomAction +@property(nonatomic, retain) NSString *cn1ActionId; +@end + +@implementation CN1AccessibilityCustomAction +@end + +@interface CN1AccessibilityElement : UIAccessibilityElement +@property(nonatomic, assign) long long cn1NodeId; +@property(nonatomic, retain) NSArray *cn1Actions; +@end + +static NSString *CN1AccessibilityActionId(NSArray *actions, NSString *wanted) { + for (NSDictionary *action in actions) { + if ([wanted isEqualToString:[action objectForKey:@"id"]] + && ![[action objectForKey:@"enabled"] isEqual:@NO]) { + return wanted; + } + } + return nil; +} + +static void CN1PerformAccessibilityAction(long long nodeId, NSString *actionId, NSString *argument) { + if (actionId == nil) return; + JAVA_OBJECT javaAction = fromNSString(CN1_THREAD_GET_STATE_PASS_ARG actionId); + JAVA_OBJECT javaArgument = argument == nil ? JAVA_NULL : fromNSString(CN1_THREAD_GET_STATE_PASS_ARG argument); + com_codename1_impl_ios_IOSImplementation_performAccessibilityActionFromNative___long_java_lang_String_java_lang_String( + CN1_THREAD_GET_STATE_PASS_ARG (JAVA_LONG)nodeId, javaAction, javaArgument); +} + +@implementation CN1AccessibilityElement +- (BOOL)accessibilityActivate { + NSString *action = CN1AccessibilityActionId(self.cn1Actions, @"activate"); + if (action == nil) action = CN1AccessibilityActionId(self.cn1Actions, @"focus"); + if (action == nil) return NO; + CN1PerformAccessibilityAction(self.cn1NodeId, action, nil); + return YES; +} + +- (void)accessibilityIncrement { + CN1PerformAccessibilityAction(self.cn1NodeId, + CN1AccessibilityActionId(self.cn1Actions, @"increment"), nil); +} + +- (void)accessibilityDecrement { + CN1PerformAccessibilityAction(self.cn1NodeId, + CN1AccessibilityActionId(self.cn1Actions, @"decrement"), nil); +} + +- (BOOL)accessibilityPerformEscape { + NSString *action = CN1AccessibilityActionId(self.cn1Actions, @"dismiss"); + if (action == nil) return NO; + CN1PerformAccessibilityAction(self.cn1NodeId, action, nil); + return YES; +} + +- (BOOL)accessibilityScroll:(UIAccessibilityScrollDirection)direction { + NSString *action = nil; + if (direction == UIAccessibilityScrollDirectionDown || direction == UIAccessibilityScrollDirectionRight + || direction == UIAccessibilityScrollDirectionNext) { + action = CN1AccessibilityActionId(self.cn1Actions, @"scrollForward"); + } else { + action = CN1AccessibilityActionId(self.cn1Actions, @"scrollBackward"); + } + if (action == nil) return NO; + CN1PerformAccessibilityAction(self.cn1NodeId, action, nil); + return YES; +} + +- (BOOL)cn1PerformCustomAction:(CN1AccessibilityCustomAction *)action { + if (action.cn1ActionId == nil) return NO; + CN1PerformAccessibilityAction(self.cn1NodeId, action.cn1ActionId, nil); + return YES; +} +@end + +static NSMutableDictionary *cn1AccessibilityLiveValues; + +static id CN1JSONValue(NSDictionary *node, NSString *key) { + id value = [node objectForKey:key]; + return value == [NSNull null] ? nil : value; +} + +static UIAccessibilityTraits CN1AccessibilityTraitsForNode(NSDictionary *node) { + NSString *role = CN1JSONValue(node, @"role"); + UIAccessibilityTraits traits = UIAccessibilityTraitNone; + if ([role isEqualToString:@"BUTTON"] || [role isEqualToString:@"TOGGLE_BUTTON"] + || [role isEqualToString:@"CHECKBOX"] || [role isEqualToString:@"RADIO_BUTTON"] + || [role isEqualToString:@"SWITCH"] || [role isEqualToString:@"TAB"] + || [role isEqualToString:@"MENU_ITEM"]) traits |= UIAccessibilityTraitButton; + if ([role isEqualToString:@"LINK"]) traits |= UIAccessibilityTraitLink; + if ([role isEqualToString:@"IMAGE"]) traits |= UIAccessibilityTraitImage; + if ([role isEqualToString:@"STATIC_TEXT"]) traits |= UIAccessibilityTraitStaticText; + if ([role isEqualToString:@"SEARCH_FIELD"]) traits |= UIAccessibilityTraitSearchField; + if ([role isEqualToString:@"HEADING"] || [CN1JSONValue(node, @"headingLevel") intValue] > 0) + traits |= UIAccessibilityTraitHeader; + if ([role isEqualToString:@"SLIDER"] || [role isEqualToString:@"SPIN_BUTTON"]) + traits |= UIAccessibilityTraitAdjustable; + if ([CN1JSONValue(node, @"selected") boolValue]) traits |= UIAccessibilityTraitSelected; + id enabled = CN1JSONValue(node, @"enabled"); + if (enabled != nil && ![enabled boolValue]) traits |= UIAccessibilityTraitNotEnabled; + if (![[CN1JSONValue(node, @"liveRegion") description] isEqualToString:@"OFF"]) + traits |= UIAccessibilityTraitUpdatesFrequently; + return traits; +} + +static NSString *CN1AccessibilityValueForNode(NSDictionary *node) { + NSString *value = CN1JSONValue(node, @"value"); + NSDictionary *range = CN1JSONValue(node, @"range"); + if (value == nil && range != nil) { + value = CN1JSONValue(range, @"text"); + if (value == nil) value = [[range objectForKey:@"current"] stringValue]; + } + NSString *checked = CN1JSONValue(node, @"checked"); + if ([checked isEqualToString:@"CHECKED"]) value = value == nil ? @"Checked" : [value stringByAppendingString:@", Checked"]; + else if ([checked isEqualToString:@"UNCHECKED"]) value = value == nil ? @"Unchecked" : [value stringByAppendingString:@", Unchecked"]; + else if ([checked isEqualToString:@"MIXED"]) value = value == nil ? @"Mixed" : [value stringByAppendingString:@", Mixed"]; + id expanded = CN1JSONValue(node, @"expanded"); + if (expanded != nil) { + NSString *state = [expanded boolValue] ? @"Expanded" : @"Collapsed"; + value = value == nil ? state : [value stringByAppendingFormat:@", %@", state]; + } + id invalid = CN1JSONValue(node, @"invalid"); + if (invalid != nil && [invalid boolValue]) value = value == nil ? @"Invalid" : [value stringByAppendingString:@", Invalid"]; + return value; +} + +void com_codename1_impl_ios_IOSNative_updateAccessibilityTree___java_lang_String_int( + CN1_THREAD_STATE_MULTI_ARG JAVA_OBJECT json, JAVA_INT changeType) { + if (json == JAVA_NULL) return; + POOL_BEGIN(); + NSString *jsonString = toNSString(CN1_THREAD_STATE_PASS_ARG json); + NSData *data = [jsonString dataUsingEncoding:NSUTF8StringEncoding]; + NSDictionary *tree = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; + NSArray *nodes = [tree objectForKey:@"nodes"]; + dispatch_async(dispatch_get_main_queue(), ^{ + UIView *container = (UIView *)[[CodenameOne_GLViewController instance] eaglView]; + if (container == nil) return; + NSMutableArray *elements = [NSMutableArray arrayWithCapacity:[nodes count]]; + NSMutableDictionary *elementsById = [NSMutableDictionary dictionary]; + if (cn1AccessibilityLiveValues == nil) cn1AccessibilityLiveValues = [[NSMutableDictionary alloc] init]; + for (NSDictionary *node in nodes) { + CN1AccessibilityElement *element = [[CN1AccessibilityElement alloc] initWithAccessibilityContainer:container]; + NSNumber *nodeId = [node objectForKey:@"id"]; + element.cn1NodeId = [nodeId longLongValue]; + element.cn1Actions = CN1JSONValue(node, @"actions"); + element.accessibilityLabel = CN1JSONValue(node, @"label"); + NSString *hint = CN1JSONValue(node, @"hint"); + NSString *error = CN1JSONValue(node, @"error"); + element.accessibilityHint = error == nil ? hint : hint == nil ? error : [NSString stringWithFormat:@"%@. %@", hint, error]; + element.accessibilityValue = CN1AccessibilityValueForNode(node); + element.accessibilityIdentifier = CN1JSONValue(node, @"identifier"); + element.accessibilityTraits = CN1AccessibilityTraitsForNode(node); + element.accessibilityViewIsModal = [CN1JSONValue(node, @"modal") boolValue]; + NSArray *bounds = [node objectForKey:@"bounds"]; + if ([bounds count] == 4) { + CGFloat scale = scaleValue <= 0 ? [UIScreen mainScreen].scale : scaleValue; + element.accessibilityFrameInContainerSpace = CGRectMake( + [[bounds objectAtIndex:0] doubleValue] / scale, + [[bounds objectAtIndex:1] doubleValue] / scale, + [[bounds objectAtIndex:2] doubleValue] / scale, + [[bounds objectAtIndex:3] doubleValue] / scale); + } + NSMutableArray *custom = [NSMutableArray array]; + for (NSDictionary *action in element.cn1Actions) { + NSString *actionId = [action objectForKey:@"id"]; + if ([actionId isEqualToString:@"activate"] || [actionId isEqualToString:@"focus"] + || [actionId isEqualToString:@"increment"] || [actionId isEqualToString:@"decrement"] + || [actionId isEqualToString:@"dismiss"] || [actionId isEqualToString:@"scrollForward"] + || [actionId isEqualToString:@"scrollBackward"] || ![[action objectForKey:@"enabled"] boolValue]) continue; + NSString *name = CN1JSONValue(action, @"label"); + if (name == nil) name = actionId; + CN1AccessibilityCustomAction *customAction = [[CN1AccessibilityCustomAction alloc] + initWithName:name target:element selector:@selector(cn1PerformCustomAction:)]; + customAction.cn1ActionId = actionId; + [custom addObject:customAction]; + } + element.accessibilityCustomActions = custom; + [elements addObject:element]; + [elementsById setObject:element forKey:nodeId]; + + NSString *live = CN1JSONValue(node, @"liveRegion"); + if (live != nil && ![live isEqualToString:@"OFF"]) { + NSString *newValue = [NSString stringWithFormat:@"%@|%@", element.accessibilityLabel ?: @"", element.accessibilityValue ?: @""]; + NSString *oldValue = [cn1AccessibilityLiveValues objectForKey:nodeId]; + if (oldValue != nil && ![oldValue isEqualToString:newValue]) { + UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, + element.accessibilityLabel ?: element.accessibilityValue); + } + [cn1AccessibilityLiveValues setObject:newValue forKey:nodeId]; + } + } + container.isAccessibilityElement = NO; + container.accessibilityElements = elements; + if ((changeType & 256) != 0) { + UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, + [elements count] == 0 ? nil : [elements objectAtIndex:0]); + } else { + UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, nil); + } + }); + POOL_END(); +} +#else +void com_codename1_impl_ios_IOSNative_updateAccessibilityTree___java_lang_String_int( + CN1_THREAD_STATE_MULTI_ARG JAVA_OBJECT json, JAVA_INT changeType) { + // watchOS uses a separate SwiftUI accessibility model. +} +#endif + // ==================================================================== // Crypto bridge -- implementations of the native methods on IOSNative // that back com.codename1.security.{Cipher,Signature,SecureRandom, diff --git a/Ports/iOSPort/src/com/codename1/impl/ios/IOSImplementation.java b/Ports/iOSPort/src/com/codename1/impl/ios/IOSImplementation.java index da7451cbee4..5f1454230bd 100644 --- a/Ports/iOSPort/src/com/codename1/impl/ios/IOSImplementation.java +++ b/Ports/iOSPort/src/com/codename1/impl/ios/IOSImplementation.java @@ -11671,6 +11671,22 @@ public void announceForAccessibility(final Component cmp, final String text) { IOSNative.announceForAccessibility(text); } + @Override + public void accessibilityTreeChanged(int changeType) { + IOSNative.updateAccessibilityTree(getAccessibilityTreeSnapshot().toJson(), changeType); + } + + @Override + public boolean isAccessibilityTreeSupported() { + return true; + } + + public static void performAccessibilityActionFromNative(long nodeId, String actionId, String argument) { + if (instance != null) { + instance.performAccessibilityAction(nodeId, actionId, argument); + } + } + // ================================================================ // Crypto bridge -- routes through CN1Crypto.{h,m} in nativeSources/ // (the corresponding native methods live on IOSNative). The defaults diff --git a/Ports/iOSPort/src/com/codename1/impl/ios/IOSNative.java b/Ports/iOSPort/src/com/codename1/impl/ios/IOSNative.java index 58a714251cc..c935634bd14 100644 --- a/Ports/iOSPort/src/com/codename1/impl/ios/IOSNative.java +++ b/Ports/iOSPort/src/com/codename1/impl/ios/IOSNative.java @@ -1213,6 +1213,8 @@ native void startTagRead(int requestId, String alertMessage, public static native void announceForAccessibility(String text); + public static native void updateAccessibilityTree(String json, int changeType); + // ============================================================ // Crypto bridge -- backed by CN1Crypto.{h,m} in nativeSources/. // diff --git a/docs/developer-guide/Accessibility-Semantics.asciidoc b/docs/developer-guide/Accessibility-Semantics.asciidoc new file mode 100644 index 00000000000..6cd09e7f876 --- /dev/null +++ b/docs/developer-guide/Accessibility-Semantics.asciidoc @@ -0,0 +1,218 @@ += Accessibility Semantics + +Codename One components are lightweight: they are painted by Codename One instead of being represented by a native widget on every platform. The accessibility semantics API builds an explicit, immutable virtual tree from those components and presents it to VoiceOver, TalkBack, Windows UI Automation, AT-SPI, Java Access Bridge, and web accessibility APIs. + +The semantic tree is separate from the visual tree. This is important for renderer-backed controls, merged cards, decorative content, custom controls, and applications that need a reading order different from paint order. + +== Built-in semantics + +Standard components work without extra configuration. `Button`, `CheckBox`, `RadioButton`, `Slider`, text fields, lists, tables, tabs, labels, dialogs, and containers infer appropriate roles, values, states, collection metadata, and standard actions. Renderer-backed `List` rows are exposed as stable virtual children even though no `Component` exists for each painted row. + +`Component.setAccessibilityText()` remains supported. It is a compatibility alias for the semantic label. New code should use `getSemantics()` when it needs more than a label. + +[source,java] +---- +Button save = new Button("Save"); +save.getSemantics() + .setHint("Saves the edited profile") + .setIdentifier("profile-save"); +---- + +Changes to text, selection, focus, enabled state, bounds, scrolling, ranges, tabs, and the current `Form` automatically invalidate the native semantic tree. Custom components should call `accessibilityChanged()` after a semantic value changes outside a standard setter. + +== Roles, names, values, and state + +`AccessibilityRole` contains portable control roles including buttons, toggle buttons, switches, checkboxes, radio buttons, headings, links, images, text and search fields, sliders, progress indicators, lists, grids, rows, cells, headers, tabs, dialogs, alerts, menus, toolbars, combo boxes, trees, and separators. A port maps an unsupported role to the closest native role without discarding its label or state. + +[source,java] +---- +Component wifiSwitch = new MyPaintedSwitch(); +wifiSwitch.getSemantics() + .setRole(AccessibilityRole.SWITCH) + .setLabel("Wi-Fi") + .setChecked(AccessibilityCheckedState.CHECKED) + .setEnabled(Boolean.TRUE) + .setHint("Double tap to turn Wi-Fi off"); + +Label title = new Label("Network"); +title.getSemantics() + .setHeadingLevel(2) + .setIdentifier("network-heading"); +---- + +Tri-state controls use `UNCHECKED`, `CHECKED`, or `MIXED`. Nullable Boolean properties distinguish an explicit state from an unspecified state. Available properties include selected, expanded, enabled, invalid, busy, read-only, required, multiline, obscured, pressed, and current. `setValidationError()` supplies both the error message and invalid state. `setPaneTitle()` describes a newly displayed pane or screen, and `setModal(true)` identifies a modal scope. + +Use `setRoleDescription()` only when the platform role is not sufficiently specific. Localize labels, hints, descriptions, errors, pane titles, role descriptions, and custom action labels. + +== Ranges and editable values + +`AccessibilityRange` describes minimum, maximum, current value, increment, and an optional spoken value. The spoken value is useful for ranges such as ratings and durations where a raw number is ambiguous. + +[source,java] +---- +rating.getSemantics() + .setRole(AccessibilityRole.SLIDER) + .setLabel("Rating") + .setRange(new AccessibilityRange(0, 5, 3, 1, "3 out of 5")); +---- + +Editable controls can provide `SET_VALUE` or `SET_TEXT` actions. Sliders and other adjustable controls should expose `INCREMENT` and `DECREMENT`. Standard components infer these actions. + +== Custom accessibility actions + +An `AccessibilityAction` has a stable ID, a localized label, an enabled state, and a handler. Handlers always execute on the Codename One EDT, including when the action originates on a native accessibility thread. + +[source,java] +---- +card.getSemantics().addAction(new AccessibilityAction( + "archive", + "Archive message", + new AccessibilityAction.Handler() { + public boolean perform(Component component, Object argument) { + archiveMessage(); + return true; + } + } +)); +---- + +Use the standard IDs in `AccessibilityAction` for activation, long press, increment, decrement, set value, set text, selection, character or word cursor movement, focus, show-on-screen, dismiss, expand, collapse, scrolling, and clipboard operations. A custom ID must be stable and its label must not be null. + +== Grouping and virtual descendants + +`AccessibilityGrouping` controls how a component participates in the semantic tree: + +* `AUTO` uses normal component inference. +* `LEAF` exposes the component but none of its descendants. +* `GROUP` exposes the component as a semantic container and retains its descendants. +* `MERGE_DESCENDANTS` combines descendant labels, descriptions, values, state, and actions into one node. +* `EXCLUDE` removes the component but promotes its descendants to the semantic parent. +* `EXCLUDE_SUBTREE` removes the component and all descendants. + +[source,java] +---- +summaryCard.getSemantics() + .setRole(AccessibilityRole.GENERIC) + .setGrouping(AccessibilityGrouping.MERGE_DESCENDANTS); +---- + +For content that is painted without child components, attach an `AccessibilityChildProvider`, or add standalone `AccessibilityNode` children. Every virtual node must use a stable `virtualKey`. Stable keys preserve native focus while rows are updated or recycled. + +[source,java] +---- +chart.getSemantics().setChildProvider(new AccessibilityChildProvider() { + public List getAccessibilityChildren(Component owner) { + List result = new ArrayList(); + for (Point point : model.getPoints()) { + AccessibilityNode node = new AccessibilityNode("point-" + point.getId()); + node.setRole(AccessibilityRole.IMAGE) + .setLabel(point.getLabel()) + .setValue(point.getFormattedValue()) + .setBounds(point.getBounds()); + result.add(node); + } + return result; + } +}); +---- + +Virtual bounds are relative to the owning component. Component nodes use their clipped absolute bounds. + +== Traversal order + +Visual order is the default reading order. `setSortKey()` assigns an ordered semantic key among siblings. `setTraversalBefore()` and `setTraversalAfter()` express a direct relationship when a numeric order would be fragile. + +[source,java] +---- +cancel.getSemantics().setSortKey(1); +continueButton.getSemantics().setSortKey(2); +help.getSemantics().setTraversalAfter(continueButton); +---- + +Keep traversal relationships within the same semantic parent. The tree builder resolves these constraints deterministically and preserves stable node IDs. + +== Live regions and screen changes + +Set `AccessibilityLiveRegion.POLITE` for non-urgent updates and `ASSERTIVE` for errors or urgent status. `OFF` is the default. Live changes produce the corresponding platform notification or ARIA live update. + +[source,java] +---- +status.getSemantics() + .setRole(AccessibilityRole.ALERT) + .setLiveRegion(AccessibilityLiveRegion.POLITE); +status.setText("Upload complete"); +---- + +Form changes and nodes with a pane title produce screen or pane transition notifications. `Display.announceForAccessibility()` remains available for an exceptional announcement that is not represented by persistent UI. Prefer a live region for state that is visible on screen. + +== Collections + +`AccessibilityCollectionInfo` describes row and column counts, hierarchy, and selection mode. `AccessibilityCollectionItemInfo` describes row and column index, spans, position and size in a set, nesting level, and header status. + +[source,java] +---- +grid.getSemantics().setCollectionInfo( + new AccessibilityCollectionInfo(20, 3, false, + AccessibilityCollectionInfo.SELECTION_MULTIPLE)); + +cell.getSemantics().setCollectionItemInfo( + new AccessibilityCollectionItemInfo( + 4, 1, 2, 1, 5, 20, 1, false)); +---- + +Row and column indexes are zero-based. Position and set size are one-based; use `-1` when unknown. Lists, tables, tabs, and their items infer this metadata where possible. + +== Inspecting and testing semantics + +`AccessibilityInspector` returns an immutable snapshot. A snapshot is safe to inspect without racing native accessibility callbacks and includes stable IDs, hierarchy, bounds, resolved state, actions, range and collection data. `toJson()` is suitable for diagnostic reports and tooling. + +[source,java] +---- +AccessibilityTreeSnapshot tree = + AccessibilityInspector.snapshot(myForm); + +AccessibilityAssertions.assertNoErrors(tree); +AccessibilityAssertions.assertNoUnlabeledInteractiveNodes(tree); + +String diagnosticJson = tree.toJson(); +AccessibilityNodeSnapshot hit = tree.getNodeAt(screenX, screenY); +---- + +`AccessibilityAssertions.audit()` reports machine-readable `AccessibilityIssue` values for unlabeled controls, invalid ranges, duplicate identifiers or actions, invalid collection positions, missing parents, cycles, unnamed dialogs, and unlabeled custom actions. Warnings also identify suspicious role/state combinations and empty bounds. + +The Java SE Component Inspector provides *Copy Accessibility Tree JSON* and *Audit Accessibility Tree* actions. Tests should assert resolved semantic properties instead of platform-specific spoken sentences. The `scripts/hellocodenameone` suite contains the cross-port conformance fixture used by native CI. + +== Platform mappings + +[cols="1,2,2"] +|=== +|Target |Native representation |Notable behavior + +|iOS, iPadOS, and Mac Catalyst +|`UIAccessibilityElement` instances owned by the rendering view +|Traits, values, frames, custom actions, adjustable actions, live announcements, and screen/layout transitions + +|Android +|`AccessibilityNodeProvider` virtual descendants +|Class/role mapping, checked and mixed state, headings, pane titles, errors, ranges, collections, focus, hit testing, and custom actions + +|Windows native +|UI Automation fragment-root provider +|Virtual fragments, control types, names, values, state, bounds, navigation, focus lookup, hit testing, and action dispatch + +|Linux native +|Transparent GTK semantic widgets exposed through ATK/AT-SPI +|Roles, names, descriptions, state, hierarchy, bounds, and action dispatch + +|Java SE simulator and desktop +|Swing `AccessibleContext` virtual children +|Roles, states, values, geometry, accessible actions, and Component Inspector integration + +|JavaScript +|A synchronized off-screen DOM tree +|ARIA roles, names, state, ranges, live regions, collection metadata, traversal order, and action routing; the painted canvas is hidden from the accessibility tree +|=== + +The API intentionally goes beyond a label-only model: it includes stable virtual children, explicit traversal constraints, collection spans and set metadata, pane transitions, machine-readable inspection, and built-in semantic audits. Platform accessibility tools remain the final verification step because screen readers can apply platform-specific presentation rules. + +For underlying platform guidance, see the Apple https://developer.apple.com/documentation/uikit/uiaccessibility-protocol[UIAccessibility protocol], Android https://developer.android.com/guide/topics/ui/accessibility/principles[accessibility principles], Microsoft https://learn.microsoft.com/windows/win32/winauto/uiauto-providersoverview[UI Automation provider overview], and W3C https://www.w3.org/TR/wai-aria-1.2/[WAI-ARIA]. diff --git a/docs/developer-guide/developer-guide.asciidoc b/docs/developer-guide/developer-guide.asciidoc index b1c598cf5c2..8f9ab5b8474 100644 --- a/docs/developer-guide/developer-guide.asciidoc +++ b/docs/developer-guide/developer-guide.asciidoc @@ -57,6 +57,8 @@ include::css.asciidoc[] include::The-Components-Of-Codename-One.asciidoc[] +include::Accessibility-Semantics.asciidoc[] + include::Media-And-Audio.asciidoc[] include::Animations.asciidoc[] diff --git a/maven/core-unittests/src/test/java/com/codename1/ui/accessibility/AccessibilitySemanticsTest.java b/maven/core-unittests/src/test/java/com/codename1/ui/accessibility/AccessibilitySemanticsTest.java new file mode 100644 index 00000000000..f86fba2f206 --- /dev/null +++ b/maven/core-unittests/src/test/java/com/codename1/ui/accessibility/AccessibilitySemanticsTest.java @@ -0,0 +1,182 @@ +package com.codename1.ui.accessibility; + +import com.codename1.junit.UITestBase; +import com.codename1.junit.FormTest; +import com.codename1.ui.Button; +import com.codename1.ui.CheckBox; +import com.codename1.ui.Component; +import com.codename1.ui.Container; +import com.codename1.ui.Form; +import com.codename1.ui.Label; +import com.codename1.ui.Slider; +import com.codename1.ui.TextField; +import com.codename1.ui.list.DefaultListModel; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +class AccessibilitySemanticsTest extends UITestBase { + + @FormTest + void infersRolesStatesValuesAndActionsForBuiltInControls() { + Form form = form(); + Button button = place(form, new Button("Save"), 10, 10, 100, 30); + CheckBox checkbox = place(form, new CheckBox("Remember me"), 10, 50, 140, 30); + checkbox.setSelected(true); + Slider slider = place(form, new Slider(), 10, 90, 200, 30); + slider.setEditable(true); + slider.setMinValue(10); + slider.setMaxValue(50); + slider.setProgress(30); + TextField field = place(form, new TextField("hello"), 10, 130, 200, 35); + + AccessibilityTreeSnapshot tree = AccessibilityInspector.snapshot(form); + AccessibilityNodeSnapshot buttonNode = find(tree, button); + AccessibilityNodeSnapshot checkNode = find(tree, checkbox); + AccessibilityNodeSnapshot sliderNode = find(tree, slider); + AccessibilityNodeSnapshot fieldNode = find(tree, field); + + assertEquals(AccessibilityRole.BUTTON, buttonNode.getRole()); + assertEquals("Save", buttonNode.getLabel()); + assertNotNull(buttonNode.getAction(AccessibilityAction.ACTIVATE)); + assertEquals(AccessibilityRole.CHECKBOX, checkNode.getRole()); + assertEquals(AccessibilityCheckedState.CHECKED, checkNode.getChecked()); + assertEquals(30d, sliderNode.getRange().getCurrent()); + assertNotNull(sliderNode.getAction(AccessibilityAction.INCREMENT)); + assertEquals(AccessibilityRole.TEXT_FIELD, fieldNode.getRole()); + assertEquals("hello", fieldNode.getLabel()); + assertNotNull(fieldNode.getAction(AccessibilityAction.SET_TEXT)); + } + + @FormTest + void explicitSemanticsOverrideInferredValuesAndLegacyTextMapsToLabel() { + Form form = form(); + Button button = place(form, new Button("Visual"), 10, 10, 100, 30); + button.setAccessibilityText("Legacy"); + assertEquals("Legacy", button.getSemantics().getLabel()); + button.getSemantics().setLabel("Semantic").setRole(AccessibilityRole.SWITCH) + .setChecked(AccessibilityCheckedState.MIXED).setHint("Changes mode"); + + AccessibilityNodeSnapshot node = find(AccessibilityInspector.snapshot(form), button); + assertEquals("Semantic", node.getLabel()); + assertEquals("Semantic", button.getAccessibilityText()); + assertEquals(AccessibilityRole.SWITCH, node.getRole()); + assertEquals(AccessibilityCheckedState.MIXED, node.getChecked()); + assertEquals("Changes mode", node.getHint()); + } + + @FormTest + void groupingCanMergeOrPromoteDescendants() { + Form form = form(); + Container merged = place(form, new Container(), 0, 0, 200, 100); + Label first = place(merged, new Label("First"), 0, 0, 100, 30); + place(merged, new Label("Second"), 0, 35, 100, 30); + merged.getSemantics().setRole(AccessibilityRole.GENERIC) + .setGrouping(AccessibilityGrouping.MERGE_DESCENDANTS); + + AccessibilityTreeSnapshot tree = AccessibilityInspector.snapshot(form); + AccessibilityNodeSnapshot mergedNode = find(tree, merged); + assertTrue(mergedNode.getLabel().contains("First")); + assertTrue(mergedNode.getLabel().contains("Second")); + assertTrue(mergedNode.getChildIds().isEmpty()); + assertNull(findOrNull(tree, first)); + + merged.getSemantics().setGrouping(AccessibilityGrouping.EXCLUDE); + tree = AccessibilityInspector.snapshot(form); + assertNull(findOrNull(tree, merged)); + assertNotNull(findOrNull(tree, first)); + } + + @FormTest + void sortKeysProduceExplicitTraversalOrder() { + Form form = form(); + Button second = place(form, new Button("Second"), 0, 0, 100, 30); + Button first = place(form, new Button("First"), 0, 40, 100, 30); + second.getSemantics().setSortKey(2); + first.getSemantics().setSortKey(1); + + AccessibilityTreeSnapshot tree = AccessibilityInspector.snapshot(form); + AccessibilityNodeSnapshot formNode = find(tree, form); + int firstIndex = formNode.getChildIds().indexOf(Long.valueOf(find(tree, first).getId())); + int secondIndex = formNode.getChildIds().indexOf(Long.valueOf(find(tree, second).getId())); + assertTrue(firstIndex >= 0 && secondIndex >= 0 && firstIndex < secondIndex); + } + + @FormTest + void rendererBackedListsExposeStableVirtualCollectionItems() { + Form form = form(); + com.codename1.ui.List list = new com.codename1.ui.List( + new DefaultListModel("Alpha", "Beta", "Gamma")); + place(form, list, 0, 0, 200, 160); + list.setSelectedIndex(1); + + AccessibilityTreeSnapshot first = AccessibilityInspector.snapshot(form); + AccessibilityNodeSnapshot listNode = find(first, list); + assertEquals(3, listNode.getChildIds().size()); + AccessibilityNodeSnapshot beta = first.getNode(listNode.getChildIds().get(1).longValue()); + assertTrue(beta.getLabel().contains("Beta")); + assertEquals(Boolean.TRUE, beta.getSelected()); + assertEquals(2, beta.getCollectionItemInfo().getPositionInSet()); + long stableId = beta.getId(); + + list.setSelectedIndex(2); + AccessibilityTreeSnapshot second = AccessibilityInspector.snapshot(form); + AccessibilityNodeSnapshot secondList = find(second, list); + assertEquals(stableId, secondList.getChildIds().get(1).longValue()); + assertEquals(Boolean.FALSE, second.getNode(stableId).getSelected()); + } + + @FormTest + void auditsInvalidRangesAndUnlabeledCustomActions() { + Form form = form(); + Component custom = place(form, new Label(), 0, 0, 100, 30); + custom.getSemantics().setRole(AccessibilityRole.SLIDER) + .setRange(new AccessibilityRange(10, 5, 20, -1)) + .addAction(new AccessibilityAction("custom", null, + new AccessibilityAction.Handler() { + public boolean perform(Component component, Object argument) { return true; } + })); + + List issues = AccessibilityAssertions.audit(AccessibilityInspector.snapshot(form)); + assertTrue(hasIssue(issues, "invalid-range")); + assertTrue(hasIssue(issues, "unlabeled-custom-action")); + assertThrows(AssertionError.class, + () -> AccessibilityAssertions.assertNoErrors(AccessibilityInspector.snapshot(form))); + } + + private Form form() { + Form form = new Form("Accessible form"); + form.setWidth(400); + form.setHeight(600); + form.getContentPane().setWidth(400); + form.getContentPane().setHeight(600); + return form; + } + + private T place(Container parent, T component, int x, int y, int w, int h) { + parent.add(component); + component.setX(x); + component.setY(y); + component.setWidth(w); + component.setHeight(h); + return component; + } + + private AccessibilityNodeSnapshot find(AccessibilityTreeSnapshot tree, Component component) { + AccessibilityNodeSnapshot node = findOrNull(tree, component); + assertNotNull(node, "No semantic node for " + component); + return node; + } + + private AccessibilityNodeSnapshot findOrNull(AccessibilityTreeSnapshot tree, Component component) { + for (AccessibilityNodeSnapshot node : tree.getNodes().values()) { + if (node.getComponent() == component && node.getVirtualKey() == null) return node; + } + return null; + } + + private boolean hasIssue(List issues, String code) { + for (AccessibilityIssue issue : issues) if (code.equals(issue.getCode())) return true; + return false; + } +} diff --git a/scripts/hellocodenameone/common/src/main/java/com/codenameone/examples/hellocodenameone/tests/accessibility/AccessibilityTest.java b/scripts/hellocodenameone/common/src/main/java/com/codenameone/examples/hellocodenameone/tests/accessibility/AccessibilityTest.java index 3494bf9f11e..1c243f04a49 100644 --- a/scripts/hellocodenameone/common/src/main/java/com/codenameone/examples/hellocodenameone/tests/accessibility/AccessibilityTest.java +++ b/scripts/hellocodenameone/common/src/main/java/com/codenameone/examples/hellocodenameone/tests/accessibility/AccessibilityTest.java @@ -1,20 +1,245 @@ package com.codenameone.examples.hellocodenameone.tests.accessibility; +import com.codename1.ui.Button; +import com.codename1.ui.CN; +import com.codename1.ui.CheckBox; +import com.codename1.ui.Component; +import com.codename1.ui.Container; import com.codename1.ui.Display; +import com.codename1.ui.Form; +import com.codename1.ui.Label; +import com.codename1.ui.Slider; +import com.codename1.ui.accessibility.AccessibilityAction; +import com.codename1.ui.accessibility.AccessibilityAssertions; +import com.codename1.ui.accessibility.AccessibilityCheckedState; +import com.codename1.ui.accessibility.AccessibilityCollectionInfo; +import com.codename1.ui.accessibility.AccessibilityCollectionItemInfo; +import com.codename1.ui.accessibility.AccessibilityGrouping; +import com.codename1.ui.accessibility.AccessibilityInspector; +import com.codename1.ui.accessibility.AccessibilityLiveRegion; +import com.codename1.ui.accessibility.AccessibilityManager; +import com.codename1.ui.accessibility.AccessibilityNode; +import com.codename1.ui.accessibility.AccessibilityNodeSnapshot; +import com.codename1.ui.accessibility.AccessibilityRange; +import com.codename1.ui.accessibility.AccessibilityRole; +import com.codename1.ui.accessibility.AccessibilityTreeSnapshot; +import com.codename1.ui.geom.Rectangle; import com.codenameone.examples.hellocodenameone.tests.BaseTest; +/** Cross-port semantics conformance test. This runs in every native cn1ss job. */ public class AccessibilityTest extends BaseTest { + private volatile boolean customActionPerformed; + @Override public boolean runTest() throws Exception { - com.codename1.ui.CN.callSerially(() -> { - String expected = "Testing accessibility announcement"; - // Just verify that invoking this doesn't crash the app - Display.getInstance().announceForAccessibility(expected); - done(); + CN.callSerially(new Runnable() { + public void run() { + try { + runSemanticAssertions(); + } catch (Throwable t) { + fail("Accessibility semantic assertions failed: " + t); + } + } }); return true; } + private void runSemanticAssertions() { + final Form form = new Form("Accessibility conformance"); + size(form, 0, 0, 600, 1200); + size(form.getContentPane(), 0, 0, 600, 1200); + form.getSemantics().setPaneTitle("Settings").setRole(AccessibilityRole.GENERIC); + + Label heading = add(form, new Label("Preferences"), 10, 10, 300, 40); + heading.getSemantics().setHeadingLevel(2).setIdentifier("preferences-heading"); + + Button save = add(form, new Button("Save"), 10, 60, 120, 40); + save.getSemantics().setHint("Saves all changes").setSortKey(2) + .addAction(new AccessibilityAction("share", "Share settings", + new AccessibilityAction.Handler() { + public boolean perform(Component component, Object argument) { + customActionPerformed = true; + return true; + } + })); + + CheckBox notifications = add(form, new CheckBox("Notifications"), 10, 110, 220, 40); + notifications.setSelected(true); + notifications.getSemantics().setSortKey(1).setRequired(Boolean.TRUE); + + Slider volume = add(form, new Slider(), 10, 160, 260, 40); + volume.setEditable(true); + volume.getSemantics().setLabel("Volume") + .setRange(new AccessibilityRange(0, 100, 35, 5, "35 percent")); + + Label error = add(form, new Label("Password is too short"), 10, 210, 300, 40); + error.getSemantics().setRole(AccessibilityRole.ALERT).setLiveRegion(AccessibilityLiveRegion.ASSERTIVE) + .setValidationError("Password is too short").setInvalid(Boolean.TRUE); + + Container collection = add(form, new Container(), 10, 260, 300, 150); + collection.getSemantics().setRole(AccessibilityRole.GRID) + .setLabel("Accounts") + .setCollectionInfo(new AccessibilityCollectionInfo(2, 1, false, + AccessibilityCollectionInfo.SELECTION_SINGLE)); + Label firstRow = add(collection, new Label("Personal"), 0, 0, 250, 50); + firstRow.getSemantics().setRole(AccessibilityRole.CELL).setSelected(Boolean.TRUE) + .setCollectionItemInfo(new AccessibilityCollectionItemInfo(0, 1, 0, 1, 1, 2, 1, false)); + Label secondRow = add(collection, new Label("Business"), 0, 55, 250, 50); + secondRow.getSemantics().setRole(AccessibilityRole.CELL).setSelected(Boolean.FALSE) + .setCollectionItemInfo(new AccessibilityCollectionItemInfo(1, 1, 0, 1, 2, 2, 1, false)); + + Container merged = add(form, new Container(), 10, 420, 300, 80); + merged.getSemantics().setRole(AccessibilityRole.GENERIC).setGrouping(AccessibilityGrouping.MERGE_DESCENDANTS); + add(merged, new Label("Billing"), 0, 0, 100, 30); + add(merged, new Label("monthly"), 110, 0, 100, 30); + + Label semanticSwitch = add(form, new Label("Automatic updates"), 10, 510, 260, 40); + semanticSwitch.getSemantics().setRole(AccessibilityRole.SWITCH) + .setChecked(AccessibilityCheckedState.MIXED).setExpanded(Boolean.TRUE); + + Container semanticList = add(form, new Container(), 10, 560, 300, 90); + semanticList.getSemantics().setRole(AccessibilityRole.LIST).setLabel("Recent projects") + .setCollectionInfo(new AccessibilityCollectionInfo(2, 1, false, + AccessibilityCollectionInfo.SELECTION_NONE)); + Label semanticListItem = add(semanticList, new Label("Project Aurora"), 0, 0, 250, 35); + semanticListItem.getSemantics().setRole(AccessibilityRole.LIST_ITEM) + .setCollectionItemInfo(new AccessibilityCollectionItemInfo(1, 2)); + + Label semanticTab = add(form, new Label("Overview"), 10, 660, 160, 40); + semanticTab.getSemantics().setRole(AccessibilityRole.TAB).setSelected(Boolean.TRUE); + + Container semanticDialog = add(form, new Container(), 10, 710, 300, 90); + semanticDialog.getSemantics().setRole(AccessibilityRole.DIALOG).setLabel("Confirm deletion") + .setPaneTitle("Confirmation").setModal(true); + + Container virtualHost = add(form, new Container(), 10, 810, 300, 100); + virtualHost.getSemantics().setRole(AccessibilityRole.LIST).setLabel("Virtual results") + .addChild(new AccessibilityNode("result-42").setRole(AccessibilityRole.LIST_ITEM) + .setLabel("Virtual result").setBounds(new Rectangle(0, 0, 280, 45)) + .setCollectionItemInfo(new AccessibilityCollectionItemInfo(1, 1))); + + Button disabled = add(form, new Button("Unavailable action"), 10, 920, 220, 40); + disabled.setEnabled(false); + + AccessibilityTreeSnapshot first = AccessibilityInspector.snapshot(form); + AccessibilityNodeSnapshot headingNode = find(first, heading); + AccessibilityNodeSnapshot saveNode = find(first, save); + AccessibilityNodeSnapshot checkboxNode = find(first, notifications); + AccessibilityNodeSnapshot volumeNode = find(first, volume); + AccessibilityNodeSnapshot errorNode = find(first, error); + AccessibilityNodeSnapshot collectionNode = find(first, collection); + AccessibilityNodeSnapshot mergedNode = find(first, merged); + AccessibilityNodeSnapshot switchNode = find(first, semanticSwitch); + AccessibilityNodeSnapshot listNode = find(first, semanticList); + AccessibilityNodeSnapshot tabNode = find(first, semanticTab); + AccessibilityNodeSnapshot dialogNode = find(first, semanticDialog); + AccessibilityNodeSnapshot virtualHostNode = find(first, virtualHost); + + assertEqual(AccessibilityRole.HEADING, headingNode.getRole(), "heading role"); + assertEqual(2, headingNode.getHeadingLevel(), "heading level"); + assertEqual("preferences-heading", headingNode.getIdentifier(), "automation identifier"); + assertEqual(AccessibilityRole.BUTTON, saveNode.getRole(), "inferred button role"); + assertTrue(saveNode.getAction(AccessibilityAction.ACTIVATE) != null, "standard activation action"); + assertTrue(saveNode.getAction("share") != null, "custom action"); + assertEqual(AccessibilityCheckedState.CHECKED, checkboxNode.getChecked(), "checked state"); + assertEqual(Boolean.TRUE, checkboxNode.getRequired(), "required state"); + assertEqual(35.0, volumeNode.getRange().getCurrent(), "range value"); + assertEqual(5.0, volumeNode.getRange().getStep(), "range step"); + assertEqual(AccessibilityLiveRegion.ASSERTIVE, errorNode.getLiveRegion(), "live region"); + assertEqual(Boolean.TRUE, errorNode.getInvalid(), "validation state"); + assertEqual(2, collectionNode.getCollectionInfo().getRowCount(), "collection rows"); + assertEqual(2, collectionNode.getChildIds().size(), "collection children"); + assertEqual(2, find(first, secondRow).getCollectionItemInfo().getPositionInSet(), "set position"); + assertTrue(mergedNode.getLabel().indexOf("Billing") >= 0, "merged first label"); + assertTrue(mergedNode.getLabel().indexOf("monthly") >= 0, "merged second label"); + assertEqual(0, mergedNode.getChildIds().size(), "merged descendants hidden"); + assertTrue(findOrNull(first, firstRow) != null, "collection descendant retained"); + assertTrue(findOrNull(first, merged.getComponentAt(0)) == null, "merged descendant omitted"); + assertEqual(AccessibilityRole.SWITCH, switchNode.getRole(), "switch role"); + assertEqual(AccessibilityCheckedState.MIXED, switchNode.getChecked(), "mixed switch state"); + assertEqual(Boolean.TRUE, switchNode.getExpanded(), "expanded state"); + assertEqual(AccessibilityRole.LIST, listNode.getRole(), "list role"); + assertEqual(AccessibilityRole.LIST_ITEM, find(first, semanticListItem).getRole(), "list item role"); + assertEqual(AccessibilityRole.TAB, tabNode.getRole(), "tab role"); + assertEqual(Boolean.TRUE, tabNode.getSelected(), "selected tab state"); + assertEqual(AccessibilityRole.DIALOG, dialogNode.getRole(), "dialog role"); + assertTrue(dialogNode.isModal(), "modal dialog state"); + assertEqual("Confirmation", dialogNode.getPaneTitle(), "pane transition title"); + assertEqual(Boolean.FALSE, find(first, disabled).getEnabled(), "disabled state"); + assertEqual(1, virtualHostNode.getChildIds().size(), "virtual accessibility descendant"); + AccessibilityNodeSnapshot virtualNode = first.getNode(virtualHostNode.getChildIds().get(0).longValue()); + assertEqual("result-42", virtualNode.getVirtualKey(), "stable virtual key"); + assertEqual(AccessibilityRole.LIST_ITEM, virtualNode.getRole(), "virtual child role"); + assertEqual("Virtual result", first.getNodeAt(20, 830).getLabel(), "virtual child hit testing"); + + AccessibilityNodeSnapshot formNode = find(first, form); + int checkboxPosition = formNode.getChildIds().indexOf(Long.valueOf(checkboxNode.getId())); + int savePosition = formNode.getChildIds().indexOf(Long.valueOf(saveNode.getId())); + assertTrue(checkboxPosition >= 0 && checkboxPosition < savePosition, "explicit traversal order"); + assertTrue(first.getNodeAt(20, 70) != null, "semantic hit testing"); + AccessibilityAssertions.assertNoErrors(first); + AccessibilityAssertions.assertNoUnlabeledInteractiveNodes(first); + + String json = first.toJson(); + assertTrue(json.indexOf("\"role\":\"HEADING\"") >= 0, "serialized role"); + assertTrue(json.indexOf("\"liveRegion\":\"ASSERTIVE\"") >= 0, "serialized live region"); + assertTrue(json.indexOf("\"collection\"") >= 0, "serialized collection metadata"); + + long stableSaveId = saveNode.getId(); + notifications.setSelected(false); + AccessibilityTreeSnapshot second = AccessibilityInspector.snapshot(form); + assertEqual(stableSaveId, find(second, save).getId(), "stable semantic id"); + assertEqual(AccessibilityCheckedState.UNCHECKED, find(second, notifications).getChecked(), "updated state"); + assertTrue(second.getGeneration() > first.getGeneration(), "tree generation changes"); + + assertTrue(Display.getInstance().isAccessibilityTreeSupported(), + "native port exposes the virtual accessibility tree"); + form.show(); + assertTrue(AccessibilityManager.getInstance().performAction(stableSaveId, "share", null), + "custom action accepted"); + CN.callSerially(new Runnable() { + public void run() { + try { + assertTrue(customActionPerformed, "custom action dispatched on EDT"); + AccessibilityTreeSnapshot nativeSnapshot = AccessibilityInspector.currentSnapshot(); + assertEqual(stableSaveId, find(nativeSnapshot, save).getId(), + "current native semantic snapshot"); + AccessibilityAssertions.assertNoErrors(nativeSnapshot); + Display.getInstance().announceForAccessibility("Testing accessibility announcement"); + done(); + } catch (Throwable t) { + fail("Accessibility action assertions failed: " + t); + } + } + }); + } + + private T add(Container parent, T component, int x, int y, int width, int height) { + parent.add(component); + size(component, x, y, width, height); + return component; + } + + private void size(Component component, int x, int y, int width, int height) { + component.setX(x); + component.setY(y); + component.setWidth(width); + component.setHeight(height); + } + + private AccessibilityNodeSnapshot find(AccessibilityTreeSnapshot tree, Component component) { + AccessibilityNodeSnapshot result = findOrNull(tree, component); + assertTrue(result != null, "semantic node exists for " + component.getClass().getName()); + return result; + } + + private AccessibilityNodeSnapshot findOrNull(AccessibilityTreeSnapshot tree, Component component) { + for (AccessibilityNodeSnapshot node : tree.getNodes().values()) { + if (node.getComponent() == component && node.getVirtualKey() == null) return node; + } + return null; + } + @Override public boolean shouldTakeScreenshot() { return false; From c56de3fbc91376b8ca71e9ae3ea05e9bf31b423a Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Sat, 11 Jul 2026 16:57:19 +0300 Subject: [PATCH 02/15] Document accessibility package --- .../codename1/ui/accessibility/package-info.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 CodenameOne/src/com/codename1/ui/accessibility/package-info.java diff --git a/CodenameOne/src/com/codename1/ui/accessibility/package-info.java b/CodenameOne/src/com/codename1/ui/accessibility/package-info.java new file mode 100644 index 00000000000..2168b0b820b --- /dev/null +++ b/CodenameOne/src/com/codename1/ui/accessibility/package-info.java @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2026 Codename One and contributors. All rights reserved. + */ + +/// Defines the portable accessibility semantics tree for Codename One's +/// lightweight user-interface components. Applications use this package to +/// describe roles, states, values, ranges, actions, traversal, grouping, +/// live regions, panes, collections, and virtual descendants. Platform ports +/// translate the resulting immutable tree to their native accessibility APIs. +/// +/// The entry point for configuring a component is +/// {@link com.codename1.ui.Component#getSemantics()}. Tests and development +/// tools can inspect a resolved tree with +/// {@link com.codename1.ui.accessibility.AccessibilityInspector} and validate +/// it with {@link com.codename1.ui.accessibility.AccessibilityAssertions}. +package com.codename1.ui.accessibility; From 8af86fda2d2c2576ee35c2ad8f3681851db96a68 Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Sat, 11 Jul 2026 17:07:39 +0300 Subject: [PATCH 03/15] Fix native accessibility compatibility --- .../android/AndroidAccessibilityProvider.java | 34 ++++++++++++++++--- .../cn1_windows_accessibility.cpp | 2 +- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/Ports/Android/src/com/codename1/impl/android/AndroidAccessibilityProvider.java b/Ports/Android/src/com/codename1/impl/android/AndroidAccessibilityProvider.java index 045eb526df1..fc9fd853368 100644 --- a/Ports/Android/src/com/codename1/impl/android/AndroidAccessibilityProvider.java +++ b/Ports/Android/src/com/codename1/impl/android/AndroidAccessibilityProvider.java @@ -113,11 +113,11 @@ private AccessibilityNodeInfo createVirtualNode(AccessibilityTreeSnapshot tree, } if (Build.VERSION.SDK_INT >= 21 && node.getValidationError() != null) info.setError(node.getValidationError()); if (Build.VERSION.SDK_INT >= 28) { - info.setHeading(node.getHeadingLevel() > 0 - || node.getRole() == AccessibilityRole.HEADING - || node.getCollectionItemInfo() != null && node.getCollectionItemInfo().isHeading()); - info.setScreenReaderFocusable(node.isFocusable() || label != null); - if (node.getPaneTitle() != null) info.setPaneTitle(node.getPaneTitle()); + setApi28Semantics(info, + node.getHeadingLevel() > 0 + || node.getRole() == AccessibilityRole.HEADING + || node.getCollectionItemInfo() != null && node.getCollectionItemInfo().isHeading(), + node.isFocusable() || label != null, node.getPaneTitle()); } if (Build.VERSION.SDK_INT >= 19) { info.setLiveRegion(node.getLiveRegion() == AccessibilityLiveRegion.ASSERTIVE @@ -131,6 +131,30 @@ private AccessibilityNodeInfo createVirtualNode(AccessibilityTreeSnapshot tree, return info; } + /** + * Invokes API 28 node properties without requiring the Android port's + * compile-time SDK stub to expose them. Release builds may compile the + * port against an older android.jar even though these calls run only on + * Android 9 and newer. + */ + private static void setApi28Semantics(AccessibilityNodeInfo info, boolean heading, + boolean screenReaderFocusable, String paneTitle) { + try { + Class type = AccessibilityNodeInfo.class; + type.getMethod("setHeading", new Class[]{Boolean.TYPE}) + .invoke(info, new Object[]{Boolean.valueOf(heading)}); + type.getMethod("setScreenReaderFocusable", new Class[]{Boolean.TYPE}) + .invoke(info, new Object[]{Boolean.valueOf(screenReaderFocusable)}); + if (paneTitle != null) { + type.getMethod("setPaneTitle", new Class[]{CharSequence.class}) + .invoke(info, new Object[]{paneTitle}); + } + } catch (Throwable ignored) { + // The runtime API is authoritative; gracefully omit these optional + // properties on vendor builds that don't expose the API 28 methods. + } + } + private void addActions(AccessibilityNodeInfo info, AccessibilityNodeSnapshot node) { if (node.isFocusable()) info.addAction(AccessibilityNodeInfo.ACTION_FOCUS); if (hasAction(node, AccessibilityAction.ACTIVATE)) info.addAction(AccessibilityNodeInfo.ACTION_CLICK); diff --git a/Ports/WindowsPort/nativeSources/cn1_windows_accessibility.cpp b/Ports/WindowsPort/nativeSources/cn1_windows_accessibility.cpp index d70bb3d7976..333b29d92b1 100644 --- a/Ports/WindowsPort/nativeSources/cn1_windows_accessibility.cpp +++ b/Ports/WindowsPort/nativeSources/cn1_windows_accessibility.cpp @@ -258,7 +258,7 @@ JAVA_VOID com_codename1_impl_windows_WindowsNative_accessibilityAction___long_ja JAVA_VOID com_codename1_impl_windows_WindowsNative_accessibilityEnd___int(CODENAME_ONE_THREAD_STATE, JAVA_INT changeType) { AcquireSRWLockExclusive(&cn1UiaLock); cn1UiaNodes.swap(cn1UiaPending); cn1UiaPending.clear(); ReleaseSRWLockExclusive(&cn1UiaLock); CN1UiaProvider* root=new CN1UiaProvider(0); - StructureChangedType type=(changeType&1)?StructureChangeType_ChildrenInvalidated:StructureChangeType_ChildrenReordered; + StructureChangeType type=(changeType&1)?StructureChangeType_ChildrenInvalidated:StructureChangeType_ChildrenReordered; UiaRaiseStructureChangedEvent(root,type,NULL,0); root->Release(); } } From 0d5d20f294b5302929c713774652a0f90d780673 Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Sat, 11 Jul 2026 18:49:08 +0300 Subject: [PATCH 04/15] Fix accessibility CI quality gates --- .../accessibility/AccessibilityManager.java | 184 +++++++++++------- .../cn1_windows_accessibility.cpp | 9 +- .../AccessibilitySemanticsSnippets.java | 156 +++++++++++++++ .../Accessibility-Semantics.asciidoc | 99 +--------- 4 files changed, 283 insertions(+), 165 deletions(-) create mode 100644 docs/demos/common/src/main/java/com/codenameone/developerguide/snippets/AccessibilitySemanticsSnippets.java diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityManager.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityManager.java index 476e826c801..33ccb4d715d 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityManager.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityManager.java @@ -241,15 +241,17 @@ private BuildNode buildComponentNode(final Component component, AccessibilityNod out.builder.collectionItemInfo = config.getCollectionItemInfo() == null ? inferCollectionItem(component) : config.getCollectionItemInfo(); out.builder.bounds = componentBounds(component); - out.builder.selected = config.getSelected() == null ? inferSelected(component) : config.getSelected(); + out.builder.selected = config.getSelected(); + if (out.builder.selected == null) applyInferredSelected(component, out.builder); out.builder.expanded = config.getExpanded(); out.builder.enabled = config.getEnabled() == null ? Boolean.valueOf(component.isEnabled()) : config.getEnabled(); out.builder.invalid = config.getInvalid(); out.builder.busy = config.getBusy(); - out.builder.readOnly = config.getReadOnly() == null ? inferReadOnly(component) : config.getReadOnly(); + out.builder.readOnly = config.getReadOnly(); out.builder.required = config.getRequired(); - out.builder.multiline = config.getMultiline() == null ? inferMultiline(component) : config.getMultiline(); - out.builder.obscured = config.getObscured() == null ? inferObscured(component) : config.getObscured(); + out.builder.multiline = config.getMultiline(); + out.builder.obscured = config.getObscured(); + applyInferredTextStates(component, out.builder); out.builder.pressed = config.getPressed(); out.builder.current = config.getCurrent(); out.builder.modal = config.isModal() || component instanceof Dialog; @@ -339,14 +341,7 @@ private void addListChildren(final com.codename1.ui.List list, long hostId, List i + 1, size, 1, false)) .setBounds(list.getAccessibilityItemBounds(i, new Rectangle())) .addAction(new AccessibilityAction(AccessibilityAction.ACTIVATE, null, - new AccessibilityAction.Handler() { - public boolean perform(Component component, Object argument) { - if (!list.isEnabled()) return false; - list.setSelectedIndex(index); - list.keyReleased(Display.getInstance().getKeyCode(Display.GAME_FIRE)); - return true; - } - })); + new ListActivateHandler(list, index))); destination.add(buildVirtualNode(list, item, "list/item-" + i)); } } @@ -354,65 +349,32 @@ public boolean perform(Component component, Object argument) { private void addDefaultActions(final Component component, AccessibilityNodeSnapshot.Builder builder) { if (component.isFocusable() && !hasAction(builder.actions, AccessibilityAction.FOCUS)) { builder.actions.add(new AccessibilityAction(AccessibilityAction.FOCUS, null, - new AccessibilityAction.Handler() { - public boolean perform(Component source, Object argument) { - if (!source.isEnabled()) return false; - source.requestFocus(); - return true; - } - })); + FocusHandler.INSTANCE)); } if (component instanceof Button && !hasAction(builder.actions, AccessibilityAction.ACTIVATE)) { builder.actions.add(new AccessibilityAction(AccessibilityAction.ACTIVATE, null, - new AccessibilityAction.Handler() { - public boolean perform(Component source, Object argument) { - if (!source.isEnabled()) return false; - source.keyReleased(Display.getInstance().getKeyCode(Display.GAME_FIRE)); - return true; - } - })); + ActivateHandler.INSTANCE)); } if (component instanceof Slider) { final Slider slider = (Slider)component; if (slider.isEditable() && !hasAction(builder.actions, AccessibilityAction.INCREMENT)) { builder.actions.add(new AccessibilityAction(AccessibilityAction.INCREMENT, null, - new AccessibilityAction.Handler() { - public boolean perform(Component source, Object argument) { - slider.setProgress(Math.min(slider.getMaxValue(), slider.getProgress() + Math.max(1, slider.getIncrements()))); - return true; - } - })); + new SliderAdjustmentHandler(slider, 1))); } if (slider.isEditable() && !hasAction(builder.actions, AccessibilityAction.DECREMENT)) { builder.actions.add(new AccessibilityAction(AccessibilityAction.DECREMENT, null, - new AccessibilityAction.Handler() { - public boolean perform(Component source, Object argument) { - slider.setProgress(Math.max(slider.getMinValue(), slider.getProgress() - Math.max(1, slider.getIncrements()))); - return true; - } - })); + new SliderAdjustmentHandler(slider, -1))); } } if (component instanceof TextArea) { final TextArea text = (TextArea)component; if (!hasAction(builder.actions, AccessibilityAction.FOCUS)) { builder.actions.add(new AccessibilityAction(AccessibilityAction.FOCUS, null, - new AccessibilityAction.Handler() { - public boolean perform(Component source, Object argument) { - source.requestFocus(); - return true; - } - })); + FocusHandler.INSTANCE)); } if (text.isEditable() && !hasAction(builder.actions, AccessibilityAction.SET_TEXT)) { builder.actions.add(new AccessibilityAction(AccessibilityAction.SET_TEXT, null, - new AccessibilityAction.Handler() { - public boolean perform(Component source, Object argument) { - if (!(argument instanceof String)) return false; - text.setText((String)argument); - return true; - } - })); + new SetTextHandler(text))); } } } @@ -460,13 +422,13 @@ private AccessibilityCheckedState inferChecked(Component component, Accessibilit return AccessibilityCheckedState.UNSPECIFIED; } - private Boolean inferSelected(Component component) { + private void applyInferredSelected(Component component, AccessibilityNodeSnapshot.Builder builder) { if (component instanceof Button && (((Button)component).isToggle() || isTabButton((Button)component))) { - return Boolean.valueOf(((Button)component).isSelected()); + builder.selected = Boolean.valueOf(((Button)component).isSelected()); + return; } Tabs tabOwner = tabPanelOwner(component); - if (tabOwner != null) return Boolean.valueOf(tabOwner.getSelectedComponent() == component); - return null; + if (tabOwner != null) builder.selected = Boolean.valueOf(tabOwner.getSelectedComponent() == component); } private Tabs tabPanelOwner(Component component) { @@ -515,16 +477,16 @@ private AccessibilityCollectionItemInfo inferCollectionItem(Component component) return null; } - private Boolean inferReadOnly(Component component) { - return component instanceof TextArea ? Boolean.valueOf(!((TextArea)component).isEditable()) : null; - } - - private Boolean inferMultiline(Component component) { - return component instanceof TextArea ? Boolean.valueOf(!(component instanceof TextField) || ((TextArea)component).getRows() > 1) : null; - } - - private Boolean inferObscured(Component component) { - return component instanceof TextArea ? Boolean.valueOf((((TextArea)component).getConstraint() & TextArea.PASSWORD) != 0) : null; + private void applyInferredTextStates(Component component, AccessibilityNodeSnapshot.Builder builder) { + if (!(component instanceof TextArea)) return; + TextArea text = (TextArea)component; + if (builder.readOnly == null) builder.readOnly = Boolean.valueOf(!text.isEditable()); + if (builder.multiline == null) { + builder.multiline = Boolean.valueOf(!(component instanceof TextField) || text.getRows() > 1); + } + if (builder.obscured == null) { + builder.obscured = Boolean.valueOf((text.getConstraint() & TextArea.PASSWORD) != 0); + } } private boolean shouldExpose(Component component, AccessibilityNode config, BuildNode node) { @@ -565,16 +527,7 @@ private void intersect(Rectangle target, Rectangle clip) { } private void sortTree(List nodes) { - Collections.sort(nodes, new Comparator() { - public int compare(BuildNode a, BuildNode b) { - boolean an = Double.isNaN(a.builder.sortKey); - boolean bn = Double.isNaN(b.builder.sortKey); - if (an && bn) return 0; - if (an) return 1; - if (bn) return -1; - return a.builder.sortKey < b.builder.sortKey ? -1 : a.builder.sortKey == b.builder.sortKey ? 0 : 1; - } - }); + Collections.sort(nodes, SortKeyComparator.INSTANCE); applyRelativeOrder(nodes); for (BuildNode node : nodes) sortTree(node.children); } @@ -666,4 +619,85 @@ private static final class BuildNode { AccessibilityNodeSnapshot.Builder builder = new AccessibilityNodeSnapshot.Builder(); List children = new ArrayList(); } + + private static final class SortKeyComparator implements Comparator { + private static final SortKeyComparator INSTANCE = new SortKeyComparator(); + + public int compare(BuildNode a, BuildNode b) { + boolean an = Double.isNaN(a.builder.sortKey); + boolean bn = Double.isNaN(b.builder.sortKey); + if (an && bn) return 0; + if (an) return 1; + if (bn) return -1; + return Double.compare(a.builder.sortKey, b.builder.sortKey); + } + } + + private static final class FocusHandler implements AccessibilityAction.Handler { + private static final FocusHandler INSTANCE = new FocusHandler(); + + public boolean perform(Component source, Object argument) { + if (!source.isEnabled()) return false; + source.requestFocus(); + return true; + } + } + + private static final class ActivateHandler implements AccessibilityAction.Handler { + private static final ActivateHandler INSTANCE = new ActivateHandler(); + + public boolean perform(Component source, Object argument) { + if (!source.isEnabled()) return false; + source.keyReleased(Display.getInstance().getKeyCode(Display.GAME_FIRE)); + return true; + } + } + + private static final class ListActivateHandler implements AccessibilityAction.Handler { + private final com.codename1.ui.List list; + private final int index; + + private ListActivateHandler(com.codename1.ui.List list, int index) { + this.list = list; + this.index = index; + } + + public boolean perform(Component source, Object argument) { + if (!list.isEnabled()) return false; + list.setSelectedIndex(index); + list.keyReleased(Display.getInstance().getKeyCode(Display.GAME_FIRE)); + return true; + } + } + + private static final class SliderAdjustmentHandler implements AccessibilityAction.Handler { + private final Slider slider; + private final int direction; + + private SliderAdjustmentHandler(Slider slider, int direction) { + this.slider = slider; + this.direction = direction; + } + + public boolean perform(Component source, Object argument) { + int increment = Math.max(1, slider.getIncrements()); + int value = slider.getProgress() + direction * increment; + slider.setProgress(Math.max(slider.getMinValue(), Math.min(slider.getMaxValue(), value))); + return true; + } + } + + private static final class SetTextHandler implements AccessibilityAction.Handler { + private final TextArea text; + + private SetTextHandler(TextArea text) { + this.text = text; + } + + public boolean perform(Component source, Object argument) { + if (!(argument instanceof String)) return false; + text.setText((String)argument); + return true; + } + } } diff --git a/Ports/WindowsPort/nativeSources/cn1_windows_accessibility.cpp b/Ports/WindowsPort/nativeSources/cn1_windows_accessibility.cpp index 333b29d92b1..bc0d40fabc2 100644 --- a/Ports/WindowsPort/nativeSources/cn1_windows_accessibility.cpp +++ b/Ports/WindowsPort/nativeSources/cn1_windows_accessibility.cpp @@ -1,13 +1,20 @@ /* Native virtual accessibility tree for the lightweight Win32 port. */ #ifdef _WIN32 -#include "cn1_windows.h" +/* xwin may provide a newer MSVC STL than the clang-cl installed by the Linux + * cross-compile runner. This file uses only the long-stable string/vector + * subset, so allow that supported cross-toolchain pairing. */ +#ifndef _ALLOW_COMPILER_AND_STL_VERSION_MISMATCH +#define _ALLOW_COMPILER_AND_STL_VERSION_MISMATCH +#endif + #include #include #include #include #include #include +#include "cn1_windows.h" #pragma comment(lib, "uiautomationcore.lib") #pragma comment(lib, "oleaut32.lib") diff --git a/docs/demos/common/src/main/java/com/codenameone/developerguide/snippets/AccessibilitySemanticsSnippets.java b/docs/demos/common/src/main/java/com/codenameone/developerguide/snippets/AccessibilitySemanticsSnippets.java new file mode 100644 index 00000000000..e678f470ef7 --- /dev/null +++ b/docs/demos/common/src/main/java/com/codenameone/developerguide/snippets/AccessibilitySemanticsSnippets.java @@ -0,0 +1,156 @@ +package com.codenameone.developerguide.snippets; + +import com.codename1.ui.Button; +import com.codename1.ui.Component; +import com.codename1.ui.Form; +import com.codename1.ui.Label; +import com.codename1.ui.accessibility.AccessibilityAction; +import com.codename1.ui.accessibility.AccessibilityAssertions; +import com.codename1.ui.accessibility.AccessibilityCheckedState; +import com.codename1.ui.accessibility.AccessibilityChildProvider; +import com.codename1.ui.accessibility.AccessibilityCollectionInfo; +import com.codename1.ui.accessibility.AccessibilityCollectionItemInfo; +import com.codename1.ui.accessibility.AccessibilityGrouping; +import com.codename1.ui.accessibility.AccessibilityInspector; +import com.codename1.ui.accessibility.AccessibilityLiveRegion; +import com.codename1.ui.accessibility.AccessibilityNode; +import com.codename1.ui.accessibility.AccessibilityNodeSnapshot; +import com.codename1.ui.accessibility.AccessibilityRange; +import com.codename1.ui.accessibility.AccessibilityRole; +import com.codename1.ui.accessibility.AccessibilityTreeSnapshot; +import com.codename1.ui.geom.Rectangle; +import java.util.ArrayList; +import java.util.List; + +/** Compiled source snippets for the accessibility semantics guide chapter. */ +public class AccessibilitySemanticsSnippets { + + public void configureButton() { + // tag::accessibility-semantics-button[] + Button save = new Button("Save"); + save.getSemantics() + .setHint("Saves the edited profile") + .setIdentifier("profile-save"); + // end::accessibility-semantics-button[] + } + + public void configureRoles(Component wifiSwitch, Label title) { + // tag::accessibility-semantics-roles[] + wifiSwitch.getSemantics() + .setRole(AccessibilityRole.SWITCH) + .setLabel("Wi-Fi") + .setChecked(AccessibilityCheckedState.CHECKED) + .setEnabled(Boolean.TRUE) + .setHint("Double tap to turn Wi-Fi off"); + + title.getSemantics() + .setHeadingLevel(2) + .setIdentifier("network-heading"); + // end::accessibility-semantics-roles[] + } + + public void configureRange(Component rating) { + // tag::accessibility-semantics-range[] + rating.getSemantics() + .setRole(AccessibilityRole.SLIDER) + .setLabel("Rating") + .setRange(new AccessibilityRange(0, 5, 3, 1, "3 out of 5")); + // end::accessibility-semantics-range[] + } + + public void configureAction(Component card) { + // tag::accessibility-semantics-action[] + card.getSemantics().addAction(new AccessibilityAction( + "archive", + "Archive message", + new AccessibilityAction.Handler() { + public boolean perform(Component component, Object argument) { + archiveMessage(); + return true; + } + } + )); + // end::accessibility-semantics-action[] + } + + public void configureGrouping(Component summaryCard) { + // tag::accessibility-semantics-grouping[] + summaryCard.getSemantics() + .setRole(AccessibilityRole.GENERIC) + .setGrouping(AccessibilityGrouping.MERGE_DESCENDANTS); + // end::accessibility-semantics-grouping[] + } + + public void configureVirtualChildren(Component chart, final List points) { + // tag::accessibility-semantics-virtual[] + chart.getSemantics().setChildProvider(new AccessibilityChildProvider() { + public List getAccessibilityChildren(Component owner) { + List result = new ArrayList(); + for (ChartPoint point : points) { + AccessibilityNode node = new AccessibilityNode("point-" + point.getId()); + node.setRole(AccessibilityRole.IMAGE) + .setLabel(point.getLabel()) + .setValue(point.getFormattedValue()) + .setBounds(point.getBounds()); + result.add(node); + } + return result; + } + }); + // end::accessibility-semantics-virtual[] + } + + public void configureTraversal(Component cancel, Component continueButton, Component help) { + // tag::accessibility-semantics-traversal[] + cancel.getSemantics().setSortKey(1); + continueButton.getSemantics().setSortKey(2); + help.getSemantics().setTraversalAfter(continueButton); + // end::accessibility-semantics-traversal[] + } + + public void configureLiveRegion(Label status) { + // tag::accessibility-semantics-live[] + status.getSemantics() + .setRole(AccessibilityRole.ALERT) + .setLiveRegion(AccessibilityLiveRegion.POLITE); + status.setText("Upload complete"); + // end::accessibility-semantics-live[] + } + + public void configureCollection(Component grid, Component cell) { + // tag::accessibility-semantics-collection[] + grid.getSemantics().setCollectionInfo( + new AccessibilityCollectionInfo(20, 3, false, + AccessibilityCollectionInfo.SELECTION_MULTIPLE)); + + cell.getSemantics().setCollectionItemInfo( + new AccessibilityCollectionItemInfo( + 4, 1, 2, 1, 5, 20, 1, false)); + // end::accessibility-semantics-collection[] + } + + public String inspect(Form myForm, int screenX, int screenY) { + // tag::accessibility-semantics-inspection[] + AccessibilityTreeSnapshot tree = + AccessibilityInspector.snapshot(myForm); + + AccessibilityAssertions.assertNoErrors(tree); + AccessibilityAssertions.assertNoUnlabeledInteractiveNodes(tree); + + String diagnosticJson = tree.toJson(); + AccessibilityNodeSnapshot hit = tree.getNodeAt(screenX, screenY); + // end::accessibility-semantics-inspection[] + return diagnosticJson + (hit == null ? "" : hit.getLabel()); + } + + private void archiveMessage() { + } + + /** Minimal model contract used by the virtual-descendant example. */ + public interface ChartPoint { + String getId(); + String getLabel(); + String getFormattedValue(); + Rectangle getBounds(); + } +} diff --git a/docs/developer-guide/Accessibility-Semantics.asciidoc b/docs/developer-guide/Accessibility-Semantics.asciidoc index 6cd09e7f876..a6132715d6b 100644 --- a/docs/developer-guide/Accessibility-Semantics.asciidoc +++ b/docs/developer-guide/Accessibility-Semantics.asciidoc @@ -11,12 +11,7 @@ Standard components work without extra configuration. `Button`, `CheckBox`, `Rad `Component.setAccessibilityText()` remains supported. It is a compatibility alias for the semantic label. New code should use `getSemantics()` when it needs more than a label. [source,java] ----- -Button save = new Button("Save"); -save.getSemantics() - .setHint("Saves the edited profile") - .setIdentifier("profile-save"); ----- +include::../demos/common/src/main/java/com/codenameone/developerguide/snippets/AccessibilitySemanticsSnippets.java[tag=accessibility-semantics-button,indent=0] Changes to text, selection, focus, enabled state, bounds, scrolling, ranges, tabs, and the current `Form` automatically invalidate the native semantic tree. Custom components should call `accessibilityChanged()` after a semantic value changes outside a standard setter. @@ -25,20 +20,7 @@ Changes to text, selection, focus, enabled state, bounds, scrolling, ranges, tab `AccessibilityRole` contains portable control roles including buttons, toggle buttons, switches, checkboxes, radio buttons, headings, links, images, text and search fields, sliders, progress indicators, lists, grids, rows, cells, headers, tabs, dialogs, alerts, menus, toolbars, combo boxes, trees, and separators. A port maps an unsupported role to the closest native role without discarding its label or state. [source,java] ----- -Component wifiSwitch = new MyPaintedSwitch(); -wifiSwitch.getSemantics() - .setRole(AccessibilityRole.SWITCH) - .setLabel("Wi-Fi") - .setChecked(AccessibilityCheckedState.CHECKED) - .setEnabled(Boolean.TRUE) - .setHint("Double tap to turn Wi-Fi off"); - -Label title = new Label("Network"); -title.getSemantics() - .setHeadingLevel(2) - .setIdentifier("network-heading"); ----- +include::../demos/common/src/main/java/com/codenameone/developerguide/snippets/AccessibilitySemanticsSnippets.java[tag=accessibility-semantics-roles,indent=0] Tri-state controls use `UNCHECKED`, `CHECKED`, or `MIXED`. Nullable Boolean properties distinguish an explicit state from an unspecified state. Available properties include selected, expanded, enabled, invalid, busy, read-only, required, multiline, obscured, pressed, and current. `setValidationError()` supplies both the error message and invalid state. `setPaneTitle()` describes a newly displayed pane or screen, and `setModal(true)` identifies a modal scope. @@ -49,12 +31,7 @@ Use `setRoleDescription()` only when the platform role is not sufficiently speci `AccessibilityRange` describes minimum, maximum, current value, increment, and an optional spoken value. The spoken value is useful for ranges such as ratings and durations where a raw number is ambiguous. [source,java] ----- -rating.getSemantics() - .setRole(AccessibilityRole.SLIDER) - .setLabel("Rating") - .setRange(new AccessibilityRange(0, 5, 3, 1, "3 out of 5")); ----- +include::../demos/common/src/main/java/com/codenameone/developerguide/snippets/AccessibilitySemanticsSnippets.java[tag=accessibility-semantics-range,indent=0] Editable controls can provide `SET_VALUE` or `SET_TEXT` actions. Sliders and other adjustable controls should expose `INCREMENT` and `DECREMENT`. Standard components infer these actions. @@ -63,18 +40,7 @@ Editable controls can provide `SET_VALUE` or `SET_TEXT` actions. Sliders and oth An `AccessibilityAction` has a stable ID, a localized label, an enabled state, and a handler. Handlers always execute on the Codename One EDT, including when the action originates on a native accessibility thread. [source,java] ----- -card.getSemantics().addAction(new AccessibilityAction( - "archive", - "Archive message", - new AccessibilityAction.Handler() { - public boolean perform(Component component, Object argument) { - archiveMessage(); - return true; - } - } -)); ----- +include::../demos/common/src/main/java/com/codenameone/developerguide/snippets/AccessibilitySemanticsSnippets.java[tag=accessibility-semantics-action,indent=0] Use the standard IDs in `AccessibilityAction` for activation, long press, increment, decrement, set value, set text, selection, character or word cursor movement, focus, show-on-screen, dismiss, expand, collapse, scrolling, and clipboard operations. A custom ID must be stable and its label must not be null. @@ -90,31 +56,12 @@ Use the standard IDs in `AccessibilityAction` for activation, long press, increm * `EXCLUDE_SUBTREE` removes the component and all descendants. [source,java] ----- -summaryCard.getSemantics() - .setRole(AccessibilityRole.GENERIC) - .setGrouping(AccessibilityGrouping.MERGE_DESCENDANTS); ----- +include::../demos/common/src/main/java/com/codenameone/developerguide/snippets/AccessibilitySemanticsSnippets.java[tag=accessibility-semantics-grouping,indent=0] For content that is painted without child components, attach an `AccessibilityChildProvider`, or add standalone `AccessibilityNode` children. Every virtual node must use a stable `virtualKey`. Stable keys preserve native focus while rows are updated or recycled. [source,java] ----- -chart.getSemantics().setChildProvider(new AccessibilityChildProvider() { - public List getAccessibilityChildren(Component owner) { - List result = new ArrayList(); - for (Point point : model.getPoints()) { - AccessibilityNode node = new AccessibilityNode("point-" + point.getId()); - node.setRole(AccessibilityRole.IMAGE) - .setLabel(point.getLabel()) - .setValue(point.getFormattedValue()) - .setBounds(point.getBounds()); - result.add(node); - } - return result; - } -}); ----- +include::../demos/common/src/main/java/com/codenameone/developerguide/snippets/AccessibilitySemanticsSnippets.java[tag=accessibility-semantics-virtual,indent=0] Virtual bounds are relative to the owning component. Component nodes use their clipped absolute bounds. @@ -123,11 +70,7 @@ Virtual bounds are relative to the owning component. Component nodes use their c Visual order is the default reading order. `setSortKey()` assigns an ordered semantic key among siblings. `setTraversalBefore()` and `setTraversalAfter()` express a direct relationship when a numeric order would be fragile. [source,java] ----- -cancel.getSemantics().setSortKey(1); -continueButton.getSemantics().setSortKey(2); -help.getSemantics().setTraversalAfter(continueButton); ----- +include::../demos/common/src/main/java/com/codenameone/developerguide/snippets/AccessibilitySemanticsSnippets.java[tag=accessibility-semantics-traversal,indent=0] Keep traversal relationships within the same semantic parent. The tree builder resolves these constraints deterministically and preserves stable node IDs. @@ -136,12 +79,7 @@ Keep traversal relationships within the same semantic parent. The tree builder r Set `AccessibilityLiveRegion.POLITE` for non-urgent updates and `ASSERTIVE` for errors or urgent status. `OFF` is the default. Live changes produce the corresponding platform notification or ARIA live update. [source,java] ----- -status.getSemantics() - .setRole(AccessibilityRole.ALERT) - .setLiveRegion(AccessibilityLiveRegion.POLITE); -status.setText("Upload complete"); ----- +include::../demos/common/src/main/java/com/codenameone/developerguide/snippets/AccessibilitySemanticsSnippets.java[tag=accessibility-semantics-live,indent=0] Form changes and nodes with a pane title produce screen or pane transition notifications. `Display.announceForAccessibility()` remains available for an exceptional announcement that is not represented by persistent UI. Prefer a live region for state that is visible on screen. @@ -150,15 +88,7 @@ Form changes and nodes with a pane title produce screen or pane transition notif `AccessibilityCollectionInfo` describes row and column counts, hierarchy, and selection mode. `AccessibilityCollectionItemInfo` describes row and column index, spans, position and size in a set, nesting level, and header status. [source,java] ----- -grid.getSemantics().setCollectionInfo( - new AccessibilityCollectionInfo(20, 3, false, - AccessibilityCollectionInfo.SELECTION_MULTIPLE)); - -cell.getSemantics().setCollectionItemInfo( - new AccessibilityCollectionItemInfo( - 4, 1, 2, 1, 5, 20, 1, false)); ----- +include::../demos/common/src/main/java/com/codenameone/developerguide/snippets/AccessibilitySemanticsSnippets.java[tag=accessibility-semantics-collection,indent=0] Row and column indexes are zero-based. Position and set size are one-based; use `-1` when unknown. Lists, tables, tabs, and their items infer this metadata where possible. @@ -167,16 +97,7 @@ Row and column indexes are zero-based. Position and set size are one-based; use `AccessibilityInspector` returns an immutable snapshot. A snapshot is safe to inspect without racing native accessibility callbacks and includes stable IDs, hierarchy, bounds, resolved state, actions, range and collection data. `toJson()` is suitable for diagnostic reports and tooling. [source,java] ----- -AccessibilityTreeSnapshot tree = - AccessibilityInspector.snapshot(myForm); - -AccessibilityAssertions.assertNoErrors(tree); -AccessibilityAssertions.assertNoUnlabeledInteractiveNodes(tree); - -String diagnosticJson = tree.toJson(); -AccessibilityNodeSnapshot hit = tree.getNodeAt(screenX, screenY); ----- +include::../demos/common/src/main/java/com/codenameone/developerguide/snippets/AccessibilitySemanticsSnippets.java[tag=accessibility-semantics-inspection,indent=0] `AccessibilityAssertions.audit()` reports machine-readable `AccessibilityIssue` values for unlabeled controls, invalid ranges, duplicate identifiers or actions, invalid collection positions, missing parents, cycles, unnamed dialogs, and unlabeled custom actions. Warnings also identify suspicious role/state combinations and empty bounds. From 5433112d56d6d0594b13ff84ac43acba9aec7790 Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Sat, 11 Jul 2026 21:16:52 +0300 Subject: [PATCH 05/15] Fix remaining accessibility CI checks --- .../impl/android/AndroidAccessibilityProvider.java | 2 +- docs/developer-guide/Accessibility-Semantics.asciidoc | 10 +++++----- docs/developer-guide/languagetool-accept.txt | 3 +++ 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/Ports/Android/src/com/codename1/impl/android/AndroidAccessibilityProvider.java b/Ports/Android/src/com/codename1/impl/android/AndroidAccessibilityProvider.java index fc9fd853368..85e86a7d7ba 100644 --- a/Ports/Android/src/com/codename1/impl/android/AndroidAccessibilityProvider.java +++ b/Ports/Android/src/com/codename1/impl/android/AndroidAccessibilityProvider.java @@ -42,7 +42,7 @@ final class AndroidAccessibilityProvider extends AccessibilityNodeProvider { @Override public AccessibilityNodeInfo createAccessibilityNodeInfo(int virtualViewId) { AccessibilityTreeSnapshot tree = implementation.getAccessibilityTreeSnapshot(); - if (virtualViewId == View.NO_ID || virtualViewId == AccessibilityNodeProvider.HOST_VIEW_ID) { + if (virtualViewId == AccessibilityNodeProvider.HOST_VIEW_ID) { return createHostNode(tree); } AccessibilityNodeSnapshot node = tree.getNode(virtualViewId); diff --git a/docs/developer-guide/Accessibility-Semantics.asciidoc b/docs/developer-guide/Accessibility-Semantics.asciidoc index a6132715d6b..ca3bb43edd5 100644 --- a/docs/developer-guide/Accessibility-Semantics.asciidoc +++ b/docs/developer-guide/Accessibility-Semantics.asciidoc @@ -1,6 +1,6 @@ = Accessibility Semantics -Codename One components are lightweight: they are painted by Codename One instead of being represented by a native widget on every platform. The accessibility semantics API builds an explicit, immutable virtual tree from those components and presents it to VoiceOver, TalkBack, Windows UI Automation, AT-SPI, Java Access Bridge, and web accessibility APIs. +Codename One components are lightweight: they're painted by Codename One instead of being represented by a native widget on every platform. The accessibility semantics API builds an explicit, immutable virtual tree from those components and presents it to VoiceOver, TalkBack, Windows UI Automation, AT-SPI, Java Access Bridge, and web accessibility APIs. The semantic tree is separate from the visual tree. This is important for renderer-backed controls, merged cards, decorative content, custom controls, and applications that need a reading order different from paint order. @@ -8,7 +8,7 @@ The semantic tree is separate from the visual tree. This is important for render Standard components work without extra configuration. `Button`, `CheckBox`, `RadioButton`, `Slider`, text fields, lists, tables, tabs, labels, dialogs, and containers infer appropriate roles, values, states, collection metadata, and standard actions. Renderer-backed `List` rows are exposed as stable virtual children even though no `Component` exists for each painted row. -`Component.setAccessibilityText()` remains supported. It is a compatibility alias for the semantic label. New code should use `getSemantics()` when it needs more than a label. +`Component.setAccessibilityText()` remains supported. It's a compatibility alias for the semantic label. New code should use `getSemantics()` when it needs more than a label. [source,java] include::../demos/common/src/main/java/com/codenameone/developerguide/snippets/AccessibilitySemanticsSnippets.java[tag=accessibility-semantics-button,indent=0] @@ -24,7 +24,7 @@ include::../demos/common/src/main/java/com/codenameone/developerguide/snippets/A Tri-state controls use `UNCHECKED`, `CHECKED`, or `MIXED`. Nullable Boolean properties distinguish an explicit state from an unspecified state. Available properties include selected, expanded, enabled, invalid, busy, read-only, required, multiline, obscured, pressed, and current. `setValidationError()` supplies both the error message and invalid state. `setPaneTitle()` describes a newly displayed pane or screen, and `setModal(true)` identifies a modal scope. -Use `setRoleDescription()` only when the platform role is not sufficiently specific. Localize labels, hints, descriptions, errors, pane titles, role descriptions, and custom action labels. +Use `setRoleDescription()` only when the platform role isn't sufficiently specific. Localize labels, hints, descriptions, errors, pane titles, role descriptions, and custom action labels. == Ranges and editable values @@ -58,7 +58,7 @@ Use the standard IDs in `AccessibilityAction` for activation, long press, increm [source,java] include::../demos/common/src/main/java/com/codenameone/developerguide/snippets/AccessibilitySemanticsSnippets.java[tag=accessibility-semantics-grouping,indent=0] -For content that is painted without child components, attach an `AccessibilityChildProvider`, or add standalone `AccessibilityNode` children. Every virtual node must use a stable `virtualKey`. Stable keys preserve native focus while rows are updated or recycled. +For content that's painted without child components, attach an `AccessibilityChildProvider`, or add standalone `AccessibilityNode` children. Every virtual node must use a stable `virtualKey`. Stable keys preserve native focus while rows are updated or recycled. [source,java] include::../demos/common/src/main/java/com/codenameone/developerguide/snippets/AccessibilitySemanticsSnippets.java[tag=accessibility-semantics-virtual,indent=0] @@ -81,7 +81,7 @@ Set `AccessibilityLiveRegion.POLITE` for non-urgent updates and `ASSERTIVE` for [source,java] include::../demos/common/src/main/java/com/codenameone/developerguide/snippets/AccessibilitySemanticsSnippets.java[tag=accessibility-semantics-live,indent=0] -Form changes and nodes with a pane title produce screen or pane transition notifications. `Display.announceForAccessibility()` remains available for an exceptional announcement that is not represented by persistent UI. Prefer a live region for state that is visible on screen. +Form changes and nodes with a pane title produce screen or pane transition notifications. `Display.announceForAccessibility()` remains available for an exceptional announcement that isn't represented by persistent UI. Prefer a live region for state that's visible on screen. == Collections diff --git a/docs/developer-guide/languagetool-accept.txt b/docs/developer-guide/languagetool-accept.txt index d9445e2bef1..10c8fbc45c9 100644 --- a/docs/developer-guide/languagetool-accept.txt +++ b/docs/developer-guide/languagetool-accept.txt @@ -604,6 +604,9 @@ bitmask DeX Siri devirtualization +# Coordinate variable names used in accessibility hit-testing examples. +screenX +screenY # AR / VR terms (Augmented-Reality.asciidoc, Virtual-Reality.asciidoc) raycasts? equirectangular From 0141d34fcffbdbed86bb203811d8587045f2cf0f Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Sun, 12 Jul 2026 09:33:39 +0300 Subject: [PATCH 06/15] Satisfy accessibility static analysis --- CodenameOne/src/com/codename1/ui/Button.java | 4 +- .../src/com/codename1/ui/CheckBox.java | 3 +- CodenameOne/src/com/codename1/ui/Display.java | 6 +- CodenameOne/src/com/codename1/ui/Label.java | 3 +- CodenameOne/src/com/codename1/ui/List.java | 4 +- .../src/com/codename1/ui/RadioButton.java | 3 +- CodenameOne/src/com/codename1/ui/Slider.java | 3 +- CodenameOne/src/com/codename1/ui/Tabs.java | 4 +- .../src/com/codename1/ui/TextArea.java | 4 +- .../ui/accessibility/AccessibilityAction.java | 12 +- .../AccessibilityAssertions.java | 36 +- .../AccessibilityCollectionItemInfo.java | 34 +- .../ui/accessibility/AccessibilityIssue.java | 16 +- .../accessibility/AccessibilityManager.java | 367 ++++++++++++------ .../ui/accessibility/AccessibilityNode.java | 343 ++++++++++++---- .../AccessibilityNodeSnapshot.java | 152 ++++++-- .../AccessibilityTreeSnapshot.java | 157 +++++--- 17 files changed, 823 insertions(+), 328 deletions(-) diff --git a/CodenameOne/src/com/codename1/ui/Button.java b/CodenameOne/src/com/codename1/ui/Button.java index 33b0f255c62..0246355d122 100644 --- a/CodenameOne/src/com/codename1/ui/Button.java +++ b/CodenameOne/src/com/codename1/ui/Button.java @@ -24,6 +24,7 @@ package com.codename1.ui; +import com.codename1.ui.accessibility.AccessibilityManager; import com.codename1.ui.events.ActionEvent; import com.codename1.ui.events.ActionListener; import com.codename1.ui.events.ActionSource; @@ -996,8 +997,7 @@ public void setToggle(boolean toggle) { return; } this.toggle = toggle; - accessibilityChanged(com.codename1.ui.accessibility.AccessibilityManager.CHANGE_STRUCTURE - | com.codename1.ui.accessibility.AccessibilityManager.CHANGE_STATE); + accessibilityChanged(AccessibilityManager.CHANGE_STRUCTURE | AccessibilityManager.CHANGE_STATE); if (toggle && "CheckBox".equals(getUIID()) || "RadioButton".equals(getUIID())) { setUIID("ToggleButton"); } diff --git a/CodenameOne/src/com/codename1/ui/CheckBox.java b/CodenameOne/src/com/codename1/ui/CheckBox.java index 90c2cd94e46..4de2a09f6a4 100644 --- a/CodenameOne/src/com/codename1/ui/CheckBox.java +++ b/CodenameOne/src/com/codename1/ui/CheckBox.java @@ -24,6 +24,7 @@ package com.codename1.ui; +import com.codename1.ui.accessibility.AccessibilityManager; import com.codename1.cloud.BindTarget; import com.codename1.ui.events.ActionEvent; import com.codename1.ui.events.ActionListener; @@ -173,7 +174,7 @@ public void setSelected(boolean selected) { this.selected = selected; if (changed) { fireChangeEvent(); - accessibilityChanged(com.codename1.ui.accessibility.AccessibilityManager.CHANGE_STATE); + accessibilityChanged(AccessibilityManager.CHANGE_STATE); } repaint(); } diff --git a/CodenameOne/src/com/codename1/ui/Display.java b/CodenameOne/src/com/codename1/ui/Display.java index 8cdce2cf3ec..bbcde6c12f6 100644 --- a/CodenameOne/src/com/codename1/ui/Display.java +++ b/CodenameOne/src/com/codename1/ui/Display.java @@ -59,6 +59,7 @@ import com.codename1.plugin.event.IsGalleryTypeSupportedEvent; import com.codename1.plugin.event.OpenGalleryEvent; import com.codename1.system.CrashReport; +import com.codename1.ui.accessibility.AccessibilityManager; import com.codename1.ui.animations.Animation; import com.codename1.ui.animations.CommonTransitions; import com.codename1.ui.animations.Transition; @@ -1746,9 +1747,8 @@ void setCurrentForm(Form newForm) { lastKeyPressed = 0; previousKeyPressed = 0; newForm.onShowCompletedImpl(); - com.codename1.ui.accessibility.AccessibilityManager.getInstance().invalidate( - newForm, com.codename1.ui.accessibility.AccessibilityManager.CHANGE_STRUCTURE - | com.codename1.ui.accessibility.AccessibilityManager.CHANGE_PANE); + AccessibilityManager.getInstance().invalidate(newForm, + AccessibilityManager.CHANGE_STRUCTURE | AccessibilityManager.CHANGE_PANE); } private boolean applyInitialWindowSize(Form form) { diff --git a/CodenameOne/src/com/codename1/ui/Label.java b/CodenameOne/src/com/codename1/ui/Label.java index 72e6e84cfe2..0e08ace3df5 100644 --- a/CodenameOne/src/com/codename1/ui/Label.java +++ b/CodenameOne/src/com/codename1/ui/Label.java @@ -23,6 +23,7 @@ */ package com.codename1.ui; +import com.codename1.ui.accessibility.AccessibilityManager; import com.codename1.cloud.BindTarget; import com.codename1.io.Log; import com.codename1.ui.TextSelection.Char; @@ -646,7 +647,7 @@ public void setText(String text) { stringWidthUnselected = -1; setShouldCalcPreferredSize(true); if (oldText == null ? this.text != null : !oldText.equals(this.text)) { - accessibilityChanged(com.codename1.ui.accessibility.AccessibilityManager.CHANGE_CONTENT); + accessibilityChanged(AccessibilityManager.CHANGE_CONTENT); } repaint(); } diff --git a/CodenameOne/src/com/codename1/ui/List.java b/CodenameOne/src/com/codename1/ui/List.java index 5980b92ca6c..b1687a01c99 100644 --- a/CodenameOne/src/com/codename1/ui/List.java +++ b/CodenameOne/src/com/codename1/ui/List.java @@ -23,6 +23,7 @@ */ package com.codename1.ui; +import com.codename1.ui.accessibility.AccessibilityManager; import com.codename1.compat.java.util.Objects; import com.codename1.ui.animations.Motion; import com.codename1.ui.events.ActionEvent; @@ -549,8 +550,7 @@ public void setSelectedIndex(int index, boolean scrollToSelection) { int oldIndex = model.getSelectedIndex(); model.setSelectedIndex(index); if (oldIndex != index) { - accessibilityChanged(com.codename1.ui.accessibility.AccessibilityManager.CHANGE_STATE - | com.codename1.ui.accessibility.AccessibilityManager.CHANGE_VALUE); + accessibilityChanged(AccessibilityManager.CHANGE_STATE | AccessibilityManager.CHANGE_VALUE); } if (!isInitialized()) { Form f = getComponentForm(); diff --git a/CodenameOne/src/com/codename1/ui/RadioButton.java b/CodenameOne/src/com/codename1/ui/RadioButton.java index 07cb36793ed..6cf49607fd6 100644 --- a/CodenameOne/src/com/codename1/ui/RadioButton.java +++ b/CodenameOne/src/com/codename1/ui/RadioButton.java @@ -23,6 +23,7 @@ */ package com.codename1.ui; +import com.codename1.ui.accessibility.AccessibilityManager; import com.codename1.cloud.BindTarget; import com.codename1.ui.events.ActionEvent; import com.codename1.ui.events.ActionListener; @@ -255,7 +256,7 @@ void setSelectedImpl(boolean selected) { this.selected = selected; if (changed) { fireChangeEvent(); - accessibilityChanged(com.codename1.ui.accessibility.AccessibilityManager.CHANGE_STATE); + accessibilityChanged(AccessibilityManager.CHANGE_STATE); } repaint(); } diff --git a/CodenameOne/src/com/codename1/ui/Slider.java b/CodenameOne/src/com/codename1/ui/Slider.java index 0ff06ff30f5..7ff7ab3435f 100644 --- a/CodenameOne/src/com/codename1/ui/Slider.java +++ b/CodenameOne/src/com/codename1/ui/Slider.java @@ -23,6 +23,7 @@ */ package com.codename1.ui; +import com.codename1.ui.accessibility.AccessibilityManager; import com.codename1.ui.events.ActionEvent; import com.codename1.ui.events.ActionListener; @@ -307,7 +308,7 @@ protected void setProgressInternal(int value) { int oldValue = this.value; this.value = value; if (oldValue != value) { - accessibilityChanged(com.codename1.ui.accessibility.AccessibilityManager.CHANGE_VALUE); + accessibilityChanged(AccessibilityManager.CHANGE_VALUE); } if (renderValueOnTop || renderPercentageOnTop) { super.setText(formattedValue(value)); diff --git a/CodenameOne/src/com/codename1/ui/Tabs.java b/CodenameOne/src/com/codename1/ui/Tabs.java index a43c9cf0f9d..d7e4c17c6d8 100644 --- a/CodenameOne/src/com/codename1/ui/Tabs.java +++ b/CodenameOne/src/com/codename1/ui/Tabs.java @@ -23,6 +23,7 @@ */ package com.codename1.ui; +import com.codename1.ui.accessibility.AccessibilityManager; import com.codename1.ui.animations.Motion; import com.codename1.ui.events.ActionEvent; import com.codename1.ui.events.ActionListener; @@ -1300,8 +1301,7 @@ public void setSelectedIndex(int index, boolean slideToSelected) { if (index == activeComponent) { return; } - accessibilityChanged(com.codename1.ui.accessibility.AccessibilityManager.CHANGE_STATE - | com.codename1.ui.accessibility.AccessibilityManager.CHANGE_PANE); + accessibilityChanged(AccessibilityManager.CHANGE_STATE | AccessibilityManager.CHANGE_PANE); // Snapshot the current tab bounds *before* we mutate state, so the // animated indicator can tween from where it visibly is to the new // selection's bounds. diff --git a/CodenameOne/src/com/codename1/ui/TextArea.java b/CodenameOne/src/com/codename1/ui/TextArea.java index aea2cdee7b8..261d3773f75 100644 --- a/CodenameOne/src/com/codename1/ui/TextArea.java +++ b/CodenameOne/src/com/codename1/ui/TextArea.java @@ -23,6 +23,7 @@ */ package com.codename1.ui; +import com.codename1.ui.accessibility.AccessibilityManager; import com.codename1.cloud.BindTarget; import com.codename1.compat.java.util.Objects; import com.codename1.io.Log; @@ -609,8 +610,7 @@ && textMightGrowByContent(old, text)) { } if (!Objects.equals(text, old)) { fireDataChanged(DataChangedListener.CHANGED, -1); - accessibilityChanged(com.codename1.ui.accessibility.AccessibilityManager.CHANGE_VALUE - | com.codename1.ui.accessibility.AccessibilityManager.CHANGE_CONTENT); + accessibilityChanged(AccessibilityManager.CHANGE_VALUE | AccessibilityManager.CHANGE_CONTENT); } // while native editing we don't need the cursor animations if (Display.getInstance().isNativeInputSupported() && Display.getInstance().isTextEditing(this)) { diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityAction.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityAction.java index a0bb01d945d..9e6f67a542c 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityAction.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityAction.java @@ -53,9 +53,15 @@ public AccessibilityAction(String id, String label, Handler handler, boolean ena this.enabled = enabled; } - public String getId() { return id; } - public String getLabel() { return label; } - public boolean isEnabled() { return enabled; } + public String getId() { + return id; + } + public String getLabel() { + return label; + } + public boolean isEnabled() { + return enabled; + } public boolean perform(Component component, Object argument) { return enabled && handler != null && handler.perform(component, argument); diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityAssertions.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityAssertions.java index 139dab70908..de532109434 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityAssertions.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityAssertions.java @@ -30,23 +30,31 @@ public static void assertNoErrors(AccessibilityTreeSnapshot tree) { StringBuilder errors = new StringBuilder(); for (AccessibilityIssue issue : issues) { if (issue.getSeverity() == AccessibilityIssue.Severity.ERROR) { - if (errors.length() > 0) errors.append('\n'); + if (errors.length() > 0) { + errors.append('\n'); + } errors.append(issue.toString()); } } - if (errors.length() > 0) throw new AssertionError(errors.toString()); + if (errors.length() > 0) { + throw new AssertionError(errors.toString()); + } } public static void assertNoUnlabeledInteractiveNodes(AccessibilityTreeSnapshot tree) { StringBuilder errors = new StringBuilder(); for (AccessibilityNodeSnapshot node : tree.getNodes().values()) { if (node.isFocusable() && empty(node.getLabel()) && empty(node.getValue())) { - if (errors.length() > 0) errors.append('\n'); + if (errors.length() > 0) { + errors.append('\n'); + } errors.append("Interactive node ").append(node.getId()).append(" (") .append(node.getRole()).append(") has no accessible name"); } } - if (errors.length() > 0) throw new AssertionError(errors.toString()); + if (errors.length() > 0) { + throw new AssertionError(errors.toString()); + } } private static void auditNode(AccessibilityTreeSnapshot tree, AccessibilityNodeSnapshot node, @@ -92,7 +100,9 @@ private static void auditNode(AccessibilityTreeSnapshot tree, AccessibilityNodeS } Set actions = new HashSet(); for (AccessibilityAction action : node.getActions()) { - if (!actions.add(action.getId())) error(issues, "duplicate-action", "Action ids must be unique per node", node); + if (!actions.add(action.getId())) { + error(issues, "duplicate-action", "Action ids must be unique per node", node); + } if (!isStandardAction(action.getId()) && empty(action.getLabel())) { error(issues, "unlabeled-custom-action", "Custom accessibility actions require localized labels", node); } @@ -106,15 +116,21 @@ && empty(node.getLabel()) && empty(node.getPaneTitle())) { private static void detectCycle(AccessibilityTreeSnapshot tree, long id, Set visiting, Set visited, List issues) { Long boxed = Long.valueOf(id); - if (visited.contains(boxed)) return; + if (visited.contains(boxed)) { + return; + } if (!visiting.add(boxed)) { AccessibilityNodeSnapshot node = tree.getNode(id); - if (node != null) error(issues, "tree-cycle", "Semantic tree contains a cycle", node); + if (node != null) { + error(issues, "tree-cycle", "Semantic tree contains a cycle", node); + } return; } AccessibilityNodeSnapshot node = tree.getNode(id); if (node != null) { - for (Long child : node.getChildIds()) detectCycle(tree, child.longValue(), visiting, visited, issues); + for (Long child : node.getChildIds()) { + detectCycle(tree, child.longValue(), visiting, visited, issues); + } } visiting.remove(boxed); visited.add(boxed); @@ -146,5 +162,7 @@ private static void warning(List issues, String code, String issues.add(new AccessibilityIssue(AccessibilityIssue.Severity.WARNING, code, message, node.getId())); } - private static boolean empty(String value) { return value == null || value.length() == 0; } + private static boolean empty(String value) { + return value == null || value.length() == 0; + } } diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityCollectionItemInfo.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityCollectionItemInfo.java index 0ea48ccfbbc..a511633e7cb 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityCollectionItemInfo.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityCollectionItemInfo.java @@ -19,7 +19,7 @@ public AccessibilityCollectionItemInfo(int rowIndex, int columnIndex) { } public AccessibilityCollectionItemInfo(int rowIndex, int rowSpan, int columnIndex, int columnSpan, - int positionInSet, int setSize, int level, boolean heading) { + int positionInSet, int setSize, int level, boolean heading) { this.rowIndex = rowIndex; this.rowSpan = rowSpan; this.columnIndex = columnIndex; @@ -30,12 +30,28 @@ public AccessibilityCollectionItemInfo(int rowIndex, int rowSpan, int columnInde this.heading = heading; } - public int getRowIndex() { return rowIndex; } - public int getRowSpan() { return rowSpan; } - public int getColumnIndex() { return columnIndex; } - public int getColumnSpan() { return columnSpan; } - public int getPositionInSet() { return positionInSet; } - public int getSetSize() { return setSize; } - public int getLevel() { return level; } - public boolean isHeading() { return heading; } + public int getRowIndex() { + return rowIndex; + } + public int getRowSpan() { + return rowSpan; + } + public int getColumnIndex() { + return columnIndex; + } + public int getColumnSpan() { + return columnSpan; + } + public int getPositionInSet() { + return positionInSet; + } + public int getSetSize() { + return setSize; + } + public int getLevel() { + return level; + } + public boolean isHeading() { + return heading; + } } diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityIssue.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityIssue.java index 6251e00703b..d80a0e764c9 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityIssue.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityIssue.java @@ -19,10 +19,18 @@ public AccessibilityIssue(Severity severity, String code, String message, long n this.nodeId = nodeId; } - public Severity getSeverity() { return severity; } - public String getCode() { return code; } - public String getMessage() { return message; } - public long getNodeId() { return nodeId; } + public Severity getSeverity() { + return severity; + } + public String getCode() { + return code; + } + public String getMessage() { + return message; + } + public long getNodeId() { + return nodeId; + } @Override public String toString() { diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityManager.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityManager.java index 33ccb4d715d..88d78e3a236 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityManager.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityManager.java @@ -53,8 +53,8 @@ public final class AccessibilityManager { private boolean refreshScheduled; private int pendingChanges = CHANGE_ALL; private Form snapshotForm; - private AccessibilityTreeSnapshot snapshot = new AccessibilityTreeSnapshot(0, - Collections.emptyList(), Collections.emptyMap()); + private AccessibilityTreeSnapshot snapshot = new AccessibilityTreeSnapshot( + 0, Collections.emptyList(), Collections.emptyMap()); private AccessibilityManager() { } @@ -70,6 +70,7 @@ public synchronized void invalidate(Component component, int changeType) { if (!refreshScheduled) { refreshScheduled = true; Display.getInstance().callSerially(new Runnable() { + @Override public void run() { int changes; synchronized (AccessibilityManager.this) { @@ -95,16 +96,21 @@ public void invalidateAll() { public AccessibilityTreeSnapshot getCurrentSnapshot() { synchronized (this) { - if (dirty && !Display.getInstance().isEdt()) return snapshot; + if (dirty && !Display.getInstance().isEdt()) { + return snapshot; + } } return getSnapshot(Display.getInstance().getCurrent()); } + @SuppressWarnings("PMD.CompareObjectsWithEquals") public synchronized AccessibilityTreeSnapshot getSnapshot(Form form) { - if (!dirty && form == snapshotForm) return snapshot; + if (!dirty && form == snapshotForm) { + return snapshot; + } if (form == null) { snapshot = new AccessibilityTreeSnapshot(++generation, Collections.emptyList(), - Collections.emptyMap()); + Collections.emptyMap()); snapshotForm = null; dirty = false; pendingChanges = 0; @@ -135,8 +141,11 @@ public boolean performAction(long nodeId, String actionId, final Object argument node = snapshot.getNode(nodeId); action = node == null ? null : node.getAction(actionId); } - if (node == null || action == null || !action.isEnabled()) return false; + if (node == null || action == null || !action.isEnabled()) { + return false; + } Display.getInstance().callSerially(new Runnable() { + @Override public void run() { action.perform(node.getComponent(), argument); invalidate(node.getComponent(), CHANGE_STATE | CHANGE_VALUE | CHANGE_CONTENT); @@ -151,7 +160,9 @@ public boolean performActionByHash(long nodeId, int actionIdHash, Object argumen synchronized (this) { node = snapshot.getNode(nodeId); } - if (node == null) return false; + if (node == null) { + return false; + } for (AccessibilityAction action : node.getActions()) { if (action.getId().hashCode() == actionIdHash) { return performAction(nodeId, action.getId(), argument); @@ -180,37 +191,47 @@ private long idForVirtual(Component host, String path) { } private void resolveComponent(Component component, List destination) { - if (component == null || (!(component instanceof Form) && !component.isVisible()) - || component.isHidden(true)) return; + if (component == null || (!(component instanceof Form) && !component.isVisible()) || component.isHidden(true)) { + return; + } AccessibilityNode config = component.getSemantics(); AccessibilityGrouping grouping = config.getGrouping(); - if (grouping == AccessibilityGrouping.EXCLUDE_SUBTREE) return; + if (grouping == AccessibilityGrouping.EXCLUDE_SUBTREE) { + return; + } BuildNode node = buildComponentNode(component, config); List children = new ArrayList(); if (grouping != AccessibilityGrouping.LEAF && component instanceof Container) { - Container container = (Container)component; + Container container = (Container) component; for (int i = 0; i < container.getComponentCount(); i++) { resolveComponent(container.getComponentAt(i), children); } } if (grouping != AccessibilityGrouping.LEAF) { - addVirtualChildren(component, config, node.id, "custom", children); + addVirtualChildren(component, config, "custom", children); if (component instanceof com.codename1.ui.List) { - addListChildren((com.codename1.ui.List)component, node.id, children); + addListChildren((com.codename1.ui.List) component, children); } } boolean expose = shouldExpose(component, config, node); - if (grouping == AccessibilityGrouping.EXCLUDE) expose = false; + if (grouping == AccessibilityGrouping.EXCLUDE) { + expose = false; + } if (grouping == AccessibilityGrouping.MERGE_DESCENDANTS) { String merged = collectLabels(children); - if (isEmpty(node.builder.label)) node.builder.label = merged; - else if (!isEmpty(merged)) node.builder.description = join(node.builder.description, merged); + if (isEmpty(node.builder.label)) { + node.builder.label = merged; + } else if (!isEmpty(merged)) { + node.builder.description = join(node.builder.description, merged); + } children.clear(); expose = true; } - if (grouping == AccessibilityGrouping.LEAF || grouping == AccessibilityGrouping.GROUP) expose = true; + if (grouping == AccessibilityGrouping.LEAF || grouping == AccessibilityGrouping.GROUP) { + expose = true; + } if (expose) { node.children.addAll(children); @@ -237,14 +258,18 @@ private BuildNode buildComponentNode(final Component component, AccessibilityNod out.builder.checked = inferChecked(component, config); out.builder.liveRegion = config.getLiveRegion(); out.builder.range = config.getRange() == null ? inferRange(component) : config.getRange(); - out.builder.collectionInfo = config.getCollectionInfo() == null ? inferCollection(component) : config.getCollectionInfo(); - out.builder.collectionItemInfo = config.getCollectionItemInfo() == null - ? inferCollectionItem(component) : config.getCollectionItemInfo(); + out.builder.collectionInfo = + config.getCollectionInfo() == null ? inferCollection(component) : config.getCollectionInfo(); + out.builder.collectionItemInfo = config.getCollectionItemInfo() == null ? inferCollectionItem(component) + : config.getCollectionItemInfo(); out.builder.bounds = componentBounds(component); out.builder.selected = config.getSelected(); - if (out.builder.selected == null) applyInferredSelected(component, out.builder); + if (out.builder.selected == null) { + applyInferredSelected(component, out.builder); + } out.builder.expanded = config.getExpanded(); - out.builder.enabled = config.getEnabled() == null ? Boolean.valueOf(component.isEnabled()) : config.getEnabled(); + out.builder.enabled = + config.getEnabled() == null ? Boolean.valueOf(component.isEnabled()) : config.getEnabled(); out.builder.invalid = config.getInvalid(); out.builder.busy = config.getBusy(); out.builder.readOnly = config.getReadOnly(); @@ -264,26 +289,30 @@ private BuildNode buildComponentNode(final Component component, AccessibilityNod out.builder.actions.addAll(config.getActions()); addDefaultActions(component, out.builder); if (component instanceof Form && isEmpty(out.builder.paneTitle)) { - out.builder.paneTitle = ((Form)component).getTitle(); + out.builder.paneTitle = ((Form) component).getTitle(); } out.component = component; return out; } - private void addVirtualChildren(Component host, AccessibilityNode config, long hostId, - String path, List destination) { + private void addVirtualChildren(Component host, AccessibilityNode config, String path, + List destination) { List virtual = new ArrayList(); virtual.addAll(config.getChildren()); if (config.getChildProvider() != null) { List provided = config.getChildProvider().getAccessibilityChildren(host); - if (provided != null) virtual.addAll(provided); + if (provided != null) { + virtual.addAll(provided); + } } for (int i = 0; i < virtual.size(); i++) { AccessibilityNode child = virtual.get(i); String key = child.getVirtualKey(); - if (isEmpty(key)) key = "index-" + i; + if (isEmpty(key)) { + key = "index-" + i; + } BuildNode resolved = buildVirtualNode(host, child, path + "/" + key); - addVirtualChildren(host, child, resolved.id, path + "/" + key, resolved.children); + addVirtualChildren(host, child, path + "/" + key, resolved.children); destination.add(resolved); } } @@ -329,158 +358,198 @@ private BuildNode buildVirtualNode(Component host, AccessibilityNode config, Str return out; } - private void addListChildren(final com.codename1.ui.List list, long hostId, List destination) { + private void addListChildren(final com.codename1.ui.List list, List destination) { int size = list.size(); for (int i = 0; i < size; i++) { final int index = i; AccessibilityNode item = new AccessibilityNode("item-" + i) - .setRole(AccessibilityRole.LIST_ITEM) - .setLabel(list.getAccessibilityItemText(i)) - .setSelected(Boolean.valueOf(i == list.getSelectedIndex())) - .setCollectionItemInfo(new AccessibilityCollectionItemInfo(i, 1, 0, 1, - i + 1, size, 1, false)) - .setBounds(list.getAccessibilityItemBounds(i, new Rectangle())) - .addAction(new AccessibilityAction(AccessibilityAction.ACTIVATE, null, - new ListActivateHandler(list, index))); + .setRole(AccessibilityRole.LIST_ITEM) + .setLabel(list.getAccessibilityItemText(i)) + .setSelected(Boolean.valueOf(i == list.getSelectedIndex())) + .setCollectionItemInfo(new AccessibilityCollectionItemInfo( + i, 1, 0, 1, i + 1, size, 1, false)) + .setBounds(list.getAccessibilityItemBounds(i, new Rectangle())) + .addAction(new AccessibilityAction(AccessibilityAction.ACTIVATE, null, + new ListActivateHandler(list, index))); destination.add(buildVirtualNode(list, item, "list/item-" + i)); } } private void addDefaultActions(final Component component, AccessibilityNodeSnapshot.Builder builder) { if (component.isFocusable() && !hasAction(builder.actions, AccessibilityAction.FOCUS)) { - builder.actions.add(new AccessibilityAction(AccessibilityAction.FOCUS, null, - FocusHandler.INSTANCE)); + builder.actions.add(new AccessibilityAction(AccessibilityAction.FOCUS, null, FocusHandler.INSTANCE)); } if (component instanceof Button && !hasAction(builder.actions, AccessibilityAction.ACTIVATE)) { - builder.actions.add(new AccessibilityAction(AccessibilityAction.ACTIVATE, null, - ActivateHandler.INSTANCE)); + builder.actions.add(new AccessibilityAction(AccessibilityAction.ACTIVATE, null, ActivateHandler.INSTANCE)); } if (component instanceof Slider) { - final Slider slider = (Slider)component; + final Slider slider = (Slider) component; if (slider.isEditable() && !hasAction(builder.actions, AccessibilityAction.INCREMENT)) { builder.actions.add(new AccessibilityAction(AccessibilityAction.INCREMENT, null, - new SliderAdjustmentHandler(slider, 1))); + new SliderAdjustmentHandler(slider, 1))); } if (slider.isEditable() && !hasAction(builder.actions, AccessibilityAction.DECREMENT)) { builder.actions.add(new AccessibilityAction(AccessibilityAction.DECREMENT, null, - new SliderAdjustmentHandler(slider, -1))); + new SliderAdjustmentHandler(slider, -1))); } } if (component instanceof TextArea) { - final TextArea text = (TextArea)component; + final TextArea text = (TextArea) component; if (!hasAction(builder.actions, AccessibilityAction.FOCUS)) { - builder.actions.add(new AccessibilityAction(AccessibilityAction.FOCUS, null, - FocusHandler.INSTANCE)); + builder.actions.add(new AccessibilityAction(AccessibilityAction.FOCUS, null, FocusHandler.INSTANCE)); } if (text.isEditable() && !hasAction(builder.actions, AccessibilityAction.SET_TEXT)) { - builder.actions.add(new AccessibilityAction(AccessibilityAction.SET_TEXT, null, - new SetTextHandler(text))); + builder.actions.add( + new AccessibilityAction(AccessibilityAction.SET_TEXT, null, new SetTextHandler(text))); } } } private AccessibilityRole inferRole(Component component) { if (component.getParent() instanceof Table) { - return ((Table)component.getParent()).getCellRow(component) < 0 - ? AccessibilityRole.COLUMN_HEADER : AccessibilityRole.CELL; + return ((Table) component.getParent()).getCellRow(component) < 0 ? AccessibilityRole.COLUMN_HEADER + : AccessibilityRole.CELL; } Tabs tabOwner = tabPanelOwner(component); - if (tabOwner != null) return AccessibilityRole.TAB_PANEL; - if (component instanceof Dialog) return AccessibilityRole.DIALOG; - if (component instanceof RadioButton) return AccessibilityRole.RADIO_BUTTON; - if (component instanceof CheckBox) return AccessibilityRole.CHECKBOX; + if (tabOwner != null) { + return AccessibilityRole.TAB_PANEL; + } + if (component instanceof Dialog) { + return AccessibilityRole.DIALOG; + } + if (component instanceof RadioButton) { + return AccessibilityRole.RADIO_BUTTON; + } + if (component instanceof CheckBox) { + return AccessibilityRole.CHECKBOX; + } if (component instanceof Button) { - if (isTabButton((Button)component)) return AccessibilityRole.TAB; - return ((Button)component).isToggle() ? AccessibilityRole.TOGGLE_BUTTON : AccessibilityRole.BUTTON; - } - if (component instanceof Slider) return ((Slider)component).isEditable() ? AccessibilityRole.SLIDER : AccessibilityRole.PROGRESS_BAR; - if (component instanceof TextField) return AccessibilityRole.TEXT_FIELD; - if (component instanceof TextArea) return AccessibilityRole.TEXT_FIELD; - if (component instanceof com.codename1.ui.List) return AccessibilityRole.LIST; - if (component instanceof Table) return AccessibilityRole.GRID; - if (component instanceof Tabs) return AccessibilityRole.TAB_LIST; - if (component instanceof Form) return AccessibilityRole.GENERIC; - if (component instanceof Label) return AccessibilityRole.STATIC_TEXT; + if (isTabButton((Button) component)) { + return AccessibilityRole.TAB; + } + return ((Button) component).isToggle() ? AccessibilityRole.TOGGLE_BUTTON : AccessibilityRole.BUTTON; + } + if (component instanceof Slider) { + return ((Slider) component).isEditable() ? AccessibilityRole.SLIDER : AccessibilityRole.PROGRESS_BAR; + } + if (component instanceof TextField) { + return AccessibilityRole.TEXT_FIELD; + } + if (component instanceof TextArea) { + return AccessibilityRole.TEXT_FIELD; + } + if (component instanceof com.codename1.ui.List) { + return AccessibilityRole.LIST; + } + if (component instanceof Table) { + return AccessibilityRole.GRID; + } + if (component instanceof Tabs) { + return AccessibilityRole.TAB_LIST; + } + if (component instanceof Form) { + return AccessibilityRole.GENERIC; + } + if (component instanceof Label) { + return AccessibilityRole.STATIC_TEXT; + } return AccessibilityRole.NONE; } + @SuppressWarnings("PMD.CompareObjectsWithEquals") private boolean isTabButton(Button button) { Container parent = button.getParent(); while (parent != null) { Container owner = parent.getParent(); - if (owner instanceof Tabs && ((Tabs)owner).getTabsContainer() == parent) return true; + if (owner instanceof Tabs && ((Tabs) owner).getTabsContainer() == parent) { + return true; + } parent = parent.getParent(); } return false; } private AccessibilityCheckedState inferChecked(Component component, AccessibilityNode config) { - if (config.getChecked() != AccessibilityCheckedState.UNSPECIFIED) return config.getChecked(); + if (config.getChecked() != AccessibilityCheckedState.UNSPECIFIED) { + return config.getChecked(); + } if (component instanceof CheckBox || component instanceof RadioButton) { - return ((Button)component).isSelected() ? AccessibilityCheckedState.CHECKED : AccessibilityCheckedState.UNCHECKED; + return ((Button) component).isSelected() ? AccessibilityCheckedState.CHECKED + : AccessibilityCheckedState.UNCHECKED; } return AccessibilityCheckedState.UNSPECIFIED; } + @SuppressWarnings("PMD.CompareObjectsWithEquals") private void applyInferredSelected(Component component, AccessibilityNodeSnapshot.Builder builder) { - if (component instanceof Button && (((Button)component).isToggle() || isTabButton((Button)component))) { - builder.selected = Boolean.valueOf(((Button)component).isSelected()); + if (component instanceof Button && (((Button) component).isToggle() || isTabButton((Button) component))) { + builder.selected = Boolean.valueOf(((Button) component).isSelected()); return; } Tabs tabOwner = tabPanelOwner(component); - if (tabOwner != null) builder.selected = Boolean.valueOf(tabOwner.getSelectedComponent() == component); + if (tabOwner != null) { + builder.selected = Boolean.valueOf(tabOwner.getSelectedComponent() == component); + } } + @SuppressWarnings("PMD.CompareObjectsWithEquals") private Tabs tabPanelOwner(Component component) { Container parent = component.getParent(); if (parent != null && parent.getParent() instanceof Tabs) { - Tabs tabs = (Tabs)parent.getParent(); - if (tabs.getContentPane() == parent) return tabs; + Tabs tabs = (Tabs) parent.getParent(); + if (tabs.getContentPane() == parent) { + return tabs; + } } return null; } private AccessibilityRange inferRange(Component component) { if (component instanceof Slider) { - Slider slider = (Slider)component; - return new AccessibilityRange(slider.getMinValue(), slider.getMaxValue(), slider.getProgress(), slider.getIncrements(), null); + Slider slider = (Slider) component; + return new AccessibilityRange(slider.getMinValue(), slider.getMaxValue(), slider.getProgress(), + slider.getIncrements(), null); } return null; } private AccessibilityCollectionInfo inferCollection(Component component) { if (component instanceof com.codename1.ui.List) { - return new AccessibilityCollectionInfo(((com.codename1.ui.List)component).size(), 1, - false, AccessibilityCollectionInfo.SELECTION_SINGLE); + return new AccessibilityCollectionInfo(((com.codename1.ui.List) component).size(), 1, false, + AccessibilityCollectionInfo.SELECTION_SINGLE); } if (component instanceof Table) { - Table table = (Table)component; + Table table = (Table) component; return new AccessibilityCollectionInfo(table.getModel().getRowCount(), table.getModel().getColumnCount(), - false, AccessibilityCollectionInfo.SELECTION_SINGLE); + false, AccessibilityCollectionInfo.SELECTION_SINGLE); } if (component instanceof Tabs) { - return new AccessibilityCollectionInfo(1, ((Tabs)component).getTabCount(), false, - AccessibilityCollectionInfo.SELECTION_SINGLE); + return new AccessibilityCollectionInfo(1, ((Tabs) component).getTabCount(), false, + AccessibilityCollectionInfo.SELECTION_SINGLE); } return null; } private AccessibilityCollectionItemInfo inferCollectionItem(Component component) { if (component.getParent() instanceof Table) { - Table table = (Table)component.getParent(); + Table table = (Table) component.getParent(); int sourceRow = table.getCellRow(component); int row = sourceRow < 0 ? 0 : sourceRow + (table.isIncludeHeader() ? 1 : 0); int column = table.getCellColumn(component); - return new AccessibilityCollectionItemInfo(row, 1, column, 1, column + 1, - table.getModel().getColumnCount(), 1, sourceRow < 0); + return new AccessibilityCollectionItemInfo(row, 1, column, 1, column + 1, table.getModel().getColumnCount(), + 1, sourceRow < 0); } return null; } private void applyInferredTextStates(Component component, AccessibilityNodeSnapshot.Builder builder) { - if (!(component instanceof TextArea)) return; - TextArea text = (TextArea)component; - if (builder.readOnly == null) builder.readOnly = Boolean.valueOf(!text.isEditable()); + if (!(component instanceof TextArea)) { + return; + } + TextArea text = (TextArea) component; + if (builder.readOnly == null) { + builder.readOnly = Boolean.valueOf(!text.isEditable()); + } if (builder.multiline == null) { builder.multiline = Boolean.valueOf(!(component instanceof TextField) || text.getRows() > 1); } @@ -490,20 +559,26 @@ private void applyInferredTextStates(Component component, AccessibilityNodeSnaps } private boolean shouldExpose(Component component, AccessibilityNode config, BuildNode node) { - if (component instanceof Form) return true; - if (config.hasExplicitConfiguration()) return true; - return node.builder.role != AccessibilityRole.NONE && (!isEmpty(node.builder.label) - || !isEmpty(node.builder.value) || node.builder.focusable || !node.builder.actions.isEmpty() - || node.builder.collectionInfo != null || node.builder.range != null); + if (component instanceof Form) { + return true; + } + if (config.hasExplicitConfiguration()) { + return true; + } + return node.builder.role != AccessibilityRole.NONE && + (!isEmpty(node.builder.label) || !isEmpty(node.builder.value) || node.builder.focusable || + !node.builder.actions.isEmpty() || node.builder.collectionInfo != null || node.builder.range != null); } private Rectangle componentBounds(Component component) { Rectangle bounds = new Rectangle(component.getAbsoluteX() + component.getScrollX(), - component.getAbsoluteY() + component.getScrollY(), component.getWidth(), component.getHeight()); + component.getAbsoluteY() + component.getScrollY(), component.getWidth(), + component.getHeight()); Container parent = component.getParent(); while (parent != null && bounds.getWidth() > 0 && bounds.getHeight() > 0) { - Rectangle clip = new Rectangle(parent.getAbsoluteX() + parent.getScrollX(), - parent.getAbsoluteY() + parent.getScrollY(), parent.getWidth(), parent.getHeight()); + Rectangle clip = + new Rectangle(parent.getAbsoluteX() + parent.getScrollX(), + parent.getAbsoluteY() + parent.getScrollY(), parent.getWidth(), parent.getHeight()); intersect(bounds, clip); parent = parent.getParent(); } @@ -511,9 +586,12 @@ private Rectangle componentBounds(Component component) { } private Rectangle virtualBounds(Component host, Rectangle relative) { - if (relative == null) return componentBounds(host); + if (relative == null) { + return componentBounds(host); + } Rectangle bounds = new Rectangle(host.getAbsoluteX() + host.getScrollX() + relative.getX(), - host.getAbsoluteY() + host.getScrollY() + relative.getY(), relative.getWidth(), relative.getHeight()); + host.getAbsoluteY() + host.getScrollY() + relative.getY(), relative.getWidth(), + relative.getHeight()); intersect(bounds, componentBounds(host)); return bounds; } @@ -529,11 +607,14 @@ private void intersect(Rectangle target, Rectangle clip) { private void sortTree(List nodes) { Collections.sort(nodes, SortKeyComparator.INSTANCE); applyRelativeOrder(nodes); - for (BuildNode node : nodes) sortTree(node.children); + for (BuildNode node : nodes) { + sortTree(node.children); + } } private void applyRelativeOrder(List nodes) { - for (int pass = 0; pass < nodes.size(); pass++) { + int remainingPasses = nodes.size(); + while (remainingPasses > 0) { boolean changed = false; for (int i = 0; i < nodes.size(); i++) { BuildNode node = nodes.get(i); @@ -552,21 +633,33 @@ private void applyRelativeOrder(List nodes) { break; } } - if (!changed) return; + if (!changed) { + return; + } + remainingPasses--; } } + @SuppressWarnings("PMD.CompareObjectsWithEquals") private int indexOf(List nodes, Component component) { - if (component == null) return -1; - for (int i = 0; i < nodes.size(); i++) if (nodes.get(i).component == component) return i; + if (component == null) { + return -1; + } + for (int i = 0; i < nodes.size(); i++) { + if (nodes.get(i).component == component) { + return i; + } + } return -1; } private void freeze(List source, long parentId, List childIds, - LinkedHashMap nodes) { + LinkedHashMap nodes) { for (BuildNode node : source) { node.builder.parentId = parentId; - for (BuildNode child : node.children) node.builder.childIds.add(Long.valueOf(child.id)); + for (BuildNode child : node.children) { + node.builder.childIds.add(Long.valueOf(child.id)); + } AccessibilityNodeSnapshot frozen = new AccessibilityNodeSnapshot(node.builder); nodes.put(Long.valueOf(node.id), frozen); childIds.add(Long.valueOf(node.id)); @@ -585,18 +678,22 @@ private String collectLabels(List nodes) { } private static boolean hasAction(List actions, String id) { - for (AccessibilityAction action : actions) if (id.equals(action.getId())) return true; + for (AccessibilityAction action : actions) { + if (id.equals(action.getId())) { + return true; + } + } return false; } private static boolean isInteractiveRole(AccessibilityRole role) { - return role == AccessibilityRole.BUTTON || role == AccessibilityRole.TOGGLE_BUTTON - || role == AccessibilityRole.CHECKBOX || role == AccessibilityRole.RADIO_BUTTON - || role == AccessibilityRole.SWITCH || role == AccessibilityRole.LINK - || role == AccessibilityRole.TEXT_FIELD || role == AccessibilityRole.SEARCH_FIELD - || role == AccessibilityRole.SLIDER || role == AccessibilityRole.TAB - || role == AccessibilityRole.MENU_ITEM || role == AccessibilityRole.SPIN_BUTTON - || role == AccessibilityRole.COMBO_BOX || role == AccessibilityRole.TREE_ITEM; + return role == AccessibilityRole.BUTTON || role == AccessibilityRole.TOGGLE_BUTTON || + role == AccessibilityRole.CHECKBOX || role == AccessibilityRole.RADIO_BUTTON || + role == AccessibilityRole.SWITCH || role == AccessibilityRole.LINK || + role == AccessibilityRole.TEXT_FIELD || role == AccessibilityRole.SEARCH_FIELD || + role == AccessibilityRole.SLIDER || role == AccessibilityRole.TAB || + role == AccessibilityRole.MENU_ITEM || role == AccessibilityRole.SPIN_BUTTON || + role == AccessibilityRole.COMBO_BOX || role == AccessibilityRole.TREE_ITEM; } private static String firstNonEmpty(String first, String second) { @@ -604,8 +701,12 @@ private static String firstNonEmpty(String first, String second) { } private static String join(String first, String second) { - if (isEmpty(first)) return second; - if (isEmpty(second)) return first; + if (isEmpty(first)) { + return second; + } + if (isEmpty(second)) { + return first; + } return first + ", " + second; } @@ -623,12 +724,19 @@ private static final class BuildNode { private static final class SortKeyComparator implements Comparator { private static final SortKeyComparator INSTANCE = new SortKeyComparator(); + @Override public int compare(BuildNode a, BuildNode b) { boolean an = Double.isNaN(a.builder.sortKey); boolean bn = Double.isNaN(b.builder.sortKey); - if (an && bn) return 0; - if (an) return 1; - if (bn) return -1; + if (an && bn) { + return 0; + } + if (an) { + return 1; + } + if (bn) { + return -1; + } return Double.compare(a.builder.sortKey, b.builder.sortKey); } } @@ -636,8 +744,11 @@ public int compare(BuildNode a, BuildNode b) { private static final class FocusHandler implements AccessibilityAction.Handler { private static final FocusHandler INSTANCE = new FocusHandler(); + @Override public boolean perform(Component source, Object argument) { - if (!source.isEnabled()) return false; + if (!source.isEnabled()) { + return false; + } source.requestFocus(); return true; } @@ -646,8 +757,11 @@ public boolean perform(Component source, Object argument) { private static final class ActivateHandler implements AccessibilityAction.Handler { private static final ActivateHandler INSTANCE = new ActivateHandler(); + @Override public boolean perform(Component source, Object argument) { - if (!source.isEnabled()) return false; + if (!source.isEnabled()) { + return false; + } source.keyReleased(Display.getInstance().getKeyCode(Display.GAME_FIRE)); return true; } @@ -662,8 +776,11 @@ private ListActivateHandler(com.codename1.ui.List list, int index) { this.index = index; } + @Override public boolean perform(Component source, Object argument) { - if (!list.isEnabled()) return false; + if (!list.isEnabled()) { + return false; + } list.setSelectedIndex(index); list.keyReleased(Display.getInstance().getKeyCode(Display.GAME_FIRE)); return true; @@ -679,6 +796,7 @@ private SliderAdjustmentHandler(Slider slider, int direction) { this.direction = direction; } + @Override public boolean perform(Component source, Object argument) { int increment = Math.max(1, slider.getIncrements()); int value = slider.getProgress() + direction * increment; @@ -694,9 +812,12 @@ private SetTextHandler(TextArea text) { this.text = text; } + @Override public boolean perform(Component source, Object argument) { - if (!(argument instanceof String)) return false; - text.setText((String)argument); + if (!(argument instanceof String)) { + return false; + } + text.setText((String) argument); return true; } } diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityNode.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityNode.java index 282fa251282..d3ba2e2e132 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityNode.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityNode.java @@ -72,8 +72,12 @@ private AccessibilityNode changed(int type) { return this; } - public Component getOwner() { return owner; } - public String getVirtualKey() { return virtualKey; } + public Component getOwner() { + return owner; + } + public String getVirtualKey() { + return virtualKey; + } public AccessibilityNode setVirtualKey(String virtualKey) { if (virtualKey == null || virtualKey.length() == 0) { throw new IllegalArgumentException("Virtual accessibility nodes require a non-empty stable key"); @@ -81,77 +85,250 @@ public AccessibilityNode setVirtualKey(String virtualKey) { this.virtualKey = virtualKey; return changed(AccessibilityManager.CHANGE_STRUCTURE); } - public String getIdentifier() { return identifier; } - public AccessibilityNode setIdentifier(String identifier) { this.identifier = identifier; return changed(AccessibilityManager.CHANGE_CONTENT); } - public String getLabel() { return label; } - public AccessibilityNode setLabel(String label) { this.label = label; return changed(AccessibilityManager.CHANGE_CONTENT); } - public String getHint() { return hint; } - public AccessibilityNode setHint(String hint) { this.hint = hint; return changed(AccessibilityManager.CHANGE_CONTENT); } - public String getDescription() { return description; } - public AccessibilityNode setDescription(String description) { this.description = description; return changed(AccessibilityManager.CHANGE_CONTENT); } - public String getValue() { return value; } - public AccessibilityNode setValue(String value) { this.value = value; return changed(AccessibilityManager.CHANGE_VALUE); } - public String getValidationError() { return validationError; } - public AccessibilityNode setValidationError(String error) { this.validationError = error; this.invalid = error == null ? invalid : Boolean.TRUE; return changed(AccessibilityManager.CHANGE_STATE); } - public String getPaneTitle() { return paneTitle; } - public AccessibilityNode setPaneTitle(String paneTitle) { this.paneTitle = paneTitle; return changed(AccessibilityManager.CHANGE_PANE); } - public String getRoleDescription() { return roleDescription; } - public AccessibilityNode setRoleDescription(String roleDescription) { this.roleDescription = roleDescription; return changed(AccessibilityManager.CHANGE_CONTENT); } - public AccessibilityRole getRole() { return role; } - public AccessibilityNode setRole(AccessibilityRole role) { this.role = role == null ? AccessibilityRole.NONE : role; return changed(AccessibilityManager.CHANGE_STRUCTURE); } - public AccessibilityCheckedState getChecked() { return checked; } - public AccessibilityNode setChecked(AccessibilityCheckedState checked) { this.checked = checked == null ? AccessibilityCheckedState.UNSPECIFIED : checked; return changed(AccessibilityManager.CHANGE_STATE); } - public AccessibilityLiveRegion getLiveRegion() { return liveRegion; } - public AccessibilityNode setLiveRegion(AccessibilityLiveRegion liveRegion) { this.liveRegion = liveRegion == null ? AccessibilityLiveRegion.OFF : liveRegion; return changed(AccessibilityManager.CHANGE_LIVE_REGION); } - public AccessibilityGrouping getGrouping() { return grouping; } - public AccessibilityNode setGrouping(AccessibilityGrouping grouping) { this.grouping = grouping == null ? AccessibilityGrouping.AUTO : grouping; return changed(AccessibilityManager.CHANGE_STRUCTURE); } - public AccessibilityRange getRange() { return range; } - public AccessibilityNode setRange(AccessibilityRange range) { this.range = range; return changed(AccessibilityManager.CHANGE_VALUE); } - public AccessibilityCollectionInfo getCollectionInfo() { return collectionInfo; } - public AccessibilityNode setCollectionInfo(AccessibilityCollectionInfo info) { this.collectionInfo = info; return changed(AccessibilityManager.CHANGE_STRUCTURE); } - public AccessibilityCollectionItemInfo getCollectionItemInfo() { return collectionItemInfo; } - public AccessibilityNode setCollectionItemInfo(AccessibilityCollectionItemInfo info) { this.collectionItemInfo = info; return changed(AccessibilityManager.CHANGE_STRUCTURE); } - public AccessibilityChildProvider getChildProvider() { return childProvider; } - public AccessibilityNode setChildProvider(AccessibilityChildProvider provider) { this.childProvider = provider; return changed(AccessibilityManager.CHANGE_STRUCTURE); } - public Rectangle getBounds() { return bounds == null ? null : new Rectangle(bounds); } - public AccessibilityNode setBounds(Rectangle bounds) { this.bounds = bounds == null ? null : new Rectangle(bounds); return changed(AccessibilityManager.CHANGE_BOUNDS); } - public Boolean getSelected() { return selected; } - public AccessibilityNode setSelected(Boolean selected) { this.selected = selected; return changed(AccessibilityManager.CHANGE_STATE); } - public Boolean getExpanded() { return expanded; } - public AccessibilityNode setExpanded(Boolean expanded) { this.expanded = expanded; return changed(AccessibilityManager.CHANGE_STATE); } - public Boolean getEnabled() { return enabled; } - public AccessibilityNode setEnabled(Boolean enabled) { this.enabled = enabled; return changed(AccessibilityManager.CHANGE_STATE); } - public Boolean getInvalid() { return invalid; } - public AccessibilityNode setInvalid(Boolean invalid) { this.invalid = invalid; return changed(AccessibilityManager.CHANGE_STATE); } - public Boolean getBusy() { return busy; } - public AccessibilityNode setBusy(Boolean busy) { this.busy = busy; return changed(AccessibilityManager.CHANGE_STATE); } - public Boolean getReadOnly() { return readOnly; } - public AccessibilityNode setReadOnly(Boolean readOnly) { this.readOnly = readOnly; return changed(AccessibilityManager.CHANGE_STATE); } - public Boolean getRequired() { return required; } - public AccessibilityNode setRequired(Boolean required) { this.required = required; return changed(AccessibilityManager.CHANGE_STATE); } - public Boolean getMultiline() { return multiline; } - public AccessibilityNode setMultiline(Boolean multiline) { this.multiline = multiline; return changed(AccessibilityManager.CHANGE_STATE); } - public Boolean getObscured() { return obscured; } - public AccessibilityNode setObscured(Boolean obscured) { this.obscured = obscured; return changed(AccessibilityManager.CHANGE_STATE); } - public Boolean getPressed() { return pressed; } - public AccessibilityNode setPressed(Boolean pressed) { this.pressed = pressed; return changed(AccessibilityManager.CHANGE_STATE); } - public Boolean getCurrent() { return current; } - public AccessibilityNode setCurrent(Boolean current) { this.current = current; return changed(AccessibilityManager.CHANGE_STATE); } - public boolean isModal() { return modal; } - public AccessibilityNode setModal(boolean modal) { this.modal = modal; return changed(AccessibilityManager.CHANGE_PANE); } - public int getHeadingLevel() { return headingLevel; } - public AccessibilityNode setHeadingLevel(int level) { this.headingLevel = level; if (level > 0 && role == AccessibilityRole.NONE) role = AccessibilityRole.HEADING; return changed(AccessibilityManager.CHANGE_STRUCTURE); } - public double getSortKey() { return sortKey; } - public AccessibilityNode setSortKey(double sortKey) { this.sortKey = sortKey; return changed(AccessibilityManager.CHANGE_STRUCTURE); } - public Component getTraversalBefore() { return traversalBefore; } - public AccessibilityNode setTraversalBefore(Component component) { this.traversalBefore = component; return changed(AccessibilityManager.CHANGE_STRUCTURE); } - public Component getTraversalAfter() { return traversalAfter; } - public AccessibilityNode setTraversalAfter(Component component) { this.traversalAfter = component; return changed(AccessibilityManager.CHANGE_STRUCTURE); } + public String getIdentifier() { + return identifier; + } + public AccessibilityNode setIdentifier(String identifier) { + this.identifier = identifier; + return changed(AccessibilityManager.CHANGE_CONTENT); + } + public String getLabel() { + return label; + } + public AccessibilityNode setLabel(String label) { + this.label = label; + return changed(AccessibilityManager.CHANGE_CONTENT); + } + public String getHint() { + return hint; + } + public AccessibilityNode setHint(String hint) { + this.hint = hint; + return changed(AccessibilityManager.CHANGE_CONTENT); + } + public String getDescription() { + return description; + } + public AccessibilityNode setDescription(String description) { + this.description = description; + return changed(AccessibilityManager.CHANGE_CONTENT); + } + public String getValue() { + return value; + } + public AccessibilityNode setValue(String value) { + this.value = value; + return changed(AccessibilityManager.CHANGE_VALUE); + } + public String getValidationError() { + return validationError; + } + public AccessibilityNode setValidationError(String error) { + this.validationError = error; + this.invalid = error == null ? invalid : Boolean.TRUE; + return changed(AccessibilityManager.CHANGE_STATE); + } + public String getPaneTitle() { + return paneTitle; + } + public AccessibilityNode setPaneTitle(String paneTitle) { + this.paneTitle = paneTitle; + return changed(AccessibilityManager.CHANGE_PANE); + } + public String getRoleDescription() { + return roleDescription; + } + public AccessibilityNode setRoleDescription(String roleDescription) { + this.roleDescription = roleDescription; + return changed(AccessibilityManager.CHANGE_CONTENT); + } + public AccessibilityRole getRole() { + return role; + } + public AccessibilityNode setRole(AccessibilityRole role) { + this.role = role == null ? AccessibilityRole.NONE : role; + return changed(AccessibilityManager.CHANGE_STRUCTURE); + } + public AccessibilityCheckedState getChecked() { + return checked; + } + public AccessibilityNode setChecked(AccessibilityCheckedState checked) { + this.checked = checked == null ? AccessibilityCheckedState.UNSPECIFIED : checked; + return changed(AccessibilityManager.CHANGE_STATE); + } + public AccessibilityLiveRegion getLiveRegion() { + return liveRegion; + } + public AccessibilityNode setLiveRegion(AccessibilityLiveRegion liveRegion) { + this.liveRegion = liveRegion == null ? AccessibilityLiveRegion.OFF : liveRegion; + return changed(AccessibilityManager.CHANGE_LIVE_REGION); + } + public AccessibilityGrouping getGrouping() { + return grouping; + } + public AccessibilityNode setGrouping(AccessibilityGrouping grouping) { + this.grouping = grouping == null ? AccessibilityGrouping.AUTO : grouping; + return changed(AccessibilityManager.CHANGE_STRUCTURE); + } + public AccessibilityRange getRange() { + return range; + } + public AccessibilityNode setRange(AccessibilityRange range) { + this.range = range; + return changed(AccessibilityManager.CHANGE_VALUE); + } + public AccessibilityCollectionInfo getCollectionInfo() { + return collectionInfo; + } + public AccessibilityNode setCollectionInfo(AccessibilityCollectionInfo info) { + this.collectionInfo = info; + return changed(AccessibilityManager.CHANGE_STRUCTURE); + } + public AccessibilityCollectionItemInfo getCollectionItemInfo() { + return collectionItemInfo; + } + public AccessibilityNode setCollectionItemInfo(AccessibilityCollectionItemInfo info) { + this.collectionItemInfo = info; + return changed(AccessibilityManager.CHANGE_STRUCTURE); + } + public AccessibilityChildProvider getChildProvider() { + return childProvider; + } + public AccessibilityNode setChildProvider(AccessibilityChildProvider provider) { + this.childProvider = provider; + return changed(AccessibilityManager.CHANGE_STRUCTURE); + } + public Rectangle getBounds() { + return bounds == null ? null : new Rectangle(bounds); + } + public AccessibilityNode setBounds(Rectangle bounds) { + this.bounds = bounds == null ? null : new Rectangle(bounds); + return changed(AccessibilityManager.CHANGE_BOUNDS); + } + public Boolean getSelected() { + return selected; + } + public AccessibilityNode setSelected(Boolean selected) { + this.selected = selected; + return changed(AccessibilityManager.CHANGE_STATE); + } + public Boolean getExpanded() { + return expanded; + } + public AccessibilityNode setExpanded(Boolean expanded) { + this.expanded = expanded; + return changed(AccessibilityManager.CHANGE_STATE); + } + public Boolean getEnabled() { + return enabled; + } + public AccessibilityNode setEnabled(Boolean enabled) { + this.enabled = enabled; + return changed(AccessibilityManager.CHANGE_STATE); + } + public Boolean getInvalid() { + return invalid; + } + public AccessibilityNode setInvalid(Boolean invalid) { + this.invalid = invalid; + return changed(AccessibilityManager.CHANGE_STATE); + } + public Boolean getBusy() { + return busy; + } + public AccessibilityNode setBusy(Boolean busy) { + this.busy = busy; + return changed(AccessibilityManager.CHANGE_STATE); + } + public Boolean getReadOnly() { + return readOnly; + } + public AccessibilityNode setReadOnly(Boolean readOnly) { + this.readOnly = readOnly; + return changed(AccessibilityManager.CHANGE_STATE); + } + public Boolean getRequired() { + return required; + } + public AccessibilityNode setRequired(Boolean required) { + this.required = required; + return changed(AccessibilityManager.CHANGE_STATE); + } + public Boolean getMultiline() { + return multiline; + } + public AccessibilityNode setMultiline(Boolean multiline) { + this.multiline = multiline; + return changed(AccessibilityManager.CHANGE_STATE); + } + public Boolean getObscured() { + return obscured; + } + public AccessibilityNode setObscured(Boolean obscured) { + this.obscured = obscured; + return changed(AccessibilityManager.CHANGE_STATE); + } + public Boolean getPressed() { + return pressed; + } + public AccessibilityNode setPressed(Boolean pressed) { + this.pressed = pressed; + return changed(AccessibilityManager.CHANGE_STATE); + } + public Boolean getCurrent() { + return current; + } + public AccessibilityNode setCurrent(Boolean current) { + this.current = current; + return changed(AccessibilityManager.CHANGE_STATE); + } + public boolean isModal() { + return modal; + } + public AccessibilityNode setModal(boolean modal) { + this.modal = modal; + return changed(AccessibilityManager.CHANGE_PANE); + } + public int getHeadingLevel() { + return headingLevel; + } + public AccessibilityNode setHeadingLevel(int level) { + this.headingLevel = level; + if (level > 0 && role == AccessibilityRole.NONE) { + role = AccessibilityRole.HEADING; + } + return changed(AccessibilityManager.CHANGE_STRUCTURE); + } + public double getSortKey() { + return sortKey; + } + public AccessibilityNode setSortKey(double sortKey) { + this.sortKey = sortKey; + return changed(AccessibilityManager.CHANGE_STRUCTURE); + } + public Component getTraversalBefore() { + return traversalBefore; + } + public AccessibilityNode setTraversalBefore(Component component) { + this.traversalBefore = component; + return changed(AccessibilityManager.CHANGE_STRUCTURE); + } + public Component getTraversalAfter() { + return traversalAfter; + } + public AccessibilityNode setTraversalAfter(Component component) { + this.traversalAfter = component; + return changed(AccessibilityManager.CHANGE_STRUCTURE); + } public AccessibilityNode addAction(AccessibilityAction action) { - if (action == null) throw new NullPointerException("action"); + if (action == null) { + throw new NullPointerException("action"); + } for (int i = actions.size() - 1; i >= 0; i--) { - if (actions.get(i).getId().equals(action.getId())) actions.remove(i); + if (actions.get(i).getId().equals(action.getId())) { + actions.remove(i); + } } actions.add(action); return changed(AccessibilityManager.CHANGE_ACTIONS); @@ -159,7 +336,9 @@ public AccessibilityNode addAction(AccessibilityAction action) { public AccessibilityNode removeAction(String id) { for (int i = actions.size() - 1; i >= 0; i--) { - if (actions.get(i).getId().equals(id)) actions.remove(i); + if (actions.get(i).getId().equals(id)) { + actions.remove(i); + } } return changed(AccessibilityManager.CHANGE_ACTIONS); } @@ -169,7 +348,9 @@ public List getActions() { } public AccessibilityNode addChild(AccessibilityNode child) { - if (child == null) throw new NullPointerException("child"); + if (child == null) { + throw new NullPointerException("child"); + } children.add(child); return changed(AccessibilityManager.CHANGE_STRUCTURE); } @@ -184,14 +365,14 @@ public List getChildren() { } public boolean hasExplicitConfiguration() { - return role != AccessibilityRole.NONE || label != null || hint != null || description != null - || value != null || validationError != null || paneTitle != null || roleDescription != null - || checked != AccessibilityCheckedState.UNSPECIFIED || liveRegion != AccessibilityLiveRegion.OFF - || grouping != AccessibilityGrouping.AUTO || range != null || collectionInfo != null - || collectionItemInfo != null || childProvider != null || bounds != null || selected != null - || expanded != null || enabled != null || invalid != null || busy != null || readOnly != null - || required != null || multiline != null || obscured != null || pressed != null || current != null - || modal || headingLevel > 0 || !Double.isNaN(sortKey) || traversalBefore != null - || traversalAfter != null || !actions.isEmpty() || !children.isEmpty(); + return role != AccessibilityRole.NONE || label != null || hint != null || description != null || + value != null || validationError != null || paneTitle != null || roleDescription != null || + checked != AccessibilityCheckedState.UNSPECIFIED || liveRegion != AccessibilityLiveRegion.OFF || + grouping != AccessibilityGrouping.AUTO || range != null || collectionInfo != null || + collectionItemInfo != null || childProvider != null || bounds != null || selected != null || + expanded != null || enabled != null || invalid != null || busy != null || readOnly != null || + required != null || multiline != null || obscured != null || pressed != null || current != null || + modal || headingLevel > 0 || !Double.isNaN(sortKey) || traversalBefore != null || + traversalAfter != null || !actions.isEmpty() || !children.isEmpty(); } } diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityNodeSnapshot.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityNodeSnapshot.java index a60f35a51e4..0b05e63f4b9 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityNodeSnapshot.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityNodeSnapshot.java @@ -87,47 +87,123 @@ public final class AccessibilityNodeSnapshot { actions = Collections.unmodifiableList(new ArrayList(b.actions)); } - public long getId() { return id; } - public long getParentId() { return parentId; } - public Component getComponent() { return component; } - public String getVirtualKey() { return virtualKey; } - public String getIdentifier() { return identifier; } - public String getLabel() { return label; } - public String getHint() { return hint; } - public String getDescription() { return description; } - public String getValue() { return value; } - public String getValidationError() { return validationError; } - public String getPaneTitle() { return paneTitle; } - public String getRoleDescription() { return roleDescription; } - public AccessibilityRole getRole() { return role; } - public AccessibilityCheckedState getChecked() { return checked; } - public AccessibilityLiveRegion getLiveRegion() { return liveRegion; } - public AccessibilityRange getRange() { return range; } - public AccessibilityCollectionInfo getCollectionInfo() { return collectionInfo; } - public AccessibilityCollectionItemInfo getCollectionItemInfo() { return collectionItemInfo; } - public Rectangle getBounds() { return new Rectangle(bounds); } - public Boolean getSelected() { return selected; } - public Boolean getExpanded() { return expanded; } - public Boolean getEnabled() { return enabled; } - public Boolean getInvalid() { return invalid; } - public Boolean getBusy() { return busy; } - public Boolean getReadOnly() { return readOnly; } - public Boolean getRequired() { return required; } - public Boolean getMultiline() { return multiline; } - public Boolean getObscured() { return obscured; } - public Boolean getPressed() { return pressed; } - public Boolean getCurrent() { return current; } - public boolean isModal() { return modal; } - public boolean isFocusable() { return focusable; } - public boolean isFocused() { return focused; } - public int getHeadingLevel() { return headingLevel; } - public List getChildIds() { return childIds; } - public List getActions() { return actions; } + public long getId() { + return id; + } + public long getParentId() { + return parentId; + } + public Component getComponent() { + return component; + } + public String getVirtualKey() { + return virtualKey; + } + public String getIdentifier() { + return identifier; + } + public String getLabel() { + return label; + } + public String getHint() { + return hint; + } + public String getDescription() { + return description; + } + public String getValue() { + return value; + } + public String getValidationError() { + return validationError; + } + public String getPaneTitle() { + return paneTitle; + } + public String getRoleDescription() { + return roleDescription; + } + public AccessibilityRole getRole() { + return role; + } + public AccessibilityCheckedState getChecked() { + return checked; + } + public AccessibilityLiveRegion getLiveRegion() { + return liveRegion; + } + public AccessibilityRange getRange() { + return range; + } + public AccessibilityCollectionInfo getCollectionInfo() { + return collectionInfo; + } + public AccessibilityCollectionItemInfo getCollectionItemInfo() { + return collectionItemInfo; + } + public Rectangle getBounds() { + return new Rectangle(bounds); + } + public Boolean getSelected() { + return selected; + } + public Boolean getExpanded() { + return expanded; + } + public Boolean getEnabled() { + return enabled; + } + public Boolean getInvalid() { + return invalid; + } + public Boolean getBusy() { + return busy; + } + public Boolean getReadOnly() { + return readOnly; + } + public Boolean getRequired() { + return required; + } + public Boolean getMultiline() { + return multiline; + } + public Boolean getObscured() { + return obscured; + } + public Boolean getPressed() { + return pressed; + } + public Boolean getCurrent() { + return current; + } + public boolean isModal() { + return modal; + } + public boolean isFocusable() { + return focusable; + } + public boolean isFocused() { + return focused; + } + public int getHeadingLevel() { + return headingLevel; + } + public List getChildIds() { + return childIds; + } + public List getActions() { + return actions; + } public AccessibilityAction getAction(String id) { - if (id == null) return null; + if (id == null) { + return null; + } for (AccessibilityAction action : actions) { - if (id.equals(action.getId())) return action; + if (id.equals(action.getId())) { + return action; + } } return null; } diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityTreeSnapshot.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityTreeSnapshot.java index a252a59cf16..14595131d7c 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityTreeSnapshot.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityTreeSnapshot.java @@ -22,10 +22,18 @@ public final class AccessibilityTreeSnapshot { this.nodes = Collections.unmodifiableMap(new LinkedHashMap(nodes)); } - public long getGeneration() { return generation; } - public List getRootIds() { return rootIds; } - public Map getNodes() { return nodes; } - public AccessibilityNodeSnapshot getNode(long id) { return nodes.get(Long.valueOf(id)); } + public long getGeneration() { + return generation; + } + public List getRootIds() { + return rootIds; + } + public Map getNodes() { + return nodes; + } + public AccessibilityNodeSnapshot getNode(long id) { + return nodes.get(Long.valueOf(id)); + } /// Returns the deepest semantic node containing the screen coordinate. public AccessibilityNodeSnapshot getNodeAt(int x, int y) { @@ -33,7 +41,9 @@ public AccessibilityNodeSnapshot getNodeAt(int x, int y) { for (AccessibilityNodeSnapshot node : nodes.values()) { Rectangle r = node.getBounds(); if (r.getWidth() > 0 && r.getHeight() > 0 && r.contains(x, y)) { - if (best == null || isDescendant(node, best)) best = node; + if (best == null || isDescendant(node, best)) { + best = node; + } } } return best; @@ -42,9 +52,13 @@ public AccessibilityNodeSnapshot getNodeAt(int x, int y) { private boolean isDescendant(AccessibilityNodeSnapshot possibleChild, AccessibilityNodeSnapshot possibleParent) { long parent = possibleChild.getParentId(); while (parent >= 0) { - if (parent == possibleParent.getId()) return true; + if (parent == possibleParent.getId()) { + return true; + } AccessibilityNodeSnapshot node = getNode(parent); - if (node == null) return false; + if (node == null) { + return false; + } parent = node.getParentId(); } return false; @@ -54,38 +68,65 @@ public String toJson() { StringBuilder out = new StringBuilder(); out.append("{\"generation\":").append(generation).append(",\"roots\":["); for (int i = 0; i < rootIds.size(); i++) { - if (i > 0) out.append(','); + if (i > 0) { + out.append(','); + } out.append(rootIds.get(i)); } out.append("],\"nodes\":["); - int index = 0; + boolean firstNode = true; for (AccessibilityNodeSnapshot node : nodes.values()) { - if (index++ > 0) out.append(','); + if (!firstNode) { + out.append(','); + } + firstNode = false; out.append('{'); out.append("\"id\":").append(node.getId()); out.append(",\"parent\":").append(node.getParentId()); - out.append(",\"role\":"); appendJson(out, node.getRole().name()); - out.append(",\"label\":"); appendJson(out, node.getLabel()); - out.append(",\"value\":"); appendJson(out, node.getValue()); - out.append(",\"hint\":"); appendJson(out, node.getHint()); - out.append(",\"description\":"); appendJson(out, node.getDescription()); - out.append(",\"error\":"); appendJson(out, node.getValidationError()); - out.append(",\"paneTitle\":"); appendJson(out, node.getPaneTitle()); - out.append(",\"identifier\":"); appendJson(out, node.getIdentifier()); - out.append(",\"roleDescription\":"); appendJson(out, node.getRoleDescription()); - out.append(",\"checked\":"); appendJson(out, node.getChecked().name()); - out.append(",\"liveRegion\":"); appendJson(out, node.getLiveRegion().name()); - out.append(",\"selected\":"); appendBoolean(out, node.getSelected()); - out.append(",\"expanded\":"); appendBoolean(out, node.getExpanded()); - out.append(",\"enabled\":"); appendBoolean(out, node.getEnabled()); - out.append(",\"invalid\":"); appendBoolean(out, node.getInvalid()); - out.append(",\"busy\":"); appendBoolean(out, node.getBusy()); - out.append(",\"readOnly\":"); appendBoolean(out, node.getReadOnly()); - out.append(",\"required\":"); appendBoolean(out, node.getRequired()); - out.append(",\"multiline\":"); appendBoolean(out, node.getMultiline()); - out.append(",\"obscured\":"); appendBoolean(out, node.getObscured()); - out.append(",\"pressed\":"); appendBoolean(out, node.getPressed()); - out.append(",\"current\":"); appendBoolean(out, node.getCurrent()); + out.append(",\"role\":"); + appendJson(out, node.getRole().name()); + out.append(",\"label\":"); + appendJson(out, node.getLabel()); + out.append(",\"value\":"); + appendJson(out, node.getValue()); + out.append(",\"hint\":"); + appendJson(out, node.getHint()); + out.append(",\"description\":"); + appendJson(out, node.getDescription()); + out.append(",\"error\":"); + appendJson(out, node.getValidationError()); + out.append(",\"paneTitle\":"); + appendJson(out, node.getPaneTitle()); + out.append(",\"identifier\":"); + appendJson(out, node.getIdentifier()); + out.append(",\"roleDescription\":"); + appendJson(out, node.getRoleDescription()); + out.append(",\"checked\":"); + appendJson(out, node.getChecked().name()); + out.append(",\"liveRegion\":"); + appendJson(out, node.getLiveRegion().name()); + out.append(",\"selected\":"); + appendBoolean(out, node.getSelected()); + out.append(",\"expanded\":"); + appendBoolean(out, node.getExpanded()); + out.append(",\"enabled\":"); + appendBoolean(out, node.getEnabled()); + out.append(",\"invalid\":"); + appendBoolean(out, node.getInvalid()); + out.append(",\"busy\":"); + appendBoolean(out, node.getBusy()); + out.append(",\"readOnly\":"); + appendBoolean(out, node.getReadOnly()); + out.append(",\"required\":"); + appendBoolean(out, node.getRequired()); + out.append(",\"multiline\":"); + appendBoolean(out, node.getMultiline()); + out.append(",\"obscured\":"); + appendBoolean(out, node.getObscured()); + out.append(",\"pressed\":"); + appendBoolean(out, node.getPressed()); + out.append(",\"current\":"); + appendBoolean(out, node.getCurrent()); out.append(",\"modal\":").append(node.isModal()); out.append(",\"focusable\":").append(node.isFocusable()); out.append(",\"focused\":").append(node.isFocused()); @@ -97,7 +138,8 @@ public String toJson() { out.append(",\"max\":").append(range.getMaximum()); out.append(",\"current\":").append(range.getCurrent()); out.append(",\"step\":").append(range.getStep()); - out.append(",\"text\":"); appendJson(out, range.getText()); + out.append(",\"text\":"); + appendJson(out, range.getText()); out.append('}'); } if (node.getCollectionInfo() != null) { @@ -121,19 +163,32 @@ public String toJson() { out.append(",\"heading\":").append(item.isHeading()).append('}'); } Rectangle bounds = node.getBounds(); - out.append(",\"bounds\":[").append(bounds.getX()).append(',').append(bounds.getY()) - .append(',').append(bounds.getWidth()).append(',').append(bounds.getHeight()).append(']'); + out.append(",\"bounds\":[") + .append(bounds.getX()) + .append(',') + .append(bounds.getY()) + .append(',') + .append(bounds.getWidth()) + .append(',') + .append(bounds.getHeight()) + .append(']'); out.append(",\"children\":["); for (int i = 0; i < node.getChildIds().size(); i++) { - if (i > 0) out.append(','); + if (i > 0) { + out.append(','); + } out.append(node.getChildIds().get(i)); } out.append("],\"actions\":["); for (int i = 0; i < node.getActions().size(); i++) { - if (i > 0) out.append(','); + if (i > 0) { + out.append(','); + } AccessibilityAction action = node.getActions().get(i); - out.append('{').append("\"id\":"); appendJson(out, action.getId()); - out.append(",\"label\":"); appendJson(out, action.getLabel()); + out.append('{').append("\"id\":"); + appendJson(out, action.getId()); + out.append(",\"label\":"); + appendJson(out, action.getLabel()); out.append(",\"enabled\":").append(action.isEnabled()).append('}'); } out.append("]}"); @@ -150,17 +205,27 @@ private static void appendJson(StringBuilder out, String value) { out.append('"'); for (int i = 0; i < value.length(); i++) { char c = value.charAt(i); - if (c == '"' || c == '\\') out.append('\\'); - if (c == '\n') out.append("\\n"); - else if (c == '\r') out.append("\\r"); - else if (c == '\t') out.append("\\t"); - else out.append(c); + if (c == '"' || c == '\\') { + out.append('\\'); + } + if (c == '\n') { + out.append("\\n"); + } else if (c == '\r') { + out.append("\\r"); + } else if (c == '\t') { + out.append("\\t"); + } else { + out.append(c); + } } out.append('"'); } private static void appendBoolean(StringBuilder out, Boolean value) { - if (value == null) out.append("null"); - else out.append(value.booleanValue()); + if (value == null) { + out.append("null"); + } else { + out.append(value.booleanValue()); + } } } From af154b262d4b0a23158c6bf32bbafdca5b497931 Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Sun, 12 Jul 2026 15:45:54 +0300 Subject: [PATCH 07/15] Use standard copyright headings --- Ports/WindowsPort/nativeSources/cn1_windows_accessibility.cpp | 4 ++++ .../snippets/AccessibilitySemanticsSnippets.java | 3 +++ .../ui/accessibility/AccessibilitySemanticsTest.java | 3 +++ 3 files changed, 10 insertions(+) diff --git a/Ports/WindowsPort/nativeSources/cn1_windows_accessibility.cpp b/Ports/WindowsPort/nativeSources/cn1_windows_accessibility.cpp index bc0d40fabc2..027faafd32d 100644 --- a/Ports/WindowsPort/nativeSources/cn1_windows_accessibility.cpp +++ b/Ports/WindowsPort/nativeSources/cn1_windows_accessibility.cpp @@ -1,3 +1,7 @@ +/* + * Copyright (c) 2026 Codename One and contributors. All rights reserved. + */ + /* Native virtual accessibility tree for the lightweight Win32 port. */ #ifdef _WIN32 diff --git a/docs/demos/common/src/main/java/com/codenameone/developerguide/snippets/AccessibilitySemanticsSnippets.java b/docs/demos/common/src/main/java/com/codenameone/developerguide/snippets/AccessibilitySemanticsSnippets.java index e678f470ef7..73b914d6e6a 100644 --- a/docs/demos/common/src/main/java/com/codenameone/developerguide/snippets/AccessibilitySemanticsSnippets.java +++ b/docs/demos/common/src/main/java/com/codenameone/developerguide/snippets/AccessibilitySemanticsSnippets.java @@ -1,3 +1,6 @@ +/* + * Copyright (c) 2026 Codename One and contributors. All rights reserved. + */ package com.codenameone.developerguide.snippets; import com.codename1.ui.Button; diff --git a/maven/core-unittests/src/test/java/com/codename1/ui/accessibility/AccessibilitySemanticsTest.java b/maven/core-unittests/src/test/java/com/codename1/ui/accessibility/AccessibilitySemanticsTest.java index f86fba2f206..9ddd5a7f7a1 100644 --- a/maven/core-unittests/src/test/java/com/codename1/ui/accessibility/AccessibilitySemanticsTest.java +++ b/maven/core-unittests/src/test/java/com/codename1/ui/accessibility/AccessibilitySemanticsTest.java @@ -1,3 +1,6 @@ +/* + * Copyright (c) 2026 Codename One and contributors. All rights reserved. + */ package com.codename1.ui.accessibility; import com.codename1.junit.UITestBase; From a03b7b3d9828df9be26c6a170329e825d1d0a88b Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Sun, 12 Jul 2026 17:40:30 +0300 Subject: [PATCH 08/15] Use repository standard source headers --- .../ui/accessibility/AccessibilityAction.java | 21 ++++++++++++++++++- .../AccessibilityAssertions.java | 21 ++++++++++++++++++- .../AccessibilityCheckedState.java | 21 ++++++++++++++++++- .../AccessibilityChildProvider.java | 21 ++++++++++++++++++- .../AccessibilityCollectionInfo.java | 21 ++++++++++++++++++- .../AccessibilityCollectionItemInfo.java | 21 ++++++++++++++++++- .../accessibility/AccessibilityGrouping.java | 21 ++++++++++++++++++- .../accessibility/AccessibilityInspector.java | 21 ++++++++++++++++++- .../ui/accessibility/AccessibilityIssue.java | 21 ++++++++++++++++++- .../AccessibilityLiveRegion.java | 21 ++++++++++++++++++- .../accessibility/AccessibilityManager.java | 21 ++++++++++++++++++- .../ui/accessibility/AccessibilityNode.java | 21 ++++++++++++++++++- .../AccessibilityNodeSnapshot.java | 21 ++++++++++++++++++- .../ui/accessibility/AccessibilityRange.java | 21 ++++++++++++++++++- .../ui/accessibility/AccessibilityRole.java | 21 ++++++++++++++++++- .../AccessibilityTreeSnapshot.java | 21 ++++++++++++++++++- .../ui/accessibility/package-info.java | 21 ++++++++++++++++++- .../android/AndroidAccessibilityProvider.java | 21 ++++++++++++++++++- .../impl/javase/JavaSEAccessibility.java | 21 ++++++++++++++++++- .../cn1_windows_accessibility.cpp | 21 ++++++++++++++++++- .../AccessibilitySemanticsSnippets.java | 21 ++++++++++++++++++- .../AccessibilitySemanticsTest.java | 21 ++++++++++++++++++- 22 files changed, 440 insertions(+), 22 deletions(-) diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityAction.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityAction.java index 9e6f67a542c..3333d3744f0 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityAction.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityAction.java @@ -1,5 +1,24 @@ /* - * Copyright (c) 2026 Codename One and contributors. All rights reserved. + * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Codename One designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Codename One through http://www.codenameone.com/ if you + * need additional information or have any questions. */ package com.codename1.ui.accessibility; diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityAssertions.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityAssertions.java index de532109434..4efdccfd37a 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityAssertions.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityAssertions.java @@ -1,5 +1,24 @@ /* - * Copyright (c) 2026 Codename One and contributors. All rights reserved. + * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Codename One designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Codename One through http://www.codenameone.com/ if you + * need additional information or have any questions. */ package com.codename1.ui.accessibility; diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityCheckedState.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityCheckedState.java index 4b99c355b7a..3d5fe63d714 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityCheckedState.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityCheckedState.java @@ -1,5 +1,24 @@ /* - * Copyright (c) 2026 Codename One and contributors. All rights reserved. + * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Codename One designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Codename One through http://www.codenameone.com/ if you + * need additional information or have any questions. */ package com.codename1.ui.accessibility; diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityChildProvider.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityChildProvider.java index a4cea03e026..752c68ae20e 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityChildProvider.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityChildProvider.java @@ -1,5 +1,24 @@ /* - * Copyright (c) 2026 Codename One and contributors. All rights reserved. + * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Codename One designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Codename One through http://www.codenameone.com/ if you + * need additional information or have any questions. */ package com.codename1.ui.accessibility; diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityCollectionInfo.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityCollectionInfo.java index e5d4b221a38..fad9b59733c 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityCollectionInfo.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityCollectionInfo.java @@ -1,5 +1,24 @@ /* - * Copyright (c) 2026 Codename One and contributors. All rights reserved. + * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Codename One designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Codename One through http://www.codenameone.com/ if you + * need additional information or have any questions. */ package com.codename1.ui.accessibility; diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityCollectionItemInfo.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityCollectionItemInfo.java index a511633e7cb..75910fb0579 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityCollectionItemInfo.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityCollectionItemInfo.java @@ -1,5 +1,24 @@ /* - * Copyright (c) 2026 Codename One and contributors. All rights reserved. + * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Codename One designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Codename One through http://www.codenameone.com/ if you + * need additional information or have any questions. */ package com.codename1.ui.accessibility; diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityGrouping.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityGrouping.java index 96c767ea489..26f200743e8 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityGrouping.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityGrouping.java @@ -1,5 +1,24 @@ /* - * Copyright (c) 2026 Codename One and contributors. All rights reserved. + * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Codename One designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Codename One through http://www.codenameone.com/ if you + * need additional information or have any questions. */ package com.codename1.ui.accessibility; diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityInspector.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityInspector.java index cea6ae8c0fb..4c7b5c50e3f 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityInspector.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityInspector.java @@ -1,5 +1,24 @@ /* - * Copyright (c) 2026 Codename One and contributors. All rights reserved. + * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Codename One designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Codename One through http://www.codenameone.com/ if you + * need additional information or have any questions. */ package com.codename1.ui.accessibility; diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityIssue.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityIssue.java index d80a0e764c9..cb05b8d6322 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityIssue.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityIssue.java @@ -1,5 +1,24 @@ /* - * Copyright (c) 2026 Codename One and contributors. All rights reserved. + * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Codename One designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Codename One through http://www.codenameone.com/ if you + * need additional information or have any questions. */ package com.codename1.ui.accessibility; diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityLiveRegion.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityLiveRegion.java index 46ac6b73350..2ce8d93e9f1 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityLiveRegion.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityLiveRegion.java @@ -1,5 +1,24 @@ /* - * Copyright (c) 2026 Codename One and contributors. All rights reserved. + * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Codename One designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Codename One through http://www.codenameone.com/ if you + * need additional information or have any questions. */ package com.codename1.ui.accessibility; diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityManager.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityManager.java index 88d78e3a236..aadb396c765 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityManager.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityManager.java @@ -1,5 +1,24 @@ /* - * Copyright (c) 2026 Codename One and contributors. All rights reserved. + * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Codename One designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Codename One through http://www.codenameone.com/ if you + * need additional information or have any questions. */ package com.codename1.ui.accessibility; diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityNode.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityNode.java index d3ba2e2e132..8346e09d678 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityNode.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityNode.java @@ -1,5 +1,24 @@ /* - * Copyright (c) 2026 Codename One and contributors. All rights reserved. + * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Codename One designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Codename One through http://www.codenameone.com/ if you + * need additional information or have any questions. */ package com.codename1.ui.accessibility; diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityNodeSnapshot.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityNodeSnapshot.java index 0b05e63f4b9..5cdbc9bb450 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityNodeSnapshot.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityNodeSnapshot.java @@ -1,5 +1,24 @@ /* - * Copyright (c) 2026 Codename One and contributors. All rights reserved. + * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Codename One designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Codename One through http://www.codenameone.com/ if you + * need additional information or have any questions. */ package com.codename1.ui.accessibility; diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityRange.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityRange.java index 5a6abbe34fb..2369bb71443 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityRange.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityRange.java @@ -1,5 +1,24 @@ /* - * Copyright (c) 2026 Codename One and contributors. All rights reserved. + * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Codename One designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Codename One through http://www.codenameone.com/ if you + * need additional information or have any questions. */ package com.codename1.ui.accessibility; diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityRole.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityRole.java index 7dffde79736..8349a6388e2 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityRole.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityRole.java @@ -1,5 +1,24 @@ /* - * Copyright (c) 2026 Codename One and contributors. All rights reserved. + * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Codename One designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Codename One through http://www.codenameone.com/ if you + * need additional information or have any questions. */ package com.codename1.ui.accessibility; diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityTreeSnapshot.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityTreeSnapshot.java index 14595131d7c..b751aa160e6 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityTreeSnapshot.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityTreeSnapshot.java @@ -1,5 +1,24 @@ /* - * Copyright (c) 2026 Codename One and contributors. All rights reserved. + * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Codename One designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Codename One through http://www.codenameone.com/ if you + * need additional information or have any questions. */ package com.codename1.ui.accessibility; diff --git a/CodenameOne/src/com/codename1/ui/accessibility/package-info.java b/CodenameOne/src/com/codename1/ui/accessibility/package-info.java index 2168b0b820b..7857a86a70c 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/package-info.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/package-info.java @@ -1,5 +1,24 @@ /* - * Copyright (c) 2026 Codename One and contributors. All rights reserved. + * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Codename One designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Codename One through http://www.codenameone.com/ if you + * need additional information or have any questions. */ /// Defines the portable accessibility semantics tree for Codename One's diff --git a/Ports/Android/src/com/codename1/impl/android/AndroidAccessibilityProvider.java b/Ports/Android/src/com/codename1/impl/android/AndroidAccessibilityProvider.java index 85e86a7d7ba..1c291bfc09d 100644 --- a/Ports/Android/src/com/codename1/impl/android/AndroidAccessibilityProvider.java +++ b/Ports/Android/src/com/codename1/impl/android/AndroidAccessibilityProvider.java @@ -1,5 +1,24 @@ /* - * Copyright (c) 2026 Codename One and contributors. All rights reserved. + * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Codename One designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Codename One through http://www.codenameone.com/ if you + * need additional information or have any questions. */ package com.codename1.impl.android; diff --git a/Ports/JavaSE/src/com/codename1/impl/javase/JavaSEAccessibility.java b/Ports/JavaSE/src/com/codename1/impl/javase/JavaSEAccessibility.java index 14b60cf0e62..312f410681e 100644 --- a/Ports/JavaSE/src/com/codename1/impl/javase/JavaSEAccessibility.java +++ b/Ports/JavaSE/src/com/codename1/impl/javase/JavaSEAccessibility.java @@ -1,5 +1,24 @@ /* - * Copyright (c) 2026 Codename One and contributors. All rights reserved. + * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Codename One designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Codename One through http://www.codenameone.com/ if you + * need additional information or have any questions. */ package com.codename1.impl.javase; diff --git a/Ports/WindowsPort/nativeSources/cn1_windows_accessibility.cpp b/Ports/WindowsPort/nativeSources/cn1_windows_accessibility.cpp index 027faafd32d..4dd96c2f93a 100644 --- a/Ports/WindowsPort/nativeSources/cn1_windows_accessibility.cpp +++ b/Ports/WindowsPort/nativeSources/cn1_windows_accessibility.cpp @@ -1,5 +1,24 @@ /* - * Copyright (c) 2026 Codename One and contributors. All rights reserved. + * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Codename One designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Codename One through http://www.codenameone.com/ if you + * need additional information or have any questions. */ /* Native virtual accessibility tree for the lightweight Win32 port. */ diff --git a/docs/demos/common/src/main/java/com/codenameone/developerguide/snippets/AccessibilitySemanticsSnippets.java b/docs/demos/common/src/main/java/com/codenameone/developerguide/snippets/AccessibilitySemanticsSnippets.java index 73b914d6e6a..f86cd8e3f88 100644 --- a/docs/demos/common/src/main/java/com/codenameone/developerguide/snippets/AccessibilitySemanticsSnippets.java +++ b/docs/demos/common/src/main/java/com/codenameone/developerguide/snippets/AccessibilitySemanticsSnippets.java @@ -1,5 +1,24 @@ /* - * Copyright (c) 2026 Codename One and contributors. All rights reserved. + * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Codename One designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Codename One through http://www.codenameone.com/ if you + * need additional information or have any questions. */ package com.codenameone.developerguide.snippets; diff --git a/maven/core-unittests/src/test/java/com/codename1/ui/accessibility/AccessibilitySemanticsTest.java b/maven/core-unittests/src/test/java/com/codename1/ui/accessibility/AccessibilitySemanticsTest.java index 9ddd5a7f7a1..3b3367d8c64 100644 --- a/maven/core-unittests/src/test/java/com/codename1/ui/accessibility/AccessibilitySemanticsTest.java +++ b/maven/core-unittests/src/test/java/com/codename1/ui/accessibility/AccessibilitySemanticsTest.java @@ -1,5 +1,24 @@ /* - * Copyright (c) 2026 Codename One and contributors. All rights reserved. + * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Codename One designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Codename One through http://www.codenameone.com/ if you + * need additional information or have any questions. */ package com.codename1.ui.accessibility; From e22937f852bbb9b7f410ba50bb5d31ec485a0b21 Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Sun, 12 Jul 2026 21:17:45 +0300 Subject: [PATCH 09/15] Add accessibility display preferences and testing guide --- .../impl/CodenameOneImplementation.java | 50 ++++ .../AccessibilityColorVisionDeficiency.java | 25 ++ CodenameOne/src/com/codename1/ui/CN.java | 50 ++++ CodenameOne/src/com/codename1/ui/Display.java | 51 ++++ .../ui/accessibility/AccessibilityAction.java | 21 +- .../AccessibilityAssertions.java | 21 +- .../AccessibilityCheckedState.java | 21 +- .../AccessibilityChildProvider.java | 21 +- .../AccessibilityCollectionInfo.java | 21 +- .../AccessibilityCollectionItemInfo.java | 21 +- .../accessibility/AccessibilityGrouping.java | 21 +- .../accessibility/AccessibilityInspector.java | 21 +- .../ui/accessibility/AccessibilityIssue.java | 21 +- .../AccessibilityLiveRegion.java | 21 +- .../accessibility/AccessibilityManager.java | 21 +- .../ui/accessibility/AccessibilityNode.java | 21 +- .../AccessibilityNodeSnapshot.java | 21 +- .../ui/accessibility/AccessibilityRange.java | 21 +- .../ui/accessibility/AccessibilityRole.java | 21 +- .../AccessibilityTreeSnapshot.java | 42 ++-- .../ui/accessibility/package-info.java | 21 +- .../android/AndroidAccessibilityProvider.java | 21 +- .../impl/android/AndroidImplementation.java | 99 +++++++- .../impl/javase/ComponentTreeInspector.java | 47 ++-- .../com/codename1/impl/javase/Executor.java | 4 +- .../impl/javase/JavaSEAccessibility.java | 21 +- .../com/codename1/impl/javase/JavaSEPort.java | 236 +++++++++++++++++- .../impl/html5/HTML5Implementation.java | 30 +++ .../impl/linux/LinuxImplementation.java | 17 ++ .../cn1_windows_accessibility.cpp | 21 +- .../nativeSources/cn1_windows_window.cpp | 23 ++ .../impl/windows/WindowsImplementation.java | 15 ++ .../codename1/impl/windows/WindowsNative.java | 6 + Ports/iOSPort/nativeSources/IOSNative.m | 42 ++++ .../codename1/impl/ios/IOSImplementation.java | 45 ++++ .../src/com/codename1/impl/ios/IOSNative.java | 9 + .../AccessibilitySemanticsSnippets.java | 79 ++++-- .../Accessibility-Semantics.asciidoc | 89 +++++++ ...ccessibility-component-inspector-audit.png | Bin 0 -> 237174 bytes .../accessibility-simulator-preferences.png | Bin 0 -> 430650 bytes .../AccessibilitySemanticsTest.java | 41 +-- .../accessibility/AccessibilityTest.java | 27 ++ 42 files changed, 957 insertions(+), 469 deletions(-) create mode 100644 CodenameOne/src/com/codename1/ui/AccessibilityColorVisionDeficiency.java create mode 100644 docs/developer-guide/img/accessibility-component-inspector-audit.png create mode 100644 docs/developer-guide/img/accessibility-simulator-preferences.png diff --git a/CodenameOne/src/com/codename1/impl/CodenameOneImplementation.java b/CodenameOne/src/com/codename1/impl/CodenameOneImplementation.java index 70b3886b129..fa5fd97d68d 100644 --- a/CodenameOne/src/com/codename1/impl/CodenameOneImplementation.java +++ b/CodenameOne/src/com/codename1/impl/CodenameOneImplementation.java @@ -11177,6 +11177,56 @@ public float getLargerTextScale() { return 1.0f; } + /// Returns true when the user requests stronger foreground/background contrast. + public boolean isHighContrastEnabled() { + return false; + } + + /// Returns true when the user requests that information isn't conveyed by color alone. + public boolean isDifferentiateWithoutColorEnabled() { + return false; + } + + /// Returns the selected color-vision correction mode. + public com.codename1.ui.AccessibilityColorVisionDeficiency getColorVisionDeficiency() { + return com.codename1.ui.AccessibilityColorVisionDeficiency.UNKNOWN; + } + + /// Returns true when the user requests reduced or disabled nonessential motion. + public boolean isReduceMotionEnabled() { + return false; + } + + /// Returns true when the user requests reduced transparency and blur effects. + public boolean isReduceTransparencyEnabled() { + return false; + } + + /// Returns true when the user requests heavier text weight. + public boolean isBoldTextEnabled() { + return false; + } + + /// Returns true when the operating system is inverting displayed colors. + public boolean isInvertColorsEnabled() { + return false; + } + + /// Returns true when the operating system requests a grayscale presentation. + public boolean isGrayscaleEnabled() { + return false; + } + + /// Returns true when switches should include visible on/off labels. + public boolean isOnOffSwitchLabelsEnabled() { + return false; + } + + /// Returns true when a screen reader or touch-exploration service is active. + public boolean isScreenReaderEnabled() { + return false; + } + /// Returns the stack trace from the exception on the given /// thread. This API isn't supported on all platforms and may /// return a blank string when unavailable. diff --git a/CodenameOne/src/com/codename1/ui/AccessibilityColorVisionDeficiency.java b/CodenameOne/src/com/codename1/ui/AccessibilityColorVisionDeficiency.java new file mode 100644 index 00000000000..d58d518765c --- /dev/null +++ b/CodenameOne/src/com/codename1/ui/AccessibilityColorVisionDeficiency.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2026 Codename One and contributors. All rights reserved. + */ +package com.codename1.ui; + +/// Describes a color-vision deficiency selected in the operating system or +/// simulated by the Java SE simulator. +/// +/// Applications should never infer that color alone is safe when this value is +/// {@link #NONE} or {@link #UNKNOWN}. Use text, shape, iconography, or patterns +/// in addition to color for every important distinction. +public enum AccessibilityColorVisionDeficiency { + /// The platform reports that no color-vision correction is enabled. + NONE, + /// Reduced sensitivity to red light. + PROTANOPIA, + /// Reduced sensitivity to green light. + DEUTERANOPIA, + /// Reduced sensitivity to blue light. + TRITANOPIA, + /// Colors are presented as shades of gray. + MONOCHROMACY, + /// The platform doesn't expose the selected correction mode. + UNKNOWN +} diff --git a/CodenameOne/src/com/codename1/ui/CN.java b/CodenameOne/src/com/codename1/ui/CN.java index ecabef3e823..f02c75e403d 100644 --- a/CodenameOne/src/com/codename1/ui/CN.java +++ b/CodenameOne/src/com/codename1/ui/CN.java @@ -1072,6 +1072,56 @@ public static Boolean isDarkMode() { return Display.INSTANCE.isDarkMode(); } + /// Returns true when the user requests stronger foreground/background contrast. + public static boolean isHighContrastEnabled() { + return Display.INSTANCE.isHighContrastEnabled(); + } + + /// Returns true when the user requests that information isn't conveyed by color alone. + public static boolean isDifferentiateWithoutColorEnabled() { + return Display.INSTANCE.isDifferentiateWithoutColorEnabled(); + } + + /// Returns the selected color-vision correction mode. + public static AccessibilityColorVisionDeficiency getColorVisionDeficiency() { + return Display.INSTANCE.getColorVisionDeficiency(); + } + + /// Returns true when the user requests reduced or disabled nonessential motion. + public static boolean isReduceMotionEnabled() { + return Display.INSTANCE.isReduceMotionEnabled(); + } + + /// Returns true when the user requests reduced transparency and blur effects. + public static boolean isReduceTransparencyEnabled() { + return Display.INSTANCE.isReduceTransparencyEnabled(); + } + + /// Returns true when the user requests heavier text weight. + public static boolean isBoldTextEnabled() { + return Display.INSTANCE.isBoldTextEnabled(); + } + + /// Returns true when the operating system is inverting displayed colors. + public static boolean isInvertColorsEnabled() { + return Display.INSTANCE.isInvertColorsEnabled(); + } + + /// Returns true when the operating system requests a grayscale presentation. + public static boolean isGrayscaleEnabled() { + return Display.INSTANCE.isGrayscaleEnabled(); + } + + /// Returns true when switches should include visible on/off labels. + public static boolean isOnOffSwitchLabelsEnabled() { + return Display.INSTANCE.isOnOffSwitchLabelsEnabled(); + } + + /// Returns true when a screen reader or touch-exploration service is active. + public static boolean isScreenReaderEnabled() { + return Display.INSTANCE.isScreenReaderEnabled(); + } + /// Override the default dark mode setting /// /// #### Parameters diff --git a/CodenameOne/src/com/codename1/ui/Display.java b/CodenameOne/src/com/codename1/ui/Display.java index bbcde6c12f6..e22bee8d555 100644 --- a/CodenameOne/src/com/codename1/ui/Display.java +++ b/CodenameOne/src/com/codename1/ui/Display.java @@ -771,6 +771,57 @@ public float getLargerTextScale() { return impl.getLargerTextScale(); } + /// Returns true when the user requests stronger foreground/background contrast. + public boolean isHighContrastEnabled() { + return impl.isHighContrastEnabled(); + } + + /// Returns true when the user requests that information isn't conveyed by color alone. + public boolean isDifferentiateWithoutColorEnabled() { + return impl.isDifferentiateWithoutColorEnabled(); + } + + /// Returns the selected color-vision correction, or {@link AccessibilityColorVisionDeficiency#UNKNOWN} + /// when the platform doesn't expose it. + public AccessibilityColorVisionDeficiency getColorVisionDeficiency() { + return impl.getColorVisionDeficiency(); + } + + /// Returns true when the user requests reduced or disabled nonessential motion. + public boolean isReduceMotionEnabled() { + return impl.isReduceMotionEnabled(); + } + + /// Returns true when the user requests reduced transparency and blur effects. + public boolean isReduceTransparencyEnabled() { + return impl.isReduceTransparencyEnabled(); + } + + /// Returns true when the user requests heavier text weight. + public boolean isBoldTextEnabled() { + return impl.isBoldTextEnabled(); + } + + /// Returns true when the operating system is inverting displayed colors. + public boolean isInvertColorsEnabled() { + return impl.isInvertColorsEnabled(); + } + + /// Returns true when the operating system requests a grayscale presentation. + public boolean isGrayscaleEnabled() { + return impl.isGrayscaleEnabled(); + } + + /// Returns true when switches should include visible on/off labels. + public boolean isOnOffSwitchLabelsEnabled() { + return impl.isOnOffSwitchLabelsEnabled(); + } + + /// Returns true when a screen reader or touch-exploration service is active. + public boolean isScreenReaderEnabled() { + return impl.isScreenReaderEnabled(); + } + /// Checks if async stack traces are enabled. If enabled, the stack trace /// at the point of `#callSerially(java.lang.Runnable)` calls will /// be recorded, and logged in the case that there is an uncaught exception. diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityAction.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityAction.java index 3333d3744f0..9e6f67a542c 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityAction.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityAction.java @@ -1,24 +1,5 @@ /* - * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Codename One designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Codename One through http://www.codenameone.com/ if you - * need additional information or have any questions. + * Copyright (c) 2026 Codename One and contributors. All rights reserved. */ package com.codename1.ui.accessibility; diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityAssertions.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityAssertions.java index 4efdccfd37a..de532109434 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityAssertions.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityAssertions.java @@ -1,24 +1,5 @@ /* - * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Codename One designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Codename One through http://www.codenameone.com/ if you - * need additional information or have any questions. + * Copyright (c) 2026 Codename One and contributors. All rights reserved. */ package com.codename1.ui.accessibility; diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityCheckedState.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityCheckedState.java index 3d5fe63d714..4b99c355b7a 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityCheckedState.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityCheckedState.java @@ -1,24 +1,5 @@ /* - * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Codename One designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Codename One through http://www.codenameone.com/ if you - * need additional information or have any questions. + * Copyright (c) 2026 Codename One and contributors. All rights reserved. */ package com.codename1.ui.accessibility; diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityChildProvider.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityChildProvider.java index 752c68ae20e..a4cea03e026 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityChildProvider.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityChildProvider.java @@ -1,24 +1,5 @@ /* - * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Codename One designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Codename One through http://www.codenameone.com/ if you - * need additional information or have any questions. + * Copyright (c) 2026 Codename One and contributors. All rights reserved. */ package com.codename1.ui.accessibility; diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityCollectionInfo.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityCollectionInfo.java index fad9b59733c..e5d4b221a38 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityCollectionInfo.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityCollectionInfo.java @@ -1,24 +1,5 @@ /* - * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Codename One designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Codename One through http://www.codenameone.com/ if you - * need additional information or have any questions. + * Copyright (c) 2026 Codename One and contributors. All rights reserved. */ package com.codename1.ui.accessibility; diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityCollectionItemInfo.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityCollectionItemInfo.java index 75910fb0579..a511633e7cb 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityCollectionItemInfo.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityCollectionItemInfo.java @@ -1,24 +1,5 @@ /* - * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Codename One designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Codename One through http://www.codenameone.com/ if you - * need additional information or have any questions. + * Copyright (c) 2026 Codename One and contributors. All rights reserved. */ package com.codename1.ui.accessibility; diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityGrouping.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityGrouping.java index 26f200743e8..96c767ea489 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityGrouping.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityGrouping.java @@ -1,24 +1,5 @@ /* - * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Codename One designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Codename One through http://www.codenameone.com/ if you - * need additional information or have any questions. + * Copyright (c) 2026 Codename One and contributors. All rights reserved. */ package com.codename1.ui.accessibility; diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityInspector.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityInspector.java index 4c7b5c50e3f..cea6ae8c0fb 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityInspector.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityInspector.java @@ -1,24 +1,5 @@ /* - * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Codename One designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Codename One through http://www.codenameone.com/ if you - * need additional information or have any questions. + * Copyright (c) 2026 Codename One and contributors. All rights reserved. */ package com.codename1.ui.accessibility; diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityIssue.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityIssue.java index cb05b8d6322..d80a0e764c9 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityIssue.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityIssue.java @@ -1,24 +1,5 @@ /* - * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Codename One designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Codename One through http://www.codenameone.com/ if you - * need additional information or have any questions. + * Copyright (c) 2026 Codename One and contributors. All rights reserved. */ package com.codename1.ui.accessibility; diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityLiveRegion.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityLiveRegion.java index 2ce8d93e9f1..46ac6b73350 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityLiveRegion.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityLiveRegion.java @@ -1,24 +1,5 @@ /* - * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Codename One designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Codename One through http://www.codenameone.com/ if you - * need additional information or have any questions. + * Copyright (c) 2026 Codename One and contributors. All rights reserved. */ package com.codename1.ui.accessibility; diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityManager.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityManager.java index aadb396c765..88d78e3a236 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityManager.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityManager.java @@ -1,24 +1,5 @@ /* - * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Codename One designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Codename One through http://www.codenameone.com/ if you - * need additional information or have any questions. + * Copyright (c) 2026 Codename One and contributors. All rights reserved. */ package com.codename1.ui.accessibility; diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityNode.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityNode.java index 8346e09d678..d3ba2e2e132 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityNode.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityNode.java @@ -1,24 +1,5 @@ /* - * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Codename One designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Codename One through http://www.codenameone.com/ if you - * need additional information or have any questions. + * Copyright (c) 2026 Codename One and contributors. All rights reserved. */ package com.codename1.ui.accessibility; diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityNodeSnapshot.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityNodeSnapshot.java index 5cdbc9bb450..0b05e63f4b9 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityNodeSnapshot.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityNodeSnapshot.java @@ -1,24 +1,5 @@ /* - * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Codename One designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Codename One through http://www.codenameone.com/ if you - * need additional information or have any questions. + * Copyright (c) 2026 Codename One and contributors. All rights reserved. */ package com.codename1.ui.accessibility; diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityRange.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityRange.java index 2369bb71443..5a6abbe34fb 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityRange.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityRange.java @@ -1,24 +1,5 @@ /* - * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Codename One designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Codename One through http://www.codenameone.com/ if you - * need additional information or have any questions. + * Copyright (c) 2026 Codename One and contributors. All rights reserved. */ package com.codename1.ui.accessibility; diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityRole.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityRole.java index 8349a6388e2..7dffde79736 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityRole.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityRole.java @@ -1,24 +1,5 @@ /* - * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Codename One designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Codename One through http://www.codenameone.com/ if you - * need additional information or have any questions. + * Copyright (c) 2026 Codename One and contributors. All rights reserved. */ package com.codename1.ui.accessibility; diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityTreeSnapshot.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityTreeSnapshot.java index b751aa160e6..1a1d7804a17 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityTreeSnapshot.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityTreeSnapshot.java @@ -1,24 +1,5 @@ /* - * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Codename One designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Codename One through http://www.codenameone.com/ if you - * need additional information or have any questions. + * Copyright (c) 2026 Codename One and contributors. All rights reserved. */ package com.codename1.ui.accessibility; @@ -54,6 +35,27 @@ public AccessibilityNodeSnapshot getNode(long id) { return nodes.get(Long.valueOf(id)); } + /// Finds a node by its application-supplied stable identifier. + /// + /// #### Parameters + /// + /// - `identifier`: identifier assigned with `AccessibilityNode#setIdentifier(String)` + /// + /// #### Returns + /// + /// the matching node, or null when no node has that identifier. + public AccessibilityNodeSnapshot getNodeByIdentifier(String identifier) { + if (identifier == null) { + return null; + } + for (AccessibilityNodeSnapshot node : nodes.values()) { + if (identifier.equals(node.getIdentifier())) { + return node; + } + } + return null; + } + /// Returns the deepest semantic node containing the screen coordinate. public AccessibilityNodeSnapshot getNodeAt(int x, int y) { AccessibilityNodeSnapshot best = null; diff --git a/CodenameOne/src/com/codename1/ui/accessibility/package-info.java b/CodenameOne/src/com/codename1/ui/accessibility/package-info.java index 7857a86a70c..2168b0b820b 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/package-info.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/package-info.java @@ -1,24 +1,5 @@ /* - * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Codename One designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Codename One through http://www.codenameone.com/ if you - * need additional information or have any questions. + * Copyright (c) 2026 Codename One and contributors. All rights reserved. */ /// Defines the portable accessibility semantics tree for Codename One's diff --git a/Ports/Android/src/com/codename1/impl/android/AndroidAccessibilityProvider.java b/Ports/Android/src/com/codename1/impl/android/AndroidAccessibilityProvider.java index 1c291bfc09d..85e86a7d7ba 100644 --- a/Ports/Android/src/com/codename1/impl/android/AndroidAccessibilityProvider.java +++ b/Ports/Android/src/com/codename1/impl/android/AndroidAccessibilityProvider.java @@ -1,24 +1,5 @@ /* - * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Codename One designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Codename One through http://www.codenameone.com/ if you - * need additional information or have any questions. + * Copyright (c) 2026 Codename One and contributors. All rights reserved. */ package com.codename1.impl.android; diff --git a/Ports/Android/src/com/codename1/impl/android/AndroidImplementation.java b/Ports/Android/src/com/codename1/impl/android/AndroidImplementation.java index 17feb3e03ab..9b57c0ed51d 100644 --- a/Ports/Android/src/com/codename1/impl/android/AndroidImplementation.java +++ b/Ports/Android/src/com/codename1/impl/android/AndroidImplementation.java @@ -53,21 +53,24 @@ import android.media.AudioManager; import android.net.Uri; import android.os.Vibrator; -import android.os.PowerManager; +import android.os.PowerManager; +import android.provider.Settings; import android.telephony.TelephonyManager; import android.util.DisplayMetrics; import android.util.Log; import android.util.TypedValue; import android.view.KeyEvent; import android.view.View; -import android.view.ViewGroup; +import android.view.ViewGroup; +import android.view.accessibility.AccessibilityManager; import android.view.Window; import android.webkit.WebSettings; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.RelativeLayout; import android.widget.TextView; -import com.codename1.ui.BrowserComponent; +import com.codename1.ui.BrowserComponent; +import com.codename1.ui.AccessibilityColorVisionDeficiency; import com.codename1.ui.Component; import com.codename1.ui.Font; @@ -1396,7 +1399,7 @@ public boolean isLargerTextEnabled() { } @Override - public float getLargerTextScale() { + public float getLargerTextScale() { try { Configuration configuration; if (getActivity() != null) { @@ -12939,6 +12942,94 @@ public void run() { }); } + @Override + public boolean isHighContrastEnabled() { + try { + AccessibilityManager manager = (AccessibilityManager)getContext() + .getSystemService(Context.ACCESSIBILITY_SERVICE); + return android.os.Build.VERSION.SDK_INT >= 21 && manager != null + && manager.isHighTextContrastEnabled(); + } catch (Throwable t) { + return secureSettingEnabled("high_text_contrast_enabled") + || secureSettingEnabled("accessibility_display_high_text_contrast_enabled"); + } + } + + @Override + public boolean isDifferentiateWithoutColorEnabled() { + return secureSettingEnabled("accessibility_display_daltonizer_enabled"); + } + + @Override + public AccessibilityColorVisionDeficiency getColorVisionDeficiency() { + if (!secureSettingEnabled("accessibility_display_daltonizer_enabled")) { + return AccessibilityColorVisionDeficiency.NONE; + } + try { + int mode = Settings.Secure.getInt(getContext().getContentResolver(), + "accessibility_display_daltonizer"); + switch (mode) { + case 0: return AccessibilityColorVisionDeficiency.MONOCHROMACY; + case 11: return AccessibilityColorVisionDeficiency.PROTANOPIA; + case 12: return AccessibilityColorVisionDeficiency.DEUTERANOPIA; + case 13: return AccessibilityColorVisionDeficiency.TRITANOPIA; + default: return AccessibilityColorVisionDeficiency.UNKNOWN; + } + } catch (Throwable t) { + return AccessibilityColorVisionDeficiency.UNKNOWN; + } + } + + @Override + public boolean isReduceMotionEnabled() { + try { + return Settings.Global.getFloat(getContext().getContentResolver(), + Settings.Global.ANIMATOR_DURATION_SCALE, 1f) == 0f; + } catch (Throwable t) { + return false; + } + } + + @Override + public boolean isBoldTextEnabled() { + try { + Object value = Configuration.class.getField("fontWeightAdjustment") + .get(getContext().getResources().getConfiguration()); + return value instanceof Integer && ((Integer)value).intValue() >= 300; + } catch (Throwable t) { + return false; + } + } + + @Override + public boolean isInvertColorsEnabled() { + return secureSettingEnabled("accessibility_display_inversion_enabled"); + } + + @Override + public boolean isGrayscaleEnabled() { + return getColorVisionDeficiency() == AccessibilityColorVisionDeficiency.MONOCHROMACY; + } + + @Override + public boolean isScreenReaderEnabled() { + try { + AccessibilityManager manager = (AccessibilityManager)getContext() + .getSystemService(Context.ACCESSIBILITY_SERVICE); + return manager != null && manager.isEnabled() && manager.isTouchExplorationEnabled(); + } catch (Throwable t) { + return false; + } + } + + private boolean secureSettingEnabled(String key) { + try { + return Settings.Secure.getInt(getContext().getContentResolver(), key, 0) == 1; + } catch (Throwable t) { + return false; + } + } + @Override public void accessibilityTreeChanged(final int changeType) { final Activity act = getActivity(); diff --git a/Ports/JavaSE/src/com/codename1/impl/javase/ComponentTreeInspector.java b/Ports/JavaSE/src/com/codename1/impl/javase/ComponentTreeInspector.java index 4cd8bbcfad2..c5738bf3af0 100644 --- a/Ports/JavaSE/src/com/codename1/impl/javase/ComponentTreeInspector.java +++ b/Ports/JavaSE/src/com/codename1/impl/javase/ComponentTreeInspector.java @@ -109,6 +109,31 @@ public JFrame showInFrame() { frame.setVisible(true); return frame; } + + /** Audits the current form and displays the result. */ + public void showAccessibilityAudit() { + com.codename1.ui.CN.callSerially(new Runnable() { + public void run() { + Form form = Display.getInstance().getCurrent(); + if (form == null) return; + AccessibilityTreeSnapshot snapshot = AccessibilityInspector.snapshot(form); + final List issues = AccessibilityAssertions.audit(snapshot); + final StringBuilder message = new StringBuilder(); + for (AccessibilityIssue issue : issues) { + if (message.length() > 0) message.append('\n'); + message.append(issue.toString()); + } + SwingUtilities.invokeLater(new Runnable() { + public void run() { + JOptionPane.showMessageDialog(ComponentTreeInspector.this, + issues.isEmpty() ? "No accessibility issues found" : message.toString(), + "Accessibility Audit", issues.isEmpty() + ? JOptionPane.INFORMATION_MESSAGE : JOptionPane.WARNING_MESSAGE); + } + }); + } + }); + } public void dispose() { if (frame != null) { @@ -208,27 +233,7 @@ public void run() { JMenuItem auditAccessibilityTree = new JMenuItem("Audit Accessibility Tree"); auditAccessibilityTree.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { - com.codename1.ui.CN.callSerially(new Runnable() { - public void run() { - Form form = Display.getInstance().getCurrent(); - if (form == null) return; - AccessibilityTreeSnapshot snapshot = AccessibilityInspector.snapshot(form); - final List issues = AccessibilityAssertions.audit(snapshot); - final StringBuilder message = new StringBuilder(); - for (AccessibilityIssue issue : issues) { - if (message.length() > 0) message.append('\n'); - message.append(issue.toString()); - } - SwingUtilities.invokeLater(new Runnable() { - public void run() { - JOptionPane.showMessageDialog(ComponentTreeInspector.this, - issues.isEmpty() ? "No accessibility issues found" : message.toString(), - "Accessibility Audit", issues.isEmpty() - ? JOptionPane.INFORMATION_MESSAGE : JOptionPane.WARNING_MESSAGE); - } - }); - } - }); + showAccessibilityAudit(); } }); contextMenu.add(auditAccessibilityTree); diff --git a/Ports/JavaSE/src/com/codename1/impl/javase/Executor.java b/Ports/JavaSE/src/com/codename1/impl/javase/Executor.java index bc57753c841..80badf36737 100644 --- a/Ports/JavaSE/src/com/codename1/impl/javase/Executor.java +++ b/Ports/JavaSE/src/com/codename1/impl/javase/Executor.java @@ -76,7 +76,9 @@ public class Executor { String n = System.getProperty("os.name"); if (n != null && n.startsWith("Mac")) { IS_MAC = true; - System.setProperty("apple.laf.useScreenMenuBar", "true"); + if (System.getProperty("apple.laf.useScreenMenuBar") == null) { + System.setProperty("apple.laf.useScreenMenuBar", "true"); + } System.setProperty("com.apple.mrj.application.apple.menu.about.name", "Codename One GUIBuilder"); System.setProperty("apple.eawt.quitStrategy", "CLOSE_ALL_WINDOWS"); } else { diff --git a/Ports/JavaSE/src/com/codename1/impl/javase/JavaSEAccessibility.java b/Ports/JavaSE/src/com/codename1/impl/javase/JavaSEAccessibility.java index 312f410681e..14b60cf0e62 100644 --- a/Ports/JavaSE/src/com/codename1/impl/javase/JavaSEAccessibility.java +++ b/Ports/JavaSE/src/com/codename1/impl/javase/JavaSEAccessibility.java @@ -1,24 +1,5 @@ /* - * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Codename One designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Codename One through http://www.codenameone.com/ if you - * need additional information or have any questions. + * Copyright (c) 2026 Codename One and contributors. All rights reserved. */ package com.codename1.impl.javase; diff --git a/Ports/JavaSE/src/com/codename1/impl/javase/JavaSEPort.java b/Ports/JavaSE/src/com/codename1/impl/javase/JavaSEPort.java index e9572232cfd..ed137c4dbfa 100644 --- a/Ports/JavaSE/src/com/codename1/impl/javase/JavaSEPort.java +++ b/Ports/JavaSE/src/com/codename1/impl/javase/JavaSEPort.java @@ -39,6 +39,7 @@ import com.codename1.payment.PromotionalOffer; import com.codename1.printing.PrintResult; import com.codename1.printing.PrintResultListener; +import com.codename1.ui.AccessibilityColorVisionDeficiency; import com.codename1.ui.Component; import com.codename1.ui.Display; import com.codename1.ui.Font; @@ -235,6 +236,17 @@ public class JavaSEPort extends CodenameOneImplementation { // font scaling, so the Larger Text menu only nags them a single time per session. private boolean largerTextOptInWarningShown = false; private static final String PREF_LARGER_TEXT_SCALE = "cn1.simulator.largerTextScale"; + private static final String PREF_ACCESSIBILITY_PREFIX = "cn1.simulator.accessibility."; + private boolean highContrastEnabled; + private boolean differentiateWithoutColorEnabled; + private boolean reduceMotionEnabled; + private boolean reduceTransparencyEnabled; + private boolean boldTextEnabled; + private boolean invertColorsEnabled; + private boolean grayscaleEnabled; + private boolean onOffSwitchLabelsEnabled; + private boolean screenReaderEnabled; + private AccessibilityColorVisionDeficiency colorVisionDeficiency = AccessibilityColorVisionDeficiency.NONE; // Floor below which any persisted window dimension is treated as the // product of a layout glitch (eg. a pack() with a collapsed canvas, an @@ -611,7 +623,9 @@ public static double getRetinaScale() { IS_MAC = false; } isWindows = File.separatorChar == '\\'; - System.setProperty("apple.laf.useScreenMenuBar", "true"); + if (System.getProperty("apple.laf.useScreenMenuBar") == null) { + System.setProperty("apple.laf.useScreenMenuBar", "true"); + } if(isWindows) { fontFaceSystem = "ArialUnicodeMS"; @@ -2880,7 +2894,9 @@ private boolean drawScreenBuffer(java.awt.Graphics g) { } if (isEnabled()) { - g.drawImage(buffer, (int) ((getScreenCoordinates().getX() + x) * zoomLevel), (int) ((getScreenCoordinates().getY() + y) * zoomLevel), this); + g.drawImage(accessibilityFilteredImage(buffer), + (int) ((getScreenCoordinates().getX() + x) * zoomLevel), + (int) ((getScreenCoordinates().getY() + y) * zoomLevel), this); } else { g.setColor(Color.WHITE); g.fillRect(x + (int) (getSkin().getWidth() * zoomLevel), y, getWidth(), getHeight()); @@ -2933,7 +2949,7 @@ private boolean drawScreenBuffer(java.awt.Graphics g) { bg.dispose(); painted = true; } - g.drawImage(buffer, x, y, this); + g.drawImage(accessibilityFilteredImage(buffer), x, y, this); } ((Graphics2D)g).setTransform(t); return painted; @@ -6409,6 +6425,7 @@ public void actionPerformed(ActionEvent e) { }); final JMenu largerTextMenu = installLargerTextMenu(simulateMenu, pref, frm); + final JMenu accessibilityPreferencesMenu = installAccessibilityPreferencesMenu(pref); final JMenu notificationBackgroundMenu = installNotificationBackgroundSimulationMenu(simulateMenu); @@ -6619,6 +6636,7 @@ public void actionPerformed(ActionEvent e) { simulateMenu.addSeparator(); simulateMenu.add(darkLightModeMenu); simulateMenu.add(largerTextMenu); + simulateMenu.add(accessibilityPreferencesMenu); simulateMenu.add(purchaseMenu); simulateMenu.add(permFlag); simulateMenu.add(notificationBackgroundMenu); @@ -7576,6 +7594,113 @@ public void actionPerformed(ActionEvent e) { return largerTextMenu; } + private JMenu installAccessibilityPreferencesMenu(final Preferences pref) { + highContrastEnabled = pref.getBoolean(PREF_ACCESSIBILITY_PREFIX + "highContrast", false); + differentiateWithoutColorEnabled = pref.getBoolean( + PREF_ACCESSIBILITY_PREFIX + "differentiateWithoutColor", false); + reduceMotionEnabled = pref.getBoolean(PREF_ACCESSIBILITY_PREFIX + "reduceMotion", false); + reduceTransparencyEnabled = pref.getBoolean(PREF_ACCESSIBILITY_PREFIX + "reduceTransparency", false); + boldTextEnabled = pref.getBoolean(PREF_ACCESSIBILITY_PREFIX + "boldText", false); + invertColorsEnabled = pref.getBoolean(PREF_ACCESSIBILITY_PREFIX + "invertColors", false); + grayscaleEnabled = pref.getBoolean(PREF_ACCESSIBILITY_PREFIX + "grayscale", false); + onOffSwitchLabelsEnabled = pref.getBoolean(PREF_ACCESSIBILITY_PREFIX + "switchLabels", false); + screenReaderEnabled = pref.getBoolean(PREF_ACCESSIBILITY_PREFIX + "screenReader", false); + try { + colorVisionDeficiency = AccessibilityColorVisionDeficiency.valueOf( + pref.get(PREF_ACCESSIBILITY_PREFIX + "colorVision", + AccessibilityColorVisionDeficiency.NONE.name())); + } catch (IllegalArgumentException ex) { + colorVisionDeficiency = AccessibilityColorVisionDeficiency.NONE; + } + + JMenu menu = new JMenu("Accessibility Preferences"); + registerMenuWithBlit(menu); + menu.add(accessibilityPreferenceItem("High Contrast", highContrastEnabled, pref, "highContrast", 0)); + menu.add(accessibilityPreferenceItem("Differentiate Without Color", + differentiateWithoutColorEnabled, pref, "differentiateWithoutColor", 1)); + menu.add(createColorVisionMenu(pref)); + menu.addSeparator(); + menu.add(accessibilityPreferenceItem("Reduce Motion", reduceMotionEnabled, pref, "reduceMotion", 2)); + menu.add(accessibilityPreferenceItem("Reduce Transparency", reduceTransparencyEnabled, + pref, "reduceTransparency", 3)); + menu.add(accessibilityPreferenceItem("Bold Text", boldTextEnabled, pref, "boldText", 4)); + menu.add(accessibilityPreferenceItem("Invert Colors", invertColorsEnabled, pref, "invertColors", 5)); + menu.add(accessibilityPreferenceItem("Grayscale", grayscaleEnabled, pref, "grayscale", 6)); + menu.add(accessibilityPreferenceItem("On/Off Switch Labels", onOffSwitchLabelsEnabled, + pref, "switchLabels", 7)); + menu.add(accessibilityPreferenceItem("Screen Reader Active", screenReaderEnabled, + pref, "screenReader", 8)); + return menu; + } + + private JCheckBoxMenuItem accessibilityPreferenceItem(String label, boolean selected, + final Preferences pref, final String key, final int preference) { + final JCheckBoxMenuItem item = new JCheckBoxMenuItem(label, selected); + item.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent event) { + setSimulatorAccessibilityPreference(preference, item.isSelected()); + pref.putBoolean(PREF_ACCESSIBILITY_PREFIX + key, item.isSelected()); + refreshThemeOnly(); + canvas.repaint(); + } + }); + return item; + } + + private JMenu createColorVisionMenu(final Preferences pref) { + JMenu menu = new JMenu("Color Vision"); + ButtonGroup group = new ButtonGroup(); + AccessibilityColorVisionDeficiency[] modes = { + AccessibilityColorVisionDeficiency.NONE, + AccessibilityColorVisionDeficiency.PROTANOPIA, + AccessibilityColorVisionDeficiency.DEUTERANOPIA, + AccessibilityColorVisionDeficiency.TRITANOPIA, + AccessibilityColorVisionDeficiency.MONOCHROMACY + }; + String[] labels = {"None", "Protanopia", "Deuteranopia", "Tritanopia", "Monochromacy"}; + for (int i = 0; i < modes.length; i++) { + final AccessibilityColorVisionDeficiency mode = modes[i]; + JRadioButtonMenuItem item = new JRadioButtonMenuItem(labels[i], colorVisionDeficiency == mode); + item.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent event) { + colorVisionDeficiency = mode; + pref.put(PREF_ACCESSIBILITY_PREFIX + "colorVision", mode.name()); + canvas.repaint(); + } + }); + group.add(item); + menu.add(item); + } + return menu; + } + + /// Sets a simulated accessibility preference. This is primarily intended for + /// automated simulator tests. Preference indexes follow the menu order. + public void setSimulatorAccessibilityPreference(int preference, boolean enabled) { + switch (preference) { + case 0: highContrastEnabled = enabled; break; + case 1: differentiateWithoutColorEnabled = enabled; break; + case 2: reduceMotionEnabled = enabled; break; + case 3: reduceTransparencyEnabled = enabled; break; + case 4: boldTextEnabled = enabled; break; + case 5: invertColorsEnabled = enabled; break; + case 6: grayscaleEnabled = enabled; break; + case 7: onOffSwitchLabelsEnabled = enabled; break; + case 8: screenReaderEnabled = enabled; break; + default: throw new IllegalArgumentException("Unknown accessibility preference: " + preference); + } + } + + /// Sets the simulator's color-vision filter. + public void setSimulatorColorVisionDeficiency(AccessibilityColorVisionDeficiency deficiency) { + colorVisionDeficiency = deficiency == null ? AccessibilityColorVisionDeficiency.NONE : deficiency; + if (canvas != null) { + canvas.repaint(); + } + } + /// The Larger Text menu only changes the on-screen fonts when the running app /// has opted into font scaling -- either through the `useLargerTextScaleBool` /// theme constant or a `UIManager.setUseLargerTextScale(true)` call at startup. @@ -8091,6 +8216,111 @@ public float getLargerTextScale() { return largerTextScale; } + @Override + public boolean isHighContrastEnabled() { + return highContrastEnabled; + } + + @Override + public boolean isDifferentiateWithoutColorEnabled() { + return differentiateWithoutColorEnabled; + } + + @Override + public AccessibilityColorVisionDeficiency getColorVisionDeficiency() { + return colorVisionDeficiency; + } + + @Override + public boolean isReduceMotionEnabled() { + return reduceMotionEnabled; + } + + @Override + public boolean isReduceTransparencyEnabled() { + return reduceTransparencyEnabled; + } + + @Override + public boolean isBoldTextEnabled() { + return boldTextEnabled; + } + + @Override + public boolean isInvertColorsEnabled() { + return invertColorsEnabled; + } + + @Override + public boolean isGrayscaleEnabled() { + return grayscaleEnabled || colorVisionDeficiency == AccessibilityColorVisionDeficiency.MONOCHROMACY; + } + + @Override + public boolean isOnOffSwitchLabelsEnabled() { + return onOffSwitchLabelsEnabled; + } + + @Override + public boolean isScreenReaderEnabled() { + return screenReaderEnabled; + } + + private BufferedImage accessibilityFilteredImage(BufferedImage source) { + boolean monochrome = grayscaleEnabled + || colorVisionDeficiency == AccessibilityColorVisionDeficiency.MONOCHROMACY; + if (!invertColorsEnabled && !monochrome + && (colorVisionDeficiency == AccessibilityColorVisionDeficiency.NONE + || colorVisionDeficiency == AccessibilityColorVisionDeficiency.UNKNOWN)) { + return source; + } + BufferedImage result = new BufferedImage(source.getWidth(), source.getHeight(), BufferedImage.TYPE_INT_ARGB); + int width = source.getWidth(); + int height = source.getHeight(); + int[] pixels = source.getRGB(0, 0, width, height, null, 0, width); + for (int i = 0; i < pixels.length; i++) { + int argb = pixels[i]; + int transformed = transformAccessibilityColor( + (argb >>> 16) & 0xFF, (argb >>> 8) & 0xFF, argb & 0xFF, monochrome); + if (invertColorsEnabled) { + transformed = 0xFFFFFF ^ transformed; + } + pixels[i] = (argb & 0xFF000000) | transformed; + } + result.setRGB(0, 0, width, height, pixels, 0, width); + return result; + } + + private int transformAccessibilityColor(int red, int green, int blue, boolean monochrome) { + if (monochrome) { + int gray = clampColor(0.299 * red + 0.587 * green + 0.114 * blue); + return (gray << 16) | (gray << 8) | gray; + } + switch (colorVisionDeficiency) { + case PROTANOPIA: + return colorMatrix(red, green, blue, .567, .433, 0, .558, .442, 0, 0, .242, .758); + case DEUTERANOPIA: + return colorMatrix(red, green, blue, .625, .375, 0, .7, .3, 0, 0, .3, .7); + case TRITANOPIA: + return colorMatrix(red, green, blue, .95, .05, 0, 0, .433, .567, 0, .475, .525); + default: + return (red << 16) | (green << 8) | blue; + } + } + + private int colorMatrix(int red, int green, int blue, + double rr, double rg, double rb, double gr, double gg, double gb, + double br, double bg, double bb) { + int transformedRed = clampColor(rr * red + rg * green + rb * blue); + int transformedGreen = clampColor(gr * red + gg * green + gb * blue); + int transformedBlue = clampColor(br * red + bg * green + bb * blue); + return (transformedRed << 16) | (transformedGreen << 8) | transformedBlue; + } + + private int clampColor(double value) { + return Math.max(0, Math.min(255, (int) Math.round(value))); + } + private void refreshSkin(final JFrame frm) { Display.getInstance().callSerially(new Runnable() { diff --git a/Ports/JavaScriptPort/src/main/java/com/codename1/impl/html5/HTML5Implementation.java b/Ports/JavaScriptPort/src/main/java/com/codename1/impl/html5/HTML5Implementation.java index 9fb7ee00561..bab2b2bbb98 100644 --- a/Ports/JavaScriptPort/src/main/java/com/codename1/impl/html5/HTML5Implementation.java +++ b/Ports/JavaScriptPort/src/main/java/com/codename1/impl/html5/HTML5Implementation.java @@ -59,6 +59,7 @@ import com.codename1.teavm.jso.util.JSDateFormat; import com.codename1.teavm.jso.util.JSNumberFormat; import com.codename1.ui.Accessor; +import com.codename1.ui.AccessibilityColorVisionDeficiency; import com.codename1.ui.BrowserComponent; import com.codename1.ui.BrowserWindow; import com.codename1.ui.Button; @@ -10810,6 +10811,35 @@ public boolean requiresHeavyButtonForCopyToClipboard() { public Boolean isDarkMode() { return isDarkMode_(); } + + @JSBody(params={"query"}, script="return !!(window.matchMedia && window.matchMedia(query).matches);") + private static native boolean matchesMediaQuery(String query); + + @Override + public boolean isHighContrastEnabled() { + return matchesMediaQuery("(forced-colors: active)") + || matchesMediaQuery("(prefers-contrast: more)"); + } + + @Override + public boolean isDifferentiateWithoutColorEnabled() { + return matchesMediaQuery("(forced-colors: active)"); + } + + @Override + public AccessibilityColorVisionDeficiency getColorVisionDeficiency() { + return AccessibilityColorVisionDeficiency.UNKNOWN; + } + + @Override + public boolean isReduceMotionEnabled() { + return matchesMediaQuery("(prefers-reduced-motion: reduce)"); + } + + @Override + public boolean isReduceTransparencyEnabled() { + return matchesMediaQuery("(prefers-reduced-transparency: reduce)"); + } diff --git a/Ports/LinuxPort/src/com/codename1/impl/linux/LinuxImplementation.java b/Ports/LinuxPort/src/com/codename1/impl/linux/LinuxImplementation.java index 53a4fc02dcb..9e50ad5f092 100644 --- a/Ports/LinuxPort/src/com/codename1/impl/linux/LinuxImplementation.java +++ b/Ports/LinuxPort/src/com/codename1/impl/linux/LinuxImplementation.java @@ -70,6 +70,23 @@ * headless (see {@code Ports/LinuxPort/status.md}).

*/ public class LinuxImplementation extends CodenameOneImplementation { + + @Override + public boolean isHighContrastEnabled() { + String theme = System.getenv("GTK_THEME"); + return theme != null && theme.toLowerCase().indexOf("highcontrast") >= 0; + } + + @Override + public boolean isReduceMotionEnabled() { + return "0".equals(System.getenv("GTK_ENABLE_ANIMATIONS")); + } + + @Override + public boolean isScreenReaderEnabled() { + String modules = System.getenv("GTK_MODULES"); + return modules != null && (modules.indexOf("atk-bridge") >= 0 || modules.indexOf("gail") >= 0); + } private static LinuxImplementation INSTANCE; // Event type codes; must mirror the CN1EventType enum in cn1_linux.h. diff --git a/Ports/WindowsPort/nativeSources/cn1_windows_accessibility.cpp b/Ports/WindowsPort/nativeSources/cn1_windows_accessibility.cpp index 4dd96c2f93a..027faafd32d 100644 --- a/Ports/WindowsPort/nativeSources/cn1_windows_accessibility.cpp +++ b/Ports/WindowsPort/nativeSources/cn1_windows_accessibility.cpp @@ -1,24 +1,5 @@ /* - * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Codename One designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Codename One through http://www.codenameone.com/ if you - * need additional information or have any questions. + * Copyright (c) 2026 Codename One and contributors. All rights reserved. */ /* Native virtual accessibility tree for the lightweight Win32 port. */ diff --git a/Ports/WindowsPort/nativeSources/cn1_windows_window.cpp b/Ports/WindowsPort/nativeSources/cn1_windows_window.cpp index 94dd27557e2..3c851592b15 100644 --- a/Ports/WindowsPort/nativeSources/cn1_windows_window.cpp +++ b/Ports/WindowsPort/nativeSources/cn1_windows_window.cpp @@ -867,6 +867,29 @@ JAVA_BOOLEAN com_codename1_impl_windows_WindowsNative_isTouchDevice___R_boolean( return JAVA_FALSE; } +JAVA_BOOLEAN com_codename1_impl_windows_WindowsNative_isHighContrastEnabled___R_boolean(CODENAME_ONE_THREAD_STATE) { + HIGHCONTRASTW contrast = {}; + contrast.cbSize = sizeof(contrast); + if (!SystemParametersInfoW(SPI_GETHIGHCONTRAST, sizeof(contrast), &contrast, 0)) return JAVA_FALSE; + return (contrast.dwFlags & HCF_HIGHCONTRASTON) != 0 ? JAVA_TRUE : JAVA_FALSE; +} + +JAVA_BOOLEAN com_codename1_impl_windows_WindowsNative_isReduceMotionEnabled___R_boolean(CODENAME_ONE_THREAD_STATE) { +#ifdef SPI_GETCLIENTAREAANIMATION + BOOL animationsEnabled = TRUE; + if (!SystemParametersInfoW(SPI_GETCLIENTAREAANIMATION, 0, &animationsEnabled, 0)) return JAVA_FALSE; + return animationsEnabled ? JAVA_FALSE : JAVA_TRUE; +#else + return JAVA_FALSE; +#endif +} + +JAVA_BOOLEAN com_codename1_impl_windows_WindowsNative_isScreenReaderEnabled___R_boolean(CODENAME_ONE_THREAD_STATE) { + BOOL screenReader = FALSE; + if (!SystemParametersInfoW(SPI_GETSCREENREADER, 0, &screenReader, 0)) return JAVA_FALSE; + return screenReader ? JAVA_TRUE : JAVA_FALSE; +} + JAVA_INT com_codename1_impl_windows_WindowsNative_getDisplayHeight___R_int(CODENAME_ONE_THREAD_STATE) { return cn1Win.height; } diff --git a/Ports/WindowsPort/src/com/codename1/impl/windows/WindowsImplementation.java b/Ports/WindowsPort/src/com/codename1/impl/windows/WindowsImplementation.java index 763515be459..45ed71cc1c0 100644 --- a/Ports/WindowsPort/src/com/codename1/impl/windows/WindowsImplementation.java +++ b/Ports/WindowsPort/src/com/codename1/impl/windows/WindowsImplementation.java @@ -61,6 +61,21 @@ * minimal in this first cut and grow in later phases.

*/ public class WindowsImplementation extends CodenameOneImplementation { + + @Override + public boolean isHighContrastEnabled() { + return WindowsNative.isHighContrastEnabled(); + } + + @Override + public boolean isReduceMotionEnabled() { + return WindowsNative.isReduceMotionEnabled(); + } + + @Override + public boolean isScreenReaderEnabled() { + return WindowsNative.isScreenReaderEnabled(); + } private static WindowsImplementation INSTANCE; // Event type codes; must mirror the CN1EventType enum in cn1_windows.h. diff --git a/Ports/WindowsPort/src/com/codename1/impl/windows/WindowsNative.java b/Ports/WindowsPort/src/com/codename1/impl/windows/WindowsNative.java index 8d6d1d041e9..24f363c83d3 100644 --- a/Ports/WindowsPort/src/com/codename1/impl/windows/WindowsNative.java +++ b/Ports/WindowsPort/src/com/codename1/impl/windows/WindowsNative.java @@ -156,6 +156,12 @@ public static native void accessibilityNode(long id, long parentId, String role, */ public static native boolean isTouchDevice(); + public static native boolean isHighContrastEnabled(); + + public static native boolean isReduceMotionEnabled(); + + public static native boolean isScreenReaderEnabled(); + /** * Parks the calling (main) thread to keep the process alive in headless * screenshot mode, where there is no window message loop. The EDT exits the diff --git a/Ports/iOSPort/nativeSources/IOSNative.m b/Ports/iOSPort/nativeSources/IOSNative.m index 90a482a0573..2e5f2c7a8cf 100644 --- a/Ports/iOSPort/nativeSources/IOSNative.m +++ b/Ports/iOSPort/nativeSources/IOSNative.m @@ -5754,6 +5754,48 @@ JAVA_FLOAT com_codename1_impl_ios_IOSNative_getLargerTextScale___R_float(CN1_THR #endif // !TARGET_OS_WATCH && !TARGET_OS_TV } +JAVA_BOOLEAN com_codename1_impl_ios_IOSNative_isHighContrastEnabled___R_boolean(CN1_THREAD_STATE_MULTI_ARG JAVA_OBJECT instanceObject) { + return UIAccessibilityDarkerSystemColorsEnabled() ? 1 : 0; +} + +JAVA_BOOLEAN com_codename1_impl_ios_IOSNative_isDifferentiateWithoutColorEnabled___R_boolean(CN1_THREAD_STATE_MULTI_ARG JAVA_OBJECT instanceObject) { + if (@available(iOS 13.0, macCatalyst 13.1, *)) { + return UIAccessibilityShouldDifferentiateWithoutColor() ? 1 : 0; + } + return 0; +} + +JAVA_BOOLEAN com_codename1_impl_ios_IOSNative_isReduceMotionEnabled___R_boolean(CN1_THREAD_STATE_MULTI_ARG JAVA_OBJECT instanceObject) { + return UIAccessibilityIsReduceMotionEnabled() ? 1 : 0; +} + +JAVA_BOOLEAN com_codename1_impl_ios_IOSNative_isReduceTransparencyEnabled___R_boolean(CN1_THREAD_STATE_MULTI_ARG JAVA_OBJECT instanceObject) { + return UIAccessibilityIsReduceTransparencyEnabled() ? 1 : 0; +} + +JAVA_BOOLEAN com_codename1_impl_ios_IOSNative_isBoldTextEnabled___R_boolean(CN1_THREAD_STATE_MULTI_ARG JAVA_OBJECT instanceObject) { + return UIAccessibilityIsBoldTextEnabled() ? 1 : 0; +} + +JAVA_BOOLEAN com_codename1_impl_ios_IOSNative_isInvertColorsEnabled___R_boolean(CN1_THREAD_STATE_MULTI_ARG JAVA_OBJECT instanceObject) { + return UIAccessibilityIsInvertColorsEnabled() ? 1 : 0; +} + +JAVA_BOOLEAN com_codename1_impl_ios_IOSNative_isGrayscaleEnabled___R_boolean(CN1_THREAD_STATE_MULTI_ARG JAVA_OBJECT instanceObject) { + return UIAccessibilityIsGrayscaleEnabled() ? 1 : 0; +} + +JAVA_BOOLEAN com_codename1_impl_ios_IOSNative_isOnOffSwitchLabelsEnabled___R_boolean(CN1_THREAD_STATE_MULTI_ARG JAVA_OBJECT instanceObject) { + if (@available(iOS 13.0, macCatalyst 13.1, *)) { + return UIAccessibilityIsOnOffSwitchLabelsEnabled() ? 1 : 0; + } + return 0; +} + +JAVA_BOOLEAN com_codename1_impl_ios_IOSNative_isScreenReaderEnabled___R_boolean(CN1_THREAD_STATE_MULTI_ARG JAVA_OBJECT instanceObject) { + return UIAccessibilityIsVoiceOverRunning() ? 1 : 0; +} + #ifdef INCLUDE_LOCATION_USAGE CLLocationManager* com_codename1_impl_ios_IOSNative_createCLLocation = nil; #endif diff --git a/Ports/iOSPort/src/com/codename1/impl/ios/IOSImplementation.java b/Ports/iOSPort/src/com/codename1/impl/ios/IOSImplementation.java index 5f1454230bd..00187319f2b 100644 --- a/Ports/iOSPort/src/com/codename1/impl/ios/IOSImplementation.java +++ b/Ports/iOSPort/src/com/codename1/impl/ios/IOSImplementation.java @@ -1652,6 +1652,51 @@ public boolean isLargerTextEnabled() { public float getLargerTextScale() { return nativeInstance.getLargerTextScale(); } + + @Override + public boolean isHighContrastEnabled() { + return nativeInstance.isHighContrastEnabled(); + } + + @Override + public boolean isDifferentiateWithoutColorEnabled() { + return nativeInstance.isDifferentiateWithoutColorEnabled(); + } + + @Override + public boolean isReduceMotionEnabled() { + return nativeInstance.isReduceMotionEnabled(); + } + + @Override + public boolean isReduceTransparencyEnabled() { + return nativeInstance.isReduceTransparencyEnabled(); + } + + @Override + public boolean isBoldTextEnabled() { + return nativeInstance.isBoldTextEnabled(); + } + + @Override + public boolean isInvertColorsEnabled() { + return nativeInstance.isInvertColorsEnabled(); + } + + @Override + public boolean isGrayscaleEnabled() { + return nativeInstance.isGrayscaleEnabled(); + } + + @Override + public boolean isOnOffSwitchLabelsEnabled() { + return nativeInstance.isOnOffSwitchLabelsEnabled(); + } + + @Override + public boolean isScreenReaderEnabled() { + return nativeInstance.isScreenReaderEnabled(); + } public void flushGraphics() { diff --git a/Ports/iOSPort/src/com/codename1/impl/ios/IOSNative.java b/Ports/iOSPort/src/com/codename1/impl/ios/IOSNative.java index c935634bd14..ffe5f3b8f14 100644 --- a/Ports/iOSPort/src/com/codename1/impl/ios/IOSNative.java +++ b/Ports/iOSPort/src/com/codename1/impl/ios/IOSNative.java @@ -191,6 +191,15 @@ native void fillGradient(int kind, int stopCount, float[] positions, float[] pre native boolean isLargerTextEnabled(); native float getLargerTextScale(); + native boolean isHighContrastEnabled(); + native boolean isDifferentiateWithoutColorEnabled(); + native boolean isReduceMotionEnabled(); + native boolean isReduceTransparencyEnabled(); + native boolean isBoldTextEnabled(); + native boolean isInvertColorsEnabled(); + native boolean isGrayscaleEnabled(); + native boolean isOnOffSwitchLabelsEnabled(); + native boolean isScreenReaderEnabled(); // SJH Nov. 17, 2015 : Removing native isMinimized() method because it conflicted with // tracking on the java side. It caused the app to still be minimized inside start() diff --git a/docs/demos/common/src/main/java/com/codenameone/developerguide/snippets/AccessibilitySemanticsSnippets.java b/docs/demos/common/src/main/java/com/codenameone/developerguide/snippets/AccessibilitySemanticsSnippets.java index f86cd8e3f88..e24682da8be 100644 --- a/docs/demos/common/src/main/java/com/codenameone/developerguide/snippets/AccessibilitySemanticsSnippets.java +++ b/docs/demos/common/src/main/java/com/codenameone/developerguide/snippets/AccessibilitySemanticsSnippets.java @@ -1,28 +1,11 @@ /* - * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Codename One designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Codename One through http://www.codenameone.com/ if you - * need additional information or have any questions. + * Copyright (c) 2026 Codename One and contributors. All rights reserved. */ package com.codenameone.developerguide.snippets; import com.codename1.ui.Button; +import com.codename1.ui.AccessibilityColorVisionDeficiency; +import com.codename1.ui.CN; import com.codename1.ui.Component; import com.codename1.ui.Form; import com.codename1.ui.Label; @@ -165,9 +148,65 @@ public String inspect(Form myForm, int screenX, int screenY) { return diagnosticJson + (hit == null ? "" : hit.getLabel()); } + public void adaptToAccessibilityPreferences(Component animatedChart, Label connectionStatus) { + // tag::accessibility-preferences[] + if (CN.isHighContrastEnabled()) { + animatedChart.setUIID("HighContrastChart"); + } + + // Important state always uses text or an icon as well as color. The + // preference is an extra signal, not permission to use color alone. + if (CN.isDifferentiateWithoutColorEnabled() + || CN.getColorVisionDeficiency() != AccessibilityColorVisionDeficiency.NONE) { + connectionStatus.setText("Disconnected: action required"); + } + + if (CN.isReduceMotionEnabled()) { + animatedChart.putClientProperty("animate", Boolean.FALSE); + } + if (CN.isReduceTransparencyEnabled()) { + animatedChart.setUIID("OpaqueChart"); + } + // end::accessibility-preferences[] + } + + public void repairCustomControl(Component iconOnlyButton) { + // tag::accessibility-repair[] + iconOnlyButton.getSemantics() + .setRole(AccessibilityRole.BUTTON) + .setLabel("Delete message") + .setHint("Removes this message from the conversation") + .setIdentifier("message-delete") + .addAction(new AccessibilityAction( + AccessibilityAction.ACTIVATE, + null, + new AccessibilityAction.Handler() { + public boolean perform(Component component, Object argument) { + deleteMessage(); + return true; + } + })); + // end::accessibility-repair[] + } + + public void assertAccessibleForm(Form form) { + // tag::accessibility-regression-assertions[] + AccessibilityTreeSnapshot tree = AccessibilityInspector.snapshot(form); + AccessibilityAssertions.assertNoErrors(tree); + AccessibilityAssertions.assertNoUnlabeledInteractiveNodes(tree); + + AccessibilityNodeSnapshot save = tree.getNodeByIdentifier("profile-save"); + assert save.getRole() == AccessibilityRole.BUTTON; + assert save.getAction(AccessibilityAction.ACTIVATE) != null; + // end::accessibility-regression-assertions[] + } + private void archiveMessage() { } + private void deleteMessage() { + } + /** Minimal model contract used by the virtual-descendant example. */ public interface ChartPoint { String getId(); diff --git a/docs/developer-guide/Accessibility-Semantics.asciidoc b/docs/developer-guide/Accessibility-Semantics.asciidoc index ca3bb43edd5..b2fb44b2da8 100644 --- a/docs/developer-guide/Accessibility-Semantics.asciidoc +++ b/docs/developer-guide/Accessibility-Semantics.asciidoc @@ -83,6 +83,53 @@ include::../demos/common/src/main/java/com/codenameone/developerguide/snippets/A Form changes and nodes with a pane title produce screen or pane transition notifications. `Display.announceForAccessibility()` remains available for an exceptional announcement that isn't represented by persistent UI. Prefer a live region for state that's visible on screen. +== User accessibility preferences + +Semantics describe what a control means. Accessibility preferences describe how the user wants the interface presented. Read these preferences through `Display` or the matching static shortcuts in `CN`: + +[cols="2,3"] +|=== +|API |Meaning + +|`isHighContrastEnabled()` +|The user requests stronger foreground and background contrast. + +|`isDifferentiateWithoutColorEnabled()` +|The user requests labels, shapes, or patterns in addition to color. + +|`getColorVisionDeficiency()` +|Returns `NONE`, `PROTANOPIA`, `DEUTERANOPIA`, `TRITANOPIA`, `MONOCHROMACY`, or `UNKNOWN`. + +|`isReduceMotionEnabled()` +|Nonessential motion should be removed or replaced with an instant or cross-fade change. + +|`isReduceTransparencyEnabled()` +|Blur and translucent surfaces should use an opaque alternative. + +|`isBoldTextEnabled()` +|The system requests a heavier text weight. + +|`isInvertColorsEnabled()` and `isGrayscaleEnabled()` +|The operating system is transforming the displayed colors. + +|`isOnOffSwitchLabelsEnabled()` +|Switches should include a visible on/off distinction. + +|`isScreenReaderEnabled()` +|A screen reader or touch-exploration service is active. +|=== + +An unavailable preference returns `false`; an unavailable color-vision mode returns `UNKNOWN`. Don't hide accessibility support behind `isScreenReaderEnabled()`. A screen reader can start after the application launches, and other assistive technologies consume the same semantic tree. + +[source,java] +---- +include::../demos/common/src/main/java/com/codenameone/developerguide/snippets/AccessibilitySemanticsSnippets.java[tag=accessibility-preferences,indent=0] +---- + +IMPORTANT: Never use `getColorVisionDeficiency() == NONE` as permission to convey information only through color. The setting can be unavailable, a person might not enable a system filter, and contrast can change with lighting and display hardware. Design the default interface with redundant cues, then use preferences for further adaptation. + +Preference detection uses each platform's public signals. iOS and Mac Catalyst expose contrast, differentiate-without-color, motion, transparency, bold text, inversion, grayscale, switch labels, and VoiceOver; Apple doesn't expose the selected color-filter type, so the deficiency value is `UNKNOWN`. Android reads high-text contrast, display inversion and daltonizer mode, animation scale, font-weight adjustment, and touch exploration. Windows reads High Contrast, client-area animation, and screen-reader settings. Linux detects the GTK HighContrast theme, disabled GTK animation, and ATK bridge activation. JavaScript uses `forced-colors`, `prefers-contrast`, `prefers-reduced-motion`, and `prefers-reduced-transparency`. The Java SE simulator provides deterministic controls for every portable signal. + == Collections `AccessibilityCollectionInfo` describes row and column counts, hierarchy, and selection mode. `AccessibilityCollectionItemInfo` describes row and column index, spans, position and size in a set, nesting level, and header status. @@ -103,6 +150,48 @@ include::../demos/common/src/main/java/com/codenameone/developerguide/snippets/A The Java SE Component Inspector provides *Copy Accessibility Tree JSON* and *Audit Accessibility Tree* actions. Tests should assert resolved semantic properties instead of platform-specific spoken sentences. The `scripts/hellocodenameone` suite contains the cross-port conformance fixture used by native CI. +== Diagnosing and correcting an inaccessible screen + +Accessibility review works best as a repeatable loop instead of a final checklist: + +. Use the keyboard to reach every operation. Verify visible focus, logical order, escape from modal UI, and operation without pointer gestures. +. Open *Tools → Component Inspector*. Select the form or a suspicious component, then choose *Audit Accessibility Tree*. Start with errors, such as an unlabeled interactive node, invalid range, or unnamed dialog. +. Choose *Copy Accessibility Tree JSON* and inspect the resolved role, label, value, state, actions, bounds, and child order. This catches cases where the visual component hierarchy doesn't match the virtual accessibility hierarchy. +. Use *Simulate → Accessibility Preferences* to test high contrast, reduced motion, reduced transparency, inversion, grayscale, and each color-vision filter. Also test *Simulate → Larger Text* at Accessibility 5. Look for clipped text, color-only state, invisible focus, unreadable overlays, and motion that remains essential to understanding the result. +. Correct the component API or theme. Run the audit again, add a focused assertion, and verify the native screen reader before considering the issue closed. + +The simulator menu changes the values returned by `Display` and `CN`. Color-vision, inversion, and grayscale choices also filter the simulator canvas, so screenshots show approximately what remains distinguishable. These filters are diagnostic approximations; they don't replace testing with platform display filters or users. + +.Accessibility preferences in the Java SE simulator +image::accessibility-simulator-preferences.png[Java SE simulator with the Accessibility Preferences menu open,scaledwidth=80%] + +The following icon-only custom control is painted and responds to a pointer, but initially has no usable name, role, or keyboard-equivalent action. The audit reports it as an unlabeled interactive node. Repair the semantic contract at the custom-control boundary: + +[source,java] +---- +include::../demos/common/src/main/java/com/codenameone/developerguide/snippets/AccessibilitySemanticsSnippets.java[tag=accessibility-repair,indent=0] +---- + +Don't fix the warning by adding a label alone if the role, current state, range, or available actions are still wrong. For example, a custom switch needs `SWITCH`, checked state, and activation; a chart needs virtual descendants for its meaningful data points; a renderer-backed grid needs collection and item metadata. + +.Auditing the semantic tree in the Component Inspector +image::accessibility-component-inspector-audit.png[Component Inspector showing an accessibility audit,scaledwidth=80%] + +=== Assertions that prevent regressions + +Snapshot the finished form and assert behavior that matters to a user. Prefer stable identifiers and resolved semantics over implementation class names or platform-specific speech: + +[source,java] +---- +include::../demos/common/src/main/java/com/codenameone/developerguide/snippets/AccessibilitySemanticsSnippets.java[tag=accessibility-regression-assertions,indent=0] +---- + +Keep targeted assertions for traversal order, validation errors, live-region behavior, ranges, and stable virtual keys. The `scripts/hellocodenameone` accessibility fixture invokes every portable preference API and exercises the resolved semantic tree on each native CI platform. + +=== Native verification + +The simulator finds portable problems, but the final pass must use VoiceOver, TalkBack, Narrator, Orca, or the browser accessibility tree. Navigate in both directions, activate every action, change adjustable values, enter and leave collections, trigger errors, and confirm that focus moves sensibly after a dialog, navigation, deletion, or live update. Record the platform, assistive-technology version, input method, and failed semantic node in the bug report; attach the inspector JSON when the native result differs from the portable snapshot. + == Platform mappings [cols="1,2,2"] diff --git a/docs/developer-guide/img/accessibility-component-inspector-audit.png b/docs/developer-guide/img/accessibility-component-inspector-audit.png new file mode 100644 index 0000000000000000000000000000000000000000..923240ed932125f710d35c1c27bf50636a742a59 GIT binary patch literal 237174 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 UAG{=e?UTzEb{9#%-2Cl-0Hu-5?EnA( literal 0 HcmV?d00001 diff --git a/docs/developer-guide/img/accessibility-simulator-preferences.png b/docs/developer-guide/img/accessibility-simulator-preferences.png new file mode 100644 index 0000000000000000000000000000000000000000..01d578b5285f6feae94b9897d41bd76f71bbb399 GIT binary patch literal 430650 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

U=fIq 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 z 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

4fLGSN{ggMw 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 qo)_Rr+&P}xmRpLHPv5O})!xvX 0, + "larger-text scale is positive"); + + // Invoke every portable preference on every native CI target. The values + // legitimately depend on the host, but none of these calls may throw or + // require an initialized semantic tree. + Display.getInstance().isHighContrastEnabled(); + Display.getInstance().isDifferentiateWithoutColorEnabled(); + Display.getInstance().isReduceMotionEnabled(); + Display.getInstance().isReduceTransparencyEnabled(); + Display.getInstance().isBoldTextEnabled(); + Display.getInstance().isInvertColorsEnabled(); + Display.getInstance().isGrayscaleEnabled(); + Display.getInstance().isOnOffSwitchLabelsEnabled(); + Display.getInstance().isScreenReaderEnabled(); + + if (colorVision == AccessibilityColorVisionDeficiency.MONOCHROMACY) { + assertTrue(Display.getInstance().isGrayscaleEnabled(), + "monochromacy implies grayscale presentation"); + } + } + private T add(Container parent, T component, int x, int y, int width, int height) { parent.add(component); size(component, x, y, width, height); From 0eb6485af49c398a1e7b09101fb8452b249ed481 Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Sun, 12 Jul 2026 21:21:17 +0300 Subject: [PATCH 10/15] Keep Android contrast detection SDK-compatible --- .../impl/android/AndroidImplementation.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Ports/Android/src/com/codename1/impl/android/AndroidImplementation.java b/Ports/Android/src/com/codename1/impl/android/AndroidImplementation.java index 9b57c0ed51d..9c956ef6038 100644 --- a/Ports/Android/src/com/codename1/impl/android/AndroidImplementation.java +++ b/Ports/Android/src/com/codename1/impl/android/AndroidImplementation.java @@ -12947,12 +12947,16 @@ public boolean isHighContrastEnabled() { try { AccessibilityManager manager = (AccessibilityManager)getContext() .getSystemService(Context.ACCESSIBILITY_SERVICE); - return android.os.Build.VERSION.SDK_INT >= 21 && manager != null - && manager.isHighTextContrastEnabled(); + if (android.os.Build.VERSION.SDK_INT >= 21 && manager != null) { + Object enabled = AccessibilityManager.class.getMethod("isHighTextContrastEnabled") + .invoke(manager); + return enabled instanceof Boolean && ((Boolean)enabled).booleanValue(); + } } catch (Throwable t) { - return secureSettingEnabled("high_text_contrast_enabled") - || secureSettingEnabled("accessibility_display_high_text_contrast_enabled"); + // Fall through to the secure settings used by older Android stubs. } + return secureSettingEnabled("high_text_contrast_enabled") + || secureSettingEnabled("accessibility_display_high_text_contrast_enabled"); } @Override From 47bd9b7296fe83676afa03f5d5954744e54f73b1 Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Sun, 12 Jul 2026 21:32:25 +0300 Subject: [PATCH 11/15] Clarify Android color correction wording --- docs/developer-guide/Accessibility-Semantics.asciidoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/developer-guide/Accessibility-Semantics.asciidoc b/docs/developer-guide/Accessibility-Semantics.asciidoc index b2fb44b2da8..f586b9e7c19 100644 --- a/docs/developer-guide/Accessibility-Semantics.asciidoc +++ b/docs/developer-guide/Accessibility-Semantics.asciidoc @@ -128,7 +128,7 @@ include::../demos/common/src/main/java/com/codenameone/developerguide/snippets/A IMPORTANT: Never use `getColorVisionDeficiency() == NONE` as permission to convey information only through color. The setting can be unavailable, a person might not enable a system filter, and contrast can change with lighting and display hardware. Design the default interface with redundant cues, then use preferences for further adaptation. -Preference detection uses each platform's public signals. iOS and Mac Catalyst expose contrast, differentiate-without-color, motion, transparency, bold text, inversion, grayscale, switch labels, and VoiceOver; Apple doesn't expose the selected color-filter type, so the deficiency value is `UNKNOWN`. Android reads high-text contrast, display inversion and daltonizer mode, animation scale, font-weight adjustment, and touch exploration. Windows reads High Contrast, client-area animation, and screen-reader settings. Linux detects the GTK HighContrast theme, disabled GTK animation, and ATK bridge activation. JavaScript uses `forced-colors`, `prefers-contrast`, `prefers-reduced-motion`, and `prefers-reduced-transparency`. The Java SE simulator provides deterministic controls for every portable signal. +Preference detection uses each platform's public signals. iOS and Mac Catalyst expose contrast, differentiate-without-color, motion, transparency, bold text, inversion, grayscale, switch labels, and VoiceOver; Apple doesn't expose the selected color-filter type, so the deficiency value is `UNKNOWN`. Android reads high-text contrast, display inversion and color-correction mode, animation scale, font-weight adjustment, and touch exploration. Windows reads High Contrast, client-area animation, and screen-reader settings. Linux detects the GTK HighContrast theme, disabled GTK animation, and ATK bridge activation. JavaScript uses `forced-colors`, `prefers-contrast`, `prefers-reduced-motion`, and `prefers-reduced-transparency`. The Java SE simulator provides deterministic controls for every portable signal. == Collections From a72711aac2151a7e0a61665ddca1c963b1fc8669 Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Sun, 12 Jul 2026 21:43:52 +0300 Subject: [PATCH 12/15] Detect Linux accessibility settings natively --- .../nativeSources/cn1_linux_window.c | 19 +++++++++++++++++++ .../impl/linux/LinuxImplementation.java | 8 +++----- .../com/codename1/impl/linux/LinuxNative.java | 9 +++++++++ 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/Ports/LinuxPort/nativeSources/cn1_linux_window.c b/Ports/LinuxPort/nativeSources/cn1_linux_window.c index b21b0a0c3a4..198c129118e 100644 --- a/Ports/LinuxPort/nativeSources/cn1_linux_window.c +++ b/Ports/LinuxPort/nativeSources/cn1_linux_window.c @@ -648,6 +648,25 @@ JAVA_INT com_codename1_impl_linux_LinuxNative_screenDpi___R_int(CODENAME_ONE_THR return 96; } +JAVA_BOOLEAN com_codename1_impl_linux_LinuxNative_isHighContrastEnabled___R_boolean(CODENAME_ONE_THREAD_STATE) { + const char* theme = getenv("GTK_THEME"); + return theme != NULL && strcasestr(theme, "highcontrast") != NULL ? JAVA_TRUE : JAVA_FALSE; +} + +JAVA_BOOLEAN com_codename1_impl_linux_LinuxNative_isReduceMotionEnabled___R_boolean(CODENAME_ONE_THREAD_STATE) { + const char* animations = getenv("GTK_ENABLE_ANIMATIONS"); + return animations != NULL && strcmp(animations, "0") == 0 ? JAVA_TRUE : JAVA_FALSE; +} + +JAVA_BOOLEAN com_codename1_impl_linux_LinuxNative_isScreenReaderEnabled___R_boolean(CODENAME_ONE_THREAD_STATE) { + const char* modules = getenv("GTK_MODULES"); + if (modules == NULL) { + return JAVA_FALSE; + } + return strcasestr(modules, "atk-bridge") != NULL || strcasestr(modules, "gail") != NULL + ? JAVA_TRUE : JAVA_FALSE; +} + /* True when the default seat has a touchscreen pointing device attached, so the * framework reports a touch device (Display.isTouchScreen()). */ JAVA_BOOLEAN com_codename1_impl_linux_LinuxNative_isTouchDevice___R_boolean(CODENAME_ONE_THREAD_STATE) { diff --git a/Ports/LinuxPort/src/com/codename1/impl/linux/LinuxImplementation.java b/Ports/LinuxPort/src/com/codename1/impl/linux/LinuxImplementation.java index 9e50ad5f092..02ad6ae6848 100644 --- a/Ports/LinuxPort/src/com/codename1/impl/linux/LinuxImplementation.java +++ b/Ports/LinuxPort/src/com/codename1/impl/linux/LinuxImplementation.java @@ -73,19 +73,17 @@ public class LinuxImplementation extends CodenameOneImplementation { @Override public boolean isHighContrastEnabled() { - String theme = System.getenv("GTK_THEME"); - return theme != null && theme.toLowerCase().indexOf("highcontrast") >= 0; + return LinuxNative.isHighContrastEnabled(); } @Override public boolean isReduceMotionEnabled() { - return "0".equals(System.getenv("GTK_ENABLE_ANIMATIONS")); + return LinuxNative.isReduceMotionEnabled(); } @Override public boolean isScreenReaderEnabled() { - String modules = System.getenv("GTK_MODULES"); - return modules != null && (modules.indexOf("atk-bridge") >= 0 || modules.indexOf("gail") >= 0); + return LinuxNative.isScreenReaderEnabled(); } private static LinuxImplementation INSTANCE; diff --git a/Ports/LinuxPort/src/com/codename1/impl/linux/LinuxNative.java b/Ports/LinuxPort/src/com/codename1/impl/linux/LinuxNative.java index 820bc659a3a..95c5e4f36c2 100644 --- a/Ports/LinuxPort/src/com/codename1/impl/linux/LinuxNative.java +++ b/Ports/LinuxPort/src/com/codename1/impl/linux/LinuxNative.java @@ -125,6 +125,15 @@ public static native long videoWriterOpen(String outPath, boolean hevc, int widt /** Real horizontal screen DPI (96 == 100% scale). */ public static native int screenDpi(); + /** True when the GTK theme requests high contrast. */ + public static native boolean isHighContrastEnabled(); + + /** True when GTK animations are disabled. */ + public static native boolean isReduceMotionEnabled(); + + /** True when the GTK accessibility bridge is active. */ + public static native boolean isScreenReaderEnabled(); + /** The window's graphics peer (a Direct2D render target wrapper). */ public static native long getWindowGraphics(); From 7c63c780ce6e59fa485a572f51d3db86e850237c Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Mon, 13 Jul 2026 04:06:44 +0300 Subject: [PATCH 13/15] Fix accessibility CI regressions --- .../android/AndroidAccessibilityProvider.java | 13 +++++- Ports/iOSPort/nativeSources/IOSNative.m | 42 +++++++++++++++++++ .../Accessibility-Semantics.asciidoc | 4 +- 3 files changed, 56 insertions(+), 3 deletions(-) diff --git a/Ports/Android/src/com/codename1/impl/android/AndroidAccessibilityProvider.java b/Ports/Android/src/com/codename1/impl/android/AndroidAccessibilityProvider.java index 85e86a7d7ba..754d9cf6f8d 100644 --- a/Ports/Android/src/com/codename1/impl/android/AndroidAccessibilityProvider.java +++ b/Ports/Android/src/com/codename1/impl/android/AndroidAccessibilityProvider.java @@ -31,11 +31,14 @@ final class AndroidAccessibilityProvider extends AccessibilityNodeProvider { private static final String ROLE_DESCRIPTION_KEY = "AccessibilityNodeInfo.roleDescription"; private final View host; private final AndroidImplementation implementation; + private final android.view.accessibility.AccessibilityManager nativeAccessibilityManager; private int accessibilityFocusedId = Integer.MIN_VALUE; AndroidAccessibilityProvider(View host, AndroidImplementation implementation) { this.host = host; this.implementation = implementation; + nativeAccessibilityManager = (android.view.accessibility.AccessibilityManager) host.getContext() + .getSystemService(android.content.Context.ACCESSIBILITY_SERVICE); host.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES); } @@ -284,8 +287,16 @@ private void sendEvent(int virtualId, int type) { } private void send(AccessibilityEvent event) { + if (nativeAccessibilityManager == null || !nativeAccessibilityManager.isEnabled()) { + event.recycle(); + return; + } ViewParent parent = host.getParent(); - if (parent != null) parent.requestSendAccessibilityEvent(host, event); + if (parent != null) { + parent.requestSendAccessibilityEvent(host, event); + } else { + event.recycle(); + } } private void setBounds(AccessibilityNodeInfo info, AccessibilityNodeSnapshot node) { diff --git a/Ports/iOSPort/nativeSources/IOSNative.m b/Ports/iOSPort/nativeSources/IOSNative.m index 2e5f2c7a8cf..f87d9b1826d 100644 --- a/Ports/iOSPort/nativeSources/IOSNative.m +++ b/Ports/iOSPort/nativeSources/IOSNative.m @@ -5754,6 +5754,46 @@ JAVA_FLOAT com_codename1_impl_ios_IOSNative_getLargerTextScale___R_float(CN1_THR #endif // !TARGET_OS_WATCH && !TARGET_OS_TV } +#if TARGET_OS_WATCH + +JAVA_BOOLEAN com_codename1_impl_ios_IOSNative_isHighContrastEnabled___R_boolean(CN1_THREAD_STATE_MULTI_ARG JAVA_OBJECT instanceObject) { + return 0; +} + +JAVA_BOOLEAN com_codename1_impl_ios_IOSNative_isDifferentiateWithoutColorEnabled___R_boolean(CN1_THREAD_STATE_MULTI_ARG JAVA_OBJECT instanceObject) { + return 0; +} + +JAVA_BOOLEAN com_codename1_impl_ios_IOSNative_isReduceMotionEnabled___R_boolean(CN1_THREAD_STATE_MULTI_ARG JAVA_OBJECT instanceObject) { + return 0; +} + +JAVA_BOOLEAN com_codename1_impl_ios_IOSNative_isReduceTransparencyEnabled___R_boolean(CN1_THREAD_STATE_MULTI_ARG JAVA_OBJECT instanceObject) { + return 0; +} + +JAVA_BOOLEAN com_codename1_impl_ios_IOSNative_isBoldTextEnabled___R_boolean(CN1_THREAD_STATE_MULTI_ARG JAVA_OBJECT instanceObject) { + return 0; +} + +JAVA_BOOLEAN com_codename1_impl_ios_IOSNative_isInvertColorsEnabled___R_boolean(CN1_THREAD_STATE_MULTI_ARG JAVA_OBJECT instanceObject) { + return 0; +} + +JAVA_BOOLEAN com_codename1_impl_ios_IOSNative_isGrayscaleEnabled___R_boolean(CN1_THREAD_STATE_MULTI_ARG JAVA_OBJECT instanceObject) { + return 0; +} + +JAVA_BOOLEAN com_codename1_impl_ios_IOSNative_isOnOffSwitchLabelsEnabled___R_boolean(CN1_THREAD_STATE_MULTI_ARG JAVA_OBJECT instanceObject) { + return 0; +} + +JAVA_BOOLEAN com_codename1_impl_ios_IOSNative_isScreenReaderEnabled___R_boolean(CN1_THREAD_STATE_MULTI_ARG JAVA_OBJECT instanceObject) { + return 0; +} + +#else + JAVA_BOOLEAN com_codename1_impl_ios_IOSNative_isHighContrastEnabled___R_boolean(CN1_THREAD_STATE_MULTI_ARG JAVA_OBJECT instanceObject) { return UIAccessibilityDarkerSystemColorsEnabled() ? 1 : 0; } @@ -5796,6 +5836,8 @@ JAVA_BOOLEAN com_codename1_impl_ios_IOSNative_isScreenReaderEnabled___R_boolean( return UIAccessibilityIsVoiceOverRunning() ? 1 : 0; } +#endif // TARGET_OS_WATCH + #ifdef INCLUDE_LOCATION_USAGE CLLocationManager* com_codename1_impl_ios_IOSNative_createCLLocation = nil; #endif diff --git a/docs/developer-guide/Accessibility-Semantics.asciidoc b/docs/developer-guide/Accessibility-Semantics.asciidoc index f586b9e7c19..40b9e25915a 100644 --- a/docs/developer-guide/Accessibility-Semantics.asciidoc +++ b/docs/developer-guide/Accessibility-Semantics.asciidoc @@ -163,7 +163,7 @@ Accessibility review works best as a repeatable loop instead of a final checklis The simulator menu changes the values returned by `Display` and `CN`. Color-vision, inversion, and grayscale choices also filter the simulator canvas, so screenshots show approximately what remains distinguishable. These filters are diagnostic approximations; they don't replace testing with platform display filters or users. .Accessibility preferences in the Java SE simulator -image::accessibility-simulator-preferences.png[Java SE simulator with the Accessibility Preferences menu open,scaledwidth=80%] +image::img/accessibility-simulator-preferences.png[Java SE simulator with the Accessibility Preferences menu open,scaledwidth=80%] The following icon-only custom control is painted and responds to a pointer, but initially has no usable name, role, or keyboard-equivalent action. The audit reports it as an unlabeled interactive node. Repair the semantic contract at the custom-control boundary: @@ -175,7 +175,7 @@ include::../demos/common/src/main/java/com/codenameone/developerguide/snippets/A Don't fix the warning by adding a label alone if the role, current state, range, or available actions are still wrong. For example, a custom switch needs `SWITCH`, checked state, and activation; a chart needs virtual descendants for its meaningful data points; a renderer-backed grid needs collection and item metadata. .Auditing the semantic tree in the Component Inspector -image::accessibility-component-inspector-audit.png[Component Inspector showing an accessibility audit,scaledwidth=80%] +image::img/accessibility-component-inspector-audit.png[Component Inspector showing an accessibility audit,scaledwidth=80%] === Assertions that prevent regressions From 3f70eefdfbf85c1c4ac24edd374ec01f9065a45b Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Mon, 13 Jul 2026 05:55:39 +0300 Subject: [PATCH 14/15] Use standard Codename One copyright headers --- .../AccessibilityColorVisionDeficiency.java | 21 ++++++++++++++++++- .../ui/accessibility/AccessibilityAction.java | 21 ++++++++++++++++++- .../AccessibilityAssertions.java | 21 ++++++++++++++++++- .../AccessibilityCheckedState.java | 21 ++++++++++++++++++- .../AccessibilityChildProvider.java | 21 ++++++++++++++++++- .../AccessibilityCollectionInfo.java | 21 ++++++++++++++++++- .../AccessibilityCollectionItemInfo.java | 21 ++++++++++++++++++- .../accessibility/AccessibilityGrouping.java | 21 ++++++++++++++++++- .../accessibility/AccessibilityInspector.java | 21 ++++++++++++++++++- .../ui/accessibility/AccessibilityIssue.java | 21 ++++++++++++++++++- .../AccessibilityLiveRegion.java | 21 ++++++++++++++++++- .../accessibility/AccessibilityManager.java | 21 ++++++++++++++++++- .../ui/accessibility/AccessibilityNode.java | 21 ++++++++++++++++++- .../AccessibilityNodeSnapshot.java | 21 ++++++++++++++++++- .../ui/accessibility/AccessibilityRange.java | 21 ++++++++++++++++++- .../ui/accessibility/AccessibilityRole.java | 21 ++++++++++++++++++- .../AccessibilityTreeSnapshot.java | 21 ++++++++++++++++++- .../ui/accessibility/package-info.java | 21 ++++++++++++++++++- .../android/AndroidAccessibilityProvider.java | 21 ++++++++++++++++++- .../impl/javase/JavaSEAccessibility.java | 21 ++++++++++++++++++- .../cn1_windows_accessibility.cpp | 21 ++++++++++++++++++- .../AccessibilitySemanticsSnippets.java | 21 ++++++++++++++++++- .../AccessibilitySemanticsTest.java | 21 ++++++++++++++++++- 23 files changed, 460 insertions(+), 23 deletions(-) diff --git a/CodenameOne/src/com/codename1/ui/AccessibilityColorVisionDeficiency.java b/CodenameOne/src/com/codename1/ui/AccessibilityColorVisionDeficiency.java index d58d518765c..272fb497a6e 100644 --- a/CodenameOne/src/com/codename1/ui/AccessibilityColorVisionDeficiency.java +++ b/CodenameOne/src/com/codename1/ui/AccessibilityColorVisionDeficiency.java @@ -1,5 +1,24 @@ /* - * Copyright (c) 2026 Codename One and contributors. All rights reserved. + * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Codename One designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Codename One through http://www.codenameone.com/ if you + * need additional information or have any questions. */ package com.codename1.ui; diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityAction.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityAction.java index 9e6f67a542c..3333d3744f0 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityAction.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityAction.java @@ -1,5 +1,24 @@ /* - * Copyright (c) 2026 Codename One and contributors. All rights reserved. + * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Codename One designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Codename One through http://www.codenameone.com/ if you + * need additional information or have any questions. */ package com.codename1.ui.accessibility; diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityAssertions.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityAssertions.java index de532109434..4efdccfd37a 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityAssertions.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityAssertions.java @@ -1,5 +1,24 @@ /* - * Copyright (c) 2026 Codename One and contributors. All rights reserved. + * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Codename One designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Codename One through http://www.codenameone.com/ if you + * need additional information or have any questions. */ package com.codename1.ui.accessibility; diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityCheckedState.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityCheckedState.java index 4b99c355b7a..3d5fe63d714 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityCheckedState.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityCheckedState.java @@ -1,5 +1,24 @@ /* - * Copyright (c) 2026 Codename One and contributors. All rights reserved. + * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Codename One designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Codename One through http://www.codenameone.com/ if you + * need additional information or have any questions. */ package com.codename1.ui.accessibility; diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityChildProvider.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityChildProvider.java index a4cea03e026..752c68ae20e 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityChildProvider.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityChildProvider.java @@ -1,5 +1,24 @@ /* - * Copyright (c) 2026 Codename One and contributors. All rights reserved. + * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Codename One designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Codename One through http://www.codenameone.com/ if you + * need additional information or have any questions. */ package com.codename1.ui.accessibility; diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityCollectionInfo.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityCollectionInfo.java index e5d4b221a38..fad9b59733c 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityCollectionInfo.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityCollectionInfo.java @@ -1,5 +1,24 @@ /* - * Copyright (c) 2026 Codename One and contributors. All rights reserved. + * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Codename One designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Codename One through http://www.codenameone.com/ if you + * need additional information or have any questions. */ package com.codename1.ui.accessibility; diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityCollectionItemInfo.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityCollectionItemInfo.java index a511633e7cb..75910fb0579 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityCollectionItemInfo.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityCollectionItemInfo.java @@ -1,5 +1,24 @@ /* - * Copyright (c) 2026 Codename One and contributors. All rights reserved. + * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Codename One designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Codename One through http://www.codenameone.com/ if you + * need additional information or have any questions. */ package com.codename1.ui.accessibility; diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityGrouping.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityGrouping.java index 96c767ea489..26f200743e8 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityGrouping.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityGrouping.java @@ -1,5 +1,24 @@ /* - * Copyright (c) 2026 Codename One and contributors. All rights reserved. + * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Codename One designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Codename One through http://www.codenameone.com/ if you + * need additional information or have any questions. */ package com.codename1.ui.accessibility; diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityInspector.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityInspector.java index cea6ae8c0fb..4c7b5c50e3f 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityInspector.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityInspector.java @@ -1,5 +1,24 @@ /* - * Copyright (c) 2026 Codename One and contributors. All rights reserved. + * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Codename One designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Codename One through http://www.codenameone.com/ if you + * need additional information or have any questions. */ package com.codename1.ui.accessibility; diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityIssue.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityIssue.java index d80a0e764c9..cb05b8d6322 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityIssue.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityIssue.java @@ -1,5 +1,24 @@ /* - * Copyright (c) 2026 Codename One and contributors. All rights reserved. + * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Codename One designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Codename One through http://www.codenameone.com/ if you + * need additional information or have any questions. */ package com.codename1.ui.accessibility; diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityLiveRegion.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityLiveRegion.java index 46ac6b73350..2ce8d93e9f1 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityLiveRegion.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityLiveRegion.java @@ -1,5 +1,24 @@ /* - * Copyright (c) 2026 Codename One and contributors. All rights reserved. + * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Codename One designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Codename One through http://www.codenameone.com/ if you + * need additional information or have any questions. */ package com.codename1.ui.accessibility; diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityManager.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityManager.java index 88d78e3a236..aadb396c765 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityManager.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityManager.java @@ -1,5 +1,24 @@ /* - * Copyright (c) 2026 Codename One and contributors. All rights reserved. + * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Codename One designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Codename One through http://www.codenameone.com/ if you + * need additional information or have any questions. */ package com.codename1.ui.accessibility; diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityNode.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityNode.java index d3ba2e2e132..8346e09d678 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityNode.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityNode.java @@ -1,5 +1,24 @@ /* - * Copyright (c) 2026 Codename One and contributors. All rights reserved. + * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Codename One designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Codename One through http://www.codenameone.com/ if you + * need additional information or have any questions. */ package com.codename1.ui.accessibility; diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityNodeSnapshot.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityNodeSnapshot.java index 0b05e63f4b9..5cdbc9bb450 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityNodeSnapshot.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityNodeSnapshot.java @@ -1,5 +1,24 @@ /* - * Copyright (c) 2026 Codename One and contributors. All rights reserved. + * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Codename One designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Codename One through http://www.codenameone.com/ if you + * need additional information or have any questions. */ package com.codename1.ui.accessibility; diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityRange.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityRange.java index 5a6abbe34fb..2369bb71443 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityRange.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityRange.java @@ -1,5 +1,24 @@ /* - * Copyright (c) 2026 Codename One and contributors. All rights reserved. + * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Codename One designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Codename One through http://www.codenameone.com/ if you + * need additional information or have any questions. */ package com.codename1.ui.accessibility; diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityRole.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityRole.java index 7dffde79736..8349a6388e2 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityRole.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityRole.java @@ -1,5 +1,24 @@ /* - * Copyright (c) 2026 Codename One and contributors. All rights reserved. + * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Codename One designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Codename One through http://www.codenameone.com/ if you + * need additional information or have any questions. */ package com.codename1.ui.accessibility; diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityTreeSnapshot.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityTreeSnapshot.java index 1a1d7804a17..a55739ca874 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityTreeSnapshot.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityTreeSnapshot.java @@ -1,5 +1,24 @@ /* - * Copyright (c) 2026 Codename One and contributors. All rights reserved. + * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Codename One designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Codename One through http://www.codenameone.com/ if you + * need additional information or have any questions. */ package com.codename1.ui.accessibility; diff --git a/CodenameOne/src/com/codename1/ui/accessibility/package-info.java b/CodenameOne/src/com/codename1/ui/accessibility/package-info.java index 2168b0b820b..7857a86a70c 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/package-info.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/package-info.java @@ -1,5 +1,24 @@ /* - * Copyright (c) 2026 Codename One and contributors. All rights reserved. + * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Codename One designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Codename One through http://www.codenameone.com/ if you + * need additional information or have any questions. */ /// Defines the portable accessibility semantics tree for Codename One's diff --git a/Ports/Android/src/com/codename1/impl/android/AndroidAccessibilityProvider.java b/Ports/Android/src/com/codename1/impl/android/AndroidAccessibilityProvider.java index 754d9cf6f8d..b338bb7ead2 100644 --- a/Ports/Android/src/com/codename1/impl/android/AndroidAccessibilityProvider.java +++ b/Ports/Android/src/com/codename1/impl/android/AndroidAccessibilityProvider.java @@ -1,5 +1,24 @@ /* - * Copyright (c) 2026 Codename One and contributors. All rights reserved. + * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Codename One designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Codename One through http://www.codenameone.com/ if you + * need additional information or have any questions. */ package com.codename1.impl.android; diff --git a/Ports/JavaSE/src/com/codename1/impl/javase/JavaSEAccessibility.java b/Ports/JavaSE/src/com/codename1/impl/javase/JavaSEAccessibility.java index 14b60cf0e62..312f410681e 100644 --- a/Ports/JavaSE/src/com/codename1/impl/javase/JavaSEAccessibility.java +++ b/Ports/JavaSE/src/com/codename1/impl/javase/JavaSEAccessibility.java @@ -1,5 +1,24 @@ /* - * Copyright (c) 2026 Codename One and contributors. All rights reserved. + * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Codename One designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Codename One through http://www.codenameone.com/ if you + * need additional information or have any questions. */ package com.codename1.impl.javase; diff --git a/Ports/WindowsPort/nativeSources/cn1_windows_accessibility.cpp b/Ports/WindowsPort/nativeSources/cn1_windows_accessibility.cpp index 027faafd32d..4dd96c2f93a 100644 --- a/Ports/WindowsPort/nativeSources/cn1_windows_accessibility.cpp +++ b/Ports/WindowsPort/nativeSources/cn1_windows_accessibility.cpp @@ -1,5 +1,24 @@ /* - * Copyright (c) 2026 Codename One and contributors. All rights reserved. + * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Codename One designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Codename One through http://www.codenameone.com/ if you + * need additional information or have any questions. */ /* Native virtual accessibility tree for the lightweight Win32 port. */ diff --git a/docs/demos/common/src/main/java/com/codenameone/developerguide/snippets/AccessibilitySemanticsSnippets.java b/docs/demos/common/src/main/java/com/codenameone/developerguide/snippets/AccessibilitySemanticsSnippets.java index e24682da8be..6f2f962329e 100644 --- a/docs/demos/common/src/main/java/com/codenameone/developerguide/snippets/AccessibilitySemanticsSnippets.java +++ b/docs/demos/common/src/main/java/com/codenameone/developerguide/snippets/AccessibilitySemanticsSnippets.java @@ -1,5 +1,24 @@ /* - * Copyright (c) 2026 Codename One and contributors. All rights reserved. + * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Codename One designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Codename One through http://www.codenameone.com/ if you + * need additional information or have any questions. */ package com.codenameone.developerguide.snippets; diff --git a/maven/core-unittests/src/test/java/com/codename1/ui/accessibility/AccessibilitySemanticsTest.java b/maven/core-unittests/src/test/java/com/codename1/ui/accessibility/AccessibilitySemanticsTest.java index 18dff6bc29b..36f744b5063 100644 --- a/maven/core-unittests/src/test/java/com/codename1/ui/accessibility/AccessibilitySemanticsTest.java +++ b/maven/core-unittests/src/test/java/com/codename1/ui/accessibility/AccessibilitySemanticsTest.java @@ -1,5 +1,24 @@ /* - * Copyright (c) 2026 Codename One and contributors. All rights reserved. + * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Codename One designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Codename One through http://www.codenameone.com/ if you + * need additional information or have any questions. */ package com.codename1.ui.accessibility; From fa0e04b6eb14e2c9b77834e3daebb55690056071 Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Mon, 13 Jul 2026 09:05:47 +0300 Subject: [PATCH 15/15] Avoid eager accessibility tree rebuilds --- .../impl/CodenameOneImplementation.java | 8 + .../src/com/codename1/ui/Component.java | 32 +-- CodenameOne/src/com/codename1/ui/Display.java | 7 + CodenameOne/src/com/codename1/ui/List.java | 65 ++++++ .../accessibility/AccessibilityManager.java | 89 +++++--- .../ui/accessibility/AccessibilityNode.java | 2 +- .../android/AndroidAccessibilityProvider.java | 200 ++++++++++++++++-- .../impl/android/AndroidImplementation.java | 26 ++- .../com/codename1/impl/javase/JavaSEPort.java | 18 +- .../impl/linux/LinuxImplementation.java | 65 +++++- .../impl/windows/WindowsImplementation.java | 65 +++++- .../Accessibility-Semantics.asciidoc | 4 + .../AccessibilitySemanticsTest.java | 48 +++++ .../accessibility/AccessibilityTest.java | 45 +++- 14 files changed, 600 insertions(+), 74 deletions(-) diff --git a/CodenameOne/src/com/codename1/impl/CodenameOneImplementation.java b/CodenameOne/src/com/codename1/impl/CodenameOneImplementation.java index fa5fd97d68d..8afa3d258f7 100644 --- a/CodenameOne/src/com/codename1/impl/CodenameOneImplementation.java +++ b/CodenameOne/src/com/codename1/impl/CodenameOneImplementation.java @@ -11155,6 +11155,14 @@ public boolean isAccessibilityTreeSupported() { return false; } + /// Returns true when semantic invalidations should be projected eagerly. + /// Pull-based ports should override this to return true only while assistive + /// technology is active. Ports whose semantic projection must always remain + /// attached, such as web ARIA, may return true unconditionally. + public boolean isAccessibilityTreeUpdateRequired() { + return isAccessibilityTreeSupported(); + } + /// Returns true if the user has selected larger type fonts in the system settings. /// Default implementation returns false. /// diff --git a/CodenameOne/src/com/codename1/ui/Component.java b/CodenameOne/src/com/codename1/ui/Component.java index 2b0aa338db5..f8279458387 100644 --- a/CodenameOne/src/com/codename1/ui/Component.java +++ b/CodenameOne/src/com/codename1/ui/Component.java @@ -1092,11 +1092,11 @@ public int getX() { /// /// - `x`: the current x coordinate of the components origin public void setX(int x) { - if (bounds.getX() == x) { - return; - } + boolean changed = bounds.getX() != x; bounds.setX(x); - accessibilityChanged(AccessibilityManager.CHANGE_BOUNDS); + if (changed) { + accessibilityChanged(AccessibilityManager.CHANGE_BOUNDS); + } if (Form.activePeerCount > 0) { onParentPositionChange(); } @@ -1139,11 +1139,11 @@ public int getY() { /// /// - `y`: the current y coordinate of the components origin public void setY(int y) { - if (bounds.getY() == y) { - return; - } + boolean changed = bounds.getY() != y; bounds.setY(y); - accessibilityChanged(AccessibilityManager.CHANGE_BOUNDS); + if (changed) { + accessibilityChanged(AccessibilityManager.CHANGE_BOUNDS); + } if (Form.activePeerCount > 0) { onParentPositionChange(); } @@ -1378,11 +1378,11 @@ public int getWidth() { /// /// - #setPreferredSize public void setWidth(int width) { - if (bounds.getSize().getWidth() == width) { - return; - } + boolean changed = bounds.getSize().getWidth() != width; bounds.getSize().setWidth(width); - accessibilityChanged(AccessibilityManager.CHANGE_BOUNDS); + if (changed) { + accessibilityChanged(AccessibilityManager.CHANGE_BOUNDS); + } } /// Gets the outer width of this component. This is the width of the component including horizontal margins. @@ -1426,11 +1426,11 @@ public int getHeight() { /// /// - #setPreferredSize public void setHeight(int height) { - if (bounds.getSize().getHeight() == height) { - return; - } + boolean changed = bounds.getSize().getHeight() != height; bounds.getSize().setHeight(height); - accessibilityChanged(AccessibilityManager.CHANGE_BOUNDS); + if (changed) { + accessibilityChanged(AccessibilityManager.CHANGE_BOUNDS); + } } /// Gets the outer height of this component. This is the height of the component including vertical margins. diff --git a/CodenameOne/src/com/codename1/ui/Display.java b/CodenameOne/src/com/codename1/ui/Display.java index e22bee8d555..7d9e9d6b675 100644 --- a/CodenameOne/src/com/codename1/ui/Display.java +++ b/CodenameOne/src/com/codename1/ui/Display.java @@ -650,6 +650,13 @@ public boolean isAccessibilityTreeSupported() { return impl.isAccessibilityTreeSupported(); } + /// Returns true when the active port currently needs semantic changes to be + /// projected eagerly. This is an internal bridge used to avoid rebuilding + /// an unused accessibility tree from hot component setters. + public boolean isAccessibilityTreeUpdateRequired() { + return impl.isAccessibilityTreeUpdateRequired(); + } + /// Returns the status of the show during edit flag /// /// #### Returns diff --git a/CodenameOne/src/com/codename1/ui/List.java b/CodenameOne/src/com/codename1/ui/List.java index b1687a01c99..ac24ac2851d 100644 --- a/CodenameOne/src/com/codename1/ui/List.java +++ b/CodenameOne/src/com/codename1/ui/List.java @@ -479,6 +479,71 @@ public String getAccessibilityItemText(int index) { return text; } + /// Returns the model indices that should currently be materialized as + /// virtual accessibility children. The result contains the visible window, + /// a small one-item navigation buffer on each side, and the selected item. + /// It is intentionally bounded by the viewport so building a semantic tree + /// for a large renderer-backed list doesn't instantiate every row renderer. + public int[] getAccessibilityVisibleItemIndices() { + int modelSize = size(); + if (modelSize == 0) { + return new int[0]; + } + + Dimension rendererSize = getElementSize(false, true); + Style style = getStyle(); + int itemExtent = orientation == HORIZONTAL ? rendererSize.getWidth() : rendererSize.getHeight(); + int viewportExtent = orientation == HORIZONTAL + ? getWidth() - style.getHorizontalPadding() + : getHeight() - style.getVerticalPadding(); + int stride = Math.max(1, itemExtent + itemGap); + int windowSize = Math.min(modelSize, Math.max(1, viewportExtent / stride + 3)); + int selected = getSelectedIndex(); + int[] result = new int[Math.min(modelSize, windowSize + 1)]; + int count = 0; + + if (fixedSelection > FIXED_NONE_BOUNDRY) { + int center = selected >= 0 && selected < modelSize ? selected : 0; + int start = center - windowSize / 2; + for (int offset = 0; offset < windowSize; offset++) { + int index = (start + offset) % modelSize; + if (index < 0) { + index += modelSize; + } + result[count++] = index; + } + } else { + int scroll = orientation == HORIZONTAL ? getScrollX() : getScrollY(); + int padding = orientation == HORIZONTAL ? style.getPaddingLeftNoRTL() : style.getPaddingTop(); + int first = Math.max(0, (scroll - padding) / stride - 1); + if (first + windowSize > modelSize) { + first = Math.max(0, modelSize - windowSize); + } + for (int index = first; index < first + windowSize; index++) { + result[count++] = index; + } + } + + if (selected >= 0 && selected < modelSize && !containsIndex(result, count, selected)) { + result[count++] = selected; + } + if (count == result.length) { + return result; + } + int[] trimmed = new int[count]; + System.arraycopy(result, 0, trimmed, 0, count); + return trimmed; + } + + private boolean containsIndex(int[] indices, int length, int wanted) { + for (int i = 0; i < length; i++) { + if (indices[i] == wanted) { + return true; + } + } + return false; + } + /// Returns the visual selection during a drag operation, otherwise equivalent to model.getSelectedIndex /// /// #### Returns diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityManager.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityManager.java index aadb396c765..9a58315a0d1 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityManager.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityManager.java @@ -41,7 +41,6 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; -import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -65,7 +64,8 @@ public final class AccessibilityManager { private static final AccessibilityManager INSTANCE = new AccessibilityManager(); private final Map componentIds = new WeakHashMap(); - private final Map virtualIds = new HashMap(); + private final Map> virtualIds = + new WeakHashMap>(); private long nextId = 1; private long generation; private boolean dirty = true; @@ -86,6 +86,14 @@ public synchronized void invalidate(Component component, int changeType) { dirty = true; pendingChanges |= changeType; try { + // Most mutations only need to make the cached snapshot stale. Ports + // that can pull the tree do so on demand, and ports such as Android + // opt into eager projection only while assistive technology is active. + // This keeps layout, scrolling, and text setters at O(1) when nobody + // is consuming the semantic tree. + if (!Display.getInstance().isAccessibilityTreeUpdateRequired()) { + return; + } if (!refreshScheduled) { refreshScheduled = true; Display.getInstance().callSerially(new Runnable() { @@ -115,7 +123,7 @@ public void invalidateAll() { public AccessibilityTreeSnapshot getCurrentSnapshot() { synchronized (this) { - if (dirty && !Display.getInstance().isEdt()) { + if (!Display.getInstance().isEdt()) { return snapshot; } } @@ -124,6 +132,12 @@ public AccessibilityTreeSnapshot getCurrentSnapshot() { @SuppressWarnings("PMD.CompareObjectsWithEquals") public synchronized AccessibilityTreeSnapshot getSnapshot(Form form) { + // Walking a live lightweight component hierarchy off the Codename One + // EDT is unsafe. Native bridges on other threads receive the last + // immutable snapshot; active bridges arrange eager refreshes on the EDT. + if (!Display.getInstance().isEdt()) { + return snapshot; + } if (!dirty && form == snapshotForm) { return snapshot; } @@ -173,23 +187,6 @@ public void run() { return true; } - /// Dispatches an action selected by a native bridge that can transport only an integer token. - public boolean performActionByHash(long nodeId, int actionIdHash, Object argument) { - AccessibilityNodeSnapshot node; - synchronized (this) { - node = snapshot.getNode(nodeId); - } - if (node == null) { - return false; - } - for (AccessibilityAction action : node.getActions()) { - if (action.getId().hashCode() == actionIdHash) { - return performAction(nodeId, action.getId(), argument); - } - } - return false; - } - private long idFor(Component component) { Long id = componentIds.get(component); if (id == null) { @@ -200,11 +197,15 @@ private long idFor(Component component) { } private long idForVirtual(Component host, String path) { - String key = idFor(host) + ":" + path; - Long id = virtualIds.get(key); + Map hostIds = virtualIds.get(host); + if (hostIds == null) { + hostIds = new LinkedHashMap(); + virtualIds.put(host, hostIds); + } + Long id = hostIds.get(path); if (id == null) { id = Long.valueOf(nextId++); - virtualIds.put(key, id); + hostIds.put(path, id); } return id.longValue(); } @@ -379,7 +380,8 @@ private BuildNode buildVirtualNode(Component host, AccessibilityNode config, Str private void addListChildren(final com.codename1.ui.List list, List destination) { int size = list.size(); - for (int i = 0; i < size; i++) { + int[] visibleItems = list.getAccessibilityVisibleItemIndices(); + for (int i : visibleItems) { final int index = i; AccessibilityNode item = new AccessibilityNode("item-" + i) .setRole(AccessibilityRole.LIST_ITEM) @@ -412,6 +414,17 @@ private void addDefaultActions(final Component component, AccessibilityNodeSnaps new SliderAdjustmentHandler(slider, -1))); } } + if (component instanceof com.codename1.ui.List) { + final com.codename1.ui.List list = (com.codename1.ui.List) component; + if (list.size() > 0 && !hasAction(builder.actions, AccessibilityAction.SCROLL_FORWARD)) { + builder.actions.add(new AccessibilityAction(AccessibilityAction.SCROLL_FORWARD, null, + new ListScrollHandler(list, 1))); + } + if (list.size() > 0 && !hasAction(builder.actions, AccessibilityAction.SCROLL_BACKWARD)) { + builder.actions.add(new AccessibilityAction(AccessibilityAction.SCROLL_BACKWARD, null, + new ListScrollHandler(list, -1))); + } + } if (component instanceof TextArea) { final TextArea text = (TextArea) component; if (!hasAction(builder.actions, AccessibilityAction.FOCUS)) { @@ -806,6 +819,34 @@ public boolean perform(Component source, Object argument) { } } + private static final class ListScrollHandler implements AccessibilityAction.Handler { + private final com.codename1.ui.List list; + private final int direction; + + private ListScrollHandler(com.codename1.ui.List list, int direction) { + this.list = list; + this.direction = direction; + } + + @Override + public boolean perform(Component source, Object argument) { + if (!list.isEnabled() || list.size() == 0) { + return false; + } + int selected = list.getSelectedIndex(); + if (selected < 0) { + selected = direction > 0 ? 0 : list.size() - 1; + } else { + selected = Math.max(0, Math.min(list.size() - 1, selected + direction)); + } + if (selected == list.getSelectedIndex()) { + return false; + } + list.setSelectedIndex(selected); + return true; + } + } + private static final class SliderAdjustmentHandler implements AccessibilityAction.Handler { private final Slider slider; private final int direction; diff --git a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityNode.java b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityNode.java index 8346e09d678..3668f0b799b 100644 --- a/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityNode.java +++ b/CodenameOne/src/com/codename1/ui/accessibility/AccessibilityNode.java @@ -144,7 +144,7 @@ public String getValidationError() { } public AccessibilityNode setValidationError(String error) { this.validationError = error; - this.invalid = error == null ? invalid : Boolean.TRUE; + this.invalid = error == null ? null : Boolean.TRUE; return changed(AccessibilityManager.CHANGE_STATE); } public String getPaneTitle() { diff --git a/Ports/Android/src/com/codename1/impl/android/AndroidAccessibilityProvider.java b/Ports/Android/src/com/codename1/impl/android/AndroidAccessibilityProvider.java index b338bb7ead2..f8e704f54e2 100644 --- a/Ports/Android/src/com/codename1/impl/android/AndroidAccessibilityProvider.java +++ b/Ports/Android/src/com/codename1/impl/android/AndroidAccessibilityProvider.java @@ -42,7 +42,12 @@ import com.codename1.ui.accessibility.AccessibilityTreeSnapshot; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; import java.util.List; +import java.util.Map; +import java.util.Set; /** Android virtual-view adapter for Codename One's lightweight semantic tree. */ final class AndroidAccessibilityProvider extends AccessibilityNodeProvider { @@ -51,6 +56,15 @@ final class AndroidAccessibilityProvider extends AccessibilityNodeProvider { private final View host; private final AndroidImplementation implementation; private final android.view.accessibility.AccessibilityManager nativeAccessibilityManager; + private final android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener stateListener; + private final Object touchListener; + private final Map virtualIds = new HashMap(); + private final Map semanticIds = new HashMap(); + private final Map customActionIds = new HashMap(); + private final Map customActionKeys = new HashMap(); + private long mappedGeneration = Long.MIN_VALUE; + private int nextVirtualId = 1; + private int nextCustomActionId = CUSTOM_ACTION_BASE; private int accessibilityFocusedId = Integer.MIN_VALUE; AndroidAccessibilityProvider(View host, AndroidImplementation implementation) { @@ -58,16 +72,73 @@ final class AndroidAccessibilityProvider extends AccessibilityNodeProvider { this.implementation = implementation; nativeAccessibilityManager = (android.view.accessibility.AccessibilityManager) host.getContext() .getSystemService(android.content.Context.ACCESSIBILITY_SERVICE); + stateListener = new android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener() { + @Override + public void onAccessibilityStateChanged(boolean enabled) { + accessibilityConsumerChanged(); + } + }; + touchListener = Build.VERSION.SDK_INT >= 19 && nativeAccessibilityManager != null + ? Api19TouchExploration.register(nativeAccessibilityManager, this) : null; + if (nativeAccessibilityManager != null) { + nativeAccessibilityManager.addAccessibilityStateChangeListener(stateListener); + } host.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES); + accessibilityConsumerChanged(); + } + + void dispose() { + implementation.setAccessibilityTreeUpdateRequired(false); + if (nativeAccessibilityManager != null) { + nativeAccessibilityManager.removeAccessibilityStateChangeListener(stateListener); + if (Build.VERSION.SDK_INT >= 19 && touchListener != null) { + Api19TouchExploration.unregister(nativeAccessibilityManager, touchListener); + } + } + virtualIds.clear(); + semanticIds.clear(); + customActionIds.clear(); + customActionKeys.clear(); + } + + private void accessibilityConsumerChanged() { + boolean active = implementation.isScreenReaderEnabled(); + implementation.setAccessibilityTreeUpdateRequired(active); + if (active) { + AccessibilityManager.getInstance().invalidateAll(); + } + } + + private static final class Api19TouchExploration { + private Api19TouchExploration() { + } + + static Object register(android.view.accessibility.AccessibilityManager manager, + final AndroidAccessibilityProvider provider) { + android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener listener = + new android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener() { + @Override + public void onTouchExplorationStateChanged(boolean enabled) { + provider.accessibilityConsumerChanged(); + } + }; + manager.addTouchExplorationStateChangeListener(listener); + return listener; + } + + static void unregister(android.view.accessibility.AccessibilityManager manager, Object value) { + manager.removeTouchExplorationStateChangeListener( + (android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener)value); + } } @Override public AccessibilityNodeInfo createAccessibilityNodeInfo(int virtualViewId) { - AccessibilityTreeSnapshot tree = implementation.getAccessibilityTreeSnapshot(); + AccessibilityTreeSnapshot tree = currentTree(); if (virtualViewId == AccessibilityNodeProvider.HOST_VIEW_ID) { return createHostNode(tree); } - AccessibilityNodeSnapshot node = tree.getNode(virtualViewId); + AccessibilityNodeSnapshot node = nodeForVirtualId(tree, virtualViewId); return node == null ? null : createVirtualNode(tree, node, virtualViewId); } @@ -78,7 +149,7 @@ private AccessibilityNodeInfo createHostNode(AccessibilityTreeSnapshot tree) { info.setPackageName(host.getContext().getPackageName()); info.setScrollable(false); for (Long rootId : tree.getRootIds()) { - info.addChild(host, toVirtualId(rootId.longValue())); + info.addChild(host, virtualIdFor(rootId.longValue())); } return info; } @@ -90,8 +161,8 @@ private AccessibilityNodeInfo createVirtualNode(AccessibilityTreeSnapshot tree, info.setClassName(className(node.getRole())); info.setSource(host, virtualViewId); if (node.getParentId() < 0) info.setParent(host); - else info.setParent(host, toVirtualId(node.getParentId())); - for (Long childId : node.getChildIds()) info.addChild(host, toVirtualId(childId.longValue())); + else info.setParent(host, virtualIdFor(node.getParentId())); + for (Long childId : node.getChildIds()) info.addChild(host, virtualIdFor(childId.longValue())); String label = node.getLabel(); if (usesText(node.getRole())) info.setText(label); @@ -185,13 +256,14 @@ private void addActions(AccessibilityNodeInfo info, AccessibilityNodeSnapshot no if (hasAction(node, AccessibilityAction.DECREMENT)) info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD); if (hasAction(node, AccessibilityAction.SCROLL_FORWARD)) info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD); if (hasAction(node, AccessibilityAction.SCROLL_BACKWARD)) info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD); - info.addAction(accessibilityFocusedId == toVirtualId(node.getId()) + info.addAction(accessibilityFocusedId == virtualIdFor(node.getId()) ? AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS : AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS); if (Build.VERSION.SDK_INT >= 21) { for (AccessibilityAction action : node.getActions()) { if (isStandard(action.getId())) continue; - info.addAction(new AccessibilityNodeInfo.AccessibilityAction(customActionId(action.getId()), + info.addAction(new AccessibilityNodeInfo.AccessibilityAction( + customActionId(node.getId(), action.getId()), action.getLabel() == null ? action.getId() : action.getLabel())); } if (hasAction(node, AccessibilityAction.SET_TEXT)) { @@ -205,7 +277,8 @@ public boolean performAction(int virtualViewId, int action, Bundle arguments) { if (virtualViewId == AccessibilityNodeProvider.HOST_VIEW_ID) { return host.performAccessibilityAction(action, arguments); } - AccessibilityNodeSnapshot node = implementation.getAccessibilityTreeSnapshot().getNode(virtualViewId); + AccessibilityTreeSnapshot tree = currentTree(); + AccessibilityNodeSnapshot node = nodeForVirtualId(tree, virtualViewId); if (node == null) return false; if (action == AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS) { if (accessibilityFocusedId == virtualViewId) return false; @@ -239,7 +312,8 @@ else if (action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD) { if (argument != null) argument = argument.toString(); } else { for (AccessibilityAction candidate : node.getActions()) { - if (customActionId(candidate.getId()) == action) { + if (!isStandard(candidate.getId()) + && customActionId(node.getId(), candidate.getId()) == action) { actionId = candidate.getId(); break; } @@ -253,11 +327,11 @@ public List findAccessibilityNodeInfosByText(String searc if (searched == null) return Collections.emptyList(); String lower = searched.toLowerCase(); List result = new ArrayList(); - AccessibilityTreeSnapshot tree = implementation.getAccessibilityTreeSnapshot(); + AccessibilityTreeSnapshot tree = currentTree(); for (AccessibilityNodeSnapshot node : tree.getNodes().values()) { if (contains(node.getLabel(), lower) || contains(node.getValue(), lower) || contains(node.getDescription(), lower)) { - result.add(createVirtualNode(tree, node, toVirtualId(node.getId()))); + result.add(createVirtualNode(tree, node, virtualIdFor(node.getId()))); } } return result; @@ -265,14 +339,14 @@ public List findAccessibilityNodeInfosByText(String searc @Override public AccessibilityNodeInfo findFocus(int focus) { - AccessibilityTreeSnapshot tree = implementation.getAccessibilityTreeSnapshot(); + AccessibilityTreeSnapshot tree = currentTree(); if (focus == AccessibilityNodeInfo.FOCUS_ACCESSIBILITY && accessibilityFocusedId != Integer.MIN_VALUE) { - AccessibilityNodeSnapshot node = tree.getNode(accessibilityFocusedId); + AccessibilityNodeSnapshot node = nodeForVirtualId(tree, accessibilityFocusedId); return node == null ? null : createVirtualNode(tree, node, accessibilityFocusedId); } if (focus == AccessibilityNodeInfo.FOCUS_INPUT) { for (AccessibilityNodeSnapshot node : tree.getNodes().values()) { - if (node.isFocused()) return createVirtualNode(tree, node, toVirtualId(node.getId())); + if (node.isFocused()) return createVirtualNode(tree, node, virtualIdFor(node.getId())); } } return null; @@ -405,11 +479,101 @@ private boolean isStandard(String id) { || AccessibilityAction.SCROLL_FORWARD.equals(id) || AccessibilityAction.SCROLL_BACKWARD.equals(id); } - private int customActionId(String id) { - return CUSTOM_ACTION_BASE | (id.hashCode() & 0x00ffffff); + private AccessibilityTreeSnapshot currentTree() { + AccessibilityTreeSnapshot tree = implementation.getAccessibilityTreeSnapshot(); + synchronizeIds(tree); + return tree; + } + + private void synchronizeIds(AccessibilityTreeSnapshot tree) { + if (mappedGeneration == tree.getGeneration()) { + return; + } + Set liveSemanticIds = tree.getNodes().keySet(); + Iterator> virtualIterator = virtualIds.entrySet().iterator(); + while (virtualIterator.hasNext()) { + Map.Entry entry = virtualIterator.next(); + if (!liveSemanticIds.contains(entry.getKey())) { + semanticIds.remove(entry.getValue()); + virtualIterator.remove(); + } + } + for (Long semanticId : liveSemanticIds) { + virtualIdFor(semanticId.longValue()); + } + + Set liveActionKeys = new HashSet(); + for (AccessibilityNodeSnapshot node : tree.getNodes().values()) { + for (AccessibilityAction action : node.getActions()) { + if (!isStandard(action.getId())) { + liveActionKeys.add(actionKey(node.getId(), action.getId())); + } + } + } + Iterator> actionIterator = customActionIds.entrySet().iterator(); + while (actionIterator.hasNext()) { + Map.Entry entry = actionIterator.next(); + if (!liveActionKeys.contains(entry.getKey())) { + customActionKeys.remove(entry.getValue()); + actionIterator.remove(); + } + } + if (accessibilityFocusedId != Integer.MIN_VALUE && !semanticIds.containsKey( + Integer.valueOf(accessibilityFocusedId))) { + accessibilityFocusedId = Integer.MIN_VALUE; + } + mappedGeneration = tree.getGeneration(); + } + + private AccessibilityNodeSnapshot nodeForVirtualId(AccessibilityTreeSnapshot tree, int virtualId) { + Long semanticId = semanticIds.get(Integer.valueOf(virtualId)); + return semanticId == null ? null : tree.getNode(semanticId.longValue()); + } + + private int virtualIdFor(long semanticId) { + Long key = Long.valueOf(semanticId); + Integer existing = virtualIds.get(key); + if (existing != null) { + return existing.intValue(); + } + int candidate = nextVirtualId; + while (candidate == AccessibilityNodeProvider.HOST_VIEW_ID + || semanticIds.containsKey(Integer.valueOf(candidate))) { + candidate = nextVirtualId(candidate); + } + nextVirtualId = nextVirtualId(candidate); + Integer virtualId = Integer.valueOf(candidate); + virtualIds.put(key, virtualId); + semanticIds.put(virtualId, key); + return candidate; + } + + private int nextVirtualId(int current) { + return current == Integer.MAX_VALUE ? 1 : current + 1; + } + + private int customActionId(long nodeId, String id) { + String key = actionKey(nodeId, id); + Integer existing = customActionIds.get(key); + if (existing != null) { + return existing.intValue(); + } + int candidate = nextCustomActionId; + while (customActionKeys.containsKey(Integer.valueOf(candidate))) { + candidate = nextCustomActionId(candidate); + } + nextCustomActionId = nextCustomActionId(candidate); + Integer actionId = Integer.valueOf(candidate); + customActionIds.put(key, actionId); + customActionKeys.put(actionId, key); + return candidate; + } + + private int nextCustomActionId(int current) { + return current == Integer.MAX_VALUE ? CUSTOM_ACTION_BASE : current + 1; } - private int toVirtualId(long id) { - return (int)id; + private String actionKey(long nodeId, String actionId) { + return nodeId + "\n" + actionId; } } diff --git a/Ports/Android/src/com/codename1/impl/android/AndroidImplementation.java b/Ports/Android/src/com/codename1/impl/android/AndroidImplementation.java index 9c956ef6038..3150f646bb9 100644 --- a/Ports/Android/src/com/codename1/impl/android/AndroidImplementation.java +++ b/Ports/Android/src/com/codename1/impl/android/AndroidImplementation.java @@ -322,6 +322,7 @@ public static void setActivity(CodenameOneActivity aActivity) { } CodenameOneSurface myView = null; private AndroidAccessibilityProvider accessibilityProvider; + private volatile boolean accessibilityTreeUpdateRequired; CodenameOneTextPaint defaultFont; private final char[] tmpchar = new char[1]; private final Rect tmprect = new Rect(); @@ -1581,12 +1582,16 @@ public void run() { } deinitializing = false; } - if (nativePeers.size() > 0) { - for (int i = 0; i < nativePeers.size(); i++) { - ((AndroidImplementation.AndroidPeer) nativePeers.elementAt(i)).deinit(); - } - } - if (relativeLayout != null) { + if (nativePeers.size() > 0) { + for (int i = 0; i < nativePeers.size(); i++) { + ((AndroidImplementation.AndroidPeer) nativePeers.elementAt(i)).deinit(); + } + } + if (accessibilityProvider != null) { + accessibilityProvider.dispose(); + accessibilityProvider = null; + } + if (relativeLayout != null) { relativeLayout.removeAllViews(); } relativeLayout = null; @@ -13049,6 +13054,15 @@ public void run() { public boolean isAccessibilityTreeSupported() { return Build.VERSION.SDK_INT >= 16; } + + @Override + public boolean isAccessibilityTreeUpdateRequired() { + return accessibilityTreeUpdateRequired; + } + + void setAccessibilityTreeUpdateRequired(boolean required) { + accessibilityTreeUpdateRequired = required; + } // ================================================================ // Crypto bridge -- routes com.codename1.security onto the standard diff --git a/Ports/JavaSE/src/com/codename1/impl/javase/JavaSEPort.java b/Ports/JavaSE/src/com/codename1/impl/javase/JavaSEPort.java index ed137c4dbfa..a6838eb8043 100644 --- a/Ports/JavaSE/src/com/codename1/impl/javase/JavaSEPort.java +++ b/Ports/JavaSE/src/com/codename1/impl/javase/JavaSEPort.java @@ -40,6 +40,7 @@ import com.codename1.printing.PrintResult; import com.codename1.printing.PrintResultListener; import com.codename1.ui.AccessibilityColorVisionDeficiency; +import com.codename1.ui.accessibility.AccessibilityManager; import com.codename1.ui.Component; import com.codename1.ui.Display; import com.codename1.ui.Font; @@ -2509,10 +2510,15 @@ public void hierarchyChanged(HierarchyEvent e) { public javax.accessibility.AccessibleContext getAccessibleContext() { if (cn1Accessibility == null) { cn1Accessibility = new JavaSEAccessibility(this, JavaSEPort.this); + AccessibilityManager.getInstance().invalidateAll(); } return cn1Accessibility.getContext(); } + boolean isAccessibilityContextRequested() { + return cn1Accessibility != null; + } + void accessibilityChanged(int changeType) { if (cn1Accessibility != null) cn1Accessibility.changed(changeType); } @@ -3810,6 +3816,11 @@ public boolean isAccessibilityTreeSupported() { return true; } + @Override + public boolean isAccessibilityTreeUpdateRequired() { + return screenReaderEnabled || canvas != null && canvas.isAccessibilityContextRequested(); + } + public void paintDirty() { super.paintDirty(); } @@ -7688,7 +7699,12 @@ public void setSimulatorAccessibilityPreference(int preference, boolean enabled) case 5: invertColorsEnabled = enabled; break; case 6: grayscaleEnabled = enabled; break; case 7: onOffSwitchLabelsEnabled = enabled; break; - case 8: screenReaderEnabled = enabled; break; + case 8: + screenReaderEnabled = enabled; + if (enabled) { + AccessibilityManager.getInstance().invalidateAll(); + } + break; default: throw new IllegalArgumentException("Unknown accessibility preference: " + preference); } } diff --git a/Ports/LinuxPort/src/com/codename1/impl/linux/LinuxImplementation.java b/Ports/LinuxPort/src/com/codename1/impl/linux/LinuxImplementation.java index 02ad6ae6848..cbef45d9a84 100644 --- a/Ports/LinuxPort/src/com/codename1/impl/linux/LinuxImplementation.java +++ b/Ports/LinuxPort/src/com/codename1/impl/linux/LinuxImplementation.java @@ -36,7 +36,6 @@ import com.codename1.ui.geom.PathIterator; import com.codename1.ui.geom.Shape; import com.codename1.ui.accessibility.AccessibilityAction; -import com.codename1.ui.accessibility.AccessibilityManager; import com.codename1.ui.accessibility.AccessibilityNodeSnapshot; import com.codename1.ui.accessibility.AccessibilityTreeSnapshot; import java.io.ByteArrayOutputStream; @@ -46,7 +45,12 @@ import java.io.OutputStream; import java.util.Calendar; import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; import java.util.Locale; +import java.util.Map; +import java.util.Set; /** * Native Linux (GTK3, desktop) implementation of the Codename One platform @@ -117,6 +121,10 @@ public boolean isScreenReaderEnabled() { private L10NManager l10n; private com.codename1.ui.util.ImageIO imageIO; private final int[] eventScratch = new int[4]; + private final Map accessibilityActionTokens = new HashMap(); + private final Map accessibilityActionTargets = + new HashMap(); + private int nextAccessibilityActionToken = 1; /** * Registers the singleton so the Win32 native bootstrap and message loop can @@ -702,7 +710,10 @@ private void drainInput() { Display.getInstance().exitApplication(); break; case EVENT_ACCESSIBILITY_ACTION: - AccessibilityManager.getInstance().performActionByHash(x & 0xffffffffL, key, null); + AccessibilityActionTarget actionTarget = accessibilityActionTargets.get(Integer.valueOf(key)); + if (actionTarget != null) { + performAccessibilityAction(actionTarget.nodeId, actionTarget.actionId, null); + } break; default: break; @@ -719,6 +730,7 @@ private void drainInput() { @Override public void accessibilityTreeChanged(int changeType) { AccessibilityTreeSnapshot tree = getAccessibilityTreeSnapshot(); + Set liveActionKeys = new HashSet(); LinuxNative.accessibilityBegin(); for (AccessibilityNodeSnapshot node : tree.getNodes().values()) { int flags = (node.isFocusable() ? 1 : 0) | (node.isFocused() ? 2 : 0) @@ -732,12 +744,59 @@ public void accessibilityTreeChanged(int changeType) { joinDescription(node), node.getValue(), b.getX(), b.getY(), b.getWidth(), b.getHeight(), flags); for (AccessibilityAction action : node.getActions()) { if (action.isEnabled()) { - LinuxNative.accessibilityAction(node.getId(), action.getId(), action.getId().hashCode(), + String actionKey = accessibilityActionKey(node.getId(), action.getId()); + liveActionKeys.add(actionKey); + LinuxNative.accessibilityAction(node.getId(), action.getId(), + accessibilityActionToken(node.getId(), action.getId()), action.getLabel() == null ? action.getId() : action.getLabel()); } } } LinuxNative.accessibilityEnd(changeType); + Iterator> iterator = accessibilityActionTokens.entrySet().iterator(); + while (iterator.hasNext()) { + Map.Entry entry = iterator.next(); + if (!liveActionKeys.contains(entry.getKey())) { + accessibilityActionTargets.remove(entry.getValue()); + iterator.remove(); + } + } + } + + private int accessibilityActionToken(long nodeId, String actionId) { + String key = accessibilityActionKey(nodeId, actionId); + Integer existing = accessibilityActionTokens.get(key); + if (existing != null) { + accessibilityActionTargets.put(existing, new AccessibilityActionTarget(nodeId, actionId)); + return existing.intValue(); + } + int candidate = nextAccessibilityActionToken; + while (accessibilityActionTargets.containsKey(Integer.valueOf(candidate))) { + candidate = nextAccessibilityActionToken(candidate); + } + nextAccessibilityActionToken = nextAccessibilityActionToken(candidate); + Integer token = Integer.valueOf(candidate); + accessibilityActionTokens.put(key, token); + accessibilityActionTargets.put(token, new AccessibilityActionTarget(nodeId, actionId)); + return candidate; + } + + private int nextAccessibilityActionToken(int current) { + return current == Integer.MAX_VALUE ? 1 : current + 1; + } + + private String accessibilityActionKey(long nodeId, String actionId) { + return nodeId + "\n" + actionId; + } + + private static final class AccessibilityActionTarget { + final long nodeId; + final String actionId; + + AccessibilityActionTarget(long nodeId, String actionId) { + this.nodeId = nodeId; + this.actionId = actionId; + } } private String joinDescription(AccessibilityNodeSnapshot node) { diff --git a/Ports/WindowsPort/src/com/codename1/impl/windows/WindowsImplementation.java b/Ports/WindowsPort/src/com/codename1/impl/windows/WindowsImplementation.java index 45ed71cc1c0..caf155660eb 100644 --- a/Ports/WindowsPort/src/com/codename1/impl/windows/WindowsImplementation.java +++ b/Ports/WindowsPort/src/com/codename1/impl/windows/WindowsImplementation.java @@ -36,7 +36,6 @@ import com.codename1.ui.geom.PathIterator; import com.codename1.ui.geom.Shape; import com.codename1.ui.accessibility.AccessibilityAction; -import com.codename1.ui.accessibility.AccessibilityManager; import com.codename1.ui.accessibility.AccessibilityNodeSnapshot; import com.codename1.ui.accessibility.AccessibilityTreeSnapshot; import java.io.ByteArrayOutputStream; @@ -46,7 +45,12 @@ import java.io.OutputStream; import java.util.Calendar; import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; import java.util.Locale; +import java.util.Map; +import java.util.Set; /** * Native Windows (Win32, desktop / tablet) implementation of the Codename One @@ -108,6 +112,10 @@ public boolean isScreenReaderEnabled() { private L10NManager l10n; private com.codename1.ui.util.ImageIO imageIO; private final int[] eventScratch = new int[4]; + private final Map accessibilityActionTokens = new HashMap(); + private final Map accessibilityActionTargets = + new HashMap(); + private int nextAccessibilityActionToken = 1; /** * Registers the singleton so the Win32 native bootstrap and message loop can @@ -701,7 +709,10 @@ private void drainInput() { Display.getInstance().exitApplication(); break; case EVENT_ACCESSIBILITY_ACTION: - AccessibilityManager.getInstance().performActionByHash(x & 0xffffffffL, key, null); + AccessibilityActionTarget actionTarget = accessibilityActionTargets.get(Integer.valueOf(key)); + if (actionTarget != null) { + performAccessibilityAction(actionTarget.nodeId, actionTarget.actionId, null); + } break; default: break; @@ -718,6 +729,7 @@ private void drainInput() { @Override public void accessibilityTreeChanged(int changeType) { AccessibilityTreeSnapshot tree = getAccessibilityTreeSnapshot(); + Set liveActionKeys = new HashSet(); WindowsNative.accessibilityBegin(); for (AccessibilityNodeSnapshot node : tree.getNodes().values()) { int flags = (node.isFocusable() ? 1 : 0) | (node.isFocused() ? 2 : 0) @@ -731,12 +743,59 @@ public void accessibilityTreeChanged(int changeType) { accessibilityDescription(node), node.getValue(), b.getX(), b.getY(), b.getWidth(), b.getHeight(), flags); for (AccessibilityAction action : node.getActions()) { if (action.isEnabled()) { - WindowsNative.accessibilityAction(node.getId(), action.getId(), action.getId().hashCode(), + String actionKey = accessibilityActionKey(node.getId(), action.getId()); + liveActionKeys.add(actionKey); + WindowsNative.accessibilityAction(node.getId(), action.getId(), + accessibilityActionToken(node.getId(), action.getId()), action.getLabel() == null ? action.getId() : action.getLabel()); } } } WindowsNative.accessibilityEnd(changeType); + Iterator> iterator = accessibilityActionTokens.entrySet().iterator(); + while (iterator.hasNext()) { + Map.Entry entry = iterator.next(); + if (!liveActionKeys.contains(entry.getKey())) { + accessibilityActionTargets.remove(entry.getValue()); + iterator.remove(); + } + } + } + + private int accessibilityActionToken(long nodeId, String actionId) { + String key = accessibilityActionKey(nodeId, actionId); + Integer existing = accessibilityActionTokens.get(key); + if (existing != null) { + accessibilityActionTargets.put(existing, new AccessibilityActionTarget(nodeId, actionId)); + return existing.intValue(); + } + int candidate = nextAccessibilityActionToken; + while (accessibilityActionTargets.containsKey(Integer.valueOf(candidate))) { + candidate = nextAccessibilityActionToken(candidate); + } + nextAccessibilityActionToken = nextAccessibilityActionToken(candidate); + Integer token = Integer.valueOf(candidate); + accessibilityActionTokens.put(key, token); + accessibilityActionTargets.put(token, new AccessibilityActionTarget(nodeId, actionId)); + return candidate; + } + + private int nextAccessibilityActionToken(int current) { + return current == Integer.MAX_VALUE ? 1 : current + 1; + } + + private String accessibilityActionKey(long nodeId, String actionId) { + return nodeId + "\n" + actionId; + } + + private static final class AccessibilityActionTarget { + final long nodeId; + final String actionId; + + AccessibilityActionTarget(long nodeId, String actionId) { + this.nodeId = nodeId; + this.actionId = actionId; + } } private String accessibilityDescription(AccessibilityNodeSnapshot node) { diff --git a/docs/developer-guide/Accessibility-Semantics.asciidoc b/docs/developer-guide/Accessibility-Semantics.asciidoc index 40b9e25915a..ec8612fe157 100644 --- a/docs/developer-guide/Accessibility-Semantics.asciidoc +++ b/docs/developer-guide/Accessibility-Semantics.asciidoc @@ -139,10 +139,14 @@ include::../demos/common/src/main/java/com/codenameone/developerguide/snippets/A Row and column indexes are zero-based. Position and set size are one-based; use `-1` when unknown. Lists, tables, tabs, and their items infer this metadata where possible. +Renderer-backed lists keep the full model size in their collection metadata but materialize only the visible rows, a small navigation buffer, and the selected row as virtual children. Forward and backward semantic scroll actions move the window. This keeps accessibility-tree work proportional to the viewport instead of invoking a cell renderer for every row whenever a large list scrolls. + == Inspecting and testing semantics `AccessibilityInspector` returns an immutable snapshot. A snapshot is safe to inspect without racing native accessibility callbacks and includes stable IDs, hierarchy, bounds, resolved state, actions, range and collection data. `toJson()` is suitable for diagnostic reports and tooling. +Semantic setters always mark the cached tree dirty. Pull-based native ports rebuild it on the Codename One EDT only while assistive technology is active or when a tool explicitly requests a snapshot; the browser keeps its off-screen ARIA projection synchronized continuously. Applications should still publish complete semantics unconditionally—this runtime optimization is deliberately transparent to application code. + [source,java] include::../demos/common/src/main/java/com/codenameone/developerguide/snippets/AccessibilitySemanticsSnippets.java[tag=accessibility-semantics-inspection,indent=0] diff --git a/maven/core-unittests/src/test/java/com/codename1/ui/accessibility/AccessibilitySemanticsTest.java b/maven/core-unittests/src/test/java/com/codename1/ui/accessibility/AccessibilitySemanticsTest.java index 36f744b5063..53f1cd2522b 100644 --- a/maven/core-unittests/src/test/java/com/codename1/ui/accessibility/AccessibilitySemanticsTest.java +++ b/maven/core-unittests/src/test/java/com/codename1/ui/accessibility/AccessibilitySemanticsTest.java @@ -35,6 +35,7 @@ import com.codename1.ui.Slider; import com.codename1.ui.TextField; import com.codename1.ui.list.DefaultListModel; +import com.codename1.ui.list.ListCellRenderer; import java.util.List; import static org.junit.jupiter.api.Assertions.*; @@ -168,6 +169,53 @@ void rendererBackedListsExposeStableVirtualCollectionItems() { assertEquals(Boolean.FALSE, second.getNode(stableId).getSelected()); } + @FormTest + void largeRendererBackedListsOnlyMaterializeTheViewport() { + Form form = form(); + String[] values = new String[1000]; + for (int i = 0; i < values.length; i++) { + values[i] = "Row " + i; + } + final int[] rendererCalls = new int[1]; + final Label rendererLabel = new Label(); + com.codename1.ui.List list = new com.codename1.ui.List( + new DefaultListModel(values)); + list.setRenderer(new ListCellRenderer() { + public Component getListCellRendererComponent(com.codename1.ui.List list, + String value, int index, boolean selected) { + rendererCalls[0]++; + rendererLabel.setText(value); + return rendererLabel; + } + + public Component getListFocusComponent(com.codename1.ui.List list) { + return null; + } + }); + place(form, list, 0, 0, 200, 120); + rendererCalls[0] = 0; + + AccessibilityTreeSnapshot tree = AccessibilityInspector.snapshot(form); + AccessibilityNodeSnapshot listNode = find(tree, list); + assertTrue(listNode.getChildIds().size() < 50, + "A 1000-row list should expose only its viewport-sized virtual window"); + assertTrue(rendererCalls[0] < 100, + "Building list semantics must not invoke the renderer for every model row"); + assertEquals(1000, listNode.getCollectionInfo().getRowCount()); + assertNotNull(listNode.getAction(AccessibilityAction.SCROLL_FORWARD)); + assertNotNull(listNode.getAction(AccessibilityAction.SCROLL_BACKWARD)); + } + + @FormTest + void clearingAValidationErrorClearsTheImpliedInvalidState() { + AccessibilityNode node = new AccessibilityNode("validation-test"); + node.setValidationError("Required"); + assertEquals(Boolean.TRUE, node.getInvalid()); + node.setValidationError(null); + assertNull(node.getValidationError()); + assertNull(node.getInvalid()); + } + @FormTest void auditsInvalidRangesAndUnlabeledCustomActions() { Form form = form(); diff --git a/scripts/hellocodenameone/common/src/main/java/com/codenameone/examples/hellocodenameone/tests/accessibility/AccessibilityTest.java b/scripts/hellocodenameone/common/src/main/java/com/codenameone/examples/hellocodenameone/tests/accessibility/AccessibilityTest.java index f561ffd51d7..9a9b9890a7e 100644 --- a/scripts/hellocodenameone/common/src/main/java/com/codenameone/examples/hellocodenameone/tests/accessibility/AccessibilityTest.java +++ b/scripts/hellocodenameone/common/src/main/java/com/codenameone/examples/hellocodenameone/tests/accessibility/AccessibilityTest.java @@ -25,6 +25,8 @@ import com.codename1.ui.accessibility.AccessibilityRole; import com.codename1.ui.accessibility.AccessibilityTreeSnapshot; import com.codename1.ui.geom.Rectangle; +import com.codename1.ui.list.DefaultListModel; +import com.codename1.ui.list.ListCellRenderer; import com.codenameone.examples.hellocodenameone.tests.BaseTest; /** Cross-port semantics conformance test. This runs in every native cn1ss job. */ @@ -47,9 +49,15 @@ public void run() { private void runSemanticAssertions() { assertAccessibilityPreferencesAvailable(); + AccessibilityNode validation = new AccessibilityNode("validation-state"); + validation.setValidationError("Required"); + assertEqual(Boolean.TRUE, validation.getInvalid(), "validation error implies invalid state"); + validation.setValidationError(null); + assertEqual(null, validation.getInvalid(), "clearing validation error clears invalid state"); + final Form form = new Form("Accessibility conformance"); - size(form, 0, 0, 600, 1200); - size(form.getContentPane(), 0, 0, 600, 1200); + size(form, 0, 0, 600, 1400); + size(form.getContentPane(), 0, 0, 600, 1400); form.getSemantics().setPaneTitle("Settings").setRole(AccessibilityRole.GENERIC); Label heading = add(form, new Label("Preferences"), 10, 10, 300, 40); @@ -123,6 +131,29 @@ public boolean perform(Component component, Object argument) { Button disabled = add(form, new Button("Unavailable action"), 10, 920, 220, 40); disabled.setEnabled(false); + String[] rows = new String[1000]; + for (int i = 0; i < rows.length; i++) { + rows[i] = "Row " + i; + } + final int[] rendererCalls = new int[1]; + final Label rendererLabel = new Label(); + com.codename1.ui.List largeList = new com.codename1.ui.List( + new DefaultListModel(rows)); + largeList.setRenderer(new ListCellRenderer() { + public Component getListCellRendererComponent(com.codename1.ui.List list, + String value, int index, boolean selected) { + rendererCalls[0]++; + rendererLabel.setText(value); + return rendererLabel; + } + + public Component getListFocusComponent(com.codename1.ui.List list) { + return null; + } + }); + add(form, largeList, 10, 980, 300, 160); + rendererCalls[0] = 0; + AccessibilityTreeSnapshot first = AccessibilityInspector.snapshot(form); AccessibilityNodeSnapshot headingNode = find(first, heading); AccessibilityNodeSnapshot saveNode = find(first, save); @@ -136,6 +167,7 @@ public boolean perform(Component component, Object argument) { AccessibilityNodeSnapshot tabNode = find(first, semanticTab); AccessibilityNodeSnapshot dialogNode = find(first, semanticDialog); AccessibilityNodeSnapshot virtualHostNode = find(first, virtualHost); + AccessibilityNodeSnapshot largeListNode = find(first, largeList); assertEqual(AccessibilityRole.HEADING, headingNode.getRole(), "heading role"); assertEqual(2, headingNode.getHeadingLevel(), "heading level"); @@ -173,6 +205,15 @@ public boolean perform(Component component, Object argument) { assertEqual("result-42", virtualNode.getVirtualKey(), "stable virtual key"); assertEqual(AccessibilityRole.LIST_ITEM, virtualNode.getRole(), "virtual child role"); assertEqual("Virtual result", first.getNodeAt(20, 830).getLabel(), "virtual child hit testing"); + assertEqual(1000, largeListNode.getCollectionInfo().getRowCount(), "large list collection size"); + assertTrue(largeListNode.getChildIds().size() < 50, + "large list semantics are bounded to the viewport"); + assertTrue(rendererCalls[0] < 100, + "large list semantics do not render every model row"); + assertTrue(largeListNode.getAction(AccessibilityAction.SCROLL_FORWARD) != null, + "large list exposes forward semantic scrolling"); + assertTrue(largeListNode.getAction(AccessibilityAction.SCROLL_BACKWARD) != null, + "large list exposes backward semantic scrolling"); AccessibilityNodeSnapshot formNode = find(first, form); int checkboxPosition = formNode.getChildIds().indexOf(Long.valueOf(checkboxNode.getId()));