Commit fba6f58a authored by runge's avatar runge

x11vnc: X DAMAGE support, -clip WxH+X+Y, identd.

parent 4ff783f5
2005-03-12 Karl Runge <runge@karlrunge.com>
* x11vnc: X DAMAGE support, -clip WxH+X+Y, identd.
2005-03-05 Karl Runge <runge@karlrunge.com>
* autoconf: rpm -> rpmbuild and echo -n -> printf
......
2005-03-12 Karl Runge <runge@karlrunge.com>
* support for the X DAMAGE extension to receive damage
rectangle reports from the X server. On by default, disable
with -noxdamage. Currently only trusts small rects
(but see -xd_area n) and uses the rest as "hints" for the
scanline polling.
* -clip WxH+X+Y to show a clipped sub-region of the screen.
* use RFC 1413 (identd) to attach a name to a client in
friendly environments.
* fix XAUTHORITY wrt '-auth ... -gui other:0'.
2005-03-04 Karl Runge <runge@karlrunge.com>
* add changes to couple with -listen option, in particular
the behavior of -localhost and remote control cmds.
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -115,6 +115,7 @@ Screen
flashcmap
notruecolor
--
clip:
=P blackout:
xinerama
--
......@@ -139,12 +140,16 @@ Keyboard
Pointer
=D-C:none,arrow,X,some,most cursor:
noxfixes
noalphablend
--
cursorpos
=D nocursorshape
--
noxfixes
noalphablend
alphacut:
alphafrac:
alpharemove
--
buttonmap:
--
xwarppointer
......@@ -220,10 +225,6 @@ Tuning
noshm
flipbyteorder
onetile
--
alphacut:
alphafrac:
alpharemove
-- D
speeds:
=D wait:
......@@ -237,6 +238,11 @@ Tuning
fuzz:
snapfb
--
xdamage
xd_mem:
xd_area:
xd_width:
--
threads
--
progressive:
......@@ -2042,17 +2048,18 @@ proc client_dialog {client} {
global menu_var text_area cleanup_window item_bool
append_text "\nClient info string: $client\n\n"
if {[regexp {^(.*):(.*):(.*):(.*):(.*):(.*)$} \
$client m0 m1 m2 m3 m4 m5 m6]} {
# id:ip:port:hostname:input:loginvo
if {[regexp {^(.*):(.*):(.*):(.*):(.*):(.*):(.*)$} \
$client m0 m1 m2 m3 m4 m5 m6 m7]} {
# id:ip:port:user:hostname:input:loginvo
set cid $m1
set ip $m2
set port $m3
set host $m4
set user $m4
set host $m5
regsub {\..*$} $host "" host
set input $m5
set logvo $m6
append_text "Host: $host, Port: $port, IP: $ip, Id: $cid\n"
set input $m6
set logvo $m7
append_text "Host: $host, Port: $port, User: $user, IP: $ip, Id: $cid\n"
append_text " - originally logged in as: "
if {$logvo == "1" } {
append_text "View-Only Client\n"
......@@ -2184,10 +2191,10 @@ proc update_clients_menu {list} {
$subm add separator
set count 0
foreach client [split $list ","] {
if {[regexp {^(.*):(.*):(.*):(.*):(.*):(.*)$} \
$client m0 m1 m2 m3 m4 m5 m6]} {
# id:ip:port:hostname:input:loginvo
set host $m4
if {[regexp {^(.*):(.*):(.*):(.*):(.*):(.*):(.*)$} \
$client m0 m1 m2 m3 m4 m5 m6 m7]} {
# id:ip:port:user:hostname:input:loginvo
set host $m5
regsub {\..*$} $host "" host
set clabel "$host $m1"
} else {
......
......@@ -121,6 +121,7 @@
" flashcmap\n"
" notruecolor\n"
" --\n"
" clip:\n"
" =P blackout:\n"
" xinerama\n"
" --\n"
......@@ -145,12 +146,16 @@
"\n"
"Pointer\n"
" =D-C:none,arrow,X,some,most cursor:\n"
" noxfixes\n"
" noalphablend\n"
" --\n"
" cursorpos\n"
" =D nocursorshape\n"
" --\n"
" noxfixes\n"
" noalphablend\n"
" alphacut:\n"
" alphafrac:\n"
" alpharemove\n"
" --\n"
" buttonmap:\n"
" --\n"
" xwarppointer\n"
......@@ -226,10 +231,6 @@
" noshm\n"
" flipbyteorder\n"
" onetile\n"
" --\n"
" alphacut:\n"
" alphafrac:\n"
" alpharemove\n"
" -- D\n"
" speeds:\n"
" =D wait:\n"
......@@ -243,6 +244,11 @@
" fuzz:\n"
" snapfb\n"
" --\n"
" xdamage\n"
" xd_mem:\n"
" xd_area:\n"
" xd_width:\n"
" --\n"
" threads\n"
" --\n"
" progressive:\n"
......@@ -2048,17 +2054,18 @@
" global menu_var text_area cleanup_window item_bool\n"
"\n"
" append_text \"\\nClient info string: $client\\n\\n\"\n"
" if {[regexp {^(.*):(.*):(.*):(.*):(.*):(.*)$} \\\n"
" $client m0 m1 m2 m3 m4 m5 m6]} {\n"
" # id:ip:port:hostname:input:loginvo\n"
" if {[regexp {^(.*):(.*):(.*):(.*):(.*):(.*):(.*)$} \\\n"
" $client m0 m1 m2 m3 m4 m5 m6 m7]} {\n"
" # id:ip:port:user:hostname:input:loginvo\n"
" set cid $m1\n"
" set ip $m2\n"
" set port $m3\n"
" set host $m4\n"
" set user $m4\n"
" set host $m5\n"
" regsub {\\..*$} $host \"\" host\n"
" set input $m5\n"
" set logvo $m6\n"
" append_text \"Host: $host, Port: $port, IP: $ip, Id: $cid\\n\"\n"
" set input $m6\n"
" set logvo $m7\n"
" append_text \"Host: $host, Port: $port, User: $user, IP: $ip, Id: $cid\\n\"\n"
" append_text \" - originally logged in as: \"\n"
" if {$logvo == \"1\" } {\n"
" append_text \"View-Only Client\\n\"\n"
......@@ -2190,10 +2197,10 @@
" $subm add separator\n"
" set count 0\n"
" foreach client [split $list \",\"] {\n"
" if {[regexp {^(.*):(.*):(.*):(.*):(.*):(.*)$} \\\n"
" $client m0 m1 m2 m3 m4 m5 m6]} {\n"
" # id:ip:port:hostname:input:loginvo\n"
" set host $m4\n"
" if {[regexp {^(.*):(.*):(.*):(.*):(.*):(.*):(.*)$} \\\n"
" $client m0 m1 m2 m3 m4 m5 m6 m7]} {\n"
" # id:ip:port:user:hostname:input:loginvo\n"
" set host $m5\n"
" regsub {\\..*$} $host \"\" host\n"
" set clabel \"$host $m1\"\n"
" } else {\n"
......
......@@ -2,7 +2,7 @@
.TH X11VNC "1" "March 2005" "x11vnc " "User Commands"
.SH NAME
x11vnc - allow VNC connections to real X11 displays
version: 0.7.2pre, lastmod: 2005-03-04
version: 0.7.2pre, lastmod: 2005-03-12
.SH SYNOPSIS
.B x11vnc
[OPTION]...
......@@ -89,6 +89,15 @@ shifts a root view to it: this shows SaveUnders menus,
etc, although they will be clipped if they extend beyond
the window.
.PP
\fB-clip\fR \fIWxH+X+Y\fR
.IP
Only show the sub-region of the full display that
corresponds to the rectangle with size WxH and offset
+X+Y. The VNC display has size WxH (i.e. smaller than
the full display). This also works for \fB-id/-sid\fR mode
where the offset is relative to the upper left corner
of the selected window.
.PP
\fB-flashcmap\fR
.IP
In 8bpp indexed color, let the installed colormap flash
......@@ -994,6 +1003,43 @@ Time in seconds after NO activity (e.g. screen blank)
to really throttle down the screen polls (i.e. sleep
for about 1.5 secs). Use 0 to disable. Default: 60
.PP
\fB-noxdamage\fR
.IP
Do not use the X DAMAGE extension to detect framebuffer
changes even if it is available.
.IP
x11vnc's use of the DAMAGE extension: 1) significantly
reduces the load when the screen is not changing much,
and 2) detects changed areas (small ones by default)
more quickly.
.IP
Currently the DAMAGE extension is overly conservative
and often reports large areas (e.g. a whole terminal
or browser window) as damaged even though the actual
changed region is much smaller (sometimes just a few
pixels). So heuristics were introduced to skip large
areas and use the damage rectangles only as "hints"
for the traditional scanline polling. The following
tuning parameters are introduced to adjust this
behavior:
.PP
\fB-xd_area\fR \fIA\fR
.IP
Set the largest DAMAGE rectangle area \fIA\fR (in
pixels: width * height) to trust as truly damaged:
the rectangle will be copied from the framebuffer
(slow) no matter what. Set to zero to trust *all*
rectangles. Default: 20000
.PP
\fB-xd_mem\fR \fIf\fR
.IP
Set how long DAMAGE rectangles should be "remembered",
\fIf\fR is a floating point number and is in units of the
scanline repeat cycle time (32 iterations). The default
(1.0) should give no painting problems. Increase it if
there are problems or decrease it to live on the edge
(perhaps useful on a slow machine).
.PP
\fB-sigpipe\fR \fIstring\fR
.IP
Broken pipe (SIGPIPE) handling. \fIstring\fR can be
......@@ -1149,6 +1195,8 @@ id:windowid set \fB-id\fR window to "windowid". empty
.IP
sid:windowid set \fB-sid\fR window to "windowid"
.IP
clip:WxH+X+Y set \fB-clip\fR mode to "WxH+X+Y"
.IP
flashcmap enable \fB-flashcmap\fR mode.
.IP
noflashcmap disable \fB-flashcmap\fR mode.
......@@ -1387,6 +1435,14 @@ nonap disable \fB-nap\fR mode.
.IP
sb:n set \fB-sb\fR to n s, same as screen_blank:n
.IP
xdamage enable xdamage polling hints.
.IP
noxdamage disable xdamage polling hints.
.IP
xd_area:A set \fB-xd_area\fR max pixel area to "A"
.IP
xd_mem:f set \fB-xd_mem\fR remembrance to "f"
.IP
fs:frac set \fB-fs\fR fraction to "frac", e.g. 0.5
.IP
gaps:n set \fB-gaps\fR to n.
......@@ -1491,7 +1547,7 @@ the returned value corresponds to (hint: the ext_*
variables correspond to the presence of X extensions):
.IP
ans= stop quit exit shutdown ping blacken zero
refresh reset close disconnect id sid waitmapped
refresh reset close disconnect id sid clip waitmapped
nowaitmapped flashcmap noflashcmap truecolor notruecolor
overlay nooverlay overlay_cursor overlay_yescursor
nooverlay_nocursor nooverlay_cursor nooverlay_yescursor
......@@ -1507,9 +1563,10 @@ clear_mods noclear_mods clear_keys noclear_keys
remap repeat norepeat fb nofb bell nobell sel
nosel primary noprimary cursorshape nocursorshape
cursorpos nocursorpos cursor show_cursor noshow_cursor
nocursor xfixes noxfixes alphacut alphafrac alpharemove
noalpharemove alphablend noalphablend xwarp xwarppointer
noxwarp noxwarppointer buttonmap dragging nodragging
nocursor xfixes noxfixes xdamage noxdamage xd_area
xd_mem alphacut alphafrac alpharemove noalpharemove
alphablend noalphablend xwarp xwarppointer noxwarp
noxwarppointer buttonmap dragging nodragging
pointer_mode pm input_skip input client_input speeds
debug_pointer dp nodebug_pointer nodp debug_keyboard dk
nodebug_keyboard nodk deferupdate defer wait rfbwait
......@@ -1520,15 +1577,16 @@ noalwaysshared nevershared noalwaysshared dontdisconnect
nodontdisconnect desktop noremote
.IP
aro= display vncdisplay desktopname http_url auth
users rootshift scale_str scaled_x scaled_y scale_numer
scale_denom scale_fac scaling_noblend scaling_nomult4
scaling_pad scaling_interpolate inetd safer unsafe
passwdfile using_shm logfile o rc norc h help V version
lastmod bg sigpipe threads clients client_count pid
ext_xtest ext_xkb ext_xshm ext_xinerama ext_overlay
ext_xfixes ext_xdamage ext_xrandr rootwin num_buttons
button_mask mouse_x mouse_y bpp depth indexed_color
dpy_x dpy_y rfbauth passwd
users rootshift clipshift scale_str scaled_x scaled_y
scale_numer scale_denom scale_fac scaling_noblend
scaling_nomult4 scaling_pad scaling_interpolate inetd
safer unsafe passwdfile using_shm logfile o rc norc
h help V version lastmod bg sigpipe threads clients
client_count pid ext_xtest ext_xkb ext_xshm ext_xinerama
ext_overlay ext_xfixes ext_xdamage ext_xrandr rootwin
num_buttons button_mask mouse_x mouse_y bpp depth
indexed_color dpy_x dpy_y wdpy_x wdpy_y off_x off_y
cdpy_x cdpy_y coff_x coff_y rfbauth passwd
.PP
\fB-sync\fR
.IP
......
......@@ -169,7 +169,7 @@
/*
#define LIBVNCSERVER_HAVE_LIBXINERAMA 1
#define LIBVNCSERVER_HAVE_XFIXES 1
#define LIBVNCSERVER_HAVE_XDAMAGE 1
#define LIBVNCSERVER_HAVE_LIBXDAMAGE 1
*/
#endif /* OLD_TREE */
......@@ -329,13 +329,21 @@ static int xfixes_base_event_type;
#endif
int xdamage_present = 0;
int using_xdamage = 0;
int use_xdamage_hints = 1; /* just use the xdamage rects. for scanline hints */
#if LIBVNCSERVER_HAVE_LIBXDAMAGE
#include <X11/extensions/Xdamage.h>
static int xdamage_base_event_type;
Damage xdamage = 0;
#endif
int xdamage_max_area = 20000; /* pixels */
double xdamage_memory = 1.0; /* in units of NSCAN */
int xdamage_tile_count;
int hack_val = 0;
/* date +'lastmod: %Y-%m-%d' */
char lastmod[] = "0.7.2pre lastmod: 2005-03-04";
char lastmod[] = "0.7.2pre lastmod: 2005-03-12";
/* X display info */
......@@ -347,6 +355,8 @@ int bpp, depth;
int indexed_color = 0;
int dpy_x, dpy_y; /* size of 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 */
int button_mask = 0; /* button state and info */
int num_buttons = -1;
......@@ -395,6 +405,7 @@ unsigned short main_red_shift, main_green_shift, main_blue_shift;
typedef struct _ClientData {
int uid;
char *hostname;
char *username;
int client_port;
int server_port;
char *server_ip;
......@@ -432,6 +443,7 @@ int ntiles, ntiles_x, ntiles_y;
/* arrays that indicate changed or checked tiles. */
unsigned char *tile_has_diff, *tile_tried, *tile_copied;
unsigned char *tile_has_xdamage_diff, *tile_row_has_xdamage_diff;
/* times of recent events */
time_t last_event, last_input, last_client = 0;
......@@ -466,6 +478,15 @@ Atom vnc_connect_prop = None;
struct utsname UT;
/* scan pattern jitter from x0rfbserver */
#define NSCAN 32
int scanlines[NSCAN] = {
0, 16, 8, 24, 4, 20, 12, 28,
10, 26, 18, 2, 22, 6, 30, 14,
1, 17, 9, 25, 7, 23, 15, 31,
19, 3, 27, 11, 29, 13, 5, 21
};
/* function prototypes (see filename comment above) */
int all_clients_initialized(void);
......@@ -511,6 +532,9 @@ void free_tiles(void);
void initialize_watch_bell(void);
void initialize_xinerama(void);
void initialize_xfixes(void);
void initialize_xdamage(void);
void create_xdamage(void);
void destroy_xdamage(void);
void initialize_xrandr(void);
XImage *initialize_xdisplay_fb(void);
......@@ -596,24 +620,25 @@ void refresh_screen(void);
/*
* variables for the command line options
*/
char *use_dpy = NULL;
char *auth_file = NULL;
char *visual_str = NULL;
char *logfile = NULL;
char *use_dpy = NULL; /* -display */
char *auth_file = NULL; /* -auth/-xauth */
char *visual_str = NULL; /* -visual */
char *logfile = NULL; /* -o, -logfile */
int logfile_append = 0;
char *passwdfile = NULL;
char *blackout_str = NULL;
int use_solid_bg = 0;
char *passwdfile = NULL; /* -passwdfile */
char *blackout_str = NULL; /* -blackout */
char *clip_str = NULL; /* -clip */
int use_solid_bg = 0; /* -solid */
char *solid_str = NULL;
char *solid_default = "cyan4";
char *speeds_str = NULL;
char *speeds_str = NULL; /* -speeds TBD */
int measure_speeds = 1;
int speeds_net_rate = 0;
int speeds_net_latency = 0;
int speeds_read_rate = 0;
char *rc_rcfile = NULL;
char *rc_rcfile = NULL; /* -rc */
int rc_norc = 0;
int opts_bg = 0;
......@@ -866,6 +891,32 @@ int scan_hexdec(char *str, unsigned long *num) {
return 1;
}
int parse_geom(char *str, int *wp, int *hp, int *xp, int *yp, int W, int H) {
int w, h, x, y;
/* handle +/-x and +/-y */
if (sscanf(str, "%dx%d+%d+%d", &w, &h, &x, &y) == 4) {
;
} else if (sscanf(str, "%dx%d-%d+%d", &w, &h, &x, &y) == 4) {
w = nabs(w);
x = W - x - w;
} else if (sscanf(str, "%dx%d+%d-%d", &w, &h, &x, &y) == 4) {
h = nabs(h);
y = H - y - h;
} else if (sscanf(str, "%dx%d-%d-%d", &w, &h, &x, &y) == 4) {
w = nabs(w);
h = nabs(h);
x = W - x - w;
y = H - y - h;
} else {
return 0;
}
*wp = w;
*hp = h;
*xp = x;
*yp = y;
return 1;
}
void set_env(char *name, char *value) {
char *str;
str = (char *)malloc(strlen(name)+strlen(value)+2);
......@@ -1704,6 +1755,7 @@ void try_to_switch_users(void) {
free(users);
}
/* -- inet.c -- */
/*
* Simple utility to map host name to dotted IP address. Ignores aliases.
* Up to caller to free returned string.
......@@ -1728,9 +1780,6 @@ char *ip2host(char *ip) {
char *str;
#if LIBVNCSERVER_HAVE_NETDB_H && LIBVNCSERVER_HAVE_NETINET_IN_H
struct hostent *hp;
#ifndef in_addr_t
typedef unsigned int in_addr_t;
#endif
in_addr_t iaddr;
iaddr = inet_addr(ip);
......@@ -1821,6 +1870,96 @@ char *get_local_host(int sock) {
return get_host(sock, 0);
}
char *ident_username(rfbClientPtr client) {
ClientData *cd = (ClientData *) client->clientData;
char *str, *newhost, *user = NULL, *newuser = NULL;
int len;
if (cd) {
user = cd->username;
}
if (!user || *user == '\0') {
char msg[128];
int n, sock, ok = 0;
if ((sock = rfbConnectToTcpAddr(client->host, 113)) < 0) {
rfbLog("could not connect to ident: %s:%d\n",
client->host, 113);
} else {
int ret;
fd_set rfds;
struct timeval tv;
int rport = get_remote_port(client->sock);
int lport = get_local_port(client->sock);
sprintf(msg, "%d, %d\r\n", rport, lport);
n = write(sock, msg, strlen(msg));
FD_ZERO(&rfds);
FD_SET(sock, &rfds);
tv.tv_sec = 4;
tv.tv_usec = 0;
ret = select(sock+1, &rfds, NULL, NULL, &tv);
if (ret > 0) {
int i;
char *q, *p;
for (i=0; i<128; i++) {
msg[i] = '\0';
}
usleep(250*1000);
n = read(sock, msg, 127);
close(sock);
if (n <= 0) goto badreply;
/* 32782 , 6000 : USERID : UNIX :runge */
q = strstr(msg, "USERID");
if (!q) goto badreply;
q = strstr(q, ":");
if (!q) goto badreply;
q++;
q = strstr(q, ":");
if (!q) goto badreply;
q++;
q = lblanks(q);
p = q;
while (*p) {
if (*p == '\r' || *p == '\n') {
*p = '\0';
}
p++;
}
ok = 1;
if (strlen(q) > 24) {
*(q+24) = '\0';
}
newuser = strdup(q);
badreply:
n = 0; /* avoid syntax error */
} else {
close(sock);
}
}
if (! ok || !newuser) {
newuser = strdup("unknown-user");
}
if (cd) {
free(cd->username);
cd->username = newuser;
}
user = newuser;
}
newhost = ip2host(client->host);
len = strlen(user) + 1 + strlen(newhost) + 1;
str = (char *)malloc(len);
sprintf(str, "%s@%s", user, newhost);
free(newhost);
return str;
}
/* -- ximage.c -- */
/*
* used in rfbGetScreen and rfbNewFramebuffer: and estimate to the number
* of bits per color, of course for some visuals, e.g. 565, the number
......@@ -1846,42 +1985,25 @@ int guess_bits_per_color(int bits_per_pixel) {
return bits_per_color;
}
/* count number of clients supporting NewFBSize */
int new_fb_size_clients(rfbScreenInfoPtr s) {
rfbClientIteratorPtr iter;
rfbClientPtr cl;
int count = 0;
if (! s) {
return 0;
}
iter = rfbGetClientIterator(s);
while( (cl = rfbClientIteratorNext(iter)) ) {
if (cl->useNewFBSize) {
count++;
}
}
rfbReleaseClientIterator(iter);
return count;
}
/*
* Kludge to interpose image gets and limit to a subset rectangle of
* the rootwin. This is the -sid option trying to work around invisible
* saveUnders menu, etc, windows.
* saveUnders menu, etc, windows. Also -clip option.
*/
int rootshift = 0;
int clipshift = 0;
#define ADJUST_ROOTSHIFT \
if (rootshift && subwin) { \
d = rootwin; \
x += off_x; \
y += off_y; \
} \
if (clipshift) { \
x += coff_x; \
y += coff_y; \
}
/* -- ximage.c -- */
/*
* Wrappers for Image related X calls
*/
......@@ -2025,7 +2147,7 @@ XImage *XCreateImage_wr(Display *disp, Visual *visual, unsigned int depth,
void copy_image(XImage *dest, int x, int y, unsigned int w, unsigned int h) {
/* default (w=0,h=0) is the fill the entire XImage */
/* default (w=0, h=0) is the fill the entire XImage */
if (w < 1) {
w = dest->width;
}
......@@ -2222,6 +2344,11 @@ void clean_up_exit (int ret) {
}
X_LOCK;
XTestDiscard_wr(dpy);
#if LIBVNCSERVER_HAVE_LIBXDAMAGE
if (xdamage) {
XDamageDestroy(dpy, xdamage);
}
#endif
XCloseDisplay(dpy);
X_UNLOCK;
......@@ -2493,9 +2620,9 @@ char *list_clients(void) {
/*
* each client:
* <id>:<ip>:<port>:<hostname>:<input>:<loginview>,
* 8+1+16+1+5+1+256+1+5+1+1+1
* 123.123.123.123:60000/0x11111111-rw, = 297 bytes
* <id>:<ip>:<port>:<user>:<hostname>:<input>:<loginview>,
* 8+1+16+1+5+1+24+1+256+1+5+1+1+1
* 123.123.123.123:60000/0x11111111-rw,
* so count+1 * 400 must cover it.
*/
list = (char *) malloc((count+1)*400);
......@@ -2514,6 +2641,12 @@ char *list_clients(void) {
strcat(list, ":");
sprintf(tmp, "%d:", cd->client_port);
strcat(list, tmp);
if (*(cd->username) == '\0') {
char *s = ident_username(cl);
if (s) free(s);
}
strcat(list, cd->username);
strcat(list, ":");
strcat(list, cd->hostname);
strcat(list, ":");
strcat(list, cd->input);
......@@ -2525,6 +2658,26 @@ char *list_clients(void) {
return list;
}
/* count number of clients supporting NewFBSize */
int new_fb_size_clients(rfbScreenInfoPtr s) {
rfbClientIteratorPtr iter;
rfbClientPtr cl;
int count = 0;
if (! s) {
return 0;
}
iter = rfbGetClientIterator(s);
while( (cl = rfbClientIteratorNext(iter)) ) {
if (cl->useNewFBSize) {
count++;
}
}
rfbReleaseClientIterator(iter);
return count;
}
void close_all_clients(void) {
rfbClientIteratorPtr iter;
rfbClientPtr cl;
......@@ -2779,6 +2932,9 @@ static void client_gone(rfbClientPtr client) {
if (cd->hostname) {
free(cd->hostname);
}
if (cd->username) {
free(cd->username);
}
}
free(client->clientData);
}
......@@ -2958,8 +3114,8 @@ static int check_access(char *addr) {
* x11vnc's first (and only) visible widget: accept/reject dialog window.
* We go through this pain to avoid dependency on libXt...
*/
static int ugly_accept_window(char *addr, int X, int Y, int timeout,
char *mode) {
static int ugly_accept_window(char *addr, char *userhost, int X, int Y,
int timeout, char *mode) {
#define t2x2_width 16
#define t2x2_height 16
......@@ -2989,6 +3145,7 @@ static char t2x2_bits[] = {
/* strings and geometries y/n */
KeyCode key_y, key_n, key_v;
char strh[100];
char stri[100];
char str1_b[] = "To accept: press \"y\" or click the \"Yes\" button";
char str2_b[] = "To reject: press \"n\" or click the \"No\" button";
char str3_b[] = "View only: press \"v\" or click the \"View\" button";
......@@ -3002,7 +3159,7 @@ static char t2x2_bits[] = {
char str_y[] = "Yes";
char str_n[] = "No";
char str_v[] = "View";
int x, y, w = 345, h = 150, ret = 0;
int x, y, w = 345, h = 175, ret = 0;
int X_sh = 20, Y_sh = 30, dY = 20;
int Ye_x = 20, Ye_y = 0, Ye_w = 45, Ye_h = 20;
int No_x = 75, No_y = 0, No_w = 45, No_h = 20;
......@@ -3026,6 +3183,7 @@ static char t2x2_bits[] = {
h -= dY;
}
/* XXX handle coff_x/coff_y? */
if (X < -dpy_x) {
x = (dpy_x - w)/2; /* large negative: center */
if (x < 0) x = 0;
......@@ -3086,7 +3244,8 @@ static char t2x2_bits[] = {
XMapWindow(dpy, awin);
XFlush(dpy);
sprintf(strh, "x11vnc: accept connection from %s?", addr);
snprintf(strh, 100, "x11vnc: accept connection from %s?", addr);
snprintf(stri, 100, " (%s)", userhost);
key_y = XKeysymToKeycode(dpy, XStringToKeysym("y"));
key_n = XKeysymToKeycode(dpy, XStringToKeysym("n"));
key_v = XKeysymToKeycode(dpy, XStringToKeysym("v"));
......@@ -3122,6 +3281,8 @@ static char t2x2_bits[] = {
/* instructions */
XDrawString(dpy, awin, gc, X_sh, Y_sh+(k++)*dY,
strh, strlen(strh));
XDrawString(dpy, awin, gc, X_sh, Y_sh+(k++)*dY,
stri, strlen(stri));
XDrawString(dpy, awin, gc, X_sh, Y_sh+(k++)*dY,
str1, strlen(str1));
XDrawString(dpy, awin, gc, X_sh, Y_sh+(k++)*dY,
......@@ -3336,6 +3497,7 @@ static int accept_client(rfbClientPtr client) {
addr = "unknown-host";
}
if (strstr(accept_cmd, "popup") == accept_cmd) {
/* use our builtin popup button */
......@@ -3344,6 +3506,7 @@ static int accept_client(rfbClientPtr client) {
int ret, timeout = 120;
int x = -64000, y = -64000;
char *p, *mode;
char *userhost = ident_username(client);
/* extract timeout */
if ((p = strchr(accept_cmd, ':')) != NULL) {
......@@ -3380,7 +3543,9 @@ static int accept_client(rfbClientPtr client) {
}
rfbLog("accept_client: using builtin popup for: %s\n", addr);
if ((ret = ugly_accept_window(addr, x, y, timeout, mode))) {
if ((ret = ugly_accept_window(addr, userhost, x, y, timeout,
mode))) {
free(userhost);
if (ret == 2) {
rfbLog("accept_client: viewonly: %s\n", addr);
client->viewOnly = TRUE;
......@@ -3388,6 +3553,7 @@ static int accept_client(rfbClientPtr client) {
rfbLog("accept_client: popup accepted: %s\n", addr);
return 1;
} else {
free(userhost);
rfbLog("accept_client: popup rejected: %s\n", addr);
return 0;
}
......@@ -3787,6 +3953,7 @@ enum rfbNewClientAction new_client(rfbClientPtr client) {
cd->server_port = get_local_port(client->sock);
cd->server_ip = get_local_host(client->sock);
cd->hostname = ip2host(client->host);
cd->username = strdup("");
cd->input[0] = '-';
cd->login_viewonly = -1;
......@@ -5755,11 +5922,15 @@ static void update_x11_pointer_position(int x, int y) {
X_LOCK;
if (use_xwarppointer) {
/* off_x and off_y not needed with XWarpPointer */
XWarpPointer(dpy, None, window, 0, 0, 0, 0, x, y);
/*
* off_x and off_y not needed with XWarpPointer since
* window is used:
*/
XWarpPointer(dpy, None, window, 0, 0, 0, 0, x + coff_x,
y + coff_y);
} else {
XTestFakeMotionEvent_wr(dpy, scr, x+off_x, y+off_y,
CurrentTime);
XTestFakeMotionEvent_wr(dpy, scr, x + off_x + coff_x,
y + off_y + coff_y, CurrentTime);
}
X_UNLOCK;
......@@ -5786,7 +5957,7 @@ static void update_x11_pointer_position(int x, int y) {
}
/*
* Send a pointer position event to the X server.
* Send a pointer button event to the X server.
*/
static void update_x11_pointer_mask(int mask) {
int i, mb;
......@@ -6164,8 +6335,8 @@ XErrorHandler old_getimage_handler;
/* -- xrandr.c -- */
void initialize_xrandr(void) {
#if LIBVNCSERVER_HAVE_LIBXRANDR
if (xrandr_present) {
#if LIBVNCSERVER_HAVE_LIBXRANDR
Rotation rot;
xrandr_width = XDisplayWidth(dpy, scr);
......@@ -6177,15 +6348,20 @@ void initialize_xrandr(void) {
} else {
XRRSelectInput(dpy, rootwin, 0);
}
}
#endif
} else if (xrandr) {
rfbLog("-xrandr mode specified, but no RANDR support on\n");
rfbLog(" display or in client library. Disabling -xrandr "
"mode.\n");
xrandr = 0;
}
}
void handle_xrandr_change(int, int);
int handle_subwin_resize(char *msg) {
int new_x, new_y;
int i, check = 10, ms = 250; /* 2.5 secs... */
int i, check = 10, ms = 250; /* 2.5 secs total... */
if (! subwin) {
return 0; /* hmmm... */
......@@ -6200,7 +6376,7 @@ int handle_subwin_resize(char *msg) {
X_UNLOCK;
clean_up_exit(1);
}
if (dpy_x == new_x && dpy_y == new_y) {
if (wdpy_x == new_x && wdpy_y == new_y) {
/* no change */
return 0;
}
......@@ -6225,7 +6401,7 @@ int handle_subwin_resize(char *msg) {
}
rfbLog("subwin 0x%lx new size: x: %d -> %d, y: %d -> %d\n",
subwin, dpy_x, new_x, dpy_y, new_y);
subwin, wdpy_x, new_x, wdpy_y, new_y);
rfbLog("calling handle_xrandr_change() for resizing\n");
X_UNLOCK;
......@@ -6268,11 +6444,11 @@ void handle_xrandr_change(int new_x, int new_y) {
/* default, resize, and newfbsize create a new fb: */
rfbLog("check_xrandr_event: trying to create new framebuffer...\n");
if (new_x < dpy_x || new_y < dpy_y) {
if (new_x < wdpy_x || new_y < wdpy_y) {
check_black_fb();
}
do_new_fb(1);
rfbLog("check_xrandr_event: fb WxH: %dx%d\n", dpy_x, dpy_y);
rfbLog("check_xrandr_event: fb WxH: %dx%d\n", wdpy_x, wdpy_y);
}
int check_xrandr_event(char *msg) {
......@@ -6304,8 +6480,8 @@ int check_xrandr_event(char *msg) {
rfbLog(" mheight: %d mm\n", (int) rev->mheight);
rfbLog("\n");
rfbLog("check_xrandr_event: previous WxH: %dx%d\n",
dpy_x, dpy_y);
if (dpy_x == rev->width && dpy_y == rev->height &&
wdpy_x, wdpy_y);
if (wdpy_x == rev->width && wdpy_y == rev->height &&
xrandr_rotation == (int) rev->rotation) {
rfbLog("check_xrandr_event: no change detected.\n");
do_change = 0;
......@@ -6624,6 +6800,7 @@ void initialize_xevents(void) {
static int did_xcreate_simple_window = 0;
static int did_vnc_connect_prop = 0;
static int did_xfixes = 0;
static int did_xdamage = 0;
static int did_xrandr = 0;
X_LOCK;
......@@ -6656,6 +6833,10 @@ void initialize_xevents(void) {
initialize_xfixes();
did_xfixes = 1;
}
if (xdamage_present && !did_xdamage) {
initialize_xdamage();
did_xdamage = 1;
}
}
/*
......@@ -7407,7 +7588,8 @@ char *process_remote_cmd(char *cmd, int stringonly) {
Window twin;
COLON_CHECK("id:")
if (query) {
snprintf(buf, bufn, "ans=%s%s0x%lx", p, co, subwin);
snprintf(buf, bufn, "ans=%s%s0x%lx", p, co,
rootshift ? 0 : subwin);
goto qry;
}
p += strlen("id:");
......@@ -7444,7 +7626,8 @@ char *process_remote_cmd(char *cmd, int stringonly) {
Window twin;
COLON_CHECK("sid:")
if (query) {
snprintf(buf, bufn, "ans=%s%s0x%lx", p, co, subwin);
snprintf(buf, bufn, "ans=%s%s0x%lx", p, co,
!rootshift ? 0 : subwin);
goto qry;
}
p += strlen("sid:");
......@@ -7475,6 +7658,20 @@ char *process_remote_cmd(char *cmd, int stringonly) {
do_new_fb(1);
}
}
} else if (strstr(p, "clip") == p) {
COLON_CHECK("clip:")
if (query) {
snprintf(buf, bufn, "ans=%s%s%s", p, co,
NONUL(clip_str));
goto qry;
}
p += strlen("clip:");
if (clip_str) free(clip_str);
clip_str = strdup(p);
/* OK, this requires a new fb... */
do_new_fb(1);
} else if (strstr(p, "waitmapped") == p) {
if (query) {
snprintf(buf, bufn, "ans=%s:%d", p,
......@@ -8676,6 +8873,73 @@ char *process_remote_cmd(char *cmd, int stringonly) {
initialize_xfixes();
first_cursor();
} else if (!strcmp(p, "xdamage")) {
int orig = use_xdamage_hints;
if (query) {
snprintf(buf, bufn, "ans=%s:%d", p, use_xdamage_hints);
goto qry;
}
if (! xdamage_present) {
rfbLog("process_remote_cmd: cannot enable xdamage hints "
"(not supported on X display)\n");
goto done;
}
rfbLog("process_remote_cmd: enabling xdamage hints"
" (if supported).\n");
use_xdamage_hints = 1;
if (use_xdamage_hints != orig) {
initialize_xdamage();
create_xdamage();
}
} else if (!strcmp(p, "noxdamage")) {
int orig = use_xdamage_hints;
if (query) {
snprintf(buf, bufn, "ans=%s:%d", p, !use_xdamage_hints);
goto qry;
}
if (! xdamage_present) {
rfbLog("process_remote_cmd: disabling xdamage hints "
"(but not supported on X display)\n");
goto done;
}
rfbLog("process_remote_cmd: disabling xdamage hints.\n");
use_xdamage_hints = 0;
if (use_xdamage_hints != orig) {
initialize_xdamage();
destroy_xdamage();
}
} else if (strstr(p, "xd_area") == p) {
int a;
COLON_CHECK("xd_area:")
if (query) {
snprintf(buf, bufn, "ans=%s%s%d", p, co,
xdamage_max_area);
goto qry;
}
p += strlen("xd_area:");
a = atoi(p);
if (a >= 0) {
rfbLog("process_remote_cmd: setting xdamage_max_area "
"%d -> %d.\n", xdamage_max_area, a);
xdamage_max_area = a;
}
} else if (strstr(p, "xd_mem") == p) {
double a;
COLON_CHECK("xd_mem:")
if (query) {
snprintf(buf, bufn, "ans=%s%s%.3f", p, co,
xdamage_memory);
goto qry;
}
p += strlen("xd_mem:");
a = atof(p);
if (a >= 0.0) {
rfbLog("process_remote_cmd: setting xdamage_memory "
"%.3f -> %.3f.\n", xdamage_memory, a);
xdamage_memory = a;
}
} else if (strstr(p, "alphacut") == p) {
int a;
COLON_CHECK("alphacut:")
......@@ -9282,6 +9546,12 @@ char *process_remote_cmd(char *cmd, int stringonly) {
rfbLog("process_remote_cmd: disabling remote commands.\n");
accept_remote_cmds = 0; /* cannot be turned back on. */
} else if (strstr(p, "hack:") == p) { /* skip-cmd-list */
NOTAPP
p += strlen("hack:");
hack_val = atoi(p);
rfbLog("set hack_val to: %d\n", hack_val);
} else if (query) {
/* read-only variables that can only be queried: */
......@@ -9314,6 +9584,8 @@ char *process_remote_cmd(char *cmd, int stringonly) {
snprintf(buf, bufn, "aro=%s:%s", p, NONUL(users_list));
} else if (!strcmp(p, "rootshift")) {
snprintf(buf, bufn, "aro=%s:%d", p, rootshift);
} else if (!strcmp(p, "clipshift")) {
snprintf(buf, bufn, "aro=%s:%d", p, clipshift);
} else if (!strcmp(p, "scale_str")) {
snprintf(buf, bufn, "aro=%s:%s", p, NONUL(scale_str));
} else if (!strcmp(p, "scaled_x")) {
......@@ -9406,6 +9678,22 @@ char *process_remote_cmd(char *cmd, int stringonly) {
snprintf(buf, bufn, "aro=%s:%d", p, dpy_x);
} else if (!strcmp(p, "dpy_y")) {
snprintf(buf, bufn, "aro=%s:%d", p, dpy_y);
} else if (!strcmp(p, "wdpy_x")) {
snprintf(buf, bufn, "aro=%s:%d", p, wdpy_x);
} else if (!strcmp(p, "wdpy_y")) {
snprintf(buf, bufn, "aro=%s:%d", p, wdpy_y);
} else if (!strcmp(p, "off_x")) {
snprintf(buf, bufn, "aro=%s:%d", p, off_x);
} else if (!strcmp(p, "off_y")) {
snprintf(buf, bufn, "aro=%s:%d", p, off_y);
} else if (!strcmp(p, "cdpy_x")) {
snprintf(buf, bufn, "aro=%s:%d", p, cdpy_x);
} else if (!strcmp(p, "cdpy_y")) {
snprintf(buf, bufn, "aro=%s:%d", p, cdpy_y);
} else if (!strcmp(p, "coff_x")) {
snprintf(buf, bufn, "aro=%s:%d", p, coff_x);
} else if (!strcmp(p, "coff_y")) {
snprintf(buf, bufn, "aro=%s:%d", p, coff_y);
} else if (!strcmp(p, "rfbauth")) {
NOTAPPRO
} else if (!strcmp(p, "passwd")) {
......@@ -9447,6 +9735,329 @@ char *process_remote_cmd(char *cmd, int stringonly) {
return NULL;
}
/* -- xdamage.c -- */
sraRegionPtr *xdamage_regions = NULL;
int xdamage_ticker = 0;
/* for stats */
int XD_skip = 0, XD_tot = 0, XD_des = 0;
void record_desired_xdamage_rect(int x, int y, int w, int h) {
/*
* Unfortunately we currently can't trust an xdamage event
* to correspond to real screen damage. E.g. focus-in for
* mozilla (depending on wm) will mark the whole toplevel
* area as damaged, when only the border has changed.
* Similar things for terminal windows.
*
* This routine uses some heuristics to detect small enough
* damage regions that we will not have a performance problem
* if we believe them even though they are wrong. We record
* the corresponding tiles the damage regions touch.
*/
int dt_x, dt_y, nt_x1, nt_y1, nt_x2, nt_y2, nt;
int ix, iy, cnt = 0;
int area = w*h, always_accept = 0;
if (xdamage_max_area <= 0) {
always_accept = 1;
}
if (!always_accept && area > xdamage_max_area) {
return;
}
dt_x = w / tile_x;
dt_y = h / tile_y;
if (!always_accept && dt_y >= 2 && area > 1000) {
/*
* should be caught by a normal scanline poll, but we might
* as well keep if small.
*/
return;
}
nt_x1 = nfix( (x)/tile_x, ntiles_x);
nt_x2 = nfix((x+w)/tile_x, ntiles_x);
nt_y1 = nfix( (y)/tile_y, ntiles_y);
nt_y2 = nfix((y+h)/tile_y, ntiles_y);
/* loop over the rectangle of tiles (1 tile for a small input rect */
for (ix = nt_x1; ix <= nt_x2; ix++) {
for (iy = nt_y1; iy <= nt_y2; iy++) {
nt = ix + iy * ntiles_x;
cnt++;
if (! tile_has_xdamage_diff[nt]) {
XD_des++;
}
tile_has_xdamage_diff[nt] = 1;
tile_row_has_xdamage_diff[iy] = 1;
xdamage_tile_count++;
}
}
}
void collect_xdamage(int scancnt) {
#if LIBVNCSERVER_HAVE_LIBXDAMAGE
XDamageNotifyEvent *dev;
#if 0
XserverRegion xregion;
#endif
XEvent ev;
sraRegionPtr tmpregion;
sraRegionPtr reg;
static int rect_count = 0;
int nreg, ccount = 0, dcount = 0;
static time_t last_rpt = 0;
time_t now;
int x, y, w, h, x2, y2;
int i, dup, next, dup_max = 0;
#define DUPSZ 16
int dup_x[DUPSZ], dup_y[DUPSZ], dup_w[DUPSZ], dup_h[DUPSZ];
if (! xdamage_present || ! using_xdamage) {
return;
}
if (! xdamage) {
return;
}
nreg = (xdamage_memory * NSCAN) + 1;
xdamage_ticker = (xdamage_ticker+1) % nreg;
reg = xdamage_regions[xdamage_ticker];
sraRgnMakeEmpty(reg);
X_LOCK;
while (XCheckTypedEvent(dpy, xdamage_base_event_type+XDamageNotify, &ev)) {
/* TODO max cut off time in this loop? */
if (ev.type != xdamage_base_event_type + XDamageNotify) {
break;
}
dev = (XDamageNotifyEvent *) &ev;
if (dev->damage != xdamage) {
continue; /* not ours! */
}
x = dev->area.x;
y = dev->area.y;
w = dev->area.width;
h = dev->area.height;
/*
* we try to manually remove some duplicates because
* certain activities can lead to many 10's of dups
* in a row. The region work can be costly and reg is
* later used in xdamage_hint_skip loops, so it is good
* to skip them if possible.
*/
dup = 0;
for (i=0; i < dup_max; i++) {
if (dup_x[i] == x && dup_y[i] == y && dup_w[i] == w &&
dup_h[i] == h) {
dup = 1;
break;
}
}
if (dup) {
dcount++;
continue;
}
if (dup_max < DUPSZ) {
next = dup_max;
dup_max++;
} else {
next = (next+1) % DUPSZ;
}
dup_x[next] = x;
dup_y[next] = y;
dup_w[next] = w;
dup_h[next] = h;
/* translate if needed */
if (clipshift) {
/* set coords relative to fb origin */
if (0 && rootshift) {
/*
* not needed because damage is relative
* to subwin, not rootwin.
*/
x = x - off_x;
y = y - off_y;
}
if (clipshift) {
x = x - coff_x;
y = y - coff_y;
}
x2 = x + w; /* upper point */
x = nfix(x, dpy_x); /* place both in fb area */
x2 = nfix(x2, dpy_x);
w = x2 - x; /* recompute w */
y2 = y + h;
y = nfix(y, dpy_y);
y2 = nfix(y2, dpy_y);
h = y2 - y;
if (w <= 0 || h <= 0) {
continue;
}
}
record_desired_xdamage_rect(x, y, w, h);
tmpregion = sraRgnCreateRect(x, y, x + w, y + h);
sraRgnOr(reg, tmpregion);
sraRgnDestroy(tmpregion);
rect_count++;
ccount++;
}
/* clear the whole damage region for next time. XXX check */
XDamageSubtract(dpy, xdamage, None, None);
X_UNLOCK;
now = time(0);
if (! last_rpt) {
last_rpt = now;
}
if (now > last_rpt + 15) {
double rat = -1.0;
if (XD_tot) {
rat = ((double) XD_skip)/XD_tot;
}
if (0) fprintf(stderr, "skip/tot: %04d/%04d rat=%.3f rect_count: %d desired_rects: %d\n",
XD_skip, XD_tot, rat, rect_count, XD_des);
XD_skip = 0;
XD_tot = 0;
XD_des = 0;
rect_count = 0;
last_rpt = now;
}
#endif
}
int xdamage_hint_skip(int y) {
static sraRegionPtr scanline = NULL;
sraRegionPtr reg, tmpl;
int ret, i, n, nreg;
if (!xdamage_present || !using_xdamage || !use_xdamage_hints) {
return 0; /* cannot skip */
}
if (! xdamage_regions) {
return 0; /* cannot skip */
}
if (! scanline) {
scanline = sraRgnCreate();
}
tmpl = sraRgnCreateRect(0, y, dpy_x, y+1);
nreg = (xdamage_memory * NSCAN) + 1;
ret = 1;
for (i=0; i<nreg; i++) {
/* go back thru the history starting at most recent */
n = (xdamage_ticker + nreg - i) % nreg;
reg = xdamage_regions[n];
if (sraRgnEmpty(reg)) {
/* checking for emptiness is very fast */
continue;
}
sraRgnMakeEmpty(scanline);
sraRgnOr(scanline, tmpl);
if (sraRgnAnd(scanline, reg)) {
ret = 0;
break;
}
}
sraRgnDestroy(tmpl);
return ret;
}
void initialize_xdamage(void) {
sraRegionPtr *ptr;
int i, nreg;
using_xdamage = 0;
if (xdamage_present) {
if (use_xdamage_hints) {
using_xdamage = 1;
}
}
if (xdamage_regions) {
ptr = xdamage_regions;
while (*ptr != NULL) {
sraRgnDestroy(*ptr);
ptr++;
}
free(xdamage_regions);
xdamage_regions = NULL;
}
if (using_xdamage) {
nreg = (xdamage_memory * NSCAN) + 2;
xdamage_regions = (sraRegionPtr *)
malloc(nreg * sizeof(sraRegionPtr));
for (i = 0; i < nreg; i++) {
ptr = xdamage_regions+i;
if (i == nreg - 1) {
*ptr = NULL;
} else {
*ptr = sraRgnCreate();
sraRgnMakeEmpty(*ptr);
}
}
/* set so will be 0 in first collect_xdamage call */
xdamage_ticker = -1;
}
}
void create_xdamage(void) {
#if LIBVNCSERVER_HAVE_LIBXDAMAGE
if (! xdamage) {
X_LOCK;
xdamage = XDamageCreate(dpy, window, XDamageReportRawRectangles);
XDamageSubtract(dpy, xdamage, None, None);
X_UNLOCK;
rfbLog("created xdamage object: 0x%lx\n", xdamage);
}
#endif
}
void destroy_xdamage(void) {
#if LIBVNCSERVER_HAVE_LIBXDAMAGE
if (xdamage) {
X_LOCK;
XDamageDestroy(dpy, xdamage);
X_UNLOCK;
rfbLog("destroyed xdamage object: 0x%lx\n", xdamage);
xdamage = 0;
}
#endif
}
void check_xdamage_state(void) {
if (! using_xdamage || ! xdamage_present) {
return;
}
/*
* Create or destroy the Damage object as needed, we don't want
* one if no clients are connected.
*/
if (client_count) {
create_xdamage();
} else {
destroy_xdamage();
}
}
/* -- cursor.c -- */
/*
* Here begins a bit of a mess to experiment with multiple cursors
......@@ -9525,7 +10136,7 @@ static cursor_info_t cur_arrow = {NULL, NULL, 18, 18, 0, 0, 0, NULL};
/*
* It turns out we can at least detect mouse is on the root window so
* show it (under -cursorX or -X) with this familiar cursor...
* show it (under -cursor X) with this familiar cursor...
*/
static char* curs_root_data =
" "
......@@ -10868,8 +11479,8 @@ void check_x11_pointer(void) {
}
/* offset subtracted since XQueryPointer relative to rootwin */
x = root_x - off_x;
y = root_y - off_y;
x = root_x - off_x - coff_x;
y = root_y - off_y - coff_y;
/* record the cursor position in the rfb screen */
cursor_position(x, y);
......@@ -11286,8 +11897,8 @@ XImage *initialize_xdisplay_fb(void) {
if (! subwin) {
/* full screen */
window = rootwin;
dpy_x = DisplayWidth(dpy, scr);
dpy_y = DisplayHeight(dpy, scr);
dpy_x = wdpy_x = DisplayWidth(dpy, scr);
dpy_y = wdpy_y = DisplayHeight(dpy, scr);
off_x = 0;
off_y = 0;
/* this may be overridden via visual_id below */
......@@ -11302,8 +11913,8 @@ XImage *initialize_xdisplay_fb(void) {
X_UNLOCK;
clean_up_exit(1);
}
dpy_x = attr.width;
dpy_y = attr.height;
dpy_x = wdpy_x = attr.width;
dpy_y = wdpy_y = attr.height;
subwin_bs = attr.backing_store;
......@@ -11315,6 +11926,46 @@ XImage *initialize_xdisplay_fb(void) {
X_LOCK;
}
clipshift = 0;
cdpy_x = cdpy_y = coff_x = coff_y = 0;
if (clip_str) {
int w, h, x, y, bad = 0;
if (parse_geom(clip_str, &w, &h, &x, &y, wdpy_x, wdpy_y)) {
if (x < 0) {
x = 0;
}
if (y < 0) {
y = 0;
}
if (x + w > wdpy_x) {
w = wdpy_x - x;
}
if (y + h > wdpy_y) {
h = wdpy_y - y;
}
if (w <= 0 || h <= 0) {
bad = 1;
}
} else {
bad = 1;
}
if (bad) {
rfbLog("skipping invalid -clip WxH+X+Y: %s\n",
clip_str);
} else {
/* OK, change geom behind everyone's back... */
cdpy_x = w;
cdpy_y = h;
coff_x = x;
coff_y = y;
clipshift = 1;
dpy_x = cdpy_x;
dpy_y = cdpy_y;
}
}
/* initialize depth to reasonable value, visual_id may override */
depth = DefaultDepth(dpy, scr);
......@@ -11379,13 +12030,13 @@ XImage *initialize_xdisplay_fb(void) {
/* subwins can be a dicey if they are changing size... */
XTranslateCoordinates(dpy, window, rootwin, 0, 0, &subwin_x,
&subwin_y, &twin);
if (subwin_x + dpy_x > disp_x) {
if (subwin_x + wdpy_x > disp_x) {
shift = 1;
subwin_x = disp_x - dpy_x - 3;
subwin_x = disp_x - wdpy_x - 3;
}
if (subwin_y + dpy_y > disp_y) {
if (subwin_y + wdpy_y > disp_y) {
shift = 1;
subwin_y = disp_y - dpy_y - 3;
subwin_y = disp_y - wdpy_y - 3;
}
if (subwin_x < 0) {
shift = 1;
......@@ -11438,7 +12089,7 @@ XImage *initialize_xdisplay_fb(void) {
rfbLog("trapped GetImage at SUBWIN creation.\n");
if (try < subwin_tries) {
usleep(250 * 1000);
if (!get_window_size(window, &dpy_x, &dpy_y)) {
if (!get_window_size(window, &wdpy_x, &wdpy_y)) {
rfbLog("could not get size of subwin "
"0x%lx\n", subwin);
X_UNLOCK;
......@@ -11727,7 +12378,7 @@ void initialize_screen(int *argc, char **argv, XImage *fb) {
screen->serverFormat.greenMax = 0;
screen->serverFormat.blueMax = 0;
/* these main_* formats are use elsewhere by us. */
/* these main_* formats are used generally. */
main_red_shift = 0;
main_green_shift = 0;
main_blue_shift = 0;
......@@ -12080,12 +12731,12 @@ void solid_root(char *color) {
swa.background_pixmap = None;
visual.visualid = CopyFromParent;
mask = (CWOverrideRedirect|CWBackingStore|CWSaveUnder|CWBackPixmap);
expose = XCreateWindow(dpy, window, 0, 0, dpy_x, dpy_y, 0, depth,
expose = XCreateWindow(dpy, window, 0, 0, wdpy_x, wdpy_y, 0, depth,
InputOutput, &visual, mask, &swa);
if (! color) {
/* restore the root window from the XImage snapshot */
pixmap = XCreatePixmap(dpy, window, dpy_x, dpy_y, depth);
pixmap = XCreatePixmap(dpy, window, wdpy_x, wdpy_y, depth);
if (! image) {
/* whoops */
......@@ -12100,7 +12751,7 @@ void solid_root(char *color) {
gcv.plane_mask = AllPlanes;
gc = XCreateGC(dpy, window, GCFunction|GCPlaneMask, &gcv);
XPutImage(dpy, pixmap, gc, image, 0, 0, 0, 0, dpy_x, dpy_y);
XPutImage(dpy, pixmap, gc, image, 0, 0, 0, 0, wdpy_x, wdpy_y);
gcv.foreground = gcv.background = BlackPixel(dpy, scr);
gc = XCreateGC(dpy, window, GCForeground|GCBackground, &gcv);
......@@ -12130,14 +12781,14 @@ void solid_root(char *color) {
iswa.save_under = False;
iswa.background_pixmap = ParentRelative;
iwin = XCreateWindow(dpy, window, 0, 0, dpy_x, dpy_y, 0, depth,
InputOutput, &visual, mask, &iswa);
iwin = XCreateWindow(dpy, window, 0, 0, wdpy_x, wdpy_y, 0,
depth, InputOutput, &visual, mask, &iswa);
rfbLog("snapshotting background...\n");
XMapWindow(dpy, iwin);
XSync(dpy, False);
image = XGetImage(dpy, iwin, 0, 0, dpy_x, dpy_y, AllPlanes,
image = XGetImage(dpy, iwin, 0, 0, wdpy_x, wdpy_y, AllPlanes,
ZPixmap);
XSync(dpy, False);
XDestroyWindow(dpy, iwin);
......@@ -12191,7 +12842,7 @@ void solid_cde(char *color) {
swa.background_pixmap = None;
visual.visualid = CopyFromParent;
mask = (CWOverrideRedirect|CWBackingStore|CWSaveUnder|CWBackPixmap);
expose = XCreateWindow(dpy, window, 0, 0, dpy_x, dpy_y, 0, depth,
expose = XCreateWindow(dpy, window, 0, 0, wdpy_x, wdpy_y, 0, depth,
InputOutput, &visual, mask, &swa);
if (! color) {
......@@ -12212,7 +12863,8 @@ void solid_cde(char *color) {
continue;
}
pixmap = XCreatePixmap(dpy, twin, dpy_x, dpy_y, depth);
pixmap = XCreatePixmap(dpy, twin, wdpy_x, wdpy_y,
depth);
/* draw the image to a pixmap: */
gcv.function = GXcopy;
......@@ -12220,7 +12872,7 @@ void solid_cde(char *color) {
gc = XCreateGC(dpy, twin, GCFunction|GCPlaneMask, &gcv);
XPutImage(dpy, pixmap, gc, image[n], 0, 0, 0, 0,
dpy_x, dpy_y);
wdpy_x, wdpy_y);
gcv.foreground = gcv.background = BlackPixel(dpy, scr);
gc = XCreateGC(dpy, twin, GCForeground|GCBackground,
......@@ -12366,7 +13018,7 @@ void solid_cde(char *color) {
iswa.background_pixmap = ParentRelative;
visual.visualid = CopyFromParent;
iwin = XCreateWindow(dpy, twin, 0, 0, dpy_x, dpy_y,
iwin = XCreateWindow(dpy, twin, 0, 0, wdpy_x, wdpy_y,
0, depth, InputOutput, &visual, mask, &iswa);
rfbLog("snapshotting CDE backdrop ws%d 0x%lx -> "
......@@ -12374,7 +13026,7 @@ void solid_cde(char *color) {
XMapWindow(dpy, iwin);
XSync(dpy, False);
image[n] = XGetImage(dpy, iwin, 0, 0, dpy_x, dpy_y,
image[n] = XGetImage(dpy, iwin, 0, 0, wdpy_x, wdpy_y,
AllPlanes, ZPixmap);
XSync(dpy, False);
XDestroyWindow(dpy, iwin);
......@@ -12673,21 +13325,7 @@ void initialize_blackouts(char *list) {
p = strtok(blist, ", \t");
while (p) {
/* handle +/-x and +/-y */
if (sscanf(p, "%dx%d+%d+%d", &w, &h, &x, &y) == 4) {
;
} else if (sscanf(p, "%dx%d-%d+%d", &w, &h, &x, &y) == 4) {
w = nabs(w);
x = dpy_x - x - w;
} else if (sscanf(p, "%dx%d+%d-%d", &w, &h, &x, &y) == 4) {
h = nabs(h);
y = dpy_y - y - h;
} else if (sscanf(p, "%dx%d-%d-%d", &w, &h, &x, &y) == 4) {
w = nabs(w);
h = nabs(h);
x = dpy_x - x - w;
y = dpy_y - y - h;
} else {
if (! parse_geom(p, &w, &h, &x, &y, dpy_x, dpy_y)) {
if (*p != '\0') {
rfbLog("skipping invalid geometry: %s\n", p);
}
......@@ -13055,15 +13693,6 @@ static int nap_ok = 0, nap_diff_count = 0;
static int scan_count = 0; /* indicates which scan pattern we are on */
static int scan_in_progress = 0;
/* scan pattern jitter from x0rfbserver */
#define NSCAN 32
static int scanlines[NSCAN] = {
0, 16, 8, 24, 4, 20, 12, 28,
10, 26, 18, 2, 22, 6, 30, 14,
1, 17, 9, 25, 7, 23, 15, 31,
19, 3, 27, 11, 29, 13, 5, 21
};
typedef struct tile_change_region {
/* start and end lines, along y, of the changed area inside a tile. */
unsigned short first_line, last_line;
......@@ -13087,6 +13716,10 @@ void initialize_tiles(void) {
tile_has_diff = (unsigned char *)
malloc((size_t) (ntiles * sizeof(unsigned char)));
tile_has_xdamage_diff = (unsigned char *)
malloc((size_t) (ntiles * sizeof(unsigned char)));
tile_row_has_xdamage_diff = (unsigned char *)
malloc((size_t) (ntiles_y * sizeof(unsigned char)));
tile_tried = (unsigned char *)
malloc((size_t) (ntiles * sizeof(unsigned char)));
tile_copied = (unsigned char *)
......@@ -13109,6 +13742,14 @@ void free_tiles(void) {
free(tile_has_diff);
tile_has_diff = NULL;
}
if (tile_has_xdamage_diff) {
free(tile_has_xdamage_diff);
tile_has_xdamage_diff = NULL;
}
if (tile_row_has_xdamage_diff) {
free(tile_row_has_xdamage_diff);
tile_row_has_xdamage_diff = NULL;
}
if (tile_tried) {
free(tile_tried);
tile_tried = NULL;
......@@ -15032,7 +15673,7 @@ static int scan_display(int ystart, int rescan) {
int pixelsize = bpp/8;
int x, y, w, n;
int tile_count = 0;
int whole_line = 1, nodiffs = 0;
int nodiffs = 0, diff_hint;
y = ystart;
......@@ -15043,6 +15684,15 @@ static int scan_display(int ystart, int rescan) {
while (y < dpy_y) {
if (using_xdamage) {
XD_tot++;
if (xdamage_hint_skip(y)) {
XD_skip++;
y += NSCAN;
continue;
}
}
/* grab the horizontal scanline from the display: */
X_LOCK;
XRANDR_SET_TRAP_RET(-1, "scan_display-set");
......@@ -15054,7 +15704,7 @@ static int scan_display(int ystart, int rescan) {
src = scanline->data;
dst = main_fb + y * main_bytes_per_line;
if (whole_line && ! memcmp(dst, src, main_bytes_per_line)) {
if (! memcmp(dst, src, main_bytes_per_line)) {
/* no changes anywhere in scan line */
nodiffs = 1;
if (! rescan) {
......@@ -15066,6 +15716,7 @@ static int scan_display(int ystart, int rescan) {
x = 0;
while (x < dpy_x) {
n = (x/tile_x) + (y/tile_y) * ntiles_x;
diff_hint = 0;
if (blackouts) {
if (blackout_line_skip(n, x, y, rescan,
......@@ -15081,6 +15732,10 @@ static int scan_display(int ystart, int rescan) {
x += NSCAN;
continue;
}
} else if (xdamage_tile_count &&
tile_has_xdamage_diff[n]) {
tile_has_xdamage_diff[n] = 2;
diff_hint = 1;
}
/* set ptrs to correspond to the x offset: */
......@@ -15094,7 +15749,7 @@ static int scan_display(int ystart, int rescan) {
w = NSCAN;
}
if (memcmp(dst, src, w * pixelsize)) {
if (diff_hint || memcmp(dst, src, w * pixelsize)) {
/* found a difference, record it: */
if (! blackouts) {
tile_has_diff[n] = 1;
......@@ -15129,9 +15784,15 @@ int scan_for_updates(int count_only) {
double frac3 = 0.02; /* do scan_display() again after copy_tiles() */
for (i=0; i < ntiles; i++) {
tile_has_diff[i] = 0;
tile_has_xdamage_diff[i] = 0;
tile_tried[i] = 0;
tile_copied[i] = 0;
}
for (i=0; i < ntiles_y; i++) {
/* could be useful, currently not used */
tile_row_has_xdamage_diff[i] = 0;
}
xdamage_tile_count = 0;
/*
* n.b. this program has only been tested so far with
......@@ -15142,15 +15803,16 @@ int scan_for_updates(int count_only) {
scan_count++;
scan_count %= NSCAN;
if (scan_count % (NSCAN/4) == 0) {
/* some periodic maintenance */
if (subwin) {
set_offset(); /* follow the subwindow */
}
if (indexed_color) { /* check for changed colormap */
if (indexed_color && scan_count % 4 == 0) {
/* check for changed colormap */
set_colormap(0);
}
if (using_xdamage) {
collect_xdamage(scan_count);
}
}
......@@ -15172,6 +15834,20 @@ int scan_for_updates(int count_only) {
return tile_count;
}
if (xdamage_tile_count) {
/* pick up "known" damaged tiles we missed in scan_display() */
for (i=0; i < ntiles; i++) {
if (tile_has_diff[i]) {
continue;
}
if (tile_has_xdamage_diff[i] == 1) {
tile_has_xdamage_diff[i] = 2;
tile_has_diff[i] = 1;
tile_count++;
}
}
}
nap_set(tile_count);
if (fs_factor && frac1 >= fs_frac) {
......@@ -15349,9 +16025,11 @@ void run_gui(char *gui_xdisplay, int connect_to_x11vnc, int simple_gui,
exit(0);
}
if (getenv("DISPLAY") != NULL) {
/* worst case */
x11vnc_xdisplay = strdup(getenv("DISPLAY"));
}
if (use_dpy) {
/* better */
x11vnc_xdisplay = strdup(use_dpy);
}
if (connect_to_x11vnc) {
......@@ -15360,6 +16038,8 @@ void run_gui(char *gui_xdisplay, int connect_to_x11vnc, int simple_gui,
if (! client_connect_file) {
if (getenv("XAUTHORITY") != NULL) {
old_xauth = strdup(getenv("XAUTHORITY"));
} else {
old_xauth = strdup("");
}
dpy = XOpenDisplay(x11vnc_xdisplay);
if (! dpy && auth_file) {
......@@ -15367,11 +16047,12 @@ void run_gui(char *gui_xdisplay, int connect_to_x11vnc, int simple_gui,
dpy = XOpenDisplay(x11vnc_xdisplay);
}
if (! dpy && ! x11vnc_xdisplay) {
/* worstest case */
x11vnc_xdisplay = strdup(":0");
dpy = XOpenDisplay(x11vnc_xdisplay);
}
if (! dpy) {
fprintf(stderr, "gui: could not open "
fprintf(stderr, "gui: could not open x11vnc "
"display: %s\n", NONUL(x11vnc_xdisplay));
exit(1);
}
......@@ -15398,7 +16079,7 @@ void run_gui(char *gui_xdisplay, int connect_to_x11vnc, int simple_gui,
}
set_env("X11VNC_XDISPLAY", x11vnc_xdisplay);
if (getenv("XAUTHORITY") != NULL) {
set_env("X11VNC_XAUTHORITY", getenv("XAUTHORITY"));
set_env("X11VNC_AUTH_FILE", getenv("XAUTHORITY"));
}
if (rc == 0) {
fprintf(stderr, "gui: ping succeeded.\n");
......@@ -15411,7 +16092,15 @@ void run_gui(char *gui_xdisplay, int connect_to_x11vnc, int simple_gui,
XCloseDisplay(dpy);
}
if (old_xauth) {
if (*old_xauth == '\0') {
/* wasn't set, hack it out if it is now */
char *xauth = getenv("XAUTHORITY");
if (xauth) {
*(xauth-2) = '_'; /* yow */
}
} else {
set_env("XAUTHORITY", old_xauth);
}
free(old_xauth);
}
}
......@@ -15459,8 +16148,6 @@ void run_gui(char *gui_xdisplay, int connect_to_x11vnc, int simple_gui,
if (simple_gui) {
set_env("X11VNC_SIMPLE_GUI", "1");
}
if (auth_file) {
}
sprintf(cmd, "%s -", wish);
tmpf = tmpfile();
......@@ -16509,6 +17196,10 @@ static void watch_loop(void) {
continue;
}
if (using_xdamage) {
check_xdamage_state();
}
if (watch_bell) {
/* n.b. assumes -nofb folks do not want bell... */
check_bell_event();
......@@ -16618,6 +17309,12 @@ static void print_help(int mode) {
" shifts a root view to it: this shows SaveUnders menus,\n"
" etc, although they will be clipped if they extend beyond\n"
" the window.\n"
"-clip WxH+X+Y Only show the sub-region of the full display that\n"
" corresponds to the rectangle with size WxH and offset\n"
" +X+Y. The VNC display has size WxH (i.e. smaller than\n"
" the full display). This also works for -id/-sid mode\n"
" where the offset is relative to the upper left corner\n"
" of the selected window.\n"
"-flashcmap In 8bpp indexed color, let the installed colormap flash\n"
" as the pointer moves from window to window (slow).\n"
"-notruecolor For 8bpp displays, force indexed color (i.e. a colormap)\n"
......@@ -17292,6 +17989,36 @@ static void print_help(int mode) {
" to really throttle down the screen polls (i.e. sleep\n"
" for about 1.5 secs). Use 0 to disable. Default: %d\n"
"\n"
"-noxdamage Do not use the X DAMAGE extension to detect framebuffer\n"
" changes even if it is available.\n"
"\n"
" x11vnc's use of the DAMAGE extension: 1) significantly\n"
" reduces the load when the screen is not changing much,\n"
" and 2) detects changed areas (small ones by default)\n"
" more quickly.\n"
"\n"
" Currently the DAMAGE extension is overly conservative\n"
" and often reports large areas (e.g. a whole terminal\n"
" or browser window) as damaged even though the actual\n"
" changed region is much smaller (sometimes just a few\n"
" pixels). So heuristics were introduced to skip large\n"
" areas and use the damage rectangles only as \"hints\"\n"
" for the traditional scanline polling. The following\n"
" tuning parameters are introduced to adjust this\n"
" behavior:\n"
"\n"
"-xd_area A Set the largest DAMAGE rectangle area \"A\" (in\n"
" pixels: width * height) to trust as truly damaged:\n"
" the rectangle will be copied from the framebuffer\n"
" (slow) no matter what. Set to zero to trust *all*\n"
" rectangles. Default: %d\n"
"-xd_mem f Set how long DAMAGE rectangles should be \"remembered\",\n"
" \"f\" is a floating point number and is in units of the\n"
" scanline repeat cycle time (%d iterations). The default\n"
" (%.1f) should give no painting problems. Increase it if\n"
" there are problems or decrease it to live on the edge\n"
" (perhaps useful on a slow machine).\n"
"\n"
"-sigpipe string Broken pipe (SIGPIPE) handling. \"string\" can be\n"
" \"ignore\" or \"exit\". For \"ignore\" libvncserver\n"
" will handle the abrupt loss of a client and continue,\n"
......@@ -17417,6 +18144,7 @@ static void print_help(int mode) {
" id:windowid set -id window to \"windowid\". empty\n"
" or \"root\" to go back to root window\n"
" sid:windowid set -sid window to \"windowid\"\n"
" clip:WxH+X+Y set -clip mode to \"WxH+X+Y\"\n"
" flashcmap enable -flashcmap mode.\n"
" noflashcmap disable -flashcmap mode.\n"
" notruecolor enable -notruecolor mode.\n"
......@@ -17559,6 +18287,10 @@ static void print_help(int mode) {
" nap enable -nap mode.\n"
" nonap disable -nap mode.\n"
" sb:n set -sb to n s, same as screen_blank:n\n"
" xdamage enable xdamage polling hints.\n"
" noxdamage disable xdamage polling hints.\n"
" xd_area:A set -xd_area max pixel area to \"A\"\n"
" xd_mem:f set -xd_mem remembrance to \"f\"\n"
" fs:frac set -fs fraction to \"frac\", e.g. 0.5\n"
" gaps:n set -gaps to n.\n"
" grow:n set -grow to n.\n"
......@@ -17625,7 +18357,7 @@ static void print_help(int mode) {
" variables correspond to the presence of X extensions):\n"
"\n"
" ans= stop quit exit shutdown ping blacken zero\n"
" refresh reset close disconnect id sid waitmapped\n"
" refresh reset close disconnect id sid clip waitmapped\n"
" nowaitmapped flashcmap noflashcmap truecolor notruecolor\n"
" overlay nooverlay overlay_cursor overlay_yescursor\n"
" nooverlay_nocursor nooverlay_cursor nooverlay_yescursor\n"
......@@ -17641,9 +18373,10 @@ static void print_help(int mode) {
" remap repeat norepeat fb nofb bell nobell sel\n"
" nosel primary noprimary cursorshape nocursorshape\n"
" cursorpos nocursorpos cursor show_cursor noshow_cursor\n"
" nocursor xfixes noxfixes alphacut alphafrac alpharemove\n"
" noalpharemove alphablend noalphablend xwarp xwarppointer\n"
" noxwarp noxwarppointer buttonmap dragging nodragging\n"
" nocursor xfixes noxfixes xdamage noxdamage xd_area\n"
" xd_mem alphacut alphafrac alpharemove noalpharemove\n"
" alphablend noalphablend xwarp xwarppointer noxwarp\n"
" noxwarppointer buttonmap dragging nodragging\n"
" pointer_mode pm input_skip input client_input speeds\n"
" debug_pointer dp nodebug_pointer nodp debug_keyboard dk\n"
" nodebug_keyboard nodk deferupdate defer wait rfbwait\n"
......@@ -17654,15 +18387,16 @@ static void print_help(int mode) {
" nodontdisconnect desktop noremote\n"
"\n"
" aro= display vncdisplay desktopname http_url auth\n"
" users rootshift scale_str scaled_x scaled_y scale_numer\n"
" scale_denom scale_fac scaling_noblend scaling_nomult4\n"
" scaling_pad scaling_interpolate inetd safer unsafe\n"
" passwdfile using_shm logfile o rc norc h help V version\n"
" lastmod bg sigpipe threads clients client_count pid\n"
" ext_xtest ext_xkb ext_xshm ext_xinerama ext_overlay\n"
" ext_xfixes ext_xdamage ext_xrandr rootwin num_buttons\n"
" button_mask mouse_x mouse_y bpp depth indexed_color\n"
" dpy_x dpy_y rfbauth passwd\n"
" users rootshift clipshift scale_str scaled_x scaled_y\n"
" scale_numer scale_denom scale_fac scaling_noblend\n"
" scaling_nomult4 scaling_pad scaling_interpolate inetd\n"
" safer unsafe passwdfile using_shm logfile o rc norc\n"
" h help V version lastmod bg sigpipe threads clients\n"
" client_count pid ext_xtest ext_xkb ext_xshm ext_xinerama\n"
" ext_overlay ext_xfixes ext_xdamage ext_xrandr rootwin\n"
" num_buttons button_mask mouse_x mouse_y bpp depth\n"
" indexed_color dpy_x dpy_y wdpy_x wdpy_y off_x off_y\n"
" cdpy_x cdpy_y coff_x coff_y rfbauth passwd\n"
"\n"
"-sync By default -remote commands are run asynchronously, that\n"
" is, the request is posted and the program immediately\n"
......@@ -17761,6 +18495,7 @@ static void print_help(int mode) {
waitms,
take_naps ? "take naps":"no naps",
screen_blank,
xdamage_max_area, NSCAN, xdamage_memory,
use_threads ? "-threads":"-nothreads",
fs_frac,
gaps_fill,
......@@ -18126,6 +18861,7 @@ int main(int argc, char* argv[]) {
int vpw_loc = -1;
int dt = 0, bg = 0;
int got_rfbwait = 0, got_deferupdate = 0, got_defer = 0;
int got_noxdamage = 0;
/* used to pass args we do not know about to rfbGetScreen(): */
int argc_vnc = 1; char *argv_vnc[128];
......@@ -18211,6 +18947,9 @@ int main(int argc, char* argv[]) {
}
} else if (!strcmp(arg, "-waitmapped")) {
subwin_wait_mapped = 1;
} else if (!strcmp(arg, "-clip")) {
CHECK_ARGC
clip_str = strdup(argv[++i]);
} else if (!strcmp(arg, "-flashcmap")) {
flash_cmap = 1;
} else if (!strcmp(arg, "-notruecolor")) {
......@@ -18468,6 +19207,24 @@ int main(int argc, char* argv[]) {
} else if (!strcmp(arg, "-sb")) {
CHECK_ARGC
screen_blank = atoi(argv[++i]);
} else if (!strcmp(arg, "-noxdamage")) {
using_xdamage = 0;
use_xdamage_hints = 0;
got_noxdamage = 1;
} else if (!strcmp(arg, "-xd_area")) {
int tn;
CHECK_ARGC
tn = atoi(argv[++i]);
if (tn >= 0) {
xdamage_max_area = tn;
}
} else if (!strcmp(arg, "-xd_mem")) {
double f;
CHECK_ARGC
f = atof(argv[++i]);
if (f >= 0.0) {
xdamage_memory = f;
}
} else if (!strcmp(arg, "-sigpipe")) {
CHECK_ARGC
if (known_sigpipe_mode(argv[++i])) {
......@@ -18820,6 +19577,8 @@ int main(int argc, char* argv[]) {
: "null");
fprintf(stderr, " subwin: 0x%lx\n", subwin);
fprintf(stderr, " -sid mode: %d\n", rootshift);
fprintf(stderr, " clip: %s\n", clip_str ? clip_str
: "null");
fprintf(stderr, " flashcmap: %d\n", flash_cmap);
fprintf(stderr, " force_idx: %d\n", force_indexed_color);
fprintf(stderr, " visual: %s\n", visual_str ? visual_str
......@@ -18909,6 +19668,9 @@ int main(int argc, char* argv[]) {
fprintf(stderr, " waitms: %d\n", waitms);
fprintf(stderr, " take_naps: %d\n", take_naps);
fprintf(stderr, " sb: %d\n", screen_blank);
fprintf(stderr, " xdamage: %d\n", !got_noxdamage);
fprintf(stderr, " xd_area: %d\n", xdamage_max_area);
fprintf(stderr, " xd_mem: %.3f\n", xdamage_memory);
fprintf(stderr, " sigpipe: %s\n", sigpipe
? sigpipe : "null");
fprintf(stderr, " threads: %d\n", use_threads);
......@@ -19050,6 +19812,12 @@ int main(int argc, char* argv[]) {
xdamage_present = 1;
}
#endif
if (! quiet && xdamage_present && ! got_noxdamage) {
rfbLog("X DAMAGE available on display, using it for"
" polling hints\n");
rfbLog(" to disable this behavior use: "
"'-noxdamage'\n");
}
overlay_present = 0;
#ifdef SOLARIS_OVERLAY
......
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