--- old/src/macosx/classes/sun/lwawt/LWComponentPeer.java 2014-02-04 15:17:29.426049700 +0400 +++ new/src/macosx/classes/sun/lwawt/LWComponentPeer.java 2014-02-04 15:17:29.156049300 +0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,9 +42,6 @@ import java.awt.peer.KeyboardFocusManagerPeer; import java.util.concurrent.atomic.AtomicBoolean; -import java.lang.reflect.Field; -import java.security.AccessController; -import java.security.PrivilegedAction; import sun.awt.*; @@ -132,7 +129,7 @@ private volatile boolean isLayouting; private final D delegate; - private Container delegateContainer; + private final Container delegateContainer; private Component delegateDropTarget; private final Object dropTargetLock = new Object(); @@ -157,9 +154,6 @@ */ @SuppressWarnings("serial")// Safe: outer class is non-serializable. private final class DelegateContainer extends Container { - { - enableEvents(0xFFFFFFFF); - } // Empty non private constructor was added because access to this // class shouldn't be emulated by a synthetic accessor method. @@ -212,73 +206,27 @@ } // the delegate must be created after the target is set - AWTEventListener toolkitListener = null; - synchronized (Toolkit.getDefaultToolkit()) { - try { - toolkitListener = getToolkitAWTEventListener(); - setToolkitAWTEventListener(null); - - synchronized (getDelegateLock()) { - delegate = createDelegate(); - if (delegate != null) { - delegate.setVisible(false); - delegateContainer = new DelegateContainer(); - delegateContainer.add(delegate); - delegateContainer.addNotify(); - delegate.addNotify(); - resetColorsAndFont(delegate); - delegate.setOpaque(true); - } else { - return; - } - } - - } finally { - setToolkitAWTEventListener(toolkitListener); + synchronized (getDelegateLock()) { + delegate = createDelegate(); + if (delegate == null) { + delegateContainer = null; + return; } - - // todo swing: later on we will probably have one global RM - SwingUtilities3.setDelegateRepaintManager(delegate, new RepaintManager() { - @Override - public void addDirtyRegion(final JComponent c, final int x, final int y, final int w, final int h) { - repaintPeer(SwingUtilities.convertRectangle( - c, new Rectangle(x, y, w, h), getDelegate())); - } - }); + delegate.setVisible(false); + delegateContainer = new DelegateContainer(); + delegateContainer.add(delegate); + delegateContainer.addNotify(); + resetColorsAndFont(delegate); + delegate.setOpaque(true); } - } - - /** - * This method must be called under Toolkit.getDefaultToolkit() lock - * and followed by setToolkitAWTEventListener() - */ - protected final AWTEventListener getToolkitAWTEventListener() { - return AccessController.doPrivileged(new PrivilegedAction() { - public AWTEventListener run() { - Toolkit toolkit = Toolkit.getDefaultToolkit(); - try { - Field field = Toolkit.class.getDeclaredField("eventListener"); - field.setAccessible(true); - return (AWTEventListener) field.get(toolkit); - } catch (Exception e) { - throw new InternalError(e.toString()); - } - } - }); - } - protected final void setToolkitAWTEventListener(final AWTEventListener listener) { - AccessController.doPrivileged(new PrivilegedAction() { - public Void run() { - Toolkit toolkit = Toolkit.getDefaultToolkit(); - try { - Field field = Toolkit.class.getDeclaredField("eventListener"); - field.setAccessible(true); - field.set(toolkit, listener); - } catch (Exception e) { - throw new InternalError(e.toString()); - } - return null; + // todo swing: later on we will probably have one global RM + SwingUtilities3.setDelegateRepaintManager(delegate, new RepaintManager() { + @Override + public void addDirtyRegion(final JComponent c, final int x, + final int y, final int w, final int h) { + repaintPeer(SwingUtilities.convertRectangle( + c, new Rectangle(x, y, w, h), getDelegate())); } }); } --- /dev/null 2014-02-04 15:17:31.000000000 +0400 +++ new/test/java/awt/event/AWTEvent/Container/ContainerAddedTest.java 2014-02-04 15:17:31.447052600 +0400 @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +import java.awt.AWTEvent; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.Label; +import java.awt.Toolkit; +import java.awt.event.AWTEventListener; + +/** + * @test + * @summary Verify the proper number of ComponentEvents are delivered + * @library ../../../regtesthelpers + * @build VisibilityValidator + * @run main ContainerAddedTest + */ +public final class ContainerAddedTest { + static final int LOOP = 100; + + class ContainerEventCounter { + static final int TIMEOUT = 5000; // Wait up to five seconds + private int counter = 0; + private AWTEventListener listener = null; + + ContainerEventCounter() { + listener = e -> { + //System.out.println("AWTEvent: " + e); + doEvent(e); + }; + Toolkit.getDefaultToolkit().addAWTEventListener(listener, + AWTEvent.CONTAINER_EVENT_MASK); + } + + public void reset() { + counter = 0; + } + + public void dispose() { + Toolkit.getDefaultToolkit().removeAWTEventListener(listener); + } + + synchronized public boolean requireEvents(int total) { + long endtime = System.currentTimeMillis() + TIMEOUT; + try { + while (counter < total) { + if (System.currentTimeMillis() < endtime) { + wait(TIMEOUT); + } else { + break; + } + } + } catch (InterruptedException ix) { + } + if (counter != total) { + System.out.println( + "### ERROR: expected " + total + " events but received " + counter + " events."); + } + return (counter == total); + } + + synchronized void doEvent(AWTEvent e) { + if (e.getSource() instanceof Frame) { + counter++; + notify(); + } + } + } + + public void testContainerEvents01() throws Exception { + Frame frame = null; + ContainerEventCounter collector = null; + try { + // Thread.currentThread().setName( "ContainerAddedTest Thread" ); + + // Bring up a test frame + frame = new Frame("ContainerAddedTest "); + frame.setLayout(new FlowLayout()); + frame.setSize(300, 400); + VisibilityValidator.setVisibleAndConfirm(frame); + + // Add components and count the events + collector = new ContainerEventCounter(); + if (!collector.requireEvents(0)) { + throw new RuntimeException( + "Nothing added yet, no container events expected"); + } + for (int i = 0; i < LOOP; i++) { + frame.add(new Label("-" + i + "-")); + } + + if (!collector.requireEvents(LOOP)) { + throw new RuntimeException(LOOP + " events expected"); + } + + frame.validate(); + if (!frame.isValid()) { + throw new RuntimeException("The frame should be valid now"); + } + collector.reset(); + frame.removeAll(); + + if (!collector.requireEvents(LOOP)) { + throw new RuntimeException(LOOP + " events expected"); + } + + if (frame.isValid()) { + throw new RuntimeException("The frame should not be valid yet"); + } + frame.validate(); + if (!frame.isValid()) { + throw new RuntimeException("The frame should be valid now"); + } + + } finally { + if (frame != null) { + frame.setVisible(false); + frame.dispose(); + } + + if (collector != null) { + collector.dispose(); + } + + } + } + + public static void main(String[] args) throws Exception { + ContainerAddedTest test = new ContainerAddedTest(); + test.testContainerEvents01(); + } +} --- /dev/null 2014-02-04 15:17:33.000000000 +0400 +++ new/test/java/awt/regtesthelpers/VisibilityValidator.java 2014-02-04 15:17:33.078054900 +0400 @@ -0,0 +1,282 @@ +/* + * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +import java.awt.AWTException; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.Point; +import java.awt.Robot; +import java.awt.Window; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +/* + * @summary Utility routines that wait for a window to be displayed or for colors to be visible + * @summary com.apple.junit.utils + */ +public class VisibilityValidator { + static final int SETUP_PERIOD = 5000; // Wait up to five seconds for our window events + static final boolean DEBUG = false; + + volatile Window win = null; + boolean activated = false; + boolean opened = false; + boolean focused = false; + volatile boolean valid = false; + + // + // Utility functions that encapsulates normal usage patterns + // + public static void setVisibleAndConfirm(Frame testframe) throws Exception { + setVisibleAndConfirm(testframe, "Could not confirm test frame was visible"); + } + + public static void setVisibleAndConfirm(Frame testframe, String msg) throws Exception { + if (testframe.isVisible()) { + throw new RuntimeException("Frame is already visible"); + } + + VisibilityValidator checkpoint = new VisibilityValidator(testframe); + testframe.setVisible(true); + checkpoint.requireVisible(); + if (!checkpoint.isValid()) { + //System.err.println(msg); + throw new Exception("Frame not visible after " + SETUP_PERIOD + " milliseconds"); + } + } + + // + // Add listeners to the window + // + public VisibilityValidator(Window win) { + this.win = win; + WindowAdapter watcher = new WindowAdapter() { + public void windowOpened(WindowEvent e) { + doOpen(); + } + + public void windowActivated(WindowEvent e) { + doActivate(); + } + + public void windowGainedFocus(WindowEvent e) { + doGainedFocus(); + } + }; + + win.addWindowListener(watcher); + win.addWindowFocusListener(watcher); + } + + // Make the window visible + // + // The only way to make it through this routine is for the window to generate BOTH + // a windowOpened, a windowActivated event and a windowGainedFocus, or to timeout. + // + synchronized public void requireVisible() { + int tries = 0; + + // wait for windowOpened and windowActivated events + try { + while ((opened == false) || (activated == false) || (focused == false)) { + if (tries < 4) { + tries += 1; + wait(SETUP_PERIOD); + } else { + break; + } + } + + if (opened && activated) { + valid = true; + } else { + valid = false; + } + } catch (InterruptedException ix) { + valid = false; + } + + // Extra-super paranoid checks + if (win.isVisible() == false) { + valid = false; + } + + if (win.isShowing() == false) { + valid = false; + } + + if (win.isFocused() == false) { + valid = false; + } + + if (DEBUG) { + if (!isValid()) { + System.out.println("\tactivated:" + new Boolean(activated)); + System.out.println("\topened:" + new Boolean(opened)); + System.out.println("\tfocused:" + new Boolean(focused)); + System.out.println("\tvalid:" + new Boolean(valid)); + System.out.println("\tisVisible():" + new Boolean(win.isVisible())); + System.out.println("\tisShowing():" + new Boolean(win.isShowing())); + System.out.println("\tisFocused():" + new Boolean(win.isFocused())); + } + } + + } + + synchronized void doOpen() { + opened = true; + notify(); + } + + synchronized void doActivate() { + activated = true; + notify(); + } + + synchronized void doGainedFocus() { + focused = true; + notify(); + } + + public boolean isValid() { + return valid; + } + + public boolean isClear() { + return valid; + } + + volatile static Robot robot = null; + + // utility function that waits until a Component is shown with the appropriate color + public static boolean waitForColor(Component c, Color expected) throws AWTException, InterruptedException { + Dimension dim = c.getSize(); + int xOff = dim.width / 2; + int yOff = dim.height / 2; + return waitForColor(c, xOff, yOff, expected); + } + + // utility function that waits for 5 seconds for Component to be shown with the appropriate color + public static boolean waitForColor(Component c, int xOff, int yOff, Color expected) throws AWTException, InterruptedException { + return waitForColor(c, xOff, yOff, expected, 5000L); + } + + // utility function that waits until a Component is up with the appropriate color + public static boolean waitForColor(Component c, int xOff, int yOff, Color expected, long timeout) throws AWTException, InterruptedException { + Point p = c.getLocationOnScreen(); + int x = (int)p.getX() + xOff; + int y = (int)p.getY() + yOff; + return waitForColor(x, y, expected, timeout); + } + + // utility function that waits until specific screen coords have the appropriate color + public static boolean waitForColor(int locX, int locY, Color expected, long timeout) throws AWTException, InterruptedException { + if (robot == null) { + robot = new Robot(); + } + + long endtime = System.currentTimeMillis() + timeout; + while (endtime > System.currentTimeMillis()) { + if (colorMatch(robot.getPixelColor(locX, locY), expected)) { + return true; + } + Thread.sleep(50); + } + + return false; + } + + // utility function that asserts that two colors are similar to each other + public static void assertColorEquals(final String message, + final Color actual, + final Color expected) { + //System.out.println("actual color: " + actual); + //System.out.println("expect color: " + expected); + if (!colorMatch(actual, expected)) { + System.err.println(message); + } + } + + // determines if two colors are close in hue and brightness + public static boolean colorMatch(final Color actual, final Color expected) { + //System.out.println("colorMatch actual: " + actual + " expect: " + expected); + final float[] actualHSB = getHSB(actual); + final float[] expectedHSB = getHSB(expected); + + final float actualHue = actualHSB[0]; + final float expectedHue = expectedHSB[0]; + final boolean hueMatched = closeMatchHue(actualHue, expectedHue, 0.17f); + //System.out.println("hueMatched? " + hueMatched); + final float actualBrightness = actualHSB[2]; + final float expectedBrightness = expectedHSB[2]; + final boolean brightnessMatched = closeMatch(actualBrightness, expectedBrightness, 0.15f); + //System.out.println("brightnessMatched? " + brightnessMatched); + + // check to see if the brightness was so low or so high that the hue got clamped to red + if (brightnessMatched && !hueMatched) { + return (expectedBrightness < 0.15f); + } + + //System.out.println("colorMatched? " + (brightnessMatched && hueMatched)); + return brightnessMatched && hueMatched; + } + + static float[] getHSB(final Color color) { + final float[] hsb = new float[3]; + Color.RGBtoHSB(color.getRed(), color.getGreen(), color.getBlue(), hsb); + return hsb; + } + + // matches hues from 0.0 to 1.0, accounting for wrap-around at the 1.0/0.0 boundry + static boolean closeMatchHue(final float actual, final float expected, final float tolerance) { + if (closeMatch(actual, expected, tolerance)) return true; + + // all that remains is the overflow and underflow cases + final float expectedHigh = expected + tolerance; + final float expectedLow = expected - tolerance; + + if (expectedHigh > 1.0f) { + // expected is too high, and actual was too low + //System.out.println("\thue expected too high, actual too low"); + return closeMatch(actual + 0.5f, expected - 0.5f, tolerance); + } + + if (expectedLow < 0.0f) { + // expected is too low, and actual was too high + //System.out.println("\thue expected too low, actual too high"); + return closeMatch(actual - 0.5f, expected + 0.5f, tolerance); + } + + //System.out.println("\tcloseMatchHue? " + false); + return false; + } + + static boolean closeMatch(final float actual, final float expected, final float tolerance) { + //System.out.println("\tcloseMatch actual: " + actual + " expect: " + expected + " tolerance: " + tolerance); + //System.out.println("\tcloseMatch " + ((expected + tolerance) > actual) + " && " + ((expected - tolerance) < actual)); + return (expected + tolerance) > actual && (expected - tolerance) < actual; + } +}