diff options
Diffstat (limited to 'libjava/classpath/java/awt/LightweightDispatcher.java')
-rw-r--r-- | libjava/classpath/java/awt/LightweightDispatcher.java | 362 |
1 files changed, 0 insertions, 362 deletions
diff --git a/libjava/classpath/java/awt/LightweightDispatcher.java b/libjava/classpath/java/awt/LightweightDispatcher.java deleted file mode 100644 index 11b83d8..0000000 --- a/libjava/classpath/java/awt/LightweightDispatcher.java +++ /dev/null @@ -1,362 +0,0 @@ -/* LightweightDispatcher.java -- Dispatches mouse events to lightweights - Copyright (C) 2006 Free Software Foundation, Inc. - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - - -package java.awt; - -import java.awt.event.InputEvent; -import java.awt.event.MouseEvent; -import java.awt.event.MouseWheelEvent; -import java.awt.peer.LightweightPeer; -import java.util.WeakHashMap; - -/** - * Redispatches mouse events to lightweight components. The native peers know - * nothing about the lightweight components and thus mouse events are always - * targetted at Windows or heavyweight components. This class listenes directly - * on the eventqueue and dispatches mouse events to lightweight components. - * - * @author Roman Kennke (kennke@aicas.com) - */ -final class LightweightDispatcher -{ - - /** - * Maps thread groups to lightweight dispatcher instances. We need to - * have one instance per thread group so that 2 or more applets or otherwise - * separated applications (like in OSGI) do not interfer with each other. - */ - private static WeakHashMap instances = new WeakHashMap(); - - /** - * The last mouse event target. If the target changes, additional - * MOUSE_ENTERED and MOUSE_EXITED events must be dispatched. - */ - private Component lastTarget; - - /** - * The current mouseEventTarget. - */ - private Component mouseEventTarget; - - /** - * Returns an instance of LightweightDispatcher for the current thread's - * thread group. - * - * @return an instance of LightweightDispatcher for the current thread's - * thread group - */ - static LightweightDispatcher getInstance() - { - Thread t = Thread.currentThread(); - ThreadGroup tg = t.getThreadGroup(); - LightweightDispatcher instance = (LightweightDispatcher) instances.get(tg); - if (instance == null) - { - instance = new LightweightDispatcher(); - instances.put(tg, instance); - } - return instance; - } - - /** - * Creates a new LightweightDispatcher. This is private to prevent access - * from outside. Use {@link #getInstance()} instead. - */ - private LightweightDispatcher() - { - // Nothing to do here. - } - - /** - * Receives notification if a mouse event passes along the eventqueue. - * - * @param event the event - */ - public boolean dispatchEvent(final AWTEvent event) - { - if (event instanceof MouseEvent) - { - MouseEvent mouseEvent = (MouseEvent) event; - return handleMouseEvent(mouseEvent); - } - return false; - } - - /** - * Handles all mouse events that are targetted at toplevel containers - * (Window instances) and dispatches them to the correct lightweight child. - * - * @param ev the mouse event - * @return whether or not we found a lightweight that handled the event. - */ - private boolean handleMouseEvent(final MouseEvent ev) - { - Container container = (Container) ev.getSource(); - Component target = findTarget(container, ev.getX(), ev.getY()); - trackEnterExit(target, ev); - int id = ev.getID(); - - // Dont update the mouseEventTarget when dragging. Also, MOUSE_CLICKED - // must be dispatched to the original target of MOUSE_PRESSED, so don't - // update in this case either. - if (! isDragging(ev) && id != MouseEvent.MOUSE_CLICKED) - mouseEventTarget = (target != container) ? target : null; - - if (mouseEventTarget != null) - { - switch (id) - { - case MouseEvent.MOUSE_ENTERED: - case MouseEvent.MOUSE_EXITED: - // This is already handled in trackEnterExit(). - break; - case MouseEvent.MOUSE_PRESSED: - case MouseEvent.MOUSE_RELEASED: - case MouseEvent.MOUSE_MOVED: - redispatch(ev, mouseEventTarget, id); - break; - case MouseEvent.MOUSE_CLICKED: - // MOUSE_CLICKED must be dispatched to the original target of - // MOUSE_PRESSED. - if (target == mouseEventTarget) - redispatch(ev, mouseEventTarget, id); - break; - case MouseEvent.MOUSE_DRAGGED: - if (isDragging(ev)) - redispatch(ev, mouseEventTarget, id); - break; - case MouseEvent.MOUSE_WHEEL: - redispatch(ev, mouseEventTarget, id); - } - ev.consume(); - } - - return ev.isConsumed(); - } - - /** - * Finds the actual target for a mouseevent, starting at <code>c</code>. - * This searches through the children of the container and finds the first - * one which is showing, at the location from the mouse event and has - * a MouseListener or MouseMotionListener attached. If no such child component - * is found, null is returned. - * - * @param c the container to search through - * @param loc the mouse event point - * - * @return the actual receiver of the mouse event, or null, if no such - * component has been found - */ - private Component findTarget(final Container c, final int x, final int y) - { - Component target = null; - - // First we check the children of the container. - - // Note: It is important that we use the package private Container - // fields ncomponents and component here. There are applications - // that override getComponentCount() - // and getComponent() to hide internal components, which makes - // the LightweightDispatcher not work correctly in these cases. - // As a positive sideeffect this is slightly more efficient. - int nChildren = c.ncomponents; - for (int i = 0; i < nChildren && target == null; i++) - { - Component child = c.component[i]; - int childX = x - child.x; - int childY = y - child.y; - if (child != null && child.visible - && child.peer instanceof LightweightPeer - && child.contains(childX, childY)) - { - // Check if there's a deeper possible target. - if (child instanceof Container) - { - Component deeper = findTarget((Container) child, - childX, childY); - if (deeper != null) - target = deeper; - } - // Check if the child itself is interested in mouse events. - else if (isMouseListening(child)) - target = child; - } - } - - // Check the container itself, if we didn't find a target yet. - if (target == null && c.contains(x, y) && isMouseListening(c)) - target = c; - - return target; - } - - /** - * Checks if the specified component would be interested in a mouse event. - * - * @param c the component to check - * - * @return <code>true</code> if the component has mouse listeners installed, - * <code>false</code> otherwise - */ - private boolean isMouseListening(final Component c) - { - // Note: It is important to NOT check if the component is listening - // for a specific event (for instance, mouse motion events). The event - // gets dispatched to the component if the component is listening - // for ANY mouse event, even when the component is not listening for the - // specific type of event. There are applications that depend on this - // (sadly). - return c.mouseListener != null - || c.mouseMotionListener != null - || c.mouseWheelListener != null - || (c.eventMask & AWTEvent.MOUSE_EVENT_MASK) != 0 - || (c.eventMask & AWTEvent.MOUSE_MOTION_EVENT_MASK) != 0 - || (c.eventMask & AWTEvent.MOUSE_WHEEL_EVENT_MASK) != 0; - } - - /** - * Tracks MOUSE_ENTERED and MOUSE_EXIT as well as MOUSE_MOVED and - * MOUSE_DRAGGED and creates synthetic MOUSE_ENTERED and MOUSE_EXITED for - * lightweight component.s - * - * @param target the current mouse event target - * @param ev the mouse event - */ - private void trackEnterExit(final Component target, final MouseEvent ev) - { - int id = ev.getID(); - if (target != lastTarget) - { - if (lastTarget != null) - redispatch(ev, lastTarget, MouseEvent.MOUSE_EXITED); - if (id == MouseEvent.MOUSE_EXITED) - ev.consume(); - if (target != null) - redispatch(ev, target, MouseEvent.MOUSE_ENTERED); - if (id == MouseEvent.MOUSE_ENTERED) - ev.consume(); - lastTarget = target; - } - - } - - /** - * Redispatches the specified mouse event to the specified target with the - * specified id. - * - * @param ev the mouse event - * @param target the new target - * @param id the new id - */ - private void redispatch(MouseEvent ev, Component target, int id) - { - Component source = ev.getComponent(); - assert target != null; - if (target.isShowing()) - { - // Translate coordinates. - int x = ev.getX(); - int y = ev.getY(); - for (Component c = target; c != null && c != source; c = c.getParent()) - { - x -= c.x; - y -= c.y; - } - - // Retarget event. - MouseEvent retargeted; - if (id == MouseEvent.MOUSE_WHEEL) - { - MouseWheelEvent mwe = (MouseWheelEvent) ev; - retargeted = new MouseWheelEvent(target, id, ev.getWhen(), - ev.getModifiers() - | ev.getModifiersEx(), x, y, - ev.getClickCount(), - ev.isPopupTrigger(), - mwe.getScrollType(), - mwe.getScrollAmount(), - mwe.getWheelRotation()); - } - else - { - retargeted = new MouseEvent(target, id, ev.getWhen(), - ev.getModifiers() | ev.getModifiersEx(), - x, y, ev.getClickCount(), - ev.isPopupTrigger(), ev.getButton()); - } - - if (target == source) - ((Container) target).dispatchNoLightweight(retargeted); - else - target.dispatchEvent(retargeted); - } - } - - /** - * Determines if we are in the middle of a drag operation, that is, if - * any of the buttons is held down. - * - * @param ev the mouse event to check - * - * @return <code>true</code> if we are in the middle of a drag operation, - * <code>false</code> otherwise - */ - private boolean isDragging(MouseEvent ev) - { - int mods = ev.getModifiersEx(); - int id = ev.getID(); - if (id == MouseEvent.MOUSE_PRESSED || id == MouseEvent.MOUSE_RELEASED) - { - switch (ev.getButton()) - { - case MouseEvent.BUTTON1: - mods ^= InputEvent.BUTTON1_DOWN_MASK; - break; - case MouseEvent.BUTTON2: - mods ^= InputEvent.BUTTON2_DOWN_MASK; - break; - case MouseEvent.BUTTON3: - mods ^= InputEvent.BUTTON3_DOWN_MASK; - break; - } - } - return (mods & (InputEvent.BUTTON1_DOWN_MASK - | InputEvent.BUTTON2_DOWN_MASK - | InputEvent.BUTTON3_DOWN_MASK)) != 0; - } -} |