src/spacenav-lib-hack.c
branchv_0
changeset 2 3ba27504be0e
parent 1 ac5f3768ebb1
child 3 d8793f61ee43
equal deleted inserted replaced
1:ac5f3768ebb1 2:3ba27504be0e
    19 
    19 
    20 #include <stdio.h>
    20 #include <stdio.h>
    21 #include <stdint.h>
    21 #include <stdint.h>
    22 #include <dlfcn.h>
    22 #include <dlfcn.h>
    23 #include <stdlib.h>
    23 #include <stdlib.h>
    24 #include <pthread.h>
    24 #include <unistd.h>
    25 
    25 
    26 #include <X11/Xlib.h>
    26 #include <X11/Xlib.h>
    27 #include <spnav.h>
    27 #include <spnav.h>
    28 
       
    29 static Display* spacenav_hack_dpy;
       
    30 static Window spacenav_hack_win;
       
    31 
       
    32 static pthread_t spacenav_hack_thread;
       
    33 
    28 
    34 // from proto_x11.c (spacenavd)
    29 // from proto_x11.c (spacenavd)
    35 static Atom xa_event_motion, xa_event_bpress, xa_event_brelease, xa_event_cmd;
    30 static Atom xa_event_motion, xa_event_bpress, xa_event_brelease, xa_event_cmd;
    36 static float x11_sens = 1.0;
    31 static float x11_sens = 1.0;
       
    32 
       
    33 /* X11 error handler */
       
    34 static int xerr(Display *dpy, XErrorEvent *err) {
       
    35 	char buf[512];
       
    36 
       
    37 	fprintf(stderr, "xerr(%p, %p)\n", (void*) dpy, (void*) err);
       
    38 	if (err->error_code == BadWindow) {
       
    39 		fprintf(stderr, "BadWindow\n");
       
    40 	} else {
       
    41 		XGetErrorText(dpy, err->error_code, buf, sizeof buf);
       
    42 		fprintf(stderr, "Caught unexpected X error: %s\n", buf);
       
    43 	}
       
    44 	return 0;
       
    45 }
       
    46 
       
    47 /* X11 I/O error handler
       
    48  * This function must not return or xlib will abort.
       
    49  */
       
    50 static int xioerr(Display *display) {
       
    51 	fprintf(stderr, "Lost the X server!\n");
       
    52 	return 0;
       
    53 }
    37 
    54 
    38 /**
    55 /**
    39  * This function is based on proto_x11.c (spacenavd) written by:
    56  * This function is based on proto_x11.c (spacenavd) written by:
    40  * Copyright (C) 2007-2019 John Tsiombikas <nuclear@member.fsf.org>
    57  * Copyright (C) 2007-2019 John Tsiombikas <nuclear@member.fsf.org>
    41  * and published under GNU GPLv3+
    58  * and published under GNU GPLv3+
    78 
    95 
    79 		default:
    96 		default:
    80 			break;
    97 			break;
    81 	}
    98 	}
    82 
    99 
    83 	XSendEvent(dpy, win, False, 0, &xevent);
   100 	Window xxx;
    84 	XFlush(dpy);
   101 	int zzz;
    85 }
   102 	int yyy = XGetInputFocus(dpy, &xxx, &zzz);
    86 
   103 	fprintf(stderr, "spnav-lib-hack: XGetInputFocus(%p, %lx, %d) = %d\n", dpy, xxx, zzz, yyy);
    87 static void* spacenav_hack_translate_events(void* arg) {
   104 	Status result = XSendEvent(dpy, win, False, 0, &xevent);
    88 	pthread_setname_np(pthread_self(), "spacenav-hack"); // can be found with: ps H -o 'pid tid cmd comm'
   105 	int xflushResult = XFlush(dpy);
       
   106 	fprintf(stderr, "spnav-lib-hack: send_xevent(); XSendEvent() = %d; XFlush() = %d\n", result, xflushResult);
       
   107 }
       
   108 
       
   109 static void spacenav_hack_translate_events(Window win) {
    89 	spnav_event event;
   110 	spnav_event event;
       
   111 	Display* dpy = XOpenDisplay(0);
       
   112 	XSetErrorHandler(xerr);
       
   113 	XSetIOErrorHandler(xioerr);
       
   114 	fprintf(stderr, "Error handlers were set\n");
       
   115 
       
   116 	/*
       
   117 	xa_event_motion = XInternAtom(dpy, "MotionEvent", False);
       
   118 	xa_event_bpress = XInternAtom(dpy, "ButtonPressEvent", False);
       
   119 	xa_event_brelease = XInternAtom(dpy, "ButtonReleaseEvent", False);
       
   120 	xa_event_cmd = XInternAtom(dpy, "CommandEvent", False);
       
   121 	 */
       
   122 
       
   123 	fprintf(stderr, "spnav-lib-hack: xa_event_motion = %ld\n", xa_event_motion);
       
   124 	fprintf(stderr, "spnav-lib-hack: xa_event_bpress = %ld\n", xa_event_bpress);
       
   125 	fprintf(stderr, "spnav-lib-hack: xa_event_brelease = %ld\n", xa_event_brelease);
       
   126 	fprintf(stderr, "spnav-lib-hack: xa_event_cmd = %ld\n", xa_event_cmd);
       
   127 
    90 	while (1) {
   128 	while (1) {
    91 		if (spnav_wait_event(&event)) {
   129 		if (spnav_wait_event(&event)) {
    92 			//fprintf(stderr, "spnav-lib-hack: got event\n");
   130 			fprintf(stderr, "spnav-lib-hack: got event: PID=%d dpy=%p win=%lx\n", getpid(), dpy, win);
    93 			XLockDisplay(spacenav_hack_dpy);
   131 			//XLockDisplay(dpy);
    94 			send_xevent(&event, spacenav_hack_dpy, spacenav_hack_win);
   132 			send_xevent(&event, dpy, win);
    95 			XUnlockDisplay(spacenav_hack_dpy);
   133 			//XUnlockDisplay(dpy);
    96 		}
   134 		}
    97 	}
   135 	}
    98 }
   136 }
    99 
   137 
   100 int spnav_x11_open(Display* dpy, Window win) {
   138 int spnav_x11_open(Display* dpy, Window win) {
   101 	spacenav_hack_dpy = dpy;
       
   102 	spacenav_hack_win = win;
       
   103 
       
   104 	int result = spnav_open();
   139 	int result = spnav_open();
   105 	fprintf(stderr, "spnav-lib-hack: instead of spnav_x11_open(%p, 0x%lx) calling spnav_open() = %d\n", dpy, win, result);
   140 	fprintf(stderr, "spnav-lib-hack: instead of spnav_x11_open(%p, 0x%lx) calling spnav_open() = %d\n", dpy, win, result);
   106 
   141 
       
   142 	xa_event_motion = XInternAtom(dpy, "MotionEvent", False);
       
   143 	xa_event_bpress = XInternAtom(dpy, "ButtonPressEvent", False);
       
   144 	xa_event_brelease = XInternAtom(dpy, "ButtonReleaseEvent", False);
       
   145 	xa_event_cmd = XInternAtom(dpy, "CommandEvent", False);
       
   146 
   107 	if (result == 0) {
   147 	if (result == 0) {
   108 		xa_event_motion = XInternAtom(dpy, "MotionEvent", False);
   148 		pid_t pid = fork();
   109 		xa_event_bpress = XInternAtom(dpy, "ButtonPressEvent", False);
   149 		fprintf(stderr, "spnav-lib-hack: fork() = %d; PID=%d\n", pid, getpid());
   110 		xa_event_brelease = XInternAtom(dpy, "ButtonReleaseEvent", False);
   150 		if (pid == -1) return 1;
   111 		xa_event_cmd = XInternAtom(dpy, "CommandEvent", False);
   151 		if (pid == 0) spacenav_hack_translate_events(win);
   112 		
   152 	}
   113 		XInitThreads();
   153 
   114 		pthread_create(&spacenav_hack_thread, NULL, spacenav_hack_translate_events, NULL);
   154 	return result;
   115 	}
   155 }
   116 
   156 
   117 	return result;
   157 /**
   118 }
   158  * This function is based on proto_x11.c (spacenavd) written by:
   119 
   159  * Copyright (C) 2007-2019 John Tsiombikas <nuclear@member.fsf.org>
   120 
   160  * and published under GNU GPLv3+
   121 
   161  * 
   122 /*
   162  * @param dpy
       
   163  * @param win
       
   164  * @return 
       
   165  */
   123 int spnav_x11_event(const XEvent* xev, spnav_event* event) {
   166 int spnav_x11_event(const XEvent* xev, spnav_event* event) {
   124 	xev.
   167 	/*
       
   168 	 * Because real spnav_x11_open() was not called, the library has not initialized xa_event_*
       
   169 	 * variables and thus will return 0 (= not a spacenav event).
       
   170 	 */
       
   171 
       
   172 	int i;
       
   173 	int xmsg_type;
       
   174 
       
   175 	if (xev->type != ClientMessage) {
       
   176 		return 0;
       
   177 	}
       
   178 
       
   179 	xmsg_type = xev->xclient.message_type;
       
   180 
       
   181 	if (xmsg_type != xa_event_motion && xmsg_type != xa_event_bpress &&
       
   182 			xmsg_type != xa_event_brelease) {
       
   183 		return 0;
       
   184 	}
       
   185 
       
   186 	if (xmsg_type == xa_event_motion) {
       
   187 		event->type = SPNAV_EVENT_MOTION;
       
   188 		event->motion.data = &event->motion.x;
       
   189 
       
   190 		for (i = 0; i < 6; i++) {
       
   191 			event->motion.data[i] = xev->xclient.data.s[i + 2];
       
   192 		}
       
   193 		event->motion.period = xev->xclient.data.s[8];
       
   194 	} else {
       
   195 		event->type = SPNAV_EVENT_BUTTON;
       
   196 		event->button.press = xmsg_type == xa_event_bpress ? 1 : 0;
       
   197 		event->button.bnum = xev->xclient.data.s[2];
       
   198 	}
       
   199 	return event->type;
       
   200 
       
   201 	/*
   125 	static int (*real_spnav_x11_event)(const XEvent*, spnav_event*) = NULL;
   202 	static int (*real_spnav_x11_event)(const XEvent*, spnav_event*) = NULL;
   126 	if (!real_spnav_x11_event) real_spnav_x11_event = dlsym(RTLD_NEXT, "spnav_x11_event");
   203 	if (!real_spnav_x11_event) real_spnav_x11_event = dlsym(RTLD_NEXT, "spnav_x11_event");
   127 	int result = real_spnav_x11_event(xev, event);
   204 	int result = real_spnav_x11_event(xev, event);
   128 	if (result == SPNAV_EVENT_MOTION || result == SPNAV_EVENT_BUTTON) fprintf(stderr, "spnav-lib-hack: spnav_x11_event() = %d\n", result);
   205 	if (result == SPNAV_EVENT_MOTION || result == SPNAV_EVENT_BUTTON) fprintf(stderr, "spnav-lib-hack: spnav_x11_event() = %d\n", result);
   129 	return result;
   206 	return result;
   130 }
   207 	 */
   131  */
   208 }
   132 
   209 
   133 
   210 
   134 /*
   211 /*
   135 int spnav_x11_open(Display* dpy, Window win) {
   212 int spnav_x11_open(Display* dpy, Window win) {
   136 	static int (*real_spnav_x11_open)(Display*, Window) = NULL;
   213 	static int (*real_spnav_x11_open)(Display*, Window) = NULL;