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 import java.awt.*; 29 30 import sun.awt.dnd.SunDropTargetContextPeer; 31 import sun.awt.dnd.SunDropTargetEvent; 32 33 import javax.swing.*; 34 35 36 final class CDropTargetContextPeer extends SunDropTargetContextPeer { 37 38 private long fNativeDropTransfer = 0; 39 private long fNativeDataAvailable = 0; 40 private Object fNativeData = null; 41 private boolean insideTarget = true; 42 43 Object awtLockAccess = new Object(); 44 45 static CDropTargetContextPeer getDropTargetContextPeer() { 46 return new CDropTargetContextPeer(); 47 } 48 49 private CDropTargetContextPeer() { 50 super(); 51 } 52 53 // We block, waiting for an empty event to get posted (CToolkit.invokeAndWait) 54 // This is so we finish dispatching DropTarget events before we dispatch the dragDropFinished event (which is a higher priority). 55 private void flushEvents(Component c) { 56 try { 57 LWCToolkit.invokeAndWait(new Runnable() { 58 public synchronized void run() { 59 } 60 }, c); 61 } 62 catch(Exception e) { 63 e.printStackTrace(); 64 } 65 } 66 67 protected Object getNativeData(long format) { 68 long nativeDropTarget = this.getNativeDragContext(); 69 70 synchronized (awtLockAccess) { 71 fNativeDataAvailable = 0; 72 73 if (fNativeDropTransfer == 0) { 74 fNativeDropTransfer = startTransfer(nativeDropTarget, format); 75 } else { 76 addTransfer(nativeDropTarget, fNativeDropTransfer, format); 77 } 78 79 while (format != fNativeDataAvailable) { 80 try { 81 awtLockAccess.wait(); 82 } catch (Throwable e) { 83 e.printStackTrace(); 84 } 85 } 86 } 87 88 return fNativeData; 89 } 90 91 // We need to take care of dragExit message because for some reason it is not being 92 // generated for lightweight components 93 @Override 94 protected void processMotionMessage(SunDropTargetEvent event, boolean operationChanged) { 95 Component eventSource = (Component)event.getComponent(); 96 Point screenPoint = event.getPoint(); 97 SwingUtilities.convertPointToScreen(screenPoint, eventSource); 98 Rectangle screenBounds = new Rectangle(eventSource.getLocationOnScreen().x, 99 eventSource.getLocationOnScreen().y, 100 eventSource.getWidth(), eventSource.getHeight()); 101 if(insideTarget) { 102 if(!screenBounds.contains(screenPoint)) { 103 processExitMessage(event); 104 insideTarget = false; 105 return; 106 } 107 } else { 108 if(screenBounds.contains(screenPoint)) { 109 processEnterMessage(event); 110 insideTarget = true; 111 } else { 112 return; 113 } 114 } 115 super.processMotionMessage(event, operationChanged); 116 } 117 118 @Override 119 protected void processDropMessage(SunDropTargetEvent event) { 120 Component eventSource = (Component)event.getComponent(); 121 Point screenPoint = event.getPoint(); 122 SwingUtilities.convertPointToScreen(screenPoint, eventSource); 123 Rectangle screenBounds = new Rectangle(eventSource.getLocationOnScreen().x, 124 eventSource.getLocationOnScreen().y, 125 eventSource.getWidth(), eventSource.getHeight()); 126 if(screenBounds.contains(screenPoint)) { 127 super.processDropMessage(event); 128 } 129 } 130 131 @Override 132 protected int postDropTargetEvent(Component component, int x, int y, int dropAction, 133 int actions, long[] formats, long nativeCtxt, int eventID, 134 boolean dispatchType) { 135 // On MacOS X all the DnD events should be synchronous 136 return super.postDropTargetEvent(component, x, y, dropAction, actions, formats, nativeCtxt, 137 eventID, SunDropTargetContextPeer.DISPATCH_SYNC); 138 } 139 140 // Signal drop complete: 141 protected void doDropDone(boolean success, int dropAction, boolean isLocal) { 142 long nativeDropTarget = this.getNativeDragContext(); 143 144 dropDone(nativeDropTarget, fNativeDropTransfer, isLocal, success, dropAction); 145 } 146 147 // Notify transfer complete - this is an upcall from getNativeData's native calls: 148 private void newData(long format, byte[] data) { 149 fNativeDataAvailable = format; 150 fNativeData = data; 151 152 awtLockAccess.notifyAll(); 153 } 154 155 // Notify transfer failed - this is an upcall from getNativeData's native calls: 156 private void transferFailed(long format) { 157 fNativeDataAvailable = format; 158 fNativeData = null; 159 160 awtLockAccess.notifyAll(); 161 } 162 163 // Schedule a native dnd transfer: 164 private native long startTransfer(long nativeDropTarget, long format); 165 166 // Schedule a native dnd data transfer: 167 private native void addTransfer(long nativeDropTarget, long nativeDropTransfer, long format); 168 169 // Notify drop completed: 170 private native void dropDone(long nativeDropTarget, long nativeDropTransfer, boolean isLocal, boolean success, int dropAction); 171 }