Skip to content

Commit fcfd25f

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 905fdb9 commit fcfd25f

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
@@ -4784,12 +4784,9 @@ public boolean setParent (Composite parent) {
47844784
if (OS.SetParent (topHandle, parent.handle) == 0) return false;
47854785
this.parent = parent;
47864786
// If parent changed, zoom level might need to be adjusted
4787-
if (parent.nativeZoom != nativeZoom) {
4788-
int newZoom = parent.nativeZoom;
4789-
Event zoomChangedEvent = createZoomChangedEvent(newZoom);
4790-
if (currentDpiChangeEvent != null) {
4791-
currentDpiChangeEvent.doit = false;
4792-
}
4787+
int newZoom = parent.nativeZoom;
4788+
if (newZoom != nativeZoom) {
4789+
Event zoomChangedEvent = createZoomChangedEvent(newZoom, false);
47934790
sendZoomChangedEvent(zoomChangedEvent, getShell());
47944791
}
47954792
int flags = OS.SWP_NOSIZE | OS.SWP_NOMOVE | OS.SWP_NOACTIVATE;
@@ -4985,7 +4982,10 @@ LRESULT WM_DESTROY (long wParam, long lParam) {
49854982

49864983
private void handleMonitorSpecificDpiChange(int newNativeZoom, Rectangle newBoundsInPixels) {
49874984
DPIUtil.setDeviceZoom (newNativeZoom);
4988-
Event zoomChangedEvent = createZoomChangedEvent(newNativeZoom);
4985+
// Do not process DPI change for child shells asynchronous to avoid relayouting when
4986+
// repositioning the child shell to a different monitor upon opening
4987+
boolean processDpiChangeAsynchronous = getShell().getParent() == null;
4988+
Event zoomChangedEvent = createZoomChangedEvent(newNativeZoom, processDpiChangeAsynchronous);
49894989
if (currentDpiChangeEvent != null) {
49904990
currentDpiChangeEvent.doit = false;
49914991
}
@@ -4994,13 +4994,15 @@ private void handleMonitorSpecificDpiChange(int newNativeZoom, Rectangle newBoun
49944994
this.setBoundsInPixels(newBoundsInPixels.x, newBoundsInPixels.y, newBoundsInPixels.width, newBoundsInPixels.height);
49954995
}
49964996

4997-
Event createZoomChangedEvent(int zoom) {
4997+
Event createZoomChangedEvent(int zoom, boolean asyncExec) {
49984998
Event event = new Event();
49994999
event.type = SWT.ZoomChanged;
50005000
event.widget = this;
50015001
event.detail = zoom;
50025002
event.doit = true;
5003-
event.data = new DPIChangeExecution();
5003+
DPIChangeExecution dpiChangeExecution = new DPIChangeExecution();
5004+
dpiChangeExecution.asyncExec = asyncExec;
5005+
event.data = dpiChangeExecution;
50045006
return event;
50055007
}
50065008

0 commit comments

Comments
 (0)