Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/native/sun/xawt/XToolkit.c
32287 views
/*1* Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425#include <X11/Xlib.h>26#include <X11/Xutil.h>27#include <X11/Xos.h>28#include <X11/Xatom.h>29#ifdef __linux__30#include <execinfo.h>31#endif3233#include <jvm.h>34#include <jni.h>35#include <jlong.h>36#include <jni_util.h>3738#include "awt_p.h"39#include "awt_Component.h"40#include "awt_MenuComponent.h"41#include "awt_Font.h"42#include "awt_util.h"4344#include "sun_awt_X11_XToolkit.h"45#include "java_awt_SystemColor.h"46#include "java_awt_TrayIcon.h"47#include <X11/extensions/XTest.h>4849#include <unistd.h>5051uint32_t awt_NumLockMask = 0;52Boolean awt_ModLockIsShiftLock = False;5354static int32_t num_buttons = 0;55int32_t getNumButtons();5657extern JavaVM *jvm;5859// Tracing level60static int tracing = 0;61#ifdef PRINT62#undef PRINT63#endif64#ifdef PRINT265#undef PRINT266#endif6768#define PRINT if (tracing) printf69#define PRINT2 if (tracing > 1) printf707172struct ComponentIDs componentIDs;7374struct MenuComponentIDs menuComponentIDs;7576#ifndef HEADLESS7778extern Display* awt_init_Display(JNIEnv *env, jobject this);79extern void freeNativeStringArray(char **array, jsize length);80extern char** stringArrayToNative(JNIEnv *env, jobjectArray array, jsize * ret_length);8182struct XFontPeerIDs xFontPeerIDs;8384JNIEXPORT void JNICALL85Java_sun_awt_X11_XFontPeer_initIDs86(JNIEnv *env, jclass cls)87{88xFontPeerIDs.xfsname =89(*env)->GetFieldID(env, cls, "xfsname", "Ljava/lang/String;");90}91#endif /* !HEADLESS */9293/* This function gets called from the static initializer for FileDialog.java94to initialize the fieldIDs for fields that may be accessed from C */9596JNIEXPORT void JNICALL97Java_java_awt_FileDialog_initIDs98(JNIEnv *env, jclass cls)99{100101}102103JNIEXPORT void JNICALL104Java_sun_awt_X11_XToolkit_initIDs105(JNIEnv *env, jclass clazz)106{107jfieldID fid = (*env)->GetStaticFieldID(env, clazz, "numLockMask", "I");108CHECK_NULL(fid);109awt_NumLockMask = (*env)->GetStaticIntField(env, clazz, fid);110DTRACE_PRINTLN1("awt_NumLockMask = %u", awt_NumLockMask);111fid = (*env)->GetStaticFieldID(env, clazz, "modLockIsShiftLock", "I");112CHECK_NULL(fid);113awt_ModLockIsShiftLock = (*env)->GetStaticIntField(env, clazz, fid) != 0 ? True : False;114}115116/*117* Class: sun_awt_X11_XToolkit118* Method: getTrayIconDisplayTimeout119* Signature: ()J120*/121JNIEXPORT jlong JNICALL Java_sun_awt_X11_XToolkit_getTrayIconDisplayTimeout122(JNIEnv *env, jclass clazz)123{124#ifndef JAVASE_EMBEDDED125return (jlong) 2000;126#else127return (jlong) 10000;128#endif129}130131/*132* Class: sun_awt_X11_XToolkit133* Method: getDefaultXColormap134* Signature: ()J135*/136JNIEXPORT jlong JNICALL Java_sun_awt_X11_XToolkit_getDefaultXColormap137(JNIEnv *env, jclass clazz)138{139AwtGraphicsConfigDataPtr defaultConfig =140getDefaultConfig(DefaultScreen(awt_display));141142return (jlong) defaultConfig->awt_cmap;143}144145JNIEXPORT jint JNICALL146JNI_OnLoad(JavaVM *vm, void *reserved)147{148jvm = vm;149150//Set the gtk backend to x11 on all the systems151putenv("GDK_BACKEND=x11");152153return JNI_VERSION_1_2;154}155156/*157* Class: sun_awt_X11_XToolkit158* Method: nativeLoadSystemColors159* Signature: ([I)V160*/161JNIEXPORT void JNICALL Java_sun_awt_X11_XToolkit_nativeLoadSystemColors162(JNIEnv *env, jobject this, jintArray systemColors)163{164AwtGraphicsConfigDataPtr defaultConfig =165getDefaultConfig(DefaultScreen(awt_display));166awtJNI_CreateColorData(env, defaultConfig, 1);167}168169JNIEXPORT void JNICALL170Java_java_awt_Component_initIDs171(JNIEnv *env, jclass cls)172{173jclass keyclass = NULL;174175176componentIDs.x = (*env)->GetFieldID(env, cls, "x", "I");177CHECK_NULL(componentIDs.x);178componentIDs.y = (*env)->GetFieldID(env, cls, "y", "I");179CHECK_NULL(componentIDs.y);180componentIDs.width = (*env)->GetFieldID(env, cls, "width", "I");181CHECK_NULL(componentIDs.width);182componentIDs.height = (*env)->GetFieldID(env, cls, "height", "I");183CHECK_NULL(componentIDs.height);184componentIDs.isPacked = (*env)->GetFieldID(env, cls, "isPacked", "Z");185CHECK_NULL(componentIDs.isPacked);186componentIDs.peer =187(*env)->GetFieldID(env, cls, "peer", "Ljava/awt/peer/ComponentPeer;");188CHECK_NULL(componentIDs.peer);189componentIDs.background =190(*env)->GetFieldID(env, cls, "background", "Ljava/awt/Color;");191CHECK_NULL(componentIDs.background);192componentIDs.foreground =193(*env)->GetFieldID(env, cls, "foreground", "Ljava/awt/Color;");194CHECK_NULL(componentIDs.foreground);195componentIDs.graphicsConfig =196(*env)->GetFieldID(env, cls, "graphicsConfig",197"Ljava/awt/GraphicsConfiguration;");198CHECK_NULL(componentIDs.graphicsConfig);199componentIDs.name =200(*env)->GetFieldID(env, cls, "name", "Ljava/lang/String;");201CHECK_NULL(componentIDs.name);202203/* Use _NoClientCode() methods for trusted methods, so that we204* know that we are not invoking client code on trusted threads205*/206componentIDs.getParent =207(*env)->GetMethodID(env, cls, "getParent_NoClientCode",208"()Ljava/awt/Container;");209CHECK_NULL(componentIDs.getParent);210211componentIDs.getLocationOnScreen =212(*env)->GetMethodID(env, cls, "getLocationOnScreen_NoTreeLock",213"()Ljava/awt/Point;");214CHECK_NULL(componentIDs.getLocationOnScreen);215216keyclass = (*env)->FindClass(env, "java/awt/event/KeyEvent");217CHECK_NULL(keyclass);218219componentIDs.isProxyActive =220(*env)->GetFieldID(env, keyclass, "isProxyActive",221"Z");222CHECK_NULL(componentIDs.isProxyActive);223224componentIDs.appContext =225(*env)->GetFieldID(env, cls, "appContext",226"Lsun/awt/AppContext;");227228(*env)->DeleteLocalRef(env, keyclass);229}230231232JNIEXPORT void JNICALL233Java_java_awt_Container_initIDs234(JNIEnv *env, jclass cls)235{236237}238239240JNIEXPORT void JNICALL241Java_java_awt_Button_initIDs242(JNIEnv *env, jclass cls)243{244245}246247JNIEXPORT void JNICALL248Java_java_awt_Scrollbar_initIDs249(JNIEnv *env, jclass cls)250{251252}253254255JNIEXPORT void JNICALL256Java_java_awt_Window_initIDs257(JNIEnv *env, jclass cls)258{259260}261262JNIEXPORT void JNICALL263Java_java_awt_Frame_initIDs264(JNIEnv *env, jclass cls)265{266267}268269270JNIEXPORT void JNICALL271Java_java_awt_MenuComponent_initIDs(JNIEnv *env, jclass cls)272{273menuComponentIDs.appContext =274(*env)->GetFieldID(env, cls, "appContext", "Lsun/awt/AppContext;");275}276277JNIEXPORT void JNICALL278Java_java_awt_Cursor_initIDs(JNIEnv *env, jclass cls)279{280}281282283JNIEXPORT void JNICALL Java_java_awt_MenuItem_initIDs284(JNIEnv *env, jclass cls)285{286}287288289JNIEXPORT void JNICALL Java_java_awt_Menu_initIDs290(JNIEnv *env, jclass cls)291{292}293294JNIEXPORT void JNICALL295Java_java_awt_TextArea_initIDs296(JNIEnv *env, jclass cls)297{298}299300301JNIEXPORT void JNICALL302Java_java_awt_Checkbox_initIDs303(JNIEnv *env, jclass cls)304{305}306307308JNIEXPORT void JNICALL Java_java_awt_ScrollPane_initIDs309(JNIEnv *env, jclass cls)310{311}312313JNIEXPORT void JNICALL314Java_java_awt_TextField_initIDs315(JNIEnv *env, jclass cls)316{317}318319JNIEXPORT jboolean JNICALL AWTIsHeadless() {320#ifdef HEADLESS321return JNI_TRUE;322#else323return JNI_FALSE;324#endif325}326327JNIEXPORT void JNICALL Java_java_awt_Dialog_initIDs (JNIEnv *env, jclass cls)328{329}330331332/* ========================== Begin poll section ================================ */333334// Includes335336#include <sys/time.h>337#include <limits.h>338#include <locale.h>339#include <pthread.h>340341#include <dlfcn.h>342#include <fcntl.h>343344#include <poll.h>345#ifndef POLLRDNORM346#define POLLRDNORM POLLIN347#endif348349// Prototypes350351static void waitForEvents(JNIEnv *, jlong);352static void awt_pipe_init();353static void processOneEvent(XtInputMask iMask);354static Boolean performPoll(JNIEnv *, jlong);355static void wakeUp();356static void update_poll_timeout(int timeout_control);357static uint32_t get_poll_timeout(jlong nextTaskTime);358359// Defines360361#ifndef bzero362#define bzero(a,b) memset(a, 0, b)363#endif364365#define AWT_POLL_BUFSIZE 100 /* bytes */366#define AWT_READPIPE (awt_pipe_fds[0])367#define AWT_WRITEPIPE (awt_pipe_fds[1])368369#ifdef JAVASE_EMBEDDED370#define DEF_AWT_MAX_POLL_TIMEOUT ((uint32_t)4000000000) /* milliseconds */371#else372#define DEF_AWT_MAX_POLL_TIMEOUT ((uint32_t)500) /* milliseconds */373#endif374375#define DEF_AWT_FLUSH_TIMEOUT ((uint32_t)100) /* milliseconds */376#define AWT_MIN_POLL_TIMEOUT ((uint32_t)0) /* milliseconds */377378#define TIMEOUT_TIMEDOUT 0379#define TIMEOUT_EVENTS 1380381/* awt_poll_alg - AWT Poll Events Aging Algorithms */382#define AWT_POLL_FALSE 1383#define AWT_POLL_AGING_SLOW 2384#define AWT_POLL_AGING_FAST 3385386#define AWT_POLL_THRESHOLD 1000 // msec, Block if delay is larger387#define AWT_POLL_BLOCK -1 // cause poll() block388389// Static fields390391#ifdef JAVASE_EMBEDDED392static int awt_poll_alg = AWT_POLL_AGING_FAST;393#else394static int awt_poll_alg = AWT_POLL_AGING_SLOW;395#endif396397static uint32_t AWT_FLUSH_TIMEOUT = DEF_AWT_FLUSH_TIMEOUT; /* milliseconds */398static uint32_t AWT_MAX_POLL_TIMEOUT = DEF_AWT_MAX_POLL_TIMEOUT; /* milliseconds */399static pthread_t awt_MainThread = 0;400static int32_t awt_pipe_fds[2]; /* fds for wkaeup pipe */401static Boolean awt_pipe_inited = False; /* make sure pipe is initialized before write */402static jlong awt_next_flush_time = 0LL; /* 0 == no scheduled flush */403static jlong awt_last_flush_time = 0LL; /* 0 == no scheduled flush */404static uint32_t curPollTimeout;405static struct pollfd pollFds[2];406static jlong poll_sleep_time = 0LL; // Used for tracing407static jlong poll_wakeup_time = 0LL; // Used for tracing408409// AWT static poll timeout. Zero means "not set", aging algorithm is410// used. Static poll timeout values higher than 50 cause application411// look "slow" - they don't respond to user request fast412// enough. Static poll timeout value less than 10 are usually413// considered by schedulers as zero, so this might cause unnecessary414// CPU consumption by Java. The values between 10 - 50 are suggested415// for single client desktop configurations. For SunRay servers, it416// is highly recomended to use aging algorithm (set static poll timeout417// to 0).418static int32_t static_poll_timeout = 0;419420static Bool isMainThread() {421return awt_MainThread == pthread_self();422}423424/*425* Creates the AWT utility pipe. This pipe exists solely so that426* we can cause the main event thread to wake up from a poll() or427* select() by writing to this pipe.428*/429static void430awt_pipe_init() {431432if (awt_pipe_inited) {433return;434}435436if ( pipe ( awt_pipe_fds ) == 0 )437{438/*439** the write wakes us up from the infinite sleep, which440** then we cause a delay of AWT_FLUSHTIME and then we441** flush.442*/443int32_t flags = 0;444/* set the pipe to be non-blocking */445flags = fcntl ( AWT_READPIPE, F_GETFL, 0 );446fcntl( AWT_READPIPE, F_SETFL, flags | O_NDELAY | O_NONBLOCK );447flags = fcntl ( AWT_WRITEPIPE, F_GETFL, 0 );448fcntl( AWT_WRITEPIPE, F_SETFL, flags | O_NDELAY | O_NONBLOCK );449awt_pipe_inited = True;450}451else452{453AWT_READPIPE = -1;454AWT_WRITEPIPE = -1;455}456457458} /* awt_pipe_init() */459460/**461* Reads environment variables to initialize timeout fields.462*/463static void readEnv() {464char * value;465int tmp_poll_alg;466static Boolean env_read = False;467if (env_read) return;468469env_read = True;470471value = getenv("_AWT_MAX_POLL_TIMEOUT");472if (value != NULL) {473AWT_MAX_POLL_TIMEOUT = atoi(value);474if (AWT_MAX_POLL_TIMEOUT == 0) {475AWT_MAX_POLL_TIMEOUT = DEF_AWT_MAX_POLL_TIMEOUT;476}477}478curPollTimeout = AWT_MAX_POLL_TIMEOUT/2;479480value = getenv("_AWT_FLUSH_TIMEOUT");481if (value != NULL) {482AWT_FLUSH_TIMEOUT = atoi(value);483if (AWT_FLUSH_TIMEOUT == 0) {484AWT_FLUSH_TIMEOUT = DEF_AWT_FLUSH_TIMEOUT;485}486}487488value = getenv("_AWT_POLL_TRACING");489if (value != NULL) {490tracing = atoi(value);491}492493value = getenv("_AWT_STATIC_POLL_TIMEOUT");494if (value != NULL) {495static_poll_timeout = atoi(value);496}497if (static_poll_timeout != 0) {498curPollTimeout = static_poll_timeout;499}500501// non-blocking poll()502value = getenv("_AWT_POLL_ALG");503if (value != NULL) {504tmp_poll_alg = atoi(value);505switch(tmp_poll_alg) {506case AWT_POLL_FALSE:507case AWT_POLL_AGING_SLOW:508case AWT_POLL_AGING_FAST:509awt_poll_alg = tmp_poll_alg;510break;511default:512PRINT("Unknown value of _AWT_POLL_ALG, assuming Slow Aging Algorithm by default");513awt_poll_alg = AWT_POLL_AGING_SLOW;514break;515}516}517}518519/**520* Returns the amount of milliseconds similar to System.currentTimeMillis()521*/522static jlong523awtJNI_TimeMillis(void)524{525struct timeval t;526527gettimeofday(&t, 0);528529return jlong_add(jlong_mul(jint_to_jlong(t.tv_sec), jint_to_jlong(1000)),530jint_to_jlong(t.tv_usec / 1000));531}532533/**534* Updates curPollTimeout according to the aging algorithm.535* @param timeout_control Either TIMEOUT_TIMEDOUT or TIMEOUT_EVENTS536*/537static void update_poll_timeout(int timeout_control) {538PRINT2("tout: %d\n", timeout_control);539540// If static_poll_timeout is set, curPollTimeout has the fixed value541if (static_poll_timeout != 0) return;542543// Update it otherwise544545switch(awt_poll_alg) {546case AWT_POLL_AGING_SLOW:547if (timeout_control == TIMEOUT_TIMEDOUT) {548/* add 1/4 (plus 1, in case the division truncates to 0) */549curPollTimeout += ((curPollTimeout>>2) + 1);550curPollTimeout = min(AWT_MAX_POLL_TIMEOUT, curPollTimeout);551} else if (timeout_control == TIMEOUT_EVENTS) {552/* subtract 1/4 (plus 1, in case the division truncates to 0) */553curPollTimeout -= ((curPollTimeout>>2) + 1);554curPollTimeout = max(AWT_MIN_POLL_TIMEOUT, curPollTimeout);555}556break;557case AWT_POLL_AGING_FAST:558if (timeout_control == TIMEOUT_TIMEDOUT) {559curPollTimeout += ((curPollTimeout>>2) + 1);560curPollTimeout = min(AWT_MAX_POLL_TIMEOUT, curPollTimeout);561if((int)curPollTimeout > AWT_POLL_THRESHOLD || (int)curPollTimeout == AWT_POLL_BLOCK)562curPollTimeout = AWT_POLL_BLOCK;563} else if (timeout_control == TIMEOUT_EVENTS) {564curPollTimeout = max(AWT_MIN_POLL_TIMEOUT, 1);565}566break;567}568}569570/*571* Gets the best timeout for the next call to poll().572*573* @param nextTaskTime -1, if there are no tasks; next time when574* timeout task needs to be run, in millis(of currentTimeMillis)575*/576static uint32_t get_poll_timeout(jlong nextTaskTime)577{578uint32_t ret_timeout = 0;579uint32_t timeout;580uint32_t taskTimeout;581uint32_t flushTimeout;582583jlong curTime = awtJNI_TimeMillis();584timeout = curPollTimeout;585switch(awt_poll_alg) {586case AWT_POLL_AGING_SLOW:587case AWT_POLL_AGING_FAST:588taskTimeout = (nextTaskTime == -1) ? AWT_MAX_POLL_TIMEOUT : (uint32_t)max(0, (int32_t)(nextTaskTime - curTime));589flushTimeout = (awt_next_flush_time > 0) ? (uint32_t)max(0, (int32_t)(awt_next_flush_time - curTime)) : AWT_MAX_POLL_TIMEOUT;590591PRINT2("to: %d, ft: %d, to: %d, tt: %d, mil: %d\n", taskTimeout, flushTimeout, timeout, (int)nextTaskTime, (int)curTime);592593// Adjust timeout to flush_time and task_time594ret_timeout = min(flushTimeout, min(taskTimeout, timeout));595if((int)curPollTimeout == AWT_POLL_BLOCK)596ret_timeout = AWT_POLL_BLOCK;597break;598599case AWT_POLL_FALSE:600ret_timeout = (nextTaskTime > curTime) ?601(nextTaskTime - curTime) :602((nextTaskTime == -1) ? -1 : 0);603break;604}605606return ret_timeout;607608} /* get_poll_timeout() */609610/*611* Waits for X/Xt events to appear on the pipe. Returns only when612* it is likely (but not definite) that there are events waiting to613* be processed.614*615* This routine also flushes the outgoing X queue, when the616* awt_next_flush_time has been reached.617*618* If fdAWTPipe is greater or equal than zero the routine also619* checks if there are events pending on the putback queue.620*/621void622waitForEvents(JNIEnv *env, jlong nextTaskTime) {623if (performPoll(env, nextTaskTime)624&& (awt_next_flush_time > 0)625&& (awtJNI_TimeMillis() >= awt_next_flush_time)) {626627XFlush(awt_display);628awt_last_flush_time = awt_next_flush_time;629awt_next_flush_time = 0LL;630}631} /* waitForEvents() */632633JNIEXPORT void JNICALL Java_sun_awt_X11_XToolkit_waitForEvents (JNIEnv *env, jclass class, jlong nextTaskTime) {634waitForEvents(env, nextTaskTime);635}636637JNIEXPORT void JNICALL Java_sun_awt_X11_XToolkit_awt_1toolkit_1init (JNIEnv *env, jclass class) {638awt_MainThread = pthread_self();639640awt_pipe_init();641readEnv();642}643644JNIEXPORT void JNICALL Java_sun_awt_X11_XToolkit_awt_1output_1flush (JNIEnv *env, jclass class) {645awt_output_flush();646}647648JNIEXPORT void JNICALL Java_sun_awt_X11_XToolkit_wakeup_1poll (JNIEnv *env, jclass class) {649wakeUp();650}651652/*653* Polls both the X pipe and our AWT utility pipe. Returns654* when there is data on one of the pipes, or the operation times655* out.656*657* Not all Xt events come across the X pipe (e.g., timers658* and alternate inputs), so we must time out every now and659* then to check the Xt event queue.660*661* The fdAWTPipe will be empty when this returns.662*/663static Boolean664performPoll(JNIEnv *env, jlong nextTaskTime) {665static Bool pollFdsInited = False;666static char read_buf[AWT_POLL_BUFSIZE + 1]; /* dummy buf to empty pipe */667668uint32_t timeout = get_poll_timeout(nextTaskTime);669int32_t result;670671if (!pollFdsInited) {672pollFds[0].fd = ConnectionNumber(awt_display);673pollFds[0].events = POLLRDNORM;674pollFds[0].revents = 0;675676pollFds[1].fd = AWT_READPIPE;677pollFds[1].events = POLLRDNORM;678pollFds[1].revents = 0;679pollFdsInited = True;680} else {681pollFds[0].revents = 0;682pollFds[1].revents = 0;683}684685AWT_NOFLUSH_UNLOCK();686687/* ACTUALLY DO THE POLL() */688if (timeout == 0) {689// be sure other threads get a chance690if (!awtJNI_ThreadYield(env)) {691return FALSE;692}693}694695if (tracing) poll_sleep_time = awtJNI_TimeMillis();696result = poll( pollFds, 2, (int32_t) timeout );697if (tracing) poll_wakeup_time = awtJNI_TimeMillis();698PRINT("%d of %d, res: %d\n", (int)(poll_wakeup_time-poll_sleep_time), (int)timeout, result);699700AWT_LOCK();701if (result == 0) {702/* poll() timed out -- update timeout value */703update_poll_timeout(TIMEOUT_TIMEDOUT);704PRINT2("performPoll(): TIMEOUT_TIMEDOUT curPollTimeout = %d \n", curPollTimeout);705}706if (pollFds[1].revents) {707int count;708PRINT("Woke up\n");709/* There is data on the AWT pipe - empty it */710do {711count = read(AWT_READPIPE, read_buf, AWT_POLL_BUFSIZE );712} while (count == AWT_POLL_BUFSIZE );713PRINT2("performPoll(): data on the AWT pipe: curPollTimeout = %d \n", curPollTimeout);714}715if (pollFds[0].revents) {716// Events in X pipe717update_poll_timeout(TIMEOUT_EVENTS);718PRINT2("performPoll(): TIMEOUT_EVENTS curPollTimeout = %ld \n", curPollTimeout);719}720return TRUE;721722} /* performPoll() */723724/**725* Schedules next auto-flush event or performs forced flush depending726* on the time of the previous flush.727*/728void awt_output_flush() {729if (awt_next_flush_time == 0) {730JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);731732jlong curTime = awtJNI_TimeMillis(); // current time733jlong l_awt_last_flush_time = awt_last_flush_time; // last time we flushed queue734jlong next_flush_time = l_awt_last_flush_time + AWT_FLUSH_TIMEOUT;735736if (curTime >= next_flush_time) {737// Enough time passed from last flush738PRINT("f1\n");739AWT_LOCK();740XFlush(awt_display);741awt_last_flush_time = curTime;742AWT_NOFLUSH_UNLOCK();743} else {744awt_next_flush_time = next_flush_time;745PRINT("f2\n");746wakeUp();747}748}749}750751752/**753* Wakes-up poll() in performPoll754*/755static void wakeUp() {756static char wakeUp_char = 'p';757if (!isMainThread() && awt_pipe_inited) {758write ( AWT_WRITEPIPE, &wakeUp_char, 1 );759}760}761762763/* ========================== End poll section ================================= */764765/*766* Class: java_awt_KeyboardFocusManager767* Method: initIDs768* Signature: ()V769*/770JNIEXPORT void JNICALL771Java_java_awt_KeyboardFocusManager_initIDs772(JNIEnv *env, jclass cls)773{774}775776/*777* Class: sun_awt_X11_XToolkit778* Method: getEnv779* Signature: (Ljava/lang/String;)Ljava/lang/String;780*/781JNIEXPORT jstring JNICALL Java_sun_awt_X11_XToolkit_getEnv782(JNIEnv *env , jclass clazz, jstring key) {783char *ptr = NULL;784const char *keystr = NULL;785jstring ret = NULL;786787keystr = JNU_GetStringPlatformChars(env, key, NULL);788if (keystr) {789ptr = getenv(keystr);790if (ptr) {791ret = JNU_NewStringPlatform(env, (const char *) ptr);792}793JNU_ReleaseStringPlatformChars(env, key, (const char*)keystr);794}795return ret;796}797798#ifdef __linux__799void print_stack(void)800{801void *array[10];802size_t size;803char **strings;804size_t i;805806size = backtrace (array, 10);807strings = backtrace_symbols (array, size);808809fprintf (stderr, "Obtained %zd stack frames.\n", size);810811for (i = 0; i < size; i++)812fprintf (stderr, "%s\n", strings[i]);813814free (strings);815}816#endif817818Window get_xawt_root_shell(JNIEnv *env) {819static jclass classXRootWindow = NULL;820static jmethodID methodGetXRootWindow = NULL;821static Window xawt_root_shell = None;822823if (xawt_root_shell == None){824if (classXRootWindow == NULL){825jclass cls_tmp = (*env)->FindClass(env, "sun/awt/X11/XRootWindow");826if (!JNU_IsNull(env, cls_tmp)) {827classXRootWindow = (jclass)(*env)->NewGlobalRef(env, cls_tmp);828(*env)->DeleteLocalRef(env, cls_tmp);829}830}831if( classXRootWindow != NULL) {832methodGetXRootWindow = (*env)->GetStaticMethodID(env, classXRootWindow, "getXRootWindow", "()J");833}834if( classXRootWindow != NULL && methodGetXRootWindow !=NULL ) {835xawt_root_shell = (Window) (*env)->CallStaticLongMethod(env, classXRootWindow, methodGetXRootWindow);836}837if ((*env)->ExceptionCheck(env)) {838(*env)->ExceptionDescribe(env);839(*env)->ExceptionClear(env);840}841}842return xawt_root_shell;843}844845/*846* Old, compatibility, backdoor for DT. This is a different847* implementation. It keeps the signature, but acts on848* awt_root_shell, not the frame passed as an argument. Note, that849* the code that uses the old backdoor doesn't work correctly with850* gnome session proxy that checks for WM_COMMAND when the window is851* firts mapped, because DT code calls this old backdoor *after* the852* frame is shown or it would get NPE with old AWT (previous853* implementation of this backdoor) otherwise. Old style session854* managers (e.g. CDE) that check WM_COMMAND only during session855* checkpoint should work fine, though.856*857* NB: The function name looks deceptively like a JNI native method858* name. It's not! It's just a plain function.859*/860861JNIEXPORT void JNICALL862Java_sun_awt_motif_XsessionWMcommand(JNIEnv *env, jobject this,863jobject frame, jstring jcommand)864{865const char *command;866XTextProperty text_prop;867char *c[1];868int32_t status;869Window xawt_root_window;870871AWT_LOCK();872xawt_root_window = get_xawt_root_shell(env);873874if ( xawt_root_window == None ) {875AWT_UNLOCK();876JNU_ThrowNullPointerException(env, "AWT root shell is unrealized");877return;878}879880command = (char *) JNU_GetStringPlatformChars(env, jcommand, NULL);881if (command != NULL) {882c[0] = (char *)command;883status = XmbTextListToTextProperty(awt_display, c, 1,884XStdICCTextStyle, &text_prop);885886if (status == Success || status > 0) {887XSetTextProperty(awt_display, xawt_root_window,888&text_prop, XA_WM_COMMAND);889if (text_prop.value != NULL)890XFree(text_prop.value);891}892JNU_ReleaseStringPlatformChars(env, jcommand, command);893}894AWT_UNLOCK();895}896897898/*899* New DT backdoor to set WM_COMMAND. New code should use this900* backdoor and call it *before* the first frame is shown so that901* gnome session proxy can correctly handle it.902*903* NB: The function name looks deceptively like a JNI native method904* name. It's not! It's just a plain function.905*/906JNIEXPORT void JNICALL907Java_sun_awt_motif_XsessionWMcommand_New(JNIEnv *env, jobjectArray jarray)908{909jsize length;910char ** array;911XTextProperty text_prop;912int status;913Window xawt_root_window;914915AWT_LOCK();916xawt_root_window = get_xawt_root_shell(env);917918if (xawt_root_window == None) {919AWT_UNLOCK();920JNU_ThrowNullPointerException(env, "AWT root shell is unrealized");921return;922}923924array = stringArrayToNative(env, jarray, &length);925926if (array != NULL) {927status = XmbTextListToTextProperty(awt_display, array, length,928XStdICCTextStyle, &text_prop);929if (status < 0) {930switch (status) {931case XNoMemory:932JNU_ThrowOutOfMemoryError(env,933"XmbTextListToTextProperty: XNoMemory");934break;935case XLocaleNotSupported:936JNU_ThrowInternalError(env,937"XmbTextListToTextProperty: XLocaleNotSupported");938break;939case XConverterNotFound:940JNU_ThrowNullPointerException(env,941"XmbTextListToTextProperty: XConverterNotFound");942break;943default:944JNU_ThrowInternalError(env,945"XmbTextListToTextProperty: unknown error");946}947} else {948XSetTextProperty(awt_display, xawt_root_window,949&text_prop, XA_WM_COMMAND);950}951952if (text_prop.value != NULL)953XFree(text_prop.value);954955freeNativeStringArray(array, length);956}957AWT_UNLOCK();958}959960/*961* Class: java_awt_TrayIcon962* Method: initIDs963* Signature: ()V964*/965JNIEXPORT void JNICALL Java_java_awt_TrayIcon_initIDs(JNIEnv *env , jclass clazz)966{967}968969970/*971* Class: java_awt_Cursor972* Method: finalizeImpl973* Signature: ()V974*/975JNIEXPORT void JNICALL976Java_java_awt_Cursor_finalizeImpl(JNIEnv *env, jclass clazz, jlong pData)977{978Cursor xcursor;979980xcursor = (Cursor)pData;981if (xcursor != None) {982AWT_LOCK();983XFreeCursor(awt_display, xcursor);984AWT_UNLOCK();985}986}987988989/*990* Class: sun_awt_X11_XToolkit991* Method: getNumberOfButtonsImpl992* Signature: ()I993*/994JNIEXPORT jint JNICALL Java_sun_awt_X11_XToolkit_getNumberOfButtonsImpl995(JNIEnv * env, jobject cls){996if (num_buttons == 0) {997num_buttons = getNumButtons();998}999return num_buttons;1000}10011002int32_t getNumButtons() {1003int32_t major_opcode, first_event, first_error;1004int32_t xinputAvailable;1005int32_t numDevices, devIdx, clsIdx;1006XDeviceInfo* devices;1007XDeviceInfo* aDevice;1008XButtonInfo* bInfo;1009int32_t local_num_buttons = 0;10101011/* 4700242:1012* If XTest is asked to press a non-existant mouse button1013* (i.e. press Button3 on a system configured with a 2-button mouse),1014* then a crash may happen. To avoid this, we use the XInput1015* extension to query for the number of buttons on the XPointer, and check1016* before calling XTestFakeButtonEvent().1017*/1018xinputAvailable = XQueryExtension(awt_display, INAME, &major_opcode, &first_event, &first_error);1019if (xinputAvailable) {1020DTRACE_PRINTLN3("RobotPeer: XQueryExtension(XINPUT) returns major_opcode = %d, first_event = %d, first_error = %d",1021major_opcode, first_event, first_error);1022devices = XListInputDevices(awt_display, &numDevices);1023for (devIdx = 0; devIdx < numDevices; devIdx++) {1024aDevice = &(devices[devIdx]);1025#ifdef IsXExtensionPointer1026if (aDevice->use == IsXExtensionPointer) {1027for (clsIdx = 0; clsIdx < aDevice->num_classes; clsIdx++) {1028if (aDevice->inputclassinfo[clsIdx].class == ButtonClass) {1029bInfo = (XButtonInfo*)(&(aDevice->inputclassinfo[clsIdx]));1030local_num_buttons = bInfo->num_buttons;1031DTRACE_PRINTLN1("RobotPeer: XPointer has %d buttons", num_buttons);1032break;1033}1034}1035break;1036}1037#endif1038if (local_num_buttons <= 0 ) {1039if (aDevice->use == IsXPointer) {1040for (clsIdx = 0; clsIdx < aDevice->num_classes; clsIdx++) {1041if (aDevice->inputclassinfo[clsIdx].class == ButtonClass) {1042bInfo = (XButtonInfo*)(&(aDevice->inputclassinfo[clsIdx]));1043local_num_buttons = bInfo->num_buttons;1044DTRACE_PRINTLN1("RobotPeer: XPointer has %d buttons", num_buttons);1045break;1046}1047}1048break;1049}1050}1051}10521053XFreeDeviceList(devices);1054}1055else {1056DTRACE_PRINTLN1("RobotPeer: XINPUT extension is unavailable, assuming %d mouse buttons", num_buttons);1057}1058if (local_num_buttons == 0 ) {1059local_num_buttons = 3;1060}10611062return local_num_buttons;1063}10641065/*1066* Class: sun_awt_X11_XWindowPeer1067* Method: getJvmPID1068* Signature: ()I1069*/1070JNIEXPORT jint JNICALL Java_sun_awt_X11_XWindowPeer_getJvmPID1071(JNIEnv *env, jclass cls)1072{1073/* Return the JVM's PID. */1074return getpid();1075}10761077#ifndef HOST_NAME_MAX1078#define HOST_NAME_MAX 1024 /* Overestimated */1079#endif10801081/*1082* Class: sun_awt_X11_XWindowPeer1083* Method: getLocalHostname1084* Signature: ()Ljava/lang/String;1085*/1086JNIEXPORT jstring JNICALL Java_sun_awt_X11_XWindowPeer_getLocalHostname1087(JNIEnv *env, jclass cls)1088{1089/* Return the machine's FQDN. */1090char hostname[HOST_NAME_MAX + 1];1091if (gethostname(hostname, HOST_NAME_MAX + 1) == 0) {1092hostname[HOST_NAME_MAX] = '\0';1093jstring res = (*env)->NewStringUTF(env, hostname);1094return res;1095}10961097return (jstring)NULL;1098}109911001101