diff -r c90a9d542c79 -r 3c6755bdc55f jdk/src/share/classes/sun/awt/KeyboardFocusManagerPeerImpl.java --- 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); } }