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