Skip to content

Commit 81f9a56

Browse files
committed
Adapt size of Windows with default size upon zoom change
When moved between monitors of different zoom, Windows may not show their full contents anymore. This is caused by their shell and the used fonts being linearly scaled in size according to the zoom, even though font size and required area for a font of a size are not linearly related. I.e., a font of double the size required more than double of the width and height. Since there are many ways to customize Windows and their sizes/layouts during and after initialization, it's difficult to solve that problem in general. It is, however, most severe for Windows that use the default calculated size and are not resizable, as those Windows not have sophisticated layouts that adapt to the limited space and may easily lead to cut offs the user cannot work around by resizing. Thus, this change adds according zoom change and resize listeners to identify if a Window uses the default computed size and, in that case, recomputes it upon zoom change.
1 parent 8ff6a17 commit 81f9a56

File tree

1 file changed

+48
-0
lines changed
  • bundles/org.eclipse.jface/src/org/eclipse/jface/window

1 file changed

+48
-0
lines changed

bundles/org.eclipse.jface/src/org/eclipse/jface/window/Window.java

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
package org.eclipse.jface.window;
1515

1616
import java.util.ArrayList;
17+
import java.util.concurrent.atomic.AtomicReference;
1718

1819
import org.eclipse.core.runtime.Assert;
1920
import org.eclipse.jface.resource.JFaceResources;
@@ -433,6 +434,53 @@ public void create() {
433434
//initialize the bounds of the shell to that appropriate for the
434435
// contents
435436
initializeBounds();
437+
hookZoomChangeListenerForDefaultSizedDialogs();
438+
}
439+
440+
/*
441+
* There is no linear relation between font size and containing control size
442+
* scaled according to some zoom value. In consequence, text with a scaled font
443+
* size may not fit into a control/shell with a size scaled by the same zoom. To
444+
* adhere for this in case of Windows using the default computed size, ensure
445+
* that on zoom change the new proper size is computed and applied. This will
446+
* not affect Windows that have a custom size, either programmatically or
447+
* manually applied.
448+
*/
449+
private void hookZoomChangeListenerForDefaultSizedDialogs() {
450+
boolean hasCustomSize = !shell.getSize().equals(shell.computeSize(SWT.DEFAULT, SWT.DEFAULT, true));
451+
boolean isEmpty = shell.getChildren().length == 0;
452+
if (resizeHasOccurred || hasCustomSize || isEmpty) {
453+
return;
454+
}
455+
456+
AtomicReference<Listener> customResizeListener = new AtomicReference<>();
457+
Listener adaptDefaultSizeListener = event -> {
458+
if (shell == null || shell.isDisposed()) {
459+
return;
460+
}
461+
Point size = shell.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
462+
shell.setSize(size);
463+
};
464+
AtomicReference<Listener> zoomChangeListener = new AtomicReference<>();
465+
zoomChangeListener.set(event -> {
466+
if (shell == null || shell.isDisposed()) {
467+
return;
468+
}
469+
shell.addListener(SWT.Resize, adaptDefaultSizeListener);
470+
shell.removeListener(SWT.Resize, customResizeListener.get());
471+
shell.getChildren()[0].removeListener(SWT.ZoomChanged, zoomChangeListener.get());
472+
});
473+
customResizeListener.set(event -> {
474+
if (shell == null || shell.isDisposed()) {
475+
return;
476+
}
477+
shell.getChildren()[0].removeListener(SWT.ZoomChanged, zoomChangeListener.get());
478+
});
479+
480+
shell.getChildren()[0].addListener(SWT.ZoomChanged, zoomChangeListener.get());
481+
// If custom resize happens before first zoom change, the dialog is custom sized
482+
// and should not be auto-resized on zoom change
483+
shell.addListener(SWT.Resize, customResizeListener.get());
436484
}
437485

438486
/**

0 commit comments

Comments
 (0)