diff --git a/org.eclipse.gef4.fx.swt/src/org/eclipse/gef4/fx/swt/canvas/FXCanvasEx.java b/org.eclipse.gef4.fx.swt/src/org/eclipse/gef4/fx/swt/canvas/FXCanvasEx.java index b485ac0b14..660ec58116 100644 --- a/org.eclipse.gef4.fx.swt/src/org/eclipse/gef4/fx/swt/canvas/FXCanvasEx.java +++ b/org.eclipse.gef4.fx.swt/src/org/eclipse/gef4/fx/swt/canvas/FXCanvasEx.java @@ -15,6 +15,8 @@ package org.eclipse.gef4.fx.swt.canvas; import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; import org.eclipse.gef4.common.reflect.ReflectionUtils; import org.eclipse.gef4.fx.swt.gestures.SWT2FXEventConverter; @@ -24,11 +26,15 @@ import org.eclipse.swt.graphics.ImageData; import org.eclipse.swt.widgets.Canvas; import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.embed.swt.FXCanvas; import javafx.embed.swt.SWTFXUtils; +import javafx.event.Event; +import javafx.event.EventDispatchChain; +import javafx.event.EventDispatcher; import javafx.scene.Cursor; import javafx.scene.ImageCursor; import javafx.scene.Scene; @@ -50,6 +56,47 @@ public class FXCanvasEx extends FXCanvas { private SWT2FXEventConverter gestureConverter; + private EventDispatcher initialEventDispatcher; + private boolean wasUpdated = true; + private List deferredEvents = new ArrayList<>(); + + private EventDispatcher deferringEventDispatcher = 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 (!wasUpdated) { + deferredEvents.add(event); + return event; + } + // schedule runnable + wasUpdated = false; + Display.getDefault().asyncExec(new Runnable() { + @Override + public void run() { + wasUpdated = true; + if (!deferredEvents.isEmpty()) { + // dispatch deferred events + for (Event e : deferredEvents) { + initialEventDispatcher.dispatchEvent(e, tail); + } + // clear deferred events + deferredEvents.clear(); + } + // update UI + while (Display.getDefault().readAndDispatch()) { + ; + } + } + }); + // dispatch the most recent event + Event returnedEvent = initialEventDispatcher.dispatchEvent(event, + tail); + // return dispatched event + return returnedEvent; + } + }; private ChangeListener cursorChangeListener = new ChangeListener() { @Override @@ -143,10 +190,13 @@ public Window getStage() { public void setScene(Scene newScene) { Scene oldScene = getScene(); if (oldScene != null) { + oldScene.setEventDispatcher(initialEventDispatcher); oldScene.cursorProperty().removeListener(cursorChangeListener); } super.setScene(newScene); if (newScene != null) { + initialEventDispatcher = newScene.getEventDispatcher(); + newScene.setEventDispatcher(deferringEventDispatcher); newScene.cursorProperty().addListener(cursorChangeListener); } }