Skip to content

Commit 76682b6

Browse files
committed
8286204: [Accessibility,macOS,VoiceOver] VoiceOver reads the spinner value 10 as 1 when user iterates to 10 for the first time on macOS
Backport-of: cd9f1d3d921531511a7552807d099d5d3cce01a6
1 parent 9adc9eb commit 76682b6

File tree

2 files changed

+81
-1
lines changed

2 files changed

+81
-1
lines changed

src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessible.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232

3333
import javax.accessibility.Accessible;
3434
import javax.accessibility.AccessibleContext;
35+
import javax.swing.JSpinner;
3536
import javax.swing.JTabbedPane;
3637

3738
import static javax.accessibility.AccessibleContext.ACCESSIBLE_ACTIVE_DESCENDANT_PROPERTY;
@@ -121,7 +122,11 @@ public void propertyChange(PropertyChangeEvent e) {
121122
if (name.equals(ACCESSIBLE_CARET_PROPERTY)) {
122123
selectedTextChanged(ptr);
123124
} else if (name.equals(ACCESSIBLE_TEXT_PROPERTY)) {
124-
valueChanged(ptr);
125+
AccessibleContext thisAC = accessible.getAccessibleContext();
126+
Accessible parentAccessible = thisAC.getAccessibleParent();
127+
if (!(parentAccessible instanceof JSpinner.NumberEditor)) {
128+
valueChanged(ptr);
129+
}
125130
} else if (name.equals(ACCESSIBLE_SELECTION_PROPERTY)) {
126131
selectionChanged(ptr);
127132
} else if (name.equals(ACCESSIBLE_TABLE_MODEL_CHANGED)) {
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*
2+
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
import java.awt.BorderLayout;
25+
26+
import javax.swing.JFrame;
27+
import javax.swing.JSpinner;
28+
import javax.swing.SpinnerModel;
29+
import javax.swing.SpinnerNumberModel;
30+
31+
/*
32+
* @test
33+
* @bug 8286204
34+
* @summary Verifies that VoiceOver announces the JSpinner's value correctly
35+
* @requires os.family == "mac"
36+
* @library /java/awt/regtesthelpers
37+
* @build PassFailJFrame
38+
* @run main/manual TestJSpinnerAccessibility
39+
*/
40+
41+
public class TestJSpinnerAccessibility {
42+
public static void main(String[] args) throws Exception {
43+
String INSTRUCTIONS = """
44+
Test UI contains a JSpinner with minimum value 0, maximum value 20
45+
and current value 5. On press of up / down arrow, value will be
46+
incremented / decremented by 1.
47+
48+
Follow these steps to test the behaviour:
49+
50+
1. Start the VoiceOver (Press Command + F5) application
51+
2. Move focus on test window if it is not focused
52+
3. Press Up / Down arrow to increase / decrease Spinner value
53+
4. VO should announce correct values in terms of percentage
54+
(e.g. For JSpinner's value 10, VO should announce 50%)
55+
5. Press Pass if you are able to hear correct announcements
56+
else Fail""";
57+
58+
PassFailJFrame.builder()
59+
.title("TestJSpinnerAccessibility Instruction")
60+
.instructions(INSTRUCTIONS)
61+
.columns(40)
62+
.testUI(TestJSpinnerAccessibility::createUI)
63+
.build()
64+
.awaitAndCheck();
65+
}
66+
67+
private static JFrame createUI() {
68+
JFrame frame = new JFrame("A Frame with JSpinner");
69+
SpinnerModel spinnerModel = new SpinnerNumberModel(5, 0, 20, 1);
70+
JSpinner spinner = new JSpinner(spinnerModel);
71+
frame.getContentPane().add(spinner, BorderLayout.CENTER);
72+
frame.setSize(200, 100);
73+
return frame;
74+
}
75+
}

0 commit comments

Comments
 (0)