1 /* 2 * Copyright (c) 2003, 2015, 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.awt.X11; 27 28 import java.awt.Component; 29 import java.awt.peer.ComponentPeer; 30 31 import java.io.IOException; 32 33 import java.util.Iterator; 34 35 import sun.awt.AWTAccessor; 36 import sun.util.logging.PlatformLogger; 37 38 import sun.awt.AppContext; 39 import sun.awt.SunToolkit; 40 41 import sun.awt.dnd.SunDropTargetContextPeer; 42 import sun.awt.dnd.SunDropTargetEvent; 43 44 import sun.misc.Unsafe; 45 46 /** 47 * The XDropTargetContextPeer is the class responsible for handling 48 * the interaction between the XDnD/Motif DnD subsystem and Java drop targets. 49 * 50 * @since 1.5 51 */ 52 final class XDropTargetContextPeer extends SunDropTargetContextPeer { 53 private static final PlatformLogger logger = 54 PlatformLogger.getLogger("sun.awt.X11.xembed.xdnd.XDropTargetContextPeer"); 55 56 private static final Unsafe unsafe = XlibWrapper.unsafe; 57 58 /* 59 * A key to store a peer instance for an AppContext. 60 */ 61 private static final Object DTCP_KEY = "DropTargetContextPeer"; 62 63 private XDropTargetContextPeer() {} 64 65 static XDropTargetContextPeer getPeer(AppContext appContext) { 66 synchronized (_globalLock) { 67 XDropTargetContextPeer peer = 68 (XDropTargetContextPeer)appContext.get(DTCP_KEY); 69 if (peer == null) { 70 peer = new XDropTargetContextPeer(); 71 appContext.put(DTCP_KEY, peer); 72 } 73 74 return peer; 75 } 76 } 77 78 static XDropTargetProtocolListener getXDropTargetProtocolListener() { 79 return XDropTargetProtocolListenerImpl.getInstance(); 80 } 81 82 /* 83 * @param returnValue the drop action selected by the Java drop target. 84 */ 85 protected void eventProcessed(SunDropTargetEvent e, int returnValue, 86 boolean dispatcherDone) { 87 /* The native context is the pointer to the XClientMessageEvent 88 structure. */ 89 long ctxt = getNativeDragContext(); 90 /* If the event was not consumed, send a response to the source. */ 91 try { 92 if (ctxt != 0 && !e.isConsumed()) { 93 Iterator<XDropTargetProtocol> dropTargetProtocols = 94 XDragAndDropProtocols.getDropTargetProtocols(); 95 96 while (dropTargetProtocols.hasNext()) { 97 XDropTargetProtocol dropTargetProtocol = 98 dropTargetProtocols.next(); 99 if (dropTargetProtocol.sendResponse(ctxt, e.getID(), 100 returnValue)) { 101 break; 102 } 103 } 104 } 105 } finally { 106 if (dispatcherDone && ctxt != 0) { 107 unsafe.freeMemory(ctxt); 108 } 109 } 110 } 111 112 protected void doDropDone(boolean success, int dropAction, 113 boolean isLocal) { 114 /* The native context is the pointer to the XClientMessageEvent 115 structure. */ 116 long ctxt = getNativeDragContext(); 117 118 if (ctxt != 0) { 119 try { 120 Iterator<XDropTargetProtocol> dropTargetProtocols = 121 XDragAndDropProtocols.getDropTargetProtocols(); 122 123 while (dropTargetProtocols.hasNext()) { 124 XDropTargetProtocol dropTargetProtocol = 125 dropTargetProtocols.next(); 126 if (dropTargetProtocol.sendDropDone(ctxt, success, 127 dropAction)) { 128 break; 129 } 130 } 131 } finally { 132 unsafe.freeMemory(ctxt); 133 } 134 } 135 } 136 137 protected Object getNativeData(long format) 138 throws IOException { 139 /* The native context is the pointer to the XClientMessageEvent 140 structure. */ 141 long ctxt = getNativeDragContext(); 142 143 if (ctxt != 0) { 144 Iterator<XDropTargetProtocol> dropTargetProtocols = 145 XDragAndDropProtocols.getDropTargetProtocols(); 146 147 while (dropTargetProtocols.hasNext()) { 148 XDropTargetProtocol dropTargetProtocol = 149 dropTargetProtocols.next(); 150 // getData throws IAE if ctxt is not for this protocol. 151 try { 152 return dropTargetProtocol.getData(ctxt, format); 153 } catch (IllegalArgumentException iae) { 154 } 155 } 156 } 157 158 return null; 159 } 160 161 private void cleanup() { 162 } 163 164 protected void processEnterMessage(SunDropTargetEvent event) { 165 if (!processSunDropTargetEvent(event)) { 166 super.processEnterMessage(event); 167 } 168 } 169 170 protected void processExitMessage(SunDropTargetEvent event) { 171 if (!processSunDropTargetEvent(event)) { 172 super.processExitMessage(event); 173 } 174 } 175 176 protected void processMotionMessage(SunDropTargetEvent event, 177 boolean operationChanged) { 178 if (!processSunDropTargetEvent(event)) { 179 super.processMotionMessage(event, operationChanged); 180 } 181 } 182 183 protected void processDropMessage(SunDropTargetEvent event) { 184 if (!processSunDropTargetEvent(event)) { 185 super.processDropMessage(event); 186 } 187 } 188 189 // If source is an XEmbedCanvasPeer, passes the event to it for processing and 190 // return true if the event is forwarded to the XEmbed child. 191 // Otherwise, does nothing and return false. 192 private boolean processSunDropTargetEvent(SunDropTargetEvent event) { 193 Object source = event.getSource(); 194 195 if (source instanceof Component) { 196 Object peer = AWTAccessor.getComponentAccessor() 197 .getPeer((Component) source); 198 if (peer instanceof XEmbedCanvasPeer) { 199 XEmbedCanvasPeer xEmbedCanvasPeer = (XEmbedCanvasPeer)peer; 200 /* The native context is the pointer to the XClientMessageEvent 201 structure. */ 202 long ctxt = getNativeDragContext(); 203 204 if (logger.isLoggable(PlatformLogger.Level.FINER)) { 205 logger.finer(" processing " + event + " ctxt=" + ctxt + 206 " consumed=" + event.isConsumed()); 207 } 208 /* If the event is not consumed, pass it to the 209 XEmbedCanvasPeer for processing. */ 210 if (!event.isConsumed()) { 211 // NOTE: ctxt can be zero at this point. 212 if (xEmbedCanvasPeer.processXEmbedDnDEvent(ctxt, 213 event.getID())) { 214 event.consume(); 215 return true; 216 } 217 } 218 } 219 } 220 221 return false; 222 } 223 224 public void forwardEventToEmbedded(long embedded, long ctxt, 225 int eventID) { 226 Iterator<XDropTargetProtocol> dropTargetProtocols = 227 XDragAndDropProtocols.getDropTargetProtocols(); 228 229 while (dropTargetProtocols.hasNext()) { 230 XDropTargetProtocol dropTargetProtocol = dropTargetProtocols.next(); 231 if (dropTargetProtocol.forwardEventToEmbedded(embedded, ctxt, 232 eventID)) { 233 break; 234 } 235 } 236 } 237 238 static final class XDropTargetProtocolListenerImpl 239 implements XDropTargetProtocolListener { 240 241 private static final XDropTargetProtocolListener theInstance = 242 new XDropTargetProtocolListenerImpl(); 243 244 private XDropTargetProtocolListenerImpl() {} 245 246 static XDropTargetProtocolListener getInstance() { 247 return theInstance; 248 } 249 250 public void handleDropTargetNotification(XWindow xwindow, int x, int y, 251 int dropAction, int actions, 252 long[] formats, long nativeCtxt, 253 int eventID) { 254 Object target = xwindow.getTarget(); 255 256 // The Every component is associated with some AppContext. 257 assert target instanceof Component; 258 259 Component component = (Component)target; 260 261 AppContext appContext = SunToolkit.targetToAppContext(target); 262 263 // Every component is associated with some AppContext. 264 assert appContext != null; 265 266 XDropTargetContextPeer peer = XDropTargetContextPeer.getPeer(appContext); 267 268 peer.postDropTargetEvent(component, x, y, dropAction, actions, formats, 269 nativeCtxt, eventID, 270 !SunDropTargetContextPeer.DISPATCH_SYNC); 271 } 272 } 273 }