Skip to content

Commit 99f22f7

Browse files
committed
Destroy unused handles od 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 #62 and #127
1 parent 02e20d6 commit 99f22f7

File tree

10 files changed

+172
-58
lines changed

10 files changed

+172
-58
lines changed

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -693,6 +693,9 @@ public boolean loadFont (String path) {
693693
}
694694

695695
void new_Object (Object object) {
696+
if (!tracking) {
697+
return;
698+
}
696699
synchronized (trackingLock) {
697700
for (int i=0; i<objects.length; i++) {
698701
if (objects [i] == null) {

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

Lines changed: 15 additions & 1 deletion
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,19 @@ public Resource() {
123124
void destroy() {
124125
}
125126

127+
/**
128+
* This method is supposed to be overridden by those resources which contain
129+
* multiple handles for different zoom levels. The method destroys handles of
130+
* the resource for all the zoom levels expect for the those passed in the
131+
* argument.
132+
*
133+
* @param zoomLevels The zoom levels for which the handles are supposed to be
134+
* retained.
135+
*/
136+
void destroyHandlesExcept(Set<Integer> zoomLevels) {
137+
138+
}
139+
126140
/**
127141
* Disposes of the operating system resources associated with
128142
* this resource. Applications must dispose of all resources
@@ -158,7 +172,7 @@ void ignoreNonDisposed() {
158172
}
159173

160174
void init() {
161-
if (device.tracking) device.new_Object(this);
175+
device.new_Object(this);
162176
}
163177

164178
void initNonDisposeTracking() {

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -911,6 +911,9 @@ long logProc (long log_domain, long log_level, long message, long user_data) {
911911
}
912912

913913
void new_Object (Object object) {
914+
if (!tracking) {
915+
return;
916+
}
914917
synchronized (trackingLock) {
915918
for (int i=0; i<objects.length; i++) {
916919
if (objects [i] == null) {

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

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

1616

17+
import java.util.*;
18+
1719
import org.eclipse.swt.*;
1820
import org.eclipse.swt.internal.*;
1921
import org.eclipse.swt.internal.gdip.*;
2022
import org.eclipse.swt.internal.win32.*;
23+
import org.eclipse.swt.widgets.*;
2124

2225
/**
2326
* This class is the abstract superclass of all device objects,
@@ -117,6 +120,7 @@ public Device(DeviceData data) {
117120
debug = data.debug;
118121
tracking = data.tracking;
119122
}
123+
initializeObjects();
120124
if (tracking) {
121125
startTracking();
122126
}
@@ -148,26 +152,25 @@ public void setTracking(boolean tracking) {
148152
if (tracking == this.tracking) {
149153
return;
150154
}
151-
this.tracking = tracking;
155+
initializeObjects();
152156
if (tracking) {
153157
startTracking();
154158
} else {
155159
stopTracking();
156160
}
157161
}
158162

159-
private void startTracking() {
160-
errors = new Error [128];
163+
private void initializeObjects() {
161164
objects = new Object [128];
162165
trackingLock = new Object ();
163166
}
164167

168+
private void startTracking() {
169+
errors = new Error [128];
170+
}
171+
165172
private void stopTracking() {
166-
synchronized (trackingLock) {
167-
objects = null;
168-
errors = null;
169-
trackingLock = null;
170-
}
173+
errors = null;
171174
}
172175

173176

@@ -336,13 +339,13 @@ public void dispose () {
336339

337340
destroy ();
338341
disposed = true;
339-
if (tracking) {
340-
synchronized (trackingLock) {
341-
printErrors ();
342-
objects = null;
342+
synchronized (trackingLock) {
343+
printErrors ();
344+
objects = null;
345+
if (tracking) {
343346
errors = null;
344-
trackingLock = null;
345347
}
348+
trackingLock = null;
346349
}
347350
}
348351
}
@@ -353,7 +356,9 @@ void dispose_Object (Object object) {
353356
for (int i=0; i<objects.length; i++) {
354357
if (objects [i] == object) {
355358
objects [i] = null;
356-
errors [i] = null;
359+
if(tracking) {
360+
errors [i] = null;
361+
}
357362
return;
358363
}
359364
}
@@ -436,26 +441,27 @@ public DeviceData getDeviceData () {
436441
DeviceData data = new DeviceData ();
437442
data.debug = debug;
438443
data.tracking = tracking;
439-
if (tracking) {
440-
synchronized (trackingLock) {
441-
int count = 0, length = objects.length;
442-
for (int i=0; i<length; i++) {
443-
if (objects [i] != null) count++;
444-
}
445-
int index = 0;
446-
data.objects = new Object [count];
444+
synchronized (trackingLock) {
445+
int count = 0, length = objects.length;
446+
for (int i=0; i<length; i++) {
447+
if (objects [i] != null) count++;
448+
}
449+
int index = 0;
450+
data.objects = new Object [count];
451+
if (tracking) {
447452
data.errors = new Error [count];
448-
for (int i=0; i<length; i++) {
449-
if (objects [i] != null) {
450-
data.objects [index] = objects [i];
453+
} else {
454+
data.errors = new Error [0];
455+
}
456+
for (int i=0; i<length; i++) {
457+
if (objects [i] != null) {
458+
data.objects [index] = objects [i];
459+
if (tracking) {
451460
data.errors [index] = errors [i];
452-
index++;
453461
}
462+
index++;
454463
}
455464
}
456-
} else {
457-
data.objects = new Object [0];
458-
data.errors = new Error [0];
459465
}
460466
return data;
461467
}
@@ -820,26 +826,30 @@ void new_Object (Object object) {
820826
for (int i=0; i<objects.length; i++) {
821827
if (objects [i] == null) {
822828
objects [i] = object;
823-
errors [i] = new Error ();
829+
if (tracking) {
830+
errors [i] = new Error ();
831+
}
824832
return;
825833
}
826834
}
827835
Object [] newObjects = new Object [objects.length + 128];
828836
System.arraycopy (objects, 0, newObjects, 0, objects.length);
829837
newObjects [objects.length] = object;
830838
objects = newObjects;
831-
Error [] newErrors = new Error [errors.length + 128];
832-
System.arraycopy (errors, 0, newErrors, 0, errors.length);
833-
newErrors [errors.length] = new Error ();
834-
errors = newErrors;
839+
if (tracking) {
840+
Error [] newErrors = new Error [errors.length + 128];
841+
System.arraycopy (errors, 0, newErrors, 0, errors.length);
842+
newErrors [errors.length] = new Error ();
843+
errors = newErrors;
844+
}
835845
}
836846
}
837847

838848
void printErrors () {
839849
if (!DEBUG) return;
840850
if (tracking) {
841851
synchronized (trackingLock) {
842-
if (objects == null || errors == null) return;
852+
if (objects == null && errors == null) return;
843853
int objectCount = 0;
844854
int colors = 0, cursors = 0, fonts = 0, gcs = 0, images = 0;
845855
int paths = 0, patterns = 0, regions = 0, textLayouts = 0, transforms = 0;
@@ -874,8 +884,10 @@ void printErrors () {
874884
string = string.substring (0, string.length () - 2);
875885
System.err.println (string);
876886
}
877-
for (Error error : errors) {
878-
if (error != null) error.printStackTrace (System.err);
887+
if(tracking) {
888+
for (Error error : errors) {
889+
if (error != null) error.printStackTrace (System.err);
890+
}
879891
}
880892
}
881893
}
@@ -947,4 +959,22 @@ public void setWarnings (boolean warnings) {
947959
protected int getDeviceZoom () {
948960
return DPIUtil.mapDPIToZoom ( _getDPIx ());
949961
}
962+
963+
/**
964+
* Destroys the handles of all the resources in the resource tracker by
965+
* identifying the zoom levels which is not valid for any monitor
966+
*
967+
* @noreference This method is not intended to be referenced by clients.
968+
*/
969+
public static void win32_destroyUnusedHandles(Display display) {
970+
Set<Integer> availableZoomLevels = new HashSet<>();
971+
for (Monitor monitor : display.getMonitors()) {
972+
availableZoomLevels.add(DPIUtil.getZoomForAutoscaleProperty(monitor.getZoom()));
973+
}
974+
for (Object object: ((Device) display).objects) {
975+
if (object instanceof Resource resource) {
976+
resource.destroyHandlesExcept(availableZoomLevels);
977+
}
978+
}
979+
}
950980
}

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

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1186,16 +1186,31 @@ void destroy () {
11861186

11871187
private void destroyHandle () {
11881188
for (Long handle : zoomLevelToHandle.values()) {
1189-
if (type == SWT.ICON) {
1190-
OS.DestroyIcon (handle);
1191-
} else {
1192-
OS.DeleteObject (handle);
1193-
}
1189+
destroyHandle(handle);
11941190
}
11951191
zoomLevelToHandle.clear();
11961192
handle = 0;
11971193
}
11981194

1195+
@Override
1196+
void destroyHandlesExcept(Set<Integer> zoomLevels) {
1197+
zoomLevelToHandle.entrySet().removeIf(entry -> {
1198+
if (!zoomLevels.contains(entry.getKey()) && entry.getKey() != DPIUtil.getZoomForAutoscaleProperty(initialNativeZoom)) {
1199+
destroyHandle(entry.getValue());
1200+
return true;
1201+
}
1202+
return false;
1203+
});
1204+
}
1205+
1206+
private void destroyHandle(long handle) {
1207+
if (type == SWT.ICON) {
1208+
OS.DestroyIcon (handle);
1209+
} else {
1210+
OS.DeleteObject (handle);
1211+
}
1212+
}
1213+
11991214
/**
12001215
* Compares the argument to the receiver, and returns true
12011216
* 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: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,17 @@ void destroy() {
438438
zoomLevelToHandle.clear();
439439
}
440440

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

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

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -260,21 +260,7 @@ void setImageHandle(Image image, int zoom) {
260260
@Override
261261
void destroy() {
262262
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-
}
263+
destroyHandle(handle);
278264
}
279265
zoomLevelToHandle.clear();
280266
if (bitmapDestructor != null) {
@@ -283,6 +269,35 @@ void destroy() {
283269
}
284270
}
285271

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

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,17 @@ void destroy () {
227227
operations.clear();
228228
}
229229

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

0 commit comments

Comments
 (0)