blob: 975d710264d2746fe3185bab596de715ec45fd36 [file] [log] [blame]
/*
* Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt.X11;
import java.awt.Component;
import java.awt.peer.ComponentPeer;
import java.io.IOException;
import java.util.Iterator;
import sun.util.logging.PlatformLogger;
import sun.awt.AppContext;
import sun.awt.SunToolkit;
import sun.awt.dnd.SunDropTargetContextPeer;
import sun.awt.dnd.SunDropTargetEvent;
import sun.misc.Unsafe;
/**
* The XDropTargetContextPeer is the class responsible for handling
* the interaction between the XDnD/Motif DnD subsystem and Java drop targets.
*
* @since 1.5
*/
final class XDropTargetContextPeer extends SunDropTargetContextPeer {
private static final PlatformLogger logger =
PlatformLogger.getLogger("sun.awt.X11.xembed.xdnd.XDropTargetContextPeer");
private static final Unsafe unsafe = XlibWrapper.unsafe;
/*
* A key to store a peer instance for an AppContext.
*/
private static final Object DTCP_KEY = "DropTargetContextPeer";
private XDropTargetContextPeer() {}
static XDropTargetContextPeer getPeer(AppContext appContext) {
synchronized (_globalLock) {
XDropTargetContextPeer peer =
(XDropTargetContextPeer)appContext.get(DTCP_KEY);
if (peer == null) {
peer = new XDropTargetContextPeer();
appContext.put(DTCP_KEY, peer);
}
return peer;
}
}
static XDropTargetProtocolListener getXDropTargetProtocolListener() {
return XDropTargetProtocolListenerImpl.getInstance();
}
/*
* @param returnValue the drop action selected by the Java drop target.
*/
protected void eventProcessed(SunDropTargetEvent e, int returnValue,
boolean dispatcherDone) {
/* The native context is the pointer to the XClientMessageEvent
structure. */
long ctxt = getNativeDragContext();
/* If the event was not consumed, send a response to the source. */
try {
if (ctxt != 0 && !e.isConsumed()) {
Iterator dropTargetProtocols =
XDragAndDropProtocols.getDropTargetProtocols();
while (dropTargetProtocols.hasNext()) {
XDropTargetProtocol dropTargetProtocol =
(XDropTargetProtocol)dropTargetProtocols.next();
if (dropTargetProtocol.sendResponse(ctxt, e.getID(),
returnValue)) {
break;
}
}
}
} finally {
if (dispatcherDone && ctxt != 0) {
unsafe.freeMemory(ctxt);
}
}
}
protected void doDropDone(boolean success, int dropAction,
boolean isLocal) {
/* The native context is the pointer to the XClientMessageEvent
structure. */
long ctxt = getNativeDragContext();
if (ctxt != 0) {
try {
Iterator dropTargetProtocols =
XDragAndDropProtocols.getDropTargetProtocols();
while (dropTargetProtocols.hasNext()) {
XDropTargetProtocol dropTargetProtocol =
(XDropTargetProtocol)dropTargetProtocols.next();
if (dropTargetProtocol.sendDropDone(ctxt, success,
dropAction)) {
break;
}
}
} finally {
unsafe.freeMemory(ctxt);
}
}
}
protected Object getNativeData(long format)
throws IOException {
/* The native context is the pointer to the XClientMessageEvent
structure. */
long ctxt = getNativeDragContext();
if (ctxt != 0) {
Iterator dropTargetProtocols =
XDragAndDropProtocols.getDropTargetProtocols();
while (dropTargetProtocols.hasNext()) {
XDropTargetProtocol dropTargetProtocol =
(XDropTargetProtocol)dropTargetProtocols.next();
// getData throws IAE if ctxt is not for this protocol.
try {
return dropTargetProtocol.getData(ctxt, format);
} catch (IllegalArgumentException iae) {
}
}
}
return null;
}
private void cleanup() {
}
protected void processEnterMessage(SunDropTargetEvent event) {
if (!processSunDropTargetEvent(event)) {
super.processEnterMessage(event);
}
}
protected void processExitMessage(SunDropTargetEvent event) {
if (!processSunDropTargetEvent(event)) {
super.processExitMessage(event);
}
}
protected void processMotionMessage(SunDropTargetEvent event,
boolean operationChanged) {
if (!processSunDropTargetEvent(event)) {
super.processMotionMessage(event, operationChanged);
}
}
protected void processDropMessage(SunDropTargetEvent event) {
if (!processSunDropTargetEvent(event)) {
super.processDropMessage(event);
}
}
// If source is an XEmbedCanvasPeer, passes the event to it for processing and
// return true if the event is forwarded to the XEmbed child.
// Otherwise, does nothing and return false.
private boolean processSunDropTargetEvent(SunDropTargetEvent event) {
Object source = event.getSource();
if (source instanceof Component) {
ComponentPeer peer = ((Component)source).getPeer();
if (peer instanceof XEmbedCanvasPeer) {
XEmbedCanvasPeer xEmbedCanvasPeer = (XEmbedCanvasPeer)peer;
/* The native context is the pointer to the XClientMessageEvent
structure. */
long ctxt = getNativeDragContext();
if (logger.isLoggable(PlatformLogger.FINER)) {
logger.finer(" processing " + event + " ctxt=" + ctxt +
" consumed=" + event.isConsumed());
}
/* If the event is not consumed, pass it to the
XEmbedCanvasPeer for processing. */
if (!event.isConsumed()) {
// NOTE: ctxt can be zero at this point.
if (xEmbedCanvasPeer.processXEmbedDnDEvent(ctxt,
event.getID())) {
event.consume();
return true;
}
}
}
}
return false;
}
public void forwardEventToEmbedded(long embedded, long ctxt,
int eventID) {
Iterator dropTargetProtocols =
XDragAndDropProtocols.getDropTargetProtocols();
while (dropTargetProtocols.hasNext()) {
XDropTargetProtocol dropTargetProtocol =
(XDropTargetProtocol)dropTargetProtocols.next();
if (dropTargetProtocol.forwardEventToEmbedded(embedded, ctxt,
eventID)) {
break;
}
}
}
static final class XDropTargetProtocolListenerImpl
implements XDropTargetProtocolListener {
private final static XDropTargetProtocolListener theInstance =
new XDropTargetProtocolListenerImpl();
private XDropTargetProtocolListenerImpl() {}
static XDropTargetProtocolListener getInstance() {
return theInstance;
}
public void handleDropTargetNotification(XWindow xwindow, int x, int y,
int dropAction, int actions,
long[] formats, long nativeCtxt,
int eventID) {
Object target = xwindow.getTarget();
// The Every component is associated with some AppContext.
assert target instanceof Component;
Component component = (Component)target;
AppContext appContext = SunToolkit.targetToAppContext(target);
// Every component is associated with some AppContext.
assert appContext != null;
XDropTargetContextPeer peer = XDropTargetContextPeer.getPeer(appContext);
peer.postDropTargetEvent(component, x, y, dropAction, actions, formats,
nativeCtxt, eventID,
!SunDropTargetContextPeer.DISPATCH_SYNC);
}
}
}