--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/classes/sun/awt/X11/MotifDnDDragSourceProtocol.java Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,420 @@
+/*
+ * Copyright 2003-2007 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.awt.X11;
+
+import java.awt.datatransfer.Transferable;
+
+import java.awt.dnd.DnDConstants;
+import java.awt.dnd.InvalidDnDOperationException;
+
+import java.util.Map;
+
+import sun.misc.Unsafe;
+
+/**
+ * XDragSourceProtocol implementation for Motif DnD protocol.
+ *
+ * @since 1.5
+ */
+class MotifDnDDragSourceProtocol extends XDragSourceProtocol
+ implements XEventDispatcher {
+
+ private static final Unsafe unsafe = XlibWrapper.unsafe;
+
+ private long targetEnterServerTime = XlibWrapper.CurrentTime;
+
+ protected MotifDnDDragSourceProtocol(XDragSourceProtocolListener listener) {
+ super(listener);
+ XToolkit.addEventDispatcher(XWindow.getXAWTRootWindow().getWindow(), this);
+ }
+
+ /**
+ * Creates an instance associated with the specified listener.
+ *
+ * @throws NullPointerException if listener is <code>null</code>.
+ */
+ static XDragSourceProtocol createInstance(XDragSourceProtocolListener listener) {
+ return new MotifDnDDragSourceProtocol(listener);
+ }
+
+ public String getProtocolName() {
+ return XDragAndDropProtocols.MotifDnD;
+ }
+
+ protected void initializeDragImpl(int actions, Transferable contents,
+ Map formatMap, long[] formats)
+ throws InvalidDnDOperationException,
+ IllegalArgumentException, XException {
+
+ long window = XDragSourceProtocol.getDragSourceWindow();
+
+ /* Write the Motif DnD initiator info on the root XWindow. */
+ try {
+ int index = MotifDnDConstants.getIndexForTargetList(formats);
+
+ MotifDnDConstants.writeDragInitiatorInfoStruct(window, index);
+ } catch (XException xe) {
+ cleanup();
+ throw xe;
+ } catch (InvalidDnDOperationException idoe) {
+ cleanup();
+ throw idoe;
+ }
+
+ if (!MotifDnDConstants.MotifDnDSelection.setOwner(contents, formatMap,
+ formats,
+ XlibWrapper.CurrentTime)) {
+ cleanup();
+ throw new InvalidDnDOperationException("Cannot acquire selection ownership");
+ }
+ }
+
+ /**
+ * Processes the specified client message event.
+ *
+ * @returns true if the event was successfully processed.
+ */
+ public boolean processClientMessage(XClientMessageEvent xclient) {
+ if (xclient.get_message_type() !=
+ MotifDnDConstants.XA_MOTIF_DRAG_AND_DROP_MESSAGE.getAtom()) {
+ return false;
+ }
+
+ long data = xclient.get_data();
+ byte reason = (byte)(unsafe.getByte(data) &
+ MotifDnDConstants.MOTIF_MESSAGE_REASON_MASK);
+ byte origin = (byte)(unsafe.getByte(data) &
+ MotifDnDConstants.MOTIF_MESSAGE_SENDER_MASK);
+ byte byteOrder = unsafe.getByte(data + 1);
+ boolean swapNeeded = byteOrder != MotifDnDConstants.getByteOrderByte();
+ int action = DnDConstants.ACTION_NONE;
+ int x = 0;
+ int y = 0;
+
+ /* Only receiver messages should be handled. */
+ if (origin != MotifDnDConstants.MOTIF_MESSAGE_FROM_RECEIVER) {
+ return false;
+ }
+
+ switch (reason) {
+ case MotifDnDConstants.DROP_SITE_ENTER:
+ case MotifDnDConstants.DROP_SITE_LEAVE:
+ case MotifDnDConstants.DRAG_MOTION:
+ case MotifDnDConstants.OPERATION_CHANGED:
+ break;
+ default:
+ // Unknown reason.
+ return false;
+ }
+
+ int t = unsafe.getInt(data + 4);
+ if (swapNeeded) {
+ t = MotifDnDConstants.Swapper.swap(t);
+ }
+ long time = t;
+
+ /* Discard events from the previous receiver. */
+ if (targetEnterServerTime == XlibWrapper.CurrentTime ||
+ time < targetEnterServerTime) {
+ return true;
+ }
+
+ if (reason != MotifDnDConstants.DROP_SITE_LEAVE) {
+ short flags = unsafe.getShort(data + 2);
+ if (swapNeeded) {
+ flags = MotifDnDConstants.Swapper.swap(flags);
+ }
+
+ byte status = (byte)((flags & MotifDnDConstants.MOTIF_DND_STATUS_MASK) >>
+ MotifDnDConstants.MOTIF_DND_STATUS_SHIFT);
+ byte motif_action = (byte)((flags & MotifDnDConstants.MOTIF_DND_ACTION_MASK) >>
+ MotifDnDConstants.MOTIF_DND_ACTION_SHIFT);
+
+ if (status == MotifDnDConstants.MOTIF_VALID_DROP_SITE) {
+ action = MotifDnDConstants.getJavaActionsForMotifActions(motif_action);
+ } else {
+ action = DnDConstants.ACTION_NONE;
+ }
+
+ short tx = unsafe.getShort(data + 8);
+ short ty = unsafe.getShort(data + 10);
+ if (swapNeeded) {
+ tx = MotifDnDConstants.Swapper.swap(tx);
+ ty = MotifDnDConstants.Swapper.swap(ty);
+ }
+ x = tx;
+ y = ty;
+ }
+
+ getProtocolListener().handleDragReply(action, x, y);
+
+ return true;
+ }
+
+ public TargetWindowInfo getTargetWindowInfo(long window) {
+ assert XToolkit.isAWTLockHeldByCurrentThread();
+
+ WindowPropertyGetter wpg =
+ new WindowPropertyGetter(window,
+ MotifDnDConstants.XA_MOTIF_DRAG_RECEIVER_INFO,
+ 0, 0xFFFF, false,
+ XlibWrapper.AnyPropertyType);
+
+ try {
+ int status = wpg.execute(XToolkit.IgnoreBadWindowHandler);
+
+ /*
+ * DragICCI.h:
+ *
+ * typedef struct _xmDragReceiverInfoStruct{
+ * BYTE byte_order;
+ * BYTE protocol_version;
+ * BYTE drag_protocol_style;
+ * BYTE pad1;
+ * CARD32 proxy_window B32;
+ * CARD16 num_drop_sites B16;
+ * CARD16 pad2 B16;
+ * CARD32 heap_offset B32;
+ * } xmDragReceiverInfoStruct;
+ */
+ if (status == (int)XlibWrapper.Success && wpg.getData() != 0 &&
+ wpg.getActualType() != 0 && wpg.getActualFormat() == 8 &&
+ wpg.getNumberOfItems() >=
+ MotifDnDConstants.MOTIF_RECEIVER_INFO_SIZE) {
+
+ long data = wpg.getData();
+ byte byteOrderByte = unsafe.getByte(data);
+ byte dragProtocolStyle = unsafe.getByte(data + 2);
+ switch (dragProtocolStyle) {
+ case MotifDnDConstants.MOTIF_PREFER_PREREGISTER_STYLE :
+ case MotifDnDConstants.MOTIF_PREFER_DYNAMIC_STYLE :
+ case MotifDnDConstants.MOTIF_DYNAMIC_STYLE :
+ case MotifDnDConstants.MOTIF_PREFER_RECEIVER_STYLE :
+ int proxy = unsafe.getInt(data + 4);
+ if (byteOrderByte != MotifDnDConstants.getByteOrderByte()) {
+ proxy = MotifDnDConstants.Swapper.swap(proxy);
+ }
+
+ int protocolVersion = unsafe.getByte(data + 1);
+
+ return new TargetWindowInfo(proxy, protocolVersion);
+ default:
+ // Unsupported protocol style.
+ return null;
+ }
+ } else {
+ return null;
+ }
+ } finally {
+ wpg.dispose();
+ }
+ }
+
+ public void sendEnterMessage(long[] formats,
+ int sourceAction, int sourceActions, long time) {
+ assert XToolkit.isAWTLockHeldByCurrentThread();
+ assert getTargetWindow() != 0;
+ assert formats != null;
+
+ targetEnterServerTime = time;
+
+ XClientMessageEvent msg = new XClientMessageEvent();
+ try {
+ msg.set_type(XlibWrapper.ClientMessage);
+ msg.set_window(getTargetWindow());
+ msg.set_format(8);
+ msg.set_message_type(MotifDnDConstants.XA_MOTIF_DRAG_AND_DROP_MESSAGE.getAtom());
+
+ long data = msg.get_data();
+ int flags =
+ (MotifDnDConstants.getMotifActionsForJavaActions(sourceAction) <<
+ MotifDnDConstants.MOTIF_DND_ACTION_SHIFT) |
+ (MotifDnDConstants.getMotifActionsForJavaActions(sourceActions) <<
+ MotifDnDConstants.MOTIF_DND_ACTIONS_SHIFT);
+
+ unsafe.putByte(data,
+ (byte)(MotifDnDConstants.TOP_LEVEL_ENTER |
+ MotifDnDConstants.MOTIF_MESSAGE_FROM_INITIATOR));
+ unsafe.putByte(data + 1,
+ MotifDnDConstants.getByteOrderByte());
+ unsafe.putShort(data + 2, (short)flags);
+ unsafe.putInt(data + 4, (int)time);
+ unsafe.putInt(data + 8, (int)XDragSourceProtocol.getDragSourceWindow());
+ unsafe.putInt(data + 12, (int)MotifDnDConstants.XA_MOTIF_ATOM_0.getAtom());
+
+ XlibWrapper.XSendEvent(XToolkit.getDisplay(),
+ getTargetProxyWindow(),
+ false, XlibWrapper.NoEventMask,
+ msg.pData);
+ } finally {
+ msg.dispose();
+ }
+ }
+
+ public void sendMoveMessage(int xRoot, int yRoot,
+ int sourceAction, int sourceActions, long time) {
+ assert XToolkit.isAWTLockHeldByCurrentThread();
+ assert getTargetWindow() != 0;
+
+ XClientMessageEvent msg = new XClientMessageEvent();
+ try {
+ msg.set_type(XlibWrapper.ClientMessage);
+ msg.set_window(getTargetWindow());
+ msg.set_format(8);
+ msg.set_message_type(MotifDnDConstants.XA_MOTIF_DRAG_AND_DROP_MESSAGE.getAtom());
+
+ long data = msg.get_data();
+ int flags =
+ (MotifDnDConstants.getMotifActionsForJavaActions(sourceAction) <<
+ MotifDnDConstants.MOTIF_DND_ACTION_SHIFT) |
+ (MotifDnDConstants.getMotifActionsForJavaActions(sourceActions) <<
+ MotifDnDConstants.MOTIF_DND_ACTIONS_SHIFT);
+
+ unsafe.putByte(data,
+ (byte)(MotifDnDConstants.DRAG_MOTION |
+ MotifDnDConstants.MOTIF_MESSAGE_FROM_INITIATOR));
+ unsafe.putByte(data + 1,
+ MotifDnDConstants.getByteOrderByte());
+ unsafe.putShort(data + 2, (short)flags);
+ unsafe.putInt(data + 4, (int)time);
+ unsafe.putShort(data + 8, (short)xRoot);
+ unsafe.putShort(data + 10, (short)yRoot);
+
+ XlibWrapper.XSendEvent(XToolkit.getDisplay(),
+ getTargetProxyWindow(),
+ false, XlibWrapper.NoEventMask,
+ msg.pData);
+ } finally {
+ msg.dispose();
+ }
+ }
+
+ public void sendLeaveMessage(long time) {
+ assert XToolkit.isAWTLockHeldByCurrentThread();
+ assert getTargetWindow() != 0;
+
+ XClientMessageEvent msg = new XClientMessageEvent();
+ try {
+ msg.set_type(XlibWrapper.ClientMessage);
+ msg.set_window(getTargetWindow());
+ msg.set_format(8);
+ msg.set_message_type(MotifDnDConstants.XA_MOTIF_DRAG_AND_DROP_MESSAGE.getAtom());
+
+ long data = msg.get_data();
+
+ unsafe.putByte(data,
+ (byte)(MotifDnDConstants.TOP_LEVEL_LEAVE |
+ MotifDnDConstants.MOTIF_MESSAGE_FROM_INITIATOR));
+ unsafe.putByte(data + 1,
+ MotifDnDConstants.getByteOrderByte());
+ unsafe.putShort(data + 2, (short)0);
+ unsafe.putInt(data + 4, (int)time);
+ unsafe.putInt(data + 8, (int)XDragSourceProtocol.getDragSourceWindow());
+
+ XlibWrapper.XSendEvent(XToolkit.getDisplay(),
+ getTargetProxyWindow(),
+ false, XlibWrapper.NoEventMask,
+ msg.pData);
+ } finally {
+ msg.dispose();
+ }
+ }
+
+ protected void sendDropMessage(int xRoot, int yRoot,
+ int sourceAction, int sourceActions,
+ long time) {
+ assert XToolkit.isAWTLockHeldByCurrentThread();
+ assert getTargetWindow() != 0;
+
+ /*
+ * Motif drop sites expect TOP_LEVEL_LEAVE before DROP_START.
+ */
+ sendLeaveMessage(time);
+
+ XClientMessageEvent msg = new XClientMessageEvent();
+ try {
+ msg.set_type(XlibWrapper.ClientMessage);
+ msg.set_window(getTargetWindow());
+ msg.set_format(8);
+ msg.set_message_type(MotifDnDConstants.XA_MOTIF_DRAG_AND_DROP_MESSAGE.getAtom());
+
+ long data = msg.get_data();
+ int flags =
+ (MotifDnDConstants.getMotifActionsForJavaActions(sourceAction) <<
+ MotifDnDConstants.MOTIF_DND_ACTION_SHIFT) |
+ (MotifDnDConstants.getMotifActionsForJavaActions(sourceActions) <<
+ MotifDnDConstants.MOTIF_DND_ACTIONS_SHIFT);
+
+ unsafe.putByte(data,
+ (byte)(MotifDnDConstants.DROP_START |
+ MotifDnDConstants.MOTIF_MESSAGE_FROM_INITIATOR));
+ unsafe.putByte(data + 1,
+ MotifDnDConstants.getByteOrderByte());
+ unsafe.putShort(data + 2, (short)flags);
+ unsafe.putInt(data + 4, (int)time);
+ unsafe.putShort(data + 8, (short)xRoot);
+ unsafe.putShort(data + 10, (short)yRoot);
+ unsafe.putInt(data + 12, (int)MotifDnDConstants.XA_MOTIF_ATOM_0.getAtom());
+ unsafe.putInt(data + 16, (int)XDragSourceProtocol.getDragSourceWindow());
+
+ XlibWrapper.XSendEvent(XToolkit.getDisplay(),
+ getTargetProxyWindow(),
+ false, XlibWrapper.NoEventMask,
+ msg.pData);
+ } finally {
+ msg.dispose();
+ }
+ }
+
+ public boolean processProxyModeEvent(XClientMessageEvent xclient,
+ long sourceWindow) {
+ // Motif DnD for XEmbed is not implemented.
+ return false;
+ }
+
+ public void cleanupTargetInfo() {
+ super.cleanupTargetInfo();
+ targetEnterServerTime = XlibWrapper.CurrentTime;
+ }
+
+ public void dispatchEvent(XEvent ev) {
+ switch (ev.get_type()) {
+ case XlibWrapper.SelectionRequest:
+ XSelectionRequestEvent xsre = ev.get_xselectionrequest();
+ long atom = xsre.get_selection();
+
+ if (atom == MotifDnDConstants.XA_MOTIF_ATOM_0.getAtom()) {
+ long target = xsre.get_target();
+ if (target == MotifDnDConstants.XA_XmTRANSFER_SUCCESS.getAtom()) {
+ getProtocolListener().handleDragFinished(true);
+ } else if (target == MotifDnDConstants.XA_XmTRANSFER_FAILURE.getAtom()) {
+ getProtocolListener().handleDragFinished(false);
+ }
+ }
+ break;
+ }
+ }
+}