summaryrefslogtreecommitdiffstats
path: root/src/newt/native
diff options
context:
space:
mode:
Diffstat (limited to 'src/newt/native')
-rw-r--r--src/newt/native/X11Event.c312
-rw-r--r--src/newt/native/X11Event.h9
-rw-r--r--src/newt/native/X11ScreenRandR11.c329
-rw-r--r--src/newt/native/X11ScreenRandR13.c372
-rw-r--r--src/newt/native/XCBEvent.c314
-rw-r--r--src/newt/native/XCBEvent.h10
6 files changed, 1346 insertions, 0 deletions
diff --git a/src/newt/native/X11Event.c b/src/newt/native/X11Event.c
new file mode 100644
index 000000000..5402ffe34
--- /dev/null
+++ b/src/newt/native/X11Event.c
@@ -0,0 +1,312 @@
+
+#include "X11Event.h"
+
+void X11EventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom, jlong windowDeleteAtom) {
+ Atom wm_delete_atom = (Atom)windowDeleteAtom;
+ int num_events = 100;
+ int autoRepeatModifiers = 0;
+
+ 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 == XQLength(): 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) )
+ if ( 0 >= XEventsQueued(dpy, QueuedAfterFlush) )
+ {
+ // 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);
+
+ jwindow = getJavaWindowProperty(env, dpy, evt.xany.window, javaObjectAtom,
+ #ifdef VERBOSE_ON
+ True
+ #else
+ False
+ #endif
+ );
+
+ 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:
+ if (XEventsQueued(dpy, QueuedAfterReading)) {
+ XEvent nevt;
+ XPeekEvent(dpy, &nevt);
+
+ if (nevt.type == KeyPress && nevt.xkey.time == evt.xkey.time &&
+ nevt.xkey.keycode == evt.xkey.keycode)
+ {
+ autoRepeatModifiers |= EVENT_AUTOREPEAT_MASK;
+ } else {
+ autoRepeatModifiers &= ~EVENT_AUTOREPEAT_MASK;
+ }
+ }
+ // fall through intended
+ 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) | autoRepeatModifiers;
+ 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
+ jboolean closed;
+ DBG_PRINT( "X11: event . ClientMessage call %p type 0x%X ..\n",
+ (void*)evt.xclient.window, (unsigned int)evt.xclient.message_type);
+ closed = (*env)->CallBooleanMethod(env, jwindow, windowDestroyNotifyID, JNI_FALSE);
+ DBG_PRINT( "X11: event . ClientMessage call %p type 0x%X, closed: %d\n",
+ (void*)evt.xclient.window, (unsigned int)evt.xclient.message_type, (int)closed);
+ // 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/X11Event.h b/src/newt/native/X11Event.h
new file mode 100644
index 000000000..969bcdeed
--- /dev/null
+++ b/src/newt/native/X11Event.h
@@ -0,0 +1,9 @@
+
+#ifndef _X11Event_h
+#define _X11Event_h
+
+#include "X11Common.h"
+
+extern void X11EventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom, jlong wmDeleteAtom);
+
+#endif /* _X11Event_h */
diff --git a/src/newt/native/X11ScreenRandR11.c b/src/newt/native/X11ScreenRandR11.c
new file mode 100644
index 000000000..bc7d91d20
--- /dev/null
+++ b/src/newt/native/X11ScreenRandR11.c
@@ -0,0 +1,329 @@
+/**
+ * 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"
+
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getAvailableScreenModeRotations0_RandR11
+ (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;
+}
+
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getNumScreenModeResolutions0_RandR11
+ (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx)
+{
+ Display *dpy = (Display *) (intptr_t) display;
+ Window root = RootWindow(dpy, (int)scrn_idx);
+
+ 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_ScreenDriver
+ * Method: getScreenModeResolutions0_RandR11
+ * Signature: (JII)[I
+ */
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getScreenModeResolution0_RandR11
+ (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx, jint resMode_idx)
+{
+ Display *dpy = (Display *) (intptr_t) display;
+
+ 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_ScreenDriver
+ * Method: getScreenModeRates0_RandR11
+ * Signature: (JII)[I
+ */
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getScreenModeRates0_RandR11
+ (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx, jint resMode_idx)
+{
+ Display *dpy = (Display *) (intptr_t) display;
+
+ 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_ScreenDriver
+ * Method: getCurrentScreenRate0_RandR11
+ * Signature: (JI)I
+ */
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getCurrentScreenRate0_RandR11
+ (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx)
+{
+ Display *dpy = (Display *) (intptr_t) display;
+ Window root = RootWindow(dpy, (int)scrn_idx);
+
+ // 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_ScreenDriver
+ * Method: getCurrentScreenRotation0_RandR11
+ * Signature: (JI)I
+ */
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getCurrentScreenRotation0_RandR11
+ (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx)
+{
+ Display *dpy = (Display *) (intptr_t) display;
+ Window root = RootWindow(dpy, (int)scrn_idx);
+
+ //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_ScreenDriver
+ * Method: getCurrentScreenResolutionIndex0_RandR11
+ * Signature: (JI)I
+ */
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getCurrentScreenResolutionIndex0_RandR11
+ (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx)
+{
+ Display *dpy = (Display *) (intptr_t) display;
+ Window root = RootWindow(dpy, (int)scrn_idx);
+
+ // 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_ScreenDriver
+ * Method: setCurrentScreenModeStart0_RandR11
+ * Signature: (JIIII)Z
+ */
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_setCurrentScreenModeStart0_RandR11
+ (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);
+
+ 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);
+
+ rot = int NewtScreen_Degree2XRotation(env, 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_ScreenDriver
+ * Method: setCurrentScreenModePollEnd0_RandR11
+ * Signature: (J)Z
+ */
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_setCurrentScreenModePollEnd0_RandR11
+ (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;
+
+ 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/X11ScreenRandR13.c b/src/newt/native/X11ScreenRandR13.c
new file mode 100644
index 000000000..da90d15c9
--- /dev/null
+++ b/src/newt/native/X11ScreenRandR13.c
@@ -0,0 +1,372 @@
+/**
+ * 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"
+
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getOrigin0_RandR13
+ (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx)
+{
+ Display * dpy = (Display *) (intptr_t) display;
+ Window root = RootWindow(dpy, (int)scrn_idx);
+ int pos[] = { 0, 0 } ;
+
+ int i;
+ XRRScreenResources *xrrScreenResources = XRRGetScreenResources(dpy, root);
+ fprintf(stderr, "XRRScreenResources %p: RRCrtc crtcs %d\n", xrrScreenResources, xrrScreenResources->ncrtc);
+ for(i=0; i<xrrScreenResources->ncrtc; i++) {
+ RRCrtc crtc = xrrScreenResources->crtcs[i];
+ XRRCrtcInfo *xrrCrtcInfo = XRRGetCrtcInfo (dpy, xrrScreenResources, crtc);
+ fprintf(stderr, "RRCrtc %d: %d/%d %dx%d\n", i, xrrCrtcInfo->x, xrrCrtcInfo->y, xrrCrtcInfo->width, xrrCrtcInfo->height);
+ XRRFreeCrtcInfo(xrrCrtcInfo);
+ }
+
+ jintArray jpos = (*env)->NewIntArray(env, num_rotations);
+ if (properties == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", 2);
+ }
+
+ // move from the temp structure to the java structure
+ (*env)->SetIntArrayRegion(env, jpos, 0, 2, pos);
+ return jpos;
+}
+
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getAvailableScreenModeRotations0_RandR13
+ (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;
+}
+
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getNumScreenModeResolutions0_RandR13
+ (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx)
+{
+ Display *dpy = (Display *) (intptr_t) display;
+ Window root = RootWindow(dpy, (int)scrn_idx);
+
+ int num_sizes;
+ XRRScreenSize *xrrs = XRRSizes(dpy, (int)scrn_idx, &num_sizes); //get possible screen resolutions
+
+ DBG_PRINT("getNumScreenModeResolutions0: %d\n", num_sizes);
+
+ int i;
+ XRRScreenResources *xrrScreenResources = XRRGetScreenResources(dpy, root);
+ fprintf(stderr, "XRRScreenResources %p: RRCrtc crtcs %d\n", xrrScreenResources, xrrScreenResources->ncrtc);
+ for(i=0; i<xrrScreenResources->ncrtc; i++) {
+ RRCrtc crtc = xrrScreenResources->crtcs[i];
+ XRRCrtcInfo *xrrCrtcInfo = XRRGetCrtcInfo (dpy, xrrScreenResources, crtc);
+ fprintf(stderr, "RRCrtc %d: %d/%d %dx%d\n", i, xrrCrtcInfo->x, xrrCrtcInfo->y, xrrCrtcInfo->width, xrrCrtcInfo->height);
+ XRRFreeCrtcInfo(xrrCrtcInfo);
+ }
+ fprintf(stderr, "XRRScreenResources %p: XRRModeInfo modes %d\n", xrrScreenResources, xrrScreenResources->nmode);
+ for(i=0; i<xrrScreenResources->nmode; i++) {
+ XRRModeInfo xrrModeInfo = xrrScreenResources->modes[i];
+ fprintf(stderr, "XRRModeInfo %d: %dx%d, %s, %X\n", i, xrrModeInfo.width, xrrModeInfo.height, xrrModeInfo.name, xrrModeInfo.id);
+ }
+ XRRFreeScreenResources(xrrScreenResources);
+
+ return num_sizes;
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_ScreenDriver
+ * Method: getScreenModeResolutions0_RandR13
+ * Signature: (JII)[I
+ */
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getScreenModeResolution0_RandR13
+ (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx, jint resMode_idx)
+{
+ Display *dpy = (Display *) (intptr_t) display;
+
+ 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_ScreenDriver
+ * Method: getScreenModeRates0_RandR13
+ * Signature: (JII)[I
+ */
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getScreenModeRates0_RandR13
+ (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx, jint resMode_idx)
+{
+ Display *dpy = (Display *) (intptr_t) display;
+
+ 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_ScreenDriver
+ * Method: getCurrentScreenRate0_RandR13
+ * Signature: (JI)I
+ */
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getCurrentScreenRate0_RandR13
+ (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx)
+{
+ Display *dpy = (Display *) (intptr_t) display;
+ Window root = RootWindow(dpy, (int)scrn_idx);
+
+ // 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_ScreenDriver
+ * Method: getCurrentScreenRotation0_RandR13
+ * Signature: (JI)I
+ */
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getCurrentScreenRotation0_RandR13
+ (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx)
+{
+ Display *dpy = (Display *) (intptr_t) display;
+ Window root = RootWindow(dpy, (int)scrn_idx);
+
+ //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_ScreenDriver
+ * Method: getCurrentScreenResolutionIndex0_RandR13
+ * Signature: (JI)I
+ */
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getCurrentScreenResolutionIndex0_RandR13
+ (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx)
+{
+ Display *dpy = (Display *) (intptr_t) display;
+ Window root = RootWindow(dpy, (int)scrn_idx);
+
+ // 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_ScreenDriver
+ * Method: setCurrentScreenModeStart0_RandR13
+ * Signature: (JIIII)Z
+ */
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_setCurrentScreenModeStart0_RandR13
+ (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);
+
+ 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);
+
+ rot = int NewtScreen_Degree2XRotation(env, 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_ScreenDriver
+ * Method: setCurrentScreenModePollEnd0_RandR13
+ * Signature: (J)Z
+ */
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_setCurrentScreenModePollEnd0_RandR13
+ (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;
+
+ 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/XCBEvent.c b/src/newt/native/XCBEvent.c
new file mode 100644
index 000000000..77a3380db
--- /dev/null
+++ b/src/newt/native/XCBEvent.c
@@ -0,0 +1,314 @@
+
+#define VERBOSE_ON 1
+
+#include "XCBEvent.h"
+
+#include <xcb/xcb.h>
+#include <xcb/xcb_event.h>
+#include <xcb/xproto.h>
+#include <xcb/xcb_keysyms.h>
+#include <X11/Xlib-xcb.h>
+
+void XCBSetEventQueueOwner(Display *dpy) {
+ XSetEventQueueOwner(dpy, XCBOwnsEventQueue);
+}
+
+void XCBEventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom, jlong wmDeleteAtom) {
+ int num_events = 100;
+ xcb_connection_t *conn = NULL;
+
+ if ( NULL == dpy ) {
+ return;
+ }
+ conn = XGetXCBConnection(dpy);
+
+ // Periodically take a break
+ while( num_events > 0 ) {
+ jobject jwindow = NULL;
+ xcb_generic_event_t *evt;
+ // KeySym keySym = 0;
+ jint modifiers = 0;
+ char keyChar = 0;
+ // char text[255];
+
+ evt = xcb_poll_for_event(conn);
+ if(NULL == evt) {
+ // DBG_PRINT( "X11: DispatchMessages 0x%X - Leave 1\n", dpy);
+ return;
+ }
+ num_events--;
+
+ /*if( 0==evt.xany.window ) {
+ free(evt);
+ NewtCommon_throwNewRuntimeException(env, "event window NULL, bail out!");
+ return ;
+ }
+
+ if(dpy!=evt.xany.display) {
+ free(evt);
+ 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, evt.type);
+
+ // X11WindowDisplayErrorHandlerEnable(1, env);
+
+ // jwindow = X11WindowGetJavaWindowProperty(env, dpy, evt.xany.window, javaObjectAtom, VERBOSE_BOOL);
+
+ //X11WindowDisplayErrorHandlerEnable(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;
+ }*/
+
+ uint8_t xcb_event_type = evt->response_type & ~0x80;
+ xcb_window_t event_window = 0;
+
+ switch( xcb_event_type ) {
+ case XCB_BUTTON_PRESS:
+ case XCB_BUTTON_RELEASE:
+ event_window = ((xcb_button_press_event_t *)evt)->event;
+ modifiers = X11InputState2NewtModifiers(((xcb_button_press_event_t *)evt)->state);
+ break;
+ case XCB_MOTION_NOTIFY:
+ event_window = ((xcb_motion_notify_event_t *)evt)->event;
+ break;
+ case XCB_KEY_PRESS:
+ case XCB_KEY_RELEASE: {
+ xcb_key_press_event_t *_evt = (xcb_key_press_event_t *)evt;
+ event_window = _evt->event;
+ /*
+ xcb_keycode_t detail = _evt->detail;
+ 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 XCB_EXPOSE:
+ event_window = ((xcb_expose_event_t *)evt)->window;
+ break;
+ case XCB_MAP_NOTIFY:
+ event_window = ((xcb_map_notify_event_t *)evt)->window;
+ break;
+ case XCB_UNMAP_NOTIFY:
+ event_window = ((xcb_unmap_notify_event_t *)evt)->window;
+ break;
+ }
+ if(0==event_window) {
+ fprintf(stderr, "Warning: NEWT X11 DisplayDispatch %p, Couldn't handle event %d, no X11 window associated\n",
+ (void*)dpy, xcb_event_type);
+ continue;
+ }
+ jwindow = getJavaWindowProperty(env, dpy, event_window, javaObjectAtom,
+ #ifdef VERBOSE_ON
+ True
+ #else
+ False
+ #endif
+ );
+ if(NULL==jwindow) {
+ fprintf(stderr, "Warning: NEWT X11 DisplayDispatch %p, Couldn't handle event %d for X11 window %p\n",
+ (void*)(intptr_t)dpy, xcb_event_type, (void*)(intptr_t)event_window);
+ continue;
+ }
+
+ switch( xcb_event_type ) {
+ case XCB_BUTTON_PRESS: {
+ xcb_button_press_event_t *_evt = (xcb_button_press_event_t *)evt;
+ (*env)->CallVoidMethod(env, jwindow, requestFocusID, JNI_FALSE);
+ #ifdef USE_SENDIO_DIRECT
+ (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_PRESSED,
+ modifiers,
+ (jint) _evt->event_x, (jint) _evt->event_y, (jint) _evt->state, 0 /*rotation*/);
+ #else
+ (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_PRESSED,
+ modifiers,
+ (jint) _evt->event_x, (jint) _evt->event_y, (jint) _evt->state, 0 /*rotation*/);
+ #endif
+ } break;
+ case XCB_BUTTON_RELEASE: {
+ xcb_button_release_event_t *_evt = (xcb_button_release_event_t *)evt;
+ #ifdef USE_SENDIO_DIRECT
+ (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_RELEASED,
+ modifiers,
+ (jint) _evt->event_x, (jint) _evt->event_y, (jint) _evt->state, 0 /*rotation*/);
+ #else
+ (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_RELEASED,
+ modifiers,
+ (jint) _evt->event_x, (jint) _evt->event_y, (jint) _evt->state, 0 /*rotation*/);
+ #endif
+ } break;
+ case XCB_MOTION_NOTIFY: {
+ xcb_motion_notify_event_t *_evt = (xcb_motion_notify_event_t *)evt;
+ #ifdef USE_SENDIO_DIRECT
+ (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_MOVED,
+ modifiers,
+ (jint) _evt->event_x, (jint) _evt->event_y, (jint)0, 0 /*rotation*/);
+ #else
+ (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_MOVED,
+ modifiers,
+ (jint) _evt->event_x, (jint) _evt->event_y, (jint)0, 0 /*rotation*/);
+ #endif
+ } break;
+ case XCB_KEY_PRESS: {
+ xcb_key_press_event_t *_evt = (xcb_key_press_event_t *)evt;
+ #ifdef USE_SENDIO_DIRECT
+ (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_PRESSED,
+ modifiers, X11KeySym2NewtVKey(_evt->state), (jchar) keyChar);
+ #else
+ (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_PRESSED,
+ modifiers, X11KeySym2NewtVKey(_evt->state), (jchar) keyChar);
+ #endif
+ } break;
+ case XCB_KEY_RELEASE: {
+ xcb_key_release_event_t *_evt = (xcb_key_release_event_t *)evt;
+ event_window = ((xcb_key_release_event_t *)evt)->event;
+ #ifdef USE_SENDIO_DIRECT
+ (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_RELEASED,
+ modifiers, X11KeySym2NewtVKey(_evt->state), (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(_evt->state), (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
+ (*env)->CallVoidMethod(env, jwindow, sizeChangedID,
+ (jint) evt.xconfigure.width, (jint) evt.xconfigure.height, JNI_FALSE);
+ (*env)->CallVoidMethod(env, jwindow, positionChangedID,
+ (jint) evt.xconfigure.x, (jint) evt.xconfigure.y);
+ }
+ break;
+ case ClientMessage:
+ if (evt.xclient.send_event==True && evt.xclient.data.l[0]==(Atom)wmDeleteAtom) {
+ 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_TRUE);
+ break;
+
+ case FocusOut:
+ DBG_PRINT( "X11: event . FocusOut call %p\n", (void*)evt.xvisibility.window);
+ (*env)->CallVoidMethod(env, jwindow, focusChangedID, JNI_FALSE);
+ break;
+ */
+
+ case XCB_EXPOSE: {
+ xcb_expose_event_t *_evt = (xcb_expose_event_t *)evt;
+ DBG_PRINT( "X11: event . Expose call %p %d/%d %dx%d count %d\n", (void*)(intptr_t)_evt->window,
+ _evt->x, _evt->y, _evt->width, _evt->height, _evt->count);
+
+ if (_evt->count == 0 && _evt->width > 0 && _evt->height > 0) {
+ (*env)->CallVoidMethod(env, jwindow, windowRepaintID,
+ _evt->x, _evt->y, _evt->width, _evt->height);
+ }
+ } break;
+
+ case XCB_MAP_NOTIFY: {
+ xcb_map_notify_event_t *_evt = (xcb_map_notify_event_t *)evt;
+ DBG_PRINT( "X11: event . MapNotify call Event %p, Window %p, override_redirect %d, child-event: %d\n",
+ (void*)(intptr_t)_evt->event, (void*)(intptr_t)_evt->window, (int)_evt->override_redirect,
+ _evt->event!=_evt->window);
+ if( _evt->event == _evt->window ) {
+ // ignore child window notification
+ (*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_TRUE);
+ }
+ } break;
+
+ case XCB_UNMAP_NOTIFY: {
+ xcb_unmap_notify_event_t *_evt = (xcb_unmap_notify_event_t *)evt;
+ DBG_PRINT( "X11: event . UnmapNotify call Event %p, Window %p, child-event: %d\n",
+ (void*)(intptr_t)_evt->event, (void*)(intptr_t)_evt->window,
+ _evt->event!=_evt->window);
+ if( _evt->event == _evt->window ) {
+ // ignore child window notification
+ (*env)->CallVoidMethod(env, jwindow, visibleChangedID, 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 OldParent %p (root %p, top %p), NewParent %p (root %p, top %p), Window %p (root %p, top %p)\n",
+ (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, windowReparentedID, parentResult);
+ }
+ break;
+ */
+
+ // unhandled events .. yet ..
+
+ default:
+ DBG_PRINT("XCB: event . unhandled %d 0x%X call %p\n", (int)xcb_event_type, (unsigned int)xcb_event_type, (void*)(intptr_t)event_window);
+ }
+ free(evt);
+ }
+}
+
+
diff --git a/src/newt/native/XCBEvent.h b/src/newt/native/XCBEvent.h
new file mode 100644
index 000000000..d70797566
--- /dev/null
+++ b/src/newt/native/XCBEvent.h
@@ -0,0 +1,10 @@
+
+#ifndef _XCBEvent_h
+#define _XCBEvent_h
+
+#include "X11Common.h"
+
+extern void XCBSetEventQueueOwner(Display *dpy);
+extern void XCBEventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom, jlong wmDeleteAtom);
+
+#endif /* _XCBDisplayXCBEvent_h */