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 }