Skip to content

Commit 72786fd

Browse files
committed
[win32] Dynamic handle creation for region
This commit refactors Region in the win32 implementation to better support multiple handles for different zoom settings by creating all handles only on demand.
1 parent cee70b7 commit 72786fd

File tree

1 file changed

+96
-58
lines changed
  • bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics

1 file changed

+96
-58
lines changed

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

Lines changed: 96 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616

1717
import java.util.*;
18+
import java.util.function.*;
1819
import java.util.stream.*;
1920

2021
import org.eclipse.swt.*;
@@ -36,12 +37,12 @@
3637
*/
3738
public final class Region extends Resource {
3839

39-
private int initialZoom;
40-
41-
private HashMap<Integer, Long> zoomToHandle = new HashMap<>();
40+
private Map<Integer, RegionHandle> zoomToHandle = new HashMap<>();
4241

4342
private List<Operation> operations = new ArrayList<>();
4443

44+
private boolean isDestroyed;
45+
4546
/**
4647
* Constructs a new empty region.
4748
* <p>
@@ -79,10 +80,6 @@ public Region () {
7980
*/
8081
public Region (Device device) {
8182
super(device);
82-
initialZoom = DPIUtil.getDeviceZoom();
83-
long handle = OS.CreateRectRgn (0, 0, 0, 0);
84-
zoomToHandle.put(initialZoom, handle);
85-
if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
8683
init();
8784
this.device.registerResourceWithZoomSupport(this);
8885
}
@@ -192,11 +189,16 @@ public void add (Region region) {
192189
*/
193190
public boolean contains (int x, int y) {
194191
if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
195-
return containsInPixels(DPIUtil.scaleUp(x, initialZoom), DPIUtil.scaleUp(y, initialZoom));
192+
return applyUsingAnyHandle(regionHandle -> {
193+
int zoom = regionHandle.zoom;
194+
int xInPixels = DPIUtil.scaleUp(x, zoom);
195+
int yInPixels = DPIUtil.scaleUp(y, zoom);
196+
return containsInPixels(regionHandle.handle, xInPixels, yInPixels);
197+
});
196198
}
197199

198-
boolean containsInPixels (int x, int y) {
199-
return OS.PtInRegion (getHandleForInitialZoom(), x, y);
200+
boolean containsInPixels (long handle, int x, int y) {
201+
return OS.PtInRegion (handle, x, y);
200202
}
201203

202204
/**
@@ -217,30 +219,26 @@ boolean containsInPixels (int x, int y) {
217219
public boolean contains (Point pt) {
218220
if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
219221
if (pt == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
220-
Point p = DPIUtil.scaleUp(pt, initialZoom);
221-
return containsInPixels(p.x, p.y);
222+
return applyUsingAnyHandle(regionHandle -> {
223+
int zoom = regionHandle.zoom;
224+
Point p = DPIUtil.scaleUp(pt, zoom);
225+
return containsInPixels(regionHandle.handle, p.x, p.y);
226+
});
222227
}
223228

224229
@Override
225230
void destroy () {
226231
device.deregisterResourceWithZoomSupport(this);
227-
zoomToHandle.values().forEach(handle -> OS.DeleteObject(handle));
232+
zoomToHandle.values().forEach(RegionHandle::destroy);
228233
zoomToHandle.clear();
229-
operations.clear();
234+
this.isDestroyed = true;
230235
}
231236

232237
@Override
233238
void destroyHandlesExcept(Set<Integer> zoomLevels) {
234-
zoomToHandle.entrySet().removeIf(entry -> {
235-
final Integer zoom = entry.getKey();
236-
if (!zoomLevels.contains(zoom) && zoom != initialZoom) {
237-
OS.DeleteObject(entry.getValue());
238-
return true;
239-
}
240-
return false;
241-
});
242-
}
243-
239+
// As long as we keep the operations, we can cleanup all handles
240+
zoomToHandle.values().forEach(RegionHandle::destroy);
241+
zoomToHandle.clear();
244242
}
245243

246244
/**
@@ -258,16 +256,17 @@ void destroyHandlesExcept(Set<Integer> zoomLevels) {
258256
*/
259257
public Rectangle getBounds () {
260258
if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
261-
return DPIUtil.scaleDown(getBoundsInPixels(), initialZoom);
259+
return applyUsingAnyHandle(regionHandle -> {
260+
return DPIUtil.scaleDown(getBoundsInPixels(regionHandle.handle), regionHandle.zoom);
261+
});
262262
}
263263

264-
Rectangle getBoundsInPixels() {
264+
private Rectangle getBoundsInPixels(long handle) {
265265
RECT rect = new RECT();
266-
OS.GetRgnBox(getHandleForInitialZoom(), rect);
266+
OS.GetRgnBox(handle, rect);
267267
return new Rectangle(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
268268
}
269269

270-
271270
/**
272271
* Intersects the given rectangle to the collection of polygons
273272
* the receiver maintains to describe its area.
@@ -362,10 +361,10 @@ public boolean intersects (int x, int y, int width, int height) {
362361
return intersects(new Rectangle(x, y, width, height));
363362
}
364363

365-
boolean intersectsInPixels (int x, int y, int width, int height) {
364+
boolean intersectsInPixels (long handle, int x, int y, int width, int height) {
366365
RECT r = new RECT ();
367366
OS.SetRect (r, x, y, x + width, y + height);
368-
return OS.RectInRegion (getHandleForInitialZoom(), r);
367+
return OS.RectInRegion(handle, r);
369368
}
370369

371370
/**
@@ -388,8 +387,10 @@ boolean intersectsInPixels (int x, int y, int width, int height) {
388387
public boolean intersects (Rectangle rect) {
389388
if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
390389
if (rect == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
391-
Rectangle r = DPIUtil.scaleUp(rect, initialZoom);
392-
return intersectsInPixels(r.x, r.y, r.width, r.height);
390+
return applyUsingAnyHandle(regionHandle -> {
391+
Rectangle r = DPIUtil.scaleUp(rect, regionHandle.zoom);
392+
return intersectsInPixels(regionHandle.handle, r.x, r.y, r.width, r.height);
393+
});
393394
}
394395

395396
/**
@@ -404,7 +405,7 @@ public boolean intersects (Rectangle rect) {
404405
*/
405406
@Override
406407
public boolean isDisposed() {
407-
return zoomToHandle.isEmpty();
408+
return isDestroyed;
408409
}
409410

410411
/**
@@ -421,9 +422,11 @@ public boolean isDisposed() {
421422
public boolean isEmpty () {
422423
if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
423424
RECT rect = new RECT ();
424-
int result = OS.GetRgnBox (getHandleForInitialZoom(), rect);
425-
if (result == OS.NULLREGION) return true;
426-
return ((rect.right - rect.left) <= 0) || ((rect.bottom - rect.top) <= 0);
425+
return applyUsingAnyHandle(regionHandle -> {
426+
int result = OS.GetRgnBox(regionHandle.handle, rect);
427+
if (result == OS.NULLREGION) return true;
428+
return ((rect.right - rect.left) <= 0) || ((rect.bottom - rect.top) <= 0);
429+
});
427430
}
428431

429432
/**
@@ -561,13 +564,44 @@ public void translate (Point pt) {
561564
storeAndApplyOperationForAllHandles(operation);
562565
}
563566

564-
private long getHandleForInitialZoom() {
565-
return win32_getHandle(this, initialZoom);
566-
}
567-
568567
private void storeAndApplyOperationForAllHandles(Operation operation) {
569568
operations.add(operation);
570-
zoomToHandle.forEach((zoom, handle) -> operation.apply(handle, zoom));
569+
zoomToHandle.forEach((zoom, handle) -> operation.apply(handle));
570+
}
571+
572+
private <T> T applyUsingAnyHandle(Function<RegionHandle, T> function) {
573+
if (zoomToHandle.isEmpty()) {
574+
return applyUsingTemporaryHandle(device.getDeviceZoom(), function);
575+
} else {
576+
return function.apply(zoomToHandle.values().iterator().next());
577+
}
578+
}
579+
580+
private <T> T applyUsingTemporaryHandle(int zoom, Function<RegionHandle, T> function) {
581+
RegionHandle temporaryHandle = newRegionHandle(zoom);
582+
try {
583+
return function.apply(temporaryHandle);
584+
} finally {
585+
temporaryHandle.destroy();
586+
}
587+
}
588+
589+
private RegionHandle newRegionHandle(int zoom) {
590+
long newHandle = OS.CreateRectRgn (0, 0, 0, 0);
591+
if (newHandle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
592+
RegionHandle newRegionHandle = new RegionHandle(newHandle, zoom);
593+
for (Operation operation : operations) {
594+
operation.apply(newRegionHandle);
595+
}
596+
return newRegionHandle;
597+
}
598+
599+
private RegionHandle getRegionHandle(int zoom) {
600+
if (!zoomToHandle.containsKey(zoom)) {
601+
RegionHandle regionHandle = newRegionHandle(zoom);
602+
zoomToHandle.put(zoom, regionHandle);
603+
}
604+
return zoomToHandle.get(zoom);
571605
}
572606

573607
/**
@@ -588,14 +622,7 @@ private void storeAndApplyOperationForAllHandles(Operation operation) {
588622
* @noreference This method is not intended to be referenced by clients.
589623
*/
590624
public static long win32_getHandle(Region region, int zoom) {
591-
if(!region.zoomToHandle.containsKey(zoom)) {
592-
long handle = OS.CreateRectRgn(0, 0, 0, 0);
593-
for(Operation operation : region.operations) {
594-
operation.apply(handle, zoom);
595-
}
596-
region.zoomToHandle.put(zoom, handle);
597-
}
598-
return region.zoomToHandle.get(zoom);
625+
return region.getRegionHandle(zoom).handle;
599626
}
600627

601628
/**
@@ -610,20 +637,34 @@ public String toString () {
610637
return "Region {" + zoomToHandle.entrySet().stream().map(entry -> entry.getValue() + "(zoom:" + entry.getKey() + ")").collect(Collectors.joining(","));
611638
}
612639

640+
private class RegionHandle {
641+
private long handle;
642+
private int zoom;
643+
644+
public RegionHandle(long handle, int zoom) {
645+
this.handle = handle;
646+
this.zoom = zoom;
647+
}
648+
649+
void destroy() {
650+
OS.DeleteObject(handle);
651+
}
652+
}
653+
613654
@FunctionalInterface
614655
private interface OperationStrategy {
615656
void apply(Operation operation, long handle, int zoom);
616657
}
617658

618659
private abstract class Operation {
619-
private OperationStrategy operationStrategy;
660+
private final OperationStrategy operationStrategy;
620661

621662
Operation(OperationStrategy operationStrategy) {
622663
this.operationStrategy = operationStrategy;
623664
}
624665

625-
void apply(long handle, int zoom) {
626-
operationStrategy.apply(this, handle, zoom);
666+
void apply(RegionHandle regionHandle) {
667+
operationStrategy.apply(this, regionHandle.handle, regionHandle.zoom);
627668
}
628669

629670
abstract void add(long handle, int zoom);
@@ -636,8 +677,7 @@ void apply(long handle, int zoom) {
636677
}
637678

638679
private class OperationWithRectangle extends Operation {
639-
640-
Rectangle data;
680+
private final Rectangle data;
641681

642682
OperationWithRectangle(OperationStrategy operationStrategy, Rectangle data) {
643683
super(operationStrategy);
@@ -695,8 +735,7 @@ private Rectangle getScaledRectangle(int zoom) {
695735
}
696736

697737
private class OperationWithArray extends Operation {
698-
699-
int[] data;
738+
private final int[] data;
700739

701740
public OperationWithArray(OperationStrategy operationStrategy, int[] data) {
702741
super(operationStrategy);
@@ -743,8 +782,7 @@ private int[] getScaledPoints(int zoom) {
743782
}
744783

745784
private class OperationWithPoint extends Operation {
746-
747-
Point data;
785+
private final Point data;
748786

749787
public OperationWithPoint(OperationStrategy operationStrategy, Point data) {
750788
super(operationStrategy);

0 commit comments

Comments
 (0)