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 #1401] Wed, 26 September 2007 19:44 Go to next message
Eclipse User
Originally posted by: canadianguy.gmail.com

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() + ")");*/
}
One more issue [message #1407 is a reply to message #1401] Wed, 26 September 2007 20:24 Go to previous messageGo to next message
Eclipse User
Originally posted by: canadianguy.gmail.com

This also has to do with putting the EmbeddedSwingComposite under a tab
folder.

When AWT has focus and the tab is clicked, AWT loses focus but the composite
does not get a focusGained event (as far as SWT is concerned, it never lost
focus).

I have added a check when the AWT window loses focus to inform the SWT
handler that the backing composite may have re-gained the focus.

At the end of AwtFocusHandler.windowLostFocus:
if (!swtHandler.getDisplay().isDisposed())
{
Runnable runnable = new Runnable()
{
public void run()
{
swtHandler.reApplyFocus();
}
};
swtHandler.getDisplay().asyncExec(runnable);
}

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


if (Display.getCurrent() != null &&
!Display.getCurrent().isDisposed() && composite ==
Display.getCurrent().getFocusControl())
{
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();
}
});
}
}
Re: More tips for the sample code [message #1412 is a reply to message #1401] Thu, 27 September 2007 20:50 Go to previous messageGo to next message
Gordon Hirsch is currently offline Gordon Hirsch
Messages: 100
Registered: July 2009
Senior Member
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.
Re: One more issue [message #1416 is a reply to message #1407] Thu, 27 September 2007 21:20 Go to previous messageGo to next message
Gordon Hirsch is currently offline Gordon Hirsch
Messages: 100
Registered: July 2009
Senior Member
James,

Excellent, thanks! I had noticed this problem, but my attempted solution
had bad side effects. You can still find it (partially) in the
commented-out code. I think you are doing a better job of using the
right thread in all cases, so that may be what avoids the side effects.

As I recall, the problem with my attempt was that the AWT frame would
grab focus in cases where it shouldn't. For example, if I tried to
activate a different application's window, suddenly the RCP app with the
embedded AWT frame would pop up on top of it. I assume you haven't seen
anything like this with your fix?

James wrote:
> This also has to do with putting the EmbeddedSwingComposite under a tab
> folder.
>
> When AWT has focus and the tab is clicked, AWT loses focus but the composite
> does not get a focusGained event (as far as SWT is concerned, it never lost
> focus).
>
> I have added a check when the AWT window loses focus to inform the SWT
> handler that the backing composite may have re-gained the focus.
>
> At the end of AwtFocusHandler.windowLostFocus:
> if (!swtHandler.getDisplay().isDisposed())
> {
> Runnable runnable = new Runnable()
> {
> public void run()
> {
> swtHandler.reApplyFocus();
> }
> };
> swtHandler.getDisplay().asyncExec(runnable);
> }
>
> In SwtFocusHandler:
> public void reApplyFocus()
> {
> assert awtHandler != null;
> assert Display.getCurrent() != null; // On SWT event thread
>
>
> if (Display.getCurrent() != null &&
> !Display.getCurrent().isDisposed() && composite ==
> Display.getCurrent().getFocusControl())
> {
> 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();
> }
> });
> }
> }
>
>
Re: More tips for the sample code [message #1420 is a reply to message #1401] Thu, 27 September 2007 21:25 Go to previous messageGo to next message
Gordon Hirsch is currently offline Gordon Hirsch
Messages: 100
Registered: July 2009
Senior Member
James wrote:
> #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)
> {

One other thing I forgot to mention... in the article, I had an
implementation of EmbeddedSwingComposite.dispose like this:

public void dispose() {
if (!isDisposed()) {
getDisplay().removeListener(SWT.Settings, settingsListener);
getDisplay().removeFilter(SWT.Show, menuListener);
super.dispose();
}
}

This is the wrong way to write code that runs at dispose time. The two
listeners should be removed in a dispose listener, just like the one
you've created here, so you should add them to your widgetDisposed() and
remove the dispose() method.

> final Frame frame = getFrame();
> Runnable disposeEDTRunnable = new Runnable()
> {
> public void run()
> {
> disposeInEDT(frame);
> }
> };
> if (SwingUtilities.isEventDispatchThread())
> disposeEDTRunnable.run();
> else
> SwingUtilities.invokeLater(disposeEDTRunnable);
> }
> });
> currentSystemFont = getFont();
> }
>
>
Re: One more issue [message #1424 is a reply to message #1416] Fri, 28 September 2007 11:33 Go to previous messageGo to next message
Eclipse User
Originally posted by: canadianguy.gmail.com

Gordon,

I haven't seen anything like that but that doesn't guarantee that it won't
happen in a kind of 'perfect storm' of the two UI Threads. When the RCP
application loses focus to another application, this causes the SWT's focus
component to become null, so the AWT component shouldn't re-grab the focus.

-James

"Gordon Hirsch" <gordon.hirsch@sas.com> wrote in message
news:fdh6qi$v82$1@build.eclipse.org...
> James,
>
> Excellent, thanks! I had noticed this problem, but my attempted solution
> had bad side effects. You can still find it (partially) in the
> commented-out code. I think you are doing a better job of using the
> right thread in all cases, so that may be what avoids the side effects.
>
> As I recall, the problem with my attempt was that the AWT frame would
> grab focus in cases where it shouldn't. For example, if I tried to
> activate a different application's window, suddenly the RCP app with the
> embedded AWT frame would pop up on top of it. I assume you haven't seen
> anything like this with your fix?
>
> James wrote:
> > This also has to do with putting the EmbeddedSwingComposite under a tab
> > folder.
> >
> > When AWT has focus and the tab is clicked, AWT loses focus but the
composite
> > does not get a focusGained event (as far as SWT is concerned, it never
lost
> > focus).
> >
> > I have added a check when the AWT window loses focus to inform the SWT
> > handler that the backing composite may have re-gained the focus.
> >
> > At the end of AwtFocusHandler.windowLostFocus:
> > if (!swtHandler.getDisplay().isDisposed())
> > {
> > Runnable runnable = new Runnable()
> > {
> > public void run()
> > {
> > swtHandler.reApplyFocus();
> > }
> > };
> > swtHandler.getDisplay().asyncExec(runnable);
> > }
> >
> > In SwtFocusHandler:
> > public void reApplyFocus()
> > {
> > assert awtHandler != null;
> > assert Display.getCurrent() != null; // On SWT event thread
> >
> >
> > if (Display.getCurrent() != null &&
> > !Display.getCurrent().isDisposed() && composite ==
> > Display.getCurrent().getFocusControl())
> > {
> > 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();
> > }
> > });
> > }
> > }
> >
> >
Re: More tips for the sample code [message #1428 is a reply to message #1420] Fri, 28 September 2007 11:40 Go to previous messageGo to next message
Eclipse User
Originally posted by: canadianguy.gmail.com

I thought that was the case (I noticed that the dispose code wasn't getting
called). I have already moved the dispose code elsewhere and call it from
the dispose listener.

"Gordon Hirsch" <gordon.hirsch@sas.com> wrote in message
news:fdh750$un$1@build.eclipse.org...
> James wrote:
> > #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)
> > {
>
> One other thing I forgot to mention... in the article, I had an
> implementation of EmbeddedSwingComposite.dispose like this:
>
> public void dispose() {
> if (!isDisposed()) {
> getDisplay().removeListener(SWT.Settings, settingsListener);
> getDisplay().removeFilter(SWT.Show, menuListener);
> super.dispose();
> }
> }
>
> This is the wrong way to write code that runs at dispose time. The two
> listeners should be removed in a dispose listener, just like the one
> you've created here, so you should add them to your widgetDisposed() and
> remove the dispose() method.
>
> > final Frame frame = getFrame();
> > Runnable disposeEDTRunnable = new Runnable()
> > {
> > public void run()
> > {
> > disposeInEDT(frame);
> > }
> > };
> > if (SwingUtilities.isEventDispatchThread())
> > disposeEDTRunnable.run();
> > else
> > SwingUtilities.invokeLater(disposeEDTRunnable);
> > }
> > });
> > currentSystemFont = getFont();
> > }
> >
> >
Re: More tips for the sample code [message #1432 is a reply to message #1412] Fri, 28 September 2007 11:54 Go to previous messageGo to next message
Eclipse User
Originally posted by: canadianguy.gmail.com

"Gordon Hirsch" <gordon.hirsch@sas.com> wrote in message
news:fdh53e$j7i$1@build.eclipse.org...
> 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.

Not a problem. Your article code allowed us to have a product that was at
least usable (I was going crazy dealing with modal dialogs). We all benefit
from making these two UIs play well together.

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

In my version of the article code (I'm not sure it changed after I
downloaded it), the setFocus doesn't make any AWT Calls. It simple checks
to see if it is focusable and calls super.setFocus()... strange.

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

Yes, I'm pretty sure that this is the same bug (as I recall from the last
time I ran this through a profiler). The GlobalRef stays in place until
another component gets focus. In our case (probably some of the special
world of the SWT/AWT mix), it is reproducable 100% of the time. I have
found that setting the setFocusableWindowState to false before the frame is
disposed is also a work-around to the problem. To be honest, I don't know
if the other explicit call to dispose is necessary.

> 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.
>
Re: More tips for the sample code [message #1435 is a reply to message #1432] Fri, 28 September 2007 12:05 Go to previous messageGo to next message
Eclipse User
Originally posted by: canadianguy.gmail.com

Aside from not seeming to make an AWT call out side of the AWT Thread, this
alternate implementation you have proposed breaks the fix for keyboard
navigation I describe (the SWT Component never really gains focus so it can
never lose it).

> In my version of the article code (I'm not sure it changed after I
> downloaded it), the setFocus doesn't make any AWT Calls. It simple checks
> to see if it is focusable and calls super.setFocus()... strange.
>
> > 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.
> >
Re: More tips for the sample code [message #3240 is a reply to message #1435] Sun, 07 October 2007 18:10 Go to previous messageGo to next message
Gordon Hirsch is currently offline Gordon Hirsch
Messages: 100
Registered: July 2009
Senior Member
James wrote:
> Aside from not seeming to make an AWT call out side of the AWT Thread, this
> alternate implementation you have proposed breaks the fix for keyboard
> navigation I describe (the SWT Component never really gains focus so it can
> never lose it).

You're right. After looking a little closer, I don't think the
implementations of setFocus/forceFocus are necessary at all.

By the way, the extra code in setFocus/forceFocus was not part of the
original article. Sorry for any confusion I might have caused.

>
>> In my version of the article code (I'm not sure it changed after I
>> downloaded it), the setFocus doesn't make any AWT Calls. It simple checks
>> to see if it is focusable and calls super.setFocus()... strange.
>>
>>> 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.
>>>
>
>
Re: More tips for the sample code [message #5247 is a reply to message #1412] Tue, 27 November 2007 02:35 Go to previous messageGo to next message
Eclipse User
Originally posted by: canadianguy.gmail.com

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@sas.com> wrote in message
news:fdh53e$j7i$1@build.eclipse.org...
> 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.
>
Re: More tips for the sample code [message #5313 is a reply to message #5247] Tue, 27 November 2007 16:19 Go to previous messageGo to next message
Gordon Hirsch is currently offline Gordon Hirsch
Messages: 100
Registered: July 2009
Senior Member
James Peltzer wrote:
> 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.

Could you post stack traces from the deadlocked JVM? They would be
extremely helpful in diagnosing what the two EDTs (and possibly other
threads) are doing at that point.
Re: More tips for the sample code [message #5368 is a reply to message #5313] Tue, 27 November 2007 23:31 Go to previous messageGo to next message
Eclipse User
Originally posted by: canadianguy.gmail.com

Unfortunately I seem the Debugger seems to throw errors whenever I try to
suspend execution. I have changed my Eclipse version from 3.2.2 to 3.3.1.1
and the issue has gone back into hiding. I'll try to get more information
to you.

-James

"Gordon Hirsch" <gordon.hirsch@sas.com> wrote in message
news:fihg2f$rkr$1@build.eclipse.org...
> James Peltzer wrote:
>> 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.
>
> Could you post stack traces from the deadlocked JVM? They would be
> extremely helpful in diagnosing what the two EDTs (and possibly other
> threads) are doing at that point.
Re: More tips for the sample code [message #6694 is a reply to message #5368] Wed, 28 November 2007 16:31 Go to previous messageGo to next message
Gordon Hirsch is currently offline Gordon Hirsch
Messages: 100
Registered: July 2009
Senior Member
You can also get the stack traces with the jconsole tool that comes with
the JDK
( http://java.sun.com/j2se/1.5.0/docs/guide/management/jconsol e.html) or
by hitting Ctrl-Break (on Windows, running with java.exe as opposed to
javaw.exe).

James Peltzer wrote:
> Unfortunately I seem the Debugger seems to throw errors whenever I try to
> suspend execution. I have changed my Eclipse version from 3.2.2 to 3.3.1.1
> and the issue has gone back into hiding. I'll try to get more information
> to you.
>
> -James
>
> "Gordon Hirsch" <gordon.hirsch@sas.com> wrote in message
> news:fihg2f$rkr$1@build.eclipse.org...
>> James Peltzer wrote:
>>> 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.
>> Could you post stack traces from the deadlocked JVM? They would be
>> extremely helpful in diagnosing what the two EDTs (and possibly other
>> threads) are doing at that point.
>
>
Re: More tips for the sample code [message #10860 is a reply to message #6694] Fri, 28 November 2008 17:17 Go to previous messageGo to next message
Jan Gurda is currently offline Jan Gurda
Messages: 2
Registered: July 2009
Junior Member
Hi I have similar problem. During invocation of function
JTabbedPane.setSelectedIndex my application hangs.

Here is part of stack trace from jconsole:

Name: AWT-EventQueue-1
State: BLOCKED on java.awt.Component$AWTTreeLock@1cc2f15 owned by:
AWT-EventQueue-0
Total blocked: 9 726 Total waited: 145 509

Stack trace:
java.awt.Component.invalidate(Unknown Source)
java.awt.Container.invalidate(Unknown Source)
javax.swing.JComponent.revalidate(Unknown Source)
javax.swing.plaf.basic.BasicTextUI$RootView.preferenceChange d(Unknown
Source)
javax.swing.text.View.preferenceChanged(Unknown Source)
javax.swing.text.PlainView.updateDamage(Unknown Source)
javax.swing.text.PlainView.insertUpdate(Unknown Source)
javax.swing.plaf.basic.BasicTextUI$RootView.insertUpdate(Unk nown Source)
javax.swing.plaf.basic.BasicTextUI$UpdateHandler.insertUpdat e(Unknown
Source)
javax.swing.text.AbstractDocument.fireInsertUpdate(Unknown Source)
javax.swing.text.AbstractDocument.handleInsertString(Unknown Source)
javax.swing.text.AbstractDocument.insertString(Unknown Source)
javax.swing.text.PlainDocument.insertString(Unknown Source)
javax.swing.JTextArea.append(Unknown Source)
com.sun.deploy.util.ConsoleWindow$25.run(Unknown Source)
java.awt.event.InvocationEvent.dispatch(Unknown Source)
java.awt.EventQueue.dispatchEvent(Unknown Source)
java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
java.awt.EventDispatchThread.pumpEvents(Unknown Source)
java.awt.EventDispatchThread.pumpEvents(Unknown Source)
java.awt.EventDispatchThread.run(Unknown Source)


Name: ConsoleWriterThread
State: WAITING on java.lang.Object@180dc21
Total blocked: 31 Total waited: 20 612

Stack trace:
java.lang.Object.wait(Native Method)
java.lang.Object.wait(Object.java:485)
com.sun.deploy.util.ConsoleTraceListener$ConsoleWriterThread .run(Unknown
Source)


Name: CacheCleanUpThread
State: WAITING on com.sun.deploy.cache.CleanupThread@1887a29
Total blocked: 0 Total waited: 1

Stack trace:
java.lang.Object.wait(Native Method)
java.lang.Object.wait(Object.java:485)
com.sun.deploy.cache.CleanupThread.run(Unknown Source)


Name: TimerQueue
State: TIMED_WAITING on javax.swing.TimerQueue@6a2cde
Total blocked: 8 Total waited: 284 784

Stack trace:
java.lang.Object.wait(Native Method)
javax.swing.TimerQueue.run(Unknown Source)
java.lang.Thread.run(Unknown Source)

Name: AWT-EventQueue-0
State: RUNNABLE
Total blocked: 6 119 Total waited: 721 830

Stack trace:
sun.awt.windows.WComponentPeer._requestFocus(Native Method)
sun.awt.windows.WComponentPeer.requestFocus(Unknown Source)
java.awt.Component.requestFocusHelper(Unknown Source)
java.awt.Component.requestFocus(Unknown Source)
java.awt.Component.postNextFocusHelper(Unknown Source)
java.awt.Component.nextFocusHelper(Unknown Source)
java.awt.Container.nextFocusHelper(Unknown Source)
java.awt.Component.doAutoTransfer(Unknown Source)
java.awt.Component.autoTransferFocus(Unknown Source)
java.awt.Component.autoTransferFocus(Unknown Source)
java.awt.Component.hide(Unknown Source)
- locked java.awt.Component$AWTTreeLock@1cc2f15
java.awt.Component.show(Unknown Source)
java.awt.Component.setVisible(Unknown Source)
javax.swing.JComponent.setVisible(Unknown Source)
javax.swing.JTabbedPane.fireStateChanged(Unknown Source)
javax.swing.JTabbedPane$ModelListener.stateChanged(Unknown Source)
javax.swing.DefaultSingleSelectionModel.fireStateChanged(Unk nown Source)
javax.swing.DefaultSingleSelectionModel.setSelectedIndex(Unk nown Source)
javax.swing.JTabbedPane.setSelectedIndexImpl(Unknown Source)
javax.swing.JTabbedPane.setSelectedIndex(Unknown Source)
com.qumak.toolbar.client.mail.gui.MailPanel_Tabs.setSelected LastPanel(MailPanel_Tabs.java:122)
com.qumak.toolbar.client.mail.gui.MailPanel_Controller.prepa reGUIForNewMail(MailPanel_Controller.java:385)
com.qumak.toolbar.client.mail.gui.MailPanel_Incomming$Forwar dMailWorker.done(MailPanel_Incomming.java:300)
javax.swing.SwingWorker$5.run(Unknown Source)
javax.swing.SwingWorker$DoSubmitAccumulativeRunnable.run(Unk nown Source)
sun.swing.AccumulativeRunnable.run(Unknown Source)
javax.swing.SwingWorker$DoSubmitAccumulativeRunnable.actionP erformed(Unknown
Source)
javax.swing.Timer.fireActionPerformed(Unknown Source)
javax.swing.Timer$DoPostEvent.run(Unknown Source)
java.awt.event.InvocationEvent.dispatch(Unknown Source)
java.awt.EventQueue.dispatchEvent(Unknown Source)
java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
java.awt.EventDispatchThread.pumpEvents(Unknown Source)
java.awt.EventDispatchThread.pumpEvents(Unknown Source)
java.awt.EventDispatchThread.run(Unknown Source)



Last thread is causing the deadlock, but I don't know why. Currently I use
some components built on SWT (3.5 Milestone 1). Also I cannot notice any
swt function invocations in the whole jconsole trace.

I will be very grateful for reply. What do you think?

Regards,

Jan Gurda
Re: More tips for the sample code [message #10874 is a reply to message #10860] Tue, 02 December 2008 18:20 Go to previous messageGo to next message
Gordon Hirsch is currently offline Gordon Hirsch
Messages: 100
Registered: July 2009
Senior Member
This doesn't look like a problem with SWT/Swing integration. What's
unusual is that you seem to have two AWT event threads running and there
is some contention between them. I don't know you'd diagnose/fix this
problem.

Jan Gurda wrote:
> Hi I have similar problem. During invocation of function
> JTabbedPane.setSelectedIndex my application hangs.
>
> Here is part of stack trace from jconsole:
>
> Name: AWT-EventQueue-1
> State: BLOCKED on java.awt.Component$AWTTreeLock@1cc2f15 owned by:
> AWT-EventQueue-0
> Total blocked: 9 726 Total waited: 145 509
>
> Stack trace: java.awt.Component.invalidate(Unknown Source)
> java.awt.Container.invalidate(Unknown Source)
> javax.swing.JComponent.revalidate(Unknown Source)
> javax.swing.plaf.basic.BasicTextUI$RootView.preferenceChange d(Unknown
> Source)
> javax.swing.text.View.preferenceChanged(Unknown Source)
> javax.swing.text.PlainView.updateDamage(Unknown Source)
> javax.swing.text.PlainView.insertUpdate(Unknown Source)
> javax.swing.plaf.basic.BasicTextUI$RootView.insertUpdate(Unk nown Source)
> javax.swing.plaf.basic.BasicTextUI$UpdateHandler.insertUpdat e(Unknown
> Source)
> javax.swing.text.AbstractDocument.fireInsertUpdate(Unknown Source)
> javax.swing.text.AbstractDocument.handleInsertString(Unknown Source)
> javax.swing.text.AbstractDocument.insertString(Unknown Source)
> javax.swing.text.PlainDocument.insertString(Unknown Source)
> javax.swing.JTextArea.append(Unknown Source)
> com.sun.deploy.util.ConsoleWindow$25.run(Unknown Source)
> java.awt.event.InvocationEvent.dispatch(Unknown Source)
> java.awt.EventQueue.dispatchEvent(Unknown Source)
> java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
> java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
> java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
> java.awt.EventDispatchThread.pumpEvents(Unknown Source)
> java.awt.EventDispatchThread.pumpEvents(Unknown Source)
> java.awt.EventDispatchThread.run(Unknown Source)
>
>
> Name: ConsoleWriterThread
> State: WAITING on java.lang.Object@180dc21
> Total blocked: 31 Total waited: 20 612
>
> Stack trace: java.lang.Object.wait(Native Method)
> java.lang.Object.wait(Object.java:485)
> com.sun.deploy.util.ConsoleTraceListener$ConsoleWriterThread .run(Unknown
> Source)
>
>
> Name: CacheCleanUpThread
> State: WAITING on com.sun.deploy.cache.CleanupThread@1887a29
> Total blocked: 0 Total waited: 1
>
> Stack trace: java.lang.Object.wait(Native Method)
> java.lang.Object.wait(Object.java:485)
> com.sun.deploy.cache.CleanupThread.run(Unknown Source)
>
>
> Name: TimerQueue
> State: TIMED_WAITING on javax.swing.TimerQueue@6a2cde
> Total blocked: 8 Total waited: 284 784
>
> Stack trace: java.lang.Object.wait(Native Method)
> javax.swing.TimerQueue.run(Unknown Source)
> java.lang.Thread.run(Unknown Source)
>
> Name: AWT-EventQueue-0
> State: RUNNABLE
> Total blocked: 6 119 Total waited: 721 830
>
> Stack trace: sun.awt.windows.WComponentPeer._requestFocus(Native Method)
> sun.awt.windows.WComponentPeer.requestFocus(Unknown Source)
> java.awt.Component.requestFocusHelper(Unknown Source)
> java.awt.Component.requestFocus(Unknown Source)
> java.awt.Component.postNextFocusHelper(Unknown Source)
> java.awt.Component.nextFocusHelper(Unknown Source)
> java.awt.Container.nextFocusHelper(Unknown Source)
> java.awt.Component.doAutoTransfer(Unknown Source)
> java.awt.Component.autoTransferFocus(Unknown Source)
> java.awt.Component.autoTransferFocus(Unknown Source)
> java.awt.Component.hide(Unknown Source)
> - locked java.awt.Component$AWTTreeLock@1cc2f15
> java.awt.Component.show(Unknown Source)
> java.awt.Component.setVisible(Unknown Source)
> javax.swing.JComponent.setVisible(Unknown Source)
> javax.swing.JTabbedPane.fireStateChanged(Unknown Source)
> javax.swing.JTabbedPane$ModelListener.stateChanged(Unknown Source)
> javax.swing.DefaultSingleSelectionModel.fireStateChanged(Unk nown Source)
> javax.swing.DefaultSingleSelectionModel.setSelectedIndex(Unk nown Source)
> javax.swing.JTabbedPane.setSelectedIndexImpl(Unknown Source)
> javax.swing.JTabbedPane.setSelectedIndex(Unknown Source)
> com.qumak.toolbar.client.mail.gui.MailPanel_Tabs.setSelected LastPanel(MailPanel_Tabs.java:122)
>
> com.qumak.toolbar.client.mail.gui.MailPanel_Controller.prepa reGUIForNewMail(MailPanel_Controller.java:385)
>
> com.qumak.toolbar.client.mail.gui.MailPanel_Incomming$Forwar dMailWorker.done(MailPanel_Incomming.java:300)
>
> javax.swing.SwingWorker$5.run(Unknown Source)
> javax.swing.SwingWorker$DoSubmitAccumulativeRunnable.run(Unk nown Source)
> sun.swing.AccumulativeRunnable.run(Unknown Source)
> javax.swing.SwingWorker$DoSubmitAccumulativeRunnable.actionP erformed(Unknown
> Source)
> javax.swing.Timer.fireActionPerformed(Unknown Source)
> javax.swing.Timer$DoPostEvent.run(Unknown Source)
> java.awt.event.InvocationEvent.dispatch(Unknown Source)
> java.awt.EventQueue.dispatchEvent(Unknown Source)
> java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
> java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
> java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
> java.awt.EventDispatchThread.pumpEvents(Unknown Source)
> java.awt.EventDispatchThread.pumpEvents(Unknown Source)
> java.awt.EventDispatchThread.run(Unknown Source)
>
>
>
> Last thread is causing the deadlock, but I don't know why. Currently I
> use some components built on SWT (3.5 Milestone 1). Also I cannot notice
> any swt function invocations in the whole jconsole trace.
>
> I will be very grateful for reply. What do you think?
>
> Regards,
>
> Jan Gurda
>
>
Re: More tips for the sample code [message #11052 is a reply to message #1412] Tue, 23 June 2009 23:46 Go to previous message
Ken is currently offline Ken
Messages: 36
Registered: July 2009
Member
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@sas.com> wrote in message
news:fdh53e$j7i$1@build.eclipse.org...
> 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.
>
One more issue [message #572392 is a reply to message #1401] Wed, 26 September 2007 20:24 Go to previous message
James is currently offline James
Messages: 272
Registered: July 2009
Senior Member
This also has to do with putting the EmbeddedSwingComposite under a tab
folder.

When AWT has focus and the tab is clicked, AWT loses focus but the composite
does not get a focusGained event (as far as SWT is concerned, it never lost
focus).

I have added a check when the AWT window loses focus to inform the SWT
handler that the backing composite may have re-gained the focus.

At the end of AwtFocusHandler.windowLostFocus:
if (!swtHandler.getDisplay().isDisposed())
{
Runnable runnable = new Runnable()
{
public void run()
{
swtHandler.reApplyFocus();
}
};
swtHandler.getDisplay().asyncExec(runnable);
}

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


if (Display.getCurrent() != null &&
!Display.getCurrent().isDisposed() && composite ==
Display.getCurrent().getFocusControl())
{
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();
}
});
}
}
Re: More tips for the sample code [message #572420 is a reply to message #1401] Thu, 27 September 2007 20:50 Go to previous message
Gordon Hirsch is currently offline Gordon Hirsch
Messages: 100
Registered: July 2009
Senior Member
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
Re: One more issue [message #572442 is a reply to message #1407] Thu, 27 September 2007 21:20 Go to previous message
Gordon Hirsch is currently offline Gordon Hirsch
Messages: 100
Registered: July 2009
Senior Member
James,

Excellent, thanks! I had noticed this problem, but my attempted solution
had bad side effects. You can still find it (partially) in the
commented-out code. I think you are doing a better job of using the
right thread in all cases, so that may be what avoids the side effects.

As I recall, the problem with my attempt was that the AWT frame would
grab focus in cases where it shouldn't. For example, if I tried to
activate a different application's window, suddenly the RCP app with the
embedded AWT frame would pop up on top of it. I assume you haven't seen
anything like this with your fix?

James wrote:
> This also has to do with putting the EmbeddedSwingComposite under a tab
> folder.
>
> When AWT has focus and the tab is clicked, AWT loses focus but the composite
> does not get a focusGained event (as far as SWT is concerned, it never lost
> focus).
>
> I have added a check when the AWT window loses focus to inform the SWT
> handler that the backing composite may have re-gained the focus.
>
> At the end of AwtFocusHandler.windowLostFocus:
> if (!swtHandler.getDisplay().isDisposed())
> {
> Runnable runnable = new Runnable()
> {
> public void run()
> {
> swtHandler.reApplyFocus();
> }
> };
> swtHandler.getDisplay().asyncExec(runnable);
> }
>
> In SwtFocusHandler:
> public void reApplyFocus()
> {
> assert awtHandler != null;
> assert Display.getCurrent() != null; // On SWT event thread
>
>
> if (Display.getCurrent() != null &&
> !Display.getCurrent().isDisposed() && composite ==
> Display.getCurrent().getFocusControl())
> {
> 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();
> }
> });
> }
> }
>
>
Re: More tips for the sample code [message #572456 is a reply to message #1401] Thu, 27 September 2007 21:25 Go to previous message
Gordon Hirsch is currently offline Gordon Hirsch
Messages: 100
Registered: July 2009
Senior Member
James wrote:
> #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)
> {

One other thing I forgot to mention... in the article, I had an
implementation of EmbeddedSwingComposite.dispose like this:

public void dispose() {
if (!isDisposed()) {
getDisplay().removeListener(SWT.Settings, settingsListener);
getDisplay().removeFilter(SWT.Show, menuListener);
super.dispose();
}
}

This is the wrong way to write code that runs at dispose time. The two
listeners should be removed in a dispose listener, just like the one
you've created here, so you should add them to your widgetDisposed() and
remove the dispose() method.

> final Frame frame = getFrame();
> Runnable disposeEDTRunnable = new Runnable()
> {
> public void run()
> {
> disposeInEDT(frame);
> }
> };
> if (SwingUtilities.isEventDispatchThread())
> disposeEDTRunnable.run();
> else
> SwingUtilities.invokeLater(disposeEDTRunnable);
> }
> });
> currentSystemFont = getFont();
> }
>
>
Re: One more issue [message #572494 is a reply to message #1416] Fri, 28 September 2007 11:33 Go to previous message
James is currently offline James
Messages: 272
Registered: July 2009
Senior Member
Gordon,

I haven't seen anything like that but that doesn't guarantee that it won't
happen in a kind of 'perfect storm' of the two UI Threads. When the RCP
application loses focus to another application, this causes the SWT's focus
component to become null, so the AWT component shouldn't re-grab the focus.

-James

"Gordon Hirsch" <gordon.hirsch@sas.com> wrote in message
news:fdh6qi$v82$1@build.eclipse.org...
> James,
>
> Excellent, thanks! I had noticed this problem, but my attempted solution
> had bad side effects. You can still find it (partially) in the
> commented-out code. I think you are doing a better job of using the
> right thread in all cases, so that may be what avoids the side effects.
>
> As I recall, the problem with my attempt was that the AWT frame would
> grab focus in cases where it shouldn't. For example, if I tried to
> activate a different application's window, suddenly the RCP app with the
> embedded AWT frame would pop up on top of it. I assume you haven't seen
> anything like this with your fix?
>
> James wrote:
> > This also has to do with putting the EmbeddedSwingComposite under a tab
> > folder.
> >
> > When AWT has focus and the tab is clicked, AWT loses focus but the
composite
> > does not get a focusGained event (as far as SWT is concerned, it never
lost
> > focus).
> >
> > I have added a check when the AWT window loses focus to inform the SWT
> > handler that the backing composite may have re-gained the focus.
> >
> > At the end of AwtFocusHandler.windowLostFocus:
> > if (!swtHandler.getDisplay().isDisposed())
> > {
> > Runnable runnable = new Runnable()
> > {
> > public void run()
> > {
> > swtHandler.reApplyFocus();
> > }
> > };
> > swtHandler.getDisplay().asyncExec(runnable);
> > }
> >
> > In SwtFocusHandler:
> > public void reApplyFocus()
> > {
> > assert awtHandler != null;
> > assert Display.getCurrent() != null; // On SWT event thread
> >
> >
> > if (Display.getCurrent() != null &&
> > !Display.getCurrent().isDisposed() && composite ==
> > Display.getCurrent().getFocusControl())
> > {
> > 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();
> > }
> > });
> > }
> > }
> >
> >
Re: More tips for the sample code [message #572565 is a reply to message #1420] Fri, 28 September 2007 11:40 Go to previous message
James is currently offline James
Messages: 272
Registered: July 2009
Senior Member
I thought that was the case (I noticed that the dispose code wasn't getting
called). I have already moved the dispose code elsewhere and call it from
the dispose listener.

"Gordon Hirsch" <gordon.hirsch@sas.com> wrote in message
news:fdh750$un$1@build.eclipse.org...
> James wrote:
> > #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)
> > {
>
> One other thing I forgot to mention... in the article, I had an
> implementation of EmbeddedSwingComposite.dispose like this:
>
> public void dispose() {
> if (!isDisposed()) {
> getDisplay().removeListener(SWT.Settings, settingsListener);
> getDisplay().removeFilter(SWT.Show, menuListener);
> super.dispose();
> }
> }
>
> This is the wrong way to write code that runs at dispose time. The two
> listeners should be removed in a dispose listener, just like the one
> you've created here, so you should add them to your widgetDisposed() and
> remove the dispose() method.
>
> > final Frame frame = getFrame();
> > Runnable disposeEDTRunnable = new Runnable()
> > {
> > public void run()
> > {
> > disposeInEDT(frame);
> > }
> > };
> > if (SwingUtilities.isEventDispatchThread())
> > disposeEDTRunnable.run();
> > else
> > SwingUtilities.invokeLater(disposeEDTRunnable);
> > }
> > });
> > currentSystemFont = getFont();
> > }
> >
> >
Re: More tips for the sample code [message #572628 is a reply to message #1412] Fri, 28 September 2007 11:54 Go to previous message
James is currently offline James
Messages: 272
Registered: July 2009
Senior Member
"Gordon Hirsch" <gordon.hirsch@sas.com> wrote in message
news:fdh53e$j7i$1@build.eclipse.org...
> 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.

Not a problem. Your article code allowed us to have a product that was at
least usable (I was going crazy dealing with modal dialogs). We all benefit
from making these two UIs play well together.

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

In my version of the article code (I'm not sure it changed after I
downloaded it), the setFocus doesn't make any AWT Calls. It simple checks
to see if it is focusable and calls super.setFocus()... strange.

> 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

Yes, I'm pretty sure that this is the same bug (as I recall from the last
time I ran this through a profiler). The GlobalRef stays in place until
another component gets focus. In our case (probably some of the special
world of the SWT/AWT mix), it is reproducable 100% of the time. I have
found that setting the setFocusableWindowState to false before the frame is
disposed is also a work-around to the problem. To be honest, I don't know
if the other explicit call to dispose is necessary.

> 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
>
Re: More tips for the sample code [message #572661 is a reply to message #1432] Fri, 28 September 2007 12:05 Go to previous message
James is currently offline James
Messages: 272
Registered: July 2009
Senior Member
Aside from not seeming to make an AWT call out side of the AWT Thread, this
alternate implementation you have proposed breaks the fix for keyboard
navigation I describe (the SWT Component never really gains focus so it can
never lose it).

> In my version of the article code (I'm not sure it changed after I
> downloaded it), the setFocus doesn't make any AWT Calls. It simple checks
> to see if it is focusable and calls super.setFocus()... strange.
>
> > 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.
> >
Re: More tips for the sample code [message #572762 is a reply to message #1435] Sun, 07 October 2007 18:10 Go to previous message
Gordon Hirsch is currently offline Gordon Hirsch
Messages: 100
Registered: July 2009
Senior Member
James wrote:
> Aside from not seeming to make an AWT call out side of the AWT Thread, this
> alternate implementation you have proposed breaks the fix for keyboard
> navigation I describe (the SWT Component never really gains focus so it can
> never lose it).

You're right. After looking a little closer, I don't think the
implementations of setFocus/forceFocus are necessary at all.

By the way, the extra code in setFocus/forceFocus was not part of the
original article. Sorry for any confusion I might have caused.

>
>> In my version of the article code (I'm not sure it changed after I
>> downloaded it), the setFocus doesn't make any AWT Calls. It simple checks
>> to see if it is focusable and calls super.setFocus()... strange.
>>
>>> 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.
>>>
>
>
Re: More tips for the sample code [message #573612 is a reply to message #1412] Tue, 27 November 2007 02:35 Go to previous message
James Peltzer is currently offline James Peltzer
Messages: 43
Registered: July 2009
Member
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@sas.com> wrote in message
news:fdh53e$j7i$1@build.eclipse.org...
> 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
>
Re: More tips for the sample code [message #573633 is a reply to message #5247] Tue, 27 November 2007 16:19 Go to previous message
Gordon Hirsch is currently offline Gordon Hirsch
Messages: 100
Registered: July 2009
Senior Member
James Peltzer wrote:
> 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.

Could you post stack traces from the deadlocked JVM? They would be
extremely helpful in diagnosing what the two EDTs (and possibly other
threads) are doing at that point.
Re: More tips for the sample code [message #573664 is a reply to message #5313] Tue, 27 November 2007 23:31 Go to previous message
James Peltzer is currently offline James Peltzer
Messages: 43
Registered: July 2009
Member
Unfortunately I seem the Debugger seems to throw errors whenever I try to
suspend execution. I have changed my Eclipse version from 3.2.2 to 3.3.1.1
and the issue has gone back into hiding. I'll try to get more information
to you.

-James

"Gordon Hirsch" <gordon.hirsch@sas.com> wrote in message
news:fihg2f$rkr$1@build.eclipse.org...
> James Peltzer wrote:
>> 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.
>
> Could you post stack traces from the deadlocked JVM? They would be
> extremely helpful in diagnosing what the two EDTs (and possibly other
> threads) are doing at that point.
Re: More tips for the sample code [message #573684 is a reply to message #5368] Wed, 28 November 2007 16:31 Go to previous message
Gordon Hirsch is currently offline Gordon Hirsch
Messages: 100
Registered: July 2009
Senior Member
You can also get the stack traces with the jconsole tool that comes with
the JDK
( http://java.sun.com/j2se/1.5.0/docs/guide/management/jconsol e.html) or
by hitting Ctrl-Break (on Windows, running with java.exe as opposed to
javaw.exe).

James Peltzer wrote:
> Unfortunately I seem the Debugger seems to throw errors whenever I try to
> suspend execution. I have changed my Eclipse version from 3.2.2 to 3.3.1.1
> and the issue has gone back into hiding. I'll try to get more information
> to you.
>
> -James
>
> "Gordon Hirsch" <gordon.hirsch@sas.com> wrote in message
> news:fihg2f$rkr$1@build.eclipse.org...
>> James Peltzer wrote:
>>> 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.
>> Could you post stack traces from the deadlocked JVM? They would be
>> extremely helpful in diagnosing what the two EDTs (and possibly other
>> threads) are doing at that point.
>
>
Re: More tips for the sample code [message #574847 is a reply to message #6694] Fri, 28 November 2008 17:17 Go to previous message
Jan Gurda is currently offline Jan Gurda
Messages: 2
Registered: July 2009
Junior Member
Hi I have similar problem. During invocation of function
JTabbedPane.setSelectedIndex my application hangs.

Here is part of stack trace from jconsole:

Name: AWT-EventQueue-1
State: BLOCKED on java.awt.Component$AWTTreeLock@1cc2f15 owned by:
AWT-EventQueue-0
Total blocked: 9 726 Total waited: 145 509

Stack trace:
java.awt.Component.invalidate(Unknown Source)
java.awt.Container.invalidate(Unknown Source)
javax.swing.JComponent.revalidate(Unknown Source)
javax.swing.plaf.basic.BasicTextUI$RootView.preferenceChange d(Unknown
Source)
javax.swing.text.View.preferenceChanged(Unknown Source)
javax.swing.text.PlainView.updateDamage(Unknown Source)
javax.swing.text.PlainView.insertUpdate(Unknown Source)
javax.swing.plaf.basic.BasicTextUI$RootView.insertUpdate(Unk nown Source)
javax.swing.plaf.basic.BasicTextUI$UpdateHandler.insertUpdat e(Unknown
Source)
javax.swing.text.AbstractDocument.fireInsertUpdate(Unknown Source)
javax.swing.text.AbstractDocument.handleInsertString(Unknown Source)
javax.swing.text.AbstractDocument.insertString(Unknown Source)
javax.swing.text.PlainDocument.insertString(Unknown Source)
javax.swing.JTextArea.append(Unknown Source)
com.sun.deploy.util.ConsoleWindow$25.run(Unknown Source)
java.awt.event.InvocationEvent.dispatch(Unknown Source)
java.awt.EventQueue.dispatchEvent(Unknown Source)
java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
java.awt.EventDispatchThread.pumpEvents(Unknown Source)
java.awt.EventDispatchThread.pumpEvents(Unknown Source)
java.awt.EventDispatchThread.run(Unknown Source)


Name: ConsoleWriterThread
State: WAITING on java.lang.Object@180dc21
Total blocked: 31 Total waited: 20 612

Stack trace:
java.lang.Object.wait(Native Method)
java.lang.Object.wait(Object.java:485)
com.sun.deploy.util.ConsoleTraceListener$ConsoleWriterThread .run(Unknown
Source)


Name: CacheCleanUpThread
State: WAITING on com.sun.deploy.cache.CleanupThread@1887a29
Total blocked: 0 Total waited: 1

Stack trace:
java.lang.Object.wait(Native Method)
java.lang.Object.wait(Object.java:485)
com.sun.deploy.cache.CleanupThread.run(Unknown Source)


Name: TimerQueue
State: TIMED_WAITING on javax.swing.TimerQueue@6a2cde
Total blocked: 8 Total waited: 284 784

Stack trace:
java.lang.Object.wait(Native Method)
javax.swing.TimerQueue.run(Unknown Source)
java.lang.Thread.run(Unknown Source)

Name: AWT-EventQueue-0
State: RUNNABLE
Total blocked: 6 119 Total waited: 721 830

Stack trace:
sun.awt.windows.WComponentPeer._requestFocus(Native Method)
sun.awt.windows.WComponentPeer.requestFocus(Unknown Source)
java.awt.Component.requestFocusHelper(Unknown Source)
java.awt.Component.requestFocus(Unknown Source)
java.awt.Component.postNextFocusHelper(Unknown Source)
java.awt.Component.nextFocusHelper(Unknown Source)
java.awt.Container.nextFocusHelper(Unknown Source)
java.awt.Component.doAutoTransfer(Unknown Source)
java.awt.Component.autoTransferFocus(Unknown Source)
java.awt.Component.autoTransferFocus(Unknown Source)
java.awt.Component.hide(Unknown Source)
- locked java.awt.Component$AWTTreeLock@1cc2f15
java.awt.Component.show(Unknown Source)
java.awt.Component.setVisible(Unknown Source)
javax.swing.JComponent.setVisible(Unknown Source)
javax.swing.JTabbedPane.fireStateChanged(Unknown Source)
javax.swing.JTabbedPane$ModelListener.stateChanged(Unknown Source)
javax.swing.DefaultSingleSelectionModel.fireStateChanged(Unk nown Source)
javax.swing.DefaultSingleSelectionModel.setSelectedIndex(Unk nown Source)
javax.swing.JTabbedPane.setSelectedIndexImpl(Unknown Source)
javax.swing.JTabbedPane.setSelectedIndex(Unknown Source)
com.qumak.toolbar.client.mail.gui.MailPanel_Tabs.setSelected LastPanel(MailPanel_Tabs.java:122)
com.qumak.toolbar.client.mail.gui.MailPanel_Controller.prepa reGUIForNewMail(MailPanel_Controller.java:385)
com.qumak.toolbar.client.mail.gui.MailPanel_Incomming$Forwar dMailWorker.done(MailPanel_Incomming.java:300)
javax.swing.SwingWorker$5.run(Unknown Source)
javax.swing.SwingWorker$DoSubmitAccumulativeRunnable.run(Unk nown Source)
sun.swing.AccumulativeRunnable.run(Unknown Source)
javax.swing.SwingWorker$DoSubmitAccumulativeRunnable.actionP erformed(Unknown
Source)
javax.swing.Timer.fireActionPerformed(Unknown Source)
javax.swing.Timer$DoPostEvent.run(Unknown Source)
java.awt.event.InvocationEvent.dispatch(Unknown Source)
java.awt.EventQueue.dispatchEvent(Unknown Source)
java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
java.awt.EventDispatchThread.pumpEvents(Unknown Source)
java.awt.EventDispatchThread.pumpEvents(Unknown Source)
java.awt.EventDispatchThread.run(Unknown Source)



Last thread is causing the deadlock, but I don't know why. Currently I use
some components built on SWT (3.5 Milestone 1). Also I cannot notice any
swt function invocations in the whole jconsole trace.

I will be very grateful for reply. What do you think?

Regards,

Jan Gurda
Re: More tips for the sample code [message #574867 is a reply to message #10860] Tue, 02 December 2008 18:20 Go to previous message
Gordon Hirsch is currently offline Gordon Hirsch
Messages: 100
Registered: July 2009
Senior Member
This doesn't look like a problem with SWT/Swing integration. What's
unusual is that you seem to have two AWT event threads running and there
is some contention between them. I don't know you'd diagnose/fix this
problem.

Jan Gurda wrote:
> Hi I have similar problem. During invocation of function
> JTabbedPane.setSelectedIndex my application hangs.
>
> Here is part of stack trace from jconsole:
>
> Name: AWT-EventQueue-1
> State: BLOCKED on java.awt.Component$AWTTreeLock@1cc2f15 owned by:
> AWT-EventQueue-0
> Total blocked: 9 726 Total waited: 145 509
>
> Stack trace: java.awt.Component.invalidate(Unknown Source)
> java.awt.Container.invalidate(Unknown Source)
> javax.swing.JComponent.revalidate(Unknown Source)
> javax.swing.plaf.basic.BasicTextUI$RootView.preferenceChange d(Unknown
> Source)
> javax.swing.text.View.preferenceChanged(Unknown Source)
> javax.swing.text.PlainView.updateDamage(Unknown Source)
> javax.swing.text.PlainView.insertUpdate(Unknown Source)
> javax.swing.plaf.basic.BasicTextUI$RootView.insertUpdate(Unk nown Source)
> javax.swing.plaf.basic.BasicTextUI$UpdateHandler.insertUpdat e(Unknown
> Source)
> javax.swing.text.AbstractDocument.fireInsertUpdate(Unknown Source)
> javax.swing.text.AbstractDocument.handleInsertString(Unknown Source)
> javax.swing.text.AbstractDocument.insertString(Unknown Source)
> javax.swing.text.PlainDocument.insertString(Unknown Source)
> javax.swing.JTextArea.append(Unknown Source)
> com.sun.deploy.util.ConsoleWindow$25.run(Unknown Source)
> java.awt.event.InvocationEvent.dispatch(Unknown Source)
> java.awt.EventQueue.dispatchEvent(Unknown Source)
> java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
> java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
> java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
> java.awt.EventDispatchThread.pumpEvents(Unknown Source)
> java.awt.EventDispatchThread.pumpEvents(Unknown Source)
> java.awt.EventDispatchThread.run(Unknown Source)
>
>
> Name: ConsoleWriterThread
> State: WAITING on java.lang.Object@180dc21
> Total blocked: 31 Total waited: 20 612
>
> Stack trace: java.lang.Object.wait(Native Method)
> java.lang.Object.wait(Object.java:485)
> com.sun.deploy.util.ConsoleTraceListener$ConsoleWriterThread .run(Unknown
> Source)
>
>
> Name: CacheCleanUpThread
> State: WAITING on com.sun.deploy.cache.CleanupThread@1887a29
> Total blocked: 0 Total waited: 1
>
> Stack trace: java.lang.Object.wait(Native Method)
> java.lang.Object.wait(Object.java:485)
> com.sun.deploy.cache.CleanupThread.run(Unknown Source)
>
>
> Name: TimerQueue
> State: TIMED_WAITING on javax.swing.TimerQueue@6a2cde
> Total blocked: 8 Total waited: 284 784
>
> Stack trace: java.lang.Object.wait(Native Method)
> javax.swing.TimerQueue.run(Unknown Source)
> java.lang.Thread.run(Unknown Source)
>
> Name: AWT-EventQueue-0
> State: RUNNABLE
> Total blocked: 6 119 Total waited: 721 830
>
> Stack trace: sun.awt.windows.WComponentPeer._requestFocus(Native Method)
> sun.awt.windows.WComponentPeer.requestFocus(Unknown Source)
> java.awt.Component.requestFocusHelper(Unknown Source)
> java.awt.Component.requestFocus(Unknown Source)
> java.awt.Component.postNextFocusHelper(Unknown Source)
> java.awt.Component.nextFocusHelper(Unknown Source)
> java.awt.Container.nextFocusHelper(Unknown Source)
> java.awt.Component.doAutoTransfer(Unknown Source)
> java.awt.Component.autoTransferFocus(Unknown Source)
> java.awt.Component.autoTransferFocus(Unknown Source)
> java.awt.Component.hide(Unknown Source)
> - locked java.awt.Component$AWTTreeLock@1cc2f15
> java.awt.Component.show(Unknown Source)
> java.awt.Component.setVisible(Unknown Source)
> javax.swing.JComponent.setVisible(Unknown Source)
> javax.swing.JTabbedPane.fireStateChanged(Unknown Source)
> javax.swing.JTabbedPane$ModelListener.stateChanged(Unknown Source)
> javax.swing.DefaultSingleSelectionModel.fireStateChanged(Unk nown Source)
> javax.swing.DefaultSingleSelectionModel.setSelectedIndex(Unk nown Source)
> javax.swing.JTabbedPane.setSelectedIndexImpl(Unknown Source)
> javax.swing.JTabbedPane.setSelectedIndex(Unknown Source)
> com.qumak.toolbar.client.mail.gui.MailPanel_Tabs.setSelected LastPanel(MailPanel_Tabs.java:122)
>
> com.qumak.toolbar.client.mail.gui.MailPanel_Controller.prepa reGUIForNewMail(MailPanel_Controller.java:385)
>
> com.qumak.toolbar.client.mail.gui.MailPanel_Incomming$Forwar dMailWorker.done(MailPanel_Incomming.java:300)
>
> javax.swing.SwingWorker$5.run(Unknown Source)
> javax.swing.SwingWorker$DoSubmitAccumulativeRunnable.run(Unk nown Source)
> sun.swing.AccumulativeRunnable.run(Unknown Source)
> javax.swing.SwingWorker$DoSubmitAccumulativeRunnable.actionP erformed(Unknown
> Source)
> javax.swing.Timer.fireActionPerformed(Unknown Source)
> javax.swing.Timer$DoPostEvent.run(Unknown Source)
> java.awt.event.InvocationEvent.dispatch(Unknown Source)
> java.awt.EventQueue.dispatchEvent(Unknown Source)
> java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
> java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
> java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
> java.awt.EventDispatchThread.pumpEvents(Unknown Source)
> java.awt.EventDispatchThread.pumpEvents(Unknown Source)
> java.awt.EventDispatchThread.run(Unknown Source)
>
>
>
> Last thread is causing the deadlock, but I don't know why. Currently I
> use some components built on SWT (3.5 Milestone 1). Also I cannot notice
> any swt function invocations in the whole jconsole trace.
>
> I will be very grateful for reply. What do you think?
>
> Regards,
>
> Jan Gurda
>
>
Re: More tips for the sample code [message #575209 is a reply to message #1412] Tue, 23 June 2009 23:46 Go to previous message
Ken is currently offline Ken
Messages: 36
Registered: July 2009
Member
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@sas.com> wrote in message
news:fdh53e$j7i$1@build.eclipse.org...
> 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
>
Previous Topic:Restoring the active shell in SwtInputBlocker does not work properly
Next Topic:ctrl-c ctrl-v not working in 3.5
Goto Forum:
  


Current Time: Fri Sep 19 01:59:10 GMT 2014

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

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