1 /*
   2  * Copyright (c) 2003, 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 // TODO: Propogate applicationActive from Java
  27 
  28 #ifdef HEADLESS
  29     #error This file should not be included in headless library
  30 #endif
  31 
  32 #include "awt_p.h"
  33 
  34 #include <X11/Xproto.h>
  35 #include <X11/Xlib.h>
  36 #include <X11/Xatom.h>
  37 #include <Xm/MwmUtil.h>
  38 #ifdef __linux__
  39 #include <execinfo.h>
  40 #endif
  41 #include <stdio.h>
  42 #include <stdlib.h>
  43 
  44 /* JNI headers */
  45 #include "java_awt_Frame.h"     /* for frame state constants */
  46 #include "java_awt_event_KeyEvent.h"
  47 #include "awt_wm.h"
  48 #include "awt_util.h"           /* for X11 error handling macros */
  49 #include "awt_xembed.h"
  50 #include "awt_Component.h"
  51 #include "awt_AWTEvent.h"
  52 #include "canvas.h"
  53 #include "sun_awt_motif_MEmbedCanvasPeer.h"
  54 
  55 #ifdef DOTRACE
  56 #define MTRACE(param) fprintf(stderr, param)
  57 #define MTRACEP1(format, p1) fprintf(stderr, format, p1)
  58 #define MTRACEP2(format, p1, p2) fprintf(stderr, format, p1, p2)
  59 #define MTRACEP3(format, p1, p2, p3) fprintf(stderr, format, p1, p2, p3)
  60 #define MTRACEP4(format, p1, p2, p3, p4) fprintf(stderr, format, p1, p2, p3, p4)
  61 #define MTRACEP5(format, p1, p2, p3, p4, p5) fprintf(stderr, format, p1, p2, p3, p4, p5)
  62 #define MTRACEP6(format, p1, p2, p3, p4, p5, p6) fprintf(stderr, format, p1, p2, p3, p4, p5, p6)
  63 #define MTRACEP7(format, p1, p2, p3, p4, p5, p6, p7) fprintf(stderr, format, p1, p2, p3, p4, p5, p6, p7)
  64 #else
  65 #define MTRACE(param)
  66 #define MTRACEP1(format, p1)
  67 #define MTRACEP2(format, p1, p2)
  68 #define MTRACEP3(format, p1, p2, p3)
  69 #define MTRACEP4(format, p1, p2, p3, p4)
  70 #define MTRACEP5(format, p1, p2, p3, p4, p5)
  71 #define MTRACEP6(format, p1, p2, p3, p4, p5, p6)
  72 #define MTRACEP7(format, p1, p2, p3, p4, p5, p6, p7)
  73 #endif
  74 
  75 /**************************** XEmbed server DnD support ***********************/
  76 extern Atom XA_XdndAware;
  77 extern Boolean
  78 register_xembed_drop_site(JNIEnv* env, Display* dpy, jobject server,
  79                           Window serverHandle, Window clientHandle);
  80 extern Boolean
  81 unregister_xembed_drop_site(JNIEnv* env, Display* dpy, jobject server,
  82                             Window serverHandle, Window clientHandle);
  83 extern void
  84 forward_event_to_embedded(Window embedded, jlong ctxt, jint eventID);
  85 
  86 extern const char * msg_to_str(int msg);
  87 
  88 void
  89 set_xembed_drop_target(JNIEnv* env, jobject server);
  90 void
  91 remove_xembed_drop_target(JNIEnv* env, jobject server);
  92 Boolean
  93 is_xembed_client(Window window);
  94 /******************************************************************************/
  95 extern struct MComponentPeerIDs mComponentPeerIDs;
  96 static jobject createRectangle(JNIEnv* env, int x, int y, int width, int height);
  97 static jobject createDimension(JNIEnv* env, int width, int height);
  98 static void processXEmbedInfo(JNIEnv* env, jobject this);
  99 static Atom XA_XEmbedInfo;
 100 static Atom XA_XEmbed;
 101 static jmethodID requestXEmbedFocusMID, focusNextMID, focusPrevMID,
 102     registerAcceleratorMID, unregisterAcceleratorMID,
 103     grabKeyMID, ungrabKeyMID, childResizedMID,
 104     setXEmbedDropTargetMID, removeXEmbedDropTargetMID;
 105 static jfieldID keysymFID, modifiersFID, applicationActiveFID;
 106 
 107 typedef struct _xembed_server_data {
 108     Window handle; // pointer to plugin intermediate widget, XEmbed client
 109     Window serverHandle;
 110     Widget serverWidget;
 111     Boolean dispatching; // whether we dispatch messages for handle
 112     int version;
 113     jobject server;
 114     struct _xembed_server_data * next;
 115 } xembed_server_data, * pxembed_server_data;
 116 
 117 static pxembed_server_data xembed_list = NULL;
 118 
 119 static pxembed_server_data
 120 getData(Window handle) {
 121     pxembed_server_data temp = xembed_list;
 122     while (temp != NULL) {
 123         if (temp->handle == handle) {
 124             return temp;
 125         }
 126         temp = temp->next;
 127     }
 128     return NULL;
 129 }
 130 
 131 static pxembed_server_data
 132 getDataByEmbedder(jobject server) {
 133     JNIEnv      *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 134     pxembed_server_data temp = xembed_list;
 135     DASSERT(server != NULL);
 136     while (temp != NULL) {
 137         if ((*env)->IsSameObject(env, temp->server, server)) {
 138             return temp;
 139         }
 140         temp = temp->next;
 141     }
 142     return NULL;
 143 }
 144 
 145 static pxembed_server_data
 146 getDataByServerHandle(Window serverHandle) {
 147     JNIEnv      *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 148     pxembed_server_data temp = xembed_list;
 149     Widget serverWidget = NULL;
 150     if (serverHandle == None) {
 151         return NULL;
 152     }
 153     serverWidget = XtWindowToWidget(awt_display, serverHandle);
 154     while (temp != NULL) {
 155         if (temp->serverHandle == serverHandle || temp->serverWidget == serverWidget) {
 156             temp->serverHandle = serverWidget;
 157             return temp;
 158         }
 159         temp = temp->next;
 160     }
 161     return NULL;
 162 }
 163 
 164 static pxembed_server_data
 165 addData(jobject server) {
 166     JNIEnv      *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 167     struct ComponentData *cdata;
 168     xembed_server_data * data = malloc(sizeof(xembed_server_data));
 169     DASSERT(server != NULL);
 170     memset(data, 0, sizeof(xembed_server_data));
 171     data->server = server;
 172     cdata = (struct ComponentData *)
 173         JNU_GetLongFieldAsPtr(env, server, mComponentPeerIDs.pData);
 174     DASSERT(cdata != NULL);
 175     data->serverHandle = XtWindow(cdata->widget);
 176     data->serverWidget = cdata->widget;
 177     data->next = xembed_list;
 178     xembed_list = data;
 179     return data;
 180 }
 181 
 182 static void
 183 removeData(jobject server) {
 184     JNIEnv      *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 185     pxembed_server_data * temp = &xembed_list;
 186     DASSERT(server != NULL);
 187     while (*temp != NULL) {
 188         if ((*env)->IsSameObject(env, (*temp)->server, server)) {
 189             xembed_server_data * data = *temp;
 190             *temp = (*temp)->next;
 191             DASSERT(data->server != NULL);
 192             (*env)->DeleteGlobalRef(env, data->server);
 193             free(data);
 194             return;
 195         }
 196         temp = &(*temp)->next;
 197     }
 198 }
 199 
 200 void
 201 initXEmbedServerData() {
 202     JNIEnv      *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 203     jclass clazz;
 204     MTRACE("initXEmbedServerData\n");
 205     XA_XEmbedInfo = XInternAtom(awt_display, "_XEMBED_INFO", False);
 206     XA_XEmbed = XInternAtom(awt_display, "_XEMBED", False);
 207 
 208     clazz = (*env)->FindClass(env, "sun/awt/motif/MEmbedCanvasPeer");
 209     DASSERT(clazz != NULL);
 210     requestXEmbedFocusMID = (*env)->GetMethodID(env, clazz, "requestXEmbedFocus", "()V");
 211     DASSERT(requestXEmbedFocusMID != NULL);
 212     focusNextMID = (*env)->GetMethodID(env, clazz, "focusNext", "()V");
 213     DASSERT(focusNextMID != NULL);
 214     focusPrevMID = (*env)->GetMethodID(env, clazz, "focusPrev", "()V");
 215     DASSERT(focusPrevMID != NULL);
 216     registerAcceleratorMID = (*env)->GetMethodID(env, clazz, "registerAccelerator", "(JJJ)V");
 217     DASSERT(registerAcceleratorMID != NULL);
 218     unregisterAcceleratorMID = (*env)->GetMethodID(env, clazz, "unregisterAccelerator", "(J)V");
 219     DASSERT(unregisterAcceleratorMID != NULL);
 220     grabKeyMID = (*env)->GetMethodID(env, clazz, "grabKey", "(JJ)V");
 221     DASSERT(grabKeyMID != NULL);
 222     ungrabKeyMID = (*env)->GetMethodID(env, clazz, "ungrabKey", "(JJ)V");
 223     DASSERT(ungrabKeyMID != NULL);
 224     childResizedMID = (*env)->GetMethodID(env, clazz, "childResized", "()V");
 225     DASSERT(childResizedMID != NULL);
 226     setXEmbedDropTargetMID =
 227         (*env)->GetMethodID(env, clazz, "setXEmbedDropTarget", "()V");
 228     DASSERT(setXEmbedDropTargetMID != NULL);
 229     removeXEmbedDropTargetMID =
 230         (*env)->GetMethodID(env, clazz, "removeXEmbedDropTarget", "()V");
 231     DASSERT(removeXEmbedDropTargetMID != NULL);
 232 
 233     applicationActiveFID = (*env)->GetFieldID(env, clazz, "applicationActive", "Z");
 234     DASSERT(applicationActiveFID != NULL);
 235     (*env)->DeleteLocalRef(env, clazz);
 236 
 237     clazz = (*env)->FindClass(env, "sun/awt/motif/GrabbedKey");
 238     DASSERT(clazz != NULL);
 239     keysymFID = (*env)->GetFieldID(env, clazz, "keysym", "J");
 240     DASSERT(keysymFID != NULL);
 241     modifiersFID = (*env)->GetFieldID(env, clazz, "modifiers", "J");
 242     DASSERT(modifiersFID != NULL);
 243     (*env)->DeleteLocalRef(env, clazz);
 244 }
 245 
 246 /*
 247  * Class:     sun_awt_motif_MEmbedCanvasPeer
 248  * Method:    initXEmbedServer
 249  * Signature: ()V
 250  */
 251 JNIEXPORT void JNICALL
 252 Java_sun_awt_motif_MEmbedCanvasPeer_initXEmbedServer(JNIEnv *env, jobject this) {
 253     struct ComponentData *cdata;
 254     AWT_LOCK();
 255     MTRACE("initXEmbedServer\n");
 256     addData((*env)->NewGlobalRef(env, this));
 257     if (XA_XEmbedInfo == None) {
 258         initXEmbedServerData();
 259     }
 260     cdata = (struct ComponentData *)
 261         JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData);
 262 /*     XSelectInput(awt_display, XtWindow(cdata->widget), SubstructureNotifyMask); */
 263     XtAddEventHandler(cdata->widget,
 264                       SubstructureNotifyMask,
 265                       False, null_event_handler, NULL);
 266     AWT_UNLOCK();
 267 }
 268 
 269 /*
 270  * Class:     sun_awt_motif_MEmbedCanvasPeer
 271  * Method:    destroyXEmbedServer
 272  * Signature: ()V
 273  */
 274 JNIEXPORT void JNICALL
 275 Java_sun_awt_motif_MEmbedCanvasPeer_destroyXEmbedServer(JNIEnv *env, jobject this) {
 276     AWT_LOCK();
 277     MTRACE("destroyXEmbedServer\n");
 278     removeData(this);
 279     AWT_UNLOCK();
 280 }
 281 
 282 /*
 283  * Class:     sun_awt_motif_MEmbedCanvasPeer
 284  * Method:    isXEmbedActive
 285  * Signature: ()Z
 286  */
 287 JNIEXPORT jboolean JNICALL
 288 Java_sun_awt_motif_MEmbedCanvasPeer_isXEmbedActive(JNIEnv *env, jobject this) {
 289     pxembed_server_data sdata;
 290     jboolean res = JNI_FALSE;
 291     AWT_LOCK();
 292     sdata = getDataByEmbedder(this);
 293     if (sdata != NULL) {
 294         res = (sdata->handle != None)?JNI_TRUE:JNI_FALSE;
 295     }
 296     AWT_UNLOCK();
 297     return res;
 298 }
 299 
 300 /*
 301  * Class:     sun_awt_motif_MEmbedCanvasPeer
 302  * Method:    initDispatching
 303  * Signature: ()V
 304  */
 305 JNIEXPORT void JNICALL
 306 Java_sun_awt_motif_MEmbedCanvasPeer_initDispatching (JNIEnv *env, jobject this) {
 307     pxembed_server_data sdata;
 308     AWT_LOCK();
 309     MTRACE("initDispatching\n");
 310     sdata = getDataByEmbedder(this);
 311     if (sdata != NULL) {
 312         XSelectInput(awt_display, sdata->handle, StructureNotifyMask | PropertyChangeMask);
 313         sdata->dispatching = True;
 314         register_xembed_drop_site(env, awt_display, sdata->server,
 315                                   sdata->serverHandle, sdata->handle);
 316     }
 317     processXEmbedInfo(env, this);
 318     Java_sun_awt_motif_MEmbedCanvasPeer_notifyChildEmbedded(env, this);
 319     AWT_UNLOCK();
 320 }
 321 
 322 /*
 323  * Class:     sun_awt_motif_MEmbedCanvasPeer
 324  * Method:    endDispatching
 325  * Signature: ()V
 326  */
 327 JNIEXPORT void JNICALL
 328 Java_sun_awt_motif_MEmbedCanvasPeer_endDispatching (JNIEnv *env, jobject this) {
 329     pxembed_server_data sdata;
 330     AWT_LOCK();
 331     MTRACE("endDispatching\n");
 332     sdata = getDataByEmbedder(this);
 333     if (sdata != NULL) {
 334         unregister_xembed_drop_site(env, awt_display, sdata->server,
 335                                     sdata->serverHandle, sdata->handle);
 336         sdata->dispatching = False;
 337     }
 338     AWT_UNLOCK();
 339 }
 340 
 341 /*
 342  * Class:     sun_awt_motif_MEmbedCanvasPeer
 343  * Method:    embedChild
 344  * Signature: (J)V
 345  */
 346 JNIEXPORT void JNICALL
 347 Java_sun_awt_motif_MEmbedCanvasPeer_embedChild (JNIEnv * env, jobject this, jlong handle) {
 348     pxembed_server_data sdata;
 349     AWT_LOCK();
 350     MTRACE("embedChild\n");
 351     sdata = getDataByEmbedder(this);
 352     if (sdata != NULL) {
 353         if (sdata->handle != None) {
 354             Java_sun_awt_motif_MEmbedCanvasPeer_detachChild(env, this);
 355         }
 356         sdata->handle = (Window)handle;
 357         Java_sun_awt_motif_MEmbedCanvasPeer_initDispatching(env, this);
 358     }
 359     AWT_UNLOCK();
 360 }
 361 
 362 /*
 363  * Class:     sun_awt_motif_MEmbedCanvasPeer
 364  * Method:    childDestroyed
 365  * Signature: ()V
 366  */
 367 JNIEXPORT void JNICALL
 368 Java_sun_awt_motif_MEmbedCanvasPeer_childDestroyed (JNIEnv *env, jobject this) {
 369     pxembed_server_data sdata;
 370     AWT_LOCK();
 371     MTRACE("childDestroyed\n");
 372     Java_sun_awt_motif_MEmbedCanvasPeer_endDispatching(env, this);
 373     sdata = getDataByEmbedder(this);
 374     if (sdata != NULL) {
 375         sdata->handle = None;
 376     }
 377     AWT_UNLOCK();
 378 }
 379 
 380 /*
 381  * Class:     sun_awt_motif_MEmbedCanvasPeer
 382  * Method:    getEmbedPreferredSize
 383  * Signature: ()Ljava/awt/Dimension;
 384  */
 385 JNIEXPORT jobject JNICALL
 386 Java_sun_awt_motif_MEmbedCanvasPeer_getEmbedPreferredSize (JNIEnv *env, jobject this) {
 387     pxembed_server_data sdata;
 388     jobject res = NULL;
 389     XSizeHints * hints;
 390     long dummy;
 391     AWT_LOCK();
 392     MTRACE("getPreferredSize\n");
 393     sdata = getDataByEmbedder(this);
 394     if (sdata != NULL) {
 395         hints = XAllocSizeHints();
 396         DASSERT(hints != NULL);
 397         DASSERT(sdata->handle != None);
 398         if (XGetWMNormalHints(awt_display, sdata->handle, hints, &dummy) == Success) {
 399             res = createDimension(env, hints->width, hints->height);
 400         }
 401         XFree(hints);
 402     }
 403     AWT_UNLOCK();
 404     return res;
 405 }
 406 
 407 /*
 408  * Class:     sun_awt_motif_MEmbedCanvasPeer
 409  * Method:    getEmbedMinimumSize
 410  * Signature: ()Ljava/awt/Dimension;
 411  */
 412 JNIEXPORT jobject JNICALL
 413 Java_sun_awt_motif_MEmbedCanvasPeer_getEmbedMinimumSize (JNIEnv *env, jobject this) {
 414     pxembed_server_data sdata;
 415     jobject res = NULL;
 416     XSizeHints * hints;
 417     long dummy;
 418     AWT_LOCK();
 419     MTRACE("getMinimumSize\n");
 420     sdata = getDataByEmbedder(this);
 421     if (sdata != NULL) {
 422         hints = XAllocSizeHints();
 423         DASSERT(hints != NULL);
 424         DASSERT(sdata->handle != None);
 425         if (XGetWMNormalHints(awt_display, sdata->handle, hints, &dummy) == Success) {
 426             res = createDimension(env, hints->min_width, hints->min_height);
 427         }
 428         XFree(hints);
 429     }
 430     AWT_UNLOCK();
 431     return res;
 432 }
 433 
 434 /*
 435  * Class:     sun_awt_motif_MEmbedCanvasPeer
 436  * Method:    getClientBounds
 437  * Signature: ()Ljava/awt/Rectangle;
 438  */
 439 JNIEXPORT jobject JNICALL
 440 Java_sun_awt_motif_MEmbedCanvasPeer_getClientBounds (JNIEnv *env, jobject this) {
 441     pxembed_server_data sdata;
 442     jobject res = NULL;
 443     AWT_LOCK();
 444     MTRACE("getClientBounds\n");
 445     sdata = getDataByEmbedder(this);
 446     if (sdata != NULL) {
 447         XWindowAttributes attrs;
 448         DASSERT(sdata->handle != None);
 449         if (XGetWindowAttributes(awt_display, sdata->handle, &attrs) == Success) {
 450             res = createRectangle(env, attrs.x, attrs.y, attrs.width, attrs.height);
 451         }
 452     }
 453     AWT_UNLOCK();
 454     return res;
 455 }
 456 
 457 Boolean
 458 isApplicationActive(JNIEnv * env, jobject this) {
 459     return (*env)->GetBooleanField(env, this, applicationActiveFID);
 460 }
 461 
 462 /*
 463  * Class:     sun_awt_motif_MEmbedCanvasPeer
 464  * Method:    notifyChildEmbedded
 465  * Signature: ()V
 466  */
 467 JNIEXPORT void JNICALL
 468 Java_sun_awt_motif_MEmbedCanvasPeer_notifyChildEmbedded (JNIEnv *env, jobject this) {
 469     struct ComponentData *cdata;
 470     pxembed_server_data sdata;
 471     AWT_LOCK();
 472     MTRACE("notifyChildEmbedded\n");
 473     cdata = (struct ComponentData *)
 474         JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData);
 475     sdata = getDataByEmbedder(this);
 476     if (sdata != NULL) {
 477         DASSERT(sdata->handle != None);
 478         DASSERT(cdata != NULL);
 479         DASSERT(XtWindow(cdata->widget) != None);
 480         sendMessageHelper(sdata->handle, XEMBED_EMBEDDED_NOTIFY, XtWindow(cdata->widget), min(sdata->version, XEMBED_VERSION), 0);
 481         if (isApplicationActive(env, this)) {
 482             sendMessage(sdata->handle, XEMBED_WINDOW_ACTIVATE);
 483         }
 484     }
 485     AWT_UNLOCK();
 486 }
 487 
 488 /*
 489  * Class:     sun_awt_motif_MEmbedCanvasPeer
 490  * Method:    detachChild
 491  * Signature: ()V
 492  */
 493 JNIEXPORT void JNICALL
 494 Java_sun_awt_motif_MEmbedCanvasPeer_detachChild (JNIEnv *env, jobject this) {
 495     pxembed_server_data sdata;
 496     AWT_LOCK();
 497     MTRACE("detachChild\n");
 498     sdata = getDataByEmbedder(this);
 499     if (sdata != NULL) {
 500         /**
 501          *  XEmbed specification:
 502          *  "The embedder can unmap the client and reparent the client window to the root window. If the
 503          *  client receives an ReparentNotify event, it should check the parent field of the XReparentEvent
 504          *  structure. If this is the root window of the window's screen, then the protocol is finished and
 505          *  there is no further interaction. If it is a window other than the root window, then the protocol
 506          *  continues with the new parent acting as the embedder window."
 507          */
 508         DASSERT(sdata->handle != None);
 509         XUnmapWindow(awt_display, sdata->handle);
 510         XReparentWindow(awt_display, sdata->handle, DefaultRootWindow(awt_display), 0, 0);
 511         Java_sun_awt_motif_MEmbedCanvasPeer_endDispatching(env, this);
 512         sdata->handle = None;
 513     }
 514     AWT_UNLOCK();
 515 }
 516 
 517 /*
 518  * Class:     sun_awt_motif_MEmbedCanvasPeer
 519  * Method:    forwardKeyEvent
 520  * Signature: (Ljava/awt/event/KeyEvent;)V
 521  */
 522 JNIEXPORT void JNICALL
 523 Java_sun_awt_motif_MEmbedCanvasPeer_forwardKeyEvent (JNIEnv *env, jobject this, jobject event) {
 524     pxembed_server_data sdata;
 525     jbyteArray array;
 526     XEvent *xevent;
 527     AWT_LOCK();
 528     MTRACE("forwardKeyEvent\n");
 529     sdata = getDataByEmbedder(this);
 530     if (sdata != NULL) {
 531         DASSERT(sdata->handle != None);
 532         array = (jbyteArray)(*env)->GetObjectField(env, event, awtEventIDs.bdata);
 533         if (array == NULL) {
 534             MTRACE("array is null\n");
 535             AWT_UNLOCK();
 536             return;
 537         }
 538 
 539         xevent = (XEvent *)(*env)->GetByteArrayElements(env, array, NULL);
 540         if (xevent == NULL) {
 541             (*env)->DeleteLocalRef(env, array);
 542             MTRACE("xevent is null\n");
 543             AWT_UNLOCK();
 544             return;
 545         }
 546         xevent->xany.window = sdata->handle;
 547         XSendEvent(awt_display, sdata->handle, False, NoEventMask, xevent);
 548         (*env)->DeleteLocalRef(env, array);
 549     }
 550     AWT_UNLOCK();
 551 }
 552 
 553 /*
 554  * Class:     sun_awt_motif_MEmbedCanvasPeer
 555  * Method:    getAWTKeyCodeForKeySym
 556  * Signature: (I)I
 557  */
 558 JNIEXPORT jint JNICALL
 559 Java_sun_awt_motif_MEmbedCanvasPeer_getAWTKeyCodeForKeySym (JNIEnv *env, jobject this, jint keysym) {
 560     jint keycode = java_awt_event_KeyEvent_VK_UNDEFINED;
 561     Boolean mapsToUnicodeChar;
 562     jint keyLocation;
 563     keysymToAWTKeyCode(keysym, &keycode, &mapsToUnicodeChar, &keyLocation);
 564     return keycode;
 565 }
 566 
 567 /*
 568  * Class:     sun_awt_motif_MEmbedCanvasPeer
 569  * Method:    sendMessage
 570  * Signature: (I)V
 571  */
 572 JNIEXPORT void JNICALL
 573 Java_sun_awt_motif_MEmbedCanvasPeer_sendMessage__I (JNIEnv *env, jobject this, jint msg) {
 574     pxembed_server_data sdata;
 575     AWT_LOCK();
 576     MTRACEP2("sendMessage %d(%s)\n", msg, msg_to_str(msg));
 577     sdata = getDataByEmbedder(this);
 578     if (sdata != NULL) {
 579         DASSERT(sdata->handle != None);
 580         sendMessage(sdata->handle, msg);
 581     }
 582     AWT_UNLOCK();
 583 }
 584 
 585 /*
 586  * Class:     sun_awt_motif_MEmbedCanvasPeer
 587  * Method:    sendMessage
 588  * Signature: (IJJJ)V
 589  */
 590 JNIEXPORT void JNICALL
 591 Java_sun_awt_motif_MEmbedCanvasPeer_sendMessage__IJJJ (JNIEnv *env, jobject this, jint msg, jlong detail, jlong data1, jlong data2) {
 592     pxembed_server_data sdata;
 593     AWT_LOCK();
 594     MTRACEP5("sendMessage2 msg %d(%s) detail %d data: %d %d\n", msg, msg_to_str(msg), detail, data1, data2);
 595     sdata = getDataByEmbedder(this);
 596     if (sdata != NULL) {
 597         DASSERT(sdata->handle != None);
 598         sendMessageHelper(sdata->handle, msg, detail, data1, data2);
 599     }
 600     AWT_UNLOCK();
 601 }
 602 
 603 static jobject
 604 createRectangle(JNIEnv* env, int x, int y, int width, int height) {
 605     static jclass clazz;
 606     static jmethodID mid;
 607     jobject rect = NULL;
 608     if (mid == 0) {
 609         jclass l_clazz = (*env)->FindClass(env, "java/awt/Rectangle");
 610         DASSERT(l_clazz != NULL);
 611         mid = (*env)->GetMethodID(env, clazz, "<init>", "(IIII)V");
 612         DASSERT(mid != NULL);
 613         clazz = (*env)->NewGlobalRef(env, l_clazz);
 614         (*env)->DeleteLocalRef(env, l_clazz);
 615     }
 616     if (mid != NULL) {
 617         rect = (*env)->NewObject(env, clazz, mid, x, y, width, height);
 618         if ((*env)->ExceptionOccurred(env)) {
 619             return NULL;
 620         }
 621     }
 622     return rect;
 623 }
 624 
 625 static jobject
 626 createDimension(JNIEnv* env, int width, int height) {
 627     static jclass clazz;
 628     static jmethodID mid;
 629     jobject dim = NULL;
 630     if (mid == 0) {
 631         jclass l_clazz = (*env)->FindClass(env, "java/awt/Dimension");
 632         DASSERT(l_clazz != NULL);
 633         mid = (*env)->GetMethodID(env, clazz, "<init>", "(II)V");
 634         DASSERT(mid != NULL);
 635         clazz = (*env)->NewGlobalRef(env, l_clazz);
 636         (*env)->DeleteLocalRef(env, l_clazz);
 637     }
 638     if (mid != NULL) {
 639         dim = (*env)->NewObject(env, clazz, mid, width, height);
 640         if ((*env)->ExceptionOccurred(env)) {
 641             return NULL;
 642         }
 643     }
 644     return dim;
 645 }
 646 
 647 Boolean isMapped(JNIEnv* env, Window w) {
 648     XWindowAttributes attr;
 649     Status status = 0;
 650     jboolean errorOccurredFlag;
 651     jobject errorHandlerRef;
 652     jobject savedError;
 653     unsigned char xerror_code;
 654 
 655     EXEC_WITH_XERROR_HANDLER(env, "sun/awt/X11/XErrorHandler$IgnoreBadWindowHandler",
 656         "()Lsun/awt/X11/XErrorHandler$IgnoreBadWindowHandler;", JNI_FALSE,
 657         errorHandlerRef, errorOccurredFlag,
 658         status = XGetWindowAttributes(awt_display, w, &attr));
 659     xerror_code = GET_XERROR_CODE(env, savedError);
 660     if (status == 0 || xerror_code != Success) {
 661         return False;
 662     }
 663     return !(attr.map_state == IsUnmapped);
 664 }
 665 
 666 static void
 667 processXEmbedInfo(JNIEnv * env, jobject this) {
 668     pxembed_server_data sdata;
 669     AWT_LOCK();
 670     MTRACE("processXEmbedInfo\n");
 671     sdata = getDataByEmbedder(this);
 672     if (Java_sun_awt_motif_MEmbedCanvasPeer_isXEmbedActive(env, this)) {
 673         Atom actual_type;
 674         int actual_format;
 675         unsigned long nitems;
 676         unsigned long bytes_after;
 677         CARD32 * data = NULL;
 678         DASSERT(sdata->handle != None);
 679         if (XGetWindowProperty(awt_display, sdata->handle, XA_XEmbedInfo,
 680                            0, 2, False, XA_XEmbedInfo, &actual_type,
 681                            &actual_format, &nitems, &bytes_after,
 682                                (unsigned char**)&data) != Success)
 683         {
 684             AWT_UNLOCK();
 685             return;
 686         }
 687         if (actual_type == XA_XEmbedInfo && actual_format == 32
 688             && nitems == 2)
 689         {
 690             CARD32 flags;
 691             Boolean new_mapped, currently_mapped;
 692             sdata->version = *data;
 693             flags = *(data+1);
 694             new_mapped = (flags & XEMBED_MAPPED) != 0;
 695             currently_mapped = isMapped(env, sdata->handle);
 696             if (new_mapped != currently_mapped) {
 697                 if (new_mapped) {
 698                     XMapWindow(awt_display, sdata->handle);
 699                 } else {
 700                     XUnmapWindow(awt_display, sdata->handle);
 701                 }
 702             }
 703         }
 704         if (data != NULL) {
 705             XFree(data);
 706         }
 707     }
 708     AWT_UNLOCK();
 709 }
 710 
 711 /**
 712  * Handles client message on embedder
 713  */
 714 static void
 715 handleClientMessage(JNIEnv* env, jobject this, XClientMessageEvent * ev) {
 716     pxembed_server_data sdata;
 717     AWT_LOCK();
 718     MTRACEP5("handleClientMessage: 0=%ld 1=%ld 2=%ld 3=%ld 4=%ld\n",
 719             ev->data.l[0], ev->data.l[1], ev->data.l[2], ev->data.l[3], ev->data.l[4]);
 720     sdata = getDataByEmbedder(this);
 721     if (sdata != NULL && sdata->handle != None) {
 722         switch ((int)ev->data.l[1]) {
 723           case XEMBED_REQUEST_FOCUS:
 724               MTRACE("REQUEST_FOCUS\n");
 725               (*env)->CallVoidMethod(env, this, requestXEmbedFocusMID);
 726               break;
 727           case XEMBED_FOCUS_NEXT:
 728               MTRACE("FOCUS_NEXT\n");
 729               (*env)->CallVoidMethod(env, this, focusNextMID);
 730               break;
 731           case XEMBED_FOCUS_PREV:
 732               MTRACE("FOCUS_PREV\n");
 733               (*env)->CallVoidMethod(env, this, focusPrevMID);
 734               break;
 735           case XEMBED_REGISTER_ACCELERATOR:
 736               MTRACE("REGISTER_ACCEL\n");
 737               (*env)->CallVoidMethod(env, this, registerAcceleratorMID,
 738                                      (jlong)ev->data.l[2],
 739                                      (jlong)ev->data.l[3],
 740                                      (jlong)ev->data.l[4]);
 741               break;
 742           case XEMBED_UNREGISTER_ACCELERATOR:
 743               MTRACE("UNREGISTER_ACCEL\n");
 744               (*env)->CallVoidMethod(env, this, unregisterAcceleratorMID,
 745                                      (jlong)ev->data.l[2]);
 746               break;
 747           case NON_STANDARD_XEMBED_GTK_GRAB_KEY:
 748               MTRACE("GRAB_KEY\n");
 749               (*env)->CallVoidMethod(env, this, grabKeyMID,
 750                                      (jlong)ev->data.l[3],
 751                                      (jlong)ev->data.l[4]);
 752               break;
 753           case NON_STANDARD_XEMBED_GTK_UNGRAB_KEY:
 754               MTRACE("UNGRAB_KEY\n");
 755               (*env)->CallVoidMethod(env, this, ungrabKeyMID,
 756                                      (jlong)ev->data.l[3],
 757                                      (jlong)ev->data.l[4]);
 758           case _SUN_XEMBED_START:
 759               MTRACE("XEMBED_START\n");
 760               processXEmbedInfo(env, this);
 761               Java_sun_awt_motif_MEmbedCanvasPeer_notifyChildEmbedded(env, this);
 762               break;
 763         }
 764     }
 765     AWT_UNLOCK();
 766 }
 767 
 768 /**
 769  * Handles property changes on xembed client
 770  */
 771 static void
 772 handlePropertyNotify(XPropertyEvent * ev) {
 773     JNIEnv      *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 774     pxembed_server_data sdata;
 775     AWT_LOCK();
 776     MTRACE("handlePropertyNotify\n");
 777     sdata = getData(ev->window);
 778     if (sdata != NULL) {
 779         if (ev->atom == XA_WM_NORMAL_HINTS) {
 780             DASSERT(sdata->server != NULL);
 781             (*env)->CallVoidMethod(env, sdata->server, childResizedMID);
 782             MTRACE("NORMAL_HINTS have changed\n");
 783         } else if (ev->atom == XA_XdndAware) {
 784             unregister_xembed_drop_site(env, awt_display, sdata->server,
 785                                         sdata->serverHandle, sdata->handle);
 786             if (ev->state == PropertyNewValue) {
 787                 register_xembed_drop_site(env, awt_display, sdata->server,
 788                                           sdata->serverHandle, sdata->handle);
 789             }
 790         } else if (ev->atom == XA_XEmbedInfo) {
 791             DASSERT(sdata->server != NULL);
 792             MTRACE("XEMBED_INFO has changed\n");
 793             processXEmbedInfo(env, sdata->server);
 794         }
 795     }
 796     AWT_UNLOCK();
 797 }
 798 
 799 static void
 800 handleConfigureNotify(XConfigureEvent * ev) {
 801     JNIEnv      *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 802     pxembed_server_data sdata;
 803     AWT_LOCK();
 804     MTRACE("handleConfigureNotify\n");
 805     sdata = getData(ev->window);
 806     if (sdata != NULL) {
 807         DASSERT(sdata->server != NULL);
 808         (*env)->CallVoidMethod(env, sdata->server, childResizedMID);
 809     }
 810     AWT_UNLOCK();
 811 }
 812 
 813 /*
 814  * Class:     sun_awt_motif_MEmbedCanvasPeer
 815  * Method:    sendMessage
 816  * Signature: (IJJJ)V
 817  */
 818 JNIEXPORT void JNICALL
 819 Java_sun_awt_motif_GrabbedKey_initKeySymAndModifiers (JNIEnv *env, jobject this, jobject keyevent) {
 820     jbyteArray array;
 821     XEvent *xevent;
 822     int keysym, modifiers;
 823     int keycode;
 824     AWT_LOCK();
 825     array = (jbyteArray)(*env)->GetObjectField(env, keyevent, awtEventIDs.bdata);
 826     if (array == NULL) {
 827         AWT_UNLOCK();
 828         return;
 829     }
 830     xevent = (XEvent *)(*env)->GetByteArrayElements(env, array, NULL);
 831     if (xevent == NULL) {
 832         (*env)->DeleteLocalRef(env, array);
 833         AWT_UNLOCK();
 834         return;
 835     }
 836     keycode = (*env)->GetIntField(env, keyevent, keyEventIDs.keyCode);
 837     keysym = awt_getX11KeySym(keycode);
 838     modifiers = xevent->xkey.state;
 839     (*env)->SetLongField(env, this, keysymFID, (jlong)keysym);
 840     (*env)->SetLongField(env, this, modifiersFID, (jlong)modifiers);
 841     (*env)->DeleteLocalRef(env, array);
 842     AWT_UNLOCK();
 843 }
 844 
 845 #ifdef __linux__
 846 void
 847 print_stack (void)
 848 {
 849   void *array[10];
 850   size_t size;
 851   char **strings;
 852   size_t i;
 853 
 854   size = backtrace (array, 10);
 855   strings = backtrace_symbols (array, size);
 856 
 857   fprintf (stderr, "Obtained %zd stack frames.\n", size);
 858 
 859   for (i = 0; i < size; i++)
 860      fprintf (stderr, "%s\n", strings[i]);
 861 
 862   free (strings);
 863 }
 864 #endif
 865 
 866 extern int32_t  numEventsHandled;
 867 
 868 XCreateWindowEvent cr;
 869 
 870 void
 871 dispatchEmbedderEvent(jobject server, XEvent * ev) {
 872     JNIEnv      *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 873     DASSERT(server != NULL);
 874     DASSERT(ev != NULL);
 875     AWT_LOCK();
 876 /*     MTRACE("dispatchEmebddedEvent\n"); */
 877     switch (ev->type) {
 878       case CreateNotify:
 879 
 880           MTRACEP3("CreateNotify for %x, serial %d, num events %d\n", (ev->xcreatewindow.window), (ev->xany.serial), (numEventsHandled));
 881           Java_sun_awt_motif_MEmbedCanvasPeer_embedChild(env, server, ev->xcreatewindow.window);
 882           break;
 883       case DestroyNotify:
 884           MTRACE("DestroyNotify\n");
 885           Java_sun_awt_motif_MEmbedCanvasPeer_childDestroyed(env, server);
 886           break;
 887       case ReparentNotify:
 888           MTRACEP2("ReparentNotify for %x, parent %x\n", (ev->xreparent.window), (ev->xreparent.parent));
 889           Java_sun_awt_motif_MEmbedCanvasPeer_embedChild(env, server, ev->xreparent.window);
 890           break;
 891       case ClientMessage:
 892           MTRACE("ClientMessage\n");
 893           handleClientMessage(env, server, &ev->xclient);
 894           break;
 895     }
 896     AWT_UNLOCK();
 897 }
 898 
 899 void
 900 dispatchEmbeddingClientEvent(XEvent * ev) {
 901     DASSERT(ev != NULL);
 902     MTRACE("dispatchEmbeddingClientEvent\n");
 903     switch (ev->type) {
 904       case PropertyNotify:
 905           handlePropertyNotify(&ev->xproperty);
 906           break;
 907       case ConfigureNotify:
 908           handleConfigureNotify(&ev->xconfigure);
 909           break;
 910     }
 911 }
 912 
 913 void
 914 xembed_serverEventHandler(XEvent * ev) {
 915     pxembed_server_data sdata;
 916     sdata = getData(ev->xany.window);
 917     if (sdata != NULL) { // Event on client
 918         dispatchEmbeddingClientEvent(ev);
 919     } else {
 920         sdata = getDataByServerHandle(ev->xany.window);
 921         if (sdata != NULL) {
 922             DASSERT(sdata->server != NULL);
 923             dispatchEmbedderEvent(sdata->server, ev);
 924         }
 925     }
 926 }
 927 
 928 /**************************** XEmbed server DnD support ***********************/
 929 void
 930 set_xembed_drop_target(JNIEnv* env, jobject server) {
 931 
 932     (*env)->CallVoidMethod(env, server, setXEmbedDropTargetMID);
 933 }
 934 
 935 void
 936 remove_xembed_drop_target(JNIEnv* env, jobject server) {
 937     (*env)->CallVoidMethod(env, server, removeXEmbedDropTargetMID);
 938 }
 939 
 940 Boolean
 941 is_xembed_client(Window window) {
 942     return getData(window) != NULL;
 943 }
 944 /******************************************************************************/
 945 
 946 /*
 947  * Class:     sun_awt_motif_MEmbedCanvasPeer
 948  * Method:    getWindow
 949  * Signature: ()V
 950  */
 951 JNIEXPORT jlong JNICALL
 952 Java_sun_awt_motif_MEmbedCanvasPeer_getWindow(JNIEnv *env, jobject this) {
 953     struct ComponentData *cdata;
 954     Window res = None;
 955     AWT_LOCK();
 956     cdata = (struct ComponentData *)
 957         JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData);
 958     DASSERT(cdata != NULL);
 959     res = XtWindow(cdata->widget);
 960     AWT_UNLOCK();
 961     return (jlong)res;
 962 }
 963 
 964 JNIEXPORT void JNICALL
 965 Java_sun_awt_motif_MEmbedCanvasPeer_forwardEventToEmbedded(JNIEnv *env,
 966                                                            jobject this,
 967                                                            jlong ctxt,
 968                                                            jint eventID){
 969     pxembed_server_data sdata;
 970     AWT_LOCK();
 971     sdata = getDataByEmbedder(this);
 972     if (sdata != NULL) {
 973         forward_event_to_embedded(sdata->handle, ctxt, eventID);
 974     }
 975     AWT_UNLOCK();
 976 }