8226653: [accessibility] Can edit text cell correctly, but Accessibility Tool reads nothing about editor
authorserb
Mon, 15 Jul 2019 16:25:23 -0700
changeset 55699 04d80e7ad3f4
parent 55698 284ac8027efa
child 55700 1bb102c1cf27
8226653: [accessibility] Can edit text cell correctly, but Accessibility Tool reads nothing about editor Reviewed-by: prr
src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessible.java
src/java.desktop/share/classes/javax/swing/JTable.java
test/jdk/javax/accessibility/JTable/JTableCellEditor.java
--- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessible.java	Mon Jul 15 09:53:23 2019 -0700
+++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessible.java	Mon Jul 15 16:25:23 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2019, 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
@@ -34,7 +34,6 @@
 import javax.swing.JProgressBar;
 import javax.swing.JTabbedPane;
 import javax.swing.JSlider;
-import javax.swing.JCheckBox;
 import javax.swing.event.ChangeEvent;
 import javax.swing.event.ChangeListener;
 
@@ -42,6 +41,7 @@
 import static javax.accessibility.AccessibleContext.ACCESSIBLE_CARET_PROPERTY;
 import static javax.accessibility.AccessibleContext.ACCESSIBLE_SELECTION_PROPERTY;
 import static javax.accessibility.AccessibleContext.ACCESSIBLE_STATE_PROPERTY;
+import static javax.accessibility.AccessibleContext.ACCESSIBLE_TABLE_MODEL_CHANGED;
 import static javax.accessibility.AccessibleContext.ACCESSIBLE_TEXT_PROPERTY;
 import static javax.accessibility.AccessibleContext.ACCESSIBLE_NAME_PROPERTY;
 
@@ -129,6 +129,8 @@
                     valueChanged(ptr);
                 } else if (name.compareTo(ACCESSIBLE_SELECTION_PROPERTY) == 0) {
                     selectionChanged(ptr);
+                } else if (name.compareTo(ACCESSIBLE_TABLE_MODEL_CHANGED) == 0) {
+                    valueChanged(ptr);
                 } else if (name.compareTo(ACCESSIBLE_ACTIVE_DESCENDANT_PROPERTY) == 0 ) {
                     if (newValue instanceof AccessibleContext) {
                         activeDescendant = (AccessibleContext)newValue;
--- a/src/java.desktop/share/classes/javax/swing/JTable.java	Mon Jul 15 09:53:23 2019 -0700
+++ b/src/java.desktop/share/classes/javax/swing/JTable.java	Mon Jul 15 16:25:23 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, 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
@@ -5278,7 +5278,8 @@
                 // Don't start when just a modifier is pressed
                 int code = e.getKeyCode();
                 if (code == KeyEvent.VK_SHIFT || code == KeyEvent.VK_CONTROL ||
-                    code == KeyEvent.VK_ALT) {
+                    code == KeyEvent.VK_ALT || code == KeyEvent.VK_META ||
+                    code == KeyEvent.VK_ALT_GRAPH) {
                     return false;
                 }
                 // Try to install the editor
@@ -5302,7 +5303,9 @@
                 // If we have started an editor as a result of the user
                 // pressing a key and the surrendersFocusOnKeystroke property
                 // is true, give the focus to the new editor.
-                if (getSurrendersFocusOnKeystroke()) {
+                Object prop = getClientProperty("JTable.forceAutoStartsEdit");
+                if (getSurrendersFocusOnKeystroke()
+                        || Boolean.TRUE.equals(prop)) {
                     editorComponent.requestFocus();
                 }
             }
@@ -6668,6 +6671,7 @@
          */
         protected AccessibleJTable() {
             super();
+            JTable.this.putClientProperty("JTable.forceAutoStartsEdit", true);
             JTable.this.addPropertyChangeListener(this);
             JTable.this.getSelectionModel().addListSelectionListener(this);
             TableColumnModel tcm = JTable.this.getColumnModel();
@@ -7104,15 +7108,12 @@
             int row = rowAtPoint(p);
 
             if ((column != -1) && (row != -1)) {
-                TableColumn aColumn = getColumnModel().getColumn(column);
-                TableCellRenderer renderer = aColumn.getCellRenderer();
-                if (renderer == null) {
-                    Class<?> columnClass = getColumnClass(column);
-                    renderer = getDefaultRenderer(columnClass);
-                }
-                Component component = renderer.getTableCellRendererComponent(
-                                  JTable.this, null, false, false,
-                                  row, column);
+                if (row == getEditingRow() && column == getEditingColumn()) {
+                    Component editor = getEditorComponent();
+                    if (editor instanceof Accessible) {
+                        return (Accessible) editor;
+                    }
+                }
                 return new AccessibleJTableCell(JTable.this, row, column,
                       getAccessibleIndexAt(row, column));
             }
@@ -7145,15 +7146,12 @@
                 int column = getAccessibleColumnAtIndex(i);
                 int row = getAccessibleRowAtIndex(i);
 
-                TableColumn aColumn = getColumnModel().getColumn(column);
-                TableCellRenderer renderer = aColumn.getCellRenderer();
-                if (renderer == null) {
-                    Class<?> columnClass = getColumnClass(column);
-                    renderer = getDefaultRenderer(columnClass);
-                }
-                Component component = renderer.getTableCellRendererComponent(
-                                  JTable.this, null, false, false,
-                                  row, column);
+                if (row == getEditingRow() && column == getEditingColumn()) {
+                    Component editor = getEditorComponent();
+                    if (editor instanceof Accessible) {
+                        return (Accessible) editor;
+                    }
+                }
                 return new AccessibleJTableCell(JTable.this, row, column,
                       getAccessibleIndexAt(row, column));
             }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/accessibility/JTable/JTableCellEditor.java	Mon Jul 15 16:25:23 2019 -0700
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2019, 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.EventQueue;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Locale;
+
+import javax.accessibility.AccessibleRole;
+import javax.accessibility.AccessibleTable;
+import javax.swing.JFrame;
+import javax.swing.JTable;
+import javax.swing.table.DefaultTableModel;
+import javax.swing.table.TableModel;
+
+/**
+ * @test
+ * @bug 8226653
+ * @key headful
+ * @summary The active cell editor should be reported as a child of the table.
+ *          Note that the accessibility API ignores the real children of the
+ *          table, but reports the "virtual" child per cell in the grid.
+ */
+public final class JTableCellEditor {
+
+    private static final int COUNT = 3;
+    private static JTable table;
+    private static JFrame frame;
+
+    public static void main(final String[] args)
+            throws InvocationTargetException, InterruptedException {
+        EventQueue.invokeAndWait(() -> {
+            frame = new JFrame();
+            table = new JTable(testSelectionWithFilterTable());
+            frame.add(table);
+            frame.pack();
+        });
+        EventQueue.invokeAndWait(() -> table.editCellAt(1, 1));
+        EventQueue.invokeAndWait(() -> {
+            AccessibleTable aTable = table.getAccessibleContext()
+                                          .getAccessibleTable();
+            int aColumns = aTable.getAccessibleColumnCount();
+            int aRows = aTable.getAccessibleRowCount();
+            // We cannot assume which component will be used as an editor of the
+            // table cell, but we can expect it will have the "text" role.
+            AccessibleRole role = aTable.getAccessibleAt(1, 1)
+                                        .getAccessibleContext()
+                                        .getAccessibleRole();
+            frame.dispose();
+            if (!role.toDisplayString(Locale.ENGLISH).equals("text")) {
+                throw new RuntimeException("Unexpected role: " + role);
+            }
+            if (aColumns != COUNT) {
+                throw new RuntimeException("Wrong columns: " + aColumns);
+            }
+            if (aRows != COUNT) {
+                throw new RuntimeException("Wrong rows: " + aRows);
+            }
+        });
+    }
+
+    /**
+     * Creates a dummy table model.
+     */
+    private static TableModel testSelectionWithFilterTable() {
+        DefaultTableModel model = new DefaultTableModel(0, 3);
+        for (int i = 0; i < COUNT; i++) {
+            model.addRow(new Object[]{i + "x0", i + "x1", i + "x2"});
+        }
+        return model;
+    }
+}