src/java.desktop/unix/native/libawt_xawt/xawt/XToolkit.c
changeset 47216 71c04702a3d5
parent 42455 a66ed8458668
child 53112 6e8c8d16ecb4
child 56230 489867818774
equal deleted inserted replaced
47215:4ebc2e2fb97c 47216:71c04702a3d5
       
     1 /*
       
     2  * Copyright (c) 2002, 2016, Oracle and/or its affiliates. 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.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 
       
    26 #include <X11/Xlib.h>
       
    27 #include <X11/Xutil.h>
       
    28 #include <X11/Xos.h>
       
    29 #include <X11/Xatom.h>
       
    30 #ifdef __linux__
       
    31 #include <execinfo.h>
       
    32 #endif
       
    33 
       
    34 #include <jvm.h>
       
    35 #include <jni.h>
       
    36 #include <jlong.h>
       
    37 #include <jni_util.h>
       
    38 
       
    39 #include "awt_p.h"
       
    40 #include "awt_Component.h"
       
    41 #include "awt_MenuComponent.h"
       
    42 #include "awt_Font.h"
       
    43 #include "awt_util.h"
       
    44 
       
    45 #include "sun_awt_X11_XToolkit.h"
       
    46 #include "java_awt_SystemColor.h"
       
    47 #include "java_awt_TrayIcon.h"
       
    48 #include <X11/extensions/XTest.h>
       
    49 
       
    50 #include <unistd.h>
       
    51 
       
    52 uint32_t awt_NumLockMask = 0;
       
    53 Boolean  awt_ModLockIsShiftLock = False;
       
    54 
       
    55 static int32_t num_buttons = 0;
       
    56 int32_t getNumButtons();
       
    57 
       
    58 extern JavaVM *jvm;
       
    59 
       
    60 // Tracing level
       
    61 static int tracing = 0;
       
    62 #ifdef PRINT
       
    63 #undef PRINT
       
    64 #endif
       
    65 #ifdef PRINT2
       
    66 #undef PRINT2
       
    67 #endif
       
    68 
       
    69 #define PRINT if (tracing) printf
       
    70 #define PRINT2 if (tracing > 1) printf
       
    71 
       
    72 
       
    73 struct ComponentIDs componentIDs;
       
    74 
       
    75 struct MenuComponentIDs menuComponentIDs;
       
    76 
       
    77 #ifndef HEADLESS
       
    78 
       
    79 extern Display* awt_init_Display(JNIEnv *env, jobject this);
       
    80 extern void freeNativeStringArray(char **array, jsize length);
       
    81 extern char** stringArrayToNative(JNIEnv *env, jobjectArray array, jsize * ret_length);
       
    82 
       
    83 struct XFontPeerIDs xFontPeerIDs;
       
    84 
       
    85 JNIEXPORT void JNICALL
       
    86 Java_sun_awt_X11_XFontPeer_initIDs
       
    87   (JNIEnv *env, jclass cls)
       
    88 {
       
    89     xFontPeerIDs.xfsname =
       
    90       (*env)->GetFieldID(env, cls, "xfsname", "Ljava/lang/String;");
       
    91 }
       
    92 #endif /* !HEADLESS */
       
    93 
       
    94 /* This function gets called from the static initializer for FileDialog.java
       
    95    to initialize the fieldIDs for fields that may be accessed from C */
       
    96 
       
    97 JNIEXPORT void JNICALL
       
    98 Java_java_awt_FileDialog_initIDs
       
    99   (JNIEnv *env, jclass cls)
       
   100 {
       
   101 
       
   102 }
       
   103 
       
   104 JNIEXPORT void JNICALL
       
   105 Java_sun_awt_X11_XToolkit_initIDs
       
   106   (JNIEnv *env, jclass clazz)
       
   107 {
       
   108     jfieldID fid = (*env)->GetStaticFieldID(env, clazz, "numLockMask", "I");
       
   109     CHECK_NULL(fid);
       
   110     awt_NumLockMask = (*env)->GetStaticIntField(env, clazz, fid);
       
   111     DTRACE_PRINTLN1("awt_NumLockMask = %u", awt_NumLockMask);
       
   112     fid = (*env)->GetStaticFieldID(env, clazz, "modLockIsShiftLock", "I");
       
   113     CHECK_NULL(fid);
       
   114     awt_ModLockIsShiftLock = (*env)->GetStaticIntField(env, clazz, fid) != 0 ? True : False;
       
   115 }
       
   116 
       
   117 /*
       
   118  * Class:     sun_awt_X11_XToolkit
       
   119  * Method:    getTrayIconDisplayTimeout
       
   120  * Signature: ()J
       
   121  */
       
   122 JNIEXPORT jlong JNICALL Java_sun_awt_X11_XToolkit_getTrayIconDisplayTimeout
       
   123   (JNIEnv *env, jclass clazz)
       
   124 {
       
   125     return (jlong) 2000;
       
   126 }
       
   127 
       
   128 /*
       
   129  * Class:     sun_awt_X11_XToolkit
       
   130  * Method:    getDefaultXColormap
       
   131  * Signature: ()J
       
   132  */
       
   133 JNIEXPORT jlong JNICALL Java_sun_awt_X11_XToolkit_getDefaultXColormap
       
   134   (JNIEnv *env, jclass clazz)
       
   135 {
       
   136     AwtGraphicsConfigDataPtr defaultConfig =
       
   137         getDefaultConfig(DefaultScreen(awt_display));
       
   138 
       
   139     return (jlong) defaultConfig->awt_cmap;
       
   140 }
       
   141 
       
   142 JNIEXPORT jlong JNICALL Java_sun_awt_X11_XToolkit_getDefaultScreenData
       
   143   (JNIEnv *env, jclass clazz)
       
   144 {
       
   145     return ptr_to_jlong(getDefaultConfig(DefaultScreen(awt_display)));
       
   146 }
       
   147 
       
   148 
       
   149 JNIEXPORT jint JNICALL
       
   150 DEF_JNI_OnLoad(JavaVM *vm, void *reserved)
       
   151 {
       
   152     jvm = vm;
       
   153     return JNI_VERSION_1_2;
       
   154 }
       
   155 
       
   156 /*
       
   157  * Class:     sun_awt_X11_XToolkit
       
   158  * Method:    nativeLoadSystemColors
       
   159  * Signature: ([I)V
       
   160  */
       
   161 JNIEXPORT void JNICALL Java_sun_awt_X11_XToolkit_nativeLoadSystemColors
       
   162   (JNIEnv *env, jobject this, jintArray systemColors)
       
   163 {
       
   164     AwtGraphicsConfigDataPtr defaultConfig =
       
   165         getDefaultConfig(DefaultScreen(awt_display));
       
   166     awtJNI_CreateColorData(env, defaultConfig, 1);
       
   167 }
       
   168 
       
   169 JNIEXPORT void JNICALL
       
   170 Java_java_awt_Component_initIDs
       
   171   (JNIEnv *env, jclass cls)
       
   172 {
       
   173     jclass keyclass = NULL;
       
   174 
       
   175 
       
   176     componentIDs.x = (*env)->GetFieldID(env, cls, "x", "I");
       
   177     CHECK_NULL(componentIDs.x);
       
   178     componentIDs.y = (*env)->GetFieldID(env, cls, "y", "I");
       
   179     CHECK_NULL(componentIDs.y);
       
   180     componentIDs.width = (*env)->GetFieldID(env, cls, "width", "I");
       
   181     CHECK_NULL(componentIDs.width);
       
   182     componentIDs.height = (*env)->GetFieldID(env, cls, "height", "I");
       
   183     CHECK_NULL(componentIDs.height);
       
   184     componentIDs.isPacked = (*env)->GetFieldID(env, cls, "isPacked", "Z");
       
   185     CHECK_NULL(componentIDs.isPacked);
       
   186     componentIDs.peer =
       
   187       (*env)->GetFieldID(env, cls, "peer", "Ljava/awt/peer/ComponentPeer;");
       
   188     CHECK_NULL(componentIDs.peer);
       
   189     componentIDs.background =
       
   190       (*env)->GetFieldID(env, cls, "background", "Ljava/awt/Color;");
       
   191     CHECK_NULL(componentIDs.background);
       
   192     componentIDs.foreground =
       
   193       (*env)->GetFieldID(env, cls, "foreground", "Ljava/awt/Color;");
       
   194     CHECK_NULL(componentIDs.foreground);
       
   195     componentIDs.graphicsConfig =
       
   196         (*env)->GetFieldID(env, cls, "graphicsConfig",
       
   197                            "Ljava/awt/GraphicsConfiguration;");
       
   198     CHECK_NULL(componentIDs.graphicsConfig);
       
   199     componentIDs.name =
       
   200       (*env)->GetFieldID(env, cls, "name", "Ljava/lang/String;");
       
   201     CHECK_NULL(componentIDs.name);
       
   202 
       
   203     /* Use _NoClientCode() methods for trusted methods, so that we
       
   204      *  know that we are not invoking client code on trusted threads
       
   205      */
       
   206     componentIDs.getParent =
       
   207       (*env)->GetMethodID(env, cls, "getParent_NoClientCode",
       
   208                          "()Ljava/awt/Container;");
       
   209     CHECK_NULL(componentIDs.getParent);
       
   210 
       
   211     componentIDs.getLocationOnScreen =
       
   212       (*env)->GetMethodID(env, cls, "getLocationOnScreen_NoTreeLock",
       
   213                          "()Ljava/awt/Point;");
       
   214     CHECK_NULL(componentIDs.getLocationOnScreen);
       
   215 
       
   216     keyclass = (*env)->FindClass(env, "java/awt/event/KeyEvent");
       
   217     CHECK_NULL(keyclass);
       
   218 
       
   219     componentIDs.isProxyActive =
       
   220         (*env)->GetFieldID(env, keyclass, "isProxyActive",
       
   221                            "Z");
       
   222     CHECK_NULL(componentIDs.isProxyActive);
       
   223 
       
   224     componentIDs.appContext =
       
   225         (*env)->GetFieldID(env, cls, "appContext",
       
   226                            "Lsun/awt/AppContext;");
       
   227 
       
   228     (*env)->DeleteLocalRef(env, keyclass);
       
   229 }
       
   230 
       
   231 
       
   232 JNIEXPORT void JNICALL
       
   233 Java_java_awt_Container_initIDs
       
   234   (JNIEnv *env, jclass cls)
       
   235 {
       
   236 
       
   237 }
       
   238 
       
   239 
       
   240 JNIEXPORT void JNICALL
       
   241 Java_java_awt_Button_initIDs
       
   242   (JNIEnv *env, jclass cls)
       
   243 {
       
   244 
       
   245 }
       
   246 
       
   247 JNIEXPORT void JNICALL
       
   248 Java_java_awt_Scrollbar_initIDs
       
   249   (JNIEnv *env, jclass cls)
       
   250 {
       
   251 
       
   252 }
       
   253 
       
   254 
       
   255 JNIEXPORT void JNICALL
       
   256 Java_java_awt_Window_initIDs
       
   257   (JNIEnv *env, jclass cls)
       
   258 {
       
   259 
       
   260 }
       
   261 
       
   262 JNIEXPORT void JNICALL
       
   263 Java_java_awt_Frame_initIDs
       
   264   (JNIEnv *env, jclass cls)
       
   265 {
       
   266 
       
   267 }
       
   268 
       
   269 
       
   270 JNIEXPORT void JNICALL
       
   271 Java_java_awt_MenuComponent_initIDs(JNIEnv *env, jclass cls)
       
   272 {
       
   273     menuComponentIDs.appContext =
       
   274       (*env)->GetFieldID(env, cls, "appContext", "Lsun/awt/AppContext;");
       
   275 }
       
   276 
       
   277 JNIEXPORT void JNICALL
       
   278 Java_java_awt_Cursor_initIDs(JNIEnv *env, jclass cls)
       
   279 {
       
   280 }
       
   281 
       
   282 
       
   283 JNIEXPORT void JNICALL Java_java_awt_MenuItem_initIDs
       
   284   (JNIEnv *env, jclass cls)
       
   285 {
       
   286 }
       
   287 
       
   288 
       
   289 JNIEXPORT void JNICALL Java_java_awt_Menu_initIDs
       
   290   (JNIEnv *env, jclass cls)
       
   291 {
       
   292 }
       
   293 
       
   294 JNIEXPORT void JNICALL
       
   295 Java_java_awt_TextArea_initIDs
       
   296   (JNIEnv *env, jclass cls)
       
   297 {
       
   298 }
       
   299 
       
   300 
       
   301 JNIEXPORT void JNICALL
       
   302 Java_java_awt_Checkbox_initIDs
       
   303   (JNIEnv *env, jclass cls)
       
   304 {
       
   305 }
       
   306 
       
   307 
       
   308 JNIEXPORT void JNICALL Java_java_awt_ScrollPane_initIDs
       
   309   (JNIEnv *env, jclass cls)
       
   310 {
       
   311 }
       
   312 
       
   313 JNIEXPORT void JNICALL
       
   314 Java_java_awt_TextField_initIDs
       
   315   (JNIEnv *env, jclass cls)
       
   316 {
       
   317 }
       
   318 
       
   319 JNIEXPORT jboolean JNICALL AWTIsHeadless() {
       
   320 #ifdef HEADLESS
       
   321     return JNI_TRUE;
       
   322 #else
       
   323     return JNI_FALSE;
       
   324 #endif
       
   325 }
       
   326 
       
   327 JNIEXPORT void JNICALL Java_java_awt_Dialog_initIDs (JNIEnv *env, jclass cls)
       
   328 {
       
   329 }
       
   330 
       
   331 
       
   332 /* ========================== Begin poll section ================================ */
       
   333 
       
   334 // Includes
       
   335 
       
   336 #include <sys/time.h>
       
   337 #include <limits.h>
       
   338 #include <locale.h>
       
   339 #include <pthread.h>
       
   340 
       
   341 #include <dlfcn.h>
       
   342 #include <fcntl.h>
       
   343 
       
   344 #include <poll.h>
       
   345 #ifndef POLLRDNORM
       
   346 #define POLLRDNORM POLLIN
       
   347 #endif
       
   348 
       
   349 // Prototypes
       
   350 
       
   351 static void     waitForEvents(JNIEnv *, jlong);
       
   352 static void     awt_pipe_init();
       
   353 static Boolean  performPoll(JNIEnv *, jlong);
       
   354 static void     wakeUp();
       
   355 static void     update_poll_timeout(int timeout_control);
       
   356 static uint32_t get_poll_timeout(jlong nextTaskTime);
       
   357 
       
   358 // Defines
       
   359 
       
   360 #ifndef bzero
       
   361 #define bzero(a,b) memset(a, 0, b)
       
   362 #endif
       
   363 
       
   364 #define AWT_POLL_BUFSIZE        100 /* bytes */
       
   365 #define AWT_READPIPE            (awt_pipe_fds[0])
       
   366 #define AWT_WRITEPIPE           (awt_pipe_fds[1])
       
   367 
       
   368 #define DEF_AWT_MAX_POLL_TIMEOUT ((uint32_t)500) /* milliseconds */
       
   369 #define DEF_AWT_FLUSH_TIMEOUT ((uint32_t)100) /* milliseconds */
       
   370 #define AWT_MIN_POLL_TIMEOUT ((uint32_t)0) /* milliseconds */
       
   371 
       
   372 #define TIMEOUT_TIMEDOUT 0
       
   373 #define TIMEOUT_EVENTS 1
       
   374 
       
   375 /* awt_poll_alg - AWT Poll Events Aging Algorithms */
       
   376 #define AWT_POLL_FALSE        1
       
   377 #define AWT_POLL_AGING_SLOW   2
       
   378 #define AWT_POLL_AGING_FAST   3
       
   379 
       
   380 #define AWT_POLL_THRESHOLD 1000  // msec, Block if delay is larger
       
   381 #define AWT_POLL_BLOCK       -1  // cause poll() block
       
   382 
       
   383 // Static fields
       
   384 
       
   385 static int          awt_poll_alg = AWT_POLL_AGING_SLOW;
       
   386 
       
   387 static uint32_t AWT_FLUSH_TIMEOUT  =  DEF_AWT_FLUSH_TIMEOUT; /* milliseconds */
       
   388 static uint32_t AWT_MAX_POLL_TIMEOUT = DEF_AWT_MAX_POLL_TIMEOUT; /* milliseconds */
       
   389 static pthread_t    awt_MainThread = 0;
       
   390 static int32_t      awt_pipe_fds[2];                   /* fds for wkaeup pipe */
       
   391 static Boolean      awt_pipe_inited = False;           /* make sure pipe is initialized before write */
       
   392 static jlong        awt_next_flush_time = 0LL; /* 0 == no scheduled flush */
       
   393 static jlong        awt_last_flush_time = 0LL; /* 0 == no scheduled flush */
       
   394 static uint32_t     curPollTimeout;
       
   395 static struct pollfd pollFds[2];
       
   396 static jlong        poll_sleep_time = 0LL; // Used for tracing
       
   397 static jlong        poll_wakeup_time = 0LL; // Used for tracing
       
   398 
       
   399 // AWT static poll timeout.  Zero means "not set", aging algorithm is
       
   400 // used.  Static poll timeout values higher than 50 cause application
       
   401 // look "slow" - they don't respond to user request fast
       
   402 // enough. Static poll timeout value less than 10 are usually
       
   403 // considered by schedulers as zero, so this might cause unnecessary
       
   404 // CPU consumption by Java.  The values between 10 - 50 are suggested
       
   405 // for single client desktop configurations.  For SunRay servers, it
       
   406 // is highly recomended to use aging algorithm (set static poll timeout
       
   407 // to 0).
       
   408 static int32_t static_poll_timeout = 0;
       
   409 
       
   410 static Bool isMainThread() {
       
   411     return awt_MainThread == pthread_self();
       
   412 }
       
   413 
       
   414 /*
       
   415  * Creates the AWT utility pipe. This pipe exists solely so that
       
   416  * we can cause the main event thread to wake up from a poll() or
       
   417  * select() by writing to this pipe.
       
   418  */
       
   419 static void
       
   420 awt_pipe_init() {
       
   421 
       
   422     if (awt_pipe_inited) {
       
   423         return;
       
   424     }
       
   425 
       
   426     if ( pipe ( awt_pipe_fds ) == 0 )
       
   427     {
       
   428         /*
       
   429         ** the write wakes us up from the infinite sleep, which
       
   430         ** then we cause a delay of AWT_FLUSHTIME and then we
       
   431         ** flush.
       
   432         */
       
   433         int32_t flags = 0;
       
   434         /* set the pipe to be non-blocking */
       
   435         flags = fcntl ( AWT_READPIPE, F_GETFL, 0 );
       
   436         fcntl( AWT_READPIPE, F_SETFL, flags | O_NDELAY | O_NONBLOCK );
       
   437         flags = fcntl ( AWT_WRITEPIPE, F_GETFL, 0 );
       
   438         fcntl( AWT_WRITEPIPE, F_SETFL, flags | O_NDELAY | O_NONBLOCK );
       
   439         awt_pipe_inited = True;
       
   440     }
       
   441     else
       
   442     {
       
   443         AWT_READPIPE = -1;
       
   444         AWT_WRITEPIPE = -1;
       
   445     }
       
   446 
       
   447 
       
   448 } /* awt_pipe_init() */
       
   449 
       
   450 /**
       
   451  * Reads environment variables to initialize timeout fields.
       
   452  */
       
   453 static void readEnv() {
       
   454     char * value;
       
   455     int tmp_poll_alg;
       
   456     static Boolean env_read = False;
       
   457     if (env_read) return;
       
   458 
       
   459     env_read = True;
       
   460 
       
   461     value = getenv("_AWT_MAX_POLL_TIMEOUT");
       
   462     if (value != NULL) {
       
   463         AWT_MAX_POLL_TIMEOUT = atoi(value);
       
   464         if (AWT_MAX_POLL_TIMEOUT == 0) {
       
   465             AWT_MAX_POLL_TIMEOUT = DEF_AWT_MAX_POLL_TIMEOUT;
       
   466         }
       
   467     }
       
   468     curPollTimeout = AWT_MAX_POLL_TIMEOUT/2;
       
   469 
       
   470     value = getenv("_AWT_FLUSH_TIMEOUT");
       
   471     if (value != NULL) {
       
   472         AWT_FLUSH_TIMEOUT = atoi(value);
       
   473         if (AWT_FLUSH_TIMEOUT == 0) {
       
   474             AWT_FLUSH_TIMEOUT = DEF_AWT_FLUSH_TIMEOUT;
       
   475         }
       
   476     }
       
   477 
       
   478     value = getenv("_AWT_POLL_TRACING");
       
   479     if (value != NULL) {
       
   480         tracing = atoi(value);
       
   481     }
       
   482 
       
   483     value = getenv("_AWT_STATIC_POLL_TIMEOUT");
       
   484     if (value != NULL) {
       
   485         static_poll_timeout = atoi(value);
       
   486     }
       
   487     if (static_poll_timeout != 0) {
       
   488         curPollTimeout = static_poll_timeout;
       
   489     }
       
   490 
       
   491     // non-blocking poll()
       
   492     value = getenv("_AWT_POLL_ALG");
       
   493     if (value != NULL) {
       
   494         tmp_poll_alg = atoi(value);
       
   495         switch(tmp_poll_alg) {
       
   496         case AWT_POLL_FALSE:
       
   497         case AWT_POLL_AGING_SLOW:
       
   498         case AWT_POLL_AGING_FAST:
       
   499             awt_poll_alg = tmp_poll_alg;
       
   500             break;
       
   501         default:
       
   502             PRINT("Unknown value of _AWT_POLL_ALG, assuming Slow Aging Algorithm by default");
       
   503             awt_poll_alg = AWT_POLL_AGING_SLOW;
       
   504             break;
       
   505         }
       
   506     }
       
   507 }
       
   508 
       
   509 /**
       
   510  * Returns the amount of milliseconds similar to System.currentTimeMillis()
       
   511  */
       
   512 static jlong
       
   513 awtJNI_TimeMillis(void)
       
   514 {
       
   515     struct timeval t;
       
   516 
       
   517     gettimeofday(&t, 0);
       
   518 
       
   519     return jlong_add(jlong_mul(jint_to_jlong(t.tv_sec), jint_to_jlong(1000)),
       
   520              jint_to_jlong(t.tv_usec / 1000));
       
   521 }
       
   522 
       
   523 /**
       
   524  * Updates curPollTimeout according to the aging algorithm.
       
   525  * @param timeout_control Either TIMEOUT_TIMEDOUT or TIMEOUT_EVENTS
       
   526  */
       
   527 static void update_poll_timeout(int timeout_control) {
       
   528     PRINT2("tout: %d\n", timeout_control);
       
   529 
       
   530     // If static_poll_timeout is set, curPollTimeout has the fixed value
       
   531     if (static_poll_timeout != 0) return;
       
   532 
       
   533     // Update it otherwise
       
   534 
       
   535     switch(awt_poll_alg) {
       
   536     case AWT_POLL_AGING_SLOW:
       
   537         if (timeout_control == TIMEOUT_TIMEDOUT) {
       
   538             /* add 1/4 (plus 1, in case the division truncates to 0) */
       
   539             curPollTimeout += ((curPollTimeout>>2) + 1);
       
   540             curPollTimeout = min(AWT_MAX_POLL_TIMEOUT, curPollTimeout);
       
   541         } else if (timeout_control == TIMEOUT_EVENTS) {
       
   542             /* subtract 1/4 (plus 1, in case the division truncates to 0) */
       
   543             if (curPollTimeout > 0) {
       
   544                 curPollTimeout -= ((curPollTimeout>>2) + 1);
       
   545                 curPollTimeout = max(AWT_MIN_POLL_TIMEOUT, curPollTimeout);
       
   546             }
       
   547         }
       
   548         break;
       
   549     case AWT_POLL_AGING_FAST:
       
   550         if (timeout_control == TIMEOUT_TIMEDOUT) {
       
   551             curPollTimeout += ((curPollTimeout>>2) + 1);
       
   552             curPollTimeout = min(AWT_MAX_POLL_TIMEOUT, curPollTimeout);
       
   553             if((int)curPollTimeout > AWT_POLL_THRESHOLD || (int)curPollTimeout == AWT_POLL_BLOCK)
       
   554                 curPollTimeout = AWT_POLL_BLOCK;
       
   555         } else if (timeout_control == TIMEOUT_EVENTS) {
       
   556             curPollTimeout = max(AWT_MIN_POLL_TIMEOUT, 1);
       
   557         }
       
   558         break;
       
   559     }
       
   560 }
       
   561 
       
   562 /*
       
   563  * Gets the best timeout for the next call to poll().
       
   564  *
       
   565  * @param nextTaskTime -1, if there are no tasks; next time when
       
   566  * timeout task needs to be run, in millis(of currentTimeMillis)
       
   567  */
       
   568 static uint32_t get_poll_timeout(jlong nextTaskTime)
       
   569 {
       
   570     uint32_t ret_timeout = 0;
       
   571     uint32_t timeout;
       
   572     uint32_t taskTimeout;
       
   573     uint32_t flushTimeout;
       
   574 
       
   575     jlong curTime = awtJNI_TimeMillis();
       
   576     timeout = curPollTimeout;
       
   577     switch(awt_poll_alg) {
       
   578     case AWT_POLL_AGING_SLOW:
       
   579     case AWT_POLL_AGING_FAST:
       
   580         taskTimeout = (nextTaskTime == -1) ? AWT_MAX_POLL_TIMEOUT : (uint32_t)max(0, (int32_t)(nextTaskTime - curTime));
       
   581         flushTimeout = (awt_next_flush_time > 0) ? (uint32_t)max(0, (int32_t)(awt_next_flush_time - curTime)) : AWT_MAX_POLL_TIMEOUT;
       
   582 
       
   583         PRINT2("to: %d, ft: %d, to: %d, tt: %d, mil: %d\n", taskTimeout, flushTimeout, timeout, (int)nextTaskTime, (int)curTime);
       
   584 
       
   585         // Adjust timeout to flush_time and task_time
       
   586         ret_timeout = min(flushTimeout, min(taskTimeout, timeout));
       
   587         if((int)curPollTimeout == AWT_POLL_BLOCK)
       
   588            ret_timeout = AWT_POLL_BLOCK;
       
   589         break;
       
   590 
       
   591     case AWT_POLL_FALSE:
       
   592         ret_timeout = (nextTaskTime > curTime) ?
       
   593             (nextTaskTime - curTime) :
       
   594             ((nextTaskTime == -1) ? -1 : 0);
       
   595         break;
       
   596     }
       
   597 
       
   598     return ret_timeout;
       
   599 
       
   600 } /* get_poll_timeout() */
       
   601 
       
   602 /*
       
   603  * Waits for X events to appear on the pipe. Returns only when
       
   604  * it is likely (but not definite) that there are events waiting to
       
   605  * be processed.
       
   606  *
       
   607  * This routine also flushes the outgoing X queue, when the
       
   608  * awt_next_flush_time has been reached.
       
   609  *
       
   610  * If fdAWTPipe is greater or equal than zero the routine also
       
   611  * checks if there are events pending on the putback queue.
       
   612  */
       
   613 void
       
   614 waitForEvents(JNIEnv *env, jlong nextTaskTime) {
       
   615     if (performPoll(env, nextTaskTime)
       
   616           && (awt_next_flush_time > 0)
       
   617           && (awtJNI_TimeMillis() >= awt_next_flush_time)) {
       
   618 
       
   619                 XFlush(awt_display);
       
   620                 awt_last_flush_time = awt_next_flush_time;
       
   621                 awt_next_flush_time = 0LL;
       
   622     }
       
   623 } /* waitForEvents() */
       
   624 
       
   625 JNIEXPORT void JNICALL Java_sun_awt_X11_XToolkit_waitForEvents (JNIEnv *env, jclass class, jlong nextTaskTime) {
       
   626     waitForEvents(env, nextTaskTime);
       
   627 }
       
   628 
       
   629 JNIEXPORT void JNICALL Java_sun_awt_X11_XToolkit_awt_1toolkit_1init (JNIEnv *env, jclass class) {
       
   630     awt_MainThread = pthread_self();
       
   631 
       
   632     awt_pipe_init();
       
   633     readEnv();
       
   634 }
       
   635 
       
   636 JNIEXPORT void JNICALL Java_sun_awt_X11_XToolkit_awt_1output_1flush (JNIEnv *env, jclass class) {
       
   637     awt_output_flush();
       
   638 }
       
   639 
       
   640 JNIEXPORT void JNICALL Java_sun_awt_X11_XToolkit_wakeup_1poll (JNIEnv *env, jclass class) {
       
   641     wakeUp();
       
   642 }
       
   643 
       
   644 /*
       
   645  * Polls both the X pipe and our AWT utility pipe. Returns
       
   646  * when there is data on one of the pipes, or the operation times
       
   647  * out.
       
   648  *
       
   649  * Not all Xt events come across the X pipe (e.g., timers
       
   650  * and alternate inputs), so we must time out every now and
       
   651  * then to check the Xt event queue.
       
   652  *
       
   653  * The fdAWTPipe will be empty when this returns.
       
   654  */
       
   655 static Boolean
       
   656 performPoll(JNIEnv *env, jlong nextTaskTime) {
       
   657     static Bool pollFdsInited = False;
       
   658     static char read_buf[AWT_POLL_BUFSIZE + 1];    /* dummy buf to empty pipe */
       
   659 
       
   660     uint32_t timeout = get_poll_timeout(nextTaskTime);
       
   661     int32_t result;
       
   662 
       
   663     if (!pollFdsInited) {
       
   664         pollFds[0].fd = ConnectionNumber(awt_display);
       
   665         pollFds[0].events = POLLRDNORM;
       
   666         pollFds[0].revents = 0;
       
   667 
       
   668         pollFds[1].fd = AWT_READPIPE;
       
   669         pollFds[1].events = POLLRDNORM;
       
   670         pollFds[1].revents = 0;
       
   671         pollFdsInited = True;
       
   672     } else {
       
   673         pollFds[0].revents = 0;
       
   674         pollFds[1].revents = 0;
       
   675     }
       
   676 
       
   677     AWT_NOFLUSH_UNLOCK();
       
   678 
       
   679     /* ACTUALLY DO THE POLL() */
       
   680     if (timeout == 0) {
       
   681         // be sure other threads get a chance
       
   682         if (!awtJNI_ThreadYield(env)) {
       
   683             return FALSE;
       
   684         }
       
   685     }
       
   686 
       
   687     if (tracing) poll_sleep_time = awtJNI_TimeMillis();
       
   688     result = poll( pollFds, 2, (int32_t) timeout );
       
   689     if (tracing) poll_wakeup_time = awtJNI_TimeMillis();
       
   690     PRINT("%d of %d, res: %d\n", (int)(poll_wakeup_time-poll_sleep_time), (int)timeout, result);
       
   691 
       
   692     AWT_LOCK();
       
   693     if (result == 0) {
       
   694         /* poll() timed out -- update timeout value */
       
   695         update_poll_timeout(TIMEOUT_TIMEDOUT);
       
   696         PRINT2("performPoll(): TIMEOUT_TIMEDOUT curPollTimeout = %d \n", curPollTimeout);
       
   697     }
       
   698     if (pollFds[1].revents) {
       
   699         int count;
       
   700         PRINT("Woke up\n");
       
   701         /* There is data on the AWT pipe - empty it */
       
   702         do {
       
   703             count = read(AWT_READPIPE, read_buf, AWT_POLL_BUFSIZE );
       
   704         } while (count == AWT_POLL_BUFSIZE );
       
   705         PRINT2("performPoll():  data on the AWT pipe: curPollTimeout = %d \n", curPollTimeout);
       
   706     }
       
   707     if (pollFds[0].revents) {
       
   708         // Events in X pipe
       
   709         update_poll_timeout(TIMEOUT_EVENTS);
       
   710         PRINT2("performPoll(): TIMEOUT_EVENTS curPollTimeout = %d \n", curPollTimeout);
       
   711     }
       
   712     return TRUE;
       
   713 
       
   714 } /* performPoll() */
       
   715 
       
   716 /**
       
   717  * Schedules next auto-flush event or performs forced flush depending
       
   718  * on the time of the previous flush.
       
   719  */
       
   720 void awt_output_flush() {
       
   721     if (awt_next_flush_time == 0) {
       
   722         JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
   723 
       
   724         jlong curTime = awtJNI_TimeMillis(); // current time
       
   725         jlong l_awt_last_flush_time = awt_last_flush_time; // last time we flushed queue
       
   726         jlong next_flush_time = l_awt_last_flush_time + AWT_FLUSH_TIMEOUT;
       
   727 
       
   728         if (curTime >= next_flush_time) {
       
   729             // Enough time passed from last flush
       
   730             PRINT("f1\n");
       
   731             AWT_LOCK();
       
   732             XFlush(awt_display);
       
   733             awt_last_flush_time = curTime;
       
   734             AWT_NOFLUSH_UNLOCK();
       
   735         } else {
       
   736             awt_next_flush_time = next_flush_time;
       
   737             PRINT("f2\n");
       
   738             wakeUp();
       
   739         }
       
   740     }
       
   741 }
       
   742 
       
   743 
       
   744 /**
       
   745  * Wakes-up poll() in performPoll
       
   746  */
       
   747 static void wakeUp() {
       
   748     static char wakeUp_char = 'p';
       
   749     if (!isMainThread() && awt_pipe_inited) {
       
   750         write ( AWT_WRITEPIPE, &wakeUp_char, 1 );
       
   751     }
       
   752 }
       
   753 
       
   754 
       
   755 /* ========================== End poll section ================================= */
       
   756 
       
   757 /*
       
   758  * Class:     java_awt_KeyboardFocusManager
       
   759  * Method:    initIDs
       
   760  * Signature: ()V
       
   761  */
       
   762 JNIEXPORT void JNICALL
       
   763 Java_java_awt_KeyboardFocusManager_initIDs
       
   764     (JNIEnv *env, jclass cls)
       
   765 {
       
   766 }
       
   767 
       
   768 /*
       
   769  * Class:     sun_awt_X11_XToolkit
       
   770  * Method:    getEnv
       
   771  * Signature: (Ljava/lang/String;)Ljava/lang/String;
       
   772  */
       
   773 JNIEXPORT jstring JNICALL Java_sun_awt_X11_XToolkit_getEnv
       
   774 (JNIEnv *env , jclass clazz, jstring key) {
       
   775     char *ptr = NULL;
       
   776     const char *keystr = NULL;
       
   777     jstring ret = NULL;
       
   778 
       
   779     keystr = JNU_GetStringPlatformChars(env, key, NULL);
       
   780     if (keystr) {
       
   781         ptr = getenv(keystr);
       
   782         if (ptr) {
       
   783             ret = JNU_NewStringPlatform(env, (const char *) ptr);
       
   784         }
       
   785         JNU_ReleaseStringPlatformChars(env, key, (const char*)keystr);
       
   786     }
       
   787     return ret;
       
   788 }
       
   789 
       
   790 #ifdef __linux__
       
   791 void print_stack(void)
       
   792 {
       
   793   void *array[10];
       
   794   size_t size;
       
   795   char **strings;
       
   796   size_t i;
       
   797 
       
   798   size = backtrace (array, 10);
       
   799   strings = backtrace_symbols (array, size);
       
   800 
       
   801   fprintf (stderr, "Obtained %zd stack frames.\n", size);
       
   802 
       
   803   for (i = 0; i < size; i++)
       
   804      fprintf (stderr, "%s\n", strings[i]);
       
   805 
       
   806   free (strings);
       
   807 }
       
   808 #endif
       
   809 
       
   810 Window get_xawt_root_shell(JNIEnv *env) {
       
   811   static jclass classXRootWindow = NULL;
       
   812   static jmethodID methodGetXRootWindow = NULL;
       
   813   static Window xawt_root_shell = None;
       
   814 
       
   815   if (xawt_root_shell == None){
       
   816       if (classXRootWindow == NULL){
       
   817           jclass cls_tmp = (*env)->FindClass(env, "sun/awt/X11/XRootWindow");
       
   818           if (!JNU_IsNull(env, cls_tmp)) {
       
   819               classXRootWindow = (jclass)(*env)->NewGlobalRef(env, cls_tmp);
       
   820               (*env)->DeleteLocalRef(env, cls_tmp);
       
   821           }
       
   822       }
       
   823       if( classXRootWindow != NULL) {
       
   824           methodGetXRootWindow = (*env)->GetStaticMethodID(env, classXRootWindow, "getXRootWindow", "()J");
       
   825       }
       
   826       if( classXRootWindow != NULL && methodGetXRootWindow !=NULL ) {
       
   827           xawt_root_shell = (Window) (*env)->CallStaticLongMethod(env, classXRootWindow, methodGetXRootWindow);
       
   828       }
       
   829       if ((*env)->ExceptionCheck(env)) {
       
   830         (*env)->ExceptionDescribe(env);
       
   831         (*env)->ExceptionClear(env);
       
   832       }
       
   833   }
       
   834   return xawt_root_shell;
       
   835 }
       
   836 
       
   837 /*
       
   838  * Old, compatibility, backdoor for DT.  This is a different
       
   839  * implementation.  It keeps the signature, but acts on
       
   840  * awt_root_shell, not the frame passed as an argument.  Note, that
       
   841  * the code that uses the old backdoor doesn't work correctly with
       
   842  * gnome session proxy that checks for WM_COMMAND when the window is
       
   843  * firts mapped, because DT code calls this old backdoor *after* the
       
   844  * frame is shown or it would get NPE with old AWT (previous
       
   845  * implementation of this backdoor) otherwise.  Old style session
       
   846  * managers (e.g. CDE) that check WM_COMMAND only during session
       
   847  * checkpoint should work fine, though.
       
   848  *
       
   849  * NB: The function name looks deceptively like a JNI native method
       
   850  * name.  It's not!  It's just a plain function.
       
   851  */
       
   852 
       
   853 JNIEXPORT void JNICALL
       
   854 Java_sun_awt_motif_XsessionWMcommand(JNIEnv *env, jobject this,
       
   855     jobject frame, jstring jcommand)
       
   856 {
       
   857     const char *command;
       
   858     XTextProperty text_prop;
       
   859     char *c[1];
       
   860     int32_t status;
       
   861     Window xawt_root_window;
       
   862 
       
   863     AWT_LOCK();
       
   864     xawt_root_window = get_xawt_root_shell(env);
       
   865 
       
   866     if ( xawt_root_window == None ) {
       
   867         AWT_UNLOCK();
       
   868         JNU_ThrowNullPointerException(env, "AWT root shell is unrealized");
       
   869         return;
       
   870     }
       
   871 
       
   872     command = (char *) JNU_GetStringPlatformChars(env, jcommand, NULL);
       
   873     if (command != NULL) {
       
   874         c[0] = (char *)command;
       
   875         status = XmbTextListToTextProperty(awt_display, c, 1,
       
   876                                            XStdICCTextStyle, &text_prop);
       
   877 
       
   878         if (status == Success || status > 0) {
       
   879             XSetTextProperty(awt_display, xawt_root_window,
       
   880                              &text_prop, XA_WM_COMMAND);
       
   881             if (text_prop.value != NULL)
       
   882                 XFree(text_prop.value);
       
   883         }
       
   884         JNU_ReleaseStringPlatformChars(env, jcommand, command);
       
   885     }
       
   886     AWT_UNLOCK();
       
   887 }
       
   888 
       
   889 
       
   890 /*
       
   891  * New DT backdoor to set WM_COMMAND.  New code should use this
       
   892  * backdoor and call it *before* the first frame is shown so that
       
   893  * gnome session proxy can correctly handle it.
       
   894  *
       
   895  * NB: The function name looks deceptively like a JNI native method
       
   896  * name.  It's not!  It's just a plain function.
       
   897  */
       
   898 JNIEXPORT void JNICALL
       
   899 Java_sun_awt_motif_XsessionWMcommand_New(JNIEnv *env, jobjectArray jarray)
       
   900 {
       
   901     jsize length;
       
   902     char ** array;
       
   903     XTextProperty text_prop;
       
   904     int status;
       
   905     Window xawt_root_window;
       
   906 
       
   907     AWT_LOCK();
       
   908     xawt_root_window = get_xawt_root_shell(env);
       
   909 
       
   910     if (xawt_root_window == None) {
       
   911       AWT_UNLOCK();
       
   912       JNU_ThrowNullPointerException(env, "AWT root shell is unrealized");
       
   913       return;
       
   914     }
       
   915 
       
   916     array = stringArrayToNative(env, jarray, &length);
       
   917 
       
   918     if (array != NULL) {
       
   919         status = XmbTextListToTextProperty(awt_display, array, length,
       
   920                                            XStdICCTextStyle, &text_prop);
       
   921         if (status < 0) {
       
   922             switch (status) {
       
   923             case XNoMemory:
       
   924                 JNU_ThrowOutOfMemoryError(env,
       
   925                     "XmbTextListToTextProperty: XNoMemory");
       
   926                 break;
       
   927             case XLocaleNotSupported:
       
   928                 JNU_ThrowInternalError(env,
       
   929                     "XmbTextListToTextProperty: XLocaleNotSupported");
       
   930                 break;
       
   931             case XConverterNotFound:
       
   932                 JNU_ThrowNullPointerException(env,
       
   933                     "XmbTextListToTextProperty: XConverterNotFound");
       
   934                 break;
       
   935             default:
       
   936                 JNU_ThrowInternalError(env,
       
   937                     "XmbTextListToTextProperty: unknown error");
       
   938             }
       
   939         } else {
       
   940             XSetTextProperty(awt_display, xawt_root_window,
       
   941                                  &text_prop, XA_WM_COMMAND);
       
   942         }
       
   943 
       
   944         if (text_prop.value != NULL)
       
   945             XFree(text_prop.value);
       
   946 
       
   947         freeNativeStringArray(array, length);
       
   948     }
       
   949     AWT_UNLOCK();
       
   950 }
       
   951 
       
   952 /*
       
   953  * Class:     java_awt_TrayIcon
       
   954  * Method:    initIDs
       
   955  * Signature: ()V
       
   956  */
       
   957 JNIEXPORT void JNICALL Java_java_awt_TrayIcon_initIDs(JNIEnv *env , jclass clazz)
       
   958 {
       
   959 }
       
   960 
       
   961 
       
   962 /*
       
   963  * Class:     java_awt_Cursor
       
   964  * Method:    finalizeImpl
       
   965  * Signature: ()V
       
   966  */
       
   967 JNIEXPORT void JNICALL
       
   968 Java_java_awt_Cursor_finalizeImpl(JNIEnv *env, jclass clazz, jlong pData)
       
   969 {
       
   970     Cursor xcursor;
       
   971 
       
   972     xcursor = (Cursor)pData;
       
   973     if (xcursor != None) {
       
   974         AWT_LOCK();
       
   975         XFreeCursor(awt_display, xcursor);
       
   976         AWT_UNLOCK();
       
   977     }
       
   978 }
       
   979 
       
   980 
       
   981 /*
       
   982  * Class:     sun_awt_X11_XToolkit
       
   983  * Method:    getNumberOfButtonsImpl
       
   984  * Signature: ()I
       
   985  */
       
   986 JNIEXPORT jint JNICALL Java_sun_awt_X11_XToolkit_getNumberOfButtonsImpl
       
   987 (JNIEnv * env, jobject cls){
       
   988     if (num_buttons == 0) {
       
   989         num_buttons = getNumButtons();
       
   990     }
       
   991     return num_buttons;
       
   992 }
       
   993 
       
   994 int32_t getNumButtons() {
       
   995     int32_t major_opcode, first_event, first_error;
       
   996     int32_t xinputAvailable;
       
   997     int32_t numDevices, devIdx, clsIdx;
       
   998     XDeviceInfo* devices;
       
   999     XDeviceInfo* aDevice;
       
  1000     XButtonInfo* bInfo;
       
  1001     int32_t local_num_buttons = 0;
       
  1002 
       
  1003     /* 4700242:
       
  1004      * If XTest is asked to press a non-existant mouse button
       
  1005      * (i.e. press Button3 on a system configured with a 2-button mouse),
       
  1006      * then a crash may happen.  To avoid this, we use the XInput
       
  1007      * extension to query for the number of buttons on the XPointer, and check
       
  1008      * before calling XTestFakeButtonEvent().
       
  1009      */
       
  1010     xinputAvailable = XQueryExtension(awt_display, INAME, &major_opcode, &first_event, &first_error);
       
  1011     if (xinputAvailable) {
       
  1012         DTRACE_PRINTLN3("RobotPeer: XQueryExtension(XINPUT) returns major_opcode = %d, first_event = %d, first_error = %d",
       
  1013                         major_opcode, first_event, first_error);
       
  1014         devices = XListInputDevices(awt_display, &numDevices);
       
  1015         for (devIdx = 0; devIdx < numDevices; devIdx++) {
       
  1016             aDevice = &(devices[devIdx]);
       
  1017 #ifdef IsXExtensionPointer
       
  1018             if (aDevice->use == IsXExtensionPointer) {
       
  1019                 for (clsIdx = 0; clsIdx < aDevice->num_classes; clsIdx++) {
       
  1020                     if (aDevice->inputclassinfo[clsIdx].class == ButtonClass) {
       
  1021                         bInfo = (XButtonInfo*)(&(aDevice->inputclassinfo[clsIdx]));
       
  1022                         local_num_buttons = bInfo->num_buttons;
       
  1023                         DTRACE_PRINTLN1("RobotPeer: XPointer has %d buttons", num_buttons);
       
  1024                         break;
       
  1025                     }
       
  1026                 }
       
  1027                 break;
       
  1028             }
       
  1029 #endif
       
  1030             if (local_num_buttons <= 0 ) {
       
  1031                 if (aDevice->use == IsXPointer) {
       
  1032                     for (clsIdx = 0; clsIdx < aDevice->num_classes; clsIdx++) {
       
  1033                         if (aDevice->inputclassinfo[clsIdx].class == ButtonClass) {
       
  1034                             bInfo = (XButtonInfo*)(&(aDevice->inputclassinfo[clsIdx]));
       
  1035                             local_num_buttons = bInfo->num_buttons;
       
  1036                             DTRACE_PRINTLN1("RobotPeer: XPointer has %d buttons", num_buttons);
       
  1037                             break;
       
  1038                         }
       
  1039                     }
       
  1040                     break;
       
  1041                 }
       
  1042             }
       
  1043         }
       
  1044 
       
  1045         XFreeDeviceList(devices);
       
  1046     }
       
  1047     else {
       
  1048         DTRACE_PRINTLN1("RobotPeer: XINPUT extension is unavailable, assuming %d mouse buttons", num_buttons);
       
  1049     }
       
  1050     if (local_num_buttons == 0 ) {
       
  1051         local_num_buttons = 3;
       
  1052     }
       
  1053 
       
  1054     return local_num_buttons;
       
  1055 }
       
  1056 
       
  1057 /*
       
  1058  * Class:     sun_awt_X11_XWindowPeer
       
  1059  * Method:    getJvmPID
       
  1060  * Signature: ()I
       
  1061  */
       
  1062 JNIEXPORT jint JNICALL Java_sun_awt_X11_XWindowPeer_getJvmPID
       
  1063 (JNIEnv *env, jclass cls)
       
  1064 {
       
  1065     /* Return the JVM's PID. */
       
  1066     return getpid();
       
  1067 }
       
  1068 
       
  1069 #ifndef HOST_NAME_MAX
       
  1070 #define HOST_NAME_MAX 1024 /* Overestimated */
       
  1071 #endif
       
  1072 
       
  1073 /*
       
  1074  * Class:     sun_awt_X11_XWindowPeer
       
  1075  * Method:    getLocalHostname
       
  1076  * Signature: ()Ljava/lang/String;
       
  1077  */
       
  1078 JNIEXPORT jstring JNICALL Java_sun_awt_X11_XWindowPeer_getLocalHostname
       
  1079 (JNIEnv *env, jclass cls)
       
  1080 {
       
  1081     /* Return the machine's FQDN. */
       
  1082     char hostname[HOST_NAME_MAX + 1];
       
  1083     if (gethostname(hostname, HOST_NAME_MAX + 1) == 0) {
       
  1084         hostname[HOST_NAME_MAX] = '\0';
       
  1085         jstring res = (*env)->NewStringUTF(env, hostname);
       
  1086         return res;
       
  1087     }
       
  1088 
       
  1089     return (jstring)NULL;
       
  1090 }