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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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