Skip to content

Commit 7be6e97

Browse files
akoch-yattaHeikoKlare
authored andcommitted
[win32] Create handles with disposed Regions
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 c1e0ef6 commit 7be6e97

File tree

2 files changed

+62
-26
lines changed

2 files changed

+62
-26
lines changed

bundles/org.eclipse.swt/Eclipse SWT Tests/win32/org/eclipse/swt/graphics/RegionWin32Tests.java

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ public void testRegionMustBeScaledOnHandleOfScaledZoomLevel() {
5757
assertEquals("scaled region's y position should be double of unscaled region", bounds.y * scalingFactor, scaledBounds.y);
5858
}
5959

60-
6160
@Test
6261
public void testRegionMustIntersectProperlyOn175Zoom() {
6362
Display display = Display.getDefault();
@@ -81,7 +80,24 @@ public void testRegionMustIntersectProperlyOn175Zoom() {
8180
// be rounded independently
8281
boolean shouldNotIntersect = region.intersects(0, 27, 100, 31);
8382
assertFalse(shouldNotIntersect);
84-
83+
region.dispose();
8584
}
8685

86+
@Test
87+
public void testCreateRegionHandleWithDisposedRegionInvolved() {
88+
Display display = Display.getDefault();
89+
90+
Region region = new Region(display);
91+
region.add(0, 0, 100, 100);
92+
93+
Region region2 = new Region(display);
94+
region.add(50, 50, 100, 100);
95+
96+
region.add(region2);
97+
98+
region2.dispose();
99+
Region.win32_getHandle(region, 100);
100+
Region.win32_getHandle(region, 200);
101+
region.dispose();
102+
}
87103
}

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

Lines changed: 44 additions & 24 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.*;
@@ -80,9 +81,8 @@ public Region () {
8081
public Region (Device device) {
8182
super(device);
8283
initialZoom = DPIUtil.getDeviceZoom();
83-
long handle = OS.CreateRectRgn (0, 0, 0, 0);
84+
long handle = newEmptyRegionHandle();
8485
zoomToHandle.put(initialZoom, handle);
85-
if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
8686
init();
8787
this.device.registerResourceWithZoomSupport(this);
8888
}
@@ -597,6 +597,29 @@ private void storeAndApplyOperationForAllHandles(Operation operation) {
597597
zoomToHandle.forEach((zoom, handle) -> operation.apply(handle, zoom));
598598
}
599599

600+
private static <T> T applyUsingTemporaryHandle(int zoom, List<Operation> operations, Function<Long, T> function) {
601+
long temporaryHandle = newRegionHandle(operations, zoom);
602+
try {
603+
return function.apply(temporaryHandle);
604+
} finally {
605+
OS.DeleteObject(temporaryHandle);
606+
}
607+
}
608+
609+
private static long newEmptyRegionHandle() {
610+
long newHandle = OS.CreateRectRgn (0, 0, 0, 0);
611+
if (newHandle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
612+
return newHandle;
613+
}
614+
615+
private static long newRegionHandle(List<Operation> operations, int zoom) {
616+
long newHandle = newEmptyRegionHandle();
617+
for (Operation operation : operations) {
618+
operation.apply(newHandle, zoom);
619+
}
620+
return newHandle;
621+
}
622+
600623
/**
601624
* <b>IMPORTANT:</b> This method is not part of the public
602625
* API for Image. It is marked public only so that it
@@ -615,9 +638,9 @@ private void storeAndApplyOperationForAllHandles(Operation operation) {
615638
* @noreference This method is not intended to be referenced by clients.
616639
*/
617640
public static long win32_getHandle(Region region, int zoom) {
618-
if(!region.zoomToHandle.containsKey(zoom)) {
619-
long handle = OS.CreateRectRgn(0, 0, 0, 0);
620-
for(Operation operation : region.operations) {
641+
if (!region.zoomToHandle.containsKey(zoom)) {
642+
long handle = newEmptyRegionHandle();
643+
for (Operation operation : region.operations) {
621644
operation.apply(handle, zoom);
622645
}
623646
region.zoomToHandle.put(zoom, handle);
@@ -642,7 +665,7 @@ private interface OperationStrategy {
642665
void apply(Operation operation, long handle, int zoom);
643666
}
644667

645-
private abstract class Operation {
668+
private abstract static class Operation {
646669
private OperationStrategy operationStrategy;
647670

648671
Operation(OperationStrategy operationStrategy) {
@@ -662,7 +685,7 @@ void apply(long handle, int zoom) {
662685
abstract void translate(long handle, int zoom);
663686
}
664687

665-
private class OperationWithRectangle extends Operation {
688+
private static class OperationWithRectangle extends Operation {
666689

667690
Rectangle data;
668691

@@ -721,7 +744,7 @@ private Rectangle getScaledRectangle(int zoom) {
721744

722745
}
723746

724-
private class OperationWithArray extends Operation {
747+
private static class OperationWithArray extends Operation {
725748

726749
int[] data;
727750

@@ -769,7 +792,7 @@ private int[] getScaledPoints(int zoom) {
769792
}
770793
}
771794

772-
private class OperationWithPoint extends Operation {
795+
private static class OperationWithPoint extends Operation {
773796

774797
Point data;
775798

@@ -801,41 +824,38 @@ void translate(long handle, int zoom) {
801824

802825
}
803826

804-
private class OperationWithRegion extends Operation {
805-
806-
Region data;
827+
private static class OperationWithRegion extends Operation {
828+
private final List<Operation> operations;
807829

808830
OperationWithRegion(OperationStrategy operationStrategy, Region data) {
809831
super(operationStrategy);
810-
this.data = data;
832+
this.operations = data.operations;
811833
}
812834

813835
@Override
814836
void add(long handle, int zoom) {
815-
long scaledHandle = getHandleForScaledRegion(zoom);
816-
OS.CombineRgn (handle, handle, scaledHandle, OS.RGN_OR);
837+
applyUsingTemporaryHandle(zoom, operations, regionHandle -> {
838+
return OS.CombineRgn (handle, handle, regionHandle, OS.RGN_OR);
839+
});
817840
}
818841

819842
@Override
820843
void subtract(long handle, int zoom) {
821-
long scaledHandle = getHandleForScaledRegion(zoom);
822-
OS.CombineRgn (handle, handle, scaledHandle, OS.RGN_DIFF);
844+
applyUsingTemporaryHandle(zoom, operations, regionHandle -> {
845+
return OS.CombineRgn (handle, handle, regionHandle, OS.RGN_DIFF);
846+
});
823847
}
824848

825849
@Override
826850
void intersect(long handle, int zoom) {
827-
long scaledHandle = getHandleForScaledRegion(zoom);
828-
OS.CombineRgn (handle, handle, scaledHandle, OS.RGN_AND);
851+
applyUsingTemporaryHandle(zoom, operations, regionHandle -> {
852+
return OS.CombineRgn (handle, handle, regionHandle, OS.RGN_AND);
853+
});
829854
}
830855

831856
@Override
832857
void translate(long handle, int zoom) {
833858
throw new UnsupportedOperationException();
834859
}
835-
836-
private long getHandleForScaledRegion(int zoom) {
837-
if (data.isDisposed() || data == Region.this) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
838-
return win32_getHandle(data, zoom);
839-
}
840860
}
841861
}

0 commit comments

Comments
 (0)