JBR-4362 [mac] system menu opens with duplicated items

(cherry picked from commit e32defe49d)
This commit is contained in:
Anton Tarasov
2022-04-11 21:18:32 +03:00
committed by jbrbot
parent 310c6feb92
commit d1367f4f27
5 changed files with 83 additions and 8 deletions

View File

@@ -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;
}
/**

View File

@@ -26,6 +26,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;
@@ -59,18 +60,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);
@@ -145,6 +152,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");

View File

@@ -39,8 +39,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")
@@ -53,6 +53,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) {

View File

@@ -29,6 +29,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;
@@ -86,6 +88,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");
@@ -96,8 +99,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);

View File

@@ -0,0 +1,3 @@
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