From 99f22f72c34f3a3d52abc5ccb012c77bc16cc63e Mon Sep 17 00:00:00 2001 From: Amartya Parijat Date: Wed, 18 Sep 2024 17:46:49 +0200 Subject: [PATCH] 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 --- .../org/eclipse/swt/graphics/Device.java | 3 + .../org/eclipse/swt/graphics/Resource.java | 16 ++- .../gtk/org/eclipse/swt/graphics/Device.java | 3 + .../org/eclipse/swt/graphics/Device.java | 104 +++++++++++------- .../win32/org/eclipse/swt/graphics/Image.java | 25 ++++- .../win32/org/eclipse/swt/graphics/Path.java | 11 ++ .../org/eclipse/swt/graphics/Pattern.java | 45 +++++--- .../org/eclipse/swt/graphics/Region.java | 11 ++ .../org/eclipse/swt/graphics/Transform.java | 11 ++ .../org/eclipse/swt/widgets/Control.java | 1 + 10 files changed, 172 insertions(+), 58 deletions(-) diff --git a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/graphics/Device.java b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/graphics/Device.java index ef30e780765..fabbc880925 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/graphics/Device.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/graphics/Device.java @@ -693,6 +693,9 @@ public boolean loadFont (String path) { } void new_Object (Object object) { + if (!tracking) { + return; + } synchronized (trackingLock) { for (int i=0; i zoomLevels) { + +} + /** * Disposes of the operating system resources associated with * this resource. Applications must dispose of all resources @@ -158,7 +172,7 @@ void ignoreNonDisposed() { } void init() { - if (device.tracking) device.new_Object(this); + device.new_Object(this); } void initNonDisposeTracking() { diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/Device.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/Device.java index 3363ea5ae86..82b74976a1b 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/Device.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/Device.java @@ -911,6 +911,9 @@ long logProc (long log_domain, long log_level, long message, long user_data) { } void new_Object (Object object) { + if (!tracking) { + return; + } synchronized (trackingLock) { for (int i=0; i availableZoomLevels = new HashSet<>(); + for (Monitor monitor : display.getMonitors()) { + availableZoomLevels.add(DPIUtil.getZoomForAutoscaleProperty(monitor.getZoom())); + } + for (Object object: ((Device) display).objects) { + if (object instanceof Resource resource) { + resource.destroyHandlesExcept(availableZoomLevels); + } + } +} } diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Image.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Image.java index afed0488e7e..6d1153e4f73 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Image.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Image.java @@ -1186,16 +1186,31 @@ void destroy () { private void destroyHandle () { for (Long handle : zoomLevelToHandle.values()) { - if (type == SWT.ICON) { - OS.DestroyIcon (handle); - } else { - OS.DeleteObject (handle); - } + destroyHandle(handle); } zoomLevelToHandle.clear(); handle = 0; } +@Override +void destroyHandlesExcept(Set zoomLevels) { + zoomLevelToHandle.entrySet().removeIf(entry -> { + if (!zoomLevels.contains(entry.getKey()) && entry.getKey() != DPIUtil.getZoomForAutoscaleProperty(initialNativeZoom)) { + destroyHandle(entry.getValue()); + return true; + } + return false; + }); +} + +private void destroyHandle(long handle) { + if (type == SWT.ICON) { + OS.DestroyIcon (handle); + } else { + OS.DeleteObject (handle); + } +} + /** * Compares the argument to the receiver, and returns true * if they represent the same object using a class diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Path.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Path.java index 54d392f09a6..79ef7756065 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Path.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Path.java @@ -438,6 +438,17 @@ void destroy() { zoomLevelToHandle.clear(); } +@Override +void destroyHandlesExcept(Set zoomLevels) { + zoomLevelToHandle.entrySet().removeIf(entry -> { + if (!zoomLevels.contains(entry.getKey()) && entry.getKey() != initialZoom) { + Gdip.GraphicsPath_delete(entry.getValue()); + return true; + } + return false; + }); +} + /** * Replaces the first four elements in the parameter with values that * describe the smallest rectangle that will completely contain the diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Pattern.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Pattern.java index 02a065f325f..0c1c43725af 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Pattern.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Pattern.java @@ -260,21 +260,7 @@ void setImageHandle(Image image, int zoom) { @Override void destroy() { for (long handle: zoomLevelToHandle.values()) { - int type = Gdip.Brush_GetType(handle); - switch (type) { - case Gdip.BrushTypeSolidColor: - Gdip.SolidBrush_delete(handle); - break; - case Gdip.BrushTypeHatchFill: - Gdip.HatchBrush_delete(handle); - break; - case Gdip.BrushTypeLinearGradient: - Gdip.LinearGradientBrush_delete(handle); - break; - case Gdip.BrushTypeTextureFill: - Gdip.TextureBrush_delete(handle); - break; - } + destroyHandle(handle); } zoomLevelToHandle.clear(); if (bitmapDestructor != null) { @@ -283,6 +269,35 @@ void destroy() { } } +@Override +void destroyHandlesExcept(Set zoomLevels) { + zoomLevelToHandle.entrySet().removeIf(entry -> { + if (!zoomLevels.contains(entry.getKey()) && entry.getKey() != initialZoom) { + destroyHandle(entry.getValue()); + return true; + } + return false; + }); +} + +private void destroyHandle(long handle) { + int type = Gdip.Brush_GetType(handle); + switch (type) { + case Gdip.BrushTypeSolidColor: + Gdip.SolidBrush_delete(handle); + break; + case Gdip.BrushTypeHatchFill: + Gdip.HatchBrush_delete(handle); + break; + case Gdip.BrushTypeLinearGradient: + Gdip.LinearGradientBrush_delete(handle); + break; + case Gdip.BrushTypeTextureFill: + Gdip.TextureBrush_delete(handle); + break; + } +} + /** * Returns true if the Pattern has been disposed, * and false otherwise. diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Region.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Region.java index 6c726998146..7c0d161de96 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Region.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Region.java @@ -227,6 +227,17 @@ void destroy () { operations.clear(); } +@Override +void destroyHandlesExcept(Set zoomLevels) { + zoomToHandle.entrySet().removeIf(entry -> { + if (!zoomLevels.contains(entry.getKey()) && entry.getKey() != initialZoom) { + OS.DeleteObject(entry.getValue()); + return true; + } + return false; + }); +} + /** * Compares the argument to the receiver, and returns true * if they represent the same object using a class diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Transform.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Transform.java index 058974d7a0f..987fd761441 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Transform.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Transform.java @@ -159,6 +159,17 @@ void destroy() { zoomLevelToHandle.clear(); } +@Override +void destroyHandlesExcept(Set zoomLevels) { + zoomLevelToHandle.entrySet().removeIf(entry -> { + if (!zoomLevels.contains(entry.getKey()) && entry.getKey() != initialZoom) { + Gdip.Matrix_delete(entry.getValue()); + return true; + } + return false; + }); +} + /** * Fills the parameter with the values of the transformation matrix * that the receiver represents, in the order {m11, m12, m21, m22, dx, dy}. diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Control.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Control.java index 03c32a4c72d..9bb56a990f2 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Control.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Control.java @@ -4901,6 +4901,7 @@ LRESULT WM_DPICHANGED (long wParam, long lParam) { // Map DPI to Zoom and compare int newNativeZoom = DPIUtil.mapDPIToZoom (OS.HIWORD (wParam)); if (getDisplay().isRescalingAtRuntime()) { + Device.win32_destroyUnusedHandles(getDisplay()); int oldNativeZoom = nativeZoom; if (newNativeZoom != oldNativeZoom) { DPIUtil.setDeviceZoom (newNativeZoom);