924 lines · 29.0 KB · Java
RawDownload
/* * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package sun.awt.dnd; import java.awt.Component;import java.awt.Point; import java.awt.datatransfer.DataFlavor;import java.awt.datatransfer.Transferable;import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.dnd.DnDConstants; import java.awt.dnd.DropTarget;import java.awt.dnd.DropTargetContext;import java.awt.dnd.DropTargetListener;import java.awt.dnd.DropTargetEvent;import java.awt.dnd.DropTargetDragEvent;import java.awt.dnd.DropTargetDropEvent;import java.awt.dnd.InvalidDnDOperationException; import java.awt.dnd.peer.DropTargetContextPeer; import java.util.HashSet;import java.util.Map;import java.util.Arrays; import sun.util.logging.PlatformLogger; import java.io.IOException;import java.io.InputStream; import sun.awt.AppContext;import sun.awt.SunToolkit;import sun.awt.datatransfer.DataTransferer;import sun.awt.datatransfer.ToolkitThreadBlockedHandler;import sun.security.util.SecurityConstants; /** * <p> * The SunDropTargetContextPeer class is the generic class responsible for handling * the interaction between a windowing systems DnD system and Java. * </p> * * @since JDK1.3.1 * */ public abstract class SunDropTargetContextPeer implements DropTargetContextPeer, Transferable {     /*     * A boolean constant that requires the peer to wait until the     * SunDropTargetEvent is processed and return the status back     * to the native code.     */    public static final boolean DISPATCH_SYNC = true;    private   DropTarget              currentDT;    private   DropTargetContext       currentDTC;    private   long[]                  currentT;    private   int                     currentA;   // target actions    private   int                     currentSA;  // source actions    private   int                     currentDA;  // current drop action    private   int                     previousDA;     private   long                    nativeDragContext;     private   Transferable            local;     private boolean                   dragRejected = false;     protected int                     dropStatus   = STATUS_NONE;    protected boolean                 dropComplete = false;     // The flag is used to monitor whether the drop action is    // handled by a user. That allows to distinct during    // which operation getTransferData() method is invoked.    boolean                           dropInProcess = false;     /*     * global lock     */     protected static final Object _globalLock = new Object();     private static final PlatformLogger dndLog = PlatformLogger.getLogger("sun.awt.dnd.SunDropTargetContextPeer");     /*     * a primitive mechanism for advertising intra-JVM Transferables     */     protected static Transferable         currentJVMLocalSourceTransferable = null;     public static void setCurrentJVMLocalSourceTransferable(Transferable t) throws InvalidDnDOperationException {        synchronized(_globalLock) {            if (t != null && currentJVMLocalSourceTransferable != null) {                    throw new InvalidDnDOperationException();            } else {                currentJVMLocalSourceTransferable = t;            }        }    }     /**     * obtain the transferable iff the operation is in the same VM     */     private static Transferable getJVMLocalSourceTransferable() {        return currentJVMLocalSourceTransferable;    }     /*     * constants used by dropAccept() or dropReject()     */     protected final static int STATUS_NONE   =  0; // none pending    protected final static int STATUS_WAIT   =  1; // drop pending    protected final static int STATUS_ACCEPT =  2;    protected final static int STATUS_REJECT = -1;     /**     * create the peer     */     public SunDropTargetContextPeer() {        super();    }     /**     * @return the DropTarget associated with this peer     */     public DropTarget getDropTarget() { return currentDT; }     /**     * @param actions set the current actions     */     public synchronized void setTargetActions(int actions) {        currentA = actions &            (DnDConstants.ACTION_COPY_OR_MOVE | DnDConstants.ACTION_LINK);    }     /**     * @return the current target actions     */     public int getTargetActions() {        return currentA;    }     /**     * get the Transferable associated with the drop     */     public Transferable getTransferable() {        return this;    }     /**     * @return current DataFlavors available     */    // NOTE: This method may be called by privileged threads.    //       DO NOT INVOKE CLIENT CODE ON THIS THREAD!     public DataFlavor[] getTransferDataFlavors() {        final Transferable    localTransferable = local;         if (localTransferable != null) {            return localTransferable.getTransferDataFlavors();        } else {            return DataTransferer.getInstance().getFlavorsForFormatsAsArray                (currentT, DataTransferer.adaptFlavorMap                    (currentDT.getFlavorMap()));        }    }     /**     * @return if the flavor is supported     */     public boolean isDataFlavorSupported(DataFlavor df) {        Transferable localTransferable = local;         if (localTransferable != null) {            return localTransferable.isDataFlavorSupported(df);        } else {            return DataTransferer.getInstance().getFlavorsForFormats                (currentT, DataTransferer.adaptFlavorMap                    (currentDT.getFlavorMap())).                containsKey(df);        }    }     /**     * @return the data     */     public Object getTransferData(DataFlavor df)      throws UnsupportedFlavorException, IOException,        InvalidDnDOperationException    {         SecurityManager sm = System.getSecurityManager();        try {            if (!dropInProcess && sm != null) {                sm.checkSystemClipboardAccess();            }        } catch (Exception e) {            Thread currentThread = Thread.currentThread();            currentThread.getUncaughtExceptionHandler().uncaughtException(currentThread, e);            return null;        }         Long lFormat = null;        Transferable localTransferable = local;         if (localTransferable != null) {            return localTransferable.getTransferData(df);        }         if (dropStatus != STATUS_ACCEPT || dropComplete) {            throw new InvalidDnDOperationException("No drop current");        }         Map flavorMap = DataTransferer.getInstance().getFlavorsForFormats            (currentT, DataTransferer.adaptFlavorMap                (currentDT.getFlavorMap()));         lFormat = (Long)flavorMap.get(df);        if (lFormat == null) {            throw new UnsupportedFlavorException(df);        }         if (df.isRepresentationClassRemote() &&            currentDA != DnDConstants.ACTION_LINK) {            throw new InvalidDnDOperationException("only ACTION_LINK is permissable for transfer of java.rmi.Remote objects");        }         final long format = lFormat.longValue();        Object ret = getNativeData(format);         if (ret instanceof byte[]) {            try {                return DataTransferer.getInstance().                    translateBytes((byte[])ret, df, format, this);            } catch (IOException e) {                throw new InvalidDnDOperationException(e.getMessage());            }        } else if (ret instanceof InputStream) {            try {                return DataTransferer.getInstance().                    translateStream((InputStream)ret, df, format, this);            } catch (IOException e) {                throw new InvalidDnDOperationException(e.getMessage());            }        } else {            throw new IOException("no native data was transfered");        }    }     protected abstract Object getNativeData(long format)      throws IOException;     /**     * @return if the transfer is a local one     */    public boolean isTransferableJVMLocal() {        return local != null || getJVMLocalSourceTransferable() != null;    }     private int handleEnterMessage(final Component component,                                   final int x, final int y,                                   final int dropAction,                                   final int actions, final long[] formats,                                   final long nativeCtxt) {        return postDropTargetEvent(component, x, y, dropAction, actions,                                   formats, nativeCtxt,                                   SunDropTargetEvent.MOUSE_ENTERED,                                   SunDropTargetContextPeer.DISPATCH_SYNC);    }     /**     * actual processing on EventQueue Thread     */     protected void processEnterMessage(SunDropTargetEvent event) {        Component  c    = (Component)event.getSource();        DropTarget dt   = c.getDropTarget();        Point      hots = event.getPoint();         local = getJVMLocalSourceTransferable();         if (currentDTC != null) { // some wreckage from last time            currentDTC.removeNotify();            currentDTC = null;        }         if (c.isShowing() && dt != null && dt.isActive()) {            currentDT  = dt;            currentDTC = currentDT.getDropTargetContext();             currentDTC.addNotify(this);             currentA   = dt.getDefaultActions();             try {                ((DropTargetListener)dt).dragEnter(new DropTargetDragEvent(currentDTC,                                                                           hots,                                                                           currentDA,                                                                           currentSA));            } catch (Exception e) {                e.printStackTrace();                currentDA = DnDConstants.ACTION_NONE;            }        } else {            currentDT  = null;            currentDTC = null;            currentDA   = DnDConstants.ACTION_NONE;            currentSA   = DnDConstants.ACTION_NONE;            currentA   = DnDConstants.ACTION_NONE;        }     }     /**     * upcall to handle exit messages     */     private void handleExitMessage(final Component component,                                   final long nativeCtxt) {        /*         * Even though the return value is irrelevant for this event, it is         * dispatched synchronously to fix 4393148 properly.         */        postDropTargetEvent(component, 0, 0, DnDConstants.ACTION_NONE,                            DnDConstants.ACTION_NONE, null, nativeCtxt,                            SunDropTargetEvent.MOUSE_EXITED,                            SunDropTargetContextPeer.DISPATCH_SYNC);    }     /**     *     */     protected void processExitMessage(SunDropTargetEvent event) {        Component         c   = (Component)event.getSource();        DropTarget        dt  = c.getDropTarget();        DropTargetContext dtc = null;         if (dt == null) {            currentDT = null;            currentT  = null;             if (currentDTC != null) {                currentDTC.removeNotify();            }             currentDTC = null;             return;        }         if (dt != currentDT) {             if (currentDTC != null) {                currentDTC.removeNotify();            }             currentDT  = dt;            currentDTC = dt.getDropTargetContext();             currentDTC.addNotify(this);        }         dtc = currentDTC;         if (dt.isActive()) try {            ((DropTargetListener)dt).dragExit(new DropTargetEvent(dtc));        } catch (Exception e) {            e.printStackTrace();        } finally {            currentA  = DnDConstants.ACTION_NONE;            currentSA = DnDConstants.ACTION_NONE;            currentDA = DnDConstants.ACTION_NONE;            currentDT = null;            currentT  = null;             currentDTC.removeNotify();            currentDTC = null;             local = null;             dragRejected = false;        }    }     private int handleMotionMessage(final Component component,                                    final int x, final int y,                                    final int dropAction,                                    final int actions, final long[] formats,                                    final long nativeCtxt) {        return postDropTargetEvent(component, x, y, dropAction, actions,                                   formats, nativeCtxt,                                   SunDropTargetEvent.MOUSE_DRAGGED,                                   SunDropTargetContextPeer.DISPATCH_SYNC);    }     /**     *     */     protected void processMotionMessage(SunDropTargetEvent event,                                      boolean operationChanged) {        Component         c    = (Component)event.getSource();        Point             hots = event.getPoint();        int               id   = event.getID();        DropTarget        dt   = c.getDropTarget();        DropTargetContext dtc  = null;         if (c.isShowing() && (dt != null) && dt.isActive()) {            if (currentDT != dt) {                if (currentDTC != null) {                    currentDTC.removeNotify();                }                 currentDT  = dt;                currentDTC = null;            }             dtc = currentDT.getDropTargetContext();            if (dtc != currentDTC) {                if (currentDTC != null) {                    currentDTC.removeNotify();                }                 currentDTC = dtc;                currentDTC.addNotify(this);            }             currentA = currentDT.getDefaultActions();             try {                DropTargetDragEvent dtde = new DropTargetDragEvent(dtc,                                                                   hots,                                                                   currentDA,                                                                   currentSA);                DropTargetListener dtl = (DropTargetListener)dt;                if (operationChanged) {                    dtl.dropActionChanged(dtde);                } else {                    dtl.dragOver(dtde);                }                 if (dragRejected) {                    currentDA = DnDConstants.ACTION_NONE;                }            } catch (Exception e) {                e.printStackTrace();                currentDA = DnDConstants.ACTION_NONE;            }        } else {            currentDA = DnDConstants.ACTION_NONE;        }    }     /**     * upcall to handle the Drop message     */     private void handleDropMessage(final Component component,                                   final int x, final int y,                                   final int dropAction, final int actions,                                   final long[] formats,                                   final long nativeCtxt) {        postDropTargetEvent(component, x, y, dropAction, actions,                            formats, nativeCtxt,                            SunDropTargetEvent.MOUSE_DROPPED,

Lines 1–500 of 924.