--- 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;
+ */
}
- */
/*