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