--- old/src/java.desktop/share/classes/java/awt/Component.java 2016-04-19 12:12:39.576698300 +0300 +++ new/src/java.desktop/share/classes/java/awt/Component.java 2016-04-19 12:12:39.076697600 +0300 @@ -877,8 +877,8 @@ { comp.setGraphicsConfiguration(gc); } - public boolean requestFocus(Component comp, FocusEvent.Cause cause) { - return comp.requestFocus(cause); + public void requestFocus(Component comp, FocusEvent.Cause cause) { + comp.requestFocus(cause); } public boolean canBeFocusOwner(Component comp) { return comp.canBeFocusOwner(); @@ -7537,8 +7537,51 @@ requestFocusHelper(false, true); } - boolean requestFocus(FocusEvent.Cause cause) { - return requestFocusHelper(false, true, cause); + + /** + * Requests by the reason of {@code cause} that this Component get the input + * focus, and that this Component's top-level ancestor become the + * focused Window. This component must be displayable, focusable, visible + * and all of its ancestors (with the exception of the top-level Window) + * must be visible for the request to be granted. Every effort will be + * made to honor the request; however, in some cases it may be + * impossible to do so. Developers must never assume that this + * Component is the focus owner until this Component receives a + * FOCUS_GAINED event. + *

+ * The focus request effect may also depend on the provided + * cause value. If this request is succeed the {@code FocusEvent} + * generated in the result will receive the cause value specified as the + * argument of method. If this request is denied because this Component's + * top-level Window cannot become the focused Window, the request will be + * remembered and will be granted when the Window is later focused by the + * user. + *

+ * This method cannot be used to set the focus owner to no Component at + * all. Use {@code KeyboardFocusManager.clearGlobalFocusOwner()} + * instead. + *

+ * Because the focus behavior of this method is platform-dependent, + * developers are strongly encouraged to use + * {@code requestFocusInWindow(FocusEvent.Cause)} when possible. + * + *

Note: Not all focus transfers result from invoking this method. As + * such, a component may receive focus without this or any of the other + * {@code requestFocus} methods of {@code Component} being invoked. + * + * @param cause the cause why the focus is requested + * @see FocusEvent + * @see FocusEvent.Cause + * @see #requestFocusInWindow(FocusEvent.Cause) + * @see java.awt.event.FocusEvent + * @see #addFocusListener + * @see #isFocusable + * @see #isDisplayable + * @see KeyboardFocusManager#clearGlobalFocusOwner + * @since 9 + */ + public void requestFocus(FocusEvent.Cause cause) { + requestFocusHelper(false, true, cause); } /** @@ -7604,9 +7647,77 @@ return requestFocusHelper(temporary, true); } - boolean requestFocus(boolean temporary, FocusEvent.Cause cause) { + /** + * Requests by the reason of {@code cause} that this {@code Component} get + * the input focus, and that this {@code Component}'s top-level ancestor + * become the focused {@code Window}. This component must be + * displayable, focusable, visible and all of its ancestors (with + * the exception of the top-level Window) must be visible for the + * request to be granted. Every effort will be made to honor the + * request; however, in some cases it may be impossible to do + * so. Developers must never assume that this component is the + * focus owner until this component receives a FOCUS_GAINED + * event. If this request is denied because this component's + * top-level window cannot become the focused window, the request + * will be remembered and will be granted when the window is later + * focused by the user. + *

+ * This method returns a boolean value. If {@code false} is returned, + * the request is guaranteed to fail. If {@code true} is + * returned, the request will succeed unless it is vetoed, or an + * extraordinary event, such as disposal of the component's peer, occurs + * before the request can be granted by the native windowing system. Again, + * while a return value of {@code true} indicates that the request is + * likely to succeed, developers must never assume that this component is + * the focus owner until this component receives a FOCUS_GAINED event. + *

+ * The focus request effect may also depend on the provided + * cause value. If this request is succeed the {FocusEvent} + * generated in the result will receive the cause value specified as the + * argument of the method. + *

+ * This method cannot be used to set the focus owner to no component at + * all. Use {@code KeyboardFocusManager.clearGlobalFocusOwner} + * instead. + *

+ * Because the focus behavior of this method is platform-dependent, + * developers are strongly encouraged to use + * {@code requestFocusInWindow} when possible. + *

+ * Every effort will be made to ensure that {@code FocusEvent}s + * generated as a + * result of this request will have the specified temporary value. However, + * because specifying an arbitrary temporary state may not be implementable + * on all native windowing systems, correct behavior for this method can be + * guaranteed only for lightweight {@code Component}s. + * This method is not intended + * for general use, but exists instead as a hook for lightweight component + * libraries, such as Swing. + *

+ * Note: Not all focus transfers result from invoking this method. As + * such, a component may receive focus without this or any of the other + * {@code requestFocus} methods of {@code Component} being invoked. + * + * @param temporary true if the focus change is temporary, + * such as when the window loses the focus; for + * more information on temporary focus changes see the + *Focus Specification + * + * @param cause the cause why the focus is requested + * @return {@code false} if the focus change request is guaranteed to + * fail; {@code true} if it is likely to succeed + * @see FocusEvent + * @see FocusEvent.Cause + * @see #addFocusListener + * @see #isFocusable + * @see #isDisplayable + * @see KeyboardFocusManager#clearGlobalFocusOwner + * @since 9 + */ + protected boolean requestFocus(boolean temporary, FocusEvent.Cause cause) { return requestFocusHelper(temporary, true, cause); } + /** * Requests that this Component get the input focus, if this * Component's top-level ancestor is already the focused @@ -7655,7 +7766,59 @@ return requestFocusHelper(false, false); } - boolean requestFocusInWindow(FocusEvent.Cause cause) { + /** + * Requests by the reason of {@code cause} that this Component get the input + * focus, if this Component's top-level ancestor is already the focused + * Window. This component must be displayable, focusable, visible + * and all of its ancestors (with the exception of the top-level + * Window) must be visible for the request to be granted. Every + * effort will be made to honor the request; however, in some + * cases it may be impossible to do so. Developers must never + * assume that this Component is the focus owner until this + * Component receives a FOCUS_GAINED event. + *

+ * This method returns a boolean value. If {@code false} is returned, + * the request is guaranteed to fail. If {@code true} is + * returned, the request will succeed unless it is vetoed, or an + * extraordinary event, such as disposal of the Component's peer, occurs + * before the request can be granted by the native windowing system. Again, + * while a return value of {@code true} indicates that the request is + * likely to succeed, developers must never assume that this Component is + * the focus owner until this Component receives a FOCUS_GAINED event. + *

+ * The focus request effect may also depend on the provided + * cause value. If this request is succeed the {@code FocusEvent} + * generated in the result will receive the cause value specified as the + * argument of the method. + *

+ * This method cannot be used to set the focus owner to no Component at + * all. Use {@code KeyboardFocusManager.clearGlobalFocusOwner()} + * instead. + *

+ * The focus behavior of this method can be implemented uniformly across + * platforms, and thus developers are strongly encouraged to use this + * method over {@code requestFocus(FocusEvent.Cause)} when possible. + * Code which relies on {@code requestFocus(FocusEvent.Cause)} may exhibit + * different focus behavior on different platforms. + * + *

Note: Not all focus transfers result from invoking this method. As + * such, a component may receive focus without this or any of the other + * {@code requestFocus} methods of {@code Component} being invoked. + * + * @param cause the cause why the focus is requested + * @return {@code false} if the focus change request is guaranteed to + * fail; {@code true} if it is likely to succeed + * @see #requestFocus(FocusEvent.Cause) + * @see FocusEvent + * @see FocusEvent.Cause + * @see java.awt.event.FocusEvent + * @see #addFocusListener + * @see #isFocusable + * @see #isDisplayable + * @see KeyboardFocusManager#clearGlobalFocusOwner + * @since 9 + */ + public boolean requestFocusInWindow(FocusEvent.Cause cause) { return requestFocusHelper(false, false, cause); } --- old/src/java.desktop/share/classes/sun/awt/AWTAccessor.java 2016-04-19 12:12:44.052705500 +0300 +++ new/src/java.desktop/share/classes/sun/awt/AWTAccessor.java 2016-04-19 12:12:43.542704700 +0300 @@ -105,7 +105,7 @@ /* * Requests focus to the component. */ - boolean requestFocus(Component comp, Cause cause); + void requestFocus(Component comp, Cause cause); /* * Determines if the component can gain focus. */ --- old/src/java.desktop/share/classes/sun/awt/KeyboardFocusManagerPeerImpl.java 2016-04-19 12:12:46.680709600 +0300 +++ new/src/java.desktop/share/classes/sun/awt/KeyboardFocusManagerPeerImpl.java 2016-04-19 12:12:46.162708400 +0300 @@ -142,8 +142,8 @@ } // WARNING: Don't call it on the Toolkit thread. - public static boolean requestFocusFor(Component target, FocusEvent.Cause cause) { - return AWTAccessor.getComponentAccessor().requestFocus(target, cause); + public static void requestFocusFor(Component target, FocusEvent.Cause cause) { + AWTAccessor.getComponentAccessor().requestFocus(target, cause); } // WARNING: Don't call it on the Toolkit thread. --- /dev/null 2016-04-19 12:12:49.000000000 +0300 +++ new/test/java/awt/Focus/RequestFocusByCause/RequestFocusByCauseTest.java 2016-04-19 12:12:48.686714400 +0300 @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2016, 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. + */ + +/* + @test + @bug 8154434 + @summary Open the request focus methods of the java.awt.Component which accept + FocusEvent.Cause + @run main RequestFocusByCauseTest +*/ + +import java.awt.*; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; + +public class RequestFocusByCauseTest { + static boolean success; + + public static void main(String[] args) throws Exception { + testRequestFocusCause(); + testRequestFocusTemporaryCause(); + testRequestFocusInWindowCause(); + System.out.println("ok"); + } + + private static void testRequestFocusCause() throws AWTException { + Frame frame = new Frame(); + Component c = new Button(); + frame.add(new Button()); + frame.add(c); + c.addFocusListener(new FocusListener() { + @Override + public void focusGained(FocusEvent e) { + success = e.getCause() == FocusEvent.Cause.UNEXPECTED; + } + + @Override + public void focusLost(FocusEvent e) {} + }); + Robot robot = new Robot(); + + try { + frame.setVisible(true); + robot.waitForIdle(); + robot.delay(200); + success = false; + + c.requestFocus(FocusEvent.Cause.UNEXPECTED); + robot.waitForIdle(); + robot.delay(200); + if(!success) { + throw new RuntimeException("request failed"); + } + } finally { + frame.dispose(); + } + } + + private static void testRequestFocusTemporaryCause() throws AWTException { + Frame frame = new Frame(); + frame.add(new Button() { + @Override + protected boolean requestFocus(boolean temporary, + FocusEvent.Cause cause) { + success = cause == FocusEvent.Cause.ROLLBACK; + return super.requestFocus(temporary, cause); + } + }); + Component c = new Button() { + @Override + public void requestFocus() { + super.requestFocus(); + setFocusable(false); + } + }; + frame.add(c); + Robot robot = new Robot(); + + try { + frame.setVisible(true); + robot.waitForIdle(); + robot.delay(200); + + success = false; + c.requestFocus(); + robot.waitForIdle(); + robot.delay(200); + + + if(!success) { + throw new RuntimeException("rollback request is not triggered"); + } + } finally { + frame.dispose(); + } + } + + private static void testRequestFocusInWindowCause() throws AWTException { + Frame frame = new Frame(); + Component c = new Button(); + frame.add(new Button()); + frame.add(c); + c.addFocusListener(new FocusListener() { + @Override + public void focusGained(FocusEvent e) { + success = e.getCause() == FocusEvent.Cause.UNEXPECTED; + } + + @Override + public void focusLost(FocusEvent e) { + } + }); + Robot robot = new Robot(); + + try { + frame.setVisible(true); + robot.waitForIdle(); + robot.delay(200); + success = false; + + c.requestFocusInWindow(FocusEvent.Cause.UNEXPECTED); + robot.waitForIdle(); + robot.delay(200); + if (!success) { + throw new RuntimeException("request in window failed"); + } + } finally { + frame.dispose(); + } + } +} \ No newline at end of file