Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 336238

Summary: Shell.setBounds sometimes fails to set the right location
Product: [Eclipse Project] Platform Reporter: Dominik Schmid <dominik.schmid>
Component: SWTAssignee: Xi Yan <xixiyan>
Status: VERIFIED FIXED QA Contact:
Severity: normal    
Priority: P3 CC: akurtakov, eclipse.felipe, ericwill, patrick.tasse, remy.suen
Version: 3.6.1Keywords: 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:

Description Dominik Schmid CLA 2011-02-03 10:09:21 EST
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
Comment 1 Felipe Heidrich CLA 2011-02-03 11:11:06 EST
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 ?
Comment 2 Dominik Schmid CLA 2011-02-04 06:40:44 EST
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.
Comment 3 Eric Williams CLA 2016-10-18 16:40:36 EDT
I can reproduce this bug.
Comment 4 Patrick Tasse CLA 2018-04-13 09:21:10 EDT
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);
});
Comment 5 Eric Williams CLA 2018-07-12 15:19:45 EDT
Xi, please investigate.
Comment 6 Eclipse Genie CLA 2018-07-20 17:03:54 EDT
New Gerrit change created: https://git.eclipse.org/r/126408
Comment 8 Eric Williams CLA 2018-08-23 08:54:00 EDT
Verified in I20180821-2000.