Skip to content

Commit 642e207

Browse files
committed
[Win32] Fix wrong layout when opening shell or reparenting control #2608
In multiple situation, relayouting due to DPI change events does not work as expected: - When opening child shells, they may be relayouted after being opened if their position changed to a different monitor between the OS handle was created and a new position was set - When reparenting controls between different shells, the target shell may not be properly relayout at all Since the user experience when performing these two cases asynchronously is not good anyway (e.g., reparenting leads to unexpected asynchronous relayouting operations), this change adapts the two use cases to process the DPI change synchronously. Fixes #2608
1 parent 2b554d9 commit 642e207

File tree

2 files changed

+12
-10
lines changed

2 files changed

+12
-10
lines changed

bundles/org.eclipse.swt/Eclipse SWT Tests/win32/org/eclipse/swt/widgets/DPITestUtil.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ private DPITestUtil() {
2828

2929
public static void changeDPIZoom (Shell shell, int nativeZoom) {
3030
DPIUtil.setDeviceZoom(nativeZoom);
31-
Event event = shell.createZoomChangedEvent(nativeZoom);
31+
Event event = shell.createZoomChangedEvent(nativeZoom, true);
3232
shell.sendZoomChangedEvent(event, shell);
3333
DPIChangeExecution data = (DPIChangeExecution) event.data;
3434
waitForDPIChange(shell, TIMEOUT_MILLIS, data.taskCount);

bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Control.java

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4771,12 +4771,9 @@ public boolean setParent (Composite parent) {
47714771
if (OS.SetParent (topHandle, parent.handle) == 0) return false;
47724772
this.parent = parent;
47734773
// If parent changed, zoom level might need to be adjusted
4774-
if (parent.nativeZoom != nativeZoom) {
4775-
int newZoom = parent.nativeZoom;
4776-
Event zoomChangedEvent = createZoomChangedEvent(newZoom);
4777-
if (currentDpiChangeEvent != null) {
4778-
currentDpiChangeEvent.doit = false;
4779-
}
4774+
int newZoom = parent.nativeZoom;
4775+
if (newZoom != nativeZoom) {
4776+
Event zoomChangedEvent = createZoomChangedEvent(newZoom, false);
47804777
sendZoomChangedEvent(zoomChangedEvent, getShell());
47814778
}
47824779
int flags = OS.SWP_NOSIZE | OS.SWP_NOMOVE | OS.SWP_NOACTIVATE;
@@ -4972,7 +4969,10 @@ LRESULT WM_DESTROY (long wParam, long lParam) {
49724969

49734970
private void handleMonitorSpecificDpiChange(int newNativeZoom, Rectangle newBoundsInPixels) {
49744971
DPIUtil.setDeviceZoom (newNativeZoom);
4975-
Event zoomChangedEvent = createZoomChangedEvent(newNativeZoom);
4972+
// Do not process DPI change for child shells asynchronous to avoid relayouting when
4973+
// repositioning the child shell to a different monitor upon opening
4974+
boolean processDpiChangeAsynchronous = getShell().getParent() == null;
4975+
Event zoomChangedEvent = createZoomChangedEvent(newNativeZoom, processDpiChangeAsynchronous);
49764976
if (currentDpiChangeEvent != null) {
49774977
currentDpiChangeEvent.doit = false;
49784978
}
@@ -4981,13 +4981,15 @@ private void handleMonitorSpecificDpiChange(int newNativeZoom, Rectangle newBoun
49814981
this.setBoundsInPixels(newBoundsInPixels.x, newBoundsInPixels.y, newBoundsInPixels.width, newBoundsInPixels.height);
49824982
}
49834983

4984-
Event createZoomChangedEvent(int zoom) {
4984+
Event createZoomChangedEvent(int zoom, boolean asyncExec) {
49854985
Event event = new Event();
49864986
event.type = SWT.ZoomChanged;
49874987
event.widget = this;
49884988
event.detail = zoom;
49894989
event.doit = true;
4990-
event.data = new DPIChangeExecution();
4990+
DPIChangeExecution dpiChangeExecution = new DPIChangeExecution();
4991+
dpiChangeExecution.asyncExec = asyncExec;
4992+
event.data = dpiChangeExecution;
49914993
return event;
49924994
}
49934995

0 commit comments

Comments
 (0)