1 /*
   2  * Copyright (c) 1995, 2003, 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 #ifdef HEADLESS
  27     #error This file should not be included in headless library
  28 #endif
  29 
  30 #include "awt_p.h"
  31 #include "color.h"
  32 #include "awt_TopLevel.h"
  33 #include <X11/IntrinsicP.h>
  34 #include <X11/Xatom.h>
  35 #include <X11/Xmd.h>
  36 #include <X11/Xutil.h>
  37 #include <X11/Xproto.h>
  38 #ifndef XAWT
  39 #include <Xm/MenuShell.h>
  40 #include <Xm/List.h>
  41 #include <Xm/Form.h>
  42 #include <Xm/RowColumn.h>
  43 #include <Xm/MwmUtil.h>
  44 #endif /* XAWT */
  45 #include <jni.h>
  46 #include <jni_util.h>
  47 #include <sys/time.h>
  48 
  49 #include "awt_xembed.h"
  50 
  51 
  52 #ifndef XAWT
  53 #if MOTIF_VERSION!=1
  54     #include <Xm/GrabShell.h>
  55 #endif
  56 #endif
  57 
  58 #include "java_awt_event_MouseWheelEvent.h"
  59 
  60 /*
  61  * Since X reports protocol errors asynchronously, we often need to
  62  * install an error handler that acts like a callback.  While that
  63  * specialized handler is installed we save original handler here.
  64  */
  65 XErrorHandler xerror_saved_handler;
  66 
  67 /*
  68  * A place for error handler to report the error code.
  69  */
  70 unsigned char xerror_code;
  71 
  72 extern jint getModifiers(uint32_t state, jint button, jint keyCode);
  73 extern jint getButton(uint32_t button);
  74 
  75 static int32_t winmgr_running = 0;
  76 static Atom OLDecorDelAtom = 0;
  77 static Atom MWMHints = 0;
  78 static Atom DTWMHints = 0;
  79 static Atom decor_list[9];
  80 
  81 #ifndef MAX
  82 #define MAX(a,b) ((a) > (b) ? (a) : (b))
  83 #endif
  84 
  85 #ifndef MIN
  86 #define MIN(a,b) ((a) < (b) ? (a) : (b))
  87 #endif
  88 
  89 #ifndef XAWT
  90 /*
  91  * The following three funtions are to work around menu problems
  92  */
  93 
  94 /*
  95  * test if there is a menu that has the current focus
  96  * called from awt_Dialog.c and awt_Component.c
  97  */
  98 Boolean
  99 awt_util_focusIsOnMenu(Display *display)
 100 {
 101   Window window;
 102   Widget widget;
 103   int32_t rtr;
 104 
 105   XGetInputFocus(display, &window, &rtr);
 106   if (window == None) {
 107     return False;
 108   }
 109 
 110   widget = XtWindowToWidget(display, window);
 111   if (widget == NULL) {
 112     return False;
 113   }
 114 
 115   if (XtIsSubclass(widget, xmMenuShellWidgetClass)) {
 116     return True;
 117   }
 118 
 119   #if MOTIF_VERSION!=1
 120   /* Motif 2.1 uses XmGrabShell on XmComboBox instead
 121      of XmMenuShell
 122   */
 123   if (XtIsSubclass(widget, xmGrabShellWidgetClass)) {
 124       return True;
 125   }
 126   /* Fix 4800638 check the ancestor of focus widget is
 127      GrabSell
 128    */
 129   if (XtIsSubclass(widget, xmListWidgetClass))
 130   {
 131       Widget shell = getShellWidget(widget);
 132       if (shell && XtIsSubclass(shell,
 133           xmGrabShellWidgetClass))
 134       {
 135           return True;
 136       }
 137   }
 138   #endif
 139 
 140   if (XtIsSubclass(widget, xmRowColumnWidgetClass)) {
 141       unsigned char type;
 142       XtVaGetValues(widget, XmNrowColumnType, &type, NULL);
 143       if (type == XmMENU_BAR) {
 144           return True;
 145       }
 146   }
 147   return False;
 148 }
 149 
 150 static
 151 void fillButtonEvent(XButtonEvent *ev, int32_t type, Display *display, Window window) {
 152     ev->type = type;
 153     ev->display = display;
 154     ev->window = window;
 155     ev->send_event = True;
 156 
 157     /* REMIND: multi-screen */
 158     ev->root = RootWindow(display, DefaultScreen(display));
 159     ev->subwindow = (Window)None;
 160     ev->time = CurrentTime;
 161     ev->x = 0;
 162     ev->y = 0;
 163     ev->x_root = 0;
 164     ev->y_root = 0;
 165     ev->same_screen = True;
 166     ev->button = Button1;
 167     ev->state = Button1Mask;
 168 }
 169 
 170 /*
 171  * generates a mouse press event and a release event
 172  * called from awt_Dialog.c
 173  */
 174 int32_t
 175 awt_util_sendButtonClick(Display *display, Window window)
 176 {
 177   XButtonEvent ev;
 178   int32_t status;
 179 
 180   fillButtonEvent(&ev, ButtonPress, display, window);
 181   status = XSendEvent(display, window, True, ButtonPressMask, (XEvent *)&ev);
 182 
 183   if (status != 0) {
 184       fillButtonEvent(&ev, ButtonRelease, display, window);
 185       status = XSendEvent(display, window, False, ButtonReleaseMask,
 186                           (XEvent *)&ev);
 187   }
 188   return status;
 189 }
 190 
 191 Widget
 192 awt_util_createWarningWindow(Widget parent, char *warning)
 193 {
 194     Widget warningWindow;
 195 #ifdef NETSCAPE
 196     extern Widget FE_MakeAppletSecurityChrome(Widget parent, char* message);
 197     warningWindow = FE_MakeAppletSecurityChrome(parent, warning);
 198 #else
 199     Widget label;
 200     int32_t argc;
 201 #define MAX_ARGC 10
 202     Arg args[MAX_ARGC];
 203     int32_t screen = 0;
 204     int32_t i;
 205     AwtGraphicsConfigDataPtr adata;
 206     extern int32_t awt_numScreens;
 207 
 208     Pixel gray;
 209     Pixel black;
 210 
 211     for (i = 0; i < awt_numScreens; i++) {
 212         if (ScreenOfDisplay(awt_display, i) == XtScreen(parent)) {
 213             screen = i;
 214             break;
 215         }
 216     }
 217     adata = getDefaultConfig(screen);
 218 
 219     gray = adata->AwtColorMatch(192, 192, 192, adata);
 220     black = adata->AwtColorMatch(0, 0, 0, adata);
 221 
 222     argc = 0;
 223     XtSetArg(args[argc], XmNbackground, gray); argc++;
 224     XtSetArg(args[argc], XmNmarginHeight, 0); argc++;
 225     XtSetArg(args[argc], XmNmarginWidth, 0); argc++;
 226     XtSetArg (args[argc], XmNscreen, XtScreen(parent)); argc++;
 227 
 228     DASSERT(!(argc > MAX_ARGC));
 229     warningWindow =  XmCreateForm(parent, "main", args, argc);
 230 
 231     XtManageChild(warningWindow);
 232     label = XtVaCreateManagedWidget(warning,
 233                                     xmLabelWidgetClass, warningWindow,
 234                                     XmNhighlightThickness, 0,
 235                                     XmNbackground, gray,
 236                                     XmNforeground, black,
 237                                     XmNalignment, XmALIGNMENT_CENTER,
 238                                     XmNrecomputeSize, False,
 239                                     NULL);
 240     XtVaSetValues(label,
 241                   XmNbottomAttachment, XmATTACH_FORM,
 242                   XmNtopAttachment, XmATTACH_FORM,
 243                   XmNleftAttachment, XmATTACH_FORM,
 244                   XmNrightAttachment, XmATTACH_FORM,
 245                   NULL);
 246 #endif
 247     return warningWindow;
 248 }
 249 
 250 void
 251 awt_setWidgetGravity(Widget w, int32_t gravity)
 252 {
 253     XSetWindowAttributes    xattr;
 254     Window  win = XtWindow(w);
 255 
 256     if (win != None) {
 257         xattr.bit_gravity = StaticGravity;
 258         xattr.win_gravity = StaticGravity;
 259         XChangeWindowAttributes(XtDisplay(w), win,
 260                                 CWBitGravity|CWWinGravity,
 261                                 &xattr);
 262     }
 263 }
 264 
 265 Widget get_shell_focused_widget(Widget w) {
 266     while (w != NULL && !XtIsShell(w)) {
 267         w = XtParent(w);
 268     }
 269     if (w != NULL) {
 270         return XmGetFocusWidget(w);
 271     } else {
 272         return NULL;
 273     }
 274 }
 275 
 276 void
 277 awt_util_reshape(Widget w, jint x, jint y, jint wd, jint ht)
 278 {
 279     Widget parent;
 280     Dimension ww, wh;
 281     Position wx, wy;
 282     Boolean move = False;
 283     Boolean resize = False;
 284     Boolean mapped_when_managed = False;
 285     Boolean need_to_unmanage = True;
 286     Widget saved_focus_widget = NULL;
 287 
 288     if (w == NULL) {
 289         JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 290         JNU_ThrowNullPointerException(env,"NullPointerException");
 291         return;
 292     }
 293     parent = XtParent(w);
 294 
 295     /* Aim: hack to prevent direct children of scrollpane from
 296      * being unmanaged during a reshape operation (which results
 297      * in too many expose events).
 298      */
 299     if (parent != NULL && XtParent(parent) != NULL &&
 300         XtIsSubclass(XtParent(parent), xmScrolledWindowWidgetClass)) {
 301         need_to_unmanage = False;
 302     }
 303 
 304     XtVaGetValues(w,
 305                   XmNwidth, &ww,
 306                   XmNheight, &wh,
 307                   XmNx, &wx,
 308                   XmNy, &wy,
 309                   NULL);
 310 
 311     if (x != wx || y != wy) {
 312         move = True;
 313     }
 314     if (wd != ww || ht != wh) {
 315         resize = True;
 316     }
 317     if (!move && !resize) {
 318         return;
 319     }
 320 
 321     if (need_to_unmanage) {
 322         if (!resize) {
 323             mapped_when_managed = w->core.mapped_when_managed;
 324             w->core.mapped_when_managed = False;
 325         }
 326         saved_focus_widget = get_shell_focused_widget(w);
 327         XtUnmanageChild(w);
 328     }
 329 
 330     /* GES: AVH's hack:
 331      * Motif ignores attempts to move a toplevel window to 0,0.
 332      * Instead we set the position to 1,1. The expected value is
 333      * returned by Frame.getBounds() since it uses the internally
 334      * held rectangle rather than querying the peer.
 335      * N.B. [pauly, 9/97]  This is only required for wm shells
 336      * under the Motif Window Manager (MWM), not for any others.
 337      * Note. Utilizes C short-circuiting if w is not a wm shell.
 338      */
 339     if ((x == 0) && (y == 0) &&
 340         (XtIsSubclass(w, wmShellWidgetClass)) &&
 341         (XmIsMotifWMRunning(w))) {
 342         XtVaSetValues(w, XmNx, 1, XmNy, 1, NULL);
 343     }
 344 
 345     if (move && !resize) {
 346         XtVaSetValues(w, XmNx, x, XmNy, y, NULL);
 347 
 348     } else if (resize && !move) {
 349         XtVaSetValues(w,
 350                       XmNwidth, (wd > 0) ? wd : 1,
 351                       XmNheight, (ht > 0) ? ht : 1,
 352                       NULL);
 353 
 354     } else  {
 355         XtVaSetValues(w,
 356                   XmNx, x,
 357                   XmNy, y,
 358                   XmNwidth, (wd > 0) ? wd : 1,
 359                   XmNheight, (ht > 0) ? ht : 1,
 360                   NULL);
 361     }
 362 
 363     if (need_to_unmanage) {
 364         XtManageChild(w);
 365         if (!resize) {
 366             w->core.mapped_when_managed = mapped_when_managed;
 367         }
 368         if (saved_focus_widget != NULL) {
 369             Boolean result = XmProcessTraversal(saved_focus_widget, XmTRAVERSE_CURRENT);
 370             if (!result)
 371             {
 372                 Widget shell = saved_focus_widget;
 373                 while(shell != NULL && !XtIsShell(shell)) {
 374                     shell = XtParent(shell);
 375                 }
 376                 XtSetKeyboardFocus(shell, saved_focus_widget);
 377             }
 378         }
 379     }
 380 }
 381 
 382 void
 383 awt_util_hide(Widget w)
 384 {
 385     if (w == NULL) {
 386         JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 387         JNU_ThrowNullPointerException(env,"NullPointerException");
 388         return;
 389     }
 390     XtSetMappedWhenManaged(w, False);
 391 }
 392 
 393 void
 394 awt_util_show(Widget w)
 395 {
 396 /*
 397     extern Boolean  scrollBugWorkAround;
 398 */
 399     if (w == NULL) {
 400         JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 401         JNU_ThrowNullPointerException(env,"NullPointerException");
 402         return;
 403     }
 404     XtSetMappedWhenManaged(w, True);
 405 /*
 406   XXX: causes problems on 2.5
 407     if (!scrollBugWorkAround) {
 408         awt_setWidgetGravity(w, StaticGravity);
 409     }
 410 */
 411 }
 412 
 413 void
 414 awt_util_enable(Widget w)
 415 {
 416     XtSetSensitive(w, True);
 417 }
 418 
 419 void
 420 awt_util_disable(Widget w)
 421 {
 422     XtSetSensitive(w, False);
 423 }
 424 
 425 void
 426 awt_util_mapChildren(Widget w, void (*func)(Widget,void *),
 427                      int32_t applyToCurrent, void *data) {
 428     WidgetList                  wlist;
 429     Cardinal                    wlen = 0;
 430     Cardinal                    i;
 431 
 432     /* The widget may have been destroyed by another thread. */
 433     if ((w == NULL) || (!XtIsObject(w)) || (w->core.being_destroyed))
 434         return;
 435 
 436     if (applyToCurrent != 0) {
 437         (*func)(w, data);
 438     }
 439     if (!XtIsComposite(w)) {
 440         return;
 441     }
 442 
 443     XtVaGetValues(w,
 444                   XmNchildren, &wlist,
 445                   XmNnumChildren, &wlen,
 446                   NULL);
 447     if (wlen > 0) {
 448         for (i=0; i < wlen; i++) {
 449             awt_util_mapChildren(wlist[i], func, 1, data);
 450         }
 451     }
 452 }
 453 
 454 void
 455 awt_changeAttributes(Display *dpy, Widget w, unsigned long mask,
 456                      XSetWindowAttributes *xattr)
 457 {
 458     WidgetList          wlist;
 459     Cardinal            wlen = 0;
 460     Cardinal            i;
 461 
 462     if (XtWindow(w) && XtIsRealized(w)) {
 463         XChangeWindowAttributes(dpy,
 464                                 XtWindow(w),
 465                                 mask,
 466                                 xattr);
 467     } else {
 468         return;
 469     }
 470     XtVaGetValues(w,
 471                   XmNchildren, &wlist,
 472                   XmNnumChildren, &wlen,
 473                   NULL);
 474     for (i = 0; i < wlen; i++) {
 475         if (XtWindow(wlist[i]) && XtIsRealized(wlist[i])) {
 476             XChangeWindowAttributes(dpy,
 477                                     XtWindow(wlist[i]),
 478                                     mask,
 479                                     xattr);
 480         }
 481     }
 482 }
 483 
 484 static Widget prevWgt = NULL;
 485 
 486 static void
 487 DestroyCB(Widget w, XtPointer client_data, XtPointer call_data) {
 488     if (prevWgt == w) {
 489         prevWgt = NULL;
 490     }
 491 }
 492 
 493 int32_t
 494 awt_util_setCursor(Widget w, Cursor c) {
 495     static Cursor prevCur = None;
 496 
 497     if (XtIsRealized(w)) {
 498         unsigned long valuemask = 0;
 499         XSetWindowAttributes    attributes;
 500 
 501         valuemask = CWCursor;
 502         if (prevWgt != NULL) {
 503             attributes.cursor = None;
 504             XChangeWindowAttributes(awt_display,
 505                         XtWindow(prevWgt),
 506                         valuemask,
 507                         &attributes);
 508         }
 509 
 510         if (c == None) {
 511             c = prevCur;
 512             if (w != NULL) {
 513                 XtAddCallback(w, XmNdestroyCallback, DestroyCB, NULL);
 514             }
 515             prevWgt = w;
 516         } else {
 517             prevCur = c;
 518             prevWgt = NULL;
 519         }
 520         attributes.cursor = c;
 521         XChangeWindowAttributes(awt_display,
 522                                 XtWindow(w),
 523                                 valuemask,
 524                                 &attributes);
 525         XFlush(awt_display);
 526         return 1;
 527     } else
 528         return 0;
 529 }
 530 
 531 void
 532 awt_util_convertEventTimeAndModifiers(XEvent *event,
 533                                       ConvertEventTimeAndModifiers *output) {
 534     switch (event->type) {
 535     case KeyPress:
 536     case KeyRelease:
 537         output->when = awt_util_nowMillisUTC_offset(event->xkey.time);
 538         output->modifiers = getModifiers(event->xkey.state, 0, 0);
 539         break;
 540     case ButtonPress:
 541     case ButtonRelease:
 542         output->when = awt_util_nowMillisUTC_offset(event->xbutton.time);
 543         output->modifiers = getModifiers(event->xbutton.state,
 544             getButton(event->xbutton.button), 0);
 545         break;
 546     default:
 547         output->when = awt_util_nowMillisUTC();
 548         output->modifiers =0;
 549         break;
 550     }
 551 }
 552 
 553 
 554 /*
 555   Part fix for bug id 4017222. Return the widget at the given screen coords
 556   by searching the widget tree beginning at root. This function will return
 557   null if the pointer is not over the root widget or child of the root widget.
 558 
 559   Additionally, this function will only return a Widget with non-nil XmNuserData.
 560   In 1.2.1, when the mouse was dragged over a Choice component, this function
 561   returned the GadgetButton associated with the Choice.  This GadgetButton had
 562   nil as its XmNuserData.  This lead to a crash when the nil XmNuserData was
 563   extracted and used as a reference to a peer.  Ooops.
 564   Now the GadgetButton is not returned and the function goes on to find a widget
 565   which contains the correct peer reference in XmNuserData.
 566 */
 567 Widget
 568 awt_WidgetAtXY(Widget root, Position pointerx, Position pointery) {
 569   Widget answer = NULL;
 570 
 571   if(!root) return NULL;
 572 
 573   if(XtIsComposite(root)) {
 574     int32_t i=0;
 575     WidgetList wl=NULL;
 576     Cardinal wlen=0;
 577 
 578     XtVaGetValues(root, XmNchildren, &wl, XmNnumChildren, &wlen, NULL);
 579 
 580     if(wlen>0) {
 581       for(i=0; i<wlen && !answer; i++) {
 582         answer = awt_WidgetAtXY(wl[i], pointerx, pointery);
 583       }
 584     }
 585   }
 586 
 587   if(!answer) {
 588     Position wx=0, wy=0;
 589     Dimension width=0, height=0;
 590     int32_t lastx=0, lasty=0;
 591     XtPointer widgetUserData=NULL;
 592 
 593     XtVaGetValues(root, XmNwidth, &width, XmNheight, &height,
 594                   XmNuserData, &widgetUserData,
 595                   NULL);
 596 
 597     XtTranslateCoords(root, 0, 0, &wx, &wy);
 598     lastx = wx + width;
 599     lasty = wy + height;
 600 
 601     if(pointerx>=wx && pointerx<=lastx && pointery>=wy && pointery<=lasty &&
 602            widgetUserData)
 603         answer = root;
 604   }
 605 
 606   return answer;
 607 }
 608 #ifdef __linux__
 609 
 610 
 611 #define MAXARGS 10
 612 static Arg xic_vlist[MAXARGS];
 613 static Arg status_vlist[MAXARGS];
 614 static Arg preedit_vlist[MAXARGS];
 615 
 616 #define NO_ARG_VAL -1
 617 #define SEPARATOR_HEIGHT 2
 618 
 619 static XFontSet extract_fontset(XmFontList);
 620 
 621 /* get_im_height: returns height of the input method status area in pixels.
 622  *
 623  * This function assumes that if any XIM related information cannot be
 624  * queried then the app must not have an input method status area in the
 625  * current locale and returns zero as the status area height
 626  */
 627 
 628 static XtPointer*
 629 get_im_info_ptr(Widget  w,
 630                 Boolean create)
 631 {
 632   Widget p;
 633   XmVendorShellExtObject ve;
 634   XmWidgetExtData extData;
 635   XmImShellInfo im_info;
 636   XmImDisplayInfo xim_info;
 637 
 638   if (w == NULL)
 639     return NULL;
 640 
 641   p = w;
 642   while (!XtIsShell(p))
 643     p = XtParent(p);
 644 
 645   /* Check extension data since app could be attempting to create
 646    * a text widget as child of menu shell.  This is illegal, and will
 647    * be detected later, but check here so we don't core dump.
 648    */
 649   if ((extData = _XmGetWidgetExtData((Widget)p, XmSHELL_EXTENSION)) == NULL)
 650     return NULL;
 651 
 652   ve = (XmVendorShellExtObject) extData->widget;
 653 
 654   return &ve->vendor.im_info;
 655 }
 656 
 657 static XmImShellInfo
 658 get_im_info(Widget w,
 659             Boolean create)
 660 {
 661   XmImShellInfo* ptr = (XmImShellInfo *) get_im_info_ptr(w, create);
 662   if (ptr != NULL)
 663     return *ptr;
 664   else
 665     return NULL;
 666 }
 667 
 668 #endif /* !linux */
 669 
 670 Widget
 671 awt_util_getXICStatusAreaWindow(Widget w)
 672 {
 673     while (!XtIsShell(w)){
 674         w = XtParent(w);
 675     }
 676     return w;
 677 }
 678 
 679 #ifdef __linux__
 680 static XRectangle geometryRect;
 681 XVaNestedList awt_util_getXICStatusAreaList(Widget w)
 682 {
 683     XIC xic;
 684     XmImXICInfo icp;
 685     XmVendorShellExtObject ve;
 686     XmWidgetExtData extData;
 687     XmImShellInfo im_info;
 688     XmFontList fl=NULL;
 689 
 690     XRectangle  *ssgeometry = &geometryRect;
 691     XRectangle geomRect ;
 692     XRectangle *im_rect;
 693     XFontSet   *im_font;
 694 
 695     Pixel bg ;
 696     Pixel fg ;
 697     Dimension height, width ;
 698     Position x,y ;
 699     Pixmap bpm, *bpmout ;
 700 
 701     XVaNestedList list = NULL;
 702 
 703     char *ret;
 704     Widget p=w;
 705 
 706     while (!XtIsShell(p)) {
 707         p = XtParent(p);
 708     }
 709 
 710     XtVaGetValues(p,
 711         XmNx, &x,
 712         XmNy, &y,
 713         XmNwidth, &width,
 714         XmNheight, &height,
 715         XmNbackgroundPixmap, &bpm,
 716         NULL);
 717 
 718     extData = _XmGetWidgetExtData((Widget) p, XmSHELL_EXTENSION);
 719     if (extData == NULL) {
 720         return NULL;
 721     }
 722     ve = (XmVendorShellExtObject) extData->widget;
 723     im_info = get_im_info(w, False);
 724 
 725     if (im_info == NULL) {
 726         return NULL;
 727     } else {
 728         icp = im_info->iclist;
 729     }
 730 
 731     if (icp) {
 732         /*
 733          * We have at least a textfield/textarea in the frame, use the
 734          * first one.
 735          */
 736         ssgeometry->x = 0;
 737         ssgeometry->y = height - icp->sp_height;
 738         ssgeometry->width = icp->status_width;
 739         ssgeometry->height = icp->sp_height;
 740         XtVaGetValues(w, XmNbackground, &bg, NULL);
 741         XtVaGetValues(w, XmNforeground, &fg, NULL);
 742         XtVaGetValues(w, XmNfontList, &fl, NULL);
 743         /*
 744          * use motif TextComponent's resource
 745          */
 746 
 747         list = XVaCreateNestedList(0,
 748                         XNFontSet, extract_fontset(fl),
 749                         XNArea, ssgeometry,
 750                         XNBackground, bg,
 751                         XNForeground, fg,
 752                         NULL);
 753    }
 754    return list ;
 755 }
 756 
 757 static XFontSet
 758 extract_fontset(XmFontList fl)
 759 {
 760     XmFontContext context;
 761     XmFontListEntry next_entry;
 762     XmFontType type_return;
 763     XtPointer tmp_font;
 764     XFontSet first_fs = NULL;
 765     char *font_tag;
 766 
 767     if (!XmFontListInitFontContext(&context, fl))
 768         return NULL;
 769 
 770     do {
 771         next_entry = XmFontListNextEntry(context);
 772         if (next_entry) {
 773             tmp_font = XmFontListEntryGetFont(next_entry, &type_return);
 774             if (type_return == XmFONT_IS_FONTSET) {
 775                 font_tag = XmFontListEntryGetTag(next_entry);
 776                 if (!strcmp(font_tag, XmFONTLIST_DEFAULT_TAG)) {
 777                     XmFontListFreeFontContext(context);
 778                     XtFree(font_tag);
 779                     return (XFontSet) tmp_font;
 780                 }
 781                 XtFree(font_tag);
 782                 if (first_fs == NULL)
 783                     first_fs = (XFontSet) tmp_font;
 784             }
 785         }
 786     } while (next_entry);
 787 
 788     XmFontListFreeFontContext(context);
 789     return first_fs;
 790 }
 791 #endif
 792 
 793 /*the caller does have the responsibility to free the memory return
 794   from this function...*/
 795 char* awt_util_makeWMMenuItem(char *target, Atom protocol){
 796     char        *buf = NULL;
 797     int32_t         buflen = 0;
 798 
 799     /*a label in a menuitem is not supposed to be a FullOfSpaceString... */
 800     buflen = strlen(target) * 3;
 801     buf = (char*)malloc(buflen + 20);
 802     if (buf == NULL){
 803         JNU_ThrowOutOfMemoryError((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2), NULL);
 804     }
 805     else{
 806       int32_t   off = 0;
 807       char  *ptr = target;
 808       while ((off < (buflen - 20)) && (*ptr != '\0')){
 809         if (*ptr == ' '){
 810           *(buf + off++) = 0x5c;
 811         }
 812         *(buf + off++) = *ptr++;
 813       }
 814       sprintf(buf + off, " f.send_msg %ld", protocol);
 815     }
 816     return buf;
 817 }
 818 
 819 /*
 820  * This callback proc is installed via setting the XmNinsertPosition
 821  * resource on a widget. It ensures that components added
 822  * to a widget are inserted in the correct z-order position
 823  * to match up with their peer/target ordering in Container.java
 824  */
 825 Cardinal
 826 awt_util_insertCallback(Widget w)
 827 {
 828     jobject peer;
 829     WidgetList children;
 830     Cardinal num_children;
 831     Widget parent;
 832     XtPointer userdata;
 833     Cardinal index;
 834     int32_t pos;
 835     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 836 
 837     parent = XtParent(w);
 838     XtVaGetValues(parent,
 839                   XmNnumChildren, &num_children,
 840                   XmNchildren, &children,
 841                   NULL);
 842     XtVaGetValues(w, XmNuserData, &userdata, NULL);
 843 
 844     index = num_children;         /* default is to add to end */
 845 
 846     if (userdata != NULL) {
 847         peer = (jobject) userdata;
 848 
 849         // SECURITY: We are running on the privileged toolkit thread.
 850         //           The peer must *NOT* call into user code
 851         pos = (int32_t) JNU_CallMethodByName(env
 852                                           ,NULL
 853                                           ,(jobject) peer
 854                                           ,"getZOrderPosition_NoClientCode"
 855                                           ,"()I").i;
 856         if ((*env)->ExceptionOccurred(env)) {
 857             (*env)->ExceptionDescribe(env);
 858             (*env)->ExceptionClear(env);
 859         }
 860         index = (Cardinal) (pos != -1 ? pos : num_children);
 861     }
 862     return index;
 863 }
 864 
 865 void
 866 awt_util_consumeAllXEvents(Widget widget)
 867 {
 868     /* Remove all queued X Events for the window of the widget. */
 869 
 870 #define ALL_EVENTS_MASK 0xFFFF
 871 
 872     XEvent xev;
 873 
 874     XFlush(awt_display);
 875     while (XCheckWindowEvent(awt_display, XtWindow(widget),
 876                ALL_EVENTS_MASK, &xev)) ;
 877 }
 878 
 879 #endif /* XAWT */
 880 /**
 881  * Gets the thread we are currently executing on
 882  */
 883 jobject
 884 awtJNI_GetCurrentThread(JNIEnv *env) {
 885     static jclass threadClass = NULL;
 886     static jmethodID currentThreadMethodID = NULL;
 887 
 888     jobject currentThread = NULL;
 889 
 890     /* Initialize our java identifiers once. Checking before locking
 891      * is a huge performance win.
 892      */
 893     if (threadClass == NULL) {
 894         // should enter a monitor here...
 895         Boolean err = FALSE;
 896         if (threadClass == NULL) {
 897             jclass tc = (*env)->FindClass(env, "java/lang/Thread");
 898             threadClass = (*env)->NewGlobalRef(env, tc);
 899             if (threadClass != NULL) {
 900                 currentThreadMethodID = (*env)->GetStaticMethodID(env,
 901                                               threadClass,
 902                                               "currentThread",
 903                                               "()Ljava/lang/Thread;"
 904                                                 );
 905             }
 906         }
 907         if (currentThreadMethodID == NULL) {
 908             threadClass = NULL;
 909             err = TRUE;
 910         }
 911         if (err) {
 912             return NULL;
 913         }
 914     } /* threadClass == NULL*/
 915 
 916     currentThread = (*env)->CallStaticObjectMethod(
 917                         env, threadClass, currentThreadMethodID);
 918     DASSERT(!((*env)->ExceptionOccurred(env)));
 919     /*JNU_PrintString(env, "getCurrentThread() -> ", JNU_ToString(env,currentThread));*/
 920     return currentThread;
 921 } /* awtJNI_GetCurrentThread() */
 922 
 923 void
 924 awtJNI_ThreadYield(JNIEnv *env) {
 925 
 926     static jclass threadClass = NULL;
 927     static jmethodID yieldMethodID = NULL;
 928 
 929     /* Initialize our java identifiers once. Checking before locking
 930      * is a huge performance win.
 931      */
 932     if (threadClass == NULL) {
 933         // should enter a monitor here...
 934         Boolean err = FALSE;
 935         if (threadClass == NULL) {
 936             jclass tc = (*env)->FindClass(env, "java/lang/Thread");
 937             threadClass = (*env)->NewGlobalRef(env, tc);
 938             (*env)->DeleteLocalRef(env, tc);
 939             if (threadClass != NULL) {
 940                 yieldMethodID = (*env)->GetStaticMethodID(env,
 941                                               threadClass,
 942                                               "yield",
 943                                               "()V"
 944                                                 );
 945             }
 946         }
 947         if (yieldMethodID == NULL) {
 948             threadClass = NULL;
 949             err = TRUE;
 950         }
 951         if (err) {
 952             return;
 953         }
 954     } /* threadClass == NULL*/
 955 
 956     (*env)->CallStaticVoidMethod(env, threadClass, yieldMethodID);
 957     DASSERT(!((*env)->ExceptionOccurred(env)));
 958 } /* awtJNI_ThreadYield() */
 959 
 960 #ifndef XAWT
 961 
 962 void
 963 awt_util_cleanupBeforeDestroyWidget(Widget widget)
 964 {
 965     /* Bug 4017222: Drag processing uses global prevWidget. */
 966     if (widget == prevWidget) {
 967         prevWidget = NULL;
 968     }
 969 }
 970 
 971 static Boolean timeStampUpdated = False;
 972 
 973 static int32_t
 974 isTimeStampUpdated(void* p) {
 975     return timeStampUpdated;
 976 }
 977 
 978 static void
 979 propertyChangeEventHandler(Widget w, XtPointer client_data,
 980                            XEvent* event, Boolean* continue_to_dispatch) {
 981     timeStampUpdated = True;
 982 }
 983 
 984 /*
 985  * If the application doesn't receive events with timestamp for a long time
 986  * XtLastTimestampProcessed() will return out-of-date value. This may cause
 987  * selection handling routines to fail (see BugTraq ID 4085183).
 988  * This routine is to resolve this problem. It queries the current X server
 989  * time by appending a zero-length data to a property as prescribed by
 990  * X11 Reference Manual.
 991  * Note that this is a round-trip request, so it can be slow. If you know
 992  * that the Xt timestamp is up-to-date use XtLastTimestampProcessed().
 993  */
 994 Time
 995 awt_util_getCurrentServerTime() {
 996 
 997     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 998     static Atom _XA_JAVA_TIME_PROPERTY_ATOM = 0;
 999     Time server_time = 0;
1000 
1001     AWT_LOCK();
1002 
1003     if (_XA_JAVA_TIME_PROPERTY_ATOM == 0) {
1004         XtAddEventHandler(awt_root_shell, PropertyChangeMask, False,
1005                           propertyChangeEventHandler, NULL);
1006         _XA_JAVA_TIME_PROPERTY_ATOM = XInternAtom(awt_display, "_SUNW_JAVA_AWT_TIME", False);
1007     }
1008 
1009     timeStampUpdated = False;
1010     XChangeProperty(awt_display, XtWindow(awt_root_shell),
1011                     _XA_JAVA_TIME_PROPERTY_ATOM, XA_ATOM, 32, PropModeAppend,
1012                     (unsigned char *)"", 0);
1013     XFlush(awt_display);
1014 
1015     if (awt_currentThreadIsPrivileged(env)) {
1016         XEvent event;
1017         XMaskEvent(awt_display, PropertyChangeMask, &event);
1018         XtDispatchEvent(&event);
1019     } else {
1020         awt_MToolkit_modalWait(isTimeStampUpdated, NULL);
1021     }
1022     server_time = XtLastTimestampProcessed(awt_display);
1023 
1024     AWT_UNLOCK();
1025 
1026     return server_time;
1027 }
1028 
1029 /*
1030  * This function is stolen from /src/solaris/hpi/src/system_md.c
1031  * It is used in setting the time in Java-level InputEvents
1032  */
1033 jlong
1034 awt_util_nowMillisUTC()
1035 {
1036     struct timeval t;
1037     gettimeofday(&t, NULL);
1038     return ((jlong)t.tv_sec) * 1000 + (jlong)(t.tv_usec/1000);
1039 }
1040 
1041 /*
1042  * This function converts between the X server time (number of milliseconds
1043  * since the last server reset) and the UTC time for the 'when' field of an
1044  * InputEvent (or another event type with a timestamp).
1045  */
1046 jlong
1047 awt_util_nowMillisUTC_offset(Time server_offset)
1048 {
1049     /*
1050      * Because Time is of type 'unsigned long', it is possible that Time will
1051      * never wrap when using 64-bit Xlib. However, if a 64-bit client
1052      * connects to a 32-bit server, I suspect the values will still wrap. So
1053      * we should not attempt to remove the wrap checking even if _LP64 is
1054      * true.
1055      */
1056     static const jlong WRAP_TIME_MILLIS = (jlong)((uint32_t)-1);
1057     static jlong reset_time_utc;
1058 
1059     jlong current_time_utc = awt_util_nowMillisUTC();
1060 
1061     if ((current_time_utc - reset_time_utc) > WRAP_TIME_MILLIS) {
1062         reset_time_utc = awt_util_nowMillisUTC() -
1063             awt_util_getCurrentServerTime();
1064     }
1065 
1066     return reset_time_utc + server_offset;
1067 }
1068 
1069 void awt_util_do_wheel_scroll(Widget scrolled_window, jint scrollType,
1070                               jint scrollAmt, jint wheelAmt) {
1071     Widget scrollbar = NULL;
1072     int value;
1073     int slider_size;
1074     int min;
1075     int max;
1076     int increment;
1077     int page_increment;
1078     int scrollAdjustment;
1079     int newValue;
1080 
1081     /* TODO:
1082      * If a TextArea's scrollbar policy is set to never, it should still
1083      * wheel scroll, but right now it doesn't.
1084      */
1085 
1086     scrollbar = awt_util_get_scrollbar_to_scroll(scrolled_window);
1087     if (scrollbar == NULL) { /* no suitable scrollbar for scrolling */
1088         return;
1089     }
1090 
1091     XtVaGetValues(scrollbar, XmNvalue, &value,
1092                              XmNsliderSize, &slider_size,
1093                              XmNminimum, &min,
1094                              XmNmaximum, &max,
1095                              XmNincrement, &increment,
1096                              XmNpageIncrement, &page_increment, NULL);
1097 
1098     if (scrollType == java_awt_event_MouseWheelEvent_WHEEL_BLOCK_SCROLL) {
1099         scrollAdjustment = page_increment;
1100     }
1101     else { // WHEEL_UNIT_SCROLL
1102         scrollAdjustment = increment * scrollAmt;
1103     }
1104 
1105     if (wheelAmt < 0) {
1106         // Don't need to check that newValue < max - slider_size because
1107         // newValue < current value.  If scrollAmt is ever user-configurable,
1108         // we'll have to check this.
1109         newValue = MAX(min, value+ (scrollAdjustment * wheelAmt));
1110     }
1111     else {
1112         newValue = MIN(max - slider_size,
1113                        value + (scrollAdjustment * wheelAmt));
1114     }
1115 
1116     XtVaSetValues(scrollbar, XmNvalue, newValue, NULL);
1117     XtCallCallbacks(scrollbar, XmNvalueChangedCallback, NULL);
1118 }
1119 
1120 
1121 /* Given a ScrollWindow widget, return the Scrollbar that the wheel should
1122  * scroll.  A null return value means that the ScrollWindow has a scrollbar
1123  * display policy of none, or that neither scrollbar can be scrolled.
1124  */
1125 Widget awt_util_get_scrollbar_to_scroll(Widget scrolled_window) {
1126     Widget scrollbar = NULL;
1127     int value;
1128     int slider_size;
1129     int min;
1130     int max;
1131 
1132     /* first, try the vertical scrollbar */
1133     XtVaGetValues(scrolled_window, XmNverticalScrollBar, &scrollbar, NULL);
1134     if (scrollbar != NULL) {
1135         XtVaGetValues(scrollbar, XmNvalue, &value,
1136                                  XmNsliderSize, &slider_size,
1137                                  XmNminimum, &min,
1138                                  XmNmaximum, &max, NULL);
1139         if (slider_size < max - min) {
1140             return scrollbar;
1141         }
1142     }
1143 
1144     /* then, try the horiz */
1145     XtVaGetValues(scrolled_window, XmNhorizontalScrollBar, &scrollbar, NULL);
1146     if (scrollbar != NULL) {
1147         XtVaGetValues(scrollbar, XmNvalue, &value,
1148                                  XmNsliderSize, &slider_size,
1149                                  XmNminimum, &min,
1150                                  XmNmaximum, &max, NULL);
1151         if (slider_size < max - min) {
1152             return scrollbar;
1153         }
1154     }
1155     /* neither is suitable for scrolling */
1156     return NULL;
1157 }
1158 
1159 EmbeddedFrame *theEmbeddedFrameList = NULL;
1160 
1161 static void awt_util_updateXtCoordinatesForEmbeddedFrame(Widget ef)
1162 {
1163     Window ef_window;
1164     Window win;
1165     int32_t x, y;
1166     ef_window = XtWindow(ef);
1167     if (ef_window != None) {
1168         if (XTranslateCoordinates(awt_display, ef_window,
1169             RootWindowOfScreen(XtScreen(ef)),
1170             0, 0, &x, &y, &win)) {
1171             DTRACE_PRINTLN("correcting coordinates");
1172             ef->core.x = x;
1173             ef->core.y = y;
1174         }
1175     }
1176 }
1177 
1178 Boolean awt_util_processEventForEmbeddedFrame(XEvent *ev)
1179 {
1180     EmbeddedFrame *ef;
1181     Boolean dummy;
1182     Boolean eventProcessed = False;
1183     switch (ev->type) {
1184     case FocusIn:
1185     case FocusOut:
1186         ef = theEmbeddedFrameList;
1187         while (ef != NULL) {
1188             if (ef->frameContainer == ev->xfocus.window) {
1189                 eventProcessed = True;
1190                 if (isXEmbedActiveByWindow(XtWindow(ef->embeddedFrame))) {
1191                     return True;
1192                 }
1193                 // pretend that the embedded frame gets a focus event
1194                 // the event's window field is not the same as
1195                 // the embeddedFrame's widget, but luckily the shellEH
1196                 // doesnt seem to care about this.
1197                 shellEH(ef->embeddedFrame, ef->javaRef, ev, &dummy);
1198             }
1199             ef = ef->next;
1200         }
1201         return eventProcessed;
1202     case ConfigureNotify:
1203         for (ef = theEmbeddedFrameList; ef != NULL; ef = ef->next) {
1204             awt_util_updateXtCoordinatesForEmbeddedFrame(ef->embeddedFrame);
1205         }
1206         return True;
1207     }
1208     return False;
1209 }
1210 
1211 void awt_util_addEmbeddedFrame(Widget embeddedFrame, jobject javaRef)
1212 {
1213     EmbeddedFrame *ef, *eflist;
1214     Atom WM_STATE;
1215     Window win;
1216     Window parent, root;
1217     Window *children;
1218     uint32_t nchildren;
1219     Atom type = None;
1220     int32_t format;
1221     unsigned long nitems, after;
1222     unsigned char * data;
1223     XWindowAttributes win_attributes;
1224 
1225     WM_STATE = XInternAtom(awt_display, "WM_STATE", True);
1226     if (WM_STATE == None) {
1227         return;
1228     }
1229     win = XtWindow(embeddedFrame);
1230     if (win == None)
1231         return;
1232     /*
1233      * according to XICCM, we search our toplevel window
1234      * by looking for WM_STATE property
1235      */
1236     while (True) {
1237         if (!XQueryTree(awt_display, win, &root, &parent,
1238             &children, &nchildren)) {
1239             return;
1240         }
1241         if (children) {
1242             XFree(children);
1243         }
1244         if (parent == NULL || parent == root) {
1245             return;
1246         }
1247         win = parent;
1248         /*
1249          * Add StructureNotifyMask through hierarchy upto toplevel
1250          */
1251         XGetWindowAttributes(awt_display, win, &win_attributes);
1252         XSelectInput(awt_display, win, win_attributes.your_event_mask |
1253                 StructureNotifyMask);
1254 
1255         if (XGetWindowProperty(awt_display, win, WM_STATE,
1256                 0, 0, False, AnyPropertyType,
1257                 &type, &format, &nitems, &after, &data) == Success) {
1258             XFree(data);
1259             if (type) {
1260                 break;
1261             }
1262         }
1263     }
1264     ef = (EmbeddedFrame *) malloc(sizeof(EmbeddedFrame));
1265     if (ef == NULL) {
1266         JNU_ThrowOutOfMemoryError((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2),
1267             "OutOfMemory in awt_util_addEmbeddedFrame");
1268         return;
1269     }
1270     ef->embeddedFrame = embeddedFrame;
1271     ef->frameContainer = win;
1272     ef->javaRef = javaRef;
1273     ef->eventSelectedPreviously = False;
1274     /* initialize the xt coordinates */
1275     awt_util_updateXtCoordinatesForEmbeddedFrame(embeddedFrame);
1276 
1277     /*
1278      * go through the exisiting embedded frames see if we have
1279      * already selected the event on the same frameContainer
1280      */
1281     eflist = theEmbeddedFrameList;
1282     while (eflist != NULL) {
1283         if (eflist->frameContainer == win) {
1284             break;
1285         }
1286         eflist = eflist->next;
1287     }
1288     if (eflist != NULL) {
1289         /*
1290          * we already have a embedded frame selecting this container's
1291          * event, we remember its eventSelectedPreviously value
1292          * so that we know whether to deselect later when we are removed
1293          */
1294         ef->eventSelectedPreviously = eflist->eventSelectedPreviously;
1295     } else {
1296         XGetWindowAttributes(awt_display, ef->frameContainer,
1297             &win_attributes);
1298         XSelectInput(awt_display, ef->frameContainer,
1299                      win_attributes.your_event_mask | FocusChangeMask);
1300     }
1301 
1302     /* ef will become the head of the embedded frame list */
1303     ef->next = theEmbeddedFrameList;
1304     if (theEmbeddedFrameList != NULL) {
1305         theEmbeddedFrameList->prev = ef;
1306     }
1307     ef->prev = NULL;
1308     theEmbeddedFrameList = ef;
1309 }
1310 
1311 void awt_util_delEmbeddedFrame(Widget embeddedFrame)
1312 {
1313     EmbeddedFrame *ef = theEmbeddedFrameList;
1314     Window frameContainer;
1315     XWindowAttributes win_attributes;
1316     Boolean needToDeselect;
1317 
1318     while (ef != NULL) {
1319         if (ef->embeddedFrame == embeddedFrame) {
1320             break;
1321         }
1322         ef = ef->next;
1323     }
1324     if (ef == NULL) { /* cannot find specified embedded frame */
1325         return;
1326     }
1327     /* remove ef from link list EmbeddedFrameList */
1328     if (ef->prev) {
1329         ef->prev->next = ef->next;
1330     }
1331     if (ef->next) {
1332         ef->next->prev = ef->prev;
1333     }
1334     if (theEmbeddedFrameList == ef) {
1335         theEmbeddedFrameList = ef->next;
1336     }
1337 
1338     frameContainer = ef->frameContainer;
1339     needToDeselect = ef->eventSelectedPreviously ? False : True;
1340     free(ef);
1341     if (!needToDeselect) {
1342         return;
1343     }
1344     /*
1345      * now decide whether we need to stop listenning event for
1346      * frameContainer
1347      */
1348     ef = theEmbeddedFrameList;
1349     while (ef != NULL) {
1350         if (ef->frameContainer == frameContainer) {
1351             break;
1352         }
1353         ef = ef->next;
1354     }
1355     if (ef == NULL)  {
1356         /*
1357          * if we get here, no one is interested in this frame
1358          * and StructureNotify was not selected by anyone else
1359          * so we deselect it
1360          */
1361         DTRACE_PRINTLN("remove event from frame");
1362         XGetWindowAttributes(awt_display, frameContainer, &win_attributes);
1363         XSelectInput(awt_display, frameContainer,
1364             win_attributes.your_event_mask &
1365                 (~FocusChangeMask));
1366     }
1367 }
1368 
1369 #endif /* XAWT */
1370 
1371 void awt_util_debug_init() {
1372 #if defined(DEBUG)
1373     DTrace_Initialize();
1374 #endif
1375 }
1376 
1377 static void awt_util_debug_fini() {
1378 #if defined(DEBUG)
1379     DTrace_Shutdown();
1380 #endif
1381 }