Commit 816d7e06 authored by runge's avatar runge

x11vnc: first pass at touchscreens via uinput.

parent 0bc50a9d
2006-08-10 Karl Runge <runge@karlrunge.com>
* x11vnc: first pass at touchscreens via uinput.
2006-08-02 Karl Runge <runge@karlrunge.com>
* x11vnc: add -ssltimeout option; tweak ssl timeouts.
......
This diff is collapsed.
......@@ -620,34 +620,38 @@ void print_help(int mode) {
" above command is run as the user who just authenticated\n"
" via the login and password prompt.\n"
"\n"
" Also in the case of -unixpw, the user logging in\n"
" can place a colon at the end of his username and\n"
" supply a few options: scale=, scale_cursor= (or sc=),\n"
" solid (or so), id=, clear_mods (or cm), clear_keys\n"
" (or ck), repeat, speeds= (or sp=), readtimeout=\n"
" (or rd=), or rotate= (or ro=) separated by commas if there is more than one.\n"
" After the user logs in successfully, these options will\n"
" be applied to the VNC screen. For example,\n"
" Also in the case of -unixpw, the user logging in can\n"
" place a colon at the end of his username and supply\n"
" a few options: scale=, scale_cursor= (or sc=), solid\n"
" (or so), id=, clear_mods (or cm), clear_keys (or ck),\n"
" repeat, speeds= (or sp=), readtimeout= (or rd=), or\n"
" rotate= (or ro=) separated by commas if there is more\n"
" than one. After the user logs in successfully, these\n"
" options will be applied to the VNC screen. For example,\n"
"\n"
" login: fred:scale=3/4,sc=1,repeat\n"
" Password: ...\n"
"\n"
" login: runge:sp=modem,rd=120,solid=root:\n"
" login: runge:sp=modem,rd=120,solid\n"
"\n"
" for convenience m/n implies scale= e.g. fred:3/4\n"
" To disable this set the environment variable\n"
" X11VNC_NO_UNIXPW_OPTS=1. To set any other options,\n"
" the user can use the gui (x11vnc -gui connect) or the\n"
" remote control method (x11vnc -R opt:val) during his\n"
" VNC session.\n"
" for convenience m/n implies scale= e.g. fred:3/4 If you\n"
" type and enter your password incorrectly, to retrieve\n"
" your long \"login:\" line press the Up arrow once\n"
" (before typing anything else).\n"
"\n"
" So the combination of -display WAIT:cmd=... and\n"
" -unixpw allows automatic pairing of an unix\n"
" authenticated VNC user with his desktop. This could\n"
" be very useful on SunRays and also any system where\n"
" multiple users share a given machine. The user does\n"
" not need to remember special ports or passwords set up\n"
" for his desktop and VNC.\n"
" To disable the option setting set the environment\n"
" variable X11VNC_NO_UNIXPW_OPTS=1 before starting x11vnc.\n"
" To set any other options, the user can use the gui\n"
" (x11vnc -gui connect) or the remote control method\n"
" (x11vnc -R opt:val) during his VNC session.\n"
"\n"
" The combination of -display WAIT:cmd=... and -unixpw\n"
" allows automatic pairing of an unix authenticated VNC\n"
" user with his desktop. This could be very useful on\n"
" SunRays and also any system where multiple users share\n"
" a given machine. The user does not need to remember\n"
" special ports or passwords set up for his desktop\n"
" and VNC.\n"
"\n"
" A nice way to use WAIT:cmd=... is out of inetd(8)\n"
" (it automatically forks a new x11vnc for each user).\n"
......@@ -1181,7 +1185,7 @@ void print_help(int mode) {
" unreliable (especially if the user takes much time to\n"
" ponder the Certificate dialogs in his browser, Java VM,\n"
" or VNC Viewer applet. That's right 3 separate \"Are\n"
" you sure you want to connect\" dialogs!)\n"
" you sure you want to connect?\" dialogs!)\n"
"\n"
" So use the -https option to provide a separate, more\n"
" reliable HTTPS port that x11vnc will listen on. If\n"
......@@ -2714,6 +2718,16 @@ void print_help(int mode) {
" cause jerkiness or unexpected behavior with menus, etc.\n"
" Use reset=0 to disable.\n"
"\n"
" If the uinput device has an absolute pointer (as opposed\n"
" to a normal mouse that is a relative pointer) you can\n"
" specify the option \"abs\". Note that a touchpad\n"
" on a laptop is an absolute device t some degree.\n"
" This (usually) avoids all the problems with mouse\n"
" acceleration. If x11vnc has trouble deducing the size\n"
" of the device, use \"abs=WxH\". Furthermore, if the\n"
" device is a touchscreen (assumed to have an absolute\n"
" pointer) use \"touch\" or \"touch=WxH\".\n"
"\n"
" If you set the env. var X11VNC_UINPUT_THRESHOLDS then\n"
" the thresh=n mode will be enabled. It it currently\n"
" not working well. If |dx| <= thresh and |dy| < thresh\n"
......
......@@ -94,20 +94,6 @@ char *console_guess(char *str, int *fd) {
}
}
if (do_input) {
if (tty >=0 && tty < 64) {
pipeinput_str = (char *) malloc(10);
sprintf(pipeinput_str, "CONSOLE%d", tty);
rfbLog("console_guess: file pipeinput %s\n",
pipeinput_str);
initialize_pipeinput();
} else if (have_uinput) {
pipeinput_str = strdup("UINPUT");
rfbLog("console_guess: file pipeinput %s\n",
pipeinput_str);
initialize_pipeinput();
}
}
if (! atparms) {
#if LIBVNCSERVER_HAVE_LINUX_FB_H
#if LIBVNCSERVER_HAVE_SYS_IOCTL_H
......@@ -153,6 +139,30 @@ char *console_guess(char *str, int *fd) {
#endif
}
if (atparms) {
int gw, gh, gb;
if (sscanf(atparms, "%dx%dx%d", &gw, &gh, &gb) == 3) {
fb_x = gw;
fb_y = gh;
fb_b = gb;
}
}
if (do_input) {
if (tty >=0 && tty < 64) {
pipeinput_str = (char *) malloc(10);
sprintf(pipeinput_str, "CONSOLE%d", tty);
rfbLog("console_guess: file pipeinput %s\n",
pipeinput_str);
initialize_pipeinput();
} else if (have_uinput) {
pipeinput_str = strdup("UINPUT");
rfbLog("console_guess: file pipeinput %s\n",
pipeinput_str);
initialize_pipeinput();
}
}
if (! atparms) {
rfbLog("console_guess: could not get @ parameters.\n");
return NULL;
......
......@@ -28,9 +28,15 @@ int initialize_uinput(void);
int set_uinput_accel(char *str);
int set_uinput_thresh(char *str);
void set_uinput_reset(int ms);
void set_uinput_always(int);
void set_uinput_touchscreen(int);
void set_uinput_abs(int);
char *get_uinput_accel();
char *get_uinput_thresh();
int get_uinput_reset();
int get_uinput_always();
int get_uinput_touchscreen();
int get_uinput_abs();
void parse_uinput_str(char *str);
void uinput_pointer_command(int mask, int x, int y, rfbClientPtr client);
void uinput_key_command(int down, int keysym, rfbClientPtr client);
......@@ -51,6 +57,9 @@ static int bmask = 0;
static char *injectable = NULL;
static char *uinput_dev = NULL;
static int uinput_touchscreen = 0;
static int uinput_abs = 0;
static int abs_x = 0, abs_y = 0;
static char *devs[] = {
"/dev/misc/uinput",
......@@ -78,9 +87,12 @@ int check_uinput(void) {
if (maj < 2) {
return 0;
} else if (maj == 2) {
/* hmmm IPAQ 2.4.19-rmk6-pxa1-hh37 works... */
#if 0
if (min < 6) {
return 0;
}
#endif
}
}
}
......@@ -210,6 +222,35 @@ int initialize_uinput(void) {
ioctl(fd, UI_SET_KEYBIT, BTN_FORWARD);
ioctl(fd, UI_SET_KEYBIT, BTN_BACK);
if (uinput_touchscreen) {
ioctl(fd, UI_SET_KEYBIT, BTN_TOUCH);
rfbLog("uinput: touchscreen enabled.\n");
}
if (uinput_touchscreen || uinput_abs) {
int gw = abs_x, gh = abs_y;
if (! gw || ! gh) {
gw = fb_x; gh = fb_y;
}
if (! gw || ! gh) {
gw = dpy_x; gh = dpy_y;
}
abs_x = gw;
abs_y = gh;
ioctl(fd, UI_SET_EVBIT, EV_ABS);
ioctl(fd, UI_SET_ABSBIT, ABS_X);
ioctl(fd, UI_SET_ABSBIT, ABS_Y);
udev.absmin[ABS_X] = 0;
udev.absmax[ABS_X] = gw;
udev.absfuzz[ABS_X] = 0;
udev.absflat[ABS_X] = 0;
udev.absmin[ABS_Y] = 0;
udev.absmax[ABS_Y] = gh;
udev.absfuzz[ABS_Y] = 0;
udev.absflat[ABS_Y] = 0;
rfbLog("uinput: absolute pointer enabled at %dx%d.\n", abs_x, abs_y);
set_uinput_accel_xy(1.0, 1.0);
}
write(fd, &udev, sizeof(udev));
if (ioctl(fd, UI_DEV_CREATE) != 0) {
......@@ -287,6 +328,14 @@ void set_uinput_always(int a) {
uinput_always = a;
}
void set_uinput_touchscreen(int b) {
uinput_touchscreen = b;
}
void set_uinput_abs(int b) {
uinput_abs = b;
}
char *get_uinput_accel(void) {
return uinput_accel_str;
}
......@@ -301,6 +350,14 @@ int get_uinput_always(void) {
return uinput_always;
}
int get_uinput_touchscreen(void) {
return uinput_touchscreen;
}
int get_uinput_abs(void) {
return uinput_abs;
}
void parse_uinput_str(char *in) {
char *p, *q, *str = strdup(in);
......@@ -309,6 +366,10 @@ void parse_uinput_str(char *in) {
injectable = strdup("KMB");
}
uinput_touchscreen = 0;
uinput_abs = 0;
abs_x = abs_y = 0;
p = strtok(str, ",");
while (p) {
if (p[0] == '/') {
......@@ -336,6 +397,24 @@ void parse_uinput_str(char *in) {
free(injectable);
}
injectable = strdup(p);
} else if (strstr(p, "touch") == p) {
int gw, gh;
q = strchr(p, '=');
set_uinput_touchscreen(1);
set_uinput_abs(1);
if (q && sscanf(q+1, "%dx%d", &gw, &gh) == 2) {
abs_x = gw;
abs_y = gh;
}
} else if (strstr(p, "abs") == p) {
int gw, gh;
q = strchr(p, '=');
set_uinput_abs(1);
if (q && sscanf(q+1, "%dx%d", &gw, &gh) == 2) {
abs_x = gw;
abs_y = gh;
}
} else {
rfbLog("invalid UINPUT option: %s\n", p);
clean_up_exit(1);
......@@ -373,6 +452,36 @@ static void ptr_move(int dx, int dy) {
#endif
}
static void ptr_abs(int x, int y) {
#ifdef UINPUT_OK
struct input_event ev;
if (injectable && strchr(injectable, 'M') == NULL) {
return;
}
memset(&ev, 0, sizeof(ev));
if (db) fprintf(stderr, "ptr_abs(%d, %d)\n", x, y);
gettimeofday(&ev.time, NULL);
ev.type = EV_ABS;
ev.code = ABS_Y;
ev.value = y;
write(fd, &ev, sizeof(ev));
ev.type = EV_ABS;
ev.code = ABS_X;
ev.value = x;
write(fd, &ev, sizeof(ev));
ev.type = EV_SYN;
ev.code = SYN_REPORT;
ev.value = 0;
write(fd, &ev, sizeof(ev));
#endif
}
static int inside_thresh(int dx, int dy, int thr) {
if (thresh_or) {
/* this is peeking at qt-embedded qmouse_qws.cpp */
......@@ -528,7 +637,10 @@ static void button_click(int down, int btn) {
ev.type = EV_KEY;
ev.value = down;
if (btn == 1) {
if (uinput_touchscreen) {
ev.code = BTN_TOUCH;
if (db) fprintf(stderr, "set code to BTN_TOUCH\n");
} else if (btn == 1) {
ev.code = BTN_LEFT;
} else if (btn == 2) {
ev.code = BTN_MIDDLE;
......@@ -583,7 +695,7 @@ void uinput_pointer_command(int mask, int x, int y, rfbClientPtr client) {
do_reset = 1;
if (mask || bmask) {
do_reset = 0; /* do not do reset if moust button down */
do_reset = 0; /* do not do reset if mouse button down */
} else if (! input.motion) {
do_reset = 0;
} else if (now < last_zero + zero_delay) {
......@@ -600,6 +712,18 @@ void uinput_pointer_command(int mask, int x, int y, rfbClientPtr client) {
if (uinput_always && !mask && !bmask && input.motion) {
do_reset = 1;
}
if (uinput_abs) {
#if 0
/* this is a bad idea... need to do something else */
if (do_reset) {
ptr_abs(dpy_x, dpy_y);
usleep(10*1000);
ptr_abs(x, y);
usleep(10*1000);
}
#endif
do_reset = 0;
}
if (do_reset) {
static int first = 1;
......@@ -696,7 +820,11 @@ void uinput_pointer_command(int mask, int x, int y, rfbClientPtr client) {
if (input.motion) {
if (x != last_x || y != last_y) {
ptr_rel(x - last_x, y - last_y);
if (uinput_abs) {
ptr_abs(x, y);
} else {
ptr_rel(x - last_x, y - last_y);
}
last_x = x;
last_y = y;
}
......
......@@ -9,10 +9,14 @@ extern int set_uinput_accel(char *str);
extern int set_uinput_thresh(char *str);
extern void set_uinput_reset(int ms);
extern void set_uinput_always(int);
extern void set_uinput_touchscreen(int);
extern void set_uinput_abs(int);
extern char *get_uinput_accel();
extern char *get_uinput_thresh();
extern int get_uinput_reset();
extern int get_uinput_always();
extern int get_uinput_touchscreen();
extern int get_uinput_abs();
extern void parse_uinput_str(char *str);
extern void uinput_pointer_command(int mask, int x, int y, rfbClientPtr client);
extern void uinput_key_command(int down, int keysym, rfbClientPtr client);
......
......@@ -2,7 +2,7 @@
.TH X11VNC "1" "August 2006" "x11vnc " "User Commands"
.SH NAME
x11vnc - allow VNC connections to real X11 displays
version: 0.8.3, lastmod: 2006-08-02
version: 0.8.3, lastmod: 2006-08-10
.SH SYNOPSIS
.B x11vnc
[OPTION]...
......@@ -740,34 +740,38 @@ In the case of \fB-unixpw\fR (but not \fB-unixpw_nis),\fR then the
above command is run as the user who just authenticated
via the login and password prompt.
.IP
Also in the case of \fB-unixpw,\fR the user logging in
can place a colon at the end of his username and
supply a few options: scale=, scale_cursor= (or sc=),
solid (or so), id=, clear_mods (or cm), clear_keys
(or ck), repeat, speeds= (or sp=), readtimeout=
(or rd=), or rotate= (or ro=) separated by commas if there is more than one.
After the user logs in successfully, these options will
be applied to the VNC screen. For example,
Also in the case of \fB-unixpw,\fR the user logging in can
place a colon at the end of his username and supply
a few options: scale=, scale_cursor= (or sc=), solid
(or so), id=, clear_mods (or cm), clear_keys (or ck),
repeat, speeds= (or sp=), readtimeout= (or rd=), or
rotate= (or ro=) separated by commas if there is more
than one. After the user logs in successfully, these
options will be applied to the VNC screen. For example,
.IP
login: fred:scale=3/4,sc=1,repeat
Password: ...
.IP
login: runge:sp=modem,rd=120,solid=root:
login: runge:sp=modem,rd=120,solid
.IP
for convenience m/n implies scale= e.g. fred:3/4
To disable this set the environment variable
X11VNC_NO_UNIXPW_OPTS=1. To set any other options,
the user can use the gui (x11vnc \fB-gui\fR connect) or the
remote control method (x11vnc \fB-R\fR opt:val) during his
VNC session.
for convenience m/n implies scale= e.g. fred:3/4 If you
type and enter your password incorrectly, to retrieve
your long "login:" line press the Up arrow once
(before typing anything else).
.IP
So the combination of \fB-display\fR WAIT:cmd=... and
\fB-unixpw\fR allows automatic pairing of an unix
authenticated VNC user with his desktop. This could
be very useful on SunRays and also any system where
multiple users share a given machine. The user does
not need to remember special ports or passwords set up
for his desktop and VNC.
To disable the option setting set the environment
variable X11VNC_NO_UNIXPW_OPTS=1 before starting x11vnc.
To set any other options, the user can use the gui
(x11vnc \fB-gui\fR connect) or the remote control method
(x11vnc \fB-R\fR opt:val) during his VNC session.
.IP
The combination of \fB-display\fR WAIT:cmd=... and \fB-unixpw\fR
allows automatic pairing of an unix authenticated VNC
user with his desktop. This could be very useful on
SunRays and also any system where multiple users share
a given machine. The user does not need to remember
special ports or passwords set up for his desktop
and VNC.
.IP
A nice way to use WAIT:cmd=... is out of
.IR inetd (8)
......@@ -1340,7 +1344,7 @@ adds a few seconds delay to each connection and can be
unreliable (especially if the user takes much time to
ponder the Certificate dialogs in his browser, Java VM,
or VNC Viewer applet. That's right 3 separate "Are
you sure you want to connect" dialogs!)
you sure you want to connect?" dialogs!)
.IP
So use the \fB-https\fR option to provide a separate, more
reliable HTTPS port that x11vnc will listen on. If
......@@ -3182,6 +3186,16 @@ in 1 jump), This correction seems to be needed but can
cause jerkiness or unexpected behavior with menus, etc.
Use reset=0 to disable.
.IP
If the uinput device has an absolute pointer (as opposed
to a normal mouse that is a relative pointer) you can
specify the option "abs". Note that a touchpad
on a laptop is an absolute device t some degree.
This (usually) avoids all the problems with mouse
acceleration. If x11vnc has trouble deducing the size
of the device, use "abs=WxH". Furthermore, if the
device is a touchscreen (assumed to have an absolute
pointer) use "touch" or "touch=WxH".
.IP
If you set the env. var X11VNC_UINPUT_THRESHOLDS then
the thresh=n mode will be enabled. It it currently
not working well. If |dx| <= thresh and |dy| < thresh
......
......@@ -3234,14 +3234,18 @@ int main(int argc, char* argv[]) {
rfb_desktop_name = strdup(argv_vnc[argc_vnc-1]);
}
initialize_pipeinput();
/*
* Create the XImage corresponding to the display framebuffer.
*/
fb0 = initialize_xdisplay_fb();
/*
* In some cases (UINPUT touchscreens) we need the dpy_x dpy_y
* to initialize pipeinput. So we do it after fb is created.
*/
initialize_pipeinput();
/*
* n.b. we do not have to X_LOCK any X11 calls until watch_loop()
* is called since we are single-threaded until then.
......
......@@ -345,6 +345,7 @@ extern Visual *default_visual; /* the default visual (unless -visual) */
extern int bpp, depth;
extern int indexed_color;
extern int dpy_x, dpy_y; /* size of display */
extern int fb_x, fb_y, fb_b; /* fb size and bpp guesses at display */
extern int off_x, off_y; /* offsets for -sid */
extern int wdpy_x, wdpy_y; /* for actual sizes in case of -clip */
extern int cdpy_x, cdpy_y, coff_x, coff_y; /* the -clip params */
......
......@@ -15,7 +15,7 @@ int xtrap_base_event_type = 0;
int xdamage_base_event_type = 0;
/* date +'lastmod: %Y-%m-%d' */
char lastmod[] = "0.8.3 lastmod: 2006-08-02";
char lastmod[] = "0.8.3 lastmod: 2006-08-10";
/* X display info */
......@@ -27,7 +27,8 @@ Window window = None, rootwin = None; /* polled window, root window (usu. same)
Visual *default_visual = NULL; /* the default visual (unless -visual) */
int bpp = 0, depth = 0;
int indexed_color = 0;
int dpy_x, dpy_y; /* size of display */
int dpy_x = 0, dpy_y = 0; /* size of display */
int fb_x = 0, fb_y = 0, fb_b = 0; /* fb size and bpp guesses at display */
int off_x, off_y; /* offsets for -sid */
int wdpy_x, wdpy_y; /* for actual sizes in case of -clip */
int cdpy_x, cdpy_y, coff_x, coff_y; /* the -clip params */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment