4690 postEvent(e); 4691 } 4692 4693 /** 4694 * Dispatches an event to this component or one of its sub components. 4695 * Calls <code>processEvent</code> before returning for 1.1-style 4696 * events which have been enabled for the <code>Component</code>. 4697 * @param e the event 4698 */ 4699 public final void dispatchEvent(AWTEvent e) { 4700 dispatchEventImpl(e); 4701 } 4702 4703 @SuppressWarnings("deprecation") 4704 void dispatchEventImpl(AWTEvent e) { 4705 int id = e.getID(); 4706 4707 // Check that this component belongs to this app-context 4708 AppContext compContext = appContext; 4709 if (compContext != null && !compContext.equals(AppContext.getAppContext())) { 4710 if (eventLog.isLoggable(PlatformLogger.FINE)) { 4711 eventLog.fine("Event " + e + " is being dispatched on the wrong AppContext"); 4712 } 4713 } 4714 4715 if (eventLog.isLoggable(PlatformLogger.FINEST)) { 4716 eventLog.finest("{0}", e); 4717 } 4718 4719 /* 4720 * 0. Set timestamp and modifiers of current event. 4721 */ 4722 if (!(e instanceof KeyEvent)) { 4723 // Timestamp of a key event is set later in DKFM.preDispatchKeyEvent(KeyEvent). 4724 EventQueue.setCurrentEventAndMostRecentTime(e); 4725 } 4726 4727 /* 4728 * 1. Pre-dispatchers. Do any necessary retargeting/reordering here 4729 * before we notify AWTEventListeners. 4730 */ 4731 4732 if (e instanceof SunDropTargetEvent) { 4733 ((SunDropTargetEvent)e).dispatch(); 4734 return; 4735 } 4736 4737 if (!e.focusManagerIsDispatching) { 4738 // Invoke the private focus retargeting method which provides 4739 // lightweight Component support 4740 if (e.isPosted) { 4741 e = KeyboardFocusManager.retargetFocusEvent(e); 4742 e.isPosted = true; 4743 } 4744 4745 // Now, with the event properly targeted to a lightweight 4746 // descendant if necessary, invoke the public focus retargeting 4747 // and dispatching function 4748 if (KeyboardFocusManager.getCurrentKeyboardFocusManager(). 4749 dispatchEvent(e)) 4750 { 4751 return; 4752 } 4753 } 4754 if ((e instanceof FocusEvent) && focusLog.isLoggable(PlatformLogger.FINEST)) { 4755 focusLog.finest("" + e); 4756 } 4757 // MouseWheel may need to be retargeted here so that 4758 // AWTEventListener sees the event go to the correct 4759 // Component. If the MouseWheelEvent needs to go to an ancestor, 4760 // the event is dispatched to the ancestor, and dispatching here 4761 // stops. 4762 if (id == MouseEvent.MOUSE_WHEEL && 4763 (!eventTypeEnabled(id)) && 4764 (peer != null && !peer.handlesWheelScrolling()) && 4765 (dispatchMouseWheelToAncestor((MouseWheelEvent)e))) 4766 { 4767 return; 4768 } 4769 4770 /* 4771 * 2. Allow the Toolkit to pass this to AWTEventListeners. 4772 */ 4773 Toolkit toolkit = Toolkit.getDefaultToolkit(); 4774 toolkit.notifyAWTEventListeners(e); 4792 * 4. Allow input methods to process the event 4793 */ 4794 if (areInputMethodsEnabled()) { 4795 // We need to pass on InputMethodEvents since some host 4796 // input method adapters send them through the Java 4797 // event queue instead of directly to the component, 4798 // and the input context also handles the Java composition window 4799 if(((e instanceof InputMethodEvent) && !(this instanceof CompositionArea)) 4800 || 4801 // Otherwise, we only pass on input and focus events, because 4802 // a) input methods shouldn't know about semantic or component-level events 4803 // b) passing on the events takes time 4804 // c) isConsumed() is always true for semantic events. 4805 (e instanceof InputEvent) || (e instanceof FocusEvent)) { 4806 InputContext inputContext = getInputContext(); 4807 4808 4809 if (inputContext != null) { 4810 inputContext.dispatchEvent(e); 4811 if (e.isConsumed()) { 4812 if ((e instanceof FocusEvent) && focusLog.isLoggable(PlatformLogger.FINEST)) { 4813 focusLog.finest("3579: Skipping " + e); 4814 } 4815 return; 4816 } 4817 } 4818 } 4819 } else { 4820 // When non-clients get focus, we need to explicitly disable the native 4821 // input method. The native input method is actually not disabled when 4822 // the active/passive/peered clients loose focus. 4823 if (id == FocusEvent.FOCUS_GAINED) { 4824 InputContext inputContext = getInputContext(); 4825 if (inputContext != null && inputContext instanceof sun.awt.im.InputContext) { 4826 ((sun.awt.im.InputContext)inputContext).disableNativeIM(); 4827 } 4828 } 4829 } 4830 4831 4832 /* 4833 * 5. Pre-process any special events before delivery 4834 */ 4835 switch(id) { 4836 // Handling of the PAINT and UPDATE events is now done in the 4837 // peer's handleEvent() method so the background can be cleared 4838 // selectively for non-native components on Windows only. 4839 // - Fred.Ecks@Eng.sun.com, 5-8-98 4840 4841 case KeyEvent.KEY_PRESSED: 4842 case KeyEvent.KEY_RELEASED: 4843 Container p = (Container)((this instanceof Container) ? this : parent); 4844 if (p != null) { 4845 p.preProcessKeyEvent((KeyEvent)e); 4846 if (e.isConsumed()) { 4847 if (focusLog.isLoggable(PlatformLogger.FINEST)) { 4848 focusLog.finest("Pre-process consumed event"); 4849 } 4850 return; 4851 } 4852 } 4853 break; 4854 4855 case WindowEvent.WINDOW_CLOSING: 4856 if (toolkit instanceof WindowClosingListener) { 4857 windowClosingException = ((WindowClosingListener) 4858 toolkit).windowClosingNotify((WindowEvent)e); 4859 if (checkWindowClosingException()) { 4860 return; 4861 } 4862 } 4863 break; 4864 4865 default: 4866 break; 4867 } 4960 * If newEventsOnly is false, method is called so that ScrollPane can 4961 * override it and handle common-case mouse wheel scrolling. NOP 4962 * for Component. 4963 */ 4964 void autoProcessMouseWheel(MouseWheelEvent e) {} 4965 4966 /* 4967 * Dispatch given MouseWheelEvent to the first ancestor for which 4968 * MouseWheelEvents are enabled. 4969 * 4970 * Returns whether or not event was dispatched to an ancestor 4971 */ 4972 boolean dispatchMouseWheelToAncestor(MouseWheelEvent e) { 4973 int newX, newY; 4974 newX = e.getX() + getX(); // Coordinates take into account at least 4975 newY = e.getY() + getY(); // the cursor's position relative to this 4976 // Component (e.getX()), and this Component's 4977 // position relative to its parent. 4978 MouseWheelEvent newMWE; 4979 4980 if (eventLog.isLoggable(PlatformLogger.FINEST)) { 4981 eventLog.finest("dispatchMouseWheelToAncestor"); 4982 eventLog.finest("orig event src is of " + e.getSource().getClass()); 4983 } 4984 4985 /* parent field for Window refers to the owning Window. 4986 * MouseWheelEvents should NOT be propagated into owning Windows 4987 */ 4988 synchronized (getTreeLock()) { 4989 Container anc = getParent(); 4990 while (anc != null && !anc.eventEnabled(e)) { 4991 // fix coordinates to be relative to new event source 4992 newX += anc.getX(); 4993 newY += anc.getY(); 4994 4995 if (!(anc instanceof Window)) { 4996 anc = anc.getParent(); 4997 } 4998 else { 4999 break; 5000 } 5001 } 5002 5003 if (eventLog.isLoggable(PlatformLogger.FINEST)) { 5004 eventLog.finest("new event src is " + anc.getClass()); 5005 } 5006 5007 if (anc != null && anc.eventEnabled(e)) { 5008 // Change event to be from new source, with new x,y 5009 // For now, just create a new event - yucky 5010 5011 newMWE = new MouseWheelEvent(anc, // new source 5012 e.getID(), 5013 e.getWhen(), 5014 e.getModifiers(), 5015 newX, // x relative to new source 5016 newY, // y relative to new source 5017 e.getXOnScreen(), 5018 e.getYOnScreen(), 5019 e.getClickCount(), 5020 e.isPopupTrigger(), 5021 e.getScrollType(), 5022 e.getScrollAmount(), 5023 e.getWheelRotation(), 5483 synchronized (this) { 5484 notifyAncestors = 5485 (hierarchyBoundsListener != null && 5486 (eventMask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) == 0); 5487 hierarchyBoundsListener = 5488 AWTEventMulticaster.remove(hierarchyBoundsListener, l); 5489 notifyAncestors = (notifyAncestors && 5490 hierarchyBoundsListener == null); 5491 } 5492 if (notifyAncestors) { 5493 synchronized (getTreeLock()) { 5494 adjustListeningChildrenOnParent( 5495 AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK, -1); 5496 } 5497 } 5498 } 5499 5500 // Should only be called while holding the tree lock 5501 int numListening(long mask) { 5502 // One mask or the other, but not neither or both. 5503 if (eventLog.isLoggable(PlatformLogger.FINE)) { 5504 if ((mask != AWTEvent.HIERARCHY_EVENT_MASK) && 5505 (mask != AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK)) 5506 { 5507 eventLog.fine("Assertion failed"); 5508 } 5509 } 5510 if ((mask == AWTEvent.HIERARCHY_EVENT_MASK && 5511 (hierarchyListener != null || 5512 (eventMask & AWTEvent.HIERARCHY_EVENT_MASK) != 0)) || 5513 (mask == AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK && 5514 (hierarchyBoundsListener != null || 5515 (eventMask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0))) { 5516 return 1; 5517 } else { 5518 return 0; 5519 } 5520 } 5521 5522 // Should only be called while holding tree lock 5523 int countHierarchyMembers() { 5524 return 1; 5525 } 5526 // Should only be called while holding the tree lock 5527 int createHierarchyEvents(int id, Component changed, 5528 Container changedParent, long changeFlags, 5529 boolean enabledOnToolkit) { 5530 switch (id) { 5531 case HierarchyEvent.HIERARCHY_CHANGED: 5532 if (hierarchyListener != null || 5533 (eventMask & AWTEvent.HIERARCHY_EVENT_MASK) != 0 || 5534 enabledOnToolkit) { 5535 HierarchyEvent e = new HierarchyEvent(this, id, changed, 5536 changedParent, 5537 changeFlags); 5538 dispatchEvent(e); 5539 return 1; 5540 } 5541 break; 5542 case HierarchyEvent.ANCESTOR_MOVED: 5543 case HierarchyEvent.ANCESTOR_RESIZED: 5544 if (eventLog.isLoggable(PlatformLogger.FINE)) { 5545 if (changeFlags != 0) { 5546 eventLog.fine("Assertion (changeFlags == 0) failed"); 5547 } 5548 } 5549 if (hierarchyBoundsListener != null || 5550 (eventMask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0 || 5551 enabledOnToolkit) { 5552 HierarchyEvent e = new HierarchyEvent(this, id, changed, 5553 changedParent); 5554 dispatchEvent(e); 5555 return 1; 5556 } 5557 break; 5558 default: 5559 // assert false 5560 if (eventLog.isLoggable(PlatformLogger.FINE)) { 5561 eventLog.fine("This code must never be reached"); 5562 } 5563 break; 5564 } 5565 return 0; 5566 } 5567 5568 /** 5569 * Returns an array of all the hierarchy bounds listeners 5570 * registered on this component. 5571 * 5572 * @return all of this component's <code>HierarchyBoundsListener</code>s 5573 * or an empty array if no hierarchy bounds 5574 * listeners are currently registered 5575 * 5576 * @see #addHierarchyBoundsListener 5577 * @see #removeHierarchyBoundsListener 5578 * @since 1.4 5579 */ 5580 public synchronized HierarchyBoundsListener[] getHierarchyBoundsListeners() { 7626 if (currentEvent instanceof MouseEvent && 7627 SunToolkit.isSystemGenerated(currentEvent)) 7628 { 7629 // 2) Sanity check: if the mouse event component source belongs to the same containing window. 7630 Component source = ((MouseEvent)currentEvent).getComponent(); 7631 if (source == null || source.getContainingWindow() == getContainingWindow()) { 7632 focusLog.finest("requesting focus by mouse event \"in window\""); 7633 7634 // If both the conditions are fulfilled the focus request should be strictly 7635 // bounded by the toplevel window. It's assumed that the mouse event activates 7636 // the window (if it wasn't active) and this makes it possible for a focus 7637 // request with a strong in-window requirement to change focus in the bounds 7638 // of the toplevel. If, by any means, due to asynchronous nature of the event 7639 // dispatching mechanism, the window happens to be natively inactive by the time 7640 // this focus request is eventually handled, it should not re-activate the 7641 // toplevel. Otherwise the result may not meet user expectations. See 6981400. 7642 focusedWindowChangeAllowed = false; 7643 } 7644 } 7645 if (!isRequestFocusAccepted(temporary, focusedWindowChangeAllowed, cause)) { 7646 if (focusLog.isLoggable(PlatformLogger.FINEST)) { 7647 focusLog.finest("requestFocus is not accepted"); 7648 } 7649 return false; 7650 } 7651 // Update most-recent map 7652 KeyboardFocusManager.setMostRecentFocusOwner(this); 7653 7654 Component window = this; 7655 while ( (window != null) && !(window instanceof Window)) { 7656 if (!window.isVisible()) { 7657 if (focusLog.isLoggable(PlatformLogger.FINEST)) { 7658 focusLog.finest("component is recurively invisible"); 7659 } 7660 return false; 7661 } 7662 window = window.parent; 7663 } 7664 7665 ComponentPeer peer = this.peer; 7666 Component heavyweight = (peer instanceof LightweightPeer) 7667 ? getNativeContainer() : this; 7668 if (heavyweight == null || !heavyweight.isVisible()) { 7669 if (focusLog.isLoggable(PlatformLogger.FINEST)) { 7670 focusLog.finest("Component is not a part of visible hierarchy"); 7671 } 7672 return false; 7673 } 7674 peer = heavyweight.peer; 7675 if (peer == null) { 7676 if (focusLog.isLoggable(PlatformLogger.FINEST)) { 7677 focusLog.finest("Peer is null"); 7678 } 7679 return false; 7680 } 7681 7682 // Focus this Component 7683 long time = 0; 7684 if (EventQueue.isDispatchThread()) { 7685 time = Toolkit.getEventQueue().getMostRecentKeyEventTime(); 7686 } else { 7687 // A focus request made from outside EDT should not be associated with any event 7688 // and so its time stamp is simply set to the current time. 7689 time = System.currentTimeMillis(); 7690 } 7691 7692 boolean success = peer.requestFocus 7693 (this, temporary, focusedWindowChangeAllowed, time, cause); 7694 if (!success) { 7695 KeyboardFocusManager.getCurrentKeyboardFocusManager 7696 (appContext).dequeueKeyEvents(time, this); 7697 if (focusLog.isLoggable(PlatformLogger.FINEST)) { 7698 focusLog.finest("Peer request failed"); 7699 } 7700 } else { 7701 if (focusLog.isLoggable(PlatformLogger.FINEST)) { 7702 focusLog.finest("Pass for " + this); 7703 } 7704 } 7705 return success; 7706 } 7707 7708 private boolean isRequestFocusAccepted(boolean temporary, 7709 boolean focusedWindowChangeAllowed, 7710 CausedFocusEvent.Cause cause) 7711 { 7712 if (!isFocusable() || !isVisible()) { 7713 if (focusLog.isLoggable(PlatformLogger.FINEST)) { 7714 focusLog.finest("Not focusable or not visible"); 7715 } 7716 return false; 7717 } 7718 7719 ComponentPeer peer = this.peer; 7720 if (peer == null) { 7721 if (focusLog.isLoggable(PlatformLogger.FINEST)) { 7722 focusLog.finest("peer is null"); 7723 } 7724 return false; 7725 } 7726 7727 Window window = getContainingWindow(); 7728 if (window == null || !window.isFocusableWindow()) { 7729 if (focusLog.isLoggable(PlatformLogger.FINEST)) { 7730 focusLog.finest("Component doesn't have toplevel"); 7731 } 7732 return false; 7733 } 7734 7735 // We have passed all regular checks for focus request, 7736 // now let's call RequestFocusController and see what it says. 7737 Component focusOwner = KeyboardFocusManager.getMostRecentFocusOwner(window); 7738 if (focusOwner == null) { 7739 // sometimes most recent focus owner may be null, but focus owner is not 7740 // e.g. we reset most recent focus owner if user removes focus owner 7741 focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); 7742 if (focusOwner != null && focusOwner.getContainingWindow() != window) { 7743 focusOwner = null; 7744 } 7745 } 7746 7747 if (focusOwner == this || focusOwner == null) { 7748 // Controller is supposed to verify focus transfers and for this it 7749 // should know both from and to components. And it shouldn't verify 7750 // transfers from when these components are equal. 7751 if (focusLog.isLoggable(PlatformLogger.FINEST)) { 7752 focusLog.finest("focus owner is null or this"); 7753 } 7754 return true; 7755 } 7756 7757 if (CausedFocusEvent.Cause.ACTIVATION == cause) { 7758 // we shouldn't call RequestFocusController in case we are 7759 // in activation. We do request focus on component which 7760 // has got temporary focus lost and then on component which is 7761 // most recent focus owner. But most recent focus owner can be 7762 // changed by requestFocsuXXX() call only, so this transfer has 7763 // been already approved. 7764 if (focusLog.isLoggable(PlatformLogger.FINEST)) { 7765 focusLog.finest("cause is activation"); 7766 } 7767 return true; 7768 } 7769 7770 boolean ret = Component.requestFocusController.acceptRequestFocus(focusOwner, 7771 this, 7772 temporary, 7773 focusedWindowChangeAllowed, 7774 cause); 7775 if (focusLog.isLoggable(PlatformLogger.FINEST)) { 7776 focusLog.finest("RequestFocusController returns {0}", ret); 7777 } 7778 7779 return ret; 7780 } 7781 7782 private static RequestFocusController requestFocusController = new DummyRequestFocusController(); 7783 7784 // Swing access this method through reflection to implement InputVerifier's functionality. 7785 // Perhaps, we should make this method public (later ;) 7786 private static class DummyRequestFocusController implements RequestFocusController { 7787 public boolean acceptRequestFocus(Component from, Component to, 7788 boolean temporary, boolean focusedWindowChangeAllowed, 7789 CausedFocusEvent.Cause cause) 7790 { 7791 return true; 7792 } 7793 }; 7794 7795 synchronized static void setRequestFocusController(RequestFocusController requestController) 7847 /** 7848 * Transfers the focus to the next component, as though this Component were 7849 * the focus owner. 7850 * @see #requestFocus() 7851 * @since JDK1.1 7852 */ 7853 public void transferFocus() { 7854 nextFocus(); 7855 } 7856 7857 /** 7858 * @deprecated As of JDK version 1.1, 7859 * replaced by transferFocus(). 7860 */ 7861 @Deprecated 7862 public void nextFocus() { 7863 transferFocus(false); 7864 } 7865 7866 boolean transferFocus(boolean clearOnFailure) { 7867 if (focusLog.isLoggable(PlatformLogger.FINER)) { 7868 focusLog.finer("clearOnFailure = " + clearOnFailure); 7869 } 7870 Component toFocus = getNextFocusCandidate(); 7871 boolean res = false; 7872 if (toFocus != null && !toFocus.isFocusOwner() && toFocus != this) { 7873 res = toFocus.requestFocusInWindow(CausedFocusEvent.Cause.TRAVERSAL_FORWARD); 7874 } 7875 if (clearOnFailure && !res) { 7876 if (focusLog.isLoggable(PlatformLogger.FINER)) { 7877 focusLog.finer("clear global focus owner"); 7878 } 7879 KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwnerPriv(); 7880 } 7881 if (focusLog.isLoggable(PlatformLogger.FINER)) { 7882 focusLog.finer("returning result: " + res); 7883 } 7884 return res; 7885 } 7886 7887 final Component getNextFocusCandidate() { 7888 Container rootAncestor = getTraversalRoot(); 7889 Component comp = this; 7890 while (rootAncestor != null && 7891 !(rootAncestor.isShowing() && rootAncestor.canBeFocusOwner())) 7892 { 7893 comp = rootAncestor; 7894 rootAncestor = comp.getFocusCycleRootAncestor(); 7895 } 7896 if (focusLog.isLoggable(PlatformLogger.FINER)) { 7897 focusLog.finer("comp = " + comp + ", root = " + rootAncestor); 7898 } 7899 Component candidate = null; 7900 if (rootAncestor != null) { 7901 FocusTraversalPolicy policy = rootAncestor.getFocusTraversalPolicy(); 7902 Component toFocus = policy.getComponentAfter(rootAncestor, comp); 7903 if (focusLog.isLoggable(PlatformLogger.FINER)) { 7904 focusLog.finer("component after is " + toFocus); 7905 } 7906 if (toFocus == null) { 7907 toFocus = policy.getDefaultComponent(rootAncestor); 7908 if (focusLog.isLoggable(PlatformLogger.FINER)) { 7909 focusLog.finer("default component is " + toFocus); 7910 } 7911 } 7912 if (toFocus == null) { 7913 Applet applet = EmbeddedFrame.getAppletIfAncestorOf(this); 7914 if (applet != null) { 7915 toFocus = applet; 7916 } 7917 } 7918 candidate = toFocus; 7919 } 7920 if (focusLog.isLoggable(PlatformLogger.FINER)) { 7921 focusLog.finer("Focus transfer candidate: " + candidate); 7922 } 7923 return candidate; 7924 } 7925 7926 /** 7927 * Transfers the focus to the previous component, as though this Component 7928 * were the focus owner. 7929 * @see #requestFocus() 7930 * @since 1.4 7931 */ 7932 public void transferFocusBackward() { 7933 transferFocusBackward(false); 7934 } 7935 7936 boolean transferFocusBackward(boolean clearOnFailure) { 7937 Container rootAncestor = getTraversalRoot(); 7938 Component comp = this; 7939 while (rootAncestor != null && 7940 !(rootAncestor.isShowing() && rootAncestor.canBeFocusOwner())) 7941 { 7942 comp = rootAncestor; 7943 rootAncestor = comp.getFocusCycleRootAncestor(); 7944 } 7945 boolean res = false; 7946 if (rootAncestor != null) { 7947 FocusTraversalPolicy policy = rootAncestor.getFocusTraversalPolicy(); 7948 Component toFocus = policy.getComponentBefore(rootAncestor, comp); 7949 if (toFocus == null) { 7950 toFocus = policy.getDefaultComponent(rootAncestor); 7951 } 7952 if (toFocus != null) { 7953 res = toFocus.requestFocusInWindow(CausedFocusEvent.Cause.TRAVERSAL_BACKWARD); 7954 } 7955 } 7956 if (clearOnFailure && !res) { 7957 if (focusLog.isLoggable(PlatformLogger.FINER)) { 7958 focusLog.finer("clear global focus owner"); 7959 } 7960 KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwnerPriv(); 7961 } 7962 if (focusLog.isLoggable(PlatformLogger.FINER)) { 7963 focusLog.finer("returning result: " + res); 7964 } 7965 return res; 7966 } 7967 7968 /** 7969 * Transfers the focus up one focus traversal cycle. Typically, the focus 7970 * owner is set to this Component's focus cycle root, and the current focus 7971 * cycle root is set to the new focus owner's focus cycle root. If, 7972 * however, this Component's focus cycle root is a Window, then the focus 7973 * owner is set to the focus cycle root's default Component to focus, and 7974 * the current focus cycle root is unchanged. 7975 * 7976 * @see #requestFocus() 7977 * @see Container#isFocusCycleRoot() 7978 * @see Container#setFocusCycleRoot(boolean) 7979 * @since 1.4 7980 */ 7981 public void transferFocusUpCycle() { 7982 Container rootAncestor; 9723 * Check whether we can trust the current bounds of the component. 9724 * The return value of false indicates that the container of the 9725 * component is invalid, and therefore needs to be layed out, which would 9726 * probably mean changing the bounds of its children. 9727 * Null-layout of the container or absence of the container mean 9728 * the bounds of the component are final and can be trusted. 9729 */ 9730 final boolean areBoundsValid() { 9731 Container cont = getContainer(); 9732 return cont == null || cont.isValid() || cont.getLayout() == null; 9733 } 9734 9735 /** 9736 * Applies the shape to the component 9737 * @param shape Shape to be applied to the component 9738 */ 9739 void applyCompoundShape(Region shape) { 9740 checkTreeLock(); 9741 9742 if (!areBoundsValid()) { 9743 if (mixingLog.isLoggable(PlatformLogger.FINE)) { 9744 mixingLog.fine("this = " + this + "; areBoundsValid = " + areBoundsValid()); 9745 } 9746 return; 9747 } 9748 9749 if (!isLightweight()) { 9750 ComponentPeer peer = getPeer(); 9751 if (peer != null) { 9752 // The Region class has some optimizations. That's why 9753 // we should manually check whether it's empty and 9754 // substitute the object ourselves. Otherwise we end up 9755 // with some incorrect Region object with loX being 9756 // greater than the hiX for instance. 9757 if (shape.isEmpty()) { 9758 shape = Region.EMPTY_REGION; 9759 } 9760 9761 9762 // Note: the shape is not really copied/cloned. We create 9763 // the Region object ourselves, so there's no any possibility 9764 // to modify the object outside of the mixing code. 9765 // Nullifying compoundShape means that the component has normal shape 9766 // (or has no shape at all). 9767 if (shape.equals(getNormalShape())) { 9768 if (this.compoundShape == null) { 9769 return; 9770 } 9771 this.compoundShape = null; 9772 peer.applyShape(null); 9773 } else { 9774 if (shape.equals(getAppliedShape())) { 9775 return; 9776 } 9777 this.compoundShape = shape; 9778 Point compAbsolute = getLocationOnWindow(); 9779 if (mixingLog.isLoggable(PlatformLogger.FINER)) { 9780 mixingLog.fine("this = " + this + 9781 "; compAbsolute=" + compAbsolute + "; shape=" + shape); 9782 } 9783 peer.applyShape(shape.getTranslatedRegion(-compAbsolute.x, -compAbsolute.y)); 9784 } 9785 } 9786 } 9787 } 9788 9789 /** 9790 * Returns the shape previously set with applyCompoundShape(). 9791 * If the component is LW or no shape was applied yet, 9792 * the method returns the normal shape. 9793 */ 9794 private Region getAppliedShape() { 9795 checkTreeLock(); 9796 //XXX: if we allow LW components to have a shape, this must be changed 9797 return (this.compoundShape == null || isLightweight()) ? getNormalShape() : this.compoundShape; 9798 } 9799 9893 checkTreeLock(); 9894 Container parent = getContainer(); 9895 if (parent == null) { 9896 return -1; 9897 } 9898 9899 int nextBelow = parent.getComponentZOrder(this) + 1; 9900 9901 return nextBelow >= parent.getComponentCount() ? -1 : nextBelow; 9902 } 9903 9904 final boolean isNonOpaqueForMixing() { 9905 return mixingCutoutRegion != null && 9906 mixingCutoutRegion.isEmpty(); 9907 } 9908 9909 private Region calculateCurrentShape() { 9910 checkTreeLock(); 9911 Region s = getNormalShape(); 9912 9913 if (mixingLog.isLoggable(PlatformLogger.FINE)) { 9914 mixingLog.fine("this = " + this + "; normalShape=" + s); 9915 } 9916 9917 if (getContainer() != null) { 9918 Component comp = this; 9919 Container cont = comp.getContainer(); 9920 9921 while (cont != null) { 9922 for (int index = comp.getSiblingIndexAbove(); index != -1; --index) { 9923 /* It is assumed that: 9924 * 9925 * getComponent(getContainer().getComponentZOrder(comp)) == comp 9926 * 9927 * The assumption has been made according to the current 9928 * implementation of the Container class. 9929 */ 9930 Component c = cont.getComponent(index); 9931 if (c.isLightweight() && c.isShowing()) { 9932 s = s.getDifference(c.getOpaqueShape()); 9933 } 9934 } 9935 9936 if (cont.isLightweight()) { 9937 s = s.getIntersection(cont.getNormalShape()); 9938 } else { 9939 break; 9940 } 9941 9942 comp = cont; 9943 cont = cont.getContainer(); 9944 } 9945 } 9946 9947 if (mixingLog.isLoggable(PlatformLogger.FINE)) { 9948 mixingLog.fine("currentShape=" + s); 9949 } 9950 9951 return s; 9952 } 9953 9954 void applyCurrentShape() { 9955 checkTreeLock(); 9956 if (!areBoundsValid()) { 9957 if (mixingLog.isLoggable(PlatformLogger.FINE)) { 9958 mixingLog.fine("this = " + this + "; areBoundsValid = " + areBoundsValid()); 9959 } 9960 return; // Because applyCompoundShape() ignores such components anyway 9961 } 9962 if (mixingLog.isLoggable(PlatformLogger.FINE)) { 9963 mixingLog.fine("this = " + this); 9964 } 9965 applyCompoundShape(calculateCurrentShape()); 9966 } 9967 9968 final void subtractAndApplyShape(Region s) { 9969 checkTreeLock(); 9970 9971 if (mixingLog.isLoggable(PlatformLogger.FINE)) { 9972 mixingLog.fine("this = " + this + "; s=" + s); 9973 } 9974 9975 applyCompoundShape(getAppliedShape().getDifference(s)); 9976 } 9977 9978 private final void applyCurrentShapeBelowMe() { 9979 checkTreeLock(); 9980 Container parent = getContainer(); 9981 if (parent != null && parent.isShowing()) { 9982 // First, reapply shapes of my siblings 9983 parent.recursiveApplyCurrentShape(getSiblingIndexBelow()); 9984 9985 // Second, if my container is non-opaque, reapply shapes of siblings of my container 9986 Container parent2 = parent.getContainer(); 9987 while (!parent.isOpaque() && parent2 != null) { 9988 parent2.recursiveApplyCurrentShape(parent.getSiblingIndexBelow()); 9989 9990 parent = parent2; 9991 parent2 = parent.getContainer(); 9998 Container parent = getContainer(); 9999 if (parent != null && isShowing()) { 10000 Region opaqueShape = getOpaqueShape(); 10001 10002 // First, cut my siblings 10003 parent.recursiveSubtractAndApplyShape(opaqueShape, getSiblingIndexBelow()); 10004 10005 // Second, if my container is non-opaque, cut siblings of my container 10006 Container parent2 = parent.getContainer(); 10007 while (!parent.isOpaque() && parent2 != null) { 10008 parent2.recursiveSubtractAndApplyShape(opaqueShape, parent.getSiblingIndexBelow()); 10009 10010 parent = parent2; 10011 parent2 = parent.getContainer(); 10012 } 10013 } 10014 } 10015 10016 void mixOnShowing() { 10017 synchronized (getTreeLock()) { 10018 if (mixingLog.isLoggable(PlatformLogger.FINE)) { 10019 mixingLog.fine("this = " + this); 10020 } 10021 if (!isMixingNeeded()) { 10022 return; 10023 } 10024 if (isLightweight()) { 10025 subtractAndApplyShapeBelowMe(); 10026 } else { 10027 applyCurrentShape(); 10028 } 10029 } 10030 } 10031 10032 void mixOnHiding(boolean isLightweight) { 10033 // We cannot be sure that the peer exists at this point, so we need the argument 10034 // to find out whether the hiding component is (well, actually was) a LW or a HW. 10035 synchronized (getTreeLock()) { 10036 if (mixingLog.isLoggable(PlatformLogger.FINE)) { 10037 mixingLog.fine("this = " + this + "; isLightweight = " + isLightweight); 10038 } 10039 if (!isMixingNeeded()) { 10040 return; 10041 } 10042 if (isLightweight) { 10043 applyCurrentShapeBelowMe(); 10044 } 10045 } 10046 } 10047 10048 void mixOnReshaping() { 10049 synchronized (getTreeLock()) { 10050 if (mixingLog.isLoggable(PlatformLogger.FINE)) { 10051 mixingLog.fine("this = " + this); 10052 } 10053 if (!isMixingNeeded()) { 10054 return; 10055 } 10056 if (isLightweight()) { 10057 applyCurrentShapeBelowMe(); 10058 } else { 10059 applyCurrentShape(); 10060 } 10061 } 10062 } 10063 10064 void mixOnZOrderChanging(int oldZorder, int newZorder) { 10065 synchronized (getTreeLock()) { 10066 boolean becameHigher = newZorder < oldZorder; 10067 Container parent = getContainer(); 10068 10069 if (mixingLog.isLoggable(PlatformLogger.FINE)) { 10070 mixingLog.fine("this = " + this + 10071 "; oldZorder=" + oldZorder + "; newZorder=" + newZorder + "; parent=" + parent); 10072 } 10073 if (!isMixingNeeded()) { 10074 return; 10075 } 10076 if (isLightweight()) { 10077 if (becameHigher) { 10078 if (parent != null && isShowing()) { 10079 parent.recursiveSubtractAndApplyShape(getOpaqueShape(), getSiblingIndexBelow(), oldZorder); 10080 } 10081 } else { 10082 if (parent != null) { 10083 parent.recursiveApplyCurrentShape(oldZorder, newZorder); 10084 } 10085 } 10086 } else { 10087 if (becameHigher) { 10088 applyCurrentShape(); 10089 } else { 10093 for (int index = oldZorder; index < newZorder; index++) { 10094 Component c = parent.getComponent(index); 10095 if (c.isLightweight() && c.isShowing()) { 10096 shape = shape.getDifference(c.getOpaqueShape()); 10097 } 10098 } 10099 applyCompoundShape(shape); 10100 } 10101 } 10102 } 10103 } 10104 } 10105 10106 void mixOnValidating() { 10107 // This method gets overriden in the Container. Obviously, a plain 10108 // non-container components don't need to handle validation. 10109 } 10110 10111 final boolean isMixingNeeded() { 10112 if (SunToolkit.getSunAwtDisableMixing()) { 10113 if (mixingLog.isLoggable(PlatformLogger.FINEST)) { 10114 mixingLog.finest("this = " + this + "; Mixing disabled via sun.awt.disableMixing"); 10115 } 10116 return false; 10117 } 10118 if (!areBoundsValid()) { 10119 if (mixingLog.isLoggable(PlatformLogger.FINE)) { 10120 mixingLog.fine("this = " + this + "; areBoundsValid = " + areBoundsValid()); 10121 } 10122 return false; 10123 } 10124 Window window = getContainingWindow(); 10125 if (window != null) { 10126 if (!window.hasHeavyweightDescendants() || !window.hasLightweightDescendants() || window.isDisposing()) { 10127 if (mixingLog.isLoggable(PlatformLogger.FINE)) { 10128 mixingLog.fine("containing window = " + window + 10129 "; has h/w descendants = " + window.hasHeavyweightDescendants() + 10130 "; has l/w descendants = " + window.hasLightweightDescendants() + 10131 "; disposing = " + window.isDisposing()); 10132 } 10133 return false; 10134 } 10135 } else { 10136 if (mixingLog.isLoggable(PlatformLogger.FINE)) { 10137 mixingLog.fine("this = " + this + "; containing window is null"); 10138 } 10139 return false; 10140 } 10141 return true; 10142 } 10143 10144 // ****************** END OF MIXING CODE ******************************** 10145 10146 // Note that the method is overriden in the Window class, 10147 // a window doesn't need to be updated in the Z-order. 10148 void updateZOrder() { 10149 peer.setZOrder(getHWPeerAboveMe()); 10150 } 10151 10152 } | 4690 postEvent(e); 4691 } 4692 4693 /** 4694 * Dispatches an event to this component or one of its sub components. 4695 * Calls <code>processEvent</code> before returning for 1.1-style 4696 * events which have been enabled for the <code>Component</code>. 4697 * @param e the event 4698 */ 4699 public final void dispatchEvent(AWTEvent e) { 4700 dispatchEventImpl(e); 4701 } 4702 4703 @SuppressWarnings("deprecation") 4704 void dispatchEventImpl(AWTEvent e) { 4705 int id = e.getID(); 4706 4707 // Check that this component belongs to this app-context 4708 AppContext compContext = appContext; 4709 if (compContext != null && !compContext.equals(AppContext.getAppContext())) { 4710 if (eventLog.isLoggable(PlatformLogger.Level.FINE)) { 4711 eventLog.fine("Event " + e + " is being dispatched on the wrong AppContext"); 4712 } 4713 } 4714 4715 if (eventLog.isLoggable(PlatformLogger.Level.FINEST)) { 4716 eventLog.finest("{0}", e); 4717 } 4718 4719 /* 4720 * 0. Set timestamp and modifiers of current event. 4721 */ 4722 if (!(e instanceof KeyEvent)) { 4723 // Timestamp of a key event is set later in DKFM.preDispatchKeyEvent(KeyEvent). 4724 EventQueue.setCurrentEventAndMostRecentTime(e); 4725 } 4726 4727 /* 4728 * 1. Pre-dispatchers. Do any necessary retargeting/reordering here 4729 * before we notify AWTEventListeners. 4730 */ 4731 4732 if (e instanceof SunDropTargetEvent) { 4733 ((SunDropTargetEvent)e).dispatch(); 4734 return; 4735 } 4736 4737 if (!e.focusManagerIsDispatching) { 4738 // Invoke the private focus retargeting method which provides 4739 // lightweight Component support 4740 if (e.isPosted) { 4741 e = KeyboardFocusManager.retargetFocusEvent(e); 4742 e.isPosted = true; 4743 } 4744 4745 // Now, with the event properly targeted to a lightweight 4746 // descendant if necessary, invoke the public focus retargeting 4747 // and dispatching function 4748 if (KeyboardFocusManager.getCurrentKeyboardFocusManager(). 4749 dispatchEvent(e)) 4750 { 4751 return; 4752 } 4753 } 4754 if ((e instanceof FocusEvent) && focusLog.isLoggable(PlatformLogger.Level.FINEST)) { 4755 focusLog.finest("" + e); 4756 } 4757 // MouseWheel may need to be retargeted here so that 4758 // AWTEventListener sees the event go to the correct 4759 // Component. If the MouseWheelEvent needs to go to an ancestor, 4760 // the event is dispatched to the ancestor, and dispatching here 4761 // stops. 4762 if (id == MouseEvent.MOUSE_WHEEL && 4763 (!eventTypeEnabled(id)) && 4764 (peer != null && !peer.handlesWheelScrolling()) && 4765 (dispatchMouseWheelToAncestor((MouseWheelEvent)e))) 4766 { 4767 return; 4768 } 4769 4770 /* 4771 * 2. Allow the Toolkit to pass this to AWTEventListeners. 4772 */ 4773 Toolkit toolkit = Toolkit.getDefaultToolkit(); 4774 toolkit.notifyAWTEventListeners(e); 4792 * 4. Allow input methods to process the event 4793 */ 4794 if (areInputMethodsEnabled()) { 4795 // We need to pass on InputMethodEvents since some host 4796 // input method adapters send them through the Java 4797 // event queue instead of directly to the component, 4798 // and the input context also handles the Java composition window 4799 if(((e instanceof InputMethodEvent) && !(this instanceof CompositionArea)) 4800 || 4801 // Otherwise, we only pass on input and focus events, because 4802 // a) input methods shouldn't know about semantic or component-level events 4803 // b) passing on the events takes time 4804 // c) isConsumed() is always true for semantic events. 4805 (e instanceof InputEvent) || (e instanceof FocusEvent)) { 4806 InputContext inputContext = getInputContext(); 4807 4808 4809 if (inputContext != null) { 4810 inputContext.dispatchEvent(e); 4811 if (e.isConsumed()) { 4812 if ((e instanceof FocusEvent) && focusLog.isLoggable(PlatformLogger.Level.FINEST)) { 4813 focusLog.finest("3579: Skipping " + e); 4814 } 4815 return; 4816 } 4817 } 4818 } 4819 } else { 4820 // When non-clients get focus, we need to explicitly disable the native 4821 // input method. The native input method is actually not disabled when 4822 // the active/passive/peered clients loose focus. 4823 if (id == FocusEvent.FOCUS_GAINED) { 4824 InputContext inputContext = getInputContext(); 4825 if (inputContext != null && inputContext instanceof sun.awt.im.InputContext) { 4826 ((sun.awt.im.InputContext)inputContext).disableNativeIM(); 4827 } 4828 } 4829 } 4830 4831 4832 /* 4833 * 5. Pre-process any special events before delivery 4834 */ 4835 switch(id) { 4836 // Handling of the PAINT and UPDATE events is now done in the 4837 // peer's handleEvent() method so the background can be cleared 4838 // selectively for non-native components on Windows only. 4839 // - Fred.Ecks@Eng.sun.com, 5-8-98 4840 4841 case KeyEvent.KEY_PRESSED: 4842 case KeyEvent.KEY_RELEASED: 4843 Container p = (Container)((this instanceof Container) ? this : parent); 4844 if (p != null) { 4845 p.preProcessKeyEvent((KeyEvent)e); 4846 if (e.isConsumed()) { 4847 if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) { 4848 focusLog.finest("Pre-process consumed event"); 4849 } 4850 return; 4851 } 4852 } 4853 break; 4854 4855 case WindowEvent.WINDOW_CLOSING: 4856 if (toolkit instanceof WindowClosingListener) { 4857 windowClosingException = ((WindowClosingListener) 4858 toolkit).windowClosingNotify((WindowEvent)e); 4859 if (checkWindowClosingException()) { 4860 return; 4861 } 4862 } 4863 break; 4864 4865 default: 4866 break; 4867 } 4960 * If newEventsOnly is false, method is called so that ScrollPane can 4961 * override it and handle common-case mouse wheel scrolling. NOP 4962 * for Component. 4963 */ 4964 void autoProcessMouseWheel(MouseWheelEvent e) {} 4965 4966 /* 4967 * Dispatch given MouseWheelEvent to the first ancestor for which 4968 * MouseWheelEvents are enabled. 4969 * 4970 * Returns whether or not event was dispatched to an ancestor 4971 */ 4972 boolean dispatchMouseWheelToAncestor(MouseWheelEvent e) { 4973 int newX, newY; 4974 newX = e.getX() + getX(); // Coordinates take into account at least 4975 newY = e.getY() + getY(); // the cursor's position relative to this 4976 // Component (e.getX()), and this Component's 4977 // position relative to its parent. 4978 MouseWheelEvent newMWE; 4979 4980 if (eventLog.isLoggable(PlatformLogger.Level.FINEST)) { 4981 eventLog.finest("dispatchMouseWheelToAncestor"); 4982 eventLog.finest("orig event src is of " + e.getSource().getClass()); 4983 } 4984 4985 /* parent field for Window refers to the owning Window. 4986 * MouseWheelEvents should NOT be propagated into owning Windows 4987 */ 4988 synchronized (getTreeLock()) { 4989 Container anc = getParent(); 4990 while (anc != null && !anc.eventEnabled(e)) { 4991 // fix coordinates to be relative to new event source 4992 newX += anc.getX(); 4993 newY += anc.getY(); 4994 4995 if (!(anc instanceof Window)) { 4996 anc = anc.getParent(); 4997 } 4998 else { 4999 break; 5000 } 5001 } 5002 5003 if (eventLog.isLoggable(PlatformLogger.Level.FINEST)) { 5004 eventLog.finest("new event src is " + anc.getClass()); 5005 } 5006 5007 if (anc != null && anc.eventEnabled(e)) { 5008 // Change event to be from new source, with new x,y 5009 // For now, just create a new event - yucky 5010 5011 newMWE = new MouseWheelEvent(anc, // new source 5012 e.getID(), 5013 e.getWhen(), 5014 e.getModifiers(), 5015 newX, // x relative to new source 5016 newY, // y relative to new source 5017 e.getXOnScreen(), 5018 e.getYOnScreen(), 5019 e.getClickCount(), 5020 e.isPopupTrigger(), 5021 e.getScrollType(), 5022 e.getScrollAmount(), 5023 e.getWheelRotation(), 5483 synchronized (this) { 5484 notifyAncestors = 5485 (hierarchyBoundsListener != null && 5486 (eventMask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) == 0); 5487 hierarchyBoundsListener = 5488 AWTEventMulticaster.remove(hierarchyBoundsListener, l); 5489 notifyAncestors = (notifyAncestors && 5490 hierarchyBoundsListener == null); 5491 } 5492 if (notifyAncestors) { 5493 synchronized (getTreeLock()) { 5494 adjustListeningChildrenOnParent( 5495 AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK, -1); 5496 } 5497 } 5498 } 5499 5500 // Should only be called while holding the tree lock 5501 int numListening(long mask) { 5502 // One mask or the other, but not neither or both. 5503 if (eventLog.isLoggable(PlatformLogger.Level.FINE)) { 5504 if ((mask != AWTEvent.HIERARCHY_EVENT_MASK) && 5505 (mask != AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK)) 5506 { 5507 eventLog.fine("Assertion failed"); 5508 } 5509 } 5510 if ((mask == AWTEvent.HIERARCHY_EVENT_MASK && 5511 (hierarchyListener != null || 5512 (eventMask & AWTEvent.HIERARCHY_EVENT_MASK) != 0)) || 5513 (mask == AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK && 5514 (hierarchyBoundsListener != null || 5515 (eventMask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0))) { 5516 return 1; 5517 } else { 5518 return 0; 5519 } 5520 } 5521 5522 // Should only be called while holding tree lock 5523 int countHierarchyMembers() { 5524 return 1; 5525 } 5526 // Should only be called while holding the tree lock 5527 int createHierarchyEvents(int id, Component changed, 5528 Container changedParent, long changeFlags, 5529 boolean enabledOnToolkit) { 5530 switch (id) { 5531 case HierarchyEvent.HIERARCHY_CHANGED: 5532 if (hierarchyListener != null || 5533 (eventMask & AWTEvent.HIERARCHY_EVENT_MASK) != 0 || 5534 enabledOnToolkit) { 5535 HierarchyEvent e = new HierarchyEvent(this, id, changed, 5536 changedParent, 5537 changeFlags); 5538 dispatchEvent(e); 5539 return 1; 5540 } 5541 break; 5542 case HierarchyEvent.ANCESTOR_MOVED: 5543 case HierarchyEvent.ANCESTOR_RESIZED: 5544 if (eventLog.isLoggable(PlatformLogger.Level.FINE)) { 5545 if (changeFlags != 0) { 5546 eventLog.fine("Assertion (changeFlags == 0) failed"); 5547 } 5548 } 5549 if (hierarchyBoundsListener != null || 5550 (eventMask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0 || 5551 enabledOnToolkit) { 5552 HierarchyEvent e = new HierarchyEvent(this, id, changed, 5553 changedParent); 5554 dispatchEvent(e); 5555 return 1; 5556 } 5557 break; 5558 default: 5559 // assert false 5560 if (eventLog.isLoggable(PlatformLogger.Level.FINE)) { 5561 eventLog.fine("This code must never be reached"); 5562 } 5563 break; 5564 } 5565 return 0; 5566 } 5567 5568 /** 5569 * Returns an array of all the hierarchy bounds listeners 5570 * registered on this component. 5571 * 5572 * @return all of this component's <code>HierarchyBoundsListener</code>s 5573 * or an empty array if no hierarchy bounds 5574 * listeners are currently registered 5575 * 5576 * @see #addHierarchyBoundsListener 5577 * @see #removeHierarchyBoundsListener 5578 * @since 1.4 5579 */ 5580 public synchronized HierarchyBoundsListener[] getHierarchyBoundsListeners() { 7626 if (currentEvent instanceof MouseEvent && 7627 SunToolkit.isSystemGenerated(currentEvent)) 7628 { 7629 // 2) Sanity check: if the mouse event component source belongs to the same containing window. 7630 Component source = ((MouseEvent)currentEvent).getComponent(); 7631 if (source == null || source.getContainingWindow() == getContainingWindow()) { 7632 focusLog.finest("requesting focus by mouse event \"in window\""); 7633 7634 // If both the conditions are fulfilled the focus request should be strictly 7635 // bounded by the toplevel window. It's assumed that the mouse event activates 7636 // the window (if it wasn't active) and this makes it possible for a focus 7637 // request with a strong in-window requirement to change focus in the bounds 7638 // of the toplevel. If, by any means, due to asynchronous nature of the event 7639 // dispatching mechanism, the window happens to be natively inactive by the time 7640 // this focus request is eventually handled, it should not re-activate the 7641 // toplevel. Otherwise the result may not meet user expectations. See 6981400. 7642 focusedWindowChangeAllowed = false; 7643 } 7644 } 7645 if (!isRequestFocusAccepted(temporary, focusedWindowChangeAllowed, cause)) { 7646 if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) { 7647 focusLog.finest("requestFocus is not accepted"); 7648 } 7649 return false; 7650 } 7651 // Update most-recent map 7652 KeyboardFocusManager.setMostRecentFocusOwner(this); 7653 7654 Component window = this; 7655 while ( (window != null) && !(window instanceof Window)) { 7656 if (!window.isVisible()) { 7657 if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) { 7658 focusLog.finest("component is recurively invisible"); 7659 } 7660 return false; 7661 } 7662 window = window.parent; 7663 } 7664 7665 ComponentPeer peer = this.peer; 7666 Component heavyweight = (peer instanceof LightweightPeer) 7667 ? getNativeContainer() : this; 7668 if (heavyweight == null || !heavyweight.isVisible()) { 7669 if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) { 7670 focusLog.finest("Component is not a part of visible hierarchy"); 7671 } 7672 return false; 7673 } 7674 peer = heavyweight.peer; 7675 if (peer == null) { 7676 if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) { 7677 focusLog.finest("Peer is null"); 7678 } 7679 return false; 7680 } 7681 7682 // Focus this Component 7683 long time = 0; 7684 if (EventQueue.isDispatchThread()) { 7685 time = Toolkit.getEventQueue().getMostRecentKeyEventTime(); 7686 } else { 7687 // A focus request made from outside EDT should not be associated with any event 7688 // and so its time stamp is simply set to the current time. 7689 time = System.currentTimeMillis(); 7690 } 7691 7692 boolean success = peer.requestFocus 7693 (this, temporary, focusedWindowChangeAllowed, time, cause); 7694 if (!success) { 7695 KeyboardFocusManager.getCurrentKeyboardFocusManager 7696 (appContext).dequeueKeyEvents(time, this); 7697 if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) { 7698 focusLog.finest("Peer request failed"); 7699 } 7700 } else { 7701 if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) { 7702 focusLog.finest("Pass for " + this); 7703 } 7704 } 7705 return success; 7706 } 7707 7708 private boolean isRequestFocusAccepted(boolean temporary, 7709 boolean focusedWindowChangeAllowed, 7710 CausedFocusEvent.Cause cause) 7711 { 7712 if (!isFocusable() || !isVisible()) { 7713 if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) { 7714 focusLog.finest("Not focusable or not visible"); 7715 } 7716 return false; 7717 } 7718 7719 ComponentPeer peer = this.peer; 7720 if (peer == null) { 7721 if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) { 7722 focusLog.finest("peer is null"); 7723 } 7724 return false; 7725 } 7726 7727 Window window = getContainingWindow(); 7728 if (window == null || !window.isFocusableWindow()) { 7729 if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) { 7730 focusLog.finest("Component doesn't have toplevel"); 7731 } 7732 return false; 7733 } 7734 7735 // We have passed all regular checks for focus request, 7736 // now let's call RequestFocusController and see what it says. 7737 Component focusOwner = KeyboardFocusManager.getMostRecentFocusOwner(window); 7738 if (focusOwner == null) { 7739 // sometimes most recent focus owner may be null, but focus owner is not 7740 // e.g. we reset most recent focus owner if user removes focus owner 7741 focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); 7742 if (focusOwner != null && focusOwner.getContainingWindow() != window) { 7743 focusOwner = null; 7744 } 7745 } 7746 7747 if (focusOwner == this || focusOwner == null) { 7748 // Controller is supposed to verify focus transfers and for this it 7749 // should know both from and to components. And it shouldn't verify 7750 // transfers from when these components are equal. 7751 if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) { 7752 focusLog.finest("focus owner is null or this"); 7753 } 7754 return true; 7755 } 7756 7757 if (CausedFocusEvent.Cause.ACTIVATION == cause) { 7758 // we shouldn't call RequestFocusController in case we are 7759 // in activation. We do request focus on component which 7760 // has got temporary focus lost and then on component which is 7761 // most recent focus owner. But most recent focus owner can be 7762 // changed by requestFocsuXXX() call only, so this transfer has 7763 // been already approved. 7764 if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) { 7765 focusLog.finest("cause is activation"); 7766 } 7767 return true; 7768 } 7769 7770 boolean ret = Component.requestFocusController.acceptRequestFocus(focusOwner, 7771 this, 7772 temporary, 7773 focusedWindowChangeAllowed, 7774 cause); 7775 if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) { 7776 focusLog.finest("RequestFocusController returns {0}", ret); 7777 } 7778 7779 return ret; 7780 } 7781 7782 private static RequestFocusController requestFocusController = new DummyRequestFocusController(); 7783 7784 // Swing access this method through reflection to implement InputVerifier's functionality. 7785 // Perhaps, we should make this method public (later ;) 7786 private static class DummyRequestFocusController implements RequestFocusController { 7787 public boolean acceptRequestFocus(Component from, Component to, 7788 boolean temporary, boolean focusedWindowChangeAllowed, 7789 CausedFocusEvent.Cause cause) 7790 { 7791 return true; 7792 } 7793 }; 7794 7795 synchronized static void setRequestFocusController(RequestFocusController requestController) 7847 /** 7848 * Transfers the focus to the next component, as though this Component were 7849 * the focus owner. 7850 * @see #requestFocus() 7851 * @since JDK1.1 7852 */ 7853 public void transferFocus() { 7854 nextFocus(); 7855 } 7856 7857 /** 7858 * @deprecated As of JDK version 1.1, 7859 * replaced by transferFocus(). 7860 */ 7861 @Deprecated 7862 public void nextFocus() { 7863 transferFocus(false); 7864 } 7865 7866 boolean transferFocus(boolean clearOnFailure) { 7867 if (focusLog.isLoggable(PlatformLogger.Level.FINER)) { 7868 focusLog.finer("clearOnFailure = " + clearOnFailure); 7869 } 7870 Component toFocus = getNextFocusCandidate(); 7871 boolean res = false; 7872 if (toFocus != null && !toFocus.isFocusOwner() && toFocus != this) { 7873 res = toFocus.requestFocusInWindow(CausedFocusEvent.Cause.TRAVERSAL_FORWARD); 7874 } 7875 if (clearOnFailure && !res) { 7876 if (focusLog.isLoggable(PlatformLogger.Level.FINER)) { 7877 focusLog.finer("clear global focus owner"); 7878 } 7879 KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwnerPriv(); 7880 } 7881 if (focusLog.isLoggable(PlatformLogger.Level.FINER)) { 7882 focusLog.finer("returning result: " + res); 7883 } 7884 return res; 7885 } 7886 7887 final Component getNextFocusCandidate() { 7888 Container rootAncestor = getTraversalRoot(); 7889 Component comp = this; 7890 while (rootAncestor != null && 7891 !(rootAncestor.isShowing() && rootAncestor.canBeFocusOwner())) 7892 { 7893 comp = rootAncestor; 7894 rootAncestor = comp.getFocusCycleRootAncestor(); 7895 } 7896 if (focusLog.isLoggable(PlatformLogger.Level.FINER)) { 7897 focusLog.finer("comp = " + comp + ", root = " + rootAncestor); 7898 } 7899 Component candidate = null; 7900 if (rootAncestor != null) { 7901 FocusTraversalPolicy policy = rootAncestor.getFocusTraversalPolicy(); 7902 Component toFocus = policy.getComponentAfter(rootAncestor, comp); 7903 if (focusLog.isLoggable(PlatformLogger.Level.FINER)) { 7904 focusLog.finer("component after is " + toFocus); 7905 } 7906 if (toFocus == null) { 7907 toFocus = policy.getDefaultComponent(rootAncestor); 7908 if (focusLog.isLoggable(PlatformLogger.Level.FINER)) { 7909 focusLog.finer("default component is " + toFocus); 7910 } 7911 } 7912 if (toFocus == null) { 7913 Applet applet = EmbeddedFrame.getAppletIfAncestorOf(this); 7914 if (applet != null) { 7915 toFocus = applet; 7916 } 7917 } 7918 candidate = toFocus; 7919 } 7920 if (focusLog.isLoggable(PlatformLogger.Level.FINER)) { 7921 focusLog.finer("Focus transfer candidate: " + candidate); 7922 } 7923 return candidate; 7924 } 7925 7926 /** 7927 * Transfers the focus to the previous component, as though this Component 7928 * were the focus owner. 7929 * @see #requestFocus() 7930 * @since 1.4 7931 */ 7932 public void transferFocusBackward() { 7933 transferFocusBackward(false); 7934 } 7935 7936 boolean transferFocusBackward(boolean clearOnFailure) { 7937 Container rootAncestor = getTraversalRoot(); 7938 Component comp = this; 7939 while (rootAncestor != null && 7940 !(rootAncestor.isShowing() && rootAncestor.canBeFocusOwner())) 7941 { 7942 comp = rootAncestor; 7943 rootAncestor = comp.getFocusCycleRootAncestor(); 7944 } 7945 boolean res = false; 7946 if (rootAncestor != null) { 7947 FocusTraversalPolicy policy = rootAncestor.getFocusTraversalPolicy(); 7948 Component toFocus = policy.getComponentBefore(rootAncestor, comp); 7949 if (toFocus == null) { 7950 toFocus = policy.getDefaultComponent(rootAncestor); 7951 } 7952 if (toFocus != null) { 7953 res = toFocus.requestFocusInWindow(CausedFocusEvent.Cause.TRAVERSAL_BACKWARD); 7954 } 7955 } 7956 if (clearOnFailure && !res) { 7957 if (focusLog.isLoggable(PlatformLogger.Level.FINER)) { 7958 focusLog.finer("clear global focus owner"); 7959 } 7960 KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwnerPriv(); 7961 } 7962 if (focusLog.isLoggable(PlatformLogger.Level.FINER)) { 7963 focusLog.finer("returning result: " + res); 7964 } 7965 return res; 7966 } 7967 7968 /** 7969 * Transfers the focus up one focus traversal cycle. Typically, the focus 7970 * owner is set to this Component's focus cycle root, and the current focus 7971 * cycle root is set to the new focus owner's focus cycle root. If, 7972 * however, this Component's focus cycle root is a Window, then the focus 7973 * owner is set to the focus cycle root's default Component to focus, and 7974 * the current focus cycle root is unchanged. 7975 * 7976 * @see #requestFocus() 7977 * @see Container#isFocusCycleRoot() 7978 * @see Container#setFocusCycleRoot(boolean) 7979 * @since 1.4 7980 */ 7981 public void transferFocusUpCycle() { 7982 Container rootAncestor; 9723 * Check whether we can trust the current bounds of the component. 9724 * The return value of false indicates that the container of the 9725 * component is invalid, and therefore needs to be layed out, which would 9726 * probably mean changing the bounds of its children. 9727 * Null-layout of the container or absence of the container mean 9728 * the bounds of the component are final and can be trusted. 9729 */ 9730 final boolean areBoundsValid() { 9731 Container cont = getContainer(); 9732 return cont == null || cont.isValid() || cont.getLayout() == null; 9733 } 9734 9735 /** 9736 * Applies the shape to the component 9737 * @param shape Shape to be applied to the component 9738 */ 9739 void applyCompoundShape(Region shape) { 9740 checkTreeLock(); 9741 9742 if (!areBoundsValid()) { 9743 if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) { 9744 mixingLog.fine("this = " + this + "; areBoundsValid = " + areBoundsValid()); 9745 } 9746 return; 9747 } 9748 9749 if (!isLightweight()) { 9750 ComponentPeer peer = getPeer(); 9751 if (peer != null) { 9752 // The Region class has some optimizations. That's why 9753 // we should manually check whether it's empty and 9754 // substitute the object ourselves. Otherwise we end up 9755 // with some incorrect Region object with loX being 9756 // greater than the hiX for instance. 9757 if (shape.isEmpty()) { 9758 shape = Region.EMPTY_REGION; 9759 } 9760 9761 9762 // Note: the shape is not really copied/cloned. We create 9763 // the Region object ourselves, so there's no any possibility 9764 // to modify the object outside of the mixing code. 9765 // Nullifying compoundShape means that the component has normal shape 9766 // (or has no shape at all). 9767 if (shape.equals(getNormalShape())) { 9768 if (this.compoundShape == null) { 9769 return; 9770 } 9771 this.compoundShape = null; 9772 peer.applyShape(null); 9773 } else { 9774 if (shape.equals(getAppliedShape())) { 9775 return; 9776 } 9777 this.compoundShape = shape; 9778 Point compAbsolute = getLocationOnWindow(); 9779 if (mixingLog.isLoggable(PlatformLogger.Level.FINER)) { 9780 mixingLog.fine("this = " + this + 9781 "; compAbsolute=" + compAbsolute + "; shape=" + shape); 9782 } 9783 peer.applyShape(shape.getTranslatedRegion(-compAbsolute.x, -compAbsolute.y)); 9784 } 9785 } 9786 } 9787 } 9788 9789 /** 9790 * Returns the shape previously set with applyCompoundShape(). 9791 * If the component is LW or no shape was applied yet, 9792 * the method returns the normal shape. 9793 */ 9794 private Region getAppliedShape() { 9795 checkTreeLock(); 9796 //XXX: if we allow LW components to have a shape, this must be changed 9797 return (this.compoundShape == null || isLightweight()) ? getNormalShape() : this.compoundShape; 9798 } 9799 9893 checkTreeLock(); 9894 Container parent = getContainer(); 9895 if (parent == null) { 9896 return -1; 9897 } 9898 9899 int nextBelow = parent.getComponentZOrder(this) + 1; 9900 9901 return nextBelow >= parent.getComponentCount() ? -1 : nextBelow; 9902 } 9903 9904 final boolean isNonOpaqueForMixing() { 9905 return mixingCutoutRegion != null && 9906 mixingCutoutRegion.isEmpty(); 9907 } 9908 9909 private Region calculateCurrentShape() { 9910 checkTreeLock(); 9911 Region s = getNormalShape(); 9912 9913 if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) { 9914 mixingLog.fine("this = " + this + "; normalShape=" + s); 9915 } 9916 9917 if (getContainer() != null) { 9918 Component comp = this; 9919 Container cont = comp.getContainer(); 9920 9921 while (cont != null) { 9922 for (int index = comp.getSiblingIndexAbove(); index != -1; --index) { 9923 /* It is assumed that: 9924 * 9925 * getComponent(getContainer().getComponentZOrder(comp)) == comp 9926 * 9927 * The assumption has been made according to the current 9928 * implementation of the Container class. 9929 */ 9930 Component c = cont.getComponent(index); 9931 if (c.isLightweight() && c.isShowing()) { 9932 s = s.getDifference(c.getOpaqueShape()); 9933 } 9934 } 9935 9936 if (cont.isLightweight()) { 9937 s = s.getIntersection(cont.getNormalShape()); 9938 } else { 9939 break; 9940 } 9941 9942 comp = cont; 9943 cont = cont.getContainer(); 9944 } 9945 } 9946 9947 if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) { 9948 mixingLog.fine("currentShape=" + s); 9949 } 9950 9951 return s; 9952 } 9953 9954 void applyCurrentShape() { 9955 checkTreeLock(); 9956 if (!areBoundsValid()) { 9957 if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) { 9958 mixingLog.fine("this = " + this + "; areBoundsValid = " + areBoundsValid()); 9959 } 9960 return; // Because applyCompoundShape() ignores such components anyway 9961 } 9962 if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) { 9963 mixingLog.fine("this = " + this); 9964 } 9965 applyCompoundShape(calculateCurrentShape()); 9966 } 9967 9968 final void subtractAndApplyShape(Region s) { 9969 checkTreeLock(); 9970 9971 if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) { 9972 mixingLog.fine("this = " + this + "; s=" + s); 9973 } 9974 9975 applyCompoundShape(getAppliedShape().getDifference(s)); 9976 } 9977 9978 private final void applyCurrentShapeBelowMe() { 9979 checkTreeLock(); 9980 Container parent = getContainer(); 9981 if (parent != null && parent.isShowing()) { 9982 // First, reapply shapes of my siblings 9983 parent.recursiveApplyCurrentShape(getSiblingIndexBelow()); 9984 9985 // Second, if my container is non-opaque, reapply shapes of siblings of my container 9986 Container parent2 = parent.getContainer(); 9987 while (!parent.isOpaque() && parent2 != null) { 9988 parent2.recursiveApplyCurrentShape(parent.getSiblingIndexBelow()); 9989 9990 parent = parent2; 9991 parent2 = parent.getContainer(); 9998 Container parent = getContainer(); 9999 if (parent != null && isShowing()) { 10000 Region opaqueShape = getOpaqueShape(); 10001 10002 // First, cut my siblings 10003 parent.recursiveSubtractAndApplyShape(opaqueShape, getSiblingIndexBelow()); 10004 10005 // Second, if my container is non-opaque, cut siblings of my container 10006 Container parent2 = parent.getContainer(); 10007 while (!parent.isOpaque() && parent2 != null) { 10008 parent2.recursiveSubtractAndApplyShape(opaqueShape, parent.getSiblingIndexBelow()); 10009 10010 parent = parent2; 10011 parent2 = parent.getContainer(); 10012 } 10013 } 10014 } 10015 10016 void mixOnShowing() { 10017 synchronized (getTreeLock()) { 10018 if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) { 10019 mixingLog.fine("this = " + this); 10020 } 10021 if (!isMixingNeeded()) { 10022 return; 10023 } 10024 if (isLightweight()) { 10025 subtractAndApplyShapeBelowMe(); 10026 } else { 10027 applyCurrentShape(); 10028 } 10029 } 10030 } 10031 10032 void mixOnHiding(boolean isLightweight) { 10033 // We cannot be sure that the peer exists at this point, so we need the argument 10034 // to find out whether the hiding component is (well, actually was) a LW or a HW. 10035 synchronized (getTreeLock()) { 10036 if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) { 10037 mixingLog.fine("this = " + this + "; isLightweight = " + isLightweight); 10038 } 10039 if (!isMixingNeeded()) { 10040 return; 10041 } 10042 if (isLightweight) { 10043 applyCurrentShapeBelowMe(); 10044 } 10045 } 10046 } 10047 10048 void mixOnReshaping() { 10049 synchronized (getTreeLock()) { 10050 if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) { 10051 mixingLog.fine("this = " + this); 10052 } 10053 if (!isMixingNeeded()) { 10054 return; 10055 } 10056 if (isLightweight()) { 10057 applyCurrentShapeBelowMe(); 10058 } else { 10059 applyCurrentShape(); 10060 } 10061 } 10062 } 10063 10064 void mixOnZOrderChanging(int oldZorder, int newZorder) { 10065 synchronized (getTreeLock()) { 10066 boolean becameHigher = newZorder < oldZorder; 10067 Container parent = getContainer(); 10068 10069 if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) { 10070 mixingLog.fine("this = " + this + 10071 "; oldZorder=" + oldZorder + "; newZorder=" + newZorder + "; parent=" + parent); 10072 } 10073 if (!isMixingNeeded()) { 10074 return; 10075 } 10076 if (isLightweight()) { 10077 if (becameHigher) { 10078 if (parent != null && isShowing()) { 10079 parent.recursiveSubtractAndApplyShape(getOpaqueShape(), getSiblingIndexBelow(), oldZorder); 10080 } 10081 } else { 10082 if (parent != null) { 10083 parent.recursiveApplyCurrentShape(oldZorder, newZorder); 10084 } 10085 } 10086 } else { 10087 if (becameHigher) { 10088 applyCurrentShape(); 10089 } else { 10093 for (int index = oldZorder; index < newZorder; index++) { 10094 Component c = parent.getComponent(index); 10095 if (c.isLightweight() && c.isShowing()) { 10096 shape = shape.getDifference(c.getOpaqueShape()); 10097 } 10098 } 10099 applyCompoundShape(shape); 10100 } 10101 } 10102 } 10103 } 10104 } 10105 10106 void mixOnValidating() { 10107 // This method gets overriden in the Container. Obviously, a plain 10108 // non-container components don't need to handle validation. 10109 } 10110 10111 final boolean isMixingNeeded() { 10112 if (SunToolkit.getSunAwtDisableMixing()) { 10113 if (mixingLog.isLoggable(PlatformLogger.Level.FINEST)) { 10114 mixingLog.finest("this = " + this + "; Mixing disabled via sun.awt.disableMixing"); 10115 } 10116 return false; 10117 } 10118 if (!areBoundsValid()) { 10119 if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) { 10120 mixingLog.fine("this = " + this + "; areBoundsValid = " + areBoundsValid()); 10121 } 10122 return false; 10123 } 10124 Window window = getContainingWindow(); 10125 if (window != null) { 10126 if (!window.hasHeavyweightDescendants() || !window.hasLightweightDescendants() || window.isDisposing()) { 10127 if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) { 10128 mixingLog.fine("containing window = " + window + 10129 "; has h/w descendants = " + window.hasHeavyweightDescendants() + 10130 "; has l/w descendants = " + window.hasLightweightDescendants() + 10131 "; disposing = " + window.isDisposing()); 10132 } 10133 return false; 10134 } 10135 } else { 10136 if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) { 10137 mixingLog.fine("this = " + this + "; containing window is null"); 10138 } 10139 return false; 10140 } 10141 return true; 10142 } 10143 10144 // ****************** END OF MIXING CODE ******************************** 10145 10146 // Note that the method is overriden in the Window class, 10147 // a window doesn't need to be updated in the Z-order. 10148 void updateZOrder() { 10149 peer.setZOrder(getHWPeerAboveMe()); 10150 } 10151 10152 } |