summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2019-03-27 03:10:41 +0100
committerSven Gothel <[email protected]>2019-03-27 03:10:41 +0100
commit746383476aa449e9cab4a25df27be85b61aa074b (patch)
tree8f5d54b10abd6fbc23b8b82011b4a24bb16c7d21 /src
parent92006e4baef57f1f3fb647dd307aed5989fd4c8d (diff)
Bug 1348: X11 XI Multitouch: Fixes of previous commit 92006e4baef57f1f3fb647dd307aed5989fd4c8d
Previous commit 92006e4baef57f1f3fb647dd307aed5989fd4c8d (Note to Danny: I cannot test this now - please re-test and/or review) X11Common::JavaWindow - Owns XI extension's xiOpcode, selected xiTouchDeviceId and tracked XITouchPosition array X11Window::CreateWindow - Query XI extension only once @ window creation and earmark xiOpcode in JavaWindow instance - Fix: Device selection code was "class->type != XITouchClass", but shouldn't it be 'XITouchClass == class->type' (as patched here) - Fix: Free XIQueryDevice returned XIDeviceInfo array via XIFreeDeviceInfo - Earmark deviceid in JavaWindow instance X11Display - Moved global static touch_coordinates to JavaWindow::xiTouchCoords instance X11Display::DispatchMessage - Changed event handling structure similar to https://keithp.com/blogs/Cursor_tracking/ - Fix: Free XGetEventData's optional memory allocation via XFreeEventData - Reuse JavaWindow's queried xiOpcode - Fix: Don't overrise windowPointer, instead validate and require a match. JavaWindow must match! - Fix: Also validate chosen deviceid with JavaWindow's registered device Newt Build: - Added libXi in build recipe and doc
Diffstat (limited to 'src')
-rw-r--r--src/newt/native/X11Common.h11
-rw-r--r--src/newt/native/X11Display.c166
-rw-r--r--src/newt/native/X11Window.c86
3 files changed, 120 insertions, 143 deletions
diff --git a/src/newt/native/X11Common.h b/src/newt/native/X11Common.h
index 78fa18cc8..99795b6e8 100644
--- a/src/newt/native/X11Common.h
+++ b/src/newt/native/X11Common.h
@@ -75,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;
@@ -86,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 effc488f9..1f3388fff 100644
--- a/src/newt/native/X11Display.c
+++ b/src/newt/native/X11Display.c
@@ -58,12 +58,6 @@ static jmethodID visibleChangedSendMouseEventID = NULL;
static jmethodID sizePosMaxInsetsVisibleChangedID = NULL;
static jmethodID sendTouchScreenEventID = NULL;
-struct touchPosition {
- int touch_id;
- int x;
- int y;
-};
-
/**
* Keycode
*/
@@ -226,8 +220,6 @@ static jint X11InputState2NewtModifiers(unsigned int xstate, jshort javaVKey, jb
}
-static struct touchPosition touch_coordinates[10];
-
/**
* Keycode
*/
@@ -275,8 +267,8 @@ 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");
- sendKeyEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendKeyEvent", "(SISSCLjava/lang/String;)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 ||
sendRRScreenChangeNotifyID == NULL ||
@@ -301,8 +293,6 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_initIDs0
return JNI_FALSE;
}
- memset(touch_coordinates, -1, sizeof(touch_coordinates));
-
return JNI_TRUE;
}
@@ -397,28 +387,24 @@ static int NewtWindows_updateVisibility(JNIEnv *env, Display *dpy, JavaWindow *j
return visibleChange;
}
-void sendTouchScreenEvent(JNIEnv *env, jobject window,
+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 cnt = 0;
- jint pointerNames[10];
- jint x[10];
- jint y[10];
- jfloat pressure[] = {1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f};
+ 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 = 0;
-
- for(i = 0; i < 10; i++)
- {
- if(touch_coordinates[i].touch_id != -1)
- {
- x[cnt] = touch_coordinates[i].x;
- y[cnt] = touch_coordinates[i].y;
- pointerNames[cnt] = touch_coordinates[i].touch_id;
- if (touch_coordinates[i].touch_id == actionId)
- {
+ 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++;
@@ -449,10 +435,9 @@ void sendTouchScreenEvent(JNIEnv *env, jobject window,
}
(*env)->SetFloatArrayRegion(env, jPressure, 0, cnt, pressure);
- (*env)->CallVoidMethod(env, window, sendTouchScreenEventID,
+ (*env)->CallVoidMethod(env, jw->jwindow, sendTouchScreenEventID,
(jshort)eventType, (jint)modifiers, (jint)actionIdx,
jNames, jX, jY, jPressure, (jfloat)1.0f);
-
}
/*
@@ -521,36 +506,9 @@ 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);
-
- int isXInputExtensionEvent = 0;
- XGenericEventCookie *cookie = &evt.xcookie; // hacks!
- XIDeviceEvent *devev;
-
-
- if (XGetEventData(dpy, cookie)) // extended event
- {
- int xi_opcode;
- int ev;
- int err;
- XQueryExtension(dpy, "XInputExtension", &xi_opcode, &ev, &err);
-
- // check if this belongs to XInput
- if (cookie->type == GenericEvent
- && cookie->extension == xi_opcode) {
- static int last = -1;
-
- devev = cookie->data;
- windowPointer = devev->event;
- isXInputExtensionEvent = 1;
-
- }
- }
-
-
jw = getJavaWindowProperty(env, dpy, windowPointer, javaObjectAtom,
#ifdef VERBOSE_ON
True
@@ -564,59 +522,55 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage
continue;
}
- if (isXInputExtensionEvent) {
- int i;
-
- switch (devev->evtype) {
- case XI_TouchBegin:
-
- for (i = 0; i < 10; i++)
- {
- if (touch_coordinates[i].touch_id == -1)
- {
- touch_coordinates[i].touch_id = devev->detail % 32767;
- touch_coordinates[i].x = devev->event_x;
- touch_coordinates[i].y = devev->event_y;
- break;
+ 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->jwindow, EVENT_MOUSE_PRESSED,
- 0, devev->detail % 32767);
-
- break;
- case XI_TouchUpdate:
-
- for (i = 0; i < 10; i++)
- {
- if (touch_coordinates[i].touch_id == devev->detail % 32767)
- {
- touch_coordinates[i].x = devev->event_x;
- touch_coordinates[i].y = devev->event_y;
+ 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->jwindow, EVENT_MOUSE_MOVED, 0,
- devev->detail % 32767);
-
- break;
- case XI_TouchEnd:
-
- sendTouchScreenEvent(env, jw->jwindow, EVENT_MOUSE_RELEASED,
- 0, devev->detail % 32767);
-
- for (i = 0; i < 10; i++)
- {
- if (touch_coordinates[i].touch_id == devev->detail % 32767)
- {
- touch_coordinates[i].touch_id = -1;
+ 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;
-
- continue;
+ 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 7208b205a..8fb3ecbb9 100644
--- a/src/newt/native/X11Window.c
+++ b/src/newt/native/X11Window.c
@@ -953,47 +953,59 @@ JNIEXPORT jlongArray JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWind
}
}
+ // Register X11 Multitouch Events for new Window
+ // https://www.x.org/wiki/Development/Documentation/Multitouch/
{
- XIDeviceInfo *di;
- XIDeviceInfo *dev;
- XITouchClassInfo *class;
- int devid = -1;
+ 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;
- int cnt;
- int i, j;
-
- di = XIQueryDevice(dpy, XIAllDevices, &cnt);
- for (i = 0; i < cnt; i ++)
- {
- dev = &di[i];
- for (j = 0; j < dev->num_classes; j ++)
- {
- class = (XITouchClassInfo*)(dev->classes[j]);
- if (class->type != XITouchClass)
- {
- devid = dev->deviceid;
- break;
- }
- }
- if(devid != -1)
- {
- break;
- }
- }
+ // 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);
- XIEventMask mask = {
- .deviceid = devid, //XIAllDevices,
- .mask_len = XIMaskLen(XI_TouchEnd)
- };
+ XISelectEvents(dpy, window, &mask, 1);
- mask.mask = (unsigned char*)calloc(3, sizeof(char));
- XISetMask(mask.mask, XI_TouchBegin);
- XISetMask(mask.mask, XI_TouchUpdate);
- XISetMask(mask.mask, XI_TouchEnd);
-
- XISelectEvents(dpy, window, &mask, 1);
-
- free(mask.mask);
+ free(mask.mask);
+
+ javaWindow->xiTouchDeviceId = devid;
+ }
+ }
+ }
}
XFlush(dpy);