提交 35d6ef29 编写于 作者: A ant

6522725: Component in a minimized Frame has focus and receives key events

Summary: XAWT: a window natively focused may request focus in it only synthetically
Reviewed-by: son
上级 9841fcb8
......@@ -420,40 +420,36 @@ public class XComponentPeer extends XWindow implements ComponentPeer, DropTarget
case SNFH_SUCCESS_PROCEED:
// Currently we just generate focus events like we deal with lightweight instead of calling
// XSetInputFocus on native window
if (focusLog.isLoggable(Level.FINER)) focusLog.finer("Proceeding with request to " + lightweightChild + " in " + target);
if (focusLog.isLoggable(Level.FINER)) focusLog.finer("Proceeding with request to " +
lightweightChild + " in " + target);
/**
* The problems with requests in non-focused window arise because shouldNativelyFocusHeavyweight
* checks that native window is focused while appropriate WINDOW_GAINED_FOCUS has not yet
* been processed - it is in EventQueue. Thus, SNFH allows native request and stores request record
* in requests list - and it breaks our requests sequence as first record on WGF should be the last focus
* owner which had focus before WLF. So, we should not add request record for such requests
* in requests list - and it breaks our requests sequence as first record on WGF should be the last
* focus owner which had focus before WLF. So, we should not add request record for such requests
* but store this component in mostRecent - and return true as before for compatibility.
*/
Window parentWindow = getContainingWindow(target);
if (parentWindow != null) {
// and check that it is focused
if (!parentWindow.isFocused()) {
XWindowPeer wpeer = (XWindowPeer)parentWindow.getPeer();
/*
* Fix for 6314575.
* Shouldn't restore focus on 'actualFocusedWindow'
* when a component inside a Frame is requesting it.
*/
wpeer.setActualFocusedWindow(null);
boolean res = wpeer.requestWindowFocus();
if (focusLog.isLoggable(Level.FINER)) focusLog.finer("Requested window focus: " + res);
// If parent window can be made focused and has been made focused(synchronously)
// then we can proceed with children, otherwise we retreat.
if (!(res && parentWindow.isFocused())) {
focusLog.finer("Waiting for asynchronous processing of window focus request");
KeyboardFocusManagerPeerImpl.removeLastFocusRequest(target);
return false;
}
}
} else {
if (focusLog.isLoggable(Level.FINER)) focusLog.finer("WARNING: Parent window is null");
return false;
if (parentWindow == null) {
return rejectFocusRequestHelper("WARNING: Parent window is null");
}
XWindowPeer wpeer = (XWindowPeer)parentWindow.getPeer();
if (wpeer == null) {
return rejectFocusRequestHelper("WARNING: Parent window's peer is null");
}
/*
* Passing null 'actualFocusedWindow' as we don't want to restore focus on it
* when a component inside a Frame is requesting focus.
* See 6314575 for details.
*/
boolean res = wpeer.requestWindowFocus(null);
if (focusLog.isLoggable(Level.FINER)) focusLog.finer("Requested window focus: " + res);
// If parent window can be made focused and has been made focused(synchronously)
// then we can proceed with children, otherwise we retreat.
if (!(res && parentWindow.isFocused())) {
return rejectFocusRequestHelper("Waiting for asynchronous processing of the request");
}
// NOTE: We simulate heavyweight behavior of Motif - component receives focus right
......@@ -469,6 +465,12 @@ public class XComponentPeer extends XWindow implements ComponentPeer, DropTarget
return false;
}
private boolean rejectFocusRequestHelper(String logMsg) {
if (focusLog.isLoggable(Level.FINER)) focusLog.finer(logMsg);
KeyboardFocusManagerPeerImpl.removeLastFocusRequest(target);
return false;
}
void handleJavaFocusEvent(AWTEvent e) {
if (focusLog.isLoggable(Level.FINER)) focusLog.finer(e.toString());
if (e.getID() == FocusEvent.FOCUS_GAINED) {
......
......@@ -1013,16 +1013,6 @@ abstract class XDecoratedPeer extends XWindowPeer {
private void handleWmTakeFocus(XClientMessageEvent cl) {
focusLog.log(Level.FINE, "WM_TAKE_FOCUS on {0}", new Object[]{this});
// A workaround to Metacity issue (see 6613426).
// The first check is to skip redundant WM_TAKE_FOCUS on click
// in a focused frame. The second check is to allow requesting focus
// on click in a frame when its owned window is currently focused.
if (this == getNativeFocusedWindowPeer() &&
target == XKeyboardFocusManagerPeer.getCurrentNativeFocusedWindow())
{
focusLog.fine("The window is already focused, skipping.");
return;
}
requestWindowFocus(cl.get_data(1), true);
}
......@@ -1124,53 +1114,51 @@ abstract class XDecoratedPeer extends XWindowPeer {
focusLog.fine("Request for decorated window focus");
// If this is Frame or Dialog we can't assure focus request success - but we still can try
// If this is Window and its owner Frame is active we can be sure request succedded.
Window win = (Window)target;
Window focusedWindow = XKeyboardFocusManagerPeer.getCurrentNativeFocusedWindow();
Window activeWindow = XWindowPeer.getDecoratedOwner(focusedWindow);
focusLog.log(Level.FINER, "Current window is: active={0}, focused={1}",
new Object[]{ Boolean.valueOf(win == activeWindow),
Boolean.valueOf(win == focusedWindow)});
new Object[]{ Boolean.valueOf(target == activeWindow),
Boolean.valueOf(target == focusedWindow)});
XWindowPeer toFocus = this;
while (toFocus.nextTransientFor != null) {
toFocus = toFocus.nextTransientFor;
}
if (toFocus == null || !toFocus.focusAllowedFor()) {
// This might change when WM will have property to determine focus policy.
// Right now, because policy is unknown we can't be sure we succedded
return false;
}
if (this == toFocus) {
if (focusAllowedFor()) {
if (win == activeWindow && win != focusedWindow) {
// Happens when focus is on window child
focusLog.fine("Focus is on child window - transfering it back");
handleWindowFocusInSync(-1);
} else {
focusLog.fine("Requesting focus to this window");
if (timeProvided) {
requestXFocus(time);
} else {
requestXFocus();
}
}
return true;
} else {
if (isWMStateNetHidden()) {
focusLog.fine("The window is unmapped, so rejecting the request");
return false;
}
}
else if (toFocus.focusAllowedFor()) {
focusLog.fine("Requesting focus to " + toFocus);
if (timeProvided) {
toFocus.requestXFocus(time);
} else {
toFocus.requestXFocus();
if (target == activeWindow && target != focusedWindow) {
// Happens when an owned window is currently focused
focusLog.fine("Focus is on child window - transfering it back to the owner");
handleWindowFocusInSync(-1);
return true;
}
Window realNativeFocusedWindow = XWindowPeer.getNativeFocusedWindow();
focusLog.finest("Real native focused window: " + realNativeFocusedWindow +
"\nKFM's focused window: " + focusedWindow);
// See 6522725, 6613426.
if (target == realNativeFocusedWindow) {
focusLog.fine("The window is already natively focused.");
return true;
}
return false;
}
else
{
// This might change when WM will have property to determine focus policy.
// Right now, because policy is unknown we can't be sure we succedded
return false;
focusLog.fine("Requesting focus to " + (this == toFocus ? "this window" : toFocus));
if (timeProvided) {
toFocus.requestXFocus(time);
} else {
toFocus.requestXFocus();
}
return (this == toFocus);
}
XWindowPeer actualFocusedWindow = null;
......
......@@ -582,7 +582,7 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
}
/*
* Converts native focused X window id into Java peer.
* Retrives real native focused window and converts it into Java peer.
*/
static XWindowPeer getNativeFocusedWindowPeer() {
XBaseWindow baseWindow = XToolkit.windowToXWindow(xGetInputFocus());
......@@ -591,6 +591,14 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
((XFocusProxyWindow)baseWindow).getOwner() : null;
}
/*
* Retrives real native focused window and converts it into Java window.
*/
static Window getNativeFocusedWindow() {
XWindowPeer peer = getNativeFocusedWindowPeer();
return peer != null ? (Window)peer.target : null;
}
boolean isFocusableWindow() {
if (XToolkit.isToolkitThread() || SunToolkit.isAWTLockHeldByCurrentThread())
{
......@@ -1252,7 +1260,7 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
return res;
}
private boolean isWMStateNetHidden() {
protected boolean isWMStateNetHidden() {
XNETProtocol protocol = XWM.getWM().getNETProtocol();
return (protocol != null && protocol.isWMStateNetHidden(this));
}
......@@ -1740,6 +1748,11 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
return window;
}
public boolean requestWindowFocus(XWindowPeer actualFocusedWindow) {
setActualFocusedWindow(actualFocusedWindow);
return requestWindowFocus();
}
public boolean requestWindowFocus() {
return requestWindowFocus(0, false);
}
......@@ -1748,25 +1761,25 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
focusLog.fine("Request for window focus");
// If this is Frame or Dialog we can't assure focus request success - but we still can try
// If this is Window and its owner Frame is active we can be sure request succedded.
Window win = (Window) target;
Window owner = XWindowPeer.getDecoratedOwner(win);
Window ownerWindow = XWindowPeer.getDecoratedOwner((Window)target);
Window focusedWindow = XKeyboardFocusManagerPeer.getCurrentNativeFocusedWindow();
Window activeWindow = XWindowPeer.getDecoratedOwner(focusedWindow);
final Window activeWindow =
XWindowPeer.getDecoratedOwner(XKeyboardFocusManagerPeer.getCurrentNativeFocusedWindow());
if (activeWindow == owner) {
if (isWMStateNetHidden()) {
focusLog.fine("The window is unmapped, so rejecting the request");
return false;
}
if (activeWindow == ownerWindow) {
focusLog.fine("Parent window is active - generating focus for this window");
handleWindowFocusInSync(-1);
return true;
} else {
focusLog.fine("Parent window is not active");
}
ComponentPeer peer = ComponentAccessor.getPeer(owner);
if (peer instanceof XDecoratedPeer) {
XDecoratedPeer wpeer = (XDecoratedPeer) peer;
if (wpeer.requestWindowFocus(this, time, timeProvided)) {
focusLog.fine("Parent window accepted focus request - generating focus for this window");
return true;
}
}
focusLog.fine("Parent window is not active");
XDecoratedPeer wpeer = (XDecoratedPeer)ComponentAccessor.getPeer(ownerWindow);
if (wpeer != null && wpeer.requestWindowFocus(this, time, timeProvided)) {
focusLog.fine("Parent window accepted focus request - generating focus for this window");
return true;
}
focusLog.fine("Denied - parent window is not active and didn't accept focus request");
return false;
......
/*
* 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 6522725
@summary Tests for proper request-focus-back on FOCUS_LOST.
@author Anton Tarasov: area=awt-focus
@library ../../regtesthelpers
@build Util
@run main IconifiedFrameFocusChangeTest
*/
import java.awt.*;
import java.applet.Applet;
import java.awt.event.*;
import test.java.awt.regtesthelpers.Util;
public class IconifiedFrameFocusChangeTest extends Applet {
Frame testFrame = new Frame("Test Frame");
Frame otherFrame = new Frame("Other Frame");
Button testButton = new Button("test button");
Button otherButton = new Button("other button");
Robot robot;
public static void main(String[] args) {
IconifiedFrameFocusChangeTest app = new IconifiedFrameFocusChangeTest();
app.init();
app.start();
}
public void init() {
robot = Util.createRobot();
testFrame.add(testButton);
testFrame.pack();
otherFrame.add(otherButton);
otherFrame.pack();
otherFrame.setLocation(200, 0);
testButton.addFocusListener(new FocusAdapter() {
public void focusLost(FocusEvent e) {
testButton.requestFocus();
}
});
}
public void start() {
otherFrame.setVisible(true);
Util.waitForIdle(robot);
testFrame.setVisible(true);
Util.waitForIdle(robot);
if (!testButton.hasFocus()) {
throw new TestErrorException("wrong initial focus");
}
/*
* Iconify the Frame. Test that focus switches properly.
*/
Runnable action = new Runnable() {
public void run() {
testFrame.setExtendedState(Frame.ICONIFIED);
}
};
if (!Util.trackFocusGained(otherButton, action, 2000, true)) {
throw new TestFailedException("iconifying focused window didn't trigger focus change");
}
/*
* Test that key events go into the focus owner.
*/
action = new Runnable() {
public void run() {
robot.keyPress(KeyEvent.VK_SPACE);
robot.delay(50);
robot.keyRelease(KeyEvent.VK_SPACE);
}
};
if (!Util.trackActionPerformed(otherButton, action, 2000, true)) {
throw new TestFailedException("Java focus owner doesn't match to the native one");
}
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);
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册