Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion bundles/org.eclipse.jface/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.jface;singleton:=true
Bundle-Version: 3.35.100.qualifier
Bundle-Version: 3.35.200.qualifier
Bundle-Vendor: %providerName
Bundle-Localization: plugin
Export-Package: org.eclipse.jface,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.util.Policy;
Expand Down Expand Up @@ -207,7 +208,7 @@ void addAllocatedFontsToStale(Font defaultFont) {
*/
protected Runnable displayRunnable = this::clearCaches;

private boolean displayDisposeHooked;
private final Set<Display> displayDisposeHooked = ConcurrentHashMap.newKeySet();

private final boolean cleanOnDisplayDisposal;

Expand Down Expand Up @@ -492,7 +493,7 @@ private FontRecord createFont(String symbolicName, FontData[] fonts) {
if (display == null) {
return null;
}
if (cleanOnDisplayDisposal && !displayDisposeHooked) {
if (cleanOnDisplayDisposal && !displayDisposeHooked.contains(display)) {
hookDisplayDispose(display);
}

Expand Down Expand Up @@ -718,7 +719,7 @@ protected void clearCaches() {
stringToFontRecord.clear();
staleFonts.clear();

displayDisposeHooked = false;
displayDisposeHooked.remove(Display.getCurrent());
}

/**
Expand All @@ -736,7 +737,7 @@ private void disposeFonts(Iterator<Font> iterator) {
* Hook a dispose listener on the SWT display.
*/
private void hookDisplayDispose(Display display) {
displayDisposeHooked = true;
displayDisposeHooked.add(display);
display.disposeExec(displayRunnable);
}

Expand Down
2 changes: 1 addition & 1 deletion tests/org.eclipse.jface.tests/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %Bundle-Name
Bundle-SymbolicName: org.eclipse.jface.tests
Bundle-Version: 1.4.700.qualifier
Bundle-Version: 1.4.800.qualifier
Automatic-Module-Name: org.eclipse.jface.tests
Bundle-RequiredExecutionEnvironment: JavaSE-17
Require-Bundle: org.junit;bundle-version="4.12.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,20 @@
package org.eclipse.jface.tests.resources;

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;

import java.time.Duration;
import java.time.Instant;
import java.util.concurrent.atomic.AtomicReference;

import org.eclipse.core.runtime.Platform.OS;
import org.eclipse.jface.resource.FontRegistry;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.swt.graphics.Device;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.widgets.Display;
Expand All @@ -41,4 +53,48 @@ public void testBug544026() {
assertArrayEquals(fontData, JFaceResources.getDefaultFont().getFontData());
}

@Test
public void multipleDisplayDispose() {
assumeTrue("multiple Display instance only allowed on Windows", OS.isWindows());

FontRegistry fontRegistry = new FontRegistry();
Display secondDisplay = initializeDisplayInSeparateThread();
Font fontOnSecondDisplay = secondDisplay.syncCall(fontRegistry::defaultFont);

Font fontOnThisDisplayBeforeSecondDisplayDispose = fontRegistry.defaultFont();
Device displayOfFontOnSecondDisplay = fontOnSecondDisplay.getDevice();
// font registry returns same font for every display
assertEquals(secondDisplay, displayOfFontOnSecondDisplay);
assertEquals(fontOnThisDisplayBeforeSecondDisplayDispose, fontOnSecondDisplay);

// after disposing font's display, registry should reinitialize the font
secondDisplay.syncExec(secondDisplay::dispose);
assertTrue(fontOnSecondDisplay.isDisposed());
Font fontOnThisDisplayAfterSecondDisplayDispose = fontRegistry.defaultFont();
assertNotEquals(fontOnThisDisplayAfterSecondDisplayDispose, fontOnSecondDisplay);
}

private static Display initializeDisplayInSeparateThread() {
AtomicReference<Display> displayReference = new AtomicReference<>();
new Thread(() -> {
Display display = new Display();
displayReference.set(display);
while (!display.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
}, "async display creation").start();
waitForDisplayInstantiation(displayReference);
return displayReference.get();
}

private static void waitForDisplayInstantiation(AtomicReference<Display> displayReference) {
Instant maximumEndTime = Instant.now().plus(Duration.ofSeconds(10));
while (displayReference.get() == null) {
assertFalse("display was not instantiated in time", Instant.now().isAfter(maximumEndTime));
Thread.yield();
}
}

}
Loading