jdk/src/solaris/classes/sun/awt/X11/MotifDnDDropTargetProtocol.java
changeset 2 90ce3da70b43
child 117 766ae458aaf1
equal deleted inserted replaced
0:fd16c54261b3 2:90ce3da70b43
       
     1 /*
       
     2  * Copyright 2003-2007 Sun Microsystems, Inc.  All Rights Reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Sun designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Sun in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    22  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    23  * have any questions.
       
    24  */
       
    25 
       
    26 package sun.awt.X11;
       
    27 
       
    28 import java.awt.Point;
       
    29 
       
    30 import java.awt.dnd.DnDConstants;
       
    31 
       
    32 import java.awt.event.MouseEvent;
       
    33 
       
    34 import java.io.IOException;
       
    35 
       
    36 import sun.misc.Unsafe;
       
    37 
       
    38 /**
       
    39  * XDropTargetProtocol implementation for Motif DnD protocol.
       
    40  *
       
    41  * @since 1.5
       
    42  */
       
    43 class MotifDnDDropTargetProtocol extends XDropTargetProtocol {
       
    44     private static final Unsafe unsafe = XlibWrapper.unsafe;
       
    45 
       
    46     private long sourceWindow = 0;
       
    47     private long sourceWindowMask = 0;
       
    48     private int sourceProtocolVersion = 0;
       
    49     private int sourceActions = DnDConstants.ACTION_NONE;
       
    50     private long[] sourceFormats = null;
       
    51     private long sourceAtom = 0;
       
    52     private int userAction = DnDConstants.ACTION_NONE;
       
    53     private int sourceX = 0;
       
    54     private int sourceY = 0;
       
    55     private XWindow targetXWindow = null;
       
    56     private boolean topLevelLeavePostponed = false;
       
    57 
       
    58     protected MotifDnDDropTargetProtocol(XDropTargetProtocolListener listener) {
       
    59         super(listener);
       
    60     }
       
    61 
       
    62     /**
       
    63      * Creates an instance associated with the specified listener.
       
    64      *
       
    65      * @throws NullPointerException if listener is <code>null</code>.
       
    66      */
       
    67     static XDropTargetProtocol createInstance(XDropTargetProtocolListener listener) {
       
    68         return new MotifDnDDropTargetProtocol(listener);
       
    69     }
       
    70 
       
    71     public String getProtocolName() {
       
    72         return XDragAndDropProtocols.MotifDnD;
       
    73     }
       
    74 
       
    75     public void registerDropTarget(long window) {
       
    76         assert XToolkit.isAWTLockHeldByCurrentThread();
       
    77 
       
    78         MotifDnDConstants.writeDragReceiverInfoStruct(window);
       
    79     }
       
    80 
       
    81     public void unregisterDropTarget(long window) {
       
    82         assert XToolkit.isAWTLockHeldByCurrentThread();
       
    83 
       
    84         MotifDnDConstants.XA_MOTIF_ATOM_0.DeleteProperty(window);
       
    85     }
       
    86 
       
    87     public void registerEmbedderDropSite(long embedder) {
       
    88         assert XToolkit.isAWTLockHeldByCurrentThread();
       
    89 
       
    90         boolean overriden = false;
       
    91         int version = 0;
       
    92         long proxy = 0;
       
    93         long newProxy = XDropTargetRegistry.getDnDProxyWindow();
       
    94         int status = 0;
       
    95         long data = 0;
       
    96         int dataSize = MotifDnDConstants.MOTIF_RECEIVER_INFO_SIZE;
       
    97 
       
    98         WindowPropertyGetter wpg =
       
    99             new WindowPropertyGetter(embedder,
       
   100                                      MotifDnDConstants.XA_MOTIF_DRAG_RECEIVER_INFO,
       
   101                                      0, 0xFFFF, false,
       
   102                                      XlibWrapper.AnyPropertyType);
       
   103 
       
   104         try {
       
   105             status = wpg.execute(XToolkit.IgnoreBadWindowHandler);
       
   106 
       
   107             /*
       
   108              * DragICCI.h:
       
   109              *
       
   110              * typedef struct _xmDragReceiverInfoStruct{
       
   111              *     BYTE byte_order;
       
   112              *     BYTE protocol_version;
       
   113              *     BYTE drag_protocol_style;
       
   114              *     BYTE pad1;
       
   115              *     CARD32       proxy_window B32;
       
   116              *     CARD16       num_drop_sites B16;
       
   117              *     CARD16       pad2 B16;
       
   118              *     CARD32       heap_offset B32;
       
   119              * } xmDragReceiverInfoStruct;
       
   120              */
       
   121             if (status == (int)XlibWrapper.Success && wpg.getData() != 0 &&
       
   122                 wpg.getActualType() != 0 && wpg.getActualFormat() == 8 &&
       
   123                 wpg.getNumberOfItems() >=
       
   124                 MotifDnDConstants.MOTIF_RECEIVER_INFO_SIZE) {
       
   125 
       
   126                 overriden = true;
       
   127                 data = wpg.getData();
       
   128                 dataSize = wpg.getNumberOfItems();
       
   129 
       
   130                 byte byteOrderByte = unsafe.getByte(data);
       
   131 
       
   132                 {
       
   133                     int tproxy = unsafe.getInt(data + 4);
       
   134                     if (byteOrderByte != MotifDnDConstants.getByteOrderByte()) {
       
   135                         tproxy = MotifDnDConstants.Swapper.swap(tproxy);
       
   136                     }
       
   137                     proxy = tproxy;
       
   138                 }
       
   139 
       
   140                 if (proxy == newProxy) {
       
   141                     // Embedder already registered.
       
   142                     return;
       
   143                 }
       
   144 
       
   145                 {
       
   146                     int tproxy = (int)newProxy;
       
   147                     if (byteOrderByte != MotifDnDConstants.getByteOrderByte()) {
       
   148                         tproxy = MotifDnDConstants.Swapper.swap(tproxy);
       
   149                     }
       
   150                     unsafe.putInt(data + 4, tproxy);
       
   151                 }
       
   152             } else {
       
   153                 data = unsafe.allocateMemory(dataSize);
       
   154 
       
   155                 unsafe.putByte(data, MotifDnDConstants.getByteOrderByte()); /* byte order */
       
   156                 unsafe.putByte(data + 1, MotifDnDConstants.MOTIF_DND_PROTOCOL_VERSION); /* protocol version */
       
   157                 unsafe.putByte(data + 2, (byte)MotifDnDConstants.MOTIF_DYNAMIC_STYLE); /* protocol style */
       
   158                 unsafe.putByte(data + 3, (byte)0); /* pad */
       
   159                 unsafe.putInt(data + 4, (int)newProxy); /* proxy window */
       
   160                 unsafe.putShort(data + 8, (short)0); /* num_drop_sites */
       
   161                 unsafe.putShort(data + 10, (short)0); /* pad */
       
   162                 unsafe.putInt(data + 12, dataSize);
       
   163             }
       
   164 
       
   165             XToolkit.WITH_XERROR_HANDLER(XWM.VerifyChangePropertyHandler);
       
   166             XlibWrapper.XChangeProperty(XToolkit.getDisplay(), embedder,
       
   167                                         MotifDnDConstants.XA_MOTIF_DRAG_RECEIVER_INFO.getAtom(),
       
   168                                         MotifDnDConstants.XA_MOTIF_DRAG_RECEIVER_INFO.getAtom(),
       
   169                                         8, XlibWrapper.PropModeReplace,
       
   170                                         data, dataSize);
       
   171             XToolkit.RESTORE_XERROR_HANDLER();
       
   172 
       
   173             if (XToolkit.saved_error != null &&
       
   174                 XToolkit.saved_error.get_error_code() != XlibWrapper.Success) {
       
   175                 throw new XException("Cannot write Motif receiver info property");
       
   176             }
       
   177         } finally {
       
   178             if (!overriden) {
       
   179                 unsafe.freeMemory(data);
       
   180                 data = 0;
       
   181             }
       
   182             wpg.dispose();
       
   183         }
       
   184 
       
   185         putEmbedderRegistryEntry(embedder, overriden, version, proxy);
       
   186     }
       
   187 
       
   188     public void unregisterEmbedderDropSite(long embedder) {
       
   189         assert XToolkit.isAWTLockHeldByCurrentThread();
       
   190 
       
   191         EmbedderRegistryEntry entry = getEmbedderRegistryEntry(embedder);
       
   192 
       
   193         if (entry == null) {
       
   194             return;
       
   195         }
       
   196 
       
   197         if (entry.isOverriden()) {
       
   198             int status = 0;
       
   199 
       
   200             WindowPropertyGetter wpg =
       
   201                 new WindowPropertyGetter(embedder,
       
   202                                          MotifDnDConstants.XA_MOTIF_DRAG_RECEIVER_INFO,
       
   203                                          0, 0xFFFF, false,
       
   204                                          XlibWrapper.AnyPropertyType);
       
   205 
       
   206             try {
       
   207                 status = wpg.execute(XToolkit.IgnoreBadWindowHandler);
       
   208 
       
   209                 /*
       
   210                  * DragICCI.h:
       
   211                  *
       
   212                  * typedef struct _xmDragReceiverInfoStruct{
       
   213                  *     BYTE     byte_order;
       
   214                  *     BYTE     protocol_version;
       
   215                  *     BYTE     drag_protocol_style;
       
   216                  *     BYTE     pad1;
       
   217                  *     CARD32   proxy_window B32;
       
   218                  *     CARD16   num_drop_sites B16;
       
   219                  *     CARD16   pad2 B16;
       
   220                  *     CARD32   heap_offset B32;
       
   221                  * } xmDragReceiverInfoStruct;
       
   222                  */
       
   223                 if (status == (int)XlibWrapper.Success && wpg.getData() != 0 &&
       
   224                     wpg.getActualType() != 0 && wpg.getActualFormat() == 8 &&
       
   225                     wpg.getNumberOfItems() >=
       
   226                     MotifDnDConstants.MOTIF_RECEIVER_INFO_SIZE) {
       
   227 
       
   228                     int dataSize = MotifDnDConstants.MOTIF_RECEIVER_INFO_SIZE;
       
   229                     long data = wpg.getData();
       
   230                     byte byteOrderByte = unsafe.getByte(data);
       
   231 
       
   232                     int tproxy = (int)entry.getProxy();
       
   233                     if (MotifDnDConstants.getByteOrderByte() != byteOrderByte) {
       
   234                         tproxy = MotifDnDConstants.Swapper.swap(tproxy);
       
   235                     }
       
   236 
       
   237                     unsafe.putInt(data + 4, tproxy);
       
   238 
       
   239                     XToolkit.WITH_XERROR_HANDLER(XWM.VerifyChangePropertyHandler);
       
   240                     XlibWrapper.XChangeProperty(XToolkit.getDisplay(), embedder,
       
   241                                                 MotifDnDConstants.XA_MOTIF_DRAG_RECEIVER_INFO.getAtom(),
       
   242                                                 MotifDnDConstants.XA_MOTIF_DRAG_RECEIVER_INFO.getAtom(),
       
   243                                                 8, XlibWrapper.PropModeReplace,
       
   244                                                 data, dataSize);
       
   245                     XToolkit.RESTORE_XERROR_HANDLER();
       
   246 
       
   247                     if (XToolkit.saved_error != null &&
       
   248                         XToolkit.saved_error.get_error_code() != XlibWrapper.Success) {
       
   249                         throw new XException("Cannot write Motif receiver info property");
       
   250                     }
       
   251                 }
       
   252             } finally {
       
   253                 wpg.dispose();
       
   254             }
       
   255         } else {
       
   256             MotifDnDConstants.XA_MOTIF_DRAG_RECEIVER_INFO.DeleteProperty(embedder);
       
   257         }
       
   258     }
       
   259 
       
   260     /*
       
   261      * Gets and stores in the registry the embedder's Motif DnD drop site info
       
   262      * from the embedded.
       
   263      */
       
   264     public void registerEmbeddedDropSite(long embedded) {
       
   265         assert XToolkit.isAWTLockHeldByCurrentThread();
       
   266 
       
   267         boolean overriden = false;
       
   268         int version = 0;
       
   269         long proxy = 0;
       
   270         int status = 0;
       
   271 
       
   272         WindowPropertyGetter wpg =
       
   273             new WindowPropertyGetter(embedded,
       
   274                                      MotifDnDConstants.XA_MOTIF_DRAG_RECEIVER_INFO,
       
   275                                      0, 0xFFFF, false,
       
   276                                      XlibWrapper.AnyPropertyType);
       
   277 
       
   278         try {
       
   279             status = wpg.execute(XToolkit.IgnoreBadWindowHandler);
       
   280 
       
   281             /*
       
   282              * DragICCI.h:
       
   283              *
       
   284              * typedef struct _xmDragReceiverInfoStruct{
       
   285              *     BYTE byte_order;
       
   286              *     BYTE protocol_version;
       
   287              *     BYTE drag_protocol_style;
       
   288              *     BYTE pad1;
       
   289              *     CARD32       proxy_window B32;
       
   290              *     CARD16       num_drop_sites B16;
       
   291              *     CARD16       pad2 B16;
       
   292              *     CARD32       heap_offset B32;
       
   293              * } xmDragReceiverInfoStruct;
       
   294              */
       
   295             if (status == (int)XlibWrapper.Success && wpg.getData() != 0 &&
       
   296                 wpg.getActualType() != 0 && wpg.getActualFormat() == 8 &&
       
   297                 wpg.getNumberOfItems() >=
       
   298                 MotifDnDConstants.MOTIF_RECEIVER_INFO_SIZE) {
       
   299 
       
   300                 overriden = true;
       
   301                 long data = wpg.getData();
       
   302 
       
   303                 byte byteOrderByte = unsafe.getByte(data);
       
   304 
       
   305                 {
       
   306                     int tproxy = unsafe.getInt(data + 4);
       
   307                     if (byteOrderByte != MotifDnDConstants.getByteOrderByte()) {
       
   308                         tproxy = MotifDnDConstants.Swapper.swap(tproxy);
       
   309                     }
       
   310                     proxy = tproxy;
       
   311                 }
       
   312             }
       
   313         } finally {
       
   314             wpg.dispose();
       
   315         }
       
   316 
       
   317         putEmbedderRegistryEntry(embedded, overriden, version, proxy);
       
   318     }
       
   319 
       
   320     public boolean isProtocolSupported(long window) {
       
   321         WindowPropertyGetter wpg =
       
   322             new WindowPropertyGetter(window,
       
   323                                      MotifDnDConstants.XA_MOTIF_DRAG_RECEIVER_INFO,
       
   324                                      0, 0xFFFF, false,
       
   325                                      XlibWrapper.AnyPropertyType);
       
   326 
       
   327         try {
       
   328             int status = wpg.execute(XToolkit.IgnoreBadWindowHandler);
       
   329 
       
   330             if (status == (int)XlibWrapper.Success && wpg.getData() != 0 &&
       
   331                 wpg.getActualType() != 0 && wpg.getActualFormat() == 8 &&
       
   332                 wpg.getNumberOfItems() >=
       
   333                 MotifDnDConstants.MOTIF_RECEIVER_INFO_SIZE) {
       
   334                 return true;
       
   335             } else {
       
   336                 return false;
       
   337             }
       
   338         } finally {
       
   339             wpg.dispose();
       
   340         }
       
   341     }
       
   342 
       
   343     private boolean processTopLevelEnter(XClientMessageEvent xclient) {
       
   344         assert XToolkit.isAWTLockHeldByCurrentThread();
       
   345 
       
   346         if (targetXWindow != null || sourceWindow != 0) {
       
   347             return false;
       
   348         }
       
   349 
       
   350         if (!(XToolkit.windowToXWindow(xclient.get_window()) instanceof XWindow)
       
   351             && getEmbedderRegistryEntry(xclient.get_window()) == null) {
       
   352             return false;
       
   353         }
       
   354 
       
   355         long source_win = 0;
       
   356         long source_win_mask = 0;
       
   357         int protocol_version = 0;
       
   358         long property_atom = 0;
       
   359         long[] formats = null;
       
   360 
       
   361         {
       
   362             long data = xclient.get_data();
       
   363             byte eventByteOrder = unsafe.getByte(data + 1);
       
   364             source_win = MotifDnDConstants.Swapper.getInt(data + 8, eventByteOrder);
       
   365             property_atom = MotifDnDConstants.Swapper.getInt(data + 12, eventByteOrder);
       
   366         }
       
   367 
       
   368         /* Extract the available data types. */
       
   369         {
       
   370             WindowPropertyGetter wpg =
       
   371                 new WindowPropertyGetter(source_win,
       
   372                                          XAtom.get(property_atom),
       
   373                                          0, 0xFFFF,
       
   374                                          false,
       
   375                                          MotifDnDConstants.XA_MOTIF_DRAG_INITIATOR_INFO.getAtom());
       
   376 
       
   377             try {
       
   378                 int status = wpg.execute(XToolkit.IgnoreBadWindowHandler);
       
   379 
       
   380                 if (status == XlibWrapper.Success && wpg.getData() != 0 &&
       
   381                     wpg.getActualType() ==
       
   382                     MotifDnDConstants.XA_MOTIF_DRAG_INITIATOR_INFO.getAtom() &&
       
   383                     wpg.getActualFormat() == 8 &&
       
   384                     wpg.getNumberOfItems() ==
       
   385                     MotifDnDConstants.MOTIF_INITIATOR_INFO_SIZE) {
       
   386 
       
   387                     long data = wpg.getData();
       
   388                     byte propertyByteOrder = unsafe.getByte(data);
       
   389 
       
   390                     protocol_version = unsafe.getByte(data + 1);
       
   391 
       
   392                     if (protocol_version !=
       
   393                         MotifDnDConstants.MOTIF_DND_PROTOCOL_VERSION) {
       
   394                         return false;
       
   395                     }
       
   396 
       
   397                     int index =
       
   398                         MotifDnDConstants.Swapper.getShort(data + 2, propertyByteOrder);
       
   399 
       
   400                     formats = MotifDnDConstants.getTargetListForIndex(index);
       
   401                 } else {
       
   402                     formats = new long[0];
       
   403                 }
       
   404             } finally {
       
   405                 wpg.dispose();
       
   406             }
       
   407         }
       
   408 
       
   409         /*
       
   410          * Select for StructureNotifyMask to receive DestroyNotify in case of source
       
   411          * crash.
       
   412          */
       
   413         XWindowAttributes wattr = new XWindowAttributes();
       
   414         try {
       
   415             XToolkit.WITH_XERROR_HANDLER(XToolkit.IgnoreBadWindowHandler);
       
   416             int status = XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(),
       
   417                                                           source_win, wattr.pData);
       
   418 
       
   419             XToolkit.RESTORE_XERROR_HANDLER();
       
   420 
       
   421             if (status == 0 ||
       
   422                 (XToolkit.saved_error != null &&
       
   423                  XToolkit.saved_error.get_error_code() != XlibWrapper.Success)) {
       
   424                 throw new XException("XGetWindowAttributes failed");
       
   425             }
       
   426 
       
   427             source_win_mask = wattr.get_your_event_mask();
       
   428         } finally {
       
   429             wattr.dispose();
       
   430         }
       
   431 
       
   432         XToolkit.WITH_XERROR_HANDLER(XToolkit.IgnoreBadWindowHandler);
       
   433         XlibWrapper.XSelectInput(XToolkit.getDisplay(), source_win,
       
   434                                  source_win_mask |
       
   435                                  XlibWrapper.StructureNotifyMask);
       
   436 
       
   437         XToolkit.RESTORE_XERROR_HANDLER();
       
   438 
       
   439         if (XToolkit.saved_error != null &&
       
   440             XToolkit.saved_error.get_error_code() != XlibWrapper.Success) {
       
   441             throw new XException("XSelectInput failed");
       
   442         }
       
   443 
       
   444         sourceWindow = source_win;
       
   445         sourceWindowMask = source_win_mask;
       
   446         sourceProtocolVersion = protocol_version;
       
   447         /*
       
   448          * TOP_LEVEL_ENTER doesn't communicate the list of supported actions
       
   449          * They are provided in DRAG_MOTION.
       
   450          */
       
   451         sourceActions = DnDConstants.ACTION_NONE;
       
   452         sourceFormats = formats;
       
   453         sourceAtom = property_atom;
       
   454 
       
   455         return true;
       
   456     }
       
   457 
       
   458     private boolean processDragMotion(XClientMessageEvent xclient) {
       
   459         long data = xclient.get_data();
       
   460         byte eventByteOrder = unsafe.getByte(data + 1);
       
   461         byte eventReason = (byte)(unsafe.getByte(data) &
       
   462                                   MotifDnDConstants.MOTIF_MESSAGE_REASON_MASK);
       
   463         int x = 0;
       
   464         int y = 0;
       
   465 
       
   466         short flags = MotifDnDConstants.Swapper.getShort(data + 2, eventByteOrder);
       
   467 
       
   468         int motif_action = (flags & MotifDnDConstants.MOTIF_DND_ACTION_MASK) >>
       
   469             MotifDnDConstants.MOTIF_DND_ACTION_SHIFT;
       
   470         int motif_actions = (flags & MotifDnDConstants.MOTIF_DND_ACTIONS_MASK) >>
       
   471             MotifDnDConstants.MOTIF_DND_ACTIONS_SHIFT;
       
   472 
       
   473         int java_action = MotifDnDConstants.getJavaActionsForMotifActions(motif_action);
       
   474         int java_actions = MotifDnDConstants.getJavaActionsForMotifActions(motif_actions);
       
   475 
       
   476         /* Append source window id to the event data, so that we can send the
       
   477            response properly. */
       
   478         {
       
   479             int win = (int)sourceWindow;
       
   480             if (eventByteOrder != MotifDnDConstants.getByteOrderByte()) {
       
   481                 win = MotifDnDConstants.Swapper.swap(win);
       
   482             }
       
   483             unsafe.putInt(data + 12, win);
       
   484         }
       
   485 
       
   486         XWindow xwindow = null;
       
   487         {
       
   488             XBaseWindow xbasewindow = XToolkit.windowToXWindow(xclient.get_window());
       
   489             if (xbasewindow instanceof XWindow) {
       
   490                 xwindow = (XWindow)xbasewindow;
       
   491             }
       
   492         }
       
   493 
       
   494         if (eventReason == MotifDnDConstants.OPERATION_CHANGED) {
       
   495             /* OPERATION_CHANGED event doesn't provide coordinates, so we use
       
   496                previously stored position and component ref. */
       
   497             x = sourceX;
       
   498             y = sourceY;
       
   499 
       
   500             if (xwindow == null) {
       
   501                 xwindow = targetXWindow;
       
   502             }
       
   503         } else {
       
   504             x = MotifDnDConstants.Swapper.getShort(data + 8, eventByteOrder);
       
   505             y = MotifDnDConstants.Swapper.getShort(data + 10, eventByteOrder);
       
   506 
       
   507             if (xwindow == null) {
       
   508                 long receiver =
       
   509                     XDropTargetRegistry.getRegistry().getEmbeddedDropSite(
       
   510                         xclient.get_window(), x, y);
       
   511 
       
   512                 if (receiver != 0) {
       
   513                     XBaseWindow xbasewindow = XToolkit.windowToXWindow(receiver);
       
   514                     if (xbasewindow instanceof XWindow) {
       
   515                         xwindow = (XWindow)xbasewindow;
       
   516                     }
       
   517                 }
       
   518             }
       
   519 
       
   520             if (xwindow != null) {
       
   521                 Point p = xwindow.toLocal(x, y);
       
   522                 x = p.x;
       
   523                 y = p.y;
       
   524             }
       
   525         }
       
   526 
       
   527         if (xwindow == null) {
       
   528             if (targetXWindow != null) {
       
   529                 notifyProtocolListener(targetXWindow, x, y,
       
   530                                        DnDConstants.ACTION_NONE, java_actions,
       
   531                                        xclient, MouseEvent.MOUSE_EXITED);
       
   532             }
       
   533         } else {
       
   534             int java_event_id = 0;
       
   535 
       
   536             if (targetXWindow == null) {
       
   537                 java_event_id = MouseEvent.MOUSE_ENTERED;
       
   538             } else {
       
   539                 java_event_id = MouseEvent.MOUSE_DRAGGED;
       
   540             }
       
   541 
       
   542             notifyProtocolListener(xwindow, x, y, java_action, java_actions,
       
   543                                    xclient, java_event_id);
       
   544         }
       
   545 
       
   546         sourceActions = java_actions;
       
   547         userAction = java_action;
       
   548         sourceX = x;
       
   549         sourceY = y;
       
   550         targetXWindow = xwindow;
       
   551 
       
   552         return true;
       
   553     }
       
   554 
       
   555     private boolean processTopLevelLeave(XClientMessageEvent xclient) {
       
   556         assert XToolkit.isAWTLockHeldByCurrentThread();
       
   557 
       
   558         long data = xclient.get_data();
       
   559         byte eventByteOrder = unsafe.getByte(data + 1);
       
   560 
       
   561         long source_win = MotifDnDConstants.Swapper.getInt(data + 8, eventByteOrder);
       
   562 
       
   563         /* Ignore Motif DnD messages from all other windows. */
       
   564         if (source_win != sourceWindow) {
       
   565             return false;
       
   566         }
       
   567 
       
   568         /*
       
   569          * Postpone upcall to java, so that we can abort it in case
       
   570          * if drop immediatelly follows (see BugTraq ID 4395290).
       
   571          * Send a dummy ClientMessage event to guarantee that a postponed java
       
   572          * upcall will be processed.
       
   573          */
       
   574         topLevelLeavePostponed = true;
       
   575         {
       
   576             long proxy;
       
   577 
       
   578             /*
       
   579              * If this is an embedded drop site, the event should go to the
       
   580              * awt_root_window as this is a proxy for all embedded drop sites.
       
   581              * Otherwise the event should go to the event->window, as we don't use
       
   582              * proxies for normal drop sites.
       
   583              */
       
   584             if (getEmbedderRegistryEntry(xclient.get_window()) != null) {
       
   585                 proxy = XDropTargetRegistry.getDnDProxyWindow();
       
   586             } else {
       
   587                 proxy = xclient.get_window();
       
   588             }
       
   589 
       
   590             XClientMessageEvent dummy = new XClientMessageEvent();
       
   591 
       
   592             try {
       
   593                 dummy.set_type(XlibWrapper.ClientMessage);
       
   594                 dummy.set_window(xclient.get_window());
       
   595                 dummy.set_format(32);
       
   596                 dummy.set_message_type(0);
       
   597                 dummy.set_data(0, 0);
       
   598                 dummy.set_data(1, 0);
       
   599                 dummy.set_data(2, 0);
       
   600                 dummy.set_data(3, 0);
       
   601                 dummy.set_data(4, 0);
       
   602                 XlibWrapper.XSendEvent(XToolkit.getDisplay(),
       
   603                                        proxy, false, XlibWrapper.NoEventMask,
       
   604                                        dummy.pData);
       
   605             } finally {
       
   606                 dummy.dispose();
       
   607             }
       
   608         }
       
   609         return true;
       
   610     }
       
   611 
       
   612     private boolean processDropStart(XClientMessageEvent xclient) {
       
   613         long data = xclient.get_data();
       
   614         byte eventByteOrder = unsafe.getByte(data + 1);
       
   615 
       
   616         long source_win =
       
   617             MotifDnDConstants.Swapper.getInt(data + 16, eventByteOrder);
       
   618 
       
   619         /* Ignore Motif DnD messages from all other windows. */
       
   620         if (source_win != sourceWindow) {
       
   621             return false;
       
   622         }
       
   623 
       
   624         long property_atom =
       
   625             MotifDnDConstants.Swapper.getInt(data + 12, eventByteOrder);
       
   626 
       
   627         short flags =
       
   628             MotifDnDConstants.Swapper.getShort(data + 2, eventByteOrder);
       
   629 
       
   630         int motif_action = (flags & MotifDnDConstants.MOTIF_DND_ACTION_MASK) >>
       
   631             MotifDnDConstants.MOTIF_DND_ACTION_SHIFT;
       
   632         int motif_actions = (flags & MotifDnDConstants.MOTIF_DND_ACTIONS_MASK) >>
       
   633             MotifDnDConstants.MOTIF_DND_ACTIONS_SHIFT;
       
   634 
       
   635         int java_action = MotifDnDConstants.getJavaActionsForMotifActions(motif_action);
       
   636         int java_actions = MotifDnDConstants.getJavaActionsForMotifActions(motif_actions);
       
   637 
       
   638         int x = MotifDnDConstants.Swapper.getShort(data + 8, eventByteOrder);
       
   639         int y = MotifDnDConstants.Swapper.getShort(data + 10, eventByteOrder);
       
   640 
       
   641         XWindow xwindow = null;
       
   642         {
       
   643             XBaseWindow xbasewindow = XToolkit.windowToXWindow(xclient.get_window());
       
   644             if (xbasewindow instanceof XWindow) {
       
   645                 xwindow = (XWindow)xbasewindow;
       
   646             }
       
   647         }
       
   648 
       
   649         if (xwindow == null) {
       
   650             long receiver =
       
   651                 XDropTargetRegistry.getRegistry().getEmbeddedDropSite(
       
   652                     xclient.get_window(), x, y);
       
   653 
       
   654             if (receiver != 0) {
       
   655                 XBaseWindow xbasewindow = XToolkit.windowToXWindow(receiver);
       
   656                 if (xbasewindow instanceof XWindow) {
       
   657                     xwindow = (XWindow)xbasewindow;
       
   658                 }
       
   659             }
       
   660         }
       
   661 
       
   662         if (xwindow != null) {
       
   663             Point p = xwindow.toLocal(x, y);
       
   664             x = p.x;
       
   665             y = p.y;
       
   666         }
       
   667 
       
   668         if (xwindow != null) {
       
   669             notifyProtocolListener(xwindow, x, y, java_action, java_actions,
       
   670                                    xclient, MouseEvent.MOUSE_RELEASED);
       
   671         } else if (targetXWindow != null) {
       
   672             notifyProtocolListener(targetXWindow, x, y,
       
   673                                    DnDConstants.ACTION_NONE, java_actions,
       
   674                                    xclient, MouseEvent.MOUSE_EXITED);
       
   675         }
       
   676 
       
   677         return true;
       
   678     }
       
   679 
       
   680     public int getMessageType(XClientMessageEvent xclient) {
       
   681         if (xclient.get_message_type() !=
       
   682             MotifDnDConstants.XA_MOTIF_DRAG_AND_DROP_MESSAGE.getAtom()) {
       
   683 
       
   684             return UNKNOWN_MESSAGE;
       
   685         }
       
   686 
       
   687         long data = xclient.get_data();
       
   688         byte reason = (byte)(unsafe.getByte(data) &
       
   689                              MotifDnDConstants.MOTIF_MESSAGE_REASON_MASK);
       
   690 
       
   691         switch (reason) {
       
   692         case MotifDnDConstants.TOP_LEVEL_ENTER :
       
   693             return ENTER_MESSAGE;
       
   694         case MotifDnDConstants.DRAG_MOTION :
       
   695         case MotifDnDConstants.OPERATION_CHANGED :
       
   696             return MOTION_MESSAGE;
       
   697         case MotifDnDConstants.TOP_LEVEL_LEAVE :
       
   698             return LEAVE_MESSAGE;
       
   699         case MotifDnDConstants.DROP_START :
       
   700             return DROP_MESSAGE;
       
   701         default:
       
   702             return UNKNOWN_MESSAGE;
       
   703         }
       
   704     }
       
   705 
       
   706     protected boolean processClientMessageImpl(XClientMessageEvent xclient) {
       
   707         if (xclient.get_message_type() !=
       
   708             MotifDnDConstants.XA_MOTIF_DRAG_AND_DROP_MESSAGE.getAtom()) {
       
   709             if (topLevelLeavePostponed) {
       
   710                 topLevelLeavePostponed = false;
       
   711                 cleanup();
       
   712             }
       
   713 
       
   714             return false;
       
   715         }
       
   716 
       
   717         long data = xclient.get_data();
       
   718         byte reason = (byte)(unsafe.getByte(data) &
       
   719             MotifDnDConstants.MOTIF_MESSAGE_REASON_MASK);
       
   720         byte origin = (byte)(unsafe.getByte(data) &
       
   721             MotifDnDConstants.MOTIF_MESSAGE_SENDER_MASK);
       
   722 
       
   723         if (topLevelLeavePostponed) {
       
   724             topLevelLeavePostponed = false;
       
   725             if (reason != MotifDnDConstants.DROP_START) {
       
   726                 cleanup();
       
   727             }
       
   728         }
       
   729 
       
   730         /* Only initiator messages should be handled. */
       
   731         if (origin != MotifDnDConstants.MOTIF_MESSAGE_FROM_INITIATOR) {
       
   732             return false;
       
   733         }
       
   734 
       
   735         switch (reason) {
       
   736         case MotifDnDConstants.TOP_LEVEL_ENTER :
       
   737             return processTopLevelEnter(xclient);
       
   738         case MotifDnDConstants.DRAG_MOTION :
       
   739         case MotifDnDConstants.OPERATION_CHANGED :
       
   740             return processDragMotion(xclient);
       
   741         case MotifDnDConstants.TOP_LEVEL_LEAVE :
       
   742             return processTopLevelLeave(xclient);
       
   743         case MotifDnDConstants.DROP_START :
       
   744             return processDropStart(xclient);
       
   745         default:
       
   746             return false;
       
   747         }
       
   748     }
       
   749 
       
   750     /*
       
   751      * Currently we don't synthesize enter/leave messages for Motif DnD
       
   752      * protocol. See comments in XDropTargetProtocol.postProcessClientMessage.
       
   753      */
       
   754     protected void sendEnterMessageToToplevel(long win,
       
   755                                               XClientMessageEvent xclient) {
       
   756         throw new Error("UNIMPLEMENTED");
       
   757     }
       
   758 
       
   759     protected void sendLeaveMessageToToplevel(long win,
       
   760                                               XClientMessageEvent xclient) {
       
   761         throw new Error("UNIMPLEMENTED");
       
   762     }
       
   763 
       
   764     public boolean forwardEventToEmbedded(long embedded, long ctxt,
       
   765                                           int eventID) {
       
   766         // UNIMPLEMENTED.
       
   767         return false;
       
   768     }
       
   769 
       
   770     public boolean isXEmbedSupported() {
       
   771         return false;
       
   772     }
       
   773 
       
   774     public boolean sendResponse(long ctxt, int eventID, int action) {
       
   775         XClientMessageEvent xclient = new XClientMessageEvent(ctxt);
       
   776         if (xclient.get_message_type() !=
       
   777             MotifDnDConstants.XA_MOTIF_DRAG_AND_DROP_MESSAGE.getAtom()) {
       
   778             return false;
       
   779         }
       
   780 
       
   781         long data = xclient.get_data();
       
   782         byte reason = (byte)(unsafe.getByte(data) &
       
   783             MotifDnDConstants.MOTIF_MESSAGE_REASON_MASK);
       
   784         byte origin = (byte)(unsafe.getByte(data) &
       
   785             MotifDnDConstants.MOTIF_MESSAGE_SENDER_MASK);
       
   786         byte eventByteOrder = unsafe.getByte(data + 1);
       
   787         byte response_reason = (byte)0;
       
   788 
       
   789         /* Only initiator messages should be handled. */
       
   790         if (origin != MotifDnDConstants.MOTIF_MESSAGE_FROM_INITIATOR) {
       
   791             return false;
       
   792         }
       
   793 
       
   794         switch (reason) {
       
   795         case MotifDnDConstants.TOP_LEVEL_ENTER:
       
   796         case MotifDnDConstants.TOP_LEVEL_LEAVE:
       
   797             /* Receiver shouldn't rely to these messages. */
       
   798             return false;
       
   799         case MotifDnDConstants.DRAG_MOTION:
       
   800             switch (eventID) {
       
   801             case MouseEvent.MOUSE_ENTERED:
       
   802                 response_reason = MotifDnDConstants.DROP_SITE_ENTER;
       
   803                 break;
       
   804             case MouseEvent.MOUSE_DRAGGED:
       
   805                 response_reason = MotifDnDConstants.DRAG_MOTION;
       
   806                 break;
       
   807             case MouseEvent.MOUSE_EXITED:
       
   808                 response_reason = MotifDnDConstants.DROP_SITE_LEAVE;
       
   809                 break;
       
   810             }
       
   811             break;
       
   812         case MotifDnDConstants.OPERATION_CHANGED:
       
   813         case MotifDnDConstants.DROP_START:
       
   814             response_reason = reason;
       
   815             break;
       
   816         default:
       
   817             // Unknown reason. Shouldn't get here.
       
   818             assert false;
       
   819         }
       
   820 
       
   821         XClientMessageEvent msg = new XClientMessageEvent();
       
   822 
       
   823         try {
       
   824             msg.set_type(XlibWrapper.ClientMessage);
       
   825             msg.set_window(MotifDnDConstants.Swapper.getInt(data + 12, eventByteOrder));
       
   826             msg.set_format(8);
       
   827             msg.set_message_type(MotifDnDConstants.XA_MOTIF_DRAG_AND_DROP_MESSAGE.getAtom());
       
   828 
       
   829             long responseData = msg.get_data();
       
   830 
       
   831             unsafe.putByte(responseData, (byte)(response_reason |
       
   832                            MotifDnDConstants.MOTIF_MESSAGE_FROM_RECEIVER));
       
   833             unsafe.putByte(responseData + 1, MotifDnDConstants.getByteOrderByte());
       
   834 
       
   835             int response_flags = 0;
       
   836 
       
   837             if (response_reason != MotifDnDConstants.DROP_SITE_LEAVE) {
       
   838                 short flags = MotifDnDConstants.Swapper.getShort(data + 2,
       
   839                                                                  eventByteOrder);
       
   840                 byte dropSiteStatus = (action == DnDConstants.ACTION_NONE) ?
       
   841                     MotifDnDConstants.MOTIF_INVALID_DROP_SITE :
       
   842                     MotifDnDConstants.MOTIF_VALID_DROP_SITE;
       
   843 
       
   844                 /* Clear action and drop site status bits. */
       
   845                 response_flags = flags &
       
   846                     ~MotifDnDConstants.MOTIF_DND_ACTION_MASK &
       
   847                     ~MotifDnDConstants.MOTIF_DND_STATUS_MASK;
       
   848                 /* Fill in new action and drop site status. */
       
   849                 response_flags |=
       
   850                     MotifDnDConstants.getMotifActionsForJavaActions(action) <<
       
   851                     MotifDnDConstants.MOTIF_DND_ACTION_SHIFT;
       
   852                 response_flags |=
       
   853                     dropSiteStatus << MotifDnDConstants.MOTIF_DND_STATUS_SHIFT;
       
   854             } else {
       
   855                 response_flags = 0;
       
   856             }
       
   857 
       
   858             unsafe.putShort(responseData + 2, (short)response_flags);
       
   859 
       
   860             /* Write time stamp. */
       
   861             int time = MotifDnDConstants.Swapper.getInt(data + 4, eventByteOrder);
       
   862             unsafe.putInt(responseData + 4, time);
       
   863 
       
   864             /* Write coordinates. */
       
   865             if (response_reason != MotifDnDConstants.DROP_SITE_LEAVE) {
       
   866                 short x = MotifDnDConstants.Swapper.getShort(data + 8,
       
   867                                                              eventByteOrder);
       
   868                 short y = MotifDnDConstants.Swapper.getShort(data + 10,
       
   869                                                              eventByteOrder);
       
   870                 unsafe.putShort(responseData + 8, x); // x
       
   871                 unsafe.putShort(responseData + 10, y); // y
       
   872             } else {
       
   873                 unsafe.putShort(responseData + 8, (short)0); // x
       
   874                 unsafe.putShort(responseData + 10, (short)0); // y
       
   875             }
       
   876 
       
   877             XToolkit.awtLock();
       
   878             try {
       
   879                 XlibWrapper.XSendEvent(XToolkit.getDisplay(),
       
   880                                        msg.get_window(),
       
   881                                        false, XlibWrapper.NoEventMask,
       
   882                                        msg.pData);
       
   883             } finally {
       
   884                 XToolkit.awtUnlock();
       
   885             }
       
   886         } finally {
       
   887             msg.dispose();
       
   888         }
       
   889 
       
   890         return true;
       
   891     }
       
   892 
       
   893     public Object getData(long ctxt, long format)
       
   894       throws IllegalArgumentException, IOException {
       
   895         XClientMessageEvent xclient = new XClientMessageEvent(ctxt);
       
   896 
       
   897         if (xclient.get_message_type() !=
       
   898             MotifDnDConstants.XA_MOTIF_DRAG_AND_DROP_MESSAGE.getAtom()) {
       
   899             throw new IllegalArgumentException();
       
   900         }
       
   901 
       
   902         long data = xclient.get_data();
       
   903         byte reason = (byte)(unsafe.getByte(data) &
       
   904             MotifDnDConstants.MOTIF_MESSAGE_REASON_MASK);
       
   905         byte origin = (byte)(unsafe.getByte(data) &
       
   906             MotifDnDConstants.MOTIF_MESSAGE_SENDER_MASK);
       
   907         byte eventByteOrder = unsafe.getByte(data + 1);
       
   908 
       
   909         if (origin != MotifDnDConstants.MOTIF_MESSAGE_FROM_INITIATOR) {
       
   910             throw new IOException("Cannot get data: corrupted context");
       
   911         }
       
   912 
       
   913         long selatom = 0;
       
   914 
       
   915         switch (reason) {
       
   916         case MotifDnDConstants.DRAG_MOTION :
       
   917         case MotifDnDConstants.OPERATION_CHANGED :
       
   918             selatom = sourceAtom;
       
   919             break;
       
   920         case MotifDnDConstants.DROP_START :
       
   921             selatom = MotifDnDConstants.Swapper.getInt(data + 12, eventByteOrder);
       
   922             break;
       
   923         default:
       
   924             throw new IOException("Cannot get data: invalid message reason");
       
   925         }
       
   926 
       
   927         if (selatom == 0) {
       
   928             throw new IOException("Cannot get data: drag source property atom unavailable");
       
   929         }
       
   930 
       
   931         long time_stamp = MotifDnDConstants.Swapper.getInt(data + 4, eventByteOrder);
       
   932         XAtom selectionAtom = XAtom.get(selatom);
       
   933 
       
   934         XSelection selection = XSelection.getSelection(selectionAtom);
       
   935         if (selection == null) {
       
   936             selection = new XSelection(selectionAtom, null);
       
   937         }
       
   938 
       
   939         return selection.getData(format, time_stamp);
       
   940     }
       
   941 
       
   942     public boolean sendDropDone(long ctxt, boolean success, int dropAction) {
       
   943         XClientMessageEvent xclient = new XClientMessageEvent(ctxt);
       
   944 
       
   945         if (xclient.get_message_type() !=
       
   946             MotifDnDConstants.XA_MOTIF_DRAG_AND_DROP_MESSAGE.getAtom()) {
       
   947             return false;
       
   948         }
       
   949 
       
   950         long data = xclient.get_data();
       
   951         byte reason = (byte)(unsafe.getByte(data) &
       
   952             MotifDnDConstants.MOTIF_MESSAGE_REASON_MASK);
       
   953         byte origin = (byte)(unsafe.getByte(data) &
       
   954             MotifDnDConstants.MOTIF_MESSAGE_SENDER_MASK);
       
   955         byte eventByteOrder = unsafe.getByte(data + 1);
       
   956 
       
   957         if (origin != MotifDnDConstants.MOTIF_MESSAGE_FROM_INITIATOR) {
       
   958             return false;
       
   959         }
       
   960 
       
   961         if (reason != MotifDnDConstants.DROP_START) {
       
   962             return false;
       
   963         }
       
   964 
       
   965         long time_stamp = MotifDnDConstants.Swapper.getInt(data + 4, eventByteOrder);
       
   966         long sel_atom = MotifDnDConstants.Swapper.getInt(data + 12, eventByteOrder);
       
   967 
       
   968         long status_atom = 0;
       
   969 
       
   970         if (success) {
       
   971             status_atom = MotifDnDConstants.XA_XmTRANSFER_SUCCESS.getAtom();
       
   972         } else {
       
   973             status_atom = MotifDnDConstants.XA_XmTRANSFER_FAILURE.getAtom();
       
   974         }
       
   975 
       
   976         XToolkit.awtLock();
       
   977         try {
       
   978             XlibWrapper.XConvertSelection(XToolkit.getDisplay(),
       
   979                                           sel_atom,
       
   980                                           status_atom,
       
   981                                           MotifDnDConstants.XA_MOTIF_ATOM_0.getAtom(),
       
   982                                           XWindow.getXAWTRootWindow().getWindow(),
       
   983                                           time_stamp);
       
   984 
       
   985             /*
       
   986              * Flush the buffer to guarantee that the drop completion event is sent
       
   987              * to the source before the method returns.
       
   988              */
       
   989             XlibWrapper.XFlush(XToolkit.getDisplay());
       
   990         } finally {
       
   991             XToolkit.awtUnlock();
       
   992         }
       
   993 
       
   994         /* Trick to prevent cleanup() from posting dragExit */
       
   995         targetXWindow = null;
       
   996 
       
   997         /* Cannot do cleanup before the drop finishes as we may need
       
   998            source protocol version to send drop finished message. */
       
   999         cleanup();
       
  1000         return true;
       
  1001     }
       
  1002 
       
  1003     public final long getSourceWindow() {
       
  1004         return sourceWindow;
       
  1005     }
       
  1006 
       
  1007     /**
       
  1008      * Reset the state of the object.
       
  1009      */
       
  1010     public void cleanup() {
       
  1011         // Clear the reference to this protocol.
       
  1012         XDropTargetEventProcessor.reset();
       
  1013 
       
  1014         if (targetXWindow != null) {
       
  1015             notifyProtocolListener(targetXWindow, 0, 0,
       
  1016                                    DnDConstants.ACTION_NONE, sourceActions,
       
  1017                                    null, MouseEvent.MOUSE_EXITED);
       
  1018         }
       
  1019 
       
  1020         if (sourceWindow != 0) {
       
  1021             XToolkit.awtLock();
       
  1022             try {
       
  1023                 XToolkit.WITH_XERROR_HANDLER(XToolkit.IgnoreBadWindowHandler);
       
  1024                 XlibWrapper.XSelectInput(XToolkit.getDisplay(), sourceWindow,
       
  1025                                          sourceWindowMask);
       
  1026                 XToolkit.RESTORE_XERROR_HANDLER();
       
  1027             } finally {
       
  1028                 XToolkit.awtUnlock();
       
  1029             }
       
  1030         }
       
  1031 
       
  1032         sourceWindow = 0;
       
  1033         sourceWindowMask = 0;
       
  1034         sourceProtocolVersion = 0;
       
  1035         sourceActions = DnDConstants.ACTION_NONE;
       
  1036         sourceFormats = null;
       
  1037         sourceAtom = 0;
       
  1038         userAction = DnDConstants.ACTION_NONE;
       
  1039         sourceX = 0;
       
  1040         sourceY = 0;
       
  1041         targetXWindow = null;
       
  1042         topLevelLeavePostponed = false;
       
  1043     }
       
  1044 
       
  1045     public boolean isDragOverComponent() {
       
  1046         return targetXWindow != null;
       
  1047     }
       
  1048 
       
  1049     private void notifyProtocolListener(XWindow xwindow, int x, int y,
       
  1050                                         int dropAction, int actions,
       
  1051                                         XClientMessageEvent xclient,
       
  1052                                         int eventID) {
       
  1053         long nativeCtxt = 0;
       
  1054 
       
  1055         // Make a copy of the passed XClientMessageEvent structure, since
       
  1056         // the original structure can be freed before this
       
  1057         // SunDropTargetEvent is dispatched.
       
  1058         if (xclient != null) {
       
  1059             int size = new XClientMessageEvent(nativeCtxt).getSize();
       
  1060 
       
  1061             nativeCtxt = unsafe.allocateMemory(size + 4 * Native.getLongSize());
       
  1062 
       
  1063             unsafe.copyMemory(xclient.pData, nativeCtxt, size);
       
  1064         }
       
  1065 
       
  1066         getProtocolListener().handleDropTargetNotification(xwindow, x, y,
       
  1067                                                            dropAction,
       
  1068                                                            actions,
       
  1069                                                            sourceFormats,
       
  1070                                                            nativeCtxt,
       
  1071                                                            eventID);
       
  1072     }
       
  1073 }