Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Archived » Albireo » More tips for the sample code
More tips for the sample code [message #572297] Wed, 26 September 2007 19:44
James is currently offline JamesFriend
Messages: 272
Registered: July 2009
Senior Member
I have found several more issues relating to focus and the SWT/Swing
integration. I have breifly outlined each issue below and posted my code
modifications at the bottom. I suspect I may not be clear enough in
describing both the issues, the solutions, and how they work, so please ask
any questions you might have. I would imagine others have periodically
noticed at least some of these issues as well.

Any thoughts on these Gordon?

My workarounds affect EmbeddedSwingComposite, SwtFocusHandler, and
AwtFocusHandler classes.

The issues:
#1
When using keyboard navigation, the default code misses sending the focus to
the AWT control on its first pass through (the returned focus component is
null). This can be solved by setting awtHasFocus to true at the top of the
gainFocus method instead of at the bottom. This will ensure that an attempt
is made to find a focusable swing control on the first focus attempt.

#2
I use an EmbeddedSwingComponent as the full contents of an editor
(consequently, the IWorkbenchPart's setFocus method sets the focus to the
EmbeddedSwingComponent). When issue #1 is fixed (ie, the AWT control
automatically gets the focus when the SWT control gets the focus), there is
occasionally a deadlock in Java 1.6 when several editors are opened at once
(even though only asycExec and invokeLater calls are used). The deadlock is
happening way down in AWT Code in the WPanelPeer class and is triggered by
the component.requestFocus inside of the awtHandler's gainFocus method.
This seems to be solved when issue #3 is solved.

#3
When the EmbeddedSwingComponent is the only focusable component inside of a
Tab Folder, the awtHandler.gainFocus call causes a malfunction in keyboard
navigation. When the tab labels get the focus (a tab's label is
underlined), typically one can switch between tabs by using the arrow keys
and then dive into the current tab using the 'tab' key. To do this, the SWT
Tab Folder seems to momentarily set the focus to the tab's contents and then
return focus to the tab label.

The problem is that we are telling AWT to take the focus when the tab's
contents gets the focus, so the focus doesn't go back to tab's label. I
have added set/get AbortFocus methods to the SwtFocusHandler. The abort
focus value is set whenever the SWT Control's focus is gained or lost. This
way if the SWT control loses focus before AWT has a chance to set its focus
we can decide not to set the AWT focus.

I suspect the deadlock also has something to do with this quick transfer of
focus.

#4
There is a memory leak when you dispose of the SWT Control even if you set
the frame to null. This leak is present in Java 1.5 update 11 and Java 1.6.
To remove the memory leak, the frame needs to have its FocusableWindowState
set to false and it should be disposed of when the EmbeddedSwingComponent is
disposed of. The frame should be disposed of in the Swing EDT.

In EmbeddedSwingComposite:

public EmbeddedSwingComposite(Composite parent, int style) {
super(parent, style | SWT.EMBEDDED | SWT.NO_BACKGROUND);
getDisplay().addListener(SWT.Settings, settingsListener);
setLayout(new FillLayout());
this.addDisposeListener(new DisposeListener()
{
public void widgetDisposed(DisposeEvent e)
{
final Frame frame = getFrame();
Runnable disposeEDTRunnable = new Runnable()
{
public void run()
{
disposeInEDT(frame);
}
};
if (SwingUtilities.isEventDispatchThread())
disposeEDTRunnable.run();
else
SwingUtilities.invokeLater(disposeEDTRunnable);
}
});
currentSystemFont = getFont();
}


private boolean awtDisposed = false;
public void disposeInEDT(Frame frame)
{
if (!awtDisposed)
{
awtDisposed = true;
if (frame != null)
{
frame.setFocusableWindowState(false);
frame.setFocusable(false);
frame.setEnabled(false);

getRootPaneContainer().getRootPane().getContentPane().remove All();
frame.removeAll();
frame.dispose();
}
}
}

A summary of my code changes below:

In AwtFocusHandler
public void gainFocus() {
assert frame != null;
// assert !awtHasFocus;
assert EventQueue.isDispatchThread(); // On AWT event thread

if (getSwtHandler().getAbortFocus())
{
awtHasFocus = false;
return;
}

awtHasFocus = true;
...

In SwtFocusHandler:
public void focusGained(FocusEvent e)
{
assert awtHandler != null;
assert Display.getCurrent() != null; // On SWT event thread

setAbortFocus(false);

System.out.println("Gained: " + e.toString() + " (" +
e.widget.getClass().getName() + ")");
EventQueue.invokeLater(new Runnable() {
public void run() {
System.out.println("Gain Focus - SWT Focus Handler EDT");
awtHandler.gainFocus();
}
});
}

private volatile boolean abortFocus = false;
public boolean getAbortFocus()
{
return abortFocus;
}

public void setAbortFocus(boolean abort)
{
this.abortFocus = abort;
}

public void focusLost(FocusEvent e)
{
setAbortFocus(true);/*
System.out.print("Focus Control: ");
System.out.println(e.display.getFocusControl());
System.out.println("Lost: " + e.toString() + " (" +
e.widget.getClass().getName() + ")");*/
}
Previous Topic:From the SWT/Swing artical proposal in Bugzilla
Next Topic:Creation Review Date?
Goto Forum:
  


Current Time: Thu Mar 28 20:35:12 GMT 2024

Powered by FUDForum. Page generated in 0.02900 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top