From 397abc7260b70fad7a46ce395bd60ddd48df0ba9 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Mon, 27 Sep 2010 16:11:58 +0400 Subject: [PATCH] 6505819: Provide traverseIn method for sun.awt.EmbeddedFrame Reviewed-by: dcherepanov, art --- .../java/awt/KeyboardFocusManager.java | 3 ++ .../share/classes/sun/awt/AWTAccessor.java | 5 +++ .../share/classes/sun/awt/EmbeddedFrame.java | 40 ++++++++++++++++++- .../classes/sun/awt/X11/XEmbeddedFrame.java | 32 +++++++++++++++ .../sun/awt/X11/XEmbeddedFramePeer.java | 18 +++++++++ .../sun/awt/windows/WEmbeddedFrame.java | 15 ++++++- 6 files changed, 110 insertions(+), 3 deletions(-) diff --git a/jdk/src/share/classes/java/awt/KeyboardFocusManager.java b/jdk/src/share/classes/java/awt/KeyboardFocusManager.java index 0c272763508..07ecefe1def 100644 --- a/jdk/src/share/classes/java/awt/KeyboardFocusManager.java +++ b/jdk/src/share/classes/java/awt/KeyboardFocusManager.java @@ -142,6 +142,9 @@ public abstract class KeyboardFocusManager public void removeLastFocusRequest(Component heavyweight) { KeyboardFocusManager.removeLastFocusRequest(heavyweight); } + public void setMostRecentFocusOwner(Window window, Component component) { + KeyboardFocusManager.setMostRecentFocusOwner(window, component); + } } ); } diff --git a/jdk/src/share/classes/sun/awt/AWTAccessor.java b/jdk/src/share/classes/sun/awt/AWTAccessor.java index 669f15ad8b8..27609806967 100644 --- a/jdk/src/share/classes/sun/awt/AWTAccessor.java +++ b/jdk/src/share/classes/sun/awt/AWTAccessor.java @@ -344,6 +344,11 @@ public final class AWTAccessor { * Removes the last focus request for the heavyweight from the queue. */ void removeLastFocusRequest(Component heavyweight); + + /* + * Sets the most recent focus owner in the window. + */ + void setMostRecentFocusOwner(Window window, Component component); } /* diff --git a/jdk/src/share/classes/sun/awt/EmbeddedFrame.java b/jdk/src/share/classes/sun/awt/EmbeddedFrame.java index b3e6a2f7801..96b1325f8cb 100644 --- a/jdk/src/share/classes/sun/awt/EmbeddedFrame.java +++ b/jdk/src/share/classes/sun/awt/EmbeddedFrame.java @@ -70,7 +70,10 @@ public abstract class EmbeddedFrame extends Frame // JDK 1.1 compatibility private static final long serialVersionUID = 2967042741780317130L; - // Use these in traverseOut method to determine directions + /* + * The constants define focus traversal directions. + * Use them in {@code traverseIn}, {@code traverseOut} methods. + */ protected static final boolean FORWARD = true; protected static final boolean BACKWARD = false; @@ -283,6 +286,41 @@ public abstract class EmbeddedFrame extends Frame return false; } + /** + * This method is called by the embedder when we should receive focus as element + * of the traversal chain. The method requests focus on: + * 1. the first Component of this EmbeddedFrame if user moves focus forward + * in the focus traversal cycle. + * 2. the last Component of this EmbeddedFrame if user moves focus backward + * in the focus traversal cycle. + * + * The direction parameter specifies which of the two mentioned cases is + * happening. Use FORWARD and BACKWARD constants defined in the EmbeddedFrame class + * to avoid confusing boolean values. + * + * A concrete implementation of this method is defined in the platform-dependent + * subclasses. + * + * @param direction FORWARD or BACKWARD + * @return true, if the EmbeddedFrame wants to get focus, false otherwise. + */ + public boolean traverseIn(boolean direction) { + Component comp = null; + + if (direction == FORWARD) { + comp = getFocusTraversalPolicy().getFirstComponent(this); + } else { + comp = getFocusTraversalPolicy().getLastComponent(this); + } + if (comp != null) { + // comp.requestFocus(); - Leads to a hung. + + AWTAccessor.getKeyboardFocusManagerAccessor().setMostRecentFocusOwner(this, comp); + synthesizeWindowActivation(true); + } + return (null != comp); + } + /** * This method is called from dispatchKeyEvent in the following two cases: * 1. The focus is on the first Component of this EmbeddedFrame and we are diff --git a/jdk/src/solaris/classes/sun/awt/X11/XEmbeddedFrame.java b/jdk/src/solaris/classes/sun/awt/X11/XEmbeddedFrame.java index 221ffb5e326..e9d0fcb6e7a 100644 --- a/jdk/src/solaris/classes/sun/awt/X11/XEmbeddedFrame.java +++ b/jdk/src/solaris/classes/sun/awt/X11/XEmbeddedFrame.java @@ -28,9 +28,12 @@ package sun.awt.X11; import sun.awt.EmbeddedFrame; import java.awt.*; import java.awt.AWTKeyStroke; +import java.util.logging.Logger; public class XEmbeddedFrame extends EmbeddedFrame { + private static final Logger log = Logger.getLogger(XEmbeddedFrame.class.getName()); + long handle; public XEmbeddedFrame() { } @@ -70,6 +73,21 @@ public class XEmbeddedFrame extends EmbeddedFrame { this(handle, supportsXEmbed, false); } + /* + * The method shouldn't be called in case of active XEmbed. + */ + public boolean traverseIn(boolean direction) { + XEmbeddedFramePeer peer = (XEmbeddedFramePeer)getPeer(); + if (peer != null) { + if (peer.supportsXEmbed() && peer.isXEmbedActive()) { + log.fine("The method shouldn't be called when XEmbed is active!"); + } else { + return super.traverseIn(direction); + } + } + return false; + } + protected boolean traverseOut(boolean direction) { XEmbeddedFramePeer xefp = (XEmbeddedFramePeer) getPeer(); if (direction == FORWARD) { @@ -81,6 +99,20 @@ public class XEmbeddedFrame extends EmbeddedFrame { return true; } + /* + * The method shouldn't be called in case of active XEmbed. + */ + public void synthesizeWindowActivation(boolean doActivate) { + XEmbeddedFramePeer peer = (XEmbeddedFramePeer)getPeer(); + if (peer != null) { + if (peer.supportsXEmbed() && peer.isXEmbedActive()) { + log.fine("The method shouldn't be called when XEmbed is active!"); + } else { + peer.synthesizeFocusInOut(doActivate); + } + } + } + public void registerAccelerator(AWTKeyStroke stroke) { XEmbeddedFramePeer xefp = (XEmbeddedFramePeer) getPeer(); if (xefp != null) { diff --git a/jdk/src/solaris/classes/sun/awt/X11/XEmbeddedFramePeer.java b/jdk/src/solaris/classes/sun/awt/X11/XEmbeddedFramePeer.java index 5825277207b..9fee20f90df 100644 --- a/jdk/src/solaris/classes/sun/awt/X11/XEmbeddedFramePeer.java +++ b/jdk/src/solaris/classes/sun/awt/X11/XEmbeddedFramePeer.java @@ -35,6 +35,8 @@ import sun.util.logging.PlatformLogger; import sun.awt.EmbeddedFrame; import sun.awt.SunToolkit; +import static sun.awt.X11.XConstants.*; + public class XEmbeddedFramePeer extends XFramePeer { private static final PlatformLogger xembedLog = PlatformLogger.getLogger("sun.awt.X11.xembed.XEmbeddedFramePeer"); @@ -305,4 +307,20 @@ public class XEmbeddedFramePeer extends XFramePeer { EmbeddedFrame frame = (EmbeddedFrame)target; frame.notifyModalBlocked(blocker, blocked); } + + public void synthesizeFocusInOut(boolean doFocus) { + XFocusChangeEvent xev = new XFocusChangeEvent(); + + XToolkit.awtLock(); + try { + xev.set_type(doFocus ? FocusIn : FocusOut); + xev.set_window(getFocusProxy().getWindow()); + xev.set_mode(NotifyNormal); + XlibWrapper.XSendEvent(XToolkit.getDisplay(), getFocusProxy().getWindow(), false, + NoEventMask, xev.pData); + } finally { + XToolkit.awtUnlock(); + xev.dispose(); + } + } } diff --git a/jdk/src/windows/classes/sun/awt/windows/WEmbeddedFrame.java b/jdk/src/windows/classes/sun/awt/windows/WEmbeddedFrame.java index 18489f91db4..908c1aac8e2 100644 --- a/jdk/src/windows/classes/sun/awt/windows/WEmbeddedFrame.java +++ b/jdk/src/windows/classes/sun/awt/windows/WEmbeddedFrame.java @@ -191,9 +191,20 @@ public class WEmbeddedFrame extends EmbeddedFrame { public void activateEmbeddingTopLevel() { } - public void synthesizeWindowActivation(boolean doActivate) { - ((WEmbeddedFramePeer)getPeer()).synthesizeWmActivate(doActivate); + public void synthesizeWindowActivation(final boolean doActivate) { + if (!doActivate || EventQueue.isDispatchThread()) { + ((WEmbeddedFramePeer)getPeer()).synthesizeWmActivate(doActivate); + } else { + // To avoid focus concurrence b/w IE and EmbeddedFrame + // activation is postponed by means of posting it to EDT. + EventQueue.invokeLater(new Runnable() { + public void run() { + ((WEmbeddedFramePeer)getPeer()).synthesizeWmActivate(true); + } + }); + } } + public void registerAccelerator(AWTKeyStroke stroke) {} public void unregisterAccelerator(AWTKeyStroke stroke) {}