Skip to content

Commit 176f715

Browse files
fedejeannearunjose696
authored andcommitted
Check if the browser is disposed before scheduling runnable in Edge
For the unlikely (but possible) case in which the callback is executed too late and the browser/display has already been disposed. Add a new private method to funnel all calls to Display::asyncExec and check there if the display is still usable.
1 parent 10cc2e6 commit 176f715

File tree

10 files changed

+116
-65
lines changed

10 files changed

+116
-65
lines changed

bundles/org.eclipse.swt/Eclipse SWT Browser/win32/org/eclipse/swt/browser/Edge.java

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -840,7 +840,7 @@ void browserDispose(Event event) {
840840
if (inCallback > 0) {
841841
ICoreWebView2Controller controller1 = controller;
842842
controller.put_IsVisible(false);
843-
browser.getDisplay().asyncExec(() -> {
843+
asyncExec(() -> {
844844
controller1.Close();
845845
controller1.Release();
846846
});
@@ -1004,7 +1004,7 @@ private String getExposedUrl(String url) {
10041004
}
10051005

10061006
int handleCloseRequested(long pView, long pArgs) {
1007-
browser.getDisplay().asyncExec(() -> {
1007+
asyncExec(() -> {
10081008
if (browser.isDisposed()) return;
10091009
WindowEvent event = new WindowEvent(browser);
10101010
event.display = browser.getDisplay();
@@ -1022,7 +1022,7 @@ int handleDocumentTitleChanged(long pView, long pArgs) {
10221022
long[] ppsz = new long[1];
10231023
webViewProvider.getWebView(false).get_DocumentTitle(ppsz);
10241024
String title = wstrToString(ppsz[0], true);
1025-
browser.getDisplay().asyncExec(() -> {
1025+
asyncExec(() -> {
10261026
if (browser.isDisposed()) return;
10271027
TitleEvent event = new TitleEvent(browser);
10281028
event.display = browser.getDisplay();
@@ -1152,7 +1152,7 @@ int handleSourceChanged(long pView, long pArgs) {
11521152
} else {
11531153
location = url;
11541154
}
1155-
browser.getDisplay().asyncExec(() -> {
1155+
asyncExec(() -> {
11561156
if (browser.isDisposed()) return;
11571157
LocationEvent event = new LocationEvent(browser);
11581158
event.display = browser.getDisplay();
@@ -1169,7 +1169,7 @@ int handleSourceChanged(long pView, long pArgs) {
11691169
}
11701170

11711171
void sendProgressCompleted() {
1172-
browser.getDisplay().asyncExec(() -> {
1172+
asyncExec(() -> {
11731173
if (browser.isDisposed()) return;
11741174
ProgressEvent event = new ProgressEvent(browser);
11751175
event.display = browser.getDisplay();
@@ -1326,7 +1326,7 @@ int handleNavigationCompleted(long pView, long pArgs, boolean top) {
13261326
int[] pIsSuccess = new int[1];
13271327
args.get_IsSuccess(pIsSuccess);
13281328
if (pIsSuccess[0] != 0) {
1329-
browser.getDisplay().asyncExec(() -> {
1329+
asyncExec(() -> {
13301330
if (browser.isDisposed()) return;
13311331
LocationEvent event = new LocationEvent(browser);
13321332
event.display = browser.getDisplay();
@@ -1426,12 +1426,17 @@ int handleNewWindowRequested(long pView, long pArgs) {
14261426
if (inEvaluate) {
14271427
openWindowHandler.run();
14281428
} else {
1429-
browser.getDisplay().asyncExec(openWindowHandler);
1429+
asyncExec(openWindowHandler);
14301430
}
14311431

14321432
return COM.S_OK;
14331433
}
14341434

1435+
private void asyncExec(Runnable r) {
1436+
if (browser.isDisposed()) return;
1437+
browser.getDisplay().asyncExec(r);
1438+
}
1439+
14351440
int handleGotFocus(long pView, long pArg) {
14361441
if (ignoreGotFocus) {
14371442
ignoreGotFocus = false;

bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/graphics/Image.java

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -850,6 +850,9 @@ public Image(Device device, ImageDataProvider imageDataProvider) {
850850
try {
851851
init (data, 100);
852852
init ();
853+
StrictChecks.runIfStrictChecksEnabled(() -> {
854+
DPIUtil.validateLinearScaling(imageDataProvider);
855+
});
853856
ImageData data2x = imageDataProvider.getImageData (200);
854857
if (data2x != null) {
855858
alphaInfo_200 = new AlphaInfo();
@@ -1822,13 +1825,18 @@ public String toString () {
18221825
* @noreference This method is not intended to be referenced by clients.
18231826
*/
18241827
public static void drawScaled(GC gc, ImageData imageData, int width, int height, float scaleFactor) {
1825-
Image imageToDraw = new Image(gc.device, (ImageDataProvider) zoom -> imageData);
1826-
gc.drawImage (imageToDraw, 0, 0, CocoaDPIUtil.pixelToPoint (width), CocoaDPIUtil.pixelToPoint (height),
1827-
/* E.g. destWidth here is effectively DPIUtil.autoScaleDown (scaledWidth), but avoiding rounding errors.
1828-
* Nevertheless, we still have some rounding errors due to the point-based API GC#drawImage(..).
1829-
*/
1830-
0, 0, Math.round (CocoaDPIUtil.pixelToPoint (width * scaleFactor)), Math.round (CocoaDPIUtil.pixelToPoint (height * scaleFactor)));
1831-
imageToDraw.dispose();
1828+
StrictChecks.runWithStrictChecksDisabled(() -> {
1829+
Image imageToDraw = new Image(gc.device, (ImageDataProvider) zoom -> imageData);
1830+
gc.drawImage(imageToDraw, 0, 0, CocoaDPIUtil.pixelToPoint(width), CocoaDPIUtil.pixelToPoint(height),
1831+
/*
1832+
* E.g. destWidth here is effectively DPIUtil.autoScaleDown (scaledWidth), but
1833+
* avoiding rounding errors. Nevertheless, we still have some rounding errors
1834+
* due to the point-based API GC#drawImage(..).
1835+
*/
1836+
0, 0, Math.round(CocoaDPIUtil.pixelToPoint(width * scaleFactor)),
1837+
Math.round(CocoaDPIUtil.pixelToPoint(height * scaleFactor)));
1838+
imageToDraw.dispose();
1839+
});
18321840
}
18331841

18341842
}

bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/DPIUtil.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,26 @@ public static int mapZoomToDPI (int zoom) {
223223
return roundedDpi;
224224
}
225225

226+
public static void validateLinearScaling(ImageDataProvider provider) {
227+
final int baseZoom = 100;
228+
final int scaledZoom = 200;
229+
final int scaleFactor = scaledZoom / baseZoom;
230+
ImageData baseImageData = provider.getImageData(baseZoom);
231+
ImageData scaledImageData = provider.getImageData(scaledZoom);
232+
233+
if (scaledImageData == null) {
234+
return;
235+
}
236+
237+
if (scaledImageData.width != scaleFactor * baseImageData.width
238+
|| scaledImageData.height != scaleFactor * baseImageData.height) {
239+
System.err.println(String.format(
240+
"***WARNING: ImageData should be linearly scaled across zooms but size is (%d, %d) at 100%% and (%d, %d) at 200%%.",
241+
baseImageData.width, baseImageData.height, scaledImageData.width, scaledImageData.height));
242+
new Error().printStackTrace(System.err);
243+
}
244+
}
245+
226246
/**
227247
* Represents an element, such as some image data, at a specific zoom level.
228248
*
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2025 Yatta Solutions
3+
*
4+
* This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License 2.0
6+
* which accompanies this distribution, and is available at
7+
* https://www.eclipse.org/legal/epl-2.0/
8+
*
9+
* SPDX-License-Identifier: EPL-2.0
10+
*
11+
* Contributors:
12+
* Yatta Solutions - initial API and implementation
13+
*******************************************************************************/
14+
package org.eclipse.swt.internal;
15+
16+
public class StrictChecks {
17+
18+
private static final boolean STRICT_CHECKS =
19+
System.getProperty("org.eclipse.swt.internal.enableStrictChecks") != null;
20+
21+
private StrictChecks() {
22+
}
23+
24+
public static void runIfStrictChecksEnabled(Runnable runnable) {
25+
if (STRICT_CHECKS) {
26+
runnable.run();
27+
}
28+
}
29+
30+
public static void runWithStrictChecksDisabled(Runnable runnable) {
31+
if (!STRICT_CHECKS) {
32+
runnable.run();
33+
}
34+
}
35+
}

bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/Image.java

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -672,6 +672,9 @@ public Image(Device device, ImageDataProvider imageDataProvider) {
672672
currentDeviceZoom = DPIUtil.getDeviceZoom();
673673
initFromImageDataProvider(currentDeviceZoom);
674674
init ();
675+
StrictChecks.runIfStrictChecksEnabled(() -> {
676+
DPIUtil.validateLinearScaling(imageDataProvider);
677+
});
675678
}
676679

677680
/**
@@ -1583,13 +1586,17 @@ public String toString () {
15831586
* @noreference This method is not intended to be referenced by clients.
15841587
*/
15851588
public static void drawScaled(GC gc, ImageData imageData, int width, int height, float scaleFactor) {
1586-
Image imageToDraw = new Image(gc.device, (ImageDataProvider) zoom -> imageData);
1587-
gc.drawImage (imageToDraw, 0, 0, width, height,
1588-
/* E.g. destWidth here is effectively DPIUtil.autoScaleDown (scaledWidth), but avoiding rounding errors.
1589-
* Nevertheless, we still have some rounding errors due to the point-based API GC#drawImage(..).
1590-
*/
1591-
0, 0, Math.round (width * scaleFactor), Math.round (height * scaleFactor));
1592-
imageToDraw.dispose();
1589+
StrictChecks.runWithStrictChecksDisabled(() -> {
1590+
Image imageToDraw = new Image(gc.device, (ImageDataProvider) zoom -> imageData);
1591+
gc.drawImage(imageToDraw, 0, 0, width, height,
1592+
/*
1593+
* E.g. destWidth here is effectively DPIUtil.autoScaleDown (scaledWidth), but
1594+
* avoiding rounding errors. Nevertheless, we still have some rounding errors
1595+
* due to the point-based API GC#drawImage(..).
1596+
*/
1597+
0, 0, Math.round(width * scaleFactor), Math.round(height * scaleFactor));
1598+
imageToDraw.dispose();
1599+
});
15931600
}
15941601

15951602
}

bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,6 @@
116116
*/
117117
public class Display extends Device implements Executor {
118118

119-
static boolean strictChecks = System.getProperty("org.eclipse.swt.internal.enableStrictChecks") != null;
120-
121119
private static final int SLOT_IN_USE = -2;
122120
private static final int LAST_TABLE_INDEX = -1;
123121

@@ -880,12 +878,12 @@ void addWidget (long handle, Widget widget) {
880878
widgetTable = newWidgetTable;
881879
}
882880
int index = freeSlot + 1;
883-
if(strictChecks) {
881+
StrictChecks.runIfStrictChecksEnabled(() -> {
884882
long data = OS.g_object_get_qdata (handle, SWT_OBJECT_INDEX);
885883
if(data > 0 && data != index) {
886884
SWT.error(SWT.ERROR_INVALID_ARGUMENT, null, ". Potential leak of " + widget + debugInfoForIndex(data - 1));
887885
}
888-
}
886+
});
889887
OS.g_object_set_qdata (handle, SWT_OBJECT_INDEX, index);
890888
int oldSlot = freeSlot;
891889
freeSlot = indexTable[oldSlot];

bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Shell.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3258,14 +3258,14 @@ void deregister () {
32583258
if(shellHandle != 0 && !(disposed instanceof Shell)) {
32593259
SWT.error(SWT.ERROR_INVALID_RETURN_VALUE, null, ". Wrong widgetTable entry: " + disposed + " removed for shell: " + this + display.dumpWidgetTableInfo());
32603260
}
3261-
if(Display.strictChecks) {
3261+
StrictChecks.runIfStrictChecksEnabled(() -> {
32623262
Shell[] shells = display.getShells();
32633263
for (Shell shell : shells) {
32643264
if(shell == this) {
32653265
SWT.error(SWT.ERROR_INVALID_RETURN_VALUE, null, ". Disposed shell still in the widgetTable: " + this + display.dumpWidgetTableInfo());
32663266
}
32673267
}
3268-
}
3268+
});
32693269
}
32703270

32713271
boolean requiresUngrab () {

bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Device.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,6 @@
3434
*/
3535
public abstract class Device implements Drawable {
3636

37-
static boolean strictChecks = System.getProperty("org.eclipse.swt.internal.enableStrictChecks") != null;
38-
3937
/* Debugging */
4038
public static boolean DEBUG;
4139
boolean debug = DEBUG;

bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GC.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -210,9 +210,9 @@ private void validateGCState() {
210210
}
211211

212212
void checkGC(int mask) {
213-
if (Device.strictChecks) {
213+
StrictChecks.runIfStrictChecksEnabled(() -> {
214214
validateGCState();
215-
}
215+
});
216216
int state = data.state;
217217
if ((state & mask) == mask) return;
218218
state = (state ^ mask) & mask;
@@ -4402,10 +4402,10 @@ private void init(Drawable drawable, GCData data, long hDC) {
44024402
}
44034403

44044404
private static int extractZoom(long hDC) {
4405-
if (Device.strictChecks) {
4405+
StrictChecks.runIfStrictChecksEnabled(() -> {
44064406
System.err.println("***WARNING: GC is initialized with a missing zoom. This indicates an "
44074407
+ "incompatible custom Drawable implementation.");
4408-
}
4408+
});
44094409
long hwnd = OS.WindowFromDC(hDC);
44104410
long parentWindow = OS.GetAncestor(hwnd, OS.GA_ROOT);
44114411
long monitorParent = OS.MonitorFromWindow(parentWindow, OS.MONITOR_DEFAULTTONEAREST);

bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Image.java

Lines changed: 12 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -612,33 +612,13 @@ public Image(Device device, ImageDataProvider imageDataProvider) {
612612
SWT.error(SWT.ERROR_INVALID_ARGUMENT, null,
613613
": ImageDataProvider [" + imageDataProvider + "] returns null ImageData at 100% zoom.");
614614
}
615-
if (Device.strictChecks) {
616-
validateLinearScaling(imageDataProvider);
617-
}
615+
StrictChecks.runIfStrictChecksEnabled(() -> {
616+
DPIUtil.validateLinearScaling(imageDataProvider);
617+
});
618618
init();
619619
this.device.registerResourceWithZoomSupport(this);
620620
}
621621

622-
private void validateLinearScaling(ImageDataProvider provider) {
623-
final int baseZoom = 100;
624-
final int scaledZoom = 200;
625-
final int scaleFactor = scaledZoom / baseZoom;
626-
ImageData baseImageData = provider.getImageData(baseZoom);
627-
ImageData scaledImageData = provider.getImageData(scaledZoom);
628-
629-
if (scaledImageData == null) {
630-
return;
631-
}
632-
633-
if (scaledImageData.width != scaleFactor * baseImageData.width
634-
|| scaledImageData.height != scaleFactor * baseImageData.height) {
635-
System.err.println(String.format(
636-
"***WARNING: ImageData should be linearly scaled across zooms but size is (%d, %d) at 100%% and (%d, %d) at 200%%.",
637-
baseImageData.width, baseImageData.height, scaledImageData.width, scaledImageData.height));
638-
new Error().printStackTrace(System.err);
639-
}
640-
}
641-
642622
/**
643623
* The provided ImageGcDrawer will be called on demand whenever a new variant of the
644624
* Image for an additional zoom is required. Depending on the OS-specific implementation
@@ -851,13 +831,13 @@ public static long win32_getHandle (Image image, int zoom) {
851831
* @noreference This method is not intended to be referenced by clients.
852832
*/
853833
public static void drawScaled(GC gc, ImageData imageData, int width, int height, float scaleFactor) {
854-
boolean originalStrictChecks = Device.strictChecks;
855-
Device.strictChecks = false;
856-
Image imageToDraw = new Image(gc.device, (ImageDataProvider) zoom -> imageData);
857-
gc.drawImage (imageToDraw, 0, 0, width, height,
858-
0, 0, Math.round (width * scaleFactor), Math.round (height * scaleFactor), false);
859-
Device.strictChecks = originalStrictChecks;
860-
imageToDraw.dispose();
834+
835+
StrictChecks.runWithStrictChecksDisabled(() -> {
836+
Image imageToDraw = new Image(gc.device, (ImageDataProvider) zoom -> imageData);
837+
gc.drawImage(imageToDraw, 0, 0, width, height, 0, 0, Math.round(width * scaleFactor),
838+
Math.round(height * scaleFactor), false);
839+
imageToDraw.dispose();
840+
});
861841
}
862842

863843
long [] createGdipImage(Integer zoom) {
@@ -1753,9 +1733,9 @@ private long configureGC(GCData data, ZoomContext zoomContext) {
17531733
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
17541734
}
17551735

1756-
if (Device.strictChecks) {
1736+
StrictChecks.runIfStrictChecksEnabled(() -> {
17571737
checkImageTypeForValidCustomDrawing(zoomContext.targetZoom());
1758-
}
1738+
});
17591739
/* Create a compatible HDC for the device */
17601740
long hDC = device.internal_new_GC(null);
17611741
long imageDC = OS.CreateCompatibleDC(hDC);

0 commit comments

Comments
 (0)