Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/classes/sun/awt/X11/XDnDDragSourceProtocol.java
32288 views
/*1* Copyright (c) 2003, 2013, 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.util.logging.PlatformLogger;3536import sun.misc.Unsafe;3738/**39* XDragSourceProtocol implementation for XDnD protocol.40*41* @since 1.542*/43class XDnDDragSourceProtocol extends XDragSourceProtocol {44private static final PlatformLogger logger =45PlatformLogger.getLogger("sun.awt.X11.xembed.xdnd.XDnDDragSourceProtocol");4647private static final Unsafe unsafe = XlibWrapper.unsafe;4849protected XDnDDragSourceProtocol(XDragSourceProtocolListener listener) {50super(listener);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 XDnDDragSourceProtocol(listener);60}6162public String getProtocolName() {63return XDragAndDropProtocols.XDnD;64}6566/**67* Performs protocol-specific drag initialization.68*69* @returns true if the initialized successfully.70*/71protected void initializeDragImpl(int actions, Transferable contents,72Map formatMap, long[] formats)73throws InvalidDnDOperationException,74IllegalArgumentException, XException {75assert XToolkit.isAWTLockHeldByCurrentThread();7677long window = XDragSourceProtocol.getDragSourceWindow();7879long data = Native.allocateLongArray(3);80int action_count = 0;81try {82if ((actions & DnDConstants.ACTION_COPY) != 0) {83Native.putLong(data, action_count,84XDnDConstants.XA_XdndActionCopy.getAtom());85action_count++;86}87if ((actions & DnDConstants.ACTION_MOVE) != 0) {88Native.putLong(data, action_count,89XDnDConstants.XA_XdndActionMove.getAtom());90action_count++;91}92if ((actions & DnDConstants.ACTION_LINK) != 0) {93Native.putLong(data, action_count,94XDnDConstants.XA_XdndActionLink.getAtom());95action_count++;96}9798XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());99XDnDConstants.XA_XdndActionList.setAtomData(window,100XAtom.XA_ATOM,101data, action_count);102XErrorHandlerUtil.RESTORE_XERROR_HANDLER();103104if ((XErrorHandlerUtil.saved_error) != null &&105(XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {106cleanup();107throw new XException("Cannot write XdndActionList property");108}109} finally {110unsafe.freeMemory(data);111data = 0;112}113114data = Native.allocateLongArray(formats.length);115116try {117Native.put(data, formats);118119XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());120XDnDConstants.XA_XdndTypeList.setAtomData(window,121XAtom.XA_ATOM,122data, formats.length);123XErrorHandlerUtil.RESTORE_XERROR_HANDLER();124125if ((XErrorHandlerUtil.saved_error != null) &&126(XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {127cleanup();128throw new XException("Cannot write XdndActionList property");129}130} finally {131unsafe.freeMemory(data);132data = 0;133}134135if (!XDnDConstants.XDnDSelection.setOwner(contents, formatMap, formats,136XConstants.CurrentTime)) {137cleanup();138throw new InvalidDnDOperationException("Cannot acquire selection ownership");139}140}141142private boolean processXdndStatus(XClientMessageEvent xclient) {143int action = DnDConstants.ACTION_NONE;144145/* Ignore XDnD messages from all other windows. */146if (xclient.get_data(0) != getTargetWindow()) {147return true;148}149150if ((xclient.get_data(1) & XDnDConstants.XDND_ACCEPT_DROP_FLAG) != 0) {151/* This feature is new in XDnD version 2, but we can use it as XDnD152compliance only requires supporting version 3 and up. */153action = XDnDConstants.getJavaActionForXDnDAction(xclient.get_data(4));154}155156getProtocolListener().handleDragReply(action);157158return true;159}160161private boolean processXdndFinished(XClientMessageEvent xclient) {162/* Ignore XDnD messages from all other windows. */163if (xclient.get_data(0) != getTargetWindow()) {164return true;165}166167if (getTargetProtocolVersion() >= 5) {168boolean success = (xclient.get_data(1) & XDnDConstants.XDND_ACCEPT_DROP_FLAG) != 0;169int action = XDnDConstants.getJavaActionForXDnDAction(xclient.get_data(2));170getProtocolListener().handleDragFinished(success, action);171} else {172getProtocolListener().handleDragFinished();173}174175finalizeDrop();176177return true;178}179180public boolean processClientMessage(XClientMessageEvent xclient) {181if (xclient.get_message_type() == XDnDConstants.XA_XdndStatus.getAtom()) {182return processXdndStatus(xclient);183} else if (xclient.get_message_type() == XDnDConstants.XA_XdndFinished.getAtom()) {184return processXdndFinished(xclient);185} else {186return false;187}188}189190public TargetWindowInfo getTargetWindowInfo(long window) {191assert XToolkit.isAWTLockHeldByCurrentThread();192193WindowPropertyGetter wpg1 =194new WindowPropertyGetter(window, XDnDConstants.XA_XdndAware, 0, 1,195false, XConstants.AnyPropertyType);196197int status = wpg1.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());198199if (status == XConstants.Success &&200wpg1.getData() != 0 && wpg1.getActualType() == XAtom.XA_ATOM) {201202int targetVersion = (int)Native.getLong(wpg1.getData());203204wpg1.dispose();205206if (targetVersion >= XDnDConstants.XDND_MIN_PROTOCOL_VERSION) {207long proxy = 0;208int protocolVersion =209targetVersion < XDnDConstants.XDND_PROTOCOL_VERSION ?210targetVersion : XDnDConstants.XDND_PROTOCOL_VERSION;211212WindowPropertyGetter wpg2 =213new WindowPropertyGetter(window, XDnDConstants.XA_XdndProxy,2140, 1, false, XAtom.XA_WINDOW);215216try {217status = wpg2.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());218219if (status == XConstants.Success &&220wpg2.getData() != 0 &&221wpg2.getActualType() == XAtom.XA_WINDOW) {222223proxy = Native.getLong(wpg2.getData());224}225} finally {226wpg2.dispose();227}228229if (proxy != 0) {230WindowPropertyGetter wpg3 =231new WindowPropertyGetter(proxy, XDnDConstants.XA_XdndProxy,2320, 1, false, XAtom.XA_WINDOW);233234try {235status = wpg3.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());236237if (status != XConstants.Success ||238wpg3.getData() == 0 ||239wpg3.getActualType() != XAtom.XA_WINDOW ||240Native.getLong(wpg3.getData()) != proxy) {241242proxy = 0;243} else {244WindowPropertyGetter wpg4 =245new WindowPropertyGetter(proxy,246XDnDConstants.XA_XdndAware,2470, 1, false,248XConstants.AnyPropertyType);249250try {251status = wpg4.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());252253if (status != XConstants.Success ||254wpg4.getData() == 0 ||255wpg4.getActualType() != XAtom.XA_ATOM) {256257proxy = 0;258}259} finally {260wpg4.dispose();261}262}263} finally {264wpg3.dispose();265}266}267268return new TargetWindowInfo(proxy, protocolVersion);269}270} else {271wpg1.dispose();272}273274return null;275}276277public void sendEnterMessage(long[] formats,278int sourceAction, int sourceActions, long time) {279assert XToolkit.isAWTLockHeldByCurrentThread();280assert getTargetWindow() != 0;281assert formats != null;282283XClientMessageEvent msg = new XClientMessageEvent();284try {285msg.set_type((int)XConstants.ClientMessage);286msg.set_window(getTargetWindow());287msg.set_format(32);288msg.set_message_type(XDnDConstants.XA_XdndEnter.getAtom());289msg.set_data(0, XDragSourceProtocol.getDragSourceWindow());290long data1 =291getTargetProtocolVersion() << XDnDConstants.XDND_PROTOCOL_SHIFT;292data1 |= formats.length > 3 ? XDnDConstants.XDND_DATA_TYPES_BIT : 0;293msg.set_data(1, data1);294msg.set_data(2, formats.length > 0 ? formats[0] : 0);295msg.set_data(3, formats.length > 1 ? formats[1] : 0);296msg.set_data(4, formats.length > 2 ? formats[2] : 0);297XlibWrapper.XSendEvent(XToolkit.getDisplay(),298getTargetProxyWindow(),299false, XConstants.NoEventMask,300msg.pData);301} finally {302msg.dispose();303}304}305306public void sendMoveMessage(int xRoot, int yRoot,307int sourceAction, int sourceActions, long time) {308assert XToolkit.isAWTLockHeldByCurrentThread();309assert getTargetWindow() != 0;310311XClientMessageEvent msg = new XClientMessageEvent();312try {313msg.set_type((int)XConstants.ClientMessage);314msg.set_window(getTargetWindow());315msg.set_format(32);316msg.set_message_type(XDnDConstants.XA_XdndPosition.getAtom());317msg.set_data(0, XDragSourceProtocol.getDragSourceWindow());318msg.set_data(1, 0); /* flags */319msg.set_data(2, xRoot << 16 | yRoot);320msg.set_data(3, time);321msg.set_data(4, XDnDConstants.getXDnDActionForJavaAction(sourceAction));322XlibWrapper.XSendEvent(XToolkit.getDisplay(),323getTargetProxyWindow(),324false, XConstants.NoEventMask,325msg.pData);326} finally {327msg.dispose();328}329}330331public void sendLeaveMessage(long time) {332assert XToolkit.isAWTLockHeldByCurrentThread();333assert getTargetWindow() != 0;334335XClientMessageEvent msg = new XClientMessageEvent();336try {337msg.set_type((int)XConstants.ClientMessage);338msg.set_window(getTargetWindow());339msg.set_format(32);340msg.set_message_type(XDnDConstants.XA_XdndLeave.getAtom());341msg.set_data(0, XDragSourceProtocol.getDragSourceWindow());342msg.set_data(1, 0);343msg.set_data(2, 0);344msg.set_data(3, 0);345msg.set_data(4, 0);346XlibWrapper.XSendEvent(XToolkit.getDisplay(),347getTargetProxyWindow(),348false, XConstants.NoEventMask,349msg.pData);350} finally {351msg.dispose();352}353}354355public void sendDropMessage(int xRoot, int yRoot,356int sourceAction, int sourceActions,357long time) {358assert XToolkit.isAWTLockHeldByCurrentThread();359assert getTargetWindow() != 0;360361XClientMessageEvent msg = new XClientMessageEvent();362try {363msg.set_type((int)XConstants.ClientMessage);364msg.set_window(getTargetWindow());365msg.set_format(32);366msg.set_message_type(XDnDConstants.XA_XdndDrop.getAtom());367msg.set_data(0, XDragSourceProtocol.getDragSourceWindow());368msg.set_data(1, 0); /* flags */369msg.set_data(2, time);370msg.set_data(3, 0);371msg.set_data(4, 0);372XlibWrapper.XSendEvent(XToolkit.getDisplay(),373getTargetProxyWindow(),374false, XConstants.NoEventMask,375msg.pData);376} finally {377msg.dispose();378}379}380381public boolean processProxyModeEvent(XClientMessageEvent xclient,382long sourceWindow) {383if (xclient.get_message_type() == XDnDConstants.XA_XdndStatus.getAtom() ||384xclient.get_message_type() == XDnDConstants.XA_XdndFinished.getAtom()) {385386if (xclient.get_message_type() == XDnDConstants.XA_XdndFinished.getAtom()) {387XDragSourceContextPeer.setProxyModeSourceWindow(0);388}389390// This can happen if the drag operation started in the XEmbed server.391// In this case there is no need to forward it elsewhere, we should392// process it here.393if (xclient.get_window() == sourceWindow) {394return false;395}396397if (logger.isLoggable(PlatformLogger.Level.FINEST)) {398logger.finest(" sourceWindow=" + sourceWindow +399" get_window=" + xclient.get_window() +400" xclient=" + xclient);401}402xclient.set_data(0, xclient.get_window());403xclient.set_window(sourceWindow);404405assert XToolkit.isAWTLockHeldByCurrentThread();406407XlibWrapper.XSendEvent(XToolkit.getDisplay(), sourceWindow,408false, XConstants.NoEventMask,409xclient.pData);410411return true;412}413414return false;415}416417// TODO: register this runnable with XDnDSelection.418public void run() {419// XdndSelection ownership lost.420cleanup();421}422}423424425