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 = false; 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 LWCToolkit.flushPendingEventsOnAppkit(c); 57 } 58 59 protected Object getNativeData(long format) { 60 long nativeDropTarget = this.getNativeDragContext(); 61 62 synchronized (awtLockAccess) { 63 fNativeDataAvailable = 0; 64 65 if (fNativeDropTransfer == 0) { 66 fNativeDropTransfer = startTransfer(nativeDropTarget, format); 67 } else { 68 addTransfer(nativeDropTarget, fNativeDropTransfer, format); 69 } 70 71 while (format != fNativeDataAvailable) { 72 try { 73 awtLockAccess.wait(); 74 } catch (Throwable e) { 75 e.printStackTrace(); 76 } 77 } 78 } 79 80 return fNativeData; 81 } 82 83 // We need to take care of dragExit message because for some reason it is not being 84 // generated for lightweight components 85 @Override 86 protected void processMotionMessage(SunDropTargetEvent event, boolean operationChanged) { 87 Component eventSource = (Component)event.getComponent(); 88 Point screenPoint = event.getPoint(); 89 SwingUtilities.convertPointToScreen(screenPoint, eventSource); 90 Rectangle screenBounds = new Rectangle(eventSource.getLocationOnScreen().x, 91 eventSource.getLocationOnScreen().y, 92 eventSource.getWidth(), eventSource.getHeight()); 93 if(insideTarget) { 94 if(!screenBounds.contains(screenPoint)) { 95 processExitMessage(event); 96 insideTarget = false; 97 return; 98 } 99 } else { 100 if(screenBounds.contains(screenPoint)) { 101 processEnterMessage(event); 102 insideTarget = true; 103 } else { 104 return; 105 } 106 } 107 super.processMotionMessage(event, operationChanged); 108 } 109 110 @Override 111 protected void processDropMessage(SunDropTargetEvent event) { 112 Component eventSource = (Component)event.getComponent(); 113 Point screenPoint = event.getPoint(); 114 SwingUtilities.convertPointToScreen(screenPoint, eventSource); 115 Rectangle screenBounds = new Rectangle(eventSource.getLocationOnScreen().x, 116 eventSource.getLocationOnScreen().y, 117 eventSource.getWidth(), eventSource.getHeight()); 118 if(screenBounds.contains(screenPoint)) { 119 super.processDropMessage(event); 120 } 121 } 122 123 // Signal drop complete: 124 protected void doDropDone(boolean success, int dropAction, boolean isLocal) { 125 long nativeDropTarget = this.getNativeDragContext(); 126 127 dropDone(nativeDropTarget, fNativeDropTransfer, isLocal, success, dropAction); 128 } 129 130 // Notify transfer complete - this is an upcall from getNativeData's native calls: 131 private void newData(long format, byte[] data) { 132 fNativeDataAvailable = format; 133 fNativeData = data; 134 135 awtLockAccess.notifyAll(); 136 } 137 138 // Notify transfer failed - this is an upcall from getNativeData's native calls: 139 private void transferFailed(long format) { 140 fNativeDataAvailable = format; 141 fNativeData = null; 142 143 awtLockAccess.notifyAll(); 144 } 145 146 // Schedule a native dnd transfer: 147 private native long startTransfer(long nativeDropTarget, long format); 148 149 // Schedule a native dnd data transfer: 150 private native void addTransfer(long nativeDropTarget, long nativeDropTransfer, long format); 151 152 // Notify drop completed: 153 private native void dropDone(long nativeDropTarget, long nativeDropTransfer, boolean isLocal, boolean success, int dropAction); 154 }