aboutsummaryrefslogtreecommitdiffstats
path: root/src/newt/native
diff options
context:
space:
mode:
Diffstat (limited to 'src/newt/native')
-rw-r--r--src/newt/native/X11Common.h12
-rw-r--r--src/newt/native/X11Display.c115
-rw-r--r--src/newt/native/X11Window.c56
3 files changed, 178 insertions, 5 deletions
diff --git a/src/newt/native/X11Common.h b/src/newt/native/X11Common.h
index f9254ab76..99795b6e8 100644
--- a/src/newt/native/X11Common.h
+++ b/src/newt/native/X11Common.h
@@ -42,6 +42,7 @@
#include <X11/Xutil.h>
#include <X11/keysym.h>
#include <X11/Xatom.h>
+#include <X11/extensions/XInput2.h>
#include <X11/extensions/Xrandr.h>
@@ -74,6 +75,14 @@ extern jmethodID visibleChangedID;
extern jmethodID insetsVisibleChangedID;
typedef struct {
+ int id;
+ int x;
+ int y;
+} XITouchPosition;
+
+#define XI_TOUCHCOORD_COUNT 10
+
+typedef struct {
Window window;
jobject jwindow;
Atom * allAtoms;
@@ -85,6 +94,9 @@ typedef struct {
Bool maxVert;
/** flag whether window is mapped */
Bool isMapped;
+ int xiOpcode;
+ int xiTouchDeviceId;
+ XITouchPosition xiTouchCoords[XI_TOUCHCOORD_COUNT];
} JavaWindow;
JavaWindow * getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlong javaObjectAtom, Bool showWarning);
diff --git a/src/newt/native/X11Display.c b/src/newt/native/X11Display.c
index 32e0f8786..1f3388fff 100644
--- a/src/newt/native/X11Display.c
+++ b/src/newt/native/X11Display.c
@@ -56,6 +56,7 @@ static jmethodID sendMouseEventRequestFocusID = NULL;
static jmethodID visibleChangedWindowRepaintID = NULL;
static jmethodID visibleChangedSendMouseEventID = NULL;
static jmethodID sizePosMaxInsetsVisibleChangedID = NULL;
+static jmethodID sendTouchScreenEventID = NULL;
/**
* Keycode
@@ -266,6 +267,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_initIDs0
sendMouseEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendMouseEvent", "(SIIISF)V");
sendMouseEventRequestFocusID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendMouseEventRequestFocus", "(SIIISF)V");
visibleChangedSendMouseEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "visibleChangedSendMouseEvent", "(ZISIIISF)V");
+ sendTouchScreenEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendTouchScreenEvent", "(SII[I[I[I[FF)V");
sendKeyEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendKeyEvent", "(SISSCLjava/lang/String;)V");
if (displayCompletedID == NULL ||
@@ -286,11 +288,11 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_initIDs0
sendMouseEventID == NULL ||
sendMouseEventRequestFocusID == NULL ||
visibleChangedSendMouseEventID == NULL ||
+ sendTouchScreenEventID == NULL ||
sendKeyEventID == NULL) {
return JNI_FALSE;
}
-
return JNI_TRUE;
}
@@ -385,6 +387,59 @@ static int NewtWindows_updateVisibility(JNIEnv *env, Display *dpy, JavaWindow *j
return visibleChange;
}
+static void sendTouchScreenEvent(JNIEnv *env, JavaWindow *jw,
+ short eventType, // MouseEvent.EVENT_MOUSE_PRESSED, MouseEvent.EVENT_MOUSE_RELEASED, MouseEvent.EVENT_MOUSE_MOVED
+ int modifiers, // 0!
+ int actionId) // index of multiple-pointer arrays representing the pointer which triggered the event
+{
+ jint pointerNames[XI_TOUCHCOORD_COUNT];
+ jint x[XI_TOUCHCOORD_COUNT];
+ jint y[XI_TOUCHCOORD_COUNT];
+ jfloat pressure[] = {1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f};
+ jint actionIdx = -1;
+ int i, cnt;
+
+ for(i = 0, cnt = 0; i < XI_TOUCHCOORD_COUNT; i++) {
+ if( -1 != jw->xiTouchCoords[i].id ) {
+ x[cnt] = jw->xiTouchCoords[i].x;
+ y[cnt] = jw->xiTouchCoords[i].y;
+ pointerNames[cnt] = jw->xiTouchCoords[i].id;
+ if (jw->xiTouchCoords[i].id == actionId) {
+ actionIdx = cnt;
+ }
+ cnt++;
+ }
+ }
+
+ jintArray jNames = (*env)->NewIntArray(env, cnt);
+ if (jNames == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array (names) of size %d", cnt);
+ }
+ (*env)->SetIntArrayRegion(env, jNames, 0, cnt, pointerNames);
+
+ jintArray jX = (*env)->NewIntArray(env, cnt);
+ if (jX == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array (x) of size %d", cnt);
+ }
+ (*env)->SetIntArrayRegion(env, jX, 0, cnt, x);
+
+ jintArray jY = (*env)->NewIntArray(env, cnt);
+ if (jY == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array (y) of size %d", cnt);
+ }
+ (*env)->SetIntArrayRegion(env, jY, 0, cnt, y);
+
+ jfloatArray jPressure = (*env)->NewFloatArray(env, cnt);
+ if (jPressure == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate float array (pressure) of size %d", cnt);
+ }
+ (*env)->SetFloatArrayRegion(env, jPressure, 0, cnt, pressure);
+
+ (*env)->CallVoidMethod(env, jw->jwindow, sendTouchScreenEventID,
+ (jshort)eventType, (jint)modifiers, (jint)actionIdx,
+ jNames, jX, jY, jPressure, (jfloat)1.0f);
+}
+
/*
* Class: jogamp_newt_driver_x11_DisplayDriver
* Method: DispatchMessages0
@@ -451,9 +506,10 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage
continue;
}
- // DBG_PRINT( "X11: DispatchMessages dpy %p, win %p, Event %d\n", (void*)dpy, (void*)evt.xany.window, (int)evt.type);
+ Window windowPointer = evt.xany.window;
+ // DBG_PRINT( "X11: DispatchMessages dpy %p, win %p, Event %d\n", (void*)dpy, (void*)windowPointer, (int)evt.type);
- jw = getJavaWindowProperty(env, dpy, evt.xany.window, javaObjectAtom,
+ jw = getJavaWindowProperty(env, dpy, windowPointer, javaObjectAtom,
#ifdef VERBOSE_ON
True
#else
@@ -462,10 +518,59 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage
);
if(NULL==jw) {
- 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);
+ fprintf(stderr, "Warning: NEWT X11 DisplayDispatch %p, Couldn't handle event %d for X11 window %p\n", (void*)dpy, evt.type, (void*)windowPointer);
continue;
}
-
+
+ XGenericEventCookie *cookie = &evt.xcookie; // hacks: https://keithp.com/blogs/Cursor_tracking/
+
+ if ( GenericEvent == cookie->type && jw->xiOpcode == cookie->extension && XGetEventData(dpy, cookie) ) {
+ // Valid registered XI Event w/ cookie data
+ // Here: https://www.x.org/wiki/Development/Documentation/Multitouch/
+ XIDeviceEvent *devev = cookie->data;
+ if( devev->event != windowPointer ) {
+ DBG_PRINT( "X11: DispatchMessages.XI dpy %p, win %p, Event %d: Event Window %p not matching\n", (void*)dpy, (void*)windowPointer, (int)evt.type, (void*)devev->event);
+ } else if( devev->deviceid != jw->xiTouchDeviceId) {
+ DBG_PRINT( "X11: DispatchMessages.XI dpy %p, win %p, Event %d: DeviceID not matching: Window %d, this %d\n", (void*)dpy, (void*)windowPointer, (int)evt.type, devev->deviceid, jw->xiTouchDeviceId);
+ } else {
+ int i;
+ switch (devev->evtype) {
+ case XI_TouchBegin:
+ for (i = 0; i < XI_TOUCHCOORD_COUNT; i++) {
+ if (jw->xiTouchCoords[i].id == -1) {
+ jw->xiTouchCoords[i].id = devev->detail % 32767;
+ jw->xiTouchCoords[i].x = devev->event_x;
+ jw->xiTouchCoords[i].y = devev->event_y;
+ break;
+ }
+ }
+ sendTouchScreenEvent(env, jw, EVENT_MOUSE_PRESSED, 0, devev->detail % 32767);
+ break;
+
+ case XI_TouchUpdate:
+ for (i = 0; i < XI_TOUCHCOORD_COUNT; i++) {
+ if (jw->xiTouchCoords[i].id == devev->detail % 32767) {
+ jw->xiTouchCoords[i].x = devev->event_x;
+ jw->xiTouchCoords[i].y = devev->event_y;
+ }
+ }
+ sendTouchScreenEvent(env, jw, EVENT_MOUSE_MOVED, 0, devev->detail % 32767);
+ break;
+
+ case XI_TouchEnd:
+ sendTouchScreenEvent(env, jw, EVENT_MOUSE_RELEASED, 0, devev->detail % 32767);
+ for (i = 0; i < XI_TOUCHCOORD_COUNT; i++) {
+ if (jw->xiTouchCoords[i].id == devev->detail % 32767) {
+ jw->xiTouchCoords[i].id = -1;
+ }
+ }
+ break;
+ }
+ }
+ XFreeEventData(dpy, cookie);
+ continue; // next event, skip evt.type below
+ }
+
switch(evt.type) {
case KeyRelease:
if (XEventsQueued(dpy, QueuedAfterReading)) {
diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c
index de2bddc86..8fb3ecbb9 100644
--- a/src/newt/native/X11Window.c
+++ b/src/newt/native/X11Window.c
@@ -952,6 +952,62 @@ JNIEXPORT jlongArray JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWind
NewtWindows_setMinMaxSize(dpy, javaWindow, width, height, width, height);
}
}
+
+ // Register X11 Multitouch Events for new Window
+ // https://www.x.org/wiki/Development/Documentation/Multitouch/
+ {
+ int xi_opcode, event, error;
+
+ javaWindow->xiTouchDeviceId = -1;
+
+ if( XQueryExtension(dpy, "XInputExtension", &xi_opcode, &event, &error) ) {
+ XIDeviceInfo *di;
+ int devid = -1;
+ int cnt = 0;
+
+ javaWindow->xiOpcode = xi_opcode;
+ di = XIQueryDevice(dpy, XIAllDevices, &cnt);
+
+ if( NULL != di && 0 < cnt ) {
+ XIDeviceInfo *dev;
+ int i, j;
+
+ // find the 1st XITouchClass device available
+ for (i = 0; i < cnt && -1 == devid; i ++) {
+ dev = &di[i];
+ for (j = 0; j < dev->num_classes; j ++) {
+ XITouchClassInfo *class = (XITouchClassInfo*)(dev->classes[j]);
+ if ( XITouchClass == class->type ) {
+ devid = dev->deviceid;
+ break;
+ }
+ }
+ }
+ XIFreeDeviceInfo(di);
+ di = NULL;
+
+ if( -1 != devid ) {
+ // register 1st XITouchClass device if available
+ XIEventMask mask = {
+ .deviceid = devid,
+ .mask_len = XIMaskLen(XI_TouchEnd) // in bytes
+ };
+
+ mask.mask = (unsigned char*)calloc(mask.mask_len, sizeof(unsigned char));
+ XISetMask(mask.mask, XI_TouchBegin);
+ XISetMask(mask.mask, XI_TouchUpdate);
+ XISetMask(mask.mask, XI_TouchEnd);
+
+ XISelectEvents(dpy, window, &mask, 1);
+
+ free(mask.mask);
+
+ javaWindow->xiTouchDeviceId = devid;
+ }
+ }
+ }
+ }
+
XFlush(dpy);
handles[0] = (jlong)(intptr_t)window;
handles[1] = (jlong)(intptr_t)javaWindow;