very hackish and… working v_0
authorFrantišek Kučera <franta-hg@frantovo.cz>
Fri, 08 Mar 2019 22:38:58 +0100
branchv_0
changeset 2 3ba27504be0e
parent 1 ac5f3768ebb1
child 3 d8793f61ee43
very hackish and… working
nbproject/project.xml
src/spacenav-lib-hack.c
--- a/nbproject/project.xml	Fri Mar 08 20:11:23 2019 +0100
+++ b/nbproject/project.xml	Fri Mar 08 22:38:58 2019 +0100
@@ -44,7 +44,7 @@
         <data xmlns="http://www.netbeans.org/ns/make-project/1">
             <name>spacenav-lib-hack</name>
             <c-extensions>c</c-extensions>
-            <cpp-extensions>cpp</cpp-extensions>
+            <cpp-extensions>cpp,cxx</cpp-extensions>
             <header-extensions>h</header-extensions>
             <sourceEncoding>UTF-8</sourceEncoding>
             <sourceRootList>
--- a/src/spacenav-lib-hack.c	Fri Mar 08 20:11:23 2019 +0100
+++ b/src/spacenav-lib-hack.c	Fri Mar 08 22:38:58 2019 +0100
@@ -21,20 +21,37 @@
 #include <stdint.h>
 #include <dlfcn.h>
 #include <stdlib.h>
-#include <pthread.h>
+#include <unistd.h>
 
 #include <X11/Xlib.h>
 #include <spnav.h>
 
-static Display* spacenav_hack_dpy;
-static Window spacenav_hack_win;
-
-static pthread_t spacenav_hack_thread;
-
 // from proto_x11.c (spacenavd)
 static Atom xa_event_motion, xa_event_bpress, xa_event_brelease, xa_event_cmd;
 static float x11_sens = 1.0;
 
+/* X11 error handler */
+static int xerr(Display *dpy, XErrorEvent *err) {
+	char buf[512];
+
+	fprintf(stderr, "xerr(%p, %p)\n", (void*) dpy, (void*) err);
+	if (err->error_code == BadWindow) {
+		fprintf(stderr, "BadWindow\n");
+	} else {
+		XGetErrorText(dpy, err->error_code, buf, sizeof buf);
+		fprintf(stderr, "Caught unexpected X error: %s\n", buf);
+	}
+	return 0;
+}
+
+/* X11 I/O error handler
+ * This function must not return or xlib will abort.
+ */
+static int xioerr(Display *display) {
+	fprintf(stderr, "Lost the X server!\n");
+	return 0;
+}
+
 /**
  * This function is based on proto_x11.c (spacenavd) written by:
  * Copyright (C) 2007-2019 John Tsiombikas <nuclear@member.fsf.org>
@@ -80,55 +97,115 @@
 			break;
 	}
 
-	XSendEvent(dpy, win, False, 0, &xevent);
-	XFlush(dpy);
+	Window xxx;
+	int zzz;
+	int yyy = XGetInputFocus(dpy, &xxx, &zzz);
+	fprintf(stderr, "spnav-lib-hack: XGetInputFocus(%p, %lx, %d) = %d\n", dpy, xxx, zzz, yyy);
+	Status result = XSendEvent(dpy, win, False, 0, &xevent);
+	int xflushResult = XFlush(dpy);
+	fprintf(stderr, "spnav-lib-hack: send_xevent(); XSendEvent() = %d; XFlush() = %d\n", result, xflushResult);
 }
 
-static void* spacenav_hack_translate_events(void* arg) {
-	pthread_setname_np(pthread_self(), "spacenav-hack"); // can be found with: ps H -o 'pid tid cmd comm'
+static void spacenav_hack_translate_events(Window win) {
 	spnav_event event;
+	Display* dpy = XOpenDisplay(0);
+	XSetErrorHandler(xerr);
+	XSetIOErrorHandler(xioerr);
+	fprintf(stderr, "Error handlers were set\n");
+
+	/*
+	xa_event_motion = XInternAtom(dpy, "MotionEvent", False);
+	xa_event_bpress = XInternAtom(dpy, "ButtonPressEvent", False);
+	xa_event_brelease = XInternAtom(dpy, "ButtonReleaseEvent", False);
+	xa_event_cmd = XInternAtom(dpy, "CommandEvent", False);
+	 */
+
+	fprintf(stderr, "spnav-lib-hack: xa_event_motion = %ld\n", xa_event_motion);
+	fprintf(stderr, "spnav-lib-hack: xa_event_bpress = %ld\n", xa_event_bpress);
+	fprintf(stderr, "spnav-lib-hack: xa_event_brelease = %ld\n", xa_event_brelease);
+	fprintf(stderr, "spnav-lib-hack: xa_event_cmd = %ld\n", xa_event_cmd);
+
 	while (1) {
 		if (spnav_wait_event(&event)) {
-			//fprintf(stderr, "spnav-lib-hack: got event\n");
-			XLockDisplay(spacenav_hack_dpy);
-			send_xevent(&event, spacenav_hack_dpy, spacenav_hack_win);
-			XUnlockDisplay(spacenav_hack_dpy);
+			fprintf(stderr, "spnav-lib-hack: got event: PID=%d dpy=%p win=%lx\n", getpid(), dpy, win);
+			//XLockDisplay(dpy);
+			send_xevent(&event, dpy, win);
+			//XUnlockDisplay(dpy);
 		}
 	}
 }
 
 int spnav_x11_open(Display* dpy, Window win) {
-	spacenav_hack_dpy = dpy;
-	spacenav_hack_win = win;
-
 	int result = spnav_open();
 	fprintf(stderr, "spnav-lib-hack: instead of spnav_x11_open(%p, 0x%lx) calling spnav_open() = %d\n", dpy, win, result);
 
+	xa_event_motion = XInternAtom(dpy, "MotionEvent", False);
+	xa_event_bpress = XInternAtom(dpy, "ButtonPressEvent", False);
+	xa_event_brelease = XInternAtom(dpy, "ButtonReleaseEvent", False);
+	xa_event_cmd = XInternAtom(dpy, "CommandEvent", False);
+
 	if (result == 0) {
-		xa_event_motion = XInternAtom(dpy, "MotionEvent", False);
-		xa_event_bpress = XInternAtom(dpy, "ButtonPressEvent", False);
-		xa_event_brelease = XInternAtom(dpy, "ButtonReleaseEvent", False);
-		xa_event_cmd = XInternAtom(dpy, "CommandEvent", False);
-		
-		XInitThreads();
-		pthread_create(&spacenav_hack_thread, NULL, spacenav_hack_translate_events, NULL);
+		pid_t pid = fork();
+		fprintf(stderr, "spnav-lib-hack: fork() = %d; PID=%d\n", pid, getpid());
+		if (pid == -1) return 1;
+		if (pid == 0) spacenav_hack_translate_events(win);
 	}
 
 	return result;
 }
 
+/**
+ * This function is based on proto_x11.c (spacenavd) written by:
+ * Copyright (C) 2007-2019 John Tsiombikas <nuclear@member.fsf.org>
+ * and published under GNU GPLv3+
+ * 
+ * @param dpy
+ * @param win
+ * @return 
+ */
+int spnav_x11_event(const XEvent* xev, spnav_event* event) {
+	/*
+	 * Because real spnav_x11_open() was not called, the library has not initialized xa_event_*
+	 * variables and thus will return 0 (= not a spacenav event).
+	 */
 
+	int i;
+	int xmsg_type;
+
+	if (xev->type != ClientMessage) {
+		return 0;
+	}
 
-/*
-int spnav_x11_event(const XEvent* xev, spnav_event* event) {
-	xev.
+	xmsg_type = xev->xclient.message_type;
+
+	if (xmsg_type != xa_event_motion && xmsg_type != xa_event_bpress &&
+			xmsg_type != xa_event_brelease) {
+		return 0;
+	}
+
+	if (xmsg_type == xa_event_motion) {
+		event->type = SPNAV_EVENT_MOTION;
+		event->motion.data = &event->motion.x;
+
+		for (i = 0; i < 6; i++) {
+			event->motion.data[i] = xev->xclient.data.s[i + 2];
+		}
+		event->motion.period = xev->xclient.data.s[8];
+	} else {
+		event->type = SPNAV_EVENT_BUTTON;
+		event->button.press = xmsg_type == xa_event_bpress ? 1 : 0;
+		event->button.bnum = xev->xclient.data.s[2];
+	}
+	return event->type;
+
+	/*
 	static int (*real_spnav_x11_event)(const XEvent*, spnav_event*) = NULL;
 	if (!real_spnav_x11_event) real_spnav_x11_event = dlsym(RTLD_NEXT, "spnav_x11_event");
 	int result = real_spnav_x11_event(xev, event);
 	if (result == SPNAV_EVENT_MOTION || result == SPNAV_EVENT_BUTTON) fprintf(stderr, "spnav-lib-hack: spnav_x11_event() = %d\n", result);
 	return result;
+	 */
 }
- */
 
 
 /*