History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/java/awt/KeyboardFocusManager.java (1 of 18352 files). Show all

Unified · Split

java/pkg/java/awt/KeyboardFocusManager.java+3065−0
@@ -0,0 +1,3065 @@
1+/*
2+ * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+package java.awt;
26+
27+import java.awt.event.FocusEvent;
28+import java.awt.event.InputEvent;
29+import java.awt.event.KeyEvent;
30+import java.awt.event.WindowEvent;
31+
32+import java.awt.peer.KeyboardFocusManagerPeer;
33+import java.awt.peer.LightweightPeer;
34+
35+import java.beans.PropertyChangeListener;
36+import java.beans.PropertyChangeSupport;
37+import java.beans.PropertyVetoException;
38+import java.beans.VetoableChangeListener;
39+import java.beans.VetoableChangeSupport;
40+
41+import java.lang.ref.WeakReference;
42+
43+import java.lang.reflect.Field;
44+
45+import java.security.AccessController;
46+import java.security.PrivilegedAction;
47+
48+import java.util.Collections;
49+import java.util.HashSet;
50+import java.util.Iterator;
51+import java.util.LinkedList;
52+import java.util.Set;
53+import java.util.StringTokenizer;
54+import java.util.WeakHashMap;
55+
56+import sun.util.logging.PlatformLogger;
57+
58+import sun.awt.AppContext;
59+import sun.awt.HeadlessToolkit;
60+import sun.awt.SunToolkit;
61+import sun.awt.CausedFocusEvent;
62+import sun.awt.KeyboardFocusManagerPeerProvider;
63+import sun.awt.AWTAccessor;
64+
65+/**
66+ * The KeyboardFocusManager is responsible for managing the active and focused
67+ * Windows, and the current focus owner. The focus owner is defined as the
68+ * Component in an application that will typically receive all KeyEvents
69+ * generated by the user. The focused Window is the Window that is, or
70+ * contains, the focus owner. Only a Frame or a Dialog can be the active
71+ * Window. The native windowing system may denote the active Window or its
72+ * children with special decorations, such as a highlighted title bar. The
73+ * active Window is always either the focused Window, or the first Frame or
74+ * Dialog that is an owner of the focused Window.
75+ * <p>
76+ * The KeyboardFocusManager is both a centralized location for client code to
77+ * query for the focus owner and initiate focus changes, and an event
78+ * dispatcher for all FocusEvents, WindowEvents related to focus, and
79+ * KeyEvents.
80+ * <p>
81+ * Some browsers partition applets in different code bases into separate
82+ * contexts, and establish walls between these contexts. In such a scenario,
83+ * there will be one KeyboardFocusManager per context. Other browsers place all
84+ * applets into the same context, implying that there will be only a single,
85+ * global KeyboardFocusManager for all applets. This behavior is
86+ * implementation-dependent. Consult your browser's documentation for more
87+ * information. No matter how many contexts there may be, however, there can
88+ * never be more than one focus owner, focused Window, or active Window, per
89+ * ClassLoader.
90+ * <p>
91+ * Please see
92+ * <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/focus.html">
93+ * How to Use the Focus Subsystem</a>,
94+ * a section in <em>The Java Tutorial</em>, and the
95+ * <a href="../../java/awt/doc-files/FocusSpec.html">Focus Specification</a>
96+ * for more information.
97+ *
98+ * @author David Mendenhall
99+ *
100+ * @see Window
101+ * @see Frame
102+ * @see Dialog
103+ * @see java.awt.event.FocusEvent
104+ * @see java.awt.event.WindowEvent
105+ * @see java.awt.event.KeyEvent
106+ * @since 1.4
107+ */
108+public abstract class KeyboardFocusManager
109+ implements KeyEventDispatcher, KeyEventPostProcessor
110+{
111+
112+ // Shared focus engine logger
113+ private static final PlatformLogger focusLog = PlatformLogger.getLogger("java.awt.focus.KeyboardFocusManager");
114+
115+ static {
116+ /* ensure that the necessary native libraries are loaded */
117+ Toolkit.loadLibraries();
118+ if (!GraphicsEnvironment.isHeadless()) {
119+ initIDs();
120+ }
121+ AWTAccessor.setKeyboardFocusManagerAccessor(
122+ new AWTAccessor.KeyboardFocusManagerAccessor() {
123+ public int shouldNativelyFocusHeavyweight(Component heavyweight,
124+ Component descendant,
125+ boolean temporary,
126+ boolean focusedWindowChangeAllowed,
127+ long time,
128+ CausedFocusEvent.Cause cause)
129+ {
130+ return KeyboardFocusManager.shouldNativelyFocusHeavyweight(
131+ heavyweight, descendant, temporary, focusedWindowChangeAllowed, time, cause);
132+ }
133+ public boolean processSynchronousLightweightTransfer(Component heavyweight,
134+ Component descendant,
135+ boolean temporary,
136+ boolean focusedWindowChangeAllowed,
137+ long time)
138+ {
139+ return KeyboardFocusManager.processSynchronousLightweightTransfer(
140+ heavyweight, descendant, temporary, focusedWindowChangeAllowed, time);
141+ }
142+ public void removeLastFocusRequest(Component heavyweight) {
143+ KeyboardFocusManager.removeLastFocusRequest(heavyweight);
144+ }
145+ public void setMostRecentFocusOwner(Window window, Component component) {
146+ KeyboardFocusManager.setMostRecentFocusOwner(window, component);
147+ }
148+ }
149+ );
150+ }
151+
152+ transient KeyboardFocusManagerPeer peer;
153+
154+ /**
155+ * Initialize JNI field and method IDs
156+ */
157+ private static native void initIDs();
158+
159+ private static final PlatformLogger log = PlatformLogger.getLogger("java.awt.KeyboardFocusManager");
160+
161+ /**
162+ * The identifier for the Forward focus traversal keys.
163+ *
164+ * @see #setDefaultFocusTraversalKeys
165+ * @see #getDefaultFocusTraversalKeys
166+ * @see Component#setFocusTraversalKeys
167+ * @see Component#getFocusTraversalKeys
168+ */
169+ public static final int FORWARD_TRAVERSAL_KEYS = 0;
170+
171+ /**
172+ * The identifier for the Backward focus traversal keys.
173+ *
174+ * @see #setDefaultFocusTraversalKeys
175+ * @see #getDefaultFocusTraversalKeys
176+ * @see Component#setFocusTraversalKeys
177+ * @see Component#getFocusTraversalKeys
178+ */
179+ public static final int BACKWARD_TRAVERSAL_KEYS = 1;
180+
181+ /**
182+ * The identifier for the Up Cycle focus traversal keys.
183+ *
184+ * @see #setDefaultFocusTraversalKeys
185+ * @see #getDefaultFocusTraversalKeys
186+ * @see Component#setFocusTraversalKeys
187+ * @see Component#getFocusTraversalKeys
188+ */
189+ public static final int UP_CYCLE_TRAVERSAL_KEYS = 2;
190+
191+ /**
192+ * The identifier for the Down Cycle focus traversal keys.
193+ *
194+ * @see #setDefaultFocusTraversalKeys
195+ * @see #getDefaultFocusTraversalKeys
196+ * @see Component#setFocusTraversalKeys
197+ * @see Component#getFocusTraversalKeys
198+ */
199+ public static final int DOWN_CYCLE_TRAVERSAL_KEYS = 3;
200+
201+ static final int TRAVERSAL_KEY_LENGTH = DOWN_CYCLE_TRAVERSAL_KEYS + 1;
202+
203+ /**
204+ * Returns the current KeyboardFocusManager instance for the calling
205+ * thread's context.
206+ *
207+ * @return this thread's context's KeyboardFocusManager
208+ * @see #setCurrentKeyboardFocusManager
209+ */
210+ public static KeyboardFocusManager getCurrentKeyboardFocusManager() {
211+ return getCurrentKeyboardFocusManager(AppContext.getAppContext());
212+ }
213+
214+ synchronized static KeyboardFocusManager
215+ getCurrentKeyboardFocusManager(AppContext appcontext)
216+ {
217+ KeyboardFocusManager manager = (KeyboardFocusManager)
218+ appcontext.get(KeyboardFocusManager.class);
219+ if (manager == null) {
220+ manager = new DefaultKeyboardFocusManager();
221+ appcontext.put(KeyboardFocusManager.class, manager);
222+ }
223+ return manager;
224+ }
225+
226+ /**
227+ * Sets the current KeyboardFocusManager instance for the calling thread's
228+ * context. If null is specified, then the current KeyboardFocusManager
229+ * is replaced with a new instance of DefaultKeyboardFocusManager.
230+ * <p>
231+ * If a SecurityManager is installed, the calling thread must be granted
232+ * the AWTPermission "replaceKeyboardFocusManager" in order to replace the
233+ * the current KeyboardFocusManager. If this permission is not granted,
234+ * this method will throw a SecurityException, and the current
235+ * KeyboardFocusManager will be unchanged.
236+ *
237+ * @param newManager the new KeyboardFocusManager for this thread's context
238+ * @see #getCurrentKeyboardFocusManager
239+ * @see DefaultKeyboardFocusManager
240+ * @throws SecurityException if the calling thread does not have permission
241+ * to replace the current KeyboardFocusManager
242+ */
243+ public static void setCurrentKeyboardFocusManager(
244+ KeyboardFocusManager newManager) throws SecurityException
245+ {
246+ SecurityManager security = System.getSecurityManager();
247+ if (security != null) {
248+ if (replaceKeyboardFocusManagerPermission == null) {
249+ replaceKeyboardFocusManagerPermission =
250+ new AWTPermission("replaceKeyboardFocusManager");
251+ }
252+ security.
253+ checkPermission(replaceKeyboardFocusManagerPermission);
254+ }
255+
256+ KeyboardFocusManager oldManager = null;
257+
258+ synchronized (KeyboardFocusManager.class) {
259+ AppContext appcontext = AppContext.getAppContext();
260+
261+ if (newManager != null) {
262+ oldManager = getCurrentKeyboardFocusManager(appcontext);
263+
264+ appcontext.put(KeyboardFocusManager.class, newManager);
265+ } else {
266+ oldManager = getCurrentKeyboardFocusManager(appcontext);
267+ appcontext.remove(KeyboardFocusManager.class);
268+ }
269+ }
270+
271+ if (oldManager != null) {
272+ oldManager.firePropertyChange("managingFocus",
273+ Boolean.TRUE,
274+ Boolean.FALSE);
275+ }
276+ if (newManager != null) {
277+ newManager.firePropertyChange("managingFocus",
278+ Boolean.FALSE,
279+ Boolean.TRUE);
280+ }
281+ }
282+
283+ /**
284+ * The Component in an application that will typically receive all
285+ * KeyEvents generated by the user.
286+ */
287+ private static Component focusOwner;
288+
289+ /**
290+ * The Component in an application that will regain focus when an
291+ * outstanding temporary focus transfer has completed, or the focus owner,
292+ * if no outstanding temporary transfer exists.
293+ */
294+ private static Component permanentFocusOwner;
295+
296+ /**
297+ * The Window which is, or contains, the focus owner.
298+ */
299+ private static Window focusedWindow;
300+
301+ /**
302+ * Only a Frame or a Dialog can be the active Window. The native windowing
303+ * system may denote the active Window with a special decoration, such as a
304+ * highlighted title bar. The active Window is always either the focused
305+ * Window, or the first Frame or Dialog which is an owner of the focused
306+ * Window.
307+ */
308+ private static Window activeWindow;
309+
310+ /**
311+ * The default FocusTraversalPolicy for all Windows that have no policy of
312+ * their own set. If those Windows have focus-cycle-root children that have
313+ * no keyboard-traversal policy of their own, then those children will also
314+ * inherit this policy (as will, recursively, their focus-cycle-root
315+ * children).
316+ */
317+ private FocusTraversalPolicy defaultPolicy =
318+ new DefaultFocusTraversalPolicy();
319+
320+ /**
321+ * The bound property names of each focus traversal key.
322+ */
323+ private static final String[] defaultFocusTraversalKeyPropertyNames = {
324+ "forwardDefaultFocusTraversalKeys",
325+ "backwardDefaultFocusTraversalKeys",
326+ "upCycleDefaultFocusTraversalKeys",
327+ "downCycleDefaultFocusTraversalKeys"
328+ };
329+
330+ /**
331+ * The default strokes for initializing the default focus traversal keys.
332+ */
333+ private static final AWTKeyStroke[][] defaultFocusTraversalKeyStrokes = {
334+ {
335+ AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, 0, false),
336+ AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, InputEvent.CTRL_DOWN_MASK | InputEvent.CTRL_MASK, false),
337+ },
338+ {
339+ AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, InputEvent.SHIFT_DOWN_MASK | InputEvent.SHIFT_MASK, false),
340+ AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB,
341+ InputEvent.SHIFT_DOWN_MASK | InputEvent.SHIFT_MASK | InputEvent.CTRL_DOWN_MASK | InputEvent.CTRL_MASK,
342+ false),
343+ },
344+ {},
345+ {},
346+ };
347+ /**
348+ * The default focus traversal keys. Each array of traversal keys will be
349+ * in effect on all Windows that have no such array of their own explicitly
350+ * set. Each array will also be inherited, recursively, by any child
351+ * Component of those Windows that has no such array of its own explicitly
352+ * set.
353+ */
354+ private Set[] defaultFocusTraversalKeys = new Set[4];
355+
356+ /**
357+ * The current focus cycle root. If the focus owner is itself a focus cycle
358+ * root, then it may be ambiguous as to which Components represent the next
359+ * and previous Components to focus during normal focus traversal. In that
360+ * case, the current focus cycle root is used to differentiate among the
361+ * possibilities.
362+ */
363+ private static Container currentFocusCycleRoot;
364+
365+ /**
366+ * A description of any VetoableChangeListeners which have been registered.
367+ */
368+ private VetoableChangeSupport vetoableSupport;
369+
370+ /**
371+ * A description of any PropertyChangeListeners which have been registered.
372+ */
373+ private PropertyChangeSupport changeSupport;
374+
375+ /**
376+ * This KeyboardFocusManager's KeyEventDispatcher chain. The List does not
377+ * include this KeyboardFocusManager unless it was explicitly re-registered
378+ * via a call to <code>addKeyEventDispatcher</code>. If no other
379+ * KeyEventDispatchers are registered, this field may be null or refer to
380+ * a List of length 0.
381+ */
382+ private java.util.LinkedList keyEventDispatchers;
383+
384+ /**
385+ * This KeyboardFocusManager's KeyEventPostProcessor chain. The List does
386+ * not include this KeyboardFocusManager unless it was explicitly
387+ * re-registered via a call to <code>addKeyEventPostProcessor</code>.
388+ * If no other KeyEventPostProcessors are registered, this field may be
389+ * null or refer to a List of length 0.
390+ */
391+ private java.util.LinkedList keyEventPostProcessors;
392+
393+ /**
394+ * Maps Windows to those Windows' most recent focus owners.
395+ */
396+ private static java.util.Map mostRecentFocusOwners = new WeakHashMap();
397+
398+ /**
399+ * Error String for initializing SecurityExceptions.
400+ */
401+ private static final String notPrivileged = "this KeyboardFocusManager is not installed in the current thread's context";
402+
403+ /**
404+ * We cache the permission used to verify that the calling thread is
405+ * permitted to access the global focus state.
406+ */
407+ private static AWTPermission replaceKeyboardFocusManagerPermission;
408+
409+ /*
410+ * SequencedEvent which is currently dispatched in AppContext.
411+ */
412+ transient SequencedEvent currentSequencedEvent = null;
413+
414+ final void setCurrentSequencedEvent(SequencedEvent current) {
415+ synchronized (SequencedEvent.class) {
416+ assert(current == null || currentSequencedEvent == null);
417+ currentSequencedEvent = current;
418+ }
419+ }
420+
421+ final SequencedEvent getCurrentSequencedEvent() {
422+ synchronized (SequencedEvent.class) {
423+ return currentSequencedEvent;
424+ }
425+ }
426+
427+ static Set initFocusTraversalKeysSet(String value, Set targetSet) {
428+ StringTokenizer tokens = new StringTokenizer(value, ",");
429+ while (tokens.hasMoreTokens()) {
430+ targetSet.add(AWTKeyStroke.getAWTKeyStroke(tokens.nextToken()));
431+ }
432+ return (targetSet.isEmpty())
433+ ? Collections.EMPTY_SET
434+ : Collections.unmodifiableSet(targetSet);
435+ }
436+
437+ /**
438+ * Initializes a KeyboardFocusManager.
439+ */
440+ public KeyboardFocusManager() {
441+ for (int i = 0; i < TRAVERSAL_KEY_LENGTH; i++) {
442+ Set work_set = new HashSet();
443+ for (int j = 0; j < defaultFocusTraversalKeyStrokes[i].length; j++) {
444+ work_set.add(defaultFocusTraversalKeyStrokes[i][j]);
445+ }
446+ defaultFocusTraversalKeys[i] = (work_set.isEmpty())
447+ ? Collections.EMPTY_SET
448+ : Collections.unmodifiableSet(work_set);
449+ }
450+ initPeer();
451+ }
452+
453+ private void initPeer() {
454+ Toolkit tk = Toolkit.getDefaultToolkit();
455+ KeyboardFocusManagerPeerProvider peerProvider = (KeyboardFocusManagerPeerProvider)tk;
456+ peer = peerProvider.createKeyboardFocusManagerPeer(this);
457+ }
458+
459+ /**
460+ * Returns the focus owner, if the focus owner is in the same context as
461+ * the calling thread. The focus owner is defined as the Component in an
462+ * application that will typically receive all KeyEvents generated by the
463+ * user. KeyEvents which map to the focus owner's focus traversal keys will
464+ * not be delivered if focus traversal keys are enabled for the focus
465+ * owner. In addition, KeyEventDispatchers may retarget or consume
466+ * KeyEvents before they reach the focus owner.
467+ *
468+ * @return the focus owner, or null if the focus owner is not a member of
469+ * the calling thread's context
470+ * @see #getGlobalFocusOwner
471+ * @see #setGlobalFocusOwner
472+ */
473+ public Component getFocusOwner() {
474+ synchronized (KeyboardFocusManager.class) {
475+ if (focusOwner == null) {
476+ return null;
477+ }
478+
479+ return (focusOwner.appContext == AppContext.getAppContext())
480+ ? focusOwner
481+ : null;
482+ }
483+ }
484+
485+ /**
486+ * Returns the focus owner, even if the calling thread is in a different
487+ * context than the focus owner. The focus owner is defined as the
488+ * Component in an application that will typically receive all KeyEvents
489+ * generated by the user. KeyEvents which map to the focus owner's focus
490+ * traversal keys will not be delivered if focus traversal keys are enabled
491+ * for the focus owner. In addition, KeyEventDispatchers may retarget or
492+ * consume KeyEvents before they reach the focus owner.
493+ * <p>
494+ * This method will throw a SecurityException if this KeyboardFocusManager
495+ * is not the current KeyboardFocusManager for the calling thread's
496+ * context.
497+ *
498+ * @return the focus owner
499+ * @see #getFocusOwner
500+ * @see #setGlobalFocusOwner
501+ * @throws SecurityException if this KeyboardFocusManager is not the
502+ * current KeyboardFocusManager for the calling thread's context
503+ */
504+ protected Component getGlobalFocusOwner() throws SecurityException {
505+ synchronized (KeyboardFocusManager.class) {
506+ if (this == getCurrentKeyboardFocusManager()) {
507+ return focusOwner;
508+ } else {
509+ if (focusLog.isLoggable(PlatformLogger.FINER)) {
510+ focusLog.finer("This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
511+ }
512+ throw new SecurityException(notPrivileged);
513+ }
514+ }
515+ }
516+
517+ /**
518+ * Sets the focus owner. The operation will be cancelled if the Component
519+ * is not focusable. The focus owner is defined as the Component in an
520+ * application that will typically receive all KeyEvents generated by the
521+ * user. KeyEvents which map to the focus owner's focus traversal keys will
522+ * not be delivered if focus traversal keys are enabled for the focus
523+ * owner. In addition, KeyEventDispatchers may retarget or consume
524+ * KeyEvents before they reach the focus owner.
525+ * <p>
526+ * This method does not actually set the focus to the specified Component.
527+ * It merely stores the value to be subsequently returned by
528+ * <code>getFocusOwner()</code>. Use <code>Component.requestFocus()</code>
529+ * or <code>Component.requestFocusInWindow()</code> to change the focus
530+ * owner, subject to platform limitations.
531+ *
532+ * @param focusOwner the focus owner
533+ * @see #getFocusOwner
534+ * @see #getGlobalFocusOwner
535+ * @see Component#requestFocus()
536+ * @see Component#requestFocusInWindow()
537+ * @see Component#isFocusable
538+ * @beaninfo
539+ * bound: true
540+ */
541+ protected void setGlobalFocusOwner(Component focusOwner) {
542+ Component oldFocusOwner = null;
543+ boolean shouldFire = false;
544+
545+ if (focusOwner == null || focusOwner.isFocusable()) {
546+ synchronized (KeyboardFocusManager.class) {
547+ oldFocusOwner = getFocusOwner();
548+
549+ try {
550+ fireVetoableChange("focusOwner", oldFocusOwner,
551+ focusOwner);
552+ } catch (PropertyVetoException e) {
553+ // rejected
554+ return;
555+ }
556+
557+ KeyboardFocusManager.focusOwner = focusOwner;
558+
559+ if (focusOwner != null &&
560+ (getCurrentFocusCycleRoot() == null ||
561+ !focusOwner.isFocusCycleRoot(getCurrentFocusCycleRoot())))
562+ {
563+ Container rootAncestor =
564+ focusOwner.getFocusCycleRootAncestor();
565+ if (rootAncestor == null && (focusOwner instanceof Window))
566+ {
567+ rootAncestor = (Container)focusOwner;
568+ }
569+ if (rootAncestor != null) {
570+ setGlobalCurrentFocusCycleRoot(rootAncestor);
571+ }
572+ }
573+
574+ shouldFire = true;
575+ }
576+ }
577+
578+ if (shouldFire) {
579+ firePropertyChange("focusOwner", oldFocusOwner, focusOwner);
580+ }
581+ }
582+
583+ /**
584+ * Clears the global focus owner at both the Java and native levels. If
585+ * there exists a focus owner, that Component will receive a permanent
586+ * FOCUS_LOST event. After this operation completes, the native windowing
587+ * system will discard all user-generated KeyEvents until the user selects
588+ * a new Component to receive focus, or a Component is given focus
589+ * explicitly via a call to <code>requestFocus()</code>. This operation
590+ * does not change the focused or active Windows.
591+ *
592+ * @see Component#requestFocus()
593+ * @see java.awt.event.FocusEvent#FOCUS_LOST
594+ */
595+ public void clearGlobalFocusOwner() {
596+ if (!GraphicsEnvironment.isHeadless()) {
597+ // Toolkit must be fully initialized, otherwise
598+ // _clearGlobalFocusOwner will crash or throw an exception
599+ Toolkit.getDefaultToolkit();
600+
601+ _clearGlobalFocusOwner();
602+ }
603+ }
604+ private void _clearGlobalFocusOwner() {
605+ Window activeWindow = markClearGlobalFocusOwner();
606+ peer.clearGlobalFocusOwner(activeWindow);
607+ }
608+
609+ Component getNativeFocusOwner() {
610+ return peer.getCurrentFocusOwner();
611+ }
612+
613+ void setNativeFocusOwner(Component comp) {
614+ if (focusLog.isLoggable(PlatformLogger.FINEST)) {
615+ focusLog.finest("Calling peer {0} setCurrentFocusOwner for {1}",
616+ String.valueOf(peer), String.valueOf(comp));
617+ }
618+ peer.setCurrentFocusOwner(comp);
619+ }
620+
621+ Window getNativeFocusedWindow() {
622+ return peer.getCurrentFocusedWindow();
623+ }
624+
625+ /**
626+ * Returns the permanent focus owner, if the permanent focus owner is in
627+ * the same context as the calling thread. The permanent focus owner is
628+ * defined as the last Component in an application to receive a permanent
629+ * FOCUS_GAINED event. The focus owner and permanent focus owner are
630+ * equivalent unless a temporary focus change is currently in effect. In
631+ * such a situation, the permanent focus owner will again be the focus
632+ * owner when the temporary focus change ends.
633+ *
634+ * @return the permanent focus owner, or null if the permanent focus owner
635+ * is not a member of the calling thread's context
636+ * @see #getGlobalPermanentFocusOwner
637+ * @see #setGlobalPermanentFocusOwner
638+ */
639+ public Component getPermanentFocusOwner() {
640+ synchronized (KeyboardFocusManager.class) {
641+ if (permanentFocusOwner == null) {
642+ return null;
643+ }
644+
645+ return (permanentFocusOwner.appContext ==
646+ AppContext.getAppContext())
647+ ? permanentFocusOwner
648+ : null;
649+ }
650+ }
651+
652+ /**
653+ * Returns the permanent focus owner, even if the calling thread is in a
654+ * different context than the permanent focus owner. The permanent focus
655+ * owner is defined as the last Component in an application to receive a
656+ * permanent FOCUS_GAINED event. The focus owner and permanent focus owner
657+ * are equivalent unless a temporary focus change is currently in effect.
658+ * In such a situation, the permanent focus owner will again be the focus
659+ * owner when the temporary focus change ends.
660+ * <p>
661+ * This method will throw a SecurityException if this KeyboardFocusManager
662+ * is not the current KeyboardFocusManager for the calling thread's
663+ * context.
664+ *
665+ * @return the permanent focus owner
666+ * @see #getPermanentFocusOwner
667+ * @see #setGlobalPermanentFocusOwner
668+ * @throws SecurityException if this KeyboardFocusManager is not the
669+ * current KeyboardFocusManager for the calling thread's context
670+ */
671+ protected Component getGlobalPermanentFocusOwner()
672+ throws SecurityException
673+ {
674+ synchronized (KeyboardFocusManager.class) {
675+ if (this == getCurrentKeyboardFocusManager()) {
676+ return permanentFocusOwner;
677+ } else {
678+ if (focusLog.isLoggable(PlatformLogger.FINER)) {
679+ focusLog.finer("This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
680+ }
681+ throw new SecurityException(notPrivileged);
682+ }
683+ }
684+ }
685+
686+ /**
687+ * Sets the permanent focus owner. The operation will be cancelled if the
688+ * Component is not focusable. The permanent focus owner is defined as the
689+ * last Component in an application to receive a permanent FOCUS_GAINED
690+ * event. The focus owner and permanent focus owner are equivalent unless
691+ * a temporary focus change is currently in effect. In such a situation,
692+ * the permanent focus owner will again be the focus owner when the
693+ * temporary focus change ends.
694+ * <p>
695+ * This method does not actually set the focus to the specified Component.
696+ * It merely stores the value to be subsequently returned by
697+ * <code>getPermanentFocusOwner()</code>. Use
698+ * <code>Component.requestFocus()</code> or
699+ * <code>Component.requestFocusInWindow()</code> to change the focus owner,
700+ * subject to platform limitations.
701+ *
702+ * @param permanentFocusOwner the permanent focus owner
703+ * @see #getPermanentFocusOwner
704+ * @see #getGlobalPermanentFocusOwner
705+ * @see Component#requestFocus()
706+ * @see Component#requestFocusInWindow()
707+ * @see Component#isFocusable
708+ * @beaninfo
709+ * bound: true
710+ */
711+ protected void setGlobalPermanentFocusOwner(Component permanentFocusOwner)
712+ {
713+ Component oldPermanentFocusOwner = null;
714+ boolean shouldFire = false;
715+
716+ if (permanentFocusOwner == null || permanentFocusOwner.isFocusable()) {
717+ synchronized (KeyboardFocusManager.class) {
718+ oldPermanentFocusOwner = getPermanentFocusOwner();
719+
720+ try {
721+ fireVetoableChange("permanentFocusOwner",
722+ oldPermanentFocusOwner,
723+ permanentFocusOwner);
724+ } catch (PropertyVetoException e) {
725+ // rejected
726+ return;
727+ }
728+
729+ KeyboardFocusManager.permanentFocusOwner = permanentFocusOwner;
730+
731+ KeyboardFocusManager.
732+ setMostRecentFocusOwner(permanentFocusOwner);
733+
734+ shouldFire = true;
735+ }
736+ }
737+
738+ if (shouldFire) {
739+ firePropertyChange("permanentFocusOwner", oldPermanentFocusOwner,
740+ permanentFocusOwner);
741+ }
742+ }
743+
744+ /**
745+ * Returns the focused Window, if the focused Window is in the same context
746+ * as the calling thread. The focused Window is the Window that is or
747+ * contains the focus owner.
748+ *
749+ * @return the focused Window, or null if the focused Window is not a
750+ * member of the calling thread's context
751+ * @see #getGlobalFocusedWindow
752+ * @see #setGlobalFocusedWindow
753+ */
754+ public Window getFocusedWindow() {
755+ synchronized (KeyboardFocusManager.class) {
756+ if (focusedWindow == null) {
757+ return null;
758+ }
759+
760+ return (focusedWindow.appContext == AppContext.getAppContext())
761+ ? focusedWindow
762+ : null;
763+ }
764+ }
765+
766+ /**
767+ * Returns the focused Window, even if the calling thread is in a different
768+ * context than the focused Window. The focused Window is the Window that
769+ * is or contains the focus owner.
770+ * <p>
771+ * This method will throw a SecurityException if this KeyboardFocusManager
772+ * is not the current KeyboardFocusManager for the calling thread's
773+ * context.
774+ *
775+ * @return the focused Window
776+ * @see #getFocusedWindow
777+ * @see #setGlobalFocusedWindow
778+ * @throws SecurityException if this KeyboardFocusManager is not the
779+ * current KeyboardFocusManager for the calling thread's context
780+ */
781+ protected Window getGlobalFocusedWindow() throws SecurityException {
782+ synchronized (KeyboardFocusManager.class) {
783+ if (this == getCurrentKeyboardFocusManager()) {
784+ return focusedWindow;
785+ } else {
786+ if (focusLog.isLoggable(PlatformLogger.FINER)) {
787+ focusLog.finer("This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
788+ }
789+ throw new SecurityException(notPrivileged);
790+ }
791+ }
792+ }
793+
794+ /**
795+ * Sets the focused Window. The focused Window is the Window that is or
796+ * contains the focus owner. The operation will be cancelled if the
797+ * specified Window to focus is not a focusable Window.
798+ * <p>
799+ * This method does not actually change the focused Window as far as the
800+ * native windowing system is concerned. It merely stores the value to be
801+ * subsequently returned by <code>getFocusedWindow()</code>. Use
802+ * <code>Component.requestFocus()</code> or
803+ * <code>Component.requestFocusInWindow()</code> to change the focused
804+ * Window, subject to platform limitations.
805+ *
806+ * @param focusedWindow the focused Window
807+ * @see #getFocusedWindow
808+ * @see #getGlobalFocusedWindow
809+ * @see Component#requestFocus()
810+ * @see Component#requestFocusInWindow()
811+ * @see Window#isFocusableWindow
812+ * @beaninfo
813+ * bound: true
814+ */
815+ protected void setGlobalFocusedWindow(Window focusedWindow) {
816+ Window oldFocusedWindow = null;
817+ boolean shouldFire = false;
818+
819+ if (focusedWindow == null || focusedWindow.isFocusableWindow()) {
820+ synchronized (KeyboardFocusManager.class) {
821+ oldFocusedWindow = getFocusedWindow();
822+
823+ try {
824+ fireVetoableChange("focusedWindow", oldFocusedWindow,
825+ focusedWindow);
826+ } catch (PropertyVetoException e) {
827+ // rejected
828+ return;
829+ }
830+
831+ KeyboardFocusManager.focusedWindow = focusedWindow;
832+ shouldFire = true;
833+ }
834+ }
835+
836+ if (shouldFire) {
837+ firePropertyChange("focusedWindow", oldFocusedWindow,
838+ focusedWindow);
839+ }
840+ }
841+
842+ /**
843+ * Returns the active Window, if the active Window is in the same context
844+ * as the calling thread. Only a Frame or a Dialog can be the active
845+ * Window. The native windowing system may denote the active Window or its
846+ * children with special decorations, such as a highlighted title bar.
847+ * The active Window is always either the focused Window, or the first
848+ * Frame or Dialog that is an owner of the focused Window.
849+ *
850+ * @return the active Window, or null if the active Window is not a member
851+ * of the calling thread's context
852+ * @see #getGlobalActiveWindow
853+ * @see #setGlobalActiveWindow
854+ */
855+ public Window getActiveWindow() {
856+ synchronized (KeyboardFocusManager.class) {
857+ if (activeWindow == null) {
858+ return null;
859+ }
860+
861+ return (activeWindow.appContext == AppContext.getAppContext())
862+ ? activeWindow
863+ : null;
864+ }
865+ }
866+
867+ /**
868+ * Returns the active Window, even if the calling thread is in a different
869+ * context than the active Window. Only a Frame or a Dialog can be the
870+ * active Window. The native windowing system may denote the active Window
871+ * or its children with special decorations, such as a highlighted title
872+ * bar. The active Window is always either the focused Window, or the first
873+ * Frame or Dialog that is an owner of the focused Window.
874+ * <p>
875+ * This method will throw a SecurityException if this KeyboardFocusManager
876+ * is not the current KeyboardFocusManager for the calling thread's
877+ * context.
878+ *
879+ * @return the active Window
880+ * @see #getActiveWindow
881+ * @see #setGlobalActiveWindow
882+ * @throws SecurityException if this KeyboardFocusManager is not the
883+ * current KeyboardFocusManager for the calling thread's context
884+ */
885+ protected Window getGlobalActiveWindow() throws SecurityException {
886+ synchronized (KeyboardFocusManager.class) {
887+ if (this == getCurrentKeyboardFocusManager()) {
888+ return activeWindow;
889+ } else {
890+ if (focusLog.isLoggable(PlatformLogger.FINER)) {
891+ focusLog.finer("This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
892+ }
893+ throw new SecurityException(notPrivileged);
894+ }
895+ }
896+ }
897+
898+ /**
899+ * Sets the active Window. Only a Frame or a Dialog can be the active
900+ * Window. The native windowing system may denote the active Window or its
901+ * children with special decorations, such as a highlighted title bar. The
902+ * active Window is always either the focused Window, or the first Frame or
903+ * Dialog that is an owner of the focused Window.
904+ * <p>
905+ * This method does not actually change the active Window as far as the
906+ * native windowing system is concerned. It merely stores the value to be
907+ * subsequently returned by <code>getActiveWindow()</code>. Use
908+ * <code>Component.requestFocus()</code> or
909+ * <code>Component.requestFocusInWindow()</code>to change the active
910+ * Window, subject to platform limitations.
911+ *
912+ * @param activeWindow the active Window
913+ * @see #getActiveWindow
914+ * @see #getGlobalActiveWindow
915+ * @see Component#requestFocus()
916+ * @see Component#requestFocusInWindow()
917+ * @beaninfo
918+ * bound: true
919+ */
920+ protected void setGlobalActiveWindow(Window activeWindow) {
921+ Window oldActiveWindow;
922+ synchronized (KeyboardFocusManager.class) {
923+ oldActiveWindow = getActiveWindow();
924+ if (focusLog.isLoggable(PlatformLogger.FINER)) {
925+ focusLog.finer("Setting global active window to " + activeWindow + ", old active " + oldActiveWindow);
926+ }
927+
928+ try {
929+ fireVetoableChange("activeWindow", oldActiveWindow,
930+ activeWindow);
931+ } catch (PropertyVetoException e) {
932+ // rejected
933+ return;
934+ }
935+
936+ KeyboardFocusManager.activeWindow = activeWindow;
937+ }
938+
939+ firePropertyChange("activeWindow", oldActiveWindow, activeWindow);
940+ }
941+
942+ /**
943+ * Returns the default FocusTraversalPolicy. Top-level components
944+ * use this value on their creation to initialize their own focus traversal
945+ * policy by explicit call to Container.setFocusTraversalPolicy.
946+ *
947+ * @return the default FocusTraversalPolicy. null will never be returned.
948+ * @see #setDefaultFocusTraversalPolicy
949+ * @see Container#setFocusTraversalPolicy
950+ * @see Container#getFocusTraversalPolicy
951+ */
952+ public synchronized FocusTraversalPolicy getDefaultFocusTraversalPolicy() {
953+ return defaultPolicy;
954+ }
955+
956+ /**
957+ * Sets the default FocusTraversalPolicy. Top-level components
958+ * use this value on their creation to initialize their own focus traversal
959+ * policy by explicit call to Container.setFocusTraversalPolicy.
960+ * Note: this call doesn't affect already created components as they have
961+ * their policy initialized. Only new components will use this policy as
962+ * their default policy.
963+ *
964+ * @param defaultPolicy the new, default FocusTraversalPolicy
965+ * @see #getDefaultFocusTraversalPolicy
966+ * @see Container#setFocusTraversalPolicy
967+ * @see Container#getFocusTraversalPolicy
968+ * @throws IllegalArgumentException if defaultPolicy is null
969+ * @beaninfo
970+ * bound: true
971+ */
972+ public void setDefaultFocusTraversalPolicy(FocusTraversalPolicy
973+ defaultPolicy) {
974+ if (defaultPolicy == null) {
975+ throw new IllegalArgumentException("default focus traversal policy cannot be null");
976+ }
977+
978+ FocusTraversalPolicy oldPolicy;
979+
980+ synchronized (this) {
981+ oldPolicy = this.defaultPolicy;
982+ this.defaultPolicy = defaultPolicy;
983+ }
984+
985+ firePropertyChange("defaultFocusTraversalPolicy", oldPolicy,
986+ defaultPolicy);
987+ }
988+
989+ /**
990+ * Sets the default focus traversal keys for a given traversal operation.
991+ * This traversal key <code>Set</code> will be in effect on all
992+ * <code>Window</code>s that have no such <code>Set</code> of
993+ * their own explicitly defined. This <code>Set</code> will also be
994+ * inherited, recursively, by any child <code>Component</code> of
995+ * those <code>Windows</code> that has
996+ * no such <code>Set</code> of its own explicitly defined.
997+ * <p>
998+ * The default values for the default focus traversal keys are
999+ * implementation-dependent. Sun recommends that all implementations for a
1000+ * particular native platform use the same default values. The
1001+ * recommendations for Windows and Unix are listed below. These
1002+ * recommendations are used in the Sun AWT implementations.
1003+ *
1004+ * <table border=1 summary="Recommended default values for focus traversal keys">
1005+ * <tr>
1006+ * <th>Identifier</th>
1007+ * <th>Meaning</th>
1008+ * <th>Default</th>
1009+ * </tr>
1010+ * <tr>
1011+ * <td><code>KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS</code></td>
1012+ * <td>Normal forward keyboard traversal</td>
1013+ * <td><code>TAB</code> on <code>KEY_PRESSED</code>,
1014+ * <code>CTRL-TAB</code> on <code>KEY_PRESSED</code></td>
1015+ * </tr>
1016+ * <tr>
1017+ * <td><code>KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS</code></td>
1018+ * <td>Normal reverse keyboard traversal</td>
1019+ * <td><code>SHIFT-TAB</code> on <code>KEY_PRESSED</code>,
1020+ * <code>CTRL-SHIFT-TAB</code> on <code>KEY_PRESSED</code></td>
1021+ * </tr>
1022+ * <tr>
1023+ * <td><code>KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS</code></td>
1024+ * <td>Go up one focus traversal cycle</td>
1025+ * <td>none</td>
1026+ * </tr>
1027+ * <tr>
1028+ * <td><code>KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS</code></td>
1029+ * <td>Go down one focus traversal cycle</td>
1030+ * <td>none</td>
1031+ * </tr>
1032+ * </table>
1033+ *
1034+ * To disable a traversal key, use an empty <code>Set</code>;
1035+ * <code>Collections.EMPTY_SET</code> is recommended.
1036+ * <p>
1037+ * Using the <code>AWTKeyStroke</code> API, client code can
1038+ * specify on which of two
1039+ * specific <code>KeyEvent</code>s, <code>KEY_PRESSED</code> or
1040+ * <code>KEY_RELEASED</code>, the focus traversal operation will
1041+ * occur. Regardless of which <code>KeyEvent</code> is specified,
1042+ * however, all <code>KeyEvent</code>s related to the focus
1043+ * traversal key, including the associated <code>KEY_TYPED</code>
1044+ * event, will be consumed, and will not be dispatched
1045+ * to any <code>Component</code>. It is a runtime error to
1046+ * specify a <code>KEY_TYPED</code> event as
1047+ * mapping to a focus traversal operation, or to map the same event to
1048+ * multiple default focus traversal operations.
1049+ *
1050+ * @param id one of
1051+ * <code>KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS</code>,
1052+ * <code>KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS</code>,
1053+ * <code>KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS</code>, or
1054+ * <code>KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS</code>
1055+ * @param keystrokes the Set of <code>AWTKeyStroke</code>s for the
1056+ * specified operation
1057+ * @see #getDefaultFocusTraversalKeys
1058+ * @see Component#setFocusTraversalKeys
1059+ * @see Component#getFocusTraversalKeys
1060+ * @throws IllegalArgumentException if id is not one of
1061+ * <code>KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS</code>,
1062+ * <code>KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS</code>,
1063+ * <code>KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS</code>, or
1064+ * <code>KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS</code>,
1065+ * or if keystrokes is <code>null</code>,
1066+ * or if keystrokes contains <code>null</code>,
1067+ * or if any <code>Object</code> in
1068+ * keystrokes is not an <code>AWTKeyStroke</code>,
1069+ * or if any keystroke
1070+ * represents a <code>KEY_TYPED</code> event,
1071+ * or if any keystroke already maps
1072+ * to another default focus traversal operation
1073+ * @beaninfo
1074+ * bound: true
1075+ */
1076+ public void
1077+ setDefaultFocusTraversalKeys(int id,
1078+ Set<? extends AWTKeyStroke> keystrokes)
1079+ {
1080+ if (id < 0 || id >= TRAVERSAL_KEY_LENGTH) {
1081+ throw new IllegalArgumentException("invalid focus traversal key identifier");
1082+ }
1083+ if (keystrokes == null) {
1084+ throw new IllegalArgumentException("cannot set null Set of default focus traversal keys");
1085+ }
1086+
1087+ Set oldKeys;
1088+
1089+ synchronized (this) {
1090+ for (Iterator iter = keystrokes.iterator(); iter.hasNext(); ) {
1091+ Object obj = iter.next();
1092+
1093+ if (obj == null) {
1094+ throw new IllegalArgumentException("cannot set null focus traversal key");
1095+ }
1096+
1097+ // Fix for 6195831:
1098+ //According to javadoc this method should throw IAE instead of ClassCastException
1099+ if (!(obj instanceof AWTKeyStroke)) {
1100+ throw new IllegalArgumentException("object is expected to be AWTKeyStroke");
1101+ }
1102+ AWTKeyStroke keystroke = (AWTKeyStroke)obj;
1103+
1104+ if (keystroke.getKeyChar() != KeyEvent.CHAR_UNDEFINED) {
1105+ throw new IllegalArgumentException("focus traversal keys cannot map to KEY_TYPED events");
1106+ }
1107+
1108+ // Check to see if key already maps to another traversal
1109+ // operation
1110+ for (int i = 0; i < TRAVERSAL_KEY_LENGTH; i++) {
1111+ if (i == id) {
1112+ continue;
1113+ }
1114+
1115+ if (defaultFocusTraversalKeys[i].contains(keystroke)) {
1116+ throw new IllegalArgumentException("focus traversal keys must be unique for a Component");
1117+ }
1118+ }
1119+ }
1120+
1121+ oldKeys = defaultFocusTraversalKeys[id];
1122+ defaultFocusTraversalKeys[id] =
1123+ Collections.unmodifiableSet(new HashSet(keystrokes));
1124+ }
1125+
1126+ firePropertyChange(defaultFocusTraversalKeyPropertyNames[id],
1127+ oldKeys, keystrokes);
1128+ }
1129+
1130+ /**
1131+ * Returns a Set of default focus traversal keys for a given traversal
1132+ * operation. This traversal key Set will be in effect on all Windows that
1133+ * have no such Set of their own explicitly defined. This Set will also be
1134+ * inherited, recursively, by any child Component of those Windows that has
1135+ * no such Set of its own explicitly defined. (See
1136+ * <code>setDefaultFocusTraversalKeys</code> for a full description of each
1137+ * operation.)
1138+ *
1139+ * @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
1140+ * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
1141+ * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
1142+ * KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
1143+ * @return the <code>Set</code> of <code>AWTKeyStroke</code>s
1144+ * for the specified operation; the <code>Set</code>
1145+ * will be unmodifiable, and may be empty; <code>null</code>
1146+ * will never be returned
1147+ * @see #setDefaultFocusTraversalKeys
1148+ * @see Component#setFocusTraversalKeys
1149+ * @see Component#getFocusTraversalKeys
1150+ * @throws IllegalArgumentException if id is not one of
1151+ * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
1152+ * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
1153+ * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
1154+ * KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
1155+ */
1156+ public Set<AWTKeyStroke> getDefaultFocusTraversalKeys(int id) {
1157+ if (id < 0 || id >= TRAVERSAL_KEY_LENGTH) {
1158+ throw new IllegalArgumentException("invalid focus traversal key identifier");
1159+ }
1160+
1161+ // Okay to return Set directly because it is an unmodifiable view
1162+ return defaultFocusTraversalKeys[id];
1163+ }
1164+
1165+ /**
1166+ * Returns the current focus cycle root, if the current focus cycle root is
1167+ * in the same context as the calling thread. If the focus owner is itself
1168+ * a focus cycle root, then it may be ambiguous as to which Components
1169+ * represent the next and previous Components to focus during normal focus
1170+ * traversal. In that case, the current focus cycle root is used to
1171+ * differentiate among the possibilities.
1172+ * <p>
1173+ * This method is intended to be used only by KeyboardFocusManagers and
1174+ * focus implementations. It is not for general client use.
1175+ *
1176+ * @return the current focus cycle root, or null if the current focus cycle
1177+ * root is not a member of the calling thread's context
1178+ * @see #getGlobalCurrentFocusCycleRoot
1179+ * @see #setGlobalCurrentFocusCycleRoot
1180+ */
1181+ public Container getCurrentFocusCycleRoot() {
1182+ synchronized (KeyboardFocusManager.class) {
1183+ if (currentFocusCycleRoot == null) {
1184+ return null;
1185+ }
1186+
1187+ return (currentFocusCycleRoot.appContext ==
1188+ AppContext.getAppContext())
1189+ ? currentFocusCycleRoot
1190+ : null;
1191+ }
1192+ }
1193+
1194+ /**
1195+ * Returns the current focus cycle root, even if the calling thread is in a
1196+ * different context than the current focus cycle root. If the focus owner
1197+ * is itself a focus cycle root, then it may be ambiguous as to which
1198+ * Components represent the next and previous Components to focus during
1199+ * normal focus traversal. In that case, the current focus cycle root is
1200+ * used to differentiate among the possibilities.
1201+ * <p>
1202+ * This method will throw a SecurityException if this KeyboardFocusManager
1203+ * is not the current KeyboardFocusManager for the calling thread's
1204+ * context.
1205+ *
1206+ * @return the current focus cycle root, or null if the current focus cycle
1207+ * root is not a member of the calling thread's context
1208+ * @see #getCurrentFocusCycleRoot
1209+ * @see #setGlobalCurrentFocusCycleRoot
1210+ * @throws SecurityException if this KeyboardFocusManager is not the
1211+ * current KeyboardFocusManager for the calling thread's context
1212+ */
1213+ protected Container getGlobalCurrentFocusCycleRoot()
1214+ throws SecurityException
1215+ {
1216+ synchronized (KeyboardFocusManager.class) {
1217+ if (this == getCurrentKeyboardFocusManager()) {
1218+ return currentFocusCycleRoot;
1219+ } else {
1220+ if (focusLog.isLoggable(PlatformLogger.FINER)) {
1221+ focusLog.finer("This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
1222+ }
1223+ throw new SecurityException(notPrivileged);
1224+ }
1225+ }
1226+ }
1227+
1228+ /**
1229+ * Sets the current focus cycle root. If the focus owner is itself a focus
1230+ * cycle root, then it may be ambiguous as to which Components represent
1231+ * the next and previous Components to focus during normal focus traversal.
1232+ * In that case, the current focus cycle root is used to differentiate
1233+ * among the possibilities.
1234+ * <p>
1235+ * This method is intended to be used only by KeyboardFocusManagers and
1236+ * focus implementations. It is not for general client use.
1237+ *
1238+ * @param newFocusCycleRoot the new focus cycle root
1239+ * @see #getCurrentFocusCycleRoot
1240+ * @see #getGlobalCurrentFocusCycleRoot
1241+ * @beaninfo
1242+ * bound: true
1243+ */
1244+ public void setGlobalCurrentFocusCycleRoot(Container newFocusCycleRoot) {
1245+ Container oldFocusCycleRoot;
1246+
1247+ synchronized (KeyboardFocusManager.class) {
1248+ oldFocusCycleRoot = getCurrentFocusCycleRoot();
1249+ currentFocusCycleRoot = newFocusCycleRoot;
1250+ }
1251+
1252+ firePropertyChange("currentFocusCycleRoot", oldFocusCycleRoot,
1253+ newFocusCycleRoot);
1254+ }
1255+
1256+ /**
1257+ * Adds a PropertyChangeListener to the listener list. The listener is
1258+ * registered for all bound properties of this class, including the
1259+ * following:
1260+ * <ul>
1261+ * <li>whether the KeyboardFocusManager is currently managing focus
1262+ * for this application or applet's browser context
1263+ * ("managingFocus")</li>
1264+ * <li>the focus owner ("focusOwner")</li>
1265+ * <li>the permanent focus owner ("permanentFocusOwner")</li>
1266+ * <li>the focused Window ("focusedWindow")</li>
1267+ * <li>the active Window ("activeWindow")</li>
1268+ * <li>the default focus traversal policy
1269+ * ("defaultFocusTraversalPolicy")</li>
1270+ * <li>the Set of default FORWARD_TRAVERSAL_KEYS
1271+ * ("forwardDefaultFocusTraversalKeys")</li>
1272+ * <li>the Set of default BACKWARD_TRAVERSAL_KEYS
1273+ * ("backwardDefaultFocusTraversalKeys")</li>
1274+ * <li>the Set of default UP_CYCLE_TRAVERSAL_KEYS
1275+ * ("upCycleDefaultFocusTraversalKeys")</li>
1276+ * <li>the Set of default DOWN_CYCLE_TRAVERSAL_KEYS
1277+ * ("downCycleDefaultFocusTraversalKeys")</li>
1278+ * <li>the current focus cycle root ("currentFocusCycleRoot")</li>
1279+ * </ul>
1280+ * If listener is null, no exception is thrown and no action is performed.
1281+ *
1282+ * @param listener the PropertyChangeListener to be added
1283+ * @see #removePropertyChangeListener
1284+ * @see #getPropertyChangeListeners
1285+ * @see #addPropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
1286+ */
1287+ public void addPropertyChangeListener(PropertyChangeListener listener) {
1288+ if (listener != null) {
1289+ synchronized (this) {
1290+ if (changeSupport == null) {
1291+ changeSupport = new PropertyChangeSupport(this);
1292+ }
1293+ changeSupport.addPropertyChangeListener(listener);
1294+ }
1295+ }
1296+ }
1297+
1298+ /**
1299+ * Removes a PropertyChangeListener from the listener list. This method
1300+ * should be used to remove the PropertyChangeListeners that were
1301+ * registered for all bound properties of this class.
1302+ * <p>
1303+ * If listener is null, no exception is thrown and no action is performed.
1304+ *
1305+ * @param listener the PropertyChangeListener to be removed
1306+ * @see #addPropertyChangeListener
1307+ * @see #getPropertyChangeListeners
1308+ * @see #removePropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
1309+ */
1310+ public void removePropertyChangeListener(PropertyChangeListener listener) {
1311+ if (listener != null) {
1312+ synchronized (this) {
1313+ if (changeSupport != null) {
1314+ changeSupport.removePropertyChangeListener(listener);
1315+ }
1316+ }
1317+ }
1318+ }
1319+
1320+ /**
1321+ * Returns an array of all the property change listeners
1322+ * registered on this keyboard focus manager.
1323+ *
1324+ * @return all of this keyboard focus manager's
1325+ * <code>PropertyChangeListener</code>s
1326+ * or an empty array if no property change
1327+ * listeners are currently registered
1328+ *
1329+ * @see #addPropertyChangeListener
1330+ * @see #removePropertyChangeListener
1331+ * @see #getPropertyChangeListeners(java.lang.String)
1332+ * @since 1.4
1333+ */
1334+ public synchronized PropertyChangeListener[] getPropertyChangeListeners() {
1335+ if (changeSupport == null) {
1336+ changeSupport = new PropertyChangeSupport(this);
1337+ }
1338+ return changeSupport.getPropertyChangeListeners();
1339+ }
1340+
1341+ /**
1342+ * Adds a PropertyChangeListener to the listener list for a specific
1343+ * property. The specified property may be user-defined, or one of the
1344+ * following:
1345+ * <ul>
1346+ * <li>whether the KeyboardFocusManager is currently managing focus
1347+ * for this application or applet's browser context
1348+ * ("managingFocus")</li>
1349+ * <li>the focus owner ("focusOwner")</li>
1350+ * <li>the permanent focus owner ("permanentFocusOwner")</li>
1351+ * <li>the focused Window ("focusedWindow")</li>
1352+ * <li>the active Window ("activeWindow")</li>
1353+ * <li>the default focus traversal policy
1354+ * ("defaultFocusTraversalPolicy")</li>
1355+ * <li>the Set of default FORWARD_TRAVERSAL_KEYS
1356+ * ("forwardDefaultFocusTraversalKeys")</li>
1357+ * <li>the Set of default BACKWARD_TRAVERSAL_KEYS
1358+ * ("backwardDefaultFocusTraversalKeys")</li>
1359+ * <li>the Set of default UP_CYCLE_TRAVERSAL_KEYS
1360+ * ("upCycleDefaultFocusTraversalKeys")</li>
1361+ * <li>the Set of default DOWN_CYCLE_TRAVERSAL_KEYS
1362+ * ("downCycleDefaultFocusTraversalKeys")</li>
1363+ * <li>the current focus cycle root ("currentFocusCycleRoot")</li>
1364+ * </ul>
1365+ * If listener is null, no exception is thrown and no action is performed.
1366+ *
1367+ * @param propertyName one of the property names listed above
1368+ * @param listener the PropertyChangeListener to be added
1369+ * @see #addPropertyChangeListener(java.beans.PropertyChangeListener)
1370+ * @see #removePropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
1371+ * @see #getPropertyChangeListeners(java.lang.String)
1372+ */
1373+ public void addPropertyChangeListener(String propertyName,
1374+ PropertyChangeListener listener) {
1375+ if (listener != null) {
1376+ synchronized (this) {
1377+ if (changeSupport == null) {
1378+ changeSupport = new PropertyChangeSupport(this);
1379+ }
1380+ changeSupport.addPropertyChangeListener(propertyName,
1381+ listener);
1382+ }
1383+ }
1384+ }
1385+
1386+ /**
1387+ * Removes a PropertyChangeListener from the listener list for a specific
1388+ * property. This method should be used to remove PropertyChangeListeners
1389+ * that were registered for a specific bound property.
1390+ * <p>
1391+ * If listener is null, no exception is thrown and no action is performed.
1392+ *
1393+ * @param propertyName a valid property name
1394+ * @param listener the PropertyChangeListener to be removed
1395+ * @see #addPropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
1396+ * @see #getPropertyChangeListeners(java.lang.String)
1397+ * @see #removePropertyChangeListener(java.beans.PropertyChangeListener)
1398+ */
1399+ public void removePropertyChangeListener(String propertyName,
1400+ PropertyChangeListener listener) {
1401+ if (listener != null) {
1402+ synchronized (this) {
1403+ if (changeSupport != null) {
1404+ changeSupport.removePropertyChangeListener(propertyName,
1405+ listener);
1406+ }
1407+ }
1408+ }
1409+ }
1410+
1411+ /**
1412+ * Returns an array of all the <code>PropertyChangeListener</code>s
1413+ * associated with the named property.
1414+ *
1415+ * @return all of the <code>PropertyChangeListener</code>s associated with
1416+ * the named property or an empty array if no such listeners have
1417+ * been added.
1418+ *
1419+ * @see #addPropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
1420+ * @see #removePropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
1421+ * @since 1.4
1422+ */
1423+ public synchronized PropertyChangeListener[] getPropertyChangeListeners(String propertyName) {
1424+ if (changeSupport == null) {
1425+ changeSupport = new PropertyChangeSupport(this);
1426+ }
1427+ return changeSupport.getPropertyChangeListeners(propertyName);
1428+ }
1429+
1430+ /**
1431+ * Fires a PropertyChangeEvent in response to a change in a bound property.
1432+ * The event will be delivered to all registered PropertyChangeListeners.
1433+ * No event will be delivered if oldValue and newValue are the same.
1434+ *
1435+ * @param propertyName the name of the property that has changed
1436+ * @param oldValue the property's previous value
1437+ * @param newValue the property's new value
1438+ */
1439+ protected void firePropertyChange(String propertyName, Object oldValue,
1440+ Object newValue)
1441+ {
1442+ if (oldValue == newValue) {
1443+ return;
1444+ }
1445+ PropertyChangeSupport changeSupport = this.changeSupport;
1446+ if (changeSupport != null) {
1447+ changeSupport.firePropertyChange(propertyName, oldValue, newValue);
1448+ }
1449+ }
1450+
1451+ /**
1452+ * Adds a VetoableChangeListener to the listener list. The listener is
1453+ * registered for all vetoable properties of this class, including the
1454+ * following:
1455+ * <ul>
1456+ * <li>the focus owner ("focusOwner")</li>
1457+ * <li>the permanent focus owner ("permanentFocusOwner")</li>
1458+ * <li>the focused Window ("focusedWindow")</li>
1459+ * <li>the active Window ("activeWindow")</li>
1460+ * </ul>
1461+ * If listener is null, no exception is thrown and no action is performed.
1462+ *
1463+ * @param listener the VetoableChangeListener to be added
1464+ * @see #removeVetoableChangeListener
1465+ * @see #getVetoableChangeListeners
1466+ * @see #addVetoableChangeListener(java.lang.String,java.beans.VetoableChangeListener)
1467+ */
1468+ public void addVetoableChangeListener(VetoableChangeListener listener) {
1469+ if (listener != null) {
1470+ synchronized (this) {
1471+ if (vetoableSupport == null) {
1472+ vetoableSupport =
1473+ new VetoableChangeSupport(this);
1474+ }
1475+ vetoableSupport.addVetoableChangeListener(listener);
1476+ }
1477+ }
1478+ }
1479+
1480+ /**
1481+ * Removes a VetoableChangeListener from the listener list. This method
1482+ * should be used to remove the VetoableChangeListeners that were
1483+ * registered for all vetoable properties of this class.
1484+ * <p>
1485+ * If listener is null, no exception is thrown and no action is performed.
1486+ *
1487+ * @param listener the VetoableChangeListener to be removed
1488+ * @see #addVetoableChangeListener
1489+ * @see #getVetoableChangeListeners
1490+ * @see #removeVetoableChangeListener(java.lang.String,java.beans.VetoableChangeListener)
1491+ */
1492+ public void removeVetoableChangeListener(VetoableChangeListener listener) {
1493+ if (listener != null) {
1494+ synchronized (this) {
1495+ if (vetoableSupport != null) {
1496+ vetoableSupport.removeVetoableChangeListener(listener);
1497+ }
1498+ }
1499+ }
1500+ }
1501+
1502+ /**
1503+ * Returns an array of all the vetoable change listeners
1504+ * registered on this keyboard focus manager.
1505+ *
1506+ * @return all of this keyboard focus manager's
1507+ * <code>VetoableChangeListener</code>s
1508+ * or an empty array if no vetoable change
1509+ * listeners are currently registered
1510+ *
1511+ * @see #addVetoableChangeListener
1512+ * @see #removeVetoableChangeListener
1513+ * @see #getVetoableChangeListeners(java.lang.String)
1514+ * @since 1.4
1515+ */
1516+ public synchronized VetoableChangeListener[] getVetoableChangeListeners() {
1517+ if (vetoableSupport == null) {
1518+ vetoableSupport = new VetoableChangeSupport(this);
1519+ }
1520+ return vetoableSupport.getVetoableChangeListeners();
1521+ }
1522+
1523+ /**
1524+ * Adds a VetoableChangeListener to the listener list for a specific
1525+ * property. The specified property may be user-defined, or one of the
1526+ * following:
1527+ * <ul>
1528+ * <li>the focus owner ("focusOwner")</li>
1529+ * <li>the permanent focus owner ("permanentFocusOwner")</li>
1530+ * <li>the focused Window ("focusedWindow")</li>
1531+ * <li>the active Window ("activeWindow")</li>
1532+ * </ul>
1533+ * If listener is null, no exception is thrown and no action is performed.
1534+ *
1535+ * @param propertyName one of the property names listed above
1536+ * @param listener the VetoableChangeListener to be added
1537+ * @see #addVetoableChangeListener(java.beans.VetoableChangeListener)
1538+ * @see #removeVetoableChangeListener
1539+ * @see #getVetoableChangeListeners
1540+ */
1541+ public void addVetoableChangeListener(String propertyName,
1542+ VetoableChangeListener listener) {
1543+ if (listener != null) {
1544+ synchronized (this) {
1545+ if (vetoableSupport == null) {
1546+ vetoableSupport =
1547+ new VetoableChangeSupport(this);
1548+ }
1549+ vetoableSupport.addVetoableChangeListener(propertyName,
1550+ listener);
1551+ }
1552+ }
1553+ }
1554+
1555+ /**
1556+ * Removes a VetoableChangeListener from the listener list for a specific
1557+ * property. This method should be used to remove VetoableChangeListeners
1558+ * that were registered for a specific bound property.
1559+ * <p>
1560+ * If listener is null, no exception is thrown and no action is performed.
1561+ *
1562+ * @param propertyName a valid property name
1563+ * @param listener the VetoableChangeListener to be removed
1564+ * @see #addVetoableChangeListener
1565+ * @see #getVetoableChangeListeners
1566+ * @see #removeVetoableChangeListener(java.beans.VetoableChangeListener)
1567+ */
1568+ public void removeVetoableChangeListener(String propertyName,
1569+ VetoableChangeListener listener) {
1570+ if (listener != null) {
1571+ synchronized (this) {
1572+ if (vetoableSupport != null) {
1573+ vetoableSupport.removeVetoableChangeListener(propertyName,
1574+ listener);
1575+ }
1576+ }
1577+ }
1578+ }
1579+
1580+ /**
1581+ * Returns an array of all the <code>VetoableChangeListener</code>s
1582+ * associated with the named property.
1583+ *
1584+ * @return all of the <code>VetoableChangeListener</code>s associated with
1585+ * the named property or an empty array if no such listeners have
1586+ * been added.
1587+ *
1588+ * @see #addVetoableChangeListener(java.lang.String,java.beans.VetoableChangeListener)
1589+ * @see #removeVetoableChangeListener(java.lang.String,java.beans.VetoableChangeListener)
1590+ * @see #getVetoableChangeListeners
1591+ * @since 1.4
1592+ */
1593+ public synchronized VetoableChangeListener[] getVetoableChangeListeners(String propertyName) {
1594+ if (vetoableSupport == null) {
1595+ vetoableSupport = new VetoableChangeSupport(this);
1596+ }
1597+ return vetoableSupport.getVetoableChangeListeners(propertyName);
1598+ }
1599+
1600+ /**
1601+ * Fires a PropertyChangeEvent in response to a change in a vetoable
1602+ * property. The event will be delivered to all registered
1603+ * VetoableChangeListeners. If a VetoableChangeListener throws a
1604+ * PropertyVetoException, a new event is fired reverting all
1605+ * VetoableChangeListeners to the old value and the exception is then
1606+ * rethrown. No event will be delivered if oldValue and newValue are the
1607+ * same.
1608+ *
1609+ * @param propertyName the name of the property that has changed
1610+ * @param oldValue the property's previous value
1611+ * @param newValue the property's new value
1612+ * @throws java.beans.PropertyVetoException if a
1613+ * <code>VetoableChangeListener</code> threw
1614+ * <code>PropertyVetoException</code>
1615+ */
1616+ protected void fireVetoableChange(String propertyName, Object oldValue,
1617+ Object newValue)
1618+ throws PropertyVetoException
1619+ {
1620+ if (oldValue == newValue) {
1621+ return;
1622+ }
1623+ VetoableChangeSupport vetoableSupport =
1624+ this.vetoableSupport;
1625+ if (vetoableSupport != null) {
1626+ vetoableSupport.fireVetoableChange(propertyName, oldValue,
1627+ newValue);
1628+ }
1629+ }
1630+
1631+ /**
1632+ * Adds a KeyEventDispatcher to this KeyboardFocusManager's dispatcher
1633+ * chain. This KeyboardFocusManager will request that each
1634+ * KeyEventDispatcher dispatch KeyEvents generated by the user before
1635+ * finally dispatching the KeyEvent itself. KeyEventDispatchers will be
1636+ * notified in the order in which they were added. Notifications will halt
1637+ * as soon as one KeyEventDispatcher returns <code>true</code> from its
1638+ * <code>dispatchKeyEvent</code> method. There is no limit to the total
1639+ * number of KeyEventDispatchers which can be added, nor to the number of
1640+ * times which a particular KeyEventDispatcher instance can be added.
1641+ * <p>
1642+ * If a null dispatcher is specified, no action is taken and no exception
1643+ * is thrown.
1644+ * <p>
1645+ * In a multithreaded application, {@link KeyEventDispatcher} behaves
1646+ * the same as other AWT listeners. See
1647+ * <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
1648+ * >AWT Threading Issues</a> for more details.
1649+ *
1650+ * @param dispatcher the KeyEventDispatcher to add to the dispatcher chain
1651+ * @see #removeKeyEventDispatcher
1652+ */
1653+ public void addKeyEventDispatcher(KeyEventDispatcher dispatcher) {
1654+ if (dispatcher != null) {
1655+ synchronized (this) {
1656+ if (keyEventDispatchers == null) {
1657+ keyEventDispatchers = new java.util.LinkedList();
1658+ }
1659+ keyEventDispatchers.add(dispatcher);
1660+ }
1661+ }
1662+ }
1663+
1664+ /**
1665+ * Removes a KeyEventDispatcher which was previously added to this
1666+ * KeyboardFocusManager's dispatcher chain. This KeyboardFocusManager
1667+ * cannot itself be removed, unless it was explicitly re-registered via a
1668+ * call to <code>addKeyEventDispatcher</code>.
1669+ * <p>
1670+ * If a null dispatcher is specified, if the specified dispatcher is not
1671+ * in the dispatcher chain, or if this KeyboardFocusManager is specified
1672+ * without having been explicitly re-registered, no action is taken and no
1673+ * exception is thrown.
1674+ * <p>
1675+ * In a multithreaded application, {@link KeyEventDispatcher} behaves
1676+ * the same as other AWT listeners. See
1677+ * <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
1678+ * >AWT Threading Issues</a> for more details.
1679+ *
1680+ * @param dispatcher the KeyEventDispatcher to remove from the dispatcher
1681+ * chain
1682+ * @see #addKeyEventDispatcher
1683+ */
1684+ public void removeKeyEventDispatcher(KeyEventDispatcher dispatcher) {
1685+ if (dispatcher != null) {
1686+ synchronized (this) {
1687+ if (keyEventDispatchers != null) {
1688+ keyEventDispatchers.remove(dispatcher);
1689+ }
1690+ }
1691+ }
1692+ }
1693+
1694+ /**
1695+ * Returns this KeyboardFocusManager's KeyEventDispatcher chain as a List.
1696+ * The List will not include this KeyboardFocusManager unless it was
1697+ * explicitly re-registered via a call to
1698+ * <code>addKeyEventDispatcher</code>. If no other KeyEventDispatchers are
1699+ * registered, implementations are free to return null or a List of length
1700+ * 0. Client code should not assume one behavior over another, nor should
1701+ * it assume that the behavior, once established, will not change.
1702+ *
1703+ * @return a possibly null or empty List of KeyEventDispatchers
1704+ * @see #addKeyEventDispatcher
1705+ * @see #removeKeyEventDispatcher
1706+ */
1707+ protected synchronized java.util.List<KeyEventDispatcher>
1708+ getKeyEventDispatchers()
1709+ {
1710+ return (keyEventDispatchers != null)
1711+ ? (java.util.List)keyEventDispatchers.clone()
1712+ : null;
1713+ }
1714+
1715+ /**
1716+ * Adds a KeyEventPostProcessor to this KeyboardFocusManager's post-
1717+ * processor chain. After a KeyEvent has been dispatched to and handled by
1718+ * its target, KeyboardFocusManager will request that each
1719+ * KeyEventPostProcessor perform any necessary post-processing as part
1720+ * of the KeyEvent's final resolution. KeyEventPostProcessors
1721+ * will be notified in the order in which they were added; the current
1722+ * KeyboardFocusManager will be notified last. Notifications will halt
1723+ * as soon as one KeyEventPostProcessor returns <code>true</code> from its
1724+ * <code>postProcessKeyEvent</code> method. There is no limit to the the
1725+ * total number of KeyEventPostProcessors that can be added, nor to the
1726+ * number of times that a particular KeyEventPostProcessor instance can be
1727+ * added.
1728+ * <p>
1729+ * If a null post-processor is specified, no action is taken and no
1730+ * exception is thrown.
1731+ * <p>
1732+ * In a multithreaded application, {@link KeyEventPostProcessor} behaves
1733+ * the same as other AWT listeners. See
1734+ * <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
1735+ * >AWT Threading Issues</a> for more details.
1736+ *
1737+ * @param processor the KeyEventPostProcessor to add to the post-processor
1738+ * chain
1739+ * @see #removeKeyEventPostProcessor
1740+ */
1741+ public void addKeyEventPostProcessor(KeyEventPostProcessor processor) {
1742+ if (processor != null) {
1743+ synchronized (this) {
1744+ if (keyEventPostProcessors == null) {
1745+ keyEventPostProcessors = new java.util.LinkedList();
1746+ }
1747+ keyEventPostProcessors.add(processor);
1748+ }
1749+ }
1750+ }
1751+
1752+
1753+ /**
1754+ * Removes a previously added KeyEventPostProcessor from this
1755+ * KeyboardFocusManager's post-processor chain. This KeyboardFocusManager
1756+ * cannot itself be entirely removed from the chain. Only additional
1757+ * references added via <code>addKeyEventPostProcessor</code> can be
1758+ * removed.
1759+ * <p>
1760+ * If a null post-processor is specified, if the specified post-processor
1761+ * is not in the post-processor chain, or if this KeyboardFocusManager is
1762+ * specified without having been explicitly added, no action is taken and
1763+ * no exception is thrown.
1764+ * <p>
1765+ * In a multithreaded application, {@link KeyEventPostProcessor} behaves
1766+ * the same as other AWT listeners. See
1767+ * <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
1768+ * >AWT Threading Issues</a> for more details.
1769+ *
1770+ * @param processor the KeyEventPostProcessor to remove from the post-
1771+ * processor chain
1772+ * @see #addKeyEventPostProcessor
1773+ */
1774+ public void removeKeyEventPostProcessor(KeyEventPostProcessor processor) {
1775+ if (processor != null) {
1776+ synchronized (this) {
1777+ if (keyEventPostProcessors != null) {
1778+ keyEventPostProcessors.remove(processor);
1779+ }
1780+ }
1781+ }
1782+ }
1783+
1784+
1785+ /**
1786+ * Returns this KeyboardFocusManager's KeyEventPostProcessor chain as a
1787+ * List. The List will not include this KeyboardFocusManager unless it was
1788+ * explicitly added via a call to <code>addKeyEventPostProcessor</code>. If
1789+ * no KeyEventPostProcessors are registered, implementations are free to
1790+ * return null or a List of length 0. Client code should not assume one
1791+ * behavior over another, nor should it assume that the behavior, once
1792+ * established, will not change.
1793+ *
1794+ * @return a possibly null or empty List of KeyEventPostProcessors
1795+ * @see #addKeyEventPostProcessor
1796+ * @see #removeKeyEventPostProcessor
1797+ */
1798+ protected java.util.List<KeyEventPostProcessor>
1799+ getKeyEventPostProcessors()
1800+ {
1801+ return (keyEventPostProcessors != null)
1802+ ? (java.util.List)keyEventPostProcessors.clone()
1803+ : null;
1804+ }
1805+
1806+
1807+
1808+ static void setMostRecentFocusOwner(Component component) {
1809+ Component window = component;
1810+ while (window != null && !(window instanceof Window)) {
1811+ window = window.parent;
1812+ }
1813+ if (window != null) {
1814+ setMostRecentFocusOwner((Window)window, component);
1815+ }
1816+ }
1817+ static synchronized void setMostRecentFocusOwner(Window window,
1818+ Component component) {
1819+ // ATTN: component has a strong reference to window via chain
1820+ // of Component.parent fields. Since WeakHasMap refers to its
1821+ // values strongly, we need to break the strong link from the
1822+ // value (component) back to its key (window).
1823+ WeakReference weakValue = null;
1824+ if (component != null) {
1825+ weakValue = new WeakReference(component);
1826+ }
1827+ mostRecentFocusOwners.put(window, weakValue);
1828+ }
1829+ static void clearMostRecentFocusOwner(Component comp) {
1830+ Container window;
1831+
1832+ if (comp == null) {
1833+ return;
1834+ }
1835+
1836+ synchronized (comp.getTreeLock()) {
1837+ window = comp.getParent();
1838+ while (window != null && !(window instanceof Window)) {
1839+ window = window.getParent();
1840+ }
1841+ }
1842+
1843+ synchronized (KeyboardFocusManager.class) {
1844+ if ((window != null)
1845+ && (getMostRecentFocusOwner((Window)window) == comp))
1846+ {
1847+ setMostRecentFocusOwner((Window)window, null);
1848+ }
1849+ // Also clear temporary lost component stored in Window
1850+ if (window != null) {
1851+ Window realWindow = (Window)window;
1852+ if (realWindow.getTemporaryLostComponent() == comp) {
1853+ realWindow.setTemporaryLostComponent(null);
1854+ }
1855+ }
1856+ }
1857+ }
1858+
1859+ /*
1860+ * Please be careful changing this method! It is called from
1861+ * javax.swing.JComponent.runInputVerifier() using reflection.
1862+ */
1863+ static synchronized Component getMostRecentFocusOwner(Window window) {
1864+ WeakReference weakValue =
1865+ (WeakReference)mostRecentFocusOwners.get(window);
1866+ return weakValue == null ? null : (Component)weakValue.get();
1867+ }
1868+
1869+ /**
1870+ * This method is called by the AWT event dispatcher requesting that the
1871+ * current KeyboardFocusManager dispatch the specified event on its behalf.
1872+ * It is expected that all KeyboardFocusManagers will dispatch all
1873+ * FocusEvents, all WindowEvents related to focus, and all KeyEvents.
1874+ * These events should be dispatched based on the KeyboardFocusManager's
1875+ * notion of the focus owner and the focused and active Windows, sometimes
1876+ * overriding the source of the specified AWTEvent. Dispatching must be
1877+ * done using <code>redispatchEvent</code> to prevent the AWT event
1878+ * dispatcher from recursively requesting that the KeyboardFocusManager
1879+ * dispatch the event again. If this method returns <code>false</code>,
1880+ * then the AWT event dispatcher will attempt to dispatch the event itself.
1881+ *
1882+ * @param e the AWTEvent to be dispatched
1883+ * @return <code>true</code> if this method dispatched the event;
1884+ * <code>false</code> otherwise
1885+ * @see #redispatchEvent
1886+ * @see #dispatchKeyEvent
1887+ */
1888+ public abstract boolean dispatchEvent(AWTEvent e);
1889+
1890+ /**
1891+ * Redispatches an AWTEvent in such a way that the AWT event dispatcher
1892+ * will not recursively request that the KeyboardFocusManager, or any
1893+ * installed KeyEventDispatchers, dispatch the event again. Client
1894+ * implementations of <code>dispatchEvent</code> and client-defined
1895+ * KeyEventDispatchers must call <code>redispatchEvent(target, e)</code>
1896+ * instead of <code>target.dispatchEvent(e)</code> to dispatch an event.
1897+ * <p>
1898+ * This method is intended to be used only by KeyboardFocusManagers and
1899+ * KeyEventDispatchers. It is not for general client use.
1900+ *
1901+ * @param target the Component to which the event should be dispatched
1902+ * @param e the event to dispatch
1903+ * @see #dispatchEvent
1904+ * @see KeyEventDispatcher
1905+ */
1906+ public final void redispatchEvent(Component target, AWTEvent e) {
1907+ e.focusManagerIsDispatching = true;
1908+ target.dispatchEvent(e);
1909+ e.focusManagerIsDispatching = false;
1910+ }
1911+
1912+ /**
1913+ * Typically this method will be called by <code>dispatchEvent</code> if no
1914+ * other KeyEventDispatcher in the dispatcher chain dispatched the
1915+ * KeyEvent, or if no other KeyEventDispatchers are registered. If an
1916+ * implementation of this method returns <code>false</code>,
1917+ * <code>dispatchEvent</code> may try to dispatch the KeyEvent itself, or
1918+ * may simply return <code>false</code>. If <code>true</code> is returned,
1919+ * <code>dispatchEvent</code> should return <code>true</code> as well.
1920+ *
1921+ * @param e the KeyEvent which the current KeyboardFocusManager has
1922+ * requested that this KeyEventDispatcher dispatch
1923+ * @return <code>true</code> if the KeyEvent was dispatched;
1924+ * <code>false</code> otherwise
1925+ * @see #dispatchEvent
1926+ */
1927+ public abstract boolean dispatchKeyEvent(KeyEvent e);
1928+
1929+ /**
1930+ * This method will be called by <code>dispatchKeyEvent</code>.
1931+ * By default, this method will handle any unconsumed KeyEvents that
1932+ * map to an AWT <code>MenuShortcut</code> by consuming the event
1933+ * and activating the shortcut.
1934+ *
1935+ * @param e the KeyEvent to post-process
1936+ * @return <code>true</code> to indicate that no other
1937+ * KeyEventPostProcessor will be notified of the KeyEvent.
1938+ * @see #dispatchKeyEvent
1939+ * @see MenuShortcut
1940+ */
1941+ public abstract boolean postProcessKeyEvent(KeyEvent e);
1942+
1943+ /**
1944+ * This method initiates a focus traversal operation if and only if the
1945+ * KeyEvent represents a focus traversal key for the specified
1946+ * focusedComponent. It is expected that focusedComponent is the current
1947+ * focus owner, although this need not be the case. If it is not,
1948+ * focus traversal will nevertheless proceed as if focusedComponent
1949+ * were the current focus owner.
1950+ *
1951+ * @param focusedComponent the Component that will be the basis for a focus
1952+ * traversal operation if the specified event represents a focus
1953+ * traversal key for the Component
1954+ * @param e the event that may represent a focus traversal key
1955+ */
1956+ public abstract void processKeyEvent(Component focusedComponent,
1957+ KeyEvent e);
1958+
1959+ /**
1960+ * Called by the AWT to notify the KeyboardFocusManager that it should
1961+ * delay dispatching of KeyEvents until the specified Component becomes
1962+ * the focus owner. If client code requests a focus change, and the AWT
1963+ * determines that this request might be granted by the native windowing
1964+ * system, then the AWT will call this method. It is the responsibility of
1965+ * the KeyboardFocusManager to delay dispatching of KeyEvents with
1966+ * timestamps later than the specified time stamp until the specified
1967+ * Component receives a FOCUS_GAINED event, or the AWT cancels the delay
1968+ * request by invoking <code>dequeueKeyEvents</code> or
1969+ * <code>discardKeyEvents</code>.
1970+ *
1971+ * @param after timestamp of current event, or the current, system time if
1972+ * the current event has no timestamp, or the AWT cannot determine
1973+ * which event is currently being handled
1974+ * @param untilFocused Component which should receive a FOCUS_GAINED event
1975+ * before any pending KeyEvents
1976+ * @see #dequeueKeyEvents
1977+ * @see #discardKeyEvents
1978+ */
1979+ protected abstract void enqueueKeyEvents(long after,
1980+ Component untilFocused);
1981+
1982+ /**
1983+ * Called by the AWT to notify the KeyboardFocusManager that it should
1984+ * cancel delayed dispatching of KeyEvents. All KeyEvents which were
1985+ * enqueued because of a call to <code>enqueueKeyEvents</code> with the
1986+ * same timestamp and Component should be released for normal dispatching
1987+ * to the current focus owner. If the given timestamp is less than zero,
1988+ * the outstanding enqueue request for the given Component with the <b>
1989+ * oldest</b> timestamp (if any) should be cancelled.
1990+ *
1991+ * @param after the timestamp specified in the call to
1992+ * <code>enqueueKeyEvents</code>, or any value < 0
1993+ * @param untilFocused the Component specified in the call to
1994+ * <code>enqueueKeyEvents</code>
1995+ * @see #enqueueKeyEvents
1996+ * @see #discardKeyEvents
1997+ */
1998+ protected abstract void dequeueKeyEvents(long after,
1999+ Component untilFocused);
2000+
2001+ /**
2002+ * Called by the AWT to notify the KeyboardFocusManager that it should
2003+ * cancel delayed dispatching of KeyEvents. All KeyEvents which were
2004+ * enqueued because of one or more calls to <code>enqueueKeyEvents</code>
2005+ * with the same Component should be discarded.
2006+ *
2007+ * @param comp the Component specified in one or more calls to
2008+ * <code>enqueueKeyEvents</code>
2009+ * @see #enqueueKeyEvents
2010+ * @see #dequeueKeyEvents
2011+ */
2012+ protected abstract void discardKeyEvents(Component comp);
2013+
2014+ /**
2015+ * Focuses the Component after aComponent, typically based on a
2016+ * FocusTraversalPolicy.
2017+ *
2018+ * @param aComponent the Component that is the basis for the focus
2019+ * traversal operation
2020+ * @see FocusTraversalPolicy
2021+ */
2022+ public abstract void focusNextComponent(Component aComponent);
2023+
2024+ /**
2025+ * Focuses the Component before aComponent, typically based on a
2026+ * FocusTraversalPolicy.
2027+ *
2028+ * @param aComponent the Component that is the basis for the focus
2029+ * traversal operation
2030+ * @see FocusTraversalPolicy
2031+ */
2032+ public abstract void focusPreviousComponent(Component aComponent);
2033+
2034+ /**
2035+ * Moves the focus up one focus traversal cycle. Typically, the focus owner
2036+ * is set to aComponent's focus cycle root, and the current focus cycle
2037+ * root is set to the new focus owner's focus cycle root. If, however,
2038+ * aComponent's focus cycle root is a Window, then typically the focus
2039+ * owner is set to the Window's default Component to focus, and the current
2040+ * focus cycle root is unchanged.
2041+ *
2042+ * @param aComponent the Component that is the basis for the focus
2043+ * traversal operation
2044+ */
2045+ public abstract void upFocusCycle(Component aComponent);
2046+
2047+ /**
2048+ * Moves the focus down one focus traversal cycle. Typically, if
2049+ * aContainer is a focus cycle root, then the focus owner is set to
2050+ * aContainer's default Component to focus, and the current focus cycle
2051+ * root is set to aContainer. If aContainer is not a focus cycle root, then
2052+ * no focus traversal operation occurs.
2053+ *
2054+ * @param aContainer the Container that is the basis for the focus
2055+ * traversal operation
2056+ */
2057+ public abstract void downFocusCycle(Container aContainer);
2058+
2059+ /**
2060+ * Focuses the Component after the current focus owner.
2061+ */
2062+ public final void focusNextComponent() {
2063+ Component focusOwner = getFocusOwner();
2064+ if (focusOwner != null) {
2065+ focusNextComponent(focusOwner);
2066+ }
2067+ }
2068+
2069+ /**
2070+ * Focuses the Component before the current focus owner.
2071+ */
2072+ public final void focusPreviousComponent() {
2073+ Component focusOwner = getFocusOwner();
2074+ if (focusOwner != null) {
2075+ focusPreviousComponent(focusOwner);
2076+ }
2077+ }
2078+
2079+ /**
2080+ * Moves the focus up one focus traversal cycle from the current focus
2081+ * owner. Typically, the new focus owner is set to the current focus
2082+ * owner's focus cycle root, and the current focus cycle root is set to the
2083+ * new focus owner's focus cycle root. If, however, the current focus
2084+ * owner's focus cycle root is a Window, then typically the focus owner is
2085+ * set to the focus cycle root's default Component to focus, and the
2086+ * current focus cycle root is unchanged.
2087+ */
2088+ public final void upFocusCycle() {
2089+ Component focusOwner = getFocusOwner();
2090+ if (focusOwner != null) {
2091+ upFocusCycle(focusOwner);
2092+ }
2093+ }
2094+
2095+ /**
2096+ * Moves the focus down one focus traversal cycle from the current focus
2097+ * owner, if and only if the current focus owner is a Container that is a
2098+ * focus cycle root. Typically, the focus owner is set to the current focus
2099+ * owner's default Component to focus, and the current focus cycle root is
2100+ * set to the current focus owner. If the current focus owner is not a
2101+ * Container that is a focus cycle root, then no focus traversal operation
2102+ * occurs.
2103+ */
2104+ public final void downFocusCycle() {
2105+ Component focusOwner = getFocusOwner();
2106+ if (focusOwner instanceof Container) {
2107+ downFocusCycle((Container)focusOwner);
2108+ }
2109+ }
2110+
2111+ /**
2112+ * Dumps the list of focus requests to stderr
2113+ */
2114+ void dumpRequests() {
2115+ System.err.println(">>> Requests dump, time: " + System.currentTimeMillis());
2116+ synchronized (heavyweightRequests) {
2117+ for (HeavyweightFocusRequest req : heavyweightRequests) {
2118+ System.err.println(">>> Req: " + req);
2119+ }
2120+ }
2121+ System.err.println("");
2122+ }
2123+
2124+ private static final class LightweightFocusRequest {
2125+ final Component component;
2126+ final boolean temporary;
2127+ final CausedFocusEvent.Cause cause;
2128+
2129+ LightweightFocusRequest(Component component, boolean temporary, CausedFocusEvent.Cause cause) {
2130+ this.component = component;
2131+ this.temporary = temporary;
2132+ this.cause = cause;
2133+ }
2134+ public String toString() {
2135+ return "LightweightFocusRequest[component=" + component +
2136+ ",temporary=" + temporary + ", cause=" + cause + "]";
2137+ }
2138+ }
2139+
2140+ private static final class HeavyweightFocusRequest {
2141+ final Component heavyweight;
2142+ final LinkedList<LightweightFocusRequest> lightweightRequests;
2143+
2144+ static final HeavyweightFocusRequest CLEAR_GLOBAL_FOCUS_OWNER =
2145+ new HeavyweightFocusRequest();
2146+
2147+ private HeavyweightFocusRequest() {
2148+ heavyweight = null;
2149+ lightweightRequests = null;
2150+ }
2151+
2152+ HeavyweightFocusRequest(Component heavyweight, Component descendant,
2153+ boolean temporary, CausedFocusEvent.Cause cause) {
2154+ if (log.isLoggable(PlatformLogger.FINE)) {
2155+ if (heavyweight == null) {
2156+ log.fine("Assertion (heavyweight != null) failed");
2157+ }
2158+ }
2159+
2160+ this.heavyweight = heavyweight;
2161+ this.lightweightRequests = new LinkedList<LightweightFocusRequest>();
2162+ addLightweightRequest(descendant, temporary, cause);
2163+ }
2164+ boolean addLightweightRequest(Component descendant,
2165+ boolean temporary, CausedFocusEvent.Cause cause) {
2166+ if (log.isLoggable(PlatformLogger.FINE)) {
2167+ if (this == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER) {
2168+ log.fine("Assertion (this != HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER) failed");
2169+ }
2170+ if (descendant == null) {
2171+ log.fine("Assertion (descendant != null) failed");
2172+ }
2173+ }
2174+
2175+ Component lastDescendant = ((lightweightRequests.size() > 0)
2176+ ? lightweightRequests.getLast().component
2177+ : null);
2178+
2179+ if (descendant != lastDescendant) {
2180+ // Not a duplicate request
2181+ lightweightRequests.add
2182+ (new LightweightFocusRequest(descendant, temporary, cause));
2183+ return true;
2184+ } else {
2185+ return false;
2186+ }
2187+ }
2188+
2189+ LightweightFocusRequest getFirstLightweightRequest() {
2190+ if (this == CLEAR_GLOBAL_FOCUS_OWNER) {
2191+ return null;
2192+ }
2193+ return lightweightRequests.getFirst();
2194+ }
2195+ public String toString() {
2196+ boolean first = true;
2197+ String str = "HeavyweightFocusRequest[heavweight=" + heavyweight +
2198+ ",lightweightRequests=";
2199+ if (lightweightRequests == null) {
2200+ str += null;
2201+ } else {
2202+ str += "[";
2203+
2204+ for (LightweightFocusRequest lwRequest : lightweightRequests) {
2205+ if (first) {
2206+ first = false;
2207+ } else {
2208+ str += ",";
2209+ }
2210+ str += lwRequest;
2211+ }
2212+ str += "]";
2213+ }
2214+ str += "]";
2215+ return str;
2216+ }
2217+ }
2218+
2219+ /*
2220+ * heavyweightRequests is used as a monitor for synchronized changes of
2221+ * currentLightweightRequests, clearingCurrentLightweightRequests and
2222+ * newFocusOwner.
2223+ */
2224+ private static LinkedList<HeavyweightFocusRequest> heavyweightRequests =
2225+ new LinkedList<HeavyweightFocusRequest>();
2226+ private static LinkedList<LightweightFocusRequest> currentLightweightRequests;
2227+ private static boolean clearingCurrentLightweightRequests;
2228+ private static boolean allowSyncFocusRequests = true;
2229+ private static Component newFocusOwner = null;
2230+ private static volatile boolean disableRestoreFocus;
2231+
2232+ static final int SNFH_FAILURE = 0;
2233+ static final int SNFH_SUCCESS_HANDLED = 1;
2234+ static final int SNFH_SUCCESS_PROCEED = 2;
2235+
2236+ static boolean processSynchronousLightweightTransfer(Component heavyweight, Component descendant,
2237+ boolean temporary, boolean focusedWindowChangeAllowed,
2238+ long time)
2239+ {
2240+ Window parentWindow = SunToolkit.getContainingWindow(heavyweight);
2241+ if (parentWindow == null || !parentWindow.syncLWRequests) {
2242+ return false;
2243+ }
2244+ if (descendant == null) {
2245+ // Focus transfers from a lightweight child back to the
2246+ // heavyweight Container should be treated like lightweight
2247+ // focus transfers.
2248+ descendant = heavyweight;
2249+ }
2250+
2251+ KeyboardFocusManager manager = getCurrentKeyboardFocusManager(SunToolkit.targetToAppContext(descendant));
2252+
2253+ FocusEvent currentFocusOwnerEvent = null;
2254+ FocusEvent newFocusOwnerEvent = null;
2255+ Component currentFocusOwner = manager.getGlobalFocusOwner();
2256+
2257+ synchronized (heavyweightRequests) {
2258+ HeavyweightFocusRequest hwFocusRequest = getLastHWRequest();
2259+ if (hwFocusRequest == null &&
2260+ heavyweight == manager.getNativeFocusOwner() &&
2261+ allowSyncFocusRequests)
2262+ {
2263+
2264+ if (descendant == currentFocusOwner) {
2265+ // Redundant request.
2266+ return true;
2267+ }
2268+
2269+ // 'heavyweight' owns the native focus and there are no pending
2270+ // requests. 'heavyweight' must be a Container and
2271+ // 'descendant' must not be the focus owner. Otherwise,
2272+ // we would never have gotten this far.
2273+ manager.enqueueKeyEvents(time, descendant);
2274+
2275+ hwFocusRequest =
2276+ new HeavyweightFocusRequest(heavyweight, descendant,
2277+ temporary, CausedFocusEvent.Cause.UNKNOWN);
2278+ heavyweightRequests.add(hwFocusRequest);
2279+
2280+ if (currentFocusOwner != null) {
2281+ currentFocusOwnerEvent =
2282+ new FocusEvent(currentFocusOwner,
2283+ FocusEvent.FOCUS_LOST,
2284+ temporary, descendant);
2285+ }
2286+ newFocusOwnerEvent =
2287+ new FocusEvent(descendant, FocusEvent.FOCUS_GAINED,
2288+ temporary, currentFocusOwner);
2289+ }
2290+ }
2291+ boolean result = false;
2292+ final boolean clearing = clearingCurrentLightweightRequests;
2293+
2294+ Throwable caughtEx = null;
2295+ try {
2296+ clearingCurrentLightweightRequests = false;
2297+ synchronized(Component.LOCK) {
2298+
2299+ if (currentFocusOwnerEvent != null && currentFocusOwner != null) {
2300+ ((AWTEvent) currentFocusOwnerEvent).isPosted = true;
2301+ caughtEx = dispatchAndCatchException(caughtEx, currentFocusOwner, currentFocusOwnerEvent);
2302+ result = true;
2303+ }
2304+
2305+ if (newFocusOwnerEvent != null && descendant != null) {
2306+ ((AWTEvent) newFocusOwnerEvent).isPosted = true;
2307+ caughtEx = dispatchAndCatchException(caughtEx, descendant, newFocusOwnerEvent);
2308+ result = true;
2309+ }
2310+ }
2311+ } finally {
2312+ clearingCurrentLightweightRequests = clearing;
2313+ }
2314+ if (caughtEx instanceof RuntimeException) {
2315+ throw (RuntimeException)caughtEx;
2316+ } else if (caughtEx instanceof Error) {
2317+ throw (Error)caughtEx;
2318+ }
2319+ return result;
2320+ }
2321+
2322+ /**
2323+ * Indicates whether the native implementation should proceed with a
2324+ * pending, native focus request. Before changing the focus at the native
2325+ * level, the AWT implementation should always call this function for
2326+ * permission. This function will reject the request if a duplicate request
2327+ * preceded it, or if the specified heavyweight Component already owns the
2328+ * focus and no native focus changes are pending. Otherwise, the request
2329+ * will be approved and the focus request list will be updated so that,
2330+ * if necessary, the proper descendant will be focused when the
2331+ * corresponding FOCUS_GAINED event on the heavyweight is received.
2332+ *
2333+ * An implementation must ensure that calls to this method and native
2334+ * focus changes are atomic. If this is not guaranteed, then the ordering
2335+ * of the focus request list may be incorrect, leading to errors in the
2336+ * type-ahead mechanism. Typically this is accomplished by only calling
2337+ * this function from the native event pumping thread, or by holding a
2338+ * global, native lock during invocation.
2339+ */
2340+ static int shouldNativelyFocusHeavyweight
2341+ (Component heavyweight, Component descendant, boolean temporary,
2342+ boolean focusedWindowChangeAllowed, long time, CausedFocusEvent.Cause cause)
2343+ {
2344+ if (log.isLoggable(PlatformLogger.FINE)) {
2345+ if (heavyweight == null) {
2346+ log.fine("Assertion (heavyweight != null) failed");
2347+ }
2348+ if (time == 0) {
2349+ log.fine("Assertion (time != 0) failed");
2350+ }
2351+ }
2352+
2353+ if (descendant == null) {
2354+ // Focus transfers from a lightweight child back to the
2355+ // heavyweight Container should be treated like lightweight
2356+ // focus transfers.
2357+ descendant = heavyweight;
2358+ }
2359+
2360+ KeyboardFocusManager manager =
2361+ getCurrentKeyboardFocusManager(SunToolkit.targetToAppContext(descendant));
2362+ KeyboardFocusManager thisManager = getCurrentKeyboardFocusManager();
2363+ Component currentFocusOwner = thisManager.getGlobalFocusOwner();
2364+ Component nativeFocusOwner = thisManager.getNativeFocusOwner();
2365+ Window nativeFocusedWindow = thisManager.getNativeFocusedWindow();
2366+ if (focusLog.isLoggable(PlatformLogger.FINER)) {
2367+ focusLog.finer("SNFH for {0} in {1}",
2368+ String.valueOf(descendant), String.valueOf(heavyweight));
2369+ }
2370+ if (focusLog.isLoggable(PlatformLogger.FINEST)) {
2371+ focusLog.finest("0. Current focus owner {0}",
2372+ String.valueOf(currentFocusOwner));
2373+ focusLog.finest("0. Native focus owner {0}",
2374+ String.valueOf(nativeFocusOwner));
2375+ focusLog.finest("0. Native focused window {0}",
2376+ String.valueOf(nativeFocusedWindow));
2377+ }
2378+ synchronized (heavyweightRequests) {
2379+ HeavyweightFocusRequest hwFocusRequest = getLastHWRequest();
2380+ if (focusLog.isLoggable(PlatformLogger.FINEST)) {
2381+ focusLog.finest("Request {0}", String.valueOf(hwFocusRequest));
2382+ }
2383+ if (hwFocusRequest == null &&
2384+ heavyweight == nativeFocusOwner)
2385+ {
2386+ if (descendant == currentFocusOwner) {
2387+ // Redundant request.
2388+ if (focusLog.isLoggable(PlatformLogger.FINEST))
2389+ focusLog.finest("1. SNFH_FAILURE for {0}",
2390+ String.valueOf(descendant));
2391+ return SNFH_FAILURE;
2392+ }
2393+
2394+ // 'heavyweight' owns the native focus and there are no pending
2395+ // requests. 'heavyweight' must be a Container and
2396+ // 'descendant' must not be the focus owner. Otherwise,
2397+ // we would never have gotten this far.
2398+ manager.enqueueKeyEvents(time, descendant);
2399+
2400+ hwFocusRequest =
2401+ new HeavyweightFocusRequest(heavyweight, descendant,
2402+ temporary, cause);
2403+ heavyweightRequests.add(hwFocusRequest);
2404+
2405+ if (currentFocusOwner != null) {
2406+ FocusEvent currentFocusOwnerEvent =
2407+ new CausedFocusEvent(currentFocusOwner,
2408+ FocusEvent.FOCUS_LOST,
2409+ temporary, descendant, cause);
2410+ // Fix 5028014. Rolled out.
2411+ // SunToolkit.postPriorityEvent(currentFocusOwnerEvent);
2412+ SunToolkit.postEvent(currentFocusOwner.appContext,
2413+ currentFocusOwnerEvent);
2414+ }
2415+ FocusEvent newFocusOwnerEvent =
2416+ new CausedFocusEvent(descendant, FocusEvent.FOCUS_GAINED,
2417+ temporary, currentFocusOwner, cause);
2418+ // Fix 5028014. Rolled out.
2419+ // SunToolkit.postPriorityEvent(newFocusOwnerEvent);
2420+ SunToolkit.postEvent(descendant.appContext, newFocusOwnerEvent);
2421+
2422+ if (focusLog.isLoggable(PlatformLogger.FINEST))
2423+ focusLog.finest("2. SNFH_HANDLED for {0}", String.valueOf(descendant));
2424+ return SNFH_SUCCESS_HANDLED;
2425+ } else if (hwFocusRequest != null &&
2426+ hwFocusRequest.heavyweight == heavyweight) {
2427+ // 'heavyweight' doesn't have the native focus right now, but
2428+ // if all pending requests were completed, it would. Add
2429+ // descendant to the heavyweight's list of pending
2430+ // lightweight focus transfers.
2431+ if (hwFocusRequest.addLightweightRequest(descendant,
2432+ temporary, cause)) {
2433+ manager.enqueueKeyEvents(time, descendant);
2434+ }
2435+
2436+ if (focusLog.isLoggable(PlatformLogger.FINEST))
2437+ focusLog.finest("3. SNFH_HANDLED for lightweight" +
2438+ descendant + " in " + heavyweight);
2439+ return SNFH_SUCCESS_HANDLED;
2440+ } else {
2441+ if (!focusedWindowChangeAllowed) {
2442+ // For purposes of computing oldFocusedWindow, we should look at
2443+ // the second to last HeavyweightFocusRequest on the queue iff the
2444+ // last HeavyweightFocusRequest is CLEAR_GLOBAL_FOCUS_OWNER. If
2445+ // there is no second to last HeavyweightFocusRequest, null is an
2446+ // acceptable value.
2447+ if (hwFocusRequest ==
2448+ HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER)
2449+ {
2450+ int size = heavyweightRequests.size();
2451+ hwFocusRequest = (HeavyweightFocusRequest)((size >= 2)
2452+ ? heavyweightRequests.get(size - 2)
2453+ : null);
2454+ }
2455+ if (focusedWindowChanged(heavyweight,
2456+ (hwFocusRequest != null)
2457+ ? hwFocusRequest.heavyweight
2458+ : nativeFocusedWindow)) {
2459+ if (focusLog.isLoggable(PlatformLogger.FINEST))
2460+ focusLog.finest("4. SNFH_FAILURE for " + descendant);
2461+ return SNFH_FAILURE;
2462+ }
2463+ }
2464+
2465+ manager.enqueueKeyEvents(time, descendant);
2466+ heavyweightRequests.add
2467+ (new HeavyweightFocusRequest(heavyweight, descendant,
2468+ temporary, cause));
2469+ if (focusLog.isLoggable(PlatformLogger.FINEST))
2470+ focusLog.finest("5. SNFH_PROCEED for " + descendant);
2471+ return SNFH_SUCCESS_PROCEED;
2472+ }
2473+ }
2474+ }
2475+
2476+ /**
2477+ * Returns the Window which will be active after processing this request,
2478+ * or null if this is a duplicate request. The active Window is useful
2479+ * because some native platforms do not support setting the native focus
2480+ * owner to null. On these platforms, the obvious choice is to set the
2481+ * focus owner to the focus proxy of the active Window.
2482+ */
2483+ static Window markClearGlobalFocusOwner() {
2484+ // need to call this out of synchronized block to avoid possible deadlock
2485+ // see 6454631.
2486+ final Component nativeFocusedWindow =
2487+ getCurrentKeyboardFocusManager().getNativeFocusedWindow();
2488+
2489+ synchronized (heavyweightRequests) {
2490+ HeavyweightFocusRequest hwFocusRequest = getLastHWRequest();
2491+ if (hwFocusRequest ==
2492+ HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER)
2493+ {
2494+ // duplicate request
2495+ return null;
2496+ }
2497+
2498+ heavyweightRequests.add
2499+ (HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER);
2500+
2501+ Component activeWindow = ((hwFocusRequest != null)
2502+ ? SunToolkit.getContainingWindow(hwFocusRequest.heavyweight)
2503+ : nativeFocusedWindow);
2504+ while (activeWindow != null &&
2505+ !((activeWindow instanceof Frame) ||
2506+ (activeWindow instanceof Dialog)))
2507+ {
2508+ activeWindow = activeWindow.getParent_NoClientCode();
2509+ }
2510+
2511+ return (Window) activeWindow;
2512+ }
2513+ }
2514+ Component getCurrentWaitingRequest(Component parent) {
2515+ synchronized (heavyweightRequests) {
2516+ HeavyweightFocusRequest hwFocusRequest = getFirstHWRequest();
2517+ if (hwFocusRequest != null) {
2518+ if (hwFocusRequest.heavyweight == parent) {
2519+ LightweightFocusRequest lwFocusRequest =
2520+ hwFocusRequest.lightweightRequests.getFirst();
2521+ if (lwFocusRequest != null) {
2522+ return lwFocusRequest.component;
2523+ }
2524+ }
2525+ }
2526+ }
2527+ return null;
2528+ }
2529+
2530+ static boolean isAutoFocusTransferEnabled() {
2531+ synchronized (heavyweightRequests) {
2532+ return (heavyweightRequests.size() == 0)
2533+ && !disableRestoreFocus
2534+ && (null == currentLightweightRequests);
2535+ }
2536+ }
2537+
2538+ static boolean isAutoFocusTransferEnabledFor(Component comp) {
2539+ return isAutoFocusTransferEnabled() && comp.isAutoFocusTransferOnDisposal();
2540+ }
2541+
2542+ /*
2543+ * Used to process exceptions in dispatching focus event (in focusLost/focusGained callbacks).
2544+ * @param ex previously caught exception that may be processed right here, or null
2545+ * @param comp the component to dispatch the event to
2546+ * @param event the event to dispatch to the component
2547+ */
2548+ static private Throwable dispatchAndCatchException(Throwable ex, Component comp, FocusEvent event) {
2549+ Throwable retEx = null;
2550+ try {
2551+ comp.dispatchEvent(event);
2552+ } catch (RuntimeException re) {
2553+ retEx = re;
2554+ } catch (Error er) {
2555+ retEx = er;
2556+ }
2557+ if (retEx != null) {
2558+ if (ex != null) {
2559+ handleException(ex);
2560+ }
2561+ return retEx;
2562+ }
2563+ return ex;
2564+ }
2565+
2566+ static private void handleException(Throwable ex) {
2567+ ex.printStackTrace();
2568+ }
2569+
2570+ static void processCurrentLightweightRequests() {
2571+ KeyboardFocusManager manager = getCurrentKeyboardFocusManager();
2572+ LinkedList<LightweightFocusRequest> localLightweightRequests = null;
2573+
2574+ Component globalFocusOwner = manager.getGlobalFocusOwner();
2575+ if ((globalFocusOwner != null) &&
2576+ (globalFocusOwner.appContext != AppContext.getAppContext()))
2577+ {
2578+ // The current app context differs from the app context of a focus
2579+ // owner (and all pending lightweight requests), so we do nothing
2580+ // now and wait for a next event.
2581+ return;
2582+ }
2583+
2584+ synchronized(heavyweightRequests) {
2585+ if (currentLightweightRequests != null) {
2586+ clearingCurrentLightweightRequests = true;
2587+ disableRestoreFocus = true;
2588+ localLightweightRequests = currentLightweightRequests;
2589+ allowSyncFocusRequests = (localLightweightRequests.size() < 2);
2590+ currentLightweightRequests = null;
2591+ } else {
2592+ // do nothing
2593+ return;
2594+ }
2595+ }
2596+
2597+ Throwable caughtEx = null;
2598+ try {
2599+ if (localLightweightRequests != null) {
2600+ Component lastFocusOwner = null;
2601+ Component currentFocusOwner = null;
2602+
2603+ for (Iterator iter = localLightweightRequests.iterator(); iter.hasNext(); ) {
2604+
2605+ currentFocusOwner = manager.getGlobalFocusOwner();
2606+ LightweightFocusRequest lwFocusRequest =
2607+ (LightweightFocusRequest)iter.next();
2608+
2609+ /*
2610+ * WARNING: This is based on DKFM's logic solely!
2611+ *
2612+ * We allow to trigger restoreFocus() in the dispatching process
2613+ * only if we have the last request to dispatch. If the last request
2614+ * fails, focus will be restored to either the component of the last
2615+ * previously succedded request, or to to the focus owner that was
2616+ * before this clearing proccess.
2617+ */
2618+ if (!iter.hasNext()) {
2619+ disableRestoreFocus = false;
2620+ }
2621+
2622+ FocusEvent currentFocusOwnerEvent = null;
2623+ /*
2624+ * We're not dispatching FOCUS_LOST while the current focus owner is null.
2625+ * But regardless of whether it's null or not, we're clearing ALL the local
2626+ * lw requests.
2627+ */
2628+ if (currentFocusOwner != null) {
2629+ currentFocusOwnerEvent = new CausedFocusEvent(currentFocusOwner,
2630+ FocusEvent.FOCUS_LOST,
2631+ lwFocusRequest.temporary,
2632+ lwFocusRequest.component, lwFocusRequest.cause);
2633+ }
2634+ FocusEvent newFocusOwnerEvent =
2635+ new CausedFocusEvent(lwFocusRequest.component,
2636+ FocusEvent.FOCUS_GAINED,
2637+ lwFocusRequest.temporary,
2638+ currentFocusOwner == null ? lastFocusOwner : currentFocusOwner,
2639+ lwFocusRequest.cause);
2640+
2641+ if (currentFocusOwner != null) {
2642+ ((AWTEvent) currentFocusOwnerEvent).isPosted = true;
2643+ caughtEx = dispatchAndCatchException(caughtEx, currentFocusOwner, currentFocusOwnerEvent);
2644+ }
2645+
2646+ ((AWTEvent) newFocusOwnerEvent).isPosted = true;
2647+ caughtEx = dispatchAndCatchException(caughtEx, lwFocusRequest.component, newFocusOwnerEvent);
2648+
2649+ if (manager.getGlobalFocusOwner() == lwFocusRequest.component) {
2650+ lastFocusOwner = lwFocusRequest.component;
2651+ }
2652+ }
2653+ }
2654+ } finally {
2655+ clearingCurrentLightweightRequests = false;
2656+ disableRestoreFocus = false;
2657+ localLightweightRequests = null;
2658+ allowSyncFocusRequests = true;
2659+ }
2660+ if (caughtEx instanceof RuntimeException) {
2661+ throw (RuntimeException)caughtEx;
2662+ } else if (caughtEx instanceof Error) {
2663+ throw (Error)caughtEx;
2664+ }
2665+ }
2666+
2667+ static FocusEvent retargetUnexpectedFocusEvent(FocusEvent fe) {
2668+ synchronized (heavyweightRequests) {
2669+ // Any other case represents a failure condition which we did
2670+ // not expect. We need to clearFocusRequestList() and patch up
2671+ // the event as best as possible.
2672+
2673+ if (removeFirstRequest()) {
2674+ return (FocusEvent)retargetFocusEvent(fe);
2675+ }
2676+
2677+ Component source = fe.getComponent();
2678+ Component opposite = fe.getOppositeComponent();
2679+ boolean temporary = false;
2680+ if (fe.getID() == FocusEvent.FOCUS_LOST &&
2681+ (opposite == null || isTemporary(opposite, source)))
2682+ {
2683+ temporary = true;
2684+ }
2685+ return new CausedFocusEvent(source, fe.getID(), temporary, opposite,
2686+ CausedFocusEvent.Cause.NATIVE_SYSTEM);
2687+ }
2688+ }
2689+
2690+ static FocusEvent retargetFocusGained(FocusEvent fe) {
2691+ assert (fe.getID() == FocusEvent.FOCUS_GAINED);
2692+
2693+ Component currentFocusOwner = getCurrentKeyboardFocusManager().
2694+ getGlobalFocusOwner();
2695+ Component source = fe.getComponent();
2696+ Component opposite = fe.getOppositeComponent();
2697+ Component nativeSource = getHeavyweight(source);
2698+
2699+ synchronized (heavyweightRequests) {
2700+ HeavyweightFocusRequest hwFocusRequest = getFirstHWRequest();
2701+
2702+ if (hwFocusRequest == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER)
2703+ {
2704+ return retargetUnexpectedFocusEvent(fe);
2705+ }
2706+
2707+ if (source != null && nativeSource == null && hwFocusRequest != null) {
2708+ // if source w/o peer and
2709+ // if source is equal to first lightweight
2710+ // then we should correct source and nativeSource
2711+ if (source == hwFocusRequest.getFirstLightweightRequest().component)
2712+ {
2713+ source = hwFocusRequest.heavyweight;
2714+ nativeSource = source; // source is heavuweight itself
2715+ }
2716+ }
2717+ if (hwFocusRequest != null &&
2718+ nativeSource == hwFocusRequest.heavyweight)
2719+ {
2720+ // Focus change as a result of a known call to requestFocus(),
2721+ // or known click on a peer focusable heavyweight Component.
2722+
2723+ heavyweightRequests.removeFirst();
2724+
2725+ LightweightFocusRequest lwFocusRequest =
2726+ hwFocusRequest.lightweightRequests.removeFirst();
2727+
2728+ Component newSource = lwFocusRequest.component;
2729+ if (currentFocusOwner != null) {
2730+ /*
2731+ * Since we receive FOCUS_GAINED when current focus
2732+ * owner is not null, correcponding FOCUS_LOST is supposed
2733+ * to be lost. And so, we keep new focus owner
2734+ * to determine synthetic FOCUS_LOST event which will be
2735+ * generated by KeyboardFocusManager for this FOCUS_GAINED.
2736+ *
2737+ * This code based on knowledge of
2738+ * DefaultKeyboardFocusManager's implementation and might
2739+ * be not applicable for another KeyboardFocusManager.
2740+ */
2741+ newFocusOwner = newSource;
2742+ }
2743+
2744+ boolean temporary = (opposite == null ||
2745+ isTemporary(newSource, opposite))
2746+ ? false
2747+ : lwFocusRequest.temporary;
2748+
2749+ if (hwFocusRequest.lightweightRequests.size() > 0) {
2750+ currentLightweightRequests =
2751+ hwFocusRequest.lightweightRequests;
2752+ EventQueue.invokeLater(new Runnable() {
2753+ public void run() {
2754+ processCurrentLightweightRequests();
2755+ }
2756+ });
2757+ }
2758+
2759+ // 'opposite' will be fixed by
2760+ // DefaultKeyboardFocusManager.realOppositeComponent
2761+ return new CausedFocusEvent(newSource,
2762+ FocusEvent.FOCUS_GAINED, temporary,
2763+ opposite, lwFocusRequest.cause);
2764+ }
2765+
2766+ if (currentFocusOwner != null
2767+ && currentFocusOwner.getContainingWindow() == source
2768+ && (hwFocusRequest == null || source != hwFocusRequest.heavyweight))
2769+ {
2770+ // Special case for FOCUS_GAINED in top-levels
2771+ // If it arrives as the result of activation we should skip it
2772+ // This event will not have appropriate request record and
2773+ // on arrival there will be already some focus owner set.
2774+ return new CausedFocusEvent(currentFocusOwner, FocusEvent.FOCUS_GAINED, false,
2775+ null, CausedFocusEvent.Cause.ACTIVATION);
2776+ }
2777+
2778+ return retargetUnexpectedFocusEvent(fe);
2779+ } // end synchronized(heavyweightRequests)
2780+ }
2781+
2782+ static FocusEvent retargetFocusLost(FocusEvent fe) {
2783+ assert (fe.getID() == FocusEvent.FOCUS_LOST);
2784+
2785+ Component currentFocusOwner = getCurrentKeyboardFocusManager().
2786+ getGlobalFocusOwner();
2787+ Component opposite = fe.getOppositeComponent();
2788+ Component nativeOpposite = getHeavyweight(opposite);
2789+
2790+ synchronized (heavyweightRequests) {
2791+ HeavyweightFocusRequest hwFocusRequest = getFirstHWRequest();
2792+
2793+ if (hwFocusRequest == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER)
2794+ {
2795+ if (currentFocusOwner != null) {
2796+ // Call to KeyboardFocusManager.clearGlobalFocusOwner()
2797+ heavyweightRequests.removeFirst();
2798+ return new CausedFocusEvent(currentFocusOwner,
2799+ FocusEvent.FOCUS_LOST, false, null,
2800+ CausedFocusEvent.Cause.CLEAR_GLOBAL_FOCUS_OWNER);
2801+ }
2802+
2803+ // Otherwise, fall through to failure case below
2804+
2805+ } else if (opposite == null)
2806+ {
2807+ // Focus leaving application
2808+ if (currentFocusOwner != null) {
2809+ return new CausedFocusEvent(currentFocusOwner,
2810+ FocusEvent.FOCUS_LOST,
2811+ true, null, CausedFocusEvent.Cause.ACTIVATION);
2812+ } else {
2813+ return fe;
2814+ }
2815+ } else if (hwFocusRequest != null &&
2816+ (nativeOpposite == hwFocusRequest.heavyweight ||
2817+ nativeOpposite == null &&
2818+ opposite == hwFocusRequest.getFirstLightweightRequest().component))
2819+ {
2820+ if (currentFocusOwner == null) {
2821+ return fe;
2822+ }
2823+ // Focus change as a result of a known call to requestFocus(),
2824+ // or click on a peer focusable heavyweight Component.
2825+ // If a focus transfer is made across top-levels, then the
2826+ // FOCUS_LOST event is always temporary, and the FOCUS_GAINED
2827+ // event is always permanent. Otherwise, the stored temporary
2828+ // value is honored.
2829+
2830+ LightweightFocusRequest lwFocusRequest =
2831+ hwFocusRequest.lightweightRequests.getFirst();
2832+
2833+ boolean temporary = isTemporary(opposite, currentFocusOwner)
2834+ ? true
2835+ : lwFocusRequest.temporary;
2836+
2837+ return new CausedFocusEvent(currentFocusOwner, FocusEvent.FOCUS_LOST,
2838+ temporary, lwFocusRequest.component, lwFocusRequest.cause);
2839+ } else if (focusedWindowChanged(opposite, currentFocusOwner)) {
2840+ // If top-level changed there might be no focus request in a list
2841+ // But we know the opposite, we now it is temporary - dispatch the event.
2842+ if (!fe.isTemporary() && currentFocusOwner != null) {
2843+ // Create copy of the event with only difference in temporary parameter.
2844+ fe = new CausedFocusEvent(currentFocusOwner, FocusEvent.FOCUS_LOST,
2845+ true, opposite, CausedFocusEvent.Cause.ACTIVATION);
2846+ }
2847+ return fe;
2848+ }
2849+
2850+ return retargetUnexpectedFocusEvent(fe);
2851+ } // end synchronized(heavyweightRequests)
2852+ }
2853+
2854+ static AWTEvent retargetFocusEvent(AWTEvent event) {
2855+ if (clearingCurrentLightweightRequests) {
2856+ return event;
2857+ }
2858+
2859+ KeyboardFocusManager manager = getCurrentKeyboardFocusManager();
2860+ if (focusLog.isLoggable(PlatformLogger.FINER)) {
2861+ if (event instanceof FocusEvent || event instanceof WindowEvent) {
2862+ focusLog.finer(">>> {0}", String.valueOf(event));
2863+ }
2864+ if (focusLog.isLoggable(PlatformLogger.FINER) && event instanceof KeyEvent) {
2865+ focusLog.finer(" focus owner is {0}",
2866+ String.valueOf(manager.getGlobalFocusOwner()));
2867+ focusLog.finer(">>> {0}", String.valueOf(event));
2868+ }
2869+ }
2870+
2871+ synchronized(heavyweightRequests) {
2872+ /*
2873+ * This code handles FOCUS_LOST event which is generated by
2874+ * DefaultKeyboardFocusManager for FOCUS_GAINED.
2875+ *
2876+ * This code based on knowledge of DefaultKeyboardFocusManager's
2877+ * implementation and might be not applicable for another
2878+ * KeyboardFocusManager.
2879+ *
2880+ * Fix for 4472032
2881+ */
2882+ if (newFocusOwner != null &&
2883+ event.getID() == FocusEvent.FOCUS_LOST)
2884+ {
2885+ FocusEvent fe = (FocusEvent)event;
2886+
2887+ if (manager.getGlobalFocusOwner() == fe.getComponent() &&
2888+ fe.getOppositeComponent() == newFocusOwner)
2889+ {
2890+ newFocusOwner = null;
2891+ return event;
2892+ }
2893+ }
2894+ }
2895+
2896+ processCurrentLightweightRequests();
2897+
2898+ switch (event.getID()) {
2899+ case FocusEvent.FOCUS_GAINED: {
2900+ event = retargetFocusGained((FocusEvent)event);
2901+ break;
2902+ }
2903+ case FocusEvent.FOCUS_LOST: {
2904+ event = retargetFocusLost((FocusEvent)event);
2905+ break;
2906+ }
2907+ default:
2908+ /* do nothing */
2909+ }
2910+ return event;
2911+ }
2912+
2913+ /**
2914+ * Clears markers queue
2915+ * This method is not intended to be overridden by KFM's.
2916+ * Only DefaultKeyboardFocusManager can implement it.
2917+ * @since 1.5
2918+ */
2919+ void clearMarkers() {
2920+ }
2921+
2922+ static boolean removeFirstRequest() {
2923+ KeyboardFocusManager manager =
2924+ KeyboardFocusManager.getCurrentKeyboardFocusManager();
2925+
2926+ synchronized(heavyweightRequests) {
2927+ HeavyweightFocusRequest hwFocusRequest = getFirstHWRequest();
2928+
2929+ if (hwFocusRequest != null) {
2930+ heavyweightRequests.removeFirst();
2931+ if (hwFocusRequest.lightweightRequests != null) {
2932+ for (Iterator lwIter = hwFocusRequest.lightweightRequests.
2933+ iterator();
2934+ lwIter.hasNext(); )
2935+ {
2936+ manager.dequeueKeyEvents
2937+ (-1, ((LightweightFocusRequest)lwIter.next()).
2938+ component);
2939+ }
2940+ }
2941+ }
2942+ // Fix for 4799136 - clear type-ahead markers if requests queue is empty
2943+ // We do it here because this method is called only when problems happen
2944+ if (heavyweightRequests.size() == 0) {
2945+ manager.clearMarkers();
2946+ }
2947+ return (heavyweightRequests.size() > 0);
2948+ }
2949+ }
2950+ static void removeLastFocusRequest(Component heavyweight) {
2951+ if (log.isLoggable(PlatformLogger.FINE)) {
2952+ if (heavyweight == null) {
2953+ log.fine("Assertion (heavyweight != null) failed");
2954+ }
2955+ }
2956+
2957+ KeyboardFocusManager manager =
2958+ KeyboardFocusManager.getCurrentKeyboardFocusManager();
2959+ synchronized(heavyweightRequests) {
2960+ HeavyweightFocusRequest hwFocusRequest = getLastHWRequest();
2961+ if (hwFocusRequest != null &&
2962+ hwFocusRequest.heavyweight == heavyweight) {
2963+ heavyweightRequests.removeLast();
2964+ }
2965+ // Fix for 4799136 - clear type-ahead markers if requests queue is empty
2966+ // We do it here because this method is called only when problems happen
2967+ if (heavyweightRequests.size() == 0) {
2968+ manager.clearMarkers();
2969+ }
2970+ }
2971+ }
2972+
2973+ private static boolean focusedWindowChanged(Component to, Component from) {
2974+ Window wto = SunToolkit.getContainingWindow(to);
2975+ Window wfrom = SunToolkit.getContainingWindow(from);
2976+ if (wto == null && wfrom == null) {
2977+ return true;
2978+ }
2979+ if (wto == null) {
2980+ return true;
2981+ }
2982+ if (wfrom == null) {
2983+ return true;
2984+ }
2985+ return (wto != wfrom);
2986+ }
2987+
2988+ private static boolean isTemporary(Component to, Component from) {
2989+ Window wto = SunToolkit.getContainingWindow(to);
2990+ Window wfrom = SunToolkit.getContainingWindow(from);
2991+ if (wto == null && wfrom == null) {
2992+ return false;
2993+ }
2994+ if (wto == null) {
2995+ return true;
2996+ }
2997+ if (wfrom == null) {
2998+ return false;
2999+ }
3000+ return (wto != wfrom);
3001+ }
3002+
3003+ static Component getHeavyweight(Component comp) {
3004+ if (comp == null || comp.getPeer() == null) {
3005+ return null;
3006+ } else if (comp.getPeer() instanceof LightweightPeer) {
3007+ return comp.getNativeContainer();
3008+ } else {
3009+ return comp;
3010+ }
3011+ }
3012+
3013+ static Field proxyActive;
3014+ // Accessor to private field isProxyActive of KeyEvent
3015+ private static boolean isProxyActiveImpl(KeyEvent e) {
3016+ if (proxyActive == null) {
3017+ proxyActive = (Field) AccessController.doPrivileged(new PrivilegedAction() {
3018+ public Object run() {
3019+ Field field = null;
3020+ try {
3021+ field = KeyEvent.class.getDeclaredField("isProxyActive");
3022+ if (field != null) {
3023+ field.setAccessible(true);
3024+ }
3025+ } catch (NoSuchFieldException nsf) {
3026+ assert(false);
3027+ }
3028+ return field;
3029+ }
3030+ });
3031+ }
3032+
3033+ try {
3034+ return proxyActive.getBoolean(e);
3035+ } catch (IllegalAccessException iae) {
3036+ assert(false);
3037+ }
3038+ return false;
3039+ }
3040+
3041+ // Returns the value of this KeyEvent's field isProxyActive
3042+ static boolean isProxyActive(KeyEvent e) {
3043+ if (!GraphicsEnvironment.isHeadless()) {
3044+ return isProxyActiveImpl(e);
3045+ } else {
3046+ return false;
3047+ }
3048+ }
3049+
3050+ private static HeavyweightFocusRequest getLastHWRequest() {
3051+ synchronized(heavyweightRequests) {
3052+ return (heavyweightRequests.size() > 0)
3053+ ? heavyweightRequests.getLast()
3054+ : null;
3055+ }
3056+ }
3057+
3058+ private static HeavyweightFocusRequest getFirstHWRequest() {
3059+ synchronized(heavyweightRequests) {
3060+ return (heavyweightRequests.size() > 0)
3061+ ? heavyweightRequests.getFirst()
3062+ : null;
3063+ }
3064+ }
3065+}