diff options
Diffstat (limited to 'awt/java/awt/MouseDispatcher.java')
-rw-r--r-- | awt/java/awt/MouseDispatcher.java | 418 |
1 files changed, 418 insertions, 0 deletions
diff --git a/awt/java/awt/MouseDispatcher.java b/awt/java/awt/MouseDispatcher.java new file mode 100644 index 0000000..df48f9d --- /dev/null +++ b/awt/java/awt/MouseDispatcher.java @@ -0,0 +1,418 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @author Dmitry A. Durnev, Michael Danilov, Pavel Dolgov + * @version $Revision$ + */ +package java.awt; + +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; +import java.awt.event.MouseWheelEvent; +import java.awt.event.MouseWheelListener; +import java.awt.Dispatcher.MouseGrabManager; +import java.util.EventListener; + +import org.apache.harmony.awt.wtk.NativeEvent; +import org.apache.harmony.awt.wtk.NativeWindow; + + +class MouseDispatcher { + + // Fields for synthetic mouse click events generation + private static final int clickDelta = 5; + private final long[] lastPressTime = new long[] {0l, 0l, 0l}; + private final Point[] lastPressPos = new Point[] {null, null, null}; + private final boolean[] buttonPressed = new boolean[] {false, false, false}; + private final int[] clickCount = new int[] {0, 0, 0}; + + // Fields for mouse entered/exited support + private Component lastUnderPointer = null; + private final Point lastScreenPos = new Point(-1, -1); + + // Fields for redundant mouse moved/dragged filtering + private Component lastUnderMotion = null; + private Point lastLocalPos = new Point(-1, -1); + + private final MouseGrabManager mouseGrabManager; + private final Toolkit toolkit; + + static Point convertPoint(Component src, int x, int y, Component dest) { + Point srcPoint = getAbsLocation(src); + Point destPoint = getAbsLocation(dest); + + return new Point(x + (srcPoint.x - destPoint.x), + y + (srcPoint.y - destPoint.y)); + } + + static Point convertPoint(Component src, Point p, Component dst) { + return convertPoint(src, p.x, p.y, dst); + } + + private static Point getAbsLocation(Component comp) { + Point location = new Point(0, 0); +// BEGIN android-changed: AWT components not supported +// for (Component parent = comp; parent != null; parent = parent.parent) { +// Point parentPos = (parent instanceof EmbeddedWindow ? +// parent.getNativeWindow().getScreenPos() : +// parent.getLocation()); +// +// location.translate(parentPos.x, parentPos.y); +// +// if (parent instanceof Window) { +// break; +// } +// } +// END android-changed + + return location; + } + + MouseDispatcher(MouseGrabManager mouseGrabManager, + Toolkit toolkit) { + this.mouseGrabManager = mouseGrabManager; + this.toolkit = toolkit; + } + + Point getPointerPos() { + return lastScreenPos; + } + + boolean dispatch(Component src, NativeEvent event) { + int id = event.getEventId(); + + lastScreenPos.setLocation(event.getScreenPos()); + checkMouseEnterExit(event.getInputModifiers(), event.getTime()); + + if (id == MouseEvent.MOUSE_WHEEL) { +// BEGIN android-changed: AWT components not supported +// dispatchWheelEvent(src, event); +// END android-changed + } else if ((id != MouseEvent.MOUSE_ENTERED) && + (id != MouseEvent.MOUSE_EXITED)) { + PointerInfo info = new PointerInfo(src, event.getLocalPos()); + + mouseGrabManager.preprocessEvent(event); + findEventSource(info); + if ((id == MouseEvent.MOUSE_PRESSED) || + (id == MouseEvent.MOUSE_RELEASED)) { + + dispatchButtonEvent(info, event); + } else if ((id == MouseEvent.MOUSE_MOVED) || + (id == MouseEvent.MOUSE_DRAGGED)) { + + dispatchMotionEvent(info, event); + } + } + + return false; + } + + private void checkMouseEnterExit(int modifiers, long when) { +// BEGIN android-changed: AWT components not supported +// PointerInfo info = findComponentUnderPointer(); +// Component curUnderPointer = +// propagateEvent(info, AWTEvent.MOUSE_EVENT_MASK, +// MouseListener.class, false).src; +// +// if (curUnderPointer != lastUnderPointer) { +// Point pos = info.position; +// if ((lastUnderPointer != null) && +// lastUnderPointer.isMouseExitedExpected()) { +// +// Point exitPos = convertPoint(null, lastScreenPos.x, +// lastScreenPos.y, lastUnderPointer); +// +// postMouseEnterExit(MouseEvent.MOUSE_EXITED, modifiers, when, +// exitPos.x, exitPos.y, lastUnderPointer); +// } +// setCursor(curUnderPointer); +// if (curUnderPointer != null) { +// postMouseEnterExit(MouseEvent.MOUSE_ENTERED, modifiers, when, +// pos.x, pos.y, curUnderPointer); +// } +// lastUnderPointer = curUnderPointer; +// } +// END android-changed + } + + private void setCursor(Component comp) { + if (comp == null) { + return; + } + Component grabOwner = mouseGrabManager.getSyntheticGrabOwner(); + Component cursorComp = ((grabOwner != null) && + grabOwner.isShowing() ? grabOwner : comp); + cursorComp.setCursor(); + } + + private void postMouseEnterExit(int id, int mod, long when, + int x, int y, Component comp) { + if (comp.isIndirectlyEnabled()) { + toolkit.getSystemEventQueueImpl().postEvent( + new MouseEvent(comp, id, when, mod, x, y, 0, false)); + comp.setMouseExitedExpected(id == MouseEvent.MOUSE_ENTERED); + } else { + comp.setMouseExitedExpected(false); + } + } + + // BEGIN android-changed: AWT components not supported +// private PointerInfo findComponentUnderPointer() { +// NativeWindow nativeWindow = toolkit.getWindowFactory(). +// getWindowFromPoint(lastScreenPos); +// +// if (nativeWindow != null) { +// Component comp = toolkit.getComponentById(nativeWindow.getId()); +// +// if (comp != null) { +// Window window = comp.getWindowAncestor(); +// Point pointerPos = convertPoint(null, lastScreenPos.x, +// lastScreenPos.y, window); +// +// if (window.getClient().contains(pointerPos)) { +// PointerInfo info = new PointerInfo(window, pointerPos); +// +// fall2Child(info); +// +// return info; +// } +// } +// } +// +// return new PointerInfo(null, null); +// } +// END android-changed + + private void findEventSource(PointerInfo info) { + Component grabOwner = mouseGrabManager.getSyntheticGrabOwner(); + + if (grabOwner != null && grabOwner.isShowing()) { + info.position = convertPoint(info.src, info.position, grabOwner); + info.src = grabOwner; + } else { + //???AWT: rise2TopLevel(info); + //???AWT: fall2Child(info); + } + } + + // BEGIN android-changed: AWT components not supported +// private void rise2TopLevel(PointerInfo info) { +// while (!(info.src instanceof Window)) { +// info.position.translate(info.src.x, info.src.y); +// info.src = info.src.parent; +// } +// } +// +// private void fall2Child(PointerInfo info) { +// Insets insets = info.src.getInsets(); +// +// final Point pos = info.position; +// final int x = pos.x; +// final int y = pos.y; +// if ((x >= insets.left) && (y >= insets.top) && +// (x < (info.src.w - insets.right)) && +// (y < (info.src.h - insets.bottom))) +// { +// Component[] children = ((Container) info.src).getComponents(); +// +// for (Component child : children) { +// if (child.isShowing()) { +// if (child.contains(x - child.getX(), +// y - child.getY())) +// { +// info.src = child; +// pos.translate(-child.x, -child.y); +// +// if (child instanceof Container) { +// fall2Child(info); +// } +// +// return; +// } +// } +// } +// } +// } +// END android-changed + + private void dispatchButtonEvent(PointerInfo info, NativeEvent event) { + int button = event.getMouseButton(); + long time = event.getTime(); + int id = event.getEventId(); + int index = button - 1; + boolean clickRequired = false; + + propagateEvent(info, AWTEvent.MOUSE_EVENT_MASK, + MouseListener.class, false); + if (id == MouseEvent.MOUSE_PRESSED) { + int clickInterval = toolkit.dispatcher.clickInterval; + mouseGrabManager.onMousePressed(info.src); + buttonPressed[index] = true; + clickCount[index] = (!deltaExceeded(index, info) && + ((time - lastPressTime[index]) <= clickInterval)) ? + clickCount[index] + 1 : 1; + lastPressTime[index] = time; + lastPressPos[index] = info.position; + } else { + mouseGrabManager.onMouseReleased(info.src); + // set cursor back on synthetic mouse grab end: +// BEGIN android-changed: AWT components not supported +// setCursor(findComponentUnderPointer().src); +// END android-changed + if (buttonPressed[index]) { + buttonPressed[index] = false; + clickRequired = !deltaExceeded(index, info); + } else { + clickCount[index] = 0; + } + } + if (info.src.isIndirectlyEnabled()) { + final Point pos = info.position; + final int mod = event.getInputModifiers(); + toolkit.getSystemEventQueueImpl().postEvent( + new MouseEvent(info.src, id, time, mod, pos.x, + pos.y, clickCount[index], + event.getTrigger(), button)); + if (clickRequired) { + toolkit.getSystemEventQueueImpl().postEvent( + new MouseEvent(info.src, + MouseEvent.MOUSE_CLICKED, + time, mod, pos.x, pos.y, + clickCount[index], false, + button)); + } + } + } + + private boolean deltaExceeded(int index, PointerInfo info) { + final Point lastPos = lastPressPos[index]; + if (lastPos == null) { + return true; + } + return ((Math.abs(lastPos.x - info.position.x) > clickDelta) || + (Math.abs(lastPos.y - info.position.y) > clickDelta)); + } + + private void dispatchMotionEvent(PointerInfo info, NativeEvent event) { + propagateEvent(info, AWTEvent.MOUSE_MOTION_EVENT_MASK, + MouseMotionListener.class, false); + final Point pos = info.position; + if ((lastUnderMotion != info.src) || + !lastLocalPos.equals(pos)) { + + lastUnderMotion = info.src; + lastLocalPos = pos; + + if (info.src.isIndirectlyEnabled()) { + toolkit.getSystemEventQueueImpl().postEvent( + new MouseEvent(info.src, event.getEventId(), + event.getTime(), + event.getInputModifiers(), + pos.x, pos.y, 0, false)); + } + } + } + + MouseWheelEvent createWheelEvent(Component src, NativeEvent event, + Point where) { + + Integer scrollAmountProperty = + (Integer)toolkit.getDesktopProperty("awt.wheelScrollingSize"); //$NON-NLS-1$ + int amount = 1; + int type = MouseWheelEvent.WHEEL_UNIT_SCROLL; + + if (scrollAmountProperty != null) { + amount = scrollAmountProperty.intValue(); + if (amount == -1) { + type = MouseWheelEvent.WHEEL_BLOCK_SCROLL; + amount = 1; + } + } + return new MouseWheelEvent(src, event.getEventId(), + event.getTime(), event.getInputModifiers(), + where.x, where.y, 0, false, type, amount, + event.getWheelRotation()); + } + +// BEGIN android-changed: AWT components not supported +// private void dispatchWheelEvent(Component src, NativeEvent event) { +// PointerInfo info = findComponentUnderPointer(); +// +// if (info.src == null) { +// info.src = src; +// info.position = event.getLocalPos(); +// } +// +// propagateEvent(info, AWTEvent.MOUSE_WHEEL_EVENT_MASK, +// MouseWheelListener.class, true); +// if ((info.src != null) && info.src.isIndirectlyEnabled()) { +// toolkit.getSystemEventQueueImpl().postEvent( +// createWheelEvent(info.src, event, info.position)); +// } +// } +// END android-changed + + private PointerInfo propagateEvent(PointerInfo info, long mask, + Class<? extends EventListener> type, boolean pierceHW) { + Component src = info.src; + while ((src != null) && + (src.isLightweight() || pierceHW) && + !(src.isMouseEventEnabled(mask) || + (src.getListeners(type).length > 0))) { + + info.position.translate(src.x, src.y); +// BEGIN android-changed: AWT components not supported +// src = src.parent; +// END android-changed + info.src = src; + } + + return info; + } + +// BEGIN android-changed: AWT components not supported +// Window findWindowAt(Point p) { +// NativeWindow nativeWindow = +// toolkit.getWindowFactory().getWindowFromPoint(p); +// +// Window window = null; +// if (nativeWindow != null) { +// Component comp = toolkit.getComponentById(nativeWindow.getId()); +// +// if (comp != null) { +// window = comp.getWindowAncestor(); +// } +// } +// return window; +// } +// END android-changed + + private class PointerInfo { + + Component src; + Point position; + + PointerInfo(Component src, Point position) { + this.src = src; + this.position = position; + } + + } + +} |