diff options
author | Anton Tarasov <anton.tarasov@jetbrains.com> | 2022-04-11 21:18:32 +0300 |
---|---|---|
committer | Anton Tarasov <anton.tarasov@jetbrains.com> | 2022-04-12 15:50:50 +0300 |
commit | 7efb0075bc846235a03c040b70c9abb522fb08e0 (patch) | |
tree | 2bc6fb93c94f9a6e2951d4ad0cf2b575c4ba5c84 | |
parent | 413ff95d63afb99bb09ec2b901f0ed2c877e591b (diff) | |
download | JetBrainsRuntime-jb17-b390.tar.gz |
JBR-4362 [mac] system menu opens with duplicated itemsjb17-b390
(cherry picked from commit e32defe49d3aed2ab438ce8d14a387b9679fae43)
5 files changed, 84 insertions, 9 deletions
diff --git a/src/java.desktop/share/classes/sun/awt/AWTThreading.java b/src/java.desktop/share/classes/sun/awt/AWTThreading.java index b19eaecbec9..cf7e8988d46 100644 --- a/src/java.desktop/share/classes/sun/awt/AWTThreading.java +++ b/src/java.desktop/share/classes/sun/awt/AWTThreading.java @@ -306,19 +306,24 @@ public class AWTThreading { @Override public void dispatch() { - completeIfNotYet(super::dispatch); - futureResult.complete(null); + // Should not complete if competion has already started. + if (completeIfNotYet(super::dispatch)) { + futureResult.complete(null); + } } public void dispose(String reason) { completeIfNotYet(() -> AWTAccessor.getInvocationEventAccessor().dispose(this)); + // Should complete exceptionally regardless of whether completetion has alredy started or hasn't. futureResult.completeExceptionally(new Throwable(reason)); } - private void completeIfNotYet(Runnable competeRunnable) { + private boolean completeIfNotYet(Runnable competeRunnable) { if (!isCompletionStarted.getAndSet(true)) { competeRunnable.run(); + return true; } + return false; } /** diff --git a/test/jdk/jb/java/awt/Toolkit/AWTThreadingTest.java b/test/jdk/jb/java/awt/Toolkit/AWTThreadingTest.java index 2778c3eeb98..3f1c7e9abca 100644 --- a/test/jdk/jb/java/awt/Toolkit/AWTThreadingTest.java +++ b/test/jdk/jb/java/awt/Toolkit/AWTThreadingTest.java @@ -5,6 +5,7 @@ import java.util.Arrays; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Consumer; import java.util.function.Supplier; import sun.lwawt.macosx.CThreading; @@ -38,18 +39,24 @@ public class AWTThreadingTest { testCase(). withCaption("certain threads superposition"). - withRunnable(AWTThreadingTest::test, false). + withRunnable(AWTThreadingTest::test1, false). run(); testCase(). withCaption("random threads superposition"). - withRunnable(AWTThreadingTest::test, false). + withRunnable(AWTThreadingTest::test1, false). + run(); + + testCase(). + withCaption("JBR-4362"). + withRunnable(AWTThreadingTest::test2, false). + withCompletionTimeout(3). run(); System.out.println("Test PASSED"); } - static void test() { + static void test1() { ITER_COUNTER.set(0); var timer = new TestTimer(TIMEOUT_SECONDS * 3, TimeUnit.SECONDS); @@ -124,6 +131,53 @@ public class AWTThreadingTest { THREAD.start(); } + static void test2() { + var invocations = new CountDownLatch(1); + var invokeAndWaitCompleted = new AtomicBoolean(false); + + var log = new Consumer<String>() { + public void accept(String msg) { + System.out.println(msg); + System.out.flush(); + } + }; + + CThreading.executeOnAppKit(() -> { + log.accept("executeOnAppKit - entered"); + + // + // It's expected that LWCToolkit.invokeAndWait() does not exit before its invocation completes. + // + tryRun(() -> LWCToolkit.invokeAndWait(() -> { + log.accept("\tinvokeAndWait - entered"); + + AWTThreading.executeWaitToolkit(() -> { + log.accept("\t\texecuteWaitToolkit - entered"); + + LWCToolkit.performOnMainThreadAndWait(() -> log.accept("\t\t\tperformOnMainThreadAndWait - entered")); + + log.accept("\t\t\tperformOnMainThreadAndWait - exited"); + }); + + invokeAndWaitCompleted.set(true); + log.accept("\t\texecuteWaitToolkit - exited"); + }, FRAME)); + + log.accept("\tinvokeAndWait - exited"); + + if (!invokeAndWaitCompleted.get()) { + TEST_CASE_RESULT.completeExceptionally(new Throwable("Premature exit from invokeAndWait")); + } + + invocations.countDown(); + }); + + await(invocations, TIMEOUT_SECONDS * 2); + log.accept("executeOnAppKit + await - exited"); + + TEST_CASE_RESULT.complete(true); + } + static void dumpAllThreads() { Thread.getAllStackTraces().keySet().forEach(t -> { System.out.printf("%s\t%s\t%d\t%s\n", t.getName(), t.getState(), t.getPriority(), t.isDaemon() ? "Daemon" : "Normal"); diff --git a/test/jdk/jb/java/awt/Toolkit/LWCToolkitInvokeAndWaitTest.java b/test/jdk/jb/java/awt/Toolkit/LWCToolkitInvokeAndWaitTest.java index 53dfeb951bc..77dd2c35479 100644 --- a/test/jdk/jb/java/awt/Toolkit/LWCToolkitInvokeAndWaitTest.java +++ b/test/jdk/jb/java/awt/Toolkit/LWCToolkitInvokeAndWaitTest.java @@ -18,8 +18,8 @@ import static helper.ToolkitTestHelper.TestCase.*; * @summary Tests different scenarios for LWCToolkit.invokeAndWait(). * @requires (os.family == "mac") * @modules java.desktop/sun.lwawt.macosx java.desktop/sun.awt - * @run main/othervm -Dsun.lwawt.macosx.LWCToolkit.invokeAndWait.disposeOnEDTFree=true LWCToolkitInvokeAndWaitTest - * @run main/othervm -Dlog.level.FINER=true -Dsun.lwawt.macosx.LWCToolkit.invokeAndWait.disposeOnEDTFree=true LWCToolkitInvokeAndWaitTest + * @run main LWCToolkitInvokeAndWaitTest + * @run main/othervm -Dlog.level.FINER=true LWCToolkitInvokeAndWaitTest * @author Anton Tarasov */ @SuppressWarnings("ConstantConditions") @@ -32,6 +32,8 @@ public class LWCToolkitInvokeAndWaitTest { static volatile CountDownLatch EDT_FAST_FREE_LATCH; static { + System.setProperty("sun.lwawt.macosx.LWCToolkit.invokeAndWait.disposeOnEDTFree", "true"); + AWTThreading.setAWTThreadingFactory(edt -> new AWTThreading(edt) { @Override public CompletableFuture<Void> onEventDispatchThreadFree(Runnable runnable) { diff --git a/test/jdk/jb/java/awt/Toolkit/helper/ToolkitTestHelper.java b/test/jdk/jb/java/awt/Toolkit/helper/ToolkitTestHelper.java index 510c293d658..3e8383a2edc 100644 --- a/test/jdk/jb/java/awt/Toolkit/helper/ToolkitTestHelper.java +++ b/test/jdk/jb/java/awt/Toolkit/helper/ToolkitTestHelper.java @@ -8,6 +8,8 @@ import sun.lwawt.macosx.LWCToolkit; import javax.swing.*; import javax.swing.Timer; import java.awt.*; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; import java.util.Optional; import java.util.Random; import java.util.concurrent.Callable; @@ -65,6 +67,7 @@ public class ToolkitTestHelper { handler.uncaughtException(t, e); }); + CountDownLatch showLatch = new CountDownLatch(1); tryRun(() -> EventQueue.invokeAndWait(() -> { FRAME = new JFrame(testClass.getSimpleName()); LABEL = new JLabel("0"); @@ -75,8 +78,16 @@ public class ToolkitTestHelper { FRAME.setLocationRelativeTo(null); FRAME.setSize(200, 200); FRAME.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); + FRAME.addComponentListener(new ComponentAdapter() { + @Override + public void componentShown(ComponentEvent e) { + showLatch.countDown(); + } + }); FRAME.setVisible(true); })); + //noinspection ResultOfMethodCallIgnored + tryRun(() -> showLatch.await(1, TimeUnit.SECONDS)); Timer timer = new Timer(100, e -> UPDATE_LABEL.run()); timer.setRepeats(true); diff --git a/test/jdk/jbA11yProblemList.txt b/test/jdk/jbA11yProblemList.txt index 86e550dd76f..a07167703da 100644 --- a/test/jdk/jbA11yProblemList.txt +++ b/test/jdk/jbA11yProblemList.txt @@ -1 +1,4 @@ -sanity/client/SwingSet/src/TreeDemoTest.java JBR-3389 macosx-all +java/awt/Toolkit/LWCToolkitInvokeAndWaitTest.java nobug macosx-all,linux-all,windows-all +java/awt/Toolkit/AWTThreadingTest.java nobug macosx-all,linux-all,windows-all +java/awt/Toolkit/AWTThreadingCMenuTest.java nobug macosx-all,linux-all,windows-all +sanity/client/SwingSet/src/TreeDemoTest.java JBR-3389 macosx-all |