jdk/src/share/classes/sun/awt/KeyboardFocusManagerPeerImpl.java
changeset 2464 3c6755bdc55f
parent 2 90ce3da70b43
child 3938 ef327bd847c0
--- a/jdk/src/share/classes/sun/awt/KeyboardFocusManagerPeerImpl.java	Wed Mar 04 18:10:48 2009 +0300
+++ b/jdk/src/share/classes/sun/awt/KeyboardFocusManagerPeerImpl.java	Tue Mar 10 18:33:29 2009 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2003-2009 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
@@ -27,47 +27,150 @@
 import java.awt.Component;
 import java.awt.KeyboardFocusManager;
 import java.awt.Window;
+import java.awt.Canvas;
+import java.awt.Scrollbar;
+import java.awt.Panel;
+
+import java.awt.event.FocusEvent;
 
 import java.awt.peer.KeyboardFocusManagerPeer;
+import java.awt.peer.ComponentPeer;
 
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 
+import java.util.logging.Level;
+import java.util.logging.Logger;
 
-public class KeyboardFocusManagerPeerImpl implements KeyboardFocusManagerPeer {
-    static native Window getNativeFocusedWindow();
-    static native Component getNativeFocusOwner();
-    static native void clearNativeGlobalFocusOwner(Window activeWindow);
+public abstract class KeyboardFocusManagerPeerImpl implements KeyboardFocusManagerPeer {
+
+    private static final Logger focusLog = Logger.getLogger("sun.awt.focus.KeyboardFocusManagerPeerImpl");
+
+    private static AWTAccessor.KeyboardFocusManagerAccessor kfmAccessor =
+        AWTAccessor.getKeyboardFocusManagerAccessor();
 
-    KeyboardFocusManagerPeerImpl(KeyboardFocusManager manager) {
+    // The constants are copied from java.awt.KeyboardFocusManager
+    public static final int SNFH_FAILURE         = 0;
+    public static final int SNFH_SUCCESS_HANDLED = 1;
+    public static final int SNFH_SUCCESS_PROCEED = 2;
+
+    protected KeyboardFocusManager manager;
+
+    public KeyboardFocusManagerPeerImpl(KeyboardFocusManager manager) {
+        this.manager = manager;
     }
 
-    public Window getCurrentFocusedWindow() {
-        return getNativeFocusedWindow();
+    @Override
+    public void clearGlobalFocusOwner(Window activeWindow) {
+        if (activeWindow != null) {
+            Component focusOwner = activeWindow.getFocusOwner();
+            if (focusLog.isLoggable(Level.FINE)) focusLog.fine("Clearing global focus owner " + focusOwner);
+            if (focusOwner != null) {
+                FocusEvent fl = new CausedFocusEvent(focusOwner, FocusEvent.FOCUS_LOST, false, null,
+                                                     CausedFocusEvent.Cause.CLEAR_GLOBAL_FOCUS_OWNER);
+                SunToolkit.postPriorityEvent(fl);
+            }
+        }
     }
 
-    public void setCurrentFocusOwner(Component comp) {
+    /*
+     * WARNING: Don't call it on the Toolkit thread.
+     *
+     * Checks if the component:
+     * 1) accepts focus on click (in general)
+     * 2) may be a focus owner (in particular)
+     */
+    public static boolean shouldFocusOnClick(Component component) {
+        boolean acceptFocusOnClick = false;
+
+        // A component is generally allowed to accept focus on click
+        // if its peer is focusable. There're some exceptions though.
+
+
+        // CANVAS & SCROLLBAR accept focus on click
+        if (component instanceof Canvas ||
+            component instanceof Scrollbar)
+        {
+            acceptFocusOnClick = true;
+
+        // PANEL, empty only, accepts focus on click
+        } else if (component instanceof Panel) {
+            acceptFocusOnClick = (((Panel)component).getComponentCount() == 0);
+
+
+        // Other components
+        } else {
+            ComponentPeer peer = (component != null ? component.getPeer() : null);
+            acceptFocusOnClick = (peer != null ? peer.isFocusable() : false);
+        }
+        return acceptFocusOnClick &&
+               AWTAccessor.getComponentAccessor().canBeFocusOwner(component);
     }
 
-    public Component getCurrentFocusOwner() {
-        return getNativeFocusOwner();
-    }
-    public void clearGlobalFocusOwner(Window activeWindow) {
-        clearNativeGlobalFocusOwner(activeWindow);
+    /*
+     * Posts proper lost/gain focus events to the event queue.
+     */
+    public static boolean deliverFocus(Component lightweightChild,
+                                       Component target,
+                                       boolean temporary,
+                                       boolean focusedWindowChangeAllowed,
+                                       long time,
+                                       CausedFocusEvent.Cause cause,
+                                       Component currentFocusOwner) // provided by the descendant peers
+    {
+        if (lightweightChild == null) {
+            lightweightChild = (Component)target;
+        }
+
+        Component currentOwner = currentFocusOwner;
+        if (currentOwner != null && currentOwner.getPeer() == null) {
+            currentOwner = null;
+        }
+        if (currentOwner != null) {
+            FocusEvent fl = new CausedFocusEvent(currentOwner, FocusEvent.FOCUS_LOST,
+                                                 false, lightweightChild, cause);
+
+            if (focusLog.isLoggable(Level.FINER)) focusLog.finer("Posting focus event: " + fl);
+            SunToolkit.postPriorityEvent(fl);
+        }
+
+        FocusEvent fg = new CausedFocusEvent(lightweightChild, FocusEvent.FOCUS_GAINED,
+                                             false, currentOwner, cause);
+
+        if (focusLog.isLoggable(Level.FINER)) focusLog.finer("Posting focus event: " + fg);
+        SunToolkit.postPriorityEvent(fg);
+        return true;
     }
 
-    static Method m_removeLastFocusRequest = null;
+    // WARNING: Don't call it on the Toolkit thread.
+    public static boolean requestFocusFor(Component target, CausedFocusEvent.Cause cause) {
+        return AWTAccessor.getComponentAccessor().requestFocus(target, cause);
+    }
+
+    // WARNING: Don't call it on the Toolkit thread.
+    public static int shouldNativelyFocusHeavyweight(Component heavyweight,
+                                                     Component descendant,
+                                                     boolean temporary,
+                                                     boolean focusedWindowChangeAllowed,
+                                                     long time,
+                                                     CausedFocusEvent.Cause cause)
+    {
+        return kfmAccessor.shouldNativelyFocusHeavyweight(
+            heavyweight, descendant, temporary, focusedWindowChangeAllowed, time, cause);
+    }
+
     public static void removeLastFocusRequest(Component heavyweight) {
-        try {
-            if (m_removeLastFocusRequest == null) {
-                m_removeLastFocusRequest = SunToolkit.getMethod(KeyboardFocusManager.class, "removeLastFocusRequest",
-                                                              new Class[] {Component.class});
-            }
-            m_removeLastFocusRequest.invoke(null, new Object[]{heavyweight});
-        } catch (InvocationTargetException ite) {
-            ite.printStackTrace();
-        } catch (IllegalAccessException ex) {
-            ex.printStackTrace();
-        }
+        kfmAccessor.removeLastFocusRequest(heavyweight);
+    }
+
+    // WARNING: Don't call it on the Toolkit thread.
+    public static boolean processSynchronousLightweightTransfer(Component heavyweight,
+                                                                Component descendant,
+                                                                boolean temporary,
+                                                                boolean focusedWindowChangeAllowed,
+                                                                long time)
+    {
+        return kfmAccessor.processSynchronousLightweightTransfer(
+            heavyweight, descendant, temporary, focusedWindowChangeAllowed, time);
     }
 }