Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/classes/sun/awt/X11/MotifDnDDragSourceProtocol.java
32288 views
/*1* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.awt.X11;2627import java.awt.datatransfer.Transferable;2829import java.awt.dnd.DnDConstants;30import java.awt.dnd.InvalidDnDOperationException;3132import java.util.Map;3334import sun.misc.Unsafe;3536/**37* XDragSourceProtocol implementation for Motif DnD protocol.38*39* @since 1.540*/41class MotifDnDDragSourceProtocol extends XDragSourceProtocol42implements XEventDispatcher {4344private static final Unsafe unsafe = XlibWrapper.unsafe;4546private long targetEnterServerTime = XConstants.CurrentTime;4748protected MotifDnDDragSourceProtocol(XDragSourceProtocolListener listener) {49super(listener);50XToolkit.addEventDispatcher(XWindow.getXAWTRootWindow().getWindow(), this);51}5253/**54* Creates an instance associated with the specified listener.55*56* @throws NullPointerException if listener is <code>null</code>.57*/58static XDragSourceProtocol createInstance(XDragSourceProtocolListener listener) {59return new MotifDnDDragSourceProtocol(listener);60}6162public String getProtocolName() {63return XDragAndDropProtocols.MotifDnD;64}6566protected void initializeDragImpl(int actions, Transferable contents,67Map formatMap, long[] formats)68throws InvalidDnDOperationException,69IllegalArgumentException, XException {7071long window = XDragSourceProtocol.getDragSourceWindow();7273/* Write the Motif DnD initiator info on the root XWindow. */74try {75int index = MotifDnDConstants.getIndexForTargetList(formats);7677MotifDnDConstants.writeDragInitiatorInfoStruct(window, index);78} catch (XException xe) {79cleanup();80throw xe;81} catch (InvalidDnDOperationException idoe) {82cleanup();83throw idoe;84}8586if (!MotifDnDConstants.MotifDnDSelection.setOwner(contents, formatMap,87formats,88XConstants.CurrentTime)) {89cleanup();90throw new InvalidDnDOperationException("Cannot acquire selection ownership");91}92}9394/**95* Processes the specified client message event.96*97* @returns true if the event was successfully processed.98*/99public boolean processClientMessage(XClientMessageEvent xclient) {100if (xclient.get_message_type() !=101MotifDnDConstants.XA_MOTIF_DRAG_AND_DROP_MESSAGE.getAtom()) {102return false;103}104105long data = xclient.get_data();106byte reason = (byte)(unsafe.getByte(data) &107MotifDnDConstants.MOTIF_MESSAGE_REASON_MASK);108byte origin = (byte)(unsafe.getByte(data) &109MotifDnDConstants.MOTIF_MESSAGE_SENDER_MASK);110byte byteOrder = unsafe.getByte(data + 1);111boolean swapNeeded = byteOrder != MotifDnDConstants.getByteOrderByte();112int action = DnDConstants.ACTION_NONE;113int x = 0;114int y = 0;115116/* Only receiver messages should be handled. */117if (origin != MotifDnDConstants.MOTIF_MESSAGE_FROM_RECEIVER) {118return false;119}120121switch (reason) {122case MotifDnDConstants.DROP_SITE_ENTER:123case MotifDnDConstants.DROP_SITE_LEAVE:124case MotifDnDConstants.DRAG_MOTION:125case MotifDnDConstants.OPERATION_CHANGED:126break;127default:128// Unknown reason.129return false;130}131132int t = unsafe.getInt(data + 4);133if (swapNeeded) {134t = MotifDnDConstants.Swapper.swap(t);135}136long time = t & 0xffffffffL;137// with correction of (32-bit unsigned to 64-bit signed) implicit conversion.138139/* Discard events from the previous receiver. */140if (targetEnterServerTime == XConstants.CurrentTime ||141time < targetEnterServerTime) {142return true;143}144145if (reason != MotifDnDConstants.DROP_SITE_LEAVE) {146short flags = unsafe.getShort(data + 2);147if (swapNeeded) {148flags = MotifDnDConstants.Swapper.swap(flags);149}150151byte status = (byte)((flags & MotifDnDConstants.MOTIF_DND_STATUS_MASK) >>152MotifDnDConstants.MOTIF_DND_STATUS_SHIFT);153byte motif_action = (byte)((flags & MotifDnDConstants.MOTIF_DND_ACTION_MASK) >>154MotifDnDConstants.MOTIF_DND_ACTION_SHIFT);155156if (status == MotifDnDConstants.MOTIF_VALID_DROP_SITE) {157action = MotifDnDConstants.getJavaActionsForMotifActions(motif_action);158} else {159action = DnDConstants.ACTION_NONE;160}161162short tx = unsafe.getShort(data + 8);163short ty = unsafe.getShort(data + 10);164if (swapNeeded) {165tx = MotifDnDConstants.Swapper.swap(tx);166ty = MotifDnDConstants.Swapper.swap(ty);167}168x = tx;169y = ty;170}171172getProtocolListener().handleDragReply(action, x, y);173174return true;175}176177public TargetWindowInfo getTargetWindowInfo(long window) {178assert XToolkit.isAWTLockHeldByCurrentThread();179180WindowPropertyGetter wpg =181new WindowPropertyGetter(window,182MotifDnDConstants.XA_MOTIF_DRAG_RECEIVER_INFO,1830, 0xFFFF, false,184XConstants.AnyPropertyType);185186try {187int status = wpg.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());188189/*190* DragICCI.h:191*192* typedef struct _xmDragReceiverInfoStruct{193* BYTE byte_order;194* BYTE protocol_version;195* BYTE drag_protocol_style;196* BYTE pad1;197* CARD32 proxy_window B32;198* CARD16 num_drop_sites B16;199* CARD16 pad2 B16;200* CARD32 heap_offset B32;201* } xmDragReceiverInfoStruct;202*/203if (status == (int)XConstants.Success && wpg.getData() != 0 &&204wpg.getActualType() != 0 && wpg.getActualFormat() == 8 &&205wpg.getNumberOfItems() >=206MotifDnDConstants.MOTIF_RECEIVER_INFO_SIZE) {207208long data = wpg.getData();209byte byteOrderByte = unsafe.getByte(data);210byte dragProtocolStyle = unsafe.getByte(data + 2);211switch (dragProtocolStyle) {212case MotifDnDConstants.MOTIF_PREFER_PREREGISTER_STYLE :213case MotifDnDConstants.MOTIF_PREFER_DYNAMIC_STYLE :214case MotifDnDConstants.MOTIF_DYNAMIC_STYLE :215case MotifDnDConstants.MOTIF_PREFER_RECEIVER_STYLE :216int proxy = unsafe.getInt(data + 4);217if (byteOrderByte != MotifDnDConstants.getByteOrderByte()) {218proxy = MotifDnDConstants.Swapper.swap(proxy);219}220221int protocolVersion = unsafe.getByte(data + 1);222223return new TargetWindowInfo(proxy, protocolVersion);224default:225// Unsupported protocol style.226return null;227}228} else {229return null;230}231} finally {232wpg.dispose();233}234}235236public void sendEnterMessage(long[] formats,237int sourceAction, int sourceActions, long time) {238assert XToolkit.isAWTLockHeldByCurrentThread();239assert getTargetWindow() != 0;240assert formats != null;241242targetEnterServerTime = time;243244XClientMessageEvent msg = new XClientMessageEvent();245try {246msg.set_type(XConstants.ClientMessage);247msg.set_window(getTargetWindow());248msg.set_format(8);249msg.set_message_type(MotifDnDConstants.XA_MOTIF_DRAG_AND_DROP_MESSAGE.getAtom());250251long data = msg.get_data();252int flags =253(MotifDnDConstants.getMotifActionsForJavaActions(sourceAction) <<254MotifDnDConstants.MOTIF_DND_ACTION_SHIFT) |255(MotifDnDConstants.getMotifActionsForJavaActions(sourceActions) <<256MotifDnDConstants.MOTIF_DND_ACTIONS_SHIFT);257258unsafe.putByte(data,259(byte)(MotifDnDConstants.TOP_LEVEL_ENTER |260MotifDnDConstants.MOTIF_MESSAGE_FROM_INITIATOR));261unsafe.putByte(data + 1,262MotifDnDConstants.getByteOrderByte());263unsafe.putShort(data + 2, (short)flags);264unsafe.putInt(data + 4, (int)time);265unsafe.putInt(data + 8, (int)XDragSourceProtocol.getDragSourceWindow());266unsafe.putInt(data + 12, (int)MotifDnDConstants.XA_MOTIF_ATOM_0.getAtom());267268XlibWrapper.XSendEvent(XToolkit.getDisplay(),269getTargetProxyWindow(),270false, XConstants.NoEventMask,271msg.pData);272} finally {273msg.dispose();274}275}276277public void sendMoveMessage(int xRoot, int yRoot,278int sourceAction, int sourceActions, long time) {279assert XToolkit.isAWTLockHeldByCurrentThread();280assert getTargetWindow() != 0;281282XClientMessageEvent msg = new XClientMessageEvent();283try {284msg.set_type(XConstants.ClientMessage);285msg.set_window(getTargetWindow());286msg.set_format(8);287msg.set_message_type(MotifDnDConstants.XA_MOTIF_DRAG_AND_DROP_MESSAGE.getAtom());288289long data = msg.get_data();290int flags =291(MotifDnDConstants.getMotifActionsForJavaActions(sourceAction) <<292MotifDnDConstants.MOTIF_DND_ACTION_SHIFT) |293(MotifDnDConstants.getMotifActionsForJavaActions(sourceActions) <<294MotifDnDConstants.MOTIF_DND_ACTIONS_SHIFT);295296unsafe.putByte(data,297(byte)(MotifDnDConstants.DRAG_MOTION |298MotifDnDConstants.MOTIF_MESSAGE_FROM_INITIATOR));299unsafe.putByte(data + 1,300MotifDnDConstants.getByteOrderByte());301unsafe.putShort(data + 2, (short)flags);302unsafe.putInt(data + 4, (int)time);303unsafe.putShort(data + 8, (short)xRoot);304unsafe.putShort(data + 10, (short)yRoot);305306XlibWrapper.XSendEvent(XToolkit.getDisplay(),307getTargetProxyWindow(),308false, XConstants.NoEventMask,309msg.pData);310} finally {311msg.dispose();312}313}314315public void sendLeaveMessage(long time) {316assert XToolkit.isAWTLockHeldByCurrentThread();317assert getTargetWindow() != 0;318319XClientMessageEvent msg = new XClientMessageEvent();320try {321msg.set_type(XConstants.ClientMessage);322msg.set_window(getTargetWindow());323msg.set_format(8);324msg.set_message_type(MotifDnDConstants.XA_MOTIF_DRAG_AND_DROP_MESSAGE.getAtom());325326long data = msg.get_data();327328unsafe.putByte(data,329(byte)(MotifDnDConstants.TOP_LEVEL_LEAVE |330MotifDnDConstants.MOTIF_MESSAGE_FROM_INITIATOR));331unsafe.putByte(data + 1,332MotifDnDConstants.getByteOrderByte());333unsafe.putShort(data + 2, (short)0);334unsafe.putInt(data + 4, (int)time);335unsafe.putInt(data + 8, (int)XDragSourceProtocol.getDragSourceWindow());336337XlibWrapper.XSendEvent(XToolkit.getDisplay(),338getTargetProxyWindow(),339false, XConstants.NoEventMask,340msg.pData);341} finally {342msg.dispose();343}344}345346protected void sendDropMessage(int xRoot, int yRoot,347int sourceAction, int sourceActions,348long time) {349assert XToolkit.isAWTLockHeldByCurrentThread();350assert getTargetWindow() != 0;351352/*353* Motif drop sites expect TOP_LEVEL_LEAVE before DROP_START.354*/355sendLeaveMessage(time);356357XClientMessageEvent msg = new XClientMessageEvent();358try {359msg.set_type(XConstants.ClientMessage);360msg.set_window(getTargetWindow());361msg.set_format(8);362msg.set_message_type(MotifDnDConstants.XA_MOTIF_DRAG_AND_DROP_MESSAGE.getAtom());363364long data = msg.get_data();365int flags =366(MotifDnDConstants.getMotifActionsForJavaActions(sourceAction) <<367MotifDnDConstants.MOTIF_DND_ACTION_SHIFT) |368(MotifDnDConstants.getMotifActionsForJavaActions(sourceActions) <<369MotifDnDConstants.MOTIF_DND_ACTIONS_SHIFT);370371unsafe.putByte(data,372(byte)(MotifDnDConstants.DROP_START |373MotifDnDConstants.MOTIF_MESSAGE_FROM_INITIATOR));374unsafe.putByte(data + 1,375MotifDnDConstants.getByteOrderByte());376unsafe.putShort(data + 2, (short)flags);377unsafe.putInt(data + 4, (int)time);378unsafe.putShort(data + 8, (short)xRoot);379unsafe.putShort(data + 10, (short)yRoot);380unsafe.putInt(data + 12, (int)MotifDnDConstants.XA_MOTIF_ATOM_0.getAtom());381unsafe.putInt(data + 16, (int)XDragSourceProtocol.getDragSourceWindow());382383XlibWrapper.XSendEvent(XToolkit.getDisplay(),384getTargetProxyWindow(),385false, XConstants.NoEventMask,386msg.pData);387} finally {388msg.dispose();389}390}391392public boolean processProxyModeEvent(XClientMessageEvent xclient,393long sourceWindow) {394// Motif DnD for XEmbed is not implemented.395return false;396}397398public void cleanupTargetInfo() {399super.cleanupTargetInfo();400targetEnterServerTime = XConstants.CurrentTime;401}402403public void dispatchEvent(XEvent ev) {404switch (ev.get_type()) {405case XConstants.SelectionRequest:406XSelectionRequestEvent xsre = ev.get_xselectionrequest();407long atom = xsre.get_selection();408409if (atom == MotifDnDConstants.XA_MOTIF_ATOM_0.getAtom()) {410long target = xsre.get_target();411if (target == MotifDnDConstants.XA_XmTRANSFER_SUCCESS.getAtom()) {412getProtocolListener().handleDragFinished(true);413} else if (target == MotifDnDConstants.XA_XmTRANSFER_FAILURE.getAtom()) {414getProtocolListener().handleDragFinished(false);415}416}417break;418}419}420}421422423