blob: d4eb5ea10224857b289f5180569cbf050281e941 [file] [log] [blame]
/*
* Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
// TODO: Propogate applicationActive from Java
#ifdef HEADLESS
#error This file should not be included in headless library
#endif
#include "awt_p.h"
#include <X11/Xproto.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <Xm/MwmUtil.h>
#ifdef __linux__
#include <execinfo.h>
#endif
#include <stdio.h>
#include <stdlib.h>
/* JNI headers */
#include "java_awt_Frame.h" /* for frame state constants */
#include "java_awt_event_KeyEvent.h"
#include "awt_wm.h"
#include "awt_util.h" /* for X11 error handling macros */
#include "awt_xembed.h"
#include "awt_Component.h"
#include "awt_AWTEvent.h"
#include "canvas.h"
#include "sun_awt_motif_MEmbedCanvasPeer.h"
#ifdef DOTRACE
#define MTRACE(param) fprintf(stderr, param)
#define MTRACEP1(format, p1) fprintf(stderr, format, p1)
#define MTRACEP2(format, p1, p2) fprintf(stderr, format, p1, p2)
#define MTRACEP3(format, p1, p2, p3) fprintf(stderr, format, p1, p2, p3)
#define MTRACEP4(format, p1, p2, p3, p4) fprintf(stderr, format, p1, p2, p3, p4)
#define MTRACEP5(format, p1, p2, p3, p4, p5) fprintf(stderr, format, p1, p2, p3, p4, p5)
#define MTRACEP6(format, p1, p2, p3, p4, p5, p6) fprintf(stderr, format, p1, p2, p3, p4, p5, p6)
#define MTRACEP7(format, p1, p2, p3, p4, p5, p6, p7) fprintf(stderr, format, p1, p2, p3, p4, p5, p6, p7)
#else
#define MTRACE(param)
#define MTRACEP1(format, p1)
#define MTRACEP2(format, p1, p2)
#define MTRACEP3(format, p1, p2, p3)
#define MTRACEP4(format, p1, p2, p3, p4)
#define MTRACEP5(format, p1, p2, p3, p4, p5)
#define MTRACEP6(format, p1, p2, p3, p4, p5, p6)
#define MTRACEP7(format, p1, p2, p3, p4, p5, p6, p7)
#endif
/**************************** XEmbed server DnD support ***********************/
extern Atom XA_XdndAware;
extern Boolean
register_xembed_drop_site(JNIEnv* env, Display* dpy, jobject server,
Window serverHandle, Window clientHandle);
extern Boolean
unregister_xembed_drop_site(JNIEnv* env, Display* dpy, jobject server,
Window serverHandle, Window clientHandle);
extern void
forward_event_to_embedded(Window embedded, jlong ctxt, jint eventID);
extern const char * msg_to_str(int msg);
void
set_xembed_drop_target(JNIEnv* env, jobject server);
void
remove_xembed_drop_target(JNIEnv* env, jobject server);
Boolean
is_xembed_client(Window window);
/******************************************************************************/
extern struct MComponentPeerIDs mComponentPeerIDs;
static jobject createRectangle(JNIEnv* env, int x, int y, int width, int height);
static jobject createDimension(JNIEnv* env, int width, int height);
static void processXEmbedInfo(JNIEnv* env, jobject this);
static Atom XA_XEmbedInfo;
static Atom XA_XEmbed;
static jmethodID requestXEmbedFocusMID, focusNextMID, focusPrevMID,
registerAcceleratorMID, unregisterAcceleratorMID,
grabKeyMID, ungrabKeyMID, childResizedMID,
setXEmbedDropTargetMID, removeXEmbedDropTargetMID;
static jfieldID keysymFID, modifiersFID, applicationActiveFID;
typedef struct _xembed_server_data {
Window handle; // pointer to plugin intermediate widget, XEmbed client
Window serverHandle;
Widget serverWidget;
Boolean dispatching; // whether we dispatch messages for handle
int version;
jobject server;
struct _xembed_server_data * next;
} xembed_server_data, * pxembed_server_data;
static pxembed_server_data xembed_list = NULL;
static pxembed_server_data
getData(Window handle) {
pxembed_server_data temp = xembed_list;
while (temp != NULL) {
if (temp->handle == handle) {
return temp;
}
temp = temp->next;
}
return NULL;
}
static pxembed_server_data
getDataByEmbedder(jobject server) {
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
pxembed_server_data temp = xembed_list;
DASSERT(server != NULL);
while (temp != NULL) {
if ((*env)->IsSameObject(env, temp->server, server)) {
return temp;
}
temp = temp->next;
}
return NULL;
}
static pxembed_server_data
getDataByServerHandle(Window serverHandle) {
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
pxembed_server_data temp = xembed_list;
Widget serverWidget = NULL;
if (serverHandle == None) {
return NULL;
}
serverWidget = XtWindowToWidget(awt_display, serverHandle);
while (temp != NULL) {
if (temp->serverHandle == serverHandle || temp->serverWidget == serverWidget) {
temp->serverHandle = serverWidget;
return temp;
}
temp = temp->next;
}
return NULL;
}
static pxembed_server_data
addData(jobject server) {
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
struct ComponentData *cdata;
xembed_server_data * data = malloc(sizeof(xembed_server_data));
DASSERT(server != NULL);
memset(data, 0, sizeof(xembed_server_data));
data->server = server;
cdata = (struct ComponentData *)
JNU_GetLongFieldAsPtr(env, server, mComponentPeerIDs.pData);
DASSERT(cdata != NULL);
data->serverHandle = XtWindow(cdata->widget);
data->serverWidget = cdata->widget;
data->next = xembed_list;
xembed_list = data;
return data;
}
static void
removeData(jobject server) {
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
pxembed_server_data * temp = &xembed_list;
DASSERT(server != NULL);
while (*temp != NULL) {
if ((*env)->IsSameObject(env, (*temp)->server, server)) {
xembed_server_data * data = *temp;
*temp = (*temp)->next;
DASSERT(data->server != NULL);
(*env)->DeleteGlobalRef(env, data->server);
free(data);
return;
}
temp = &(*temp)->next;
}
}
void
initXEmbedServerData() {
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
jclass clazz;
MTRACE("initXEmbedServerData\n");
XA_XEmbedInfo = XInternAtom(awt_display, "_XEMBED_INFO", False);
XA_XEmbed = XInternAtom(awt_display, "_XEMBED", False);
clazz = (*env)->FindClass(env, "sun/awt/motif/MEmbedCanvasPeer");
DASSERT(clazz != NULL);
requestXEmbedFocusMID = (*env)->GetMethodID(env, clazz, "requestXEmbedFocus", "()V");
DASSERT(requestXEmbedFocusMID != NULL);
focusNextMID = (*env)->GetMethodID(env, clazz, "focusNext", "()V");
DASSERT(focusNextMID != NULL);
focusPrevMID = (*env)->GetMethodID(env, clazz, "focusPrev", "()V");
DASSERT(focusPrevMID != NULL);
registerAcceleratorMID = (*env)->GetMethodID(env, clazz, "registerAccelerator", "(JJJ)V");
DASSERT(registerAcceleratorMID != NULL);
unregisterAcceleratorMID = (*env)->GetMethodID(env, clazz, "unregisterAccelerator", "(J)V");
DASSERT(unregisterAcceleratorMID != NULL);
grabKeyMID = (*env)->GetMethodID(env, clazz, "grabKey", "(JJ)V");
DASSERT(grabKeyMID != NULL);
ungrabKeyMID = (*env)->GetMethodID(env, clazz, "ungrabKey", "(JJ)V");
DASSERT(ungrabKeyMID != NULL);
childResizedMID = (*env)->GetMethodID(env, clazz, "childResized", "()V");
DASSERT(childResizedMID != NULL);
setXEmbedDropTargetMID =
(*env)->GetMethodID(env, clazz, "setXEmbedDropTarget", "()V");
DASSERT(setXEmbedDropTargetMID != NULL);
removeXEmbedDropTargetMID =
(*env)->GetMethodID(env, clazz, "removeXEmbedDropTarget", "()V");
DASSERT(removeXEmbedDropTargetMID != NULL);
applicationActiveFID = (*env)->GetFieldID(env, clazz, "applicationActive", "Z");
DASSERT(applicationActiveFID != NULL);
(*env)->DeleteLocalRef(env, clazz);
clazz = (*env)->FindClass(env, "sun/awt/motif/GrabbedKey");
DASSERT(clazz != NULL);
keysymFID = (*env)->GetFieldID(env, clazz, "keysym", "J");
DASSERT(keysymFID != NULL);
modifiersFID = (*env)->GetFieldID(env, clazz, "modifiers", "J");
DASSERT(modifiersFID != NULL);
(*env)->DeleteLocalRef(env, clazz);
}
/*
* Class: sun_awt_motif_MEmbedCanvasPeer
* Method: initXEmbedServer
* Signature: ()V
*/
JNIEXPORT void JNICALL
Java_sun_awt_motif_MEmbedCanvasPeer_initXEmbedServer(JNIEnv *env, jobject this) {
struct ComponentData *cdata;
AWT_LOCK();
MTRACE("initXEmbedServer\n");
addData((*env)->NewGlobalRef(env, this));
if (XA_XEmbedInfo == None) {
initXEmbedServerData();
}
cdata = (struct ComponentData *)
JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData);
/* XSelectInput(awt_display, XtWindow(cdata->widget), SubstructureNotifyMask); */
XtAddEventHandler(cdata->widget,
SubstructureNotifyMask,
False, null_event_handler, NULL);
AWT_UNLOCK();
}
/*
* Class: sun_awt_motif_MEmbedCanvasPeer
* Method: destroyXEmbedServer
* Signature: ()V
*/
JNIEXPORT void JNICALL
Java_sun_awt_motif_MEmbedCanvasPeer_destroyXEmbedServer(JNIEnv *env, jobject this) {
AWT_LOCK();
MTRACE("destroyXEmbedServer\n");
removeData(this);
AWT_UNLOCK();
}
/*
* Class: sun_awt_motif_MEmbedCanvasPeer
* Method: isXEmbedActive
* Signature: ()Z
*/
JNIEXPORT jboolean JNICALL
Java_sun_awt_motif_MEmbedCanvasPeer_isXEmbedActive(JNIEnv *env, jobject this) {
pxembed_server_data sdata;
jboolean res = JNI_FALSE;
AWT_LOCK();
sdata = getDataByEmbedder(this);
if (sdata != NULL) {
res = (sdata->handle != None)?JNI_TRUE:JNI_FALSE;
}
AWT_UNLOCK();
return res;
}
/*
* Class: sun_awt_motif_MEmbedCanvasPeer
* Method: initDispatching
* Signature: ()V
*/
JNIEXPORT void JNICALL
Java_sun_awt_motif_MEmbedCanvasPeer_initDispatching (JNIEnv *env, jobject this) {
pxembed_server_data sdata;
AWT_LOCK();
MTRACE("initDispatching\n");
sdata = getDataByEmbedder(this);
if (sdata != NULL) {
XSelectInput(awt_display, sdata->handle, StructureNotifyMask | PropertyChangeMask);
sdata->dispatching = True;
register_xembed_drop_site(env, awt_display, sdata->server,
sdata->serverHandle, sdata->handle);
}
processXEmbedInfo(env, this);
Java_sun_awt_motif_MEmbedCanvasPeer_notifyChildEmbedded(env, this);
AWT_UNLOCK();
}
/*
* Class: sun_awt_motif_MEmbedCanvasPeer
* Method: endDispatching
* Signature: ()V
*/
JNIEXPORT void JNICALL
Java_sun_awt_motif_MEmbedCanvasPeer_endDispatching (JNIEnv *env, jobject this) {
pxembed_server_data sdata;
AWT_LOCK();
MTRACE("endDispatching\n");
sdata = getDataByEmbedder(this);
if (sdata != NULL) {
unregister_xembed_drop_site(env, awt_display, sdata->server,
sdata->serverHandle, sdata->handle);
sdata->dispatching = False;
}
AWT_UNLOCK();
}
/*
* Class: sun_awt_motif_MEmbedCanvasPeer
* Method: embedChild
* Signature: (J)V
*/
JNIEXPORT void JNICALL
Java_sun_awt_motif_MEmbedCanvasPeer_embedChild (JNIEnv * env, jobject this, jlong handle) {
pxembed_server_data sdata;
AWT_LOCK();
MTRACE("embedChild\n");
sdata = getDataByEmbedder(this);
if (sdata != NULL) {
if (sdata->handle != None) {
Java_sun_awt_motif_MEmbedCanvasPeer_detachChild(env, this);
}
sdata->handle = (Window)handle;
Java_sun_awt_motif_MEmbedCanvasPeer_initDispatching(env, this);
}
AWT_UNLOCK();
}
/*
* Class: sun_awt_motif_MEmbedCanvasPeer
* Method: childDestroyed
* Signature: ()V
*/
JNIEXPORT void JNICALL
Java_sun_awt_motif_MEmbedCanvasPeer_childDestroyed (JNIEnv *env, jobject this) {
pxembed_server_data sdata;
AWT_LOCK();
MTRACE("childDestroyed\n");
Java_sun_awt_motif_MEmbedCanvasPeer_endDispatching(env, this);
sdata = getDataByEmbedder(this);
if (sdata != NULL) {
sdata->handle = None;
}
AWT_UNLOCK();
}
/*
* Class: sun_awt_motif_MEmbedCanvasPeer
* Method: getEmbedPreferredSize
* Signature: ()Ljava/awt/Dimension;
*/
JNIEXPORT jobject JNICALL
Java_sun_awt_motif_MEmbedCanvasPeer_getEmbedPreferredSize (JNIEnv *env, jobject this) {
pxembed_server_data sdata;
jobject res = NULL;
XSizeHints * hints;
long dummy;
AWT_LOCK();
MTRACE("getPreferredSize\n");
sdata = getDataByEmbedder(this);
if (sdata != NULL) {
hints = XAllocSizeHints();
DASSERT(hints != NULL);
DASSERT(sdata->handle != None);
if (XGetWMNormalHints(awt_display, sdata->handle, hints, &dummy) == Success) {
res = createDimension(env, hints->width, hints->height);
}
XFree(hints);
}
AWT_UNLOCK();
return res;
}
/*
* Class: sun_awt_motif_MEmbedCanvasPeer
* Method: getEmbedMinimumSize
* Signature: ()Ljava/awt/Dimension;
*/
JNIEXPORT jobject JNICALL
Java_sun_awt_motif_MEmbedCanvasPeer_getEmbedMinimumSize (JNIEnv *env, jobject this) {
pxembed_server_data sdata;
jobject res = NULL;
XSizeHints * hints;
long dummy;
AWT_LOCK();
MTRACE("getMinimumSize\n");
sdata = getDataByEmbedder(this);
if (sdata != NULL) {
hints = XAllocSizeHints();
DASSERT(hints != NULL);
DASSERT(sdata->handle != None);
if (XGetWMNormalHints(awt_display, sdata->handle, hints, &dummy) == Success) {
res = createDimension(env, hints->min_width, hints->min_height);
}
XFree(hints);
}
AWT_UNLOCK();
return res;
}
/*
* Class: sun_awt_motif_MEmbedCanvasPeer
* Method: getClientBounds
* Signature: ()Ljava/awt/Rectangle;
*/
JNIEXPORT jobject JNICALL
Java_sun_awt_motif_MEmbedCanvasPeer_getClientBounds (JNIEnv *env, jobject this) {
pxembed_server_data sdata;
jobject res = NULL;
AWT_LOCK();
MTRACE("getClientBounds\n");
sdata = getDataByEmbedder(this);
if (sdata != NULL) {
XWindowAttributes attrs;
DASSERT(sdata->handle != None);
if (XGetWindowAttributes(awt_display, sdata->handle, &attrs) == Success) {
res = createRectangle(env, attrs.x, attrs.y, attrs.width, attrs.height);
}
}
AWT_UNLOCK();
return res;
}
Boolean
isApplicationActive(JNIEnv * env, jobject this) {
return (*env)->GetBooleanField(env, this, applicationActiveFID);
}
/*
* Class: sun_awt_motif_MEmbedCanvasPeer
* Method: notifyChildEmbedded
* Signature: ()V
*/
JNIEXPORT void JNICALL
Java_sun_awt_motif_MEmbedCanvasPeer_notifyChildEmbedded (JNIEnv *env, jobject this) {
struct ComponentData *cdata;
pxembed_server_data sdata;
AWT_LOCK();
MTRACE("notifyChildEmbedded\n");
cdata = (struct ComponentData *)
JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData);
sdata = getDataByEmbedder(this);
if (sdata != NULL) {
DASSERT(sdata->handle != None);
DASSERT(cdata != NULL);
DASSERT(XtWindow(cdata->widget) != None);
sendMessageHelper(sdata->handle, XEMBED_EMBEDDED_NOTIFY, XtWindow(cdata->widget), min(sdata->version, XEMBED_VERSION), 0);
if (isApplicationActive(env, this)) {
sendMessage(sdata->handle, XEMBED_WINDOW_ACTIVATE);
}
}
AWT_UNLOCK();
}
/*
* Class: sun_awt_motif_MEmbedCanvasPeer
* Method: detachChild
* Signature: ()V
*/
JNIEXPORT void JNICALL
Java_sun_awt_motif_MEmbedCanvasPeer_detachChild (JNIEnv *env, jobject this) {
pxembed_server_data sdata;
AWT_LOCK();
MTRACE("detachChild\n");
sdata = getDataByEmbedder(this);
if (sdata != NULL) {
/**
* XEmbed specification:
* "The embedder can unmap the client and reparent the client window to the root window. If the
* client receives an ReparentNotify event, it should check the parent field of the XReparentEvent
* structure. If this is the root window of the window's screen, then the protocol is finished and
* there is no further interaction. If it is a window other than the root window, then the protocol
* continues with the new parent acting as the embedder window."
*/
DASSERT(sdata->handle != None);
XUnmapWindow(awt_display, sdata->handle);
XReparentWindow(awt_display, sdata->handle, DefaultRootWindow(awt_display), 0, 0);
Java_sun_awt_motif_MEmbedCanvasPeer_endDispatching(env, this);
sdata->handle = None;
}
AWT_UNLOCK();
}
/*
* Class: sun_awt_motif_MEmbedCanvasPeer
* Method: forwardKeyEvent
* Signature: (Ljava/awt/event/KeyEvent;)V
*/
JNIEXPORT void JNICALL
Java_sun_awt_motif_MEmbedCanvasPeer_forwardKeyEvent (JNIEnv *env, jobject this, jobject event) {
pxembed_server_data sdata;
jbyteArray array;
XEvent *xevent;
AWT_LOCK();
MTRACE("forwardKeyEvent\n");
sdata = getDataByEmbedder(this);
if (sdata != NULL) {
DASSERT(sdata->handle != None);
array = (jbyteArray)(*env)->GetObjectField(env, event, awtEventIDs.bdata);
if (array == NULL) {
MTRACE("array is null\n");
AWT_UNLOCK();
return;
}
xevent = (XEvent *)(*env)->GetByteArrayElements(env, array, NULL);
if (xevent == NULL) {
(*env)->DeleteLocalRef(env, array);
MTRACE("xevent is null\n");
AWT_UNLOCK();
return;
}
xevent->xany.window = sdata->handle;
XSendEvent(awt_display, sdata->handle, False, NoEventMask, xevent);
(*env)->DeleteLocalRef(env, array);
}
AWT_UNLOCK();
}
/*
* Class: sun_awt_motif_MEmbedCanvasPeer
* Method: getAWTKeyCodeForKeySym
* Signature: (I)I
*/
JNIEXPORT jint JNICALL
Java_sun_awt_motif_MEmbedCanvasPeer_getAWTKeyCodeForKeySym (JNIEnv *env, jobject this, jint keysym) {
jint keycode = java_awt_event_KeyEvent_VK_UNDEFINED;
Boolean mapsToUnicodeChar;
jint keyLocation;
keysymToAWTKeyCode(keysym, &keycode, &mapsToUnicodeChar, &keyLocation);
return keycode;
}
/*
* Class: sun_awt_motif_MEmbedCanvasPeer
* Method: sendMessage
* Signature: (I)V
*/
JNIEXPORT void JNICALL
Java_sun_awt_motif_MEmbedCanvasPeer_sendMessage__I (JNIEnv *env, jobject this, jint msg) {
pxembed_server_data sdata;
AWT_LOCK();
MTRACEP2("sendMessage %d(%s)\n", msg, msg_to_str(msg));
sdata = getDataByEmbedder(this);
if (sdata != NULL) {
DASSERT(sdata->handle != None);
sendMessage(sdata->handle, msg);
}
AWT_UNLOCK();
}
/*
* Class: sun_awt_motif_MEmbedCanvasPeer
* Method: sendMessage
* Signature: (IJJJ)V
*/
JNIEXPORT void JNICALL
Java_sun_awt_motif_MEmbedCanvasPeer_sendMessage__IJJJ (JNIEnv *env, jobject this, jint msg, jlong detail, jlong data1, jlong data2) {
pxembed_server_data sdata;
AWT_LOCK();
MTRACEP5("sendMessage2 msg %d(%s) detail %d data: %d %d\n", msg, msg_to_str(msg), detail, data1, data2);
sdata = getDataByEmbedder(this);
if (sdata != NULL) {
DASSERT(sdata->handle != None);
sendMessageHelper(sdata->handle, msg, detail, data1, data2);
}
AWT_UNLOCK();
}
static jobject
createRectangle(JNIEnv* env, int x, int y, int width, int height) {
static jclass clazz;
static jmethodID mid;
jobject rect = NULL;
if (mid == 0) {
jclass l_clazz = (*env)->FindClass(env, "java/awt/Rectangle");
DASSERT(l_clazz != NULL);
mid = (*env)->GetMethodID(env, clazz, "<init>", "(IIII)V");
DASSERT(mid != NULL);
clazz = (*env)->NewGlobalRef(env, l_clazz);
(*env)->DeleteLocalRef(env, l_clazz);
}
if (mid != NULL) {
rect = (*env)->NewObject(env, clazz, mid, x, y, width, height);
if ((*env)->ExceptionOccurred(env)) {
return NULL;
}
}
return rect;
}
static jobject
createDimension(JNIEnv* env, int width, int height) {
static jclass clazz;
static jmethodID mid;
jobject dim = NULL;
if (mid == 0) {
jclass l_clazz = (*env)->FindClass(env, "java/awt/Dimension");
DASSERT(l_clazz != NULL);
mid = (*env)->GetMethodID(env, clazz, "<init>", "(II)V");
DASSERT(mid != NULL);
clazz = (*env)->NewGlobalRef(env, l_clazz);
(*env)->DeleteLocalRef(env, l_clazz);
}
if (mid != NULL) {
dim = (*env)->NewObject(env, clazz, mid, width, height);
if ((*env)->ExceptionOccurred(env)) {
return NULL;
}
}
return dim;
}
Boolean isMapped(Window w) {
XWindowAttributes attr;
Status status = 0;
WITH_XERROR_HANDLER(xerror_ignore_bad_window);
status = XGetWindowAttributes(awt_display, w, &attr);
RESTORE_XERROR_HANDLER;
if (status == 0 || xerror_code != Success) {
return False;
}
return !(attr.map_state == IsUnmapped);
}
static void
processXEmbedInfo(JNIEnv * env, jobject this) {
pxembed_server_data sdata;
AWT_LOCK();
MTRACE("processXEmbedInfo\n");
sdata = getDataByEmbedder(this);
if (Java_sun_awt_motif_MEmbedCanvasPeer_isXEmbedActive(env, this)) {
Atom actual_type;
int actual_format;
unsigned long nitems;
unsigned long bytes_after;
CARD32 * data = NULL;
DASSERT(sdata->handle != None);
if (XGetWindowProperty(awt_display, sdata->handle, XA_XEmbedInfo,
0, 2, False, XA_XEmbedInfo, &actual_type,
&actual_format, &nitems, &bytes_after,
(unsigned char**)&data) != Success)
{
AWT_UNLOCK();
return;
}
if (actual_type == XA_XEmbedInfo && actual_format == 32
&& nitems == 2)
{
CARD32 flags;
Boolean new_mapped, currently_mapped;
sdata->version = *data;
flags = *(data+1);
new_mapped = (flags & XEMBED_MAPPED) != 0;
currently_mapped = isMapped(sdata->handle);
if (new_mapped != currently_mapped) {
if (new_mapped) {
XMapWindow(awt_display, sdata->handle);
} else {
XUnmapWindow(awt_display, sdata->handle);
}
}
}
if (data != NULL) {
XFree(data);
}
}
AWT_UNLOCK();
}
/**
* Handles client message on embedder
*/
static void
handleClientMessage(JNIEnv* env, jobject this, XClientMessageEvent * ev) {
pxembed_server_data sdata;
AWT_LOCK();
MTRACEP5("handleClientMessage: 0=%ld 1=%ld 2=%ld 3=%ld 4=%ld\n",
ev->data.l[0], ev->data.l[1], ev->data.l[2], ev->data.l[3], ev->data.l[4]);
sdata = getDataByEmbedder(this);
if (sdata != NULL && sdata->handle != None) {
switch ((int)ev->data.l[1]) {
case XEMBED_REQUEST_FOCUS:
MTRACE("REQUEST_FOCUS\n");
(*env)->CallVoidMethod(env, this, requestXEmbedFocusMID);
break;
case XEMBED_FOCUS_NEXT:
MTRACE("FOCUS_NEXT\n");
(*env)->CallVoidMethod(env, this, focusNextMID);
break;
case XEMBED_FOCUS_PREV:
MTRACE("FOCUS_PREV\n");
(*env)->CallVoidMethod(env, this, focusPrevMID);
break;
case XEMBED_REGISTER_ACCELERATOR:
MTRACE("REGISTER_ACCEL\n");
(*env)->CallVoidMethod(env, this, registerAcceleratorMID,
(jlong)ev->data.l[2],
(jlong)ev->data.l[3],
(jlong)ev->data.l[4]);
break;
case XEMBED_UNREGISTER_ACCELERATOR:
MTRACE("UNREGISTER_ACCEL\n");
(*env)->CallVoidMethod(env, this, unregisterAcceleratorMID,
(jlong)ev->data.l[2]);
break;
case NON_STANDARD_XEMBED_GTK_GRAB_KEY:
MTRACE("GRAB_KEY\n");
(*env)->CallVoidMethod(env, this, grabKeyMID,
(jlong)ev->data.l[3],
(jlong)ev->data.l[4]);
break;
case NON_STANDARD_XEMBED_GTK_UNGRAB_KEY:
MTRACE("UNGRAB_KEY\n");
(*env)->CallVoidMethod(env, this, ungrabKeyMID,
(jlong)ev->data.l[3],
(jlong)ev->data.l[4]);
case _SUN_XEMBED_START:
MTRACE("XEMBED_START\n");
processXEmbedInfo(env, this);
Java_sun_awt_motif_MEmbedCanvasPeer_notifyChildEmbedded(env, this);
break;
}
}
AWT_UNLOCK();
}
/**
* Handles property changes on xembed client
*/
static void
handlePropertyNotify(XPropertyEvent * ev) {
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
pxembed_server_data sdata;
AWT_LOCK();
MTRACE("handlePropertyNotify\n");
sdata = getData(ev->window);
if (sdata != NULL) {
if (ev->atom == XA_WM_NORMAL_HINTS) {
DASSERT(sdata->server != NULL);
(*env)->CallVoidMethod(env, sdata->server, childResizedMID);
MTRACE("NORMAL_HINTS have changed\n");
} else if (ev->atom == XA_XdndAware) {
unregister_xembed_drop_site(env, awt_display, sdata->server,
sdata->serverHandle, sdata->handle);
if (ev->state == PropertyNewValue) {
register_xembed_drop_site(env, awt_display, sdata->server,
sdata->serverHandle, sdata->handle);
}
} else if (ev->atom == XA_XEmbedInfo) {
DASSERT(sdata->server != NULL);
MTRACE("XEMBED_INFO has changed\n");
processXEmbedInfo(env, sdata->server);
}
}
AWT_UNLOCK();
}
static void
handleConfigureNotify(XConfigureEvent * ev) {
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
pxembed_server_data sdata;
AWT_LOCK();
MTRACE("handleConfigureNotify\n");
sdata = getData(ev->window);
if (sdata != NULL) {
DASSERT(sdata->server != NULL);
(*env)->CallVoidMethod(env, sdata->server, childResizedMID);
}
AWT_UNLOCK();
}
/*
* Class: sun_awt_motif_MEmbedCanvasPeer
* Method: sendMessage
* Signature: (IJJJ)V
*/
JNIEXPORT void JNICALL
Java_sun_awt_motif_GrabbedKey_initKeySymAndModifiers (JNIEnv *env, jobject this, jobject keyevent) {
jbyteArray array;
XEvent *xevent;
int keysym, modifiers;
int keycode;
AWT_LOCK();
array = (jbyteArray)(*env)->GetObjectField(env, keyevent, awtEventIDs.bdata);
if (array == NULL) {
AWT_UNLOCK();
return;
}
xevent = (XEvent *)(*env)->GetByteArrayElements(env, array, NULL);
if (xevent == NULL) {
(*env)->DeleteLocalRef(env, array);
AWT_UNLOCK();
return;
}
keycode = (*env)->GetIntField(env, keyevent, keyEventIDs.keyCode);
keysym = awt_getX11KeySym(keycode);
modifiers = xevent->xkey.state;
(*env)->SetLongField(env, this, keysymFID, (jlong)keysym);
(*env)->SetLongField(env, this, modifiersFID, (jlong)modifiers);
(*env)->DeleteLocalRef(env, array);
AWT_UNLOCK();
}
#ifdef __linux__
void
print_stack (void)
{
void *array[10];
size_t size;
char **strings;
size_t i;
size = backtrace (array, 10);
strings = backtrace_symbols (array, size);
fprintf (stderr, "Obtained %zd stack frames.\n", size);
for (i = 0; i < size; i++)
fprintf (stderr, "%s\n", strings[i]);
free (strings);
}
#endif
extern int32_t numEventsHandled;
XCreateWindowEvent cr;
void
dispatchEmbedderEvent(jobject server, XEvent * ev) {
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
DASSERT(server != NULL);
DASSERT(ev != NULL);
AWT_LOCK();
/* MTRACE("dispatchEmebddedEvent\n"); */
switch (ev->type) {
case CreateNotify:
MTRACEP3("CreateNotify for %x, serial %d, num events %d\n", (ev->xcreatewindow.window), (ev->xany.serial), (numEventsHandled));
Java_sun_awt_motif_MEmbedCanvasPeer_embedChild(env, server, ev->xcreatewindow.window);
break;
case DestroyNotify:
MTRACE("DestroyNotify\n");
Java_sun_awt_motif_MEmbedCanvasPeer_childDestroyed(env, server);
break;
case ReparentNotify:
MTRACEP2("ReparentNotify for %x, parent %x\n", (ev->xreparent.window), (ev->xreparent.parent));
Java_sun_awt_motif_MEmbedCanvasPeer_embedChild(env, server, ev->xreparent.window);
break;
case ClientMessage:
MTRACE("ClientMessage\n");
handleClientMessage(env, server, &ev->xclient);
break;
}
AWT_UNLOCK();
}
void
dispatchEmbeddingClientEvent(XEvent * ev) {
DASSERT(ev != NULL);
MTRACE("dispatchEmbeddingClientEvent\n");
switch (ev->type) {
case PropertyNotify:
handlePropertyNotify(&ev->xproperty);
break;
case ConfigureNotify:
handleConfigureNotify(&ev->xconfigure);
break;
}
}
void
xembed_serverEventHandler(XEvent * ev) {
pxembed_server_data sdata;
sdata = getData(ev->xany.window);
if (sdata != NULL) { // Event on client
dispatchEmbeddingClientEvent(ev);
} else {
sdata = getDataByServerHandle(ev->xany.window);
if (sdata != NULL) {
DASSERT(sdata->server != NULL);
dispatchEmbedderEvent(sdata->server, ev);
}
}
}
/**************************** XEmbed server DnD support ***********************/
void
set_xembed_drop_target(JNIEnv* env, jobject server) {
(*env)->CallVoidMethod(env, server, setXEmbedDropTargetMID);
}
void
remove_xembed_drop_target(JNIEnv* env, jobject server) {
(*env)->CallVoidMethod(env, server, removeXEmbedDropTargetMID);
}
Boolean
is_xembed_client(Window window) {
return getData(window) != NULL;
}
/******************************************************************************/
/*
* Class: sun_awt_motif_MEmbedCanvasPeer
* Method: getWindow
* Signature: ()V
*/
JNIEXPORT jlong JNICALL
Java_sun_awt_motif_MEmbedCanvasPeer_getWindow(JNIEnv *env, jobject this) {
struct ComponentData *cdata;
Window res = None;
AWT_LOCK();
cdata = (struct ComponentData *)
JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData);
DASSERT(cdata != NULL);
res = XtWindow(cdata->widget);
AWT_UNLOCK();
return (jlong)res;
}
JNIEXPORT void JNICALL
Java_sun_awt_motif_MEmbedCanvasPeer_forwardEventToEmbedded(JNIEnv *env,
jobject this,
jlong ctxt,
jint eventID){
pxembed_server_data sdata;
AWT_LOCK();
sdata = getDataByEmbedder(this);
if (sdata != NULL) {
forward_event_to_embedded(sdata->handle, ctxt, eventID);
}
AWT_UNLOCK();
}