/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* The default KeyboardFocusManager for AWT applications. Focus traversal is
* done in response to a Component's focus traversal keys, and using a
* Container's FocusTraversalPolicy.
* <p>
* Please see
* How to Use the Focus Subsystem</a>,
* a section in <em>The Java Tutorial</em>, and the
* <a href="../../java/awt/doc-files/FocusSpec.html">Focus Specification</a>
* for more information.
*
* @author David Mendenhall
*
* @see FocusTraversalPolicy
* @see Component#setFocusTraversalKeys
* @see Component#getFocusTraversalKeys
* @since 1.4
*/
private static final PlatformLogger focusLog = PlatformLogger.getLogger("java.awt.focus.DefaultKeyboardFocusManager");
// null weak references to not create too many objects
private int inSendMessage;
private boolean consumeNextKeyTyped;
static {
}
});
}
private static class TypeAheadMarker {
long after;
this.untilFocused = untilFocused;
}
/**
* Returns string representation of the marker
*/
}
}
}
return window;
}
/*
* This series of restoreFocus methods is used for recovering from a
* rejected focus or activation change. Rejections typically occur when
* the user attempts to focus a non-focusable Component or Window.
*/
vetoedComponent, false))
{
} else if (realOppositeComponent != null &&
} else {
}
}
if (realOppositeWindow != null
{
// do nothing, everything is done in restoreFocus()
{
// do nothing, everything is done in restoreFocus()
} else {
}
}
boolean clearOnFailure) {
if (toFocus != null && toFocus != vetoedComponent && doRestoreFocus(toFocus, vetoedComponent, false)) {
return true;
} else if (clearOnFailure) {
return true;
} else {
return false;
}
}
}
boolean clearOnFailure)
{
{
return true;
} else {
{
return true;
} else if (clearOnFailure) {
return true;
} else {
return false;
}
}
}
/**
* A special type of SentEvent which updates a counter in the target
* KeyboardFocusManager if it is an instance of
* DefaultKeyboardFocusManager.
*/
private static class DefaultKeyboardFocusManagerSentEvent
extends SentEvent
{
/*
* serialVersionUID
*/
}
public final void dispatch() {
(manager instanceof DefaultKeyboardFocusManager)
: null;
if (defaultManager != null) {
synchronized (defaultManager) {
}
}
super.dispatch();
if (defaultManager != null) {
synchronized (defaultManager) {
}
}
}
}
/**
* Sends a synthetic AWTEvent to a Component. If the Component is in
* the current AppContext, then the event is immediately dispatched.
* If the Component is in a different AppContext, then the event is
* posted to the other AppContext's EventQueue, and this method blocks
* until the event is handled or target AppContext is disposed.
* Returns true if successfuly dispatched event, false if failed
* to dispatch.
*/
e.isPosted = true;
if (myAppContext == targetAppContext) {
} else {
if (targetAppContext.isDisposed()) {
return false;
}
if (EventQueue.isDispatchThread()) {
public boolean evaluate() {
}
});
} else {
synchronized (se) {
try {
} catch (InterruptedException ie) {
break;
}
}
}
}
}
return se.dispatched;
}
/**
* This method is called by the AWT event dispatcher requesting that the
* current KeyboardFocusManager dispatch the specified event on its behalf.
* DefaultKeyboardFocusManagers dispatch all FocusEvents, all WindowEvents
* related to focus, and all KeyEvents. These events are dispatched based
* on the KeyboardFocusManager's notion of the focus owner and the focused
* and active Windows, sometimes overriding the source of the specified
* AWTEvent. If this method returns <code>false</code>, then the AWT event
* dispatcher will attempt to dispatch the event itself.
*
* @param e the AWTEvent to be dispatched
* @return <code>true</code> if this method dispatched the event;
* <code>false</code> otherwise
*/
if (focusLog.isLoggable(PlatformLogger.FINE) && (e instanceof WindowEvent || e instanceof FocusEvent)) focusLog.fine("" + e);
switch (e.getID()) {
case WindowEvent.WINDOW_GAINED_FOCUS: {
if (newFocusedWindow == oldFocusedWindow) {
break;
}
if (!(newFocusedWindow.isFocusableWindow()
&& newFocusedWindow.isDisplayable()))
{
// we can not accept focus on such window, so reject it.
break;
}
// If there exists a current focused window, then notify it
// that it has lost focus.
if (oldFocusedWindow != null) {
boolean isEventDispatched =
// Failed to dispatch, clear by ourselfves
if (!isEventDispatched) {
}
}
// Because the native libraries do not post WINDOW_ACTIVATED
// events, we need to synthesize one if the active Window
// changed.
if (newActiveWindow != currentActiveWindow) {
if (newActiveWindow != getGlobalActiveWindow()) {
// Activation change was rejected. Unlikely, but
// possible.
break;
}
}
if (newFocusedWindow != getGlobalFocusedWindow()) {
// Focus change was rejected. Will happen if
// newFocusedWindow is not a focusable Window.
break;
}
// Restore focus to the Component which last held it. We do
// this here so that client code can override our choice in
// a WINDOW_GAINED_FOCUS handler.
//
// Make sure that the focus change request doesn't change the
// focused Window in case we are no longer the focused Window
// when the request is handled.
if (inSendMessage == 0) {
// Identify which Component should initially gain focus
// in the Window.
//
// * If we're in SendMessage, then this is a synthetic
// WINDOW_GAINED_FOCUS message which was generated by a
// the FOCUS_GAINED handler. Allow the Component to
// which the FOCUS_GAINED message was targeted to
// receive the focus.
// * Otherwise, look up the correct Component here.
// We don't use Window.getMostRecentFocusOwner because
// window is focused now and 'null' will be returned
// Calculating of most recent focus owner and focus
// request should be synchronized on KeyboardFocusManager.class
// to prevent from thread race when user will request
// focus between calculation and our request.
// But if focus transfer is synchronous, this synchronization
// may cause deadlock, thus we don't synchronize this block.
{
}
synchronized(KeyboardFocusManager.class) {
}
// The component which last has the focus when this window was focused
// should receive focus first
}
}
// If there is a component which requested focus when this window
// was inactive it expects to receive focus after activation.
}
}
}
}
case WindowEvent.WINDOW_ACTIVATED: {
if (oldActiveWindow == newActiveWindow) {
break;
}
// If there exists a current active window, then notify it that
// it has lost activation.
if (oldActiveWindow != null) {
boolean isEventDispatched =
// Failed to dispatch, clear by ourselfves
if (!isEventDispatched) {
}
if (getGlobalActiveWindow() != null) {
// Activation change was rejected. Unlikely, but
// possible.
break;
}
}
if (newActiveWindow != getGlobalActiveWindow()) {
// Activation change was rejected. Unlikely, but
// possible.
break;
}
}
case FocusEvent.FOCUS_GAINED: {
if (oldFocusOwner == newFocusOwner) {
}
// We can't just drop the event - there could be
// type-ahead markers associated with it.
break;
}
// If there exists a current focus owner, then notify it that
// it has lost focus.
if (oldFocusOwner != null) {
boolean isEventDispatched =
fe.isTemporary(),
newFocusOwner, cause));
// Failed to dispatch, clear by ourselfves
if (!isEventDispatched) {
if (!fe.isTemporary()) {
}
}
}
// 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.
if (newFocusedWindow != null &&
{
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
break;
}
}
// Refuse focus on a disabled component if the focus event
// isn't of UNKNOWN reason (i.e. not a result of a direct request
// but traversal, activation or system generated).
{
// we should not accept focus on such component, so reject it.
// If FOCUS_GAINED is for a disposed component (however
// it shouldn't happen) its toplevel parent is null. In this
// case we have to try to restore focus in the current focused
// window (for the details: 6607170).
if (newFocusedWindow == null) {
} else {
}
}
break;
}
if (newFocusOwner != getGlobalFocusOwner()) {
// Focus change was rejected. Will happen if
// newFocusOwner is not focus traversable.
}
break;
}
if (!fe.isTemporary()) {
if (newFocusOwner != getGlobalPermanentFocusOwner()) {
// Focus change was rejected. Unlikely, but possible.
}
break;
}
}
if (realOppositeComponent != null &&
fe.isTemporary(),
}
}
case FocusEvent.FOCUS_LOST: {
if (currentFocusOwner == null) {
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.
break;
}
if (getGlobalFocusOwner() != null) {
// Focus change was rejected. Unlikely, but possible.
restoreFocus(currentFocusOwner, true);
break;
}
if (!fe.isTemporary()) {
if (getGlobalPermanentFocusOwner() != null) {
// Focus change was rejected. Unlikely, but possible.
restoreFocus(currentFocusOwner, true);
break;
}
} else {
if (owningWindow != null) {
}
}
}
case WindowEvent.WINDOW_DEACTIVATED: {
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;
}
if (getGlobalActiveWindow() != null) {
// Activation change was rejected. Unlikely, but possible.
break;
}
}
case WindowEvent.WINDOW_LOST_FOCUS: {
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.
{
break;
}
if (currentFocusOwner != null) {
// The focus owner should always receive a FOCUS_LOST event
// before the Window is defocused.
if (oppositeWindow != null) {
if (oppositeComp == null) {
}
}
if (oppositeComp == null) {
}
true,
}
if (getGlobalFocusedWindow() != null) {
// Focus change was rejected. Unlikely, but possible.
break;
}
if (oppositeWindow == null) {
// Then we need to deactive the active Window as well.
// No need to synthesize in other cases, because
// WINDOW_ACTIVATED will handle it if necessary.
new WindowEvent(activeWindow,
null));
if (getGlobalActiveWindow() != null) {
// Activation change was rejected. Unlikely,
// but possible.
}
}
break;
}
case KeyEvent.KEY_PRESSED:
case KeyEvent.KEY_RELEASED:
return typeAheadAssertions(null, e);
default:
return false;
}
return true;
}
/**
* Called by <code>dispatchEvent</code> if no other
* KeyEventDispatcher in the dispatcher chain dispatched the KeyEvent, or
* if no other KeyEventDispatchers are registered. If the event has not
* been consumed, its target is enabled, and the focus owner is not null,
* this method dispatches the event to its target. This method will also
* subsequently dispatch the event to all registered
* KeyEventPostProcessors. After all this operations are finished,
* the event is passed to peers for processing.
* <p>
* In all cases, this method returns <code>true</code>, since
* DefaultKeyboardFocusManager is designed so that neither
* <code>dispatchEvent</code>, nor the AWT event dispatcher, should take
* further action on the event in any situation.
*
* @param e the KeyEvent to be dispatched
* @return <code>true</code>
* @see Component#dispatchEvent
*/
if (!e.isConsumed()) {
redispatchEvent(comp, e);
}
}
}
boolean stopPostProcessing = false;
if (processors != null) {
{
postProcessKeyEvent(e));
}
}
if (!stopPostProcessing) {
}
// Allow the peer to process KeyEvent
// if focus owner is lightweight then its native container
// processes event
}
}
peer.handleEvent(e);
}
return true;
}
/**
* This method will be called by <code>dispatchKeyEvent</code>. It will
* handle any unconsumed KeyEvents that map to an AWT
* <code>MenuShortcut</code> by consuming the event and activating the
* shortcut.
*
* @param e the KeyEvent to post-process
* @return <code>true</code>
* @see #dispatchKeyEvent
* @see MenuShortcut
*/
if (!e.isConsumed()) {
if (p != null) {
p.postProcessKeyEvent(e);
}
}
return true;
}
private void pumpApprovedKeyEvents() {
do {
synchronized (this) {
// Fixed 5064013: may appears that the events have the same time
// if (ke.getWhen() >= marker.after) {
// The fix is rolled out.
}
}
}
}
}
}
}
/**
* Dumps the list of type-ahead queue markers to stderr
*/
void dumpMarkers() {
synchronized (this) {
}
}
}
}
}
// Clear any pending events here as well as in the FOCUS_GAINED
// handler. We need this call here in case a marker was removed in
// response to a call to dequeueKeyEvents.
switch (e.getID()) {
case KeyEvent.KEY_PRESSED:
case KeyEvent.KEY_RELEASED: {
synchronized (this) {
// Fixed 5064013: may appears that the events have the same time
// if (ke.getWhen() >= marker.after) {
// The fix is rolled out.
return true;
}
}
}
// KeyEvent was posted before focus change request
return preDispatchKeyEvent(ke);
}
case FocusEvent.FOCUS_GAINED:
dumpMarkers();
// Search the marker list for the first marker tied to
// the Component which just gained focus. Then remove
// that marker, any markers which immediately follow
// and are tied to the same component, and all markers
// that preceed it. This handles the case where
// multiple focus requests were made for the same
// Component in a row and when we lost some of the
// earlier requests. Since FOCUS_GAINED events will
// not be generated for these additional requests, we
// need to clear those markers too.
synchronized (this) {
boolean found = false;
{
{
found = true;
} else if (found) {
break;
}
}
} else {
// Exception condition - event without marker
}
}
dumpMarkers();
redispatchEvent(target, e);
// Now, dispatch any pending KeyEvents which have been
// released because of the FOCUS_GAINED event so that we don't
// have to wait for another event to be posted to the queue.
return true;
default:
redispatchEvent(target, e);
return true;
}
}
/**
* Returns true if there are some marker associated with component <code>comp</code>
* in a markers' queue
* @since 1.5
*/
return true;
}
}
return false;
}
/**
* Clears markers queue
* @since 1.5
*/
void clearMarkers() {
synchronized(this) {
}
}
}
return true;
}
// Explicitly set the current event and most recent timestamp here in
// addition to the call in Component.dispatchEventImpl. Because
// KeyEvents can be delivered in response to a FOCUS_GAINED event, the
// current timestamp may be incorrect. We need to set it here so that
// KeyEventDispatchers will use the correct time.
/**
* Fix for 4495473.
* This fix allows to correctly dispatch events when native
* event proxying mechanism is active.
* If it is active we should redispatch key events after
* we detected its correct target.
*/
/**
* Fix for 4478780 - consume event after it was dispatched by peer.
*/
}
}
return true;
}
if (dispatchers != null) {
{
{
return true;
}
}
}
return dispatchKeyEvent(ke);
}
/*
* @param e is a KEY_PRESSED event that can be used
* to track the next KEY_TYPED related.
*/
consumeNextKeyTyped = true;
}
e.consume();
!e.isActionKey();
}
/*
* return true if event was consumed
*/
e.consume();
consumeNextKeyTyped = false;
return true;
}
return false;
}
/**
* This method initiates a focus traversal operation if and only if the
* KeyEvent represents a focus traversal key for the specified
* focusedComponent. It is expected that focusedComponent is the current
* focus owner, although this need not be the case. If it is not,
* focus traversal will nevertheless proceed as if focusedComponent
* were the focus owner.
*
* @param focusedComponent the Component that is the basis for a focus
* traversal operation if the specified event represents a focus
* traversal key for the Component
* @param e the event that may represent a focus traversal key
*/
// consume processed event if needed
if (consumeProcessedKeyEvent(e)) {
return;
}
// KEY_TYPED events cannot be focus traversal keys
return;
}
!e.isConsumed())
{
!stroke.isOnKeyRelease());
boolean contains, containsOpp;
if (contains || containsOpp) {
if (contains) {
}
return;
// Fix for 6637607: consumeNextKeyTyped should be reset.
consumeNextKeyTyped = false;
}
if (contains || containsOpp) {
if (contains) {
}
return;
}
if (contains || containsOpp) {
if (contains) {
}
return;
}
if (!((focusedComponent instanceof Container) &&
return;
}
if (contains || containsOpp) {
if (contains) {
}
}
}
}
/**
* Delays dispatching of KeyEvents until the specified Component becomes
* the focus owner. KeyEvents with timestamps later than the specified
* timestamp will be enqueued until the specified Component receives a
* FOCUS_GAINED event, or the AWT cancels the delay request by invoking
* <code>dequeueKeyEvents</code> or <code>discardKeyEvents</code>.
*
* @param after timestamp of current event, or the current, system time if
* the current event has no timestamp, or the AWT cannot determine
* which event is currently being handled
* @param untilFocused Component which will receive a FOCUS_GAINED event
* before any pending KeyEvents
* @see #dequeueKeyEvents
* @see #discardKeyEvents
*/
if (untilFocused == null) {
return;
}
int insertionIndex = 0,
i = typeAheadMarkers.size();
for (; i > 0; i--) {
insertionIndex = i;
break;
}
}
}
/**
* Releases for normal dispatching to the current focus owner all
* KeyEvents which were enqueued because of a call to
* <code>enqueueKeyEvents</code> with the same timestamp and Component.
* If the given timestamp is less than zero, the outstanding enqueue
* request for the given Component with the <b>oldest</b> timestamp (if
* any) should be cancelled.
*
* @param after the timestamp specified in the call to
* <code>enqueueKeyEvents</code>, or any value < 0
* @param untilFocused the Component specified in the call to
* <code>enqueueKeyEvents</code>
* @see #enqueueKeyEvents
* @see #discardKeyEvents
*/
if (untilFocused == null) {
return;
}
if (after < 0) {
{
return;
}
}
} else {
while (iter.hasPrevious()) {
{
return;
}
}
}
}
/**
* Discards all KeyEvents which were enqueued because of one or more calls
* to <code>enqueueKeyEvents</code> with the specified Component, or one of
* its descendants.
*
* @param comp the Component specified in one or more calls to
* <code>enqueueKeyEvents</code>, or a parent of such a Component
* @see #enqueueKeyEvents
* @see #dequeueKeyEvents
*/
return;
}
long start = -1;
}
if (match) {
if (start < 0) {
}
} else if (start >= 0) {
start = -1;
}
}
}
// Notes:
// * must be called inside a synchronized block
// * if 'start' is < 0, then this function does nothing
// * if 'end' is < 0, then all KeyEvents from 'start' to the end of the
// queue will be removed
if (start < 0) {
return;
}
}
break;
}
}
}
/**
* Focuses the Component before aComponent, typically based on a
* FocusTraversalPolicy.
*
* @param aComponent the Component that is the basis for the focus
* traversal operation
* @see FocusTraversalPolicy
* @see Component#transferFocusBackward
*/
if (aComponent != null) {
}
}
/**
* Focuses the Component after aComponent, typically based on a
* FocusTraversalPolicy.
*
* @param aComponent the Component that is the basis for the focus
* traversal operation
* @see FocusTraversalPolicy
* @see Component#transferFocus
*/
if (aComponent != null) {
}
}
/**
* Moves the focus up one focus traversal cycle. Typically, the focus owner
* is set to aComponent's focus cycle root, and the current focus cycle
* root is set to the new focus owner's focus cycle root. If, however,
* aComponent's focus cycle root is a Window, then the focus owner is set
* to the focus cycle root's default Component to focus, and the current
* focus cycle root is unchanged.
*
* @param aComponent the Component that is the basis for the focus
* traversal operation
* @see Component#transferFocusUpCycle
*/
if (aComponent != null) {
}
}
/**
* Moves the focus down one focus traversal cycle. If aContainer is a focus
* cycle root, then the focus owner is set to aContainer's default
* Component to focus, and the current focus cycle root is set to
* aContainer. If aContainer is not a focus cycle root, then no focus
* traversal operation occurs.
*
* @param aContainer the Container that is the basis for the focus
* traversal operation
* @see Container#transferFocusDownCycle
*/
}
}
}