Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/classes/sun/awt/X11/XDnDDropTargetProtocol.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.Point;2829import java.awt.dnd.DnDConstants;3031import java.awt.event.MouseEvent;3233import java.io.IOException;3435import sun.util.logging.PlatformLogger;3637import sun.misc.Unsafe;3839/**40* XDropTargetProtocol implementation for XDnD protocol.41*42* @since 1.543*/44class XDnDDropTargetProtocol extends XDropTargetProtocol {45private static final PlatformLogger logger =46PlatformLogger.getLogger("sun.awt.X11.xembed.xdnd.XDnDDropTargetProtocol");4748private static final Unsafe unsafe = XlibWrapper.unsafe;4950private long sourceWindow = 0;51private long sourceWindowMask = 0;52private int sourceProtocolVersion = 0;53private int sourceActions = DnDConstants.ACTION_NONE;54private long[] sourceFormats = null;55private boolean trackSourceActions = false;56private int userAction = DnDConstants.ACTION_NONE;57private int sourceX = 0;58private int sourceY = 0;59private XWindow targetXWindow = null;6061// XEmbed stuff.62private long prevCtxt = 0;63private boolean overXEmbedClient = false;6465protected XDnDDropTargetProtocol(XDropTargetProtocolListener listener) {66super(listener);67}6869/**70* Creates an instance associated with the specified listener.71*72* @throws NullPointerException if listener is <code>null</code>.73*/74static XDropTargetProtocol createInstance(XDropTargetProtocolListener listener) {75return new XDnDDropTargetProtocol(listener);76}7778public String getProtocolName() {79return XDragAndDropProtocols.XDnD;80}8182public void registerDropTarget(long window) {83assert XToolkit.isAWTLockHeldByCurrentThread();8485long data = Native.allocateLongArray(1);8687try {88Native.putLong(data, 0, XDnDConstants.XDND_PROTOCOL_VERSION);8990XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());91XDnDConstants.XA_XdndAware.setAtomData(window, XAtom.XA_ATOM, data, 1);92XErrorHandlerUtil.RESTORE_XERROR_HANDLER();9394if ((XErrorHandlerUtil.saved_error != null) &&95(XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {96throw new XException("Cannot write XdndAware property");97}98} finally {99unsafe.freeMemory(data);100data = 0;101}102}103104public void unregisterDropTarget(long window) {105assert XToolkit.isAWTLockHeldByCurrentThread();106107XDnDConstants.XA_XdndAware.DeleteProperty(window);108}109110public void registerEmbedderDropSite(long embedder) {111assert XToolkit.isAWTLockHeldByCurrentThread();112113boolean overriden = false;114int version = 0;115long proxy = 0;116long newProxy = XDropTargetRegistry.getDnDProxyWindow();117int status = 0;118119WindowPropertyGetter wpg1 =120new WindowPropertyGetter(embedder, XDnDConstants.XA_XdndAware, 0, 1,121false, XConstants.AnyPropertyType);122123try {124status = wpg1.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());125126if (status == XConstants.Success &&127wpg1.getData() != 0 && wpg1.getActualType() == XAtom.XA_ATOM) {128129overriden = true;130version = (int)Native.getLong(wpg1.getData());131}132} finally {133wpg1.dispose();134}135136/* XdndProxy is not supported for prior to XDnD version 4 */137if (overriden && version >= 4) {138WindowPropertyGetter wpg2 =139new WindowPropertyGetter(embedder, XDnDConstants.XA_XdndProxy,1400, 1, false, XAtom.XA_WINDOW);141142try {143status = wpg2.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());144145if (status == XConstants.Success &&146wpg2.getData() != 0 &&147wpg2.getActualType() == XAtom.XA_WINDOW) {148149proxy = Native.getLong(wpg2.getData());150}151} finally {152wpg2.dispose();153}154155if (proxy != 0) {156WindowPropertyGetter wpg3 =157new WindowPropertyGetter(proxy, XDnDConstants.XA_XdndProxy,1580, 1, false, XAtom.XA_WINDOW);159160try {161status = wpg3.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());162163if (status != XConstants.Success ||164wpg3.getData() == 0 ||165wpg3.getActualType() != XAtom.XA_WINDOW ||166Native.getLong(wpg3.getData()) != proxy) {167168proxy = 0;169} else {170WindowPropertyGetter wpg4 =171new WindowPropertyGetter(proxy,172XDnDConstants.XA_XdndAware,1730, 1, false,174XConstants.AnyPropertyType);175176try {177status = wpg4.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());178179if (status != XConstants.Success ||180wpg4.getData() == 0 ||181wpg4.getActualType() != XAtom.XA_ATOM) {182183proxy = 0;184}185} finally {186wpg4.dispose();187}188}189} finally {190wpg3.dispose();191}192}193}194195if (proxy == newProxy) {196// Embedder already registered.197return;198}199200long data = Native.allocateLongArray(1);201202try {203Native.putLong(data, 0, XDnDConstants.XDND_PROTOCOL_VERSION);204205/* The proxy window must have the XdndAware set, as XDnD protocol206prescribes to check the proxy window for XdndAware. */207XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());208XDnDConstants.XA_XdndAware.setAtomData(newProxy, XAtom.XA_ATOM,209data, 1);210XErrorHandlerUtil.RESTORE_XERROR_HANDLER();211212if ((XErrorHandlerUtil.saved_error != null) &&213(XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {214throw new XException("Cannot write XdndAware property");215}216217Native.putLong(data, 0, newProxy);218219/* The proxy window must have the XdndProxy set to point to itself.*/220XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());221XDnDConstants.XA_XdndProxy.setAtomData(newProxy, XAtom.XA_WINDOW,222data, 1);223XErrorHandlerUtil.RESTORE_XERROR_HANDLER();224225if ((XErrorHandlerUtil.saved_error != null) &&226(XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {227throw new XException("Cannot write XdndProxy property");228}229230Native.putLong(data, 0, XDnDConstants.XDND_PROTOCOL_VERSION);231232XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());233XDnDConstants.XA_XdndAware.setAtomData(embedder, XAtom.XA_ATOM,234data, 1);235XErrorHandlerUtil.RESTORE_XERROR_HANDLER();236237if ((XErrorHandlerUtil.saved_error != null) &&238(XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {239throw new XException("Cannot write XdndAware property");240}241242Native.putLong(data, 0, newProxy);243244XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());245XDnDConstants.XA_XdndProxy.setAtomData(embedder, XAtom.XA_WINDOW,246data, 1);247XErrorHandlerUtil.RESTORE_XERROR_HANDLER();248249if ((XErrorHandlerUtil.saved_error != null) &&250(XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {251throw new XException("Cannot write XdndProxy property");252}253} finally {254unsafe.freeMemory(data);255data = 0;256}257258putEmbedderRegistryEntry(embedder, overriden, version, proxy);259}260261public void unregisterEmbedderDropSite(long embedder) {262assert XToolkit.isAWTLockHeldByCurrentThread();263264EmbedderRegistryEntry entry = getEmbedderRegistryEntry(embedder);265266if (entry == null) {267return;268}269270if (entry.isOverriden()) {271long data = Native.allocateLongArray(1);272273try {274Native.putLong(data, 0, entry.getVersion());275276XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());277XDnDConstants.XA_XdndAware.setAtomData(embedder, XAtom.XA_ATOM,278data, 1);279XErrorHandlerUtil.RESTORE_XERROR_HANDLER();280281if ((XErrorHandlerUtil.saved_error != null) &&282(XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {283throw new XException("Cannot write XdndAware property");284}285286Native.putLong(data, 0, (int)entry.getProxy());287288XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());289XDnDConstants.XA_XdndProxy.setAtomData(embedder, XAtom.XA_WINDOW,290data, 1);291XErrorHandlerUtil.RESTORE_XERROR_HANDLER();292293if ((XErrorHandlerUtil.saved_error != null) &&294(XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {295throw new XException("Cannot write XdndProxy property");296}297} finally {298unsafe.freeMemory(data);299data = 0;300}301} else {302XDnDConstants.XA_XdndAware.DeleteProperty(embedder);303XDnDConstants.XA_XdndProxy.DeleteProperty(embedder);304}305}306307/*308* Gets and stores in the registry the embedder's XDnD drop site info309* from the embedded.310*/311public void registerEmbeddedDropSite(long embedded) {312assert XToolkit.isAWTLockHeldByCurrentThread();313314boolean overriden = false;315int version = 0;316long proxy = 0;317long newProxy = XDropTargetRegistry.getDnDProxyWindow();318int status = 0;319320WindowPropertyGetter wpg1 =321new WindowPropertyGetter(embedded, XDnDConstants.XA_XdndAware, 0, 1,322false, XConstants.AnyPropertyType);323324try {325status = wpg1.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());326327if (status == XConstants.Success &&328wpg1.getData() != 0 && wpg1.getActualType() == XAtom.XA_ATOM) {329330overriden = true;331version = (int)Native.getLong(wpg1.getData());332}333} finally {334wpg1.dispose();335}336337/* XdndProxy is not supported for prior to XDnD version 4 */338if (overriden && version >= 4) {339WindowPropertyGetter wpg2 =340new WindowPropertyGetter(embedded, XDnDConstants.XA_XdndProxy,3410, 1, false, XAtom.XA_WINDOW);342343try {344status = wpg2.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());345346if (status == XConstants.Success &&347wpg2.getData() != 0 &&348wpg2.getActualType() == XAtom.XA_WINDOW) {349350proxy = Native.getLong(wpg2.getData());351}352} finally {353wpg2.dispose();354}355356if (proxy != 0) {357WindowPropertyGetter wpg3 =358new WindowPropertyGetter(proxy, XDnDConstants.XA_XdndProxy,3590, 1, false, XAtom.XA_WINDOW);360361try {362status = wpg3.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());363364if (status != XConstants.Success ||365wpg3.getData() == 0 ||366wpg3.getActualType() != XAtom.XA_WINDOW ||367Native.getLong(wpg3.getData()) != proxy) {368369proxy = 0;370} else {371WindowPropertyGetter wpg4 =372new WindowPropertyGetter(proxy,373XDnDConstants.XA_XdndAware,3740, 1, false,375XConstants.AnyPropertyType);376377try {378status = wpg4.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());379380if (status != XConstants.Success ||381wpg4.getData() == 0 ||382wpg4.getActualType() != XAtom.XA_ATOM) {383384proxy = 0;385}386} finally {387wpg4.dispose();388}389}390} finally {391wpg3.dispose();392}393}394}395396putEmbedderRegistryEntry(embedded, overriden, version, proxy);397}398399public boolean isProtocolSupported(long window) {400assert XToolkit.isAWTLockHeldByCurrentThread();401402WindowPropertyGetter wpg1 =403new WindowPropertyGetter(window, XDnDConstants.XA_XdndAware, 0, 1,404false, XConstants.AnyPropertyType);405406try {407int status = wpg1.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());408409if (status == XConstants.Success &&410wpg1.getData() != 0 && wpg1.getActualType() == XAtom.XA_ATOM) {411412return true;413} else {414return false;415}416} finally {417wpg1.dispose();418}419}420421private boolean processXdndEnter(XClientMessageEvent xclient) {422long source_win = 0;423long source_win_mask = 0;424int protocol_version = 0;425int actions = DnDConstants.ACTION_NONE;426boolean track = true;427long[] formats = null;428429if (getSourceWindow() != 0) {430return false;431}432433if (!(XToolkit.windowToXWindow(xclient.get_window()) instanceof XWindow)434&& getEmbedderRegistryEntry(xclient.get_window()) == null) {435return false;436}437438if (xclient.get_message_type() != XDnDConstants.XA_XdndEnter.getAtom()){439return false;440}441442protocol_version =443(int)((xclient.get_data(1) & XDnDConstants.XDND_PROTOCOL_MASK) >>444XDnDConstants.XDND_PROTOCOL_SHIFT);445446/* XDnD compliance only requires supporting version 3 and up. */447if (protocol_version < XDnDConstants.XDND_MIN_PROTOCOL_VERSION) {448return false;449}450451/* Ignore the source if the protocol version is higher than we support. */452if (protocol_version > XDnDConstants.XDND_PROTOCOL_VERSION) {453return false;454}455456source_win = xclient.get_data(0);457458/* Extract the list of supported actions. */459if (protocol_version < 2) {460/* Prior to XDnD version 2 only COPY action was supported. */461actions = DnDConstants.ACTION_COPY;462} else {463WindowPropertyGetter wpg =464new WindowPropertyGetter(source_win,465XDnDConstants.XA_XdndActionList,4660, 0xFFFF, false,467XAtom.XA_ATOM);468try {469wpg.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());470471if (wpg.getActualType() == XAtom.XA_ATOM &&472wpg.getActualFormat() == 32) {473long data = wpg.getData();474475for (int i = 0; i < wpg.getNumberOfItems(); i++) {476actions |=477XDnDConstants.getJavaActionForXDnDAction(Native.getLong(data, i));478}479} else {480/*481* According to XDnD protocol, XdndActionList is optional.482* If XdndActionList is not set we try to guess which actions are483* supported.484*/485actions = DnDConstants.ACTION_COPY;486track = true;487}488} finally {489wpg.dispose();490}491}492493/* Extract the available data types. */494if ((xclient.get_data(1) & XDnDConstants.XDND_DATA_TYPES_BIT) != 0) {495WindowPropertyGetter wpg =496new WindowPropertyGetter(source_win,497XDnDConstants.XA_XdndTypeList,4980, 0xFFFF, false,499XAtom.XA_ATOM);500try {501wpg.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());502503if (wpg.getActualType() == XAtom.XA_ATOM &&504wpg.getActualFormat() == 32) {505formats = Native.toLongs(wpg.getData(),506wpg.getNumberOfItems());507} else {508formats = new long[0];509}510} finally {511wpg.dispose();512}513} else {514int countFormats = 0;515long[] formats3 = new long[3];516517for (int i = 0; i < 3; i++) {518long j;519if ((j = xclient.get_data(2 + i)) != XConstants.None) {520formats3[countFormats++] = j;521}522}523524formats = new long[countFormats];525526System.arraycopy(formats3, 0, formats, 0, countFormats);527}528529assert XToolkit.isAWTLockHeldByCurrentThread();530531/*532* Select for StructureNotifyMask to receive DestroyNotify in case of source533* crash.534*/535XWindowAttributes wattr = new XWindowAttributes();536try {537XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());538int status = XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(),539source_win, wattr.pData);540541XErrorHandlerUtil.RESTORE_XERROR_HANDLER();542543if ((status == 0) ||544((XErrorHandlerUtil.saved_error != null) &&545(XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success))) {546throw new XException("XGetWindowAttributes failed");547}548549source_win_mask = wattr.get_your_event_mask();550} finally {551wattr.dispose();552}553554XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());555XlibWrapper.XSelectInput(XToolkit.getDisplay(), source_win,556source_win_mask |557XConstants.StructureNotifyMask);558559XErrorHandlerUtil.RESTORE_XERROR_HANDLER();560561if ((XErrorHandlerUtil.saved_error != null) &&562(XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {563throw new XException("XSelectInput failed");564}565566sourceWindow = source_win;567sourceWindowMask = source_win_mask;568sourceProtocolVersion = protocol_version;569sourceActions = actions;570sourceFormats = formats;571trackSourceActions = track;572573return true;574}575576private boolean processXdndPosition(XClientMessageEvent xclient) {577long time_stamp = (int)XConstants.CurrentTime;578long xdnd_action = 0;579int java_action = DnDConstants.ACTION_NONE;580int x = 0;581int y = 0;582583/* Ignore XDnD messages from all other windows. */584if (sourceWindow != xclient.get_data(0)) {585return false;586}587588XWindow xwindow = null;589{590XBaseWindow xbasewindow = XToolkit.windowToXWindow(xclient.get_window());591if (xbasewindow instanceof XWindow) {592xwindow = (XWindow)xbasewindow;593}594}595596x = (int)(xclient.get_data(2) >> 16);597y = (int)(xclient.get_data(2) & 0xFFFF);598599if (xwindow == null) {600long receiver =601XDropTargetRegistry.getRegistry().getEmbeddedDropSite(602xclient.get_window(), x, y);603604if (receiver != 0) {605XBaseWindow xbasewindow = XToolkit.windowToXWindow(receiver);606if (xbasewindow instanceof XWindow) {607xwindow = (XWindow)xbasewindow;608}609}610}611612if (xwindow != null) {613/* Translate mouse position from root coordinates614to the target window coordinates. */615Point p = xwindow.toLocal(x, y);616x = p.x;617y = p.y;618}619620/* Time stamp - new in XDnD version 1. */621if (sourceProtocolVersion > 0) {622time_stamp = xclient.get_data(3);623}624625/* User action - new in XDnD version 2. */626if (sourceProtocolVersion > 1) {627xdnd_action = xclient.get_data(4);628} else {629/* The default action is XdndActionCopy */630xdnd_action = XDnDConstants.XA_XdndActionCopy.getAtom();631}632633java_action = XDnDConstants.getJavaActionForXDnDAction(xdnd_action);634635if (trackSourceActions) {636sourceActions |= java_action;637}638639if (xwindow == null) {640if (targetXWindow != null) {641notifyProtocolListener(targetXWindow, x, y,642DnDConstants.ACTION_NONE, xclient,643MouseEvent.MOUSE_EXITED);644}645} else {646int java_event_id = 0;647648if (targetXWindow == null) {649java_event_id = MouseEvent.MOUSE_ENTERED;650} else {651java_event_id = MouseEvent.MOUSE_DRAGGED;652}653654notifyProtocolListener(xwindow, x, y, java_action, xclient,655java_event_id);656}657658userAction = java_action;659sourceX = x;660sourceY = y;661targetXWindow = xwindow;662663return true;664}665666private boolean processXdndLeave(XClientMessageEvent xclient) {667/* Ignore XDnD messages from all other windows. */668if (sourceWindow != xclient.get_data(0)) {669return false;670}671672cleanup();673674return true;675}676677private boolean processXdndDrop(XClientMessageEvent xclient) {678/* Ignore XDnD messages from all other windows. */679if (sourceWindow != xclient.get_data(0)) {680return false;681}682683if (targetXWindow != null) {684notifyProtocolListener(targetXWindow, sourceX, sourceY, userAction,685xclient, MouseEvent.MOUSE_RELEASED);686}687688return true;689}690691public int getMessageType(XClientMessageEvent xclient) {692long messageType = xclient.get_message_type();693694if (messageType == XDnDConstants.XA_XdndEnter.getAtom()) {695return ENTER_MESSAGE;696} else if (messageType == XDnDConstants.XA_XdndPosition.getAtom()) {697return MOTION_MESSAGE;698} else if (messageType == XDnDConstants.XA_XdndLeave.getAtom()) {699return LEAVE_MESSAGE;700} else if (messageType == XDnDConstants.XA_XdndDrop.getAtom()) {701return DROP_MESSAGE;702} else {703return UNKNOWN_MESSAGE;704}705}706707protected boolean processClientMessageImpl(XClientMessageEvent xclient) {708long messageType = xclient.get_message_type();709710if (messageType == XDnDConstants.XA_XdndEnter.getAtom()) {711return processXdndEnter(xclient);712} else if (messageType == XDnDConstants.XA_XdndPosition.getAtom()) {713return processXdndPosition(xclient);714} else if (messageType == XDnDConstants.XA_XdndLeave.getAtom()) {715return processXdndLeave(xclient);716} else if (messageType == XDnDConstants.XA_XdndDrop.getAtom()) {717return processXdndDrop(xclient);718} else {719return false;720}721}722723protected void sendEnterMessageToToplevel(long toplevel,724XClientMessageEvent xclient) {725/* flags */726long data1 = sourceProtocolVersion << XDnDConstants.XDND_PROTOCOL_SHIFT;727if (sourceFormats != null && sourceFormats.length > 3) {728data1 |= XDnDConstants.XDND_DATA_TYPES_BIT;729}730long data2 = sourceFormats.length > 0 ? sourceFormats[0] : 0;731long data3 = sourceFormats.length > 1 ? sourceFormats[1] : 0;732long data4 = sourceFormats.length > 2 ? sourceFormats[2] : 0;733sendEnterMessageToToplevelImpl(toplevel, xclient.get_data(0),734data1, data2, data3, data4);735736}737738private void sendEnterMessageToToplevelImpl(long toplevel,739long sourceWindow,740long data1, long data2,741long data3, long data4) {742XClientMessageEvent enter = new XClientMessageEvent();743try {744enter.set_type((int)XConstants.ClientMessage);745enter.set_window(toplevel);746enter.set_format(32);747enter.set_message_type(XDnDConstants.XA_XdndEnter.getAtom());748/* XID of the source window */749enter.set_data(0, sourceWindow);750enter.set_data(1, data1);751enter.set_data(2, data2);752enter.set_data(3, data3);753enter.set_data(4, data4);754755forwardClientMessageToToplevel(toplevel, enter);756} finally {757enter.dispose();758}759}760761protected void sendLeaveMessageToToplevel(long toplevel,762XClientMessageEvent xclient) {763sendLeaveMessageToToplevelImpl(toplevel, xclient.get_data(0));764}765766protected void sendLeaveMessageToToplevelImpl(long toplevel,767long sourceWindow) {768XClientMessageEvent leave = new XClientMessageEvent();769try {770leave.set_type((int)XConstants.ClientMessage);771leave.set_window(toplevel);772leave.set_format(32);773leave.set_message_type(XDnDConstants.XA_XdndLeave.getAtom());774/* XID of the source window */775leave.set_data(0, sourceWindow);776/* flags */777leave.set_data(1, 0);778779forwardClientMessageToToplevel(toplevel, leave);780} finally {781leave.dispose();782}783}784785public boolean sendResponse(long ctxt, int eventID, int action) {786XClientMessageEvent xclient = new XClientMessageEvent(ctxt);787788if (xclient.get_message_type() !=789XDnDConstants.XA_XdndPosition.getAtom()) {790791return false;792}793794if (eventID == MouseEvent.MOUSE_EXITED) {795action = DnDConstants.ACTION_NONE;796}797798XClientMessageEvent msg = new XClientMessageEvent();799try {800msg.set_type((int)XConstants.ClientMessage);801msg.set_window(xclient.get_data(0));802msg.set_format(32);803msg.set_message_type(XDnDConstants.XA_XdndStatus.getAtom());804/* target window */805msg.set_data(0, xclient.get_window());806/* flags */807long flags = 0;808if (action != DnDConstants.ACTION_NONE) {809flags |= XDnDConstants.XDND_ACCEPT_DROP_FLAG;810}811msg.set_data(1, flags);812/* specify an empty rectangle */813msg.set_data(2, 0); /* x, y */814msg.set_data(3, 0); /* w, h */815/* action accepted by the target */816msg.set_data(4, XDnDConstants.getXDnDActionForJavaAction(action));817818XToolkit.awtLock();819try {820XlibWrapper.XSendEvent(XToolkit.getDisplay(),821xclient.get_data(0),822false, XConstants.NoEventMask,823msg.pData);824} finally {825XToolkit.awtUnlock();826}827} finally {828msg.dispose();829}830831return true;832}833834public Object getData(long ctxt, long format)835throws IllegalArgumentException, IOException {836XClientMessageEvent xclient = new XClientMessageEvent(ctxt);837long message_type = xclient.get_message_type();838long time_stamp = XConstants.CurrentTime;839840// NOTE: we assume that the source supports at least version 1, so we841// can use the time stamp842if (message_type == XDnDConstants.XA_XdndPosition.getAtom()) {843// X server time is an unsigned 32-bit number!844time_stamp = xclient.get_data(3) & 0xFFFFFFFFL;845} else if (message_type == XDnDConstants.XA_XdndDrop.getAtom()) {846// X server time is an unsigned 32-bit number!847time_stamp = xclient.get_data(2) & 0xFFFFFFFFL;848} else {849throw new IllegalArgumentException();850}851852return XDnDConstants.XDnDSelection.getData(format, time_stamp);853}854855public boolean sendDropDone(long ctxt, boolean success, int dropAction) {856XClientMessageEvent xclient = new XClientMessageEvent(ctxt);857858if (xclient.get_message_type() !=859XDnDConstants.XA_XdndDrop.getAtom()) {860return false;861}862863/*864* The XDnD protocol recommends that the target requests the special865* target DELETE in case if the drop action is XdndActionMove.866*/867if (dropAction == DnDConstants.ACTION_MOVE && success) {868869long time_stamp = xclient.get_data(2);870long xdndSelectionAtom =871XDnDConstants.XDnDSelection.getSelectionAtom().getAtom();872873XToolkit.awtLock();874try {875XlibWrapper.XConvertSelection(XToolkit.getDisplay(),876xdndSelectionAtom,877XAtom.get("DELETE").getAtom(),878XAtom.get("XAWT_SELECTION").getAtom(),879XWindow.getXAWTRootWindow().getWindow(),880time_stamp);881} finally {882XToolkit.awtUnlock();883}884}885886XClientMessageEvent msg = new XClientMessageEvent();887try {888msg.set_type((int)XConstants.ClientMessage);889msg.set_window(xclient.get_data(0));890msg.set_format(32);891msg.set_message_type(XDnDConstants.XA_XdndFinished.getAtom());892msg.set_data(0, xclient.get_window()); /* target window */893msg.set_data(1, 0); /* flags */894/* specify an empty rectangle */895msg.set_data(2, 0);896if (sourceProtocolVersion >= 5) {897if (success) {898msg.set_data(1, XDnDConstants.XDND_ACCEPT_DROP_FLAG);899}900/* action performed by the target */901msg.set_data(2, XDnDConstants.getXDnDActionForJavaAction(dropAction));902}903msg.set_data(3, 0);904msg.set_data(4, 0);905906XToolkit.awtLock();907try {908XlibWrapper.XSendEvent(XToolkit.getDisplay(),909xclient.get_data(0),910false, XConstants.NoEventMask,911msg.pData);912} finally {913XToolkit.awtUnlock();914}915} finally {916msg.dispose();917}918919/*920* Flush the buffer to guarantee that the drop completion event is sent921* to the source before the method returns.922*/923XToolkit.awtLock();924try {925XlibWrapper.XFlush(XToolkit.getDisplay());926} finally {927XToolkit.awtUnlock();928}929930/* Trick to prevent cleanup() from posting dragExit */931targetXWindow = null;932933/* Cannot do cleanup before the drop finishes as we may need934source protocol version to send drop finished message. */935cleanup();936return true;937}938939public final long getSourceWindow() {940return sourceWindow;941}942943/**944* Reset the state of the object.945*/946public void cleanup() {947// Clear the reference to this protocol.948XDropTargetEventProcessor.reset();949950if (targetXWindow != null) {951notifyProtocolListener(targetXWindow, 0, 0,952DnDConstants.ACTION_NONE, null,953MouseEvent.MOUSE_EXITED);954}955956if (sourceWindow != 0) {957XToolkit.awtLock();958try {959XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());960XlibWrapper.XSelectInput(XToolkit.getDisplay(), sourceWindow,961sourceWindowMask);962XErrorHandlerUtil.RESTORE_XERROR_HANDLER();963} finally {964XToolkit.awtUnlock();965}966}967968sourceWindow = 0;969sourceWindowMask = 0;970sourceProtocolVersion = 0;971sourceActions = DnDConstants.ACTION_NONE;972sourceFormats = null;973trackSourceActions = false;974userAction = DnDConstants.ACTION_NONE;975sourceX = 0;976sourceY = 0;977targetXWindow = null;978}979980public boolean isDragOverComponent() {981return targetXWindow != null;982}983984public void adjustEventForForwarding(XClientMessageEvent xclient,985EmbedderRegistryEntry entry) {986/* Adjust the event to match the XDnD protocol version. */987int version = entry.getVersion();988if (xclient.get_message_type() == XDnDConstants.XA_XdndEnter.getAtom()) {989int min_version = sourceProtocolVersion < version ?990sourceProtocolVersion : version;991long data1 = min_version << XDnDConstants.XDND_PROTOCOL_SHIFT;992if (sourceFormats != null && sourceFormats.length > 3) {993data1 |= XDnDConstants.XDND_DATA_TYPES_BIT;994}995if (logger.isLoggable(PlatformLogger.Level.FINEST)) {996logger.finest(" "997+ " entryVersion=" + version998+ " sourceProtocolVersion=" +999sourceProtocolVersion1000+ " sourceFormats.length=" +1001(sourceFormats != null ? sourceFormats.length : 0));1002}1003xclient.set_data(1, data1);1004}1005}10061007private void notifyProtocolListener(XWindow xwindow, int x, int y,1008int dropAction,1009XClientMessageEvent xclient,1010int eventID) {1011long nativeCtxt = 0;10121013// Make a copy of the passed XClientMessageEvent structure, since1014// the original structure can be freed before this1015// SunDropTargetEvent is dispatched.1016if (xclient != null) {1017int size = new XClientMessageEvent(nativeCtxt).getSize();10181019nativeCtxt = unsafe.allocateMemory(size + 4 * Native.getLongSize());10201021unsafe.copyMemory(xclient.pData, nativeCtxt, size);10221023long data1 = sourceProtocolVersion << XDnDConstants.XDND_PROTOCOL_SHIFT;1024if (sourceFormats != null && sourceFormats.length > 3) {1025data1 |= XDnDConstants.XDND_DATA_TYPES_BIT;1026}1027// Append information from the latest XdndEnter event.1028Native.putLong(nativeCtxt + size, data1);1029Native.putLong(nativeCtxt + size + Native.getLongSize(),1030sourceFormats.length > 0 ? sourceFormats[0] : 0);1031Native.putLong(nativeCtxt + size + 2 * Native.getLongSize(),1032sourceFormats.length > 1 ? sourceFormats[1] : 0);1033Native.putLong(nativeCtxt + size + 3 * Native.getLongSize(),1034sourceFormats.length > 2 ? sourceFormats[2] : 0);1035}10361037getProtocolListener().handleDropTargetNotification(xwindow, x, y,1038dropAction,1039sourceActions,1040sourceFormats,1041nativeCtxt,1042eventID);1043}10441045/*1046* The methods/fields defined below are executed/accessed only on1047* the toolkit thread.1048* The methods/fields defined below are executed/accessed only on the event1049* dispatch thread.1050*/10511052public boolean forwardEventToEmbedded(long embedded, long ctxt,1053int eventID) {1054if (logger.isLoggable(PlatformLogger.Level.FINEST)) {1055logger.finest(" ctxt=" + ctxt +1056" type=" + (ctxt != 0 ?1057getMessageType(new1058XClientMessageEvent(ctxt)) : 0) +1059" prevCtxt=" + prevCtxt +1060" prevType=" + (prevCtxt != 0 ?1061getMessageType(new1062XClientMessageEvent(prevCtxt)) : 0));1063}1064if ((ctxt == 0 ||1065getMessageType(new XClientMessageEvent(ctxt)) == UNKNOWN_MESSAGE) &&1066(prevCtxt == 0 ||1067getMessageType(new XClientMessageEvent(prevCtxt)) == UNKNOWN_MESSAGE)) {1068return false;1069}10701071// The size of XClientMessageEvent structure.1072int size = XClientMessageEvent.getSize();10731074if (ctxt != 0) {1075XClientMessageEvent xclient = new XClientMessageEvent(ctxt);1076if (!overXEmbedClient) {1077long data1 = Native.getLong(ctxt + size);1078long data2 = Native.getLong(ctxt + size + Native.getLongSize());1079long data3 = Native.getLong(ctxt + size + 2 * Native.getLongSize());1080long data4 = Native.getLong(ctxt + size + 3 * Native.getLongSize());10811082if (logger.isLoggable(PlatformLogger.Level.FINEST)) {1083logger.finest(" 1 "1084+ " embedded=" + embedded1085+ " source=" + xclient.get_data(0)1086+ " data1=" + data11087+ " data2=" + data21088+ " data3=" + data31089+ " data4=" + data4);1090}10911092// Copy XdndTypeList from source to proxy.1093if ((data1 & XDnDConstants.XDND_DATA_TYPES_BIT) != 0) {1094WindowPropertyGetter wpg =1095new WindowPropertyGetter(xclient.get_data(0),1096XDnDConstants.XA_XdndTypeList,10970, 0xFFFF, false,1098XAtom.XA_ATOM);1099try {1100wpg.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());11011102if (wpg.getActualType() == XAtom.XA_ATOM &&1103wpg.getActualFormat() == 32) {11041105XToolkit.awtLock();1106try {1107XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());1108XDnDConstants.XA_XdndTypeList.setAtomData(xclient.get_window(),1109XAtom.XA_ATOM,1110wpg.getData(),1111wpg.getNumberOfItems());1112XErrorHandlerUtil.RESTORE_XERROR_HANDLER();11131114if ((XErrorHandlerUtil.saved_error != null) &&1115(XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {1116if (logger.isLoggable(PlatformLogger.Level.WARNING)) {1117logger.warning("Cannot set XdndTypeList on the proxy window");1118}1119}1120} finally {1121XToolkit.awtUnlock();1122}1123} else {1124if (logger.isLoggable(PlatformLogger.Level.WARNING)) {1125logger.warning("Cannot read XdndTypeList from the source window");1126}1127}1128} finally {1129wpg.dispose();1130}1131}1132XDragSourceContextPeer.setProxyModeSourceWindow(xclient.get_data(0));11331134sendEnterMessageToToplevelImpl(embedded, xclient.get_window(),1135data1, data2, data3, data4);1136overXEmbedClient = true;1137}11381139if (logger.isLoggable(PlatformLogger.Level.FINEST)) {1140logger.finest(" 2 "1141+ " embedded=" + embedded1142+ " xclient=" + xclient);1143}11441145/* Make a copy of the original event, since we are going to modify the1146event while it still can be referenced from other Java events. */1147{1148XClientMessageEvent copy = new XClientMessageEvent();1149unsafe.copyMemory(xclient.pData, copy.pData, copy.getSize());11501151copy.set_data(0, xclient.get_window());11521153forwardClientMessageToToplevel(embedded, copy);1154}1155}11561157if (eventID == MouseEvent.MOUSE_EXITED) {1158if (overXEmbedClient) {1159if (ctxt != 0 || prevCtxt != 0) {1160// Last chance to send XdndLeave to the XEmbed client.1161XClientMessageEvent xclient = ctxt != 0 ?1162new XClientMessageEvent(ctxt) :1163new XClientMessageEvent(prevCtxt);1164sendLeaveMessageToToplevelImpl(embedded, xclient.get_window());1165}1166overXEmbedClient = false;1167// We have to clear the proxy mode source window here,1168// when the drag exits the XEmbedCanvasPeer.1169// NOTE: at this point the XEmbed client still might have some1170// drag notifications to process and it will send responses to1171// us. With the proxy mode source window cleared we won't be1172// able to forward these responses to the actual source. This is1173// not a problem if the drag operation was initiated in this1174// JVM. However, if it was initiated in another processes the1175// responses will be lost. We bear with it for now, as it seems1176// there is no other reliable point to clear.1177XDragSourceContextPeer.setProxyModeSourceWindow(0);1178}1179}11801181if (eventID == MouseEvent.MOUSE_RELEASED) {1182overXEmbedClient = false;1183cleanup();1184}11851186if (prevCtxt != 0) {1187unsafe.freeMemory(prevCtxt);1188prevCtxt = 0;1189}11901191if (ctxt != 0 && overXEmbedClient) {1192prevCtxt = unsafe.allocateMemory(size + 4 * Native.getLongSize());11931194unsafe.copyMemory(ctxt, prevCtxt, size + 4 * Native.getLongSize());1195}11961197return true;1198}11991200public boolean isXEmbedSupported() {1201return true;1202}1203}120412051206