6505819: Provide traverseIn method for sun.awt.EmbeddedFrame
authorant
Mon, 27 Sep 2010 16:11:58 +0400
changeset 6634 439221465ac5
parent 6487 d6ad2c68a522
child 6635 74a29718cc9e
6505819: Provide traverseIn method for sun.awt.EmbeddedFrame Reviewed-by: dcherepanov, art
jdk/src/share/classes/java/awt/KeyboardFocusManager.java
jdk/src/share/classes/sun/awt/AWTAccessor.java
jdk/src/share/classes/sun/awt/EmbeddedFrame.java
jdk/src/solaris/classes/sun/awt/X11/XEmbeddedFrame.java
jdk/src/solaris/classes/sun/awt/X11/XEmbeddedFramePeer.java
jdk/src/windows/classes/sun/awt/windows/WEmbeddedFrame.java
--- a/jdk/src/share/classes/java/awt/KeyboardFocusManager.java	Fri Sep 03 11:08:41 2010 +0400
+++ b/jdk/src/share/classes/java/awt/KeyboardFocusManager.java	Mon Sep 27 16:11:58 2010 +0400
@@ -142,6 +142,9 @@
                 public void removeLastFocusRequest(Component heavyweight) {
                     KeyboardFocusManager.removeLastFocusRequest(heavyweight);
                 }
+                public void setMostRecentFocusOwner(Window window, Component component) {
+                    KeyboardFocusManager.setMostRecentFocusOwner(window, component);
+                }
             }
         );
     }
--- a/jdk/src/share/classes/sun/awt/AWTAccessor.java	Fri Sep 03 11:08:41 2010 +0400
+++ b/jdk/src/share/classes/sun/awt/AWTAccessor.java	Mon Sep 27 16:11:58 2010 +0400
@@ -344,6 +344,11 @@
          * 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);
     }
 
     /*
--- a/jdk/src/share/classes/sun/awt/EmbeddedFrame.java	Fri Sep 03 11:08:41 2010 +0400
+++ b/jdk/src/share/classes/sun/awt/EmbeddedFrame.java	Mon Sep 27 16:11:58 2010 +0400
@@ -70,7 +70,10 @@
     // 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;
 
@@ -284,6 +287,41 @@
     }
 
     /**
+     * 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
      *    about to transfer the focus backward.
--- a/jdk/src/solaris/classes/sun/awt/X11/XEmbeddedFrame.java	Fri Sep 03 11:08:41 2010 +0400
+++ b/jdk/src/solaris/classes/sun/awt/X11/XEmbeddedFrame.java	Mon Sep 27 16:11:58 2010 +0400
@@ -28,9 +28,12 @@
 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 @@
         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 @@
         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) {
--- a/jdk/src/solaris/classes/sun/awt/X11/XEmbeddedFramePeer.java	Fri Sep 03 11:08:41 2010 +0400
+++ b/jdk/src/solaris/classes/sun/awt/X11/XEmbeddedFramePeer.java	Mon Sep 27 16:11:58 2010 +0400
@@ -35,6 +35,8 @@
 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 @@
         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();
+        }
+    }
 }
--- a/jdk/src/windows/classes/sun/awt/windows/WEmbeddedFrame.java	Fri Sep 03 11:08:41 2010 +0400
+++ b/jdk/src/windows/classes/sun/awt/windows/WEmbeddedFrame.java	Mon Sep 27 16:11:58 2010 +0400
@@ -191,9 +191,20 @@
     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) {}