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