kopia lustrzana https://github.com/FreeSpacenav/spacenavd
				
				
				
			- Fixed a bug where the daemon would quit if the X server is stopped.
- Alleviated the need for XSync in xsend_event. Now XFlush suffices. - Added separate sensitivity options for rotation and translation. - Added option to swap Y and Z translation axes. git-svn-id: svn+ssh://svn.code.sf.net/p/spacenav/code/trunk/spacenavd@96 ef983eb1-d774-4af8-acfd-baaf7b16a646pull/1/head
							rodzic
							
								
									f6a10f2786
								
							
						
					
					
						commit
						cd5312cd39
					
				|  | @ -16,7 +16,6 @@ You should have received a copy of the GNU General Public License | |||
| along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||||
| */ | ||||
| 
 | ||||
| #include "config.h" | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
|  | @ -27,19 +26,20 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>. | |||
| 
 | ||||
| enum {TX, TY, TZ, RX, RY, RZ}; | ||||
| 
 | ||||
| static const int def_axmap[] = {0, 2, 1, 3, 5, 4}; | ||||
| static const int def_axinv[] = {0, 1, 1, 0, 1, 1}; | ||||
| 
 | ||||
| void default_cfg(struct cfg *cfg) | ||||
| { | ||||
| 	int i; | ||||
| 	static const int axmap[] = {0, 2, 1, 3, 5, 4}; | ||||
| 	static const int axinv[] = {0, 1, 1, 0, 1, 1}; | ||||
| 
 | ||||
| 	cfg->sensitivity = 1.0; | ||||
| 	cfg->sensitivity = cfg->sens_trans = cfg->sens_rot = 1.0; | ||||
| 	cfg->dead_threshold = 2; | ||||
| 	cfg->led = 1; | ||||
| 
 | ||||
| 	for(i=0; i<6; i++) { | ||||
| 		cfg->invert[i] = axinv[i]; | ||||
| 		cfg->map_axis[i] = axmap[i]; | ||||
| 		cfg->invert[i] = def_axinv[i]; | ||||
| 		cfg->map_axis[i] = def_axmap[i]; | ||||
| 	} | ||||
| 
 | ||||
| 	for(i=0; i<MAX_BUTTONS; i++) { | ||||
|  | @ -100,6 +100,20 @@ int read_cfg(const char *fname, struct cfg *cfg) | |||
| 			} | ||||
| 			cfg->sensitivity = atof(val_str); | ||||
| 
 | ||||
| 		} else if(strcmp(key_str, "sensitivity-translation") == 0) { | ||||
| 			if(!isnum) { | ||||
| 				fprintf(stderr, "invalid configuration value for %s, expected a number.\n", key_str); | ||||
| 				continue; | ||||
| 			} | ||||
| 			cfg->sens_trans = atof(val_str); | ||||
| 
 | ||||
| 		} else if(strcmp(key_str, "sensitivity-rotation") == 0) { | ||||
| 			if(!isnum) { | ||||
| 				fprintf(stderr, "invalid configuration value for %s, expected a number.\n", key_str); | ||||
| 				continue; | ||||
| 			} | ||||
| 			cfg->sens_rot = atof(val_str); | ||||
| 
 | ||||
| 		} else if(strcmp(key_str, "invert-rot") == 0) { | ||||
| 			if(strchr(val_str, 'x')) { | ||||
| 				cfg->invert[RX] = !cfg->invert[RX]; | ||||
|  | @ -122,6 +136,30 @@ int read_cfg(const char *fname, struct cfg *cfg) | |||
| 				cfg->invert[TZ] = !cfg->invert[TZ]; | ||||
| 			} | ||||
| 
 | ||||
| 		} else if(strcmp(key_str, "swap-yz") == 0) { | ||||
| 			int i, swap_yz = 0; | ||||
| 
 | ||||
| 			if(isnum) { | ||||
| 				swap_yz = atoi(val_str); | ||||
| 			} else { | ||||
| 				if(strcmp(val_str, "true") == 0 || strcmp(val_str, "on") == 0 || strcmp(val_str, "yes") == 0) { | ||||
| 					swap_yz = 1; | ||||
| 				} else if(strcmp(val_str, "false") == 0 || strcmp(val_str, "off") == 0 || strcmp(val_str, "no") == 0) { | ||||
| 					swap_yz = 0; | ||||
| 				} else { | ||||
| 					fprintf(stderr, "invalid configuration value for %s, expected a boolean value.\n", key_str); | ||||
| 					continue; | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			for(i=0; i<6; i++) { | ||||
| 				if(swap_yz) { | ||||
| 					cfg->map_axis[i] = i; | ||||
| 				} else { | ||||
| 					cfg->map_axis[i] = def_axmap[i]; | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 		} else if(strcmp(key_str, "led") == 0) { | ||||
| 			if(isnum) { | ||||
| 				cfg->led = atoi(val_str); | ||||
|  | @ -170,27 +208,34 @@ int write_cfg(const char *fname, struct cfg *cfg) | |||
| 	fprintf(fp, "# sensitivity is multiplied with every motion (1.0 normal).\n"); | ||||
| 	fprintf(fp, "sensitivity = %.3f\n\n", cfg->sensitivity); | ||||
| 
 | ||||
| 	fprintf(fp, "# separate sensitivity for rotation and translation.\n"); | ||||
| 	fprintf(fp, "sensitivity-translation = %.3f\n", cfg->sens_trans); | ||||
| 	fprintf(fp, "sensitivity-rotation = %.3f\n\n", cfg->sens_rot); | ||||
| 
 | ||||
| 	fprintf(fp, "# dead zone; any motion less than this number, is discarded as noise.\n"); | ||||
| 	fprintf(fp, "dead-zone = %d\n\n", cfg->dead_threshold); | ||||
| 
 | ||||
| 	if(cfg->invert[0] || cfg->invert[1] || cfg->invert[2]) { | ||||
| 		fprintf(fp, "# invert translations on some axes.\n"); | ||||
| 		fprintf(fp, "invert-trans = "); | ||||
| 		if(cfg->invert[0]) fputc('x', fp); | ||||
| 		if(cfg->invert[1]) fputc('y', fp); | ||||
| 		if(cfg->invert[2]) fputc('z', fp); | ||||
| 		if(cfg->invert[0] != def_axinv[0]) fputc('x', fp); | ||||
| 		if(cfg->invert[1] != def_axinv[1]) fputc('y', fp); | ||||
| 		if(cfg->invert[2] != def_axinv[2]) fputc('z', fp); | ||||
| 		fputs("\n\n", fp); | ||||
| 	} | ||||
| 
 | ||||
| 	if(cfg->invert[3] || cfg->invert[4] || cfg->invert[5]) { | ||||
| 		fprintf(fp, "# invert rotations around some axes.\n"); | ||||
| 		fprintf(fp, "invert-rot = "); | ||||
| 		if(cfg->invert[3]) fputc('x', fp); | ||||
| 		if(cfg->invert[4]) fputc('y', fp); | ||||
| 		if(cfg->invert[5]) fputc('z', fp); | ||||
| 		if(cfg->invert[3] != def_axinv[3]) fputc('x', fp); | ||||
| 		if(cfg->invert[4] != def_axinv[4]) fputc('y', fp); | ||||
| 		if(cfg->invert[5] != def_axinv[5]) fputc('z', fp); | ||||
| 		fputs("\n\n", fp); | ||||
| 	} | ||||
| 
 | ||||
| 	fprintf(fp, "# swap translation along Y and Z axes\n"); | ||||
| 	fprintf(fp, "swap-yz = %s\n\n", cfg->map_axis[1] == def_axmap[1] ? "false" : "true"); | ||||
| 
 | ||||
| 	if(!cfg->led) { | ||||
| 		fprintf(fp, "# disable led\n"); | ||||
| 		fprintf(fp, "led = 0\n\n"); | ||||
|  |  | |||
|  | @ -19,12 +19,10 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>. | |||
| #ifndef CFGFILE_H_ | ||||
| #define CFGFILE_H_ | ||||
| 
 | ||||
| #include "config.h" | ||||
| 
 | ||||
| #define MAX_BUTTONS		64 | ||||
| 
 | ||||
| struct cfg { | ||||
| 	float sensitivity; | ||||
| 	float sensitivity, sens_trans, sens_rot; | ||||
| 	int dead_threshold; | ||||
| 	int invert[6]; | ||||
| 	int map_axis[6]; | ||||
|  |  | |||
|  | @ -55,9 +55,7 @@ void process_input(struct dev_input *inp) | |||
| 		inp->idx = cfg.map_axis[inp->idx]; | ||||
| 		sign = cfg.invert[inp->idx] ? -1 : 1; | ||||
| 
 | ||||
| 		if(cfg.sensitivity != 1.0) { | ||||
| 			inp->val = (int)((float)inp->val * cfg.sensitivity); | ||||
| 		} | ||||
| 		inp->val = (int)((float)inp->val * cfg.sensitivity * (inp->idx < 3 ? cfg.sens_trans : cfg.sens_rot)); | ||||
| 
 | ||||
| 		ev.type = EVENT_MOTION; | ||||
| 		ev.motion.data = (int*)&ev.motion.x; | ||||
|  | @ -71,7 +69,7 @@ void process_input(struct dev_input *inp) | |||
| 			ev_pending = 0; | ||||
| 		} | ||||
| 		inp->idx = cfg.map_button[inp->idx]; | ||||
| 		 | ||||
| 
 | ||||
| 		ev.type = EVENT_BUTTON; | ||||
| 		ev.button.press = inp->val; | ||||
| 		ev.button.bnum = inp->idx; | ||||
|  |  | |||
|  | @ -21,6 +21,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>. | |||
| #ifdef USE_X11 | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <setjmp.h> | ||||
| #include "proto_x11.h" | ||||
| #include "client.h" | ||||
| #include "spnavd.h" | ||||
|  | @ -34,7 +35,8 @@ enum cmd_msg { | |||
| }; | ||||
| 
 | ||||
| 
 | ||||
| static int catch_badwin(Display *dpy, XErrorEvent *err); | ||||
| static int xerr(Display *dpy, XErrorEvent *err); | ||||
| static int xioerr(Display *dpy); | ||||
| 
 | ||||
| static Display *dpy; | ||||
| static Window win; | ||||
|  | @ -47,6 +49,8 @@ static Atom xa_event_motion, xa_event_bpress, xa_event_brelease, xa_event_cmd; | |||
|  */ | ||||
| static float x11_sens = 1.0; | ||||
| 
 | ||||
| static jmp_buf jbuf; | ||||
| 
 | ||||
| 
 | ||||
| int init_x11(void) | ||||
| { | ||||
|  | @ -77,6 +81,14 @@ int init_x11(void) | |||
| 		xdet_start(); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	XSetErrorHandler(xerr); | ||||
| 	XSetIOErrorHandler(xioerr); | ||||
| 
 | ||||
| 	if(setjmp(jbuf)) { | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	scr_count = ScreenCount(dpy); | ||||
| 	screen = DefaultScreen(dpy); | ||||
| 	root = RootWindow(dpy, screen); | ||||
|  | @ -127,23 +139,23 @@ void close_x11(void) | |||
| 	int i, scr_count; | ||||
| 	struct client *cnode; | ||||
| 
 | ||||
| 	if(!dpy) return; | ||||
| 	if(dpy && setjmp(jbuf) == 0) { | ||||
| 		if(verbose) { | ||||
| 			printf("closing X11 connection to display \"%s\"\n", getenv("DISPLAY")); | ||||
| 		} | ||||
| 
 | ||||
| 	if(verbose) { | ||||
| 		printf("closing X11 connection to display \"%s\"\n", getenv("DISPLAY")); | ||||
| 		/* first delete all the CommandEvent properties from all root windows */ | ||||
| 		scr_count = ScreenCount(dpy); | ||||
| 		for(i=0; i<scr_count; i++) { | ||||
| 			Window root = RootWindow(dpy, i); | ||||
| 			XDeleteProperty(dpy, root, xa_event_cmd); | ||||
| 		} | ||||
| 
 | ||||
| 		XDestroyWindow(dpy, win); | ||||
| 		XCloseDisplay(dpy); | ||||
| 		dpy = 0; | ||||
| 	} | ||||
| 
 | ||||
| 	/* first delete all the CommandEvent properties from all root windows */ | ||||
| 	scr_count = ScreenCount(dpy); | ||||
| 	for(i=0; i<scr_count; i++) { | ||||
| 		Window root = RootWindow(dpy, i); | ||||
| 		XDeleteProperty(dpy, root, xa_event_cmd); | ||||
| 	} | ||||
| 
 | ||||
| 	XDestroyWindow(dpy, win); | ||||
| 	XCloseDisplay(dpy); | ||||
| 	dpy = 0; | ||||
| 
 | ||||
| 	/* also remove all x11 clients from the client list */ | ||||
| 	cnode = first_client(); | ||||
| 	while(cnode) { | ||||
|  | @ -164,18 +176,13 @@ int get_x11_socket(void) | |||
| void send_xevent(spnav_event *ev, struct client *c) | ||||
| { | ||||
| 	int i; | ||||
| 	int (*prev_xerr_handler)(Display*, XErrorEvent*); | ||||
| 	XEvent xevent; | ||||
| 
 | ||||
| 	if(!dpy) return; | ||||
| 
 | ||||
| 	/* If any of the registered clients exit without notice, we can get a
 | ||||
| 	 * BadWindow exception. Thus we must install a custom handler to avoid | ||||
| 	 * crashing the daemon when that happens. Also catch_badwin (see below) | ||||
| 	 * removes that client from the list, to avoid perpetually trying to send | ||||
| 	 * events to an invalid window. | ||||
| 	 */ | ||||
| 	prev_xerr_handler = XSetErrorHandler(catch_badwin); | ||||
| 	if(setjmp(jbuf)) { | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	xevent.type = ClientMessage; | ||||
| 	xevent.xclient.send_event = False; | ||||
|  | @ -206,12 +213,7 @@ void send_xevent(spnav_event *ev, struct client *c) | |||
| 	} | ||||
| 
 | ||||
| 	XSendEvent(dpy, get_client_window(c), False, 0, &xevent); | ||||
| 
 | ||||
| 	/* we *must* sync at this point, otherwise, a potential error may arrive
 | ||||
| 	 * after we remove the error handler and crash the daemon. | ||||
| 	 */ | ||||
| 	XSync(dpy, False); | ||||
| 	XSetErrorHandler(prev_xerr_handler); | ||||
| 	XFlush(dpy); | ||||
| } | ||||
| 
 | ||||
| int handle_xevents(fd_set *rset) | ||||
|  | @ -225,6 +227,10 @@ int handle_xevents(fd_set *rset) | |||
| 
 | ||||
| 	/* process any pending X events */ | ||||
| 	if(FD_ISSET(ConnectionNumber(dpy), rset)) { | ||||
| 		if(setjmp(jbuf)) { | ||||
| 			return 0; | ||||
| 		} | ||||
| 
 | ||||
| 		while(XPending(dpy)) { | ||||
| 			XEvent xev; | ||||
| 			XNextEvent(dpy, &xev); | ||||
|  | @ -301,12 +307,19 @@ void remove_client_window(Window win) | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* X11 error handler for bad-windows */ | ||||
| static int catch_badwin(Display *dpy, XErrorEvent *err) | ||||
| /* X11 error handler */ | ||||
| static int xerr(Display *dpy, XErrorEvent *err) | ||||
| { | ||||
| 	char buf[256]; | ||||
| 	char buf[512]; | ||||
| 
 | ||||
| 	if(verbose) { | ||||
| 		fprintf(stderr, "xerr(%p, %p)\n", (void*)dpy, (void*)err); | ||||
| 	} | ||||
| 
 | ||||
| 	if(err->error_code == BadWindow) { | ||||
| 		/* we may get a BadWindow error when trying to send events to
 | ||||
| 		 * clients that have disconnected in the meanwhile. | ||||
| 		 */ | ||||
| 		remove_client_window((Window)err->resourceid); | ||||
| 	} else { | ||||
| 		XGetErrorText(dpy, err->error_code, buf, sizeof buf); | ||||
|  | @ -315,6 +328,21 @@ static int catch_badwin(Display *dpy, XErrorEvent *err) | |||
| 	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"); | ||||
| 	dpy = 0; | ||||
| 	close_x11(); | ||||
| 	xdet_start(); | ||||
| 
 | ||||
| 	longjmp(jbuf, 1); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| #else | ||||
| int spacenavd_proto_x11_shut_up_empty_source_warning; | ||||
| #endif	/* USE_X11 */ | ||||
|  |  | |||
		Ładowanie…
	
		Reference in New Issue
	
	 John Tsiombikas
						John Tsiombikas