001: /*
002: * Copyright 2003-2004 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package sun.awt.X11;
027:
028: import java.awt.Component;
029: import java.awt.peer.ComponentPeer;
030:
031: import java.io.IOException;
032:
033: import java.util.Iterator;
034: import java.util.logging.*;
035:
036: import sun.awt.AppContext;
037: import sun.awt.SunToolkit;
038:
039: import sun.awt.dnd.SunDropTargetContextPeer;
040: import sun.awt.dnd.SunDropTargetEvent;
041:
042: import sun.misc.Unsafe;
043:
044: /**
045: * The XDropTargetContextPeer is the class responsible for handling
046: * the interaction between the XDnD/Motif DnD subsystem and Java drop targets.
047: *
048: * @since 1.5
049: */
050: final class XDropTargetContextPeer extends SunDropTargetContextPeer {
051: private static final Logger logger = Logger
052: .getLogger("sun.awt.X11.xembed.xdnd.XDropTargetContextPeer");
053:
054: private static final Unsafe unsafe = XlibWrapper.unsafe;
055:
056: /*
057: * A key to store a peer instance for an AppContext.
058: */
059: private static final Object DTCP_KEY = "DropTargetContextPeer";
060:
061: private XDropTargetContextPeer() {
062: }
063:
064: static XDropTargetContextPeer getPeer(AppContext appContext) {
065: synchronized (_globalLock) {
066: XDropTargetContextPeer peer = (XDropTargetContextPeer) appContext
067: .get(DTCP_KEY);
068: if (peer == null) {
069: peer = new XDropTargetContextPeer();
070: appContext.put(DTCP_KEY, peer);
071: }
072:
073: return peer;
074: }
075: }
076:
077: static XDropTargetProtocolListener getXDropTargetProtocolListener() {
078: return XDropTargetProtocolListenerImpl.getInstance();
079: }
080:
081: /*
082: * @param returnValue the drop action selected by the Java drop target.
083: */
084: protected void eventProcessed(SunDropTargetEvent e,
085: int returnValue, boolean dispatcherDone) {
086: /* The native context is the pointer to the XClientMessageEvent
087: structure. */
088: long ctxt = getNativeDragContext();
089: /* If the event was not consumed, send a response to the source. */
090: try {
091: if (ctxt != 0 && !e.isConsumed()) {
092: Iterator dropTargetProtocols = XDragAndDropProtocols
093: .getDropTargetProtocols();
094:
095: while (dropTargetProtocols.hasNext()) {
096: XDropTargetProtocol dropTargetProtocol = (XDropTargetProtocol) dropTargetProtocols
097: .next();
098: if (dropTargetProtocol.sendResponse(ctxt,
099: e.getID(), 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 = XDragAndDropProtocols
120: .getDropTargetProtocols();
121:
122: while (dropTargetProtocols.hasNext()) {
123: XDropTargetProtocol dropTargetProtocol = (XDropTargetProtocol) dropTargetProtocols
124: .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) 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 = XDragAndDropProtocols
143: .getDropTargetProtocols();
144:
145: while (dropTargetProtocols.hasNext()) {
146: XDropTargetProtocol dropTargetProtocol = (XDropTargetProtocol) dropTargetProtocols
147: .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
203: + " ctxt=" + ctxt + " consumed="
204: + 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 = XDragAndDropProtocols
225: .getDropTargetProtocols();
226:
227: while (dropTargetProtocols.hasNext()) {
228: XDropTargetProtocol dropTargetProtocol = (XDropTargetProtocol) dropTargetProtocols
229: .next();
230: if (dropTargetProtocol.forwardEventToEmbedded(embedded,
231: ctxt, eventID)) {
232: break;
233: }
234: }
235: }
236:
237: static final class XDropTargetProtocolListenerImpl implements
238: XDropTargetProtocolListener {
239:
240: private final static XDropTargetProtocolListener theInstance = new XDropTargetProtocolListenerImpl();
241:
242: private XDropTargetProtocolListenerImpl() {
243: }
244:
245: static XDropTargetProtocolListener getInstance() {
246: return theInstance;
247: }
248:
249: public void handleDropTargetNotification(XWindow xwindow,
250: int x, int y, int dropAction, int actions,
251: long[] formats, long nativeCtxt, 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
260: .targetToAppContext(target);
261:
262: // Every component is associated with some AppContext.
263: assert appContext != null;
264:
265: XDropTargetContextPeer peer = XDropTargetContextPeer
266: .getPeer(appContext);
267:
268: peer.postDropTargetEvent(component, x, y, dropAction,
269: actions, formats, nativeCtxt, eventID,
270: !SunDropTargetContextPeer.DISPATCH_SYNC);
271: }
272: }
273: }
|