alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (MotifDnDDropTargetProtocol.java)

This example Java source code file (MotifDnDDropTargetProtocol.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

awt, cannot, dnd, drag, drop, error, event, illegalargumentexception, ioexception, motifdnddroptargetprotocol, unknown_message, windowpropertygetter, xbasewindow, xclientmessageevent, xdroptargetprotocol, xexception, xselection, xwindow, xwindowattributes

The MotifDnDDropTargetProtocol.java Java example source code

/*
 * Copyright (c) 2003, 2013, 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.X11;

import java.awt.Point;

import java.awt.dnd.DnDConstants;

import java.awt.event.MouseEvent;

import java.io.IOException;

import sun.misc.Unsafe;

/**
 * XDropTargetProtocol implementation for Motif DnD protocol.
 *
 * @since 1.5
 */
class MotifDnDDropTargetProtocol extends XDropTargetProtocol {
    private static final Unsafe unsafe = XlibWrapper.unsafe;

    private long sourceWindow = 0;
    private long sourceWindowMask = 0;
    private int sourceProtocolVersion = 0;
    private int sourceActions = DnDConstants.ACTION_NONE;
    private long[] sourceFormats = null;
    private long sourceAtom = 0;
    private int userAction = DnDConstants.ACTION_NONE;
    private int sourceX = 0;
    private int sourceY = 0;
    private XWindow targetXWindow = null;
    private boolean topLevelLeavePostponed = false;

    protected MotifDnDDropTargetProtocol(XDropTargetProtocolListener listener) {
        super(listener);
    }

    /**
     * Creates an instance associated with the specified listener.
     *
     * @throws NullPointerException if listener is <code>null.
     */
    static XDropTargetProtocol createInstance(XDropTargetProtocolListener listener) {
        return new MotifDnDDropTargetProtocol(listener);
    }

    public String getProtocolName() {
        return XDragAndDropProtocols.MotifDnD;
    }

    public void registerDropTarget(long window) {
        assert XToolkit.isAWTLockHeldByCurrentThread();

        MotifDnDConstants.writeDragReceiverInfoStruct(window);
    }

    public void unregisterDropTarget(long window) {
        assert XToolkit.isAWTLockHeldByCurrentThread();

        MotifDnDConstants.XA_MOTIF_ATOM_0.DeleteProperty(window);
    }

    public void registerEmbedderDropSite(long embedder) {
        assert XToolkit.isAWTLockHeldByCurrentThread();

        boolean overriden = false;
        int version = 0;
        long proxy = 0;
        long newProxy = XDropTargetRegistry.getDnDProxyWindow();
        int status = 0;
        long data = 0;
        int dataSize = MotifDnDConstants.MOTIF_RECEIVER_INFO_SIZE;

        WindowPropertyGetter wpg =
            new WindowPropertyGetter(embedder,
                                     MotifDnDConstants.XA_MOTIF_DRAG_RECEIVER_INFO,
                                     0, 0xFFFF, false,
                                     XConstants.AnyPropertyType);

        try {
            status = wpg.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());

            /*
             * DragICCI.h:
             *
             * typedef struct _xmDragReceiverInfoStruct{
             *     BYTE byte_order;
             *     BYTE protocol_version;
             *     BYTE drag_protocol_style;
             *     BYTE pad1;
             *     CARD32       proxy_window B32;
             *     CARD16       num_drop_sites B16;
             *     CARD16       pad2 B16;
             *     CARD32       heap_offset B32;
             * } xmDragReceiverInfoStruct;
             */
            if (status == (int)XConstants.Success && wpg.getData() != 0 &&
                wpg.getActualType() != 0 && wpg.getActualFormat() == 8 &&
                wpg.getNumberOfItems() >=
                MotifDnDConstants.MOTIF_RECEIVER_INFO_SIZE) {

                overriden = true;
                data = wpg.getData();
                dataSize = wpg.getNumberOfItems();

                byte byteOrderByte = unsafe.getByte(data);

                {
                    int tproxy = unsafe.getInt(data + 4);
                    if (byteOrderByte != MotifDnDConstants.getByteOrderByte()) {
                        tproxy = MotifDnDConstants.Swapper.swap(tproxy);
                    }
                    proxy = tproxy;
                }

                if (proxy == newProxy) {
                    // Embedder already registered.
                    return;
                }

                {
                    int tproxy = (int)newProxy;
                    if (byteOrderByte != MotifDnDConstants.getByteOrderByte()) {
                        tproxy = MotifDnDConstants.Swapper.swap(tproxy);
                    }
                    unsafe.putInt(data + 4, tproxy);
                }
            } else {
                data = unsafe.allocateMemory(dataSize);

                unsafe.putByte(data, MotifDnDConstants.getByteOrderByte()); /* byte order */
                unsafe.putByte(data + 1, MotifDnDConstants.MOTIF_DND_PROTOCOL_VERSION); /* protocol version */
                unsafe.putByte(data + 2, (byte)MotifDnDConstants.MOTIF_DYNAMIC_STYLE); /* protocol style */
                unsafe.putByte(data + 3, (byte)0); /* pad */
                unsafe.putInt(data + 4, (int)newProxy); /* proxy window */
                unsafe.putShort(data + 8, (short)0); /* num_drop_sites */
                unsafe.putShort(data + 10, (short)0); /* pad */
                unsafe.putInt(data + 12, dataSize);
            }

            XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
            XlibWrapper.XChangeProperty(XToolkit.getDisplay(), embedder,
                                        MotifDnDConstants.XA_MOTIF_DRAG_RECEIVER_INFO.getAtom(),
                                        MotifDnDConstants.XA_MOTIF_DRAG_RECEIVER_INFO.getAtom(),
                                        8, XConstants.PropModeReplace,
                                        data, dataSize);
            XErrorHandlerUtil.RESTORE_XERROR_HANDLER();

            if ((XErrorHandlerUtil.saved_error != null) &&
                (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
                throw new XException("Cannot write Motif receiver info property");
            }
        } finally {
            if (!overriden) {
                unsafe.freeMemory(data);
                data = 0;
            }
            wpg.dispose();
        }

        putEmbedderRegistryEntry(embedder, overriden, version, proxy);
    }

    public void unregisterEmbedderDropSite(long embedder) {
        assert XToolkit.isAWTLockHeldByCurrentThread();

        EmbedderRegistryEntry entry = getEmbedderRegistryEntry(embedder);

        if (entry == null) {
            return;
        }

        if (entry.isOverriden()) {
            int status = 0;

            WindowPropertyGetter wpg =
                new WindowPropertyGetter(embedder,
                                         MotifDnDConstants.XA_MOTIF_DRAG_RECEIVER_INFO,
                                         0, 0xFFFF, false,
                                         XConstants.AnyPropertyType);

            try {
                status = wpg.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());

                /*
                 * DragICCI.h:
                 *
                 * typedef struct _xmDragReceiverInfoStruct{
                 *     BYTE     byte_order;
                 *     BYTE     protocol_version;
                 *     BYTE     drag_protocol_style;
                 *     BYTE     pad1;
                 *     CARD32   proxy_window B32;
                 *     CARD16   num_drop_sites B16;
                 *     CARD16   pad2 B16;
                 *     CARD32   heap_offset B32;
                 * } xmDragReceiverInfoStruct;
                 */
                if (status == (int)XConstants.Success && wpg.getData() != 0 &&
                    wpg.getActualType() != 0 && wpg.getActualFormat() == 8 &&
                    wpg.getNumberOfItems() >=
                    MotifDnDConstants.MOTIF_RECEIVER_INFO_SIZE) {

                    int dataSize = MotifDnDConstants.MOTIF_RECEIVER_INFO_SIZE;
                    long data = wpg.getData();
                    byte byteOrderByte = unsafe.getByte(data);

                    int tproxy = (int)entry.getProxy();
                    if (MotifDnDConstants.getByteOrderByte() != byteOrderByte) {
                        tproxy = MotifDnDConstants.Swapper.swap(tproxy);
                    }

                    unsafe.putInt(data + 4, tproxy);

                    XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
                    XlibWrapper.XChangeProperty(XToolkit.getDisplay(), embedder,
                                                MotifDnDConstants.XA_MOTIF_DRAG_RECEIVER_INFO.getAtom(),
                                                MotifDnDConstants.XA_MOTIF_DRAG_RECEIVER_INFO.getAtom(),
                                                8, XConstants.PropModeReplace,
                                                data, dataSize);
                    XErrorHandlerUtil.RESTORE_XERROR_HANDLER();

                    if ((XErrorHandlerUtil.saved_error != null) &&
                        (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
                        throw new XException("Cannot write Motif receiver info property");
                    }
                }
            } finally {
                wpg.dispose();
            }
        } else {
            MotifDnDConstants.XA_MOTIF_DRAG_RECEIVER_INFO.DeleteProperty(embedder);
        }
    }

    /*
     * Gets and stores in the registry the embedder's Motif DnD drop site info
     * from the embedded.
     */
    public void registerEmbeddedDropSite(long embedded) {
        assert XToolkit.isAWTLockHeldByCurrentThread();

        boolean overriden = false;
        int version = 0;
        long proxy = 0;
        int status = 0;

        WindowPropertyGetter wpg =
            new WindowPropertyGetter(embedded,
                                     MotifDnDConstants.XA_MOTIF_DRAG_RECEIVER_INFO,
                                     0, 0xFFFF, false,
                                     XConstants.AnyPropertyType);

        try {
            status = wpg.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());

            /*
             * DragICCI.h:
             *
             * typedef struct _xmDragReceiverInfoStruct{
             *     BYTE byte_order;
             *     BYTE protocol_version;
             *     BYTE drag_protocol_style;
             *     BYTE pad1;
             *     CARD32       proxy_window B32;
             *     CARD16       num_drop_sites B16;
             *     CARD16       pad2 B16;
             *     CARD32       heap_offset B32;
             * } xmDragReceiverInfoStruct;
             */
            if (status == (int)XConstants.Success && wpg.getData() != 0 &&
                wpg.getActualType() != 0 && wpg.getActualFormat() == 8 &&
                wpg.getNumberOfItems() >=
                MotifDnDConstants.MOTIF_RECEIVER_INFO_SIZE) {

                overriden = true;
                long data = wpg.getData();

                byte byteOrderByte = unsafe.getByte(data);

                {
                    int tproxy = unsafe.getInt(data + 4);
                    if (byteOrderByte != MotifDnDConstants.getByteOrderByte()) {
                        tproxy = MotifDnDConstants.Swapper.swap(tproxy);
                    }
                    proxy = tproxy;
                }
            }
        } finally {
            wpg.dispose();
        }

        putEmbedderRegistryEntry(embedded, overriden, version, proxy);
    }

    public boolean isProtocolSupported(long window) {
        WindowPropertyGetter wpg =
            new WindowPropertyGetter(window,
                                     MotifDnDConstants.XA_MOTIF_DRAG_RECEIVER_INFO,
                                     0, 0xFFFF, false,
                                     XConstants.AnyPropertyType);

        try {
            int status = wpg.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());

            if (status == (int)XConstants.Success && wpg.getData() != 0 &&
                wpg.getActualType() != 0 && wpg.getActualFormat() == 8 &&
                wpg.getNumberOfItems() >=
                MotifDnDConstants.MOTIF_RECEIVER_INFO_SIZE) {
                return true;
            } else {
                return false;
            }
        } finally {
            wpg.dispose();
        }
    }

    private boolean processTopLevelEnter(XClientMessageEvent xclient) {
        assert XToolkit.isAWTLockHeldByCurrentThread();

        if (targetXWindow != null || sourceWindow != 0) {
            return false;
        }

        if (!(XToolkit.windowToXWindow(xclient.get_window()) instanceof XWindow)
            && getEmbedderRegistryEntry(xclient.get_window()) == null) {
            return false;
        }

        long source_win = 0;
        long source_win_mask = 0;
        int protocol_version = 0;
        long property_atom = 0;
        long[] formats = null;

        {
            long data = xclient.get_data();
            byte eventByteOrder = unsafe.getByte(data + 1);
            source_win = MotifDnDConstants.Swapper.getInt(data + 8, eventByteOrder);
            property_atom = MotifDnDConstants.Swapper.getInt(data + 12, eventByteOrder);
        }

        /* Extract the available data types. */
        {
            WindowPropertyGetter wpg =
                new WindowPropertyGetter(source_win,
                                         XAtom.get(property_atom),
                                         0, 0xFFFF,
                                         false,
                                         MotifDnDConstants.XA_MOTIF_DRAG_INITIATOR_INFO.getAtom());

            try {
                int status = wpg.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());

                if (status == XConstants.Success && wpg.getData() != 0 &&
                    wpg.getActualType() ==
                    MotifDnDConstants.XA_MOTIF_DRAG_INITIATOR_INFO.getAtom() &&
                    wpg.getActualFormat() == 8 &&
                    wpg.getNumberOfItems() ==
                    MotifDnDConstants.MOTIF_INITIATOR_INFO_SIZE) {

                    long data = wpg.getData();
                    byte propertyByteOrder = unsafe.getByte(data);

                    protocol_version = unsafe.getByte(data + 1);

                    if (protocol_version !=
                        MotifDnDConstants.MOTIF_DND_PROTOCOL_VERSION) {
                        return false;
                    }

                    int index =
                        MotifDnDConstants.Swapper.getShort(data + 2, propertyByteOrder);

                    formats = MotifDnDConstants.getTargetListForIndex(index);
                } else {
                    formats = new long[0];
                }
            } finally {
                wpg.dispose();
            }
        }

        /*
         * Select for StructureNotifyMask to receive DestroyNotify in case of source
         * crash.
         */
        XWindowAttributes wattr = new XWindowAttributes();
        try {
            XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
            int status = XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(),
                                                          source_win, wattr.pData);

            XErrorHandlerUtil.RESTORE_XERROR_HANDLER();

            if ((status == 0) ||
                ((XErrorHandlerUtil.saved_error != null) &&
                (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success))) {
                throw new XException("XGetWindowAttributes failed");
            }

            source_win_mask = wattr.get_your_event_mask();
        } finally {
            wattr.dispose();
        }

        XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
        XlibWrapper.XSelectInput(XToolkit.getDisplay(), source_win,
                                 source_win_mask |
                                 XConstants.StructureNotifyMask);

        XErrorHandlerUtil.RESTORE_XERROR_HANDLER();

        if ((XErrorHandlerUtil.saved_error != null) &&
            (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
            throw new XException("XSelectInput failed");
        }

        sourceWindow = source_win;
        sourceWindowMask = source_win_mask;
        sourceProtocolVersion = protocol_version;
        /*
         * TOP_LEVEL_ENTER doesn't communicate the list of supported actions
         * They are provided in DRAG_MOTION.
         */
        sourceActions = DnDConstants.ACTION_NONE;
        sourceFormats = formats;
        sourceAtom = property_atom;

        return true;
    }

    private boolean processDragMotion(XClientMessageEvent xclient) {
        long data = xclient.get_data();
        byte eventByteOrder = unsafe.getByte(data + 1);
        byte eventReason = (byte)(unsafe.getByte(data) &
                                  MotifDnDConstants.MOTIF_MESSAGE_REASON_MASK);
        int x = 0;
        int y = 0;

        short flags = MotifDnDConstants.Swapper.getShort(data + 2, eventByteOrder);

        int motif_action = (flags & MotifDnDConstants.MOTIF_DND_ACTION_MASK) >>
            MotifDnDConstants.MOTIF_DND_ACTION_SHIFT;
        int motif_actions = (flags & MotifDnDConstants.MOTIF_DND_ACTIONS_MASK) >>
            MotifDnDConstants.MOTIF_DND_ACTIONS_SHIFT;

        int java_action = MotifDnDConstants.getJavaActionsForMotifActions(motif_action);
        int java_actions = MotifDnDConstants.getJavaActionsForMotifActions(motif_actions);

        /* Append source window id to the event data, so that we can send the
           response properly. */
        {
            int win = (int)sourceWindow;
            if (eventByteOrder != MotifDnDConstants.getByteOrderByte()) {
                win = MotifDnDConstants.Swapper.swap(win);
            }
            unsafe.putInt(data + 12, win);
        }

        XWindow xwindow = null;
        {
            XBaseWindow xbasewindow = XToolkit.windowToXWindow(xclient.get_window());
            if (xbasewindow instanceof XWindow) {
                xwindow = (XWindow)xbasewindow;
            }
        }

        if (eventReason == MotifDnDConstants.OPERATION_CHANGED) {
            /* OPERATION_CHANGED event doesn't provide coordinates, so we use
               previously stored position and component ref. */
            x = sourceX;
            y = sourceY;

            if (xwindow == null) {
                xwindow = targetXWindow;
            }
        } else {
            x = MotifDnDConstants.Swapper.getShort(data + 8, eventByteOrder);
            y = MotifDnDConstants.Swapper.getShort(data + 10, eventByteOrder);

            if (xwindow == null) {
                long receiver =
                    XDropTargetRegistry.getRegistry().getEmbeddedDropSite(
                        xclient.get_window(), x, y);

                if (receiver != 0) {
                    XBaseWindow xbasewindow = XToolkit.windowToXWindow(receiver);
                    if (xbasewindow instanceof XWindow) {
                        xwindow = (XWindow)xbasewindow;
                    }
                }
            }

            if (xwindow != null) {
                Point p = xwindow.toLocal(x, y);
                x = p.x;
                y = p.y;
            }
        }

        if (xwindow == null) {
            if (targetXWindow != null) {
                notifyProtocolListener(targetXWindow, x, y,
                                       DnDConstants.ACTION_NONE, java_actions,
                                       xclient, MouseEvent.MOUSE_EXITED);
            }
        } else {
            int java_event_id = 0;

            if (targetXWindow == null) {
                java_event_id = MouseEvent.MOUSE_ENTERED;
            } else {
                java_event_id = MouseEvent.MOUSE_DRAGGED;
            }

            notifyProtocolListener(xwindow, x, y, java_action, java_actions,
                                   xclient, java_event_id);
        }

        sourceActions = java_actions;
        userAction = java_action;
        sourceX = x;
        sourceY = y;
        targetXWindow = xwindow;

        return true;
    }

    private boolean processTopLevelLeave(XClientMessageEvent xclient) {
        assert XToolkit.isAWTLockHeldByCurrentThread();

        long data = xclient.get_data();
        byte eventByteOrder = unsafe.getByte(data + 1);

        long source_win = MotifDnDConstants.Swapper.getInt(data + 8, eventByteOrder);

        /* Ignore Motif DnD messages from all other windows. */
        if (source_win != sourceWindow) {
            return false;
        }

        /*
         * Postpone upcall to java, so that we can abort it in case
         * if drop immediatelly follows (see BugTraq ID 4395290).
         * Send a dummy ClientMessage event to guarantee that a postponed java
         * upcall will be processed.
         */
        topLevelLeavePostponed = true;
        {
            long proxy;

            /*
             * If this is an embedded drop site, the event should go to the
             * awt_root_window as this is a proxy for all embedded drop sites.
             * Otherwise the event should go to the event->window, as we don't use
             * proxies for normal drop sites.
             */
            if (getEmbedderRegistryEntry(xclient.get_window()) != null) {
                proxy = XDropTargetRegistry.getDnDProxyWindow();
            } else {
                proxy = xclient.get_window();
            }

            XClientMessageEvent dummy = new XClientMessageEvent();

            try {
                dummy.set_type(XConstants.ClientMessage);
                dummy.set_window(xclient.get_window());
                dummy.set_format(32);
                dummy.set_message_type(0);
                dummy.set_data(0, 0);
                dummy.set_data(1, 0);
                dummy.set_data(2, 0);
                dummy.set_data(3, 0);
                dummy.set_data(4, 0);
                XlibWrapper.XSendEvent(XToolkit.getDisplay(),
                                       proxy, false, XConstants.NoEventMask,
                                       dummy.pData);
            } finally {
                dummy.dispose();
            }
        }
        return true;
    }

    private boolean processDropStart(XClientMessageEvent xclient) {
        long data = xclient.get_data();
        byte eventByteOrder = unsafe.getByte(data + 1);

        long source_win =
            MotifDnDConstants.Swapper.getInt(data + 16, eventByteOrder);

        /* Ignore Motif DnD messages from all other windows. */
        if (source_win != sourceWindow) {
            return false;
        }

        long property_atom =
            MotifDnDConstants.Swapper.getInt(data + 12, eventByteOrder);

        short flags =
            MotifDnDConstants.Swapper.getShort(data + 2, eventByteOrder);

        int motif_action = (flags & MotifDnDConstants.MOTIF_DND_ACTION_MASK) >>
            MotifDnDConstants.MOTIF_DND_ACTION_SHIFT;
        int motif_actions = (flags & MotifDnDConstants.MOTIF_DND_ACTIONS_MASK) >>
            MotifDnDConstants.MOTIF_DND_ACTIONS_SHIFT;

        int java_action = MotifDnDConstants.getJavaActionsForMotifActions(motif_action);
        int java_actions = MotifDnDConstants.getJavaActionsForMotifActions(motif_actions);

        int x = MotifDnDConstants.Swapper.getShort(data + 8, eventByteOrder);
        int y = MotifDnDConstants.Swapper.getShort(data + 10, eventByteOrder);

        XWindow xwindow = null;
        {
            XBaseWindow xbasewindow = XToolkit.windowToXWindow(xclient.get_window());
            if (xbasewindow instanceof XWindow) {
                xwindow = (XWindow)xbasewindow;
            }
        }

        if (xwindow == null) {
            long receiver =
                XDropTargetRegistry.getRegistry().getEmbeddedDropSite(
                    xclient.get_window(), x, y);

            if (receiver != 0) {
                XBaseWindow xbasewindow = XToolkit.windowToXWindow(receiver);
                if (xbasewindow instanceof XWindow) {
                    xwindow = (XWindow)xbasewindow;
                }
            }
        }

        if (xwindow != null) {
            Point p = xwindow.toLocal(x, y);
            x = p.x;
            y = p.y;
        }

        if (xwindow != null) {
            notifyProtocolListener(xwindow, x, y, java_action, java_actions,
                                   xclient, MouseEvent.MOUSE_RELEASED);
        } else if (targetXWindow != null) {
            notifyProtocolListener(targetXWindow, x, y,
                                   DnDConstants.ACTION_NONE, java_actions,
                                   xclient, MouseEvent.MOUSE_EXITED);
        }

        return true;
    }

    public int getMessageType(XClientMessageEvent xclient) {
        if (xclient.get_message_type() !=
            MotifDnDConstants.XA_MOTIF_DRAG_AND_DROP_MESSAGE.getAtom()) {

            return UNKNOWN_MESSAGE;
        }

        long data = xclient.get_data();
        byte reason = (byte)(unsafe.getByte(data) &
                             MotifDnDConstants.MOTIF_MESSAGE_REASON_MASK);

        switch (reason) {
        case MotifDnDConstants.TOP_LEVEL_ENTER :
            return ENTER_MESSAGE;
        case MotifDnDConstants.DRAG_MOTION :
        case MotifDnDConstants.OPERATION_CHANGED :
            return MOTION_MESSAGE;
        case MotifDnDConstants.TOP_LEVEL_LEAVE :
            return LEAVE_MESSAGE;
        case MotifDnDConstants.DROP_START :
            return DROP_MESSAGE;
        default:
            return UNKNOWN_MESSAGE;
        }
    }

    protected boolean processClientMessageImpl(XClientMessageEvent xclient) {
        if (xclient.get_message_type() !=
            MotifDnDConstants.XA_MOTIF_DRAG_AND_DROP_MESSAGE.getAtom()) {
            if (topLevelLeavePostponed) {
                topLevelLeavePostponed = false;
                cleanup();
            }

            return false;
        }

        long data = xclient.get_data();
        byte reason = (byte)(unsafe.getByte(data) &
            MotifDnDConstants.MOTIF_MESSAGE_REASON_MASK);
        byte origin = (byte)(unsafe.getByte(data) &
            MotifDnDConstants.MOTIF_MESSAGE_SENDER_MASK);

        if (topLevelLeavePostponed) {
            topLevelLeavePostponed = false;
            if (reason != MotifDnDConstants.DROP_START) {
                cleanup();
            }
        }

        /* Only initiator messages should be handled. */
        if (origin != MotifDnDConstants.MOTIF_MESSAGE_FROM_INITIATOR) {
            return false;
        }

        switch (reason) {
        case MotifDnDConstants.TOP_LEVEL_ENTER :
            return processTopLevelEnter(xclient);
        case MotifDnDConstants.DRAG_MOTION :
        case MotifDnDConstants.OPERATION_CHANGED :
            return processDragMotion(xclient);
        case MotifDnDConstants.TOP_LEVEL_LEAVE :
            return processTopLevelLeave(xclient);
        case MotifDnDConstants.DROP_START :
            return processDropStart(xclient);
        default:
            return false;
        }
    }

    /*
     * Currently we don't synthesize enter/leave messages for Motif DnD
     * protocol. See comments in XDropTargetProtocol.postProcessClientMessage.
     */
    protected void sendEnterMessageToToplevel(long win,
                                              XClientMessageEvent xclient) {
        throw new Error("UNIMPLEMENTED");
    }

    protected void sendLeaveMessageToToplevel(long win,
                                              XClientMessageEvent xclient) {
        throw new Error("UNIMPLEMENTED");
    }

    public boolean forwardEventToEmbedded(long embedded, long ctxt,
                                          int eventID) {
        // UNIMPLEMENTED.
        return false;
    }

    public boolean isXEmbedSupported() {
        return false;
    }

    public boolean sendResponse(long ctxt, int eventID, int action) {
        XClientMessageEvent xclient = new XClientMessageEvent(ctxt);
        if (xclient.get_message_type() !=
            MotifDnDConstants.XA_MOTIF_DRAG_AND_DROP_MESSAGE.getAtom()) {
            return false;
        }

        long data = xclient.get_data();
        byte reason = (byte)(unsafe.getByte(data) &
            MotifDnDConstants.MOTIF_MESSAGE_REASON_MASK);
        byte origin = (byte)(unsafe.getByte(data) &
            MotifDnDConstants.MOTIF_MESSAGE_SENDER_MASK);
        byte eventByteOrder = unsafe.getByte(data + 1);
        byte response_reason = (byte)0;

        /* Only initiator messages should be handled. */
        if (origin != MotifDnDConstants.MOTIF_MESSAGE_FROM_INITIATOR) {
            return false;
        }

        switch (reason) {
        case MotifDnDConstants.TOP_LEVEL_ENTER:
        case MotifDnDConstants.TOP_LEVEL_LEAVE:
            /* Receiver shouldn't rely to these messages. */
            return false;
        case MotifDnDConstants.DRAG_MOTION:
            switch (eventID) {
            case MouseEvent.MOUSE_ENTERED:
                response_reason = MotifDnDConstants.DROP_SITE_ENTER;
                break;
            case MouseEvent.MOUSE_DRAGGED:
                response_reason = MotifDnDConstants.DRAG_MOTION;
                break;
            case MouseEvent.MOUSE_EXITED:
                response_reason = MotifDnDConstants.DROP_SITE_LEAVE;
                break;
            }
            break;
        case MotifDnDConstants.OPERATION_CHANGED:
        case MotifDnDConstants.DROP_START:
            response_reason = reason;
            break;
        default:
            // Unknown reason. Shouldn't get here.
            assert false;
        }

        XClientMessageEvent msg = new XClientMessageEvent();

        try {
            msg.set_type(XConstants.ClientMessage);
            msg.set_window(MotifDnDConstants.Swapper.getInt(data + 12, eventByteOrder));
            msg.set_format(8);
            msg.set_message_type(MotifDnDConstants.XA_MOTIF_DRAG_AND_DROP_MESSAGE.getAtom());

            long responseData = msg.get_data();

            unsafe.putByte(responseData, (byte)(response_reason |
                           MotifDnDConstants.MOTIF_MESSAGE_FROM_RECEIVER));
            unsafe.putByte(responseData + 1, MotifDnDConstants.getByteOrderByte());

            int response_flags = 0;

            if (response_reason != MotifDnDConstants.DROP_SITE_LEAVE) {
                short flags = MotifDnDConstants.Swapper.getShort(data + 2,
                                                                 eventByteOrder);
                byte dropSiteStatus = (action == DnDConstants.ACTION_NONE) ?
                    MotifDnDConstants.MOTIF_INVALID_DROP_SITE :
                    MotifDnDConstants.MOTIF_VALID_DROP_SITE;

                /* Clear action and drop site status bits. */
                response_flags = flags &
                    ~MotifDnDConstants.MOTIF_DND_ACTION_MASK &
                    ~MotifDnDConstants.MOTIF_DND_STATUS_MASK;
                /* Fill in new action and drop site status. */
                response_flags |=
                    MotifDnDConstants.getMotifActionsForJavaActions(action) <<
                    MotifDnDConstants.MOTIF_DND_ACTION_SHIFT;
                response_flags |=
                    dropSiteStatus << MotifDnDConstants.MOTIF_DND_STATUS_SHIFT;
            } else {
                response_flags = 0;
            }

            unsafe.putShort(responseData + 2, (short)response_flags);

            /* Write time stamp. */
            int time = MotifDnDConstants.Swapper.getInt(data + 4, eventByteOrder);
            unsafe.putInt(responseData + 4, time);

            /* Write coordinates. */
            if (response_reason != MotifDnDConstants.DROP_SITE_LEAVE) {
                short x = MotifDnDConstants.Swapper.getShort(data + 8,
                                                             eventByteOrder);
                short y = MotifDnDConstants.Swapper.getShort(data + 10,
                                                             eventByteOrder);
                unsafe.putShort(responseData + 8, x); // x
                unsafe.putShort(responseData + 10, y); // y
            } else {
                unsafe.putShort(responseData + 8, (short)0); // x
                unsafe.putShort(responseData + 10, (short)0); // y
            }

            XToolkit.awtLock();
            try {
                XlibWrapper.XSendEvent(XToolkit.getDisplay(),
                                       msg.get_window(),
                                       false, XConstants.NoEventMask,
                                       msg.pData);
            } finally {
                XToolkit.awtUnlock();
            }
        } finally {
            msg.dispose();
        }

        return true;
    }

    public Object getData(long ctxt, long format)
      throws IllegalArgumentException, IOException {
        XClientMessageEvent xclient = new XClientMessageEvent(ctxt);

        if (xclient.get_message_type() !=
            MotifDnDConstants.XA_MOTIF_DRAG_AND_DROP_MESSAGE.getAtom()) {
            throw new IllegalArgumentException();
        }

        long data = xclient.get_data();
        byte reason = (byte)(unsafe.getByte(data) &
            MotifDnDConstants.MOTIF_MESSAGE_REASON_MASK);
        byte origin = (byte)(unsafe.getByte(data) &
            MotifDnDConstants.MOTIF_MESSAGE_SENDER_MASK);
        byte eventByteOrder = unsafe.getByte(data + 1);

        if (origin != MotifDnDConstants.MOTIF_MESSAGE_FROM_INITIATOR) {
            throw new IOException("Cannot get data: corrupted context");
        }

        long selatom = 0;

        switch (reason) {
        case MotifDnDConstants.DRAG_MOTION :
        case MotifDnDConstants.OPERATION_CHANGED :
            selatom = sourceAtom;
            break;
        case MotifDnDConstants.DROP_START :
            selatom = MotifDnDConstants.Swapper.getInt(data + 12, eventByteOrder);
            break;
        default:
            throw new IOException("Cannot get data: invalid message reason");
        }

        if (selatom == 0) {
            throw new IOException("Cannot get data: drag source property atom unavailable");
        }

        long time_stamp = MotifDnDConstants.Swapper.getInt(data + 4, eventByteOrder) & 0xffffffffL;
                          // with correction of (32-bit unsigned to 64-bit signed) implicit conversion.

        XAtom selectionAtom = XAtom.get(selatom);

        XSelection selection = XSelection.getSelection(selectionAtom);
        if (selection == null) {
            selection = new XSelection(selectionAtom);
        }

        return selection.getData(format, time_stamp);
    }

    public boolean sendDropDone(long ctxt, boolean success, int dropAction) {
        XClientMessageEvent xclient = new XClientMessageEvent(ctxt);

        if (xclient.get_message_type() !=
            MotifDnDConstants.XA_MOTIF_DRAG_AND_DROP_MESSAGE.getAtom()) {
            return false;
        }

        long data = xclient.get_data();
        byte reason = (byte)(unsafe.getByte(data) &
            MotifDnDConstants.MOTIF_MESSAGE_REASON_MASK);
        byte origin = (byte)(unsafe.getByte(data) &
            MotifDnDConstants.MOTIF_MESSAGE_SENDER_MASK);
        byte eventByteOrder = unsafe.getByte(data + 1);

        if (origin != MotifDnDConstants.MOTIF_MESSAGE_FROM_INITIATOR) {
            return false;
        }

        if (reason != MotifDnDConstants.DROP_START) {
            return false;
        }

        long time_stamp = MotifDnDConstants.Swapper.getInt(data + 4, eventByteOrder) & 0xffffffffL;
                          // with correction of (32-bit unsigned to 64-bit signed) implicit conversion.

        long sel_atom = MotifDnDConstants.Swapper.getInt(data + 12, eventByteOrder);

        long status_atom = 0;

        if (success) {
            status_atom = MotifDnDConstants.XA_XmTRANSFER_SUCCESS.getAtom();
        } else {
            status_atom = MotifDnDConstants.XA_XmTRANSFER_FAILURE.getAtom();
        }

        XToolkit.awtLock();
        try {
            XlibWrapper.XConvertSelection(XToolkit.getDisplay(),
                                          sel_atom,
                                          status_atom,
                                          MotifDnDConstants.XA_MOTIF_ATOM_0.getAtom(),
                                          XWindow.getXAWTRootWindow().getWindow(),
                                          time_stamp);

            /*
             * Flush the buffer to guarantee that the drop completion event is sent
             * to the source before the method returns.
             */
            XlibWrapper.XFlush(XToolkit.getDisplay());
        } finally {
            XToolkit.awtUnlock();
        }

        /* Trick to prevent cleanup() from posting dragExit */
        targetXWindow = null;

        /* Cannot do cleanup before the drop finishes as we may need
           source protocol version to send drop finished message. */
        cleanup();
        return true;
    }

    public final long getSourceWindow() {
        return sourceWindow;
    }

    /**
     * Reset the state of the object.
     */
    public void cleanup() {
        // Clear the reference to this protocol.
        XDropTargetEventProcessor.reset();

        if (targetXWindow != null) {
            notifyProtocolListener(targetXWindow, 0, 0,
                                   DnDConstants.ACTION_NONE, sourceActions,
                                   null, MouseEvent.MOUSE_EXITED);
        }

        if (sourceWindow != 0) {
            XToolkit.awtLock();
            try {
                XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
                XlibWrapper.XSelectInput(XToolkit.getDisplay(), sourceWindow,
                                         sourceWindowMask);
                XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
            } finally {
                XToolkit.awtUnlock();
            }
        }

        sourceWindow = 0;
        sourceWindowMask = 0;
        sourceProtocolVersion = 0;
        sourceActions = DnDConstants.ACTION_NONE;
        sourceFormats = null;
        sourceAtom = 0;
        userAction = DnDConstants.ACTION_NONE;
        sourceX = 0;
        sourceY = 0;
        targetXWindow = null;
        topLevelLeavePostponed = false;
    }

    public boolean isDragOverComponent() {
        return targetXWindow != null;
    }

    private void notifyProtocolListener(XWindow xwindow, int x, int y,
                                        int dropAction, int actions,
                                        XClientMessageEvent xclient,
                                        int eventID) {
        long nativeCtxt = 0;

        // Make a copy of the passed XClientMessageEvent structure, since
        // the original structure can be freed before this
        // SunDropTargetEvent is dispatched.
        if (xclient != null) {
            int size = XClientMessageEvent.getSize();

            nativeCtxt = unsafe.allocateMemory(size + 4 * Native.getLongSize());

            unsafe.copyMemory(xclient.pData, nativeCtxt, size);
        }

        getProtocolListener().handleDropTargetNotification(xwindow, x, y,
                                                           dropAction,
                                                           actions,
                                                           sourceFormats,
                                                           nativeCtxt,
                                                           eventID);
    }
}

Other Java examples (source code examples)

Here is a short list of links related to this Java MotifDnDDropTargetProtocol.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.