diff options
Diffstat (limited to 'src/newt/native')
-rw-r--r-- | src/newt/native/KDWindow.c | 2 | ||||
-rw-r--r-- | src/newt/native/KeyEvent.h | 27 | ||||
-rw-r--r-- | src/newt/native/MacWindow.m | 295 | ||||
-rw-r--r-- | src/newt/native/MouseEvent.h | 27 | ||||
-rw-r--r-- | src/newt/native/NewtCommon.h | 27 | ||||
-rw-r--r-- | src/newt/native/NewtMacWindow.h | 10 | ||||
-rw-r--r-- | src/newt/native/NewtMacWindow.m | 111 | ||||
-rw-r--r-- | src/newt/native/ScreenMode.h | 28 | ||||
-rw-r--r-- | src/newt/native/Window.h | 27 | ||||
-rw-r--r-- | src/newt/native/WindowEvent.h | 27 | ||||
-rw-r--r-- | src/newt/native/WindowsWindow.c | 111 | ||||
-rw-r--r-- | src/newt/native/X11Common.h | 80 | ||||
-rw-r--r-- | src/newt/native/X11Display.c | 660 | ||||
-rw-r--r-- | src/newt/native/X11Screen.c | 469 | ||||
-rw-r--r-- | src/newt/native/X11Window.c | 1115 |
15 files changed, 1784 insertions, 1232 deletions
diff --git a/src/newt/native/KDWindow.c b/src/newt/native/KDWindow.c index 5f1affed1..e6bc7952e 100644 --- a/src/newt/native/KDWindow.c +++ b/src/newt/native/KDWindow.c @@ -256,7 +256,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_kd_KDWindow_RealizeWindow jint res = kdRealizeWindow(w, &nativeWindow); if(res) { fprintf(stderr, "[RealizeWindow] failed: 0x%X, 0x%X\n", res, kdGetError()); - nativeWindow = NULL; + nativeWindow = 0; } DBG_PRINT( "[RealizeWindow] ok: %p\n", nativeWindow); return (jlong) (intptr_t) nativeWindow; diff --git a/src/newt/native/KeyEvent.h b/src/newt/native/KeyEvent.h index 1ead0f5e8..0f7b1606b 100644 --- a/src/newt/native/KeyEvent.h +++ b/src/newt/native/KeyEvent.h @@ -1,3 +1,30 @@ +/** + * 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. + */ #ifndef _KEY_EVENT_H_ #define _KEY_EVENT_H_ diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m index a13ffaf31..ddd59f0a1 100644 --- a/src/newt/native/MacWindow.m +++ b/src/newt/native/MacWindow.m @@ -38,6 +38,7 @@ #import "MouseEvent.h" #import "KeyEvent.h" +#import "ScreenMode.h" #import <ApplicationServices/ApplicationServices.h> @@ -48,7 +49,6 @@ static const char * const ClazzAnyCstrName = "<init>"; static const char * const ClazzNamePointCstrSignature = "(II)V"; static jclass pointClz = NULL; static jmethodID pointCstr = NULL; -static jmethodID focusActionID = NULL; static NSString* jstringToNSString(JNIEnv* env, jstring jstr) { @@ -192,13 +192,57 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_MacDisplay_initNSAppli JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacDisplay_runNSApplication0 (JNIEnv *env, jclass clazz) { - // NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; DBG_PRINT( "\nrunNSApplication0.0\n"); [NSApp run]; DBG_PRINT( "\nrunNSApplication0.X\n"); - // [pool release]; + [pool release]; +} + +/* + * Class: jogamp_newt_driver_macosx_MacDisplay + * Method: stopNSApplication0 + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacDisplay_stopNSApplication0 + (JNIEnv *env, jclass clazz) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + DBG_PRINT( "\nstopNSApplication0.0 nsApp.running %d\n", (NSApp && [NSApp isRunning])); + + if(NSApp && [NSApp isRunning]) { + [NSApp performSelectorOnMainThread:@selector(stop:) withObject:nil waitUntilDone:YES]; + // [NSApp stop: nil]; + NSEvent* event = [NSEvent otherEventWithType: NSApplicationDefined + location: NSMakePoint(0,0) + modifierFlags: 0 + timestamp: 0.0 + windowNumber: 0 + context: nil + subtype: 0 + data1: 0 + data2: 0]; + DBG_PRINT( "\nstopNSApplication0.1\n"); + [NSApp postEvent: event atStart: true]; + } + /** + DBG_PRINT( "\nstopNSApplication0.2\n"); + if(NSApp && [NSApp isRunning]) { + DBG_PRINT( "\nstopNSApplication0.3\n"); + [NSApp terminate:nil]; + } */ + + DBG_PRINT( "\nstopNSApplication0.X\n"); + [pool release]; +} + +static NSScreen * NewtScreen_getNSScreenByIndex(int screen_idx) { + NSArray *screens = [NSScreen screens]; + if(screen_idx<0) screen_idx=0; + if(screen_idx>=[screens count]) screen_idx=0; + return (NSScreen *) [screens objectAtIndex: screen_idx]; } /* @@ -211,10 +255,7 @@ JNIEXPORT jint JNICALL Java_jogamp_newt_driver_macosx_MacScreen_getWidthImpl0 { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - NSArray *screens = [NSScreen screens]; - if(screen_idx<0) screen_idx=0; - if(screen_idx>=[screens count]) screen_idx=0; - NSScreen *screen = (NSScreen *) [screens objectAtIndex: screen_idx]; + NSScreen *screen = NewtScreen_getNSScreenByIndex((int)screen_idx); NSRect rect = [screen frame]; [pool release]; @@ -232,10 +273,7 @@ JNIEXPORT jint JNICALL Java_jogamp_newt_driver_macosx_MacScreen_getHeightImpl0 { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - NSArray *screens = [NSScreen screens]; - if(screen_idx<0) screen_idx=0; - if(screen_idx>=[screens count]) screen_idx=0; - NSScreen *screen = (NSScreen *) [screens objectAtIndex: screen_idx]; + NSScreen *screen = NewtScreen_getNSScreenByIndex((int)screen_idx); NSRect rect = [screen frame]; [pool release]; @@ -243,6 +281,175 @@ JNIEXPORT jint JNICALL Java_jogamp_newt_driver_macosx_MacScreen_getHeightImpl0 return (jint) (rect.size.height); } +static CGDirectDisplayID NewtScreen_getCGDirectDisplayIDByNSScreen(NSScreen *screen) { + // Mind: typedef uint32_t CGDirectDisplayID; - however, we assume it's 64bit on 64bit ?! + NSDictionary * dict = [screen deviceDescription]; + NSNumber * val = (NSNumber *) [dict objectForKey: @"NSScreenNumber"]; + // [NSNumber integerValue] returns NSInteger which is 32 or 64 bit native size + return (CGDirectDisplayID) [val integerValue]; +} + +/** + * Only in >= 10.6: + * CGDisplayModeGetWidth(mode) + * CGDisplayModeGetRefreshRate(mode) + * CGDisplayModeGetHeight(mode) + */ +static long GetDictionaryLong(CFDictionaryRef theDict, const void* key) +{ + long value = 0; + CFNumberRef numRef; + numRef = (CFNumberRef)CFDictionaryGetValue(theDict, key); + if (numRef != NULL) + CFNumberGetValue(numRef, kCFNumberLongType, &value); + return value; +} +#define CGDDGetModeWidth(mode) GetDictionaryLong((mode), kCGDisplayWidth) +#define CGDDGetModeHeight(mode) GetDictionaryLong((mode), kCGDisplayHeight) +#define CGDDGetModeRefreshRate(mode) GetDictionaryLong((mode), kCGDisplayRefreshRate) +#define CGDDGetModeBitsPerPixel(mode) GetDictionaryLong((mode), kCGDisplayBitsPerPixel) + +// Duplicate each Mode by all possible rotations (4): +// For each real-mode: [mode, 0], [mode, 90], [mode, 180], [mode, 270] +#define ROTMODES_PER_REALMODE 4 + +/* + * Class: jogamp_newt_driver_macosx_MacScreen + * Method: getScreenMode0 + * Signature: (II)[I + */ +JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_MacScreen_getScreenMode0 + (JNIEnv *env, jobject obj, jint scrn_idx, jint mode_idx) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + + int prop_num = NUM_SCREEN_MODE_PROPERTIES_ALL; + NSScreen *screen = NewtScreen_getNSScreenByIndex((int)scrn_idx); + CGDirectDisplayID display = NewtScreen_getCGDirectDisplayIDByNSScreen(screen); + + CFArrayRef availableModes = CGDisplayAvailableModes(display); + CFIndex numberOfAvailableModes = CFArrayGetCount(availableModes); + CFIndex numberOfAvailableModesRots = ROTMODES_PER_REALMODE * numberOfAvailableModes; + CFDictionaryRef mode = NULL; + int currentCCWRot = (int)CGDisplayRotation(display); + jint ccwRot = 0; + +#ifdef VERBOSE_ON + if(0 >= mode_idx) { + // only for current mode (-1) and first mode (scanning) + DBG_PRINT( "getScreenMode0: scrn %d (%p, %p), mode %d, avail: %d/%d, current rot %d ccw\n", + (int)scrn_idx, screen, (void*)(intptr_t)display, (int)mode_idx, (int)numberOfAvailableModes, (int)numberOfAvailableModesRots, currentCCWRot); + } +#endif + + if(numberOfAvailableModesRots<=mode_idx) { + // n/a - end of modes + DBG_PRINT( "getScreenMode0: end of modes: mode %d, avail: %d/%d\n", + (int)mode_idx, (int)numberOfAvailableModes, (int)numberOfAvailableModesRots); + [pool release]; + return (*env)->NewIntArray(env, 0); + } else if(-1 < mode_idx) { + // only at initialization time, where index >= 0 + prop_num++; // add 1st extra prop, mode_idx + mode = (CFDictionaryRef)CFArrayGetValueAtIndex(availableModes, mode_idx / ROTMODES_PER_REALMODE); + ccwRot = mode_idx % ROTMODES_PER_REALMODE * 90; + } else { + // current mode + mode = CGDisplayCurrentMode(display); + ccwRot = currentCCWRot; + } + // mode = CGDisplayModeRetain(mode); // 10.6 on CGDisplayModeRef + + CGSize screenDim = CGDisplayScreenSize(display); + int mWidth = CGDDGetModeWidth(mode); + int mHeight = CGDDGetModeHeight(mode); + + // swap width and height, since OSX reflects rotated dimension, we don't + if ( 90 == currentCCWRot || 270 == currentCCWRot ) { + int tempWidth = mWidth; + mWidth = mHeight; + mHeight = tempWidth; + } + + jint prop[ prop_num ]; + int propIndex = 0; + int propIndexRes = 0; + + if( -1 < mode_idx ) { + prop[propIndex++] = mode_idx; + } + prop[propIndex++] = 0; // set later for verification of iterator + propIndexRes = propIndex; + prop[propIndex++] = mWidth; + prop[propIndex++] = mHeight; + prop[propIndex++] = CGDDGetModeBitsPerPixel(mode); + prop[propIndex++] = (jint) screenDim.width; + prop[propIndex++] = (jint) screenDim.height; + prop[propIndex++] = CGDDGetModeRefreshRate(mode); + prop[propIndex++] = ccwRot; + prop[propIndex - NUM_SCREEN_MODE_PROPERTIES_ALL] = ( -1 < mode_idx ) ? propIndex-1 : propIndex ; // count == NUM_SCREEN_MODE_PROPERTIES_ALL + + DBG_PRINT( "getScreenMode0: Mode %d/%d (%d): %dx%d, %d bpp, %dx%d mm, %d Hz, rot %d ccw\n", + (int)mode_idx, (int)numberOfAvailableModesRots, (int)numberOfAvailableModes, + (int)prop[propIndexRes+0], (int)prop[propIndexRes+1], (int)prop[propIndexRes+2], + (int)prop[propIndexRes+3], (int)prop[propIndexRes+4], (int)prop[propIndexRes+5], (int)prop[propIndexRes+6]); + + jintArray properties = (*env)->NewIntArray(env, prop_num); + if (properties == NULL) { + NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", prop_num); + } + (*env)->SetIntArrayRegion(env, properties, 0, prop_num, prop); + + // CGDisplayModeRelease(mode); // 10.6 on CGDisplayModeRef + [pool release]; + + return properties; +} + +/* + * Class: jogamp_newt_driver_macosx_MacScreen + * Method: setScreenMode0 + * Signature: (II)Z + */ +JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_MacScreen_setScreenMode0 + (JNIEnv *env, jobject object, jint scrn_idx, jint mode_idx) +{ + jboolean res = JNI_TRUE; + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + + NSScreen *screen = NewtScreen_getNSScreenByIndex((int)scrn_idx); + CGDirectDisplayID display = NewtScreen_getCGDirectDisplayIDByNSScreen(screen); + + CFArrayRef availableModes = CGDisplayAvailableModes(display); + CFIndex numberOfAvailableModes = CFArrayGetCount(availableModes); + CFIndex numberOfAvailableModesRots = ROTMODES_PER_REALMODE * numberOfAvailableModes; + + CFDictionaryRef mode = (CFDictionaryRef)CFArrayGetValueAtIndex(availableModes, mode_idx / ROTMODES_PER_REALMODE); + // mode = CGDisplayModeRetain(mode); // 10.6 on CGDisplayModeRef + + int ccwRot = mode_idx % ROTMODES_PER_REALMODE * 90; + DBG_PRINT( "setScreenMode0: scrn %d (%p, %p), mode %d, rot %d ccw, avail: %d/%d\n", + (int)scrn_idx, screen, (void*)(intptr_t)display, (int)mode_idx, ccwRot, (int)numberOfAvailableModes, (int)numberOfAvailableModesRots); + + if(ccwRot!=0) { + // FIXME: How to rotate the display/screen on OSX programmatically ? + DBG_PRINT( "setScreenMode0: Don't know how to rotate screen on OS X: rot %d ccw\n", ccwRot); + res = JNI_FALSE; + } + if(JNI_TRUE == res) { + CGError err = CGDisplaySwitchToMode(display, mode); + if(kCGErrorSuccess != err) { + DBG_PRINT( "setScreenMode0: SetMode failed: %d\n", (int)err); + res = JNI_FALSE; + } + } + + // CGDisplayModeRelease(mode); // 10.6 on CGDisplayModeRef + [pool release]; + + return res; +} + /* * Class: jogamp_newt_driver_macosx_MacWindow * Method: initIDs @@ -272,11 +479,6 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_MacWindow_initIDs0 ClazzNamePoint, ClazzAnyCstrName, ClazzNamePointCstrSignature); } - focusActionID = (*env)->GetMethodID(env, clazz, "focusAction", "()Z"); - if(NULL==focusActionID) { - NewtCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_MacWindow_initIDs0: can't fetch method focusAction()Z"); - } - // Need this when debugging, as it is necessary to attach gdb to // the running java process -- "gdb java" doesn't work // printf("Going to sleep for 10 seconds\n"); @@ -449,8 +651,9 @@ NS_DURING if([mView isInFullScreenMode]) { [mView exitFullScreenModeWithOptions: NULL]; } - [mWin setContentView: nil]; - [mView release]; + // Note: mWin's release will also release it's mView! + // [mWin setContentView: nil]; + // [mView release]; } NS_HANDLER NS_ENDHANDLER @@ -463,7 +666,11 @@ NS_ENDHANDLER DBG_PRINT( "windowClose.1 - %p,%d view %p,%d, parent %p\n", mWin, getRetainCount(mWin), mView, getRetainCount(mView), pWin); - [mWin close]; // performs release! + // '[mWin close]' causes a crash at exit. + // This probably happens b/c it sends events to the main loop + // but our resources are gone ?! + // However, issuing a simple release seems to work quite well. + [mWin release]; DBG_PRINT( "windowClose.X - %p,%d view %p,%d, parent %p\n", mWin, getRetainCount(mWin), mView, getRetainCount(mView), pWin); @@ -510,26 +717,44 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_requestFocus0 (JNIEnv *env, jobject window, jlong w, jboolean force) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - NSWindow* win = (NSWindow*) ((intptr_t) w); + NSWindow* mWin = (NSWindow*) ((intptr_t) w); #ifdef VERBOSE_ON - BOOL hasFocus = [win isKeyWindow]; + BOOL hasFocus = [mWin isKeyWindow]; #endif - DBG_PRINT( "requestFocus - window: %p, force %d, hasFocus %d (START)\n", win, force, hasFocus); - - // Even if we already own the focus, we need the 'focusAction()' call - // and the other probably redundant NS calls to force proper focus traversal - // of the parent TK (AWT doesn't do it properly on OSX). - if( JNI_TRUE==force || JNI_FALSE == (*env)->CallBooleanMethod(env, window, focusActionID) ) { - DBG_PRINT( "makeKeyWindow win %p\n", win); - // [win performSelectorOnMainThread:@selector(orderFrontRegardless) withObject:nil waitUntilDone:YES]; - // [win performSelectorOnMainThread:@selector(makeKeyWindow) withObject:nil waitUntilDone:YES]; - [win orderFrontRegardless]; - [win makeKeyWindow]; - [win makeFirstResponder: nil]; - } + DBG_PRINT( "requestFocus - window: %p, force %d, hasFocus %d (START)\n", mWin, force, hasFocus); + + [mWin makeFirstResponder: nil]; + // [mWin performSelectorOnMainThread:@selector(orderFrontRegardless) withObject:nil waitUntilDone:YES]; + // [mWin performSelectorOnMainThread:@selector(makeKeyWindow) withObject:nil waitUntilDone:YES]; + [mWin orderFrontRegardless]; + [mWin makeKeyWindow]; + + DBG_PRINT( "requestFocus - window: %p, force %d (END)\n", mWin, force); + + [pool release]; +} - DBG_PRINT( "requestFocus - window: %p, force %d (END)\n", win, force); +/* + * Class: jogamp_newt_driver_macosx_MacWindow + * Method: requestFocusParent0 + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_requestFocusParent0 + (JNIEnv *env, jobject window, jlong w) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSWindow* mWin = (NSWindow*) ((intptr_t) w); + NSWindow* pWin = [mWin parentWindow]; +#ifdef VERBOSE_ON + BOOL hasFocus = [mWin isKeyWindow]; +#endif + + DBG_PRINT( "requestFocusParent0 - window: %p, parent: %p, hasFocus %d (START)\n", mWin, pWin, hasFocus ); + if(NULL != pWin) { + [pWin makeKeyWindow]; + } + DBG_PRINT( "requestFocusParent0 - window: %p, parent: %p (END)\n", mWin, pWin); [pool release]; } diff --git a/src/newt/native/MouseEvent.h b/src/newt/native/MouseEvent.h index e9c0476ef..59d63cecf 100644 --- a/src/newt/native/MouseEvent.h +++ b/src/newt/native/MouseEvent.h @@ -1,3 +1,30 @@ +/** + * 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. + */ #ifndef _MOUSE_EVENT_H_ #define _MOUSE_EVENT_H_ diff --git a/src/newt/native/NewtCommon.h b/src/newt/native/NewtCommon.h index 91fceb310..33aba64ae 100644 --- a/src/newt/native/NewtCommon.h +++ b/src/newt/native/NewtCommon.h @@ -1,3 +1,30 @@ +/** + * 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. + */ #ifndef NEWT_COMMON_H #define NEWT_COMMON_H 1 diff --git a/src/newt/native/NewtMacWindow.h b/src/newt/native/NewtMacWindow.h index cb256e71f..3ba89de1e 100644 --- a/src/newt/native/NewtMacWindow.h +++ b/src/newt/native/NewtMacWindow.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 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 @@ -40,7 +41,8 @@ // #define VERBOSE_ON 1 #ifdef VERBOSE_ON - #define DBG_PRINT(...) fprintf(stderr, __VA_ARGS__); fflush(stderr) + #define DBG_PRINT(...) NSLog(@ __VA_ARGS__) + // #define DBG_PRINT(...) fprintf(stderr, __VA_ARGS__); fflush(stderr) #else #define DBG_PRINT(...) #endif @@ -53,8 +55,8 @@ JavaVM *jvmHandle; int jvmVersion; - BOOL destroyNotifySent; - BOOL softLocked; + volatile BOOL destroyNotifySent; + volatile BOOL softLocked; pthread_mutex_t softLockSync; NSTrackingRectTag ptrTrackingTag; @@ -88,7 +90,7 @@ - (BOOL) needsDisplay; - (void) displayIfNeeded; -- (void) viewWillDraw; +- (void) display; - (void) drawRect:(NSRect)dirtyRect; - (void) viewDidHide; - (void) viewDidUnhide; diff --git a/src/newt/native/NewtMacWindow.m b/src/newt/native/NewtMacWindow.m index 1f74742ec..ce41673c4 100644 --- a/src/newt/native/NewtMacWindow.m +++ b/src/newt/native/NewtMacWindow.m @@ -44,15 +44,17 @@ jint GetDeltaY(NSEvent *event, jint javaMods) { // mouse pad case deltaY = CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventPointDeltaAxis1); + // fprintf(stderr, "WHEEL/PAD: %lf\n", (double)deltaY); } else { // traditional mouse wheel case deltaY = [event deltaY]; + // fprintf(stderr, "WHEEL/TRAD: %lf\n", (double)deltaY); if (deltaY == 0.0 && (javaMods & EVENT_SHIFT_MASK) != 0) { // shift+vertical wheel scroll produces horizontal scroll // we convert it to vertical deltaY = [event deltaX]; } - if (deltaY < 1.0 && deltaY > -1.0) { + if (-1.0 < deltaY && deltaY < 1.0) { deltaY *= 10.0; } else { if (deltaY < 0.0) { @@ -62,21 +64,15 @@ jint GetDeltaY(NSEvent *event, jint javaMods) { } } } - - if (deltaY > 0) { - return (NSInteger)deltaY; - } else if (deltaY < 0) { - return -(NSInteger)deltaY; - } - - return 0; + // fprintf(stderr, "WHEEL/res: %d\n", (int)deltaY); + return (jint) deltaY; } static jmethodID enqueueMouseEventID = NULL; static jmethodID sendMouseEventID = NULL; static jmethodID enqueueKeyEventID = NULL; static jmethodID sendKeyEventID = NULL; -static jmethodID enqueueRequestFocusID = NULL; +static jmethodID requestFocusID = NULL; static jmethodID insetsChangedID = NULL; static jmethodID sizeChangedID = NULL; @@ -104,7 +100,11 @@ static jmethodID windowRepaintID = NULL; jvmVersion = 0; destroyNotifySent = NO; softLocked = NO; - pthread_mutex_init(&softLockSync, NULL); // fast non-recursive + + pthread_mutexattr_t softLockSyncAttr; + pthread_mutexattr_init(&softLockSyncAttr); + pthread_mutexattr_settype(&softLockSyncAttr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&softLockSync, &softLockSyncAttr); // recursive ptrTrackingTag = 0; @@ -122,7 +122,7 @@ static jmethodID windowRepaintID = NULL; - (void) dealloc { if(softLocked) { - fprintf(stderr, "*** Warning: softLock still hold @ dealloc!\n"); fflush(NULL); + NSLog(@"NewtView::dealloc: softLock still hold @ dealloc!\n"); } pthread_mutex_destroy(&softLockSync); [super dealloc]; @@ -193,72 +193,61 @@ static jmethodID windowRepaintID = NULL; return destroyNotifySent; } -#define SOFT_LOCK_BLOCKING 1 - - (BOOL) softLock { + // DBG_PRINT("*************** softLock.0: %p\n", (void*)pthread_self()); + // NSLog(@"NewtView::softLock: %@",[NSThread callStackSymbols]); pthread_mutex_lock(&softLockSync); softLocked = YES; -#ifndef SOFT_LOCK_BLOCKING - pthread_mutex_unlock(&softLockSync); -#endif + // DBG_PRINT("*************** softLock.X: %p\n", (void*)pthread_self()); return softLocked; } - (void) softUnlock { -#ifndef SOFT_LOCK_BLOCKING - pthread_mutex_lock(&softLockSync); -#endif + // DBG_PRINT("*************** softUnlock: %p\n", (void*)pthread_self()); softLocked = NO; pthread_mutex_unlock(&softLockSync); } - (BOOL) needsDisplay { -#ifndef SOFT_LOCK_BLOCKING - return NO == softLocked && NO == destroyNotifySent && [super needsDisplay]; -#else return NO == destroyNotifySent && [super needsDisplay]; -#endif } - (void) displayIfNeeded { -#ifndef SOFT_LOCK_BLOCKING - if( NO == softLocked && NO == destroyNotifySent ) { + if( YES == [self needsDisplay] ) { + [self softLock]; [super displayIfNeeded]; + [self softUnlock]; } -#else - [self softLock]; - if( NO == destroyNotifySent ) { - [super displayIfNeeded]; - } - [self softUnlock]; -#endif } -- (void) viewWillDraw +- (void) display { - DBG_PRINT("*************** viewWillDraw: 0x%p\n", javaWindowObject); - [super viewWillDraw]; + if( NO == destroyNotifySent ) { + [self softLock]; + [super display]; + [self softUnlock]; + } } - (void) drawRect:(NSRect)dirtyRect { - DBG_PRINT("*************** dirtyRect: 0x%p %lf/%lf %lfx%lf\n", + DBG_PRINT("*************** dirtyRect: %p %lf/%lf %lfx%lf\n", javaWindowObject, dirtyRect.origin.x, dirtyRect.origin.y, dirtyRect.size.width, dirtyRect.size.height); int shallBeDetached = 0; JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached); if(NULL==env) { - NSLog(@"viewDidHide: null JNIEnv"); + DBG_PRINT("viewDidHide: null JNIEnv\n"); return; } NSRect viewFrame = [self frame]; - (*env)->CallVoidMethod(env, javaWindowObject, windowRepaintID, JNI_FALSE, + (*env)->CallVoidMethod(env, javaWindowObject, windowRepaintID, JNI_TRUE, // defer .. dirtyRect.origin.x, viewFrame.size.height - dirtyRect.origin.y, dirtyRect.size.width, dirtyRect.size.height); @@ -272,7 +261,7 @@ static jmethodID windowRepaintID = NULL; int shallBeDetached = 0; JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached); if(NULL==env) { - NSLog(@"viewDidHide: null JNIEnv"); + DBG_PRINT("viewDidHide: null JNIEnv\n"); return; } @@ -290,7 +279,7 @@ static jmethodID windowRepaintID = NULL; int shallBeDetached = 0; JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached); if(NULL==env) { - NSLog(@"viewDidHide: null JNIEnv"); + DBG_PRINT("viewDidHide: null JNIEnv\n"); return; } @@ -325,9 +314,9 @@ static jmethodID windowRepaintID = NULL; focusChangedID = (*env)->GetMethodID(env, clazz, "focusChanged", "(ZZ)V"); windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "()V"); windowRepaintID = (*env)->GetMethodID(env, clazz, "windowRepaint", "(ZIIII)V"); - enqueueRequestFocusID = (*env)->GetMethodID(env, clazz, "enqueueRequestFocus", "(Z)V"); + requestFocusID = (*env)->GetMethodID(env, clazz, "requestFocus", "(Z)V"); if (enqueueMouseEventID && sendMouseEventID && enqueueKeyEventID && sendKeyEventID && sizeChangedID && visibleChangedID && insetsChangedID && - positionChangedID && focusChangedID && windowDestroyNotifyID && enqueueRequestFocusID && windowRepaintID) + positionChangedID && focusChangedID && windowDestroyNotifyID && requestFocusID && windowRepaintID) { return YES; } @@ -512,14 +501,14 @@ static jint mods2JavaMods(NSUInteger mods) NewtView* view = (NewtView *) nsview; jobject javaWindowObject = [view getJavaWindowObject]; if (javaWindowObject == NULL) { - NSLog(@"sendKeyEvent: null javaWindowObject"); + DBG_PRINT("sendKeyEvent: null javaWindowObject\n"); return; } int shallBeDetached = 0; JavaVM *jvmHandle = [view getJVMHandle]; JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], &shallBeDetached); if(NULL==env) { - NSLog(@"sendKeyEvent: null JNIEnv"); + DBG_PRINT("sendKeyEvent: null JNIEnv\n"); return; } @@ -533,6 +522,8 @@ static jint mods2JavaMods(NSUInteger mods) // Note: the key code in the NSEvent does not map to anything we can use jchar keyChar = (jchar) [chars characterAtIndex: i]; + DBG_PRINT("sendKeyEvent: %d/%d char 0x%X, code 0x%X\n", i, len, (int)keyChar, (int)keyCode); + #ifdef USE_SENDIO_DIRECT (*env)->CallVoidMethod(env, javaWindowObject, sendKeyEventID, evType, javaMods, keyCode, keyChar); @@ -567,14 +558,14 @@ static jint mods2JavaMods(NSUInteger mods) NewtView* view = (NewtView *) nsview; jobject javaWindowObject = [view getJavaWindowObject]; if (javaWindowObject == NULL) { - NSLog(@"sendMouseEvent: null javaWindowObject"); + DBG_PRINT("sendMouseEvent: null javaWindowObject\n"); return; } int shallBeDetached = 0; JavaVM *jvmHandle = [view getJVMHandle]; JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], &shallBeDetached); if(NULL==env) { - NSLog(@"sendMouseEvent: null JNIEnv"); + DBG_PRINT("sendMouseEvent: null JNIEnv\n"); return; } jint javaMods = mods2JavaMods([event modifierFlags]); @@ -586,6 +577,7 @@ static jint mods2JavaMods(NSUInteger mods) switch ([event type]) { case NSScrollWheel: { scrollDeltaY = GetDeltaY(event, javaMods); + javaButtonNum = 1; break; } case NSLeftMouseDown: @@ -603,9 +595,6 @@ static jint mods2JavaMods(NSUInteger mods) case NSOtherMouseDragged: javaButtonNum = 2; break; - default: - javaButtonNum = 0; - break; } if (evType == EVENT_MOUSE_WHEEL_MOVED && scrollDeltaY == 0) { @@ -613,7 +602,7 @@ static jint mods2JavaMods(NSUInteger mods) return; } if (evType == EVENT_MOUSE_PRESSED) { - (*env)->CallVoidMethod(env, javaWindowObject, enqueueRequestFocusID, JNI_FALSE); + (*env)->CallVoidMethod(env, javaWindowObject, requestFocusID, JNI_FALSE); } NSPoint location = [self screenPos2NewtClientWinPos: [NSEvent mouseLocation]]; @@ -770,14 +759,14 @@ static jint mods2JavaMods(NSUInteger mods) NewtView* view = (NewtView *) nsview; jobject javaWindowObject = [view getJavaWindowObject]; if (javaWindowObject == NULL) { - NSLog(@"windowDidResize: null javaWindowObject"); + DBG_PRINT("windowDidResize: null javaWindowObject\n"); return; } int shallBeDetached = 0; JavaVM *jvmHandle = [view getJVMHandle]; JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], &shallBeDetached); if(NULL==env) { - NSLog(@"windowDidResize: null JNIEnv"); + DBG_PRINT("windowDidResize: null JNIEnv\n"); return; } @@ -805,14 +794,14 @@ static jint mods2JavaMods(NSUInteger mods) NewtView* view = (NewtView *) nsview; jobject javaWindowObject = [view getJavaWindowObject]; if (javaWindowObject == NULL) { - NSLog(@"windowDidMove: null javaWindowObject"); + DBG_PRINT("windowDidMove: null javaWindowObject\n"); return; } int shallBeDetached = 0; JavaVM *jvmHandle = [view getJVMHandle]; JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], &shallBeDetached); if(NULL==env) { - NSLog(@"windowDidMove: null JNIEnv"); + DBG_PRINT("windowDidMove: null JNIEnv\n"); return; } @@ -839,16 +828,16 @@ static jint mods2JavaMods(NSUInteger mods) if( false == [view getDestroyNotifySent] ) { jobject javaWindowObject = [view getJavaWindowObject]; - DBG_PRINT( "*************** windowWillClose.0: 0x%p\n", (void *)(intptr_t)javaWindowObject); + DBG_PRINT( "*************** windowWillClose.0: %p\n", (void *)(intptr_t)javaWindowObject); if (javaWindowObject == NULL) { - NSLog(@"windowWillClose: null javaWindowObject"); + DBG_PRINT("windowWillClose: null javaWindowObject\n"); return; } int shallBeDetached = 0; JavaVM *jvmHandle = [view getJVMHandle]; JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], &shallBeDetached); if(NULL==env) { - NSLog(@"windowWillClose: null JNIEnv"); + DBG_PRINT("windowWillClose: null JNIEnv\n"); return; } @@ -863,7 +852,7 @@ static jint mods2JavaMods(NSUInteger mods) if (shallBeDetached) { (*jvmHandle)->DetachCurrentThread(jvmHandle); } - DBG_PRINT( "*************** windowWillClose.X: 0x%p\n", (void *)(intptr_t)javaWindowObject); + DBG_PRINT( "*************** windowWillClose.X: %p\n", (void *)(intptr_t)javaWindowObject); } else { DBG_PRINT( "*************** windowWillClose (skip)\n"); } @@ -916,14 +905,14 @@ static jint mods2JavaMods(NSUInteger mods) NewtView* view = (NewtView *) nsview; jobject javaWindowObject = [view getJavaWindowObject]; if (javaWindowObject == NULL) { - NSLog(@"focusChanged: null javaWindowObject"); + DBG_PRINT("focusChanged: null javaWindowObject\n"); return; } int shallBeDetached = 0; JavaVM *jvmHandle = [view getJVMHandle]; JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], &shallBeDetached); if(NULL==env) { - NSLog(@"focusChanged: null JNIEnv"); + DBG_PRINT("focusChanged: null JNIEnv\n"); return; } diff --git a/src/newt/native/ScreenMode.h b/src/newt/native/ScreenMode.h index 0a760d54a..bb782910e 100644 --- a/src/newt/native/ScreenMode.h +++ b/src/newt/native/ScreenMode.h @@ -1,4 +1,32 @@ /** + * 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. + */ + +/** * WARNING: must be synced with com.jogamp.newt.util.ScreenModeUtil#streamIn*(int[]) */ diff --git a/src/newt/native/Window.h b/src/newt/native/Window.h index 865746b91..4755c4fc5 100644 --- a/src/newt/native/Window.h +++ b/src/newt/native/Window.h @@ -1,3 +1,30 @@ +/** + * 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. + */ #ifndef _WINDOW_H_ #define _WINDOW_H_ diff --git a/src/newt/native/WindowEvent.h b/src/newt/native/WindowEvent.h index 05491b43c..3dc6ba97e 100644 --- a/src/newt/native/WindowEvent.h +++ b/src/newt/native/WindowEvent.h @@ -1,3 +1,30 @@ +/** + * 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. + */ #ifndef _WINDOW_EVENT_H_ #define _WINDOW_EVENT_H_ diff --git a/src/newt/native/WindowsWindow.c b/src/newt/native/WindowsWindow.c index d60c40496..97fe6f28d 100644 --- a/src/newt/native/WindowsWindow.c +++ b/src/newt/native/WindowsWindow.c @@ -115,8 +115,7 @@ static jmethodID enqueueMouseEventID = NULL; static jmethodID sendMouseEventID = NULL; static jmethodID enqueueKeyEventID = NULL; static jmethodID sendKeyEventID = NULL; -static jmethodID focusActionID = NULL; -static jmethodID enqueueRequestFocusID = NULL; +static jmethodID requestFocusID = NULL; static RECT* UpdateInsets(JNIEnv *env, jobject window, HWND hwnd); @@ -602,18 +601,14 @@ static void NewtWindows_requestFocus (JNIEnv *env, jobject window, HWND hwnd, jb (void*) pHwnd, (void*)hwnd, current==hwnd); if( JNI_TRUE==force || current!=hwnd) { - if( JNI_TRUE==force || JNI_FALSE == (*env)->CallBooleanMethod(env, window, focusActionID) ) { - UINT flags = SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE; - SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, flags); - SetForegroundWindow(hwnd); // Slightly Higher Priority - SetFocus(hwnd);// Sets Keyboard Focus To Window - if(NULL!=pHwnd) { - SetActiveWindow(hwnd); - } - DBG_PRINT("*** WindowsWindow: requestFocus.X1\n"); - } else { - DBG_PRINT("*** WindowsWindow: requestFocus.X0\n"); + UINT flags = SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE; + SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, flags); + SetForegroundWindow(hwnd); // Slightly Higher Priority + SetFocus(hwnd);// Sets Keyboard Focus To Window + if(NULL!=pHwnd) { + SetActiveWindow(hwnd); } + DBG_PRINT("*** WindowsWindow: requestFocus.X1\n"); } DBG_PRINT("*** WindowsWindow: requestFocus.XX\n"); } @@ -870,11 +865,11 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, case WM_LBUTTONDOWN: DBG_PRINT("*** WindowsWindow: LBUTTONDOWN\n"); - (*env)->CallVoidMethod(env, window, enqueueRequestFocusID, JNI_FALSE); + (*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE); (*env)->CallVoidMethod(env, window, sendMouseEventID, (jint) EVENT_MOUSE_PRESSED, GetModifiers(), - (jint) LOWORD(lParam), (jint) HIWORD(lParam), + (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), (jint) 1, (jint) 0); useDefWindowProc = 1; break; @@ -883,18 +878,18 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, (*env)->CallVoidMethod(env, window, sendMouseEventID, (jint) EVENT_MOUSE_RELEASED, GetModifiers(), - (jint) LOWORD(lParam), (jint) HIWORD(lParam), + (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), (jint) 1, (jint) 0); useDefWindowProc = 1; break; case WM_MBUTTONDOWN: DBG_PRINT("*** WindowsWindow: MBUTTONDOWN\n"); - (*env)->CallVoidMethod(env, window, enqueueRequestFocusID, JNI_FALSE); + (*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE); (*env)->CallVoidMethod(env, window, sendMouseEventID, (jint) EVENT_MOUSE_PRESSED, GetModifiers(), - (jint) LOWORD(lParam), (jint) HIWORD(lParam), + (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), (jint) 2, (jint) 0); useDefWindowProc = 1; break; @@ -903,18 +898,18 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, (*env)->CallVoidMethod(env, window, sendMouseEventID, (jint) EVENT_MOUSE_RELEASED, GetModifiers(), - (jint) LOWORD(lParam), (jint) HIWORD(lParam), + (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), (jint) 2, (jint) 0); useDefWindowProc = 1; break; case WM_RBUTTONDOWN: DBG_PRINT("*** WindowsWindow: RBUTTONDOWN\n"); - (*env)->CallVoidMethod(env, window, enqueueRequestFocusID, JNI_FALSE); + (*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE); (*env)->CallVoidMethod(env, window, sendMouseEventID, (jint) EVENT_MOUSE_PRESSED, GetModifiers(), - (jint) LOWORD(lParam), (jint) HIWORD(lParam), + (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), (jint) 3, (jint) 0); useDefWindowProc = 1; break; @@ -923,7 +918,7 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, (*env)->CallVoidMethod(env, window, sendMouseEventID, (jint) EVENT_MOUSE_RELEASED, GetModifiers(), - (jint) LOWORD(lParam), (jint) HIWORD(lParam), + (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), (jint) 3, (jint) 0); useDefWindowProc = 1; break; @@ -932,7 +927,7 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, (*env)->CallVoidMethod(env, window, sendMouseEventID, (jint) EVENT_MOUSE_MOVED, GetModifiers(), - (jint) LOWORD(lParam), (jint) HIWORD(lParam), + (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), (jint) 0, (jint) 0); useDefWindowProc = 1; break; @@ -958,7 +953,7 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, (jint) EVENT_MOUSE_WHEEL_MOVED, GetModifiers(), (jint) eventPt.x, (jint) eventPt.y, - (jint) 0, (jint) (GET_WHEEL_DELTA_WPARAM(wParam)/120.0f)); + (jint) 1, (jint) (GET_WHEEL_DELTA_WPARAM(wParam)/120.0f)); useDefWindowProc = 1; break; } @@ -978,8 +973,8 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, break; case WM_MOVE: - DBG_PRINT("*** WindowsWindow: WM_MOVE window %p, %d/%d\n", wnd, (int)LOWORD(lParam), (int)HIWORD(lParam)); - (*env)->CallVoidMethod(env, window, positionChangedID, JNI_FALSE, (jint)LOWORD(lParam), (jint)HIWORD(lParam)); + DBG_PRINT("*** WindowsWindow: WM_MOVE window %p, %d/%d\n", wnd, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); + (*env)->CallVoidMethod(env, window, positionChangedID, JNI_FALSE, (jint)GET_X_LPARAM(lParam), (jint)GET_Y_LPARAM(lParam)); useDefWindowProc = 1; break; @@ -1046,13 +1041,47 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowsDisplay_DispatchMe /* * Class: jogamp_newt_driver_windows_WindowsScreen + * Method: getOriginX0 + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_WindowsScreen_getOriginX0 + (JNIEnv *env, jobject obj, jint scrn_idx) +{ + if( GetSystemMetrics( SM_CMONITORS) > 1) { + return (jint)GetSystemMetrics(SM_XVIRTUALSCREEN); + } else { + return 0; + } +} + +/* + * Class: jogamp_newt_driver_windows_WindowsScreen + * Method: getOriginY0 + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_WindowsScreen_getOriginY0 + (JNIEnv *env, jobject obj, jint scrn_idx) +{ + if( GetSystemMetrics( SM_CMONITORS ) > 1) { + return (jint)GetSystemMetrics(SM_YVIRTUALSCREEN); + } else { + return 0; + } +} + +/* + * Class: jogamp_newt_driver_windows_WindowsScreen * Method: getWidthImpl * Signature: (I)I */ JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_WindowsScreen_getWidthImpl0 (JNIEnv *env, jobject obj, jint scrn_idx) { - return (jint)GetSystemMetrics(SM_CXSCREEN); + if( GetSystemMetrics( SM_CMONITORS) > 1) { + return (jint)GetSystemMetrics(SM_CXVIRTUALSCREEN); + } else { + return (jint)GetSystemMetrics(SM_CXSCREEN); + } } /* @@ -1063,7 +1092,11 @@ JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_WindowsScreen_getWidthImp JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_WindowsScreen_getHeightImpl0 (JNIEnv *env, jobject obj, jint scrn_idx) { - return (jint)GetSystemMetrics(SM_CYSCREEN); + if( GetSystemMetrics( SM_CMONITORS ) > 1) { + return (jint)GetSystemMetrics(SM_CYVIRTUALSCREEN); + } else { + return (jint)GetSystemMetrics(SM_CYSCREEN); + } } static int NewtScreen_RotationNativeCCW2NewtCCW(JNIEnv *env, int native) { @@ -1270,8 +1303,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_initIDs sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(IIIIII)V"); enqueueKeyEventID = (*env)->GetMethodID(env, clazz, "enqueueKeyEvent", "(ZIIIC)V"); sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(IIIC)V"); - enqueueRequestFocusID = (*env)->GetMethodID(env, clazz, "enqueueRequestFocus", "(Z)V"); - focusActionID = (*env)->GetMethodID(env, clazz, "focusAction", "()Z"); + requestFocusID = (*env)->GetMethodID(env, clazz, "requestFocus", "(Z)V"); if (insetsChangedID == NULL || sizeChangedID == NULL || @@ -1284,8 +1316,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_initIDs sendMouseEventID == NULL || enqueueKeyEventID == NULL || sendKeyEventID == NULL || - focusActionID == NULL || - enqueueRequestFocusID == NULL) { + requestFocusID == NULL) { return JNI_FALSE; } BuildDynamicKeyMapTable(); @@ -1317,9 +1348,6 @@ static void NewtWindow_setVisiblePosSize(HWND hwnd, BOOL atop, BOOL visible, } else { flags = SWP_NOACTIVATE | SWP_NOZORDER; } - if(0>x || 0>y) { - flags |= SWP_NOMOVE; - } if(0>=width || 0>=height ) { flags |= SWP_NOSIZE; } @@ -1345,7 +1373,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_CreateWind (JNIEnv *env, jobject obj, jlong hInstance, jstring jWndClassName, jstring jWndName, jlong parent, - jint jx, jint jy, jint defaultWidth, jint defaultHeight, jint flags) + jint jx, jint jy, jint defaultWidth, jint defaultHeight, jboolean autoPosition, jint flags) { HWND parentWindow = (HWND) (intptr_t) parent; const TCHAR* wndClassName = NULL; @@ -1374,7 +1402,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_CreateWind windowStyle |= WS_POPUP | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX; } else { windowStyle |= WS_OVERLAPPEDWINDOW; - if(0>_x || 0>_y) { + if(JNI_TRUE == autoPosition) { // user didn't requested specific position, use WM default _x = CW_USEDEFAULT; _y = 0; @@ -1387,9 +1415,9 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_CreateWind (HINSTANCE) (intptr_t) hInstance, NULL); - DBG_PRINT("*** WindowsWindow: CreateWindow thread 0x%X, parent %p, window %p, %d/%d %dx%d, undeco %d, alwaysOnTop %d\n", + DBG_PRINT("*** WindowsWindow: CreateWindow thread 0x%X, parent %p, window %p, %d/%d %dx%d, undeco %d, alwaysOnTop %d, autoPosition %d\n", (int)GetCurrentThreadId(), parentWindow, window, x, y, width, height, - TST_FLAG_IS_UNDECORATED(flags), TST_FLAG_IS_ALWAYSONTOP(flags)); + TST_FLAG_IS_UNDECORATED(flags), TST_FLAG_IS_ALWAYSONTOP(flags), autoPosition); if (NULL == window) { int lastError = (int) GetLastError(); @@ -1409,7 +1437,6 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_CreateWind { RECT rc; RECT * insets; - BOOL userPos = 0<=x && 0<=y ; ShowWindow(window, SW_SHOW); @@ -1417,12 +1444,12 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_CreateWind insets = UpdateInsets(env, wud->jinstance, window); (*env)->CallVoidMethod(env, wud->jinstance, visibleChangedID, JNI_FALSE, JNI_TRUE); - if(!userPos) { + if(JNI_TRUE == autoPosition) { GetWindowRect(window, &rc); x = rc.left + insets->left; // client coords y = rc.top + insets->top; // client coords } - DBG_PRINT("*** WindowsWindow: CreateWindow client: %d/%d %dx%d (is user-pos %d)\n", x, y, width, height, userPos); + DBG_PRINT("*** WindowsWindow: CreateWindow client: %d/%d %dx%d (autoPosition %d)\n", x, y, width, height, autoPosition); x -= insets->left; // top-level y -= insets->top; // top-level diff --git a/src/newt/native/X11Common.h b/src/newt/native/X11Common.h new file mode 100644 index 000000000..cefef690f --- /dev/null +++ b/src/newt/native/X11Common.h @@ -0,0 +1,80 @@ +/** + * 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. + */ + +#ifndef _X11COMMON_H_ +#define _X11COMMON_H_ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <stdarg.h> + +#include <gluegen_stdint.h> + +#include <unistd.h> +#include <errno.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/keysym.h> +#include <X11/Xatom.h> + +#include <X11/extensions/Xrandr.h> + +#include "jogamp_newt_driver_x11_X11Screen.h" +#include "jogamp_newt_driver_x11_X11Display.h" +#include "jogamp_newt_driver_x11_X11Window.h" + +#include "Window.h" +#include "MouseEvent.h" +#include "InputEvent.h" +#include "KeyEvent.h" +#include "WindowEvent.h" +#include "ScreenMode.h" + +#include "NewtCommon.h" + +// #define VERBOSE_ON 1 + +#ifdef VERBOSE_ON + #define DBG_PRINT(...) fprintf(stderr, __VA_ARGS__); fflush(stderr) +#else + #define DBG_PRINT(...) +#endif + +extern jclass X11NewtWindowClazz; +extern jmethodID insetsChangedID; +extern jmethodID visibleChangedID; + +jobject getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlong javaObjectAtom, Bool showWarning); + +void NewtDisplay_displayDispatchErrorHandlerEnable(int onoff, JNIEnv * env); +Status NewtWindows_getRootAndParent (Display *dpy, Window w, Window * root_return, Window * parent_return); +Status NewtWindows_updateInsets(JNIEnv *env, jobject jwindow, Display *dpy, Window window, int *left, int *right, int *top, int *bottom); + +#endif /* _X11COMMON_H_ */ + 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); + } + } +} + + diff --git a/src/newt/native/X11Screen.c b/src/newt/native/X11Screen.c new file mode 100644 index 000000000..1b7fea770 --- /dev/null +++ b/src/newt/native/X11Screen.c @@ -0,0 +1,469 @@ +/** + * 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" + +/* + * Class: jogamp_newt_driver_x11_X11Screen + * Method: GetScreen + * Signature: (JI)J + */ +JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_X11Screen_GetScreen0 + (JNIEnv *env, jclass clazz, jlong display, jint screen_index) +{ + Display * dpy = (Display *)(intptr_t)display; + Screen * scrn= NULL; + + DBG_PRINT("X11: X11Screen_GetScreen0 dpy %p START\n", dpy); + + if(dpy==NULL) { + NewtCommon_FatalError(env, "invalid display connection.."); + } + + scrn = ScreenOfDisplay(dpy, screen_index); + if(scrn==NULL) { + fprintf(stderr, "couldn't get screen idx %d\n", screen_index); + } + DBG_PRINT("X11: X11Screen_GetScreen0 idx %d -> scrn %p DONE\n", screen_index, scrn); + return (jlong) (intptr_t) scrn; +} + +JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_X11Screen_getWidth0 + (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx) +{ + Display * dpy = (Display *) (intptr_t) display; + return (jint) DisplayWidth( dpy, scrn_idx); +} + +JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_X11Screen_getHeight0 + (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx) +{ + Display * dpy = (Display *) (intptr_t) display; + return (jint) DisplayHeight( dpy, scrn_idx); +} + +static int showedRandRVersion = 0; + +static Bool NewtScreen_getRANDRVersion(Display *dpy, int *major, int *minor) { + if( 0 == XRRQueryVersion(dpy, major, minor) ) { + return False; + } + if(0 == showedRandRVersion) { + fprintf(stderr, "X11 RandR Version %d.%d\n", *major, *minor); + showedRandRVersion = 1; + } + return True; +} + +static Bool NewtScreen_hasRANDR(Display *dpy) { + int major, minor; + return NewtScreen_getRANDRVersion(dpy, &major, &minor); +} + +static int NewtScreen_XRotation2Degree(JNIEnv *env, int xrotation) { + int rot; + if(xrotation == RR_Rotate_0) { + rot = 0; + } + else if(xrotation == RR_Rotate_90) { + rot = 90; + } + else if(xrotation == RR_Rotate_180) { + rot = 180; + } + else if(xrotation == RR_Rotate_270) { + rot = 270; + } else { + NewtCommon_throwNewRuntimeException(env, "invalid native rotation: %d", xrotation); + } + return rot; +} + +/* + * Class: jogamp_newt_driver_x11_X11Screen + * Method: getAvailableScreenModeRotations0 + * Signature: (JI)I + */ +JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_X11Screen_getAvailableScreenModeRotations0 + (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx) +{ + Display *dpy = (Display *) (intptr_t) display; + Window root = RootWindow(dpy, (int)scrn_idx); + int num_rotations = 0; + Rotation cur_rotation, rotations_supported; + int rotations[4]; + int major, minor; + + if(False == NewtScreen_getRANDRVersion(dpy, &major, &minor)) { + fprintf(stderr, "RANDR not available\n"); + return (*env)->NewIntArray(env, 0); + } + + rotations_supported = XRRRotations (dpy, (int)scrn_idx, &cur_rotation); + + if(0 != (rotations_supported & RR_Rotate_0)) { + rotations[num_rotations++] = 0; + } + if(0 != (rotations_supported & RR_Rotate_90)) { + rotations[num_rotations++] = 90; + } + if(0 != (rotations_supported & RR_Rotate_180)) { + rotations[num_rotations++] = 180; + } + if(0 != (rotations_supported & RR_Rotate_270)) { + rotations[num_rotations++] = 270; + } + + jintArray properties = NULL; + + if(num_rotations>0) { + properties = (*env)->NewIntArray(env, num_rotations); + if (properties == NULL) { + NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", num_rotations); + } + + // move from the temp structure to the java structure + (*env)->SetIntArrayRegion(env, properties, 0, num_rotations, rotations); + } + + return properties; +} + +/* + * Class: jogamp_newt_driver_x11_X11Screen + * Method: getNumScreenModeResolution0 + * Signature: (JI)I + */ +JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_X11Screen_getNumScreenModeResolutions0 + (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx) +{ + Display *dpy = (Display *) (intptr_t) display; + + if(False == NewtScreen_hasRANDR(dpy)) { + DBG_PRINT("Java_jogamp_newt_driver_x11_X11Screen_getNumScreenModeResolutions0: RANDR not available\n"); + return 0; + } + + int num_sizes; + XRRScreenSize *xrrs = XRRSizes(dpy, (int)scrn_idx, &num_sizes); //get possible screen resolutions + + DBG_PRINT("getNumScreenModeResolutions0: %d\n", num_sizes); + + return num_sizes; +} + +/* + * Class: jogamp_newt_driver_x11_X11Screen + * Method: getScreenModeResolutions0 + * Signature: (JII)[I + */ +JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_X11Screen_getScreenModeResolution0 + (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx, jint resMode_idx) +{ + Display *dpy = (Display *) (intptr_t) display; + + if(False == NewtScreen_hasRANDR(dpy)) { + DBG_PRINT("Java_jogamp_newt_driver_x11_X11Screen_getScreenModeResolution0: RANDR not available\n"); + return (*env)->NewIntArray(env, 0); + } + + int num_sizes; + XRRScreenSize *xrrs = XRRSizes(dpy, (int)scrn_idx, &num_sizes); //get possible screen resolutions + + if( 0 > resMode_idx || resMode_idx >= num_sizes ) { + NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes); + } + + // Fill the properties in temp jint array + int propIndex = 0; + jint prop[4]; + + prop[propIndex++] = xrrs[(int)resMode_idx].width; + prop[propIndex++] = xrrs[(int)resMode_idx].height; + prop[propIndex++] = xrrs[(int)resMode_idx].mwidth; + prop[propIndex++] = xrrs[(int)resMode_idx].mheight; + + jintArray properties = (*env)->NewIntArray(env, 4); + if (properties == NULL) { + NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", 4); + } + + // move from the temp structure to the java structure + (*env)->SetIntArrayRegion(env, properties, 0, 4, prop); + + return properties; +} + +/* + * Class: jogamp_newt_driver_x11_X11Screen + * Method: getScreenModeRates0 + * Signature: (JII)[I + */ +JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_X11Screen_getScreenModeRates0 + (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx, jint resMode_idx) +{ + Display *dpy = (Display *) (intptr_t) display; + + if(False == NewtScreen_hasRANDR(dpy)) { + DBG_PRINT("Java_jogamp_newt_driver_x11_X11Screen_getScreenModeRates0: RANDR not available\n"); + return (*env)->NewIntArray(env, 0); + } + + int num_sizes; + XRRScreenSize *xrrs = XRRSizes(dpy, (int)scrn_idx, &num_sizes); //get possible screen resolutions + + if( 0 > resMode_idx || resMode_idx >= num_sizes ) { + NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes); + } + + int num_rates; + short *rates = XRRRates(dpy, (int)scrn_idx, (int)resMode_idx, &num_rates); + + jint prop[num_rates]; + int i; + for(i=0; i<num_rates; i++) { + prop[i] = (int) rates[i]; + /** fprintf(stderr, "rate[%d, %d, %d/%d]: %d\n", (int)scrn_idx, resMode_idx, i, num_rates, prop[i]); */ + } + + jintArray properties = (*env)->NewIntArray(env, num_rates); + if (properties == NULL) { + NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", num_rates); + } + + // move from the temp structure to the java structure + (*env)->SetIntArrayRegion(env, properties, 0, num_rates, prop); + + return properties; +} + +/* + * Class: jogamp_newt_driver_x11_X11Screen + * Method: getCurrentScreenRate0 + * Signature: (JI)I + */ +JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_X11Screen_getCurrentScreenRate0 + (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx) +{ + Display *dpy = (Display *) (intptr_t) display; + Window root = RootWindow(dpy, (int)scrn_idx); + + if(False == NewtScreen_hasRANDR(dpy)) { + DBG_PRINT("Java_jogamp_newt_driver_x11_X11Screen_getCurrentScreenRate0: RANDR not available\n"); + return -1; + } + + // get current resolutions and frequencies + XRRScreenConfiguration *conf = XRRGetScreenInfo(dpy, root); + short original_rate = XRRConfigCurrentRate(conf); + + //free + XRRFreeScreenConfigInfo(conf); + + DBG_PRINT("getCurrentScreenRate0: %d\n", (int)original_rate); + + return (jint) original_rate; +} + +/* + * Class: jogamp_newt_driver_x11_X11Screen + * Method: getCurrentScreenRotation0 + * Signature: (JI)I + */ +JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_X11Screen_getCurrentScreenRotation0 + (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx) +{ + Display *dpy = (Display *) (intptr_t) display; + Window root = RootWindow(dpy, (int)scrn_idx); + + if(False == NewtScreen_hasRANDR(dpy)) { + DBG_PRINT("Java_jogamp_newt_driver_x11_X11Screen_getCurrentScreenRotation0: RANDR not available\n"); + return -1; + } + + //get current resolutions and frequencies + XRRScreenConfiguration *conf = XRRGetScreenInfo(dpy, root); + + Rotation rotation; + XRRConfigCurrentConfiguration(conf, &rotation); + + //free + XRRFreeScreenConfigInfo(conf); + + return NewtScreen_XRotation2Degree(env, rotation); +} + + +/* + * Class: jogamp_newt_driver_x11_X11Screen + * Method: getCurrentScreenResolutionIndex0 + * Signature: (JI)I + */ +JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_X11Screen_getCurrentScreenResolutionIndex0 + (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx) +{ + Display *dpy = (Display *) (intptr_t) display; + Window root = RootWindow(dpy, (int)scrn_idx); + + if(False == NewtScreen_hasRANDR(dpy)) { + DBG_PRINT("Java_jogamp_newt_driver_x11_X11Screen_getCurrentScreenResolutionIndex0: RANDR not available\n"); + return -1; + } + + // get current resolutions and frequency configuration + XRRScreenConfiguration *conf = XRRGetScreenInfo(dpy, root); + short original_rate = XRRConfigCurrentRate(conf); + + Rotation original_rotation; + SizeID original_size_id = XRRConfigCurrentConfiguration(conf, &original_rotation); + + //free + XRRFreeScreenConfigInfo(conf); + + DBG_PRINT("getCurrentScreenResolutionIndex0: %d\n", (int)original_size_id); + return (jint)original_size_id; +} + +/* + * Class: jogamp_newt_driver_x11_X11Screen + * Method: setCurrentScreenModeStart0 + * Signature: (JIIII)Z + */ +JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_X11Screen_setCurrentScreenModeStart0 + (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jint resMode_idx, jint freq, jint rotation) +{ + Display *dpy = (Display *) (intptr_t) display; + Window root = RootWindow(dpy, (int)screen_idx); + + if(False == NewtScreen_hasRANDR(dpy)) { + DBG_PRINT("Java_jogamp_newt_driver_x11_X11Screen_setCurrentScreenModeStart0: RANDR not available\n"); + return JNI_FALSE; + } + + int num_sizes; + XRRScreenSize *xrrs = XRRSizes(dpy, (int)screen_idx, &num_sizes); //get possible screen resolutions + XRRScreenConfiguration *conf; + int rot; + + if( 0 > resMode_idx || resMode_idx >= num_sizes ) { + NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes); + } + + conf = XRRGetScreenInfo(dpy, root); + + switch(rotation) { + case 0: + rot = RR_Rotate_0; + break; + case 90: + rot = RR_Rotate_90; + break; + case 180: + rot = RR_Rotate_180; + break; + case 270: + rot = RR_Rotate_270; + break; + default: + NewtCommon_throwNewRuntimeException(env, "Invalid rotation: %d", rotation); + } + + DBG_PRINT("X11Screen.setCurrentScreenMode0: CHANGED TO %d: %d x %d PIXELS, %d Hz, %d degree\n", + resMode_idx, xrrs[resMode_idx].width, xrrs[resMode_idx].height, (int)freq, rotation); + + XRRSelectInput (dpy, root, RRScreenChangeNotifyMask); + + XSync(dpy, False); + XRRSetScreenConfigAndRate(dpy, conf, root, (int)resMode_idx, rot, (short)freq, CurrentTime); + XSync(dpy, False); + + //free + XRRFreeScreenConfigInfo(conf); + XSync(dpy, False); + + return JNI_TRUE; +} + +/* + * Class: jogamp_newt_driver_x11_X11Screen + * Method: setCurrentScreenModePollEnd0 + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_X11Screen_setCurrentScreenModePollEnd0 + (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jint resMode_idx, jint freq, jint rotation) +{ + Display *dpy = (Display *) (intptr_t) display; + int randr_event_base, randr_error_base; + XEvent evt; + XRRScreenChangeNotifyEvent * scn_event = (XRRScreenChangeNotifyEvent *) &evt; + + if(False == NewtScreen_hasRANDR(dpy)) { + DBG_PRINT("Java_jogamp_newt_driver_x11_X11Screen_setCurrentScreenModePollEnd0: RANDR not available\n"); + return JNI_FALSE; + } + + int num_sizes; + XRRScreenSize *xrrs = XRRSizes(dpy, (int)screen_idx, &num_sizes); //get possible screen resolutions + XRRScreenConfiguration *conf; + + if( 0 > resMode_idx || resMode_idx >= num_sizes ) { + NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes); + } + + XRRQueryExtension(dpy, &randr_event_base, &randr_error_base); + + int done = 0; + int rot; + do { + if ( 0 >= XEventsQueued(dpy, QueuedAfterFlush) ) { + return; + } + XNextEvent(dpy, &evt); + + switch (evt.type - randr_event_base) { + case RRScreenChangeNotify: + rot = NewtScreen_XRotation2Degree(env, (int)scn_event->rotation); + DBG_PRINT( "XRANDR: event . RRScreenChangeNotify call %p (root %p) resIdx %d rot %d %dx%d\n", + (void*)scn_event->window, (void*)scn_event->root, + (int)scn_event->size_index, rot, + scn_event->width, scn_event->height); + // done = scn_event->size_index == resMode_idx; // not reliable .. + done = rot == rotation && + scn_event->width == xrrs[resMode_idx].width && + scn_event->height == xrrs[resMode_idx].height; + break; + default: + DBG_PRINT("RANDR: event . unhandled %d 0x%X call %p\n", (int)evt.type, (int)evt.type, (void*)evt.xany.window); + } + XRRUpdateConfiguration(&evt); + } while(!done); + + XSync(dpy, False); + +} + diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c index f14138a0a..0a7e1cf77 100644 --- a/src/newt/native/X11Window.c +++ b/src/newt/native/X11Window.c @@ -32,40 +32,9 @@ * */ -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <stdarg.h> - -#include <gluegen_stdint.h> - -#include <unistd.h> -#include <errno.h> -#include <X11/Xlib.h> -#include <X11/Xutil.h> -#include <X11/keysym.h> -#include <X11/Xatom.h> - -#include <X11/extensions/Xrandr.h> - -#include "jogamp_newt_driver_x11_X11Screen.h" -#include "jogamp_newt_driver_x11_X11Display.h" -#include "jogamp_newt_driver_x11_X11Window.h" - -#include "Window.h" -#include "MouseEvent.h" -#include "InputEvent.h" -#include "KeyEvent.h" -#include "WindowEvent.h" -#include "ScreenMode.h" - -#include "NewtCommon.h" - -// #define VERBOSE_ON 1 +#include "X11Common.h" #ifdef VERBOSE_ON - #define DBG_PRINT(...) fprintf(stderr, __VA_ARGS__); fflush(stderr) - #define DUMP_VISUAL_INFO(a,b) _dumpVisualInfo((a),(b)) static void _dumpVisualInfo(const char * msg, XVisualInfo *pVisualQuery) { @@ -90,259 +59,12 @@ #else - #define DBG_PRINT(...) - #define DUMP_VISUAL_INFO(a,b) #endif -/** - * 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; - - switch(keySym) { - case XK_Alt_L: - case XK_Alt_R: - return J_VK_ALT; - - case XK_Left: - return J_VK_LEFT; - case XK_Right: - return J_VK_RIGHT; - case XK_Up: - return J_VK_UP; - case XK_Down: - return J_VK_DOWN; - case XK_Page_Up: - return J_VK_PAGE_UP; - case XK_Page_Down: - return J_VK_PAGE_DOWN; - 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_Escape: - return J_VK_ESCAPE; - case XK_Delete: - return J_VK_DELETE; - } - 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; -} - #define X11_MOUSE_EVENT_MASK (ButtonPressMask | ButtonReleaseMask | PointerMotionMask | EnterWindowMask | LeaveWindowMask) -static const char * const ClazzNameNewtWindow = "com/jogamp/newt/Window"; - -static jclass newtWindowClz=NULL; - -static jmethodID insetsChangedID = NULL; -static jmethodID sizeChangedID = NULL; -static jmethodID positionChangedID = NULL; -static jmethodID focusChangedID = NULL; -static jmethodID visibleChangedID = 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 focusActionID = NULL; -static jmethodID enqueueRequestFocusID = NULL; - -static jmethodID displayCompletedID = NULL; - - -/** - * Display - */ - -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; - } - } -} - -/* - * 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); - - displayCompletedID = (*env)->GetMethodID(env, clazz, "displayCompleted", "(JJ)V"); - if (displayCompletedID == NULL) { - return JNI_FALSE; - } - - if(NULL==newtWindowClz) { - c = (*env)->FindClass(env, ClazzNameNewtWindow); - if(NULL==c) { - NewtCommon_FatalError(env, "NEWT X11Window: can't find %s", ClazzNameNewtWindow); - } - newtWindowClz = (jclass)(*env)->NewGlobalRef(env, c); - (*env)->DeleteLocalRef(env, c); - if(NULL==newtWindowClz) { - NewtCommon_FatalError(env, "NEWT X11Window: can't use %s", ClazzNameNewtWindow); - } - } - - 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); -} - - -/** - * Window - */ - static int putPtrIn32Long(unsigned long * dst, uintptr_t src) { int i=0; dst[i++] = (unsigned long) ( ( src >> 0 ) & 0xFFFFFFFF ) ; @@ -375,7 +97,7 @@ static void setJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlon (unsigned char *)&jogl_java_object_data, nitems_32); } -static jobject getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlong javaObjectAtom, Bool showWarning) { +jobject getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlong javaObjectAtom, Bool showWarning) { Atom actual_type; int actual_format; int nitems_32 = ( sizeof(uintptr_t) == 8 ) ? 2 : 1 ; @@ -413,7 +135,7 @@ static jobject getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, j XFree(jogl_java_object_data_pp); #ifdef VERBOSE_ON - if(JNI_FALSE == (*env)->IsInstanceOf(env, jwindow, newtWindowClz)) { + if(JNI_FALSE == (*env)->IsInstanceOf(env, jwindow, X11NewtWindowClazz)) { NewtCommon_throwNewRuntimeException(env, "fetched Atom NEWT_JAVA_OBJECT window is not a NEWT Window: javaWindow 0x%X !", jwindow); } #endif @@ -421,7 +143,7 @@ static jobject getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, j } /** @return zero if fails, non zero if OK */ -static Status NewtWindows_getRootAndParent (Display *dpy, Window w, Window * root_return, Window * parent_return) { +Status NewtWindows_getRootAndParent (Display *dpy, Window w, Window * root_return, Window * parent_return) { Window *children_return=NULL; unsigned int nchildren_return=0; @@ -502,7 +224,7 @@ static Status NewtWindows_getFrameExtends(Display *dpy, Window window, int *left return 1; // Ok } -static Status NewtWindows_updateInsets(JNIEnv *env, jobject jwindow, Display *dpy, Window window, int *left, int *right, int *top, int *bottom) { +Status NewtWindows_updateInsets(JNIEnv *env, jobject jwindow, Display *dpy, Window window, int *left, int *right, int *top, int *bottom) { if(0 != NewtWindows_getFrameExtends(dpy, window, left, right, top, bottom)) { DBG_PRINT( "NewtWindows_updateInsets: insets by _NET_FRAME_EXTENTS [ l %d, r %d, t %d, b %d ]\n", *left, *right, *top, *bottom); @@ -535,16 +257,14 @@ static void NewtWindows_requestFocus (JNIEnv *env, jobject window, Display *dpy, DBG_PRINT( "X11: requestFocus dpy %p,win %p, force %d, hasFocus %d\n", dpy, (void*)w, force, focus_return==w); if( JNI_TRUE==force || focus_return!=w) { - if( JNI_TRUE==force || JNI_FALSE == (*env)->CallBooleanMethod(env, window, focusActionID) ) { - DBG_PRINT( "X11: XRaiseWindow dpy %p, win %p\n", dpy, (void*)w); - XRaiseWindow(dpy, w); - NewtWindows_setCWAbove(dpy, w); - // Avoid 'BadMatch' errors from XSetInputFocus, ie if window is not viewable - XGetWindowAttributes(dpy, w, &xwa); - if(xwa.map_state == IsViewable) { - DBG_PRINT( "X11: XSetInputFocus dpy %p,win %pd\n", dpy, (void*)w); - XSetInputFocus(dpy, w, RevertToParent, CurrentTime); - } + DBG_PRINT( "X11: XRaiseWindow dpy %p, win %p\n", dpy, (void*)w); + XRaiseWindow(dpy, w); + NewtWindows_setCWAbove(dpy, w); + // Avoid 'BadMatch' errors from XSetInputFocus, ie if window is not viewable + XGetWindowAttributes(dpy, w, &xwa); + if(xwa.map_state == IsViewable) { + DBG_PRINT( "X11: XSetInputFocus dpy %p,win %pd\n", dpy, (void*)w); + XSetInputFocus(dpy, w, RevertToParent, CurrentTime); } } DBG_PRINT( "X11: requestFocus dpy %p,win %p, force %d - FIN\n", dpy, (void*)w, force); @@ -710,752 +430,6 @@ static Bool NewtWindows_setFullscreenEWMH (Display *dpy, Window root, Window w, return res; } -#define USE_SENDIO_DIRECT 1 - -/* - * 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 = upper_return; - modifiers = X11InputState2NewtModifiers(evt.xkey.state); - } else { - keyChar=0; - } - break; - - case ButtonPress: - case ButtonRelease: - case MotionNotify: - modifiers = X11InputState2NewtModifiers(evt.xbutton.state); - break; - - default: - break; - } - - switch(evt.type) { - case ButtonPress: - (*env)->CallVoidMethod(env, jwindow, enqueueRequestFocusID, 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, X11KeySym2NewtVKey(keySym), (jchar) keyChar); - #else - (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_PRESSED, - modifiers, X11KeySym2NewtVKey(keySym), (jchar) keyChar); - #endif - - break; - case KeyRelease: - #ifdef USE_SENDIO_DIRECT - (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_RELEASED, - modifiers, X11KeySym2NewtVKey(keySym), (jchar) keyChar); - - (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_TYPED, - modifiers, (jint) -1, (jchar) keyChar); - #else - (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_RELEASED, - modifiers, X11KeySym2NewtVKey(keySym), (jchar) keyChar); - - (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_TYPED, - modifiers, (jint) -1, (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); - } - } -} - - -/** - * Screen - */ - -/* - * Class: jogamp_newt_driver_x11_X11Screen - * Method: GetScreen - * Signature: (JI)J - */ -JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_X11Screen_GetScreen0 - (JNIEnv *env, jclass clazz, jlong display, jint screen_index) -{ - Display * dpy = (Display *)(intptr_t)display; - Screen * scrn= NULL; - - DBG_PRINT("X11: X11Screen_GetScreen0 dpy %p START\n", dpy); - - if(dpy==NULL) { - NewtCommon_FatalError(env, "invalid display connection.."); - } - - scrn = ScreenOfDisplay(dpy, screen_index); - if(scrn==NULL) { - fprintf(stderr, "couldn't get screen idx %d\n", screen_index); - } - DBG_PRINT("X11: X11Screen_GetScreen0 idx %d -> scrn %p DONE\n", screen_index, scrn); - return (jlong) (intptr_t) scrn; -} - -JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_X11Screen_getWidth0 - (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx) -{ - Display * dpy = (Display *) (intptr_t) display; - return (jint) XDisplayWidth( dpy, scrn_idx); -} - -JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_X11Screen_getHeight0 - (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx) -{ - Display * dpy = (Display *) (intptr_t) display; - return (jint) XDisplayHeight( dpy, scrn_idx); -} - - -static Bool NewtScreen_getRANDRVersion(Display *dpy, int *major, int *minor) { - if( 0 == XRRQueryVersion(dpy, major, minor) ) { - return False; - } - return True; -} - -static Bool NewtScreen_hasRANDR(Display *dpy) { - int major, minor; - return NewtScreen_getRANDRVersion(dpy, &major, &minor); -} - -static int NewtScreen_XRotation2Degree(JNIEnv *env, int xrotation) { - int rot; - if(xrotation == RR_Rotate_0) { - rot = 0; - } - else if(xrotation == RR_Rotate_90) { - rot = 90; - } - else if(xrotation == RR_Rotate_180) { - rot = 180; - } - else if(xrotation == RR_Rotate_270) { - rot = 270; - } else { - NewtCommon_throwNewRuntimeException(env, "invalid native rotation: %d", xrotation); - } - return rot; -} - -/* - * Class: jogamp_newt_driver_x11_X11Screen - * Method: getAvailableScreenModeRotations0 - * Signature: (JI)I - */ -JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_X11Screen_getAvailableScreenModeRotations0 - (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx) -{ - Display *dpy = (Display *) (intptr_t) display; - Window root = RootWindow(dpy, (int)scrn_idx); - int num_rotations = 0; - Rotation cur_rotation, rotations_supported; - int rotations[4]; - int major, minor; - - if(False == NewtScreen_getRANDRVersion(dpy, &major, &minor)) { - fprintf(stderr, "RANDR not available\n"); - return (*env)->NewIntArray(env, 0); - } - - rotations_supported = XRRRotations (dpy, (int)scrn_idx, &cur_rotation); - - if(0 != (rotations_supported & RR_Rotate_0)) { - rotations[num_rotations++] = 0; - } - if(0 != (rotations_supported & RR_Rotate_90)) { - rotations[num_rotations++] = 90; - } - if(0 != (rotations_supported & RR_Rotate_180)) { - rotations[num_rotations++] = 180; - } - if(0 != (rotations_supported & RR_Rotate_270)) { - rotations[num_rotations++] = 270; - } - - jintArray properties = NULL; - - if(num_rotations>0) { - properties = (*env)->NewIntArray(env, num_rotations); - if (properties == NULL) { - NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", num_rotations); - } - - // move from the temp structure to the java structure - (*env)->SetIntArrayRegion(env, properties, 0, num_rotations, rotations); - } - - return properties; -} - -/* - * Class: jogamp_newt_driver_x11_X11Screen - * Method: getNumScreenModeResolution0 - * Signature: (JI)I - */ -JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_X11Screen_getNumScreenModeResolutions0 - (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx) -{ - Display *dpy = (Display *) (intptr_t) display; - Window root = RootWindow(dpy, (int)scrn_idx); - - if(False == NewtScreen_hasRANDR(dpy)) { - DBG_PRINT("Java_jogamp_newt_driver_x11_X11Screen_getNumScreenModeResolutions0: RANDR not available\n"); - return 0; - } - - int num_sizes; - XRRScreenSize *xrrs = XRRSizes(dpy, (int)scrn_idx, &num_sizes); //get possible screen resolutions - - DBG_PRINT("getNumScreenModeResolutions0: %d\n", num_sizes); - - return num_sizes; -} - -/* - * Class: jogamp_newt_driver_x11_X11Screen - * Method: getScreenModeResolutions0 - * Signature: (JII)[I - */ -JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_X11Screen_getScreenModeResolution0 - (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx, jint resMode_idx) -{ - Display *dpy = (Display *) (intptr_t) display; - Window root = RootWindow(dpy, (int)scrn_idx); - - if(False == NewtScreen_hasRANDR(dpy)) { - DBG_PRINT("Java_jogamp_newt_driver_x11_X11Screen_getScreenModeResolution0: RANDR not available\n"); - return (*env)->NewIntArray(env, 0); - } - - int num_sizes; - XRRScreenSize *xrrs = XRRSizes(dpy, (int)scrn_idx, &num_sizes); //get possible screen resolutions - - if( 0 > resMode_idx || resMode_idx >= num_sizes ) { - NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes); - } - - // Fill the properties in temp jint array - int propIndex = 0; - jint prop[4]; - - prop[propIndex++] = xrrs[(int)resMode_idx].width; - prop[propIndex++] = xrrs[(int)resMode_idx].height; - prop[propIndex++] = xrrs[(int)resMode_idx].mwidth; - prop[propIndex++] = xrrs[(int)resMode_idx].mheight; - - jintArray properties = (*env)->NewIntArray(env, 4); - if (properties == NULL) { - NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", 4); - } - - // move from the temp structure to the java structure - (*env)->SetIntArrayRegion(env, properties, 0, 4, prop); - - return properties; -} - -/* - * Class: jogamp_newt_driver_x11_X11Screen - * Method: getScreenModeRates0 - * Signature: (JII)[I - */ -JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_X11Screen_getScreenModeRates0 - (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx, jint resMode_idx) -{ - Display *dpy = (Display *) (intptr_t) display; - Window root = RootWindow(dpy, (int)scrn_idx); - - if(False == NewtScreen_hasRANDR(dpy)) { - DBG_PRINT("Java_jogamp_newt_driver_x11_X11Screen_getScreenModeRates0: RANDR not available\n"); - return (*env)->NewIntArray(env, 0); - } - - int num_sizes; - XRRScreenSize *xrrs = XRRSizes(dpy, (int)scrn_idx, &num_sizes); //get possible screen resolutions - - if( 0 > resMode_idx || resMode_idx >= num_sizes ) { - NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes); - } - - int num_rates; - short *rates = XRRRates(dpy, (int)scrn_idx, (int)resMode_idx, &num_rates); - - jint prop[num_rates]; - int i; - for(i=0; i<num_rates; i++) { - prop[i] = (int) rates[i]; - /** fprintf(stderr, "rate[%d, %d, %d/%d]: %d\n", (int)scrn_idx, resMode_idx, i, num_rates, prop[i]); */ - } - - jintArray properties = (*env)->NewIntArray(env, num_rates); - if (properties == NULL) { - NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", num_rates); - } - - // move from the temp structure to the java structure - (*env)->SetIntArrayRegion(env, properties, 0, num_rates, prop); - - return properties; -} - -/* - * Class: jogamp_newt_driver_x11_X11Screen - * Method: getCurrentScreenRate0 - * Signature: (JI)I - */ -JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_X11Screen_getCurrentScreenRate0 - (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx) -{ - Display *dpy = (Display *) (intptr_t) display; - Window root = RootWindow(dpy, (int)scrn_idx); - - if(False == NewtScreen_hasRANDR(dpy)) { - DBG_PRINT("Java_jogamp_newt_driver_x11_X11Screen_getCurrentScreenRate0: RANDR not available\n"); - return -1; - } - - // get current resolutions and frequencies - XRRScreenConfiguration *conf = XRRGetScreenInfo(dpy, root); - short original_rate = XRRConfigCurrentRate(conf); - - //free - XRRFreeScreenConfigInfo(conf); - - DBG_PRINT("getCurrentScreenRate0: %d\n", (int)original_rate); - - return (jint) original_rate; -} - -/* - * Class: jogamp_newt_driver_x11_X11Screen - * Method: getCurrentScreenRotation0 - * Signature: (JI)I - */ -JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_X11Screen_getCurrentScreenRotation0 - (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx) -{ - Display *dpy = (Display *) (intptr_t) display; - Window root = RootWindow(dpy, (int)scrn_idx); - - if(False == NewtScreen_hasRANDR(dpy)) { - DBG_PRINT("Java_jogamp_newt_driver_x11_X11Screen_getCurrentScreenRotation0: RANDR not available\n"); - return -1; - } - - //get current resolutions and frequencies - XRRScreenConfiguration *conf = XRRGetScreenInfo(dpy, root); - - Rotation rotation; - XRRConfigCurrentConfiguration(conf, &rotation); - - //free - XRRFreeScreenConfigInfo(conf); - - return NewtScreen_XRotation2Degree(env, rotation); -} - - -/* - * Class: jogamp_newt_driver_x11_X11Screen - * Method: getCurrentScreenResolutionIndex0 - * Signature: (JI)I - */ -JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_X11Screen_getCurrentScreenResolutionIndex0 - (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx) -{ - Display *dpy = (Display *) (intptr_t) display; - Window root = RootWindow(dpy, (int)scrn_idx); - - if(False == NewtScreen_hasRANDR(dpy)) { - DBG_PRINT("Java_jogamp_newt_driver_x11_X11Screen_getCurrentScreenResolutionIndex0: RANDR not available\n"); - return -1; - } - - // get current resolutions and frequency configuration - XRRScreenConfiguration *conf = XRRGetScreenInfo(dpy, root); - short original_rate = XRRConfigCurrentRate(conf); - - Rotation original_rotation; - SizeID original_size_id = XRRConfigCurrentConfiguration(conf, &original_rotation); - - //free - XRRFreeScreenConfigInfo(conf); - - DBG_PRINT("getCurrentScreenResolutionIndex0: %d\n", (int)original_size_id); - return (jint)original_size_id; -} - -/* - * Class: jogamp_newt_driver_x11_X11Screen - * Method: setCurrentScreenModeStart0 - * Signature: (JIIII)Z - */ -JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_X11Screen_setCurrentScreenModeStart0 - (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jint resMode_idx, jint freq, jint rotation) -{ - Display *dpy = (Display *) (intptr_t) display; - Window root = RootWindow(dpy, (int)screen_idx); - - if(False == NewtScreen_hasRANDR(dpy)) { - DBG_PRINT("Java_jogamp_newt_driver_x11_X11Screen_setCurrentScreenModeStart0: RANDR not available\n"); - return JNI_FALSE; - } - - int num_sizes; - XRRScreenSize *xrrs = XRRSizes(dpy, (int)screen_idx, &num_sizes); //get possible screen resolutions - XRRScreenConfiguration *conf; - int rot; - - if( 0 > resMode_idx || resMode_idx >= num_sizes ) { - NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes); - } - - conf = XRRGetScreenInfo(dpy, root); - - switch(rotation) { - case 0: - rot = RR_Rotate_0; - break; - case 90: - rot = RR_Rotate_90; - break; - case 180: - rot = RR_Rotate_180; - break; - case 270: - rot = RR_Rotate_270; - break; - default: - NewtCommon_throwNewRuntimeException(env, "Invalid rotation: %d", rotation); - } - - DBG_PRINT("X11Screen.setCurrentScreenMode0: CHANGED TO %d: %d x %d PIXELS, %d Hz, %d degree\n", - resMode_idx, xrrs[resMode_idx].width, xrrs[resMode_idx].height, (int)freq, rotation); - - XRRSelectInput (dpy, root, RRScreenChangeNotifyMask); - - XSync(dpy, False); - XRRSetScreenConfigAndRate(dpy, conf, root, (int)resMode_idx, rot, (short)freq, CurrentTime); - XSync(dpy, False); - - //free - XRRFreeScreenConfigInfo(conf); - XSync(dpy, False); - - return JNI_TRUE; -} - -/* - * Class: jogamp_newt_driver_x11_X11Screen - * Method: setCurrentScreenModePollEnd0 - * Signature: (J)Z - */ -JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_X11Screen_setCurrentScreenModePollEnd0 - (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jint resMode_idx, jint freq, jint rotation) -{ - Display *dpy = (Display *) (intptr_t) display; - int randr_event_base, randr_error_base; - XEvent evt; - XRRScreenChangeNotifyEvent * scn_event = (XRRScreenChangeNotifyEvent *) &evt; - - if(False == NewtScreen_hasRANDR(dpy)) { - DBG_PRINT("Java_jogamp_newt_driver_x11_X11Screen_setCurrentScreenModePollEnd0: RANDR not available\n"); - return JNI_FALSE; - } - - int num_sizes; - XRRScreenSize *xrrs = XRRSizes(dpy, (int)screen_idx, &num_sizes); //get possible screen resolutions - XRRScreenConfiguration *conf; - - if( 0 > resMode_idx || resMode_idx >= num_sizes ) { - NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes); - } - - XRRQueryExtension(dpy, &randr_event_base, &randr_error_base); - - int done = 0; - int rot; - do { - if ( 0 >= XEventsQueued(dpy, QueuedAfterFlush) ) { - return; - } - XNextEvent(dpy, &evt); - - switch (evt.type - randr_event_base) { - case RRScreenChangeNotify: - rot = NewtScreen_XRotation2Degree(env, (int)scn_event->rotation); - DBG_PRINT( "XRANDR: event . RRScreenChangeNotify call %p (root %p) resIdx %d rot %d %dx%d\n", - (void*)scn_event->window, (void*)scn_event->root, - (int)scn_event->size_index, rot, - scn_event->width, scn_event->height); - // done = scn_event->size_index == resMode_idx; // not reliable .. - done = rot == rotation && - scn_event->width == xrrs[resMode_idx].width && - scn_event->height == xrrs[resMode_idx].height; - break; - default: - DBG_PRINT("RANDR: event . unhandled %d 0x%X call %p\n", (int)evt.type, (int)evt.type, (void*)evt.xany.window); - } - XRRUpdateConfiguration(&evt); - } while(!done); - - XSync(dpy, False); - -} - /** * Window */ @@ -1468,37 +442,6 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_X11Screen_setCurrentScree JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_X11Window_initIDs0 (JNIEnv *env, jclass clazz) { - insetsChangedID = (*env)->GetMethodID(env, clazz, "insetsChanged", "(ZIIII)V"); - sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(ZIIZ)V"); - positionChangedID = (*env)->GetMethodID(env, clazz, "positionChanged", "(ZII)V"); - focusChangedID = (*env)->GetMethodID(env, clazz, "focusChanged", "(ZZ)V"); - visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(ZZ)V"); - reparentNotifyID = (*env)->GetMethodID(env, clazz, "reparentNotify", "(J)V"); - windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "()V"); - windowRepaintID = (*env)->GetMethodID(env, clazz, "windowRepaint", "(ZIIII)V"); - enqueueMouseEventID = (*env)->GetMethodID(env, clazz, "enqueueMouseEvent", "(ZIIIIII)V"); - sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(IIIIII)V"); - enqueueKeyEventID = (*env)->GetMethodID(env, clazz, "enqueueKeyEvent", "(ZIIIC)V"); - sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(IIIC)V"); - enqueueRequestFocusID = (*env)->GetMethodID(env, clazz, "enqueueRequestFocus", "(Z)V"); - focusActionID = (*env)->GetMethodID(env, clazz, "focusAction", "()Z"); - - if (insetsChangedID == NULL || - sizeChangedID == NULL || - positionChangedID == NULL || - focusChangedID == NULL || - visibleChangedID == NULL || - reparentNotifyID == NULL || - windowDestroyNotifyID == NULL || - windowRepaintID == NULL || - enqueueMouseEventID == NULL || - sendMouseEventID == NULL || - enqueueKeyEventID == NULL || - sendKeyEventID == NULL || - focusActionID == NULL || - enqueueRequestFocusID == NULL) { - return JNI_FALSE; - } return JNI_TRUE; } @@ -1513,14 +456,12 @@ static Bool WaitForUnmapNotify( Display *dpy, XEvent *event, XPointer arg ) { static void NewtWindows_setPosSize(Display *dpy, Window w, jint x, jint y, jint width, jint height) { if(width>0 && height>0 || x>=0 && y>=0) { // resize/position if requested XWindowChanges xwc; - int flags = 0; + int flags = CWX | CWY; memset(&xwc, 0, sizeof(XWindowChanges)); - if(0<=x && 0<=y) { - flags |= CWX | CWY; - xwc.x=x; - xwc.y=y; - } + xwc.x=x; + xwc.y=y; + if(0<width && 0<height) { flags |= CWWidth | CWHeight; xwc.width=width; @@ -1534,13 +475,12 @@ static void NewtWindows_setPosSize(Display *dpy, Window w, jint x, jint y, jint /* * Class: jogamp_newt_driver_x11_X11Window * Method: CreateWindow - * Signature: (JJIJIIII)J */ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_X11Window_CreateWindow0 (JNIEnv *env, jobject obj, jlong parent, jlong display, jint screen_index, jlong visualID, jlong javaObjectAtom, jlong windowDeleteAtom, - jint x, jint y, jint width, jint height, int flags) + jint x, jint y, jint width, jint height, jboolean autoPosition, int flags) { Display * dpy = (Display *)(intptr_t)display; Atom wm_delete_atom = (Atom)windowDeleteAtom; @@ -1576,9 +516,9 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_X11Window_CreateWindow0 if(0==windowParent) { windowParent = root; } - DBG_PRINT( "X11: CreateWindow dpy %p, parent %p, %x/%d %dx%d, undeco %d, alwaysOnTop %d\n", + DBG_PRINT( "X11: CreateWindow dpy %p, parent %p, %d/%d %dx%d, undeco %d, alwaysOnTop %d, autoPosition %d\n", (void*)dpy, (void*)windowParent, x, y, width, height, - TST_FLAG_IS_UNDECORATED(flags), TST_FLAG_IS_ALWAYSONTOP(flags)); + TST_FLAG_IS_UNDECORATED(flags), TST_FLAG_IS_ALWAYSONTOP(flags), autoPosition); // try given VisualID on screen memset(&visualTemplate, 0, sizeof(XVisualInfo)); @@ -1628,7 +568,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_X11Window_CreateWindow0 { int _x = x, _y = y; // pos for CreateWindow, might be tweaked - if(0>_x || 0>_y) { + if(JNI_TRUE == autoPosition) { // user didn't requested specific position, use WM default _x = 0; _y = 0; @@ -1662,7 +602,6 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_X11Window_CreateWindow0 { XEvent event; int left, right, top, bottom; - Bool userPos = 0<=x && 0<=y ; XMapWindow(dpy, window); XIfEvent( dpy, &event, WaitForMapNotify, (XPointer) window ); // wait to get proper insets values @@ -1671,19 +610,17 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_X11Window_CreateWindow0 NewtWindows_updateInsets(env, jwindow, dpy, window, &left, &right, &top, &bottom); (*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_FALSE, JNI_TRUE); - if(!userPos) { + if(JNI_TRUE == autoPosition) { // get position from WM int dest_x, dest_y; Window child; XTranslateCoordinates(dpy, window, windowParent, 0, 0, &dest_x, &dest_y, &child); x = (int)dest_x; y = (int)dest_y; } - DBG_PRINT("X11: [CreateWindow]: client: %d/%d %dx%d (is user-pos %d)\n", x, y, width, height, userPos); + DBG_PRINT("X11: [CreateWindow]: client: %d/%d %dx%d (autoPosition %d)\n", x, y, width, height, autoPosition); x -= left; // top-level y -= top; // top-level - if(0>x) { x = 0; } - if(0>y) { y = 0; } DBG_PRINT("X11: [CreateWindow]: top-level: %d/%d\n", x, y); NewtWindows_setPosSize(dpy, window, x, y, width, height); @@ -1774,7 +711,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_reconfigureWindow0 fsEWMHFlags |= _NET_WM_ABOVE; // toggle above only } - displayDispatchErrorHandlerEnable(1, env); + NewtDisplay_displayDispatchErrorHandlerEnable(1, env); DBG_PRINT( "X11: reconfigureWindow0 dpy %p, scrn %d, parent %p/%p, win %p, %d/%d %dx%d, parentChange %d, hasParent %d, decorationChange %d, undecorated %d, fullscreenChange %d, fullscreen %d, alwaysOnTopChange %d, alwaysOnTop %d, visibleChange %d, visible %d, tempInvisible %d, fsEWMHFlags %d\n", (void*)dpy, screen_index, (void*) jparent, (void*)parent, (void*)w, @@ -1792,7 +729,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_reconfigureWindow0 ( TST_FLAG_CHANGE_FULLSCREEN(flags) || TST_FLAG_CHANGE_ALWAYSONTOP(flags) ) ) { Bool enable = TST_FLAG_CHANGE_FULLSCREEN(flags) ? TST_FLAG_IS_FULLSCREEN(flags) : TST_FLAG_IS_ALWAYSONTOP(flags) ; if( NewtWindows_setFullscreenEWMH(dpy, root, w, fsEWMHFlags, isVisible, enable) ) { - displayDispatchErrorHandlerEnable(0, env); + NewtDisplay_displayDispatchErrorHandlerEnable(0, env); return; } } @@ -1856,7 +793,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_reconfigureWindow0 NewtWindows_setFullscreenEWMH(dpy, root, w, fsEWMHFlags, isVisible, True); } - displayDispatchErrorHandlerEnable(0, env); + NewtDisplay_displayDispatchErrorHandlerEnable(0, env); DBG_PRINT( "X11: reconfigureWindow0 X\n"); } |