-
Bug
-
Resolution: Fixed
-
P1
-
1.1.4
-
1.1.5
-
sparc
-
solaris_2.5, solaris_2.6
-
Verified
Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-2017371 | 1.2.0 | Paul Young | P1 | Resolved | Fixed | 1.2beta2 |
The following program run on Solaris with JDK 1.1.4 should place the
frame at (0,0) in fact it comes up at a random place (well wherever
the window manager chooses). In fact a bug like this for the general
move(0,0) problem has been previously fixed (bug 1261242) with a hack
to place it at (1,1) instead, to get around the underlying Motif problem.
// MoveWindow.java
import java.awt.*;
import java.awt.event.*;
class MoveWindow extends Frame implements WindowListener {
public static void main(String args[]) {
MoveWindow w = new MoveWindow();
w.move(0,0);
w.setVisible(true);
}
public MoveWindow() {
super("MoveWindow");
add("Center", new Label("Hello World"));
addWindowListener(this);
pack();
}
public void windowOpened(WindowEvent e) {
}
public void windowClosing(WindowEvent e) {
System.exit(0);
}
public void windowClosed(WindowEvent e) {
}
public void windowIconified(WindowEvent e) {
}
public void windowDeiconified(WindowEvent e) {
}
public void windowActivated(WindowEvent e) {
}
public void windowDeactivated(WindowEvent e) {
}
}
The reason this bug is still occuring is that the fix in
src/solaris/sun/awt_Frame.c in the function
sun_awt_motif_MFramePeer_pReshape(..)
is immediately undone, where I have written "Oops"
i.e the code looks like :-
/* GES: AVH's hack from awt_util.c:
* Motif ignores attempts to move a toplevel window to 0,0.
* Instead we set the position to 1,1. The expected value is
* returned by Frame.getBounds() since it uses the internally
* held rectangle rather than querying the peer.
*/
if ((x == 0) && (y == 0)) {
XtVaSetValues(wdata->winData.shell, XmNx, 1, XmNy, 1, NULL);
}
XtVaSetValues(wdata->winData.shell,
XtNx, (XtArgVal) x, /* << Oops! */
XtNy, (XtArgVal) y, /* << Oops again! */
XtNwidth, (XtArgVal) w - (wdata->left + wdata->right),
XtNheight, (XtArgVal) h + hoffset - (wdata->top + wdata->botto
m),
NULL);
A clarification should be made I think: this bug only occurs when the
frame location is set before the window is shown. This is probably the
most common case of course.
Before the window is shown (realized in Xt speak) I think the XtSetValues
is simply "stashed away" and the susbeuqent call to XtSetValues then restores
the (0,0) which is what is in effect when XtRealize is called.
In the case for which the fix to bug 1261242 works, on windows which
are already showing, and it works because
the XtVaSetValues(wdata->winData.shell, XmNx, 1, XmNy, 1, NULL) call
immediately causes the existing window to be moved to (1,1)
So one might expect that in a Java app if you called another call
to setLocation(0,0) after the setVisible(true) call that it would
then have the desired effect. This fails becuuse the java Frame object
detects that the supposed old location is the same as the new location,
so does not actually make the Xt call.
The whole (1,1) hack looks OK to the user because the window manager
border is wider than that, and the window manager makes sure that its
border corner is placed at (0,0), so any location which is smaller than
the border will place the reparented window at screen 0,0.
frame at (0,0) in fact it comes up at a random place (well wherever
the window manager chooses). In fact a bug like this for the general
move(0,0) problem has been previously fixed (bug 1261242) with a hack
to place it at (1,1) instead, to get around the underlying Motif problem.
// MoveWindow.java
import java.awt.*;
import java.awt.event.*;
class MoveWindow extends Frame implements WindowListener {
public static void main(String args[]) {
MoveWindow w = new MoveWindow();
w.move(0,0);
w.setVisible(true);
}
public MoveWindow() {
super("MoveWindow");
add("Center", new Label("Hello World"));
addWindowListener(this);
pack();
}
public void windowOpened(WindowEvent e) {
}
public void windowClosing(WindowEvent e) {
System.exit(0);
}
public void windowClosed(WindowEvent e) {
}
public void windowIconified(WindowEvent e) {
}
public void windowDeiconified(WindowEvent e) {
}
public void windowActivated(WindowEvent e) {
}
public void windowDeactivated(WindowEvent e) {
}
}
The reason this bug is still occuring is that the fix in
src/solaris/sun/awt_Frame.c in the function
sun_awt_motif_MFramePeer_pReshape(..)
is immediately undone, where I have written "Oops"
i.e the code looks like :-
/* GES: AVH's hack from awt_util.c:
* Motif ignores attempts to move a toplevel window to 0,0.
* Instead we set the position to 1,1. The expected value is
* returned by Frame.getBounds() since it uses the internally
* held rectangle rather than querying the peer.
*/
if ((x == 0) && (y == 0)) {
XtVaSetValues(wdata->winData.shell, XmNx, 1, XmNy, 1, NULL);
}
XtVaSetValues(wdata->winData.shell,
XtNx, (XtArgVal) x, /* << Oops! */
XtNy, (XtArgVal) y, /* << Oops again! */
XtNwidth, (XtArgVal) w - (wdata->left + wdata->right),
XtNheight, (XtArgVal) h + hoffset - (wdata->top + wdata->botto
m),
NULL);
A clarification should be made I think: this bug only occurs when the
frame location is set before the window is shown. This is probably the
most common case of course.
Before the window is shown (realized in Xt speak) I think the XtSetValues
is simply "stashed away" and the susbeuqent call to XtSetValues then restores
the (0,0) which is what is in effect when XtRealize is called.
In the case for which the fix to bug 1261242 works, on windows which
are already showing, and it works because
the XtVaSetValues(wdata->winData.shell, XmNx, 1, XmNy, 1, NULL) call
immediately causes the existing window to be moved to (1,1)
So one might expect that in a Java app if you called another call
to setLocation(0,0) after the setVisible(true) call that it would
then have the desired effect. This fails becuuse the java Frame object
detects that the supposed old location is the same as the new location,
so does not actually make the Xt call.
The whole (1,1) hack looks OK to the user because the window manager
border is wider than that, and the window manager makes sure that its
border corner is placed at (0,0), so any location which is smaller than
the border will place the reparented window at screen 0,0.
- backported by
-
JDK-2017371 java.awt.Frame.setLocation(0,0) is broken on Solaris
-
- Resolved
-