// If there exists a current focus owner, then notify it that
// it has lost focus.
if (oldFocusOwner != null) {
boolean isEventDispatched =
sendMessage(oldFocusOwner,
new CausedFocusEvent(oldFocusOwner,
FocusEvent.FOCUS_LOST,
fe.isTemporary(),
newFocusOwner, cause));
// Failed to dispatch, clear by ourselfves
if (!isEventDispatched) {
setGlobalFocusOwner(null);
if (!fe.isTemporary()) {
setGlobalPermanentFocusOwner(null);
}
}
}
// Because the native windowing system has a different notion
// of the current focus and activation states, it is possible
// that a Component outside of the focused Window receives a
// FOCUS_GAINED event. We synthesize a WINDOW_GAINED_FOCUS
// event in that case.
final Window newFocusedWindow = Component.getContainingWindow(newFocusOwner);
final Window currentFocusedWindow = getGlobalFocusedWindow();
if (newFocusedWindow != null &&
newFocusedWindow != currentFocusedWindow)
{
sendMessage(newFocusedWindow,
new WindowEvent(newFocusedWindow,
WindowEvent.WINDOW_GAINED_FOCUS,
currentFocusedWindow));
if (newFocusedWindow != getGlobalFocusedWindow()) {
// Focus change was rejected. Will happen if
// newFocusedWindow is not a focusable Window.
// Need to recover type-ahead, but don't bother
// restoring focus. That was done by the
// WINDOW_GAINED_FOCUS handler
dequeueKeyEvents(-1, newFocusOwner);
break;
}
}
if (!(newFocusOwner.isFocusable() && newFocusOwner.isEnabled()
&& newFocusOwner.isShowing()))
{
// we should not accept focus on such component, so reject it.
dequeueKeyEvents(-1, newFocusOwner);
if (KeyboardFocusManager.isAutoFocusTransferEnabled())
{
restoreFocus(fe, newFocusedWindow);
}
break;
}
setGlobalFocusOwner(newFocusOwner);
if (newFocusOwner != getGlobalFocusOwner()) {
// Focus change was rejected. Will happen if
// newFocusOwner is not focus traversable.
dequeueKeyEvents(-1, newFocusOwner);
if (KeyboardFocusManager.isAutoFocusTransferEnabled()) {
restoreFocus(fe, (Window)newFocusedWindow);
}
break;
}
if (!fe.isTemporary()) {
setGlobalPermanentFocusOwner(newFocusOwner);
if (newFocusOwner != getGlobalPermanentFocusOwner()) {
// Focus change was rejected. Unlikely, but possible.
dequeueKeyEvents(-1, newFocusOwner);
if (KeyboardFocusManager.isAutoFocusTransferEnabled()) {
restoreFocus(fe, (Window)newFocusedWindow);
}
break;
}
}
setNativeFocusOwner(getHeavyweight(newFocusOwner));
Component realOppositeComponent = this.realOppositeComponentWR.get();
if (realOppositeComponent != null &&
realOppositeComponent != fe.getOppositeComponent()) {
fe = new CausedFocusEvent(newFocusOwner,
FocusEvent.FOCUS_GAINED,
fe.isTemporary(),
realOppositeComponent, cause);
((AWTEvent) fe).isPosted = true;
}
return typeAheadAssertions(newFocusOwner, fe);
}
case FocusEvent.FOCUS_LOST: {
FocusEvent fe = (FocusEvent)e;
Component currentFocusOwner = getGlobalFocusOwner();
if (currentFocusOwner == null) {
if (focusLog.isLoggable(Level.FINE)) {
focusLog.log(Level.FINE, "Skipping {0} because focus owner is null",
new Object[] {String.valueOf(e)});
}
break;
}
// Ignore cases where a Component loses focus to itself.
// If we make a mistake because of retargeting, then the
// FOCUS_GAINED handler will correct it.
if (currentFocusOwner == fe.getOppositeComponent()) {
if (focusLog.isLoggable(Level.FINE)) {
focusLog.log(Level.FINE, "Skipping {0} because current focus owner is equal to opposite",
new Object[] {String.valueOf(e)});
}
break;
}
setGlobalFocusOwner(null);
if (getGlobalFocusOwner() != null) {
// Focus change was rejected. Unlikely, but possible.
restoreFocus(currentFocusOwner, true);
break;
}
if (!fe.isTemporary()) {
setGlobalPermanentFocusOwner(null);
if (getGlobalPermanentFocusOwner() != null) {
// Focus change was rejected. Unlikely, but possible.
restoreFocus(currentFocusOwner, true);
break;
}
} else {
Window owningWindow = currentFocusOwner.getContainingWindow();
if (owningWindow != null) {
owningWindow.setTemporaryLostComponent(currentFocusOwner);
}
}
setNativeFocusOwner(null);
fe.setSource(currentFocusOwner);
realOppositeComponentWR = (fe.getOppositeComponent() != null)
? new WeakReference<Component>(currentFocusOwner)
: NULL_COMPONENT_WR;
return typeAheadAssertions(currentFocusOwner, fe);
}
case WindowEvent.WINDOW_DEACTIVATED: {
WindowEvent we = (WindowEvent)e;
Window currentActiveWindow = getGlobalActiveWindow();
if (currentActiveWindow == null) {
break;
}
if (currentActiveWindow != e.getSource()) {
// The event is lost in time.
// Allow listeners to precess the event but do not
// change any global states
break;
}
setGlobalActiveWindow(null);
if (getGlobalActiveWindow() != null) {
// Activation change was rejected. Unlikely, but possible.
break;
}
we.setSource(currentActiveWindow);
return typeAheadAssertions(currentActiveWindow, we);
}
case WindowEvent.WINDOW_LOST_FOCUS: {
WindowEvent we = (WindowEvent)e;
Window currentFocusedWindow = getGlobalFocusedWindow();
Window losingFocusWindow = we.getWindow();
Window activeWindow = getGlobalActiveWindow();
Window oppositeWindow = we.getOppositeWindow();
if (focusLog.isLoggable(Level.FINE)) {
focusLog.log(Level.FINE, "Active {0}, Current focused {1}, losing focus {2} opposite {3}",
new Object[] {String.valueOf(activeWindow), String.valueOf(currentFocusedWindow),
String.valueOf(losingFocusWindow), String.valueOf(oppositeWindow)});
}
if (currentFocusedWindow == null) {
break;
}
// Special case -- if the native windowing system posts an
// event claiming that the active Window has lost focus to the
// focused Window, then discard the event. This is an artifact
// of the native windowing system not knowing which Window is
// really focused.
if (inSendMessage == 0 && losingFocusWindow == activeWindow &&
oppositeWindow == currentFocusedWindow)
{
break;
}
Component currentFocusOwner = getGlobalFocusOwner();
if (currentFocusOwner != null) {
// The focus owner should always receive a FOCUS_LOST event
// before the Window is defocused.
Component oppositeComp = null;
if (oppositeWindow != null) {
oppositeComp = oppositeWindow.getTemporaryLostComponent();
if (oppositeComp == null) {
oppositeComp = oppositeWindow.getMostRecentFocusOwner();
}
}
if (oppositeComp == null) {
oppositeComp = oppositeWindow;
}
sendMessage(currentFocusOwner,
new CausedFocusEvent(currentFocusOwner,
FocusEvent.FOCUS_LOST,
true,
oppositeComp, CausedFocusEvent.Cause.ACTIVATION));
}