Skip to content

Commit e1efc67

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 f03d8f0 commit e1efc67

File tree

2 files changed

+57
-17
lines changed

2 files changed

+57
-17
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: 39 additions & 15 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.*;
@@ -452,8 +453,8 @@ public boolean isEmpty () {
452453
if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
453454
RECT rect = new RECT ();
454455
int result = OS.GetRgnBox (getHandleForInitialZoom(), rect);
455-
if (result == OS.NULLREGION) return true;
456-
return ((rect.right - rect.left) <= 0) || ((rect.bottom - rect.top) <= 0);
456+
if (result == OS.NULLREGION) return true;
457+
return ((rect.right - rect.left) <= 0) || ((rect.bottom - rect.top) <= 0);
457458
}
458459

459460
/**
@@ -600,6 +601,32 @@ private void storeAndApplyOperationForAllHandles(Operation operation) {
600601
zoomToHandle.forEach((zoom, handle) -> operation.apply(handle, zoom));
601602
}
602603

604+
private <T> T applyUsingAnyMatchingHandle(int zoom, Function<Long, T> function) {
605+
if (zoomToHandle.containsKey(zoom)) {
606+
return function.apply(zoomToHandle.get(zoom));
607+
} else {
608+
return applyUsingTemporaryHandle(zoom, function);
609+
}
610+
}
611+
612+
private <T> T applyUsingTemporaryHandle(int zoom, Function<Long, T> function) {
613+
long temporaryHandle = newRegionHandle(zoom);
614+
try {
615+
return function.apply(temporaryHandle);
616+
} finally {
617+
OS.DeleteObject(temporaryHandle);
618+
}
619+
}
620+
621+
private long newRegionHandle(int zoom) {
622+
long newHandle = OS.CreateRectRgn (0, 0, 0, 0);
623+
if (newHandle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
624+
for (Operation operation : operations) {
625+
operation.apply(newHandle, zoom);
626+
}
627+
return newHandle;
628+
}
629+
603630
/**
604631
* <b>IMPORTANT:</b> This method is not part of the public
605632
* API for Image. It is marked public only so that it
@@ -805,8 +832,7 @@ void translate(long handle, int zoom) {
805832
}
806833

807834
private class OperationWithRegion extends Operation {
808-
809-
Region data;
835+
private final Region data;
810836

811837
OperationWithRegion(OperationStrategy operationStrategy, Region data) {
812838
super(operationStrategy);
@@ -815,30 +841,28 @@ private class OperationWithRegion extends Operation {
815841

816842
@Override
817843
void add(long handle, int zoom) {
818-
long scaledHandle = getHandleForScaledRegion(zoom);
819-
OS.CombineRgn (handle, handle, scaledHandle, OS.RGN_OR);
844+
data.applyUsingAnyMatchingHandle(zoom, regionHandle -> {
845+
return OS.CombineRgn (handle, handle, regionHandle, OS.RGN_OR);
846+
});
820847
}
821848

822849
@Override
823850
void subtract(long handle, int zoom) {
824-
long scaledHandle = getHandleForScaledRegion(zoom);
825-
OS.CombineRgn (handle, handle, scaledHandle, OS.RGN_DIFF);
851+
data.applyUsingAnyMatchingHandle(zoom, regionHandle -> {
852+
return OS.CombineRgn (handle, handle, regionHandle, OS.RGN_DIFF);
853+
});
826854
}
827855

828856
@Override
829857
void intersect(long handle, int zoom) {
830-
long scaledHandle = getHandleForScaledRegion(zoom);
831-
OS.CombineRgn (handle, handle, scaledHandle, OS.RGN_AND);
858+
data.applyUsingAnyMatchingHandle(zoom, regionHandle -> {
859+
return OS.CombineRgn (handle, handle, regionHandle, OS.RGN_AND);
860+
});
832861
}
833862

834863
@Override
835864
void translate(long handle, int zoom) {
836865
throw new UnsupportedOperationException();
837866
}
838-
839-
private long getHandleForScaledRegion(int zoom) {
840-
if (data.isDisposed() || data == Region.this) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
841-
return win32_getHandle(data, zoom);
842-
}
843867
}
844868
}

0 commit comments

Comments
 (0)