23 * questions.
24 */
25 package java.awt;
26
27 import java.awt.event.FocusEvent;
28 import java.awt.event.KeyEvent;
29 import java.awt.event.WindowEvent;
30 import java.awt.peer.ComponentPeer;
31 import java.awt.peer.LightweightPeer;
32 import java.lang.ref.WeakReference;
33 import java.util.LinkedList;
34 import java.util.Iterator;
35 import java.util.ListIterator;
36 import java.util.Set;
37
38 import sun.util.logging.PlatformLogger;
39
40 import sun.awt.AppContext;
41 import sun.awt.SunToolkit;
42 import sun.awt.AWTAccessor;
43 import sun.awt.CausedFocusEvent;
44 import sun.awt.TimedWindowEvent;
45
46 /**
47 * The default KeyboardFocusManager for AWT applications. Focus traversal is
48 * done in response to a Component's focus traversal keys, and using a
49 * Container's FocusTraversalPolicy.
50 * <p>
51 * Please see
52 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html">
53 * How to Use the Focus Subsystem</a>,
54 * a section in <em>The Java Tutorial</em>, and the
55 * <a href="../../java/awt/doc-files/FocusSpec.html">Focus Specification</a>
56 * for more information.
57 *
58 * @author David Mendenhall
59 *
60 * @see FocusTraversalPolicy
61 * @see Component#setFocusTraversalKeys
62 * @see Component#getFocusTraversalKeys
63 * @since 1.4
148 boolean clearOnFailure) {
149 Component toFocus =
150 KeyboardFocusManager.getMostRecentFocusOwner(aWindow);
151
152 if (toFocus != null && toFocus != vetoedComponent && doRestoreFocus(toFocus, vetoedComponent, false)) {
153 return true;
154 } else if (clearOnFailure) {
155 clearGlobalFocusOwnerPriv();
156 return true;
157 } else {
158 return false;
159 }
160 }
161 private boolean restoreFocus(Component toFocus, boolean clearOnFailure) {
162 return doRestoreFocus(toFocus, null, clearOnFailure);
163 }
164 private boolean doRestoreFocus(Component toFocus, Component vetoedComponent,
165 boolean clearOnFailure)
166 {
167 if (toFocus != vetoedComponent && toFocus.isShowing() && toFocus.canBeFocusOwner() &&
168 toFocus.requestFocus(false, CausedFocusEvent.Cause.ROLLBACK))
169 {
170 return true;
171 } else {
172 Component nextFocus = toFocus.getNextFocusCandidate();
173 if (nextFocus != null && nextFocus != vetoedComponent &&
174 nextFocus.requestFocusInWindow(CausedFocusEvent.Cause.ROLLBACK))
175 {
176 return true;
177 } else if (clearOnFailure) {
178 clearGlobalFocusOwnerPriv();
179 return true;
180 } else {
181 return false;
182 }
183 }
184 }
185
186 /**
187 * A special type of SentEvent which updates a counter in the target
188 * KeyboardFocusManager if it is an instance of
189 * DefaultKeyboardFocusManager.
190 */
191 private static class DefaultKeyboardFocusManagerSentEvent
192 extends SentEvent
193 {
194 /*
414 Component toFocus = KeyboardFocusManager.
415 getMostRecentFocusOwner(newFocusedWindow);
416 if ((toFocus == null) &&
417 newFocusedWindow.isFocusableWindow())
418 {
419 toFocus = newFocusedWindow.getFocusTraversalPolicy().
420 getInitialComponent(newFocusedWindow);
421 }
422 Component tempLost = null;
423 synchronized(KeyboardFocusManager.class) {
424 tempLost = newFocusedWindow.setTemporaryLostComponent(null);
425 }
426
427 // The component which last has the focus when this window was focused
428 // should receive focus first
429 if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
430 focusLog.finer("tempLost {0}, toFocus {1}",
431 tempLost, toFocus);
432 }
433 if (tempLost != null) {
434 tempLost.requestFocusInWindow(CausedFocusEvent.Cause.ACTIVATION);
435 }
436
437 if (toFocus != null && toFocus != tempLost) {
438 // If there is a component which requested focus when this window
439 // was inactive it expects to receive focus after activation.
440 toFocus.requestFocusInWindow(CausedFocusEvent.Cause.ACTIVATION);
441 }
442 }
443
444 Window realOppositeWindow = this.realOppositeWindowWR.get();
445 if (realOppositeWindow != we.getOppositeWindow()) {
446 we = new WindowEvent(newFocusedWindow,
447 WindowEvent.WINDOW_GAINED_FOCUS,
448 realOppositeWindow);
449 }
450 return typeAheadAssertions(newFocusedWindow, we);
451 }
452
453 case WindowEvent.WINDOW_ACTIVATED: {
454 WindowEvent we = (WindowEvent)e;
455 Window oldActiveWindow = getGlobalActiveWindow();
456 Window newActiveWindow = we.getWindow();
457 if (oldActiveWindow == newActiveWindow) {
458 break;
459 }
460
473 if (getGlobalActiveWindow() != null) {
474 // Activation change was rejected. Unlikely, but
475 // possible.
476 break;
477 }
478 }
479
480 setGlobalActiveWindow(newActiveWindow);
481
482 if (newActiveWindow != getGlobalActiveWindow()) {
483 // Activation change was rejected. Unlikely, but
484 // possible.
485 break;
486 }
487
488 return typeAheadAssertions(newActiveWindow, we);
489 }
490
491 case FocusEvent.FOCUS_GAINED: {
492 FocusEvent fe = (FocusEvent)e;
493 CausedFocusEvent.Cause cause = (fe instanceof CausedFocusEvent) ?
494 ((CausedFocusEvent)fe).getCause() : CausedFocusEvent.Cause.UNKNOWN;
495 Component oldFocusOwner = getGlobalFocusOwner();
496 Component newFocusOwner = fe.getComponent();
497 if (oldFocusOwner == newFocusOwner) {
498 if (focusLog.isLoggable(PlatformLogger.Level.FINE)) {
499 focusLog.fine("Skipping {0} because focus owner is the same", e);
500 }
501 // We can't just drop the event - there could be
502 // type-ahead markers associated with it.
503 dequeueKeyEvents(-1, newFocusOwner);
504 break;
505 }
506
507 // If there exists a current focus owner, then notify it that
508 // it has lost focus.
509 if (oldFocusOwner != null) {
510 boolean isEventDispatched =
511 sendMessage(oldFocusOwner,
512 new CausedFocusEvent(oldFocusOwner,
513 FocusEvent.FOCUS_LOST,
514 fe.isTemporary(),
515 newFocusOwner, cause));
516 // Failed to dispatch, clear by ourselves
517 if (!isEventDispatched) {
518 setGlobalFocusOwner(null);
519 if (!fe.isTemporary()) {
520 setGlobalPermanentFocusOwner(null);
521 }
522 }
523 }
524
525 // Because the native windowing system has a different notion
526 // of the current focus and activation states, it is possible
527 // that a Component outside of the focused Window receives a
528 // FOCUS_GAINED event. We synthesize a WINDOW_GAINED_FOCUS
529 // event in that case.
530 final Window newFocusedWindow = SunToolkit.getContainingWindow(newFocusOwner);
531 final Window currentFocusedWindow = getGlobalFocusedWindow();
532 if (newFocusedWindow != null &&
533 newFocusedWindow != currentFocusedWindow)
534 {
535 sendMessage(newFocusedWindow,
536 new WindowEvent(newFocusedWindow,
537 WindowEvent.WINDOW_GAINED_FOCUS,
538 currentFocusedWindow));
539 if (newFocusedWindow != getGlobalFocusedWindow()) {
540 // Focus change was rejected. Will happen if
541 // newFocusedWindow is not a focusable Window.
542
543 // Need to recover type-ahead, but don't bother
544 // restoring focus. That was done by the
545 // WINDOW_GAINED_FOCUS handler
546 dequeueKeyEvents(-1, newFocusOwner);
547 break;
548 }
549 }
550
551 if (!(newFocusOwner.isFocusable() && newFocusOwner.isShowing() &&
552 // Refuse focus on a disabled component if the focus event
553 // isn't of UNKNOWN reason (i.e. not a result of a direct request
554 // but traversal, activation or system generated).
555 (newFocusOwner.isEnabled() || cause.equals(CausedFocusEvent.Cause.UNKNOWN))))
556 {
557 // we should not accept focus on such component, so reject it.
558 dequeueKeyEvents(-1, newFocusOwner);
559 if (KeyboardFocusManager.isAutoFocusTransferEnabled()) {
560 // If FOCUS_GAINED is for a disposed component (however
561 // it shouldn't happen) its toplevel parent is null. In this
562 // case we have to try to restore focus in the current focused
563 // window (for the details: 6607170).
564 if (newFocusedWindow == null) {
565 restoreFocus(fe, currentFocusedWindow);
566 } else {
567 restoreFocus(fe, newFocusedWindow);
568 }
569 setMostRecentFocusOwner(newFocusedWindow, null); // see: 8013773
570 }
571 break;
572 }
573
574 setGlobalFocusOwner(newFocusOwner);
575
584 }
585
586 if (!fe.isTemporary()) {
587 setGlobalPermanentFocusOwner(newFocusOwner);
588
589 if (newFocusOwner != getGlobalPermanentFocusOwner()) {
590 // Focus change was rejected. Unlikely, but possible.
591 dequeueKeyEvents(-1, newFocusOwner);
592 if (KeyboardFocusManager.isAutoFocusTransferEnabled()) {
593 restoreFocus(fe, newFocusedWindow);
594 }
595 break;
596 }
597 }
598
599 setNativeFocusOwner(getHeavyweight(newFocusOwner));
600
601 Component realOppositeComponent = this.realOppositeComponentWR.get();
602 if (realOppositeComponent != null &&
603 realOppositeComponent != fe.getOppositeComponent()) {
604 fe = new CausedFocusEvent(newFocusOwner,
605 FocusEvent.FOCUS_GAINED,
606 fe.isTemporary(),
607 realOppositeComponent, cause);
608 ((AWTEvent) fe).isPosted = true;
609 }
610 return typeAheadAssertions(newFocusOwner, fe);
611 }
612
613 case FocusEvent.FOCUS_LOST: {
614 FocusEvent fe = (FocusEvent)e;
615 Component currentFocusOwner = getGlobalFocusOwner();
616 if (currentFocusOwner == null) {
617 if (focusLog.isLoggable(PlatformLogger.Level.FINE))
618 focusLog.fine("Skipping {0} because focus owner is null", e);
619 break;
620 }
621 // Ignore cases where a Component loses focus to itself.
622 // If we make a mistake because of retargeting, then the
623 // FOCUS_GAINED handler will correct it.
624 if (currentFocusOwner == fe.getOppositeComponent()) {
625 if (focusLog.isLoggable(PlatformLogger.Level.FINE))
626 focusLog.fine("Skipping {0} because current focus owner is equal to opposite", e);
627 break;
712 oppositeWindow == currentFocusedWindow)
713 {
714 break;
715 }
716
717 Component currentFocusOwner = getGlobalFocusOwner();
718 if (currentFocusOwner != null) {
719 // The focus owner should always receive a FOCUS_LOST event
720 // before the Window is defocused.
721 Component oppositeComp = null;
722 if (oppositeWindow != null) {
723 oppositeComp = oppositeWindow.getTemporaryLostComponent();
724 if (oppositeComp == null) {
725 oppositeComp = oppositeWindow.getMostRecentFocusOwner();
726 }
727 }
728 if (oppositeComp == null) {
729 oppositeComp = oppositeWindow;
730 }
731 sendMessage(currentFocusOwner,
732 new CausedFocusEvent(currentFocusOwner,
733 FocusEvent.FOCUS_LOST,
734 true,
735 oppositeComp, CausedFocusEvent.Cause.ACTIVATION));
736 }
737
738 setGlobalFocusedWindow(null);
739 if (getGlobalFocusedWindow() != null) {
740 // Focus change was rejected. Unlikely, but possible.
741 restoreFocus(currentFocusedWindow, null, true);
742 break;
743 }
744
745 we.setSource(currentFocusedWindow);
746 realOppositeWindowWR = (oppositeWindow != null)
747 ? new WeakReference<Window>(currentFocusedWindow)
748 : NULL_WINDOW_WR;
749 typeAheadAssertions(currentFocusedWindow, we);
750
751 if (oppositeWindow == null) {
752 // Then we need to deactivate the active Window as well.
753 // No need to synthesize in other cases, because
754 // WINDOW_ACTIVATED will handle it if necessary.
755 sendMessage(activeWindow,
|
23 * questions.
24 */
25 package java.awt;
26
27 import java.awt.event.FocusEvent;
28 import java.awt.event.KeyEvent;
29 import java.awt.event.WindowEvent;
30 import java.awt.peer.ComponentPeer;
31 import java.awt.peer.LightweightPeer;
32 import java.lang.ref.WeakReference;
33 import java.util.LinkedList;
34 import java.util.Iterator;
35 import java.util.ListIterator;
36 import java.util.Set;
37
38 import sun.util.logging.PlatformLogger;
39
40 import sun.awt.AppContext;
41 import sun.awt.SunToolkit;
42 import sun.awt.AWTAccessor;
43 import sun.awt.TimedWindowEvent;
44
45 /**
46 * The default KeyboardFocusManager for AWT applications. Focus traversal is
47 * done in response to a Component's focus traversal keys, and using a
48 * Container's FocusTraversalPolicy.
49 * <p>
50 * Please see
51 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html">
52 * How to Use the Focus Subsystem</a>,
53 * a section in <em>The Java Tutorial</em>, and the
54 * <a href="../../java/awt/doc-files/FocusSpec.html">Focus Specification</a>
55 * for more information.
56 *
57 * @author David Mendenhall
58 *
59 * @see FocusTraversalPolicy
60 * @see Component#setFocusTraversalKeys
61 * @see Component#getFocusTraversalKeys
62 * @since 1.4
147 boolean clearOnFailure) {
148 Component toFocus =
149 KeyboardFocusManager.getMostRecentFocusOwner(aWindow);
150
151 if (toFocus != null && toFocus != vetoedComponent && doRestoreFocus(toFocus, vetoedComponent, false)) {
152 return true;
153 } else if (clearOnFailure) {
154 clearGlobalFocusOwnerPriv();
155 return true;
156 } else {
157 return false;
158 }
159 }
160 private boolean restoreFocus(Component toFocus, boolean clearOnFailure) {
161 return doRestoreFocus(toFocus, null, clearOnFailure);
162 }
163 private boolean doRestoreFocus(Component toFocus, Component vetoedComponent,
164 boolean clearOnFailure)
165 {
166 if (toFocus != vetoedComponent && toFocus.isShowing() && toFocus.canBeFocusOwner() &&
167 toFocus.requestFocus(false, FocusEvent.Cause.ROLLBACK))
168 {
169 return true;
170 } else {
171 Component nextFocus = toFocus.getNextFocusCandidate();
172 if (nextFocus != null && nextFocus != vetoedComponent &&
173 nextFocus.requestFocusInWindow(FocusEvent.Cause.ROLLBACK))
174 {
175 return true;
176 } else if (clearOnFailure) {
177 clearGlobalFocusOwnerPriv();
178 return true;
179 } else {
180 return false;
181 }
182 }
183 }
184
185 /**
186 * A special type of SentEvent which updates a counter in the target
187 * KeyboardFocusManager if it is an instance of
188 * DefaultKeyboardFocusManager.
189 */
190 private static class DefaultKeyboardFocusManagerSentEvent
191 extends SentEvent
192 {
193 /*
413 Component toFocus = KeyboardFocusManager.
414 getMostRecentFocusOwner(newFocusedWindow);
415 if ((toFocus == null) &&
416 newFocusedWindow.isFocusableWindow())
417 {
418 toFocus = newFocusedWindow.getFocusTraversalPolicy().
419 getInitialComponent(newFocusedWindow);
420 }
421 Component tempLost = null;
422 synchronized(KeyboardFocusManager.class) {
423 tempLost = newFocusedWindow.setTemporaryLostComponent(null);
424 }
425
426 // The component which last has the focus when this window was focused
427 // should receive focus first
428 if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
429 focusLog.finer("tempLost {0}, toFocus {1}",
430 tempLost, toFocus);
431 }
432 if (tempLost != null) {
433 tempLost.requestFocusInWindow(FocusEvent.Cause.ACTIVATION);
434 }
435
436 if (toFocus != null && toFocus != tempLost) {
437 // If there is a component which requested focus when this window
438 // was inactive it expects to receive focus after activation.
439 toFocus.requestFocusInWindow(FocusEvent.Cause.ACTIVATION);
440 }
441 }
442
443 Window realOppositeWindow = this.realOppositeWindowWR.get();
444 if (realOppositeWindow != we.getOppositeWindow()) {
445 we = new WindowEvent(newFocusedWindow,
446 WindowEvent.WINDOW_GAINED_FOCUS,
447 realOppositeWindow);
448 }
449 return typeAheadAssertions(newFocusedWindow, we);
450 }
451
452 case WindowEvent.WINDOW_ACTIVATED: {
453 WindowEvent we = (WindowEvent)e;
454 Window oldActiveWindow = getGlobalActiveWindow();
455 Window newActiveWindow = we.getWindow();
456 if (oldActiveWindow == newActiveWindow) {
457 break;
458 }
459
472 if (getGlobalActiveWindow() != null) {
473 // Activation change was rejected. Unlikely, but
474 // possible.
475 break;
476 }
477 }
478
479 setGlobalActiveWindow(newActiveWindow);
480
481 if (newActiveWindow != getGlobalActiveWindow()) {
482 // Activation change was rejected. Unlikely, but
483 // possible.
484 break;
485 }
486
487 return typeAheadAssertions(newActiveWindow, we);
488 }
489
490 case FocusEvent.FOCUS_GAINED: {
491 FocusEvent fe = (FocusEvent)e;
492 Component oldFocusOwner = getGlobalFocusOwner();
493 Component newFocusOwner = fe.getComponent();
494 if (oldFocusOwner == newFocusOwner) {
495 if (focusLog.isLoggable(PlatformLogger.Level.FINE)) {
496 focusLog.fine("Skipping {0} because focus owner is the same", e);
497 }
498 // We can't just drop the event - there could be
499 // type-ahead markers associated with it.
500 dequeueKeyEvents(-1, newFocusOwner);
501 break;
502 }
503
504 // If there exists a current focus owner, then notify it that
505 // it has lost focus.
506 if (oldFocusOwner != null) {
507 boolean isEventDispatched =
508 sendMessage(oldFocusOwner,
509 new FocusEvent(oldFocusOwner,
510 FocusEvent.FOCUS_LOST,
511 fe.isTemporary(),
512 newFocusOwner, fe.getCause()));
513 // Failed to dispatch, clear by ourselves
514 if (!isEventDispatched) {
515 setGlobalFocusOwner(null);
516 if (!fe.isTemporary()) {
517 setGlobalPermanentFocusOwner(null);
518 }
519 }
520 }
521
522 // Because the native windowing system has a different notion
523 // of the current focus and activation states, it is possible
524 // that a Component outside of the focused Window receives a
525 // FOCUS_GAINED event. We synthesize a WINDOW_GAINED_FOCUS
526 // event in that case.
527 final Window newFocusedWindow = SunToolkit.getContainingWindow(newFocusOwner);
528 final Window currentFocusedWindow = getGlobalFocusedWindow();
529 if (newFocusedWindow != null &&
530 newFocusedWindow != currentFocusedWindow)
531 {
532 sendMessage(newFocusedWindow,
533 new WindowEvent(newFocusedWindow,
534 WindowEvent.WINDOW_GAINED_FOCUS,
535 currentFocusedWindow));
536 if (newFocusedWindow != getGlobalFocusedWindow()) {
537 // Focus change was rejected. Will happen if
538 // newFocusedWindow is not a focusable Window.
539
540 // Need to recover type-ahead, but don't bother
541 // restoring focus. That was done by the
542 // WINDOW_GAINED_FOCUS handler
543 dequeueKeyEvents(-1, newFocusOwner);
544 break;
545 }
546 }
547
548 if (!(newFocusOwner.isFocusable() && newFocusOwner.isShowing() &&
549 // Refuse focus on a disabled component if the focus event
550 // isn't of UNKNOWN reason (i.e. not a result of a direct request
551 // but traversal, activation or system generated).
552 (newFocusOwner.isEnabled() || fe.getCause().equals(FocusEvent.Cause.UNKNOWN))))
553 {
554 // we should not accept focus on such component, so reject it.
555 dequeueKeyEvents(-1, newFocusOwner);
556 if (KeyboardFocusManager.isAutoFocusTransferEnabled()) {
557 // If FOCUS_GAINED is for a disposed component (however
558 // it shouldn't happen) its toplevel parent is null. In this
559 // case we have to try to restore focus in the current focused
560 // window (for the details: 6607170).
561 if (newFocusedWindow == null) {
562 restoreFocus(fe, currentFocusedWindow);
563 } else {
564 restoreFocus(fe, newFocusedWindow);
565 }
566 setMostRecentFocusOwner(newFocusedWindow, null); // see: 8013773
567 }
568 break;
569 }
570
571 setGlobalFocusOwner(newFocusOwner);
572
581 }
582
583 if (!fe.isTemporary()) {
584 setGlobalPermanentFocusOwner(newFocusOwner);
585
586 if (newFocusOwner != getGlobalPermanentFocusOwner()) {
587 // Focus change was rejected. Unlikely, but possible.
588 dequeueKeyEvents(-1, newFocusOwner);
589 if (KeyboardFocusManager.isAutoFocusTransferEnabled()) {
590 restoreFocus(fe, newFocusedWindow);
591 }
592 break;
593 }
594 }
595
596 setNativeFocusOwner(getHeavyweight(newFocusOwner));
597
598 Component realOppositeComponent = this.realOppositeComponentWR.get();
599 if (realOppositeComponent != null &&
600 realOppositeComponent != fe.getOppositeComponent()) {
601 fe = new FocusEvent(newFocusOwner,
602 FocusEvent.FOCUS_GAINED,
603 fe.isTemporary(),
604 realOppositeComponent, fe.getCause());
605 ((AWTEvent) fe).isPosted = true;
606 }
607 return typeAheadAssertions(newFocusOwner, fe);
608 }
609
610 case FocusEvent.FOCUS_LOST: {
611 FocusEvent fe = (FocusEvent)e;
612 Component currentFocusOwner = getGlobalFocusOwner();
613 if (currentFocusOwner == null) {
614 if (focusLog.isLoggable(PlatformLogger.Level.FINE))
615 focusLog.fine("Skipping {0} because focus owner is null", e);
616 break;
617 }
618 // Ignore cases where a Component loses focus to itself.
619 // If we make a mistake because of retargeting, then the
620 // FOCUS_GAINED handler will correct it.
621 if (currentFocusOwner == fe.getOppositeComponent()) {
622 if (focusLog.isLoggable(PlatformLogger.Level.FINE))
623 focusLog.fine("Skipping {0} because current focus owner is equal to opposite", e);
624 break;
709 oppositeWindow == currentFocusedWindow)
710 {
711 break;
712 }
713
714 Component currentFocusOwner = getGlobalFocusOwner();
715 if (currentFocusOwner != null) {
716 // The focus owner should always receive a FOCUS_LOST event
717 // before the Window is defocused.
718 Component oppositeComp = null;
719 if (oppositeWindow != null) {
720 oppositeComp = oppositeWindow.getTemporaryLostComponent();
721 if (oppositeComp == null) {
722 oppositeComp = oppositeWindow.getMostRecentFocusOwner();
723 }
724 }
725 if (oppositeComp == null) {
726 oppositeComp = oppositeWindow;
727 }
728 sendMessage(currentFocusOwner,
729 new FocusEvent(currentFocusOwner,
730 FocusEvent.FOCUS_LOST,
731 true,
732 oppositeComp, FocusEvent.Cause.ACTIVATION));
733 }
734
735 setGlobalFocusedWindow(null);
736 if (getGlobalFocusedWindow() != null) {
737 // Focus change was rejected. Unlikely, but possible.
738 restoreFocus(currentFocusedWindow, null, true);
739 break;
740 }
741
742 we.setSource(currentFocusedWindow);
743 realOppositeWindowWR = (oppositeWindow != null)
744 ? new WeakReference<Window>(currentFocusedWindow)
745 : NULL_WINDOW_WR;
746 typeAheadAssertions(currentFocusedWindow, we);
747
748 if (oppositeWindow == null) {
749 // Then we need to deactivate the active Window as well.
750 // No need to synthesize in other cases, because
751 // WINDOW_ACTIVATED will handle it if necessary.
752 sendMessage(activeWindow,
|