Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/classes/sun/awt/X11/XDropTargetProtocol.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.io.IOException;2829import java.util.HashMap;3031import sun.util.logging.PlatformLogger;3233/**34* An abstract class for drop protocols on X11 systems.35* Contains protocol-independent drop target code.36*37* @since 1.538*/39abstract class XDropTargetProtocol {40private static final PlatformLogger logger =41PlatformLogger.getLogger("sun.awt.X11.xembed.xdnd.XDropTargetProtocol");4243private final XDropTargetProtocolListener listener;4445public static final int EMBEDDER_ALREADY_REGISTERED = 0;4647public static final int UNKNOWN_MESSAGE = 0;48public static final int ENTER_MESSAGE = 1;49public static final int MOTION_MESSAGE = 2;50public static final int LEAVE_MESSAGE = 3;51public static final int DROP_MESSAGE = 4;5253protected XDropTargetProtocol(XDropTargetProtocolListener listener) {54if (listener == null) {55throw new NullPointerException("Null XDropTargetProtocolListener");56}57this.listener = listener;58}5960protected final XDropTargetProtocolListener getProtocolListener() {61return listener;62}6364/**65* Returns the protocol name. The protocol name cannot be null.66*/67public abstract String getProtocolName();6869/* The caller must hold AWT_LOCK. */70public abstract void registerDropTarget(long window);7172/* The caller must hold AWT_LOCK. */73public abstract void unregisterDropTarget(long window);7475/* The caller must hold AWT_LOCK. */76public abstract void registerEmbedderDropSite(long window);7778/* The caller must hold AWT_LOCK. */79public abstract void unregisterEmbedderDropSite(long window);8081/* The caller must hold AWT_LOCK. */82public abstract void registerEmbeddedDropSite(long embedded);8384/* The caller must hold AWT_LOCK. */85public final void unregisterEmbeddedDropSite(long embedded) {86removeEmbedderRegistryEntry(embedded);87}888990/* The caller must hold AWT_LOCK. */91public abstract boolean isProtocolSupported(long window);9293public abstract int getMessageType(XClientMessageEvent xclient);9495/* The caller must hold AWT_LOCK. */96public final boolean processClientMessage(XClientMessageEvent xclient) {97int type = getMessageType(xclient);98boolean processed = processClientMessageImpl(xclient);99100postProcessClientMessage(xclient, processed, type);101102return processed;103}104105/* The caller must hold AWT_LOCK. */106protected abstract boolean processClientMessageImpl(XClientMessageEvent xclient);107108/*109* Forwards a drag notification to the embedding toplevel modifying the event110* to match the protocol version supported by the toplevel.111* The caller must hold AWT_LOCK.112* Returns True if the event is sent, False otherwise.113*/114protected final boolean forwardClientMessageToToplevel(long toplevel,115XClientMessageEvent xclient) {116EmbedderRegistryEntry entry = getEmbedderRegistryEntry(toplevel);117118if (logger.isLoggable(PlatformLogger.Level.FINEST)) {119logger.finest(" entry={0}", entry);120}121// Window not registered as an embedder for this protocol.122if (entry == null) {123return false;124}125126if (logger.isLoggable(PlatformLogger.Level.FINEST)) {127logger.finest(" entry.isOverriden()={0}", entry.isOverriden());128}129// Window didn't have an associated drop site, so there is no need130// to forward the message.131if (!entry.isOverriden()) {132return false;133}134135adjustEventForForwarding(xclient, entry);136137long proxy = entry.getProxy();138139if (logger.isLoggable(PlatformLogger.Level.FINEST)) {140logger.finest(" proxy={0} toplevel={1}", proxy, toplevel);141}142if (proxy == 0) {143proxy = toplevel;144}145146xclient.set_window(toplevel);147148XToolkit.awtLock();149try {150XlibWrapper.XSendEvent(XToolkit.getDisplay(), proxy, false,151XConstants.NoEventMask, xclient.pData);152} finally {153XToolkit.awtUnlock();154}155156return true;157}158159160/* True iff the previous notification was MotionEvent and it was161forwarded to the browser. */162private boolean motionPassedAlong = false;163164protected abstract void sendEnterMessageToToplevel(long toplevel,165XClientMessageEvent xclient);166167protected abstract void sendLeaveMessageToToplevel(long toplevel,168XClientMessageEvent xclient);169170private void postProcessClientMessage(XClientMessageEvent xclient,171boolean processed,172int type) {173long toplevel = xclient.get_window();174175if (getEmbedderRegistryEntry(toplevel) != null) {176/*177* This code forwards drag notifications to the browser according to the178* following rules:179* - the messages that we failed to process are always forwarded to the180* browser;181* - MotionEvents and DropEvents are forwarded if and only if the drag182* is not over a plugin window;183* - XDnD: EnterEvents and LeaveEvents are never forwarded, instead, we184* send synthesized EnterEvents or LeaveEvents when the drag185* respectively exits or enters plugin windows;186* - Motif DnD: EnterEvents and LeaveEvents are always forwarded.187* Synthetic EnterEvents and LeaveEvents are needed, because the XDnD drop188* site implemented Netscape 6.2 has a nice feature: when it receives189* the first XdndPosition it continuously sends XdndStatus messages to190* the source (every 100ms) until the drag terminates or leaves the drop191* site. When the mouse is dragged over plugin window embedded in the192* browser frame, these XdndStatus messages are mixed with the XdndStatus193* messages sent from the plugin.194* For Motif DnD, synthetic events cause Motif warnings being displayed,195* so these events are always forwarded. However, Motif DnD drop site in196* Netscape 6.2 is implemented in the same way, so there could be similar197* problems if the drag source choose Motif DnD for communication.198*/199if (!processed) {200forwardClientMessageToToplevel(toplevel, xclient);201} else {202boolean motifProtocol =203xclient.get_message_type() ==204MotifDnDConstants.XA_MOTIF_DRAG_AND_DROP_MESSAGE.getAtom();205206switch (type) {207case XDropTargetProtocol.MOTION_MESSAGE:208if (!isDragOverComponent()) {209if (!motionPassedAlong && !motifProtocol) {210sendEnterMessageToToplevel(toplevel, xclient);211}212forwardClientMessageToToplevel(toplevel, xclient);213motionPassedAlong = true;214} else {215if (motionPassedAlong && !motifProtocol) {216sendLeaveMessageToToplevel(toplevel, xclient);217}218motionPassedAlong = false;219}220break;221case XDropTargetProtocol.DROP_MESSAGE:222if (!isDragOverComponent()) {223forwardClientMessageToToplevel(toplevel, xclient);224}225motionPassedAlong = false;226break;227case XDropTargetProtocol.ENTER_MESSAGE:228case XDropTargetProtocol.LEAVE_MESSAGE:229if (motifProtocol) {230forwardClientMessageToToplevel(toplevel, xclient);231}232motionPassedAlong = false;233break;234}235}236}237}238239public abstract boolean sendResponse(long ctxt, int eventID, int action);240241/*242* Retrieves the data from the drag source in the specified format.243*244* @param ctxt a pointer to the XClientMessageEvent structure for this245* protocol's drop message.246* @param format the format in which the data should be retrieved.247*248* @throws IllegalArgumentException if ctxt doesn't point to the249* XClientMessageEvent structure for this protocol's drop message.250* @throws IOException if data retrieval failed.251*/252public abstract Object getData(long ctxt, long format)253throws IllegalArgumentException, IOException;254255public abstract boolean sendDropDone(long ctxt, boolean success,256int dropAction);257258public abstract long getSourceWindow();259260public abstract void cleanup();261262public abstract boolean isDragOverComponent();263264public void adjustEventForForwarding(XClientMessageEvent xclient,265EmbedderRegistryEntry entry) {}266267public abstract boolean forwardEventToEmbedded(long embedded, long ctxt,268int eventID);269270/*271* Returns true if the XEmbed protocol prescribes that an XEmbed server must272* support this DnD protocol for drop sites associated with XEmbed clients.273*/274public abstract boolean isXEmbedSupported();275276protected static final class EmbedderRegistryEntry {277private final boolean overriden;278private final int version;279private final long proxy;280EmbedderRegistryEntry(boolean overriden, int version, long proxy) {281this.overriden = overriden;282this.version = version;283this.proxy = proxy;284}285public boolean isOverriden() {286return overriden;287}288public int getVersion() {289return version;290}291public long getProxy() {292return proxy;293}294}295296/* Access to HashMap is synchronized on this XDropTargetProtocol instance. */297private final HashMap embedderRegistry = new HashMap();298299protected final void putEmbedderRegistryEntry(long embedder,300boolean overriden,301int version,302long proxy) {303synchronized (this) {304embedderRegistry.put(Long.valueOf(embedder),305new EmbedderRegistryEntry(overriden, version,306proxy));307}308}309310protected final EmbedderRegistryEntry getEmbedderRegistryEntry(long embedder) {311synchronized (this) {312return313(EmbedderRegistryEntry)embedderRegistry.get(Long.valueOf(embedder));314}315}316317protected final void removeEmbedderRegistryEntry(long embedder) {318synchronized (this) {319embedderRegistry.remove(Long.valueOf(embedder));320}321}322}323324325