jdk/src/solaris/native/sun/awt/awt_XmDnD.c
changeset 1211 b659a7cee935
parent 1210 7798f9e88bf9
parent 1203 3e5496df0d2b
child 1212 d718a4419361
equal deleted inserted replaced
1210:7798f9e88bf9 1211:b659a7cee935
     1 /*
       
     2  * Copyright 1997-2005 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 #ifdef HEADLESS
       
    27     #error This file should not be included in headless library
       
    28 #endif
       
    29 
       
    30 #include <stdio.h>
       
    31 #include <string.h>
       
    32 
       
    33 #include "jvm.h"
       
    34 #include "jni.h"
       
    35 #include "jni_util.h"
       
    36 #include "jlong.h"
       
    37 
       
    38 #include "awt_DataTransferer.h"
       
    39 #include "awt_XmDnD.h"
       
    40 
       
    41 #include "awt_p.h"
       
    42 
       
    43 #include "java_awt_Cursor.h"
       
    44 #include "java_awt_dnd_DnDConstants.h"
       
    45 #include "java_awt_event_MouseEvent.h"
       
    46 #include "sun_awt_dnd_SunDragSourceContextPeer.h"
       
    47 #include "sun_awt_motif_MComponentPeer.h"
       
    48 #include "sun_awt_motif_MDragSourceContextPeer.h"
       
    49 #include "sun_awt_motif_MDropTargetContextPeer.h"
       
    50 
       
    51 #include <X11/cursorfont.h>
       
    52 #include <X11/Xutil.h>
       
    53 /*
       
    54  * Fix for 4285634.
       
    55  * Include the private Motif header to enable access to lastEventState.
       
    56  */
       
    57 #include <Xm/DragCP.h>
       
    58 
       
    59 #include "awt_Component.h"
       
    60 #include "awt_Cursor.h"
       
    61 #include "awt_AWTEvent.h"
       
    62 
       
    63 extern struct MComponentPeerIDs mComponentPeerIDs;
       
    64 extern struct CursorIDs cursorIDs;
       
    65 extern struct ContainerIDs containerIDs;
       
    66 
       
    67 /* globals */
       
    68 
       
    69 
       
    70 /* forwards */
       
    71 
       
    72 static void awt_XmDropProc(Widget, XtPointer, XmDropProcCallbackStruct*);
       
    73 static void awt_XmDragProc(Widget, XtPointer, XmDragProcCallbackStruct*);
       
    74 
       
    75 static void awt_XmTransferProc(Widget, XtPointer, Atom*, Atom*, XtPointer,
       
    76                                unsigned long*, int32_t*);
       
    77 
       
    78 /* for XmDragContext callbacks etc ... */
       
    79 static void awt_XmDragEnterProc(Widget, XtPointer,
       
    80                                 XmDropSiteEnterCallbackStruct*);
       
    81 static void awt_XmDragMotionProc(Widget, XtPointer,
       
    82                                  XmDragMotionCallbackStruct*);
       
    83 static void awt_XmDragLeaveProc(Widget, XtPointer,
       
    84                                 XmDropSiteLeaveCallbackStruct*);
       
    85 static void awt_XmDropOperationChangedProc(Widget, XtPointer,
       
    86                                            XmDropStartCallbackStruct*);
       
    87 static void awt_XmDropFinishProc(Widget, XtPointer,
       
    88                                  XmDropFinishCallbackStruct*);
       
    89 
       
    90 static unsigned char DnDConstantsToXm(jint operations);
       
    91 static jint XmToDnDConstants(unsigned char operations);
       
    92 static unsigned char selectOperation(unsigned char operations);
       
    93 
       
    94 static void flush_cache(JNIEnv* env);
       
    95 static void    cacheDropDone(Boolean dropDone);
       
    96 static Boolean isDropDone();
       
    97 
       
    98 static void setCursor(JNIEnv* env, Display* d, jobject c, jint type, Time t);
       
    99 
       
   100 static Atom MOTIF_DROP_ATOM = None;
       
   101 
       
   102 /* in canvas.c */
       
   103 extern jint getModifiers(uint32_t state, jint button, jint keyCode);
       
   104 
       
   105 /**
       
   106  * static cache of DropTarget related info.
       
   107  */
       
   108 
       
   109 static struct {
       
   110     Widget        w;                /* if NULL, cache invalid */
       
   111 
       
   112     jobject       peer;
       
   113     jobject       component;
       
   114 
       
   115     jobject       dtcpeer;
       
   116 
       
   117     Widget        dt;
       
   118 
       
   119     jlongArray    targets;
       
   120     Cardinal      nTargets;
       
   121 
       
   122     Boolean       dropDone;
       
   123     int32_t       transfersPending;
       
   124     Widget        transfer;
       
   125 
       
   126     jint          dropAction;       /* used only on JVM transfers */
       
   127 
       
   128     Boolean       flushPending;
       
   129 
       
   130     Window win;
       
   131     uint32_t state;
       
   132 } _cache;
       
   133 
       
   134 uint32_t
       
   135 buttonToMask(uint32_t button) {
       
   136     switch (button) {
       
   137         case Button1:
       
   138             return Button1Mask;
       
   139         case Button2:
       
   140             return Button2Mask;
       
   141         case Button3:
       
   142             return Button3Mask;
       
   143         case Button4:
       
   144             return Button4Mask;
       
   145         case Button5:
       
   146             return Button5Mask;
       
   147         default:
       
   148             return 0;
       
   149     }
       
   150 }
       
   151 
       
   152 /* Fix for 4215643: extract the values cached on drag start and send
       
   153    ButtonRelease event to the window which originated the drag */
       
   154 
       
   155 void
       
   156 dragsource_track_release(Widget w, XtPointer client_data,
       
   157                          XEvent * event, Boolean * cont)
       
   158 {
       
   159     DASSERT (event != NULL);
       
   160 
       
   161     if (_cache.win != None &&
       
   162         (buttonToMask(event->xbutton.button) & _cache.state)) {
       
   163 
       
   164         JNIEnv *env = (JNIEnv *) JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
   165         Window win = event->xbutton.window;
       
   166         event->xbutton.window = _cache.win;
       
   167         awt_put_back_event(env, event);
       
   168         event->xbutton.window = win;
       
   169         _cache.win = None;
       
   170         _cache.state = 0;
       
   171         XtRemoveEventHandler(w, ButtonReleaseMask, False,
       
   172                              dragsource_track_release, NULL);
       
   173     }
       
   174 }
       
   175 
       
   176 static void
       
   177 cancel_drag(XtPointer client_data, XtIntervalId* id) {
       
   178     Time time = awt_util_getCurrentServerTime();
       
   179     Widget dc = XmGetDragContext(awt_root_shell, time);
       
   180 
       
   181     if (dc != NULL) {
       
   182         Boolean sourceIsExternal = True;
       
   183         XtVaGetValues(dc, XmNsourceIsExternal, &sourceIsExternal, NULL);
       
   184         if (!sourceIsExternal) {
       
   185             XEvent xevent;
       
   186             XmDragCancel(dc);
       
   187 
       
   188             /*
       
   189              * When running the internal drag-and-drop event loop
       
   190              * (see DragC.c:InitiatorMainLoop) Motif DnD uses XtAppNextEvent,
       
   191              * that processes all timer callbacks and then returns the next X
       
   192              * event from the queue. Motif DnD doesn't check if the drag
       
   193              * operation is cancelled after XtAppNextEvent returns and processes
       
   194              * the returned event. When the drag operation is cancelled the
       
   195              * XmDragContext widget is destroyed and Motif will crash if the new
       
   196              * event is dispatched to the destroyed XmDragContext.
       
   197              * We cancel the drag operation in the timer callback, so we putback
       
   198              * a dummy X event. This event will be returned from XtAppNextEvent
       
   199              * and Motif DnD will safely exit from the internal event loop.
       
   200              */
       
   201             xevent.type = LASTEvent;
       
   202             xevent.xany.send_event = True;
       
   203             xevent.xany.display = awt_display;
       
   204             xevent.xany.window = XtWindow(awt_root_shell);
       
   205             XPutBackEvent(awt_display, &xevent);
       
   206         }
       
   207     }
       
   208 }
       
   209 
       
   210 #define DONT_CARE -1
       
   211 
       
   212 static void
       
   213 awt_popupCallback(Widget shell, XtPointer closure, XtPointer call_data) {
       
   214     XtGrabKind grab_kind = XtGrabNone;
       
   215 
       
   216     if (call_data != NULL) {
       
   217         grab_kind = *((XtGrabKind*)call_data);
       
   218     }
       
   219 
       
   220     if (XmIsVendorShell(shell)) {
       
   221         int input_mode;
       
   222         XtVaGetValues(shell, XmNmwmInputMode, &input_mode, NULL);
       
   223         switch (input_mode) {
       
   224         case DONT_CARE:
       
   225         case MWM_INPUT_MODELESS:
       
   226             grab_kind = XtGrabNonexclusive; break;
       
   227         case MWM_INPUT_PRIMARY_APPLICATION_MODAL:
       
   228         case MWM_INPUT_SYSTEM_MODAL:
       
   229         case MWM_INPUT_FULL_APPLICATION_MODAL:
       
   230             grab_kind = XtGrabExclusive; break;
       
   231         }
       
   232     }
       
   233 
       
   234     if (grab_kind == XtGrabExclusive) {
       
   235         /*
       
   236          * We should cancel the drag on the toolkit thread. Otherwise, it can be
       
   237          * called while the toolkit thread is waiting inside some drag callback.
       
   238          * In this case Motif will crash when the drag callback returns.
       
   239          */
       
   240         XtAppAddTimeOut(awt_appContext, 0L, cancel_drag, NULL);
       
   241     }
       
   242 }
       
   243 
       
   244 static XtInitProc xt_shell_initialize = NULL;
       
   245 
       
   246 static void
       
   247 awt_ShellInitialize(Widget req, Widget new, ArgList args, Cardinal *num_args) {
       
   248     XtAddCallback(new, XtNpopupCallback, awt_popupCallback, NULL);
       
   249     (*xt_shell_initialize)(req, new, args, num_args);
       
   250 }
       
   251 
       
   252 /*
       
   253  * Fix for 4484572.
       
   254  * Modify the 'initialize' routine for all ShellWidget instances, so that it
       
   255  * will install an XtNpopupCallback that cancels the current drag operation.
       
   256  * It is needed, since AWT doesn't have full control over all ShellWidget
       
   257  * instances (e.g. XmPopupMenu internally creates and popups an XmMenuShell).
       
   258  */
       
   259 static void
       
   260 awt_set_ShellInitialize() {
       
   261     static Boolean inited = False;
       
   262 
       
   263     DASSERT(!inited);
       
   264     if (inited) {
       
   265         return;
       
   266     }
       
   267 
       
   268     xt_shell_initialize = shellWidgetClass->core_class.initialize;
       
   269     shellWidgetClass->core_class.initialize = (XtInitProc)awt_ShellInitialize;
       
   270     inited = True;
       
   271 }
       
   272 
       
   273 /**
       
   274  * global function to initialize this client as a Dynamic-only app.
       
   275  *
       
   276  * gets called once during toolkit initialization.
       
   277  */
       
   278 
       
   279 void awt_initialize_Xm_DnD(Display* dpy) {
       
   280     JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
   281     jclass  clazz;
       
   282 
       
   283     XtVaSetValues(XmGetXmDisplay(dpy),
       
   284                   XmNdragInitiatorProtocolStyle, XmDRAG_DYNAMIC,
       
   285                   XmNdragReceiverProtocolStyle,  XmDRAG_DYNAMIC,
       
   286                   NULL
       
   287                   );
       
   288 
       
   289     MOTIF_DROP_ATOM = XInternAtom(dpy, _XA_MOTIF_DROP, False);
       
   290     if (XSaveContext(dpy, MOTIF_DROP_ATOM, awt_convertDataContext,
       
   291                      (XPointer)NULL) == XCNOMEM) {
       
   292         JNU_ThrowInternalError(env, "");
       
   293         return;
       
   294     }
       
   295 
       
   296     /* No drop in progress. */
       
   297     cacheDropDone(True);
       
   298 
       
   299     /*
       
   300      * Fix for BugTraq ID 4407057.
       
   301      * Have to disable Motif default drag support, since it doesn't work
       
   302      * reliably with our event dispatch mechanism. To do this we allow a drag
       
   303      * operation only if it is registered on the awt_root_shell.
       
   304      */
       
   305     awt_motif_enableSingleDragInitiator(awt_root_shell);
       
   306 
       
   307     awt_set_ShellInitialize();
       
   308 
       
   309     /*
       
   310      * load the Cursor stuff
       
   311      */
       
   312 
       
   313     clazz = (*env)->FindClass(env, "sun/awt/motif/MCustomCursor");
       
   314 
       
   315     if (!JNU_IsNull(env, ((*env)->ExceptionOccurred(env)))) {
       
   316         (*env)->ExceptionDescribe(env);
       
   317         (*env)->ExceptionClear(env);
       
   318     }
       
   319 }
       
   320 
       
   321 typedef struct DSInfoRec {
       
   322     Widget         widget;
       
   323 
       
   324     Pixmap         animation_mask;
       
   325     Pixmap         animation_pixmap;
       
   326     int32_t        animation_pixmap_depth;
       
   327     unsigned char  animation_style;
       
   328     XtPointer      client_data;
       
   329     XtCallbackProc drag_proc;
       
   330     XtCallbackProc drop_proc;
       
   331     XRectangle     *drop_rectangles;
       
   332     unsigned char  drop_site_activity;
       
   333     unsigned char  drop_site_operations;
       
   334     unsigned char  drop_site_type;
       
   335     Atom           *import_targets;
       
   336     Cardinal       num_drop_rectangles;
       
   337     Cardinal       num_import_targets;
       
   338 
       
   339     struct DSInfoRec* next;
       
   340 } DSInfoRec, * DSInfoPtr;
       
   341 
       
   342 #define ARG_COUNT 14
       
   343 
       
   344 /*
       
   345  * Allocates DSInfoRect structure, retrieves all attributes of a Motif drop site
       
   346  * registered on the specified widget and puts them into the allocated storage.
       
   347  * The caller should free the storage after use.
       
   348  */
       
   349 DSInfoPtr get_drop_site_info(Widget w) {
       
   350     Arg       arglist[ARG_COUNT];
       
   351     Cardinal  argcount = 0;
       
   352     DSInfoPtr info = ZALLOC(DSInfoRec);
       
   353 
       
   354     if (info == NULL) {
       
   355         JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
   356         JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError");
       
   357         return NULL;
       
   358     }
       
   359 
       
   360     XtSetArg(arglist[argcount], XmNanimationMask,
       
   361              (XtArgVal)&info->animation_mask); argcount++;
       
   362     XtSetArg(arglist[argcount], XmNanimationPixmap,
       
   363              (XtArgVal)&info->animation_pixmap); argcount++;
       
   364     XtSetArg(arglist[argcount], XmNanimationPixmapDepth,
       
   365              (XtArgVal)&info->animation_pixmap_depth); argcount++;
       
   366     XtSetArg(arglist[argcount], XmNanimationStyle,
       
   367              (XtArgVal)&info->animation_style); argcount++;
       
   368     XtSetArg(arglist[argcount], XmNclientData,
       
   369              (XtArgVal)&info->client_data); argcount++;
       
   370     XtSetArg(arglist[argcount], XmNdragProc,
       
   371              (XtArgVal)&info->drag_proc); argcount++;
       
   372     XtSetArg(arglist[argcount], XmNdropProc,
       
   373              (XtArgVal)&info->drop_proc); argcount++;
       
   374     XtSetArg(arglist[argcount], XmNdropSiteActivity,
       
   375              (XtArgVal)&info->drop_site_activity); argcount++;
       
   376     XtSetArg(arglist[argcount], XmNdropSiteOperations,
       
   377              (XtArgVal)&info->drop_site_operations); argcount++;
       
   378     XtSetArg(arglist[argcount], XmNdropSiteType,
       
   379              (XtArgVal)&info->drop_site_type); argcount++;
       
   380     XtSetArg(arglist[argcount], XmNnumDropRectangles,
       
   381              (XtArgVal)&info->num_drop_rectangles); argcount++;
       
   382     XtSetArg(arglist[argcount], XmNnumImportTargets,
       
   383              (XtArgVal)&info->num_import_targets); argcount++;
       
   384     DASSERT(argcount == ARG_COUNT - 2);
       
   385 
       
   386     XmDropSiteRetrieve(w, arglist, argcount);
       
   387 
       
   388     if (info->num_import_targets > 0) {
       
   389         Atom *targets = NULL;
       
   390 
       
   391         info->import_targets = malloc(info->num_import_targets * sizeof(Atom));
       
   392 
       
   393         if (info->import_targets == NULL) {
       
   394             JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
   395 
       
   396             free(info);
       
   397             JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError");
       
   398             return NULL;
       
   399         }
       
   400 
       
   401         XtSetArg(arglist[0], XmNimportTargets, (XtArgVal)&targets);
       
   402         XmDropSiteRetrieve(w, arglist, 1);
       
   403 
       
   404         memcpy(info->import_targets, targets,
       
   405                info->num_import_targets * sizeof(Atom));
       
   406     }
       
   407 
       
   408     if (info->drop_site_type == XmDROP_SITE_SIMPLE && info->num_drop_rectangles > 0) {
       
   409             XRectangle *rectangles = NULL;
       
   410             info->drop_rectangles =
       
   411                 malloc(info->num_drop_rectangles * sizeof(XRectangle));
       
   412 
       
   413             if (info->drop_rectangles == NULL) {
       
   414                 JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
   415 
       
   416                 if (info->import_targets != NULL) {
       
   417                     free(info->import_targets);
       
   418                 }
       
   419                 free(info);
       
   420                 JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError");
       
   421                 return NULL;
       
   422             }
       
   423 
       
   424             XtSetArg(arglist[0], XmNdropRectangles, (XtArgVal)&rectangles);
       
   425             XmDropSiteRetrieve(w, arglist, 1);
       
   426 
       
   427             memcpy(info->drop_rectangles, rectangles,
       
   428                    info->num_drop_rectangles * sizeof(XRectangle));
       
   429     } else /* if (info->drop_site_type == XmDROP_SITE_COMPOSITE) */ {
       
   430         info->num_drop_rectangles = 1;
       
   431         info->drop_rectangles = NULL;
       
   432     }
       
   433 
       
   434     info->widget = w;
       
   435     return info;
       
   436 }
       
   437 
       
   438 /*
       
   439  * Registers a Motif drop site on a widget given the information
       
   440  * in the passed DSInfoRec structure.
       
   441  */
       
   442 void restore_drop_site(DSInfoPtr info) {
       
   443     Arg      arglist[ARG_COUNT];
       
   444     Cardinal argcount = 0;
       
   445 
       
   446     if (info->drop_site_type == XmDROP_SITE_COMPOSITE) {
       
   447         info->num_drop_rectangles = 1;
       
   448         info->drop_rectangles = NULL;
       
   449     }
       
   450 
       
   451     XtSetArg(arglist[argcount], XmNanimationMask,
       
   452              (XtArgVal)info->animation_mask); argcount++;
       
   453     XtSetArg(arglist[argcount], XmNanimationPixmap,
       
   454              (XtArgVal)info->animation_pixmap); argcount++;
       
   455     XtSetArg(arglist[argcount], XmNanimationPixmapDepth,
       
   456              (XtArgVal)info->animation_pixmap_depth); argcount++;
       
   457     XtSetArg(arglist[argcount], XmNanimationStyle,
       
   458              (XtArgVal)info->animation_style); argcount++;
       
   459     XtSetArg(arglist[argcount], XmNclientData,
       
   460              (XtArgVal)info->client_data); argcount++;
       
   461     XtSetArg(arglist[argcount], XmNdragProc,
       
   462              (XtArgVal)info->drag_proc); argcount++;
       
   463     XtSetArg(arglist[argcount], XmNdropProc,
       
   464              (XtArgVal)info->drop_proc); argcount++;
       
   465     XtSetArg(arglist[argcount], XmNdropRectangles,
       
   466              (XtArgVal)info->drop_rectangles); argcount++;
       
   467     XtSetArg(arglist[argcount], XmNdropSiteActivity,
       
   468              (XtArgVal)info->drop_site_activity); argcount++;
       
   469     XtSetArg(arglist[argcount], XmNdropSiteOperations,
       
   470              (XtArgVal)info->drop_site_operations); argcount++;
       
   471     XtSetArg(arglist[argcount], XmNdropSiteType,
       
   472              (XtArgVal)info->drop_site_type); argcount++;
       
   473     XtSetArg(arglist[argcount], XmNimportTargets,
       
   474              (XtArgVal)info->import_targets); argcount++;
       
   475     XtSetArg(arglist[argcount], XmNnumDropRectangles,
       
   476              (XtArgVal)info->num_drop_rectangles); argcount++;
       
   477     XtSetArg(arglist[argcount], XmNnumImportTargets,
       
   478              (XtArgVal)info->num_import_targets); argcount++;
       
   479     DASSERT(argcount == ARG_COUNT);
       
   480 
       
   481     XmDropSiteUnregister(info->widget);
       
   482     XmDropSiteRegister(info->widget, arglist, argcount);
       
   483     XmDropSiteConfigureStackingOrder(info->widget, (Widget)NULL, XmABOVE);
       
   484 }
       
   485 
       
   486 #undef ARG_COUNT
       
   487 
       
   488 /*
       
   489  * This routine ensures that hierarchy of Motif drop sites is not broken
       
   490  * when a new drop site is registered or an existing drop site is
       
   491  * unregistered. It unregisters all drop sites registered on the descendants of
       
   492  * the specified widget, then registers or unregisters a Motif drop site on the
       
   493  * root widget depending on the value of registerNewSite. After that the routine
       
   494  * restores all the drop sites on the descendants.
       
   495  * The routine recursively traverses through the hierarchy of descendant Motif
       
   496  * drop sites and stores the info for all drop sites in a list. Then this list
       
   497  * is used to restore all descendant drop sites.
       
   498  * @param w    current widget in the hierarchy traversal
       
   499  * @param top  root widget of the traversed hierarchy - the one to be inserted or
       
   500  *             removed
       
   501  * @param list a list of DSInfoRec structures which keep drop site info for
       
   502  *             child drop sites
       
   503  * @param registerNewSite if True a new Motif drop site should be registered on
       
   504  *             the root widget. If False an existing drop site of the root widget
       
   505  *             should be unregistered.
       
   506  * @param isDropSite if True the widget being currently traversed has an
       
   507  *             associated Motif drop site.
       
   508  */
       
   509 static DSInfoPtr
       
   510 update_drop_site_hierarchy(Widget w, Widget top, DSInfoPtr list,
       
   511                            Boolean registerNewSite, Boolean isDropSite) {
       
   512 
       
   513     Widget     parent = NULL;
       
   514     Widget     *children = NULL;
       
   515     Cardinal   num_children = 0;
       
   516 
       
   517     if (w == NULL || !XtIsObject(w) || w->core.being_destroyed) {
       
   518         return NULL;
       
   519     }
       
   520 
       
   521     /* Get the child drop sites of the widget.*/
       
   522     if (XmDropSiteQueryStackingOrder(w, &parent, &children,
       
   523                                      &num_children) == 0) {
       
   524         /*
       
   525          * The widget is declared to be a drop site, but the query fails.
       
   526          * The drop site must be corrupted. Truncate traversal.
       
   527          */
       
   528         if (isDropSite) {
       
   529             return NULL;
       
   530         }
       
   531     } else {
       
   532         /* The query succeded, so the widget is definitely a drop site. */
       
   533         isDropSite = True;
       
   534     }
       
   535 
       
   536     /* Traverse descendants of the widget, if it is composite. */
       
   537     if (XtIsComposite(w)) {
       
   538         Cardinal   i = 0;
       
   539 
       
   540         /* If it is not a drop site, check all its children. */
       
   541         if (!isDropSite) {
       
   542             XtVaGetValues(w, XmNchildren, &children,
       
   543                           XmNnumChildren, &num_children, NULL);
       
   544         }
       
   545 
       
   546         for (i = 0; i < num_children; i++) {
       
   547             list = update_drop_site_hierarchy(children[i], top, list,
       
   548                                               registerNewSite, isDropSite);
       
   549         }
       
   550     }
       
   551 
       
   552     /* The storage allocated by XmDropSiteQueryStackingOrder must be freed.*/
       
   553     if (isDropSite && children != NULL) {
       
   554         XtFree((void*)children);
       
   555     }
       
   556 
       
   557     if (w != top) {
       
   558         if (isDropSite) {
       
   559             /* Prepend drop site info to the list and unregister a drop site.*/
       
   560             DSInfoPtr info = get_drop_site_info(w);
       
   561 
       
   562             if (info != NULL) {
       
   563                 info->next = list;
       
   564                 list = info;
       
   565             }
       
   566             XmDropSiteUnregister(w);
       
   567         }
       
   568     } else {
       
   569         /* Traversal is complete.*/
       
   570         DSInfoPtr info = list;
       
   571 
       
   572         if (isDropSite) {
       
   573             XmDropSiteUnregister(w);
       
   574         }
       
   575 
       
   576         if (registerNewSite) {
       
   577             Arg              args[10];
       
   578             unsigned int nargs = 0;
       
   579 
       
   580 #define SetArg(n, v) args[nargs].name = n; args[nargs++].value = (XtArgVal)(v);
       
   581 
       
   582             SetArg(XmNanimationStyle,   XmDRAG_UNDER_NONE);
       
   583             SetArg(XmNdragProc,                awt_XmDragProc);
       
   584             SetArg(XmNdropProc,                awt_XmDropProc);
       
   585             SetArg(XmNdropSiteActivity, XmDROP_SITE_ACTIVE);
       
   586 
       
   587             SetArg(XmNdropSiteOperations,
       
   588                    XmDROP_LINK | XmDROP_MOVE | XmDROP_COPY);
       
   589 
       
   590             SetArg(XmNimportTargets,    NULL);
       
   591             SetArg(XmNnumImportTargets, 0);
       
   592 
       
   593             SetArg(XmNdropSiteType,     XmDROP_SITE_COMPOSITE);
       
   594             SetArg(XmNdropRectangles,   (XRectangle*)NULL);
       
   595 #undef  SetArg
       
   596 
       
   597             XmDropSiteRegister(w, args, nargs);
       
   598             XmDropSiteConfigureStackingOrder(w, (Widget)NULL, XmABOVE);
       
   599         }
       
   600 
       
   601         /* Go through the list and restore all child drop sites.*/
       
   602         while (info != NULL) {
       
   603             restore_drop_site(info);
       
   604 
       
   605             info = info->next;
       
   606             list->next = NULL;
       
   607             if (list->import_targets != NULL) {
       
   608                 free(list->import_targets);
       
   609             }
       
   610             if (list->drop_rectangles != NULL) {
       
   611                 free(list->drop_rectangles);
       
   612             }
       
   613             free(list);
       
   614             list = info;
       
   615         }
       
   616     }
       
   617     return list;
       
   618 }
       
   619 
       
   620 void
       
   621 register_drop_site(Widget w) {
       
   622     update_drop_site_hierarchy(w, w, NULL, True, False);
       
   623 }
       
   624 
       
   625 void
       
   626 unregister_drop_site(Widget w) {
       
   627     update_drop_site_hierarchy(w, w, NULL, False, True);
       
   628 }
       
   629 
       
   630 DECLARE_JAVA_CLASS(dSCClazz, "sun/awt/motif/MDragSourceContextPeer")
       
   631 DECLARE_JAVA_CLASS(dTCClazz, "sun/awt/motif/MDropTargetContextPeer")
       
   632 
       
   633 static void
       
   634 call_dSCenter(JNIEnv* env, jobject this, jint targetActions,
       
   635               jint modifiers, jint x, jint y) {
       
   636     DECLARE_VOID_JAVA_METHOD(dSCenter, dSCClazz, "dragEnter", "(IIII)V");
       
   637     DASSERT(!JNU_IsNull(env, this));
       
   638     (*env)->CallVoidMethod(env, this, dSCenter, targetActions, modifiers, x, y);
       
   639 }
       
   640 
       
   641 static void
       
   642 call_dSCmotion(JNIEnv* env, jobject this, jint targetActions,
       
   643                jint modifiers, jint x, jint y) {
       
   644     DECLARE_VOID_JAVA_METHOD(dSCmotion, dSCClazz, "dragMotion", "(IIII)V");
       
   645     DASSERT(!JNU_IsNull(env, this));
       
   646     (*env)->CallVoidMethod(env, this, dSCmotion, targetActions,
       
   647                            modifiers, x, y);
       
   648 }
       
   649 
       
   650 static void
       
   651 call_dSCchanged(JNIEnv* env, jobject this, jint targetActions,
       
   652                 jint modifiers, jint x, jint y) {
       
   653     DECLARE_VOID_JAVA_METHOD(dSCchanged, dSCClazz, "operationChanged",
       
   654                              "(IIII)V");
       
   655     DASSERT(!JNU_IsNull(env, this));
       
   656     (*env)->CallVoidMethod(env, this, dSCchanged, targetActions,
       
   657                            modifiers, x, y);
       
   658 }
       
   659 
       
   660 static void
       
   661 call_dSCmouseMoved(JNIEnv* env, jobject this, jint targetActions,
       
   662                    jint modifiers, jint x, jint y) {
       
   663     DECLARE_VOID_JAVA_METHOD(dSCmouseMoved, dSCClazz, "dragMouseMoved",
       
   664                              "(IIII)V");
       
   665     DASSERT(!JNU_IsNull(env, this));
       
   666     (*env)->CallVoidMethod(env, this, dSCmouseMoved, targetActions,
       
   667                            modifiers, x, y);
       
   668 }
       
   669 
       
   670 static void
       
   671 call_dSCexit(JNIEnv* env, jobject this, jint x, jint y) {
       
   672     DECLARE_VOID_JAVA_METHOD(dSCexit, dSCClazz, "dragExit", "(II)V");
       
   673     DASSERT(!JNU_IsNull(env, this));
       
   674     (*env)->CallVoidMethod(env, this, dSCexit, x, y);
       
   675 }
       
   676 
       
   677 static void
       
   678 call_dSCddfinished(JNIEnv* env, jobject this, jboolean success,
       
   679                    jint operations, jint x, jint y) {
       
   680     DECLARE_VOID_JAVA_METHOD(dSCddfinished, dSCClazz, "dragDropFinished",
       
   681                              "(ZIII)V");
       
   682     DASSERT(!JNU_IsNull(env, this));
       
   683     (*env)->CallVoidMethod(env, this, dSCddfinished, success, operations, x, y);
       
   684 }
       
   685 
       
   686 static jobject
       
   687 call_dTCcreate(JNIEnv* env) {
       
   688     DECLARE_STATIC_OBJECT_JAVA_METHOD(dTCcreate, dTCClazz,
       
   689                                      "createMDropTargetContextPeer",
       
   690                                      "()Lsun/awt/motif/MDropTargetContextPeer;");
       
   691     return (*env)->CallStaticObjectMethod(env, clazz, dTCcreate);
       
   692 }
       
   693 
       
   694 static jint
       
   695 call_dTCenter(JNIEnv* env, jobject this, jobject component, jint x, jint y,
       
   696               jint dropAction, jint actions, jlongArray formats,
       
   697               jlong nativeCtxt) {
       
   698     DECLARE_JINT_JAVA_METHOD(dTCenter, dTCClazz, "handleEnterMessage",
       
   699                             "(Ljava/awt/Component;IIII[JJ)I");
       
   700     DASSERT(!JNU_IsNull(env, this));
       
   701     return (*env)->CallIntMethod(env, this, dTCenter, component, x, y, dropAction,
       
   702                                  actions, formats, nativeCtxt);
       
   703 }
       
   704 
       
   705 static void
       
   706 call_dTCexit(JNIEnv* env, jobject this, jobject component, jlong nativeCtxt) {
       
   707     DECLARE_VOID_JAVA_METHOD(dTCexit, dTCClazz, "handleExitMessage",
       
   708                             "(Ljava/awt/Component;J)V");
       
   709     DASSERT(!JNU_IsNull(env, this));
       
   710     (*env)->CallVoidMethod(env, this, dTCexit, component, nativeCtxt);
       
   711 }
       
   712 
       
   713 static jint
       
   714 call_dTCmotion(JNIEnv* env, jobject this, jobject component, jint x, jint y,
       
   715                jint dropAction, jint actions, jlongArray formats,
       
   716                jlong nativeCtxt) {
       
   717     DECLARE_JINT_JAVA_METHOD(dTCmotion, dTCClazz, "handleMotionMessage",
       
   718                             "(Ljava/awt/Component;IIII[JJ)I");
       
   719     DASSERT(!JNU_IsNull(env, this));
       
   720     return (*env)->CallIntMethod(env, this, dTCmotion, component, x, y,
       
   721                                  dropAction, actions, formats, nativeCtxt);
       
   722 }
       
   723 
       
   724 static void
       
   725 call_dTCdrop(JNIEnv* env, jobject this, jobject component, jint x, jint y,
       
   726              jint dropAction, jint actions, jlongArray formats,
       
   727              jlong nativeCtxt) {
       
   728     DECLARE_VOID_JAVA_METHOD(dTCdrop, dTCClazz, "handleDropMessage",
       
   729                             "(Ljava/awt/Component;IIII[JJ)V");
       
   730     DASSERT(!JNU_IsNull(env, this));
       
   731     (*env)->CallVoidMethod(env, this, dTCdrop, component, x, y,
       
   732                            dropAction, actions, formats, nativeCtxt);
       
   733 }
       
   734 
       
   735 static void
       
   736 call_dTCnewData(JNIEnv* env, jobject this, jlong format, jobject type,
       
   737                 jbyteArray data) {
       
   738     DECLARE_VOID_JAVA_METHOD(dTCnewData, dTCClazz, "newData",
       
   739                             "(JLjava/lang/String;[B)V");
       
   740     DASSERT(!JNU_IsNull(env, this));
       
   741     (*env)->CallVoidMethod(env, this, dTCnewData, format, type, data);
       
   742 }
       
   743 
       
   744 static void
       
   745 call_dTCtxFailed(JNIEnv* env, jobject this, jlong format) {
       
   746     DECLARE_VOID_JAVA_METHOD(dTCtxFailed, dTCClazz, "transferFailed", "(J)V");
       
   747     DASSERT(!JNU_IsNull(env, this));
       
   748     (*env)->CallVoidMethod(env, this, dTCtxFailed, format);
       
   749 }
       
   750 
       
   751 /*
       
   752  * Class:     sun_awt_motif_MComponentPeer
       
   753  * Method:    addNativeDropTarget
       
   754  * Signature: (Ljava/awt/dnd/DropTarget;)V
       
   755  */
       
   756 
       
   757 JNIEXPORT void JNICALL Java_sun_awt_motif_MComponentPeer_addNativeDropTarget
       
   758     (JNIEnv *env, jobject this, jobject droptarget)
       
   759 {
       
   760     struct ComponentData* cdata     = (struct ComponentData *)NULL;
       
   761     DropSitePtr          dropsite  = (DropSitePtr)NULL;
       
   762 
       
   763     if (JNU_IsNull(env, droptarget)) {
       
   764         JNU_ThrowNullPointerException(env, "NullPointerException");
       
   765         return;
       
   766     }
       
   767 
       
   768     AWT_LOCK();
       
   769 
       
   770     cdata = (struct ComponentData *)
       
   771         JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData);
       
   772 
       
   773     if (cdata == NULL || cdata->widget == NULL) {
       
   774         JNU_ThrowNullPointerException(env, "NullPointerException");
       
   775         AWT_UNLOCK();
       
   776         return;
       
   777     }
       
   778 
       
   779     /* introduce a new Component as a root of a set of DropTargets */
       
   780 
       
   781     if ((dropsite = cdata->dsi) == (DropSitePtr)NULL) {
       
   782         dropsite = cdata->dsi = (DropSitePtr)ZALLOC(DropSiteInfo);
       
   783 
       
   784         if (dropsite == (DropSitePtr)NULL) {
       
   785             JNU_ThrowOutOfMemoryError (env, "OutOfMemoryError");
       
   786             AWT_UNLOCK ();
       
   787             return;
       
   788         }
       
   789 
       
   790         dropsite->component = (*env)->NewGlobalRef
       
   791             (env, (*env)->GetObjectField(env, this,
       
   792                                          mComponentPeerIDs.target));
       
   793         dropsite->isComposite = True;
       
   794 
       
   795         /*
       
   796          * Fix for Bug Id 4389284.
       
   797          * Revalidate drop site hierarchy so that this drop site doesn't obscure
       
   798          * drop sites that are already registered on its children.
       
   799          */
       
   800         register_drop_site(cdata->widget);
       
   801     }
       
   802 
       
   803     dropsite->dsCnt++;
       
   804 
       
   805     AWT_UNLOCK();
       
   806 }
       
   807 
       
   808 /*
       
   809  * Class:     sun_awt_motif_MComponentPeer
       
   810  * Method:    removeNativeDropTarget
       
   811  * Signature: (Ljava/awt/dnd/DropTarget;)V
       
   812  */
       
   813 
       
   814 JNIEXPORT void JNICALL Java_sun_awt_motif_MComponentPeer_removeNativeDropTarget
       
   815     (JNIEnv *env, jobject this, jobject droptarget)
       
   816 {
       
   817     struct ComponentData* cdata;
       
   818     DropSitePtr           dropsite;
       
   819 
       
   820     if (JNU_IsNull(env, droptarget)) {
       
   821         JNU_ThrowNullPointerException(env, "NullPointerException");
       
   822         return;
       
   823     }
       
   824 
       
   825     AWT_LOCK();
       
   826 
       
   827     cdata = (struct ComponentData *)
       
   828         JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData);
       
   829 
       
   830     if (cdata == NULL || cdata->widget == NULL) {
       
   831         JNU_ThrowNullPointerException(env, "NullPointerException");
       
   832         AWT_UNLOCK();
       
   833         return;
       
   834     }
       
   835 
       
   836     if ((dropsite = cdata->dsi) == (DropSitePtr)NULL) {
       
   837         JNU_ThrowNullPointerException(env, "NullPointerException");
       
   838         AWT_UNLOCK();
       
   839         return;
       
   840     }
       
   841 
       
   842     dropsite->dsCnt--;
       
   843     if (dropsite->dsCnt == 0) {
       
   844         /*
       
   845          * Fix for Bug Id 4411368.
       
   846          * Revalidate drop site hierarchy to prevent crash when a composite drop
       
   847          * site is unregistered before its child drop sites.
       
   848          */
       
   849         unregister_drop_site(cdata->widget);
       
   850 
       
   851         (*env)->DeleteGlobalRef(env, dropsite->component);
       
   852 
       
   853         free((void *)(cdata->dsi));
       
   854         cdata->dsi = (DropSitePtr)NULL;
       
   855     }
       
   856 
       
   857     AWT_UNLOCK();
       
   858 }
       
   859 
       
   860 /**
       
   861  *
       
   862  */
       
   863 
       
   864 JNIEXPORT void JNICALL
       
   865 Java_sun_awt_motif_MDragSourceContextPeer_setNativeCursor(JNIEnv *env,
       
   866                                                           jobject this,
       
   867                                                           jlong nativeCtxt,
       
   868                                                           jobject cursor,
       
   869                                                           jint type) {
       
   870     /*
       
   871      * NOTE: no need to synchronize on awt_lock here, since we should have
       
   872      * already acquired it in MDragSourceContextPeer.setCursor().
       
   873      */
       
   874     setCursor(env, awt_display, cursor, type, CurrentTime);
       
   875 }
       
   876 
       
   877 /**
       
   878  *
       
   879  */
       
   880 
       
   881 JNIEXPORT jlong JNICALL
       
   882 Java_sun_awt_motif_MDropTargetContextPeer_startTransfer(JNIEnv *env,
       
   883                                                         jobject this,
       
   884                                                         jlong dragContextVal,
       
   885                                                         jlong atom) {
       
   886     XmDropTransferEntryRec trec;
       
   887     Widget                 dropTransfer;
       
   888     Arg                    args[3];
       
   889     Cardinal               nargs = 0;
       
   890     jboolean               isCopy;
       
   891     Widget                 dragContext = (Widget)jlong_to_ptr(dragContextVal);
       
   892 
       
   893     AWT_LOCK();
       
   894 
       
   895     trec.target      = (Atom) atom;
       
   896     trec.client_data = (XtPointer)trec.target;
       
   897 
       
   898 
       
   899 #define SetArg(n, v) args[nargs].name = n; args[nargs++].value = (XtArgVal)(v);
       
   900 
       
   901     SetArg(XmNdropTransfers,    &trec);
       
   902     SetArg(XmNnumDropTransfers, 1    );
       
   903     SetArg(XmNtransferProc,     awt_XmTransferProc);
       
   904 
       
   905 #undef SetArg
       
   906 
       
   907     _cache.transfer = dropTransfer =
       
   908         XmDropTransferStart(dragContext, args, nargs);
       
   909 
       
   910     _cache.transfersPending++;
       
   911 
       
   912     AWT_NOTIFY_ALL();
       
   913     AWT_UNLOCK();
       
   914 
       
   915     return ptr_to_jlong(dropTransfer);
       
   916 }
       
   917 
       
   918 /**
       
   919  *
       
   920  */
       
   921 
       
   922 JNIEXPORT void JNICALL
       
   923 Java_sun_awt_motif_MDropTargetContextPeer_addTransfer(JNIEnv *env,
       
   924                                                       jobject this,
       
   925                                                       jlong dropTransferVal,
       
   926                                                       jlong atom) {
       
   927     XmDropTransferEntryRec trec;
       
   928     jboolean               isCopy;
       
   929     Widget                 dropTransfer=(Widget)jlong_to_ptr(dropTransferVal);
       
   930     trec.target      = (Atom)atom;
       
   931     trec.client_data = (XtPointer)trec.target;
       
   932 
       
   933     AWT_LOCK();
       
   934 
       
   935     XmDropTransferAdd(dropTransfer, &trec, 1);
       
   936 
       
   937     _cache.transfersPending++;
       
   938 
       
   939     AWT_NOTIFY_ALL();
       
   940     AWT_UNLOCK();
       
   941 }
       
   942 
       
   943 /**
       
   944  *
       
   945  */
       
   946 
       
   947 JNIEXPORT void JNICALL Java_sun_awt_motif_MDropTargetContextPeer_dropDone
       
   948     (JNIEnv *env, jobject this, jlong dragContextVal, jlong dropTransferVal,
       
   949      jboolean isLocal, jboolean success, jint dropAction)
       
   950 {
       
   951     Widget dropTransfer = (Widget)jlong_to_ptr(dropTransferVal);
       
   952     Widget dragContext = (Widget)jlong_to_ptr(dragContextVal);
       
   953 
       
   954     AWT_LOCK();
       
   955 
       
   956     if (_cache.w == (Widget)NULL) {
       
   957         AWT_UNLOCK();
       
   958         return;
       
   959     }
       
   960 
       
   961     if (!isDropDone()) {
       
   962         if (dropTransfer != (jlong)NULL) {
       
   963             XtVaSetValues(dropTransfer,
       
   964                           XmNtransferStatus,
       
   965                           success == JNI_TRUE
       
   966                           ? XmTRANSFER_SUCCESS : XmTRANSFER_FAILURE,
       
   967                           NULL
       
   968                           );
       
   969         } else {
       
   970             /*
       
   971              * start a transfer that notifies failure
       
   972              * this causes src side callbacks to be processed.
       
   973              * However, you cannot pass an a success, so the workaround is
       
   974              * to set _cache.transferSuccess to the proper value and read it
       
   975              * on the other side.
       
   976              */
       
   977 
       
   978 
       
   979             Arg arg;
       
   980 
       
   981             /*
       
   982              * this is the workaround code
       
   983              */
       
   984             _cache.transfer = NULL;
       
   985             _cache.dropAction = dropAction;
       
   986 
       
   987             /*
       
   988              * End workaround code
       
   989              */
       
   990 
       
   991             arg.name  = XmNtransferStatus;
       
   992             arg.value = (XtArgVal)(success == JNI_TRUE ? XmTRANSFER_SUCCESS
       
   993                                    : XmTRANSFER_FAILURE
       
   994                                    );
       
   995 
       
   996             XmDropTransferStart(dragContext, &arg, 1);
       
   997         }
       
   998 
       
   999         /*
       
  1000          * bugid# 4146717
       
  1001          *
       
  1002          * If this is a local tx, then we never exec the awt_XmTransferProc,
       
  1003          * thus we need to flush the cache here as it is our only chance,
       
  1004          * otherwise we leave a mess for the next operation to fail on ....
       
  1005          *
       
  1006          */
       
  1007 
       
  1008         if (isLocal == JNI_TRUE)
       
  1009             flush_cache(env); /* flush now, last chance */
       
  1010         else
       
  1011             _cache.flushPending = True; /* flush pending in transfer proc */
       
  1012     }
       
  1013 
       
  1014     cacheDropDone(True);
       
  1015 
       
  1016     AWT_NOTIFY_ALL();
       
  1017     AWT_UNLOCK();
       
  1018 }
       
  1019 
       
  1020 
       
  1021 static Boolean exitIdleProc = False;
       
  1022 static int32_t x_root = -1, y_root = -1;
       
  1023 
       
  1024 extern void waitForEvents(JNIEnv *env, int32_t fdXPipe, int32_t fdAWTPipe);
       
  1025 
       
  1026 static jint convertModifiers(uint32_t modifiers) {
       
  1027     return getModifiers(modifiers, 0, 0);
       
  1028 }
       
  1029 
       
  1030 static void
       
  1031 checkMouseMoved(XtPointer client_data) {
       
  1032     Window rootWindow, childWindow;
       
  1033     int32_t xw, yw, xr, yr;
       
  1034     uint32_t modifiers;
       
  1035 
       
  1036     /*
       
  1037      * When dragging over the root window XmNdragMotionCallback is not called
       
  1038      * (Motif feature).
       
  1039      * Since there is no legal way to receive MotionNotify events during drag
       
  1040      * we have to query for mouse position periodically.
       
  1041      */
       
  1042     if (XQueryPointer(awt_display, XDefaultRootWindow(awt_display),
       
  1043                       &rootWindow, &childWindow,
       
  1044                       &xr, &yr, &xw, &yw, &modifiers) &&
       
  1045         childWindow == None && (xr != x_root || yr != y_root)) {
       
  1046 
       
  1047         JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
  1048         jobject this = (jobject)client_data;
       
  1049 
       
  1050         call_dSCmouseMoved(env, this, XmDROP_NOOP, convertModifiers(modifiers),
       
  1051                            xr, yr);
       
  1052 
       
  1053         if ((*env)->ExceptionCheck(env) == JNI_TRUE) {
       
  1054             (*env)->ExceptionDescribe(env);
       
  1055             (*env)->ExceptionClear(env);
       
  1056         }
       
  1057 
       
  1058         x_root = xr;
       
  1059         y_root = yr;
       
  1060     }
       
  1061 }
       
  1062 
       
  1063 static void IdleProc(XtPointer client_data, XtIntervalId* id) {
       
  1064     if (!exitIdleProc) {
       
  1065         JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
  1066         /* The pipe where X events arrive */
       
  1067         int32_t fdXPipe = ConnectionNumber(awt_display) ;
       
  1068 
       
  1069         /*
       
  1070          * Motif DnD internal event loop doesn't process the events
       
  1071          * from the AWT putback event queue. So we pass -1 instead
       
  1072          * of the AWT read pipe descriptor to disable checking of
       
  1073          * the putback event queue.
       
  1074          */
       
  1075         waitForEvents(env, fdXPipe, -1);
       
  1076 
       
  1077         checkMouseMoved(client_data);
       
  1078         /* Reschedule the timer callback */
       
  1079         XtAppAddTimeOut(awt_appContext, AWT_DND_POLL_INTERVAL / 10,
       
  1080                         IdleProc, client_data);
       
  1081     }
       
  1082 }
       
  1083 
       
  1084 static void RemoveIdleProc(Widget w,
       
  1085                            XtPointer client_data,
       
  1086                            XmDropFinishCallbackStruct* cbstruct) {
       
  1087     exitIdleProc = True;
       
  1088 }
       
  1089 
       
  1090 /**
       
  1091  *
       
  1092  */
       
  1093 
       
  1094 JNIEXPORT jlong JNICALL
       
  1095 Java_sun_awt_motif_MDragSourceContextPeer_startDrag(JNIEnv *env,
       
  1096                                                     jobject this,
       
  1097                                                     jobject component,
       
  1098                                                     jobject transferable,
       
  1099                                                     jobject trigger,
       
  1100                                                     jobject cursor,
       
  1101                                                     jint ctype,
       
  1102                                                     jint actions,
       
  1103                                                     jlongArray formats,
       
  1104                                                     jobject formatMap) {
       
  1105     Arg                    args[32];
       
  1106     Cardinal               nargs = 0;
       
  1107     jobject                dscp  = (*env)->NewGlobalRef(env, this);
       
  1108     jbyteArray             bdata =
       
  1109         (jbyteArray)(*env)->GetObjectField(env, trigger, awtEventIDs.bdata);
       
  1110     Atom*                  targets = NULL;
       
  1111     jlong*                 jTargets;
       
  1112     jsize                  nTargets;
       
  1113     Widget                 dc;
       
  1114     XtCallbackRec          dsecbr[2];
       
  1115     XtCallbackRec          dmcbr[2];
       
  1116     XtCallbackRec          occbr[2];
       
  1117     XtCallbackRec          dslcbr[2];
       
  1118     XtCallbackRec          dscbr[2];
       
  1119     XtCallbackRec          ddfcbr[2];
       
  1120     XEvent*                xevent;
       
  1121     unsigned char          xmActions = DnDConstantsToXm(actions);
       
  1122     jboolean               isCopy=JNI_TRUE;
       
  1123     awt_convertDataCallbackStruct* structPtr;
       
  1124 
       
  1125 #ifndef _LP64 /* Atom and jlong are different sizes in the 32-bit build */
       
  1126     jsize                  i;
       
  1127     jlong*                 saveJTargets;
       
  1128     Atom*                  saveTargets;
       
  1129 #endif
       
  1130 
       
  1131     if (xmActions == XmDROP_NOOP) {
       
  1132         JNU_ThrowByName(env, "java/awt/dnd/InvalidDnDOperationException",
       
  1133                         "Invalid source actions.");
       
  1134         return ptr_to_jlong(NULL);
       
  1135     }
       
  1136 
       
  1137     if (JNU_IsNull(env, formats)) {
       
  1138         JNU_ThrowNullPointerException(env, "formats");
       
  1139         return ptr_to_jlong(NULL);
       
  1140     }
       
  1141 
       
  1142     if (JNU_IsNull(env, bdata)) {
       
  1143         JNU_ThrowNullPointerException(env,
       
  1144                                       "null native data for trigger event");
       
  1145         return ptr_to_jlong(NULL);
       
  1146     }
       
  1147 
       
  1148     nTargets = (*env)->GetArrayLength(env, formats);
       
  1149 
       
  1150     /*
       
  1151      * In debug build GetLongArrayElements aborts with assertion on an empty
       
  1152      * array.
       
  1153      */
       
  1154     if (nTargets > 0) {
       
  1155         jTargets = (*env)->GetLongArrayElements(env, formats, &isCopy);
       
  1156         if (!JNU_IsNull(env, ((*env)->ExceptionOccurred(env)))) {
       
  1157             (*env)->ExceptionDescribe(env);
       
  1158             (*env)->ExceptionClear(env);
       
  1159         }
       
  1160         if (jTargets != NULL) {
       
  1161             targets = (Atom *)malloc(nTargets * sizeof(Atom));
       
  1162             if (targets != NULL) {
       
  1163 #ifdef _LP64
       
  1164                 memcpy(targets, jTargets, nTargets * sizeof(Atom));
       
  1165 #else
       
  1166                 saveJTargets = jTargets;
       
  1167                 saveTargets = targets;
       
  1168                 for (i = 0; i < nTargets; i++, targets++, jTargets++) {
       
  1169                     *targets = (Atom)*jTargets;
       
  1170                 }
       
  1171                 jTargets = saveJTargets;
       
  1172                 targets = saveTargets;
       
  1173 #endif
       
  1174             }
       
  1175             (*env)->ReleaseLongArrayElements(env, formats, jTargets, JNI_ABORT);
       
  1176         }
       
  1177     }
       
  1178     if (targets == NULL) {
       
  1179         nTargets = 0;
       
  1180     }
       
  1181 
       
  1182 #define SetCB(cbr, cb, cl) cbr[0].callback = (XtCallbackProc)cb; cbr[0].closure = (XtPointer)cl; cbr[1].callback = (XtCallbackProc)NULL; cbr[1].closure = (XtPointer)NULL
       
  1183 
       
  1184 #define SetArg(n, v) args[nargs].name = n; args[nargs++].value = (XtArgVal)(v);
       
  1185 
       
  1186     SetCB(dsecbr, awt_XmDragEnterProc,            dscp);
       
  1187     SetCB(dmcbr,  awt_XmDragMotionProc,           dscp);
       
  1188     SetCB(occbr,  awt_XmDropOperationChangedProc, dscp);
       
  1189     SetCB(dslcbr, awt_XmDragLeaveProc,            dscp);
       
  1190     SetCB(ddfcbr, awt_XmDropFinishProc,           dscp);
       
  1191 
       
  1192     SetArg(XmNblendModel,               XmBLEND_NONE      );
       
  1193     SetArg(XmNdragOperations,           xmActions         );
       
  1194     /* No incremental transfer */
       
  1195     SetArg(XmNconvertProc,              awt_convertData    );
       
  1196     SetArg(XmNdropSiteEnterCallback,    dsecbr             );
       
  1197     SetArg(XmNdragMotionCallback,       dmcbr              );
       
  1198     SetArg(XmNoperationChangedCallback, occbr              );
       
  1199     SetArg(XmNdropSiteLeaveCallback,    dslcbr             );
       
  1200     SetArg(XmNdropFinishCallback,       ddfcbr             );
       
  1201     SetArg(XmNexportTargets,            targets            );
       
  1202     SetArg(XmNnumExportTargets,         (Cardinal)nTargets );
       
  1203 
       
  1204     {
       
  1205         jsize len = (*env)->GetArrayLength(env, bdata);
       
  1206         if (len <= 0) {
       
  1207             free(targets);
       
  1208             return ptr_to_jlong(NULL);
       
  1209         }
       
  1210 
       
  1211         xevent = calloc(1, len);
       
  1212 
       
  1213         if (xevent == NULL) {
       
  1214             free(targets);
       
  1215             JNU_ThrowOutOfMemoryError(env, "");
       
  1216             return ptr_to_jlong(NULL);
       
  1217         }
       
  1218 
       
  1219         (*env)->GetByteArrayRegion(env, bdata, 0, len, (jbyte *)xevent);
       
  1220 
       
  1221         DASSERT(JNU_IsNull(env, (*env)->ExceptionOccurred(env)));
       
  1222     }
       
  1223 
       
  1224     if (xevent->type != ButtonPress &&
       
  1225         xevent->type != ButtonRelease &&
       
  1226         xevent->type != KeyRelease &&
       
  1227         xevent->type != KeyPress &&
       
  1228         xevent->type != MotionNotify) {
       
  1229 
       
  1230         JNU_ThrowByName(env, "java/awt/dnd/InvalidDnDOperationException",
       
  1231                         "A drag can only be initiated in response to an InputEvent.");
       
  1232         free(xevent);
       
  1233         free(targets);
       
  1234         return ptr_to_jlong(NULL);
       
  1235     }
       
  1236 
       
  1237     /* This call causes an UnsatisfiedLinkError on Linux.
       
  1238      * This function is a no-op for Motif 2.1.
       
  1239      * Since Linux only links against Motif 2.1, we can safely remove
       
  1240      * this function altogether from the Linux build.
       
  1241      * bchristi 1/22/2001
       
  1242      */
       
  1243 
       
  1244 #ifdef __solaris__
       
  1245     awt_motif_adjustDragTriggerEvent(xevent);
       
  1246 #endif
       
  1247 
       
  1248     AWT_LOCK();
       
  1249 
       
  1250     /*
       
  1251      * Fix for BugTraq ID 4357905.
       
  1252      * Drop is processed asynchronously on the event dispatch thread.
       
  1253      * Reject all drag attempts until the current drop is done.
       
  1254      */
       
  1255     if (!isDropDone()) {
       
  1256         JNU_ThrowByName(env, "java/awt/dnd/InvalidDnDOperationException",
       
  1257                         "Drop transfer in progress.");
       
  1258         free(xevent);
       
  1259         free(targets);
       
  1260         AWT_UNLOCK();
       
  1261         return ptr_to_jlong(NULL);
       
  1262     }
       
  1263 
       
  1264     if (XFindContext(awt_display, MOTIF_DROP_ATOM, awt_convertDataContext,
       
  1265                      (XPointer*)&structPtr) == XCNOMEM || structPtr != NULL) {
       
  1266         free(xevent);
       
  1267         free(targets);
       
  1268         AWT_UNLOCK();
       
  1269         return ptr_to_jlong(NULL);
       
  1270     }
       
  1271 
       
  1272     structPtr = calloc(1, sizeof(awt_convertDataCallbackStruct));
       
  1273     if (structPtr == NULL) {
       
  1274         free(xevent);
       
  1275         free(targets);
       
  1276         JNU_ThrowOutOfMemoryError(env, "");
       
  1277         AWT_UNLOCK();
       
  1278         return ptr_to_jlong(NULL);
       
  1279     }
       
  1280 
       
  1281     structPtr->source              = (*env)->NewGlobalRef(env, component);
       
  1282     structPtr->transferable        = (*env)->NewGlobalRef(env, transferable);
       
  1283     structPtr->formatMap           = (*env)->NewGlobalRef(env, formatMap);
       
  1284     structPtr->formats             = (*env)->NewGlobalRef(env, formats);
       
  1285 
       
  1286     if (XSaveContext(awt_display, MOTIF_DROP_ATOM, awt_convertDataContext,
       
  1287                      (XPointer)structPtr) == XCNOMEM) {
       
  1288         free(structPtr);
       
  1289         free(xevent);
       
  1290         free(targets);
       
  1291         AWT_UNLOCK();
       
  1292         return ptr_to_jlong(NULL);
       
  1293     }
       
  1294 
       
  1295     dc = XmDragStart(awt_root_shell, xevent, args, nargs);
       
  1296 
       
  1297     /* Fix for 4215643: remember the window corresponding to the drag source
       
  1298        and the button mask after the event which triggered drag start */
       
  1299 
       
  1300     if (xevent->type == ButtonPress || xevent->type == MotionNotify) {
       
  1301         _cache.win = xevent->xbutton.window;
       
  1302         if (xevent->type == ButtonPress) {
       
  1303             _cache.state = buttonToMask(xevent->xbutton.button);
       
  1304         } else {
       
  1305             _cache.state = xevent->xmotion.state & (Button1Mask | Button2Mask);
       
  1306         }
       
  1307         XtAddEventHandler(dc, ButtonReleaseMask, False,
       
  1308                           dragsource_track_release, NULL);
       
  1309     }
       
  1310 
       
  1311     free(targets);
       
  1312 
       
  1313     if (dc != (Widget)NULL) {
       
  1314         setCursor(env, awt_display, cursor, ctype, xevent->xbutton.time);
       
  1315     }
       
  1316 
       
  1317     free(xevent);
       
  1318 
       
  1319     /*
       
  1320      * With the new synchronization model we don't release awt_lock
       
  1321      * in the DragContext callbacks. During drag-n-drop operation
       
  1322      * the events processing is performed not by our awt_MToolkit_loop,
       
  1323      * but by internal Motif InitiatorMainLoop, which returns only
       
  1324      * when the operation is completed. So our polling mechanism doesn't
       
  1325      * have a chance to execute and even if there are no events in
       
  1326      * the queue AWT_LOCK will still be held by the Toolkit thread
       
  1327      * and so other threads will likely be blocked on it.
       
  1328      *
       
  1329      * The solution is to schedule a timer callback which checks
       
  1330      * for events and if the queue is empty releases AWT_LOCK and polls
       
  1331      * the X pipe for some time, then acquires AWT_LOCK back again
       
  1332      * and reschedules itself.
       
  1333      */
       
  1334     if (dc != NULL) {
       
  1335         exitIdleProc = False;
       
  1336         XtAddCallback(dc, XmNdragDropFinishCallback,
       
  1337                       (XtCallbackProc)RemoveIdleProc, NULL);
       
  1338         XtAppAddTimeOut(awt_appContext, AWT_DND_POLL_INTERVAL / 10,
       
  1339                         IdleProc, (XtPointer)dscp);
       
  1340     }
       
  1341 
       
  1342     AWT_UNLOCK();
       
  1343 
       
  1344     return ptr_to_jlong(dc);
       
  1345 
       
  1346 #undef SetArg
       
  1347 #undef SetCB
       
  1348 }
       
  1349 
       
  1350 /*****************************************************************************/
       
  1351 
       
  1352 /**
       
  1353  *
       
  1354  */
       
  1355 
       
  1356 static void setCursor(JNIEnv* env, Display* dpy, jobject cursor, jint type,
       
  1357                       Time time)
       
  1358 {
       
  1359     Cursor xcursor = None;
       
  1360 
       
  1361     if (JNU_IsNull(env, cursor)) return;
       
  1362 
       
  1363     XChangeActivePointerGrab(dpy,
       
  1364                              ButtonPressMask   |
       
  1365                              ButtonMotionMask  |
       
  1366                              ButtonReleaseMask |
       
  1367                              EnterWindowMask   |
       
  1368                              LeaveWindowMask,
       
  1369                              getCursor(env, cursor),
       
  1370                              time
       
  1371                              );
       
  1372 
       
  1373     XSync(dpy, False);
       
  1374 }
       
  1375 
       
  1376 /**
       
  1377  * Update the cached targets for this widget
       
  1378  */
       
  1379 
       
  1380 static Boolean updateCachedTargets(JNIEnv* env, Widget dt) {
       
  1381     Atom*              targets  = (Atom*)NULL;
       
  1382     Cardinal           nTargets = (Cardinal)0;
       
  1383     Arg                args[2];
       
  1384 
       
  1385     /*
       
  1386      * Get the targets for this component
       
  1387      */
       
  1388     args[0].name = XmNexportTargets;    args[0].value = (XtArgVal)&targets;
       
  1389     args[1].name = XmNnumExportTargets; args[1].value = (XtArgVal)&nTargets;
       
  1390     XtGetValues(_cache.dt = dt, args, 2);
       
  1391 
       
  1392     /*
       
  1393      * Free the previous targets if there were any
       
  1394      */
       
  1395     if (!JNU_IsNull(env, _cache.targets)) {
       
  1396         (*env)->DeleteGlobalRef(env, _cache.targets);
       
  1397         _cache.targets = (jlongArray)NULL;
       
  1398     }
       
  1399 
       
  1400     _cache.nTargets = nTargets;
       
  1401 
       
  1402     /*
       
  1403      * If the widget has targets (atoms) then copy them to the cache
       
  1404      */
       
  1405     if (nTargets > 0) {
       
  1406         jboolean isCopy;
       
  1407         jlong*   jTargets;
       
  1408 
       
  1409 #ifndef _LP64 /* Atom and jlong are different sizes in the 32-bit build */
       
  1410         jlong*   saveJTargets;
       
  1411         Cardinal i;
       
  1412 #endif
       
  1413 
       
  1414         _cache.targets = (*env)->NewLongArray(env, nTargets);
       
  1415         if (_cache.targets == NULL) {
       
  1416             _cache.nTargets = 0;
       
  1417             return False;
       
  1418         }
       
  1419 
       
  1420         _cache.targets = (*env)->NewGlobalRef(env, _cache.targets);
       
  1421         if (_cache.targets == NULL) {
       
  1422             _cache.nTargets = 0;
       
  1423             return False;
       
  1424         }
       
  1425 
       
  1426         jTargets = (*env)->GetLongArrayElements(env, _cache.targets, &isCopy);
       
  1427         if (jTargets == NULL) {
       
  1428             (*env)->DeleteGlobalRef(env, _cache.targets);
       
  1429             _cache.targets = NULL;
       
  1430             _cache.nTargets = 0;
       
  1431             return False;
       
  1432         }
       
  1433 
       
  1434 #ifdef _LP64
       
  1435         memcpy(jTargets, targets, nTargets * sizeof(Atom));
       
  1436 #else
       
  1437         saveJTargets = jTargets;
       
  1438         for (i = 0; i < nTargets; i++, jTargets++, targets++) {
       
  1439             *jTargets = (*targets & 0xFFFFFFFFLU);
       
  1440         }
       
  1441         jTargets = saveJTargets;
       
  1442 #endif
       
  1443 
       
  1444         (*env)->ReleaseLongArrayElements(env, _cache.targets, jTargets, 0);
       
  1445         return True;
       
  1446     }
       
  1447 
       
  1448     return False;
       
  1449 }
       
  1450 
       
  1451 
       
  1452 /**
       
  1453  *
       
  1454  */
       
  1455 
       
  1456 static void flush_cache(JNIEnv* env) {
       
  1457     _cache.w  = (Widget)NULL;
       
  1458     _cache.dt = (Widget)NULL;
       
  1459 
       
  1460     (*env)->DeleteGlobalRef(env, _cache.peer);
       
  1461     _cache.peer = (jobject)NULL;
       
  1462 
       
  1463     (*env)->DeleteGlobalRef(env, _cache.component);
       
  1464     _cache.component = (jobject)NULL;
       
  1465 
       
  1466     if (_cache.dtcpeer != (jobject)NULL) {
       
  1467         (*env)->DeleteGlobalRef(env, _cache.dtcpeer);
       
  1468 
       
  1469         _cache.dtcpeer = (jobject)NULL;
       
  1470     }
       
  1471 
       
  1472     _cache.nTargets  = (Cardinal)0;
       
  1473     if (_cache.targets != (jlongArray)NULL) {
       
  1474         (*env)->DeleteGlobalRef(env, _cache.targets);
       
  1475         _cache.targets = (jlongArray)NULL;
       
  1476     }
       
  1477 
       
  1478     _cache.transfersPending = 0;
       
  1479     _cache.flushPending     = False;
       
  1480     _cache.transfer         = (Widget)NULL;
       
  1481     cacheDropDone(True);
       
  1482 }
       
  1483 
       
  1484 /**
       
  1485  *
       
  1486  */
       
  1487 
       
  1488 static void update_cache(JNIEnv* env, Widget w, Widget dt) {
       
  1489     if(w != _cache.w) {
       
  1490         struct ComponentData* cdata   = (struct ComponentData *)NULL;
       
  1491         Arg                   args[1] =
       
  1492         {{ XmNuserData, (XtArgVal)&_cache.peer}};
       
  1493 
       
  1494         flush_cache(env);
       
  1495 
       
  1496         if (w == (Widget)NULL) return;
       
  1497 
       
  1498         XtGetValues(w, args, 1);
       
  1499 
       
  1500         if (JNU_IsNull(env, _cache.peer)) {
       
  1501             _cache.w = NULL;
       
  1502 
       
  1503             return;
       
  1504         }
       
  1505 
       
  1506         cdata = (struct ComponentData *)
       
  1507             JNU_GetLongFieldAsPtr(env, _cache.peer, mComponentPeerIDs.pData);
       
  1508 
       
  1509         if (cdata         == NULL ||
       
  1510             cdata->widget != w ||
       
  1511             cdata->dsi    == (DropSitePtr)NULL) {
       
  1512             _cache.w = NULL;
       
  1513 
       
  1514             return;
       
  1515         }
       
  1516 
       
  1517         _cache.w         = w;
       
  1518         _cache.component = (*env)->NewGlobalRef(env, cdata->dsi->component);
       
  1519         _cache.peer      = (*env)->NewGlobalRef(env, _cache.peer);
       
  1520         /* SECURITY: OK to call this on privileged thread - peer is secure */
       
  1521         {
       
  1522             jobject dtcpeer = call_dTCcreate(env);
       
  1523             if (!JNU_IsNull(env, dtcpeer)) {
       
  1524                 _cache.dtcpeer = (*env)->NewGlobalRef(env, dtcpeer);
       
  1525                 (*env)->DeleteLocalRef(env, dtcpeer);
       
  1526             } else {
       
  1527                 _cache.dtcpeer = NULL;
       
  1528             }
       
  1529         }
       
  1530 
       
  1531         _cache.transfersPending = 0;
       
  1532         cacheDropDone(True);
       
  1533     }
       
  1534 
       
  1535     if (_cache.w != (Widget)NULL) updateCachedTargets(env, dt);
       
  1536 }
       
  1537 
       
  1538 
       
  1539 /**
       
  1540  *
       
  1541  */
       
  1542 
       
  1543 static void
       
  1544 cacheDropDone(Boolean dropDone) {
       
  1545     _cache.dropDone = dropDone;
       
  1546 }
       
  1547 
       
  1548 static Boolean
       
  1549 isDropDone() {
       
  1550     return _cache.dropDone;
       
  1551 }
       
  1552 
       
  1553 /**
       
  1554  *
       
  1555  */
       
  1556 
       
  1557 static jint XmToDnDConstants(unsigned char operations) {
       
  1558     jint src = java_awt_dnd_DnDConstants_ACTION_NONE;
       
  1559 
       
  1560     if (operations & XmDROP_MOVE) src |= java_awt_dnd_DnDConstants_ACTION_MOVE;
       
  1561     if (operations & XmDROP_COPY) src |= java_awt_dnd_DnDConstants_ACTION_COPY;
       
  1562     if (operations & XmDROP_LINK) src |= java_awt_dnd_DnDConstants_ACTION_LINK;
       
  1563 
       
  1564     return src;
       
  1565 }
       
  1566 
       
  1567 static unsigned char selectOperation(unsigned char operations) {
       
  1568     if (operations & XmDROP_MOVE) return XmDROP_MOVE;
       
  1569     if (operations & XmDROP_COPY) return XmDROP_COPY;
       
  1570     if (operations & XmDROP_LINK) return XmDROP_LINK;
       
  1571 
       
  1572     return XmDROP_NOOP;
       
  1573 }
       
  1574 
       
  1575 /**
       
  1576  *
       
  1577  */
       
  1578 
       
  1579 static unsigned char DnDConstantsToXm(jint actions) {
       
  1580     unsigned char ret = XmDROP_NOOP;
       
  1581 
       
  1582     if (actions & java_awt_dnd_DnDConstants_ACTION_COPY) ret |= XmDROP_COPY;
       
  1583     if (actions & java_awt_dnd_DnDConstants_ACTION_MOVE) ret |= XmDROP_MOVE;
       
  1584     if (actions & java_awt_dnd_DnDConstants_ACTION_LINK) ret |= XmDROP_LINK;
       
  1585 
       
  1586     return ret;
       
  1587 }
       
  1588 
       
  1589 /**
       
  1590  *
       
  1591  */
       
  1592 
       
  1593 typedef struct DragExitProcStruct {
       
  1594     XtIntervalId timerId;
       
  1595     jobject      dtcpeer;     /* global reference */
       
  1596     jobject      component;   /* global reference */
       
  1597     jlong        dragContext; /* pointer          */
       
  1598 } DragExitProcStruct;
       
  1599 
       
  1600 static DragExitProcStruct pending_drag_exit_data =
       
  1601     { (XtIntervalId)0, NULL, NULL, (jlong)0 };
       
  1602 
       
  1603 static void drag_exit_proc(XtPointer client_data, XtIntervalId* id) {
       
  1604     JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
  1605 
       
  1606     DASSERT(!JNU_IsNull(env, pending_drag_exit_data.dtcpeer));
       
  1607     DASSERT(!JNU_IsNull(env, pending_drag_exit_data.component));
       
  1608     DASSERT(pending_drag_exit_data.dragContext != NULL);
       
  1609 
       
  1610     if (pending_drag_exit_data.timerId != (XtIntervalId)0) {
       
  1611         if (id == NULL) {
       
  1612             XtRemoveTimeOut(pending_drag_exit_data.timerId);
       
  1613         }
       
  1614         if (id == NULL || pending_drag_exit_data.timerId == *id) {
       
  1615 
       
  1616             /* SECURITY: OK to call this on privileged thread -
       
  1617                peer is secure */
       
  1618             call_dTCexit(env, pending_drag_exit_data.dtcpeer,
       
  1619                          pending_drag_exit_data.component,
       
  1620                          pending_drag_exit_data.dragContext);
       
  1621 
       
  1622             if ((*env)->ExceptionCheck(env) == JNI_TRUE) {
       
  1623                 (*env)->ExceptionDescribe(env);
       
  1624                 (*env)->ExceptionClear(env);
       
  1625             }
       
  1626         }
       
  1627     }
       
  1628 
       
  1629     /* cleanup */
       
  1630     (*env)->DeleteGlobalRef(env, pending_drag_exit_data.dtcpeer);
       
  1631     (*env)->DeleteGlobalRef(env, pending_drag_exit_data.component);
       
  1632 
       
  1633     memset(&pending_drag_exit_data, 0, sizeof(DragExitProcStruct));
       
  1634 }
       
  1635 
       
  1636 static void awt_XmDragProc(Widget w, XtPointer closure,
       
  1637                            XmDragProcCallbackStruct* cbstruct)
       
  1638 {
       
  1639     JNIEnv* env       = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
  1640     jobject component = (jobject)NULL;
       
  1641     jint    src       = java_awt_dnd_DnDConstants_ACTION_NONE;
       
  1642     jint    usrAction = java_awt_dnd_DnDConstants_ACTION_NONE;
       
  1643     jint    ret       = java_awt_dnd_DnDConstants_ACTION_NONE;
       
  1644     unsigned char srcOps = XmDROP_NOOP;
       
  1645 
       
  1646     /*
       
  1647      * Fix for BugTraq ID 4395290.
       
  1648      * We should dispatch any pending java upcall right now
       
  1649      * to keep the order of upcalls.
       
  1650      */
       
  1651     if (pending_drag_exit_data.timerId != (XtIntervalId)0) {
       
  1652         drag_exit_proc(NULL, NULL);
       
  1653     }
       
  1654 
       
  1655     /*
       
  1656      * Fix for BugTraq ID 4357905.
       
  1657      * Drop is processed asynchronously on the event dispatch thread.
       
  1658      * We reject other drop attempts to protect the SunDTCP context
       
  1659      * from being overwritten by an upcall before the drop is done.
       
  1660      */
       
  1661     if (!isDropDone()) {
       
  1662         cbstruct->operation  = XmDROP_NOOP;
       
  1663         cbstruct->dropSiteStatus = XmINVALID_DROP_SITE;
       
  1664         return;
       
  1665     }
       
  1666 
       
  1667     if (cbstruct->dragContext == NULL) {
       
  1668         cbstruct->operation  = XmDROP_NOOP;
       
  1669         cbstruct->dropSiteStatus = XmINVALID_DROP_SITE;
       
  1670         return;
       
  1671     }
       
  1672 
       
  1673     (*env)->PushLocalFrame(env, 0);
       
  1674 
       
  1675     /*
       
  1676      * Fix for BugTraq ID 4285634.
       
  1677      * If some modifier keys are pressed the Motif toolkit initializes
       
  1678      * cbstruct->operations this field to the bitwise AND of the
       
  1679      * XmDragOperations resource of the XmDragContext for this drag operation
       
  1680      * and the drop action corresponding to the current modifiers state.
       
  1681      * We need to determine the drag operations supported by the drag source, so
       
  1682      * we have to get XmNdragOperations value of the XmDragSource.
       
  1683      */
       
  1684     XtVaGetValues(cbstruct->dragContext, XmNdragOperations, &srcOps, NULL);
       
  1685     src = XmToDnDConstants(srcOps);
       
  1686     usrAction = XmToDnDConstants(selectOperation(cbstruct->operations));
       
  1687 
       
  1688     update_cache(env, w, cbstruct->dragContext);
       
  1689 
       
  1690     if (!JNU_IsNull(env, (*env)->ExceptionOccurred(env))) {
       
  1691         flush_cache(env);
       
  1692         (*env)->ExceptionDescribe(env);
       
  1693         (*env)->ExceptionClear(env);
       
  1694         goto wayout;
       
  1695     }
       
  1696 
       
  1697     switch (cbstruct->reason) {
       
  1698     case XmCR_DROP_SITE_ENTER_MESSAGE: {
       
  1699 
       
  1700         /* SECURITY: OK to call this on privileged thread -
       
  1701            peer is secure */
       
  1702         ret = call_dTCenter(env, _cache.dtcpeer, _cache.component,
       
  1703                             cbstruct->x, cbstruct->y,
       
  1704                             usrAction, src,
       
  1705                             _cache.targets,ptr_to_jlong(cbstruct->dragContext));
       
  1706 
       
  1707         if (!JNU_IsNull(env, (*env)->ExceptionOccurred(env))) {
       
  1708             flush_cache(env);
       
  1709             (*env)->ExceptionDescribe(env);
       
  1710             (*env)->ExceptionClear(env);
       
  1711         }
       
  1712     }
       
  1713     break;
       
  1714 
       
  1715     case XmCR_DROP_SITE_LEAVE_MESSAGE: {
       
  1716 
       
  1717         DASSERT(pending_drag_exit_data.timerId == (XtIntervalId)0);
       
  1718         DASSERT(JNU_IsNull(env, pending_drag_exit_data.dtcpeer));
       
  1719         DASSERT(JNU_IsNull(env, pending_drag_exit_data.component));
       
  1720         DASSERT(pending_drag_exit_data.dragContext == (jlong)0);
       
  1721 
       
  1722         DASSERT(!JNU_IsNull(env, _cache.dtcpeer));
       
  1723         DASSERT(!JNU_IsNull(env, _cache.component));
       
  1724         DASSERT(cbstruct->dragContext != NULL);
       
  1725 
       
  1726         pending_drag_exit_data.dtcpeer =
       
  1727             (*env)->NewGlobalRef(env, _cache.dtcpeer);
       
  1728         pending_drag_exit_data.component =
       
  1729             (*env)->NewGlobalRef(env, _cache.component);
       
  1730         pending_drag_exit_data.dragContext =
       
  1731             ptr_to_jlong(cbstruct->dragContext);
       
  1732 
       
  1733         /*
       
  1734          * Fix for BugTraq ID 4395290.
       
  1735          * Postpone upcall to java, so that we can abort it in case
       
  1736          * if drop immediatelly follows.
       
  1737          */
       
  1738         if (!JNU_IsNull(env, pending_drag_exit_data.dtcpeer) &&
       
  1739             !JNU_IsNull(env, pending_drag_exit_data.component)) {
       
  1740             pending_drag_exit_data.timerId =
       
  1741                 XtAppAddTimeOut(awt_appContext, 0, drag_exit_proc, NULL);
       
  1742             DASSERT(pending_drag_exit_data.timerId != (XtIntervalId)0);
       
  1743         } else {
       
  1744             JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError");
       
  1745             if ((*env)->ExceptionCheck(env) == JNI_TRUE) {
       
  1746                 (*env)->ExceptionDescribe(env);
       
  1747                 (*env)->ExceptionClear(env);
       
  1748             }
       
  1749             if (!JNU_IsNull(env, pending_drag_exit_data.dtcpeer)) {
       
  1750                 (*env)->DeleteGlobalRef(env, pending_drag_exit_data.dtcpeer);
       
  1751             }
       
  1752             if (!JNU_IsNull(env, pending_drag_exit_data.component)) {
       
  1753                 (*env)->DeleteGlobalRef(env, pending_drag_exit_data.component);
       
  1754             }
       
  1755             memset(&pending_drag_exit_data, 0, sizeof(DragExitProcStruct));
       
  1756         }
       
  1757 
       
  1758         ret = java_awt_dnd_DnDConstants_ACTION_NONE;
       
  1759 
       
  1760         /* now cleanup */
       
  1761 
       
  1762         flush_cache(env);
       
  1763     }
       
  1764     break;
       
  1765 
       
  1766     case XmCR_DROP_SITE_MOTION_MESSAGE: {
       
  1767 
       
  1768         /* SECURITY: OK to call this on privileged thread -
       
  1769            peer is secure */
       
  1770         ret = call_dTCmotion(env, _cache.dtcpeer, _cache.component,
       
  1771                              cbstruct->x, cbstruct->y,
       
  1772                              usrAction, src,
       
  1773                              _cache.targets,
       
  1774                              ptr_to_jlong(cbstruct->dragContext));
       
  1775 
       
  1776         if (!JNU_IsNull(env, (*env)->ExceptionOccurred(env))) {
       
  1777             flush_cache(env);
       
  1778             (*env)->ExceptionDescribe(env);
       
  1779             (*env)->ExceptionClear(env);
       
  1780         }
       
  1781 
       
  1782     }
       
  1783     break;
       
  1784 
       
  1785     case XmCR_OPERATION_CHANGED: {
       
  1786 
       
  1787         /* SECURITY: OK to call this on privileged thread -
       
  1788            peer is secure */
       
  1789         ret = call_dTCmotion(env, _cache.dtcpeer, _cache.component,
       
  1790                              cbstruct->x, cbstruct->y,
       
  1791                              usrAction, src,
       
  1792                              _cache.targets,
       
  1793                              ptr_to_jlong(cbstruct->dragContext));
       
  1794 
       
  1795         if (!JNU_IsNull(env, (*env)->ExceptionOccurred(env))) {
       
  1796             flush_cache(env);
       
  1797             (*env)->ExceptionDescribe(env);
       
  1798             (*env)->ExceptionClear(env);
       
  1799         }
       
  1800 
       
  1801     }
       
  1802     break;
       
  1803 
       
  1804     default: break;
       
  1805     }
       
  1806 
       
  1807  wayout:
       
  1808 
       
  1809     /*
       
  1810      * Fix for BugTraq ID 4285634.
       
  1811      * If some modifier keys are pressed the Motif toolkit initializes
       
  1812      * cbstruct->operations this field to the bitwise AND of the
       
  1813      * XmDragOperations resource of the XmDragContext for this drag operation
       
  1814      * and the drop action corresponding to the current modifiers state.
       
  1815      * We should allow the drop target to select a drop action independent of
       
  1816      * the current modifiers state.
       
  1817      */
       
  1818     cbstruct->operation  = DnDConstantsToXm(ret);
       
  1819 
       
  1820     if (cbstruct->reason != XmCR_DROP_SITE_LEAVE_MESSAGE) {
       
  1821         Arg arg;
       
  1822         arg.name = XmNdropSiteOperations;
       
  1823         arg.value = (XtArgVal)cbstruct->operation;
       
  1824 
       
  1825         XmDropSiteUpdate(w, &arg, 1);
       
  1826     }
       
  1827 
       
  1828     if (ret != java_awt_dnd_DnDConstants_ACTION_NONE) {
       
  1829         cbstruct->dropSiteStatus = XmVALID_DROP_SITE;
       
  1830     }  else {
       
  1831         cbstruct->dropSiteStatus = XmINVALID_DROP_SITE;
       
  1832     }
       
  1833 
       
  1834     (*env)->PopLocalFrame(env, NULL);
       
  1835 }
       
  1836 
       
  1837 static void drop_failure_cleanup(JNIEnv* env, Widget dragContext) {
       
  1838     Arg arg;
       
  1839 
       
  1840     DASSERT(dragContext != NULL);
       
  1841     _cache.transfer = NULL;
       
  1842     _cache.dropAction = XmDROP_NOOP;
       
  1843 
       
  1844     arg.name  = XmNtransferStatus;
       
  1845     arg.value = (XtArgVal)XmTRANSFER_FAILURE;
       
  1846     XmDropTransferStart(dragContext, &arg, 1);
       
  1847 
       
  1848     /* Flush here, since awt_XmTransferProc won't be called. */
       
  1849     flush_cache(env);
       
  1850 }
       
  1851 
       
  1852 /**
       
  1853  *
       
  1854  */
       
  1855 
       
  1856 static void awt_XmDropProc(Widget w, XtPointer closure,
       
  1857                            XmDropProcCallbackStruct* cbstruct)
       
  1858 {
       
  1859     JNIEnv*       env       = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
  1860     jint          src       = java_awt_dnd_DnDConstants_ACTION_NONE;
       
  1861     unsigned char operation = selectOperation(cbstruct->operations);
       
  1862     unsigned char srcOps = XmDROP_NOOP;
       
  1863     unsigned char dstOps = XmDROP_NOOP;
       
  1864     Arg           arg;
       
  1865     Boolean       sourceIsExternal = False;
       
  1866 
       
  1867     arg.name = XmNdropSiteOperations;
       
  1868     arg.value = (XtArgVal)&dstOps;
       
  1869     XmDropSiteRetrieve(w, &arg, 1);
       
  1870     arg.value = (XtArgVal)(XmDROP_COPY | XmDROP_MOVE | XmDROP_LINK);
       
  1871     XmDropSiteUpdate(w, &arg, 1);
       
  1872 
       
  1873     /*
       
  1874      * Fix for BugTraq ID 4357905.
       
  1875      * Drop is processed asynchronously on the event dispatch thread.
       
  1876      * We reject other drop attempts to protect the SunDTCP context
       
  1877      * from being overwritten by an upcall before the drop is done.
       
  1878      */
       
  1879     if (!isDropDone()) {
       
  1880         return;
       
  1881     }
       
  1882 
       
  1883     if (cbstruct->dragContext == NULL) {
       
  1884         cbstruct->operation  = XmDROP_NOOP;
       
  1885         cbstruct->dropSiteStatus = XmINVALID_DROP_SITE;
       
  1886         return;
       
  1887     }
       
  1888 
       
  1889     /*
       
  1890      * Fix for BugTraq ID 4492640.
       
  1891      * Because of the Motif bug #4528191 XmNdragOperations resource is always
       
  1892      * equal to XmDROP_MOVE | XmDROP_COPY when the drag source is external.
       
  1893      * The workaround for this bug is to assume that an external drag source
       
  1894      * supports all drop actions.
       
  1895      */
       
  1896     XtVaGetValues(cbstruct->dragContext,
       
  1897                   XmNsourceIsExternal, &sourceIsExternal, NULL);
       
  1898 
       
  1899     if (sourceIsExternal) {
       
  1900         srcOps = XmDROP_LINK | XmDROP_MOVE | XmDROP_COPY;
       
  1901     } else {
       
  1902         /*
       
  1903          * Fix for BugTraq ID 4285634.
       
  1904          * If some modifier keys are pressed the Motif toolkit initializes
       
  1905          * cbstruct->operations to the bitwise AND of the
       
  1906          * XmDragOperations resource of the XmDragContext for this drag operation
       
  1907          * and the drop action corresponding to the current modifiers state.
       
  1908          * We need to determine the drag operations supported by the drag source, so
       
  1909          * we have to get XmNdragOperations value of the XmDragSource.
       
  1910          */
       
  1911         XtVaGetValues(cbstruct->dragContext, XmNdragOperations, &srcOps, NULL);
       
  1912     }
       
  1913 
       
  1914     src = XmToDnDConstants(srcOps);
       
  1915 
       
  1916     if ((srcOps & dstOps) == 0) {
       
  1917         cbstruct->operation  = XmDROP_NOOP;
       
  1918         cbstruct->dropSiteStatus = XmINVALID_DROP_SITE;
       
  1919         drop_failure_cleanup(env, cbstruct->dragContext);
       
  1920         return;
       
  1921     }
       
  1922 
       
  1923     (*env)->PushLocalFrame(env, 0);
       
  1924 
       
  1925     update_cache(env, w, cbstruct->dragContext);
       
  1926 
       
  1927     cacheDropDone(False);
       
  1928 
       
  1929     if (!JNU_IsNull(env, (*env)->ExceptionOccurred(env))) {
       
  1930         (*env)->ExceptionDescribe(env);
       
  1931         (*env)->ExceptionClear(env);
       
  1932         (*env)->PopLocalFrame(env, NULL);
       
  1933         drop_failure_cleanup(env, cbstruct->dragContext);
       
  1934         return;
       
  1935     }
       
  1936 
       
  1937     /*
       
  1938      * Fix for BugTraq ID 4395290.
       
  1939      * Abort a pending upcall to dragExit.
       
  1940      */
       
  1941     pending_drag_exit_data.timerId = (XtIntervalId)0;
       
  1942 
       
  1943     /* SECURITY: OK to call this on privileged thread - peer is secure */
       
  1944     call_dTCdrop(env, _cache.dtcpeer, _cache.component,
       
  1945                  cbstruct->x, cbstruct->y,
       
  1946                  XmToDnDConstants(operation), src, _cache.targets,
       
  1947                  ptr_to_jlong(cbstruct->dragContext));
       
  1948 
       
  1949     if (!JNU_IsNull(env, (*env)->ExceptionOccurred(env))) {
       
  1950         flush_cache(env);
       
  1951         (*env)->ExceptionDescribe(env);
       
  1952         (*env)->ExceptionClear(env);
       
  1953     }
       
  1954     (*env)->PopLocalFrame(env, NULL);
       
  1955 }
       
  1956 
       
  1957 /**
       
  1958  *
       
  1959  */
       
  1960 
       
  1961 static void awt_XmTransferProc(Widget w, XtPointer closure, Atom* selection,
       
  1962                                Atom* type, XtPointer value,
       
  1963                                unsigned long* length, int32_t* format)
       
  1964 {
       
  1965     JNIEnv*  env   = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
  1966     Atom     req   = (Atom)closure;
       
  1967     Display* dpy   = XtDisplayOfObject(w);
       
  1968     jobject  tName = NULL;
       
  1969 
       
  1970     /*
       
  1971      * Note: this method is only called to transfer data between clients
       
  1972      * in different JVM's or native apps. For Intra-JVM transfers the peer
       
  1973      * code shares the sources Transferable with the destination.
       
  1974      */
       
  1975 
       
  1976     if (_cache.w == (Widget)NULL || _cache.transfer != w) {
       
  1977         if (value != NULL) {
       
  1978             XtFree(value);
       
  1979             value = NULL;
       
  1980         }
       
  1981         /* we have already cleaned up ... */
       
  1982         return;
       
  1983     }
       
  1984 
       
  1985     (*env)->PushLocalFrame(env, 0);
       
  1986 
       
  1987     if (*type == None || *type == XT_CONVERT_FAIL) {
       
  1988         /* SECURITY: OK to call this on privileged thread - peer is secure
       
  1989          */
       
  1990         call_dTCtxFailed(env, _cache.dtcpeer, (jlong)req);
       
  1991     } else {
       
  1992         switch (*format) {
       
  1993         case  8:
       
  1994         case 16:
       
  1995         case 32: {
       
  1996             jsize size = (*length <= INT_MAX) ? (jsize)*length : INT_MAX;
       
  1997             jbyteArray arry = (*env)->NewByteArray(env, size);
       
  1998 
       
  1999             if (!JNU_IsNull(env, (*env)->ExceptionOccurred(env))) {
       
  2000                 (*env)->ExceptionDescribe(env);
       
  2001                 (*env)->ExceptionClear(env);
       
  2002 
       
  2003                 /* SECURITY: OK to call this on privileged thread -
       
  2004                    peer is secure */
       
  2005                 call_dTCtxFailed(env, _cache.dtcpeer, (jlong)req);
       
  2006 
       
  2007                 goto wayout;
       
  2008             }
       
  2009 
       
  2010             (*env)->SetByteArrayRegion(env, arry, 0, size, (jbyte*)value);
       
  2011             if (!JNU_IsNull(env, (*env)->ExceptionOccurred(env))) {
       
  2012                 (*env)->ExceptionDescribe(env);
       
  2013                 (*env)->ExceptionClear(env);
       
  2014 
       
  2015                 /* SECURITY: OK to call this on privileged thread -
       
  2016                    peer is secure */
       
  2017                 call_dTCtxFailed(env, _cache.dtcpeer, (jlong)req);
       
  2018                 goto wayout;
       
  2019             }
       
  2020 
       
  2021             arry = (*env)->NewGlobalRef(env, arry);
       
  2022 
       
  2023             if (!JNU_IsNull(env, (*env)->ExceptionOccurred(env))) {
       
  2024                 (*env)->ExceptionDescribe(env);
       
  2025                 (*env)->ExceptionClear(env);
       
  2026             }
       
  2027 
       
  2028             {
       
  2029                 char* tn = XGetAtomName(dpy, *type);
       
  2030 
       
  2031                 tName = (*env)->NewStringUTF(env, (const char *)tn);
       
  2032 
       
  2033                 if (!JNU_IsNull(env, (*env)->ExceptionOccurred(env))) {
       
  2034                     (*env)->ExceptionDescribe(env);
       
  2035                     (*env)->ExceptionClear(env);
       
  2036                 }
       
  2037 
       
  2038                 XFree((void *)tn);
       
  2039             }
       
  2040 
       
  2041             /* SECURITY: OK to call this on privileged thread - peer is
       
  2042                secure */
       
  2043             call_dTCnewData(env, _cache.dtcpeer, (jlong)req, tName, arry);
       
  2044 
       
  2045             if (!JNU_IsNull(env, (*env)->ExceptionOccurred(env))) {
       
  2046                 (*env)->ExceptionDescribe(env);
       
  2047                 (*env)->ExceptionClear(env);
       
  2048             }
       
  2049         }
       
  2050 
       
  2051         default:
       
  2052             break;
       
  2053         }
       
  2054     }
       
  2055 
       
  2056  wayout:
       
  2057     if (value != NULL) {
       
  2058         XtFree(value);
       
  2059         value = NULL;
       
  2060     }
       
  2061 
       
  2062     _cache.transfersPending--;
       
  2063     while (_cache.transfersPending == 0 && !isDropDone()) {
       
  2064         AWT_WAIT(0);
       
  2065     }
       
  2066 
       
  2067     if (isDropDone() && _cache.flushPending) {
       
  2068         flush_cache(env);
       
  2069     }
       
  2070 
       
  2071     (*env)->PopLocalFrame(env, NULL);
       
  2072 }
       
  2073 
       
  2074 /**
       
  2075  *
       
  2076  */
       
  2077 
       
  2078 static void awt_XmDragEnterProc(Widget w, XtPointer closure,
       
  2079                                 XmDropSiteEnterCallbackStruct* cbstruct)
       
  2080 {
       
  2081     JNIEnv*  env   = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
  2082     jobject  this  = (jobject)closure;
       
  2083 
       
  2084     /*  This should only be valid, but Im leaving this part of the old code */
       
  2085     jboolean valid = cbstruct->dropSiteStatus == XmVALID_DROP_SITE
       
  2086         ? JNI_TRUE : JNI_FALSE;
       
  2087 
       
  2088     if (valid == JNI_TRUE) {
       
  2089         /*
       
  2090          * Workaround for Motif bug id #4457656.
       
  2091          * Pointer coordinates passed in cbstruct are incorrect.
       
  2092          * We have to make a round-trip query.
       
  2093          */
       
  2094         Window rootWindow, childWindow;
       
  2095         int32_t xw, yw, xr, yr;
       
  2096         uint32_t modifiers;
       
  2097 
       
  2098         XQueryPointer(awt_display, XtWindow(w),
       
  2099                       &rootWindow, &childWindow, &xr, &yr, &xw, &yw, &modifiers);
       
  2100 
       
  2101         (*env)->PushLocalFrame(env, 0);
       
  2102 
       
  2103         /* SECURITY: OK to call this on privileged thread - peer is secure */
       
  2104         call_dSCenter(env, this, XmToDnDConstants(cbstruct->operation),
       
  2105                       convertModifiers(modifiers), xr, yr);
       
  2106 
       
  2107         if (!JNU_IsNull(env, (*env)->ExceptionOccurred(env))) {
       
  2108             (*env)->ExceptionDescribe(env);
       
  2109             (*env)->ExceptionClear(env);
       
  2110         }
       
  2111 
       
  2112         (*env)->PopLocalFrame(env, NULL);
       
  2113     }
       
  2114 }
       
  2115 
       
  2116 /**
       
  2117  *
       
  2118  */
       
  2119 
       
  2120 static void awt_XmDragMotionProc(Widget w, XtPointer closure,
       
  2121                                  XmDragMotionCallbackStruct* cbstruct)
       
  2122 {
       
  2123     JNIEnv*  env   = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
  2124     jobject  this  = (jobject)closure;
       
  2125 
       
  2126     /*  This should only be valid, but Im leaving this part of the old code */
       
  2127     jboolean valid = cbstruct->dropSiteStatus == XmVALID_DROP_SITE
       
  2128         ? JNI_TRUE : JNI_FALSE;
       
  2129     Window rootWindow, childWindow;
       
  2130     int32_t xw, yw, xr, yr;
       
  2131     uint32_t modifiers;
       
  2132 
       
  2133     XQueryPointer(awt_display, XtWindow(w),
       
  2134                   &rootWindow, &childWindow, &xr, &yr, &xw, &yw, &modifiers);
       
  2135     /*
       
  2136      * Fix for 4285634.
       
  2137      * Use the cached modifiers state, since the directly queried state can
       
  2138      * differ from the one associated with this dnd notification.
       
  2139      */
       
  2140     modifiers = ((XmDragContext)w)->drag.lastEventState;
       
  2141     if (xr != x_root || yr != y_root) {
       
  2142         call_dSCmouseMoved(env, this, XmToDnDConstants(cbstruct->operation),
       
  2143                            convertModifiers(modifiers), xr, yr);
       
  2144 
       
  2145         if ((*env)->ExceptionCheck(env) == JNI_TRUE) {
       
  2146             (*env)->ExceptionDescribe(env);
       
  2147             (*env)->ExceptionClear(env);
       
  2148         }
       
  2149 
       
  2150         x_root = xr;
       
  2151         y_root = yr;
       
  2152     }
       
  2153 
       
  2154     if (valid == JNI_TRUE) {
       
  2155 
       
  2156         (*env)->PushLocalFrame(env, 0);
       
  2157 
       
  2158         /* SECURITY: OK to call this on privileged thread - peer is secure */
       
  2159         call_dSCmotion(env, this, XmToDnDConstants(cbstruct->operation),
       
  2160                        convertModifiers(modifiers), xr, yr);
       
  2161 
       
  2162         if (!JNU_IsNull(env, (*env)->ExceptionOccurred(env))) {
       
  2163             (*env)->ExceptionDescribe(env);
       
  2164             (*env)->ExceptionClear(env);
       
  2165         }
       
  2166 
       
  2167         (*env)->PopLocalFrame(env, NULL);
       
  2168     } else {
       
  2169         (*env)->PushLocalFrame(env, 0);
       
  2170 
       
  2171         /* SECURITY: OK to call this on privileged thread - peer is secure */
       
  2172         call_dSCexit(env, this, xr, yr);
       
  2173 
       
  2174         if (!JNU_IsNull(env, (*env)->ExceptionOccurred(env))) {
       
  2175             (*env)->ExceptionDescribe(env);
       
  2176             (*env)->ExceptionClear(env);
       
  2177         }
       
  2178 
       
  2179         (*env)->PopLocalFrame(env, NULL);
       
  2180     }
       
  2181 }
       
  2182 
       
  2183 /**
       
  2184  *
       
  2185  */
       
  2186 
       
  2187 static void awt_XmDragLeaveProc(Widget w, XtPointer closure,
       
  2188                                 XmDropSiteLeaveCallbackStruct* cbstruct)
       
  2189 {
       
  2190     JNIEnv* env  = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
  2191     jobject this = (jobject)closure;
       
  2192     Window rootWindow, childWindow;
       
  2193     int32_t xw, yw, xr, yr;
       
  2194     uint32_t modifiers;
       
  2195 
       
  2196     XQueryPointer(XtDisplay(w), XtWindow(w),
       
  2197                   &rootWindow, &childWindow, &xr, &yr, &xw, &yw, &modifiers);
       
  2198 
       
  2199     (*env)->PushLocalFrame(env, 0);
       
  2200 
       
  2201     /* SECURITY: OK to call this on privileged thread - peer is secure */
       
  2202     call_dSCexit(env, this, xr, yr);
       
  2203 
       
  2204     if (!JNU_IsNull(env, (*env)->ExceptionOccurred(env))) {
       
  2205         (*env)->ExceptionDescribe(env);
       
  2206         (*env)->ExceptionClear(env);
       
  2207     }
       
  2208 
       
  2209     (*env)->PopLocalFrame(env, NULL);
       
  2210 }
       
  2211 
       
  2212 /**
       
  2213  *
       
  2214  */
       
  2215 
       
  2216 static void awt_XmDropOperationChangedProc(Widget w, XtPointer closure,
       
  2217                                            XmDropStartCallbackStruct* cbstruct)
       
  2218 {
       
  2219     JNIEnv*  env   = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
  2220     jobject  this  = (jobject)closure;
       
  2221     Window rootWindow, childWindow;
       
  2222     int32_t xw, yw, xr, yr;
       
  2223     uint32_t modifiers;
       
  2224 
       
  2225     XQueryPointer(XtDisplay(w), XtWindow(w),
       
  2226                   &rootWindow, &childWindow, &xr, &yr, &xw, &yw, &modifiers);
       
  2227 
       
  2228     (*env)->PushLocalFrame(env, 0);
       
  2229 
       
  2230 
       
  2231     /* SECURITY: OK to call this on privileged thread - peer is secure */
       
  2232     call_dSCchanged(env, this, XmToDnDConstants(cbstruct->operation),
       
  2233                     convertModifiers(modifiers), xr, yr);
       
  2234 
       
  2235     if (!JNU_IsNull(env, (*env)->ExceptionOccurred(env))) {
       
  2236         (*env)->ExceptionDescribe(env);
       
  2237         (*env)->ExceptionClear(env);
       
  2238     }
       
  2239 
       
  2240     (*env)->PopLocalFrame(env, NULL);
       
  2241 }
       
  2242 
       
  2243 /**
       
  2244  *
       
  2245  */
       
  2246 
       
  2247 static void awt_XmDropFinishProc(Widget w, XtPointer closure,
       
  2248                                  XmDropFinishCallbackStruct* cbstruct)
       
  2249 {
       
  2250     JNIEnv* env  = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
  2251     jobject this = (jobject)closure;
       
  2252     unsigned char completionStatus = cbstruct->completionStatus;
       
  2253     jint dropAction = XmToDnDConstants(cbstruct->operation);
       
  2254     Window rootWindow, childWindow;
       
  2255     int32_t xw, yw, xr, yr;
       
  2256     uint32_t modifiers;
       
  2257 
       
  2258     XQueryPointer(XtDisplay(w), XtWindow(w),
       
  2259                   &rootWindow, &childWindow, &xr, &yr, &xw, &yw, &modifiers);
       
  2260 
       
  2261     /* cleanup */
       
  2262 
       
  2263     if (_cache.transfer == NULL) {
       
  2264         dropAction = _cache.dropAction;
       
  2265     }
       
  2266 
       
  2267     _cache.dropAction = java_awt_dnd_DnDConstants_ACTION_NONE;
       
  2268     _cache.win = None;
       
  2269     _cache.state = 0;
       
  2270     XtRemoveEventHandler(w, ButtonReleaseMask, False,
       
  2271                          dragsource_track_release, NULL);
       
  2272 
       
  2273     /* SECURITY: OK to call this on privileged thread - peer is secure */
       
  2274     call_dSCddfinished(env, this, completionStatus, dropAction, xr, yr);
       
  2275 
       
  2276     if (!JNU_IsNull(env, (*env)->ExceptionOccurred(env))) {
       
  2277         (*env)->ExceptionDescribe(env);
       
  2278         (*env)->ExceptionClear(env);
       
  2279     }
       
  2280 
       
  2281     awt_cleanupConvertDataContext(env, MOTIF_DROP_ATOM);
       
  2282 }