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

Java example source code file (MotifDnDConstants.java)

This example Java source code file (MotifDnDConstants.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, motif_dnd_copy, motif_dnd_link, motif_dnd_move, motif_dnd_noop, motif_dnd_protocol_version, motif_initiator_info_size, nio, null, swapper, util, windowpropertygetter, xa_motif_drag_window, xatom, xexception, xselection

The MotifDnDConstants.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.dnd.DnDConstants;

import java.nio.ByteOrder;

import java.util.Arrays;

import sun.misc.Unsafe;

/**
 * Motif DnD protocol global constants and convenience routines.
 *
 * @since 1.5
 */
class MotifDnDConstants {
    // utility class can not be instantiated
    private MotifDnDConstants() {}
    // Note that offsets in all native structures below do not depend on the
    // architecture.
    private static final Unsafe unsafe = XlibWrapper.unsafe;
    static final XAtom XA_MOTIF_ATOM_0 = XAtom.get("_MOTIF_ATOM_0");
    static final XAtom XA_MOTIF_DRAG_WINDOW = XAtom.get("_MOTIF_DRAG_WINDOW");
    static final XAtom XA_MOTIF_DRAG_TARGETS = XAtom.get("_MOTIF_DRAG_TARGETS");
    static final XAtom XA_MOTIF_DRAG_INITIATOR_INFO =
        XAtom.get("_MOTIF_DRAG_INITIATOR_INFO");
    static final XAtom XA_MOTIF_DRAG_RECEIVER_INFO =
        XAtom.get("_MOTIF_DRAG_RECEIVER_INFO");
    static final XAtom XA_MOTIF_DRAG_AND_DROP_MESSAGE =
        XAtom.get("_MOTIF_DRAG_AND_DROP_MESSAGE");
    static final XAtom XA_XmTRANSFER_SUCCESS =
        XAtom.get("XmTRANSFER_SUCCESS");
    static final XAtom XA_XmTRANSFER_FAILURE =
        XAtom.get("XmTRANSFER_FAILURE");
    static final XSelection MotifDnDSelection = new XSelection(XA_MOTIF_ATOM_0);

    public static final byte MOTIF_DND_PROTOCOL_VERSION = 0;

    /* Supported protocol styles */
    public static final int MOTIF_PREFER_PREREGISTER_STYLE = 2;
    public static final int MOTIF_PREFER_DYNAMIC_STYLE     = 4;
    public static final int MOTIF_DYNAMIC_STYLE            = 5;
    public static final int MOTIF_PREFER_RECEIVER_STYLE    = 6;

    /* Info structure sizes */
    public static final int MOTIF_INITIATOR_INFO_SIZE      = 8;
    public static final int MOTIF_RECEIVER_INFO_SIZE       = 16;

    /* Sender/reason message masks */
    public static final byte MOTIF_MESSAGE_REASON_MASK      = (byte)0x7F;
    public static final byte MOTIF_MESSAGE_SENDER_MASK      = (byte)0x80;
    public static final byte MOTIF_MESSAGE_FROM_RECEIVER    = (byte)0x80;
    public static final byte MOTIF_MESSAGE_FROM_INITIATOR   = (byte)0;

    /* Message flags masks and shifts */
    public static final int MOTIF_DND_ACTION_MASK   = 0x000F;
    public static final int MOTIF_DND_ACTION_SHIFT  =      0;
    public static final int MOTIF_DND_STATUS_MASK   = 0x00F0;
    public static final int MOTIF_DND_STATUS_SHIFT  =      4;
    public static final int MOTIF_DND_ACTIONS_MASK  = 0x0F00;
    public static final int MOTIF_DND_ACTIONS_SHIFT =      8;

    /* message type constants */
    public static final byte TOP_LEVEL_ENTER   = 0;
    public static final byte TOP_LEVEL_LEAVE   = 1;
    public static final byte DRAG_MOTION       = 2;
    public static final byte DROP_SITE_ENTER   = 3;
    public static final byte DROP_SITE_LEAVE   = 4;
    public static final byte DROP_START        = 5;
    public static final byte DROP_FINISH       = 6;
    public static final byte DRAG_DROP_FINISH  = 7;
    public static final byte OPERATION_CHANGED = 8;

    /* drop action constants */
    public static final int MOTIF_DND_NOOP = 0;
    public static final int MOTIF_DND_MOVE = 1 << 0;
    public static final int MOTIF_DND_COPY = 1 << 1;
    public static final int MOTIF_DND_LINK = 1 << 2;

    /* drop site status constants */
    public static final byte MOTIF_NO_DROP_SITE      = (byte)1;
    public static final byte MOTIF_INVALID_DROP_SITE = (byte)2;
    public static final byte MOTIF_VALID_DROP_SITE   = (byte)3;

    private static long readMotifWindow() throws XException {
        long defaultScreenNumber = XlibWrapper.DefaultScreen(XToolkit.getDisplay());
        long defaultRootWindow =
            XlibWrapper.RootWindow(XToolkit.getDisplay(), defaultScreenNumber);

        long motifWindow = 0;

        WindowPropertyGetter wpg = new WindowPropertyGetter(defaultRootWindow,
                                                            XA_MOTIF_DRAG_WINDOW,
                                                            0, 1,
                                                            false,
                                                            XConstants.AnyPropertyType);
        try {
            int status = wpg.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());

            if (status == XConstants.Success &&
                wpg.getData() != 0 &&
                wpg.getActualType() == XAtom.XA_WINDOW &&
                wpg.getActualFormat() == 32 &&
                wpg.getNumberOfItems() == 1) {
                long data = wpg.getData();
                // XID is CARD32.
                motifWindow = Native.getLong(data);
            }

            return motifWindow;
        } finally {
            wpg.dispose();
        }
    }

    private static long createMotifWindow() throws XException {
        assert XToolkit.isAWTLockHeldByCurrentThread();

        long defaultScreenNumber =
            XlibWrapper.DefaultScreen(XToolkit.getDisplay());
        long defaultRootWindow =
            XlibWrapper.RootWindow(XToolkit.getDisplay(), defaultScreenNumber);

        long motifWindow = 0;

        long displayString = XlibWrapper.XDisplayString(XToolkit.getDisplay());

        if (displayString == 0) {
            throw new XException("XDisplayString returns NULL");
        }

        long newDisplay = XlibWrapper.XOpenDisplay(displayString);

        if (newDisplay == 0) {
            throw new XException("XOpenDisplay returns NULL");
        }

        XlibWrapper.XGrabServer(newDisplay);

        try {
            XlibWrapper.XSetCloseDownMode(newDisplay, (int)XConstants.RetainPermanent);

            XSetWindowAttributes xwa = new XSetWindowAttributes();

            try {
                xwa.set_override_redirect(true);
                xwa.set_event_mask(XConstants.PropertyChangeMask);

                motifWindow = XlibWrapper.XCreateWindow(newDisplay, defaultRootWindow,
                                                        -10, -10, 1, 1, 0, 0,
                                                        XConstants.InputOnly,
                                                        XConstants.CopyFromParent,
                                                        (XConstants.CWOverrideRedirect |
                                                         XConstants.CWEventMask),
                                                        xwa.pData);

                if (motifWindow == 0) {
                    throw new XException("XCreateWindow returns NULL");
                }

                XlibWrapper.XMapWindow(newDisplay, motifWindow);

                long data = Native.allocateLongArray(1);

                try {
                    Native.putLong(data, motifWindow);

                    XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
                    XlibWrapper.XChangeProperty(XToolkit.getDisplay(),
                                                defaultRootWindow,
                                                XA_MOTIF_DRAG_WINDOW.getAtom(),
                                                XAtom.XA_WINDOW, 32,
                                                XConstants.PropModeReplace,
                                                data, 1);

                    XErrorHandlerUtil.RESTORE_XERROR_HANDLER();

                    if ((XErrorHandlerUtil.saved_error != null) &&
                        (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
                        throw new XException("Cannot write motif drag window handle.");
                    }

                    return motifWindow;
                } finally {
                    unsafe.freeMemory(data);
                }
            } finally {
                xwa.dispose();
            }
        } finally {
            XlibWrapper.XUngrabServer(newDisplay);
            XlibWrapper.XCloseDisplay(newDisplay);
        }
    }

    private static long getMotifWindow() throws XException {
        /*
         * Note: it is unsafe to cache the motif drag window handle, as another
         * client can change the _MOTIF_DRAG_WINDOW property on the root, the handle
         * becomes out-of-sync and all subsequent drag operations will fail.
         */
        long motifWindow = readMotifWindow();
        if (motifWindow == 0) {
            motifWindow = createMotifWindow();
        }
        return motifWindow;
    }

    public static final class Swapper {
        // utility class can not be instantiated
        private Swapper() {}

        public static short swap(short s) {
            return (short)(((s & 0xFF00) >>> 8) | ((s & 0xFF) << 8));
        }
        public static int swap(int i) {
            return ((i & 0xFF000000) >>> 24) | ((i & 0x00FF0000) >>> 8) |
                ((i & 0x0000FF00) << 8) | ((i & 0x000000FF) << 24);
        }

        public static short getShort(long data, byte order) {
            short s = unsafe.getShort(data);
            if (order != MotifDnDConstants.getByteOrderByte()) {
                return swap(s);
            } else {
                return s;
            }
        }
        public static int getInt(long data, byte order) {
            int i = unsafe.getInt(data);
            if (order != MotifDnDConstants.getByteOrderByte()) {
                return swap(i);
            } else {
                return i;
            }
        }
    }

    /**
     * DragBSI.h:
     *
     * typedef struct {
     *    BYTE          byte_order;
     *    BYTE          protocol_version;
     *    CARD16        num_target_lists B16;
     *    CARD32        heap_offset B32;
     * } xmMotifTargetsPropertyRec;
     */
    private static long[][] getTargetListTable(long motifWindow)
      throws XException {

        WindowPropertyGetter wpg = new WindowPropertyGetter(motifWindow,
                                                            XA_MOTIF_DRAG_TARGETS,
                                                            0, 100000L,
                                                            false,
                                                            XA_MOTIF_DRAG_TARGETS.getAtom());
        try {
            int status = wpg.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());

            if (status != XConstants.Success
                || wpg.getActualType() != XA_MOTIF_DRAG_TARGETS.getAtom()
                || wpg.getData() == 0) {

                return null;
            }

            long data = wpg.getData();

            if (unsafe.getByte(data + 1) != MOTIF_DND_PROTOCOL_VERSION) {
                return null;
            }

            boolean swapNeeded = unsafe.getByte(data + 0) != getByteOrderByte();

            short numTargetLists = unsafe.getShort(data + 2);

            if (swapNeeded) {
                numTargetLists = Swapper.swap(numTargetLists);
            }

            long[][] table = new long[numTargetLists][];
            ByteOrder byteOrder = ByteOrder.nativeOrder();
            if (swapNeeded) {
                byteOrder = (byteOrder == ByteOrder.LITTLE_ENDIAN) ?
                    ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN;
            }

            long bufptr = data + 8;
            for (short i = 0; i < numTargetLists; i++) {
                short numTargets = unsafe.getShort(bufptr);
                bufptr += 2;
                if (swapNeeded) {
                    numTargets = Swapper.swap(numTargets);
                }

                table[i] = new long[numTargets];

                for (short j = 0; j < numTargets; j++) {
                    // NOTE: cannot use Unsafe.getInt(), since it crashes on
                    // Solaris/Sparc if the address is not a multiple of 4.
                    int target = 0;
                    if (byteOrder == ByteOrder.LITTLE_ENDIAN) {
                        for (int idx = 0; idx < 4; idx++) {
                            target |= (unsafe.getByte(bufptr + idx) << 8*idx)
                                & (0xFF << 8*idx);
                        }
                    } else {
                        for (int idx = 0; idx < 4; idx++) {
                            target |= (unsafe.getByte(bufptr + idx) << 8*(3-idx))
                                & (0xFF << 8*(3-idx));
                        }
                    }
                    // NOTE: don't need to swap, since we read it in the proper
                    // order already.
                    table[i][j] = target;
                    bufptr += 4;
                }
            }
            return table;
        } finally {
            wpg.dispose();
        }
    }

    private static void putTargetListTable(long motifWindow, long[][] table)
      throws XException {
        assert XToolkit.isAWTLockHeldByCurrentThread();

        int tableSize = 8; /* The size of leading xmMotifTargetsPropertyRec. */

        for (int i = 0; i < table.length; i++) {
            tableSize += table[i].length * 4 + 2;
        }

        long data = unsafe.allocateMemory(tableSize);

        try {
            // BYTE          byte_order;
            unsafe.putByte(data + 0, getByteOrderByte());
            // BYTE          protocol_version;
            unsafe.putByte(data + 1, MOTIF_DND_PROTOCOL_VERSION);
            // CARD16        num_target_lists B16;
            unsafe.putShort(data + 2, (short)table.length);
            // CARD32        heap_offset B32;
            unsafe.putInt(data + 4, tableSize);

            long bufptr = data + 8;

            for (int i = 0; i < table.length; i++) {
                unsafe.putShort(bufptr, (short)table[i].length);
                bufptr += 2;

                for (int j = 0; j < table[i].length; j++) {
                    int target = (int)table[i][j];
                    // NOTE: cannot use Unsafe.putInt(), since it crashes on
                    // Solaris/Sparc if the address is not a multiple of 4.
                    if (ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN) {
                        for (int idx = 0; idx < 4; idx++) {
                            byte b = (byte)((target & (0xFF << (8*idx))) >> (8*idx));
                            unsafe.putByte(bufptr + idx, b);
                        }
                    } else {
                        for (int idx = 0; idx < 4; idx++) {
                            byte b = (byte)((target & (0xFF << (8*idx))) >> (8*idx));
                            unsafe.putByte(bufptr + (3-idx), b);
                        }
                    }
                    bufptr += 4;
                }
            }

            XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
            XlibWrapper.XChangeProperty(XToolkit.getDisplay(),
                                        motifWindow,
                                        XA_MOTIF_DRAG_TARGETS.getAtom(),
                                        XA_MOTIF_DRAG_TARGETS.getAtom(), 8,
                                        XConstants.PropModeReplace,
                                        data, tableSize);

            XErrorHandlerUtil.RESTORE_XERROR_HANDLER();

            if ((XErrorHandlerUtil.saved_error != null) &&
                (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {

                // Create a new motif window and retry.
                motifWindow = createMotifWindow();

                XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
                XlibWrapper.XChangeProperty(XToolkit.getDisplay(),
                                            motifWindow,
                                            XA_MOTIF_DRAG_TARGETS.getAtom(),
                                            XA_MOTIF_DRAG_TARGETS.getAtom(), 8,
                                            XConstants.PropModeReplace,
                                            data, tableSize);

                XErrorHandlerUtil.RESTORE_XERROR_HANDLER();

                if ((XErrorHandlerUtil.saved_error != null) &&
                    (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
                    throw new XException("Cannot write motif drag targets property.");
                }
            }
        } finally {
            unsafe.freeMemory(data);
        }
    }

    static int getIndexForTargetList(long[] formats) throws XException {
        assert XToolkit.isAWTLockHeldByCurrentThread();

        if (formats.length > 0) {
            // Make a defensive copy.
            formats = (long[])formats.clone();

            Arrays.sort(formats);
        }

        // NOTE: getMotifWindow() should never be called if the server is
        // grabbed. This will lock up the application as it grabs the server
        // itself.
        // Since we don't grab the server before getMotifWindow(), another
        // client might replace motif window after we read it from the root, but
        // before we grab the server.
        // We cannot resolve this problem, but we believe that this scenario is
        // very unlikely to happen.
        long motifWindow = getMotifWindow();

        XlibWrapper.XGrabServer(XToolkit.getDisplay());

        try {
            long[][] table = getTargetListTable(motifWindow);

            if (table != null) {
                for (int i = 0; i < table.length; i++) {
                    boolean equals = true;
                    if (table[i].length == formats.length) {
                        for (int j = 0; j < table[i].length; j++) {
                            if (table[i][j] != formats[j]) {
                                equals = false;
                                break;
                            }
                        }
                    } else {
                        equals = false;
                    }

                    if (equals) {
                        XlibWrapper.XUngrabServer(XToolkit.getDisplay());
                        return i;
                    }
                }
            } else {
                // Create a new table.
                // The first two entries must always be the same.
                // (see DragBS.c)
                table = new long[2][];
                table[0] = new long[] { 0 };
                table[1] = new long[] { XAtom.XA_STRING };
            }

            /* Index not found - expand the targets table. */
            long[][] new_table = new long[table.length + 1][];

            /* Copy the old contents to the new table. */
            for (int i = 0; i < table.length; i++) {
                new_table[i] = table[i];
            }

            /* Fill in the new entry */
            new_table[new_table.length - 1] = formats;

            putTargetListTable(motifWindow, new_table);

            return new_table.length - 1;
        } finally {
            XlibWrapper.XUngrabServer(XToolkit.getDisplay());
        }
    }

    static long[] getTargetListForIndex(int index) {
        long motifWindow = getMotifWindow();
        long[][] table = getTargetListTable(motifWindow);

        if (index < 0 || index >= table.length) {
            return new long[0];
        } else {
            return table[index];
        }
    }

    static byte getByteOrderByte() {
        // 'l' - for little endian, 'B' - for big endian.
        return ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN ?
            (byte)0x6C : (byte)0x42;
    }

    static void writeDragInitiatorInfoStruct(long window, int index) throws XException {
        assert XToolkit.isAWTLockHeldByCurrentThread();

        long structData = unsafe.allocateMemory(MOTIF_INITIATOR_INFO_SIZE);

        try {
            // BYTE byte_order
            unsafe.putByte(structData, getByteOrderByte());
            // BYTE protocol_version
            unsafe.putByte(structData + 1, MOTIF_DND_PROTOCOL_VERSION);
            // CARD16 protocol_version
            unsafe.putShort(structData + 2, (short)index);
            // CARD32 icc_handle
            unsafe.putInt(structData + 4, (int)XA_MOTIF_ATOM_0.getAtom());

            XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
            XlibWrapper.XChangeProperty(XToolkit.getDisplay(), window,
                                        XA_MOTIF_ATOM_0.getAtom(),
                                        XA_MOTIF_DRAG_INITIATOR_INFO.getAtom(),
                                        8, XConstants.PropModeReplace,
                                        structData, MOTIF_INITIATOR_INFO_SIZE);
            XErrorHandlerUtil.RESTORE_XERROR_HANDLER();

            if ((XErrorHandlerUtil.saved_error != null) &&
                (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
                throw new XException("Cannot write drag initiator info");
            }
        } finally {
            unsafe.freeMemory(structData);
        }
    }

    static void writeDragReceiverInfoStruct(long window) throws XException {
        assert XToolkit.isAWTLockHeldByCurrentThread();

        int dataSize = MotifDnDConstants.MOTIF_RECEIVER_INFO_SIZE;
        long data = unsafe.allocateMemory(dataSize);

        try {
            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)window); /* 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(), window,
                                        XA_MOTIF_DRAG_RECEIVER_INFO.getAtom(),
                                        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 {
            unsafe.freeMemory(data);
        }
    }

    public static int getMotifActionsForJavaActions(int javaActions) {
        int motifActions = MOTIF_DND_NOOP;

        if ((javaActions & DnDConstants.ACTION_MOVE) != 0) {
            motifActions |= MOTIF_DND_MOVE;
        }
        if ((javaActions & DnDConstants.ACTION_COPY) != 0) {
            motifActions |= MOTIF_DND_COPY;
        }
        if ((javaActions & DnDConstants.ACTION_LINK) != 0) {
            motifActions |= MOTIF_DND_LINK;
        }

        return motifActions;
    }

    public static int getJavaActionsForMotifActions(int motifActions) {
        int javaActions = DnDConstants.ACTION_NONE;

        if ((motifActions & MOTIF_DND_MOVE) != 0) {
            javaActions |= DnDConstants.ACTION_MOVE;
        }
        if ((motifActions & MOTIF_DND_COPY) != 0) {
            javaActions |= DnDConstants.ACTION_COPY;
        }
        if ((motifActions & MOTIF_DND_LINK) != 0) {
            javaActions |= DnDConstants.ACTION_LINK;
        }

        return javaActions;
    }
}

Other Java examples (source code examples)

Here is a short list of links related to this Java MotifDnDConstants.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.