Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 497679

Summary: FXCanvasEx does not ensure that the UI is always updated while processing events.
Product: [Tools] GEF Reporter: Matthias Wienand <matthias.wienand>
Component: GEF FXAssignee: gef-inbox <gef-inbox>
Status: RESOLVED FIXED QA Contact:
Severity: normal    
Priority: P3    
Version: 1.0.0   
Target Milestone: 4.1.0 (Neon.1) M1   
Hardware: All   
OS: All   
Whiteboard:

Description Matthias Wienand CLA 2016-07-11 09:40:51 EDT
Currently, when embedding a JavaFX application into an SWT application using FXCanvas, the UI is not always updated while processing events. This is especially noticeable when the event processing is slow, i.e. multiple events are queued while an event is being processed. This results in a UI freeze until the events are fully processed and the UI thread is free to update itself.

The FXCanvasEx should ensure that the UI is always updated while processing events. This can be done by deferring the processing of incoming events while waiting for a UI update, as follows:

Scene scene = getCanvas().getScene();
final EventDispatcher eventDispatcher = scene.getEventDispatcher();
final boolean[] updated = new boolean[] { true };
final List<Event>[] deferred = new List[] { new ArrayList<Event>() };
scene.setEventDispatcher(new EventDispatcher() {
	@Override
	public Event dispatchEvent(final Event event, final EventDispatchChain tail) {
		// defer event if display was not updated since the last event
		// was processed
		if (!updated[0]) {
			deferred[0].add(event);
			return event;
		}
		// schedule runnable
		updated[0] = false;
		Display.getDefault().asyncExec(new Runnable() {
			@Override
			public void run() {
				updated[0] = true;
				// dispatch deferred events
				if (!deferred[0].isEmpty()) {
					for (Event e : deferred[0]) {
						eventDispatcher.dispatchEvent(e, tail);
					}
					deferred[0].clear();
				}
				// update UI
				while (Display.getDefault().readAndDispatch()) {
					;
				}
			}
		});
		// dispatch the most recent event
		Event returnedEvent = eventDispatcher.dispatchEvent(event, tail);
		// return dispatched event
		return returnedEvent;
	}
});
Comment 1 Matthias Wienand CLA 2016-07-15 07:49:58 EDT
I adjusted the code so that the UI is refreshed in between event dispatching. The code is published on the R4_0_maintenance and master branches. Therefore, I resolve this ticket as fixed for 4.1.0 M1.