diff options
Diffstat (limited to 'src/newt/native/X11Display.c')
-rw-r--r-- | src/newt/native/X11Display.c | 660 |
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..283636040 --- /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; +} + +void NewtDisplay_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); + + NewtDisplay_displayDispatchErrorHandlerEnable(1, env); + + jwindow = getJavaWindowProperty(env, dpy, evt.xany.window, javaObjectAtom, + #ifdef VERBOSE_ON + True + #else + False + #endif + ); + + NewtDisplay_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); + } + } +} + + |