| Summary: | setVisible() slams previously set focus. | ||
|---|---|---|---|
| Product: | [Eclipse Project] Platform | Reporter: | Tod Creasey <Tod_Creasey> |
| Component: | SWT | Assignee: | Steve Northover <snorthov> |
| Status: | RESOLVED WONTFIX | QA Contact: | |
| Severity: | major | ||
| Priority: | P3 | ||
| Version: | 2.0 | ||
| Target Milestone: | --- | ||
| Hardware: | PC | ||
| OS: | Windows 2000 | ||
| Whiteboard: | |||
| Bug Depends on: | |||
| Bug Blocks: | 16240 | ||
If the shell was invisible, then none of its children had focus, so unless we remember this ourselves (we may, I haven't checked, but typically doing things like that gets you in trouble), we can't do what you want. SN to comment. The problem is not that the previous one was invisible - it was that setVisible (false) was sent to the one we want to get rid of. As a result it will setFocus on the first widget of the remaining one whether it is visible or not. Right, setFocus sets the focus. It doesn't restore previous saved focus widgets or anything like that. Otherwise, it could never be used to set focus to a widget. I'm pretty tired so I may not quite understand. Could you code a short example? We (VI and me) have recently played with "setVisible(false) reassigning focus if the focus was in the widget tree" and this could be a change that is burning you. Here is an example
If you press the open with composite focus button the focus will be on the
first (incorrect) widget.
If you press the open without composite focus button the focus will be on the
last (correct widget).
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.*;
public class WindowFocusTest {
public static void main(String[] args) {
final Display display = new Display();
Shell shell = new Shell(display);
GridLayout layout = new GridLayout();
shell.setLayout(layout);
Button labelButton = new Button(shell,SWT.PUSH);
labelButton.setText("Open Window With Composite Focus");
labelButton.addSelectionListener(
new SelectionListener(){
public void widgetSelected(SelectionEvent e){
openWindow(display,true);
};
public void widgetDefaultSelected
(SelectionEvent e){}
});
Button labelButton2 = new Button(shell,SWT.PUSH);
labelButton2.setText("Open Window Without Composite Focus");
labelButton2.addSelectionListener(
new SelectionListener(){
public void widgetSelected(SelectionEvent e){
openWindow(display,false);
};
public void widgetDefaultSelected
(SelectionEvent e){}
});
shell.setBounds(0,0,300,100);
labelButton.setVisible(true);
labelButton.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
/*
* Open a window for a editing text
*/
public static void openWindow(Display display, boolean focusComposite){
Shell shell = new Shell(display);
Composite composite = new Composite(shell, SWT.BORDER);
composite.setVisible(false);
GridLayout layout = new GridLayout();
layout.numColumns = 3;
composite.setLayout(layout);
GridData data = new GridData(GridData.FILL_BOTH);
data.grabExcessHorizontalSpace = true;
composite.setLayoutData(data);
composite.setVisible(true);
for(int i = 0; i < 6; i ++){
Text text = new Text(composite,SWT.NULL);
if (i ==5)
text.setFocus();
}
composite.pack();
shell.setBounds(0,0,500,500);
shell.open();
if(focusComposite)
composite.setFocus();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
}
}
This one's pretty annoying and is easily encountered. See bug 16780. This is working as designed. When you setFocus() to a composite, it finds the first child that will take focus and assigns focus there. It does not see if a child already has focus and do nothing. Am I missing something? I ran the code on Motif and it has the same behavior. The problem is that if you have setFocus on widget before it is made visible the focus is slammed into the first widget in the children even if you tried to give focus on a different one. Checking if a child had focus before slamming the first one who can take it would solve this. This makes it hard for wizard developers as we do not give them the first page and they will have to reset focus. Not a bug so I won't fix it. |
If you have a shell where you want to make one control no longer visible and make another shell visible the setFocus() method in Composite sets the focus on the first widget no matter if focus was previously set for (int i=0; i<children.length; i++) { Control child = children [i]; if (child.setFocus ()) return true; The problem is that if one the children already has focus set previously it it cleared out. A check for all of them to see if anyone hasFocus would be better first so that if there already is one with focus focus does not get slammed.