Skip to content

Conversation

@DenisUngemach
Copy link
Contributor

@DenisUngemach DenisUngemach commented Dec 19, 2025

On Mac.

My system:
Apple M3
16 GB
macOS Tahoe 26.1

With SWT: 3.133.0

In SWT is a bug, which harms the focus handling of embedded awt features.

The scenario is the following:
If we have two SWT_AWT-frames running with our AWT code, then if we switch the perspective, the focus handling of the AWT feature fails. Sometimes one of the two AWT applications no longer can get focus at all.

The reason for this behavior seems to be that the AWT activation will be executed a queue (see class SWT_AWT) and not in the SWT main thread, which means that there is a delay at the execution.
If the parent composite of SWT_AWT already lost the focus, then the AWT frame still can get focus, while the second AWT frame could request the focus at almost the same time. It seems this can break the focus handling of the AWT frame.

Since at a perspective change the focus changes happen very fast in a very short time, this can cause this bug.

As a solution we can synchronize the SWT main thread with the AWT thread.
This means:

  1. first check the focus state of the SWT parent composite and then block the main thread with a very short time
  2. then in the AWT thread execute the activation.
  • If the activation is done release both threads.
  • If the AWT activation freezes or needs more than 200 ms, just release the SWT main thread.

I will check whether I can provide a standalone snippet, which reproduces this bug.

@github-actions
Copy link
Contributor

github-actions bot commented Dec 19, 2025

Test Results (macos)

   54 files  ±0     54 suites  ±0   6m 39s ⏱️ -40s
4 512 tests ±0  4 269 ✅ ±0  243 💤 ±0  0 ❌ ±0 
  104 runs  ±0    104 ✅ ±0    0 💤 ±0  0 ❌ ±0 

Results for commit 9ed3089. ± Comparison against base commit 8b67970.

♻️ This comment has been updated with latest results.

@akurtakov akurtakov added the macOS happens on macOS label Dec 19, 2025
@DenisUngemach
Copy link
Contributor Author

Not yet working flawlessly, there is still an NPE:

Exception in thread "main" org.eclipse.swt.SWTException: Failed to execute runnable (org.eclipse.swt.SWTException: Widget is disposed)
at org.eclipse.swt.SWT.error(SWT.java:4950)
at org.eclipse.swt.SWT.error(SWT.java:4865)
at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:135)
at org.eclipse.swt.widgets.Display.runAsyncMessages(Display.java:4393)
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:4016)
at org.eclipse.swt.awt.SWT_AWT$2.handleEvent(SWT_AWT.java:218)
at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:91)
at org.eclipse.swt.widgets.Display.sendEvent(Display.java:4671)
at org.eclipse.swt.widgets.Display.sendEvent(Display.java:4660)
at org.eclipse.swt.widgets.Display.release(Display.java:4071)
at org.eclipse.swt.graphics.Device.dispose(Device.java:241)
at org.eclipse.swt.examples.SnippetAwtFeatureFocusBug.main(SnippetAwtFeatureFocusBug.java:60)
Caused by: org.eclipse.swt.SWTException: Widget is disposed
at org.eclipse.swt.SWT.error(SWT.java:4950)
at org.eclipse.swt.SWT.error(SWT.java:4865)
at org.eclipse.swt.SWT.error(SWT.java:4836)
at org.eclipse.swt.widgets.Widget.error(Widget.java:854)
at org.eclipse.swt.widgets.Widget.checkWidget(Widget.java:633)
at org.eclipse.swt.widgets.Control.isFocusControl(Control.java:2305)
at org.eclipse.swt.awt.SWT_AWT$3.lambda$5(SWT_AWT.java:263)
at org.eclipse.swt.awt.SWT_AWT$3.lambda$7(SWT_AWT.java:294)
at org.eclipse.swt.widgets.RunnableLock.run(RunnableLock.java:40)
at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:132)
... 9 more

@DenisUngemach
Copy link
Contributor Author

DenisUngemach commented Dec 19, 2025

Snippet for reproduction. Execute the Snippet and click in the left awt TextArea. The focus does not work.
With my fix, it works.
I have tested multiple variantions of TEXT_FIELDS and FOCUS_CHANGES.

At 1000 FOCUS_CHANGES, also my fix can't prevent the focus bug.

By the way my system:
Chip Apple M3
macOS Tahoe 26.1


import java.awt.FlowLayout;
import java.awt.Frame;

import org.eclipse.swt.SWT;
import org.eclipse.swt.awt.SWT_AWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

public class SnippetAwtFocusBug {


    private static final int TEXT_FIELDS = 1;
    private static final int FOCUS_CHANGES = 0;

    public static void main(String[] args) {
	Display display = new Display();
	Shell shell = new Shell(display);
	shell.setText("SWT-AWT Integration");
	shell.setLayout(new org.eclipse.swt.layout.FillLayout(SWT.HORIZONTAL));

	var c1 = createEmbedding(shell, 0);
	var c2 = createEmbedding(shell, 1);

	c1.addListener(SWT.FocusIn, (e) -> {
	    System.out.println("c1 FocusIn");
	});
	c1.addListener(SWT.FocusOut, (e) -> {
	    System.out.println("c1 FocusOut");
	});

	c2.addListener(SWT.FocusIn, (e) -> {
	    System.out.println("c2 FocusIn");
	});
	c2.addListener(SWT.FocusOut, (e) -> {
	    System.out.println("c2 FocusOut");
	});

	shell.setSize(1000, 800);
	shell.open();


	for (int i = 0; i < FOCUS_CHANGES; i++) {

	    System.out.println("Iteration: " + i);
	    display.readAndDispatch();
	    c1.setFocus();
	    display.readAndDispatch();
	    c2.setFocus();
	    display.readAndDispatch();

	}

	while (!shell.isDisposed()) {
	    if (!display.readAndDispatch())
		display.sleep();
	}

	display.dispose();
    }

    private static Composite createEmbedding(Shell s, int i) {

	Composite c = new Composite(s, SWT.EMBEDDED );

	Frame frame = SWT_AWT.new_Frame(c);

	frame.setLayout(new FlowLayout());

	for (int k = 0; k < TEXT_FIELDS; k++) {
	    var awtButton = new java.awt.TextArea("I am an AWT TextArea");
	    frame.add(awtButton);
	    awtButton.setSize(20, 20);
	}

	return c;

    }

}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

macOS happens on macOS

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants