Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/classes/sun/awt/X11/MotifDnDConstants.java
32288 views
/*1* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.awt.X11;2627import java.awt.dnd.DnDConstants;2829import java.nio.ByteOrder;3031import java.util.Arrays;3233import sun.misc.Unsafe;3435/**36* Motif DnD protocol global constants and convenience routines.37*38* @since 1.539*/40class MotifDnDConstants {41// utility class can not be instantiated42private MotifDnDConstants() {}43// Note that offsets in all native structures below do not depend on the44// architecture.45private static final Unsafe unsafe = XlibWrapper.unsafe;46static final XAtom XA_MOTIF_ATOM_0 = XAtom.get("_MOTIF_ATOM_0");47static final XAtom XA_MOTIF_DRAG_WINDOW = XAtom.get("_MOTIF_DRAG_WINDOW");48static final XAtom XA_MOTIF_DRAG_TARGETS = XAtom.get("_MOTIF_DRAG_TARGETS");49static final XAtom XA_MOTIF_DRAG_INITIATOR_INFO =50XAtom.get("_MOTIF_DRAG_INITIATOR_INFO");51static final XAtom XA_MOTIF_DRAG_RECEIVER_INFO =52XAtom.get("_MOTIF_DRAG_RECEIVER_INFO");53static final XAtom XA_MOTIF_DRAG_AND_DROP_MESSAGE =54XAtom.get("_MOTIF_DRAG_AND_DROP_MESSAGE");55static final XAtom XA_XmTRANSFER_SUCCESS =56XAtom.get("XmTRANSFER_SUCCESS");57static final XAtom XA_XmTRANSFER_FAILURE =58XAtom.get("XmTRANSFER_FAILURE");59static final XSelection MotifDnDSelection = new XSelection(XA_MOTIF_ATOM_0);6061public static final byte MOTIF_DND_PROTOCOL_VERSION = 0;6263/* Supported protocol styles */64public static final int MOTIF_PREFER_PREREGISTER_STYLE = 2;65public static final int MOTIF_PREFER_DYNAMIC_STYLE = 4;66public static final int MOTIF_DYNAMIC_STYLE = 5;67public static final int MOTIF_PREFER_RECEIVER_STYLE = 6;6869/* Info structure sizes */70public static final int MOTIF_INITIATOR_INFO_SIZE = 8;71public static final int MOTIF_RECEIVER_INFO_SIZE = 16;7273/* Sender/reason message masks */74public static final byte MOTIF_MESSAGE_REASON_MASK = (byte)0x7F;75public static final byte MOTIF_MESSAGE_SENDER_MASK = (byte)0x80;76public static final byte MOTIF_MESSAGE_FROM_RECEIVER = (byte)0x80;77public static final byte MOTIF_MESSAGE_FROM_INITIATOR = (byte)0;7879/* Message flags masks and shifts */80public static final int MOTIF_DND_ACTION_MASK = 0x000F;81public static final int MOTIF_DND_ACTION_SHIFT = 0;82public static final int MOTIF_DND_STATUS_MASK = 0x00F0;83public static final int MOTIF_DND_STATUS_SHIFT = 4;84public static final int MOTIF_DND_ACTIONS_MASK = 0x0F00;85public static final int MOTIF_DND_ACTIONS_SHIFT = 8;8687/* message type constants */88public static final byte TOP_LEVEL_ENTER = 0;89public static final byte TOP_LEVEL_LEAVE = 1;90public static final byte DRAG_MOTION = 2;91public static final byte DROP_SITE_ENTER = 3;92public static final byte DROP_SITE_LEAVE = 4;93public static final byte DROP_START = 5;94public static final byte DROP_FINISH = 6;95public static final byte DRAG_DROP_FINISH = 7;96public static final byte OPERATION_CHANGED = 8;9798/* drop action constants */99public static final int MOTIF_DND_NOOP = 0;100public static final int MOTIF_DND_MOVE = 1 << 0;101public static final int MOTIF_DND_COPY = 1 << 1;102public static final int MOTIF_DND_LINK = 1 << 2;103104/* drop site status constants */105public static final byte MOTIF_NO_DROP_SITE = (byte)1;106public static final byte MOTIF_INVALID_DROP_SITE = (byte)2;107public static final byte MOTIF_VALID_DROP_SITE = (byte)3;108109private static long readMotifWindow() throws XException {110long defaultScreenNumber = XlibWrapper.DefaultScreen(XToolkit.getDisplay());111long defaultRootWindow =112XlibWrapper.RootWindow(XToolkit.getDisplay(), defaultScreenNumber);113114long motifWindow = 0;115116WindowPropertyGetter wpg = new WindowPropertyGetter(defaultRootWindow,117XA_MOTIF_DRAG_WINDOW,1180, 1,119false,120XConstants.AnyPropertyType);121try {122int status = wpg.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());123124if (status == XConstants.Success &&125wpg.getData() != 0 &&126wpg.getActualType() == XAtom.XA_WINDOW &&127wpg.getActualFormat() == 32 &&128wpg.getNumberOfItems() == 1) {129long data = wpg.getData();130// XID is CARD32.131motifWindow = Native.getLong(data);132}133134return motifWindow;135} finally {136wpg.dispose();137}138}139140private static long createMotifWindow() throws XException {141assert XToolkit.isAWTLockHeldByCurrentThread();142143long defaultScreenNumber =144XlibWrapper.DefaultScreen(XToolkit.getDisplay());145long defaultRootWindow =146XlibWrapper.RootWindow(XToolkit.getDisplay(), defaultScreenNumber);147148long motifWindow = 0;149150long displayString = XlibWrapper.XDisplayString(XToolkit.getDisplay());151152if (displayString == 0) {153throw new XException("XDisplayString returns NULL");154}155156long newDisplay = XlibWrapper.XOpenDisplay(displayString);157158if (newDisplay == 0) {159throw new XException("XOpenDisplay returns NULL");160}161162XlibWrapper.XGrabServer(newDisplay);163164try {165XlibWrapper.XSetCloseDownMode(newDisplay, (int)XConstants.RetainPermanent);166167XSetWindowAttributes xwa = new XSetWindowAttributes();168169try {170xwa.set_override_redirect(true);171xwa.set_event_mask(XConstants.PropertyChangeMask);172173motifWindow = XlibWrapper.XCreateWindow(newDisplay, defaultRootWindow,174-10, -10, 1, 1, 0, 0,175XConstants.InputOnly,176XConstants.CopyFromParent,177(XConstants.CWOverrideRedirect |178XConstants.CWEventMask),179xwa.pData);180181if (motifWindow == 0) {182throw new XException("XCreateWindow returns NULL");183}184185XlibWrapper.XMapWindow(newDisplay, motifWindow);186187long data = Native.allocateLongArray(1);188189try {190Native.putLong(data, motifWindow);191192XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());193XlibWrapper.XChangeProperty(XToolkit.getDisplay(),194defaultRootWindow,195XA_MOTIF_DRAG_WINDOW.getAtom(),196XAtom.XA_WINDOW, 32,197XConstants.PropModeReplace,198data, 1);199200XErrorHandlerUtil.RESTORE_XERROR_HANDLER();201202if ((XErrorHandlerUtil.saved_error != null) &&203(XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {204throw new XException("Cannot write motif drag window handle.");205}206207return motifWindow;208} finally {209unsafe.freeMemory(data);210}211} finally {212xwa.dispose();213}214} finally {215XlibWrapper.XUngrabServer(newDisplay);216XlibWrapper.XCloseDisplay(newDisplay);217}218}219220private static long getMotifWindow() throws XException {221/*222* Note: it is unsafe to cache the motif drag window handle, as another223* client can change the _MOTIF_DRAG_WINDOW property on the root, the handle224* becomes out-of-sync and all subsequent drag operations will fail.225*/226long motifWindow = readMotifWindow();227if (motifWindow == 0) {228motifWindow = createMotifWindow();229}230return motifWindow;231}232233public static final class Swapper {234// utility class can not be instantiated235private Swapper() {}236237public static short swap(short s) {238return (short)(((s & 0xFF00) >>> 8) | ((s & 0xFF) << 8));239}240public static int swap(int i) {241return ((i & 0xFF000000) >>> 24) | ((i & 0x00FF0000) >>> 8) |242((i & 0x0000FF00) << 8) | ((i & 0x000000FF) << 24);243}244245public static short getShort(long data, byte order) {246short s = unsafe.getShort(data);247if (order != MotifDnDConstants.getByteOrderByte()) {248return swap(s);249} else {250return s;251}252}253public static int getInt(long data, byte order) {254int i = unsafe.getInt(data);255if (order != MotifDnDConstants.getByteOrderByte()) {256return swap(i);257} else {258return i;259}260}261}262263/**264* DragBSI.h:265*266* typedef struct {267* BYTE byte_order;268* BYTE protocol_version;269* CARD16 num_target_lists B16;270* CARD32 heap_offset B32;271* } xmMotifTargetsPropertyRec;272*/273private static long[][] getTargetListTable(long motifWindow)274throws XException {275276WindowPropertyGetter wpg = new WindowPropertyGetter(motifWindow,277XA_MOTIF_DRAG_TARGETS,2780, 100000L,279false,280XA_MOTIF_DRAG_TARGETS.getAtom());281try {282int status = wpg.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());283284if (status != XConstants.Success285|| wpg.getActualType() != XA_MOTIF_DRAG_TARGETS.getAtom()286|| wpg.getData() == 0) {287288return null;289}290291long data = wpg.getData();292293if (unsafe.getByte(data + 1) != MOTIF_DND_PROTOCOL_VERSION) {294return null;295}296297boolean swapNeeded = unsafe.getByte(data + 0) != getByteOrderByte();298299short numTargetLists = unsafe.getShort(data + 2);300301if (swapNeeded) {302numTargetLists = Swapper.swap(numTargetLists);303}304305long[][] table = new long[numTargetLists][];306ByteOrder byteOrder = ByteOrder.nativeOrder();307if (swapNeeded) {308byteOrder = (byteOrder == ByteOrder.LITTLE_ENDIAN) ?309ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN;310}311312long bufptr = data + 8;313for (short i = 0; i < numTargetLists; i++) {314short numTargets = unsafe.getShort(bufptr);315bufptr += 2;316if (swapNeeded) {317numTargets = Swapper.swap(numTargets);318}319320table[i] = new long[numTargets];321322for (short j = 0; j < numTargets; j++) {323// NOTE: cannot use Unsafe.getInt(), since it crashes on324// Solaris/Sparc if the address is not a multiple of 4.325int target = 0;326if (byteOrder == ByteOrder.LITTLE_ENDIAN) {327for (int idx = 0; idx < 4; idx++) {328target |= (unsafe.getByte(bufptr + idx) << 8*idx)329& (0xFF << 8*idx);330}331} else {332for (int idx = 0; idx < 4; idx++) {333target |= (unsafe.getByte(bufptr + idx) << 8*(3-idx))334& (0xFF << 8*(3-idx));335}336}337// NOTE: don't need to swap, since we read it in the proper338// order already.339table[i][j] = target;340bufptr += 4;341}342}343return table;344} finally {345wpg.dispose();346}347}348349private static void putTargetListTable(long motifWindow, long[][] table)350throws XException {351assert XToolkit.isAWTLockHeldByCurrentThread();352353int tableSize = 8; /* The size of leading xmMotifTargetsPropertyRec. */354355for (int i = 0; i < table.length; i++) {356tableSize += table[i].length * 4 + 2;357}358359long data = unsafe.allocateMemory(tableSize);360361try {362// BYTE byte_order;363unsafe.putByte(data + 0, getByteOrderByte());364// BYTE protocol_version;365unsafe.putByte(data + 1, MOTIF_DND_PROTOCOL_VERSION);366// CARD16 num_target_lists B16;367unsafe.putShort(data + 2, (short)table.length);368// CARD32 heap_offset B32;369unsafe.putInt(data + 4, tableSize);370371long bufptr = data + 8;372373for (int i = 0; i < table.length; i++) {374unsafe.putShort(bufptr, (short)table[i].length);375bufptr += 2;376377for (int j = 0; j < table[i].length; j++) {378int target = (int)table[i][j];379// NOTE: cannot use Unsafe.putInt(), since it crashes on380// Solaris/Sparc if the address is not a multiple of 4.381if (ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN) {382for (int idx = 0; idx < 4; idx++) {383byte b = (byte)((target & (0xFF << (8*idx))) >> (8*idx));384unsafe.putByte(bufptr + idx, b);385}386} else {387for (int idx = 0; idx < 4; idx++) {388byte b = (byte)((target & (0xFF << (8*idx))) >> (8*idx));389unsafe.putByte(bufptr + (3-idx), b);390}391}392bufptr += 4;393}394}395396XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());397XlibWrapper.XChangeProperty(XToolkit.getDisplay(),398motifWindow,399XA_MOTIF_DRAG_TARGETS.getAtom(),400XA_MOTIF_DRAG_TARGETS.getAtom(), 8,401XConstants.PropModeReplace,402data, tableSize);403404XErrorHandlerUtil.RESTORE_XERROR_HANDLER();405406if ((XErrorHandlerUtil.saved_error != null) &&407(XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {408409// Create a new motif window and retry.410motifWindow = createMotifWindow();411412XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());413XlibWrapper.XChangeProperty(XToolkit.getDisplay(),414motifWindow,415XA_MOTIF_DRAG_TARGETS.getAtom(),416XA_MOTIF_DRAG_TARGETS.getAtom(), 8,417XConstants.PropModeReplace,418data, tableSize);419420XErrorHandlerUtil.RESTORE_XERROR_HANDLER();421422if ((XErrorHandlerUtil.saved_error != null) &&423(XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {424throw new XException("Cannot write motif drag targets property.");425}426}427} finally {428unsafe.freeMemory(data);429}430}431432static int getIndexForTargetList(long[] formats) throws XException {433assert XToolkit.isAWTLockHeldByCurrentThread();434435if (formats.length > 0) {436// Make a defensive copy.437formats = (long[])formats.clone();438439Arrays.sort(formats);440}441442// NOTE: getMotifWindow() should never be called if the server is443// grabbed. This will lock up the application as it grabs the server444// itself.445// Since we don't grab the server before getMotifWindow(), another446// client might replace motif window after we read it from the root, but447// before we grab the server.448// We cannot resolve this problem, but we believe that this scenario is449// very unlikely to happen.450long motifWindow = getMotifWindow();451452XlibWrapper.XGrabServer(XToolkit.getDisplay());453454try {455long[][] table = getTargetListTable(motifWindow);456457if (table != null) {458for (int i = 0; i < table.length; i++) {459boolean equals = true;460if (table[i].length == formats.length) {461for (int j = 0; j < table[i].length; j++) {462if (table[i][j] != formats[j]) {463equals = false;464break;465}466}467} else {468equals = false;469}470471if (equals) {472XlibWrapper.XUngrabServer(XToolkit.getDisplay());473return i;474}475}476} else {477// Create a new table.478// The first two entries must always be the same.479// (see DragBS.c)480table = new long[2][];481table[0] = new long[] { 0 };482table[1] = new long[] { XAtom.XA_STRING };483}484485/* Index not found - expand the targets table. */486long[][] new_table = new long[table.length + 1][];487488/* Copy the old contents to the new table. */489for (int i = 0; i < table.length; i++) {490new_table[i] = table[i];491}492493/* Fill in the new entry */494new_table[new_table.length - 1] = formats;495496putTargetListTable(motifWindow, new_table);497498return new_table.length - 1;499} finally {500XlibWrapper.XUngrabServer(XToolkit.getDisplay());501}502}503504static long[] getTargetListForIndex(int index) {505long motifWindow = getMotifWindow();506long[][] table = getTargetListTable(motifWindow);507508if (index < 0 || index >= table.length) {509return new long[0];510} else {511return table[index];512}513}514515static byte getByteOrderByte() {516// 'l' - for little endian, 'B' - for big endian.517return ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN ?518(byte)0x6C : (byte)0x42;519}520521static void writeDragInitiatorInfoStruct(long window, int index) throws XException {522assert XToolkit.isAWTLockHeldByCurrentThread();523524long structData = unsafe.allocateMemory(MOTIF_INITIATOR_INFO_SIZE);525526try {527// BYTE byte_order528unsafe.putByte(structData, getByteOrderByte());529// BYTE protocol_version530unsafe.putByte(structData + 1, MOTIF_DND_PROTOCOL_VERSION);531// CARD16 protocol_version532unsafe.putShort(structData + 2, (short)index);533// CARD32 icc_handle534unsafe.putInt(structData + 4, (int)XA_MOTIF_ATOM_0.getAtom());535536XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());537XlibWrapper.XChangeProperty(XToolkit.getDisplay(), window,538XA_MOTIF_ATOM_0.getAtom(),539XA_MOTIF_DRAG_INITIATOR_INFO.getAtom(),5408, XConstants.PropModeReplace,541structData, MOTIF_INITIATOR_INFO_SIZE);542XErrorHandlerUtil.RESTORE_XERROR_HANDLER();543544if ((XErrorHandlerUtil.saved_error != null) &&545(XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {546throw new XException("Cannot write drag initiator info");547}548} finally {549unsafe.freeMemory(structData);550}551}552553static void writeDragReceiverInfoStruct(long window) throws XException {554assert XToolkit.isAWTLockHeldByCurrentThread();555556int dataSize = MotifDnDConstants.MOTIF_RECEIVER_INFO_SIZE;557long data = unsafe.allocateMemory(dataSize);558559try {560unsafe.putByte(data, MotifDnDConstants.getByteOrderByte()); /* byte order */561unsafe.putByte(data + 1, MotifDnDConstants.MOTIF_DND_PROTOCOL_VERSION); /* protocol version */562unsafe.putByte(data + 2, (byte)MotifDnDConstants.MOTIF_DYNAMIC_STYLE); /* protocol style */563unsafe.putByte(data + 3, (byte)0); /* pad */564unsafe.putInt(data + 4, (int)window); /* proxy window */565unsafe.putShort(data + 8, (short)0); /* num_drop_sites */566unsafe.putShort(data + 10, (short)0); /* pad */567unsafe.putInt(data + 12, dataSize);568569XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());570XlibWrapper.XChangeProperty(XToolkit.getDisplay(), window,571XA_MOTIF_DRAG_RECEIVER_INFO.getAtom(),572XA_MOTIF_DRAG_RECEIVER_INFO.getAtom(),5738, XConstants.PropModeReplace,574data, dataSize);575XErrorHandlerUtil.RESTORE_XERROR_HANDLER();576577if ((XErrorHandlerUtil.saved_error != null) &&578(XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {579throw new XException("Cannot write Motif receiver info property");580}581} finally {582unsafe.freeMemory(data);583}584}585586public static int getMotifActionsForJavaActions(int javaActions) {587int motifActions = MOTIF_DND_NOOP;588589if ((javaActions & DnDConstants.ACTION_MOVE) != 0) {590motifActions |= MOTIF_DND_MOVE;591}592if ((javaActions & DnDConstants.ACTION_COPY) != 0) {593motifActions |= MOTIF_DND_COPY;594}595if ((javaActions & DnDConstants.ACTION_LINK) != 0) {596motifActions |= MOTIF_DND_LINK;597}598599return motifActions;600}601602public static int getJavaActionsForMotifActions(int motifActions) {603int javaActions = DnDConstants.ACTION_NONE;604605if ((motifActions & MOTIF_DND_MOVE) != 0) {606javaActions |= DnDConstants.ACTION_MOVE;607}608if ((motifActions & MOTIF_DND_COPY) != 0) {609javaActions |= DnDConstants.ACTION_COPY;610}611if ((motifActions & MOTIF_DND_LINK) != 0) {612javaActions |= DnDConstants.ACTION_LINK;613}614615return javaActions;616}617}618619620