1 /* |
|
2 * Copyright (c) 2003, 2005, 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(Window w) { |
|
648 XWindowAttributes attr; |
|
649 Status status = 0; |
|
650 WITH_XERROR_HANDLER(xerror_ignore_bad_window); |
|
651 status = XGetWindowAttributes(awt_display, w, &attr); |
|
652 RESTORE_XERROR_HANDLER; |
|
653 if (status == 0 || xerror_code != Success) { |
|
654 return False; |
|
655 } |
|
656 return !(attr.map_state == IsUnmapped); |
|
657 } |
|
658 |
|
659 static void |
|
660 processXEmbedInfo(JNIEnv * env, jobject this) { |
|
661 pxembed_server_data sdata; |
|
662 AWT_LOCK(); |
|
663 MTRACE("processXEmbedInfo\n"); |
|
664 sdata = getDataByEmbedder(this); |
|
665 if (Java_sun_awt_motif_MEmbedCanvasPeer_isXEmbedActive(env, this)) { |
|
666 Atom actual_type; |
|
667 int actual_format; |
|
668 unsigned long nitems; |
|
669 unsigned long bytes_after; |
|
670 CARD32 * data = NULL; |
|
671 DASSERT(sdata->handle != None); |
|
672 if (XGetWindowProperty(awt_display, sdata->handle, XA_XEmbedInfo, |
|
673 0, 2, False, XA_XEmbedInfo, &actual_type, |
|
674 &actual_format, &nitems, &bytes_after, |
|
675 (unsigned char**)&data) != Success) |
|
676 { |
|
677 AWT_UNLOCK(); |
|
678 return; |
|
679 } |
|
680 if (actual_type == XA_XEmbedInfo && actual_format == 32 |
|
681 && nitems == 2) |
|
682 { |
|
683 CARD32 flags; |
|
684 Boolean new_mapped, currently_mapped; |
|
685 sdata->version = *data; |
|
686 flags = *(data+1); |
|
687 new_mapped = (flags & XEMBED_MAPPED) != 0; |
|
688 currently_mapped = isMapped(sdata->handle); |
|
689 if (new_mapped != currently_mapped) { |
|
690 if (new_mapped) { |
|
691 XMapWindow(awt_display, sdata->handle); |
|
692 } else { |
|
693 XUnmapWindow(awt_display, sdata->handle); |
|
694 } |
|
695 } |
|
696 } |
|
697 if (data != NULL) { |
|
698 XFree(data); |
|
699 } |
|
700 } |
|
701 AWT_UNLOCK(); |
|
702 } |
|
703 |
|
704 /** |
|
705 * Handles client message on embedder |
|
706 */ |
|
707 static void |
|
708 handleClientMessage(JNIEnv* env, jobject this, XClientMessageEvent * ev) { |
|
709 pxembed_server_data sdata; |
|
710 AWT_LOCK(); |
|
711 MTRACEP5("handleClientMessage: 0=%ld 1=%ld 2=%ld 3=%ld 4=%ld\n", |
|
712 ev->data.l[0], ev->data.l[1], ev->data.l[2], ev->data.l[3], ev->data.l[4]); |
|
713 sdata = getDataByEmbedder(this); |
|
714 if (sdata != NULL && sdata->handle != None) { |
|
715 switch ((int)ev->data.l[1]) { |
|
716 case XEMBED_REQUEST_FOCUS: |
|
717 MTRACE("REQUEST_FOCUS\n"); |
|
718 (*env)->CallVoidMethod(env, this, requestXEmbedFocusMID); |
|
719 break; |
|
720 case XEMBED_FOCUS_NEXT: |
|
721 MTRACE("FOCUS_NEXT\n"); |
|
722 (*env)->CallVoidMethod(env, this, focusNextMID); |
|
723 break; |
|
724 case XEMBED_FOCUS_PREV: |
|
725 MTRACE("FOCUS_PREV\n"); |
|
726 (*env)->CallVoidMethod(env, this, focusPrevMID); |
|
727 break; |
|
728 case XEMBED_REGISTER_ACCELERATOR: |
|
729 MTRACE("REGISTER_ACCEL\n"); |
|
730 (*env)->CallVoidMethod(env, this, registerAcceleratorMID, |
|
731 (jlong)ev->data.l[2], |
|
732 (jlong)ev->data.l[3], |
|
733 (jlong)ev->data.l[4]); |
|
734 break; |
|
735 case XEMBED_UNREGISTER_ACCELERATOR: |
|
736 MTRACE("UNREGISTER_ACCEL\n"); |
|
737 (*env)->CallVoidMethod(env, this, unregisterAcceleratorMID, |
|
738 (jlong)ev->data.l[2]); |
|
739 break; |
|
740 case NON_STANDARD_XEMBED_GTK_GRAB_KEY: |
|
741 MTRACE("GRAB_KEY\n"); |
|
742 (*env)->CallVoidMethod(env, this, grabKeyMID, |
|
743 (jlong)ev->data.l[3], |
|
744 (jlong)ev->data.l[4]); |
|
745 break; |
|
746 case NON_STANDARD_XEMBED_GTK_UNGRAB_KEY: |
|
747 MTRACE("UNGRAB_KEY\n"); |
|
748 (*env)->CallVoidMethod(env, this, ungrabKeyMID, |
|
749 (jlong)ev->data.l[3], |
|
750 (jlong)ev->data.l[4]); |
|
751 case _SUN_XEMBED_START: |
|
752 MTRACE("XEMBED_START\n"); |
|
753 processXEmbedInfo(env, this); |
|
754 Java_sun_awt_motif_MEmbedCanvasPeer_notifyChildEmbedded(env, this); |
|
755 break; |
|
756 } |
|
757 } |
|
758 AWT_UNLOCK(); |
|
759 } |
|
760 |
|
761 /** |
|
762 * Handles property changes on xembed client |
|
763 */ |
|
764 static void |
|
765 handlePropertyNotify(XPropertyEvent * ev) { |
|
766 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
|
767 pxembed_server_data sdata; |
|
768 AWT_LOCK(); |
|
769 MTRACE("handlePropertyNotify\n"); |
|
770 sdata = getData(ev->window); |
|
771 if (sdata != NULL) { |
|
772 if (ev->atom == XA_WM_NORMAL_HINTS) { |
|
773 DASSERT(sdata->server != NULL); |
|
774 (*env)->CallVoidMethod(env, sdata->server, childResizedMID); |
|
775 MTRACE("NORMAL_HINTS have changed\n"); |
|
776 } else if (ev->atom == XA_XdndAware) { |
|
777 unregister_xembed_drop_site(env, awt_display, sdata->server, |
|
778 sdata->serverHandle, sdata->handle); |
|
779 if (ev->state == PropertyNewValue) { |
|
780 register_xembed_drop_site(env, awt_display, sdata->server, |
|
781 sdata->serverHandle, sdata->handle); |
|
782 } |
|
783 } else if (ev->atom == XA_XEmbedInfo) { |
|
784 DASSERT(sdata->server != NULL); |
|
785 MTRACE("XEMBED_INFO has changed\n"); |
|
786 processXEmbedInfo(env, sdata->server); |
|
787 } |
|
788 } |
|
789 AWT_UNLOCK(); |
|
790 } |
|
791 |
|
792 static void |
|
793 handleConfigureNotify(XConfigureEvent * ev) { |
|
794 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
|
795 pxembed_server_data sdata; |
|
796 AWT_LOCK(); |
|
797 MTRACE("handleConfigureNotify\n"); |
|
798 sdata = getData(ev->window); |
|
799 if (sdata != NULL) { |
|
800 DASSERT(sdata->server != NULL); |
|
801 (*env)->CallVoidMethod(env, sdata->server, childResizedMID); |
|
802 } |
|
803 AWT_UNLOCK(); |
|
804 } |
|
805 |
|
806 /* |
|
807 * Class: sun_awt_motif_MEmbedCanvasPeer |
|
808 * Method: sendMessage |
|
809 * Signature: (IJJJ)V |
|
810 */ |
|
811 JNIEXPORT void JNICALL |
|
812 Java_sun_awt_motif_GrabbedKey_initKeySymAndModifiers (JNIEnv *env, jobject this, jobject keyevent) { |
|
813 jbyteArray array; |
|
814 XEvent *xevent; |
|
815 int keysym, modifiers; |
|
816 int keycode; |
|
817 AWT_LOCK(); |
|
818 array = (jbyteArray)(*env)->GetObjectField(env, keyevent, awtEventIDs.bdata); |
|
819 if (array == NULL) { |
|
820 AWT_UNLOCK(); |
|
821 return; |
|
822 } |
|
823 xevent = (XEvent *)(*env)->GetByteArrayElements(env, array, NULL); |
|
824 if (xevent == NULL) { |
|
825 (*env)->DeleteLocalRef(env, array); |
|
826 AWT_UNLOCK(); |
|
827 return; |
|
828 } |
|
829 keycode = (*env)->GetIntField(env, keyevent, keyEventIDs.keyCode); |
|
830 keysym = awt_getX11KeySym(keycode); |
|
831 modifiers = xevent->xkey.state; |
|
832 (*env)->SetLongField(env, this, keysymFID, (jlong)keysym); |
|
833 (*env)->SetLongField(env, this, modifiersFID, (jlong)modifiers); |
|
834 (*env)->DeleteLocalRef(env, array); |
|
835 AWT_UNLOCK(); |
|
836 } |
|
837 |
|
838 #ifdef __linux__ |
|
839 void |
|
840 print_stack (void) |
|
841 { |
|
842 void *array[10]; |
|
843 size_t size; |
|
844 char **strings; |
|
845 size_t i; |
|
846 |
|
847 size = backtrace (array, 10); |
|
848 strings = backtrace_symbols (array, size); |
|
849 |
|
850 fprintf (stderr, "Obtained %zd stack frames.\n", size); |
|
851 |
|
852 for (i = 0; i < size; i++) |
|
853 fprintf (stderr, "%s\n", strings[i]); |
|
854 |
|
855 free (strings); |
|
856 } |
|
857 #endif |
|
858 |
|
859 extern int32_t numEventsHandled; |
|
860 |
|
861 XCreateWindowEvent cr; |
|
862 |
|
863 void |
|
864 dispatchEmbedderEvent(jobject server, XEvent * ev) { |
|
865 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
|
866 DASSERT(server != NULL); |
|
867 DASSERT(ev != NULL); |
|
868 AWT_LOCK(); |
|
869 /* MTRACE("dispatchEmebddedEvent\n"); */ |
|
870 switch (ev->type) { |
|
871 case CreateNotify: |
|
872 |
|
873 MTRACEP3("CreateNotify for %x, serial %d, num events %d\n", (ev->xcreatewindow.window), (ev->xany.serial), (numEventsHandled)); |
|
874 Java_sun_awt_motif_MEmbedCanvasPeer_embedChild(env, server, ev->xcreatewindow.window); |
|
875 break; |
|
876 case DestroyNotify: |
|
877 MTRACE("DestroyNotify\n"); |
|
878 Java_sun_awt_motif_MEmbedCanvasPeer_childDestroyed(env, server); |
|
879 break; |
|
880 case ReparentNotify: |
|
881 MTRACEP2("ReparentNotify for %x, parent %x\n", (ev->xreparent.window), (ev->xreparent.parent)); |
|
882 Java_sun_awt_motif_MEmbedCanvasPeer_embedChild(env, server, ev->xreparent.window); |
|
883 break; |
|
884 case ClientMessage: |
|
885 MTRACE("ClientMessage\n"); |
|
886 handleClientMessage(env, server, &ev->xclient); |
|
887 break; |
|
888 } |
|
889 AWT_UNLOCK(); |
|
890 } |
|
891 |
|
892 void |
|
893 dispatchEmbeddingClientEvent(XEvent * ev) { |
|
894 DASSERT(ev != NULL); |
|
895 MTRACE("dispatchEmbeddingClientEvent\n"); |
|
896 switch (ev->type) { |
|
897 case PropertyNotify: |
|
898 handlePropertyNotify(&ev->xproperty); |
|
899 break; |
|
900 case ConfigureNotify: |
|
901 handleConfigureNotify(&ev->xconfigure); |
|
902 break; |
|
903 } |
|
904 } |
|
905 |
|
906 void |
|
907 xembed_serverEventHandler(XEvent * ev) { |
|
908 pxembed_server_data sdata; |
|
909 sdata = getData(ev->xany.window); |
|
910 if (sdata != NULL) { // Event on client |
|
911 dispatchEmbeddingClientEvent(ev); |
|
912 } else { |
|
913 sdata = getDataByServerHandle(ev->xany.window); |
|
914 if (sdata != NULL) { |
|
915 DASSERT(sdata->server != NULL); |
|
916 dispatchEmbedderEvent(sdata->server, ev); |
|
917 } |
|
918 } |
|
919 } |
|
920 |
|
921 /**************************** XEmbed server DnD support ***********************/ |
|
922 void |
|
923 set_xembed_drop_target(JNIEnv* env, jobject server) { |
|
924 |
|
925 (*env)->CallVoidMethod(env, server, setXEmbedDropTargetMID); |
|
926 } |
|
927 |
|
928 void |
|
929 remove_xembed_drop_target(JNIEnv* env, jobject server) { |
|
930 (*env)->CallVoidMethod(env, server, removeXEmbedDropTargetMID); |
|
931 } |
|
932 |
|
933 Boolean |
|
934 is_xembed_client(Window window) { |
|
935 return getData(window) != NULL; |
|
936 } |
|
937 /******************************************************************************/ |
|
938 |
|
939 /* |
|
940 * Class: sun_awt_motif_MEmbedCanvasPeer |
|
941 * Method: getWindow |
|
942 * Signature: ()V |
|
943 */ |
|
944 JNIEXPORT jlong JNICALL |
|
945 Java_sun_awt_motif_MEmbedCanvasPeer_getWindow(JNIEnv *env, jobject this) { |
|
946 struct ComponentData *cdata; |
|
947 Window res = None; |
|
948 AWT_LOCK(); |
|
949 cdata = (struct ComponentData *) |
|
950 JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.pData); |
|
951 DASSERT(cdata != NULL); |
|
952 res = XtWindow(cdata->widget); |
|
953 AWT_UNLOCK(); |
|
954 return (jlong)res; |
|
955 } |
|
956 |
|
957 JNIEXPORT void JNICALL |
|
958 Java_sun_awt_motif_MEmbedCanvasPeer_forwardEventToEmbedded(JNIEnv *env, |
|
959 jobject this, |
|
960 jlong ctxt, |
|
961 jint eventID){ |
|
962 pxembed_server_data sdata; |
|
963 AWT_LOCK(); |
|
964 sdata = getDataByEmbedder(this); |
|
965 if (sdata != NULL) { |
|
966 forward_event_to_embedded(sdata->handle, ctxt, eventID); |
|
967 } |
|
968 AWT_UNLOCK(); |
|
969 } |
|