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