Skip to content

Commit ac18a18

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 9cacd32 commit ac18a18

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
@@ -4801,12 +4801,9 @@ public boolean setParent (Composite parent) {
48014801
if (OS.SetParent (topHandle, parent.handle) == 0) return false;
48024802
this.parent = parent;
48034803
// If parent changed, zoom level might need to be adjusted
4804-
if (parent.nativeZoom != nativeZoom) {
4805-
int newZoom = parent.nativeZoom;
4806-
Event zoomChangedEvent = createZoomChangedEvent(newZoom);
4807-
if (currentDpiChangeEvent != null) {
4808-
currentDpiChangeEvent.doit = false;
4809-
}
4804+
int newZoom = parent.nativeZoom;
4805+
if (newZoom != nativeZoom) {
4806+
Event zoomChangedEvent = createZoomChangedEvent(newZoom, false);
48104807
sendZoomChangedEvent(zoomChangedEvent, getShell());
48114808
}
48124809
int flags = OS.SWP_NOSIZE | OS.SWP_NOMOVE | OS.SWP_NOACTIVATE;
@@ -5019,7 +5016,10 @@ LRESULT WM_DESTROY (long wParam, long lParam) {
50195016

50205017
private void handleMonitorSpecificDpiChange(int newNativeZoom, Rectangle newBoundsInPixels) {
50215018
DPIUtil.setDeviceZoom (newNativeZoom);
5022-
Event zoomChangedEvent = createZoomChangedEvent(newNativeZoom);
5019+
// Do not process DPI change for child shells asynchronous to avoid relayouting when
5020+
// repositioning the child shell to a different monitor upon opening
5021+
boolean processDpiChangeAsynchronous = getShell().getParent() == null;
5022+
Event zoomChangedEvent = createZoomChangedEvent(newNativeZoom, processDpiChangeAsynchronous);
50235023
if (currentDpiChangeEvent != null) {
50245024
currentDpiChangeEvent.doit = false;
50255025
}
@@ -5028,13 +5028,15 @@ private void handleMonitorSpecificDpiChange(int newNativeZoom, Rectangle newBoun
50285028
this.setBoundsInPixels(newBoundsInPixels.x, newBoundsInPixels.y, newBoundsInPixels.width, newBoundsInPixels.height);
50295029
}
50305030

5031-
Event createZoomChangedEvent(int zoom) {
5031+
Event createZoomChangedEvent(int zoom, boolean asyncExec) {
50325032
Event event = new Event();
50335033
event.type = SWT.ZoomChanged;
50345034
event.widget = this;
50355035
event.detail = zoom;
50365036
event.doit = true;
5037-
event.data = new DPIChangeExecution();
5037+
DPIChangeExecution dpiChangeExecution = new DPIChangeExecution();
5038+
dpiChangeExecution.asyncExec = asyncExec;
5039+
event.data = dpiChangeExecution;
50385040
return event;
50395041
}
50405042

0 commit comments

Comments
 (0)