Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 14711 - SWT widgets will not share keyboard focus with Swing widgets
Summary: SWT widgets will not share keyboard focus with Swing widgets
Status: CLOSED WONTFIX
Alias: None
Product: Platform
Classification: Eclipse Project
Component: SWT (show other bugs)
Version: 2.0   Edit
Hardware: PC Windows 2000
: P3 major with 4 votes (vote)
Target Milestone: ---   Edit
Assignee: Silenio Quarti CLA
QA Contact:
URL:
Whiteboard: stalebug
Keywords:
Depends on:
Blocks: 37724
  Show dependency tree
 
Reported: 2002-04-25 19:04 EDT by Matt Di Iorio CLA
Modified: 2020-02-17 17:16 EST (History)
5 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Matt Di Iorio CLA 2002-04-25 19:04:28 EDT
If an SWT and Swing component is in the same window the SWT component will not 
give up focus to the Swing component.

The following code creates a window with two components.  The top component is 
a Swing JTextField component and the bottom component is a SWT Text component.  

To see the problem do the following:
  1. Click in the top component (the lightweight).  It should have keyboard 
focus.  Type a few characters to verify.
  2. Click in the bottom component (the heavyweight).  It should have keyboard 
focus.  Type a few characters to verify.
  3. Now click in the top component.  It will not get focus.
  4. Switch to another application, then switch back to this test frame.  At 
this point the Swing component will have keyboard focus.
  5. Click in the bottom component.  It will have focus.
  6. Clicking in the top component will not give it focus.

Sometimes the top component gets into a wierd state where it displays the text 
cursor, but any characters typed are delivered to the bottom component.

The above behavior was seen with the 1.3.1_03 JRE and the swt-win32-2026.dll 
version of SWT and the M5 release of SWT running on Windows 2000.

This code does not exhibit focus problems when running on the 1.4.0 JRE.

-----------------------------------------

/*
 * Demonstrates a focus bug between SWT and Swing components.
 * To compile: Include swt.jar in the classpath.
 * To run: Include -Djava.library.path=<path to swt-win32-XXXX.dll> on the 
command line
 */

import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Panel;

import javax.swing.*;

import org.eclipse.swt.SWT;
import org.eclipse.swt.internal.awt.win32.SWT_AWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

public class BugTest {
	
	private DisplayThread displayThread;
	
	public BugTest() {
		displayThread = new DisplayThread();
		displayThread.start();
		
		JFrame frame = new JFrame();
		frame.setSize( 500, 500 );
		
		frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );

		frame.getContentPane().setLayout( new BoxLayout( 
frame.getContentPane(), BoxLayout.Y_AXIS ) );

		frame.setVisible( true );

		frame.getContentPane().add( createLightweight() );
		frame.getContentPane().add( createHeavyweight() );
		
		frame.validate();
	}
	
	private JPanel createLightweight() {
		JPanel panel = new JPanel();
		panel.setLayout( new BorderLayout() );
		panel.add( new JTextField( 30 ), BorderLayout.CENTER );
		return panel;
	}
	
	private Panel createHeavyweight() {
		return new MyPanel();
	}
	
	public static void main(String[] args) {
		new BugTest();
	}

	private class MyPanel extends Panel {
		private Canvas canvas;
		
		public MyPanel() {
			canvas = new Canvas();
			setLayout( new BorderLayout() );
			add( canvas, BorderLayout.CENTER );
		}
		
		public void addNotify() {
			super.addNotify();
			displayThread.getDisplay().syncExec( new Runnable() {
				public void run() {
					Shell shell = SWT_AWT.new_Shell( 
displayThread.getDisplay(), canvas );
					shell.setLayout( new FillLayout() );
					Text text = new Text( shell, 
SWT.MULTI );
				}
			} );
		}
	}
	
	private class DisplayThread extends Thread {
		private Display display;
		
		public void run() {
			display = Display.getDefault();
			swtEventLoop();
		}
		
		private void swtEventLoop() {
			while( true ) {
				if (!display.readAndDispatch()) {
					display.sleep();
				}
			}
		}
		
		public Display getDisplay() {
			return display;
		}
	}
}
Comment 1 Veronika Irvine CLA 2002-04-26 09:48:38 EDT
Matt,

In the newsgroup you said you saw this comment on the sun web site:

"Prior to Java 2 Standard Edition, JDK 1.4, the AWT focus subsystem was
inadequate. It suffered from major design and API problems, as well as
over a hundred open bugs. Many of these bugs were caused by platform
inconsistencies, or incompatibilities between the native focus system for
heavyweights and the Java focus system for lightweights."

http://java.sun.com/j2se/1.4/docs/api/java/awt/doc-files/FocusSpec.html

I just want to capture this info here as part of the investigation.
Comment 2 Veronika Irvine CLA 2002-05-27 09:18:28 EDT
We need to have an indepth look at the SWT/AWT integration after R2.0.
Comment 3 Veronika Irvine CLA 2002-09-10 10:31:23 EDT
Post 2.0. Re-opening bug reports for review.
Comment 4 Steve Northover CLA 2003-03-05 19:55:28 EST
Still happens in 2.1 RC1.
Comment 5 Steve Northover CLA 2004-03-02 17:50:06 EST
Is this still a problem in the latest?
Comment 6 Silenio Quarti CLA 2004-03-03 11:20:22 EST
Yes, this is still a problem in latest. Note that it only happens with 
JDK1.3.1 and when embedding SWT in AWT (not the other way).
Comment 7 John Long CLA 2016-04-09 22:03:42 EDT
I ran into this same issue with Java 7 and Java 8.  My workaround is to attach an AWT focus event listener and disable the SWT component when a Swing component gains focus.  Here is the relevant code stub:

    private class FocusListener implements AWTEventListener {

        @Override
        public void eventDispatched(AWTEvent e) {
            boolean focus = false;
            if (e.getSource() instanceof Component) {
                focus = isAncestorOf((Component) e.getSource());
            }

            display.asyncExec(new Runnable() {

                @Override
                public void run() {
                    shell.setEnabled(focus);
                    if (focus) {
                        frame.setFocus();
                    }
                }

            });
        }

    }

    Toolkit.getDefaultToolkit().addAWTEventListener(
                focusListener, AWTEvent.FOCUS_EVENT_MASK);
Comment 8 Alessandro D\\\'Ottavio CLA 2016-10-14 09:09:06 EDT
could you show the implementation of the method


isAncestorOf((Component) e.getSource());
Comment 9 John Long CLA 2016-10-14 12:34:48 EDT
(In reply to Alessandro D\\\'Ottavio from comment #8)
> could you show the implementation of the method
> 
> 
> isAncestorOf((Component) e.getSource());

It's provided by AWT: http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7u40-b43/java/awt/Container.java#Container.isAncestorOf%28java.awt.Component%29
Comment 10 Maarten Coene CLA 2016-12-08 04:27:26 EST
We have the same problem with SWT components when trying to upgrade our Swing application from Java 6 to Java 8.

The workaround suggested above did solve the focus issue, but causes some other issues with clicking on the SWT component (we sometimes had to click twice to get the cursor on the correct position in the SWT component, for instance when embedding the IE browser).

We found another workaround for the problem though by adding an SWT FocusListener to the SWT component. If the SWT component gets the focus, we clear the AWT focusowner.

For instance, in your example, add the following right after creating the Text component:

text.addFocusListener(new FocusListener() {
    @Override
    public void focusGained(FocusEvent e) {
        KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner();
    }

    @Override
    public void focusLost(FocusEvent e) {
    }
});

--
Maarten
Comment 11 Eclipse Genie CLA 2020-02-17 17:16:40 EST
This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet. As such, we're closing this bug.

If you have further information on the current state of the bug, please add it and reopen this bug. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant.

--
The automated Eclipse Genie.