[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Newsgroup Home]
[news.eclipse.technology.albireo] Re: More tips for the sample code

Gordon - has this fix been applied to 0.0.3? I took a look, but it seems like things have changed a lot and I was not able to identify if these changes are in the latest release. Or are they no longer even necessary?

Thanks!

- Ken

"Gordon Hirsch" <gordon.hirsch@xxxxxxx> wrote in message news:fdh53e$j7i$1@xxxxxxxxxxxxxxxxxxxx
James wrote:
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?

James, first of all, thank you for sharing your fixes and improvements. I have some comments and questions below.



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.

Yes, this is definitely a bug in the article. Another solution is to change the EmbeddedChildFocusTraversalPolicy.getCurrentComponent() method to call super.getDefaultComponent, rather than this.getDefaultComponent.



#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.

It's now pretty clear that Component.requestFocus has to be used carefully to avoid deadlock (and in our case other problems). The main thing is to make sure that it is always called from the AWT event thread. Unfortunately, the article code calls it from the SWT thread in two places. For example, I've now re-implemented EmbeddedSwingComposite.setFocus() as follows:


    public boolean setFocus() {
        checkWidget();

//if (!isFocusable()) {
// return false;
//}
if (swtHandler != null) {
// Setting focus on the embedded component must posted to the
// AWT thread because:
// 1) The AWT Component.requestFocus method can deadlock if
// called simultaneously from different threads.
// 2) The embedded component is created asynhronously (on the
// AWT thread), so it may not exist yet.
// The call below does the appropriate posting. Since it is done
// asynchronously, it is impossible to know the result, so
// always return true.
swtHandler.transferFocusToAwt();
return true;
} else {
return super.setFocus();
}
}


transferFocusToAwt is what you would expect:

    void transferFocusToAwt() {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                awtHandler.gainFocus();
            }
        });
    }

A similar change is needed to the EmbeddedSwingComposite.forceFocus method.

I suspect these fixes will eliminate the deadlock problem you saw and that your solution to #3, though useful in its own right, simply made the deadlock less likely.


#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.

I didn't know you could navigate this way, so it clearly wasn't tested :-). Your solution looks like a good one.



#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.

Interesting. SWT_AWT.new_Frame() installs a listener that is supposed to dispose the frame (on the AWT event thread) when the composite is disposed. Any ideas on why this is not happening?


Is the need to set FocusableWindowState to false maybe due to this bug?

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6469530.

Or something else? I'm wondering if there's something that needs to be reported to Sun...

I ran into a similar leak that was triggered by adding components to the frame from outside the AWT EDT. See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6411042.