summaryrefslogtreecommitdiffstats
path: root/src/newt/native/X11Display.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/newt/native/X11Display.c')
-rw-r--r--src/newt/native/X11Display.c660
1 files changed, 660 insertions, 0 deletions
diff --git a/src/newt/native/X11Display.c b/src/newt/native/X11Display.c
new file mode 100644
index 000000000..d6a099f1d
--- /dev/null
+++ b/src/newt/native/X11Display.c
@@ -0,0 +1,660 @@
+/**
+ * Copyright 2011 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+#include "X11Common.h"
+
+#define USE_SENDIO_DIRECT 1
+
+jclass X11NewtWindowClazz = NULL;
+jmethodID insetsChangedID = NULL;
+jmethodID visibleChangedID = NULL;
+
+static const char * const ClazzNameX11NewtWindow = "jogamp/newt/driver/x11/X11Window";
+
+static jmethodID displayCompletedID = NULL;
+
+static jmethodID sizeChangedID = NULL;
+static jmethodID positionChangedID = NULL;
+static jmethodID focusChangedID = NULL;
+static jmethodID reparentNotifyID = NULL;
+static jmethodID windowDestroyNotifyID = NULL;
+static jmethodID windowRepaintID = NULL;
+static jmethodID enqueueMouseEventID = NULL;
+static jmethodID sendMouseEventID = NULL;
+static jmethodID enqueueKeyEventID = NULL;
+static jmethodID sendKeyEventID = NULL;
+static jmethodID requestFocusID = NULL;
+
+static JavaVM *jvmHandle = NULL;
+static int jvmVersion = 0;
+
+static void setupJVMVars(JNIEnv * env) {
+ if(0 != (*env)->GetJavaVM(env, &jvmHandle)) {
+ jvmHandle = NULL;
+ }
+ jvmVersion = (*env)->GetVersion(env);
+}
+
+static XErrorHandler origErrorHandler = NULL ;
+
+static int displayDispatchErrorHandler(Display *dpy, XErrorEvent *e)
+{
+ fprintf(stderr, "Warning: NEWT X11 Error: DisplayDispatch %p, Code 0x%X, errno %s\n", dpy, e->error_code, strerror(errno));
+
+ if (e->error_code == BadAtom) {
+ fprintf(stderr, " BadAtom (%p): Atom probably already removed\n", (void*)e->resourceid);
+ } else if (e->error_code == BadWindow) {
+ fprintf(stderr, " BadWindow (%p): Window probably already removed\n", (void*)e->resourceid);
+ } else {
+ int shallBeDetached = 0;
+ JNIEnv *jniEnv = NULL;
+ const char * errStr = strerror(errno);
+
+ fprintf(stderr, "Info: NEWT X11 Error: Display %p, Code 0x%X, errno %s\n", dpy, e->error_code, errStr);
+
+ jniEnv = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached);
+ if(NULL==jniEnv) {
+ fprintf(stderr, "NEWT X11 Error: null JNIEnv");
+ return;
+ }
+
+ NewtCommon_throwNewRuntimeException(jniEnv, "Info: NEWT X11 Error: Display %p, Code 0x%X, errno %s",
+ dpy, e->error_code, errStr);
+
+ if (shallBeDetached) {
+ (*jvmHandle)->DetachCurrentThread(jvmHandle);
+ }
+ }
+
+ return 0;
+}
+
+static void displayDispatchErrorHandlerEnable(int onoff, JNIEnv * env) {
+ if(onoff) {
+ if(NULL==origErrorHandler) {
+ setupJVMVars(env);
+ origErrorHandler = XSetErrorHandler(displayDispatchErrorHandler);
+ }
+ } else {
+ if(NULL!=origErrorHandler) {
+ XSetErrorHandler(origErrorHandler);
+ origErrorHandler = NULL;
+ }
+ }
+}
+
+/**
+ * Keycode
+ */
+
+#define IS_WITHIN(k,a,b) ((a)<=(k)&&(k)<=(b))
+
+static jint X11KeySym2NewtVKey(KeySym keySym) {
+ if(IS_WITHIN(keySym,XK_F1,XK_F12))
+ return (keySym-XK_F1)+J_VK_F1;
+ if(IS_WITHIN(keySym,XK_KP_0,XK_KP_9))
+ return (keySym-XK_KP_0)+J_VK_NUMPAD0;
+
+ switch(keySym) {
+ case XK_Return:
+ case XK_KP_Enter:
+ return J_VK_ENTER;
+ case XK_BackSpace:
+ return J_VK_BACK_SPACE;
+ case XK_Tab:
+ case XK_KP_Tab:
+ case XK_ISO_Left_Tab:
+ return J_VK_TAB;
+ case XK_Cancel:
+ return J_VK_CANCEL;
+ case XK_Clear:
+ return J_VK_CLEAR;
+ case XK_Shift_L:
+ case XK_Shift_R:
+ return J_VK_SHIFT;
+ case XK_Control_L:
+ case XK_Control_R:
+ return J_VK_CONTROL;
+ case XK_Alt_L:
+ case XK_Alt_R:
+ return J_VK_ALT;
+ case XK_Pause:
+ return J_VK_PAUSE;
+ case XK_Caps_Lock:
+ return J_VK_CAPS_LOCK;
+ case XK_Escape:
+ return J_VK_ESCAPE;
+ case XK_space:
+ case XK_KP_Space:
+ return J_VK_SPACE;
+ case XK_Page_Up:
+ case XK_KP_Page_Up:
+ return J_VK_PAGE_UP;
+ case XK_Page_Down:
+ case XK_KP_Page_Down:
+ return J_VK_PAGE_DOWN;
+ case XK_End:
+ case XK_KP_End:
+ return J_VK_END;
+ case XK_Home:
+ case XK_KP_Home:
+ return J_VK_HOME;
+ case XK_Left:
+ case XK_KP_Left:
+ return J_VK_LEFT;
+ case XK_Up:
+ case XK_KP_Up:
+ return J_VK_UP;
+ case XK_Right:
+ case XK_KP_Right:
+ return J_VK_RIGHT;
+ case XK_Down:
+ case XK_KP_Down:
+ return J_VK_DOWN;
+ case XK_KP_Multiply:
+ return J_VK_MULTIPLY;
+ case XK_KP_Add:
+ return J_VK_ADD;
+ case XK_KP_Separator:
+ return J_VK_SEPARATOR;
+ case XK_KP_Subtract:
+ return J_VK_SUBTRACT;
+ case XK_KP_Decimal:
+ return J_VK_DECIMAL;
+ case XK_KP_Divide:
+ return J_VK_DIVIDE;
+ case XK_Delete:
+ case XK_KP_Delete:
+ return J_VK_DELETE;
+ case XK_Num_Lock:
+ return J_VK_NUM_LOCK;
+ case XK_Scroll_Lock:
+ return J_VK_SCROLL_LOCK;
+ case XK_Print:
+ return J_VK_PRINTSCREEN;
+ case XK_Insert:
+ case XK_KP_Insert:
+ return J_VK_INSERT;
+ case XK_Help:
+ return J_VK_HELP;
+ }
+ return keySym;
+}
+
+static jint X11InputState2NewtModifiers(unsigned int xstate) {
+ jint modifiers = 0;
+ if ((ControlMask & xstate) != 0) {
+ modifiers |= EVENT_CTRL_MASK;
+ }
+ if ((ShiftMask & xstate) != 0) {
+ modifiers |= EVENT_SHIFT_MASK;
+ }
+ if ((Mod1Mask & xstate) != 0) {
+ modifiers |= EVENT_ALT_MASK;
+ }
+ if ((Button1Mask & xstate) != 0) {
+ modifiers |= EVENT_BUTTON1_MASK;
+ }
+ if ((Button2Mask & xstate) != 0) {
+ modifiers |= EVENT_BUTTON2_MASK;
+ }
+ if ((Button3Mask & xstate) != 0) {
+ modifiers |= EVENT_BUTTON3_MASK;
+ }
+
+ return modifiers;
+}
+
+
+/**
+ * Keycode
+ */
+
+/*
+ * Class: jogamp_newt_driver_x11_X11Display
+ * Method: initIDs
+ * Signature: (Z)Z
+ */
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_X11Display_initIDs0
+ (JNIEnv *env, jclass clazz)
+{
+ jclass c;
+
+ NewtCommon_init(env);
+
+ if(NULL==X11NewtWindowClazz) {
+ c = (*env)->FindClass(env, ClazzNameX11NewtWindow);
+ if(NULL==c) {
+ NewtCommon_FatalError(env, "NEWT X11Window: can't find %s", ClazzNameX11NewtWindow);
+ }
+ X11NewtWindowClazz = (jclass)(*env)->NewGlobalRef(env, c);
+ (*env)->DeleteLocalRef(env, c);
+ if(NULL==X11NewtWindowClazz) {
+ NewtCommon_FatalError(env, "NEWT X11Window: can't use %s", ClazzNameX11NewtWindow);
+ }
+ }
+
+ displayCompletedID = (*env)->GetMethodID(env, clazz, "displayCompleted", "(JJ)V");
+ insetsChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "insetsChanged", "(ZIIII)V");
+ sizeChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sizeChanged", "(ZIIZ)V");
+ positionChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "positionChanged", "(ZII)V");
+ focusChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "focusChanged", "(ZZ)V");
+ visibleChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "visibleChanged", "(ZZ)V");
+ reparentNotifyID = (*env)->GetMethodID(env, X11NewtWindowClazz, "reparentNotify", "(J)V");
+ windowDestroyNotifyID = (*env)->GetMethodID(env, X11NewtWindowClazz, "windowDestroyNotify", "()V");
+ windowRepaintID = (*env)->GetMethodID(env, X11NewtWindowClazz, "windowRepaint", "(ZIIII)V");
+ enqueueMouseEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "enqueueMouseEvent", "(ZIIIIII)V");
+ sendMouseEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendMouseEvent", "(IIIIII)V");
+ enqueueKeyEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "enqueueKeyEvent", "(ZIIIC)V");
+ sendKeyEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendKeyEvent", "(IIIC)V");
+ requestFocusID = (*env)->GetMethodID(env, X11NewtWindowClazz, "requestFocus", "(Z)V");
+
+ if (displayCompletedID == NULL ||
+ insetsChangedID == NULL ||
+ sizeChangedID == NULL ||
+ positionChangedID == NULL ||
+ focusChangedID == NULL ||
+ visibleChangedID == NULL ||
+ reparentNotifyID == NULL ||
+ windowDestroyNotifyID == NULL ||
+ windowRepaintID == NULL ||
+ enqueueMouseEventID == NULL ||
+ sendMouseEventID == NULL ||
+ enqueueKeyEventID == NULL ||
+ sendKeyEventID == NULL ||
+ requestFocusID == NULL) {
+ return JNI_FALSE;
+ }
+
+
+ return JNI_TRUE;
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_X11Display
+ * Method: CompleteDisplay
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Display_CompleteDisplay0
+ (JNIEnv *env, jobject obj, jlong display)
+{
+ Display * dpy = (Display *)(intptr_t)display;
+ jlong javaObjectAtom;
+ jlong windowDeleteAtom;
+
+ if(dpy==NULL) {
+ NewtCommon_FatalError(env, "invalid display connection..");
+ }
+
+ javaObjectAtom = (jlong) XInternAtom(dpy, "NEWT_JAVA_OBJECT", False);
+ if(None==javaObjectAtom) {
+ NewtCommon_throwNewRuntimeException(env, "could not create Atom NEWT_JAVA_OBJECT, bail out!");
+ return;
+ }
+
+ windowDeleteAtom = (jlong) XInternAtom(dpy, "WM_DELETE_WINDOW", False);
+ if(None==windowDeleteAtom) {
+ NewtCommon_throwNewRuntimeException(env, "could not create Atom WM_DELETE_WINDOW, bail out!");
+ return;
+ }
+
+ // XSetCloseDownMode(dpy, RetainTemporary); // Just a try ..
+
+ DBG_PRINT("X11: X11Display_completeDisplay dpy %p\n", dpy);
+
+ (*env)->CallVoidMethod(env, obj, displayCompletedID, javaObjectAtom, windowDeleteAtom);
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_X11Display
+ * Method: DisplayRelease0
+ * Signature: (JJJ)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Display_DisplayRelease0
+ (JNIEnv *env, jobject obj, jlong display, jlong javaObjectAtom, jlong windowDeleteAtom)
+{
+ Display * dpy = (Display *)(intptr_t)display;
+ Atom wm_javaobject_atom = (Atom)javaObjectAtom;
+ Atom wm_delete_atom = (Atom)windowDeleteAtom;
+
+ if(dpy==NULL) {
+ NewtCommon_FatalError(env, "invalid display connection..");
+ }
+
+ // nothing to do to free the atoms !
+ (void) wm_javaobject_atom;
+ (void) wm_delete_atom;
+
+ XSync(dpy, True); // discard all pending events
+ DBG_PRINT("X11: X11Display_DisplayRelease dpy %p\n", dpy);
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_X11Display
+ * Method: DispatchMessages
+ * Signature: (JIJJ)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Display_DispatchMessages0
+ (JNIEnv *env, jobject obj, jlong display, jlong javaObjectAtom, jlong windowDeleteAtom)
+{
+ Display * dpy = (Display *) (intptr_t) display;
+ Atom wm_delete_atom = (Atom)windowDeleteAtom;
+ int num_events = 100;
+
+ if ( NULL == dpy ) {
+ return;
+ }
+
+ // Periodically take a break
+ while( num_events > 0 ) {
+ jobject jwindow = NULL;
+ XEvent evt;
+ KeySym keySym = 0;
+ jint modifiers = 0;
+ char keyChar = 0;
+ char text[255];
+
+ // XEventsQueued(dpy, X):
+ // QueuedAlready : No I/O Flush or system call doesn't work on some cards (eg ATI) ?)
+ // QueuedAfterFlush == XPending(): I/O Flush only if no already queued events are available
+ // QueuedAfterReading : QueuedAlready + if queue==0, attempt to read more ..
+ if ( 0 >= XPending(dpy) ) {
+ // DBG_PRINT( "X11: DispatchMessages 0x%X - Leave 1\n", dpy);
+ return;
+ }
+
+ XNextEvent(dpy, &evt);
+ num_events--;
+
+ if( 0==evt.xany.window ) {
+ NewtCommon_throwNewRuntimeException(env, "event window NULL, bail out!");
+ return ;
+ }
+
+ if(dpy!=evt.xany.display) {
+ NewtCommon_throwNewRuntimeException(env, "wrong display, bail out!");
+ return ;
+ }
+
+ // DBG_PRINT( "X11: DispatchMessages dpy %p, win %p, Event %d\n", (void*)dpy, (void*)evt.xany.window, (int)evt.type);
+
+ displayDispatchErrorHandlerEnable(1, env);
+
+ jwindow = getJavaWindowProperty(env, dpy, evt.xany.window, javaObjectAtom,
+ #ifdef VERBOSE_ON
+ True
+ #else
+ False
+ #endif
+ );
+
+ displayDispatchErrorHandlerEnable(0, env);
+
+ if(NULL==jwindow) {
+ fprintf(stderr, "Warning: NEWT X11 DisplayDispatch %p, Couldn't handle event %d for X11 window %p\n",
+ (void*)dpy, evt.type, (void*)evt.xany.window);
+ continue;
+ }
+
+ switch(evt.type) {
+ case KeyRelease:
+ case KeyPress:
+ if(XLookupString(&evt.xkey,text,255,&keySym,0)==1) {
+ KeySym lower_return = 0, upper_return = 0;
+ keyChar=text[0];
+ XConvertCase(keySym, &lower_return, &upper_return);
+ // always return upper case, set modifier masks (SHIFT, ..)
+ keySym = X11KeySym2NewtVKey(upper_return);
+ } else {
+ keyChar=0;
+ keySym = X11KeySym2NewtVKey(keySym);
+ }
+ modifiers = X11InputState2NewtModifiers(evt.xkey.state);
+ break;
+
+ case ButtonPress:
+ case ButtonRelease:
+ case MotionNotify:
+ modifiers = X11InputState2NewtModifiers(evt.xbutton.state);
+ break;
+
+ default:
+ break;
+ }
+
+ switch(evt.type) {
+ case ButtonPress:
+ (*env)->CallVoidMethod(env, jwindow, requestFocusID, JNI_FALSE);
+ #ifdef USE_SENDIO_DIRECT
+ (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_PRESSED,
+ modifiers,
+ (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0 /*rotation*/);
+ #else
+ (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_PRESSED,
+ modifiers,
+ (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0 /*rotation*/);
+ #endif
+ break;
+ case ButtonRelease:
+ #ifdef USE_SENDIO_DIRECT
+ (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_RELEASED,
+ modifiers,
+ (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0 /*rotation*/);
+ #else
+ (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_RELEASED,
+ modifiers,
+ (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0 /*rotation*/);
+ #endif
+ break;
+ case MotionNotify:
+ #ifdef USE_SENDIO_DIRECT
+ (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_MOVED,
+ modifiers,
+ (jint) evt.xmotion.x, (jint) evt.xmotion.y, (jint) 0, 0 /*rotation*/);
+ #else
+ (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_MOVED,
+ modifiers,
+ (jint) evt.xmotion.x, (jint) evt.xmotion.y, (jint) 0, 0 /*rotation*/);
+ #endif
+ break;
+ case EnterNotify:
+ DBG_PRINT( "X11: event . EnterNotify call %p %d/%d\n", (void*)evt.xcrossing.window, evt.xcrossing.x, evt.xcrossing.y);
+ #ifdef USE_SENDIO_DIRECT
+ (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_ENTERED,
+ modifiers,
+ (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0 /*rotation*/);
+ #else
+ (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_ENTERED,
+ modifiers,
+ (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0 /*rotation*/);
+ #endif
+ break;
+ case LeaveNotify:
+ DBG_PRINT( "X11: event . LeaveNotify call %p %d/%d\n", (void*)evt.xcrossing.window, evt.xcrossing.x, evt.xcrossing.y);
+ #ifdef USE_SENDIO_DIRECT
+ (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_EXITED,
+ modifiers,
+ (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0 /*rotation*/);
+ #else
+ (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_EXITED,
+ modifiers,
+ (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0 /*rotation*/);
+ #endif
+ break;
+ case KeyPress:
+ #ifdef USE_SENDIO_DIRECT
+ (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_PRESSED,
+ modifiers, keySym, (jchar) -1);
+ #else
+ (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_PRESSED,
+ modifiers, keySym, (jchar) -1);
+ #endif
+
+ break;
+ case KeyRelease:
+ #ifdef USE_SENDIO_DIRECT
+ (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_RELEASED,
+ modifiers, keySym, (jchar) -1);
+
+ (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_TYPED,
+ modifiers, keySym, (jchar) keyChar);
+ #else
+ (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_RELEASED,
+ modifiers, keySym, (jchar) -1);
+
+ (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_TYPED,
+ modifiers, keySym, (jchar) keyChar);
+ #endif
+
+ break;
+ case DestroyNotify:
+ DBG_PRINT( "X11: event . DestroyNotify call %p, parent %p, child-event: %d\n",
+ (void*)evt.xdestroywindow.window, (void*)evt.xdestroywindow.event, evt.xdestroywindow.window != evt.xdestroywindow.event);
+ if ( evt.xdestroywindow.window == evt.xdestroywindow.event ) {
+ // ignore child destroy notification
+ }
+ break;
+ case CreateNotify:
+ DBG_PRINT( "X11: event . CreateNotify call %p, parent %p, child-event: 1\n",
+ (void*)evt.xcreatewindow.window, (void*) evt.xcreatewindow.parent);
+ break;
+ case ConfigureNotify:
+ DBG_PRINT( "X11: event . ConfigureNotify call %p (parent %p, above %p) %d/%d %dx%d %d, child-event: %d\n",
+ (void*)evt.xconfigure.window, (void*)evt.xconfigure.event, (void*)evt.xconfigure.above,
+ evt.xconfigure.x, evt.xconfigure.y, evt.xconfigure.width, evt.xconfigure.height,
+ evt.xconfigure.override_redirect, evt.xconfigure.window != evt.xconfigure.event);
+ if ( evt.xconfigure.window == evt.xconfigure.event ) {
+ // ignore child window change notification
+ {
+ // update insets
+ int left, right, top, bottom;
+ NewtWindows_updateInsets(env, jwindow, dpy, evt.xany.window, &left, &right, &top, &bottom);
+ }
+ (*env)->CallVoidMethod(env, jwindow, sizeChangedID, JNI_FALSE,
+ (jint) evt.xconfigure.width, (jint) evt.xconfigure.height, JNI_FALSE);
+ (*env)->CallVoidMethod(env, jwindow, positionChangedID, JNI_FALSE,
+ (jint) evt.xconfigure.x, (jint) evt.xconfigure.y);
+ }
+ break;
+ case ClientMessage:
+ if (evt.xclient.send_event==True && evt.xclient.data.l[0]==wm_delete_atom) { // windowDeleteAtom
+ DBG_PRINT( "X11: event . ClientMessage call %p type 0x%X !!!\n",
+ (void*)evt.xclient.window, (unsigned int)evt.xclient.message_type);
+ (*env)->CallVoidMethod(env, jwindow, windowDestroyNotifyID);
+ // Called by Window.java: CloseWindow();
+ num_events = 0; // end loop in case of destroyed display
+ }
+ break;
+
+ case FocusIn:
+ DBG_PRINT( "X11: event . FocusIn call %p\n", (void*)evt.xvisibility.window);
+ (*env)->CallVoidMethod(env, jwindow, focusChangedID, JNI_FALSE, JNI_TRUE);
+ break;
+
+ case FocusOut:
+ DBG_PRINT( "X11: event . FocusOut call %p\n", (void*)evt.xvisibility.window);
+ (*env)->CallVoidMethod(env, jwindow, focusChangedID, JNI_FALSE, JNI_FALSE);
+ break;
+
+ case Expose:
+ DBG_PRINT( "X11: event . Expose call %p %d/%d %dx%d count %d\n", (void*)evt.xexpose.window,
+ evt.xexpose.x, evt.xexpose.y, evt.xexpose.width, evt.xexpose.height, evt.xexpose.count);
+
+ if (evt.xexpose.count == 0 && evt.xexpose.width > 0 && evt.xexpose.height > 0) {
+ (*env)->CallVoidMethod(env, jwindow, windowRepaintID, JNI_FALSE,
+ evt.xexpose.x, evt.xexpose.y, evt.xexpose.width, evt.xexpose.height);
+ }
+ break;
+
+ case MapNotify:
+ DBG_PRINT( "X11: event . MapNotify call Event %p, Window %p, override_redirect %d, child-event: %d\n",
+ (void*)evt.xmap.event, (void*)evt.xmap.window, (int)evt.xmap.override_redirect,
+ evt.xmap.event!=evt.xmap.window);
+ if( evt.xmap.event == evt.xmap.window ) {
+ // ignore child window notification
+ {
+ // update insets
+ int left, right, top, bottom;
+ NewtWindows_updateInsets(env, jwindow, dpy, evt.xany.window, &left, &right, &top, &bottom);
+ }
+ (*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_FALSE, JNI_TRUE);
+ }
+ break;
+
+ case UnmapNotify:
+ DBG_PRINT( "X11: event . UnmapNotify call Event %p, Window %p, from_configure %d, child-event: %d\n",
+ (void*)evt.xunmap.event, (void*)evt.xunmap.window, (int)evt.xunmap.from_configure,
+ evt.xunmap.event!=evt.xunmap.window);
+ if( evt.xunmap.event == evt.xunmap.window ) {
+ // ignore child window notification
+ (*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_FALSE, JNI_FALSE);
+ }
+ break;
+
+ case ReparentNotify:
+ {
+ jlong parentResult; // 0 if root, otherwise proper value
+ Window winRoot, winTopParent;
+ #ifdef VERBOSE_ON
+ Window oldParentRoot, oldParentTopParent;
+ Window parentRoot, parentTopParent;
+ if( 0 == NewtWindows_getRootAndParent(dpy, evt.xreparent.event, &oldParentRoot, &oldParentTopParent) ) {
+ oldParentRoot=0; oldParentTopParent = 0;
+ }
+ if( 0 == NewtWindows_getRootAndParent(dpy, evt.xreparent.parent, &parentRoot, &parentTopParent) ) {
+ parentRoot=0; parentTopParent = 0;
+ }
+ #endif
+ if( 0 == NewtWindows_getRootAndParent(dpy, evt.xreparent.window, &winRoot, &winTopParent) ) {
+ winRoot=0; winTopParent = 0;
+ }
+ if(evt.xreparent.parent == winRoot) {
+ parentResult = 0; // our java indicator for root window
+ } else {
+ parentResult = (jlong) (intptr_t) evt.xreparent.parent;
+ }
+ #ifdef VERBOSE_ON
+ DBG_PRINT( "X11: event . ReparentNotify: call %d/%d OldParent %p (root %p, top %p), NewParent %p (root %p, top %p), Window %p (root %p, top %p)\n",
+ evt.xreparent.x, evt.xreparent.y,
+ (void*)evt.xreparent.event, (void*)oldParentRoot, (void*)oldParentTopParent,
+ (void*)evt.xreparent.parent, (void*)parentRoot, (void*)parentTopParent,
+ (void*)evt.xreparent.window, (void*)winRoot, (void*)winTopParent);
+ #endif
+ (*env)->CallVoidMethod(env, jwindow, reparentNotifyID, (jlong)evt.xreparent.parent);
+ }
+ break;
+
+ // unhandled events .. yet ..
+
+ default:
+ DBG_PRINT("X11: event . unhandled %d 0x%X call %p\n", (int)evt.type, (unsigned int)evt.type, (void*)evt.xunmap.window);
+ }
+ }
+}
+
+