1 /*
   2  * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package sun.lwawt.macosx;
  27 
  28 
  29 import java.awt.*;
  30 import java.awt.dnd.*;
  31 import java.awt.event.*;
  32 
  33 import sun.awt.dnd.SunDragSourceContextPeer;
  34 
  35 
  36 class CMouseDragGestureRecognizer extends MouseDragGestureRecognizer {
  37 
  38       // Number of pixels before drag is determined to have started:
  39     private static final int fMotionThreshold = getMotionThreshold();
  40 
  41     // Default is the Aqua-approved value:
  42     private static final int kDefaultMotionThreshold = 3;
  43 
  44     private static int getMotionThreshold() {
  45         try {
  46             return ((Integer)Toolkit.getDefaultToolkit().getDesktopProperty("DnD.gestureMotionThreshold")).intValue();
  47         } catch (Exception e) {
  48             return kDefaultMotionThreshold;
  49         }
  50     }
  51 
  52     protected static final int ButtonMask = InputEvent.BUTTON1_DOWN_MASK |
  53                                             InputEvent.BUTTON2_DOWN_MASK |
  54                                             InputEvent.BUTTON3_DOWN_MASK;
  55 
  56     protected CMouseDragGestureRecognizer(DragSource ds, Component c, int act, DragGestureListener dgl) {
  57         super(ds, c, act, dgl);
  58     }
  59 
  60     protected CMouseDragGestureRecognizer(DragSource ds, Component c, int act) {
  61         this(ds, c, act, null);
  62     }
  63 
  64     protected CMouseDragGestureRecognizer(DragSource ds, Component c) {
  65         this(ds, c, DnDConstants.ACTION_NONE);
  66     }
  67 
  68     protected CMouseDragGestureRecognizer(DragSource ds) {
  69         this(ds, null);
  70     }
  71 
  72     // Determine the drop action from the event:
  73     protected int mapDragOperationFromModifiers(MouseEvent e) {
  74         int mods = e.getModifiersEx();
  75         int btns = mods & ButtonMask;
  76 
  77         // 8-29-02 VL: this shouldn't apply to OS X but let's leave this commented out until verified:
  78         // Do not allow right mouse button drag since Motif DnD does not terminate drag operation on right mouse button release.
  79         //if (!(btns == InputEvent.BUTTON1_DOWN_MASK || btns == InputEvent.BUTTON2_DOWN_MASK)) {
  80         //    return DnDConstants.ACTION_NONE;
  81         //}
  82 
  83         return SunDragSourceContextPeer.convertModifiersToDropAction(mods, getSourceActions());
  84     }
  85 
  86     // Invoked when the mouse has been clicked on a component:
  87     public void mouseClicked(MouseEvent e) {
  88         // do nothing
  89     }
  90 
  91     // Invoked when a mouse button has been pressed on a component:
  92     public void mousePressed(MouseEvent e) {
  93         events.clear();
  94 
  95         if (mapDragOperationFromModifiers(e) != DnDConstants.ACTION_NONE) {
  96             appendEvent(e);
  97         }
  98     }
  99 
 100     // Invoked when a mouse button has been released over a component:
 101     public void mouseReleased(MouseEvent e) {
 102         events.clear();
 103     }
 104 
 105     // Invoked when the mouse enters a component:
 106     public void mouseEntered(MouseEvent e) {
 107         events.clear();
 108     }
 109 
 110     // Invoked when the mouse exits a component:
 111     public void mouseExited(MouseEvent e) {
 112         if (!events.isEmpty()) { // gesture pending
 113             int dragAction = mapDragOperationFromModifiers(e);
 114 
 115             if (dragAction == DnDConstants.ACTION_NONE) {
 116                 events.clear();
 117             }
 118         }
 119     }
 120 
 121     // Invoked when a mouse button is pressed on a component:
 122     public void mouseDragged(MouseEvent e) {
 123         if (!events.isEmpty()) { // gesture pending
 124             int dop = mapDragOperationFromModifiers(e);
 125 
 126             if (dop == DnDConstants.ACTION_NONE) {
 127                 return;
 128             }
 129 
 130             MouseEvent trigger = (MouseEvent) events.get(0);
 131 
 132             Point      origin  = trigger.getPoint();
 133             Point      current = e.getPoint();
 134 
 135             int        dx      = Math.abs(origin.x - current.x);
 136             int        dy      = Math.abs(origin.y - current.y);
 137 
 138             if (dx >= fMotionThreshold || dy >= fMotionThreshold) {
 139                 fireDragGestureRecognized(dop, ((MouseEvent)getTriggerEvent()).getPoint());
 140             } else {
 141                 appendEvent(e);
 142             }
 143         }
 144     }
 145 
 146     // Invoked when the mouse button has been moved on a component (with no buttons no down):
 147     public void mouseMoved(MouseEvent e) {
 148         // do nothing
 149     }
 150 }