[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 (or anyone),
As you suspected, my workaround for the requestFocus deadlock issue is not a
solution 100% of the time. In fact, lately the issue is happening
frequently enough to prevent my next software release.
Have you any idea why I might be getting deadlock in
WComponentPeer._requestFocus when calling it from the AWT EDT after an
invokeLater from the SWT EDT? I could really use some help with this one.
Naturally, as with most timing bugs, I don't really have a snipped that I
can post.
-James
"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.
>