Home » openjdk-7 » java » awt » [javadoc | source]

    1   /*
    2    *  Licensed to the Apache Software Foundation (ASF) under one or more
    3    *  contributor license agreements.  See the NOTICE file distributed with
    4    *  this work for additional information regarding copyright ownership.
    5    *  The ASF licenses this file to You under the Apache License, Version 2.0
    6    *  (the "License"); you may not use this file except in compliance with
    7    *  the License.  You may obtain a copy of the License at
    8    *
    9    *     http://www.apache.org/licenses/LICENSE-2.0
   10    *
   11    *  Unless required by applicable law or agreed to in writing, software
   12    *  distributed under the License is distributed on an "AS IS" BASIS,
   13    *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14    *  See the License for the specific language governing permissions and
   15    *  limitations under the License.
   16    */
   17   /**
   18    * @author Dmitry A. Durnev, Michael Danilov, Pavel Dolgov
   19    */
   20   package java.awt;
   21   
   22   import java.awt.event.MouseEvent;
   23   import java.awt.event.MouseListener;
   24   import java.awt.event.MouseMotionListener;
   25   import java.awt.event.MouseWheelEvent;
   26   import java.awt.event.MouseWheelListener;
   27   import java.awt.Dispatcher.MouseGrabManager;
   28   import java.util.EventListener;
   29   
   30   import org.apache.harmony.awt.wtk.NativeEvent;
   31   import org.apache.harmony.awt.wtk.NativeWindow;
   32   
   33   
   34   class MouseDispatcher {
   35   
   36       // Fields for synthetic mouse click events generation
   37       private static final int clickDelta = 5;
   38       private final long[] lastPressTime = new long[] {0l, 0l, 0l};
   39       private final Point[] lastPressPos = new Point[] {null, null, null};
   40       private final boolean[] buttonPressed = new boolean[] {false, false, false};
   41       private final int[] clickCount = new int[] {0, 0, 0};
   42   
   43       // Fields for mouse entered/exited support
   44       private Component lastUnderPointer = null;
   45       private final Point lastScreenPos = new Point(-1, -1);
   46   
   47       // Fields for redundant mouse moved/dragged filtering
   48       private Component lastUnderMotion = null;
   49       private Point lastLocalPos = new Point(-1, -1);
   50   
   51       private final MouseGrabManager mouseGrabManager;
   52       private final Toolkit toolkit;
   53   
   54       static Point convertPoint(Component src, int x, int y, Component dest) {
   55           Point srcPoint = getAbsLocation(src);
   56           Point destPoint = getAbsLocation(dest);
   57   
   58           return new Point(x + (srcPoint.x - destPoint.x),
   59                            y + (srcPoint.y - destPoint.y));
   60       }
   61   
   62       static Point convertPoint(Component src, Point p, Component dst) {
   63           return convertPoint(src, p.x, p.y, dst);
   64       }
   65   
   66       private static Point getAbsLocation(Component comp) {
   67           Point location = new Point(0, 0);
   68   
   69           for (Component parent = comp; parent != null; parent = parent.parent) {
   70               Point parentPos = (parent instanceof EmbeddedWindow ?
   71                                  parent.getNativeWindow().getScreenPos() :
   72                                  parent.getLocation());
   73   
   74               location.translate(parentPos.x, parentPos.y);
   75   
   76               if (parent instanceof Window) {
   77                   break;
   78               }
   79           }
   80   
   81           return location;
   82       }
   83   
   84       MouseDispatcher(MouseGrabManager mouseGrabManager,
   85                       Toolkit toolkit) {
   86           this.mouseGrabManager = mouseGrabManager;
   87           this.toolkit = toolkit;
   88       }
   89   
   90       Point getPointerPos() {
   91           return lastScreenPos;
   92       }
   93   
   94       boolean dispatch(Component src, NativeEvent event) {
   95           int id = event.getEventId();
   96   
   97           lastScreenPos.setLocation(event.getScreenPos());
   98           checkMouseEnterExit(event.getInputModifiers(), event.getTime());
   99   
  100           if (id == MouseEvent.MOUSE_WHEEL) {
  101               dispatchWheelEvent(src, event);
  102           } else if ((id != MouseEvent.MOUSE_ENTERED) &&
  103                      (id != MouseEvent.MOUSE_EXITED)) {
  104               PointerInfo info = new PointerInfo(src, event.getLocalPos());
  105   
  106               mouseGrabManager.preprocessEvent(event);
  107               findEventSource(info);
  108               if ((id == MouseEvent.MOUSE_PRESSED) ||
  109                   (id == MouseEvent.MOUSE_RELEASED)) {
  110   
  111                   dispatchButtonEvent(info, event);
  112               } else if ((id == MouseEvent.MOUSE_MOVED) ||
  113                          (id == MouseEvent.MOUSE_DRAGGED)) {
  114   
  115                   dispatchMotionEvent(info, event);
  116               }
  117           }
  118   
  119           return false;
  120       }
  121   
  122       private void checkMouseEnterExit(int modifiers, long when) {
  123           PointerInfo info = findComponentUnderPointer();
  124           Component curUnderPointer =
  125                   propagateEvent(info, AWTEvent.MOUSE_EVENT_MASK,
  126                                  MouseListener.class, false).src;
  127   
  128           if (curUnderPointer != lastUnderPointer) {
  129               Point pos = info.position;
  130               if ((lastUnderPointer != null) &&
  131                    lastUnderPointer.isMouseExitedExpected()) {
  132   
  133                   Point exitPos = convertPoint(null, lastScreenPos.x,
  134                                                lastScreenPos.y, lastUnderPointer);
  135   
  136                   postMouseEnterExit(MouseEvent.MOUSE_EXITED, modifiers, when,
  137                                      exitPos.x, exitPos.y, lastUnderPointer);
  138               }
  139               setCursor(curUnderPointer);
  140               if (curUnderPointer != null) {
  141                   postMouseEnterExit(MouseEvent.MOUSE_ENTERED, modifiers, when,
  142                                      pos.x, pos.y, curUnderPointer);
  143               }
  144               lastUnderPointer = curUnderPointer;
  145           }
  146       }
  147   
  148       private void setCursor(Component comp) {
  149           if (comp == null) {
  150               return;
  151           }
  152           Component grabOwner = mouseGrabManager.getSyntheticGrabOwner();
  153           Component cursorComp = ((grabOwner != null) &&
  154                                    grabOwner.isShowing() ? grabOwner : comp);
  155           cursorComp.setCursor();
  156       }
  157   
  158       private void postMouseEnterExit(int id, int mod, long when,
  159                                       int x, int y, Component comp) {
  160           if (comp.isIndirectlyEnabled()) {
  161               toolkit.getSystemEventQueueImpl().postEvent(
  162                       new MouseEvent(comp, id, when, mod, x, y, 0, false));
  163               comp.setMouseExitedExpected(id == MouseEvent.MOUSE_ENTERED);
  164           } else {
  165               comp.setMouseExitedExpected(false);
  166           }
  167       }
  168   
  169       private PointerInfo findComponentUnderPointer() {
  170           NativeWindow nativeWindow = toolkit.getWindowFactory().
  171           getWindowFromPoint(lastScreenPos);
  172   
  173           if (nativeWindow != null) {
  174               Component comp = toolkit.getComponentById(nativeWindow.getId());
  175   
  176               if (comp != null) {
  177                   Window window = comp.getWindowAncestor();
  178                   Point pointerPos = convertPoint(null, lastScreenPos.x,
  179                                                   lastScreenPos.y, window);
  180   
  181                   if (window.getClient().contains(pointerPos)) {
  182                       PointerInfo info = new PointerInfo(window, pointerPos);
  183   
  184                       fall2Child(info);
  185   
  186                       return info;
  187                   }
  188               }
  189           }
  190   
  191           return new PointerInfo(null, null);
  192       }
  193   
  194       private void findEventSource(PointerInfo info) {
  195           Component grabOwner = mouseGrabManager.getSyntheticGrabOwner();
  196   
  197           if (grabOwner != null && grabOwner.isShowing()) {
  198               info.position = convertPoint(info.src, info.position, grabOwner);
  199               info.src = grabOwner;
  200           } else {
  201               rise2TopLevel(info);
  202               fall2Child(info);
  203           }
  204       }
  205   
  206       private void rise2TopLevel(PointerInfo info) {
  207           while (!(info.src instanceof Window)) {
  208               info.position.translate(info.src.x, info.src.y);
  209               info.src = info.src.parent;
  210           }
  211       }
  212   
  213       private void fall2Child(PointerInfo info) {
  214   		final Point pos = info.position;
  215   		final int x = pos.x;
  216   		final int y = pos.y;
  217   
  218   		for (Component child : ((Container) info.src).getComponents()) {
  219   			if (child.isShowing()) {
  220   				if (child.contains(x - child.x, y - child.y)) {
  221   					info.src = child;
  222   					pos.translate(-child.x, -child.y);
  223   
  224   					if (child instanceof Container) {
  225   						fall2Child(info);
  226   					}
  227   
  228   					return;
  229   				}
  230   			}
  231   		}
  232   	}
  233   
  234       private void dispatchButtonEvent(PointerInfo info, NativeEvent event) {
  235           int button = event.getMouseButton();
  236           long time = event.getTime();
  237           int id = event.getEventId();
  238           int index = button - 1;
  239           boolean clickRequired = false;
  240   
  241           propagateEvent(info, AWTEvent.MOUSE_EVENT_MASK,
  242                          MouseListener.class, false);
  243           if (id == MouseEvent.MOUSE_PRESSED) {
  244               int clickInterval = toolkit.dispatcher.clickInterval;
  245               mouseGrabManager.onMousePressed(info.src);
  246               buttonPressed[index] = true;
  247               clickCount[index] = (!deltaExceeded(index, info) &&
  248                       ((time - lastPressTime[index]) <= clickInterval)) ?
  249                       clickCount[index] + 1 : 1;
  250               lastPressTime[index] = time;
  251               lastPressPos[index] = info.position;
  252           } else {
  253               mouseGrabManager.onMouseReleased(info.src);
  254               // set cursor back on synthetic mouse grab end:
  255               setCursor(findComponentUnderPointer().src);
  256               if (buttonPressed[index]) {
  257                   buttonPressed[index] = false;
  258                   clickRequired = !deltaExceeded(index, info);
  259               } else {
  260                   clickCount[index] = 0;
  261               }
  262           }
  263           if (info.src.isIndirectlyEnabled()) {
  264               final Point pos = info.position;
  265               final int mod = event.getInputModifiers();
  266               toolkit.getSystemEventQueueImpl().postEvent(
  267                               new MouseEvent(info.src, id, time, mod, pos.x,
  268                               pos.y, clickCount[index],
  269                               event.getTrigger(), button));
  270               if (clickRequired) {
  271                   toolkit.getSystemEventQueueImpl().postEvent(
  272                               new MouseEvent(info.src,
  273                               MouseEvent.MOUSE_CLICKED,
  274                               time, mod, pos.x, pos.y,
  275                               clickCount[index], false,
  276                               button));
  277               }
  278           }
  279       }
  280   
  281       private boolean deltaExceeded(int index, PointerInfo info) {
  282           final Point lastPos = lastPressPos[index];
  283           if (lastPos == null) {
  284               return true;
  285           }
  286           return ((Math.abs(lastPos.x - info.position.x) > clickDelta) ||
  287                   (Math.abs(lastPos.y - info.position.y) > clickDelta));
  288       }
  289   
  290       private void dispatchMotionEvent(PointerInfo info, NativeEvent event) {
  291           propagateEvent(info, AWTEvent.MOUSE_MOTION_EVENT_MASK,
  292                          MouseMotionListener.class, false);
  293           final Point pos = info.position;
  294           if ((lastUnderMotion != info.src) ||
  295               !lastLocalPos.equals(pos)) {
  296   
  297               lastUnderMotion = info.src;
  298               lastLocalPos = pos;
  299   
  300               if (info.src.isIndirectlyEnabled()) {
  301                   toolkit.getSystemEventQueueImpl().postEvent(
  302                               new MouseEvent(info.src, event.getEventId(),
  303                               event.getTime(),
  304                               event.getInputModifiers(),
  305                               pos.x, pos.y, 0, false));
  306               }
  307           }
  308       }
  309   
  310       MouseWheelEvent createWheelEvent(Component src, NativeEvent event,
  311                                        Point where) {
  312   
  313           Integer scrollAmountProperty =
  314               (Integer)toolkit.getDesktopProperty("awt.wheelScrollingSize"); //$NON-NLS-1$
  315           int amount = 1;
  316           int type = MouseWheelEvent.WHEEL_UNIT_SCROLL;
  317   
  318           if (scrollAmountProperty != null) {
  319               amount = scrollAmountProperty.intValue();
  320               if (amount == -1) {
  321                   type = MouseWheelEvent.WHEEL_BLOCK_SCROLL;
  322                   amount = 1;
  323               }
  324           }
  325           return new MouseWheelEvent(src, event.getEventId(),
  326                   event.getTime(), event.getInputModifiers(),
  327                   where.x, where.y, 0, false, type, amount,
  328                   event.getWheelRotation());
  329       }
  330   
  331       private void dispatchWheelEvent(Component src, NativeEvent event) {
  332           PointerInfo info = findComponentUnderPointer();
  333   
  334           if (info.src == null) {
  335               info.src = src;
  336               info.position = event.getLocalPos();
  337           }
  338   
  339           propagateEvent(info, AWTEvent.MOUSE_WHEEL_EVENT_MASK,
  340                          MouseWheelListener.class, true);
  341           if ((info.src != null) && info.src.isIndirectlyEnabled()) {
  342               toolkit.getSystemEventQueueImpl().postEvent(
  343                       createWheelEvent(info.src, event, info.position));
  344           }
  345       }
  346   
  347       private PointerInfo propagateEvent(PointerInfo info, long mask,
  348                                          Class<? extends EventListener> type, boolean pierceHW) {
  349           Component src = info.src;
  350           while ((src != null) &&
  351                  (src.isLightweight() || pierceHW) &&
  352                 !(src.isMouseEventEnabled(mask) ||
  353                  (src.getListeners(type).length > 0))) {
  354   
  355               info.position.translate(src.x, src.y);
  356               src = src.parent;
  357               info.src = src;
  358           }
  359   
  360           return info;
  361       }
  362   
  363       Window findWindowAt(Point p) {
  364           NativeWindow nativeWindow =
  365               toolkit.getWindowFactory().getWindowFromPoint(p);
  366   
  367           Window window = null;
  368           if (nativeWindow != null) {
  369               Component comp = toolkit.getComponentById(nativeWindow.getId());
  370   
  371               if (comp != null) {
  372                   window = comp.getWindowAncestor();
  373               }
  374           }
  375           return window;
  376       }
  377   
  378       private class PointerInfo {
  379   
  380           Component src;
  381           Point position;
  382   
  383           PointerInfo(Component src, Point position) {
  384               this.src = src;
  385               this.position = position;
  386           }
  387   
  388       }
  389   
  390   }

Home » openjdk-7 » java » awt » [javadoc | source]