Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/classes/sun/awt/X11/MotifDnDDropTargetProtocol.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.misc.Unsafe;3637/**38* XDropTargetProtocol implementation for Motif DnD protocol.39*40* @since 1.541*/42class MotifDnDDropTargetProtocol extends XDropTargetProtocol {43private static final Unsafe unsafe = XlibWrapper.unsafe;4445private long sourceWindow = 0;46private long sourceWindowMask = 0;47private int sourceProtocolVersion = 0;48private int sourceActions = DnDConstants.ACTION_NONE;49private long[] sourceFormats = null;50private long sourceAtom = 0;51private int userAction = DnDConstants.ACTION_NONE;52private int sourceX = 0;53private int sourceY = 0;54private XWindow targetXWindow = null;55private boolean topLevelLeavePostponed = false;5657protected MotifDnDDropTargetProtocol(XDropTargetProtocolListener listener) {58super(listener);59}6061/**62* Creates an instance associated with the specified listener.63*64* @throws NullPointerException if listener is <code>null</code>.65*/66static XDropTargetProtocol createInstance(XDropTargetProtocolListener listener) {67return new MotifDnDDropTargetProtocol(listener);68}6970public String getProtocolName() {71return XDragAndDropProtocols.MotifDnD;72}7374public void registerDropTarget(long window) {75assert XToolkit.isAWTLockHeldByCurrentThread();7677MotifDnDConstants.writeDragReceiverInfoStruct(window);78}7980public void unregisterDropTarget(long window) {81assert XToolkit.isAWTLockHeldByCurrentThread();8283MotifDnDConstants.XA_MOTIF_ATOM_0.DeleteProperty(window);84}8586public void registerEmbedderDropSite(long embedder) {87assert XToolkit.isAWTLockHeldByCurrentThread();8889boolean overriden = false;90int version = 0;91long proxy = 0;92long newProxy = XDropTargetRegistry.getDnDProxyWindow();93int status = 0;94long data = 0;95int dataSize = MotifDnDConstants.MOTIF_RECEIVER_INFO_SIZE;9697WindowPropertyGetter wpg =98new WindowPropertyGetter(embedder,99MotifDnDConstants.XA_MOTIF_DRAG_RECEIVER_INFO,1000, 0xFFFF, false,101XConstants.AnyPropertyType);102103try {104status = wpg.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());105106/*107* DragICCI.h:108*109* typedef struct _xmDragReceiverInfoStruct{110* BYTE byte_order;111* BYTE protocol_version;112* BYTE drag_protocol_style;113* BYTE pad1;114* CARD32 proxy_window B32;115* CARD16 num_drop_sites B16;116* CARD16 pad2 B16;117* CARD32 heap_offset B32;118* } xmDragReceiverInfoStruct;119*/120if (status == (int)XConstants.Success && wpg.getData() != 0 &&121wpg.getActualType() != 0 && wpg.getActualFormat() == 8 &&122wpg.getNumberOfItems() >=123MotifDnDConstants.MOTIF_RECEIVER_INFO_SIZE) {124125overriden = true;126data = wpg.getData();127dataSize = wpg.getNumberOfItems();128129byte byteOrderByte = unsafe.getByte(data);130131{132int tproxy = unsafe.getInt(data + 4);133if (byteOrderByte != MotifDnDConstants.getByteOrderByte()) {134tproxy = MotifDnDConstants.Swapper.swap(tproxy);135}136proxy = tproxy;137}138139if (proxy == newProxy) {140// Embedder already registered.141return;142}143144{145int tproxy = (int)newProxy;146if (byteOrderByte != MotifDnDConstants.getByteOrderByte()) {147tproxy = MotifDnDConstants.Swapper.swap(tproxy);148}149unsafe.putInt(data + 4, tproxy);150}151} else {152data = unsafe.allocateMemory(dataSize);153154unsafe.putByte(data, MotifDnDConstants.getByteOrderByte()); /* byte order */155unsafe.putByte(data + 1, MotifDnDConstants.MOTIF_DND_PROTOCOL_VERSION); /* protocol version */156unsafe.putByte(data + 2, (byte)MotifDnDConstants.MOTIF_DYNAMIC_STYLE); /* protocol style */157unsafe.putByte(data + 3, (byte)0); /* pad */158unsafe.putInt(data + 4, (int)newProxy); /* proxy window */159unsafe.putShort(data + 8, (short)0); /* num_drop_sites */160unsafe.putShort(data + 10, (short)0); /* pad */161unsafe.putInt(data + 12, dataSize);162}163164XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());165XlibWrapper.XChangeProperty(XToolkit.getDisplay(), embedder,166MotifDnDConstants.XA_MOTIF_DRAG_RECEIVER_INFO.getAtom(),167MotifDnDConstants.XA_MOTIF_DRAG_RECEIVER_INFO.getAtom(),1688, XConstants.PropModeReplace,169data, dataSize);170XErrorHandlerUtil.RESTORE_XERROR_HANDLER();171172if ((XErrorHandlerUtil.saved_error != null) &&173(XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {174throw new XException("Cannot write Motif receiver info property");175}176} finally {177if (!overriden) {178unsafe.freeMemory(data);179data = 0;180}181wpg.dispose();182}183184putEmbedderRegistryEntry(embedder, overriden, version, proxy);185}186187public void unregisterEmbedderDropSite(long embedder) {188assert XToolkit.isAWTLockHeldByCurrentThread();189190EmbedderRegistryEntry entry = getEmbedderRegistryEntry(embedder);191192if (entry == null) {193return;194}195196if (entry.isOverriden()) {197int status = 0;198199WindowPropertyGetter wpg =200new WindowPropertyGetter(embedder,201MotifDnDConstants.XA_MOTIF_DRAG_RECEIVER_INFO,2020, 0xFFFF, false,203XConstants.AnyPropertyType);204205try {206status = wpg.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());207208/*209* DragICCI.h:210*211* typedef struct _xmDragReceiverInfoStruct{212* BYTE byte_order;213* BYTE protocol_version;214* BYTE drag_protocol_style;215* BYTE pad1;216* CARD32 proxy_window B32;217* CARD16 num_drop_sites B16;218* CARD16 pad2 B16;219* CARD32 heap_offset B32;220* } xmDragReceiverInfoStruct;221*/222if (status == (int)XConstants.Success && wpg.getData() != 0 &&223wpg.getActualType() != 0 && wpg.getActualFormat() == 8 &&224wpg.getNumberOfItems() >=225MotifDnDConstants.MOTIF_RECEIVER_INFO_SIZE) {226227int dataSize = MotifDnDConstants.MOTIF_RECEIVER_INFO_SIZE;228long data = wpg.getData();229byte byteOrderByte = unsafe.getByte(data);230231int tproxy = (int)entry.getProxy();232if (MotifDnDConstants.getByteOrderByte() != byteOrderByte) {233tproxy = MotifDnDConstants.Swapper.swap(tproxy);234}235236unsafe.putInt(data + 4, tproxy);237238XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());239XlibWrapper.XChangeProperty(XToolkit.getDisplay(), embedder,240MotifDnDConstants.XA_MOTIF_DRAG_RECEIVER_INFO.getAtom(),241MotifDnDConstants.XA_MOTIF_DRAG_RECEIVER_INFO.getAtom(),2428, XConstants.PropModeReplace,243data, dataSize);244XErrorHandlerUtil.RESTORE_XERROR_HANDLER();245246if ((XErrorHandlerUtil.saved_error != null) &&247(XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {248throw new XException("Cannot write Motif receiver info property");249}250}251} finally {252wpg.dispose();253}254} else {255MotifDnDConstants.XA_MOTIF_DRAG_RECEIVER_INFO.DeleteProperty(embedder);256}257}258259/*260* Gets and stores in the registry the embedder's Motif DnD drop site info261* from the embedded.262*/263public void registerEmbeddedDropSite(long embedded) {264assert XToolkit.isAWTLockHeldByCurrentThread();265266boolean overriden = false;267int version = 0;268long proxy = 0;269int status = 0;270271WindowPropertyGetter wpg =272new WindowPropertyGetter(embedded,273MotifDnDConstants.XA_MOTIF_DRAG_RECEIVER_INFO,2740, 0xFFFF, false,275XConstants.AnyPropertyType);276277try {278status = wpg.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());279280/*281* DragICCI.h:282*283* typedef struct _xmDragReceiverInfoStruct{284* BYTE byte_order;285* BYTE protocol_version;286* BYTE drag_protocol_style;287* BYTE pad1;288* CARD32 proxy_window B32;289* CARD16 num_drop_sites B16;290* CARD16 pad2 B16;291* CARD32 heap_offset B32;292* } xmDragReceiverInfoStruct;293*/294if (status == (int)XConstants.Success && wpg.getData() != 0 &&295wpg.getActualType() != 0 && wpg.getActualFormat() == 8 &&296wpg.getNumberOfItems() >=297MotifDnDConstants.MOTIF_RECEIVER_INFO_SIZE) {298299overriden = true;300long data = wpg.getData();301302byte byteOrderByte = unsafe.getByte(data);303304{305int tproxy = unsafe.getInt(data + 4);306if (byteOrderByte != MotifDnDConstants.getByteOrderByte()) {307tproxy = MotifDnDConstants.Swapper.swap(tproxy);308}309proxy = tproxy;310}311}312} finally {313wpg.dispose();314}315316putEmbedderRegistryEntry(embedded, overriden, version, proxy);317}318319public boolean isProtocolSupported(long window) {320WindowPropertyGetter wpg =321new WindowPropertyGetter(window,322MotifDnDConstants.XA_MOTIF_DRAG_RECEIVER_INFO,3230, 0xFFFF, false,324XConstants.AnyPropertyType);325326try {327int status = wpg.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());328329if (status == (int)XConstants.Success && wpg.getData() != 0 &&330wpg.getActualType() != 0 && wpg.getActualFormat() == 8 &&331wpg.getNumberOfItems() >=332MotifDnDConstants.MOTIF_RECEIVER_INFO_SIZE) {333return true;334} else {335return false;336}337} finally {338wpg.dispose();339}340}341342private boolean processTopLevelEnter(XClientMessageEvent xclient) {343assert XToolkit.isAWTLockHeldByCurrentThread();344345if (targetXWindow != null || sourceWindow != 0) {346return false;347}348349if (!(XToolkit.windowToXWindow(xclient.get_window()) instanceof XWindow)350&& getEmbedderRegistryEntry(xclient.get_window()) == null) {351return false;352}353354long source_win = 0;355long source_win_mask = 0;356int protocol_version = 0;357long property_atom = 0;358long[] formats = null;359360{361long data = xclient.get_data();362byte eventByteOrder = unsafe.getByte(data + 1);363source_win = MotifDnDConstants.Swapper.getInt(data + 8, eventByteOrder);364property_atom = MotifDnDConstants.Swapper.getInt(data + 12, eventByteOrder);365}366367/* Extract the available data types. */368{369WindowPropertyGetter wpg =370new WindowPropertyGetter(source_win,371XAtom.get(property_atom),3720, 0xFFFF,373false,374MotifDnDConstants.XA_MOTIF_DRAG_INITIATOR_INFO.getAtom());375376try {377int status = wpg.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());378379if (status == XConstants.Success && wpg.getData() != 0 &&380wpg.getActualType() ==381MotifDnDConstants.XA_MOTIF_DRAG_INITIATOR_INFO.getAtom() &&382wpg.getActualFormat() == 8 &&383wpg.getNumberOfItems() ==384MotifDnDConstants.MOTIF_INITIATOR_INFO_SIZE) {385386long data = wpg.getData();387byte propertyByteOrder = unsafe.getByte(data);388389protocol_version = unsafe.getByte(data + 1);390391if (protocol_version !=392MotifDnDConstants.MOTIF_DND_PROTOCOL_VERSION) {393return false;394}395396int index =397MotifDnDConstants.Swapper.getShort(data + 2, propertyByteOrder);398399formats = MotifDnDConstants.getTargetListForIndex(index);400} else {401formats = new long[0];402}403} finally {404wpg.dispose();405}406}407408/*409* Select for StructureNotifyMask to receive DestroyNotify in case of source410* crash.411*/412XWindowAttributes wattr = new XWindowAttributes();413try {414XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());415int status = XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(),416source_win, wattr.pData);417418XErrorHandlerUtil.RESTORE_XERROR_HANDLER();419420if ((status == 0) ||421((XErrorHandlerUtil.saved_error != null) &&422(XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success))) {423throw new XException("XGetWindowAttributes failed");424}425426source_win_mask = wattr.get_your_event_mask();427} finally {428wattr.dispose();429}430431XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());432XlibWrapper.XSelectInput(XToolkit.getDisplay(), source_win,433source_win_mask |434XConstants.StructureNotifyMask);435436XErrorHandlerUtil.RESTORE_XERROR_HANDLER();437438if ((XErrorHandlerUtil.saved_error != null) &&439(XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {440throw new XException("XSelectInput failed");441}442443sourceWindow = source_win;444sourceWindowMask = source_win_mask;445sourceProtocolVersion = protocol_version;446/*447* TOP_LEVEL_ENTER doesn't communicate the list of supported actions448* They are provided in DRAG_MOTION.449*/450sourceActions = DnDConstants.ACTION_NONE;451sourceFormats = formats;452sourceAtom = property_atom;453454return true;455}456457private boolean processDragMotion(XClientMessageEvent xclient) {458long data = xclient.get_data();459byte eventByteOrder = unsafe.getByte(data + 1);460byte eventReason = (byte)(unsafe.getByte(data) &461MotifDnDConstants.MOTIF_MESSAGE_REASON_MASK);462int x = 0;463int y = 0;464465short flags = MotifDnDConstants.Swapper.getShort(data + 2, eventByteOrder);466467int motif_action = (flags & MotifDnDConstants.MOTIF_DND_ACTION_MASK) >>468MotifDnDConstants.MOTIF_DND_ACTION_SHIFT;469int motif_actions = (flags & MotifDnDConstants.MOTIF_DND_ACTIONS_MASK) >>470MotifDnDConstants.MOTIF_DND_ACTIONS_SHIFT;471472int java_action = MotifDnDConstants.getJavaActionsForMotifActions(motif_action);473int java_actions = MotifDnDConstants.getJavaActionsForMotifActions(motif_actions);474475/* Append source window id to the event data, so that we can send the476response properly. */477{478int win = (int)sourceWindow;479if (eventByteOrder != MotifDnDConstants.getByteOrderByte()) {480win = MotifDnDConstants.Swapper.swap(win);481}482unsafe.putInt(data + 12, win);483}484485XWindow xwindow = null;486{487XBaseWindow xbasewindow = XToolkit.windowToXWindow(xclient.get_window());488if (xbasewindow instanceof XWindow) {489xwindow = (XWindow)xbasewindow;490}491}492493if (eventReason == MotifDnDConstants.OPERATION_CHANGED) {494/* OPERATION_CHANGED event doesn't provide coordinates, so we use495previously stored position and component ref. */496x = sourceX;497y = sourceY;498499if (xwindow == null) {500xwindow = targetXWindow;501}502} else {503x = MotifDnDConstants.Swapper.getShort(data + 8, eventByteOrder);504y = MotifDnDConstants.Swapper.getShort(data + 10, eventByteOrder);505506if (xwindow == null) {507long receiver =508XDropTargetRegistry.getRegistry().getEmbeddedDropSite(509xclient.get_window(), x, y);510511if (receiver != 0) {512XBaseWindow xbasewindow = XToolkit.windowToXWindow(receiver);513if (xbasewindow instanceof XWindow) {514xwindow = (XWindow)xbasewindow;515}516}517}518519if (xwindow != null) {520Point p = xwindow.toLocal(x, y);521x = p.x;522y = p.y;523}524}525526if (xwindow == null) {527if (targetXWindow != null) {528notifyProtocolListener(targetXWindow, x, y,529DnDConstants.ACTION_NONE, java_actions,530xclient, MouseEvent.MOUSE_EXITED);531}532} else {533int java_event_id = 0;534535if (targetXWindow == null) {536java_event_id = MouseEvent.MOUSE_ENTERED;537} else {538java_event_id = MouseEvent.MOUSE_DRAGGED;539}540541notifyProtocolListener(xwindow, x, y, java_action, java_actions,542xclient, java_event_id);543}544545sourceActions = java_actions;546userAction = java_action;547sourceX = x;548sourceY = y;549targetXWindow = xwindow;550551return true;552}553554private boolean processTopLevelLeave(XClientMessageEvent xclient) {555assert XToolkit.isAWTLockHeldByCurrentThread();556557long data = xclient.get_data();558byte eventByteOrder = unsafe.getByte(data + 1);559560long source_win = MotifDnDConstants.Swapper.getInt(data + 8, eventByteOrder);561562/* Ignore Motif DnD messages from all other windows. */563if (source_win != sourceWindow) {564return false;565}566567/*568* Postpone upcall to java, so that we can abort it in case569* if drop immediatelly follows (see BugTraq ID 4395290).570* Send a dummy ClientMessage event to guarantee that a postponed java571* upcall will be processed.572*/573topLevelLeavePostponed = true;574{575long proxy;576577/*578* If this is an embedded drop site, the event should go to the579* awt_root_window as this is a proxy for all embedded drop sites.580* Otherwise the event should go to the event->window, as we don't use581* proxies for normal drop sites.582*/583if (getEmbedderRegistryEntry(xclient.get_window()) != null) {584proxy = XDropTargetRegistry.getDnDProxyWindow();585} else {586proxy = xclient.get_window();587}588589XClientMessageEvent dummy = new XClientMessageEvent();590591try {592dummy.set_type(XConstants.ClientMessage);593dummy.set_window(xclient.get_window());594dummy.set_format(32);595dummy.set_message_type(0);596dummy.set_data(0, 0);597dummy.set_data(1, 0);598dummy.set_data(2, 0);599dummy.set_data(3, 0);600dummy.set_data(4, 0);601XlibWrapper.XSendEvent(XToolkit.getDisplay(),602proxy, false, XConstants.NoEventMask,603dummy.pData);604} finally {605dummy.dispose();606}607}608return true;609}610611private boolean processDropStart(XClientMessageEvent xclient) {612long data = xclient.get_data();613byte eventByteOrder = unsafe.getByte(data + 1);614615long source_win =616MotifDnDConstants.Swapper.getInt(data + 16, eventByteOrder);617618/* Ignore Motif DnD messages from all other windows. */619if (source_win != sourceWindow) {620return false;621}622623long property_atom =624MotifDnDConstants.Swapper.getInt(data + 12, eventByteOrder);625626short flags =627MotifDnDConstants.Swapper.getShort(data + 2, eventByteOrder);628629int motif_action = (flags & MotifDnDConstants.MOTIF_DND_ACTION_MASK) >>630MotifDnDConstants.MOTIF_DND_ACTION_SHIFT;631int motif_actions = (flags & MotifDnDConstants.MOTIF_DND_ACTIONS_MASK) >>632MotifDnDConstants.MOTIF_DND_ACTIONS_SHIFT;633634int java_action = MotifDnDConstants.getJavaActionsForMotifActions(motif_action);635int java_actions = MotifDnDConstants.getJavaActionsForMotifActions(motif_actions);636637int x = MotifDnDConstants.Swapper.getShort(data + 8, eventByteOrder);638int y = MotifDnDConstants.Swapper.getShort(data + 10, eventByteOrder);639640XWindow xwindow = null;641{642XBaseWindow xbasewindow = XToolkit.windowToXWindow(xclient.get_window());643if (xbasewindow instanceof XWindow) {644xwindow = (XWindow)xbasewindow;645}646}647648if (xwindow == null) {649long receiver =650XDropTargetRegistry.getRegistry().getEmbeddedDropSite(651xclient.get_window(), x, y);652653if (receiver != 0) {654XBaseWindow xbasewindow = XToolkit.windowToXWindow(receiver);655if (xbasewindow instanceof XWindow) {656xwindow = (XWindow)xbasewindow;657}658}659}660661if (xwindow != null) {662Point p = xwindow.toLocal(x, y);663x = p.x;664y = p.y;665}666667if (xwindow != null) {668notifyProtocolListener(xwindow, x, y, java_action, java_actions,669xclient, MouseEvent.MOUSE_RELEASED);670} else if (targetXWindow != null) {671notifyProtocolListener(targetXWindow, x, y,672DnDConstants.ACTION_NONE, java_actions,673xclient, MouseEvent.MOUSE_EXITED);674}675676return true;677}678679public int getMessageType(XClientMessageEvent xclient) {680if (xclient.get_message_type() !=681MotifDnDConstants.XA_MOTIF_DRAG_AND_DROP_MESSAGE.getAtom()) {682683return UNKNOWN_MESSAGE;684}685686long data = xclient.get_data();687byte reason = (byte)(unsafe.getByte(data) &688MotifDnDConstants.MOTIF_MESSAGE_REASON_MASK);689690switch (reason) {691case MotifDnDConstants.TOP_LEVEL_ENTER :692return ENTER_MESSAGE;693case MotifDnDConstants.DRAG_MOTION :694case MotifDnDConstants.OPERATION_CHANGED :695return MOTION_MESSAGE;696case MotifDnDConstants.TOP_LEVEL_LEAVE :697return LEAVE_MESSAGE;698case MotifDnDConstants.DROP_START :699return DROP_MESSAGE;700default:701return UNKNOWN_MESSAGE;702}703}704705protected boolean processClientMessageImpl(XClientMessageEvent xclient) {706if (xclient.get_message_type() !=707MotifDnDConstants.XA_MOTIF_DRAG_AND_DROP_MESSAGE.getAtom()) {708if (topLevelLeavePostponed) {709topLevelLeavePostponed = false;710cleanup();711}712713return false;714}715716long data = xclient.get_data();717byte reason = (byte)(unsafe.getByte(data) &718MotifDnDConstants.MOTIF_MESSAGE_REASON_MASK);719byte origin = (byte)(unsafe.getByte(data) &720MotifDnDConstants.MOTIF_MESSAGE_SENDER_MASK);721722if (topLevelLeavePostponed) {723topLevelLeavePostponed = false;724if (reason != MotifDnDConstants.DROP_START) {725cleanup();726}727}728729/* Only initiator messages should be handled. */730if (origin != MotifDnDConstants.MOTIF_MESSAGE_FROM_INITIATOR) {731return false;732}733734switch (reason) {735case MotifDnDConstants.TOP_LEVEL_ENTER :736return processTopLevelEnter(xclient);737case MotifDnDConstants.DRAG_MOTION :738case MotifDnDConstants.OPERATION_CHANGED :739return processDragMotion(xclient);740case MotifDnDConstants.TOP_LEVEL_LEAVE :741return processTopLevelLeave(xclient);742case MotifDnDConstants.DROP_START :743return processDropStart(xclient);744default:745return false;746}747}748749/*750* Currently we don't synthesize enter/leave messages for Motif DnD751* protocol. See comments in XDropTargetProtocol.postProcessClientMessage.752*/753protected void sendEnterMessageToToplevel(long win,754XClientMessageEvent xclient) {755throw new Error("UNIMPLEMENTED");756}757758protected void sendLeaveMessageToToplevel(long win,759XClientMessageEvent xclient) {760throw new Error("UNIMPLEMENTED");761}762763public boolean forwardEventToEmbedded(long embedded, long ctxt,764int eventID) {765// UNIMPLEMENTED.766return false;767}768769public boolean isXEmbedSupported() {770return false;771}772773public boolean sendResponse(long ctxt, int eventID, int action) {774XClientMessageEvent xclient = new XClientMessageEvent(ctxt);775if (xclient.get_message_type() !=776MotifDnDConstants.XA_MOTIF_DRAG_AND_DROP_MESSAGE.getAtom()) {777return false;778}779780long data = xclient.get_data();781byte reason = (byte)(unsafe.getByte(data) &782MotifDnDConstants.MOTIF_MESSAGE_REASON_MASK);783byte origin = (byte)(unsafe.getByte(data) &784MotifDnDConstants.MOTIF_MESSAGE_SENDER_MASK);785byte eventByteOrder = unsafe.getByte(data + 1);786byte response_reason = (byte)0;787788/* Only initiator messages should be handled. */789if (origin != MotifDnDConstants.MOTIF_MESSAGE_FROM_INITIATOR) {790return false;791}792793switch (reason) {794case MotifDnDConstants.TOP_LEVEL_ENTER:795case MotifDnDConstants.TOP_LEVEL_LEAVE:796/* Receiver shouldn't rely to these messages. */797return false;798case MotifDnDConstants.DRAG_MOTION:799switch (eventID) {800case MouseEvent.MOUSE_ENTERED:801response_reason = MotifDnDConstants.DROP_SITE_ENTER;802break;803case MouseEvent.MOUSE_DRAGGED:804response_reason = MotifDnDConstants.DRAG_MOTION;805break;806case MouseEvent.MOUSE_EXITED:807response_reason = MotifDnDConstants.DROP_SITE_LEAVE;808break;809}810break;811case MotifDnDConstants.OPERATION_CHANGED:812case MotifDnDConstants.DROP_START:813response_reason = reason;814break;815default:816// Unknown reason. Shouldn't get here.817assert false;818}819820XClientMessageEvent msg = new XClientMessageEvent();821822try {823msg.set_type(XConstants.ClientMessage);824msg.set_window(MotifDnDConstants.Swapper.getInt(data + 12, eventByteOrder));825msg.set_format(8);826msg.set_message_type(MotifDnDConstants.XA_MOTIF_DRAG_AND_DROP_MESSAGE.getAtom());827828long responseData = msg.get_data();829830unsafe.putByte(responseData, (byte)(response_reason |831MotifDnDConstants.MOTIF_MESSAGE_FROM_RECEIVER));832unsafe.putByte(responseData + 1, MotifDnDConstants.getByteOrderByte());833834int response_flags = 0;835836if (response_reason != MotifDnDConstants.DROP_SITE_LEAVE) {837short flags = MotifDnDConstants.Swapper.getShort(data + 2,838eventByteOrder);839byte dropSiteStatus = (action == DnDConstants.ACTION_NONE) ?840MotifDnDConstants.MOTIF_INVALID_DROP_SITE :841MotifDnDConstants.MOTIF_VALID_DROP_SITE;842843/* Clear action and drop site status bits. */844response_flags = flags &845~MotifDnDConstants.MOTIF_DND_ACTION_MASK &846~MotifDnDConstants.MOTIF_DND_STATUS_MASK;847/* Fill in new action and drop site status. */848response_flags |=849MotifDnDConstants.getMotifActionsForJavaActions(action) <<850MotifDnDConstants.MOTIF_DND_ACTION_SHIFT;851response_flags |=852dropSiteStatus << MotifDnDConstants.MOTIF_DND_STATUS_SHIFT;853} else {854response_flags = 0;855}856857unsafe.putShort(responseData + 2, (short)response_flags);858859/* Write time stamp. */860int time = MotifDnDConstants.Swapper.getInt(data + 4, eventByteOrder);861unsafe.putInt(responseData + 4, time);862863/* Write coordinates. */864if (response_reason != MotifDnDConstants.DROP_SITE_LEAVE) {865short x = MotifDnDConstants.Swapper.getShort(data + 8,866eventByteOrder);867short y = MotifDnDConstants.Swapper.getShort(data + 10,868eventByteOrder);869unsafe.putShort(responseData + 8, x); // x870unsafe.putShort(responseData + 10, y); // y871} else {872unsafe.putShort(responseData + 8, (short)0); // x873unsafe.putShort(responseData + 10, (short)0); // y874}875876XToolkit.awtLock();877try {878XlibWrapper.XSendEvent(XToolkit.getDisplay(),879msg.get_window(),880false, XConstants.NoEventMask,881msg.pData);882} finally {883XToolkit.awtUnlock();884}885} finally {886msg.dispose();887}888889return true;890}891892public Object getData(long ctxt, long format)893throws IllegalArgumentException, IOException {894XClientMessageEvent xclient = new XClientMessageEvent(ctxt);895896if (xclient.get_message_type() !=897MotifDnDConstants.XA_MOTIF_DRAG_AND_DROP_MESSAGE.getAtom()) {898throw new IllegalArgumentException();899}900901long data = xclient.get_data();902byte reason = (byte)(unsafe.getByte(data) &903MotifDnDConstants.MOTIF_MESSAGE_REASON_MASK);904byte origin = (byte)(unsafe.getByte(data) &905MotifDnDConstants.MOTIF_MESSAGE_SENDER_MASK);906byte eventByteOrder = unsafe.getByte(data + 1);907908if (origin != MotifDnDConstants.MOTIF_MESSAGE_FROM_INITIATOR) {909throw new IOException("Cannot get data: corrupted context");910}911912long selatom = 0;913914switch (reason) {915case MotifDnDConstants.DRAG_MOTION :916case MotifDnDConstants.OPERATION_CHANGED :917selatom = sourceAtom;918break;919case MotifDnDConstants.DROP_START :920selatom = MotifDnDConstants.Swapper.getInt(data + 12, eventByteOrder);921break;922default:923throw new IOException("Cannot get data: invalid message reason");924}925926if (selatom == 0) {927throw new IOException("Cannot get data: drag source property atom unavailable");928}929930long time_stamp = MotifDnDConstants.Swapper.getInt(data + 4, eventByteOrder) & 0xffffffffL;931// with correction of (32-bit unsigned to 64-bit signed) implicit conversion.932933XAtom selectionAtom = XAtom.get(selatom);934935XSelection selection = XSelection.getSelection(selectionAtom);936if (selection == null) {937selection = new XSelection(selectionAtom);938}939940return selection.getData(format, time_stamp);941}942943public boolean sendDropDone(long ctxt, boolean success, int dropAction) {944XClientMessageEvent xclient = new XClientMessageEvent(ctxt);945946if (xclient.get_message_type() !=947MotifDnDConstants.XA_MOTIF_DRAG_AND_DROP_MESSAGE.getAtom()) {948return false;949}950951long data = xclient.get_data();952byte reason = (byte)(unsafe.getByte(data) &953MotifDnDConstants.MOTIF_MESSAGE_REASON_MASK);954byte origin = (byte)(unsafe.getByte(data) &955MotifDnDConstants.MOTIF_MESSAGE_SENDER_MASK);956byte eventByteOrder = unsafe.getByte(data + 1);957958if (origin != MotifDnDConstants.MOTIF_MESSAGE_FROM_INITIATOR) {959return false;960}961962if (reason != MotifDnDConstants.DROP_START) {963return false;964}965966long time_stamp = MotifDnDConstants.Swapper.getInt(data + 4, eventByteOrder) & 0xffffffffL;967// with correction of (32-bit unsigned to 64-bit signed) implicit conversion.968969long sel_atom = MotifDnDConstants.Swapper.getInt(data + 12, eventByteOrder);970971long status_atom = 0;972973if (success) {974status_atom = MotifDnDConstants.XA_XmTRANSFER_SUCCESS.getAtom();975} else {976status_atom = MotifDnDConstants.XA_XmTRANSFER_FAILURE.getAtom();977}978979XToolkit.awtLock();980try {981XlibWrapper.XConvertSelection(XToolkit.getDisplay(),982sel_atom,983status_atom,984MotifDnDConstants.XA_MOTIF_ATOM_0.getAtom(),985XWindow.getXAWTRootWindow().getWindow(),986time_stamp);987988/*989* Flush the buffer to guarantee that the drop completion event is sent990* to the source before the method returns.991*/992XlibWrapper.XFlush(XToolkit.getDisplay());993} finally {994XToolkit.awtUnlock();995}996997/* Trick to prevent cleanup() from posting dragExit */998targetXWindow = null;9991000/* Cannot do cleanup before the drop finishes as we may need1001source protocol version to send drop finished message. */1002cleanup();1003return true;1004}10051006public final long getSourceWindow() {1007return sourceWindow;1008}10091010/**1011* Reset the state of the object.1012*/1013public void cleanup() {1014// Clear the reference to this protocol.1015XDropTargetEventProcessor.reset();10161017if (targetXWindow != null) {1018notifyProtocolListener(targetXWindow, 0, 0,1019DnDConstants.ACTION_NONE, sourceActions,1020null, MouseEvent.MOUSE_EXITED);1021}10221023if (sourceWindow != 0) {1024XToolkit.awtLock();1025try {1026XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());1027XlibWrapper.XSelectInput(XToolkit.getDisplay(), sourceWindow,1028sourceWindowMask);1029XErrorHandlerUtil.RESTORE_XERROR_HANDLER();1030} finally {1031XToolkit.awtUnlock();1032}1033}10341035sourceWindow = 0;1036sourceWindowMask = 0;1037sourceProtocolVersion = 0;1038sourceActions = DnDConstants.ACTION_NONE;1039sourceFormats = null;1040sourceAtom = 0;1041userAction = DnDConstants.ACTION_NONE;1042sourceX = 0;1043sourceY = 0;1044targetXWindow = null;1045topLevelLeavePostponed = false;1046}10471048public boolean isDragOverComponent() {1049return targetXWindow != null;1050}10511052private void notifyProtocolListener(XWindow xwindow, int x, int y,1053int dropAction, int actions,1054XClientMessageEvent xclient,1055int eventID) {1056long nativeCtxt = 0;10571058// Make a copy of the passed XClientMessageEvent structure, since1059// the original structure can be freed before this1060// SunDropTargetEvent is dispatched.1061if (xclient != null) {1062int size = XClientMessageEvent.getSize();10631064nativeCtxt = unsafe.allocateMemory(size + 4 * Native.getLongSize());10651066unsafe.copyMemory(xclient.pData, nativeCtxt, size);1067}10681069getProtocolListener().handleDropTargetNotification(xwindow, x, y,1070dropAction,1071actions,1072sourceFormats,1073nativeCtxt,1074eventID);1075}1076}107710781079