From de51aa19d6a8cbd3b83bf469cb89da16f4b6f498 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Mon, 20 Nov 2023 06:56:49 +0000 Subject: [PATCH] 8283214: [macos] Screen magnifier does not show the magnified text for JcomboBox Co-authored-by: Alexey Ivanov Reviewed-by: asemenov, kizune, aivanov --- .../com/apple/laf/AquaComboBoxButton.java | 57 ++++++++++-- .../classes/com/apple/laf/AquaComboBoxUI.java | 33 ++++++- .../TestJComboBoxScreenMagnifier.java | 91 +++++++++++++++++++ .../6567433/UpdateUIRecursionTest.java | 4 +- 4 files changed, 175 insertions(+), 10 deletions(-) create mode 100644 test/jdk/javax/accessibility/JComboBox/TestJComboBoxScreenMagnifier.java diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxButton.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxButton.java index 00ccc12fddc..b79cc98be9d 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxButton.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxButton.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2023, Oracle 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 @@ -25,13 +25,32 @@ package com.apple.laf; -import java.awt.*; +import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Insets; -import javax.swing.*; +import javax.accessibility.AccessibleContext; +import javax.swing.ButtonModel; +import javax.swing.CellRendererPane; +import javax.swing.DefaultButtonModel; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.ListCellRenderer; +import javax.swing.UIManager; import javax.swing.plaf.UIResource; +import apple.laf.JRSUIConstants.AlignmentHorizontal; +import apple.laf.JRSUIConstants.AlignmentVertical; +import apple.laf.JRSUIConstants.ArrowsOnly; +import apple.laf.JRSUIConstants.Focused; +import apple.laf.JRSUIConstants.IndicatorOnly; +import apple.laf.JRSUIConstants.Size; +import apple.laf.JRSUIConstants.State; +import apple.laf.JRSUIConstants.Widget; import apple.laf.JRSUIState; -import apple.laf.JRSUIConstants.*; @SuppressWarnings("serial") // Superclass is not serializable across versions class AquaComboBoxButton extends JButton { @@ -169,12 +188,15 @@ class AquaComboBoxButton extends JButton { } } - protected void doRendererPaint(final Graphics g, final ButtonModel buttonModel, final boolean editable, final Insets insets, int left, int top, int width, int height) { + private Component getRendererComponent() { final ListCellRenderer renderer = comboBox.getRenderer(); + return renderer.getListCellRendererComponent(list, comboBox.getSelectedItem(), -1, false, false); + } + + protected void doRendererPaint(final Graphics g, final ButtonModel buttonModel, final boolean editable, final Insets insets, int left, int top, int width, int height) { // fake it out! not renderPressed - final Component c = renderer.getListCellRendererComponent(list, comboBox.getSelectedItem(), -1, false, false); - // System.err.println("Renderer: " + renderer); + final Component c = getRendererComponent(); if (!editable && !AquaComboBoxUI.isTableCellEditor(comboBox)) { final int indentLeft = 10; @@ -233,4 +255,25 @@ class AquaComboBoxButton extends JButton { // Remove component from renderer pane, allowing it to be gc'ed. rendererPane.remove(c); } + + @Override + public AccessibleContext getAccessibleContext() { + if (accessibleContext == null) { + accessibleContext = new AccessibleAquaComboBoxButton(); + } + return accessibleContext; + } + + private final class AccessibleAquaComboBoxButton extends AccessibleJButton { + @Override + public String getAccessibleName() { + String name = super.getAccessibleName(); + if ((name == null || name.isEmpty()) + && (!comboBox.isEditable() && comboBox.getSelectedItem() != null)) { + Component c = getRendererComponent(); + name = c.getAccessibleContext().getAccessibleName(); + } + return name; + } + } } diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxUI.java index 9027f9e037e..b9b60994085 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2023, Oracle 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 @@ -728,4 +728,35 @@ public class AquaComboBoxUI extends BasicComboBoxUI implements Sizeable { static ClientPropertyApplicator, AquaComboBoxUI> getApplicator() { return APPLICATOR.get(); } + + @Override + public int getAccessibleChildrenCount(JComponent c) { + return 2; + } + + @Override + public Accessible getAccessibleChild(JComponent c, int i) { + // 0 = the popup + // 1 = the editor for editable combobox and the arrow button for non-editable combobox + switch ( i ) { + case 0: + if (popup instanceof Accessible accessiblePopup) { + AccessibleContext ac = accessiblePopup.getAccessibleContext(); + ac.setAccessibleParent(comboBox); + return accessiblePopup; + } + break; + case 1: + if (comboBox.isEditable() + && (editor instanceof Accessible accessibleEditor)) { + AccessibleContext ac = accessibleEditor.getAccessibleContext(); + ac.setAccessibleParent(comboBox); + return accessibleEditor; + } else if (!comboBox.isEditable()) { + return arrowButton; + } + break; + } + return null; + } } diff --git a/test/jdk/javax/accessibility/JComboBox/TestJComboBoxScreenMagnifier.java b/test/jdk/javax/accessibility/JComboBox/TestJComboBoxScreenMagnifier.java new file mode 100644 index 00000000000..8d2bb2415dc --- /dev/null +++ b/test/jdk/javax/accessibility/JComboBox/TestJComboBoxScreenMagnifier.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2023, Oracle 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. + * + * 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.BorderLayout; +import java.awt.GridLayout; +import java.lang.reflect.InvocationTargetException; + +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; + +/* + * @test + * @bug 8283214 + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @requires (os.family == "mac") + * @summary Verifies if item selected in JComboBox magnifies using + * screen magnifier a11y tool + * @run main/manual TestJComboBoxScreenMagnifier + */ + +public class TestJComboBoxScreenMagnifier { + private static JFrame frame; + private static final String INSTRUCTIONS = + "1) Enable Screen magnifier on the Mac\n\n" + + "System Preference -> Accessibility -> Zoom -> " + + "Select \"Enable Hover Text\"\n\n" + + "2) Move the mouse over the combo box and press " + + "\"Command\" button.\n\n" + + "3) If magnified label is visible, press Pass else Fail."; + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException { + PassFailJFrame passFailJFrame = new PassFailJFrame.Builder() + .title("JComboBox Screen Magnifier Test Instructions") + .instructions(INSTRUCTIONS) + .testTimeOut(5) + .rows(12) + .columns(40) + .screenCapture() + .build(); + + SwingUtilities.invokeAndWait(TestJComboBoxScreenMagnifier::createAndShowUI); + passFailJFrame.awaitAndCheck(); + } + + private static void createAndShowUI() { + frame = new JFrame("JComboBox A11Y Screen Magnifier Test"); + + String[] fruits = new String[] {"Apple", "Orange", + "Mango", "Pineapple", "Banana"}; + JComboBox comboBox = new JComboBox(fruits); + JPanel fruitPanel = new JPanel(new GridLayout(1, 2)); + JLabel fruitLabel = new JLabel("Fruits:", JLabel.CENTER); + fruitLabel.getAccessibleContext().setAccessibleName("Fruits Label"); + fruitPanel.add(fruitLabel); + fruitPanel.add(comboBox); + comboBox.getAccessibleContext().setAccessibleName("Fruit Combo box"); + frame.getContentPane().add(fruitPanel, BorderLayout.CENTER); + + PassFailJFrame.addTestWindow(frame); + PassFailJFrame.positionTestWindow(frame, + PassFailJFrame.Position.HORIZONTAL); + frame.pack(); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setVisible(true); + } +} diff --git a/test/jdk/javax/swing/JComboBox/6567433/UpdateUIRecursionTest.java b/test/jdk/javax/swing/JComboBox/6567433/UpdateUIRecursionTest.java index 5745e929abd..532a1b97775 100644 --- a/test/jdk/javax/swing/JComboBox/6567433/UpdateUIRecursionTest.java +++ b/test/jdk/javax/swing/JComboBox/6567433/UpdateUIRecursionTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2023, Oracle 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 @@ -24,7 +24,7 @@ /** * @test * @key headful - * @bug 6567433 + * @bug 6567433 8283214 * * @summary JComboBox.updateUI() invokes updateUI() on its cellrenderer via * SwingUtilities.updateComponentTreeUI().