Skip to content

Commit f5e534a

Browse files
amartya4256fedejeanne
authored andcommitted
Destroy unused handles of resources
This Contribution destroys those handles for the resources which were created for zoom levels which no monitor has anymore. The process is triggered on a DPI_CHANGED event. contributes to eclipse-platform#62 and eclipse-platform#127
1 parent 30f11e9 commit f5e534a

File tree

8 files changed

+145
-20
lines changed

8 files changed

+145
-20
lines changed

bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/Resource.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
*******************************************************************************/
1414
package org.eclipse.swt.graphics;
1515

16+
import java.util.*;
1617
import java.util.function.*;
1718

1819
import org.eclipse.swt.*;
@@ -123,6 +124,17 @@ public Resource() {
123124
void destroy() {
124125
}
125126

127+
/**
128+
* Destroy all handles of the resource which are not necessary for the given
129+
* zoom levels. This method is supposed to be overridden by sub-classes that
130+
* retain handles for different zoom levels.
131+
*
132+
* @param zoomLevels The zoom levels for which the handles are supposed to be
133+
* retained.
134+
*/
135+
void destroyHandlesExcept(Set<Integer> zoomLevels) {
136+
}
137+
126138
/**
127139
* Disposes of the operating system resources associated with
128140
* this resource. Applications must dispose of all resources

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

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,14 @@
1414
package org.eclipse.swt.graphics;
1515

1616

17+
import java.util.*;
18+
import java.util.concurrent.*;
19+
1720
import org.eclipse.swt.*;
1821
import org.eclipse.swt.internal.*;
1922
import org.eclipse.swt.internal.gdip.*;
2023
import org.eclipse.swt.internal.win32.*;
24+
import org.eclipse.swt.widgets.*;
2125

2226
/**
2327
* This class is the abstract superclass of all device objects,
@@ -55,6 +59,7 @@ public abstract class Device implements Drawable {
5559
String[] loadedFonts;
5660

5761
volatile boolean disposed;
62+
private Set<Resource> resourcesWithZoomSupport = ConcurrentHashMap.newKeySet();
5863

5964
/*
6065
* TEMPORARY CODE. When a graphics object is
@@ -914,6 +919,8 @@ protected void release () {
914919
Gdip.GdiplusShutdown (gdipToken[0]);
915920
}
916921
SWTFontProvider.disposeFontRegistry(this);
922+
resourcesWithZoomSupport.clear();
923+
resourcesWithZoomSupport = null;
917924
gdipToken = null;
918925
scripts = null;
919926
logFonts = null;
@@ -947,4 +954,24 @@ public void setWarnings (boolean warnings) {
947954
protected int getDeviceZoom () {
948955
return DPIUtil.mapDPIToZoom ( _getDPIx ());
949956
}
957+
958+
void registerResourceWithZoomSupport(Resource resource) {
959+
resourcesWithZoomSupport.add(resource);
960+
}
961+
962+
/**
963+
* Destroys the handles of all the resources in the resource tracker by
964+
* identifying the zoom levels which is not valid for any monitor
965+
*
966+
* @noreference This method is not intended to be referenced by clients.
967+
*/
968+
public static void win32_destroyUnusedHandles(Display display) {
969+
Set<Integer> availableZoomLevels = new HashSet<>();
970+
for (Monitor monitor : display.getMonitors()) {
971+
availableZoomLevels.add(DPIUtil.getZoomForAutoscaleProperty(monitor.getZoom()));
972+
}
973+
for (Resource resource: ((Device) display).resourcesWithZoomSupport) {
974+
resource.destroyHandlesExcept(availableZoomLevels);
975+
}
976+
}
950977
}

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

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ public final class Image extends Resource implements Drawable {
164164
Image (Device device) {
165165
super(device);
166166
initialNativeZoom = DPIUtil.getNativeDeviceZoom();
167+
this.device.registerResourceWithZoomSupport(this);
167168
}
168169

169170
/**
@@ -209,6 +210,7 @@ public Image(Device device, int width, int height) {
209210
height = DPIUtil.scaleUp (height, zoom);
210211
init(width, height);
211212
init();
213+
this.device.registerResourceWithZoomSupport(this);
212214
}
213215

214216
/**
@@ -311,6 +313,7 @@ public Image(Device device, Image srcImage, int flag) {
311313
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
312314
}
313315
init();
316+
this.device.registerResourceWithZoomSupport(this);
314317
}
315318

316319
/**
@@ -355,6 +358,7 @@ public Image(Device device, Rectangle bounds) {
355358
bounds = DPIUtil.scaleUp (bounds, getZoom());
356359
init(bounds.width, bounds.height);
357360
init();
361+
this.device.registerResourceWithZoomSupport(this);
358362
}
359363

360364
/**
@@ -388,6 +392,7 @@ public Image(Device device, ImageData data) {
388392
data = DPIUtil.autoScaleUp(device, this.dataAtBaseZoom);
389393
init(data, getZoom());
390394
init();
395+
this.device.registerResourceWithZoomSupport(this);
391396
}
392397

393398
/**
@@ -434,6 +439,7 @@ public Image(Device device, ImageData source, ImageData mask) {
434439
mask = ImageData.convertMask(mask);
435440
init(this.device, this, source, mask, getZoom());
436441
init();
442+
this.device.registerResourceWithZoomSupport(this);
437443
}
438444

439445
/**
@@ -496,6 +502,7 @@ public Image (Device device, InputStream stream) {
496502
ImageData data = DPIUtil.autoScaleUp(device, this.dataAtBaseZoom);
497503
init(data, getZoom());
498504
init();
505+
this.device.registerResourceWithZoomSupport(this);
499506
}
500507

501508
/**
@@ -538,6 +545,7 @@ public Image (Device device, String filename) {
538545
ImageData data = DPIUtil.autoScaleUp(device, this.dataAtBaseZoom);
539546
init(data, getZoom());
540547
init();
548+
this.device.registerResourceWithZoomSupport(this);
541549
}
542550

543551
/**
@@ -586,6 +594,7 @@ public Image(Device device, ImageFileNameProvider imageFileNameProvider) {
586594
init(resizedData, getZoom());
587595
}
588596
init();
597+
this.device.registerResourceWithZoomSupport(this);
589598
}
590599

591600
/**
@@ -625,6 +634,7 @@ public Image(Device device, ImageDataProvider imageDataProvider) {
625634
ImageData resizedData = DPIUtil.scaleImageData(device, data.element(), getZoom(), data.zoom());
626635
init (resizedData, getZoom());
627636
init();
637+
this.device.registerResourceWithZoomSupport(this);
628638
}
629639

630640
private ImageData adaptImageDataIfDisabledOrGray(ImageData data) {
@@ -1186,16 +1196,32 @@ void destroy () {
11861196

11871197
private void destroyHandle () {
11881198
for (Long handle : zoomLevelToHandle.values()) {
1189-
if (type == SWT.ICON) {
1190-
OS.DestroyIcon (handle);
1191-
} else {
1192-
OS.DeleteObject (handle);
1193-
}
1199+
destroyHandle(handle);
11941200
}
11951201
zoomLevelToHandle.clear();
11961202
handle = 0;
11971203
}
11981204

1205+
@Override
1206+
void destroyHandlesExcept(Set<Integer> zoomLevels) {
1207+
zoomLevelToHandle.entrySet().removeIf(entry -> {
1208+
final Integer zoom = entry.getKey();
1209+
if (!zoomLevels.contains(zoom) && zoom != DPIUtil.getZoomForAutoscaleProperty(initialNativeZoom)) {
1210+
destroyHandle(entry.getValue());
1211+
return true;
1212+
}
1213+
return false;
1214+
});
1215+
}
1216+
1217+
private void destroyHandle(long handle) {
1218+
if (type == SWT.ICON) {
1219+
OS.DestroyIcon (handle);
1220+
} else {
1221+
OS.DeleteObject (handle);
1222+
}
1223+
}
1224+
11991225
/**
12001226
* Compares the argument to the receiver, and returns true
12011227
* if they represent the <em>same</em> object using a class

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ private Path(Device device, int zoom) {
8686
if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
8787
zoomLevelToHandle.put(initialZoom, handle);
8888
init();
89+
this.device.registerResourceWithZoomSupport(this);
8990
}
9091

9192
/**
@@ -133,6 +134,7 @@ public Path (Device device, Path path, float flatness) {
133134
initialZoom = path.initialZoom;
134135
zoomLevelToHandle.put(initialZoom, handle);
135136
init();
137+
this.device.registerResourceWithZoomSupport(this);
136138
}
137139

138140
/**
@@ -172,6 +174,7 @@ private Path(Device device, PathData data, int zoom) {
172174
this(device, zoom);
173175
if (data == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
174176
init(data);
177+
this.device.registerResourceWithZoomSupport(this);
175178
}
176179

177180
/**
@@ -438,6 +441,18 @@ void destroy() {
438441
zoomLevelToHandle.clear();
439442
}
440443

444+
@Override
445+
void destroyHandlesExcept(Set<Integer> zoomLevels) {
446+
zoomLevelToHandle.entrySet().removeIf(entry -> {
447+
final Integer zoom = entry.getKey();
448+
if (!zoomLevels.contains(zoom) && zoom != initialZoom) {
449+
Gdip.GraphicsPath_delete(entry.getValue());
450+
return true;
451+
}
452+
return false;
453+
});
454+
}
455+
441456
/**
442457
* Replaces the first four elements in the parameter with values that
443458
* describe the smallest rectangle that will completely contain the

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

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ public Pattern(Device device, Image image) {
9090
initialZoom = DPIUtil.getDeviceZoom();
9191
setImageHandle(image, initialZoom);
9292
init();
93+
this.device.registerResourceWithZoomSupport(this);
9394
}
9495

9596
/**
@@ -183,6 +184,7 @@ public Pattern(Device device, float x1, float y1, float x2, float y2, Color colo
183184
this.image = null;
184185
initialZoom = DPIUtil.getDeviceZoom();
185186
initializeSize(initialZoom);
187+
this.device.registerResourceWithZoomSupport(this);
186188
}
187189

188190
long getHandle(int zoom) {
@@ -260,21 +262,7 @@ void setImageHandle(Image image, int zoom) {
260262
@Override
261263
void destroy() {
262264
for (long handle: zoomLevelToHandle.values()) {
263-
int type = Gdip.Brush_GetType(handle);
264-
switch (type) {
265-
case Gdip.BrushTypeSolidColor:
266-
Gdip.SolidBrush_delete(handle);
267-
break;
268-
case Gdip.BrushTypeHatchFill:
269-
Gdip.HatchBrush_delete(handle);
270-
break;
271-
case Gdip.BrushTypeLinearGradient:
272-
Gdip.LinearGradientBrush_delete(handle);
273-
break;
274-
case Gdip.BrushTypeTextureFill:
275-
Gdip.TextureBrush_delete(handle);
276-
break;
277-
}
265+
destroyHandle(handle);
278266
}
279267
zoomLevelToHandle.clear();
280268
if (bitmapDestructor != null) {
@@ -283,6 +271,36 @@ void destroy() {
283271
}
284272
}
285273

274+
@Override
275+
void destroyHandlesExcept(Set<Integer> zoomLevels) {
276+
zoomLevelToHandle.entrySet().removeIf(entry -> {
277+
final Integer zoom = entry.getKey();
278+
if (!zoomLevels.contains(zoom) && zoom != initialZoom) {
279+
destroyHandle(entry.getValue());
280+
return true;
281+
}
282+
return false;
283+
});
284+
}
285+
286+
private void destroyHandle(long handle) {
287+
int type = Gdip.Brush_GetType(handle);
288+
switch (type) {
289+
case Gdip.BrushTypeSolidColor:
290+
Gdip.SolidBrush_delete(handle);
291+
break;
292+
case Gdip.BrushTypeHatchFill:
293+
Gdip.HatchBrush_delete(handle);
294+
break;
295+
case Gdip.BrushTypeLinearGradient:
296+
Gdip.LinearGradientBrush_delete(handle);
297+
break;
298+
case Gdip.BrushTypeTextureFill:
299+
Gdip.TextureBrush_delete(handle);
300+
break;
301+
}
302+
}
303+
286304
/**
287305
* Returns <code>true</code> if the Pattern has been disposed,
288306
* and <code>false</code> otherwise.

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ public Region (Device device) {
8484
zoomToHandle.put(initialZoom, handle);
8585
if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
8686
init();
87+
this.device.registerResourceWithZoomSupport(this);
8788
}
8889

8990
/**
@@ -227,6 +228,18 @@ void destroy () {
227228
operations.clear();
228229
}
229230

231+
@Override
232+
void destroyHandlesExcept(Set<Integer> zoomLevels) {
233+
zoomToHandle.entrySet().removeIf(entry -> {
234+
final Integer zoom = entry.getKey();
235+
if (!zoomLevels.contains(zoom) && zoom != initialZoom) {
236+
OS.DeleteObject(entry.getValue());
237+
return true;
238+
}
239+
return false;
240+
});
241+
}
242+
230243
/**
231244
* Compares the argument to the receiver, and returns true
232245
* if they represent the <em>same</em> object using a class

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ public Transform (Device device, float m11, float m12, float m21, float m22, flo
145145
if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
146146
zoomLevelToHandle.put(initialZoom, handle);
147147
init();
148+
this.device.registerResourceWithZoomSupport(this);
148149
}
149150

150151
static float[] checkTransform(float[] elements) {
@@ -159,6 +160,18 @@ void destroy() {
159160
zoomLevelToHandle.clear();
160161
}
161162

163+
@Override
164+
void destroyHandlesExcept(Set<Integer> zoomLevels) {
165+
zoomLevelToHandle.entrySet().removeIf(entry -> {
166+
final Integer zoom = entry.getKey();
167+
if (!zoomLevels.contains(zoom) && zoom != initialZoom) {
168+
Gdip.Matrix_delete(entry.getValue());
169+
return true;
170+
}
171+
return false;
172+
});
173+
}
174+
162175
/**
163176
* Fills the parameter with the values of the transformation matrix
164177
* that the receiver represents, in the order {m11, m12, m21, m22, dx, dy}.

bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Control.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4899,6 +4899,7 @@ LRESULT WM_DPICHANGED (long wParam, long lParam) {
48994899
// Map DPI to Zoom and compare
49004900
int newNativeZoom = DPIUtil.mapDPIToZoom (OS.HIWORD (wParam));
49014901
if (getDisplay().isRescalingAtRuntime()) {
4902+
Device.win32_destroyUnusedHandles(getDisplay());
49024903
int oldNativeZoom = nativeZoom;
49034904
if (newNativeZoom != oldNativeZoom) {
49044905
DPIUtil.setDeviceZoom (newNativeZoom);

0 commit comments

Comments
 (0)