Bug 213594

Summary: SWTEventDispatcher: requestRemoveFocus called by removeNotify removes focus for any figure.
Product: [Tools] GEF Reporter: Heiko Böttger <heiko.boettger>
Component: GEF-Legacy Draw2dAssignee: gef-inbox <gef-inbox>
Status: NEW --- QA Contact:
Severity: normal    
Priority: P3    
Version: 3.2   
Target Milestone: ---   
Hardware: PC   
OS: Windows XP   
Whiteboard:

Description Heiko Böttger CLA 2007-12-20 10:33:24 EST
Build ID: M20070212-1330

Steps To Reproduce:
When a figure is removed from its parent, it invokes the requestRemoveFocus method of the EventDispatcher. In case of the SWTEventDispatcher this results in the focus to be lost when the FigureCanvas loses and gains it's focus:

  public void testDraw2D() {
    Shell shell = new Shell();
    
    // setup 
    
    FigureCanvas figureCanvas=new FigureCanvas(shell, SWT.NONE);
    Figure root = new Figure();
    figureCanvas.getViewport().setContents(root);
    
    Figure label1 = createFigureAndAdd(root);
    Figure label2 = createFigureAndAdd(root);
    Figure label3 = createFigureAndAdd(root);
    
    // test
    
    label2.requestFocus();
    
    root.remove(label3); 
    //or figureCanvas.getViewport().internalGetEventDispatcher().requestRemoveFocus(label2);
    System.out.println(label1.hasFocus() == false);
    System.out.println(label2.hasFocus() == true);
    
    figureCanvas.getViewport().internalGetEventDispatcher().dispatchFocusLost(null);
    figureCanvas.getViewport().internalGetEventDispatcher().dispatchFocusGained(null);
    
    System.out.println(label1.hasFocus() == false);
    System.out.println(label2.hasFocus() == true);
    
    shell.dispose();
  }



More information:
The current implementation of SWTEventDispatcher.requestRemoveFocus looks like this:

/**
 * @see EventDispatcher#requestRemoveFocus(IFigure)
 */
public void requestRemoveFocus(IFigure fig) {
	if (getFocusOwner() == fig)
		setFocus(null);
	if (mouseTarget == fig)
		mouseTarget = null;
	if (cursorTarget == fig)
		cursorTarget = null;
	if (hoverSource == fig)
		hoverSource = null;
	getFocusTraverseManager().setCurrentFocusOwner(null);
}

The last line should test if the figure that lost focus was the owner:

/**
 * @see EventDispatcher#requestRemoveFocus(IFigure)
 */
public void requestRemoveFocus(IFigure fig) {
	boolean wasOwner = (getFocusOwner() == fig);
	if (wasOwner) setFocus(null);
	if (mouseTarget == fig)
		mouseTarget = null;
	if (cursorTarget == fig)
		cursorTarget = null;
	if (hoverSource == fig)
		hoverSource = null;
	if (wasOwner) getFocusTraverseManager().setCurrentFocusOwner(null);
}