Skip to content

Commit 9ed3089

Browse files
committed
[mac]SWT_AWT: synchronize the main thread and the awt thread
1 parent 8b67970 commit 9ed3089

File tree

1 file changed

+54
-6
lines changed
  • bundles/org.eclipse.swt/Eclipse SWT AWT/cocoa/org/eclipse/swt/awt

1 file changed

+54
-6
lines changed

bundles/org.eclipse.swt/Eclipse SWT AWT/cocoa/org/eclipse/swt/awt/SWT_AWT.java

Lines changed: 54 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818
import java.awt.Canvas;
1919
import java.awt.event.*;
2020
import java.lang.reflect.*;
21+
import java.util.concurrent.*;
22+
import java.util.concurrent.atomic.*;
23+
import java.util.function.*;
2124

2225
import org.eclipse.swt.*;
2326
import org.eclipse.swt.graphics.Rectangle;
@@ -37,6 +40,10 @@
3740
*/
3841
public class SWT_AWT {
3942

43+
private static final int AWT_WAITING_TIME_FOR_SWT_THREAD = 5_000; // in milliseconds
44+
45+
private static final int SWT_THREAD_BLOCK_LIMIT = 200; // in milliseconds
46+
4047
/**
4148
* The name of the embedded Frame class. The default class name
4249
* for the platform will be used if <code>null</code>.
@@ -246,22 +253,63 @@ public void handleEvent (Event e) {
246253
case SWT.FocusIn:
247254
EventQueue.invokeLater(() -> {
248255
if (frame.isActive()) return;
249-
try {
250-
synthesizeWindowActivation (frame, Boolean.TRUE);
251-
} catch (Throwable e1) {e1.printStackTrace();}
256+
synchronizedExecution(() -> parent.isFocusControl(),() -> { synthesizeWindowActivation (frame, Boolean.TRUE);} );
252257
});
253258
break;
254259
case SWT.Deactivate:
255260
case SWT.FocusOut:
256261
EventQueue.invokeLater(() -> {
257262
if (!frame.isActive()) return;
258-
try {
259-
synthesizeWindowActivation (frame, Boolean.FALSE);
260-
} catch (Throwable e1) {e1.printStackTrace();}
263+
synchronizedExecution(() -> !parent.isFocusControl(),() -> { synthesizeWindowActivation (frame, Boolean.FALSE);} );
261264
});
262265
break;
263266
}
264267
}
268+
269+
/**
270+
*
271+
* It must be made sure, that the parent composite is in the same focus state like the AWT frame.
272+
* This is not sure, because AWT will be executed asynchronous, in the meantime the SWT main thread can continue and change the state again.
273+
*
274+
* Example: in eclipse the perspective changes cause many FocusIn,FocusOut events and if there are multiple SWT_AWT frames,
275+
* these can break the embedded AWT feature.
276+
*
277+
* So in the SWT main thread the state of the parent will be checked and it will be blocked for a very short time (SWT_THREAD_BLOCK_LIMIT).
278+
* In this time, we change the behaviour in the AWT thread to the right state and since we block the SWT main thread, we ensure, that
279+
* the state there does not change.
280+
*
281+
* In case the AWT part freezes or fails, then the SWT thread continues after the short time period.
282+
*
283+
* @param swtExec executed check in swt main thread
284+
* @param awtExec action to be executed in awt thread
285+
*/
286+
private void synchronizedExecution(Supplier< Boolean> swtExec, Runnable awtExec ) {
287+
288+
try {
289+
AtomicBoolean swtResult = new AtomicBoolean();
290+
final CountDownLatch swtThreadStart = new CountDownLatch(1);
291+
final CountDownLatch awtThreadEnd = new CountDownLatch(1);
292+
293+
Display.getDefault().asyncExec(() -> {
294+
swtResult.set(swtExec.get());
295+
swtThreadStart.countDown();
296+
try {
297+
awtThreadEnd.await(SWT_THREAD_BLOCK_LIMIT, TimeUnit.MILLISECONDS);
298+
} catch (InterruptedException e1) {
299+
e1.printStackTrace();
300+
}
301+
});
302+
swtThreadStart.await(AWT_WAITING_TIME_FOR_SWT_THREAD, TimeUnit.MILLISECONDS);
303+
304+
if(swtResult.get()) {
305+
awtExec.run();
306+
}
307+
awtThreadEnd.countDown();
308+
309+
} catch (Throwable e1) {e1.printStackTrace();}
310+
311+
312+
}
265313
};
266314

267315
parent.addListener (SWT.FocusIn, listener);

0 commit comments

Comments
 (0)