changeset 2514:d7b761a77f0d

No focus to disabled components.
author Denis Lila <dlila@redhat.com>
date Fri, 20 May 2011 08:56:33 -0400
parents 711c59eac969
children a86451f457c2
files ChangeLog Makefile.am NEWS patches/openjdk/4685768-focus.patch
diffstat 4 files changed, 407 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Wed May 18 09:06:00 2011 -0400
+++ b/ChangeLog	Fri May 20 08:56:33 2011 -0400
@@ -1,3 +1,10 @@
+2011-05-19  Denis Lila <dlila@redhat.com>
+
+	* Makefile.am: Apply patch.
+	* NEWS: Update with backport.
+	* patches/openjdk/4685768-focus.patchpatch: The restore focus
+	procedure now skips disabled components.
+
 2011-05-17  Denis Lila <dlila@redhat.com>
 
 	* Makefile.am: Apply patch.
--- a/Makefile.am	Wed May 18 09:06:00 2011 -0400
+++ b/Makefile.am	Fri May 20 08:56:33 2011 -0400
@@ -200,6 +200,7 @@
 	patches/openjdk/6637796-set_bounds.patch \
 	patches/openjdk/6607660-treelock.patch \
 	patches/openjdk/6607170-request_focus.patch \
+	patches/openjdk/4685768-focus.patch \
 	patches/openjdk/6616323-component_array.patch \
 	patches/openjdk/6682046-shape_calculation.patch \
 	patches/openjdk/6797195-hw_lw_mixing.patch \
--- a/NEWS	Wed May 18 09:06:00 2011 -0400
+++ b/NEWS	Fri May 20 08:56:33 2011 -0400
@@ -25,6 +25,7 @@
   - Add missing privileged block around access to the sun.awt.nativedebug property.
   - S7032388, PR682: Make HotSpot work on machines without cmov instruction again
   - S7031385, PR680: Incorrect register allocation in orderAccess_linux_x86.inline.hpp
+  - S4685768: Focus set to disabled component, can't Tab/Shift-Tab 
 * Fixes
   - G356743: Support libpng 1.5.
 * CACAO
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/openjdk/4685768-focus.patch	Fri May 20 08:56:33 2011 -0400
@@ -0,0 +1,398 @@
+# HG changeset patch
+# User ant
+# Date 1213695448 -14400
+# Node ID a9b5b5d105a8e613fe8ebacba01fa010ff087d3e
+# Parent  58a2ba2767bef1b7ca6d994d94c0812216b4f5ad
+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
+
+diff -r 58a2ba2767be -r a9b5b5d105a8 src/share/classes/java/awt/Component.java
+--- openjdk.orig/jdk/src/share/classes/java/awt/Component.java	Wed Jun 11 01:31:42 2008 -0700
++++ openjdk/jdk/src/share/classes/java/awt/Component.java	Tue Jun 17 13:37:28 2008 +0400
+@@ -7488,9 +7488,7 @@
+         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 @@
+         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 @@
+         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 @@
+      * 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;
+         }
+ 
+diff -r 58a2ba2767be -r a9b5b5d105a8 src/share/classes/java/awt/Container.java
+--- openjdk.orig/jdk/src/share/classes/java/awt/Container.java	Wed Jun 11 01:31:42 2008 -0700
++++ openjdk/jdk/src/share/classes/java/awt/Container.java	Tue Jun 17 13:37:28 2008 +0400
+@@ -860,11 +860,11 @@
+ 
+             // 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();
+                 }
+             }
+diff -r 58a2ba2767be -r a9b5b5d105a8 src/share/classes/java/awt/ContainerOrderFocusTraversalPolicy.java
+--- openjdk.orig/jdk/src/share/classes/java/awt/ContainerOrderFocusTraversalPolicy.java	Wed Jun 11 01:31:42 2008 -0700
++++ openjdk/jdk/src/share/classes/java/awt/ContainerOrderFocusTraversalPolicy.java	Tue Jun 17 13:37:28 2008 +0400
+@@ -556,8 +556,7 @@
+      *         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;
+         }
+ 
+diff -r 58a2ba2767be -r a9b5b5d105a8 src/share/classes/java/awt/DefaultKeyboardFocusManager.java
+--- openjdk.orig/jdk/src/share/classes/java/awt/DefaultKeyboardFocusManager.java	Wed Jun 11 01:31:42 2008 -0700
++++ openjdk/jdk/src/share/classes/java/awt/DefaultKeyboardFocusManager.java	Tue Jun 17 13:37:28 2008 +0400
+@@ -154,7 +154,7 @@
+     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 @@
+                     }
+                 }
+ 
+-                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 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()) {
+diff -r 58a2ba2767be -r a9b5b5d105a8 src/share/classes/java/awt/Window.java
+--- openjdk.orig/jdk/src/share/classes/java/awt/Window.java	Wed Jun 11 01:31:42 2008 -0700
++++ openjdk/jdk/src/share/classes/java/awt/Window.java	Tue Jun 17 13:37:28 2008 +0400
+@@ -3145,9 +3145,7 @@
+         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;
+diff -r 58a2ba2767be -r a9b5b5d105a8 test/java/awt/Focus/NoAutotransferToDisabledCompTest/NoAutotransferToDisabledCompTest.java
+--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
++++ openjdk/jdk/test/java/awt/Focus/NoAutotransferToDisabledCompTest/NoAutotransferToDisabledCompTest.java	Tue Jun 17 13:37:28 2008 +0400
+@@ -0,0 +1,109 @@
++/*
++ * 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);
++    }
++}
++
+diff -r 58a2ba2767be -r a9b5b5d105a8 test/java/awt/Focus/RequestFocusToDisabledCompTest/RequestFocusToDisabledCompTest.java
+--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
++++ openjdk/jdk/test/java/awt/Focus/RequestFocusToDisabledCompTest/RequestFocusToDisabledCompTest.java	Tue Jun 17 13:37:28 2008 +0400
+@@ -0,0 +1,97 @@
++/*
++ * 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);
++    }
++}
+diff -r 58a2ba2767be -r a9b5b5d105a8 test/java/awt/regtesthelpers/Util.java
+--- openjdk.orig/jdk/test/java/awt/regtesthelpers/Util.java	Wed Jun 11 01:31:42 2008 -0700
++++ openjdk/jdk/test/java/awt/regtesthelpers/Util.java	Tue Jun 17 13:37:28 2008 +0400
+@@ -124,6 +124,14 @@
+     }
+ 
+     /**
++     * 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 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);
++
++    }
+ }
+exporting patch:
+<fdopen>