Incorrect Insets in Linux

Hi, my name is Alex and I’m working on a Java game development framework for school. I’m currently having a strange problem under Linux regarding insets.

The framework allows students to create their window in windowed or fullscreen mode. When in windowed mode, I need to know the size of the borders of the window so I can properly offset my mouse clicks coordinates and translate my graphic2D object. If I do not do this, coordinate 0,0 of my application is in the upper left corner of the window, most often in the window bar itself.

To find the size of the border, I use the getInsets method from my JFrame. This works perfectly under Windows and MacOs X. However, under Linux, about 10% of the time, getInsets will return the WRONG values for the insets. This results in a image being shifted by a few pixels. This problem happens more often in KDE, although I’ve been able to reproduce it in Fluxbox and WindowMaker. I need to try in Gnome.

This problem is completely non deterministic. If I run the same application 10 times, the window will shift once or twice. Other times, I’ll need to run the application 15 times before I see the problem. I’ve been able to determine that it is the getInset method which is returning the incorrect values (using a few well placed println statements).

Here is a snippet of the code I use to create and resize the window:

[tr][td]

greEnvironment = GraphicsEnvironment.getLocalGraphicsEnvironment();

MinuetoWindow.grdDevice = greEnvironment.getDefaultScreenDevice();
MinuetoWindow.grcConfiguration = MinuetoWindow.grdDevice.getDefaultConfiguration();

this.jfrFrame = new JFrame(this.grcConfiguration);

this.jfrFrame.setUndecorated(false);

this.jfrFrame.setIgnoreRepaint(true); this.jfrFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.jfrFrame.setTitle(“Minueto”);
this.jfrFrame.pack();

MinuetoWindow.grdDevice.setFullScreenWindow(null);

this.jfrFrame.setVisible(true);

insInsets = this.jfrFrame.getInsets();

this.iWindowOffsetX = insInsets.left;
this.iWindowOffsetY = insInsets.top;

this.jfrFrame.setSize(this.iWidth + insInsets.left + insInsets.right,
this.iHeight + insInsets.top + insInsets.bottom);

this.jfrFrame.createBufferStrategy(2);
this.busBufferStrategy = this.jfrFrame.getBufferStrategy();

this.grpGraphicsPointer = (Graphics2D)this.busBufferStrategy.getDrawGraphics();

this.grpGraphicsPointer.translate(this.iWindowOffsetX, this.iWindowOffsetY);

[/td][/tr]

Any ideas why I only have this problem under Linux? Any suggestions?

Alex

Most likely a threading issue related to you grabbing the insets immediately after making the Frame visible.

Try grabbing the insets after the window has definiely been made displayable.

i.e.
add a WindowListener, and grab the insets in the windowOpened(WindowEvent) method.

The window will definitely be visible at this point, so the insets should be correct.

If they arn’t, then its a more fundamental bug =/

Well, there is no need to fiddle around with insets.

Just create a JPanel (lightweight) or a Canvas (heavyweight) and add that one to the JFrame. 0/0 will then be magically in the upper left of the drawable/visible area.

The easiest way (imo) is to extend one of those and override public Dimension getPreferredSize() and public Dimension getMinimumSize(). Both just return new Dimension(widht, height). After adding that thing to the JFrame you just call pack() and that’s it.

So i decided to go with inserting a Canvas in my JFrame since I need to be able to create a buffer strategy. Right now my code looks like this:

if (fullscreen) {
// create bufferstrategy on jframe
// draw in jframe
} else {
// insert canvas in jframe
// create bufferstrategy on canvas
// draw in canvas
}

Also, in fullscreen mode, I put the mouseListener on the jframe. In window mode, the mouseListener goes on the canvas.

So everything looks stable. I’m doing extensive testing tomorrow. I’ll post if I have any problems.

Thanks for the help.