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,8 +139,7 @@ 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"));
|
||||
}
|
||||
|
|
@ -143,6 +154,7 @@ void close_x11(void)
|
|||
XDestroyWindow(dpy, win);
|
||||
XCloseDisplay(dpy);
|
||||
dpy = 0;
|
||||
}
|
||||
|
||||
/* also remove all x11 clients from the client list */
|
||||
cnode = first_client();
|
||||
|
|
@ -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