jdk/src/solaris/native/sun/awt/awt_MToolkit.c
changeset 11319 a3d37054381f
parent 11318 e114b7d53b9b
parent 11239 885050364691
child 11320 1ed269f7cc73
equal deleted inserted replaced
11318:e114b7d53b9b 11319:a3d37054381f
     1 /*
       
     2  * Copyright (c) 1995, 2007, 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 "awt_p.h"
       
    27 
       
    28 #include <sys/time.h>
       
    29 #include <limits.h>
       
    30 #include <locale.h>
       
    31 
       
    32 #ifndef HEADLESS
       
    33 #include <X11/cursorfont.h>
       
    34 #include <Xm/MenuShell.h>
       
    35 #include <Xm/RowColumn.h>
       
    36 #endif /* !HEADLESS */
       
    37 
       
    38 #include <jvm.h>
       
    39 #include <jni.h>
       
    40 #include <jlong.h>
       
    41 #include <jni_util.h>
       
    42 
       
    43 /* JNI headers */
       
    44 #include "java_awt_AWTEvent.h"
       
    45 #include "java_awt_Frame.h"
       
    46 #include "java_awt_SystemColor.h"
       
    47 #include "sun_awt_motif_MToolkit.h"
       
    48 
       
    49 /* JNI field and method ids */
       
    50 #include "awt_Component.h"
       
    51 //#include "awt_Cursor.h"
       
    52 #include "awt_MenuComponent.h"
       
    53 #include "awt_TopLevel.h"
       
    54 #include "canvas.h"
       
    55 #include "color.h"
       
    56 #include "awt_mgrsel.h"
       
    57 #include "awt_wm.h"
       
    58 #include "awt_DrawingSurface.h"
       
    59 #include "awt_Window.h"
       
    60 #include "awt_xembed.h"
       
    61 #include "awt_xembed_server.h"
       
    62 
       
    63 extern JavaVM *jvm;
       
    64 
       
    65 #ifndef HEADLESS
       
    66 #ifdef __linux__
       
    67 extern void statusWindowEventHandler(XEvent event);
       
    68 #endif
       
    69 #endif /* !HEADLESS */
       
    70 
       
    71 JNIEXPORT jint JNICALL
       
    72 JNI_OnLoad(JavaVM *vm, void *reserved)
       
    73 {
       
    74 #ifndef HEADLESS
       
    75     awt_util_debug_init();
       
    76 #endif /* !HEADLESS */
       
    77     jvm = vm;
       
    78     return JNI_VERSION_1_2;
       
    79 }
       
    80 
       
    81 JNIEXPORT jboolean JNICALL AWTIsHeadless() {
       
    82 #ifdef HEADLESS
       
    83     return JNI_TRUE;
       
    84 #else
       
    85     return JNI_FALSE;
       
    86 #endif
       
    87 }
       
    88 
       
    89 #ifndef HEADLESS
       
    90 static jlong awtJNI_TimeMillis(void);
       
    91 extern void awt_initialize_Xm_DnD(Display*);
       
    92 extern void awt_initialize_DataTransferer();
       
    93 
       
    94 extern Display *awt_init_Display(JNIEnv *env);
       
    95 
       
    96 extern void X11SD_LibDispose(JNIEnv *env);
       
    97 
       
    98 extern Widget drag_source = NULL;
       
    99 
       
   100 extern struct ComponentIDs componentIDs;
       
   101 extern struct MenuComponentIDs menuComponentIDs;
       
   102 extern struct MComponentPeerIDs mComponentPeerIDs;
       
   103 extern struct WindowIDs windowIDs;
       
   104 
       
   105 static Atom _XA_XSETTINGS_SETTINGS = None;
       
   106 struct xsettings_callback_cookie {
       
   107     jobject mtoolkit;
       
   108     jmethodID upcallMID;
       
   109 };
       
   110 
       
   111 static struct xsettings_callback_cookie xsettings_callback_cookie;
       
   112 
       
   113 
       
   114 static XEvent focusOutEvent;
       
   115 
       
   116 static void awt_pipe_init(void);
       
   117 static void processOneEvent(XtInputMask iMask);
       
   118 extern void waitForEvents(JNIEnv *env, int32_t fdXPipe, int32_t fdAWTPipe);
       
   119 #ifdef USE_SELECT
       
   120 static void performSelect(JNIEnv *env, int32_t fdXPipe, int32_t fdAWTPipe);
       
   121 #else
       
   122 static void performPoll(JNIEnv *env,int32_t fdXPipe, int32_t fdAWTPipe);
       
   123 #endif
       
   124 
       
   125 
       
   126 #include <X11/Intrinsic.h>
       
   127 #include <dlfcn.h>
       
   128 #include <fcntl.h>
       
   129 
       
   130 #ifdef USE_SELECT
       
   131 #if defined(AIX)
       
   132 #include <sys/select.h>
       
   133 #endif
       
   134 #else
       
   135 #include <poll.h>
       
   136 #ifndef POLLRDNORM
       
   137 #define POLLRDNORM POLLIN
       
   138 #endif
       
   139 #endif
       
   140 
       
   141 #ifdef NDEBUG
       
   142 #undef DEBUG            /* NDEBUG overrides DEBUG */
       
   143 #endif
       
   144 
       
   145 static struct WidgetInfo *awt_winfo = (struct WidgetInfo *) NULL;
       
   146 static struct MenuList* menu_list = (struct MenuList*) NULL;
       
   147 
       
   148 #ifndef bzero
       
   149 #define bzero(a,b) memset(a, 0, b)
       
   150 #endif
       
   151 
       
   152 static jboolean syncUpdated = JNI_FALSE;
       
   153 static jboolean syncFailed = JNI_FALSE;
       
   154 static jint eventNumber = 0;
       
   155 static void syncWait_eventHandler(XEvent *);
       
   156 static Atom oops_atom = None;
       
   157 static Atom wm_selection = None;
       
   158 static Atom version_atom = None;
       
   159 
       
   160 static Boolean inSyncWait = False;
       
   161 
       
   162 Widget grabbed_widget = NULL;
       
   163 
       
   164 XtAppContext awt_appContext;
       
   165 Widget awt_root_shell;
       
   166 Pixel awt_defaultBg;
       
   167 Pixel awt_defaultFg;
       
   168 int32_t awt_multiclick_time;        /* milliseconds */
       
   169 uint32_t awt_MetaMask = 0;
       
   170 uint32_t awt_AltMask = 0;
       
   171 uint32_t awt_NumLockMask = 0;
       
   172 uint32_t awt_ModeSwitchMask = 0;
       
   173 Cursor awt_scrollCursor;
       
   174 Boolean  awt_ModLockIsShiftLock = False;
       
   175 extern Boolean awt_UseType4Patch;
       
   176 extern Boolean awt_UseXKB;
       
   177 
       
   178 #define SPECIAL_KEY_EVENT 2
       
   179 
       
   180 /* implement a "putback queue" -- see comments on awt_put_back_event() */
       
   181 #define PUTBACK_QUEUE_MIN_INCREMENT 5   /* min size increase */
       
   182 static XEvent *putbackQueue = NULL;     /* the queue -- next event is 0 */
       
   183 static int32_t putbackQueueCount = 0;   /* # of events available on queue */
       
   184 static int32_t putbackQueueCapacity = 0;        /* total capacity of queue */
       
   185 static XtInputMask awt_events_pending(XtAppContext appContext);
       
   186 static int32_t awt_get_next_put_back_event(XEvent *xev_out);
       
   187 
       
   188 #define AWT_FLUSH_TIMEOUT    ((uint32_t)100) /* milliseconds */
       
   189 #define AWT_MIN_POLL_TIMEOUT ((uint32_t)0) /* milliseconds */
       
   190 #define AWT_MAX_POLL_TIMEOUT ((uint32_t)250) /* milliseconds */
       
   191 
       
   192 #define AWT_POLL_BUFSIZE        100
       
   193 #define AWT_READPIPE            (awt_pipe_fds[0])
       
   194 #define AWT_WRITEPIPE           (awt_pipe_fds[1])
       
   195 #define AWT_FLUSHOUTPUT_NOW()  \
       
   196 {                              \
       
   197     XFlush(awt_display);       \
       
   198     awt_next_flush_time = 0LL; \
       
   199 }
       
   200 
       
   201 typedef XtIntervalId (*XTFUNC)();
       
   202 
       
   203 static jobject  awt_MainThread = NULL;
       
   204 static char     read_buf[AWT_POLL_BUFSIZE + 1];    /* dummy buf to empty pipe */
       
   205 static int32_t      awt_pipe_fds[2];                   /* fds for wkaeup pipe */
       
   206 static Boolean  awt_pipe_inited = False;           /* make sure pipe is initialized before write */
       
   207 static int32_t      def_poll_timeout = AWT_MAX_POLL_TIMEOUT;   /* default value for timeout */
       
   208 static jlong awt_next_flush_time = 0LL; /* 0 == no scheduled flush */
       
   209 static void     *xt_lib = NULL;
       
   210 static XTFUNC   xt_timeout = NULL;
       
   211 
       
   212 #ifdef DEBUG_AWT_LOCK
       
   213 
       
   214 int32_t awt_locked = 0;
       
   215 char *lastF = "";
       
   216 int32_t lastL = -1;
       
   217 
       
   218 #endif
       
   219 
       
   220 #ifndef NOMODALFIX
       
   221 extern Boolean awt_isModal();
       
   222 extern Boolean awt_isWidgetModal(Widget w);
       
   223 #endif
       
   224 
       
   225 Boolean keyboardGrabbed = False;
       
   226 
       
   227 static uint32_t curPollTimeout = AWT_MAX_POLL_TIMEOUT;
       
   228 
       
   229 /* Font information to feed Motif widgets. */
       
   230 static const char      *motifFontList;
       
   231 static XFontSet        defaultMotifFontSet;
       
   232 static XFontStruct     *defaultMotifFontStruct;
       
   233 static const char *defaultMotifFont =  /* a.k.a "fixed", known everywhere */
       
   234         "-misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso8859-1";
       
   235 
       
   236 XFontSet getMotifFontSet() {
       
   237     char    **missingList;
       
   238     int32_t     missingCount;
       
   239     char    *defChar;
       
   240 
       
   241     return XCreateFontSet(awt_display, motifFontList,
       
   242                           &missingList, &missingCount, &defChar);
       
   243 }
       
   244 
       
   245 XFontStruct *getMotifFontStruct() {
       
   246     return XLoadQueryFont(awt_display, defaultMotifFont);
       
   247 }
       
   248 
       
   249 XmFontList getMotifFontList() {
       
   250     XmFontListEntry motifFontListEntry;
       
   251     XmFontList fontlist;
       
   252 
       
   253     if (strchr(motifFontList, ',') == NULL) {
       
   254         /* If the default font is a single font. */
       
   255         if (defaultMotifFontStruct == NULL)
       
   256             defaultMotifFontStruct = getMotifFontStruct();
       
   257         motifFontListEntry = XmFontListEntryCreate(XmFONTLIST_DEFAULT_TAG,
       
   258                                                    XmFONT_IS_FONT,
       
   259                                            (XtPointer)defaultMotifFontStruct);
       
   260     }
       
   261     else {
       
   262         /* If the default font is multiple fonts. */
       
   263         if (defaultMotifFontSet == NULL)
       
   264             defaultMotifFontSet = getMotifFontSet();
       
   265             motifFontListEntry = XmFontListEntryCreate(XmFONTLIST_DEFAULT_TAG,
       
   266                                                XmFONT_IS_FONTSET,
       
   267                                                (XtPointer)defaultMotifFontSet);
       
   268     }
       
   269     fontlist = XmFontListAppendEntry(NULL, motifFontListEntry);
       
   270     XmFontListEntryFree(&motifFontListEntry);
       
   271     return fontlist;
       
   272 }
       
   273 
       
   274 static void
       
   275 awt_set_poll_timeout (uint32_t newTimeout)
       
   276 {
       
   277     DTRACE_PRINTLN1("awt_set_poll_timeout(%lu)", newTimeout);
       
   278 
       
   279     newTimeout = max(AWT_MIN_POLL_TIMEOUT, newTimeout);
       
   280     newTimeout = min(AWT_MAX_POLL_TIMEOUT, newTimeout);
       
   281     newTimeout = min(newTimeout, curPollTimeout);
       
   282     curPollTimeout = newTimeout;
       
   283 
       
   284 } /* awt_set_poll_timeout */
       
   285 
       
   286 /*
       
   287  * Gets the best timeout for the next call to poll() or select().
       
   288  * If timedOut is True, we assume that our previous timeout elapsed
       
   289  * with no events/timers arriving. Therefore, we can increase the
       
   290  * next timeout slightly.
       
   291  */
       
   292 static uint32_t
       
   293 awt_get_poll_timeout( Boolean timedOut )
       
   294 {
       
   295     uint32_t timeout = AWT_MAX_POLL_TIMEOUT;
       
   296 
       
   297     DTRACE_PRINTLN2("awt_get_poll_timeout(%s), awt_next_flush_time:%ld",
       
   298         (remove?"true":"false"),
       
   299         awt_next_flush_time);
       
   300 
       
   301     if (timedOut) {
       
   302         /* add 1/16 (plus 1, in case the division truncates to 0) */
       
   303         curPollTimeout += ((curPollTimeout>>4) + 1);
       
   304         curPollTimeout = min(AWT_MAX_POLL_TIMEOUT, curPollTimeout);
       
   305     }
       
   306     if (awt_next_flush_time > 0) {
       
   307         int32_t flushDiff = (int32_t)(awt_next_flush_time - awtJNI_TimeMillis());
       
   308         timeout = min(curPollTimeout, flushDiff);
       
   309     } else {
       
   310         timeout = curPollTimeout;
       
   311     }
       
   312 
       
   313     return timeout;
       
   314 } /* awt_get_poll_timeout() */
       
   315 
       
   316 static jlong
       
   317 awtJNI_TimeMillis(void)
       
   318 {
       
   319     struct timeval t;
       
   320 
       
   321     gettimeofday(&t, 0);
       
   322 
       
   323     return jlong_add(jlong_mul(jint_to_jlong(t.tv_sec), jint_to_jlong(1000)),
       
   324                      jint_to_jlong(t.tv_usec / 1000));
       
   325 }
       
   326 
       
   327 static int32_t
       
   328 xtError()
       
   329 {
       
   330 #ifdef DEBUG
       
   331     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
   332 
       
   333     jio_fprintf(stderr, "Xt error\n");
       
   334     JNU_ThrowNullPointerException(env, "NullPointerException");
       
   335 #endif
       
   336     return 0;
       
   337 }
       
   338 
       
   339 static int32_t
       
   340 xIOError(Display *dpy)
       
   341 {
       
   342     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
   343     jclass cl = (*env)->FindClass(env, "java/lang/Thread");
       
   344 
       
   345     if (errno == EPIPE) {
       
   346         jio_fprintf(stderr, "X connection to %s host broken (explicit kill or server shutdown)\n", XDisplayName(NULL));
       
   347     }
       
   348     AWT_NOFLUSH_UNLOCK();
       
   349     JVM_RaiseSignal(JVM_SIGTERM); /* Shut down cleanly */
       
   350     if (cl != NULL) {
       
   351         JVM_Sleep(env, cl, 20000);
       
   352     }
       
   353 
       
   354     return 0; /* to keep compiler happy */
       
   355 }
       
   356 
       
   357 /* Like XKeysymToKeycode, but ensures that keysym is the primary
       
   358  * symbol on the keycode returned.  Returns zero otherwise.
       
   359  */
       
   360 static int32_t
       
   361 keysym_to_keycode_if_primary(Display *dpy, KeySym sym)
       
   362 {
       
   363     KeyCode code;
       
   364     KeySym primary;
       
   365 
       
   366     code = XKeysymToKeycode(dpy, sym);
       
   367     if (code == 0) {
       
   368         return 0;
       
   369     }
       
   370 
       
   371     primary = XKeycodeToKeysym(dpy, code, 0);
       
   372     if (sym == primary) {
       
   373         return code;
       
   374     } else {
       
   375         return 0;
       
   376     }
       
   377 }
       
   378 /*
       
   379  * +kb or -kb ?
       
   380  */
       
   381 static Boolean
       
   382 isXKBenabled(Display *display) {
       
   383     int mop, beve, berr;
       
   384     /*
       
   385      * NB: TODO: hope it will return False if XkbIgnoreExtension was called!
       
   386      */
       
   387     return XQueryExtension(display, "XKEYBOARD", &mop, &beve, &berr);
       
   388 }
       
   389 
       
   390 
       
   391 /* Assign meaning - alt, meta, etc. - to X modifiers mod1 ... mod5.
       
   392  * Only consider primary symbols on keycodes attached to modifiers.
       
   393  */
       
   394 static void
       
   395 setup_modifier_map(Display *disp)
       
   396 {
       
   397     KeyCode metaL      = keysym_to_keycode_if_primary(disp, XK_Meta_L);
       
   398     KeyCode metaR      = keysym_to_keycode_if_primary(disp, XK_Meta_R);
       
   399     KeyCode altL       = keysym_to_keycode_if_primary(disp, XK_Alt_L);
       
   400     KeyCode altR       = keysym_to_keycode_if_primary(disp, XK_Alt_R);
       
   401     KeyCode numLock    = keysym_to_keycode_if_primary(disp, XK_Num_Lock);
       
   402     KeyCode modeSwitch = keysym_to_keycode_if_primary(disp, XK_Mode_switch);
       
   403     KeyCode shiftLock  = keysym_to_keycode_if_primary(disp, XK_Shift_Lock);
       
   404     KeyCode capsLock   = keysym_to_keycode_if_primary(disp, XK_Caps_Lock);
       
   405 
       
   406     XModifierKeymap *modmap = NULL;
       
   407     int32_t nkeys, modn, i;
       
   408     char *ptr = NULL;
       
   409 
       
   410     DTRACE_PRINTLN("In setup_modifier_map");
       
   411 
       
   412     modmap = XGetModifierMapping(disp);
       
   413     nkeys = modmap->max_keypermod;
       
   414 
       
   415     for (modn = Mod1MapIndex;
       
   416          (modn <= Mod5MapIndex) &&
       
   417              (awt_MetaMask == 0 || awt_AltMask == 0 ||
       
   418               awt_NumLockMask == 0 || awt_ModeSwitchMask == 0);
       
   419          ++modn)
       
   420     {
       
   421         static const uint32_t modmask[8] = {
       
   422             ShiftMask, LockMask, ControlMask,
       
   423             Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask
       
   424         };
       
   425 
       
   426 
       
   427         for (i = 0; i < nkeys; ++i) {
       
   428             /* for each keycode attached to this modifier */
       
   429             KeyCode keycode = modmap->modifiermap[modn * nkeys + i];
       
   430             if (keycode == 0) {
       
   431                 continue;
       
   432             }
       
   433 
       
   434             if (awt_MetaMask == 0 && (keycode == metaL || keycode == metaR)) {
       
   435                 awt_MetaMask = modmask[modn];
       
   436                 DTRACE_PRINTLN2("    awt_MetaMask       = %d, modn = %d", awt_MetaMask, modn);
       
   437                 break;
       
   438             } else if (awt_AltMask == 0 && (keycode == altL || keycode == altR)) {
       
   439                 awt_AltMask = modmask[modn];
       
   440                 DTRACE_PRINTLN2("    awt_AltMask        = %d, modn = %d", awt_AltMask, modn);
       
   441                 break;
       
   442             } else if (awt_NumLockMask == 0 && keycode == numLock) {
       
   443                 awt_NumLockMask = modmask[modn];
       
   444                 DTRACE_PRINTLN2("    awt_NumLockMask    = %d, modn = %d", awt_NumLockMask, modn);
       
   445                 break;
       
   446             } else if (awt_ModeSwitchMask == 0 && keycode == modeSwitch) {
       
   447                 awt_ModeSwitchMask = modmask[modn];
       
   448                 DTRACE_PRINTLN2("    awt_ModeSwitchMask = %d, modn = %d", awt_ModeSwitchMask, modn);
       
   449                 break;
       
   450             }
       
   451         }
       
   452     }
       
   453     for(i = 0; i < nkeys; i++) {
       
   454         KeyCode keycode = modmap->modifiermap[LockMapIndex * nkeys + i];
       
   455         if (keycode == 0) {
       
   456             break;
       
   457         }
       
   458         if (keycode == shiftLock) {
       
   459             awt_ModLockIsShiftLock = True;
       
   460             break;
       
   461         }
       
   462         if (keycode == capsLock) {
       
   463             break;
       
   464         }
       
   465     }
       
   466 
       
   467     DTRACE_PRINTLN1("    ShiftMask          = %d", ShiftMask);
       
   468     DTRACE_PRINTLN1("    ControlMask        = %d", ControlMask);
       
   469 
       
   470     XFreeModifiermap(modmap);
       
   471     ptr = getenv("_AWT_USE_TYPE4_PATCH");
       
   472     if( ptr != NULL && ptr[0] != 0 ) {
       
   473         if( strncmp("true", ptr, 4) == 0 ) {
       
   474            awt_UseType4Patch = True;
       
   475         }else if( strncmp("false", ptr, 5) == 0 ) {
       
   476            awt_UseType4Patch = False;
       
   477         }
       
   478     }
       
   479     awt_UseXKB = isXKBenabled(disp);
       
   480 
       
   481 }
       
   482 
       
   483 
       
   484 Boolean scrollBugWorkAround;
       
   485 
       
   486 
       
   487 void
       
   488 awt_output_flush()
       
   489 {
       
   490     char c = 'p';
       
   491 
       
   492     if (awt_next_flush_time == 0)
       
   493     {
       
   494         Boolean needsWakeup = False;
       
   495         JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
   496         if (awt_pipe_inited && (awt_get_poll_timeout(False) > (2*AWT_FLUSH_TIMEOUT))){
       
   497             needsWakeup = True;
       
   498         }
       
   499         /* awt_next_flush_time affects awt_get_poll_timeout(), so set
       
   500          * the variable *after* calling the function.
       
   501          */
       
   502         awt_next_flush_time = awtJNI_TimeMillis() + AWT_FLUSH_TIMEOUT;
       
   503         if (needsWakeup)
       
   504         {
       
   505             /* write to the utility pipe to wake up the event
       
   506              * loop, if it's sleeping
       
   507              */
       
   508             write ( AWT_WRITEPIPE, &c, 1 );
       
   509         }
       
   510     }
       
   511 #ifdef FLUSHDEBUG
       
   512 else
       
   513 jio_fprintf(stderr, "!");
       
   514 #endif
       
   515 } /* awt_output_flush() */
       
   516 
       
   517 void
       
   518 null_event_handler(Widget w, XtPointer client_data,
       
   519                    XEvent * event, Boolean * cont)
       
   520 {
       
   521     /* do nothing */
       
   522 }
       
   523 
       
   524 struct WidgetInfo *
       
   525 findWidgetInfo(Widget widget)
       
   526 {
       
   527     struct WidgetInfo *cw;
       
   528 
       
   529     for (cw = awt_winfo; cw != NULL; cw = cw->next) {
       
   530         if (cw->widget == widget || cw->origin == widget) {
       
   531             return cw;
       
   532         }
       
   533     }
       
   534     return NULL;
       
   535 }
       
   536 
       
   537 void
       
   538 awt_addWidget(Widget w, Widget origin, void *peer, jlong event_flags)
       
   539 {
       
   540     if (findWidgetInfo(w) != NULL) return;
       
   541 
       
   542     if (!XtIsSubclass(w, xmFileSelectionBoxWidgetClass)) {
       
   543         struct WidgetInfo *nw = (struct WidgetInfo *) malloc(sizeof(struct WidgetInfo));
       
   544 
       
   545         if (nw) {
       
   546             nw->widget     = w;
       
   547             nw->origin     = origin;
       
   548             nw->peer       = peer;
       
   549             nw->event_mask = event_flags;
       
   550             nw->next       = awt_winfo;
       
   551             awt_winfo      = nw;
       
   552 
       
   553             if (event_flags & java_awt_AWTEvent_MOUSE_EVENT_MASK) {
       
   554                 XtAddEventHandler(w,
       
   555                                   ButtonPressMask | ButtonReleaseMask |
       
   556                                   EnterWindowMask | LeaveWindowMask,
       
   557                                   False, null_event_handler, NULL);
       
   558                 if (w != origin) {
       
   559                     XtAddEventHandler(origin,
       
   560                                       ButtonPressMask | ButtonReleaseMask |
       
   561                                       EnterWindowMask | LeaveWindowMask,
       
   562                                       False, null_event_handler, NULL);
       
   563                 }
       
   564             }
       
   565             if (event_flags & java_awt_AWTEvent_MOUSE_MOTION_EVENT_MASK) {
       
   566                 XtAddEventHandler(w,
       
   567                                   PointerMotionMask,
       
   568                                   False, null_event_handler, NULL);
       
   569                 if (w != origin) {
       
   570                     XtAddEventHandler(origin,
       
   571                                       PointerMotionMask,
       
   572                                       False, null_event_handler, NULL);
       
   573                 }
       
   574             }
       
   575             if (event_flags & java_awt_AWTEvent_KEY_EVENT_MASK) {
       
   576                 XtAddEventHandler(w,
       
   577                                   KeyPressMask | KeyReleaseMask,
       
   578                                   False, null_event_handler, NULL);
       
   579                 if (w != origin) {
       
   580                     XtAddEventHandler(origin,
       
   581                                       KeyPressMask | KeyReleaseMask,
       
   582                                       False, null_event_handler, NULL);
       
   583                 }
       
   584             }
       
   585         } else {
       
   586             JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
   587             JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError");
       
   588         }
       
   589 
       
   590     }
       
   591 }
       
   592 
       
   593 void
       
   594 awt_delWidget(Widget w)
       
   595 {
       
   596     struct WidgetInfo *cw;
       
   597 
       
   598     if (awt_winfo != NULL) {
       
   599         if ((awt_winfo->widget == w) ||
       
   600             (awt_winfo->origin == w)) {
       
   601             cw = awt_winfo;
       
   602             awt_winfo = awt_winfo->next;
       
   603             free((void *) cw);
       
   604         } else {
       
   605             struct WidgetInfo *pw;
       
   606 
       
   607             for (pw = awt_winfo, cw = awt_winfo->next;
       
   608                  cw != NULL;
       
   609                  pw = cw, cw = cw->next) {
       
   610                 if ((cw->widget == w) ||
       
   611                     (cw->origin == w)) {
       
   612                     pw->next = cw->next;
       
   613                     free((void *) cw);
       
   614                     break;
       
   615                 }
       
   616             }
       
   617         }
       
   618     }
       
   619 }
       
   620 
       
   621 
       
   622 void *
       
   623 findPeer(Widget * pwidget)
       
   624 {
       
   625     struct WidgetInfo   *cw;
       
   626     Widget widgetParent;
       
   627     void * peer;
       
   628 
       
   629     if ((cw = findWidgetInfo(*pwidget)) != NULL) {
       
   630         return cw->peer;
       
   631     }
       
   632     /* fix for 4053856, robi.khan@eng
       
   633        couldn't find peer corresponding to widget
       
   634        but the widget may be child of one with
       
   635        a peer, so recurse up the hierarchy */
       
   636     widgetParent = XtParent(*pwidget);
       
   637     if (widgetParent != NULL ) {
       
   638         peer = findPeer(&widgetParent);
       
   639         if( peer != NULL ) {
       
   640         /* found peer attached to ancestor of given
       
   641            widget, so set widget return value as well */
       
   642             *pwidget = widgetParent;
       
   643             return peer;
       
   644         }
       
   645     }
       
   646 
       
   647     return NULL;
       
   648 }
       
   649 
       
   650 Boolean
       
   651 awt_isAwtWidget(Widget widget)
       
   652 {
       
   653     return (findWidgetInfo(widget) != NULL);
       
   654 }
       
   655 
       
   656 
       
   657 static Boolean
       
   658 awt_isAwtMenuWidget(Widget wdgt) {
       
   659     struct MenuList* cur;
       
   660 
       
   661     if (!XtIsSubclass(wdgt, xmRowColumnWidgetClass)) {
       
   662         return False;
       
   663     }
       
   664     for (cur = menu_list; cur != NULL; cur = cur->next) {
       
   665         if (cur->menu == wdgt) {
       
   666             return True;
       
   667         }
       
   668     }
       
   669     return False;
       
   670 }
       
   671 
       
   672 void
       
   673 awt_addMenuWidget(Widget wdgt) {
       
   674     DASSERT(XtIsSubclass(wdgt, xmRowColumnWidgetClass));
       
   675 
       
   676     if (!awt_isAwtMenuWidget(wdgt)) {
       
   677         struct MenuList* ml = (struct MenuList*) malloc(sizeof(struct MenuList));
       
   678         if (ml != NULL) {
       
   679             ml->menu = wdgt;
       
   680             ml->next = menu_list;
       
   681             menu_list = ml;
       
   682         } else {
       
   683             JNIEnv* env = (JNIEnv*)JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
   684             JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError");
       
   685         }
       
   686     }
       
   687 }
       
   688 
       
   689 void
       
   690 awt_delMenuWidget(Widget wdgt) {
       
   691     struct MenuList** pp;
       
   692     struct MenuList* p;
       
   693 
       
   694     DASSERT(XtIsSubclass(wdgt, xmRowColumnWidgetClass));
       
   695 
       
   696     for (pp = &menu_list; *pp != NULL; pp = &((*pp)->next)) {
       
   697         if ((*pp)->menu == wdgt) {
       
   698             p = *pp;
       
   699             *pp = (*pp)->next;
       
   700             free((void*)p);
       
   701             break;
       
   702         }
       
   703     }
       
   704 }
       
   705 
       
   706 
       
   707 static Widget
       
   708 getShellWidgetByPart(Widget part) {
       
   709     int i;
       
   710     for (i = 0; i < 3; i++) {
       
   711         if (part == NULL) return NULL;
       
   712         if (XtIsShell(part)) return part;
       
   713         part = XtParent(part);
       
   714     }
       
   715     return NULL;
       
   716 }
       
   717 
       
   718 static Boolean
       
   719 isTheSameShellWidget(Widget shell, Widget w) {
       
   720     Widget s1, s2;
       
   721     if (shell == NULL || w == NULL) return False;
       
   722     s1 = getShellWidgetByPart(shell);
       
   723     s2 = getShellWidgetByPart(w);
       
   724     if (s1 == s2 && s1 != NULL) {
       
   725         return True;
       
   726     } else {
       
   727         return False;
       
   728     }
       
   729 }
       
   730 
       
   731 static Boolean
       
   732 shouldDispatchToWidget(XEvent * xev)
       
   733 {
       
   734   /* If this function returns False, that means that it has not pre-posted
       
   735      this event to Java. The caller will then dispatch the event to Motif,
       
   736      and our handlers will be called to post it to Java.
       
   737      If this function returns true, then this function has posted this event
       
   738      to java before returning. The caller will not dispatch it to Motif;
       
   739      it will be dispatched to Motif via the putbackQueue after it has been
       
   740      processed by Java */
       
   741 
       
   742     Window win;
       
   743     Widget widget = NULL;
       
   744     struct WidgetInfo *winfo;
       
   745     void *peer = NULL;
       
   746     Boolean cont = FALSE;
       
   747 
       
   748     switch (xev->type) {
       
   749         case KeyPress:
       
   750         case KeyRelease:
       
   751             win = xev->xkey.window;
       
   752             break;
       
   753         case FocusIn:
       
   754         case FocusOut:
       
   755             win = xev->xfocus.window;
       
   756             break;
       
   757         case ButtonPress:
       
   758         case ButtonRelease:
       
   759             win = xev->xbutton.window;
       
   760             break;
       
   761         case MotionNotify:
       
   762             win = xev->xmotion.window;
       
   763             break;
       
   764         case EnterNotify:
       
   765         case LeaveNotify:
       
   766             win = xev->xcrossing.window;
       
   767             break;
       
   768         default:
       
   769             return False;
       
   770     }
       
   771 
       
   772     if ((widget = XtWindowToWidget(awt_display, win)) == NULL) {
       
   773         return False;
       
   774     }
       
   775 
       
   776     if (xev->type == KeyPress || xev->type == KeyRelease) {
       
   777         Widget focusWidget = XmGetFocusWidget(widget);
       
   778 
       
   779         /* Fix for 4328561 by ibd@sparc.spb.su
       
   780            If the widget is a Choice, the widget with focus is probably lying
       
   781            outside the current widget's sub-hierarchy, so we have to go up the
       
   782            hierarchy to reach it */
       
   783 
       
   784         if ((focusWidget == NULL) && XmIsMenuShell(widget)) {
       
   785             if ((widget = XtParent(widget)) != NULL) {
       
   786                 focusWidget = XmGetFocusWidget(widget);
       
   787             } else {
       
   788                 return False;
       
   789             }
       
   790 
       
   791             /* In this case, focus widget should be CascadeButtonGadget type,
       
   792                but we should send the events to its parent */
       
   793             if (focusWidget != NULL && XmIsCascadeButtonGadget(focusWidget)) {
       
   794                 widget = XtParent(focusWidget);
       
   795             } else {
       
   796                 /* If something went wrong, restore the original status */
       
   797                 widget = XtWindowToWidget(awt_display, win);
       
   798             }
       
   799         }
       
   800 
       
   801         /* if focus owner is null, redirect key events to focused window */
       
   802         if (focusWidget == NULL && findWidgetInfo(widget) == NULL) {
       
   803             focusWidget = findTopLevelByShell(widget);
       
   804         }
       
   805 
       
   806         /* If we are on a non-choice widget, process events in a normal way */
       
   807         if ((focusWidget != NULL) && (focusWidget != widget)) {
       
   808             if (isTheSameShellWidget(focusWidget, widget)) {
       
   809                 focusWidget = findTopLevelByShell(widget);
       
   810             }
       
   811             if (focusWidget != NULL) {
       
   812                 peer = findPeer(&focusWidget);
       
   813             }
       
   814             if (peer != NULL) {
       
   815                 widget = focusWidget;
       
   816                 win = xev->xkey.window = XtWindow(focusWidget);
       
   817             }
       
   818         }
       
   819     }
       
   820 
       
   821     if ((winfo = findWidgetInfo(widget)) == NULL) {
       
   822         return False;
       
   823     }
       
   824 
       
   825     /*
       
   826      * Fix for bug 4145193
       
   827      *
       
   828      * If a menu is up (not just a popup menu), prevent awt components from
       
   829      * getting any events until the menu is popped down.
       
   830      * Before this fix, the fact that mouse/button events were
       
   831      * preposted to the Java event queue was causing the ButtonRelease
       
   832      * (needed to pop menu down) to be seen by the menu's parent and
       
   833      * not the menu.
       
   834      */
       
   835     if (awtMenuIsActive()) {
       
   836         Widget focusWidget = XmGetFocusWidget(widget);
       
   837 
       
   838         if (focusWidget == NULL) {
       
   839             return False;
       
   840         }
       
   841 
       
   842         /* If we are on a choice, dispatch the events to widget, but do not
       
   843          * dispatch the events if we are on popped up menu.
       
   844          */
       
   845         if (!XmIsRowColumn(widget) || !XmIsCascadeButtonGadget(focusWidget)) {
       
   846             /* Fix for 4328557 by ibd@sparc.spb.su
       
   847              * If we are dragging mouse from choice and are currently outside
       
   848              * of it, dispatch events to the choice - the source of dragging.
       
   849              */
       
   850 
       
   851             if ((drag_source != NULL) && (widget != drag_source) &&
       
   852                 (peer = findPeer(&drag_source))) {
       
   853                 awt_canvas_handleEvent(drag_source, peer, xev, winfo, &cont, TRUE);
       
   854             }
       
   855             return False;
       
   856         }
       
   857     }
       
   858 
       
   859     /* If the keyboard is grabbed by a popup (such as a choice) during
       
   860        a time when a focus proxy is in effect, the abovefocusIsOnMenu
       
   861        test will not detect the sitation because the focus will be on
       
   862        the proxy. But we need events to go to Motif first, so that the
       
   863        grab can be undone when appropriate. */
       
   864     if (keyboardGrabbed) {
       
   865         return False;
       
   866     }
       
   867 
       
   868     /* If it's a keyboard event, we need to find the peer associated */
       
   869     /* with the widget that has the focus rather than the widget */
       
   870     /* associated with the window in the X event. */
       
   871 
       
   872     switch (xev->type) {
       
   873       case KeyPress:
       
   874       case KeyRelease:
       
   875           if (!(winfo->event_mask & java_awt_AWTEvent_KEY_EVENT_MASK))
       
   876               return False;
       
   877           break;
       
   878         case FocusIn:
       
   879         case FocusOut:
       
   880             if (!(winfo->event_mask & java_awt_AWTEvent_FOCUS_EVENT_MASK))
       
   881                 return False;
       
   882             break;
       
   883         case ButtonPress:
       
   884         case ButtonRelease:
       
   885             if (!(winfo->event_mask & java_awt_AWTEvent_MOUSE_EVENT_MASK)) {
       
   886                 return False;
       
   887             }
       
   888             break;
       
   889         case EnterNotify:
       
   890         case LeaveNotify:
       
   891             /*
       
   892              * Do not post the enter/leave event if it's on a subwidget
       
   893              * within the component.
       
   894              */
       
   895             if (!(winfo->event_mask & java_awt_AWTEvent_MOUSE_EVENT_MASK) ||
       
   896                 widget != winfo->origin)
       
   897                 return False;
       
   898             break;
       
   899         case MotionNotify:
       
   900             if (!(winfo->event_mask & java_awt_AWTEvent_MOUSE_MOTION_EVENT_MASK))
       
   901                 return False;
       
   902             break;
       
   903         default:
       
   904             return False;
       
   905     }
       
   906 
       
   907     peer = winfo->peer;
       
   908 
       
   909     /* If we found a widget and a suitable peer (either the focus
       
   910        peer above or the one associated with the widget then we
       
   911        dispatch to it. */
       
   912     if (peer == NULL) {
       
   913         return False;
       
   914     }
       
   915 
       
   916     /*
       
   917      * Fix for bug 4173714 - java.awt.button behaves differently under
       
   918      * Win32/Solaris.
       
   919      * Component should not get any events when it's disabled.
       
   920      */
       
   921     if (!XtIsSensitive(widget)) {
       
   922         if (xev->type == EnterNotify) {
       
   923             updateCursor(peer, CACHE_UPDATE);
       
   924         }
       
   925         return False;
       
   926     }
       
   927 
       
   928     awt_canvas_handleEvent(widget, peer, xev, winfo, &cont, TRUE);
       
   929     return (!cont);
       
   930 } /* shouldDispatchToWidget() */
       
   931 
       
   932 
       
   933 void set_toolkit_busy(Boolean busy) {
       
   934 
       
   935     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
   936 
       
   937     static jclass awtAutoShutdownClass = NULL;
       
   938     static jmethodID notifyBusyMethodID = NULL;
       
   939     static jmethodID notifyFreeMethodID = NULL;
       
   940 
       
   941     if (awtAutoShutdownClass == NULL) {
       
   942         jclass awtAutoShutdownClassLocal = (*env)->FindClass(env, "sun/awt/AWTAutoShutdown");
       
   943         if ((*env)->ExceptionOccurred(env)) {
       
   944             (*env)->ExceptionDescribe(env);
       
   945             (*env)->ExceptionClear(env);
       
   946         }
       
   947         DASSERT(awtAutoShutdownClassLocal != NULL);
       
   948         if (awtAutoShutdownClassLocal == NULL) {
       
   949             return;
       
   950         }
       
   951 
       
   952         awtAutoShutdownClass = (jclass)(*env)->NewGlobalRef(env, awtAutoShutdownClassLocal);
       
   953         (*env)->DeleteLocalRef(env, awtAutoShutdownClassLocal);
       
   954 
       
   955         notifyBusyMethodID = (*env)->GetStaticMethodID(env, awtAutoShutdownClass,
       
   956                                                     "notifyToolkitThreadBusy", "()V");
       
   957         if ((*env)->ExceptionOccurred(env)) {
       
   958             (*env)->ExceptionDescribe(env);
       
   959             (*env)->ExceptionClear(env);
       
   960         }
       
   961         notifyFreeMethodID = (*env)->GetStaticMethodID(env, awtAutoShutdownClass,
       
   962                                                     "notifyToolkitThreadFree", "()V");
       
   963         if ((*env)->ExceptionOccurred(env)) {
       
   964             (*env)->ExceptionDescribe(env);
       
   965             (*env)->ExceptionClear(env);
       
   966         }
       
   967         DASSERT(notifyBusyMethodID != NULL);
       
   968         DASSERT(notifyFreeMethodID != NULL);
       
   969         if (notifyBusyMethodID == NULL || notifyFreeMethodID == NULL) {
       
   970             return;
       
   971         }
       
   972     } /* awtAutoShutdownClass == NULL*/
       
   973 
       
   974     if (busy) {
       
   975         (*env)->CallStaticVoidMethod(env, awtAutoShutdownClass,
       
   976                                      notifyBusyMethodID);
       
   977     } else {
       
   978         (*env)->CallStaticVoidMethod(env, awtAutoShutdownClass,
       
   979                                      notifyFreeMethodID);
       
   980     }
       
   981 
       
   982     if ((*env)->ExceptionOccurred(env)) {
       
   983         (*env)->ExceptionDescribe(env);
       
   984         (*env)->ExceptionClear(env);
       
   985     }
       
   986 }
       
   987 
       
   988 #ifdef DEBUG
       
   989 static int32_t debugPrintLineCount = 0;   /* limit debug output per line */
       
   990 #endif
       
   991 
       
   992 /*
       
   993  * This is the main Xt event loop for the AWT.
       
   994  *
       
   995  * Because java applications are multithreaded, but X and Xt
       
   996  * are thread-dumb, we must make special considerations to
       
   997  * make ensure that the X/Xt libraries are not entered by
       
   998  * multiple threads simultaneously.
       
   999  *
       
  1000  * The biggest difference between the standard Xt loop
       
  1001  * and this loop is that we go to great lengths never to block
       
  1002  * in the X libraries. We poll() on the X event pipe, waiting
       
  1003  * for events, rather than simply calling XtAppNextEvent() and
       
  1004  * blocking. If this thread were to block in XtAppNextEvent(),
       
  1005  * no other thread could enter (e.g., to perform a paint or
       
  1006  * retrieve data).
       
  1007  */
       
  1008 /* #ifdef DEBUG */
       
  1009     int32_t  numEventsHandled = 0;
       
  1010 /* #endif */
       
  1011 static void
       
  1012 awt_MToolkit_loop(JNIEnv *env)
       
  1013 {
       
  1014     XtInputMask iMask;
       
  1015     int32_t  fdXPipe = -1;              /* pipe where X events arrive */
       
  1016 
       
  1017     /* only privileged thread should be running here */
       
  1018     DASSERT(awt_currentThreadIsPrivileged(env));
       
  1019 
       
  1020     /* The pipe where X events arrive */
       
  1021     fdXPipe = ConnectionNumber(awt_display) ;
       
  1022 
       
  1023     /* We execute events while locked, unlocking only when waiting
       
  1024      * for an event
       
  1025      */
       
  1026     AWT_LOCK();
       
  1027 
       
  1028     /* Create the AWT utility pipe. See the comments on awt_pipe_init() */
       
  1029     awt_pipe_init();
       
  1030 
       
  1031     /*
       
  1032      * Need to flush here in case data on the connection was read
       
  1033      * before we acquired the monitor.
       
  1034      *
       
  1035      * I don't get this, but I'm too chicken to remove it. -jethro 2Sep98
       
  1036      */
       
  1037     AWT_FLUSHOUTPUT_NOW();
       
  1038 
       
  1039     /*
       
  1040      * ACTUALLY PROCESS EVENTS
       
  1041      */
       
  1042     while(True) {
       
  1043 
       
  1044         /* process all events in the queue */
       
  1045 /*      #ifdef DEBUG */
       
  1046 /*          numEventsHandled = 0; */
       
  1047 /*      #endif */
       
  1048         while (((iMask = awt_events_pending(awt_appContext)) & XtIMAll) > 0) {
       
  1049 
       
  1050 /*          #ifdef DEBUG */
       
  1051                 ++numEventsHandled;
       
  1052 /*          #endif */
       
  1053             processOneEvent(iMask);
       
  1054 
       
  1055         }  /* end while awt_events_pending() */
       
  1056         /* At this point, we have exhausted the event queue */
       
  1057 
       
  1058         /* print the number of events handled in parens */
       
  1059         DTRACE_PRINT1("(%d events)",(int32_t)numEventsHandled);
       
  1060 #ifdef DEBUG
       
  1061         if (++debugPrintLineCount > 8) {
       
  1062             DTRACE_PRINTLN("");
       
  1063             debugPrintLineCount = 0;
       
  1064         }
       
  1065 #endif
       
  1066 
       
  1067         AWT_NOTIFY_ALL();               /* wake up modalWait() */
       
  1068 
       
  1069         set_toolkit_busy(False);
       
  1070 
       
  1071         /* Here, we wait for X events, outside of the X libs. When
       
  1072          * it's likely that an event is waiting, we process the queue
       
  1073          */
       
  1074         waitForEvents(env, fdXPipe, AWT_READPIPE);
       
  1075 
       
  1076         set_toolkit_busy(True);
       
  1077 
       
  1078     } /* while(True) */
       
  1079 
       
  1080     /* If we ever exit the loop, must unlock the toolkit */
       
  1081 
       
  1082 } /* awt_MToolkit_loop() */
       
  1083 
       
  1084 /*
       
  1085  * Creates the AWT utility pipe. This pipe exists solely so that
       
  1086  * we can cause the main event thread to wake up from a poll() or
       
  1087  * select() by writing to this pipe.
       
  1088  */
       
  1089 static void
       
  1090 awt_pipe_init(void) {
       
  1091 
       
  1092     if (awt_pipe_inited) {
       
  1093         return;
       
  1094     }
       
  1095 
       
  1096     if ( pipe ( awt_pipe_fds ) == 0 )
       
  1097     {
       
  1098         /*
       
  1099         ** the write wakes us up from the infinite sleep, which
       
  1100         ** then we cause a delay of AWT_FLUSHTIME and then we
       
  1101         ** flush.
       
  1102         */
       
  1103         int32_t flags = 0;
       
  1104         awt_set_poll_timeout (def_poll_timeout);
       
  1105         /* set the pipe to be non-blocking */
       
  1106         flags = fcntl ( AWT_READPIPE, F_GETFL, 0 );
       
  1107         fcntl( AWT_READPIPE, F_SETFL, flags | O_NDELAY | O_NONBLOCK );
       
  1108         flags = fcntl ( AWT_WRITEPIPE, F_GETFL, 0 );
       
  1109         fcntl( AWT_WRITEPIPE, F_SETFL, flags | O_NDELAY | O_NONBLOCK );
       
  1110         awt_pipe_inited = True;
       
  1111     }
       
  1112     else
       
  1113     {
       
  1114         AWT_READPIPE = -1;
       
  1115         AWT_WRITEPIPE = -1;
       
  1116         awt_pipe_inited = False;
       
  1117     }
       
  1118 } /* awt_pipe_init() */
       
  1119 
       
  1120 static Window
       
  1121 proxyTopLevel(Window proxyWindow) {
       
  1122     Window parent = None, root = None, *children = NULL, retvalue = None;
       
  1123     uint32_t nchildren = 0;
       
  1124     Status res = XQueryTree(awt_display, proxyWindow, &root, &parent,
       
  1125              &children, &nchildren);
       
  1126     if (res != 0) {
       
  1127         if (nchildren > 0) {
       
  1128             retvalue = children[0];
       
  1129         }
       
  1130         else retvalue = None;
       
  1131         if (children != NULL) {
       
  1132             XFree(children);
       
  1133         }
       
  1134         return retvalue;
       
  1135     } else {
       
  1136         return None;
       
  1137     }
       
  1138 }
       
  1139 
       
  1140 static jclass clazzF, clazzD = NULL;
       
  1141 
       
  1142 static Boolean
       
  1143 initClazzD(JNIEnv *env) {
       
  1144     jclass t_clazzD = (*env)->FindClass(env, "java/awt/Dialog");
       
  1145     if ((*env)->ExceptionOccurred(env)) {
       
  1146         (*env)->ExceptionDescribe(env);
       
  1147         (*env)->ExceptionClear(env);
       
  1148     }
       
  1149     DASSERT(t_clazzD != NULL);
       
  1150     if (t_clazzD == NULL) {
       
  1151         return False;
       
  1152     }
       
  1153     clazzD = (*env)->NewGlobalRef(env, t_clazzD);
       
  1154     DASSERT(clazzD != NULL);
       
  1155     (*env)->DeleteLocalRef(env, t_clazzD);
       
  1156     return True;
       
  1157 }
       
  1158 
       
  1159 Boolean
       
  1160 isFrameOrDialog(jobject target, JNIEnv *env) {
       
  1161     if ((*env)->EnsureLocalCapacity(env, 1) < 0) {
       
  1162         return False;
       
  1163     }
       
  1164 
       
  1165     if (clazzF == NULL) {
       
  1166         jclass t_clazzF = (*env)->FindClass(env, "java/awt/Frame");
       
  1167         if ((*env)->ExceptionOccurred(env)) {
       
  1168             (*env)->ExceptionDescribe(env);
       
  1169             (*env)->ExceptionClear(env);
       
  1170         }
       
  1171         DASSERT(t_clazzF != NULL);
       
  1172         if (t_clazzF == NULL) {
       
  1173             return False;
       
  1174         }
       
  1175         clazzF = (*env)->NewGlobalRef(env, t_clazzF);
       
  1176         DASSERT(clazzF != NULL);
       
  1177         (*env)->DeleteLocalRef(env, t_clazzF);
       
  1178     }
       
  1179 
       
  1180     if (clazzD == NULL && !initClazzD(env)) {
       
  1181         return False;
       
  1182     }
       
  1183 
       
  1184     return (*env)->IsInstanceOf(env, target, clazzF) ||
       
  1185         (*env)->IsInstanceOf(env, target, clazzD);
       
  1186 }
       
  1187 
       
  1188 Boolean
       
  1189 isDialog(jobject target, JNIEnv *env) {
       
  1190     if (clazzD == NULL && !initClazzD(env)) {
       
  1191         return False;
       
  1192     }
       
  1193     return (*env)->IsInstanceOf(env, target, clazzD);
       
  1194 }
       
  1195 
       
  1196 // Returns a local ref to a decorated owner of the target,
       
  1197 // or NULL if the target is Frame or Dialog itself.
       
  1198 // The local ref returned should be deleted by the caller.
       
  1199 jobject
       
  1200 getOwningFrameOrDialog(jobject target, JNIEnv *env) {
       
  1201     jobject _target = (*env)->NewLocalRef(env, target);
       
  1202     jobject parent = _target;
       
  1203     Boolean isSelfFrameOrDialog = True;
       
  1204 
       
  1205     while (!isFrameOrDialog(parent, env)) {
       
  1206         isSelfFrameOrDialog = False;
       
  1207         parent = (*env)->CallObjectMethod(env, _target, componentIDs.getParent);
       
  1208         (*env)->DeleteLocalRef(env, _target);
       
  1209         _target = parent;
       
  1210     }
       
  1211 
       
  1212     if (isSelfFrameOrDialog) {
       
  1213         (*env)->DeleteLocalRef(env, parent);
       
  1214         return NULL;
       
  1215     }
       
  1216     return parent;
       
  1217 }
       
  1218 
       
  1219 Widget
       
  1220 findWindowsProxy(jobject window, JNIEnv *env) {
       
  1221     struct ComponentData *cdata;
       
  1222     jobject tlPeer;
       
  1223     jobject owner_prev = NULL, owner_new = NULL;
       
  1224     /* the owner of a Window is in its parent field */
       
  1225     /* we may have a chain of Windows; go up the chain till we find the
       
  1226        owning Frame or Dialog */
       
  1227     if ((*env)->EnsureLocalCapacity(env, 4) < 0) {
       
  1228         return NULL;
       
  1229     }
       
  1230 
       
  1231     if (window == NULL) return NULL;
       
  1232 
       
  1233     owner_prev = (*env)->NewLocalRef(env, window);
       
  1234     while (!JNU_IsNull(env, owner_prev) && !(isFrameOrDialog(owner_prev, env))) {
       
  1235         owner_new = (*env)->CallObjectMethod(env, owner_prev, componentIDs.getParent);
       
  1236         (*env)->DeleteLocalRef(env, owner_prev);
       
  1237         owner_prev = owner_new;
       
  1238     }
       
  1239 
       
  1240     if (owner_prev == NULL) return NULL;
       
  1241 
       
  1242     tlPeer = (*env)->GetObjectField(env, owner_prev, componentIDs.peer);
       
  1243     (*env)->DeleteLocalRef(env, owner_prev);
       
  1244     if (tlPeer == NULL) return NULL;
       
  1245 
       
  1246     cdata = (struct ComponentData *)
       
  1247         JNU_GetLongFieldAsPtr(env, tlPeer, mComponentPeerIDs.pData);
       
  1248     (*env)->DeleteLocalRef(env, tlPeer);
       
  1249 
       
  1250     if (cdata == NULL) return NULL;
       
  1251     return(findFocusProxy(cdata->widget));
       
  1252 }
       
  1253 
       
  1254 jobject
       
  1255 findTopLevel(jobject peer, JNIEnv *env) {
       
  1256     jobject target_prev = NULL;
       
  1257     static jclass clazzW = NULL;
       
  1258 
       
  1259     if ((*env)->EnsureLocalCapacity(env, 3) < 0) {
       
  1260         return NULL;
       
  1261     }
       
  1262 
       
  1263     if (clazzW == NULL) {
       
  1264         jclass t_clazzW = (*env)->FindClass(env, "java/awt/Window");
       
  1265         if ((*env)->ExceptionOccurred(env)) {
       
  1266             (*env)->ExceptionDescribe(env);
       
  1267             (*env)->ExceptionClear(env);
       
  1268         }
       
  1269         DASSERT(t_clazzW != NULL);
       
  1270         if (t_clazzW == NULL) {
       
  1271             return NULL;
       
  1272         }
       
  1273         clazzW = (*env)->NewGlobalRef(env, t_clazzW);
       
  1274         DASSERT(clazzW != NULL);
       
  1275         (*env)->DeleteLocalRef(env, t_clazzW);
       
  1276     }
       
  1277     target_prev = (*env)->GetObjectField(env, peer, mComponentPeerIDs.target);
       
  1278     if (target_prev == NULL) {
       
  1279         return NULL;
       
  1280     }
       
  1281 
       
  1282     while ((target_prev != NULL)
       
  1283            && !(*env)->IsInstanceOf(env, target_prev, clazzW) )
       
  1284     {
       
  1285         /* go up the hierarchy until we find a window */
       
  1286         jobject target_new = (*env)->CallObjectMethod(env, target_prev, componentIDs.getParent);
       
  1287         (*env)->DeleteLocalRef(env, target_prev);
       
  1288         target_prev = target_new;
       
  1289     }
       
  1290     return target_prev;
       
  1291 }
       
  1292 
       
  1293 static Window
       
  1294 rootWindow(Window w) {
       
  1295     Window root = None;
       
  1296     Window parent = None;
       
  1297     Window *children = NULL;
       
  1298     uint32_t nchildren = 0;
       
  1299 
       
  1300     if (w != None) {
       
  1301         Status res = XQueryTree(awt_display, w, &root, &parent, &children, &nchildren);
       
  1302         if (res == 0) {
       
  1303             return None;
       
  1304         }
       
  1305         if (children != NULL) {
       
  1306             XFree(children);
       
  1307         }
       
  1308   return root;
       
  1309     } else {
       
  1310         return None;
       
  1311     }
       
  1312 }
       
  1313 
       
  1314 Boolean IsRootOf(Window root, Window child) {
       
  1315     Window w_root = None, w_parent = None, * children = NULL;
       
  1316     uint32_t c_count = 0;
       
  1317     if (root == None || child == None) {
       
  1318         return False;
       
  1319     }
       
  1320     do {
       
  1321         w_root = None;
       
  1322         w_parent = None;
       
  1323         children = NULL;
       
  1324         c_count = 0;
       
  1325         if (XQueryTree(awt_display, child, &w_root, &w_parent,
       
  1326                        &children, &c_count)) {
       
  1327             if (children != NULL) {
       
  1328                 XFree(children);
       
  1329             }
       
  1330             if (w_parent == None) {
       
  1331                 return False;
       
  1332             }
       
  1333             if (w_parent == root) {
       
  1334                 return True;
       
  1335             }
       
  1336         } else {
       
  1337             return False;
       
  1338         }
       
  1339         child = w_parent;
       
  1340     } while (True);
       
  1341 }
       
  1342 
       
  1343 Window findShellByProxy(Window proxy) {
       
  1344     Widget proxy_wid = XtWindowToWidget(awt_display, proxy);
       
  1345     while (proxy_wid != NULL && !XtIsShell(proxy_wid)) {
       
  1346         proxy_wid = XtParent(proxy_wid);
       
  1347     }
       
  1348     if (proxy_wid == NULL) {
       
  1349         return None;
       
  1350     }
       
  1351     return XtWindow(proxy_wid);
       
  1352 }
       
  1353 
       
  1354 // Window which contains focus owner when focus proxy is enabled
       
  1355 Window trueFocusWindow = None;
       
  1356 // Window which works as proxy for input events for real focus owner.
       
  1357 Window focusProxyWindow = None;
       
  1358 
       
  1359 void clearFocusPathOnWindow(Window win) {
       
  1360     if (focusProxyWindow != None && IsRootOf(win, trueFocusWindow)) {
       
  1361         XEvent ev;
       
  1362         memset(&ev, 0, sizeof(ev));
       
  1363         ev.type = FocusOut;
       
  1364         ev.xany.send_event = True;
       
  1365         ev.xany.display = awt_display;
       
  1366         ev.xfocus.mode = NotifyNormal;
       
  1367         ev.xfocus.detail = NotifyNonlinear;
       
  1368         {
       
  1369             Window root = rootWindow(trueFocusWindow);
       
  1370             JNIEnv *env = (JNIEnv *) JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
  1371             ev.xfocus.window = trueFocusWindow;
       
  1372             while (ev.xfocus.window != root &&
       
  1373                    ev.xfocus.window != None) {
       
  1374                 Widget w = XtWindowToWidget(awt_display,
       
  1375                                             ev.xfocus.window);
       
  1376                 awt_put_back_event(env, &ev);
       
  1377                 if (w == NULL) {
       
  1378                     break;
       
  1379                 }
       
  1380                 if (XtParent(w) != NULL) {
       
  1381                     ev.xfocus.window = XtWindow(XtParent(w));
       
  1382                 } else {
       
  1383                     ev.xfocus.window = None;
       
  1384                 }
       
  1385             }
       
  1386         }
       
  1387         XSetInputFocus(awt_display, findShellByProxy(focusProxyWindow), RevertToPointerRoot, CurrentTime);
       
  1388         trueFocusWindow = None;
       
  1389         focusProxyWindow = None;
       
  1390     }
       
  1391 }
       
  1392 void clearFocusPath(Widget shell) {
       
  1393     Window w = None;
       
  1394     if (shell == NULL) {
       
  1395         return;
       
  1396     }
       
  1397     w = XtWindow(shell);
       
  1398     clearFocusPathOnWindow(w);
       
  1399 }
       
  1400 
       
  1401 void globalClearFocusPath(Widget focusOwnerShell ) {
       
  1402     if (focusProxyWindow != None) {
       
  1403         Window shellWindow = findShellByProxy(trueFocusWindow);
       
  1404         if (shellWindow != None) {
       
  1405             Widget shell = XtWindowToWidget(awt_display, shellWindow);
       
  1406             if (shell != NULL && shell != focusOwnerShell) {
       
  1407                 clearFocusPath(shell);
       
  1408             }
       
  1409         }
       
  1410     }
       
  1411 }
       
  1412 
       
  1413 static void
       
  1414 focusEventForProxy(XEvent xev,
       
  1415                    JNIEnv *env,
       
  1416                    Window *trueFocusWindow,
       
  1417                    Window *focusProxyWindow) {
       
  1418 
       
  1419     DASSERT (trueFocusWindow != NULL && focusProxyWindow != NULL);
       
  1420   if (xev.type == FocusOut) {
       
  1421     if (xev.xfocus.window == *focusProxyWindow) {
       
  1422             if (*trueFocusWindow != None) {
       
  1423                 Window root = rootWindow(*trueFocusWindow);
       
  1424       focusOutEvent.xfocus.window = *trueFocusWindow;
       
  1425 #ifdef DEBUG_FOCUS
       
  1426       printf(" nulling out proxy; putting back event"
       
  1427              "\n");
       
  1428 #endif
       
  1429 
       
  1430       while (focusOutEvent.xfocus.window != root &&
       
  1431              focusOutEvent.xfocus.window != None) {
       
  1432         Widget w = XtWindowToWidget(awt_display,
       
  1433                                     focusOutEvent.xfocus.window);
       
  1434         awt_put_back_event(env, &focusOutEvent);
       
  1435         if (w != NULL && XtParent(w) != NULL) {
       
  1436           focusOutEvent.xfocus.window = XtWindow(XtParent(w));
       
  1437         } else {
       
  1438           focusOutEvent.xfocus.window = None;
       
  1439         }
       
  1440       }
       
  1441       *trueFocusWindow = None;
       
  1442       *focusProxyWindow = None;
       
  1443       return;
       
  1444     } else {
       
  1445 #ifdef DEBUG_FOCUS
       
  1446       printf("\n");
       
  1447 #endif
       
  1448       return;
       
  1449     }
       
  1450   } else {
       
  1451 #ifdef DEBUG_FOCUS
       
  1452     printf("\n");
       
  1453 #endif
       
  1454     return;
       
  1455   }
       
  1456     }
       
  1457 }
       
  1458 
       
  1459 static void
       
  1460 focusEventForFrame(XEvent xev, Window focusProxyWindow) {
       
  1461   if (xev.type == FocusIn) {
       
  1462     if (focusProxyWindow != None) {
       
  1463       /* eat it */
       
  1464       return;
       
  1465     } else /* FocusIn on Frame or Dialog */ {
       
  1466       XtDispatchEvent(&xev);
       
  1467     }
       
  1468   } else /* FocusOut on Frame or Dialog */{
       
  1469     XtDispatchEvent(&xev);
       
  1470   }
       
  1471 }
       
  1472 
       
  1473 static void
       
  1474 focusEventForWindow(XEvent xev, JNIEnv *env, Window *trueFocusWindow,
       
  1475                     Window *focusProxyWindow, jobject target) {
       
  1476   XEvent pev;
       
  1477   if (xev.type == FocusIn && xev.xfocus.mode == NotifyNormal) {
       
  1478     /* If it's a FocusIn, allow it to process, then set
       
  1479        focus to focus proxy */
       
  1480     Widget focusProxy;
       
  1481     focusProxy = findWindowsProxy(target, env);
       
  1482     if (focusProxy != NULL) {
       
  1483       XtDispatchEvent(&xev);
       
  1484       *focusProxyWindow = XtWindow(focusProxy);
       
  1485 
       
  1486       XSetInputFocus(awt_display, *focusProxyWindow,
       
  1487                      RevertToParent,
       
  1488                      CurrentTime);
       
  1489 
       
  1490       XPeekEvent(awt_display, &pev);
       
  1491       while (pev.type == FocusIn) {
       
  1492         XNextEvent(awt_display, &xev);
       
  1493         XPeekEvent(awt_display, &pev);
       
  1494       }
       
  1495       *trueFocusWindow = xev.xany.window;
       
  1496 
       
  1497     } /* otherwise error */
       
  1498   } else /* FocusOut */ {
       
  1499     /* If it's a FocusOut on a Window, discard it unless
       
  1500        it's an event generated by us. */
       
  1501     if (xev.xany.send_event) {
       
  1502       XtDispatchEvent(&xev);
       
  1503     }
       
  1504   }
       
  1505 }
       
  1506 
       
  1507 Boolean
       
  1508 isAncestor(Window ancestor, Window child) {
       
  1509   Window *children;
       
  1510   uint32_t nchildren;
       
  1511   Boolean retvalue = False;
       
  1512 
       
  1513   while (child != ancestor) {
       
  1514     Window parent, root;
       
  1515     Status status;
       
  1516 
       
  1517     status = XQueryTree(awt_display, child, &root, &parent,
       
  1518                         &children, &nchildren);
       
  1519     if (status == 0) return False; /* should be an error of some sort? */
       
  1520 
       
  1521     if (parent == root) {
       
  1522       if (child != ancestor) {
       
  1523         retvalue = False;
       
  1524         break;
       
  1525       } else {
       
  1526         retvalue = True;
       
  1527         break;
       
  1528       }
       
  1529     }
       
  1530     if (parent == ancestor) { retvalue = True; break; }
       
  1531     if (nchildren > 0) XFree(children);
       
  1532     child = parent;
       
  1533   }
       
  1534   if (nchildren > 0) XFree(children);
       
  1535   return retvalue;
       
  1536 }
       
  1537 
       
  1538 /**
       
  1539  * Returns focusability of the corresponding Java Window object
       
  1540  */
       
  1541 Boolean
       
  1542 isFocusableWindow(Window w) {
       
  1543     Widget wid = NULL;
       
  1544     JNIEnv *env = (JNIEnv *) JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
  1545 
       
  1546     wid = XtWindowToWidget(awt_display, w);
       
  1547     while (wid != NULL && !XtIsShell(wid)) {
       
  1548         wid = XtParent(wid);
       
  1549     }
       
  1550 
       
  1551     // If the window doesn't have shell consider it focusable as all windows
       
  1552     // are focusable by default
       
  1553     if (wid == NULL) return True;
       
  1554 
       
  1555     return isFocusableWindowByShell(env, wid);
       
  1556 }
       
  1557 
       
  1558 void postUngrabEvent(Widget shell) {
       
  1559     JNIEnv *env = (JNIEnv *) JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
  1560     Widget canvas = findTopLevelByShell(shell);
       
  1561     if (canvas != NULL) {
       
  1562         jobject peer = findPeer(&canvas);
       
  1563         if (peer != NULL) {
       
  1564             JNU_CallMethodByName(env, NULL, peer, "postUngrabEvent", "()V", NULL);
       
  1565         }
       
  1566     }
       
  1567 }
       
  1568 
       
  1569 Boolean eventInsideGrabbed(XEvent * ev) {
       
  1570     if (grabbed_widget == NULL) {
       
  1571         return False;
       
  1572     }
       
  1573 
       
  1574     switch (ev->xany.type) {
       
  1575       case LeaveNotify:
       
  1576       case ButtonPress:
       
  1577       case ButtonRelease:
       
  1578       case MotionNotify:
       
  1579       case EnterNotify:
       
  1580       {
       
  1581           JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
  1582           Widget grab = findTopLevelByShell(grabbed_widget);
       
  1583           if (grab != NULL) {
       
  1584               jobject peer = findPeer(&grab);
       
  1585               Widget target = XtWindowToWidget(awt_display, ev->xbutton.window);
       
  1586               jobject targetPeer = findPeer(&target);
       
  1587               if (peer != NULL) {
       
  1588                   return JNU_CallMethodByName(env, NULL, peer, "processUngrabMouseEvent", "(Lsun/awt/motif/MComponentPeer;III)Z",
       
  1589                                               targetPeer, ev->xbutton.x_root, ev->xbutton.y_root,
       
  1590                                               ev->xany.type, NULL).z;
       
  1591               }
       
  1592           }
       
  1593           return False;
       
  1594       }
       
  1595       case FocusOut:
       
  1596           if (ev->xfocus.window == XtWindow(grabbed_widget) ||
       
  1597               isAncestor(XtWindow(grabbed_widget), ev->xfocus.window))
       
  1598           {
       
  1599               postUngrabEvent(grabbed_widget);
       
  1600               return True;
       
  1601           }
       
  1602       default:
       
  1603           return True;
       
  1604     }
       
  1605 }
       
  1606 
       
  1607 /**
       
  1608  * Processes and removes one X/Xt event from the Xt event queue.
       
  1609  * Handles events pushed back via awt_put_back_event() FIRST,
       
  1610  * then new events on the X queue
       
  1611  */
       
  1612 static void
       
  1613 processOneEvent(XtInputMask iMask) {
       
  1614             XEvent xev;
       
  1615             Boolean haveEvent = False;
       
  1616             if (putbackQueueCount > 0) {
       
  1617                 // There is a pushed-back event - handle it first
       
  1618                 if (awt_get_next_put_back_event(&xev) == 0) {
       
  1619                     if (xev.xany.send_event != SPECIAL_KEY_EVENT) {
       
  1620 #ifdef DEBUG_FOCUS
       
  1621                         if (xev.type == FocusOut) {
       
  1622                             printf("putback FocusOut on window %d, mode %d, "
       
  1623                                    "detail %d, send_event  %d\n",
       
  1624                                    xev.xfocus.window, xev.xfocus.mode,
       
  1625                                    xev.xfocus.detail, xev.xfocus.send_event);
       
  1626                         }
       
  1627 #endif
       
  1628                         eventNumber++;
       
  1629                         XtDispatchEvent(&xev);
       
  1630                         return;
       
  1631                     } else {
       
  1632                         haveEvent = True;
       
  1633                     }
       
  1634                 }
       
  1635             }
       
  1636 
       
  1637             if (haveEvent || XtAppPeekEvent(awt_appContext, &xev)) {
       
  1638              /*
       
  1639               * Fix for BugTraq ID 4041235, 4100167:
       
  1640               * First check that the event still has a widget, because
       
  1641               * the widget may have been destroyed by another thread.
       
  1642               */
       
  1643               Widget widget=XtWindowToWidget(awt_display, xev.xany.window);
       
  1644               eventNumber++;
       
  1645 #ifdef __linux__
       
  1646               statusWindowEventHandler(xev);
       
  1647 #endif
       
  1648               xembed_eventHandler(&xev);
       
  1649               xembed_serverEventHandler(&xev);
       
  1650               syncWait_eventHandler(&xev);
       
  1651 
       
  1652               if (!haveEvent && awt_dnd_process_event(&xev)) {
       
  1653                   return;
       
  1654               }
       
  1655 
       
  1656               if ((widget == NULL) || (!XtIsObject(widget)) ||
       
  1657                   (widget->core.being_destroyed)) {
       
  1658                 /*
       
  1659                  * if we get here, the event could be one of
       
  1660                  * the following:
       
  1661                  * - notification that a "container" of
       
  1662                  *    any of our embedded frame has been moved
       
  1663                  * - event understandable by XFilterEvent
       
  1664                  * - for one of our old widget which has gone away
       
  1665                  */
       
  1666                 XNextEvent(awt_display, &xev);
       
  1667 
       
  1668                 if (widget == NULL) {
       
  1669                     /* an embedded frame container has been moved? */
       
  1670                     if (awt_util_processEventForEmbeddedFrame(&xev)) {
       
  1671                         return;
       
  1672                     }
       
  1673 
       
  1674                     /* manager selections related event? */
       
  1675                     if (awt_mgrsel_processEvent(&xev)) {
       
  1676                         return;
       
  1677                     }
       
  1678                 }
       
  1679 
       
  1680                 /*
       
  1681                  * Fix for BugTraq ID 4196573:
       
  1682                  * Call XFilterEvent() to give a chance to X Input
       
  1683                  * Method to process this event before being
       
  1684                  * discarded.
       
  1685                  */
       
  1686                 (void) XFilterEvent(&xev, NULL);
       
  1687                 return;
       
  1688               }
       
  1689 
       
  1690               /* There is an X event on the queue. */
       
  1691               switch (xev.type) {
       
  1692               case KeyPress:
       
  1693               case KeyRelease:
       
  1694               case ButtonPress:
       
  1695               case ButtonRelease:
       
  1696               case MotionNotify:
       
  1697               case EnterNotify:
       
  1698               case LeaveNotify:
       
  1699                 /* Fix for BugTraq ID 4048060. Dispatch scrolling events
       
  1700                    immediately to the ScrollBar widget to prevent spurious
       
  1701                    continuous scrolling. Otherwise, if the application is busy,
       
  1702                    the ButtonRelease event is not dispatched in time to prevent
       
  1703                    a ScrollBar timeout from expiring, and restarting the
       
  1704                    continuous scrolling timer.
       
  1705                    */
       
  1706                   if ((xev.type == ButtonPress                          ||
       
  1707                        xev.type == ButtonRelease                                ||
       
  1708                        (xev.type == MotionNotify                                &&
       
  1709                         (xev.xmotion.state == Button1Mask                       ||
       
  1710                          xev.xmotion.state == Button2Mask                       ||
       
  1711                          xev.xmotion.state == Button3Mask)))            &&
       
  1712                       (XtIsSubclass(widget, xmScrollBarWidgetClass))) {
       
  1713                       /* Use XNextEvent instead of XtAppNextEvent, because
       
  1714                          XtAppNextEvent processes timers before getting the next X
       
  1715                          event, causing a race condition, since the TimerEvent
       
  1716                          callback in the ScrollBar widget restarts the continuous
       
  1717                          scrolling timer.
       
  1718                       */
       
  1719                       XNextEvent(awt_display, &xev);
       
  1720 
       
  1721                       XtDispatchEvent(&xev);
       
  1722                       XSync(awt_display, False);
       
  1723 
       
  1724                       // This is the event on scrollbar.  Key, Motion,
       
  1725                       // Enter/Leave dispatch as usual, Button should
       
  1726                       // generate Ungrab after Java mouse event
       
  1727                       if (xev.type == ButtonPress && grabbed_widget != NULL) {
       
  1728                           eventInsideGrabbed(&xev);
       
  1729                       }
       
  1730                   }
       
  1731                   else {
       
  1732                       if (!haveEvent) XtAppNextEvent(awt_appContext, &xev);
       
  1733 
       
  1734                       // This is an event on one of our widgets.  Key,
       
  1735                       // Motion, Enter/Leave dispatch as usual, Button
       
  1736                       // should generate Ungrab after Java mouse event
       
  1737 /*                       if (grabbed_widget != NULL && !eventInsideGrabbed(&xev)) { */
       
  1738 /*                           return; */
       
  1739 /*                       } */
       
  1740 
       
  1741                       if (xev.type == ButtonPress) {
       
  1742                           Window window = findShellByProxy(xev.xbutton.window);
       
  1743                           if (window != None) {
       
  1744                               XWindowAttributes winAttr;
       
  1745                               memset(&winAttr, 0, sizeof(XWindowAttributes));
       
  1746                               XGetWindowAttributes(awt_display, window, &winAttr);
       
  1747                               if (winAttr.override_redirect == TRUE && isFocusableWindow(window)) {
       
  1748                                   XSetInputFocus(awt_display, window, RevertToPointerRoot, CurrentTime);
       
  1749                               }
       
  1750                           }
       
  1751                       }
       
  1752                       if(xev.type == KeyPress) {
       
  1753 #ifdef DEBUG_FOCUS
       
  1754                           printf("KeyPress on window %d\n", xev.xany.window);
       
  1755 #endif
       
  1756                       }
       
  1757 
       
  1758                     /* this could be moved to shouldDispatchToWidget */
       
  1759                     /* if there is a proxy in effect, dispatch key events
       
  1760                        through the proxy */
       
  1761                     if ((xev.type == KeyPress || xev.type == KeyRelease) &&
       
  1762                         !keyboardGrabbed && !haveEvent) {
       
  1763                         if (focusProxyWindow != None) {
       
  1764                             Widget widget;
       
  1765                             struct WidgetInfo *winfo;
       
  1766                             Boolean cont;
       
  1767                             /* Key event should be posted to the top-level
       
  1768                                widget of the proxy */
       
  1769                             xev.xany.window = proxyTopLevel(focusProxyWindow);
       
  1770                             widget = XtWindowToWidget(awt_display,
       
  1771                                                       xev.xany.window);
       
  1772                             if (widget == NULL) return;
       
  1773                             if ((winfo = findWidgetInfo(widget)) == NULL) {
       
  1774                                 return;
       
  1775                             }
       
  1776                             awt_canvas_handleEvent(widget, winfo->peer, &xev,
       
  1777                                                    winfo, &cont, TRUE);
       
  1778                             return;
       
  1779                         }
       
  1780                     }
       
  1781                     if (!shouldDispatchToWidget(&xev)) {
       
  1782                         XtDispatchEvent(&xev);
       
  1783                     }
       
  1784 
       
  1785                     // See comment above - "after time" is here.
       
  1786                     if (grabbed_widget != NULL && xev.type == ButtonPress) {
       
  1787                         eventInsideGrabbed(&xev);
       
  1788                     }
       
  1789                 }
       
  1790 
       
  1791 
       
  1792               break;
       
  1793 
       
  1794               case FocusIn:
       
  1795               case FocusOut: {
       
  1796                   void *peer;
       
  1797                   jobject target;
       
  1798 
       
  1799                   JNIEnv *env = (JNIEnv *) JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
  1800 
       
  1801 #ifdef DEBUG_FOCUS
       
  1802                   if (xev.type == FocusIn) {
       
  1803 
       
  1804                       fprintf(stderr, "FocusIn on window %x, mode %d, detail %d, "
       
  1805                              "send_event %d\n", xev.xfocus.window,
       
  1806                              xev.xfocus.mode, xev.xfocus.detail,
       
  1807                              xev.xfocus.send_event);
       
  1808                   } else {
       
  1809                       fprintf(stderr, "FocusOut on window %x, mode %d, detail %d, "
       
  1810                              "send_event %d\n", xev.xfocus.window,
       
  1811                              xev.xfocus.mode, xev.xfocus.detail,
       
  1812                              xev.xfocus.send_event);
       
  1813                   }
       
  1814 #endif
       
  1815                   XtAppNextEvent(awt_appContext, &xev);
       
  1816 
       
  1817                   if (xev.xfocus.detail == NotifyVirtual ||
       
  1818                       xev.xfocus.detail == NotifyNonlinearVirtual) {
       
  1819 #ifdef DEBUG_FOCUS
       
  1820                       printf("discarding\n");
       
  1821 #endif
       
  1822                       return;
       
  1823                   }
       
  1824 
       
  1825                   // Check for xembed on this window. If it is active and this is not XEmbed focus
       
  1826                   // event(send_event = 0) then we should skip it
       
  1827                   if (isXEmbedActiveByWindow(xev.xfocus.window) && !xev.xfocus.send_event) {
       
  1828                       return;
       
  1829                   }
       
  1830 
       
  1831                   /* In general, we need to to block out focus events
       
  1832                      that are caused by keybaord grabs initiated by
       
  1833                      dragging the title bar or the scrollbar. But we
       
  1834                      need to let through the ones that are aimed at
       
  1835                      choice boxes or menus. So we keep track of when
       
  1836                      the keyboard is grabbed by a popup. */
       
  1837 
       
  1838                   if (awt_isAwtMenuWidget(widget)) {
       
  1839                     if (xev.type == FocusIn &&
       
  1840                         xev.xfocus.mode == NotifyGrab) {
       
  1841                           extern Boolean poppingDown;
       
  1842                           if (!poppingDown) {
       
  1843                       keyboardGrabbed = True;
       
  1844                            }
       
  1845                       } else /* FocusOut */ {
       
  1846                           if (xev.type == FocusOut &&
       
  1847                               xev.xfocus.mode == NotifyUngrab) {
       
  1848                         keyboardGrabbed = False;
       
  1849                       }
       
  1850                     }
       
  1851                   }
       
  1852 
       
  1853                   if (focusProxyWindow != None) {
       
  1854 #ifdef DEBUG_FOCUS
       
  1855                       printf("non-null proxy; proxy = %d ", focusProxyWindow);
       
  1856 #endif
       
  1857                       if (trueFocusWindow != None) {
       
  1858                         /* trueFocusWindow should never be None here, but if
       
  1859                            things ever get skewed, we want to be able to
       
  1860                            recover rather than crash */
       
  1861                         focusEventForProxy(xev, env, &trueFocusWindow,
       
  1862                                            &focusProxyWindow);
       
  1863                       return;
       
  1864                       } else {
       
  1865                         /* beartrap -- remove before shipping */
       
  1866                         /* printf("trueFocusWindow None in processOneEvent;\n"); */
       
  1867                         /* printf("Please file a bug\n"); */
       
  1868                       }
       
  1869                   }
       
  1870 
       
  1871                   peer = findPeer(&widget);
       
  1872                   if (peer == NULL) {
       
  1873 #ifdef DEBUG_FOCUS
       
  1874                       printf("null peer -- shouldn't see in java handler\n");
       
  1875 #endif
       
  1876                       XtDispatchEvent(&xev);
       
  1877                       return;
       
  1878                   }
       
  1879 
       
  1880                   /* Find the top-level component */
       
  1881 
       
  1882                   if ((*env)->EnsureLocalCapacity(env, 1) < 0) {
       
  1883                     return;
       
  1884                   }
       
  1885                   target = findTopLevel(peer, env);
       
  1886                   if (target == NULL) {
       
  1887                       JNU_ThrowNullPointerException(env, "component without a "
       
  1888                                                     "window");
       
  1889                       return;
       
  1890                   }
       
  1891 
       
  1892                   if (isFrameOrDialog(target, env)) {
       
  1893 #ifdef DEBUG_FOCUS
       
  1894                       printf("Focus event directed at a frame; frame = %d\n",
       
  1895                              xev.xany.window);
       
  1896 #endif
       
  1897                       focusEventForFrame(xev, focusProxyWindow);
       
  1898                       (*env)->DeleteLocalRef(env, target);
       
  1899                       return;
       
  1900                   } else {
       
  1901 #ifdef DEBUG_FOCUS
       
  1902                       printf("Focus event directed at a window; window = %d\n",
       
  1903                              xev.xany.window);
       
  1904 #endif
       
  1905                       focusEventForWindow(xev, env, &trueFocusWindow,
       
  1906                                           &focusProxyWindow, target);
       
  1907                       (*env)->DeleteLocalRef(env, target);
       
  1908                       return;
       
  1909                   }
       
  1910               }
       
  1911 
       
  1912               case UnmapNotify:
       
  1913 #ifdef DEBUG_FOCUS
       
  1914                 printf("Unmap on window %d\n", xev.xany.window);
       
  1915                 printf("True focus window is %d\n", trueFocusWindow);
       
  1916 #endif
       
  1917                 clearFocusPathOnWindow(xev.xunmap.window);
       
  1918 
       
  1919               default:
       
  1920                 XtAppProcessEvent(awt_appContext, iMask);
       
  1921                 break;
       
  1922               }
       
  1923             }
       
  1924             else {
       
  1925               /* There must be a timer, alternate input, or signal event. */
       
  1926               XtAppProcessEvent(awt_appContext, iMask & ~XtIMXEvent);
       
  1927             }
       
  1928 
       
  1929 } /* processOneEvent() */
       
  1930 
       
  1931 /*
       
  1932  * Waits for X/Xt events to appear on the pipe. Returns only when
       
  1933  * it is likely (but not definite) that there are events waiting to
       
  1934  * be processed.
       
  1935  *
       
  1936  * This routine also flushes the outgoing X queue, when the
       
  1937  * awt_next_flush_time has been reached.
       
  1938  *
       
  1939  * If fdAWTPipe is greater or equal than zero the routine also
       
  1940  * checks if there are events pending on the putback queue.
       
  1941  */
       
  1942 void
       
  1943 waitForEvents(JNIEnv *env, int32_t fdXPipe, int32_t fdAWTPipe) {
       
  1944 
       
  1945         while ((fdAWTPipe >= 0 && awt_events_pending(awt_appContext) == 0) ||
       
  1946                (fdAWTPipe <  0 && XtAppPending(awt_appContext) == 0)) {
       
  1947 #ifdef USE_SELECT
       
  1948             performSelect(env,fdXPipe,fdAWTPipe);
       
  1949 #else
       
  1950             performPoll(env,fdXPipe,fdAWTPipe);
       
  1951 #endif
       
  1952             if ((awt_next_flush_time > 0) &&
       
  1953                 (awtJNI_TimeMillis() > awt_next_flush_time)) {
       
  1954                 AWT_FLUSHOUTPUT_NOW();
       
  1955             }
       
  1956         }  /* end while awt_events_pending() == 0 */
       
  1957 } /* waitForEvents() */
       
  1958 
       
  1959 /*************************************************************************
       
  1960  **                                                                     **
       
  1961  ** WE USE EITHER select() OR poll(), DEPENDING ON THE USE_SELECT       **
       
  1962  ** COMPILE-TIME CONSTANT.                                              **
       
  1963  **                                                                     **
       
  1964  *************************************************************************/
       
  1965 
       
  1966 #ifdef USE_SELECT
       
  1967 
       
  1968 static struct fd_set rdset;
       
  1969 struct timeval sel_time;
       
  1970 
       
  1971 /*
       
  1972  * Performs select() on both the X pipe and our AWT utility pipe.
       
  1973  * Returns when data arrives or the operation times out.
       
  1974  *
       
  1975  * Not all Xt events come across the X pipe (e.g., timers
       
  1976  * and alternate inputs), so we must time out every now and
       
  1977  * then to check the Xt event queue.
       
  1978  *
       
  1979  * The fdAWTPipe will be empty when this returns.
       
  1980  */
       
  1981 static void
       
  1982 performSelect(JNIEnv *env, int32_t fdXPipe, int32_t fdAWTPipe) {
       
  1983 
       
  1984             int32_t result;
       
  1985             int32_t count;
       
  1986             int32_t nfds = 1;
       
  1987             uint32_t timeout = awt_get_poll_timeout(False);
       
  1988 
       
  1989             /* Fixed 4250354 7/28/99 ssi@sparc.spb.su
       
  1990              * Cleaning up Global Refs in case of No Events
       
  1991              */
       
  1992             awtJNI_CleanupGlobalRefs();
       
  1993 
       
  1994             FD_ZERO( &rdset );
       
  1995             FD_SET(fdXPipe, &rdset);
       
  1996             if (fdAWTPipe >= 0) {
       
  1997                 nfds++;
       
  1998                 FD_SET(fdAWTPipe, &rdset);
       
  1999             }
       
  2000             if (timeout == 0) {
       
  2001                 // be sure other threads get a chance
       
  2002                 awtJNI_ThreadYield(env);
       
  2003             }
       
  2004             // set the appropriate time values. The DASSERT() in
       
  2005             // MToolkit_run() makes sure that this will not overflow
       
  2006             sel_time.tv_sec = (timeout * 1000) / (1000 * 1000);
       
  2007             sel_time.tv_usec = (timeout * 1000) % (1000 * 1000);
       
  2008             AWT_NOFLUSH_UNLOCK();
       
  2009             result = select(nfds, &rdset, 0, 0, &sel_time);
       
  2010             AWT_LOCK();
       
  2011 
       
  2012             /* reset tick if this was not a time out */
       
  2013             if (result == 0) {
       
  2014                 /* select() timed out -- update timeout value */
       
  2015                 awt_get_poll_timeout(True);
       
  2016             }
       
  2017             if (fdAWTPipe >= 0 && FD_ISSET ( fdAWTPipe, &rdset ) )
       
  2018             {
       
  2019                 /* There is data on the AWT pipe - empty it */
       
  2020                 do {
       
  2021                     count = read(fdAWTPipe, read_buf, AWT_POLL_BUFSIZE );
       
  2022                 } while (count == AWT_POLL_BUFSIZE );
       
  2023             }
       
  2024 } /* performSelect() */
       
  2025 
       
  2026 #else /* !USE_SELECT */
       
  2027 
       
  2028 /*
       
  2029  * Polls both the X pipe and our AWT utility pipe. Returns
       
  2030  * when there is data on one of the pipes, or the operation times
       
  2031  * out.
       
  2032  *
       
  2033  * Not all Xt events come across the X pipe (e.g., timers
       
  2034  * and alternate inputs), so we must time out every now and
       
  2035  * then to check the Xt event queue.
       
  2036  *
       
  2037  * The fdAWTPipe will be empty when this returns.
       
  2038  */
       
  2039 static void
       
  2040 performPoll(JNIEnv *env, int32_t fdXPipe, int32_t fdAWTPipe) {
       
  2041 
       
  2042             static struct pollfd pollFds[2];
       
  2043             uint32_t timeout = awt_get_poll_timeout(False);
       
  2044             int32_t result;
       
  2045             int32_t count;
       
  2046 
       
  2047             /* Fixed 4250354 7/28/99 ssi@sparc.spb.su
       
  2048              * Cleaning up Global Refs in case of No Events
       
  2049              */
       
  2050             awtJNI_CleanupGlobalRefs();
       
  2051 
       
  2052             pollFds[0].fd = fdXPipe;
       
  2053             pollFds[0].events = POLLRDNORM;
       
  2054             pollFds[0].revents = 0;
       
  2055 
       
  2056             pollFds[1].fd = fdAWTPipe;
       
  2057             pollFds[1].events = POLLRDNORM;
       
  2058             pollFds[1].revents = 0;
       
  2059 
       
  2060             AWT_NOFLUSH_UNLOCK();
       
  2061 
       
  2062             /* print the poll timeout time in brackets */
       
  2063             DTRACE_PRINT1("[%dms]",(int32_t)timeout);
       
  2064 #ifdef DEBUG
       
  2065             if (++debugPrintLineCount > 8) {
       
  2066                 DTRACE_PRINTLN("");
       
  2067                 debugPrintLineCount = 0;
       
  2068             }
       
  2069 #endif
       
  2070             /* ACTUALLY DO THE POLL() */
       
  2071             if (timeout == 0) {
       
  2072                 // be sure other threads get a chance
       
  2073                 awtJNI_ThreadYield(env);
       
  2074             }
       
  2075             result = poll( pollFds, 2, (int32_t) timeout );
       
  2076 
       
  2077 #ifdef DEBUG
       
  2078             DTRACE_PRINT1("[poll()->%d]", result);
       
  2079             if (++debugPrintLineCount > 8) {
       
  2080                 DTRACE_PRINTLN("");
       
  2081                 debugPrintLineCount = 0;
       
  2082             }
       
  2083 #endif
       
  2084             AWT_LOCK();
       
  2085             if (result == 0) {
       
  2086                 /* poll() timed out -- update timeout value */
       
  2087                 awt_get_poll_timeout(True);
       
  2088             }
       
  2089             if ( pollFds[1].revents )
       
  2090             {
       
  2091                 /* There is data on the AWT pipe - empty it */
       
  2092                 do {
       
  2093                     count = read(AWT_READPIPE, read_buf, AWT_POLL_BUFSIZE );
       
  2094                 } while (count == AWT_POLL_BUFSIZE );
       
  2095                 DTRACE_PRINTLN1("wokeup on AWTPIPE, timeout:%d", timeout);
       
  2096             }
       
  2097             return;
       
  2098 
       
  2099 } /* performPoll() */
       
  2100 
       
  2101 #endif /* !USE_SELECT */
       
  2102 
       
  2103 /*
       
  2104  * Pushes an X event back on the queue to be handled
       
  2105  * later.
       
  2106  *
       
  2107  * Ignores the request if event is NULL
       
  2108  */
       
  2109 void
       
  2110 awt_put_back_event(JNIEnv *env, XEvent *event) {
       
  2111 
       
  2112     Boolean addIt = True;
       
  2113     if (putbackQueueCount >= putbackQueueCapacity) {
       
  2114         /* not enough room - alloc 50% more space */
       
  2115         int32_t newCapacity;
       
  2116         XEvent *newQueue;
       
  2117         newCapacity = putbackQueueCapacity * 3 / 2;
       
  2118         if ((newCapacity - putbackQueueCapacity)
       
  2119                                         < PUTBACK_QUEUE_MIN_INCREMENT) {
       
  2120             /* always increase by at least min increment */
       
  2121             newCapacity = putbackQueueCapacity + PUTBACK_QUEUE_MIN_INCREMENT;
       
  2122         }
       
  2123         newQueue = (XEvent*)realloc(
       
  2124                         putbackQueue, newCapacity*(sizeof(XEvent)));
       
  2125         if (newQueue == NULL) {
       
  2126             JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError");
       
  2127             addIt = False;
       
  2128         } else {
       
  2129             putbackQueue = newQueue;
       
  2130             putbackQueueCapacity = newCapacity;
       
  2131         }
       
  2132     }
       
  2133     if (addIt) {
       
  2134         char oneChar = 'p';
       
  2135         memcpy(&(putbackQueue[putbackQueueCount]), event, sizeof(XEvent));
       
  2136         putbackQueueCount++;
       
  2137 
       
  2138         // wake up the event loop, if it's sleeping
       
  2139         write (AWT_WRITEPIPE, &oneChar, 1);
       
  2140     }
       
  2141 
       
  2142     return;
       
  2143 } /* awt_put_back_event() */
       
  2144 
       
  2145 /*
       
  2146  * Gets the next event that has been pushed back onto the queue.
       
  2147  * Returns 0 and fills in xev_out if successful
       
  2148  */
       
  2149 static int32_t
       
  2150 awt_get_next_put_back_event(XEvent *xev_out) {
       
  2151 
       
  2152     Boolean err = False;
       
  2153     if (putbackQueueCount < 1) {
       
  2154         err = True;
       
  2155     } else {
       
  2156         memcpy(xev_out, &(putbackQueue[0]), sizeof(XEvent));
       
  2157     }
       
  2158     if (!err) {
       
  2159         /* remove it from the queue */
       
  2160         if (putbackQueueCount == 1) {
       
  2161 
       
  2162             // queue is now empty
       
  2163             if (putbackQueueCapacity > PUTBACK_QUEUE_MIN_INCREMENT) {
       
  2164 
       
  2165                 /* Too much space -- delete it and rebuild later */
       
  2166                 free(putbackQueue);
       
  2167                 putbackQueue = NULL;
       
  2168                 putbackQueueCapacity = 0;
       
  2169             }
       
  2170         } else {
       
  2171             /* more than 1 event in queue - shift all events to the left */
       
  2172             /* We don't free the allocated memory until the queue
       
  2173                becomes empty, just 'cause it's easier that way. */
       
  2174             /* NOTE: use memmove(), because the memory blocks overlap */
       
  2175             memmove(&(putbackQueue[0]), &(putbackQueue[1]),
       
  2176                 (putbackQueueCount-1)*sizeof(XEvent));
       
  2177         }
       
  2178         --putbackQueueCount;
       
  2179     }
       
  2180     DASSERT(putbackQueueCount >= 0);
       
  2181 
       
  2182     return (err? -1:0);
       
  2183 
       
  2184 } /* awt_get_next_put_back_event() */
       
  2185 
       
  2186 /**
       
  2187  * Determines whether or not there are X or Xt events pending.
       
  2188  * Looks at the putbackQueue.
       
  2189  */
       
  2190 static XtInputMask
       
  2191 awt_events_pending(XtAppContext appContext) {
       
  2192     XtInputMask imask = 0L;
       
  2193     imask = XtAppPending(appContext);
       
  2194     if (putbackQueueCount > 0) {
       
  2195         imask |= XtIMXEvent;
       
  2196     }
       
  2197     return imask;
       
  2198 }
       
  2199 
       
  2200 
       
  2201 #ifndef NOMODALFIX
       
  2202 #define WIDGET_ARRAY_SIZE 5;
       
  2203 static int32_t arraySize = 0;
       
  2204 static int32_t arrayIndx = 0;
       
  2205 static Widget *dShells = NULL;
       
  2206 
       
  2207 void
       
  2208 awt_shellPoppedUp(Widget shell,
       
  2209                    XtPointer modal,
       
  2210                    XtPointer call_data)
       
  2211 {
       
  2212     if (arrayIndx == arraySize ) {
       
  2213         /* if we have not allocate an array, do it first */
       
  2214         if (arraySize == 0) {
       
  2215             arraySize += WIDGET_ARRAY_SIZE;
       
  2216             dShells = (Widget *) malloc(sizeof(Widget) * arraySize);
       
  2217         } else {
       
  2218             arraySize += WIDGET_ARRAY_SIZE;
       
  2219             dShells = (Widget *) realloc((void *)dShells, sizeof(Widget) * arraySize);
       
  2220         }
       
  2221     }
       
  2222 
       
  2223     dShells[arrayIndx] = shell;
       
  2224     arrayIndx++;
       
  2225 }
       
  2226 
       
  2227 void
       
  2228 awt_shellPoppedDown(Widget shell,
       
  2229                    XtPointer modal,
       
  2230                    XtPointer call_data)
       
  2231 {
       
  2232     arrayIndx--;
       
  2233 
       
  2234     if (dShells[arrayIndx] == shell) {
       
  2235         dShells[arrayIndx] = NULL;
       
  2236         return;
       
  2237     } else {
       
  2238         int32_t i;
       
  2239 
       
  2240         /* find the position of the shell in the array */
       
  2241         for (i = arrayIndx; i >= 0; i--) {
       
  2242             if (dShells[i] == shell) {
       
  2243                 break;
       
  2244             }
       
  2245         }
       
  2246 
       
  2247         /* remove the found element */
       
  2248         while (i <= arrayIndx-1) {
       
  2249             dShells[i] = dShells[i+1];
       
  2250             i++;
       
  2251         }
       
  2252     }
       
  2253 }
       
  2254 
       
  2255 Boolean
       
  2256 awt_isWidgetModal(Widget widget)
       
  2257 {
       
  2258     Widget w;
       
  2259 
       
  2260     for (w = widget; !XtIsShell(w); w = XtParent(w)) { }
       
  2261 
       
  2262     while (w != NULL) {
       
  2263         if (w == dShells[arrayIndx-1]) {
       
  2264             return True;
       
  2265         }
       
  2266         w = XtParent(w);
       
  2267     }
       
  2268     return False;
       
  2269 }
       
  2270 
       
  2271 Boolean
       
  2272 awt_isModal()
       
  2273 {
       
  2274     return (arrayIndx > 0);
       
  2275 }
       
  2276 #endif // NOMODALFIX
       
  2277 
       
  2278 
       
  2279 /*
       
  2280  * Simply waits for terminateFn() to return True. Waits on the
       
  2281  * awt lock and is notified to check its state by the main event
       
  2282  * loop whenever the Xt event queue is empty.
       
  2283  *
       
  2284  * NOTE: when you use this routine check if it can be called on the event
       
  2285  * dispatch thread during drag-n-drop operation and update
       
  2286  * secondary_loop_event() predicate to prevent deadlock.
       
  2287  */
       
  2288 void
       
  2289 awt_MToolkit_modalWait(int32_t (*terminateFn) (void *data), void *data )
       
  2290 {
       
  2291     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
  2292 
       
  2293     AWT_LOCK();
       
  2294     AWT_FLUSHOUTPUT_NOW();
       
  2295     while ((*terminateFn) (data) == 0) {
       
  2296         AWT_WAIT(AWT_MAX_POLL_TIMEOUT);
       
  2297         if ((*env)->ExceptionCheck(env)) {
       
  2298             (*env)->ExceptionClear(env);
       
  2299             break;
       
  2300         }
       
  2301     }
       
  2302     AWT_NOTIFY_ALL();
       
  2303     AWT_UNLOCK();
       
  2304 }
       
  2305 
       
  2306 static uint32_t
       
  2307 colorToRGB(XColor * color)
       
  2308 {
       
  2309     int32_t rgb = 0;
       
  2310 
       
  2311     rgb |= ((color->red >> 8) << 16);
       
  2312     rgb |= ((color->green >> 8) << 8);
       
  2313     rgb |= ((color->blue >> 8) << 0);
       
  2314 
       
  2315     return rgb;
       
  2316 }
       
  2317 
       
  2318 /*
       
  2319  * fix for bug #4088106 - ugly text boxes and grayed out looking text
       
  2320  */
       
  2321 
       
  2322 XmColorProc oldColorProc;
       
  2323 
       
  2324 void
       
  2325 ColorProc(XColor* bg_color,
       
  2326           XColor* fg_color,
       
  2327           XColor* sel_color,
       
  2328           XColor* ts_color,
       
  2329           XColor* bs_color)
       
  2330 {
       
  2331     unsigned long plane_masks[1];
       
  2332     unsigned long colors[5];
       
  2333 
       
  2334     AwtGraphicsConfigDataPtr defaultConfig =
       
  2335         getDefaultConfig(DefaultScreen(awt_display));
       
  2336 
       
  2337     /* use the default procedure to calculate colors */
       
  2338     oldColorProc(bg_color, fg_color, sel_color, ts_color, bs_color);
       
  2339 
       
  2340     /* check if there is enought free color cells */
       
  2341     if (XAllocColorCells(awt_display, defaultConfig->awt_cmap, False,
       
  2342         plane_masks, 0, colors, 5)) {
       
  2343         XFreeColors(awt_display, defaultConfig->awt_cmap, colors, 5, 0);
       
  2344         return;
       
  2345     }
       
  2346 
       
  2347     /* find the closest matches currently available */
       
  2348     fg_color->pixel = defaultConfig->AwtColorMatch(fg_color->red   >> 8,
       
  2349                                                    fg_color->green >> 8,
       
  2350                                                    fg_color->blue  >> 8,
       
  2351                                                    defaultConfig);
       
  2352     fg_color->flags = DoRed | DoGreen | DoBlue;
       
  2353     XQueryColor(awt_display, defaultConfig->awt_cmap, fg_color);
       
  2354     sel_color->pixel = defaultConfig->AwtColorMatch(sel_color->red   >> 8,
       
  2355                                                     sel_color->green >> 8,
       
  2356                                                     sel_color->blue  >> 8,
       
  2357                                                     defaultConfig);
       
  2358     sel_color->flags = DoRed | DoGreen | DoBlue;
       
  2359     XQueryColor(awt_display, defaultConfig->awt_cmap, sel_color);
       
  2360     ts_color->pixel = defaultConfig->AwtColorMatch(ts_color->red   >> 8,
       
  2361                                                    ts_color->green >> 8,
       
  2362                                                    ts_color->blue  >> 8,
       
  2363                                                    defaultConfig);
       
  2364     ts_color->flags = DoRed | DoGreen | DoBlue;
       
  2365     XQueryColor(awt_display, defaultConfig->awt_cmap, ts_color);
       
  2366     bs_color->pixel = defaultConfig->AwtColorMatch(bs_color->red   >> 8,
       
  2367                                                    bs_color->green >> 8,
       
  2368                                                    bs_color->blue  >> 8,
       
  2369                                                    defaultConfig);
       
  2370     bs_color->flags = DoRed | DoGreen | DoBlue;
       
  2371     XQueryColor(awt_display, defaultConfig->awt_cmap, bs_color);
       
  2372 }
       
  2373 
       
  2374 
       
  2375 /*
       
  2376  * Read _XSETTINGS_SETTINGS property from _XSETTINGS selection owner
       
  2377  * and pass its value to the java world for processing.
       
  2378  */
       
  2379 /*static*/ void
       
  2380 awt_xsettings_update(int scr, Window owner, void *cookie)
       
  2381 {
       
  2382     Display *dpy = awt_display;
       
  2383     int status;
       
  2384 
       
  2385     JNIEnv *env;
       
  2386     jobject mtoolkit;
       
  2387     jmethodID upcall;
       
  2388     jbyteArray array;
       
  2389 
       
  2390     struct xsettings_callback_cookie *upcall_cookie = cookie;
       
  2391 
       
  2392     /* Returns of XGetWindowProperty */
       
  2393     Atom actual_type;
       
  2394     int actual_format;
       
  2395     unsigned long nitems;
       
  2396     unsigned long bytes_after;
       
  2397     unsigned char *xsettings;
       
  2398 
       
  2399     DTRACE_PRINTLN2("XS: update screen %d, owner 0x%08lx",
       
  2400                     scr, owner);
       
  2401 
       
  2402 #if 1 /* XXX: kludge */
       
  2403     /*
       
  2404      * As toolkit cannot yet cope with per-screen desktop properties,
       
  2405      * only report XSETTINGS changes on the default screen.  This
       
  2406      * should be "good enough" for most cases.
       
  2407      */
       
  2408     if (scr != DefaultScreen(dpy)) {
       
  2409         DTRACE_PRINTLN2("XS: XXX: default screen is %d, update is for %d, ignoring", DefaultScreen(dpy), scr);
       
  2410         return;
       
  2411     }
       
  2412 #endif /* kludge */
       
  2413 
       
  2414     env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
  2415     DASSERT(env != NULL);
       
  2416 
       
  2417     DASSERT(upcall_cookie != NULL);
       
  2418     mtoolkit = upcall_cookie->mtoolkit;
       
  2419     upcall = upcall_cookie->upcallMID;
       
  2420 
       
  2421     DASSERT(!JNU_IsNull(env, mtoolkit));
       
  2422     DASSERT(upcall != NULL);
       
  2423 
       
  2424     /*
       
  2425      * XXX: move awt_getPropertyFOO from awt_wm.c to awt_util.c and
       
  2426      * use the appropriate one.
       
  2427      */
       
  2428     status = XGetWindowProperty(dpy, owner,
       
  2429                  _XA_XSETTINGS_SETTINGS, 0, 0xFFFF, False,
       
  2430                  _XA_XSETTINGS_SETTINGS,
       
  2431                  &actual_type, &actual_format, &nitems, &bytes_after,
       
  2432                  &xsettings);
       
  2433 
       
  2434     if (status != Success) {
       
  2435         DTRACE_PRINTLN("XS:   unable to read _XSETTINGS");
       
  2436         return;
       
  2437     }
       
  2438 
       
  2439     if (xsettings == NULL) {
       
  2440         DTRACE_PRINTLN("XS:   reading _XSETTINGS, got NULL");
       
  2441         return;
       
  2442     }
       
  2443 
       
  2444     if (actual_type != _XA_XSETTINGS_SETTINGS) {
       
  2445         XFree(xsettings);       /* NULL data already catched above */
       
  2446         DTRACE_PRINTLN("XS:   _XSETTINGS_SETTINGS is not of type _XSETTINGS_SETTINGS");
       
  2447         return;
       
  2448     }
       
  2449 
       
  2450     DTRACE_PRINTLN1("XS:   read %lu bytes of _XSETTINGS_SETTINGS",
       
  2451                     nitems);
       
  2452 
       
  2453     /* ok, propagate xsettings to the toolkit for processing */
       
  2454     if ((*env)->EnsureLocalCapacity(env, 1) < 0) {
       
  2455         DTRACE_PRINTLN("XS:   EnsureLocalCapacity failed");
       
  2456         XFree(xsettings);
       
  2457         return;
       
  2458     }
       
  2459 
       
  2460     array = (*env)->NewByteArray(env, (jint)nitems);
       
  2461     if (JNU_IsNull(env, array)) {
       
  2462         DTRACE_PRINTLN("awt_xsettings_update: NewByteArray failed");
       
  2463         XFree(xsettings);
       
  2464         return;
       
  2465     }
       
  2466 
       
  2467     (*env)->SetByteArrayRegion(env, array, 0, (jint)nitems,
       
  2468                                (jbyte *)xsettings);
       
  2469     XFree(xsettings);
       
  2470 
       
  2471     (*env)->CallVoidMethod(env, mtoolkit, upcall, (jint)scr, array);
       
  2472     (*env)->DeleteLocalRef(env, array);
       
  2473 }
       
  2474 
       
  2475 
       
  2476 /*
       
  2477  * Event handler for events on XSETTINGS selection owner.
       
  2478  * We are interested in PropertyNotify only.
       
  2479  */
       
  2480 static void
       
  2481 awt_xsettings_callback(int scr, XEvent *xev, void *cookie)
       
  2482 {
       
  2483     Display *dpy = awt_display; /* xev->xany.display */
       
  2484     XPropertyEvent *ev;
       
  2485 
       
  2486     if (xev->type != PropertyNotify) {
       
  2487         DTRACE_PRINTLN2("XS: awt_xsettings_callback(%d) event %d ignored",
       
  2488                         scr, xev->type);
       
  2489         return;
       
  2490     }
       
  2491 
       
  2492     ev = &xev->xproperty;
       
  2493 
       
  2494     if (ev->atom == None) {
       
  2495         DTRACE_PRINTLN("XS: awt_xsettings_callback(%d) atom == None");
       
  2496         return;
       
  2497     }
       
  2498 
       
  2499 #ifdef DEBUG
       
  2500     {
       
  2501         char *name;
       
  2502 
       
  2503         DTRACE_PRINT2("XS: awt_xsettings_callback(%d) 0x%08lx ",
       
  2504                       scr, ev->window);
       
  2505         name = XGetAtomName(dpy, ev->atom);
       
  2506         if (name == NULL) {
       
  2507             DTRACE_PRINT1("atom #%d", ev->atom);
       
  2508         } else {
       
  2509             DTRACE_PRINT1("%s", name);
       
  2510             XFree(name);
       
  2511         }
       
  2512         DTRACE_PRINTLN1(" %s", ev->state == PropertyNewValue ?
       
  2513                                         "changed" : "deleted");
       
  2514     }
       
  2515 #endif
       
  2516 
       
  2517     if (ev->atom != _XA_XSETTINGS_SETTINGS) {
       
  2518         DTRACE_PRINTLN("XS:   property != _XSETTINGS_SETTINGS ...  ignoring");
       
  2519         return;
       
  2520     }
       
  2521 
       
  2522 
       
  2523     if (ev->state == PropertyDelete) {
       
  2524         /* XXX: notify toolkit to reset to "defaults"? */
       
  2525         return;
       
  2526     }
       
  2527 
       
  2528     awt_xsettings_update(scr, ev->window, cookie);
       
  2529 }
       
  2530 
       
  2531 
       
  2532 /*
       
  2533  * Owner of XSETTINGS selection changed on the given screen.
       
  2534  */
       
  2535 static void
       
  2536 awt_xsettings_owner_callback(int scr, Window owner, long *data_unused,
       
  2537                              void *cookie)
       
  2538 {
       
  2539     if (owner == None) {
       
  2540         DTRACE_PRINTLN("XS: awt_xsettings_owner_callback: owner = None");
       
  2541         /* XXX: reset to defaults??? */
       
  2542         return;
       
  2543     }
       
  2544 
       
  2545     DTRACE_PRINTLN1("XS: awt_xsettings_owner_callback: owner = 0x%08lx",
       
  2546                     owner);
       
  2547 
       
  2548     awt_xsettings_update(scr, owner, cookie);
       
  2549 }
       
  2550 
       
  2551 /*
       
  2552  * Returns a reference to the class java.awt.Component.
       
  2553  */
       
  2554 jclass
       
  2555 getComponentClass(JNIEnv *env)
       
  2556 {
       
  2557     static jclass componentCls = NULL;
       
  2558 
       
  2559     // get global reference of java/awt/Component class (run only once)
       
  2560     if (componentCls == NULL) {
       
  2561         jclass componentClsLocal = (*env)->FindClass(env, "java/awt/Component");
       
  2562         DASSERT(componentClsLocal != NULL);
       
  2563         if (componentClsLocal == NULL) {
       
  2564             /* exception already thrown */
       
  2565             return NULL;
       
  2566         }
       
  2567         componentCls = (jclass)(*env)->NewGlobalRef(env, componentClsLocal);
       
  2568         (*env)->DeleteLocalRef(env, componentClsLocal);
       
  2569     }
       
  2570     return componentCls;
       
  2571 }
       
  2572 
       
  2573 
       
  2574 /*
       
  2575  * Returns a reference to the class java.awt.MenuComponent.
       
  2576  */
       
  2577 jclass
       
  2578 getMenuComponentClass(JNIEnv *env)
       
  2579 {
       
  2580     static jclass menuComponentCls = NULL;
       
  2581 
       
  2582     // get global reference of java/awt/MenuComponent class (run only once)
       
  2583     if (menuComponentCls == NULL) {
       
  2584         jclass menuComponentClsLocal = (*env)->FindClass(env, "java/awt/MenuComponent");
       
  2585         DASSERT(menuComponentClsLocal != NULL);
       
  2586         if (menuComponentClsLocal == NULL) {
       
  2587             /* exception already thrown */
       
  2588             return NULL;
       
  2589         }
       
  2590         menuComponentCls = (jclass)(*env)->NewGlobalRef(env, menuComponentClsLocal);
       
  2591         (*env)->DeleteLocalRef(env, menuComponentClsLocal);
       
  2592     }
       
  2593     return menuComponentCls;
       
  2594 }
       
  2595 
       
  2596 /*
       
  2597  * Class:     sun_awt_motif_MToolkit
       
  2598  * Method:    init
       
  2599  * Signature: (Ljava/lang/String;)V
       
  2600  */
       
  2601 JNIEXPORT void JNICALL
       
  2602 Java_sun_awt_motif_MToolkit_init(JNIEnv *env, jobject this,
       
  2603     jstring mainClassName)
       
  2604 {
       
  2605     char *appName = NULL;
       
  2606     char *mainChars = NULL;
       
  2607 
       
  2608     int32_t   argc     = 0;
       
  2609     char *argv[10] = { NULL };
       
  2610 
       
  2611     /*
       
  2612      * Note: The MToolkit object depends on the static initializer
       
  2613      * of X11GraphicsEnvironment to initialize the connection to
       
  2614      * the X11 server.
       
  2615      */
       
  2616     XFontStruct *xfont;
       
  2617     XmFontListEntry tmpFontListEntry;
       
  2618     char *multiclick_time_query;
       
  2619     AwtGraphicsConfigDataPtr defaultConfig =
       
  2620         getDefaultConfig(DefaultScreen(awt_display));
       
  2621     AwtScreenDataPtr defaultScreen =
       
  2622         getScreenData(DefaultScreen(awt_display));
       
  2623 
       
  2624     static String fallback_resources[] =
       
  2625     {
       
  2626         "*enableThinThickness:                   True",
       
  2627         "*XmFileSelectionBox.fileFilterStyle:    XmFILTER_HIDDEN_FILES",
       
  2628         "*XmFileSelectionBox.pathMode:           XmPATH_MODE_RELATIVE",
       
  2629         "*XmFileSelectionBox.resizePolicy:       XmRESIZE_GROW",
       
  2630         "*XmFileSelectionBox*dirTextLabelString:         Enter path or folder name:",
       
  2631         "*XmFileSelectionBox*applyLabelString:           Update",
       
  2632         "*XmFileSelectionBox*selectionLabelString:       Enter file name:",
       
  2633         "*XmFileSelectionBox*dirListLabelString:         Folders",
       
  2634         NULL                        /* Must be NULL terminated */
       
  2635     };
       
  2636 
       
  2637     focusOutEvent.type = FocusOut;
       
  2638     focusOutEvent.xfocus.send_event = True;
       
  2639     focusOutEvent.xfocus.display = awt_display;
       
  2640     focusOutEvent.xfocus.mode = NotifyNormal;
       
  2641     focusOutEvent.xfocus.detail = NotifyNonlinear;
       
  2642 
       
  2643     /* Need to make sure this is deleted someplace! */
       
  2644     AWT_LOCK();
       
  2645 
       
  2646     XSetIOErrorHandler(xIOError);
       
  2647 
       
  2648     if (!XSupportsLocale()) {
       
  2649         jio_fprintf(stderr,
       
  2650                     "current locale is not supported in X11, locale is set to C");
       
  2651         setlocale(LC_ALL, "C");
       
  2652     }
       
  2653     if (!XSetLocaleModifiers("")) {
       
  2654         jio_fprintf(stderr, "X locale modifiers are not supported, using default");
       
  2655     }
       
  2656 #ifdef NETSCAPE
       
  2657     if (awt_init_xt) {
       
  2658         XtToolkitInitialize();
       
  2659     }
       
  2660 #else
       
  2661     XtToolkitInitialize();
       
  2662 #endif
       
  2663 
       
  2664     {
       
  2665         jclass  fontConfigClass;
       
  2666         jmethodID methID;
       
  2667         jstring jFontList;
       
  2668         char       *cFontRsrc;
       
  2669         char       *cFontRsrc2;
       
  2670 
       
  2671         fontConfigClass = (*env)->FindClass(env, "sun/awt/motif/MFontConfiguration");
       
  2672         methID = (*env)->GetStaticMethodID(env, fontConfigClass,
       
  2673                                            "getDefaultMotifFontSet",
       
  2674                                            "()Ljava/lang/String;");
       
  2675         jFontList = (*env)->CallStaticObjectMethod(env, fontConfigClass, methID);
       
  2676         if (jFontList == NULL) {
       
  2677             motifFontList =
       
  2678                 "-monotype-arial-regular-r-normal--*-140-*-*-p-*-iso8859-1";
       
  2679         } else {
       
  2680             motifFontList = JNU_GetStringPlatformChars(env, jFontList, NULL);
       
  2681         }
       
  2682 
       
  2683         /* fprintf(stderr, "motifFontList: %s\n", motifFontList); */
       
  2684 
       
  2685         cFontRsrc = malloc(strlen(motifFontList) + 20);
       
  2686         strcpy(cFontRsrc, "*fontList: ");
       
  2687         strcat(cFontRsrc, motifFontList);
       
  2688         cFontRsrc2 = malloc(strlen(motifFontList) + 20);
       
  2689         strcpy(cFontRsrc2, "*labelFontList: ");
       
  2690         strcat(cFontRsrc2, motifFontList);
       
  2691 
       
  2692         argc = 1;
       
  2693         argv[argc++] = "-xrm";
       
  2694         argv[argc++] = cFontRsrc;
       
  2695         argv[argc++] = "-xrm";
       
  2696         argv[argc++] = cFontRsrc2;
       
  2697         argv[argc++] = "-font";
       
  2698         argv[argc++] = (char *)defaultMotifFont;
       
  2699     }
       
  2700 
       
  2701     awt_appContext = XtCreateApplicationContext();
       
  2702     XtAppSetErrorHandler(awt_appContext, (XtErrorHandler) xtError);
       
  2703     XtAppSetFallbackResources(awt_appContext, fallback_resources);
       
  2704 
       
  2705     appName = NULL;
       
  2706     mainChars = NULL;
       
  2707     if (!JNU_IsNull(env, mainClassName)) {
       
  2708         mainChars = (char *)JNU_GetStringPlatformChars(env, mainClassName, NULL);
       
  2709         appName = mainChars;
       
  2710     }
       
  2711     if (appName == NULL || appName[0] == '\0') {
       
  2712         appName = "AWT";
       
  2713     }
       
  2714 
       
  2715     XtDisplayInitialize(awt_appContext, awt_display,
       
  2716                         appName, /* application name  */
       
  2717                         appName, /* application class */
       
  2718                         NULL, 0, &argc, argv);
       
  2719 
       
  2720     /* Root shell widget that serves as a parent for all AWT top-levels.    */
       
  2721     awt_root_shell = XtVaAppCreateShell(appName, /* application name  */
       
  2722                                         appName, /* application class */
       
  2723                                         applicationShellWidgetClass,
       
  2724                                         awt_display,
       
  2725                                         /* va_list */
       
  2726                                         XmNmappedWhenManaged, False,
       
  2727                                         NULL);
       
  2728     XtRealizeWidget(awt_root_shell);
       
  2729 
       
  2730     if (mainChars != NULL) {
       
  2731         JNU_ReleaseStringPlatformChars(env, mainClassName, mainChars);
       
  2732     }
       
  2733 
       
  2734     awt_mgrsel_init();
       
  2735     awt_wm_init();
       
  2736     init_xembed();
       
  2737 
       
  2738     /*
       
  2739      * Find the correct awt_multiclick_time to use. We normally
       
  2740      * would call XtMultiClickTime() and wouldn't have to do
       
  2741      * anything special, but because OpenWindows defines its own
       
  2742      * version (OpenWindows.MultiClickTimeout), we need to
       
  2743      * determine out which resource to use.
       
  2744      *
       
  2745      * We do this by searching in order for:
       
  2746      *
       
  2747      *   1) an explicit definition of multiClickTime
       
  2748      *      (this is the resource that XtGetMultiClickTime uses)
       
  2749      *
       
  2750      * if that fails, search for:
       
  2751      *
       
  2752      *   2) an explicit definition of Openwindows.MultiClickTimeout
       
  2753      *
       
  2754      * if both searches fail:
       
  2755      *
       
  2756      *   3) use the fallback provided by XtGetMultiClickTime()
       
  2757      *      (which is 200 milliseconds... I looked at the source :-)
       
  2758      *
       
  2759      */
       
  2760     multiclick_time_query = XGetDefault(awt_display, "*", "multiClickTime");
       
  2761     if (multiclick_time_query) {
       
  2762         awt_multiclick_time = XtGetMultiClickTime(awt_display);
       
  2763     } else {
       
  2764         multiclick_time_query = XGetDefault(awt_display,
       
  2765                                             "OpenWindows", "MultiClickTimeout");
       
  2766         if (multiclick_time_query) {
       
  2767             /* Note: OpenWindows.MultiClickTimeout is in tenths of
       
  2768                a second, so we need to multiply by 100 to convert to
       
  2769                milliseconds */
       
  2770             awt_multiclick_time = atoi(multiclick_time_query) * 100;
       
  2771         } else {
       
  2772             awt_multiclick_time = XtGetMultiClickTime(awt_display);
       
  2773         }
       
  2774     }
       
  2775 
       
  2776     scrollBugWorkAround = TRUE;
       
  2777 
       
  2778     /*
       
  2779      * Create the cursor for TextArea scrollbars...
       
  2780      */
       
  2781     awt_scrollCursor = XCreateFontCursor(awt_display, XC_left_ptr);
       
  2782 
       
  2783     awt_defaultBg = defaultConfig->AwtColorMatch(200, 200, 200, defaultConfig);
       
  2784     awt_defaultFg = defaultScreen->blackpixel;
       
  2785     setup_modifier_map(awt_display);
       
  2786 
       
  2787     awt_initialize_DataTransferer();
       
  2788     awt_initialize_Xm_DnD(awt_display);
       
  2789 
       
  2790     /*
       
  2791      * fix for bug #4088106 - ugly text boxes and grayed out looking text
       
  2792      */
       
  2793     oldColorProc = XmGetColorCalculation();
       
  2794     XmSetColorCalculation(ColorProc);
       
  2795 
       
  2796     AWT_UNLOCK();
       
  2797 }
       
  2798 
       
  2799 /*
       
  2800  * Class:     sun_awt_motif_MToolkit
       
  2801  * Method:    run
       
  2802  * Signature: ()V
       
  2803  */
       
  2804 JNIEXPORT void JNICALL Java_sun_awt_motif_MToolkit_run
       
  2805   (JNIEnv *env, jobject this)
       
  2806 {
       
  2807     /*
       
  2808      * in performSelect(), we multiply the timeout by 1000. Make sure
       
  2809      * that the maximum value will not cause an overflow.
       
  2810      */
       
  2811     DASSERT(AWT_MAX_POLL_TIMEOUT <= (ULONG_MAX/1000));
       
  2812 
       
  2813     awt_MainThread = (*env)->NewGlobalRef(env, awtJNI_GetCurrentThread(env));
       
  2814     awt_MToolkit_loop(env); /* never returns */
       
  2815 }
       
  2816 
       
  2817 /*
       
  2818  * Class:     sun_awt_motif_MToolkit
       
  2819  * Method:    makeColorModel
       
  2820  * Signature: ()Ljava/awt/image/ColorModel;
       
  2821  */
       
  2822 JNIEXPORT jobject JNICALL Java_sun_awt_motif_MToolkit_makeColorModel
       
  2823   (JNIEnv *env, jclass this)
       
  2824 {
       
  2825     AwtGraphicsConfigDataPtr defaultConfig =
       
  2826         getDefaultConfig(DefaultScreen(awt_display));
       
  2827 
       
  2828     return awtJNI_GetColorModel(env, defaultConfig);
       
  2829 }
       
  2830 
       
  2831 /*
       
  2832  * Class:     sun_awt_motif_MToolkit
       
  2833  * Method:    getScreenResolution
       
  2834  * Signature: ()I
       
  2835  */
       
  2836 JNIEXPORT jint JNICALL Java_sun_awt_motif_MToolkit_getScreenResolution
       
  2837   (JNIEnv *env, jobject this)
       
  2838 {
       
  2839     return (jint) ((DisplayWidth(awt_display, DefaultScreen(awt_display))
       
  2840                     * 25.4) /
       
  2841                    DisplayWidthMM(awt_display, DefaultScreen(awt_display)));
       
  2842 }
       
  2843 
       
  2844 /*
       
  2845  * Class:     sun_awt_motif_MToolkit
       
  2846  * Method:    getScreenWidth
       
  2847  * Signature: ()I
       
  2848  */
       
  2849 JNIEXPORT jint JNICALL Java_sun_awt_motif_MToolkit_getScreenWidth
       
  2850   (JNIEnv *env, jobject this)
       
  2851 {
       
  2852     return DisplayWidth(awt_display, DefaultScreen(awt_display));
       
  2853 }
       
  2854 /*
       
  2855  * Class:     sun_awt_motif_MToolkit
       
  2856  * Method:    getScreenHeight
       
  2857  * Signature: ()I
       
  2858  */
       
  2859 JNIEXPORT jint JNICALL Java_sun_awt_motif_MToolkit_getScreenHeight
       
  2860   (JNIEnv *env, jobject this)
       
  2861 {
       
  2862     return DisplayHeight(awt_display, DefaultScreen(awt_display));
       
  2863 }
       
  2864 
       
  2865 /*
       
  2866  * Class:     sun_awt_motif_MToolkit
       
  2867  * Method:    beep
       
  2868  * Signature: ()V
       
  2869  */
       
  2870 JNIEXPORT void JNICALL Java_sun_awt_motif_MToolkit_beep
       
  2871   (JNIEnv *env, jobject this)
       
  2872 {
       
  2873     AWT_LOCK();
       
  2874     XBell(awt_display, 0);
       
  2875     AWT_FLUSH_UNLOCK();
       
  2876 }
       
  2877 
       
  2878 /*
       
  2879  * Class:     sun_awt_motif_MToolkit
       
  2880  * Method:    shutdown
       
  2881  * Signature: ()V
       
  2882  */
       
  2883 
       
  2884 JNIEXPORT void JNICALL Java_sun_awt_motif_MToolkit_shutdown
       
  2885   (JNIEnv *env, jobject this)
       
  2886 {
       
  2887     X11SD_LibDispose(env);
       
  2888 }
       
  2889 
       
  2890 /*
       
  2891  * Class:     sun_awt_motif_MToolkit
       
  2892  * Method:    getLockingKeyStateNative
       
  2893  * Signature: (I)B
       
  2894  */
       
  2895 JNIEXPORT jboolean JNICALL Java_sun_awt_motif_MToolkit_getLockingKeyStateNative
       
  2896   (JNIEnv *env, jobject this, jint awtKey)
       
  2897 {
       
  2898     KeySym sym;
       
  2899     KeyCode keyCode;
       
  2900     uint32_t byteIndex;
       
  2901     uint32_t bitIndex;
       
  2902     char keyVector[32];
       
  2903 
       
  2904     AWT_LOCK();
       
  2905 
       
  2906     sym = awt_getX11KeySym(awtKey);
       
  2907     keyCode = XKeysymToKeycode(awt_display, sym);
       
  2908     if (sym == NoSymbol || keyCode == 0) {
       
  2909         JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", "Keyboard doesn't have requested key");
       
  2910         AWT_UNLOCK();
       
  2911         return False;
       
  2912     }
       
  2913 
       
  2914     byteIndex = (keyCode/8);
       
  2915     bitIndex = keyCode & 7;
       
  2916     XQueryKeymap(awt_display, keyVector);
       
  2917 
       
  2918     AWT_UNLOCK();
       
  2919 
       
  2920     return (1 & (keyVector[byteIndex] >> bitIndex));
       
  2921 }
       
  2922 
       
  2923 /*
       
  2924  * Class:     sun_awt_motif_MToolkit
       
  2925  * Method:    loadSystemColors
       
  2926  * Signature: ([I)V
       
  2927  */
       
  2928 JNIEXPORT void JNICALL Java_sun_awt_motif_MToolkit_loadSystemColors
       
  2929   (JNIEnv *env, jobject this, jintArray systemColors)
       
  2930 {
       
  2931     Widget frame, panel, control, menu, text, scrollbar;
       
  2932     Colormap cmap;
       
  2933     Pixel bg, fg, highlight, shadow;
       
  2934     Pixel pixels[java_awt_SystemColor_NUM_COLORS];
       
  2935     XColor *colorsPtr;
       
  2936     jint rgbColors[java_awt_SystemColor_NUM_COLORS];
       
  2937     int32_t count = 0;
       
  2938     int32_t i, j;
       
  2939     Arg args[10];
       
  2940     int32_t argc;
       
  2941     AwtGraphicsConfigDataPtr defaultConfig =
       
  2942         getDefaultConfig(DefaultScreen(awt_display));
       
  2943 
       
  2944     AWT_LOCK();
       
  2945 
       
  2946     /*
       
  2947      * initialize array of pixels
       
  2948      */
       
  2949     for (i = 0; i < java_awt_SystemColor_NUM_COLORS; i++) {
       
  2950         pixels[i] = -1;
       
  2951     }
       
  2952 
       
  2953     /*
       
  2954      * Create phantom widgets in order to determine the default
       
  2955      * colors;  this is somewhat inelegant, however it is the simplest
       
  2956      * and most reliable way to determine the system's default colors
       
  2957      * for objects.
       
  2958      */
       
  2959     argc = 0;
       
  2960     XtSetArg(args[argc], XmNbuttonFontList,  getMotifFontList()); argc++;
       
  2961     XtSetArg(args[argc], XmNlabelFontList,   getMotifFontList()); argc++;
       
  2962     XtSetArg(args[argc], XmNtextFontList,    getMotifFontList()); argc++;
       
  2963     frame = XtAppCreateShell("AWTColors", "XApplication",
       
  2964                              vendorShellWidgetClass,
       
  2965                              awt_display,
       
  2966                              args, argc);
       
  2967     /*
       
  2968       XtSetMappedWhenManaged(frame, False);
       
  2969       XtRealizeWidget(frame);
       
  2970     */
       
  2971     panel = XmCreateDrawingArea(frame, "awtPanelColor", NULL, 0);
       
  2972     argc = 0;
       
  2973     XtSetArg(args[argc], XmNfontList,        getMotifFontList()); argc++;
       
  2974     control = XmCreatePushButton(panel, "awtControlColor", args, argc);
       
  2975     argc = 0;
       
  2976     XtSetArg(args[argc], XmNlabelFontList,   getMotifFontList()); argc++;
       
  2977     XtSetArg(args[argc], XmNbuttonFontList,  getMotifFontList()); argc++;
       
  2978     menu = XmCreatePulldownMenu(control, "awtColorMenu", args, argc);
       
  2979     argc = 0;
       
  2980     XtSetArg(args[argc], XmNfontList,        getMotifFontList()); argc++;
       
  2981     text = XmCreateText(panel, "awtTextColor", args, argc);
       
  2982     scrollbar = XmCreateScrollBar(panel, "awtScrollbarColor", NULL, 0);
       
  2983 
       
  2984     XtVaGetValues(panel,
       
  2985                   XmNbackground, &bg,
       
  2986                   XmNforeground, &fg,
       
  2987                   XmNcolormap, &cmap,
       
  2988                   NULL);
       
  2989 
       
  2990     pixels[java_awt_SystemColor_WINDOW] = bg;
       
  2991     count++;
       
  2992     pixels[java_awt_SystemColor_INFO] = bg;
       
  2993     count++;
       
  2994     pixels[java_awt_SystemColor_WINDOW_TEXT] = fg;
       
  2995     count++;
       
  2996     pixels[java_awt_SystemColor_INFO_TEXT] = fg;
       
  2997     count++;
       
  2998 
       
  2999     XtVaGetValues(menu,
       
  3000                   XmNbackground, &bg,
       
  3001                   XmNforeground, &fg,
       
  3002                   NULL);
       
  3003 
       
  3004     pixels[java_awt_SystemColor_MENU] = bg;
       
  3005     count++;
       
  3006     pixels[java_awt_SystemColor_MENU_TEXT] = fg;
       
  3007     count++;
       
  3008 
       
  3009     XtVaGetValues(text,
       
  3010                   XmNbackground, &bg,
       
  3011                   XmNforeground, &fg,
       
  3012                   NULL);
       
  3013 
       
  3014     pixels[java_awt_SystemColor_TEXT] = bg;
       
  3015     count++;
       
  3016     pixels[java_awt_SystemColor_TEXT_TEXT] = fg;
       
  3017     count++;
       
  3018     pixels[java_awt_SystemColor_TEXT_HIGHLIGHT] = fg;
       
  3019     count++;
       
  3020     pixels[java_awt_SystemColor_TEXT_HIGHLIGHT_TEXT] = bg;
       
  3021     count++;
       
  3022 
       
  3023     XtVaGetValues(control,
       
  3024                   XmNbackground, &bg,
       
  3025                   XmNforeground, &fg,
       
  3026                   XmNtopShadowColor, &highlight,
       
  3027                   XmNbottomShadowColor, &shadow,
       
  3028                   NULL);
       
  3029 
       
  3030     pixels[java_awt_SystemColor_CONTROL] = bg;
       
  3031     count++;
       
  3032     pixels[java_awt_SystemColor_CONTROL_TEXT] = fg;
       
  3033     count++;
       
  3034     pixels[java_awt_SystemColor_CONTROL_HIGHLIGHT] = highlight;
       
  3035     count++;
       
  3036     pixels[java_awt_SystemColor_CONTROL_LT_HIGHLIGHT] = highlight;
       
  3037     count++;
       
  3038     pixels[java_awt_SystemColor_CONTROL_SHADOW] = shadow;
       
  3039     count++;
       
  3040     pixels[java_awt_SystemColor_CONTROL_DK_SHADOW] = shadow;
       
  3041     count++;
       
  3042 
       
  3043     XtVaGetValues(scrollbar,
       
  3044                   XmNbackground, &bg,
       
  3045                   NULL);
       
  3046     pixels[java_awt_SystemColor_SCROLLBAR] = bg;
       
  3047     count++;
       
  3048 
       
  3049     /*
       
  3050      * Convert pixel values to RGB
       
  3051      */
       
  3052     colorsPtr = (XColor *) malloc(count * sizeof(XColor));
       
  3053     j = 0;
       
  3054     for (i = 0; i < java_awt_SystemColor_NUM_COLORS; i++) {
       
  3055         if (pixels[i] != -1) {
       
  3056             colorsPtr[j++].pixel = pixels[i];
       
  3057         }
       
  3058     }
       
  3059     XQueryColors(awt_display, cmap, colorsPtr, count);
       
  3060 
       
  3061     /* Get current System Colors */
       
  3062 
       
  3063     (*env)->GetIntArrayRegion (env, systemColors, 0,
       
  3064                               java_awt_SystemColor_NUM_COLORS,
       
  3065                               rgbColors);
       
  3066 
       
  3067     /*
       
  3068      * Fill systemColor array with new rgb values
       
  3069      */
       
  3070 
       
  3071     j = 0;
       
  3072     for (i = 0; i < java_awt_SystemColor_NUM_COLORS; i++) {
       
  3073         if (pixels[i] != -1) {
       
  3074             uint32_t rgb = colorToRGB(&colorsPtr[j++]);
       
  3075 
       
  3076             /*
       
  3077               printf("SystemColor[%d] = %x\n", i, rgb);
       
  3078             */
       
  3079             rgbColors[i] = (rgb | 0xFF000000);
       
  3080         }
       
  3081     }
       
  3082 
       
  3083     (*env)->SetIntArrayRegion(env,
       
  3084                               systemColors,
       
  3085                               0,
       
  3086                               java_awt_SystemColor_NUM_COLORS,
       
  3087                               rgbColors);
       
  3088 
       
  3089     /* Duplicate system colors. If color allocation is unsuccessful,
       
  3090        system colors will be approximated with matched colors */
       
  3091     if (defaultConfig->awt_depth == 8)
       
  3092         awt_allocate_systemcolors(colorsPtr, count, defaultConfig);
       
  3093 
       
  3094     /*
       
  3095      * Cleanup
       
  3096      */
       
  3097     XtDestroyWidget(frame);
       
  3098     free(colorsPtr);
       
  3099 
       
  3100     AWT_UNLOCK();
       
  3101 }
       
  3102 
       
  3103 /*
       
  3104  * Class:     sun_awt_motif_MToolkit
       
  3105  * Method:    isDynamicLayoutSupportedNative
       
  3106  * Signature: ()Z
       
  3107  *
       
  3108  * Note: there doesn't seem to be a protocol for querying the WM
       
  3109  * about its opaque resize settings, so this function just returns
       
  3110  * whether there is a solid resize option available for that WM.
       
  3111  */
       
  3112 JNIEXPORT jboolean JNICALL
       
  3113 Java_sun_awt_motif_MToolkit_isDynamicLayoutSupportedNative(JNIEnv *env, jobject this)
       
  3114 {
       
  3115     enum wmgr_t wm;
       
  3116 
       
  3117     AWT_LOCK();
       
  3118     wm = awt_wm_getRunningWM();
       
  3119     AWT_UNLOCK();
       
  3120 
       
  3121     switch (wm) {
       
  3122       case ENLIGHTEN_WM:
       
  3123       case KDE2_WM:
       
  3124       case SAWFISH_WM:
       
  3125       case ICE_WM:
       
  3126       case METACITY_WM:
       
  3127         return JNI_TRUE;
       
  3128       case OPENLOOK_WM:
       
  3129       case MOTIF_WM:
       
  3130       case CDE_WM:
       
  3131         return JNI_FALSE;
       
  3132       default:
       
  3133         return JNI_FALSE;
       
  3134     }
       
  3135 }
       
  3136 
       
  3137 /*
       
  3138  * Class:     sun_awt_motif_MToolkit
       
  3139  * Method:    isFrameStateSupported
       
  3140  * Signature: (I)Z
       
  3141  */
       
  3142 JNIEXPORT jboolean JNICALL
       
  3143 Java_sun_awt_motif_MToolkit_isFrameStateSupported(JNIEnv *env, jobject this,
       
  3144     jint state)
       
  3145 {
       
  3146     if (state == java_awt_Frame_NORMAL || state == java_awt_Frame_ICONIFIED) {
       
  3147         return JNI_TRUE;
       
  3148     } else {
       
  3149         return awt_wm_supportsExtendedState(state) ? JNI_TRUE : JNI_FALSE;
       
  3150     }
       
  3151 }
       
  3152 
       
  3153 /*
       
  3154  * Class:     sun_awt_motif_MToolkit
       
  3155  * Method:    getMulticlickTime
       
  3156  * Signature: ()I
       
  3157  */
       
  3158 JNIEXPORT jint JNICALL Java_sun_awt_motif_MToolkit_getMulticlickTime
       
  3159   (JNIEnv *env, jobject this)
       
  3160 {
       
  3161     return awt_multiclick_time;
       
  3162 }
       
  3163 
       
  3164 /*
       
  3165  * Class:     sun_awt_motif_MToolkit
       
  3166  * Method:    loadXSettings
       
  3167  * Signature: ()V
       
  3168  */
       
  3169 JNIEXPORT void JNICALL
       
  3170 Java_sun_awt_motif_MToolkit_loadXSettings(JNIEnv *env, jobject this)
       
  3171 {
       
  3172     static Boolean registered = False;
       
  3173 
       
  3174     jclass mtoolkitCLS;
       
  3175     Display *dpy = awt_display;
       
  3176     const Window *owners;
       
  3177     int scr;
       
  3178 
       
  3179     AWT_LOCK();
       
  3180 
       
  3181     if (registered) {
       
  3182         AWT_UNLOCK();
       
  3183         return;
       
  3184     }
       
  3185 
       
  3186     if (_XA_XSETTINGS_SETTINGS == None) {
       
  3187         _XA_XSETTINGS_SETTINGS = XInternAtom(dpy, "_XSETTINGS_SETTINGS", False);
       
  3188         if (_XA_XSETTINGS_SETTINGS == None) {
       
  3189             JNU_ThrowNullPointerException(env,
       
  3190                 "unable to intern _XSETTINGS_SETTINGS");
       
  3191             AWT_UNLOCK();
       
  3192             return;
       
  3193         }
       
  3194     }
       
  3195 
       
  3196     mtoolkitCLS = (*env)->GetObjectClass(env, this);
       
  3197 
       
  3198     xsettings_callback_cookie.mtoolkit =
       
  3199         (*env)->NewGlobalRef(env, this);
       
  3200     xsettings_callback_cookie.upcallMID =
       
  3201         (*env)->GetMethodID(env, mtoolkitCLS,
       
  3202                             "parseXSettings", "(I[B)V");
       
  3203 
       
  3204     if (JNU_IsNull(env, xsettings_callback_cookie.upcallMID)) {
       
  3205         JNU_ThrowNoSuchMethodException(env,
       
  3206             "sun.awt.motif.MToolkit.parseXSettings");
       
  3207         AWT_UNLOCK();
       
  3208         return;
       
  3209     }
       
  3210 
       
  3211     owners = awt_mgrsel_select("_XSETTINGS", PropertyChangeMask,
       
  3212                                &xsettings_callback_cookie,
       
  3213                                awt_xsettings_callback,
       
  3214                                awt_xsettings_owner_callback);
       
  3215     if (owners == NULL) {
       
  3216         JNU_ThrowNullPointerException(env,
       
  3217             "unable to regiser _XSETTINGS with mgrsel");
       
  3218         AWT_UNLOCK();
       
  3219         return;
       
  3220     }
       
  3221 
       
  3222     registered = True;
       
  3223 
       
  3224     for (scr = 0; scr < ScreenCount(dpy); ++scr) {
       
  3225         if (owners[scr] == None) {
       
  3226             DTRACE_PRINTLN1("XS: MToolkit.loadXSettings: none on screen %d",
       
  3227                             scr);
       
  3228             continue;
       
  3229         }
       
  3230 
       
  3231         awt_xsettings_update(scr, owners[scr], &xsettings_callback_cookie);
       
  3232     }
       
  3233 
       
  3234     AWT_UNLOCK();
       
  3235 }
       
  3236 
       
  3237 JNIEXPORT jboolean JNICALL
       
  3238 Java_sun_awt_motif_MToolkit_isAlwaysOnTopSupported(JNIEnv *env, jobject toolkit) {
       
  3239     Boolean res;
       
  3240     AWT_LOCK();
       
  3241     res = awt_wm_supportsAlwaysOnTop();
       
  3242     AWT_UNLOCK();
       
  3243     return res;
       
  3244 }
       
  3245 
       
  3246 /*
       
  3247  * Returns true if the current thread is privileged. Currently,
       
  3248  * only the main event loop thread is considered to be privileged.
       
  3249  */
       
  3250 Boolean
       
  3251 awt_currentThreadIsPrivileged(JNIEnv *env) {
       
  3252     return (*env)->IsSameObject(env,
       
  3253                         awt_MainThread, awtJNI_GetCurrentThread(env));
       
  3254 }
       
  3255 
       
  3256 JNIEXPORT jboolean JNICALL
       
  3257 Java_sun_awt_motif_MToolkit_isSyncUpdated(JNIEnv *env, jobject toolkit) {
       
  3258     return syncUpdated;
       
  3259 }
       
  3260 
       
  3261 JNIEXPORT jboolean JNICALL
       
  3262 Java_sun_awt_motif_MToolkit_isSyncFailed(JNIEnv *env, jobject toolkit) {
       
  3263     return syncFailed;
       
  3264 }
       
  3265 
       
  3266 JNIEXPORT void JNICALL
       
  3267 Java_sun_awt_motif_MToolkit_updateSyncSelection(JNIEnv *env, jobject toolkit) {
       
  3268 
       
  3269     // AWT_LOCK is held by calling function
       
  3270     if (wm_selection == None) {
       
  3271         wm_selection = XInternAtom(awt_display, "WM_S0", False);
       
  3272     }
       
  3273     if (version_atom == None) {
       
  3274         version_atom = XInternAtom(awt_display, "VERSION", False);
       
  3275     }
       
  3276     if (oops_atom == None) {
       
  3277         oops_atom = XInternAtom(awt_display, "OOPS", False);
       
  3278     }
       
  3279     syncUpdated = False;
       
  3280     syncFailed = False;
       
  3281     XConvertSelection(awt_display, wm_selection, version_atom, oops_atom, XtWindow(awt_root_shell), CurrentTime);
       
  3282     XSync(awt_display, False);
       
  3283     inSyncWait = True; // Protect from spurious events
       
  3284     // Calling function will call AWT_LOCK_WAIT instead of AWT_UNLOCK
       
  3285 }
       
  3286 
       
  3287 JNIEXPORT jint JNICALL
       
  3288 Java_sun_awt_motif_MToolkit_getEventNumber(JNIEnv *env, jobject toolkit) {
       
  3289     // AWT_LOCK must be held by the calling method
       
  3290     return eventNumber;
       
  3291 }
       
  3292 
       
  3293 static void
       
  3294 syncWait_eventHandler(XEvent * event) {
       
  3295     static jmethodID syncNotifyMID = NULL;
       
  3296     if (event != NULL && event->xany.type == SelectionNotify &&
       
  3297         event->xselection.requestor == XtWindow(awt_root_shell) &&
       
  3298         event->xselection.property == oops_atom &&
       
  3299         inSyncWait)
       
  3300     {
       
  3301         JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
  3302         syncUpdated = True;
       
  3303         inSyncWait = False;
       
  3304         AWT_NOTIFY_ALL();
       
  3305     } else if (event != NULL && event->xany.type == SelectionNotify &&
       
  3306                event->xselection.requestor == XtWindow(awt_root_shell) &&
       
  3307                event->xselection.target == version_atom &&
       
  3308                event->xselection.property == None &&
       
  3309                XGetSelectionOwner(awt_display, wm_selection) == None &&
       
  3310                event->xselection.selection == wm_selection)
       
  3311     {
       
  3312         JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
  3313         syncFailed = True;
       
  3314         inSyncWait = False;
       
  3315         AWT_NOTIFY_ALL();
       
  3316     }
       
  3317 }
       
  3318 
       
  3319 JNIEXPORT void JNICALL
       
  3320 Java_sun_awt_motif_MToolkit_nativeGrab(JNIEnv *env, jobject toolkit, jobject window) {
       
  3321     struct FrameData    *wdata;
       
  3322     static Cursor cursor = None;
       
  3323     int grab_result;
       
  3324 
       
  3325     AWT_LOCK();
       
  3326 
       
  3327     wdata = (struct FrameData *)
       
  3328         JNU_GetLongFieldAsPtr(env, window, mComponentPeerIDs.pData);
       
  3329 
       
  3330     if (wdata == NULL ||
       
  3331         wdata->winData.comp.widget == NULL ||
       
  3332         wdata->winData.shell == NULL)
       
  3333     {
       
  3334         AWT_UNLOCK();
       
  3335         return;
       
  3336     }
       
  3337     if (None == cursor) {
       
  3338         cursor = XCreateFontCursor(awt_display, XC_hand2);
       
  3339     }
       
  3340     grabbed_widget = wdata->winData.shell;
       
  3341     grab_result = XGrabPointer(awt_display, XtWindow(wdata->winData.shell),
       
  3342                                True, (ButtonPressMask | ButtonReleaseMask
       
  3343                                       | EnterWindowMask | LeaveWindowMask | PointerMotionMask
       
  3344                                       | ButtonMotionMask),
       
  3345                                GrabModeAsync, GrabModeAsync, None,
       
  3346                                cursor, CurrentTime);
       
  3347     if (GrabSuccess != grab_result) {
       
  3348         XUngrabPointer(awt_display, CurrentTime);
       
  3349         AWT_UNLOCK();
       
  3350         DTRACE_PRINTLN1("XGrabPointer() failed, result %d", grab_result);
       
  3351         return;
       
  3352     }
       
  3353     grab_result = XGrabKeyboard(awt_display, XtWindow(wdata->winData.shell),
       
  3354                                 True,
       
  3355                                 GrabModeAsync, GrabModeAsync, CurrentTime);
       
  3356     if (GrabSuccess != grab_result) {
       
  3357         XUngrabKeyboard(awt_display, CurrentTime);
       
  3358         XUngrabPointer(awt_display, CurrentTime);
       
  3359         DTRACE_PRINTLN1("XGrabKeyboard() failed, result %d", grab_result);
       
  3360     }
       
  3361     AWT_UNLOCK();
       
  3362 }
       
  3363 
       
  3364 JNIEXPORT void JNICALL
       
  3365 Java_sun_awt_motif_MToolkit_nativeUnGrab(JNIEnv *env, jobject toolkit, jobject window) {
       
  3366     struct FrameData    *wdata;
       
  3367 
       
  3368     AWT_LOCK();
       
  3369 
       
  3370     wdata = (struct FrameData *)
       
  3371         JNU_GetLongFieldAsPtr(env, window, mComponentPeerIDs.pData);
       
  3372 
       
  3373     if (wdata == NULL ||
       
  3374         wdata->winData.comp.widget == NULL ||
       
  3375         wdata->winData.shell == NULL)
       
  3376     {
       
  3377         AWT_UNLOCK();
       
  3378         return;
       
  3379     }
       
  3380 
       
  3381     XUngrabPointer(awt_display, CurrentTime);
       
  3382     XUngrabKeyboard(awt_display, CurrentTime);
       
  3383     grabbed_widget = NULL;
       
  3384     AWT_FLUSHOUTPUT_NOW();
       
  3385 
       
  3386     AWT_UNLOCK();
       
  3387 
       
  3388 }
       
  3389 
       
  3390 /*
       
  3391  * Class:     sun_awt_motif_MToolkit
       
  3392  * Method:    getWMName
       
  3393  * Signature: ()Ljava/lang/String;
       
  3394  */
       
  3395 JNIEXPORT jstring JNICALL
       
  3396 Java_sun_awt_motif_MToolkit_getWMName(JNIEnv *env, jclass this)
       
  3397 {
       
  3398     enum wmgr_t wm;
       
  3399 
       
  3400     AWT_LOCK();
       
  3401     wm = awt_wm_getRunningWM();
       
  3402     AWT_UNLOCK();
       
  3403 
       
  3404     switch (wm) {
       
  3405       case NO_WM:
       
  3406           return (*env)->NewStringUTF(env, "NO_WM");
       
  3407       case OTHER_WM:
       
  3408           return (*env)->NewStringUTF(env, "OTHER_WM");
       
  3409       case ENLIGHTEN_WM:
       
  3410           return (*env)->NewStringUTF(env, "ENLIGHTEN_WM");
       
  3411       case KDE2_WM:
       
  3412           return (*env)->NewStringUTF(env, "KDE2_WM");
       
  3413       case SAWFISH_WM:
       
  3414           return (*env)->NewStringUTF(env, "SAWFISH_WM");
       
  3415       case ICE_WM:
       
  3416           return (*env)->NewStringUTF(env, "ICE_WM");
       
  3417       case METACITY_WM:
       
  3418           return (*env)->NewStringUTF(env, "METACITY_WM");
       
  3419       case OPENLOOK_WM:
       
  3420           return (*env)->NewStringUTF(env, "OPENLOOK_WM");
       
  3421       case MOTIF_WM:
       
  3422           return (*env)->NewStringUTF(env, "MOTIF_WM");
       
  3423       case CDE_WM:
       
  3424           return (*env)->NewStringUTF(env, "CDE_WM");
       
  3425     }
       
  3426     return (*env)->NewStringUTF(env, "UNDETERMINED_WM");
       
  3427 }
       
  3428 
       
  3429 
       
  3430 #endif /* !HEADLESS */