X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.g2d%2Fsrc%2Forg%2Fsimantics%2Fg2d%2Fparticipant%2FMouseUtil.java;h=44ded472960a1686f100d1cc69f8fed9bd8137a6;hb=1b969e34d51e9a17a0038367a29b93c2822495ed;hp=8ebfb564ab80b0846351c96ea5ce5f43d1452094;hpb=969bd23cab98a79ca9101af33334000879fb60c5;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.g2d/src/org/simantics/g2d/participant/MouseUtil.java b/bundles/org.simantics.g2d/src/org/simantics/g2d/participant/MouseUtil.java index 8ebfb564a..44ded4729 100644 --- a/bundles/org.simantics.g2d/src/org/simantics/g2d/participant/MouseUtil.java +++ b/bundles/org.simantics.g2d/src/org/simantics/g2d/participant/MouseUtil.java @@ -1,350 +1,350 @@ -/******************************************************************************* - * Copyright (c) 2007, 2010 Association for Decentralized Information Management - * in Industry THTH ry. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * VTT Technical Research Centre of Finland - initial API and implementation - *******************************************************************************/ -/* - * - * @author Toni Kalajainen - */ -package org.simantics.g2d.participant; - -import java.awt.geom.Point2D; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; - -import org.simantics.g2d.canvas.Hints; -import org.simantics.g2d.canvas.impl.AbstractCanvasParticipant; -import org.simantics.g2d.canvas.impl.DependencyReflection.Dependency; -import org.simantics.g2d.canvas.impl.HintReflection.HintListener; -import org.simantics.scenegraph.g2d.events.MouseEvent; -import org.simantics.scenegraph.g2d.events.EventHandlerReflection.EventHandler; -import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonPressedEvent; -import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonReleasedEvent; -import org.simantics.scenegraph.g2d.events.MouseEvent.MouseClickEvent; -import org.simantics.scenegraph.g2d.events.MouseEvent.MouseDragBegin; -import org.simantics.scenegraph.g2d.events.MouseEvent.MouseEnterEvent; -import org.simantics.scenegraph.g2d.events.MouseEvent.MouseExitEvent; -import org.simantics.scenegraph.g2d.events.MouseEvent.MouseMovedEvent; -import org.simantics.utils.datastructures.hints.IHintObservable; -import org.simantics.utils.datastructures.hints.IHintContext.Key; - -/** - * MouseUtil tracks position and button status of mice. - * It remembers where mouse was on control and on diagram when each of its button - * was pressed. - * - * MouseUtil generates synthetic mouse events {@link MouseClickEvent} and - * {@link MouseDragBegin} for convenience. - * - * It also tracks distance how far mouse has moved since each of its - * button was pressed (used for click). - *

- * There is also debug cursor painter which can be enabled/disabled with - * hint KEY_CURSOR_STATUS. - * - * @TODO From to mouse monitor and mouse painter classes - */ -public class MouseUtil extends AbstractCanvasParticipant { - - protected @Dependency TransformUtil util; - - /** Mice info */ - protected Map miceInfo = new HashMap(); - protected Map micePressedInfo = new HashMap(); - - public static class MouseClickProfile { - public static final MouseClickProfile DEFAULT = new MouseClickProfile(); - /** Maximum time of holding a button down that counts as a click */ - public long clickHoldTimeTolerance = 300L; - /** Maximum number of pixels mouse may move while pressed to count a click */ - public double movementTolerance = 3.5; - /** Maximum time to wait for clicks to count as consecutive */ - public long consecutiveToleranceTime = 380L; - } - - protected MouseClickProfile profile = MouseClickProfile.DEFAULT; - - @HintListener(Class=Hints.class, Field="KEY_CANVAS_TRANSFORM") - public void transformChanged(IHintObservable sender, Key key, Object oldValue, Object newValue) { - if (oldValue != null && oldValue.equals(newValue)) return; - sendMicePos(); - } - - @EventHandler(priority = Integer.MAX_VALUE) - public boolean handleMouseEvent(MouseEvent e) - { - assertDependencies(); - if (e instanceof MouseEnterEvent) - { - Point2D canvasPosition = util.controlToCanvas(e.controlPosition, null); - // Reset mouse - MouseInfo mi = new MouseInfo(e.mouseId, e.controlPosition, canvasPosition, e.buttons); - miceInfo.put(e.mouseId, mi); - } else - if (e instanceof MouseExitEvent) - { - miceInfo.remove(e.mouseId); - } else - if (e instanceof MouseMovedEvent) - { - Point2D canvasPosition = util.controlToCanvas(e.controlPosition, null); - double deltaDistance = 0; - MouseInfo mi = miceInfo.get(e.mouseId); - if (mi==null) { - mi = new MouseInfo(e.mouseId, e.controlPosition, canvasPosition, 0/*e.buttons*/); - miceInfo.put(e.mouseId, mi); - } else { - deltaDistance = e.controlPosition.distance(mi.controlPosition); - mi.controlPosition = e.controlPosition; - mi.canvasPosition = canvasPosition; - } - - if (deltaDistance>0) - mi.addDistanceForButtons(deltaDistance); - - // Send mouse drag events. - for (ButtonInfo bi : mi.buttonPressInfo.values()) - { - if (!bi.down) continue; - if (bi.deltaMotion<=profile.movementTolerance) continue; - if (bi.drag) continue; - bi.drag = true; - MouseDragBegin db = new MouseDragBegin( - this, e.time, e.mouseId, e.buttons, e.stateMask, bi.button, - bi.canvasPosition, bi.controlPosition, - e.controlPosition, e.screenPosition - ); - getContext().getEventQueue().queueFirst(db); - } - - } else - if (e instanceof MouseButtonPressedEvent) - { - Point2D canvasPosition = util.controlToCanvas(e.controlPosition, null); - MouseButtonPressedEvent me = (MouseButtonPressedEvent) e; - MouseInfo mi = miceInfo.get(e.mouseId); - if (mi==null) { - mi = new MouseInfo(e.mouseId, e.controlPosition, canvasPosition, e.buttons); - miceInfo.put(e.mouseId, mi); - micePressedInfo.put(e.mouseId, mi); - } else { - mi.controlPosition = e.controlPosition; - mi.canvasPosition = canvasPosition; - micePressedInfo.put(e.mouseId, - new MouseInfo(e.mouseId, e.controlPosition, canvasPosition, e.buttons)); - } - mi.setButtonPressed(me.button, e.stateMask, e.controlPosition, canvasPosition, e.time); - } else if (e instanceof MouseButtonReleasedEvent) { - MouseButtonReleasedEvent me = (MouseButtonReleasedEvent) e; - Point2D canvasPosition = util.controlToCanvas(me.controlPosition, null); - MouseInfo mi = miceInfo.get(me.mouseId); - if (mi==null) { - mi = new MouseInfo(e.mouseId, me.controlPosition, canvasPosition, 0/*me.buttons*/); - miceInfo.put(me.mouseId, mi); - } else { - mi.controlPosition = me.controlPosition; - mi.canvasPosition = canvasPosition; - } - ButtonInfo bi = mi.releaseButton(me.button, me.time); - if (bi==null) return false; - - if (me.holdTime > profile.clickHoldTimeTolerance) return false; - if (bi.deltaMotion>profile.movementTolerance) return false; - // This is a click - - long timeSinceLastClick = me.time - bi.lastClickEventTime; - bi.lastClickEventTime = me.time; - - // reset click counter - if (timeSinceLastClick>profile.consecutiveToleranceTime) - bi.clickCount = 1; - else - bi.clickCount++; - - MouseClickEvent ce = - new MouseClickEvent(getContext(), e.time, e.mouseId, e.buttons, e.stateMask, me.button, bi.clickCount, me.controlPosition, me.screenPosition); - getContext().getEventQueue().queueFirst(ce); - } - return false; - } - - /** - * Get last known position of a mouse - * - * @param mouseId mouse id - * @return mouse position in canvas coordinates or null if mouse exited - * canvas - */ - public MouseInfo getMouseInfo(int mouseId) { - return miceInfo.get(mouseId); - } - - public MouseInfo getMousePressedInfo(int mouseId) { - return micePressedInfo.get(mouseId); - } - - /** - * Get button info - * @param mouseId mouse id - * @param buttonId button id - * @return null if button has never been pressed, or button info - */ - public ButtonInfo getButtonInfo(int mouseId, int buttonId) - { - MouseInfo mi = miceInfo.get(mouseId); - if (mi==null) return null; - return mi.getButtonPressInfo(buttonId); - } - - /** - * Get a snapshot of statuses of all mice - * @return a snapshot - */ - public Map getMiceInfo() - { - return new HashMap(miceInfo); - } - - public int getMouseCount() - { - return miceInfo.size(); - } - - public MouseClickProfile getProfile() { - return profile; - } - - public void setProfile(MouseClickProfile profile) { - assert(profile!=null); - this.profile = profile; - } - - public static final class MouseInfo { - public int mouseId; - public Point2D controlPosition; - public Point2D canvasPosition; - public int buttons; - public MouseInfo(int mouseId, Point2D initialControlPos, Point2D initialCanvasPosition, int initialButtonMask) { - this.mouseId = mouseId; - this.controlPosition = initialControlPos; - this.canvasPosition = initialCanvasPosition; - int buttonId = 0; - while (initialButtonMask!=0) { - if ((initialButtonMask & 1)==1) - setButtonPressed(buttonId, 0, initialControlPos, initialCanvasPosition, Long.MIN_VALUE); - initialButtonMask >>>= 1; - buttonId++; - } - } - - public boolean isMouseButtonPressed(int buttonId) - { - ButtonInfo bi = buttonPressInfo.get(buttonId); - return bi!=null && bi.down; - } - private void _countButtonMask() { - int result = 0; - for (ButtonInfo pi : buttonPressInfo.values()) - { - if (!pi.down) continue; - result |= 1 << (pi.button-1); - } - this.buttons = result; - } - public Map buttonPressInfo = new HashMap(); - public void setButtonPressed(int buttonId, int stateMask, Point2D controlPos, Point2D canvasPos, long eventTime) { - ButtonInfo bi = getOrCreateButtonInfo(buttonId); - bi.canvasPosition = canvasPos; - bi.controlPosition = controlPos; - bi.systemTime = System.currentTimeMillis(); - bi.eventTime = eventTime; - bi.down = true; - bi.deltaMotion = 0; - bi.drag = false; - bi.stateMask = stateMask; - _countButtonMask(); - } - public ButtonInfo releaseButton(int buttonId, long eventTime) { - ButtonInfo bi = getButtonPressInfo(buttonId); - if (bi==null) return null; - bi.down = false; - bi.holdTime = eventTime - bi.eventTime; - _countButtonMask(); - return bi; - } - ButtonInfo getOrCreateButtonInfo(int buttonId) - { - ButtonInfo bi = buttonPressInfo.get(buttonId); - if (bi==null) bi = new ButtonInfo(buttonId); - buttonPressInfo.put(buttonId, bi); - return bi; - } - public ButtonInfo getButtonPressInfo(int buttonId) { - return buttonPressInfo.get(buttonId); - } - public void addDistanceForButtons(double distance) { - for (ButtonInfo bi : buttonPressInfo.values()) - { - if (!bi.down) continue; - bi.deltaMotion += distance; - } - } - public Collection getButtonInfos() { - return buttonPressInfo.values(); - } - } - - /** Status of mouse's button press */ - public static final class ButtonInfo { - /** Position on press */ - public Point2D controlPosition; - /** Position on press */ - public Point2D canvasPosition; - public final int button; - public int stateMask; - /** System time when pressed */ - public long systemTime; - /** Event time when pressed */ - public long eventTime; - /** Hold time when released */ - public long holdTime; - /** Current up / down status */ - public boolean down = false; - /** Total movement in pixels since press */ - public double deltaMotion = 0.0; - /** Click Count */ - public int clickCount = 0; - /** Time of last click */ - public long lastClickEventTime = Long.MIN_VALUE; - /** Dragged (set true when possibility for click is excluded) */ - public boolean drag = false; - public ButtonInfo(int button) { - this.button = button; - } - } - - /** - * Sends mice positions as an event - */ - private void sendMicePos() - { - long time = System.currentTimeMillis(); - for (Entry e : miceInfo.entrySet()) { - MouseInfo mi = e.getValue(); - MouseMovedEvent mme; - // FIXME: screenPosition as null (requires adding screenPos into MouseInfo) - mme = new MouseMovedEvent(getContext(), time, e.getKey(), mi.buttons, 0 /* FIXME ??? */, mi.controlPosition, null); - getContext().getEventQueue().queueEvent(mme); - } - } - -} +/******************************************************************************* + * Copyright (c) 2007, 2010 Association for Decentralized Information Management + * in Industry THTH ry. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +/* + * + * @author Toni Kalajainen + */ +package org.simantics.g2d.participant; + +import java.awt.geom.Point2D; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + +import org.simantics.g2d.canvas.Hints; +import org.simantics.g2d.canvas.impl.AbstractCanvasParticipant; +import org.simantics.g2d.canvas.impl.DependencyReflection.Dependency; +import org.simantics.g2d.canvas.impl.HintReflection.HintListener; +import org.simantics.scenegraph.g2d.events.MouseEvent; +import org.simantics.scenegraph.g2d.events.EventHandlerReflection.EventHandler; +import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonPressedEvent; +import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonReleasedEvent; +import org.simantics.scenegraph.g2d.events.MouseEvent.MouseClickEvent; +import org.simantics.scenegraph.g2d.events.MouseEvent.MouseDragBegin; +import org.simantics.scenegraph.g2d.events.MouseEvent.MouseEnterEvent; +import org.simantics.scenegraph.g2d.events.MouseEvent.MouseExitEvent; +import org.simantics.scenegraph.g2d.events.MouseEvent.MouseMovedEvent; +import org.simantics.utils.datastructures.hints.IHintObservable; +import org.simantics.utils.datastructures.hints.IHintContext.Key; + +/** + * MouseUtil tracks position and button status of mice. + * It remembers where mouse was on control and on diagram when each of its button + * was pressed. + * + * MouseUtil generates synthetic mouse events {@link MouseClickEvent} and + * {@link MouseDragBegin} for convenience. + * + * It also tracks distance how far mouse has moved since each of its + * button was pressed (used for click). + *

+ * There is also debug cursor painter which can be enabled/disabled with + * hint KEY_CURSOR_STATUS. + * + * @TODO From to mouse monitor and mouse painter classes + */ +public class MouseUtil extends AbstractCanvasParticipant { + + protected @Dependency TransformUtil util; + + /** Mice info */ + protected Map miceInfo = new HashMap(); + protected Map micePressedInfo = new HashMap(); + + public static class MouseClickProfile { + public static final MouseClickProfile DEFAULT = new MouseClickProfile(); + /** Maximum time of holding a button down that counts as a click */ + public long clickHoldTimeTolerance = 300L; + /** Maximum number of pixels mouse may move while pressed to count a click */ + public double movementTolerance = 3.5; + /** Maximum time to wait for clicks to count as consecutive */ + public long consecutiveToleranceTime = 380L; + } + + protected MouseClickProfile profile = MouseClickProfile.DEFAULT; + + @HintListener(Class=Hints.class, Field="KEY_CANVAS_TRANSFORM") + public void transformChanged(IHintObservable sender, Key key, Object oldValue, Object newValue) { + if (oldValue != null && oldValue.equals(newValue)) return; + sendMicePos(); + } + + @EventHandler(priority = Integer.MAX_VALUE) + public boolean handleMouseEvent(MouseEvent e) + { + assertDependencies(); + if (e instanceof MouseEnterEvent) + { + Point2D canvasPosition = util.controlToCanvas(e.controlPosition, null); + // Reset mouse + MouseInfo mi = new MouseInfo(e.mouseId, e.controlPosition, canvasPosition, e.buttons); + miceInfo.put(e.mouseId, mi); + } else + if (e instanceof MouseExitEvent) + { + miceInfo.remove(e.mouseId); + } else + if (e instanceof MouseMovedEvent) + { + Point2D canvasPosition = util.controlToCanvas(e.controlPosition, null); + double deltaDistance = 0; + MouseInfo mi = miceInfo.get(e.mouseId); + if (mi==null) { + mi = new MouseInfo(e.mouseId, e.controlPosition, canvasPosition, 0/*e.buttons*/); + miceInfo.put(e.mouseId, mi); + } else { + deltaDistance = e.controlPosition.distance(mi.controlPosition); + mi.controlPosition = e.controlPosition; + mi.canvasPosition = canvasPosition; + } + + if (deltaDistance>0) + mi.addDistanceForButtons(deltaDistance); + + // Send mouse drag events. + for (ButtonInfo bi : mi.buttonPressInfo.values()) + { + if (!bi.down) continue; + if (bi.deltaMotion<=profile.movementTolerance) continue; + if (bi.drag) continue; + bi.drag = true; + MouseDragBegin db = new MouseDragBegin( + this, e.time, e.mouseId, e.buttons, e.stateMask, bi.button, + bi.canvasPosition, bi.controlPosition, + e.controlPosition, e.screenPosition + ); + getContext().getEventQueue().queueFirst(db); + } + + } else + if (e instanceof MouseButtonPressedEvent) + { + Point2D canvasPosition = util.controlToCanvas(e.controlPosition, null); + MouseButtonPressedEvent me = (MouseButtonPressedEvent) e; + MouseInfo mi = miceInfo.get(e.mouseId); + if (mi==null) { + mi = new MouseInfo(e.mouseId, e.controlPosition, canvasPosition, e.buttons); + miceInfo.put(e.mouseId, mi); + micePressedInfo.put(e.mouseId, mi); + } else { + mi.controlPosition = e.controlPosition; + mi.canvasPosition = canvasPosition; + micePressedInfo.put(e.mouseId, + new MouseInfo(e.mouseId, e.controlPosition, canvasPosition, e.buttons)); + } + mi.setButtonPressed(me.button, e.stateMask, e.controlPosition, canvasPosition, e.time); + } else if (e instanceof MouseButtonReleasedEvent) { + MouseButtonReleasedEvent me = (MouseButtonReleasedEvent) e; + Point2D canvasPosition = util.controlToCanvas(me.controlPosition, null); + MouseInfo mi = miceInfo.get(me.mouseId); + if (mi==null) { + mi = new MouseInfo(e.mouseId, me.controlPosition, canvasPosition, 0/*me.buttons*/); + miceInfo.put(me.mouseId, mi); + } else { + mi.controlPosition = me.controlPosition; + mi.canvasPosition = canvasPosition; + } + ButtonInfo bi = mi.releaseButton(me.button, me.time); + if (bi==null) return false; + + if (me.holdTime > profile.clickHoldTimeTolerance) return false; + if (bi.deltaMotion>profile.movementTolerance) return false; + // This is a click + + long timeSinceLastClick = me.time - bi.lastClickEventTime; + bi.lastClickEventTime = me.time; + + // reset click counter + if (timeSinceLastClick>profile.consecutiveToleranceTime) + bi.clickCount = 1; + else + bi.clickCount++; + + MouseClickEvent ce = + new MouseClickEvent(getContext(), e.time, e.mouseId, e.buttons, e.stateMask, me.button, bi.clickCount, me.controlPosition, me.screenPosition); + getContext().getEventQueue().queueFirst(ce); + } + return false; + } + + /** + * Get last known position of a mouse + * + * @param mouseId mouse id + * @return mouse position in canvas coordinates or null if mouse exited + * canvas + */ + public MouseInfo getMouseInfo(int mouseId) { + return miceInfo.get(mouseId); + } + + public MouseInfo getMousePressedInfo(int mouseId) { + return micePressedInfo.get(mouseId); + } + + /** + * Get button info + * @param mouseId mouse id + * @param buttonId button id + * @return null if button has never been pressed, or button info + */ + public ButtonInfo getButtonInfo(int mouseId, int buttonId) + { + MouseInfo mi = miceInfo.get(mouseId); + if (mi==null) return null; + return mi.getButtonPressInfo(buttonId); + } + + /** + * Get a snapshot of statuses of all mice + * @return a snapshot + */ + public Map getMiceInfo() + { + return new HashMap(miceInfo); + } + + public int getMouseCount() + { + return miceInfo.size(); + } + + public MouseClickProfile getProfile() { + return profile; + } + + public void setProfile(MouseClickProfile profile) { + assert(profile!=null); + this.profile = profile; + } + + public static final class MouseInfo { + public int mouseId; + public Point2D controlPosition; + public Point2D canvasPosition; + public int buttons; + public MouseInfo(int mouseId, Point2D initialControlPos, Point2D initialCanvasPosition, int initialButtonMask) { + this.mouseId = mouseId; + this.controlPosition = initialControlPos; + this.canvasPosition = initialCanvasPosition; + int buttonId = 0; + while (initialButtonMask!=0) { + if ((initialButtonMask & 1)==1) + setButtonPressed(buttonId, 0, initialControlPos, initialCanvasPosition, Long.MIN_VALUE); + initialButtonMask >>>= 1; + buttonId++; + } + } + + public boolean isMouseButtonPressed(int buttonId) + { + ButtonInfo bi = buttonPressInfo.get(buttonId); + return bi!=null && bi.down; + } + private void _countButtonMask() { + int result = 0; + for (ButtonInfo pi : buttonPressInfo.values()) + { + if (!pi.down) continue; + result |= 1 << (pi.button-1); + } + this.buttons = result; + } + public Map buttonPressInfo = new HashMap(); + public void setButtonPressed(int buttonId, int stateMask, Point2D controlPos, Point2D canvasPos, long eventTime) { + ButtonInfo bi = getOrCreateButtonInfo(buttonId); + bi.canvasPosition = canvasPos; + bi.controlPosition = controlPos; + bi.systemTime = System.currentTimeMillis(); + bi.eventTime = eventTime; + bi.down = true; + bi.deltaMotion = 0; + bi.drag = false; + bi.stateMask = stateMask; + _countButtonMask(); + } + public ButtonInfo releaseButton(int buttonId, long eventTime) { + ButtonInfo bi = getButtonPressInfo(buttonId); + if (bi==null) return null; + bi.down = false; + bi.holdTime = eventTime - bi.eventTime; + _countButtonMask(); + return bi; + } + ButtonInfo getOrCreateButtonInfo(int buttonId) + { + ButtonInfo bi = buttonPressInfo.get(buttonId); + if (bi==null) bi = new ButtonInfo(buttonId); + buttonPressInfo.put(buttonId, bi); + return bi; + } + public ButtonInfo getButtonPressInfo(int buttonId) { + return buttonPressInfo.get(buttonId); + } + public void addDistanceForButtons(double distance) { + for (ButtonInfo bi : buttonPressInfo.values()) + { + if (!bi.down) continue; + bi.deltaMotion += distance; + } + } + public Collection getButtonInfos() { + return buttonPressInfo.values(); + } + } + + /** Status of mouse's button press */ + public static final class ButtonInfo { + /** Position on press */ + public Point2D controlPosition; + /** Position on press */ + public Point2D canvasPosition; + public final int button; + public int stateMask; + /** System time when pressed */ + public long systemTime; + /** Event time when pressed */ + public long eventTime; + /** Hold time when released */ + public long holdTime; + /** Current up / down status */ + public boolean down = false; + /** Total movement in pixels since press */ + public double deltaMotion = 0.0; + /** Click Count */ + public int clickCount = 0; + /** Time of last click */ + public long lastClickEventTime = Long.MIN_VALUE; + /** Dragged (set true when possibility for click is excluded) */ + public boolean drag = false; + public ButtonInfo(int button) { + this.button = button; + } + } + + /** + * Sends mice positions as an event + */ + private void sendMicePos() + { + long time = System.currentTimeMillis(); + for (Entry e : miceInfo.entrySet()) { + MouseInfo mi = e.getValue(); + MouseMovedEvent mme; + // FIXME: screenPosition as null (requires adding screenPos into MouseInfo) + mme = new MouseMovedEvent(getContext(), time, e.getKey(), mi.buttons, 0 /* FIXME ??? */, mi.controlPosition, null); + getContext().getEventQueue().queueEvent(mme); + } + } + +}