--- a/jdk/src/solaris/native/sun/awt/awt_DataTransferer.c Fri Sep 12 14:35:51 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1068 +0,0 @@
-/*
- * Copyright 2000-2005 Sun Microsystems, Inc. All Rights Reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-#ifdef HEADLESS
- #error This file should not be included in headless library
-#endif
-
-#include "awt_p.h"
-#include <X11/Intrinsic.h>
-#include <X11/Xutil.h>
-
-#include <sys/utsname.h>
-
-#include <jni.h>
-#include <jni_util.h>
-
-#include "sun_awt_datatransfer_DataTransferer.h"
-#include "sun_awt_motif_MDataTransferer.h"
-
-#include "awt_XmDnD.h"
-#include "awt_DataTransferer.h"
-
-static jclass string;
-
-XContext awt_convertDataContext = 0;
-
-Atom XA_TARGETS;
-
-extern struct X11GraphicsConfigIDs x11GraphicsConfigIDs;
-
-typedef enum {
- SelectionPending,
- SelectionSuccess,
- SelectionFailure,
- SelectionOwnerTimedOut
-} SelectionStatus;
-
-/* Should only be accessed by the current owner of AWT_LOCK. */
-static SelectionStatus globalSelectionStatus = SelectionPending;
-
-static SelectionStatus get_selection_status() {
- return globalSelectionStatus;
-}
-
-static void set_selection_status(SelectionStatus status) {
- globalSelectionStatus = status;
-}
-
-static void
-selection_request_filter(Widget widget, XtPointer closure, XEvent *event,
- Boolean *cont) {
- if (event->type == SelectionRequest) {
- Window awt_root_window = XtWindow(awt_root_shell);
- Atom selection = event->xselectionrequest.selection;
- Window owner = XGetSelectionOwner(event->xany.display, selection);
-
- if (owner != awt_root_window) {
- XSelectionEvent notify;
-
- notify.type = SelectionNotify;
- notify.display = event->xselectionrequest.display;
- notify.requestor = event->xselectionrequest.requestor;
- notify.selection = event->xselectionrequest.selection;
- notify.time = event->xselectionrequest.time;
- notify.target = event->xselectionrequest.target;
- notify.property = None;
-
- XSendEvent(notify.display, notify.requestor, False,
- (unsigned long)0, (XEvent*)¬ify);
- *cont = False;
- }
- }
-}
-
-/**
- * global function to initialize this client as a Dynamic-only app.
- *
- * gets called once during toolkit initialization.
- */
-
-void awt_initialize_DataTransferer() {
- JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
- jclass stringClassLocal = NULL;
-
- DASSERT(string == NULL);
-
- stringClassLocal = (*env)->FindClass(env, "java/lang/String");
-
- if ((*env)->ExceptionCheck(env) == JNI_TRUE) {
- (*env)->ExceptionDescribe(env);
- (*env)->ExceptionClear(env);
- DASSERT(False);
- }
-
- if (JNU_IsNull(env, stringClassLocal)) return;
-
- string = (*env)->NewGlobalRef(env, stringClassLocal); /* never freed! */
- (*env)->DeleteLocalRef(env, stringClassLocal);
-
- if (JNU_IsNull(env, string)) {
- JNU_ThrowOutOfMemoryError(env, "");
- return;
- }
-
- DASSERT(awt_convertDataContext == 0);
- awt_convertDataContext = XUniqueContext();
- DASSERT(awt_convertDataContext != 0);
-
- /*
- * Fixes for 4513976 and 4818143.
- */
- XtAppSetSelectionTimeout(awt_appContext,
- JNU_CallStaticMethodByName(env, NULL, "sun/awt/UNIXToolkit",
- "getDatatransferTimeout", "()I").i);
-
- /*
- * Xt selection machinery doesn't respond to SelectionRequests if the
- * event arrives on a widget that is not the current selection owner.
- * This can happen if XtDisownSelection was called when SelectionRequest was
- * already on the native queue.
- * If the requestor is another JVM, it hangs for the selection timeout
- * as SelectionNotify is never sent.
- * We install an event handler that filters out SelectionRequests if the
- * awt_root_shell is not the current selection owner.
- */
- XtAddEventHandler(awt_root_shell, (EventMask)0, True,
- selection_request_filter, NULL);
-
- XA_TARGETS = XInternAtom(awt_display, "TARGETS", False);
-}
-
-/*
- * Single routine to convert to target FILE_NAME or _DT_FILENAME
- */
-Boolean
-convertFileType(jbyteArray data, Atom * type, XtPointer * value,
- unsigned long *length, int32_t *format)
-{
- /*
- * Convert the internal representation to an File Name.
- * The data passed is an array of
- * null separated bytes. Each series of bytes is a string
- * that is then converted to an XString which are then put
- * into an XStringList and put into an XTextProperty for
- * usage in other programs.
- *
- * It would be desireable to have dataConvert to this conversion
- * but it isn't possible to return a byte array that represents
- * the XTextProperty.
- */
-
- JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
- jboolean isCopy=JNI_FALSE;
- XTextProperty tp;
- jsize len;
- jsize strings = 0;
- jsize i;
- char** stringList;
- Status s;
- jbyte* bytes;
- char* start;
- size_t slen;
- char* utf;
-
- if ((*env)->PushLocalFrame(env, 16) < 0) {
- return False;
- }
-
- /* convert the data to an Array of Byte Elements */
- bytes = (*env)->GetByteArrayElements(env, data, &isCopy);
- if ((*env)->ExceptionCheck(env) == JNI_TRUE) {
- (*env)->ExceptionDescribe(env);
- (*env)->ExceptionClear(env);
- (*env)->PopLocalFrame(env, NULL);
- return False;
- }
-
- if (JNU_IsNull(env, bytes)) {
- (*env)->PopLocalFrame(env, NULL);
- return False;
- }
-
- /* Get the length of the area */
- len = (*env)->GetArrayLength(env, data);
- if (len == 0) {
- (*env)->ReleaseByteArrayElements(env, data, bytes, JNI_ABORT);
- (*env)->PopLocalFrame(env, NULL);
- return False;
- }
-
- /*
- * determine the number of lists. The byteArray is null separated list of
- * strings.
- */
- for (i = 0; i < len; i++) {
- if (bytes[i] == '\0') {
- strings++;
- }
- }
-
- /* Allocate an X11 string list */
- stringList = (char **)XtCalloc(strings, sizeof(char *));
- if (stringList == (char**)NULL) {
- (*env)->ReleaseByteArrayElements(env, data, bytes, JNI_ABORT);
- (*env)->PopLocalFrame(env, NULL);
- return False;
- }
-
- for (i = 0; i < strings; i++) {
- if (i == 0) {
- start = (char*)bytes;
- } else {
- start = (char*)&bytes[slen];
- }
-
- /*
- * if start is a NULL we're at the end of the list
- * We'll just a have null entry on the end of the list
- */
- if (start[0] == '\0') {
- stringList[i] = NULL;
- continue;
- }
- slen = strlen(start) + 1;
-
- stringList[i] = (char*)XtCalloc(slen, sizeof(char));
-
- if (stringList[i] == (char *)NULL) {
- jsize j;
-
- (*env)->ReleaseByteArrayElements(env, data, bytes, JNI_ABORT);
-
- for (j = 0; j < i; j++) {
- XtFree((void *)stringList[j]);
- }
-
- (*env)->PopLocalFrame(env, NULL);
-
- return False;
- }
-
- memcpy((void *)stringList[i], (const void*)start, slen);
- }
-
- (*env)->ReleaseByteArrayElements(env, data, bytes, JNI_ABORT);
- s = XStringListToTextProperty(stringList, strings, &tp);
-
- /* free the strings that were created */
- for (i = 0; i < strings; i++) {
- if (stringList[i] != NULL) {
- XtFree((void*)stringList[i]);
- }
- }
-
- XtFree((void*)stringList);
-
- if (s == 0) {
- (*env)->PopLocalFrame(env, NULL);
- return False;
- }
-
- *value = (XtPointer)XtCalloc(tp.nitems, sizeof(char));
-
- if (*value == (XtPointer)NULL) {
- XFree((void*)tp.value);
-
- (*env)->PopLocalFrame(env, NULL);
-
- return False;
- }
-
- memcpy((void *)(*value), (const void *)tp.value, tp.nitems);
-
- XFree((void*)tp.value);
-
- *length = tp.nitems;
- *type = tp.encoding;
- *format = tp.format;
- (*env)->PopLocalFrame(env, NULL);
- return True;
-}
-
-/*
- * Class: sun_awt_motif_MDataTransferer
- * Method: getAtomForTarget
- * Signature: (Ljava/lang/String;)J
- */
-
-JNIEXPORT jlong JNICALL
-Java_sun_awt_motif_MDataTransferer_getAtomForTarget(JNIEnv *env,
- jclass cls,
- jstring targetString)
-{
- Atom target;
- char *target_str;
-
- if (JNU_IsNull(env, targetString)) {
- JNU_ThrowNullPointerException(env, "NullPointerException");
- return -1;
- }
- target_str = (char *) JNU_GetStringPlatformChars(env, targetString, NULL);
-
- AWT_LOCK();
-
- target = XInternAtom(awt_display, target_str, False);
-
- AWT_UNLOCK();
-
- JNU_ReleaseStringPlatformChars(env, targetString,
- (const char *) target_str);
- return target;
-}
-
-/*
- * Class: sun_awt_motif_MDataTransferer
- * Method: getTargetNameForAtom
- * Signature: (J)Ljava/lang/String;
- */
-
-JNIEXPORT jstring JNICALL
-Java_sun_awt_motif_MDataTransferer_getTargetNameForAtom(JNIEnv *env,
- jclass cls,
- jlong atom)
-{
- jstring targetString;
- char *name;
-
- AWT_LOCK();
-
- name = XGetAtomName(awt_display, (Atom) atom);
-
- if (name == NULL) {
- JNU_ThrowNullPointerException(env, "Failed to retrieve atom name.");
- AWT_UNLOCK();
- return NULL;
- }
-
- targetString = (*env)->NewStringUTF(env, (const char *)name);
-
- if ((*env)->ExceptionCheck(env) == JNI_TRUE) {
- (*env)->ExceptionDescribe(env);
- (*env)->ExceptionClear(env);
- XFree (name);
- AWT_UNLOCK();
- return NULL;
- }
-
- if (JNU_IsNull(env, targetString)) {
- JNU_ThrowNullPointerException(env, "Failed to create a string.");
- XFree (name);
- AWT_UNLOCK();
- return NULL;
- }
-
- XFree (name);
-
- AWT_UNLOCK();
- return targetString;
-}
-
-/*
- * Class: sun_awt_datatransfer_DataTransferer
- * Method: dragQueryFile
- * Signature: ([B)[Ljava/lang/String;
- *
- * This method converts a byte array that came from File most likely from a
- * drag operation into a String array.
- */
-
-JNIEXPORT jobjectArray JNICALL
-Java_sun_awt_motif_MDataTransferer_dragQueryFile
- (JNIEnv *env, jobject this, jbyteArray bytes)
-{
- XTextProperty tp;
- jbyte *value;
-
- char** strings = (char **)NULL;
- int32_t nstrings = 0;
- jobject filenames;
- jobject ret = NULL;
- int32_t i;
- jsize len;
- jboolean isCopy=JNI_FALSE;
-
- /*
- * If the length of the byte array is 0 just return a null
- */
- len = (*env)->GetArrayLength(env, bytes);
- if (len == 0) {
- return NULL;
- }
-
- value = (*env)->GetByteArrayElements(env, bytes, &isCopy);
- if (JNU_IsNull(env, value)) {
- return NULL;
- }
-
- AWT_LOCK();
-
- tp.encoding = XInternAtom(awt_display, "STRING", False);
- tp.value = (unsigned char *)value;
- tp.nitems = len;
- tp.format = 8;
-
- /*
- * Convert the byte stream into a list of X11 strings
- */
- if (XTextPropertyToStringList(&tp, &strings, &nstrings) == 0 ||
- nstrings == 0)
- {
- (*env)->ReleaseByteArrayElements(env, bytes, value, JNI_ABORT);
- AWT_UNLOCK();
- return NULL;
- }
-
- (*env)->ReleaseByteArrayElements(env, bytes, value, JNI_ABORT);
-
- filenames = (*env)->NewObjectArray(env, nstrings, string, NULL);
-
- if ((*env)->ExceptionCheck(env) == JNI_TRUE) {
- (*env)->ExceptionDescribe(env);
- (*env)->ExceptionClear(env);
- goto wayout;
- }
-
- if (JNU_IsNull(env, filenames)) {
- goto wayout;
- }
-
- /*
- * Actuall conversion code per X11 String
- */
- for (i = 0; i < nstrings; i++) {
- jstring string = (*env)->NewStringUTF(env,
- (const char *)strings[i]);
- if ((*env)->ExceptionCheck(env) == JNI_TRUE) {
- (*env)->ExceptionDescribe(env);
- (*env)->ExceptionClear(env);
- goto wayout;
- }
-
- if (JNU_IsNull(env, string)) {
- goto wayout;
- }
-
- (*env)->SetObjectArrayElement(env, filenames, i, string);
-
- if ((*env)->ExceptionCheck(env) == JNI_TRUE) {
- (*env)->ExceptionDescribe(env);
- (*env)->ExceptionClear(env);
- goto wayout;
- }
-
- (*env)->DeleteLocalRef(env, string);
- }
-
- ret = filenames;
- wayout:
- /*
- * Clean up and return
- */
- XFreeStringList(strings);
- AWT_UNLOCK();
- return ret;
-}
-
-DECLARE_JAVA_CLASS(dataTransfererClazz, "sun/awt/datatransfer/DataTransferer")
-
-/**
- * Returns a local reference to the singleton DataTransferer instance.
- * The caller should delete the reference when done.
- */
-static jobject
-get_data_transferer(JNIEnv* env) {
- jobject transferer = NULL;
-
- DECLARE_STATIC_OBJECT_JAVA_METHOD(getInstanceMethodID, dataTransfererClazz,
- "getInstance",
- "()Lsun/awt/datatransfer/DataTransferer;");
-
- transferer = (*env)->CallStaticObjectMethod(env, clazz, getInstanceMethodID);
-
- if ((*env)->ExceptionCheck(env) == JNI_TRUE) {
- (*env)->ExceptionDescribe(env);
- (*env)->ExceptionClear(env);
- }
-
- DASSERT(!JNU_IsNull(env, transferer));
-
- return transferer;
-}
-
-static jobject
-call_convertData(JNIEnv* env, jobject source, jobject contents, jlong format,
- jobject formatMap) {
- jobject transferer = get_data_transferer(env);
- jobject ret = NULL;
- DECLARE_OBJECT_JAVA_METHOD(convertDataMethodID, dataTransfererClazz,
- "convertData",
- "(Ljava/lang/Object;Ljava/awt/datatransfer/Transferable;JLjava/util/Map;Z)[B");
-
- ret = (*env)->CallObjectMethod(env, transferer, convertDataMethodID,
- source, contents, format, formatMap,
- awt_currentThreadIsPrivileged(env));
-
- if ((*env)->ExceptionCheck(env) == JNI_TRUE) {
- (*env)->ExceptionDescribe(env);
- (*env)->ExceptionClear(env);
- }
-
- (*env)->DeleteLocalRef(env, transferer);
-
- return ret;
-}
-
-static void
-process_convert_data_requests() {
- JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_4);
- jobject transferer = get_data_transferer(env);
-
- DECLARE_VOID_JAVA_METHOD(processDataConversionRequestsMethodID,
- dataTransfererClazz,
- "processDataConversionRequests",
- "()V");
-
- (*env)->CallVoidMethod(env, transferer,
- processDataConversionRequestsMethodID);
-
- if ((*env)->ExceptionCheck(env) == JNI_TRUE) {
- (*env)->ExceptionDescribe(env);
- (*env)->ExceptionClear(env);
- }
-
- (*env)->DeleteLocalRef(env, transferer);
-}
-
-Boolean
-awt_convertData(Widget w, Atom * selection, Atom * target, Atom * type,
- XtPointer * value, unsigned long *length, int32_t *format) {
- JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
- Display* dpy = XtDisplay(w);
- awt_convertDataCallbackStruct* structPtr = NULL;
-
- if (XFindContext(dpy, *selection, awt_convertDataContext,
- (XPointer*)&structPtr) == XCNOMEM || structPtr == NULL) {
- return False;
- }
-
- if ((*env)->PushLocalFrame(env, 2) < 0) {
- (*env)->ExceptionDescribe(env);
- (*env)->ExceptionClear(env);
- return False;
- }
-
- if (*target == XA_TARGETS) {
- jlongArray formats = structPtr->formats;
- jsize count;
- jlong* targets;
- jboolean isCopy;
-
-#ifndef _LP64 /* Atom and jlong are different sizes in the 32-bit build */
- Atom* aValue;
- jlong* saveTargets;
- jsize i;
-#endif
-
- if (JNU_IsNull(env, formats)) {
- (*env)->PopLocalFrame(env, NULL);
- return False;
- }
-
- count = (*env)->GetArrayLength(env, formats);
- if (count == 0) {
- (*env)->PopLocalFrame(env, NULL);
- return False;
- }
-
- targets = (*env)->GetLongArrayElements(env, formats, &isCopy);
-
- *type = XA_ATOM;
- *format = 32;
-
-#ifdef _LP64
- *value = XtMalloc(count * sizeof(Atom));
- memcpy((void *)*value, (void *)targets, count * sizeof(Atom));
-#else
- *value = aValue = (Atom *)XtMalloc(count * sizeof(Atom));
- saveTargets = targets;
- for (i = 0; i < count; i++, aValue++, targets++) {
- *aValue = (Atom)*targets;
- }
- targets = saveTargets;
-#endif
- (*env)->ReleaseLongArrayElements(env, formats, targets, JNI_ABORT);
-
- *length = count;
-
- } else if (*target == XInternAtom(dpy, _XA_DELETE, False)) {
-
- /*
- * acknowledge the DELETE target here ... the "delete" semantic
- * of move will take place after the drop is complete.
- */
-
- *type = XInternAtom(dpy, _XA_NULL, False);
- *length = 0;
- *value = (XtPointer)NULL;
- /* Uninitialized format can cause crash in Xt conversion code. */
- *format = 8;
- } else if (*target == XInternAtom(dpy, _XA_HOSTNAME, False)) {
- struct utsname name;
- XTextProperty tp;
-
- uname(&name);
-
- if (!XStringListToTextProperty((char **)&name.nodename, 1, &tp)) {
- (*env)->PopLocalFrame(env, NULL);
- return False;
- }
-
- *value = (XtPointer)XtCalloc(tp.nitems, sizeof(char));
-
- memcpy((void *)*value, (const void *)tp.value, tp.nitems);
-
- XFree((void *)tp.value);
-
- *type = tp.encoding;
- *length = tp.nitems + 1;
- *format = tp.format;
- } else if (*target == XInternAtom(dpy, _XA_FILENAME, False) ||
- *target == XInternAtom(dpy, _DT_FILENAME, False)) {
-
- /*
- * Convert the internal representation to an File Name.
- * The data returned from dataConvert is a an array of
- * null separated bytes. Each series of bytes is a string
- * that is then converted to an XString which are then put
- * into an XStringList and put into an XTextProperty for
- * usage in other programs.
- *
- * It would be desireable to have dataConvert to this conversion
- * but it isn't possible to return a byte array that represents
- * the XTextProperty.
- */
- jbyteArray data;
-
- /*
- * Fix for 4513976.
- * Type None should be used instead of XT_CONVERT_FAIL
- * to report conversion failure.
- */
- /* assume forthcoming error */
- *type = None;
- *value = (XtPointer)NULL;
- *length = 0;
- *format = 8;
-
- data = call_convertData(env, structPtr->source, structPtr->transferable,
- (jlong)*target, structPtr->formatMap);
-
- /* error test */
- if ((*env)->ExceptionCheck(env) == JNI_TRUE) {
- (*env)->ExceptionDescribe(env);
- (*env)->ExceptionClear(env);
- (*env)->PopLocalFrame(env, NULL);
- return False;
- }
- if (JNU_IsNull(env, data)) {
- (*env)->PopLocalFrame(env, NULL);
- return False;
- }
-
- if (convertFileType(data, type, value, length, format) == False) {
- (*env)->PopLocalFrame(env, NULL);
- return False;
- }
- } else {
- jbyteArray bytes = NULL;
- jbyte* copy = NULL;
-
- /*
- * Fix for 4513976.
- * Type None should be used instead of XT_CONVERT_FAIL
- * to report conversion failure.
- */
- *type = None; /* assume forthcoming error */
- *value = (XtPointer)NULL;
- *length = 0;
- *format = 8;
-
- bytes = call_convertData(env, structPtr->source, structPtr->transferable,
- (jlong)*target, structPtr->formatMap);
-
- if ((*env)->ExceptionCheck(env) == JNI_TRUE) {
- (*env)->ExceptionDescribe(env);
- (*env)->ExceptionClear(env);
- (*env)->PopLocalFrame(env, NULL);
- return False;
- }
-
- if (bytes == NULL) {
- (*env)->PopLocalFrame(env, NULL);
- return False;
- } else {
- jsize len = (*env)->GetArrayLength(env, bytes);
-
- if (len == 0) {
- *type = *target;
- *format = 8;
- (*env)->PopLocalFrame(env, NULL);
- return True;
- }
-
- copy = (jbyte*)XtCalloc(1, len * sizeof(jbyte));
- if (copy == (jbyte*)NULL) {
- JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError");
- (*env)->PopLocalFrame(env, NULL);
- return False;
- }
-
- (*env)->GetByteArrayRegion(env, (jbyteArray)bytes, 0, len, copy);
-
- if ((*env)->ExceptionCheck(env) == JNI_TRUE) {
- (*env)->ExceptionDescribe(env);
- (*env)->ExceptionClear(env);
- XtFree((void *)copy);
- (*env)->PopLocalFrame(env, NULL);
- return False;
- }
-
- *value = (XtPointer)copy;
- *type = *target;
- *length = len;
- *format = 8;
- }
- }
-
- (*env)->PopLocalFrame(env, NULL);
- return True;
-}
-
-
-jlongArray
-getSelectionTargetsHelper(JNIEnv* env, XtPointer value, unsigned long length)
-{
- Atom* targets = (Atom*)value;
- jlongArray targetArray = NULL;
- jlong* checkedTargets = NULL;
- size_t count = 0, i = 0, j = 0;
-
- /* Get rid of zero atoms if there are any. */
- for (; i < length; i++) {
- if (targets[i] != 0) {
- count++;
- }
- }
- checkedTargets = calloc(count, sizeof(jlong));
- if (checkedTargets == NULL) {
- JNU_ThrowOutOfMemoryError(env, "");
- (*env)->ExceptionDescribe(env);
- (*env)->ExceptionClear(env);
- } else {
- for (i = 0; i < length; i++) {
- if (targets[i] != 0) {
- checkedTargets[j++] = targets[i];
- }
- }
-
- DASSERT(j == count);
-
- if ((*env)->EnsureLocalCapacity(env, 1) >= 0) {
-
- targetArray = (*env)->NewLongArray(env, count);
-
- if (!JNU_IsNull(env, targetArray)) {
- (*env)->SetLongArrayRegion(env, targetArray, 0, count,
- checkedTargets);
-
- if ((*env)->ExceptionCheck(env)) {
- (*env)->ExceptionDescribe(env);
- (*env)->ExceptionClear(env);
-
- (*env)->DeleteLocalRef(env, targetArray);
- targetArray = NULL;
- }
- }
- }
- free(checkedTargets);
- }
-
- return targetArray;
-}
-
-static void
-get_selection_targets_callback(Widget w, XtPointer client_data, Atom* selection,
- Atom* type, XtPointer value,
- unsigned long* length, int32_t* format) {
- JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
- jobject* pReturnArray = (jobject*)client_data;
- SelectionStatus status = SelectionFailure;
-
- /*
- * It is highly unlikely that TARGETS will ever be passed even though that
- * was what was requested. However, XA_ATOM ("ATOM") is likely.
- * Actually they are the same so treat them as such. See XToolKit
- * Intrinsic Manual on XtSelectionCallbackProc for more details on type.
- */
- if (*type == XA_TARGETS || *type == XA_ATOM) {
- jlongArray targetArray = getSelectionTargetsHelper(env, value, *length);
- if (!JNU_IsNull(env, targetArray)) {
- *pReturnArray = (*env)->NewGlobalRef(env, targetArray);
- status = SelectionSuccess;
- (*env)->DeleteLocalRef(env, targetArray);
- }
- } else if (*type == XT_CONVERT_FAIL) {
- status = SelectionOwnerTimedOut;
- } else {
- /*
- * A part of the fix for 4259272.
- * Actually Xt Intrinsics says about XtSelectionCallback that
- * "if there is no owner for the specified selection, or that owner
- * cannot convert the selected data to the requested type, then this
- * callback is called with value NULL and length zero".
- * But we report success if type is not TARGETS, XA_ATOM or XT_CONVERT_FAIL,
- * and we should not change this behaviour. We just return zero-length
- * array instead of null, because null denotes that we could not get
- * selection targets at the time of tracking changes of available on
- * the selection data flavors.
- */
- jlongArray targetArray = (*env)->NewLongArray(env, 0);
- *pReturnArray = (*env)->NewGlobalRef(env, targetArray);
- /*
- * Fix for 4655996.
- * Report success if there is no owner for this selection or the owner
- * fails to provide target types.
- */
- status = SelectionSuccess;
- (*env)->DeleteLocalRef(env, targetArray);
- }
-
- if (value != NULL) {
- XtFree(value);
- value = NULL;
- }
-
- set_selection_status(status);
-}
-
-static void
-get_selection_data_callback(Widget w, XtPointer client_data, Atom * selection,
- Atom * type, XtPointer value, unsigned long *length,
- int32_t *format) {
- JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
- jobject* pData = (jobject*)client_data;
- SelectionStatus status = SelectionFailure;
-
- if (*type == XT_CONVERT_FAIL) {
- status = SelectionOwnerTimedOut;
- } else if (*type != None) {
- if ((*env)->EnsureLocalCapacity(env, 1) >= 0) {
- jsize size = (*length <= INT_MAX) ? *length : INT_MAX;
- jbyteArray array = (*env)->NewByteArray(env, size);
-
- if (!JNU_IsNull(env, array)) {
- (*env)->SetByteArrayRegion(env, array, 0, size, (jbyte*)value);
- if ((*env)->ExceptionCheck(env) == JNI_TRUE) {
- (*env)->ExceptionDescribe(env);
- (*env)->ExceptionClear(env);
- } else {
- *pData = (*env)->NewGlobalRef(env, array);
- status = SelectionSuccess;
- }
-
- (*env)->DeleteLocalRef(env, array);
- }
- }
- }
-
- if (value != NULL) {
- XtFree(value);
- value = NULL;
- }
-
- set_selection_status(status);
-}
-
-static int32_t
-wait_for_selection_event(void *data) {
- process_convert_data_requests();
- return get_selection_status() != SelectionPending;
-}
-
-jlongArray
-get_selection_targets(JNIEnv *env, Atom selection, Time time_stamp) {
- jlongArray ret = NULL;
- jlongArray targets = NULL;
- SelectionStatus status = SelectionPending;
-
- AWT_LOCK();
-
- XtAppSetSelectionTimeout(awt_appContext,
- JNU_CallStaticMethodByName(env, NULL, "sun/awt/UNIXToolkit",
- "getDatatransferTimeout", "()I").i);
-
- set_selection_status(SelectionPending);
- XtGetSelectionValue(awt_root_shell, selection, XA_TARGETS,
- get_selection_targets_callback, (XtPointer)&targets,
- time_stamp);
-
- awt_MToolkit_modalWait(wait_for_selection_event, NULL);
- status = get_selection_status();
-
- AWT_FLUSH_UNLOCK();
-
- if (!JNU_IsNull(env, targets)) {
- ret = (*env)->NewLocalRef(env, targets);
- (*env)->DeleteGlobalRef(env, targets);
- }
-
- switch (status) {
- case SelectionSuccess:
- break;
- case SelectionFailure:
- JNU_ThrowByName(env, "java/lang/IllegalStateException",
- "Failed to get selection targets");
- break;
- case SelectionOwnerTimedOut:
- // return an empty array of targets if the selection owner timed out
- ret = (*env)->NewLongArray(env, 0);
- break;
- default:
- JNU_ThrowByName(env, "java/lang/IllegalStateException",
- "Unexpected selection status");
- break;
- }
-
- return ret;
-}
-
-jbyteArray
-get_selection_data(JNIEnv *env, Atom selection, Atom target, Time time_stamp) {
- jbyteArray ret = NULL;
- jbyteArray data = NULL;
- SelectionStatus status = SelectionPending;
-
- AWT_LOCK();
-
- XtAppSetSelectionTimeout(awt_appContext,
- JNU_CallStaticMethodByName(env, NULL, "sun/awt/UNIXToolkit",
- "getDatatransferTimeout", "()I").i);
-
- set_selection_status(SelectionPending);
- XtGetSelectionValue(awt_root_shell, selection, target,
- get_selection_data_callback,
- (XtPointer)&data, time_stamp);
-
- awt_MToolkit_modalWait(wait_for_selection_event, NULL);
- status = get_selection_status();
-
- AWT_FLUSH_UNLOCK();
-
- if (!JNU_IsNull(env, data)) {
- ret = (*env)->NewLocalRef(env, data);
- (*env)->DeleteGlobalRef(env, data);
- }
-
- switch (status) {
- case SelectionSuccess:
- break;
- case SelectionFailure:
- JNU_ThrowIOException(env, "Failed to get selection data");
- break;
- case SelectionOwnerTimedOut:
- JNU_ThrowIOException(env, "Selection owner timed out");
- break;
- default:
- JNU_ThrowIOException(env, "Unexpected selection status");
- break;
- }
-
- return ret;
-}
-
-void
-awt_cleanupConvertDataContext(JNIEnv *env, Atom selectionAtom) {
- awt_convertDataCallbackStruct* structPtr = NULL;
-
- if (XFindContext(awt_display, selectionAtom, awt_convertDataContext,
- (XPointer*)&structPtr) == 0 && structPtr != NULL) {
-
- (*env)->DeleteGlobalRef(env, structPtr->source);
- (*env)->DeleteGlobalRef(env, structPtr->transferable);
- (*env)->DeleteGlobalRef(env, structPtr->formatMap);
- (*env)->DeleteGlobalRef(env, structPtr->formats);
- free(structPtr);
- }
- /*
- * Xlib Programming Manual says that it is better to erase
- * the current entry with XDeleteContext() before XSaveContext().
- */
- XDeleteContext(awt_display, selectionAtom, awt_convertDataContext);
- if (XSaveContext(awt_display, selectionAtom, awt_convertDataContext,
- (XPointer)NULL) == XCNOMEM) {
- JNU_ThrowInternalError(env, "XError");
- (*env)->ExceptionDescribe(env);
- (*env)->ExceptionClear(env);
- }
-}
-
-static Bool exitSecondaryLoop = True;
-
-/*
- * This predicate procedure allows the Toolkit thread to process specific events
- * while it is blocked waiting for the event dispatch thread to process
- * a SunDropTargetEvent. We need this to prevent deadlock when the client code
- * processing SunDropTargetEvent sets or gets the contents of the system
- * clipboard/selection. In this case the event dispatch thread waits for the
- * Toolkit thread to process PropertyNotify or SelectionNotify events.
- */
-static Bool
-secondary_loop_event(Display* dpy, XEvent* event, char* arg) {
- return (event->type == SelectionNotify ||
- event->type == SelectionClear ||
- event->type == PropertyNotify) ? True : False;
-}
-
-
-JNIEXPORT void JNICALL
-Java_sun_awt_motif_MToolkitThreadBlockedHandler_enter(JNIEnv *env, jobject this) {
- DASSERT(exitSecondaryLoop && awt_currentThreadIsPrivileged(env));
- exitSecondaryLoop = False;
- while (!exitSecondaryLoop) {
- XEvent event;
- while (XCheckIfEvent(awt_display, &event, secondary_loop_event, NULL)) {
- XtDispatchEvent(&event);
- }
- AWT_WAIT(AWT_DND_POLL_INTERVAL);
- }
-}
-
-JNIEXPORT void JNICALL
-Java_sun_awt_motif_MToolkitThreadBlockedHandler_exit(JNIEnv *env, jobject this) {
- DASSERT(!exitSecondaryLoop && !awt_currentThreadIsPrivileged(env));
- exitSecondaryLoop = True;
- AWT_NOTIFY_ALL();
-}