提交 1896053f 编写于 作者: A ant

4685768: A11y issue - Focus set to disabled component, can't Tab/Shift-Tab

Summary: The restore-focus procedure should skip disabled components.
Reviewed-by: art, dcherepanov
上级 6cac52b9
......@@ -7488,9 +7488,7 @@ public abstract class Component implements ImageObserver, MenuContainer,
Container rootAncestor = getTraversalRoot();
Component comp = this;
while (rootAncestor != null &&
!(rootAncestor.isShowing() &&
rootAncestor.isFocusable() &&
rootAncestor.isEnabled()))
!(rootAncestor.isShowing() && rootAncestor.canBeFocusOwner()))
{
comp = rootAncestor;
rootAncestor = comp.getFocusCycleRootAncestor();
......@@ -7539,9 +7537,7 @@ public abstract class Component implements ImageObserver, MenuContainer,
Container rootAncestor = getTraversalRoot();
Component comp = this;
while (rootAncestor != null &&
!(rootAncestor.isShowing() &&
rootAncestor.isFocusable() &&
rootAncestor.isEnabled()))
!(rootAncestor.isShowing() && rootAncestor.canBeFocusOwner()))
{
comp = rootAncestor;
rootAncestor = comp.getFocusCycleRootAncestor();
......@@ -8518,6 +8514,14 @@ public abstract class Component implements ImageObserver, MenuContainer,
setComponentOrientation(orientation);
}
final boolean canBeFocusOwner() {
// It is enabled, visible, focusable.
if (isEnabled() && isDisplayable() && isVisible() && isFocusable()) {
return true;
}
return false;
}
/**
* Checks that this component meets the prerequesites to be focus owner:
* - it is enabled, visible, focusable
......@@ -8527,9 +8531,9 @@ public abstract class Component implements ImageObserver, MenuContainer,
* this component as focus owner
* @since 1.5
*/
final boolean canBeFocusOwner() {
final boolean canBeFocusOwnerRecursively() {
// - it is enabled, visible, focusable
if (!(isEnabled() && isDisplayable() && isVisible() && isFocusable())) {
if (!canBeFocusOwner()) {
return false;
}
......
......@@ -860,11 +860,11 @@ public class Container extends Component {
// If component is focus owner or parent container of focus owner check that after reparenting
// focus owner moved out if new container prohibit this kind of focus owner.
if (comp.isFocusOwner() && !comp.canBeFocusOwner()) {
if (comp.isFocusOwner() && !comp.canBeFocusOwnerRecursively()) {
comp.transferFocus();
} else if (comp instanceof Container) {
Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
if (focusOwner != null && isParentOf(focusOwner) && !focusOwner.canBeFocusOwner()) {
if (focusOwner != null && isParentOf(focusOwner) && !focusOwner.canBeFocusOwnerRecursively()) {
focusOwner.transferFocus();
}
}
......
......@@ -556,8 +556,7 @@ public class ContainerOrderFocusTraversalPolicy extends FocusTraversalPolicy
* enabled, and focusable; <code>false</code> otherwise
*/
protected boolean accept(Component aComponent) {
if (!(aComponent.isVisible() && aComponent.isDisplayable() &&
aComponent.isFocusable() && aComponent.isEnabled())) {
if (!aComponent.canBeFocusOwner()) {
return false;
}
......
......@@ -154,7 +154,7 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager {
private boolean doRestoreFocus(Component toFocus, Component vetoedComponent,
boolean clearOnFailure)
{
if (toFocus != vetoedComponent && toFocus.isShowing() && toFocus.isFocusable() &&
if (toFocus != vetoedComponent && toFocus.isShowing() && toFocus.canBeFocusOwner() &&
toFocus.requestFocus(false, CausedFocusEvent.Cause.ROLLBACK))
{
return true;
......@@ -500,8 +500,11 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager {
}
}
if (!(newFocusOwner.isFocusable() && newFocusOwner.isEnabled()
&& newFocusOwner.isShowing()))
if (!(newFocusOwner.isFocusable() && newFocusOwner.isShowing() &&
// Refuse focus on a disabled component if the focus event
// isn't of UNKNOWN reason (i.e. not a result of a direct request
// but traversal, activation or system generated).
(newFocusOwner.isEnabled() || cause.equals(CausedFocusEvent.Cause.UNKNOWN))))
{
// we should not accept focus on such component, so reject it.
dequeueKeyEvents(-1, newFocusOwner);
......@@ -742,8 +745,7 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager {
public boolean dispatchKeyEvent(KeyEvent e) {
Component focusOwner = (((AWTEvent)e).isPosted) ? getFocusOwner() : e.getComponent();
if (focusOwner != null && focusOwner.isShowing() &&
focusOwner.isFocusable() && focusOwner.isEnabled()) {
if (focusOwner != null && focusOwner.isShowing() && focusOwner.canBeFocusOwner()) {
if (!e.isConsumed()) {
Component comp = e.getComponent();
if (comp != null && comp.isEnabled()) {
......
......@@ -3145,9 +3145,7 @@ public class Window extends Container implements Accessible {
Component previousComp = temporaryLostComponent;
// Check that "component" is an acceptable focus owner and don't store it otherwise
// - or later we will have problems with opposite while handling WINDOW_GAINED_FOCUS
if (component == null
|| (component.isDisplayable() && component.isVisible() && component.isEnabled() && component.isFocusable()))
{
if (component == null || component.canBeFocusOwner()) {
temporaryLostComponent = component;
} else {
temporaryLostComponent = null;
......
/*
* Copyright 2008 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
@test
@bug 4685768
@summary Tests that auto-transfering focus doesn't stuck on a disabled component.
@author Anton Tarasov: area=awt.focus
@library ../../regtesthelpers
@build Util
@run main NoAutotransferToDisabledCompTest
*/
import java.awt.Robot;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.applet.Applet;
import test.java.awt.regtesthelpers.Util;
public class NoAutotransferToDisabledCompTest extends Applet {
Robot robot;
JFrame frame = new JFrame("Frame");
JButton b0 = new JButton("b0");
JButton b1 = new JButton("b1");
JButton b2 = new JButton("b2");
public static void main(String[] args) {
NoAutotransferToDisabledCompTest app = new NoAutotransferToDisabledCompTest();
app.init();
app.start();
}
public void init() {
robot = Util.createRobot();
frame.add(b0);
frame.add(b1);
frame.add(b2);
frame.setLayout(new FlowLayout());
frame.pack();
b1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
b1.setEnabled(false);
b2.setEnabled(false);
}
});
}
public void start() {
Util.showWindowWait(frame);
// Request focus on b1.
if (!Util.focusComponent(b1, 2000)) {
throw new TestErrorException("couldn't focus " + b1);
}
// Activate b1.
robot.keyPress(KeyEvent.VK_SPACE);
robot.delay(50);
robot.keyRelease(KeyEvent.VK_SPACE);
Util.waitForIdle(robot);
// Check that focus has been transfered to b0.
if (!b0.hasFocus()) {
throw new TestFailedException("focus wasn't auto-transfered properly!");
}
System.out.println("Test passed.");
}
}
/**
* Thrown when the behavior being verified is found wrong.
*/
class TestFailedException extends RuntimeException {
TestFailedException(String msg) {
super("Test failed: " + msg);
}
}
/**
* Thrown when an error not related to the behavior being verified is encountered.
*/
class TestErrorException extends RuntimeException {
TestErrorException(String msg) {
super("Unexpected error: " + msg);
}
}
/*
* Copyright 2008 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
@test
@bug 4685768
@summary Tests that it's possible to manually request focus on a disabled component.
@author Anton Tarasov: area=awt.focus
@library ../../regtesthelpers
@build Util
@run main RequestFocusToDisabledCompTest
*/
import java.awt.Robot;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.applet.Applet;
import test.java.awt.regtesthelpers.Util;
public class RequestFocusToDisabledCompTest extends Applet {
Robot robot;
JFrame frame = new JFrame("Frame");
JButton b0 = new JButton("b0");
JButton b1 = new JButton("b1");
public static void main(String[] args) {
RequestFocusToDisabledCompTest app = new RequestFocusToDisabledCompTest();
app.init();
app.start();
}
public void init() {
robot = Util.createRobot();
frame.add(b0);
frame.add(b1);
frame.setLayout(new FlowLayout());
frame.pack();
b1.setEnabled(false);
}
public void start() {
Util.showWindowWait(frame);
if (!b0.hasFocus()) {
// Request focus on b0.
if (!Util.focusComponent(b0, 2000)) {
throw new TestErrorException("couldn't focus " + b0);
}
}
// Try to request focus on b1.
if (!Util.focusComponent(b1, 2000)) {
throw new TestFailedException("focus wasn't requested on disabled " + b1);
}
System.out.println("Test passed.");
}
}
/**
* Thrown when the behavior being verified is found wrong.
*/
class TestFailedException extends RuntimeException {
TestFailedException(String msg) {
super("Test failed: " + msg);
}
}
/**
* Thrown when an error not related to the behavior being verified is encountered.
*/
class TestErrorException extends RuntimeException {
TestErrorException(String msg) {
super("Unexpected error: " + msg);
}
}
......@@ -123,6 +123,14 @@ public final class Util {
throw new RuntimeException("Unexpected toolkit - " + tk);
}
/**
* Makes the window visible and waits until it's shown.
*/
public static void showWindowWait(Window win) {
win.setVisible(true);
waitTillShown(win);
}
/**
* Moves mouse pointer in the center of given {@code comp} component
* using {@code robot} parameter.
......@@ -574,4 +582,22 @@ public final class Util {
public static boolean trackActionPerformed(Button button, Runnable action, int time, boolean printEvent) {
return trackEvent(ActionEvent.ACTION_PERFORMED, button, action, time, printEvent);
}
/*
* Requests focus on the component provided and waits for the result.
* @return true if the component has been focused, false otherwise.
*/
public static boolean focusComponent(Component comp, int time) {
return focusComponent(comp, time, false);
}
public static boolean focusComponent(final Component comp, int time, boolean printEvent) {
return trackFocusGained(comp,
new Runnable() {
public void run() {
comp.requestFocus();
}
},
time, printEvent);
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册