# HG changeset patch # User anthony # Date 1206000556 -10800 # Node ID 11eb29307cfb35658769dd6c4ee7d70420ec801d # Parent f995b9c9c5fab22259e7b5681a027e00a90ff256 4993545: NativeInLightFixer adds asynchronousity Summary: All the hooks related to the NativeInLightFixer have been moved to the HW/LW mixing handling methods. The NativeInLightFixer itself has been removed. Reviewed-by: son, alexp diff -r f995b9c9c5fa -r 11eb29307cfb jdk/src/share/classes/java/awt/Component.java --- a/jdk/src/share/classes/java/awt/Component.java Tue Mar 18 16:19:03 2008 +0300 +++ b/jdk/src/share/classes/java/awt/Component.java Thu Mar 20 11:09:16 2008 +0300 @@ -6492,7 +6492,7 @@ // will need some help. Container parent = this.parent; if (parent != null && parent.peer instanceof LightweightPeer) { - nativeInLightFixer = new NativeInLightFixer(); + relocateComponent(); } } invalidate(); @@ -6603,10 +6603,6 @@ } } - if (nativeInLightFixer != null) { - nativeInLightFixer.uninstall(); - } - ComponentPeer p = peer; if (p != null) { boolean isLightweight = isLightweight(); @@ -8514,8 +8510,6 @@ setComponentOrientation(orientation); } - transient NativeInLightFixer nativeInLightFixer; - /** * Checks that this component meets the prerequesites to be focus owner: * - it is enabled, visible, focusable @@ -8541,188 +8535,25 @@ } /** - * This odd class is to help out a native component that has been - * embedded in a lightweight component. Moving lightweight - * components around and changing their visibility is not seen - * by the native window system. This is a feature for lightweights, - * but a problem for native components that depend upon the - * lightweights. An instance of this class listens to the lightweight - * parents of an associated native component (the outer class). - * - * @author Timothy Prinzing - */ - final class NativeInLightFixer implements ComponentListener, ContainerListener { - - NativeInLightFixer() { - lightParents = new Vector(); - install(parent); - } - - void install(Container parent) { - lightParents.clear(); - Container p = parent; - boolean isLwParentsVisible = true; - // stash a reference to the components that are being observed so that - // we can reliably remove ourself as a listener later. - for (; p.peer instanceof LightweightPeer; p = p.parent) { - - // register listeners and stash a reference - p.addComponentListener(this); - p.addContainerListener(this); - lightParents.addElement(p); - isLwParentsVisible &= p.isVisible(); - } - // register with the native host (native parent of associated native) - // to get notified if the top-level lightweight is removed. - nativeHost = p; - p.addContainerListener(this); - - // kick start the fixup. Since the event isn't looked at - // we can simulate movement notification. - componentMoved(null); - if (!isLwParentsVisible) { - synchronized (getTreeLock()) { - if (peer != null) { - peer.hide(); - } - } - } - } - - void uninstall() { - if (nativeHost != null) { - removeReferences(); - } - } - - // --- ComponentListener ------------------------------------------- - - /** - * Invoked when one of the lightweight parents has been resized. - * This doesn't change the position of the native child so it - * is ignored. - */ - public void componentResized(ComponentEvent e) { - } - - /** - * Invoked when one of the lightweight parents has been moved. - * The native peer must be told of the new position which is - * relative to the native container that is hosting the - * lightweight components. - */ - public void componentMoved(ComponentEvent e) { - synchronized (getTreeLock()) { - int nativeX = x; - int nativeY = y; - for(Component c = parent; (c != null) && - (c.peer instanceof LightweightPeer); - c = c.parent) { - - nativeX += c.x; - nativeY += c.y; - } - if (peer != null) { - peer.setBounds(nativeX, nativeY, width, height, - ComponentPeer.SET_LOCATION); - } - } - } - - /** - * Invoked when a lightweight parent component has been - * shown. The associated native component must also be - * shown if it hasn't had an overriding hide done on it. - */ - public void componentShown(ComponentEvent e) { - if (shouldShow()) { - synchronized (getTreeLock()) { - if (peer != null) { - peer.show(); - } - } - } - } - - /** - * Invoked when one of the lightweight parents become visible. - * Returns true if component and all its lightweight - * parents are visible. - */ - private boolean shouldShow() { - boolean isLwParentsVisible = visible; - for (int i = lightParents.size() - 1; - i >= 0 && isLwParentsVisible; - i--) + * Fix the location of the HW component in a LW container hierarchy. + */ + final void relocateComponent() { + synchronized (getTreeLock()) { + if (peer == null) { + return; + } + int nativeX = x; + int nativeY = y; + for (Component cont = getContainer(); + cont != null && cont.isLightweight(); + cont = cont.getContainer()) { - isLwParentsVisible &= - ((Container) lightParents.elementAt(i)).isVisible(); - } - return isLwParentsVisible; - } - - /** - * Invoked when component has been hidden. - */ - public void componentHidden(ComponentEvent e) { - if (visible) { - synchronized (getTreeLock()) { - if (peer != null) { - peer.hide(); - } - } - } - } - - // --- ContainerListener ------------------------------------ - - /** - * Invoked when a component has been added to a lightweight - * parent. This doesn't effect the native component. - */ - public void componentAdded(ContainerEvent e) { - } - - /** - * Invoked when a lightweight parent has been removed. - * This means the services of this listener are no longer - * required and it should remove all references (ie - * registered listeners). - */ - public void componentRemoved(ContainerEvent e) { - Component c = e.getChild(); - if (c == Component.this) { - removeReferences(); - } else { - int n = lightParents.size(); - for (int i = 0; i < n; i++) { - Container p = (Container) lightParents.elementAt(i); - if (p == c) { - removeReferences(); - break; - } - } - } - } - - /** - * Removes references to this object so it can be - * garbage collected. - */ - void removeReferences() { - int n = lightParents.size(); - for (int i = 0; i < n; i++) { - Container c = (Container) lightParents.elementAt(i); - c.removeComponentListener(this); - c.removeContainerListener(this); - } - nativeHost.removeContainerListener(this); - lightParents.clear(); - nativeHost = null; - } - - Vector lightParents; - Container nativeHost; + nativeX += cont.x; + nativeY += cont.y; + } + peer.setBounds(nativeX, nativeY, width, height, + ComponentPeer.SET_LOCATION); + } } /** diff -r f995b9c9c5fa -r 11eb29307cfb jdk/src/share/classes/java/awt/Container.java --- a/jdk/src/share/classes/java/awt/Container.java Tue Mar 18 16:19:03 2008 +0300 +++ b/jdk/src/share/classes/java/awt/Container.java Thu Mar 20 11:09:16 2008 +0300 @@ -832,16 +832,8 @@ } if (!comp.isLightweight() && isLightweight()) { // If component is heavyweight and one of the containers is lightweight - // some NativeInLightFixer activity should be performed - if (!curParent.isLightweight()) { - // Moving from heavyweight container to lightweight container - should create NativeInLightFixer - // since addNotify does this - comp.nativeInLightFixer = new NativeInLightFixer(); - } else { - // Component already has NativeInLightFixer - just reinstall it - // because hierarchy changed and he needs to rebuild list of parents to listen. - comp.nativeInLightFixer.install(this); - } + // the location of the component should be fixed. + comp.relocateComponent(); } } } @@ -3953,6 +3945,83 @@ } } + private void recursiveShowHeavyweightChildren() { + if (!hasHeavyweightDescendants() || !isVisible()) { + return; + } + for (int index = 0; index < getComponentCount(); index++) { + Component comp = getComponent(index); + if (comp.isLightweight()) { + if (comp instanceof Container) { + ((Container)comp).recursiveShowHeavyweightChildren(); + } + } else { + if (comp.isVisible()) { + ComponentPeer peer = comp.getPeer(); + if (peer != null) { + peer.show(); + } + } + } + } + } + + private void recursiveHideHeavyweightChildren() { + if (!hasHeavyweightDescendants()) { + return; + } + for (int index = 0; index < getComponentCount(); index++) { + Component comp = getComponent(index); + if (comp.isLightweight()) { + if (comp instanceof Container) { + ((Container)comp).recursiveHideHeavyweightChildren(); + } + } else { + if (comp.isVisible()) { + ComponentPeer peer = comp.getPeer(); + if (peer != null) { + peer.hide(); + } + } + } + } + } + + private void recursiveRelocateHeavyweightChildren(Point origin) { + for (int index = 0; index < getComponentCount(); index++) { + Component comp = getComponent(index); + if (comp.isLightweight()) { + if (comp instanceof Container && + ((Container)comp).hasHeavyweightDescendants()) + { + final Point newOrigin = new Point(origin); + newOrigin.translate(comp.getX(), comp.getY()); + ((Container)comp).recursiveRelocateHeavyweightChildren(newOrigin); + } + } else { + ComponentPeer peer = comp.getPeer(); + if (peer != null) { + peer.setBounds(origin.x + comp.getX(), origin.y + comp.getY(), + comp.getWidth(), comp.getHeight(), + ComponentPeer.SET_LOCATION); + } + } + } + } + + /* + * Consider the heavyweight container hides or shows the HW descendants + * automatically. Therefore we care of LW containers' visibility only. + */ + private boolean isRecursivelyVisibleUpToHeavyweightContainer() { + if (!isLightweight()) { + return true; + } + return isVisible() && (getContainer() == null || + getContainer().isRecursivelyVisibleUpToHeavyweightContainer()); + } + + @Override void mixOnShowing() { synchronized (getTreeLock()) { if (mixingLog.isLoggable(Level.FINE)) { @@ -3961,6 +4030,10 @@ boolean isLightweight = isLightweight(); + if (isLightweight && isRecursivelyVisibleUpToHeavyweightContainer()) { + recursiveShowHeavyweightChildren(); + } + if (!isLightweight || (isLightweight && hasHeavyweightDescendants())) { recursiveApplyCurrentShape(); } @@ -3969,6 +4042,42 @@ } } + @Override + void mixOnHiding(boolean isLightweight) { + synchronized (getTreeLock()) { + if (mixingLog.isLoggable(Level.FINE)) { + mixingLog.fine("this = " + this + + "; isLightweight=" + isLightweight); + } + if (isLightweight) { + recursiveHideHeavyweightChildren(); + } + super.mixOnHiding(isLightweight); + } + } + + @Override + void mixOnReshaping() { + synchronized (getTreeLock()) { + if (mixingLog.isLoggable(Level.FINE)) { + mixingLog.fine("this = " + this); + } + if (isLightweight() && hasHeavyweightDescendants()) { + final Point origin = new Point(getX(), getY()); + for (Container cont = getContainer(); + cont != null && cont.isLightweight(); + cont = cont.getContainer()) + { + origin.translate(cont.getX(), cont.getY()); + } + + recursiveRelocateHeavyweightChildren(origin); + } + super.mixOnReshaping(); + } + } + + @Override void mixOnZOrderChanging(int oldZorder, int newZorder) { synchronized (getTreeLock()) { if (mixingLog.isLoggable(Level.FINE)) {