Recommended: Sing it, brah! 5 fabulous songs for developers
JW's Top 5
Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs
Page 4 of 7
Listing 3: Obtain the underlying windowing information from an AWT Canvas
/** File nativeMethods.c **/
#include <X11/Xlib.h>
#include <jni.h>
#include "jawt_md.h"
#include "SwingMenu.h"
/* The Java object canvas must be a java.awt.Canvas. */
JNIEXPORT void JNICALL Java_SwingMenu_attachShell(JNIEnv *env, jobject
obj, jobject canvas, jint shellWindow)
{
JAWT awt; /* defined in jawt.h which is included
in jawt_md.h */
JAWT_DrawingSurface *ds;
JAWT_DrawingSurfaceInfo *dsi;
JAWT_X11DrawingSurfaceInfo *dsi_X11;
jint lock;
Window win;
Display *dpy;
awt.version = JAWT_VERSION_1_3;
if (JAWT_GetAWT(env,&awt) == JNI_FALSE) {
fprintf(stderr, "Can't get AWT ! Exiting.\n");
exit(11);
}
ds = awt.GetDrawingSurface(env, canvas);
if (ds == NULL) {
fprintf(stderr, "Can't get drawind Surface ! Exiting.\n");
exit(12);
}
lock = ds->Lock(ds);
if ((lock & JAWT_LOCK_ERROR) != 0) {
fprintf(stderr, "Can't lock drawing surface ! Exiting.\n");
exit(13);
}
dsi = ds->GetDrawingSurfaceInfo(ds);
if (dsi == NULL) {
fprintf(stderr, "Can't get drawing Surface Information. Exiting !\n");
exit(14);
}
dsi_X11 = (JAWT_X11DrawingSurfaceInfo*)dsi->platformInfo;
dpy = dsi_X11->display;
win = dsi_X11->drawable;
ds->FreeDrawingSurfaceInfo(dsi);
ds->Unlock(ds);
awt.FreeDrawingSurface(ds);
}
The first thing to do is maintain a handle on an AWT structure that contains all the required information to complete the
job. Then you can access a JAWT_DrawingSurface, which is the drawing surface. After two switches to a JAWT_DrawingSurfaceInfo and to a JAWT_X11DrawingSurfaceInfo, you obtain the X11 window and the X11 display. Note that before receiving the information, you must lock your drawing surface
because Java is multithreaded, and the drawing surface's implementation might not be multithread-safe. In other words, if
two separate threads access the drawing surface concurrently, your application may crash. The locking mechanism forces the
threads to access the drawing surface one at a time.
Your Swing menu is now integrated with your legacy application. You have solved the window management issues, and you can
call back your legacy application from the Java code. Now you want to create an OpenGL window by pressing one of the Swing
buttons. To create such a window on Unix, you need to call OpenGL and glX functions (glX carefully integrates OpenGL with
X11). Why can't you proceed like you did before? Simply implement a C function declared native in your Java code and called from the actionPerformed()method. The native function would handle the OpenGL window creation. Don't spend long hours on this approach, as it will most likely fail because
of multithreading issues.
Java uses many threads -- one main thread, one for handling events, one for garbage collection, and so forth. That means different threads could concurrently access a function called from Java. Considering your application, for OpenGL and glX functions, the situation is even more complex as functions can also be called from the main thread of the legacy application.