eclipse.platform.swt
eclipse.platform.swt copied to clipboard
[Win11] Layout handling is broken while a menu is shown
Describe the bug If a menu is shown, the layout handling is broken.
To Reproduce Launch this snippet 2 times:
- just wait 5s -> the label is replaced by a button
- restart and within 5s click any menu so it remains open -> the label disappears, but the button is not becoming shown
import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;
public class OpenedMenuPreventsLayout {
private static Control visibleControl;
public static void main(String[] args) {
final Display display = new Display();
final Shell shell = new Shell(display);
setUpMenuBar(shell);
shell.setLayout(new FillLayout());
final Composite composite = new Composite(shell, 0);
composite.setLayout(new Layout() {
@Override
protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) {
return new Point(400, 300);
}
@Override
protected void layout(Composite composite, boolean flushCache) {
final Rectangle area = composite.getClientArea();
if (visibleControl != null) {
visibleControl.setBounds(area);
}
}
});
display.timerExec(5000, () -> {
if (shell.isDisposed()) {
return;
}
visibleControl.setVisible(false);
final Button button = new Button(composite, SWT.PUSH);
button.setText("Timeout");
visibleControl = button;
composite.requestLayout();
});
final Label label = new Label(composite, SWT.WRAP);
label.setText("1. Just wait 5s -> the button occurs\n\n2. Restart and within 5 seconds open the Window menu -> no button occurs");
visibleControl = label;
final Point size = shell.computeSize(SWT.DEFAULT, SWT.DEFAULT);
shell.setMinimumSize(size);
shell.setSize(size);
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
}
private static void setUpMenuBar(Shell shell) {
final Menu menuBar = new Menu(shell, SWT.BAR);
createMenu("File", menuBar);
createMenu("Edit", menuBar);
createMenu("View", menuBar);
createMenu("Window", menuBar);
shell.setMenuBar(menuBar);
}
private static void createMenu(String name, Menu menuBar) {
final MenuItem menuBarItem = new MenuItem(menuBar, SWT.CASCADE);
menuBarItem.setText(name);
final Menu menu = new Menu(menuBar.getShell(), SWT.DROP_DOWN);
menuBarItem.setMenu(menu);
new MenuItem(menu, SWT.PUSH).setText("Foo");
new MenuItem(menu, SWT.PUSH).setText("Bar");
new MenuItem(menu, SWT.PUSH).setText("Bazz");
}
}
Expected behavior The button should become visible independent of a shown menu.
Screenshots
-
just waiting
-
opening a menu
Environment:
- Select the platform(s) on which the behavior is seen:
-
- [ ] All OS
-
- [x] Windows
-
- [ ] Linux
-
- [ ] macOS
- Additional OS info (e.g. OS version, Linux Desktop, etc) Tried on Windows 11
@syntevo I am able to recreate the issue on windows 11. Thanks for the recreate.
I tried on below environment. Eclipse SDK Version: 2023-12 (4.30) Build id: I20230912-1800 OS: Windows 11, v.10.0, x86_64 / win32 Java vendor: Eclipse Adoptium Java runtime version: 20+36 Java version: 20
When any of the menuitem is open, Timeout button covering area is not getting refreshed which should ideally get refreshed in the background irrespective of menuitems being open/closed.
We have also tried same on Mac but not seeing menu bar itself on mac => looks to be a different issue on Mac. Will check once again and update accordingly on it.
We have also tried same on Mac but not seeing menu bar itself on mac => looks to be a different issue on Mac. Will check once again and update accordingly on it.
Timeout button covering area is coming properly once the menu item is clicked/when not opened. It is working as expected.
I expect it to be only a problem on Windows. Hence the [Win11] in the title.
@iloveeclipse @niraj-modi I feel this is a regression from => https://bugs.eclipse.org/bugs/show_bug.cgi?id=547373 Trying to understand the code, can you give some pointers to it.
I trace the problem to this point https://github.com/eclipse-platform/eclipse.platform.swt/blob/425f14e4c1725628ef99bbd483a3388b0f38356d/bundles/org.eclipse.swt/Eclipse%20SWT/win32/org/eclipse/swt/widgets/Composite.java#L841C64-L841C64
Here the variable display.externalEventLoop is having false due to this the deferredlayouts are not getting added to the display queue due to which shell is not getting refreshed.
I feel this is a regression from => https://bugs.eclipse.org/bugs/show_bug.cgi?id=547373 Trying to understand the code, can you give some pointers to it.
I personally have no pointers, but I believe you've found the root cause. @SyntevoAlex: something you can look at?
Unfortunately my queue is full for the next couple weeks or so.
@SyntevoAlex For me to proceed on this fix, can you give some pointers for this issue please? Please find my analysis over here => https://github.com/eclipse-platform/eclipse.platform.swt/issues/791#issuecomment-1842503703
@SyntevoAlex Sorry to bombard you again but still do you have some pointers for this issue please? Please find my analysis over here => https://github.com/eclipse-platform/eclipse.platform.swt/issues/791#issuecomment-1842503703
Here the variable display.externalEventLoop is having false due to this the deferredlayouts are not getting added to the display queue due to which shell is not getting refreshed.
I don't understand. https://github.com/eclipse-platform/eclipse.platform.swt/blob/425f14e4c1725628ef99bbd483a3388b0f38356d/bundles/org.eclipse.swt/Eclipse%20SWT/win32/org/eclipse/swt/widgets/Composite.java#L841-L844
Here, if display.externalEventLoop is false, it will be added, and you're saying it's not added.
As for the reason why there's display.externalEventLoop condition, I can make a guess. Bug 547373 talks about popup menu, and I understand that while popup menu is active, externalEventLoop will be set to true, probably here:
https://github.com/eclipse-platform/eclipse.platform.swt/blob/425f14e4c1725628ef99bbd483a3388b0f38356d/bundles/org.eclipse.swt/Eclipse%20SWT/win32/org/eclipse/swt/widgets/Control.java#L4957-4960