| Summary: | Shell.setBounds sometimes fails to set the right location | ||
|---|---|---|---|
| Product: | [Eclipse Project] Platform | Reporter: | Dominik Schmid <dominik.schmid> |
| Component: | SWT | Assignee: | Xi Yan <xixiyan> |
| Status: | VERIFIED FIXED | QA Contact: | |
| Severity: | normal | ||
| Priority: | P3 | CC: | akurtakov, eclipse.felipe, ericwill, patrick.tasse, remy.suen |
| Version: | 3.6.1 | Keywords: | helpwanted, triaged |
| Target Milestone: | 4.9 M3 | ||
| Hardware: | PC | ||
| OS: | Linux | ||
| See Also: |
https://bugs.eclipse.org/bugs/show_bug.cgi?id=445900 https://git.eclipse.org/r/126408 https://git.eclipse.org/c/platform/eclipse.platform.swt.git/commit/?id=9d77cdae8ede54cd29d86993fdb4c85b4d7229aa |
||
| Whiteboard: | |||
Have you tried the same code on Linux using a different window manager ? I suspect this happens because the window manager has some limtation or rules it follows when placing windows on the screen. When this test fails: assertEquals(x, testShell.getLocation().x); Does it fail by a few pixes or many ? I have tried it on two different systems now. 64Bit Ubuntu with GTK2.20.1 and a 32Bit Suse Linux with KDE 3.5.1. On both both systems the bug occurs more often than not. When the test fails at the assertEquals the difference between expected and actual x value varies greatly. Sometimes it's just a few pixes, some other time over 1000. I can reproduce this bug. I'm not sure if it's related but we noticed some problems yesterday with setBounds() and setLocation(). We're running on Linux (GTK2 and GTK3 both have the problem).
We were trying to have a shell snapped to the right of the display, and the shell can change size due to user interaction (widgets are created and disposed in the shell's Composite).
So imagine a display size of (1000, 1000). Our shell had original bounds of [900, 0, 100, 24] so its right side is at x=1000.
Then we dispose a widget inside the shell and the new width after layout() and computeTrim() is 75. We calculate the new bounds to be [925, 0, 75, 24]. But when we set those bounds, the resulting shell bounds are [900, 0, 75, 24] so its right side is at x=975, not 1000 as expected.
It appears as if the shell doesn't realize that its new width is 75, so it snaps back the x position so that the shell (that it thinks is still width 100) does not go out of bounds, and then the width is reduced.
However if we set the bounds a second time in an asyncExec() runnable, then it works. It's essential that the shell size is first reduced. It could be that the shell needs to be drawn once with the new size before it can take into account this new size in operations that change the bounds?
So:
// does not work
shell.setBounds(925, 0, 75, 24);
// does not work
shell.setBounds(925, 0, 75, 24);
shell.setBounds(925, 0, 75, 24);
// does not work
display.asyncExec(() -> {
shell.setBounds(925, 0, 75, 24);
});
// works
shell.setBounds(925, 0, 75, 24);
display.asyncExec(() -> {
shell.setBounds(925, 0, 75, 24);
});
It's not a specific problem to setBounds() that is changing both size and location in one call, as it happens if done with separate calls:
// does not work
shell.setSize(75, 24);
shell.setLocation(925, 0);
// works
shell.setSize(75, 24);
display.asyncExec(() -> {
shell.setLocation(925, 0);
});
Xi, please investigate. New Gerrit change created: https://git.eclipse.org/r/126408 Gerrit change https://git.eclipse.org/r/126408 was merged to [master]. Commit: http://git.eclipse.org/c/platform/eclipse.platform.swt.git/commit/?id=9d77cdae8ede54cd29d86993fdb4c85b4d7229aa Verified in I20180821-2000. |
Build Identifier: M20100909-0800 When using Shell.setLocation I regulary encountered the problem that a newly created window was relocated not correctly to the specified location. After some debugging I tracked the bug down to Shell.setBounds. The problem seems to be limited to Linux only. I added a test case, that illustrates the problem. Running it works fine under Windows (XP), but fails more often than not under Linux (64Bit). Adding a Thread.sleep seems to help a little, but it's far from a stable solution. public class setBoundsTest { static int cycles = 5; @Test public void testSetBounds() { int x; int y; int width = 100; int height = 100; for (int i=0; i < cycles; i++) { x = (new Double(Math.random()*1000)).intValue(); y = (new Double(Math.random()*1000)).intValue(); Shell testShell = new Shell(); testShell.open(); testShell.setBounds(x, y, width, height); assertEquals(x, testShell.getLocation().x); assertEquals(y, testShell.getLocation().y); testShell.close(); } } } Reproducible: Sometimes Steps to Reproduce: 1. Run the test case given in the details with a Linux64 machine