diff --git a/test/jdk/java/awt/event/HierarchyEvent/ObjectSourceTest.java b/test/jdk/java/awt/event/HierarchyEvent/ObjectSourceTest.java
new file mode 100644
index 0000000000000..8b4c6c3bfe134
--- /dev/null
+++ b/test/jdk/java/awt/event/HierarchyEvent/ObjectSourceTest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2001, 2023, 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.
+ */
+
+/*
+  @test
+  @bug 4420658
+  @summary No ClassCastException should be thrown when getComponent()
+           is called on an event with a non-Component source.
+           The result should be null.
+  @run main ObjectSourceTest
+*/
+
+import java.awt.Component;
+import java.awt.Panel;
+import java.awt.event.HierarchyEvent;
+import java.lang.reflect.InvocationTargetException;
+
+
+public class ObjectSourceTest {
+    static Panel panel;
+
+    public static void main(String args[]) throws InterruptedException,
+            InvocationTargetException {
+        panel = new Panel();
+
+        HierarchyEvent he = new HierarchyEvent(panel, HierarchyEvent.ANCESTOR_MOVED,
+                panel, panel);
+        Object obj = new Object();
+        he.setSource(obj);
+
+        Component comp = he.getComponent();
+        if (comp != null) {
+            throw new RuntimeException("ObjectSourceTest failed.  comp != null");
+        }
+    }
+}
diff --git a/test/jdk/java/awt/event/HierarchyEvent/SpecTest.java b/test/jdk/java/awt/event/HierarchyEvent/SpecTest.java
new file mode 100644
index 0000000000000..239c74ef2b21a
--- /dev/null
+++ b/test/jdk/java/awt/event/HierarchyEvent/SpecTest.java
@@ -0,0 +1,1248 @@
+/*
+ * Copyright (c) 1999, 2023, 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.
+ */
+
+/*
+  @test
+  @bug 4222172
+  @summary Verifies initial implementation of HierarchyEvent (programmatic)
+  @key headful
+  @run main SpecTest
+*/
+
+import java.awt.AWTEvent;
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.EventQueue;
+import java.awt.Frame;
+import java.awt.Label;
+import java.awt.Panel;
+import java.awt.Window;
+import java.awt.event.HierarchyBoundsListener;
+import java.awt.event.HierarchyEvent;
+import java.awt.event.HierarchyListener;
+import java.lang.reflect.InvocationTargetException;
+
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+
+public class SpecTest extends Frame implements HierarchyListener, HierarchyBoundsListener {
+    static SpecTest f;
+
+    public static void main(String args[]) throws InterruptedException,
+            InvocationTargetException {
+        EventQueue.invokeAndWait(() -> init());
+        f.start();
+    }
+
+    class EELabel extends Label {
+        private long mask = 0;
+        public EELabel(String s) {
+            super(s);
+        }
+
+        protected void processHierarchyEvent(HierarchyEvent e) {
+            super.processHierarchyEvent(e);
+            if ((mask & AWTEvent.HIERARCHY_EVENT_MASK) != 0) {
+                switch (e.getID()) {
+                    case HierarchyEvent.HIERARCHY_CHANGED:
+                        hierarchyChanged(e);
+                        break;
+                    default:
+                        break;
+                }
+            }
+        }
+
+        protected void processHierarchyBoundsEvent(HierarchyEvent e) {
+            super.processHierarchyBoundsEvent(e);
+            if ((mask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0) {
+                switch (e.getID()) {
+                    case HierarchyEvent.ANCESTOR_MOVED:
+                        ancestorMoved(e);
+                        break;
+                    case HierarchyEvent.ANCESTOR_RESIZED:
+                        ancestorResized(e);
+                        break;
+                    default:
+                        break;
+                }
+            }
+        }
+
+        public void pubEnableEvents(long eventsToEnable) {
+            mask |= eventsToEnable;
+            enableEvents(eventsToEnable);
+        }
+
+        public void pubDisableEvents(long eventsToDisable) {
+            mask &= ~eventsToDisable;
+            disableEvents(eventsToDisable);
+        }
+    }
+
+    class EEJLabel extends JLabel {
+        private long mask = 0;
+        public EEJLabel(String s) {
+            super(s);
+        }
+        protected void processHierarchyEvent(HierarchyEvent e) {
+            super.processHierarchyEvent(e);
+            if ((mask & AWTEvent.HIERARCHY_EVENT_MASK) != 0) {
+                switch (e.getID()) {
+                    case HierarchyEvent.HIERARCHY_CHANGED:
+                        hierarchyChanged(e);
+                        break;
+                    default:
+                        break;
+                }
+            }
+        }
+
+        protected void processHierarchyBoundsEvent(HierarchyEvent e) {
+            super.processHierarchyBoundsEvent(e);
+            if ((mask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0) {
+                switch (e.getID()) {
+                    case HierarchyEvent.ANCESTOR_MOVED:
+                        ancestorMoved(e);
+                        break;
+                    case HierarchyEvent.ANCESTOR_RESIZED:
+                        ancestorResized(e);
+                        break;
+                    default:
+                        break;
+                }
+            }
+        }
+
+        public void pubEnableEvents(long eventsToEnable) {
+            mask |= eventsToEnable;
+            enableEvents(eventsToEnable);
+        }
+
+        public void pubDisableEvents(long eventsToDisable) {
+            mask &= ~eventsToDisable;
+            disableEvents(eventsToDisable);
+        }
+    }
+
+    class EEPanel extends Panel {
+        private long mask = 0;
+        protected void processHierarchyEvent(HierarchyEvent e) {
+            super.processHierarchyEvent(e);
+            if ((mask & AWTEvent.HIERARCHY_EVENT_MASK) != 0) {
+                switch (e.getID()) {
+                    case HierarchyEvent.HIERARCHY_CHANGED:
+                        hierarchyChanged(e);
+                        break;
+                    default:
+                        break;
+                }
+            }
+        }
+
+        protected void processHierarchyBoundsEvent(HierarchyEvent e) {
+            super.processHierarchyBoundsEvent(e);
+            if ((mask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0) {
+                switch (e.getID()) {
+                    case HierarchyEvent.ANCESTOR_MOVED:
+                        ancestorMoved(e);
+                        break;
+                    case HierarchyEvent.ANCESTOR_RESIZED:
+                        ancestorResized(e);
+                        break;
+                    default:
+                        break;
+                }
+            }
+        }
+
+        public void pubEnableEvents(long eventsToEnable) {
+            mask |= eventsToEnable;
+            enableEvents(eventsToEnable);
+        }
+
+        public void pubDisableEvents(long eventsToDisable) {
+            mask &= ~eventsToDisable;
+            disableEvents(eventsToDisable);
+        }
+    }
+
+    class EEJPanel extends JPanel {
+        private long mask = 0;
+        protected void processHierarchyEvent(HierarchyEvent e) {
+            super.processHierarchyEvent(e);
+            if ((mask & AWTEvent.HIERARCHY_EVENT_MASK) != 0) {
+                switch (e.getID()) {
+                    case HierarchyEvent.HIERARCHY_CHANGED:
+                        hierarchyChanged(e);
+                        break;
+                    default:
+                        break;
+                }
+            }
+        }
+
+        protected void processHierarchyBoundsEvent(HierarchyEvent e) {
+            super.processHierarchyBoundsEvent(e);
+            if ((mask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0) {
+                switch (e.getID()) {
+                    case HierarchyEvent.ANCESTOR_MOVED:
+                        ancestorMoved(e);
+                        break;
+                    case HierarchyEvent.ANCESTOR_RESIZED:
+                        ancestorResized(e);
+                        break;
+                    default:
+                        break;
+                }
+            }
+        }
+
+        public void pubEnableEvents(long eventsToEnable) {
+            mask |= eventsToEnable;
+            enableEvents(eventsToEnable);
+        }
+
+        public void pubDisableEvents(long eventsToDisable) {
+            mask &= ~eventsToDisable;
+            disableEvents(eventsToDisable);
+        }
+    }
+
+    int parentChanged, displayabilityChanged, showingChanged, ancestorMoved,
+            ancestorResized;
+    private static final int OBJ_ARRAY_SIZE = 2;
+    Component[] source = new Component[OBJ_ARRAY_SIZE],
+            changed = new Component[OBJ_ARRAY_SIZE];
+    Container[] changedParent = new Container[OBJ_ARRAY_SIZE];
+
+    boolean assertParent = false, assertDisplayability = false,
+            assertShowing = false, assertMoved = false, assertResized = false;
+
+    private void flushEventQueue() throws InterruptedException, InvocationTargetException {
+        EventQueue.invokeAndWait(() -> {});
+    }
+
+    private void testAdd(Component child, Container parent, int count)
+            throws InterruptedException, InvocationTargetException {
+        assertParent = true;
+        parentChanged = count;
+        parent.add(child);
+        flushEventQueue();
+        if (parentChanged != 0) {
+            throw new RuntimeException("hierarchyChanged(PARENT_CHANGED) invoked "+
+                    parentChanged+" too few times");
+        }
+        assertParent = false;
+    }
+
+    private void testRemove(Component child, Container parent, int count)
+            throws InterruptedException, InvocationTargetException {
+        assertParent = true;
+        parentChanged = count;
+        parent.remove(child);
+        flushEventQueue();
+        if (parentChanged != 0) {
+            throw new RuntimeException("hierarchyChanged(PARENT_CHANGED) invoked "+
+                    parentChanged+" too few times");
+        }
+        assertParent = false;
+    }
+
+    private void testSetLocation(Component changed, int x, int y, int count)
+            throws InterruptedException, InvocationTargetException {
+        assertMoved = true;
+        ancestorMoved = count;
+        changed.setLocation(x, y);
+        flushEventQueue();
+        if (ancestorMoved != 0) {
+            throw new RuntimeException("ancestorMoved invoked "+ancestorMoved+
+                    " too few times");
+        }
+        assertMoved = false;
+    }
+
+    private void testSetSize(Component changed, int w, int h, int count)
+            throws InterruptedException, InvocationTargetException {
+        assertResized = true;
+        ancestorResized = count;
+        changed.setSize(w, h);
+        flushEventQueue();
+        if (ancestorResized != 0) {
+            throw new RuntimeException("ancestorResized invoked "+ancestorResized+
+                    " too few times");
+        }
+        assertResized = false;
+    }
+
+    private void testPack(Window topLevel, int displayabilityCount)
+            throws InterruptedException, InvocationTargetException {
+        assertDisplayability = true;
+        assertShowing = true;
+        displayabilityChanged = displayabilityCount;
+        showingChanged = 0;
+        topLevel.pack();
+        flushEventQueue();
+        if (displayabilityChanged != 0) {
+            throw new RuntimeException("hierarchyChanged(DISPLAYABILITY_CHANGED) "+
+                    "invoked "+displayabilityChanged+
+                    " too few times");
+        }
+        if (showingChanged != 0) {
+            throw new RuntimeException("hierarchyChanged(SHOWING_CHANGED) "+
+                    "invoked, but should not have been");
+        }
+        assertDisplayability = false;
+        assertShowing = false;
+    }
+
+    private void testShow(Window topLevel, int displayabilityCount,
+                          int showingCount)
+            throws InterruptedException, InvocationTargetException {
+        assertDisplayability = true;
+        assertShowing = true;
+        displayabilityChanged = displayabilityCount;
+        showingChanged = showingCount;
+        topLevel.show();
+        flushEventQueue();
+        if (displayabilityChanged != 0) {
+            throw new RuntimeException("hierarchyChanged(DISPLAYABILITY_CHANGED) "+
+                    "invoked "+displayabilityChanged+
+                    " too few times");
+        }
+        if (showingChanged != 0) {
+            throw new RuntimeException("hierarchyChanged(SHOWING_CHANGED) "+
+                    "invoked "+showingChanged+" too few times");
+        }
+        assertDisplayability = false;
+        assertShowing = false;
+    }
+
+    private void testHide(Window topLevel, int showingCount)
+            throws InterruptedException, InvocationTargetException {
+        assertDisplayability = true;
+        assertShowing = true;
+        displayabilityChanged = 0;
+        showingChanged = showingCount;
+        topLevel.hide();
+        flushEventQueue();
+        if (displayabilityChanged != 0) {
+            throw new RuntimeException("hierarchyChanged(DISPLAYABILITY_CHANGED) "+
+                    "invoked, but should not have been");
+        }
+        if (showingChanged != 0) {
+            throw new RuntimeException("hierarchyChanged(SHOWING_CHANGED) "+
+                    "invoked "+showingChanged+" too few times");
+        }
+        assertDisplayability = false;
+        assertShowing = false;
+    }
+
+    private void testDispose(Window topLevel, int displayabilityCount,
+                             int showingCount)
+            throws InterruptedException, InvocationTargetException {
+        assertDisplayability = true;
+        assertShowing = true;
+        displayabilityChanged = displayabilityCount;
+        showingChanged = showingCount;
+        topLevel.dispose();
+        flushEventQueue();
+        if (displayabilityChanged != 0) {
+            throw new RuntimeException("hierarchyChanged(DISPLAYABILITY_CHANGED) "+
+                    "invoked "+displayabilityChanged+
+                    " too few times");
+        }
+        if (showingChanged != 0) {
+            throw new RuntimeException("hierarchyChanged(SHOWING_CHANGED) "+
+                    "invoked "+showingChanged+" too few times");
+        }
+        assertDisplayability = false;
+        assertShowing = false;
+    }
+
+    private void assertObjectsImpl(HierarchyEvent e) {
+        int match = -1;
+
+        for (int i = 0; i < OBJ_ARRAY_SIZE; i++) {
+            if (e.getComponent() == source[i]) {
+                match = i;
+                break;
+            }
+        }
+
+        if (match == -1) {
+            String str = "\n\nsource incorrect, was "+e.getComponent()+"\n\n";
+            for (int i = 0; i < OBJ_ARRAY_SIZE; i++) {
+                str += "available source: "+source[i]+"\n\n";
+            }
+            str += "event: "+e+"\n";
+            throw new RuntimeException(str);
+        }
+
+        if (e.getChanged() != changed[match]) {
+            if (e.getID() == HierarchyEvent.HIERARCHY_CHANGED &&
+                    (e.getChangeFlags() & HierarchyEvent.DISPLAYABILITY_CHANGED) != 0) {
+                System.err.println("warning (known bug): changed for "+
+                        "DISPLAYABILITY_CHANGED event incorrect");
+            } else {
+                throw new RuntimeException("\n\nchanged incorrect, was "+
+                        e.getChanged()+
+                        ", should be "+changed[match]+"\n\n"+
+                        "event: "+e+"\n");
+            }
+        }
+
+        if (e.getChangedParent() != changedParent[match]) {
+            if (e.getID() == HierarchyEvent.HIERARCHY_CHANGED &&
+                    (e.getChangeFlags() & HierarchyEvent.DISPLAYABILITY_CHANGED) != 0) {
+                System.err.println("warning (known bug): changedParent for "+
+                        "DISPLAYABILITY_CHANGED event incorrect");
+            } else {
+                throw new RuntimeException("changedParent incorrect, was "+
+                        e.getChangedParent()+
+                        ", should be "+changedParent[match]+"\n\n"+
+                        "event: "+e+"\n");
+            }
+        }
+    }
+
+    private void setObjects(int index, Component source, Component changed,
+                            Container changedParent) {
+        this.source[index] = source;
+        this.changed[index] = changed;
+        this.changedParent[index] = changedParent;
+    }
+
+    private void resetObjects() {
+        for (int i = 0; i < OBJ_ARRAY_SIZE; i++) {
+            setObjects(i, null, null, null);
+        }
+    }
+
+    public void hierarchyChanged(HierarchyEvent e) {
+        if (assertParent &&
+                (e.getChangeFlags() & HierarchyEvent.PARENT_CHANGED) != 0) {
+            assertObjectsImpl(e);
+            parentChanged--;
+        }
+        if (assertDisplayability &&
+                (e.getChangeFlags() & HierarchyEvent.DISPLAYABILITY_CHANGED) != 0){
+            assertObjectsImpl(e);
+            displayabilityChanged--;
+        }
+        if (assertShowing &&
+                (e.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED) != 0) {
+            assertObjectsImpl(e);
+            showingChanged--;
+        }
+    }
+
+    public void ancestorMoved(HierarchyEvent e) {
+        if (!assertMoved)
+            return;
+
+        assertObjectsImpl(e);
+        ancestorMoved--;
+    }
+
+    public void ancestorResized(HierarchyEvent e) {
+        if (!assertResized)
+            return;
+
+        assertObjectsImpl(e);
+        ancestorResized--;
+    }
+
+    public static void init() {
+        f = new SpecTest();
+        f.setTitle("SpecTest");
+        f.setLayout(new BorderLayout());
+    }
+
+    private void test1(Component source, Component changed,
+                       Container changedParent, Window topLevel,
+                       int hierarchyCount, int hierarchyBoundsCount)
+            throws InterruptedException, InvocationTargetException {
+        changed.setBounds(0, 0, 100, 100);
+        topLevel.dispose();
+        resetObjects();
+
+        setObjects(0, source, changed, changedParent);
+
+        testRemove(changed, changedParent, hierarchyCount);
+        testAdd(changed, changedParent, hierarchyCount);
+        testSetLocation(changed, 200, 250, hierarchyBoundsCount);
+        testSetSize(changed, 50, 50, hierarchyBoundsCount);
+
+        setObjects(0, source, topLevel, null);
+
+        testPack(topLevel, hierarchyCount);
+        testDispose(topLevel, hierarchyCount, 0);
+        testPack(topLevel, hierarchyCount);
+        testShow(topLevel, 0, hierarchyCount);
+        testDispose(topLevel, hierarchyCount, hierarchyCount);
+        testShow(topLevel, hierarchyCount, hierarchyCount);
+        testHide(topLevel, hierarchyCount);
+        testDispose(topLevel, hierarchyCount, 0);
+
+        resetObjects();
+    }
+
+    private void test2(Component source1, Container parent1,
+                       Component source2, Container parent2,
+                       Window topLevel)
+            throws InterruptedException, InvocationTargetException {
+        topLevel.setBounds(0, 0, 100, 100);
+        topLevel.dispose();
+        resetObjects();
+
+        setObjects(0, source1, source1, parent1);
+        testRemove(source1, parent1, 1);
+        testAdd(source1, parent1, 1);
+
+        setObjects(0, source2, source2, parent2);
+        testRemove(source2, parent2, 1);
+        testAdd(source2, parent2, 1);
+
+        setObjects(0, source1, topLevel, null);
+        setObjects(1, source2, topLevel, null);
+
+        testSetLocation(topLevel, 200, 250, 2);
+        testSetSize(topLevel, 50, 50, 2);
+
+        testPack(topLevel, 2);
+        testDispose(topLevel, 2, 0);
+        testPack(topLevel, 2);
+        testShow(topLevel, 0, 2);
+        testDispose(topLevel, 2, 2);
+        testShow(topLevel, 2, 2);
+        testHide(topLevel, 2);
+        testDispose(topLevel, 2, 0);
+
+        resetObjects();
+    }
+
+    public void start() throws InterruptedException, InvocationTargetException {
+    /*
+                                    f
+                                    |
+                -----------------------------------------
+                |       |       |       |       |       |
+                l1      l2      p1      p2      p5      p6
+                                |       |       |       |
+                              -----   -----     |       |
+                              |   |   |   |     |       |
+                              l3  l4  l5  l6    p3      p4
+                                                |       |
+                                              -----   -----
+                                              |   |   |   |
+                                              l7  l8  l9  l10
+    */
+
+        // listener-only tests
+
+        {
+            Label l1 = new Label("Label 1");
+            JLabel l2 = new JLabel("Label 2");
+            Panel p1 = new Panel();
+            JPanel p2 = new JPanel();
+            Panel p5 = new Panel();
+            JPanel p6 = new JPanel();
+
+            Label l3 = new Label("Label 3");
+            JLabel l4 = new JLabel("Label 4");
+            Label l5 = new Label("Label 5");
+            JLabel l6 = new JLabel("Label 6");
+            JPanel p3 = new JPanel();
+            Panel p4 = new Panel();
+
+            Label l7 = new Label("Label 7");
+            JLabel l8 = new JLabel("Label 8");
+            JLabel l9 = new JLabel("Label 9");
+            Label l10 = new Label("Label 10");
+
+            f.add(l1);
+            f.add(l2);
+            f.add(p1);
+            f.add(p2);
+            f.add(p5);
+            f.add(p6);
+
+            p1.add(l3);
+            p1.add(l4);
+
+            p2.add(l5);
+            p2.add(l6);
+
+            p5.add(p3);
+
+            p6.add(p4);
+
+            p3.add(l7);
+            p3.add(l8);
+
+            p4.add(l9);
+            p4.add(l10);
+
+
+
+            // test1
+
+            l1.addHierarchyListener(this);
+            l1.addHierarchyBoundsListener(this);
+            test1(l1, l1, f, f, 1, 0);
+            l1.addHierarchyListener(this);
+            l1.addHierarchyBoundsListener(this);
+            test1(l1, l1, f, f, 2, 0);
+            l1.removeHierarchyListener(this);
+            l1.removeHierarchyBoundsListener(this);
+            l1.removeHierarchyListener(this);
+            l1.removeHierarchyBoundsListener(this);
+
+            l2.addHierarchyListener(this);
+            l2.addHierarchyBoundsListener(this);
+            test1(l2, l2, f, f, 1, 0);
+            l2.addHierarchyListener(this);
+            l2.addHierarchyBoundsListener(this);
+            test1(l2, l2, f, f, 2, 0);
+            l2.removeHierarchyListener(this);
+            l2.removeHierarchyBoundsListener(this);
+            l2.removeHierarchyListener(this);
+            l2.removeHierarchyBoundsListener(this);
+
+            p1.addHierarchyListener(this);
+            p1.addHierarchyBoundsListener(this);
+            test1(p1, p1, f, f, 1, 0);
+            p1.addHierarchyListener(this);
+            p1.addHierarchyBoundsListener(this);
+            test1(p1, p1, f, f, 2, 0);
+            p1.removeHierarchyListener(this);
+            p1.removeHierarchyBoundsListener(this);
+            p1.removeHierarchyListener(this);
+            p1.removeHierarchyBoundsListener(this);
+
+            p2.addHierarchyListener(this);
+            p2.addHierarchyBoundsListener(this);
+            test1(p2, p2, f, f, 1, 0);
+            p2.addHierarchyListener(this);
+            p2.addHierarchyBoundsListener(this);
+            test1(p2, p2, f, f, 2, 0);
+            p2.removeHierarchyListener(this);
+            p2.removeHierarchyBoundsListener(this);
+            p2.removeHierarchyListener(this);
+            p2.removeHierarchyBoundsListener(this);
+
+            p5.addHierarchyListener(this);
+            p5.addHierarchyBoundsListener(this);
+            test1(p5, p5, f, f, 1, 0);
+            p5.addHierarchyListener(this);
+            p5.addHierarchyBoundsListener(this);
+            test1(p5, p5, f, f, 2, 0);
+            p5.removeHierarchyListener(this);
+            p5.removeHierarchyBoundsListener(this);
+            p5.removeHierarchyListener(this);
+            p5.removeHierarchyBoundsListener(this);
+
+            p6.addHierarchyListener(this);
+            p6.addHierarchyBoundsListener(this);
+            test1(p6, p6, f, f, 1, 0);
+            p6.addHierarchyListener(this);
+            p6.addHierarchyBoundsListener(this);
+            test1(p6, p6, f, f, 2, 0);
+            p6.removeHierarchyListener(this);
+            p6.removeHierarchyBoundsListener(this);
+            p6.removeHierarchyListener(this);
+            p6.removeHierarchyBoundsListener(this);
+
+            l3.addHierarchyListener(this);
+            l3.addHierarchyBoundsListener(this);
+            test1(l3, l3, p1, f, 1, 0);
+            test1(l3, p1, f, f, 1, 1);
+            l3.addHierarchyListener(this);
+            l3.addHierarchyBoundsListener(this);
+            test1(l3, l3, p1, f, 2, 0);
+            test1(l3, p1, f, f, 2, 2);
+            l3.removeHierarchyListener(this);
+            l3.removeHierarchyBoundsListener(this);
+            l3.removeHierarchyListener(this);
+            l3.removeHierarchyBoundsListener(this);
+
+            l4.addHierarchyListener(this);
+            l4.addHierarchyBoundsListener(this);
+            test1(l4, l4, p1, f, 1, 0);
+            test1(l4, p1, f, f, 1, 1);
+            l4.addHierarchyListener(this);
+            l4.addHierarchyBoundsListener(this);
+            test1(l4, l4, p1, f, 2, 0);
+            test1(l4, p1, f, f, 2, 2);
+            l4.removeHierarchyListener(this);
+            l4.removeHierarchyBoundsListener(this);
+            l4.removeHierarchyListener(this);
+            l4.removeHierarchyBoundsListener(this);
+
+            l5.addHierarchyListener(this);
+            l5.addHierarchyBoundsListener(this);
+            test1(l5, l5, p2, f, 1, 0);
+            test1(l5, p2, f, f, 1, 1);
+            l5.addHierarchyListener(this);
+            l5.addHierarchyBoundsListener(this);
+            test1(l5, l5, p2, f, 2, 0);
+            test1(l5, p2, f, f, 2, 2);
+            l5.removeHierarchyListener(this);
+            l5.removeHierarchyBoundsListener(this);
+            l5.removeHierarchyListener(this);
+            l5.removeHierarchyBoundsListener(this);
+
+            l6.addHierarchyListener(this);
+            l6.addHierarchyBoundsListener(this);
+            test1(l6, l6, p2, f, 1, 0);
+            test1(l6, p2, f, f, 1, 1);
+            l6.addHierarchyListener(this);
+            l6.addHierarchyBoundsListener(this);
+            test1(l6, l6, p2, f, 2, 0);
+            test1(l6, p2, f, f, 2, 2);
+            l6.removeHierarchyListener(this);
+            l6.removeHierarchyBoundsListener(this);
+            l6.removeHierarchyListener(this);
+            l6.removeHierarchyBoundsListener(this);
+
+            p3.addHierarchyListener(this);
+            p3.addHierarchyBoundsListener(this);
+            test1(p3, p3, p5, f, 1, 0);
+            test1(p3, p5, f, f, 1, 1);
+            p3.addHierarchyListener(this);
+            p3.addHierarchyBoundsListener(this);
+            test1(p3, p3, p5, f, 2, 0);
+            test1(p3, p5, f, f, 2, 2);
+            p3.removeHierarchyListener(this);
+            p3.removeHierarchyBoundsListener(this);
+            p3.removeHierarchyListener(this);
+            p3.removeHierarchyBoundsListener(this);
+
+            p4.addHierarchyListener(this);
+            p4.addHierarchyBoundsListener(this);
+            test1(p4, p4, p6, f, 1, 0);
+            test1(p4, p6, f, f, 1, 1);
+            p4.addHierarchyListener(this);
+            p4.addHierarchyBoundsListener(this);
+            test1(p4, p4, p6, f, 2, 0);
+            test1(p4, p6, f, f, 2, 2);
+            p4.removeHierarchyListener(this);
+            p4.removeHierarchyBoundsListener(this);
+            p4.removeHierarchyListener(this);
+            p4.removeHierarchyBoundsListener(this);
+
+            l7.addHierarchyListener(this);
+            l7.addHierarchyBoundsListener(this);
+            test1(l7, l7, p3, f, 1, 0);
+            test1(l7, p3, p5, f, 1, 1);
+            test1(l7, p5, f, f, 1, 1);
+            l7.addHierarchyListener(this);
+            l7.addHierarchyBoundsListener(this);
+            test1(l7, l7, p3, f, 2, 0);
+            test1(l7, p3, p5, f, 2, 2);
+            test1(l7, p5, f, f, 2, 2);
+            l7.removeHierarchyListener(this);
+            l7.removeHierarchyBoundsListener(this);
+            l7.removeHierarchyListener(this);
+            l7.removeHierarchyBoundsListener(this);
+
+            l8.addHierarchyListener(this);
+            l8.addHierarchyBoundsListener(this);
+            test1(l8, l8, p3, f, 1, 0);
+            test1(l8, p3, p5, f, 1, 1);
+            test1(l8, p5, f, f, 1, 1);
+            l8.addHierarchyListener(this);
+            l8.addHierarchyBoundsListener(this);
+            test1(l8, l8, p3, f, 2, 0);
+            test1(l8, p3, p5, f, 2, 2);
+            test1(l8, p5, f, f, 2, 2);
+            l8.removeHierarchyListener(this);
+            l8.removeHierarchyBoundsListener(this);
+            l8.removeHierarchyListener(this);
+            l8.removeHierarchyBoundsListener(this);
+
+            l9.addHierarchyListener(this);
+            l9.addHierarchyBoundsListener(this);
+            test1(l9, l9, p4, f, 1, 0);
+            test1(l9, p4, p6, f, 1, 1);
+            test1(l9, p6, f, f, 1, 1);
+            l9.addHierarchyListener(this);
+            l9.addHierarchyBoundsListener(this);
+            test1(l9, l9, p4, f, 2, 0);
+            test1(l9, p4, p6, f, 2, 2);
+            test1(l9, p6, f, f, 2, 2);
+            l9.removeHierarchyListener(this);
+            l9.removeHierarchyBoundsListener(this);
+            l9.removeHierarchyListener(this);
+            l9.removeHierarchyBoundsListener(this);
+
+            l10.addHierarchyListener(this);
+            l10.addHierarchyBoundsListener(this);
+            test1(l10, l10, p4, f, 1, 0);
+            test1(l10, p4, p6, f, 1, 1);
+            test1(l10, p6, f, f, 1, 1);
+            l10.addHierarchyListener(this);
+            l10.addHierarchyBoundsListener(this);
+            test1(l10, l10, p4, f, 2, 0);
+            test1(l10, p4, p6, f, 2, 2);
+            test1(l10, p6, f, f, 2, 2);
+            l10.removeHierarchyListener(this);
+            l10.removeHierarchyBoundsListener(this);
+            l10.removeHierarchyListener(this);
+            l10.removeHierarchyBoundsListener(this);
+
+
+
+            // test2
+
+            l1.addHierarchyListener(this);
+            l10.addHierarchyListener(this);
+            l1.addHierarchyBoundsListener(this);
+            l10.addHierarchyBoundsListener(this);
+            test2(l1, f, l10, p4, f);
+            l1.removeHierarchyListener(this);
+            l10.removeHierarchyListener(this);
+            l1.removeHierarchyBoundsListener(this);
+            l10.removeHierarchyBoundsListener(this);
+
+            l2.addHierarchyListener(this);
+            l9.addHierarchyListener(this);
+            l2.addHierarchyBoundsListener(this);
+            l9.addHierarchyBoundsListener(this);
+            test2(l2, f, l9, p4, f);
+            l2.removeHierarchyListener(this);
+            l9.removeHierarchyListener(this);
+            l2.removeHierarchyBoundsListener(this);
+            l9.removeHierarchyBoundsListener(this);
+
+            l3.addHierarchyListener(this);
+            l8.addHierarchyListener(this);
+            l3.addHierarchyBoundsListener(this);
+            l8.addHierarchyBoundsListener(this);
+            test2(l3, p1, l8, p3, f);
+            l3.removeHierarchyListener(this);
+            l8.removeHierarchyListener(this);
+            l3.removeHierarchyBoundsListener(this);
+            l8.removeHierarchyBoundsListener(this);
+
+            l4.addHierarchyListener(this);
+            l7.addHierarchyListener(this);
+            l4.addHierarchyBoundsListener(this);
+            l7.addHierarchyBoundsListener(this);
+            test2(l4, p1, l7, p3, f);
+            l4.removeHierarchyListener(this);
+            l7.removeHierarchyListener(this);
+            l4.removeHierarchyBoundsListener(this);
+            l7.removeHierarchyBoundsListener(this);
+
+            l5.addHierarchyListener(this);
+            l6.addHierarchyListener(this);
+            l5.addHierarchyBoundsListener(this);
+            l6.addHierarchyBoundsListener(this);
+            test2(l5, p2, l6, p2, f);
+            l5.removeHierarchyListener(this);
+            l6.removeHierarchyListener(this);
+            l5.removeHierarchyBoundsListener(this);
+            l6.removeHierarchyBoundsListener(this);
+
+            p1.addHierarchyListener(this);
+            p4.addHierarchyListener(this);
+            p1.addHierarchyBoundsListener(this);
+            p4.addHierarchyBoundsListener(this);
+            test2(p1, f, p4, p6, f);
+            p1.removeHierarchyListener(this);
+            p4.removeHierarchyListener(this);
+            p1.removeHierarchyBoundsListener(this);
+            p4.removeHierarchyBoundsListener(this);
+
+            p2.addHierarchyListener(this);
+            p3.addHierarchyListener(this);
+            p2.addHierarchyBoundsListener(this);
+            p3.addHierarchyBoundsListener(this);
+            test2(p2, f, p3, p5, f);
+            p2.removeHierarchyListener(this);
+            p3.removeHierarchyListener(this);
+            p2.removeHierarchyBoundsListener(this);
+            p3.removeHierarchyBoundsListener(this);
+
+            p5.addHierarchyListener(this);
+            p6.addHierarchyListener(this);
+            p5.addHierarchyBoundsListener(this);
+            p6.addHierarchyBoundsListener(this);
+            test2(p5, f, p6, f, f);
+            p5.removeHierarchyListener(this);
+            p6.removeHierarchyListener(this);
+            p5.removeHierarchyBoundsListener(this);
+            p6.removeHierarchyBoundsListener(this);
+        }
+
+        EventQueue.invokeAndWait(() -> {
+            if (f != null) {
+                f.dispose();
+                f.removeAll();
+            }
+        });
+
+        // mixed listener/eventEnabled and eventEnabled-only tests
+
+        {
+            EELabel l1 = new EELabel("Label 1");
+            EEJLabel l2 = new EEJLabel("Label 2");
+            EEPanel p1 = new EEPanel();
+            EEJPanel p2 = new EEJPanel();
+            EEPanel p5 = new EEPanel();
+            EEJPanel p6 = new EEJPanel();
+
+            EELabel l3 = new EELabel("Label 3");
+            EEJLabel l4 = new EEJLabel("Label 4");
+            EELabel l5 = new EELabel("Label 5");
+            EEJLabel l6 = new EEJLabel("Label 6");
+            EEJPanel p3 = new EEJPanel();
+            EEPanel p4 = new EEPanel();
+
+            EELabel l7 = new EELabel("Label 7");
+            EEJLabel l8 = new EEJLabel("Label 8");
+            EEJLabel l9 = new EEJLabel("Label 9");
+            EELabel l10 = new EELabel("Label 10");
+
+            f.add(l1);
+            f.add(l2);
+            f.add(p1);
+            f.add(p2);
+            f.add(p5);
+            f.add(p6);
+
+            p1.add(l3);
+            p1.add(l4);
+
+            p2.add(l5);
+            p2.add(l6);
+
+            p5.add(p3);
+
+            p6.add(p4);
+
+            p3.add(l7);
+            p3.add(l8);
+
+            p4.add(l9);
+            p4.add(l10);
+
+
+
+            // test3
+
+            l1.pubEnableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            l1.pubEnableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+            test1(l1, l1, f, f, 1, 0);
+            l1.addHierarchyListener(this);
+            l1.addHierarchyBoundsListener(this);
+            test1(l1, l1, f, f, 2, 0);
+            l1.pubDisableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            l1.pubDisableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+            l1.removeHierarchyListener(this);
+            l1.removeHierarchyBoundsListener(this);
+
+            l2.pubEnableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            l2.pubEnableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+            test1(l2, l2, f, f, 1, 0);
+            l2.addHierarchyListener(this);
+            l2.addHierarchyBoundsListener(this);
+            test1(l2, l2, f, f, 2, 0);
+            l2.removeHierarchyListener(this);
+            l2.removeHierarchyBoundsListener(this);
+            l2.pubDisableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            l2.pubDisableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+
+            p1.addHierarchyListener(this);
+            p1.addHierarchyBoundsListener(this);
+            test1(p1, p1, f, f, 1, 0);
+            p1.pubEnableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            p1.pubEnableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+            test1(p1, p1, f, f, 2, 0);
+            p1.pubDisableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            p1.pubDisableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+            p1.removeHierarchyListener(this);
+            p1.removeHierarchyBoundsListener(this);
+
+            p2.addHierarchyListener(this);
+            p2.addHierarchyBoundsListener(this);
+            test1(p2, p2, f, f, 1, 0);
+            p2.pubEnableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            p2.pubEnableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+            test1(p2, p2, f, f, 2, 0);
+            p2.removeHierarchyListener(this);
+            p2.removeHierarchyBoundsListener(this);
+            p2.pubDisableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            p2.pubDisableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+
+            p5.pubEnableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            p5.pubEnableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+            test1(p5, p5, f, f, 1, 0);
+            p5.addHierarchyListener(this);
+            p5.addHierarchyBoundsListener(this);
+            test1(p5, p5, f, f, 2, 0);
+            p5.pubDisableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            p5.pubDisableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+            p5.removeHierarchyListener(this);
+            p5.removeHierarchyBoundsListener(this);
+
+            p6.pubEnableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            p6.pubEnableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+            test1(p6, p6, f, f, 1, 0);
+            p6.addHierarchyListener(this);
+            p6.addHierarchyBoundsListener(this);
+            test1(p6, p6, f, f, 2, 0);
+            p6.removeHierarchyListener(this);
+            p6.removeHierarchyBoundsListener(this);
+            p6.pubDisableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            p6.pubDisableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+
+            l3.addHierarchyListener(this);
+            l3.addHierarchyBoundsListener(this);
+            test1(l3, l3, p1, f, 1, 0);
+            test1(l3, p1, f, f, 1, 1);
+            l3.pubEnableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            l3.pubEnableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+            test1(l3, l3, p1, f, 2, 0);
+            test1(l3, p1, f, f, 2, 2);
+            l3.pubDisableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            l3.pubDisableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+            l3.removeHierarchyListener(this);
+            l3.removeHierarchyBoundsListener(this);
+
+            l4.addHierarchyListener(this);
+            l4.addHierarchyBoundsListener(this);
+            test1(l4, l4, p1, f, 1, 0);
+            test1(l4, p1, f, f, 1, 1);
+            l4.pubEnableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            l4.pubEnableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+            test1(l4, l4, p1, f, 2, 0);
+            test1(l4, p1, f, f, 2, 2);
+            l4.removeHierarchyListener(this);
+            l4.removeHierarchyBoundsListener(this);
+            l4.pubDisableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            l4.pubDisableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+
+            l5.pubEnableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            l5.pubEnableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+            test1(l5, l5, p2, f, 1, 0);
+            test1(l5, p2, f, f, 1, 1);
+            l5.addHierarchyListener(this);
+            l5.addHierarchyBoundsListener(this);
+            test1(l5, l5, p2, f, 2, 0);
+            test1(l5, p2, f, f, 2, 2);
+            l5.pubDisableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            l5.pubDisableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+            l5.removeHierarchyListener(this);
+            l5.removeHierarchyBoundsListener(this);
+
+            l6.pubEnableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            l6.pubEnableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+            test1(l6, l6, p2, f, 1, 0);
+            test1(l6, p2, f, f, 1, 1);
+            l6.addHierarchyListener(this);
+            l6.addHierarchyBoundsListener(this);
+            test1(l6, l6, p2, f, 2, 0);
+            test1(l6, p2, f, f, 2, 2);
+            l6.removeHierarchyListener(this);
+            l6.removeHierarchyBoundsListener(this);
+            l6.pubDisableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            l6.pubDisableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+
+            p3.addHierarchyListener(this);
+            p3.addHierarchyBoundsListener(this);
+            test1(p3, p3, p5, f, 1, 0);
+            test1(p3, p5, f, f, 1, 1);
+            p3.pubEnableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            p3.pubEnableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+            test1(p3, p3, p5, f, 2, 0);
+            test1(p3, p5, f, f, 2, 2);
+            p3.pubDisableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            p3.pubDisableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+            p3.removeHierarchyListener(this);
+            p3.removeHierarchyBoundsListener(this);
+
+            p4.addHierarchyListener(this);
+            p4.addHierarchyBoundsListener(this);
+            test1(p4, p4, p6, f, 1, 0);
+            test1(p4, p6, f, f, 1, 1);
+            p4.pubEnableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            p4.pubEnableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+            test1(p4, p4, p6, f, 2, 0);
+            test1(p4, p6, f, f, 2, 2);
+            p4.removeHierarchyListener(this);
+            p4.removeHierarchyBoundsListener(this);
+            p4.pubDisableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            p4.pubDisableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+
+            l7.pubEnableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            l7.pubEnableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+            test1(l7, l7, p3, f, 1, 0);
+            test1(l7, p3, p5, f, 1, 1);
+            test1(l7, p5, f, f, 1, 1);
+            l7.addHierarchyListener(this);
+            l7.addHierarchyBoundsListener(this);
+            test1(l7, l7, p3, f, 2, 0);
+            test1(l7, p3, p5, f, 2, 2);
+            test1(l7, p5, f, f, 2, 2);
+            l7.pubDisableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            l7.pubDisableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+            l7.removeHierarchyListener(this);
+            l7.removeHierarchyBoundsListener(this);
+
+            l8.pubEnableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            l8.pubEnableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+            test1(l8, l8, p3, f, 1, 0);
+            test1(l8, p3, p5, f, 1, 1);
+            test1(l8, p5, f, f, 1, 1);
+            l8.addHierarchyListener(this);
+            l8.addHierarchyBoundsListener(this);
+            test1(l8, l8, p3, f, 2, 0);
+            test1(l8, p3, p5, f, 2, 2);
+            test1(l8, p5, f, f, 2, 2);
+            l8.removeHierarchyListener(this);
+            l8.removeHierarchyBoundsListener(this);
+            l8.pubDisableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            l8.pubDisableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+
+            l9.addHierarchyListener(this);
+            l9.addHierarchyBoundsListener(this);
+            test1(l9, l9, p4, f, 1, 0);
+            test1(l9, p4, p6, f, 1, 1);
+            test1(l9, p6, f, f, 1, 1);
+            l9.pubEnableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            l9.pubEnableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+            test1(l9, l9, p4, f, 2, 0);
+            test1(l9, p4, p6, f, 2, 2);
+            test1(l9, p6, f, f, 2, 2);
+            l9.pubDisableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            l9.pubDisableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+            l9.removeHierarchyListener(this);
+            l9.removeHierarchyBoundsListener(this);
+
+            l10.addHierarchyListener(this);
+            l10.addHierarchyBoundsListener(this);
+            test1(l10, l10, p4, f, 1, 0);
+            test1(l10, p4, p6, f, 1, 1);
+            test1(l10, p6, f, f, 1, 1);
+            l10.pubEnableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            l10.pubEnableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+            test1(l10, l10, p4, f, 2, 0);
+            test1(l10, p4, p6, f, 2, 2);
+            test1(l10, p6, f, f, 2, 2);
+            l10.removeHierarchyListener(this);
+            l10.removeHierarchyBoundsListener(this);
+            l10.pubDisableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            l10.pubDisableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+
+
+
+            // test4
+
+            l1.pubEnableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            l10.pubEnableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            l1.pubEnableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+            l10.pubEnableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+            test2(l1, f, l10, p4, f);
+            l1.pubDisableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            l10.pubDisableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            l1.pubDisableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+            l10.pubDisableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+
+            l2.pubEnableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            l9.pubEnableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            l2.pubEnableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+            l9.pubEnableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+            test2(l2, f, l9, p4, f);
+            l2.pubDisableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            l9.pubDisableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            l2.pubDisableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+            l9.pubDisableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+
+            l3.pubEnableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            l8.pubEnableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            l3.pubEnableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+            l8.pubEnableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+            test2(l3, p1, l8, p3, f);
+            l3.pubDisableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            l8.pubDisableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            l3.pubDisableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+            l8.pubDisableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+
+            l4.pubEnableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            l7.pubEnableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            l4.pubEnableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+            l7.pubEnableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+            test2(l4, p1, l7, p3, f);
+            l4.pubDisableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            l7.pubDisableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            l4.pubDisableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+            l7.pubDisableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+
+            l5.pubEnableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            l6.pubEnableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            l5.pubEnableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+            l6.pubEnableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+            test2(l5, p2, l6, p2, f);
+            l5.pubDisableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            l6.pubDisableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            l5.pubDisableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+            l6.pubDisableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+
+            p1.pubEnableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            p4.pubEnableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            p1.pubEnableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+            p4.pubEnableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+            test2(p1, f, p4, p6, f);
+            p1.pubDisableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            p4.pubDisableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            p1.pubDisableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+            p4.pubDisableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+
+            p2.pubEnableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            p3.pubEnableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            p2.pubEnableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+            p3.pubEnableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+            test2(p2, f, p3, p5, f);
+            p2.pubDisableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            p3.pubDisableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            p2.pubDisableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+            p3.pubDisableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+
+            p5.pubEnableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            p6.pubEnableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            p5.pubEnableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+            p6.pubEnableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+            test2(p5, f, p6, f, f);
+            p5.pubDisableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            p6.pubDisableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
+            p5.pubDisableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+            p6.pubDisableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
+        }
+
+        System.out.println("passed");
+    }
+}
diff --git a/test/jdk/java/awt/event/InputEvent/MouseModsTest.java b/test/jdk/java/awt/event/InputEvent/MouseModsTest.java
new file mode 100644
index 0000000000000..d52b03f14bc42
--- /dev/null
+++ b/test/jdk/java/awt/event/InputEvent/MouseModsTest.java
@@ -0,0 +1,286 @@
+/*
+ * Copyright (c) 2001, 2023, 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.
+ */
+
+/*
+  @test
+  @bug 4353201
+  @summary Wrong modifiers on InputEvent
+  @key headful
+  @run main MouseModsTest
+*/
+
+import java.awt.AWTEvent;
+import java.awt.AWTException;
+import java.awt.Canvas;
+import java.awt.Color;
+import java.awt.EventQueue;
+import java.awt.Frame;
+import java.awt.MouseInfo;
+import java.awt.Panel;
+import java.awt.Point;
+import java.awt.Robot;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+import java.lang.reflect.InvocationTargetException;
+
+public class MouseModsTest {
+    static volatile int testCtrl = 0;
+    static volatile int testBtn = 0;
+    static volatile boolean passed = true;
+
+    static final int BUTTONS = Math.min(3, MouseInfo.getNumberOfButtons());
+    static final int KEYS = 2;
+
+    static Frame frame;
+    static Panel panel;
+    static Canvas button1;
+    static Canvas button2;
+
+    static volatile Point pt1;
+    static volatile Point pt2;
+
+    public static void main(String args[]) throws AWTException,
+            InterruptedException, InvocationTargetException {
+
+        EventQueue.invokeAndWait(() -> {
+            frame = new Frame("MouseModsTest");
+            panel = new Panel();
+            button1 = new TestCanvas();
+            button2 = new TestCanvas();
+            frame.setSize(300, 200);
+            panel.add(button1);
+            panel.add(button2);
+            frame.add(panel);
+            frame.setLocationRelativeTo(null);
+            frame.setVisible(true);
+        });
+
+        try {
+            Robot robot;
+            robot = new Robot();
+            robot.setAutoWaitForIdle(true);
+            robot.setAutoDelay(50);
+            robot.delay(1000);
+
+            EventQueue.invokeAndWait(() -> {
+                pt1 = button1.getLocationOnScreen();
+                pt2 = button2.getLocationOnScreen();
+
+                pt1.x += button1.getSize().width / 2;
+                pt1.y += button1.getSize().height / 2;
+
+                pt2.x += button2.getSize().width / 2;
+                pt2.y += button2.getSize().height / 2;
+            });
+
+            robot.mouseMove(pt2.x, pt2.y);
+
+            //Keyboard to Mouse Test
+            for (int ctrl = 1; ctrl <= KEYS; ++ctrl) {
+                testCtrl = ctrl;
+                robot.keyPress(getKeycode(ctrl));
+                robot.keyPress(KeyEvent.VK_A);
+                robot.keyRelease(KeyEvent.VK_A);
+                for (int btn = 2; btn <= BUTTONS; ++btn) {
+                    testBtn = btn;
+                    robot.mousePress(getMouseModifier(btn));
+                    robot.mouseMove(pt1.x, pt1.y);
+                    robot.mouseMove(pt2.x, pt2.y);
+                    robot.mouseRelease(getMouseModifier(btn));
+                }
+                robot.keyRelease(getKeycode(ctrl));
+            }
+
+            //Mouse to Mouse Test
+            for (int btn1 = 1; btn1 <= BUTTONS; ++btn1) {
+                testBtn = btn1;
+                robot.mousePress(getMouseModifier(btn1));
+                for (int btn = 1; btn <= BUTTONS; ++btn) {
+                    if (btn == btn1) continue;
+                    testBtn = btn;
+                    robot.mousePress(getMouseModifier(btn));
+                    robot.mouseMove(pt1.x, pt1.y);
+                    robot.mouseMove(pt2.x, pt2.y);
+                    robot.mouseRelease(getMouseModifier(btn));
+                }
+                testBtn = btn1;
+                robot.mouseRelease(getMouseModifier(btn1));
+            }
+            testBtn = 0;
+        } finally {
+            EventQueue.invokeAndWait(() -> {
+                if (frame != null) {
+                    frame.dispose();
+                }
+            });
+        }
+
+        if (!passed) {
+            throw new RuntimeException("Test Failed");
+        }
+    }
+
+    static int getKeycode(int ctrl) {
+        switch (ctrl) {
+        case 1: return KeyEvent.VK_SHIFT;
+        case 2: return KeyEvent.VK_CONTROL;
+        case 3: return KeyEvent.VK_ALT;
+        default: return 0;
+        }
+    }
+
+    static int getKeyModifier(int ctrl) {
+        switch (ctrl) {
+        case 1: return InputEvent.SHIFT_MASK;
+        case 2: return InputEvent.CTRL_MASK;
+        case 3: return InputEvent.ALT_MASK;
+        default: return 0;
+        }
+    }
+
+    static int getMouseModifier(int btn) {
+        switch (btn) {
+        case 1: return InputEvent.BUTTON1_MASK;
+        case 2: return InputEvent.BUTTON2_MASK;
+        case 3: return InputEvent.BUTTON3_MASK;
+        default: return 0;
+        }
+    }
+
+    static final int allKeyMods =
+    InputEvent.SHIFT_MASK
+    | InputEvent.CTRL_MASK
+    | InputEvent.ALT_MASK;
+
+    static final int allMouseMods =
+    InputEvent.BUTTON1_MASK
+    | InputEvent.BUTTON2_MASK
+    | InputEvent.BUTTON3_MASK;
+
+    static void printInputEvent(InputEvent e) {
+        System.out.println(e);
+        if (e.isAltDown()) {
+            System.out.println("Alt is Down");
+        }
+        if (e.isControlDown()) {
+            System.out.println("Ctrl is Down");
+        }
+        if (e.isShiftDown()) {
+            System.out.println("Shift is Down");
+        }
+        if (e.isMetaDown()) {
+            System.out.println("Meta is Down");
+        }
+    }
+
+    static class TestCanvas extends Canvas {
+        public TestCanvas() {
+            setSize(100, 100);
+            setBackground(Color.blue);
+            enableEvents(AWTEvent.MOUSE_EVENT_MASK
+                         | AWTEvent.MOUSE_MOTION_EVENT_MASK
+                         | AWTEvent.KEY_EVENT_MASK);
+        }
+
+        protected void processMouseEvent(MouseEvent e) {
+            try {
+                if (testBtn == 0) {
+                    return;
+                }
+                if (e.getID() == MouseEvent.MOUSE_ENTERED
+                    || e.getID() == MouseEvent.MOUSE_EXITED)
+                {
+                    if ((e.getModifiers() & getMouseModifier(testBtn)) != 0) {
+                        System.out.println("Mouse modifiers on MOUSE_ENTERED, MOUSE_EXITED are set");
+                    } else {
+                        printInputEvent(e);
+                        System.out.println("Cur mods = " + (e.getModifiers() & allMouseMods) + " Wanted = " +
+                                          getMouseModifier(testBtn));
+                        passed = false;
+                        throw new RuntimeException("Mouse modifiers on MOUSE_ENTERED, MOUSE_EXITED aren't set");
+                    }
+                }
+                if (e.getID() == MouseEvent.MOUSE_PRESSED
+                    || e.getID() == MouseEvent.MOUSE_RELEASED)
+                {
+                    if ((e.getModifiers() & getMouseModifier(testBtn)) != 0) {
+                        System.out.println("Right Mouse modifiers on MOUSE_PRESSED, MOUSE_RELEASED");
+                    } else {
+                        printInputEvent(e);
+                        System.out.println("Cur mods = " + (e.getModifiers() & allMouseMods) + " Wanted = " +
+                                          getMouseModifier(testBtn));
+                        passed = false;
+                        throw new RuntimeException("Wrong Mouse modifiers on MOUSE_PRESSED, MOUSE_RELEASED");
+                    }
+                }
+            } finally {
+                synchronized (frame) {
+                    frame.notify();
+                }
+            }
+        }
+
+        protected void processMouseMotionEvent(MouseEvent e) {
+            try {
+                if (testBtn == 0) {
+                    return;
+                }
+                if (e.getID() == MouseEvent.MOUSE_DRAGGED) {
+                    if ((e.getModifiers() & getMouseModifier(testBtn)) != 0) {
+                        System.out.println("Mouse modifiers on MOUSE_DRAGGED are set");
+                    } else {
+                        printInputEvent(e);
+                        System.out.println("Cur mods = " + (e.getModifiers() & allMouseMods) + " Wanted = " +
+                                          getMouseModifier(testBtn));
+                        passed = false;
+                        throw new RuntimeException("Mouse modifiers on MOUSE_DRAGGED aren't set");
+                    }
+                }
+            } finally {
+                synchronized (frame) {
+                    frame.notify();
+                }
+            }
+        }
+
+        protected void processKeyEvent(KeyEvent e) {
+            try {
+                if (e.getKeyCode() != KeyEvent.VK_A) {
+                    return;
+                }
+                if ((e.getModifiers() & getKeyModifier(testCtrl)) != 0) {
+                    System.out.println("Right Key modifiers on KeyEvent");
+                } else {
+                    printInputEvent(e);
+                    passed = false;
+                    throw new RuntimeException("Wrong Key modifiers on KeyEvent");
+                }
+            } finally {
+                synchronized (frame) {
+                    frame.notify();
+                }
+            }
+        }
+    }
+}
diff --git a/test/jdk/java/awt/event/InvocationEvent/CatchingThrowableTest.java b/test/jdk/java/awt/event/InvocationEvent/CatchingThrowableTest.java
new file mode 100644
index 0000000000000..d75a7583155bb
--- /dev/null
+++ b/test/jdk/java/awt/event/InvocationEvent/CatchingThrowableTest.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2003, 2023, 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.
+ */
+
+/*
+  @test
+  @bug 4403712
+  @summary Error thrown in InvokeAndWait runnable causes hang
+  @run main CatchingThrowableTest
+*/
+
+import java.awt.EventQueue;
+
+public class CatchingThrowableTest {
+    public static void main(String args[]) {
+        try {
+            EventQueue.invokeAndWait(() -> {
+                throw new RuntimeException("My Error");
+            });
+        } catch (InterruptedException ex) {
+            ex.printStackTrace();
+        } catch (java.lang.reflect.InvocationTargetException ex) {
+            ex.printStackTrace();
+        }
+
+        System.err.println("Test passed.");
+    }
+}
diff --git a/test/jdk/java/awt/event/KeyEvent/AltGraphModifier.java b/test/jdk/java/awt/event/KeyEvent/AltGraphModifier.java
new file mode 100644
index 0000000000000..8d7ca8ea30fd3
--- /dev/null
+++ b/test/jdk/java/awt/event/KeyEvent/AltGraphModifier.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2000, 2023, 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.
+ */
+
+/*
+  @test
+  @bug 4343344
+  @summary Tests key modifiers when ALT_GRAPH key is pressed by Robot.
+  @key headful
+  @requires (os.family != "mac")
+  @run main AltGraphModifier
+*/
+
+import java.awt.AWTException;
+import java.awt.Color;
+import java.awt.EventQueue;
+import java.awt.FlowLayout;
+import java.awt.Frame;
+import java.awt.Robot;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+import java.lang.reflect.InvocationTargetException;
+
+
+public class AltGraphModifier {
+    static Frame frame;
+
+    static final int[] modifierKeys = {
+        KeyEvent.VK_ALT_GRAPH
+    };
+
+    static final int[] inputMasks = {
+        InputEvent.ALT_GRAPH_DOWN_MASK
+    };
+
+    static boolean[] modifierPress = new boolean[modifierKeys.length];
+
+    static volatile boolean modKeys;
+    static int modKeyCount;
+    static volatile boolean failed = false;
+
+
+    public static void main (String args[]) throws
+            InterruptedException, InvocationTargetException, AWTException {
+
+        EventQueue.invokeAndWait(() -> {
+            frame = new Frame("Modifier Robot Key BUG");
+            frame.setLayout(new FlowLayout());
+            frame.setSize(200, 200);
+            frame.addKeyListener(new KeyListener() {
+                @Override
+                public void keyTyped(KeyEvent e) {
+                }
+
+                @Override
+                public void keyPressed(KeyEvent kp){
+                    System.out.println(kp);
+                    if (modKeys == true) {
+                        for (int i=0; i < modifierKeys.length; i++) {
+                            if (modifierPress[i] == true) {
+                                if ((kp.getModifiersEx() & inputMasks[i]) == inputMasks[i]) {
+                                } else {
+                                    failed = true;
+                                }
+                            }
+                        }
+                    }
+                }
+
+                @Override
+                public void keyReleased(KeyEvent kr){
+                }
+            });
+            frame.setBackground(Color.blue);
+            frame.setVisible(true);
+        });
+
+        try {
+            Robot robot = new Robot();
+
+            robot.delay(1000);
+            robot.mouseMove((int) (frame.getLocationOnScreen().getX()
+                + frame.getWidth() / 2),
+                (int) (frame.getLocationOnScreen().getY()
+                + frame.getHeight() / 2));
+            robot.delay(1000);
+            robot.setAutoDelay(1000);
+
+            //Imbed operations here
+            modKeys = true;
+
+            for (modKeyCount = 0; modKeyCount < modifierKeys.length; modKeyCount++) {
+                //Press the Modifier Key
+                modifierPress[modKeyCount] = true;
+                robot.keyPress(modifierKeys[modKeyCount]);
+
+                frame.requestFocus();
+                robot.delay(1000);
+
+                //Press the Modifier Key
+                modifierPress[modKeyCount] = false;
+                robot.keyRelease(modifierKeys[modKeyCount]);
+                robot.delay(1000);
+            }
+        } finally {
+            EventQueue.invokeAndWait(() -> {
+                if (frame != null) {
+                    frame.dispose();
+                }
+            });
+        }
+
+        if (failed) {
+            throw new RuntimeException("FAIL MESSAGE ---- Modifier "
+                    +" Mask is not set when the Key : "
+                    +"AltGraph"
+                    + " Key is pressed by Robot.\n");
+        }
+    }
+}
diff --git a/test/jdk/java/awt/event/KeyEvent/KeyTyped/CancelKeyTyped.java b/test/jdk/java/awt/event/KeyEvent/KeyTyped/CancelKeyTyped.java
new file mode 100644
index 0000000000000..a557eab300f39
--- /dev/null
+++ b/test/jdk/java/awt/event/KeyEvent/KeyTyped/CancelKeyTyped.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2002, 2023, 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.
+ */
+
+/*
+ * @test
+ * @bug 4754155
+ * @summary Tests that KeyTyped events are fired for the Cancel key
+ *          and that no extraneous characters are entered as a result
+ * @key headful
+ * @run main CancelKeyTyped
+ */
+
+import java.awt.AWTException;
+import java.awt.EventQueue;
+import java.awt.Frame;
+import java.awt.Robot;
+import java.awt.TextField;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+import java.lang.reflect.InvocationTargetException;
+
+
+public class CancelKeyTyped {
+    static volatile boolean cancelKeyTypedReceived = false;
+    static Frame frame;
+    static TextField tf;
+    static final String ORIGINAL = "0123456789";
+
+    public static void main(String[] args) throws AWTException,
+            InterruptedException, InvocationTargetException {
+        try {
+            Robot robot = new Robot();
+            robot.setAutoWaitForIdle(true);
+            robot.setAutoDelay(100);
+
+            EventQueue.invokeAndWait(CancelKeyTyped::init);
+            robot.waitForIdle();
+            robot.delay(1000);
+
+            // Press and release Cancel
+            robot.keyPress(KeyEvent.VK_CANCEL);
+            robot.keyRelease(KeyEvent.VK_CANCEL);
+
+            if (cancelKeyTypedReceived) {
+                if (tf.getText().equals(ORIGINAL)) {
+                    System.out.println("Test PASSED");
+                } else {
+                    System.out.println("Test FAILED: wrong string");
+                    throw new RuntimeException("The test failed: wrong string: "
+                            + tf.getText());
+                }
+            }
+        } finally {
+            EventQueue.invokeAndWait(() -> {
+                if (frame != null) {
+                    frame.dispose();
+                }
+            });
+        }
+    }
+
+    public static void init() {
+        frame = new Frame("CancelKeyTyped");
+        tf = new TextField(ORIGINAL, 20);
+        frame.add(tf);
+        frame.setSize(300, 100);
+        frame.setVisible(true);
+        frame.validate();
+
+        tf.requestFocusInWindow();
+
+        tf.addKeyListener(new KeyListener() {
+            @Override
+            public void keyTyped(KeyEvent evt) {
+                printKey(evt);
+
+                int keychar = evt.getKeyChar();
+                if (keychar == 24) { // Cancel character is 24 or \u0018
+                    cancelKeyTypedReceived = true;
+                }
+            }
+
+            @Override
+            public void keyPressed(KeyEvent evt) {
+                printKey(evt);
+            }
+
+            @Override
+            public void keyReleased(KeyEvent evt) {
+                printKey(evt);
+            }
+
+            protected void printKey(KeyEvent evt) {
+                switch (evt.getID()) {
+                    case KeyEvent.KEY_TYPED:
+                    case KeyEvent.KEY_PRESSED:
+                    case KeyEvent.KEY_RELEASED:
+                        break;
+                    default:
+                        return;
+                }
+
+                System.out.println("params= " + evt.paramString() + "  \n" +
+                        "KeyChar: " + evt.getKeyChar() + " = " +
+                        (int) evt.getKeyChar() +
+                        "   KeyCode: " + evt.getKeyCode() +
+                        "   Modifiers: " + evt.getModifiersEx());
+
+                if (evt.isActionKey()) {
+                    System.out.println("Action Key");
+                }
+
+                System.out.println("keyText= " +
+                        evt.getKeyText(evt.getKeyCode()) + "\n");
+            }
+        });
+    }
+}