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> 2005-03-05 Karl Runge <runge@karlrunge.com>
* autoconf: rpm -> rpmbuild and echo -n -> printf * 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> 2005-03-04 Karl Runge <runge@karlrunge.com>
* add changes to couple with -listen option, in particular * add changes to couple with -listen option, in particular
the behavior of -localhost and remote control cmds. 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 ...@@ -115,6 +115,7 @@ Screen
flashcmap flashcmap
notruecolor notruecolor
-- --
clip:
=P blackout: =P blackout:
xinerama xinerama
-- --
...@@ -139,12 +140,16 @@ Keyboard ...@@ -139,12 +140,16 @@ Keyboard
Pointer Pointer
=D-C:none,arrow,X,some,most cursor: =D-C:none,arrow,X,some,most cursor:
noxfixes
noalphablend
-- --
cursorpos cursorpos
=D nocursorshape =D nocursorshape
-- --
noxfixes
noalphablend
alphacut:
alphafrac:
alpharemove
--
buttonmap: buttonmap:
-- --
xwarppointer xwarppointer
...@@ -220,10 +225,6 @@ Tuning ...@@ -220,10 +225,6 @@ Tuning
noshm noshm
flipbyteorder flipbyteorder
onetile onetile
--
alphacut:
alphafrac:
alpharemove
-- D -- D
speeds: speeds:
=D wait: =D wait:
...@@ -237,6 +238,11 @@ Tuning ...@@ -237,6 +238,11 @@ Tuning
fuzz: fuzz:
snapfb snapfb
-- --
xdamage
xd_mem:
xd_area:
xd_width:
--
threads threads
-- --
progressive: progressive:
...@@ -2042,17 +2048,18 @@ proc client_dialog {client} { ...@@ -2042,17 +2048,18 @@ proc client_dialog {client} {
global menu_var text_area cleanup_window item_bool global menu_var text_area cleanup_window item_bool
append_text "\nClient info string: $client\n\n" append_text "\nClient info string: $client\n\n"
if {[regexp {^(.*):(.*):(.*):(.*):(.*):(.*)$} \ if {[regexp {^(.*):(.*):(.*):(.*):(.*):(.*):(.*)$} \
$client m0 m1 m2 m3 m4 m5 m6]} { $client m0 m1 m2 m3 m4 m5 m6 m7]} {
# id:ip:port:hostname:input:loginvo # id:ip:port:user:hostname:input:loginvo
set cid $m1 set cid $m1
set ip $m2 set ip $m2
set port $m3 set port $m3
set host $m4 set user $m4
set host $m5
regsub {\..*$} $host "" host regsub {\..*$} $host "" host
set input $m5 set input $m6
set logvo $m6 set logvo $m7
append_text "Host: $host, Port: $port, IP: $ip, Id: $cid\n" append_text "Host: $host, Port: $port, User: $user, IP: $ip, Id: $cid\n"
append_text " - originally logged in as: " append_text " - originally logged in as: "
if {$logvo == "1" } { if {$logvo == "1" } {
append_text "View-Only Client\n" append_text "View-Only Client\n"
...@@ -2184,10 +2191,10 @@ proc update_clients_menu {list} { ...@@ -2184,10 +2191,10 @@ proc update_clients_menu {list} {
$subm add separator $subm add separator
set count 0 set count 0
foreach client [split $list ","] { foreach client [split $list ","] {
if {[regexp {^(.*):(.*):(.*):(.*):(.*):(.*)$} \ if {[regexp {^(.*):(.*):(.*):(.*):(.*):(.*):(.*)$} \
$client m0 m1 m2 m3 m4 m5 m6]} { $client m0 m1 m2 m3 m4 m5 m6 m7]} {
# id:ip:port:hostname:input:loginvo # id:ip:port:user:hostname:input:loginvo
set host $m4 set host $m5
regsub {\..*$} $host "" host regsub {\..*$} $host "" host
set clabel "$host $m1" set clabel "$host $m1"
} else { } else {
......
...@@ -121,6 +121,7 @@ ...@@ -121,6 +121,7 @@
" flashcmap\n" " flashcmap\n"
" notruecolor\n" " notruecolor\n"
" --\n" " --\n"
" clip:\n"
" =P blackout:\n" " =P blackout:\n"
" xinerama\n" " xinerama\n"
" --\n" " --\n"
...@@ -145,12 +146,16 @@ ...@@ -145,12 +146,16 @@
"\n" "\n"
"Pointer\n" "Pointer\n"
" =D-C:none,arrow,X,some,most cursor:\n" " =D-C:none,arrow,X,some,most cursor:\n"
" noxfixes\n"
" noalphablend\n"
" --\n" " --\n"
" cursorpos\n" " cursorpos\n"
" =D nocursorshape\n" " =D nocursorshape\n"
" --\n" " --\n"
" noxfixes\n"
" noalphablend\n"
" alphacut:\n"
" alphafrac:\n"
" alpharemove\n"
" --\n"
" buttonmap:\n" " buttonmap:\n"
" --\n" " --\n"
" xwarppointer\n" " xwarppointer\n"
...@@ -226,10 +231,6 @@ ...@@ -226,10 +231,6 @@
" noshm\n" " noshm\n"
" flipbyteorder\n" " flipbyteorder\n"
" onetile\n" " onetile\n"
" --\n"
" alphacut:\n"
" alphafrac:\n"
" alpharemove\n"
" -- D\n" " -- D\n"
" speeds:\n" " speeds:\n"
" =D wait:\n" " =D wait:\n"
...@@ -243,6 +244,11 @@ ...@@ -243,6 +244,11 @@
" fuzz:\n" " fuzz:\n"
" snapfb\n" " snapfb\n"
" --\n" " --\n"
" xdamage\n"
" xd_mem:\n"
" xd_area:\n"
" xd_width:\n"
" --\n"
" threads\n" " threads\n"
" --\n" " --\n"
" progressive:\n" " progressive:\n"
...@@ -2048,17 +2054,18 @@ ...@@ -2048,17 +2054,18 @@
" global menu_var text_area cleanup_window item_bool\n" " global menu_var text_area cleanup_window item_bool\n"
"\n" "\n"
" append_text \"\\nClient info string: $client\\n\\n\"\n" " append_text \"\\nClient info string: $client\\n\\n\"\n"
" if {[regexp {^(.*):(.*):(.*):(.*):(.*):(.*)$} \\\n" " if {[regexp {^(.*):(.*):(.*):(.*):(.*):(.*):(.*)$} \\\n"
" $client m0 m1 m2 m3 m4 m5 m6]} {\n" " $client m0 m1 m2 m3 m4 m5 m6 m7]} {\n"
" # id:ip:port:hostname:input:loginvo\n" " # id:ip:port:user:hostname:input:loginvo\n"
" set cid $m1\n" " set cid $m1\n"
" set ip $m2\n" " set ip $m2\n"
" set port $m3\n" " set port $m3\n"
" set host $m4\n" " set user $m4\n"
" set host $m5\n"
" regsub {\\..*$} $host \"\" host\n" " regsub {\\..*$} $host \"\" host\n"
" set input $m5\n" " set input $m6\n"
" set logvo $m6\n" " set logvo $m7\n"
" append_text \"Host: $host, Port: $port, IP: $ip, Id: $cid\\n\"\n" " append_text \"Host: $host, Port: $port, User: $user, IP: $ip, Id: $cid\\n\"\n"
" append_text \" - originally logged in as: \"\n" " append_text \" - originally logged in as: \"\n"
" if {$logvo == \"1\" } {\n" " if {$logvo == \"1\" } {\n"
" append_text \"View-Only Client\\n\"\n" " append_text \"View-Only Client\\n\"\n"
...@@ -2190,10 +2197,10 @@ ...@@ -2190,10 +2197,10 @@
" $subm add separator\n" " $subm add separator\n"
" set count 0\n" " set count 0\n"
" foreach client [split $list \",\"] {\n" " foreach client [split $list \",\"] {\n"
" if {[regexp {^(.*):(.*):(.*):(.*):(.*):(.*)$} \\\n" " if {[regexp {^(.*):(.*):(.*):(.*):(.*):(.*):(.*)$} \\\n"
" $client m0 m1 m2 m3 m4 m5 m6]} {\n" " $client m0 m1 m2 m3 m4 m5 m6 m7]} {\n"
" # id:ip:port:hostname:input:loginvo\n" " # id:ip:port:user:hostname:input:loginvo\n"
" set host $m4\n" " set host $m5\n"
" regsub {\\..*$} $host \"\" host\n" " regsub {\\..*$} $host \"\" host\n"
" set clabel \"$host $m1\"\n" " set clabel \"$host $m1\"\n"
" } else {\n" " } else {\n"
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
.TH X11VNC "1" "March 2005" "x11vnc " "User Commands" .TH X11VNC "1" "March 2005" "x11vnc " "User Commands"
.SH NAME .SH NAME
x11vnc - allow VNC connections to real X11 displays 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 .SH SYNOPSIS
.B x11vnc .B x11vnc
[OPTION]... [OPTION]...
...@@ -89,6 +89,15 @@ shifts a root view to it: this shows SaveUnders menus, ...@@ -89,6 +89,15 @@ shifts a root view to it: this shows SaveUnders menus,
etc, although they will be clipped if they extend beyond etc, although they will be clipped if they extend beyond
the window. the window.
.PP .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 \fB-flashcmap\fR
.IP .IP
In 8bpp indexed color, let the installed colormap flash In 8bpp indexed color, let the installed colormap flash
...@@ -994,6 +1003,43 @@ Time in seconds after NO activity (e.g. screen blank) ...@@ -994,6 +1003,43 @@ Time in seconds after NO activity (e.g. screen blank)
to really throttle down the screen polls (i.e. sleep to really throttle down the screen polls (i.e. sleep
for about 1.5 secs). Use 0 to disable. Default: 60 for about 1.5 secs). Use 0 to disable. Default: 60
.PP .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 \fB-sigpipe\fR \fIstring\fR
.IP .IP
Broken pipe (SIGPIPE) handling. \fIstring\fR can be Broken pipe (SIGPIPE) handling. \fIstring\fR can be
...@@ -1149,6 +1195,8 @@ id:windowid set \fB-id\fR window to "windowid". empty ...@@ -1149,6 +1195,8 @@ id:windowid set \fB-id\fR window to "windowid". empty
.IP .IP
sid:windowid set \fB-sid\fR window to "windowid" sid:windowid set \fB-sid\fR window to "windowid"
.IP .IP
clip:WxH+X+Y set \fB-clip\fR mode to "WxH+X+Y"
.IP
flashcmap enable \fB-flashcmap\fR mode. flashcmap enable \fB-flashcmap\fR mode.
.IP .IP
noflashcmap disable \fB-flashcmap\fR mode. noflashcmap disable \fB-flashcmap\fR mode.
...@@ -1387,6 +1435,14 @@ nonap disable \fB-nap\fR mode. ...@@ -1387,6 +1435,14 @@ nonap disable \fB-nap\fR mode.
.IP .IP
sb:n set \fB-sb\fR to n s, same as screen_blank:n sb:n set \fB-sb\fR to n s, same as screen_blank:n
.IP .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 fs:frac set \fB-fs\fR fraction to "frac", e.g. 0.5
.IP .IP
gaps:n set \fB-gaps\fR to n. gaps:n set \fB-gaps\fR to n.
...@@ -1491,7 +1547,7 @@ the returned value corresponds to (hint: the ext_* ...@@ -1491,7 +1547,7 @@ the returned value corresponds to (hint: the ext_*
variables correspond to the presence of X extensions): variables correspond to the presence of X extensions):
.IP .IP
ans= stop quit exit shutdown ping blacken zero 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 nowaitmapped flashcmap noflashcmap truecolor notruecolor
overlay nooverlay overlay_cursor overlay_yescursor overlay nooverlay overlay_cursor overlay_yescursor
nooverlay_nocursor nooverlay_cursor nooverlay_yescursor nooverlay_nocursor nooverlay_cursor nooverlay_yescursor
...@@ -1507,9 +1563,10 @@ clear_mods noclear_mods clear_keys noclear_keys ...@@ -1507,9 +1563,10 @@ clear_mods noclear_mods clear_keys noclear_keys
remap repeat norepeat fb nofb bell nobell sel remap repeat norepeat fb nofb bell nobell sel
nosel primary noprimary cursorshape nocursorshape nosel primary noprimary cursorshape nocursorshape
cursorpos nocursorpos cursor show_cursor noshow_cursor cursorpos nocursorpos cursor show_cursor noshow_cursor
nocursor xfixes noxfixes alphacut alphafrac alpharemove nocursor xfixes noxfixes xdamage noxdamage xd_area
noalpharemove alphablend noalphablend xwarp xwarppointer xd_mem alphacut alphafrac alpharemove noalpharemove
noxwarp noxwarppointer buttonmap dragging nodragging alphablend noalphablend xwarp xwarppointer noxwarp
noxwarppointer buttonmap dragging nodragging
pointer_mode pm input_skip input client_input speeds pointer_mode pm input_skip input client_input speeds
debug_pointer dp nodebug_pointer nodp debug_keyboard dk debug_pointer dp nodebug_pointer nodp debug_keyboard dk
nodebug_keyboard nodk deferupdate defer wait rfbwait nodebug_keyboard nodk deferupdate defer wait rfbwait
...@@ -1520,15 +1577,16 @@ noalwaysshared nevershared noalwaysshared dontdisconnect ...@@ -1520,15 +1577,16 @@ noalwaysshared nevershared noalwaysshared dontdisconnect
nodontdisconnect desktop noremote nodontdisconnect desktop noremote
.IP .IP
aro= display vncdisplay desktopname http_url auth aro= display vncdisplay desktopname http_url auth
users rootshift scale_str scaled_x scaled_y scale_numer users rootshift clipshift scale_str scaled_x scaled_y
scale_denom scale_fac scaling_noblend scaling_nomult4 scale_numer scale_denom scale_fac scaling_noblend
scaling_pad scaling_interpolate inetd safer unsafe scaling_nomult4 scaling_pad scaling_interpolate inetd
passwdfile using_shm logfile o rc norc h help V version safer unsafe passwdfile using_shm logfile o rc norc
lastmod bg sigpipe threads clients client_count pid h help V version lastmod bg sigpipe threads clients
ext_xtest ext_xkb ext_xshm ext_xinerama ext_overlay client_count pid ext_xtest ext_xkb ext_xshm ext_xinerama
ext_xfixes ext_xdamage ext_xrandr rootwin num_buttons ext_overlay ext_xfixes ext_xdamage ext_xrandr rootwin
button_mask mouse_x mouse_y bpp depth indexed_color num_buttons button_mask mouse_x mouse_y bpp depth
dpy_x dpy_y rfbauth passwd 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 .PP
\fB-sync\fR \fB-sync\fR
.IP .IP
......
...@@ -169,7 +169,7 @@ ...@@ -169,7 +169,7 @@
/* /*
#define LIBVNCSERVER_HAVE_LIBXINERAMA 1 #define LIBVNCSERVER_HAVE_LIBXINERAMA 1
#define LIBVNCSERVER_HAVE_XFIXES 1 #define LIBVNCSERVER_HAVE_XFIXES 1
#define LIBVNCSERVER_HAVE_XDAMAGE 1 #define LIBVNCSERVER_HAVE_LIBXDAMAGE 1
*/ */
#endif /* OLD_TREE */ #endif /* OLD_TREE */
...@@ -329,13 +329,21 @@ static int xfixes_base_event_type; ...@@ -329,13 +329,21 @@ static int xfixes_base_event_type;
#endif #endif
int xdamage_present = 0; 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 #if LIBVNCSERVER_HAVE_LIBXDAMAGE
#include <X11/extensions/Xdamage.h> #include <X11/extensions/Xdamage.h>
static int xdamage_base_event_type; static int xdamage_base_event_type;
Damage xdamage = 0;
#endif #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' */ /* 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 */ /* X display info */
...@@ -347,6 +355,8 @@ int bpp, depth; ...@@ -347,6 +355,8 @@ int bpp, depth;
int indexed_color = 0; int indexed_color = 0;
int dpy_x, dpy_y; /* size of display */ int dpy_x, dpy_y; /* size of display */
int off_x, off_y; /* offsets for -sid */ 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 button_mask = 0; /* button state and info */
int num_buttons = -1; int num_buttons = -1;
...@@ -395,6 +405,7 @@ unsigned short main_red_shift, main_green_shift, main_blue_shift; ...@@ -395,6 +405,7 @@ unsigned short main_red_shift, main_green_shift, main_blue_shift;
typedef struct _ClientData { typedef struct _ClientData {
int uid; int uid;
char *hostname; char *hostname;
char *username;
int client_port; int client_port;
int server_port; int server_port;
char *server_ip; char *server_ip;
...@@ -432,6 +443,7 @@ int ntiles, ntiles_x, ntiles_y; ...@@ -432,6 +443,7 @@ int ntiles, ntiles_x, ntiles_y;
/* arrays that indicate changed or checked tiles. */ /* arrays that indicate changed or checked tiles. */
unsigned char *tile_has_diff, *tile_tried, *tile_copied; unsigned char *tile_has_diff, *tile_tried, *tile_copied;
unsigned char *tile_has_xdamage_diff, *tile_row_has_xdamage_diff;
/* times of recent events */ /* times of recent events */
time_t last_event, last_input, last_client = 0; time_t last_event, last_input, last_client = 0;
...@@ -466,6 +478,15 @@ Atom vnc_connect_prop = None; ...@@ -466,6 +478,15 @@ Atom vnc_connect_prop = None;
struct utsname UT; 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) */ /* function prototypes (see filename comment above) */
int all_clients_initialized(void); int all_clients_initialized(void);
...@@ -511,6 +532,9 @@ void free_tiles(void); ...@@ -511,6 +532,9 @@ void free_tiles(void);
void initialize_watch_bell(void); void initialize_watch_bell(void);
void initialize_xinerama(void); void initialize_xinerama(void);
void initialize_xfixes(void); void initialize_xfixes(void);
void initialize_xdamage(void);
void create_xdamage(void);
void destroy_xdamage(void);
void initialize_xrandr(void); void initialize_xrandr(void);
XImage *initialize_xdisplay_fb(void); XImage *initialize_xdisplay_fb(void);
...@@ -596,24 +620,25 @@ void refresh_screen(void); ...@@ -596,24 +620,25 @@ void refresh_screen(void);
/* /*
* variables for the command line options * variables for the command line options
*/ */
char *use_dpy = NULL; char *use_dpy = NULL; /* -display */
char *auth_file = NULL; char *auth_file = NULL; /* -auth/-xauth */
char *visual_str = NULL; char *visual_str = NULL; /* -visual */
char *logfile = NULL; char *logfile = NULL; /* -o, -logfile */
int logfile_append = 0; int logfile_append = 0;
char *passwdfile = NULL; char *passwdfile = NULL; /* -passwdfile */
char *blackout_str = NULL; char *blackout_str = NULL; /* -blackout */
int use_solid_bg = 0; char *clip_str = NULL; /* -clip */
int use_solid_bg = 0; /* -solid */
char *solid_str = NULL; char *solid_str = NULL;
char *solid_default = "cyan4"; char *solid_default = "cyan4";
char *speeds_str = NULL; char *speeds_str = NULL; /* -speeds TBD */
int measure_speeds = 1; int measure_speeds = 1;
int speeds_net_rate = 0; int speeds_net_rate = 0;
int speeds_net_latency = 0; int speeds_net_latency = 0;
int speeds_read_rate = 0; int speeds_read_rate = 0;
char *rc_rcfile = NULL; char *rc_rcfile = NULL; /* -rc */
int rc_norc = 0; int rc_norc = 0;
int opts_bg = 0; int opts_bg = 0;
...@@ -866,6 +891,32 @@ int scan_hexdec(char *str, unsigned long *num) { ...@@ -866,6 +891,32 @@ int scan_hexdec(char *str, unsigned long *num) {
return 1; 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) { void set_env(char *name, char *value) {
char *str; char *str;
str = (char *)malloc(strlen(name)+strlen(value)+2); str = (char *)malloc(strlen(name)+strlen(value)+2);
...@@ -1704,6 +1755,7 @@ void try_to_switch_users(void) { ...@@ -1704,6 +1755,7 @@ void try_to_switch_users(void) {
free(users); free(users);
} }
/* -- inet.c -- */
/* /*
* Simple utility to map host name to dotted IP address. Ignores aliases. * Simple utility to map host name to dotted IP address. Ignores aliases.
* Up to caller to free returned string. * Up to caller to free returned string.
...@@ -1728,9 +1780,6 @@ char *ip2host(char *ip) { ...@@ -1728,9 +1780,6 @@ char *ip2host(char *ip) {
char *str; char *str;
#if LIBVNCSERVER_HAVE_NETDB_H && LIBVNCSERVER_HAVE_NETINET_IN_H #if LIBVNCSERVER_HAVE_NETDB_H && LIBVNCSERVER_HAVE_NETINET_IN_H
struct hostent *hp; struct hostent *hp;
#ifndef in_addr_t
typedef unsigned int in_addr_t;
#endif
in_addr_t iaddr; in_addr_t iaddr;
iaddr = inet_addr(ip); iaddr = inet_addr(ip);
...@@ -1821,6 +1870,96 @@ char *get_local_host(int sock) { ...@@ -1821,6 +1870,96 @@ char *get_local_host(int sock) {
return get_host(sock, 0); 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 * used in rfbGetScreen and rfbNewFramebuffer: and estimate to the number
* of bits per color, of course for some visuals, e.g. 565, 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) { ...@@ -1846,42 +1985,25 @@ int guess_bits_per_color(int bits_per_pixel) {
return bits_per_color; 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 * Kludge to interpose image gets and limit to a subset rectangle of
* the rootwin. This is the -sid option trying to work around invisible * 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 rootshift = 0;
int clipshift = 0;
#define ADJUST_ROOTSHIFT \ #define ADJUST_ROOTSHIFT \
if (rootshift && subwin) { \ if (rootshift && subwin) { \
d = rootwin; \ d = rootwin; \
x += off_x; \ x += off_x; \
y += off_y; \ y += off_y; \
} \
if (clipshift) { \
x += coff_x; \
y += coff_y; \
} }
/* -- ximage.c -- */
/* /*
* Wrappers for Image related X calls * Wrappers for Image related X calls
*/ */
...@@ -2025,7 +2147,7 @@ XImage *XCreateImage_wr(Display *disp, Visual *visual, unsigned int depth, ...@@ -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) { 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) { if (w < 1) {
w = dest->width; w = dest->width;
} }
...@@ -2222,6 +2344,11 @@ void clean_up_exit (int ret) { ...@@ -2222,6 +2344,11 @@ void clean_up_exit (int ret) {
} }
X_LOCK; X_LOCK;
XTestDiscard_wr(dpy); XTestDiscard_wr(dpy);
#if LIBVNCSERVER_HAVE_LIBXDAMAGE
if (xdamage) {
XDamageDestroy(dpy, xdamage);
}
#endif
XCloseDisplay(dpy); XCloseDisplay(dpy);
X_UNLOCK; X_UNLOCK;
...@@ -2493,9 +2620,9 @@ char *list_clients(void) { ...@@ -2493,9 +2620,9 @@ char *list_clients(void) {
/* /*
* each client: * each client:
* <id>:<ip>:<port>:<hostname>:<input>:<loginview>, * <id>:<ip>:<port>:<user>:<hostname>:<input>:<loginview>,
* 8+1+16+1+5+1+256+1+5+1+1+1 * 8+1+16+1+5+1+24+1+256+1+5+1+1+1
* 123.123.123.123:60000/0x11111111-rw, = 297 bytes * 123.123.123.123:60000/0x11111111-rw,
* so count+1 * 400 must cover it. * so count+1 * 400 must cover it.
*/ */
list = (char *) malloc((count+1)*400); list = (char *) malloc((count+1)*400);
...@@ -2514,6 +2641,12 @@ char *list_clients(void) { ...@@ -2514,6 +2641,12 @@ char *list_clients(void) {
strcat(list, ":"); strcat(list, ":");
sprintf(tmp, "%d:", cd->client_port); sprintf(tmp, "%d:", cd->client_port);
strcat(list, tmp); 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, cd->hostname);
strcat(list, ":"); strcat(list, ":");
strcat(list, cd->input); strcat(list, cd->input);
...@@ -2525,6 +2658,26 @@ char *list_clients(void) { ...@@ -2525,6 +2658,26 @@ char *list_clients(void) {
return list; 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) { void close_all_clients(void) {
rfbClientIteratorPtr iter; rfbClientIteratorPtr iter;
rfbClientPtr cl; rfbClientPtr cl;
...@@ -2779,6 +2932,9 @@ static void client_gone(rfbClientPtr client) { ...@@ -2779,6 +2932,9 @@ static void client_gone(rfbClientPtr client) {
if (cd->hostname) { if (cd->hostname) {
free(cd->hostname); free(cd->hostname);
} }
if (cd->username) {
free(cd->username);
}
} }
free(client->clientData); free(client->clientData);
} }
...@@ -2958,8 +3114,8 @@ static int check_access(char *addr) { ...@@ -2958,8 +3114,8 @@ static int check_access(char *addr) {
* x11vnc's first (and only) visible widget: accept/reject dialog window. * x11vnc's first (and only) visible widget: accept/reject dialog window.
* We go through this pain to avoid dependency on libXt... * We go through this pain to avoid dependency on libXt...
*/ */
static int ugly_accept_window(char *addr, int X, int Y, int timeout, static int ugly_accept_window(char *addr, char *userhost, int X, int Y,
char *mode) { int timeout, char *mode) {
#define t2x2_width 16 #define t2x2_width 16
#define t2x2_height 16 #define t2x2_height 16
...@@ -2989,6 +3145,7 @@ static char t2x2_bits[] = { ...@@ -2989,6 +3145,7 @@ static char t2x2_bits[] = {
/* strings and geometries y/n */ /* strings and geometries y/n */
KeyCode key_y, key_n, key_v; KeyCode key_y, key_n, key_v;
char strh[100]; char strh[100];
char stri[100];
char str1_b[] = "To accept: press \"y\" or click the \"Yes\" button"; 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 str2_b[] = "To reject: press \"n\" or click the \"No\" button";
char str3_b[] = "View only: press \"v\" or click the \"View\" button"; char str3_b[] = "View only: press \"v\" or click the \"View\" button";
...@@ -3002,7 +3159,7 @@ static char t2x2_bits[] = { ...@@ -3002,7 +3159,7 @@ static char t2x2_bits[] = {
char str_y[] = "Yes"; char str_y[] = "Yes";
char str_n[] = "No"; char str_n[] = "No";
char str_v[] = "View"; 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 X_sh = 20, Y_sh = 30, dY = 20;
int Ye_x = 20, Ye_y = 0, Ye_w = 45, Ye_h = 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; int No_x = 75, No_y = 0, No_w = 45, No_h = 20;
...@@ -3026,6 +3183,7 @@ static char t2x2_bits[] = { ...@@ -3026,6 +3183,7 @@ static char t2x2_bits[] = {
h -= dY; h -= dY;
} }
/* XXX handle coff_x/coff_y? */
if (X < -dpy_x) { if (X < -dpy_x) {
x = (dpy_x - w)/2; /* large negative: center */ x = (dpy_x - w)/2; /* large negative: center */
if (x < 0) x = 0; if (x < 0) x = 0;
...@@ -3086,7 +3244,8 @@ static char t2x2_bits[] = { ...@@ -3086,7 +3244,8 @@ static char t2x2_bits[] = {
XMapWindow(dpy, awin); XMapWindow(dpy, awin);
XFlush(dpy); 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_y = XKeysymToKeycode(dpy, XStringToKeysym("y"));
key_n = XKeysymToKeycode(dpy, XStringToKeysym("n")); key_n = XKeysymToKeycode(dpy, XStringToKeysym("n"));
key_v = XKeysymToKeycode(dpy, XStringToKeysym("v")); key_v = XKeysymToKeycode(dpy, XStringToKeysym("v"));
...@@ -3122,6 +3281,8 @@ static char t2x2_bits[] = { ...@@ -3122,6 +3281,8 @@ static char t2x2_bits[] = {
/* instructions */ /* instructions */
XDrawString(dpy, awin, gc, X_sh, Y_sh+(k++)*dY, XDrawString(dpy, awin, gc, X_sh, Y_sh+(k++)*dY,
strh, strlen(strh)); 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, XDrawString(dpy, awin, gc, X_sh, Y_sh+(k++)*dY,
str1, strlen(str1)); str1, strlen(str1));
XDrawString(dpy, awin, gc, X_sh, Y_sh+(k++)*dY, XDrawString(dpy, awin, gc, X_sh, Y_sh+(k++)*dY,
...@@ -3336,6 +3497,7 @@ static int accept_client(rfbClientPtr client) { ...@@ -3336,6 +3497,7 @@ static int accept_client(rfbClientPtr client) {
addr = "unknown-host"; addr = "unknown-host";
} }
if (strstr(accept_cmd, "popup") == accept_cmd) { if (strstr(accept_cmd, "popup") == accept_cmd) {
/* use our builtin popup button */ /* use our builtin popup button */
...@@ -3344,6 +3506,7 @@ static int accept_client(rfbClientPtr client) { ...@@ -3344,6 +3506,7 @@ static int accept_client(rfbClientPtr client) {
int ret, timeout = 120; int ret, timeout = 120;
int x = -64000, y = -64000; int x = -64000, y = -64000;
char *p, *mode; char *p, *mode;
char *userhost = ident_username(client);
/* extract timeout */ /* extract timeout */
if ((p = strchr(accept_cmd, ':')) != NULL) { if ((p = strchr(accept_cmd, ':')) != NULL) {
...@@ -3380,7 +3543,9 @@ static int accept_client(rfbClientPtr client) { ...@@ -3380,7 +3543,9 @@ static int accept_client(rfbClientPtr client) {
} }
rfbLog("accept_client: using builtin popup for: %s\n", addr); 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) { if (ret == 2) {
rfbLog("accept_client: viewonly: %s\n", addr); rfbLog("accept_client: viewonly: %s\n", addr);
client->viewOnly = TRUE; client->viewOnly = TRUE;
...@@ -3388,6 +3553,7 @@ static int accept_client(rfbClientPtr client) { ...@@ -3388,6 +3553,7 @@ static int accept_client(rfbClientPtr client) {
rfbLog("accept_client: popup accepted: %s\n", addr); rfbLog("accept_client: popup accepted: %s\n", addr);
return 1; return 1;
} else { } else {
free(userhost);
rfbLog("accept_client: popup rejected: %s\n", addr); rfbLog("accept_client: popup rejected: %s\n", addr);
return 0; return 0;
} }
...@@ -3787,6 +3953,7 @@ enum rfbNewClientAction new_client(rfbClientPtr client) { ...@@ -3787,6 +3953,7 @@ enum rfbNewClientAction new_client(rfbClientPtr client) {
cd->server_port = get_local_port(client->sock); cd->server_port = get_local_port(client->sock);
cd->server_ip = get_local_host(client->sock); cd->server_ip = get_local_host(client->sock);
cd->hostname = ip2host(client->host); cd->hostname = ip2host(client->host);
cd->username = strdup("");
cd->input[0] = '-'; cd->input[0] = '-';
cd->login_viewonly = -1; cd->login_viewonly = -1;
...@@ -5755,11 +5922,15 @@ static void update_x11_pointer_position(int x, int y) { ...@@ -5755,11 +5922,15 @@ static void update_x11_pointer_position(int x, int y) {
X_LOCK; X_LOCK;
if (use_xwarppointer) { 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 { } else {
XTestFakeMotionEvent_wr(dpy, scr, x+off_x, y+off_y, XTestFakeMotionEvent_wr(dpy, scr, x + off_x + coff_x,
CurrentTime); y + off_y + coff_y, CurrentTime);
} }
X_UNLOCK; X_UNLOCK;
...@@ -5786,7 +5957,7 @@ static void update_x11_pointer_position(int x, int y) { ...@@ -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) { static void update_x11_pointer_mask(int mask) {
int i, mb; int i, mb;
...@@ -6164,8 +6335,8 @@ XErrorHandler old_getimage_handler; ...@@ -6164,8 +6335,8 @@ XErrorHandler old_getimage_handler;
/* -- xrandr.c -- */ /* -- xrandr.c -- */
void initialize_xrandr(void) { void initialize_xrandr(void) {
#if LIBVNCSERVER_HAVE_LIBXRANDR
if (xrandr_present) { if (xrandr_present) {
#if LIBVNCSERVER_HAVE_LIBXRANDR
Rotation rot; Rotation rot;
xrandr_width = XDisplayWidth(dpy, scr); xrandr_width = XDisplayWidth(dpy, scr);
...@@ -6177,15 +6348,20 @@ void initialize_xrandr(void) { ...@@ -6177,15 +6348,20 @@ void initialize_xrandr(void) {
} else { } else {
XRRSelectInput(dpy, rootwin, 0); XRRSelectInput(dpy, rootwin, 0);
} }
}
#endif #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); void handle_xrandr_change(int, int);
int handle_subwin_resize(char *msg) { int handle_subwin_resize(char *msg) {
int new_x, new_y; 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) { if (! subwin) {
return 0; /* hmmm... */ return 0; /* hmmm... */
...@@ -6200,7 +6376,7 @@ int handle_subwin_resize(char *msg) { ...@@ -6200,7 +6376,7 @@ int handle_subwin_resize(char *msg) {
X_UNLOCK; X_UNLOCK;
clean_up_exit(1); clean_up_exit(1);
} }
if (dpy_x == new_x && dpy_y == new_y) { if (wdpy_x == new_x && wdpy_y == new_y) {
/* no change */ /* no change */
return 0; return 0;
} }
...@@ -6225,7 +6401,7 @@ int handle_subwin_resize(char *msg) { ...@@ -6225,7 +6401,7 @@ int handle_subwin_resize(char *msg) {
} }
rfbLog("subwin 0x%lx new size: x: %d -> %d, y: %d -> %d\n", 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"); rfbLog("calling handle_xrandr_change() for resizing\n");
X_UNLOCK; X_UNLOCK;
...@@ -6268,11 +6444,11 @@ void handle_xrandr_change(int new_x, int new_y) { ...@@ -6268,11 +6444,11 @@ void handle_xrandr_change(int new_x, int new_y) {
/* default, resize, and newfbsize create a new fb: */ /* default, resize, and newfbsize create a new fb: */
rfbLog("check_xrandr_event: trying to create new framebuffer...\n"); 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(); check_black_fb();
} }
do_new_fb(1); 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) { int check_xrandr_event(char *msg) {
...@@ -6304,8 +6480,8 @@ 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(" mheight: %d mm\n", (int) rev->mheight);
rfbLog("\n"); rfbLog("\n");
rfbLog("check_xrandr_event: previous WxH: %dx%d\n", rfbLog("check_xrandr_event: previous WxH: %dx%d\n",
dpy_x, dpy_y); wdpy_x, wdpy_y);
if (dpy_x == rev->width && dpy_y == rev->height && if (wdpy_x == rev->width && wdpy_y == rev->height &&
xrandr_rotation == (int) rev->rotation) { xrandr_rotation == (int) rev->rotation) {
rfbLog("check_xrandr_event: no change detected.\n"); rfbLog("check_xrandr_event: no change detected.\n");
do_change = 0; do_change = 0;
...@@ -6624,6 +6800,7 @@ void initialize_xevents(void) { ...@@ -6624,6 +6800,7 @@ void initialize_xevents(void) {
static int did_xcreate_simple_window = 0; static int did_xcreate_simple_window = 0;
static int did_vnc_connect_prop = 0; static int did_vnc_connect_prop = 0;
static int did_xfixes = 0; static int did_xfixes = 0;
static int did_xdamage = 0;
static int did_xrandr = 0; static int did_xrandr = 0;
X_LOCK; X_LOCK;
...@@ -6656,6 +6833,10 @@ void initialize_xevents(void) { ...@@ -6656,6 +6833,10 @@ void initialize_xevents(void) {
initialize_xfixes(); initialize_xfixes();
did_xfixes = 1; 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) { ...@@ -7407,7 +7588,8 @@ char *process_remote_cmd(char *cmd, int stringonly) {
Window twin; Window twin;
COLON_CHECK("id:") COLON_CHECK("id:")
if (query) { 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; goto qry;
} }
p += strlen("id:"); p += strlen("id:");
...@@ -7444,7 +7626,8 @@ char *process_remote_cmd(char *cmd, int stringonly) { ...@@ -7444,7 +7626,8 @@ char *process_remote_cmd(char *cmd, int stringonly) {
Window twin; Window twin;
COLON_CHECK("sid:") COLON_CHECK("sid:")
if (query) { 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; goto qry;
} }
p += strlen("sid:"); p += strlen("sid:");
...@@ -7475,6 +7658,20 @@ char *process_remote_cmd(char *cmd, int stringonly) { ...@@ -7475,6 +7658,20 @@ char *process_remote_cmd(char *cmd, int stringonly) {
do_new_fb(1); 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) { } else if (strstr(p, "waitmapped") == p) {
if (query) { if (query) {
snprintf(buf, bufn, "ans=%s:%d", p, snprintf(buf, bufn, "ans=%s:%d", p,
...@@ -8676,6 +8873,73 @@ char *process_remote_cmd(char *cmd, int stringonly) { ...@@ -8676,6 +8873,73 @@ char *process_remote_cmd(char *cmd, int stringonly) {
initialize_xfixes(); initialize_xfixes();
first_cursor(); 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) { } else if (strstr(p, "alphacut") == p) {
int a; int a;
COLON_CHECK("alphacut:") COLON_CHECK("alphacut:")
...@@ -9282,6 +9546,12 @@ char *process_remote_cmd(char *cmd, int stringonly) { ...@@ -9282,6 +9546,12 @@ char *process_remote_cmd(char *cmd, int stringonly) {
rfbLog("process_remote_cmd: disabling remote commands.\n"); rfbLog("process_remote_cmd: disabling remote commands.\n");
accept_remote_cmds = 0; /* cannot be turned back on. */ 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) { } else if (query) {
/* read-only variables that can only be queried: */ /* read-only variables that can only be queried: */
...@@ -9314,6 +9584,8 @@ char *process_remote_cmd(char *cmd, int stringonly) { ...@@ -9314,6 +9584,8 @@ char *process_remote_cmd(char *cmd, int stringonly) {
snprintf(buf, bufn, "aro=%s:%s", p, NONUL(users_list)); snprintf(buf, bufn, "aro=%s:%s", p, NONUL(users_list));
} else if (!strcmp(p, "rootshift")) { } else if (!strcmp(p, "rootshift")) {
snprintf(buf, bufn, "aro=%s:%d", 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")) { } else if (!strcmp(p, "scale_str")) {
snprintf(buf, bufn, "aro=%s:%s", p, NONUL(scale_str)); snprintf(buf, bufn, "aro=%s:%s", p, NONUL(scale_str));
} else if (!strcmp(p, "scaled_x")) { } else if (!strcmp(p, "scaled_x")) {
...@@ -9406,6 +9678,22 @@ char *process_remote_cmd(char *cmd, int stringonly) { ...@@ -9406,6 +9678,22 @@ char *process_remote_cmd(char *cmd, int stringonly) {
snprintf(buf, bufn, "aro=%s:%d", p, dpy_x); snprintf(buf, bufn, "aro=%s:%d", p, dpy_x);
} else if (!strcmp(p, "dpy_y")) { } else if (!strcmp(p, "dpy_y")) {
snprintf(buf, bufn, "aro=%s:%d", 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")) { } else if (!strcmp(p, "rfbauth")) {
NOTAPPRO NOTAPPRO
} else if (!strcmp(p, "passwd")) { } else if (!strcmp(p, "passwd")) {
...@@ -9447,6 +9735,329 @@ char *process_remote_cmd(char *cmd, int stringonly) { ...@@ -9447,6 +9735,329 @@ char *process_remote_cmd(char *cmd, int stringonly) {
return NULL; 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 -- */ /* -- cursor.c -- */
/* /*
* Here begins a bit of a mess to experiment with multiple cursors * 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}; ...@@ -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 * 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 = static char* curs_root_data =
" " " "
...@@ -10868,8 +11479,8 @@ void check_x11_pointer(void) { ...@@ -10868,8 +11479,8 @@ void check_x11_pointer(void) {
} }
/* offset subtracted since XQueryPointer relative to rootwin */ /* offset subtracted since XQueryPointer relative to rootwin */
x = root_x - off_x; x = root_x - off_x - coff_x;
y = root_y - off_y; y = root_y - off_y - coff_y;
/* record the cursor position in the rfb screen */ /* record the cursor position in the rfb screen */
cursor_position(x, y); cursor_position(x, y);
...@@ -11286,8 +11897,8 @@ XImage *initialize_xdisplay_fb(void) { ...@@ -11286,8 +11897,8 @@ XImage *initialize_xdisplay_fb(void) {
if (! subwin) { if (! subwin) {
/* full screen */ /* full screen */
window = rootwin; window = rootwin;
dpy_x = DisplayWidth(dpy, scr); dpy_x = wdpy_x = DisplayWidth(dpy, scr);
dpy_y = DisplayHeight(dpy, scr); dpy_y = wdpy_y = DisplayHeight(dpy, scr);
off_x = 0; off_x = 0;
off_y = 0; off_y = 0;
/* this may be overridden via visual_id below */ /* this may be overridden via visual_id below */
...@@ -11302,8 +11913,8 @@ XImage *initialize_xdisplay_fb(void) { ...@@ -11302,8 +11913,8 @@ XImage *initialize_xdisplay_fb(void) {
X_UNLOCK; X_UNLOCK;
clean_up_exit(1); clean_up_exit(1);
} }
dpy_x = attr.width; dpy_x = wdpy_x = attr.width;
dpy_y = attr.height; dpy_y = wdpy_y = attr.height;
subwin_bs = attr.backing_store; subwin_bs = attr.backing_store;
...@@ -11315,6 +11926,46 @@ XImage *initialize_xdisplay_fb(void) { ...@@ -11315,6 +11926,46 @@ XImage *initialize_xdisplay_fb(void) {
X_LOCK; 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 */ /* initialize depth to reasonable value, visual_id may override */
depth = DefaultDepth(dpy, scr); depth = DefaultDepth(dpy, scr);
...@@ -11379,13 +12030,13 @@ XImage *initialize_xdisplay_fb(void) { ...@@ -11379,13 +12030,13 @@ XImage *initialize_xdisplay_fb(void) {
/* subwins can be a dicey if they are changing size... */ /* subwins can be a dicey if they are changing size... */
XTranslateCoordinates(dpy, window, rootwin, 0, 0, &subwin_x, XTranslateCoordinates(dpy, window, rootwin, 0, 0, &subwin_x,
&subwin_y, &twin); &subwin_y, &twin);
if (subwin_x + dpy_x > disp_x) { if (subwin_x + wdpy_x > disp_x) {
shift = 1; 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; shift = 1;
subwin_y = disp_y - dpy_y - 3; subwin_y = disp_y - wdpy_y - 3;
} }
if (subwin_x < 0) { if (subwin_x < 0) {
shift = 1; shift = 1;
...@@ -11435,17 +12086,17 @@ XImage *initialize_xdisplay_fb(void) { ...@@ -11435,17 +12086,17 @@ XImage *initialize_xdisplay_fb(void) {
if (subwin) { if (subwin) {
XSetErrorHandler(old_handler); XSetErrorHandler(old_handler);
if (trapped_xerror) { if (trapped_xerror) {
rfbLog("trapped GetImage at SUBWIN creation.\n"); rfbLog("trapped GetImage at SUBWIN creation.\n");
if (try < subwin_tries) { if (try < subwin_tries) {
usleep(250 * 1000); 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 " rfbLog("could not get size of subwin "
"0x%lx\n", subwin); "0x%lx\n", subwin);
X_UNLOCK; X_UNLOCK;
clean_up_exit(1); clean_up_exit(1);
}
goto again;
} }
goto again;
}
} }
trapped_xerror = 0; trapped_xerror = 0;
...@@ -11727,7 +12378,7 @@ void initialize_screen(int *argc, char **argv, XImage *fb) { ...@@ -11727,7 +12378,7 @@ void initialize_screen(int *argc, char **argv, XImage *fb) {
screen->serverFormat.greenMax = 0; screen->serverFormat.greenMax = 0;
screen->serverFormat.blueMax = 0; screen->serverFormat.blueMax = 0;
/* these main_* formats are use elsewhere by us. */ /* these main_* formats are used generally. */
main_red_shift = 0; main_red_shift = 0;
main_green_shift = 0; main_green_shift = 0;
main_blue_shift = 0; main_blue_shift = 0;
...@@ -12080,12 +12731,12 @@ void solid_root(char *color) { ...@@ -12080,12 +12731,12 @@ void solid_root(char *color) {
swa.background_pixmap = None; swa.background_pixmap = None;
visual.visualid = CopyFromParent; visual.visualid = CopyFromParent;
mask = (CWOverrideRedirect|CWBackingStore|CWSaveUnder|CWBackPixmap); 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); InputOutput, &visual, mask, &swa);
if (! color) { if (! color) {
/* restore the root window from the XImage snapshot */ /* 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) { if (! image) {
/* whoops */ /* whoops */
...@@ -12100,7 +12751,7 @@ void solid_root(char *color) { ...@@ -12100,7 +12751,7 @@ void solid_root(char *color) {
gcv.plane_mask = AllPlanes; gcv.plane_mask = AllPlanes;
gc = XCreateGC(dpy, window, GCFunction|GCPlaneMask, &gcv); 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); gcv.foreground = gcv.background = BlackPixel(dpy, scr);
gc = XCreateGC(dpy, window, GCForeground|GCBackground, &gcv); gc = XCreateGC(dpy, window, GCForeground|GCBackground, &gcv);
...@@ -12130,14 +12781,14 @@ void solid_root(char *color) { ...@@ -12130,14 +12781,14 @@ void solid_root(char *color) {
iswa.save_under = False; iswa.save_under = False;
iswa.background_pixmap = ParentRelative; iswa.background_pixmap = ParentRelative;
iwin = XCreateWindow(dpy, window, 0, 0, dpy_x, dpy_y, 0, depth, iwin = XCreateWindow(dpy, window, 0, 0, wdpy_x, wdpy_y, 0,
InputOutput, &visual, mask, &iswa); depth, InputOutput, &visual, mask, &iswa);
rfbLog("snapshotting background...\n"); rfbLog("snapshotting background...\n");
XMapWindow(dpy, iwin); XMapWindow(dpy, iwin);
XSync(dpy, False); 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); ZPixmap);
XSync(dpy, False); XSync(dpy, False);
XDestroyWindow(dpy, iwin); XDestroyWindow(dpy, iwin);
...@@ -12191,7 +12842,7 @@ void solid_cde(char *color) { ...@@ -12191,7 +12842,7 @@ void solid_cde(char *color) {
swa.background_pixmap = None; swa.background_pixmap = None;
visual.visualid = CopyFromParent; visual.visualid = CopyFromParent;
mask = (CWOverrideRedirect|CWBackingStore|CWSaveUnder|CWBackPixmap); 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); InputOutput, &visual, mask, &swa);
if (! color) { if (! color) {
...@@ -12212,7 +12863,8 @@ void solid_cde(char *color) { ...@@ -12212,7 +12863,8 @@ void solid_cde(char *color) {
continue; 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: */ /* draw the image to a pixmap: */
gcv.function = GXcopy; gcv.function = GXcopy;
...@@ -12220,7 +12872,7 @@ void solid_cde(char *color) { ...@@ -12220,7 +12872,7 @@ void solid_cde(char *color) {
gc = XCreateGC(dpy, twin, GCFunction|GCPlaneMask, &gcv); gc = XCreateGC(dpy, twin, GCFunction|GCPlaneMask, &gcv);
XPutImage(dpy, pixmap, gc, image[n], 0, 0, 0, 0, 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); gcv.foreground = gcv.background = BlackPixel(dpy, scr);
gc = XCreateGC(dpy, twin, GCForeground|GCBackground, gc = XCreateGC(dpy, twin, GCForeground|GCBackground,
...@@ -12366,7 +13018,7 @@ void solid_cde(char *color) { ...@@ -12366,7 +13018,7 @@ void solid_cde(char *color) {
iswa.background_pixmap = ParentRelative; iswa.background_pixmap = ParentRelative;
visual.visualid = CopyFromParent; 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); 0, depth, InputOutput, &visual, mask, &iswa);
rfbLog("snapshotting CDE backdrop ws%d 0x%lx -> " rfbLog("snapshotting CDE backdrop ws%d 0x%lx -> "
...@@ -12374,7 +13026,7 @@ void solid_cde(char *color) { ...@@ -12374,7 +13026,7 @@ void solid_cde(char *color) {
XMapWindow(dpy, iwin); XMapWindow(dpy, iwin);
XSync(dpy, False); 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); AllPlanes, ZPixmap);
XSync(dpy, False); XSync(dpy, False);
XDestroyWindow(dpy, iwin); XDestroyWindow(dpy, iwin);
...@@ -12673,21 +13325,7 @@ void initialize_blackouts(char *list) { ...@@ -12673,21 +13325,7 @@ void initialize_blackouts(char *list) {
p = strtok(blist, ", \t"); p = strtok(blist, ", \t");
while (p) { while (p) {
/* handle +/-x and +/-y */ if (! parse_geom(p, &w, &h, &x, &y, dpy_x, dpy_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 (*p != '\0') { if (*p != '\0') {
rfbLog("skipping invalid geometry: %s\n", p); rfbLog("skipping invalid geometry: %s\n", p);
} }
...@@ -13055,15 +13693,6 @@ static int nap_ok = 0, nap_diff_count = 0; ...@@ -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_count = 0; /* indicates which scan pattern we are on */
static int scan_in_progress = 0; 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 { typedef struct tile_change_region {
/* start and end lines, along y, of the changed area inside a tile. */ /* start and end lines, along y, of the changed area inside a tile. */
unsigned short first_line, last_line; unsigned short first_line, last_line;
...@@ -13087,6 +13716,10 @@ void initialize_tiles(void) { ...@@ -13087,6 +13716,10 @@ void initialize_tiles(void) {
tile_has_diff = (unsigned char *) tile_has_diff = (unsigned char *)
malloc((size_t) (ntiles * sizeof(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 *) tile_tried = (unsigned char *)
malloc((size_t) (ntiles * sizeof(unsigned char))); malloc((size_t) (ntiles * sizeof(unsigned char)));
tile_copied = (unsigned char *) tile_copied = (unsigned char *)
...@@ -13109,6 +13742,14 @@ void free_tiles(void) { ...@@ -13109,6 +13742,14 @@ void free_tiles(void) {
free(tile_has_diff); free(tile_has_diff);
tile_has_diff = NULL; 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) { if (tile_tried) {
free(tile_tried); free(tile_tried);
tile_tried = NULL; tile_tried = NULL;
...@@ -15032,7 +15673,7 @@ static int scan_display(int ystart, int rescan) { ...@@ -15032,7 +15673,7 @@ static int scan_display(int ystart, int rescan) {
int pixelsize = bpp/8; int pixelsize = bpp/8;
int x, y, w, n; int x, y, w, n;
int tile_count = 0; int tile_count = 0;
int whole_line = 1, nodiffs = 0; int nodiffs = 0, diff_hint;
y = ystart; y = ystart;
...@@ -15043,6 +15684,15 @@ static int scan_display(int ystart, int rescan) { ...@@ -15043,6 +15684,15 @@ static int scan_display(int ystart, int rescan) {
while (y < dpy_y) { 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: */ /* grab the horizontal scanline from the display: */
X_LOCK; X_LOCK;
XRANDR_SET_TRAP_RET(-1, "scan_display-set"); XRANDR_SET_TRAP_RET(-1, "scan_display-set");
...@@ -15054,7 +15704,7 @@ static int scan_display(int ystart, int rescan) { ...@@ -15054,7 +15704,7 @@ static int scan_display(int ystart, int rescan) {
src = scanline->data; src = scanline->data;
dst = main_fb + y * main_bytes_per_line; 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 */ /* no changes anywhere in scan line */
nodiffs = 1; nodiffs = 1;
if (! rescan) { if (! rescan) {
...@@ -15066,6 +15716,7 @@ static int scan_display(int ystart, int rescan) { ...@@ -15066,6 +15716,7 @@ static int scan_display(int ystart, int rescan) {
x = 0; x = 0;
while (x < dpy_x) { while (x < dpy_x) {
n = (x/tile_x) + (y/tile_y) * ntiles_x; n = (x/tile_x) + (y/tile_y) * ntiles_x;
diff_hint = 0;
if (blackouts) { if (blackouts) {
if (blackout_line_skip(n, x, y, rescan, if (blackout_line_skip(n, x, y, rescan,
...@@ -15081,6 +15732,10 @@ static int scan_display(int ystart, int rescan) { ...@@ -15081,6 +15732,10 @@ static int scan_display(int ystart, int rescan) {
x += NSCAN; x += NSCAN;
continue; 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: */ /* set ptrs to correspond to the x offset: */
...@@ -15094,7 +15749,7 @@ static int scan_display(int ystart, int rescan) { ...@@ -15094,7 +15749,7 @@ static int scan_display(int ystart, int rescan) {
w = NSCAN; w = NSCAN;
} }
if (memcmp(dst, src, w * pixelsize)) { if (diff_hint || memcmp(dst, src, w * pixelsize)) {
/* found a difference, record it: */ /* found a difference, record it: */
if (! blackouts) { if (! blackouts) {
tile_has_diff[n] = 1; tile_has_diff[n] = 1;
...@@ -15129,9 +15784,15 @@ int scan_for_updates(int count_only) { ...@@ -15129,9 +15784,15 @@ int scan_for_updates(int count_only) {
double frac3 = 0.02; /* do scan_display() again after copy_tiles() */ double frac3 = 0.02; /* do scan_display() again after copy_tiles() */
for (i=0; i < ntiles; i++) { for (i=0; i < ntiles; i++) {
tile_has_diff[i] = 0; tile_has_diff[i] = 0;
tile_has_xdamage_diff[i] = 0;
tile_tried[i] = 0; tile_tried[i] = 0;
tile_copied[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 * n.b. this program has only been tested so far with
...@@ -15142,15 +15803,16 @@ int scan_for_updates(int count_only) { ...@@ -15142,15 +15803,16 @@ int scan_for_updates(int count_only) {
scan_count++; scan_count++;
scan_count %= NSCAN; scan_count %= NSCAN;
if (scan_count % (NSCAN/4) == 0) { /* some periodic maintenance */
/* some periodic maintenance */ if (subwin) {
set_offset(); /* follow the subwindow */
if (subwin) { }
set_offset(); /* follow the subwindow */ if (indexed_color && scan_count % 4 == 0) {
} /* check for changed colormap */
if (indexed_color) { /* check for changed colormap */ set_colormap(0);
set_colormap(0); }
} if (using_xdamage) {
collect_xdamage(scan_count);
} }
} }
...@@ -15172,6 +15834,20 @@ int scan_for_updates(int count_only) { ...@@ -15172,6 +15834,20 @@ int scan_for_updates(int count_only) {
return tile_count; 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); nap_set(tile_count);
if (fs_factor && frac1 >= fs_frac) { if (fs_factor && frac1 >= fs_frac) {
...@@ -15349,9 +16025,11 @@ void run_gui(char *gui_xdisplay, int connect_to_x11vnc, int simple_gui, ...@@ -15349,9 +16025,11 @@ void run_gui(char *gui_xdisplay, int connect_to_x11vnc, int simple_gui,
exit(0); exit(0);
} }
if (getenv("DISPLAY") != NULL) { if (getenv("DISPLAY") != NULL) {
/* worst case */
x11vnc_xdisplay = strdup(getenv("DISPLAY")); x11vnc_xdisplay = strdup(getenv("DISPLAY"));
} }
if (use_dpy) { if (use_dpy) {
/* better */
x11vnc_xdisplay = strdup(use_dpy); x11vnc_xdisplay = strdup(use_dpy);
} }
if (connect_to_x11vnc) { if (connect_to_x11vnc) {
...@@ -15360,6 +16038,8 @@ void run_gui(char *gui_xdisplay, int connect_to_x11vnc, int simple_gui, ...@@ -15360,6 +16038,8 @@ void run_gui(char *gui_xdisplay, int connect_to_x11vnc, int simple_gui,
if (! client_connect_file) { if (! client_connect_file) {
if (getenv("XAUTHORITY") != NULL) { if (getenv("XAUTHORITY") != NULL) {
old_xauth = strdup(getenv("XAUTHORITY")); old_xauth = strdup(getenv("XAUTHORITY"));
} else {
old_xauth = strdup("");
} }
dpy = XOpenDisplay(x11vnc_xdisplay); dpy = XOpenDisplay(x11vnc_xdisplay);
if (! dpy && auth_file) { if (! dpy && auth_file) {
...@@ -15367,11 +16047,12 @@ void run_gui(char *gui_xdisplay, int connect_to_x11vnc, int simple_gui, ...@@ -15367,11 +16047,12 @@ void run_gui(char *gui_xdisplay, int connect_to_x11vnc, int simple_gui,
dpy = XOpenDisplay(x11vnc_xdisplay); dpy = XOpenDisplay(x11vnc_xdisplay);
} }
if (! dpy && ! x11vnc_xdisplay) { if (! dpy && ! x11vnc_xdisplay) {
/* worstest case */
x11vnc_xdisplay = strdup(":0"); x11vnc_xdisplay = strdup(":0");
dpy = XOpenDisplay(x11vnc_xdisplay); dpy = XOpenDisplay(x11vnc_xdisplay);
} }
if (! dpy) { if (! dpy) {
fprintf(stderr, "gui: could not open " fprintf(stderr, "gui: could not open x11vnc "
"display: %s\n", NONUL(x11vnc_xdisplay)); "display: %s\n", NONUL(x11vnc_xdisplay));
exit(1); exit(1);
} }
...@@ -15398,7 +16079,7 @@ void run_gui(char *gui_xdisplay, int connect_to_x11vnc, int simple_gui, ...@@ -15398,7 +16079,7 @@ void run_gui(char *gui_xdisplay, int connect_to_x11vnc, int simple_gui,
} }
set_env("X11VNC_XDISPLAY", x11vnc_xdisplay); set_env("X11VNC_XDISPLAY", x11vnc_xdisplay);
if (getenv("XAUTHORITY") != NULL) { if (getenv("XAUTHORITY") != NULL) {
set_env("X11VNC_XAUTHORITY", getenv("XAUTHORITY")); set_env("X11VNC_AUTH_FILE", getenv("XAUTHORITY"));
} }
if (rc == 0) { if (rc == 0) {
fprintf(stderr, "gui: ping succeeded.\n"); fprintf(stderr, "gui: ping succeeded.\n");
...@@ -15411,7 +16092,15 @@ void run_gui(char *gui_xdisplay, int connect_to_x11vnc, int simple_gui, ...@@ -15411,7 +16092,15 @@ void run_gui(char *gui_xdisplay, int connect_to_x11vnc, int simple_gui,
XCloseDisplay(dpy); XCloseDisplay(dpy);
} }
if (old_xauth) { if (old_xauth) {
set_env("XAUTHORITY", 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); free(old_xauth);
} }
} }
...@@ -15459,8 +16148,6 @@ void run_gui(char *gui_xdisplay, int connect_to_x11vnc, int simple_gui, ...@@ -15459,8 +16148,6 @@ void run_gui(char *gui_xdisplay, int connect_to_x11vnc, int simple_gui,
if (simple_gui) { if (simple_gui) {
set_env("X11VNC_SIMPLE_GUI", "1"); set_env("X11VNC_SIMPLE_GUI", "1");
} }
if (auth_file) {
}
sprintf(cmd, "%s -", wish); sprintf(cmd, "%s -", wish);
tmpf = tmpfile(); tmpf = tmpfile();
...@@ -16509,6 +17196,10 @@ static void watch_loop(void) { ...@@ -16509,6 +17196,10 @@ static void watch_loop(void) {
continue; continue;
} }
if (using_xdamage) {
check_xdamage_state();
}
if (watch_bell) { if (watch_bell) {
/* n.b. assumes -nofb folks do not want bell... */ /* n.b. assumes -nofb folks do not want bell... */
check_bell_event(); check_bell_event();
...@@ -16618,6 +17309,12 @@ static void print_help(int mode) { ...@@ -16618,6 +17309,12 @@ static void print_help(int mode) {
" shifts a root view to it: this shows SaveUnders menus,\n" " shifts a root view to it: this shows SaveUnders menus,\n"
" etc, although they will be clipped if they extend beyond\n" " etc, although they will be clipped if they extend beyond\n"
" the window.\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" "-flashcmap In 8bpp indexed color, let the installed colormap flash\n"
" as the pointer moves from window to window (slow).\n" " as the pointer moves from window to window (slow).\n"
"-notruecolor For 8bpp displays, force indexed color (i.e. a colormap)\n" "-notruecolor For 8bpp displays, force indexed color (i.e. a colormap)\n"
...@@ -17292,6 +17989,36 @@ static void print_help(int mode) { ...@@ -17292,6 +17989,36 @@ static void print_help(int mode) {
" to really throttle down the screen polls (i.e. sleep\n" " to really throttle down the screen polls (i.e. sleep\n"
" for about 1.5 secs). Use 0 to disable. Default: %d\n" " for about 1.5 secs). Use 0 to disable. Default: %d\n"
"\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" "-sigpipe string Broken pipe (SIGPIPE) handling. \"string\" can be\n"
" \"ignore\" or \"exit\". For \"ignore\" libvncserver\n" " \"ignore\" or \"exit\". For \"ignore\" libvncserver\n"
" will handle the abrupt loss of a client and continue,\n" " will handle the abrupt loss of a client and continue,\n"
...@@ -17417,6 +18144,7 @@ static void print_help(int mode) { ...@@ -17417,6 +18144,7 @@ static void print_help(int mode) {
" id:windowid set -id window to \"windowid\". empty\n" " id:windowid set -id window to \"windowid\". empty\n"
" or \"root\" to go back to root window\n" " or \"root\" to go back to root window\n"
" sid:windowid set -sid window to \"windowid\"\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" " flashcmap enable -flashcmap mode.\n"
" noflashcmap disable -flashcmap mode.\n" " noflashcmap disable -flashcmap mode.\n"
" notruecolor enable -notruecolor mode.\n" " notruecolor enable -notruecolor mode.\n"
...@@ -17559,6 +18287,10 @@ static void print_help(int mode) { ...@@ -17559,6 +18287,10 @@ static void print_help(int mode) {
" nap enable -nap mode.\n" " nap enable -nap mode.\n"
" nonap disable -nap mode.\n" " nonap disable -nap mode.\n"
" sb:n set -sb to n s, same as screen_blank:n\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" " fs:frac set -fs fraction to \"frac\", e.g. 0.5\n"
" gaps:n set -gaps to n.\n" " gaps:n set -gaps to n.\n"
" grow:n set -grow to n.\n" " grow:n set -grow to n.\n"
...@@ -17625,7 +18357,7 @@ static void print_help(int mode) { ...@@ -17625,7 +18357,7 @@ static void print_help(int mode) {
" variables correspond to the presence of X extensions):\n" " variables correspond to the presence of X extensions):\n"
"\n" "\n"
" ans= stop quit exit shutdown ping blacken zero\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" " nowaitmapped flashcmap noflashcmap truecolor notruecolor\n"
" overlay nooverlay overlay_cursor overlay_yescursor\n" " overlay nooverlay overlay_cursor overlay_yescursor\n"
" nooverlay_nocursor nooverlay_cursor nooverlay_yescursor\n" " nooverlay_nocursor nooverlay_cursor nooverlay_yescursor\n"
...@@ -17641,9 +18373,10 @@ static void print_help(int mode) { ...@@ -17641,9 +18373,10 @@ static void print_help(int mode) {
" remap repeat norepeat fb nofb bell nobell sel\n" " remap repeat norepeat fb nofb bell nobell sel\n"
" nosel primary noprimary cursorshape nocursorshape\n" " nosel primary noprimary cursorshape nocursorshape\n"
" cursorpos nocursorpos cursor show_cursor noshow_cursor\n" " cursorpos nocursorpos cursor show_cursor noshow_cursor\n"
" nocursor xfixes noxfixes alphacut alphafrac alpharemove\n" " nocursor xfixes noxfixes xdamage noxdamage xd_area\n"
" noalpharemove alphablend noalphablend xwarp xwarppointer\n" " xd_mem alphacut alphafrac alpharemove noalpharemove\n"
" noxwarp noxwarppointer buttonmap dragging nodragging\n" " alphablend noalphablend xwarp xwarppointer noxwarp\n"
" noxwarppointer buttonmap dragging nodragging\n"
" pointer_mode pm input_skip input client_input speeds\n" " pointer_mode pm input_skip input client_input speeds\n"
" debug_pointer dp nodebug_pointer nodp debug_keyboard dk\n" " debug_pointer dp nodebug_pointer nodp debug_keyboard dk\n"
" nodebug_keyboard nodk deferupdate defer wait rfbwait\n" " nodebug_keyboard nodk deferupdate defer wait rfbwait\n"
...@@ -17654,15 +18387,16 @@ static void print_help(int mode) { ...@@ -17654,15 +18387,16 @@ static void print_help(int mode) {
" nodontdisconnect desktop noremote\n" " nodontdisconnect desktop noremote\n"
"\n" "\n"
" aro= display vncdisplay desktopname http_url auth\n" " aro= display vncdisplay desktopname http_url auth\n"
" users rootshift scale_str scaled_x scaled_y scale_numer\n" " users rootshift clipshift scale_str scaled_x scaled_y\n"
" scale_denom scale_fac scaling_noblend scaling_nomult4\n" " scale_numer scale_denom scale_fac scaling_noblend\n"
" scaling_pad scaling_interpolate inetd safer unsafe\n" " scaling_nomult4 scaling_pad scaling_interpolate inetd\n"
" passwdfile using_shm logfile o rc norc h help V version\n" " safer unsafe passwdfile using_shm logfile o rc norc\n"
" lastmod bg sigpipe threads clients client_count pid\n" " h help V version lastmod bg sigpipe threads clients\n"
" ext_xtest ext_xkb ext_xshm ext_xinerama ext_overlay\n" " client_count pid ext_xtest ext_xkb ext_xshm ext_xinerama\n"
" ext_xfixes ext_xdamage ext_xrandr rootwin num_buttons\n" " ext_overlay ext_xfixes ext_xdamage ext_xrandr rootwin\n"
" button_mask mouse_x mouse_y bpp depth indexed_color\n" " num_buttons button_mask mouse_x mouse_y bpp depth\n"
" dpy_x dpy_y rfbauth passwd\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" "\n"
"-sync By default -remote commands are run asynchronously, that\n" "-sync By default -remote commands are run asynchronously, that\n"
" is, the request is posted and the program immediately\n" " is, the request is posted and the program immediately\n"
...@@ -17761,6 +18495,7 @@ static void print_help(int mode) { ...@@ -17761,6 +18495,7 @@ static void print_help(int mode) {
waitms, waitms,
take_naps ? "take naps":"no naps", take_naps ? "take naps":"no naps",
screen_blank, screen_blank,
xdamage_max_area, NSCAN, xdamage_memory,
use_threads ? "-threads":"-nothreads", use_threads ? "-threads":"-nothreads",
fs_frac, fs_frac,
gaps_fill, gaps_fill,
...@@ -18126,6 +18861,7 @@ int main(int argc, char* argv[]) { ...@@ -18126,6 +18861,7 @@ int main(int argc, char* argv[]) {
int vpw_loc = -1; int vpw_loc = -1;
int dt = 0, bg = 0; int dt = 0, bg = 0;
int got_rfbwait = 0, got_deferupdate = 0, got_defer = 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(): */ /* used to pass args we do not know about to rfbGetScreen(): */
int argc_vnc = 1; char *argv_vnc[128]; int argc_vnc = 1; char *argv_vnc[128];
...@@ -18211,6 +18947,9 @@ int main(int argc, char* argv[]) { ...@@ -18211,6 +18947,9 @@ int main(int argc, char* argv[]) {
} }
} else if (!strcmp(arg, "-waitmapped")) { } else if (!strcmp(arg, "-waitmapped")) {
subwin_wait_mapped = 1; subwin_wait_mapped = 1;
} else if (!strcmp(arg, "-clip")) {
CHECK_ARGC
clip_str = strdup(argv[++i]);
} else if (!strcmp(arg, "-flashcmap")) { } else if (!strcmp(arg, "-flashcmap")) {
flash_cmap = 1; flash_cmap = 1;
} else if (!strcmp(arg, "-notruecolor")) { } else if (!strcmp(arg, "-notruecolor")) {
...@@ -18468,6 +19207,24 @@ int main(int argc, char* argv[]) { ...@@ -18468,6 +19207,24 @@ int main(int argc, char* argv[]) {
} else if (!strcmp(arg, "-sb")) { } else if (!strcmp(arg, "-sb")) {
CHECK_ARGC CHECK_ARGC
screen_blank = atoi(argv[++i]); 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")) { } else if (!strcmp(arg, "-sigpipe")) {
CHECK_ARGC CHECK_ARGC
if (known_sigpipe_mode(argv[++i])) { if (known_sigpipe_mode(argv[++i])) {
...@@ -18820,6 +19577,8 @@ int main(int argc, char* argv[]) { ...@@ -18820,6 +19577,8 @@ int main(int argc, char* argv[]) {
: "null"); : "null");
fprintf(stderr, " subwin: 0x%lx\n", subwin); fprintf(stderr, " subwin: 0x%lx\n", subwin);
fprintf(stderr, " -sid mode: %d\n", rootshift); 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, " flashcmap: %d\n", flash_cmap);
fprintf(stderr, " force_idx: %d\n", force_indexed_color); fprintf(stderr, " force_idx: %d\n", force_indexed_color);
fprintf(stderr, " visual: %s\n", visual_str ? visual_str fprintf(stderr, " visual: %s\n", visual_str ? visual_str
...@@ -18909,6 +19668,9 @@ int main(int argc, char* argv[]) { ...@@ -18909,6 +19668,9 @@ int main(int argc, char* argv[]) {
fprintf(stderr, " waitms: %d\n", waitms); fprintf(stderr, " waitms: %d\n", waitms);
fprintf(stderr, " take_naps: %d\n", take_naps); fprintf(stderr, " take_naps: %d\n", take_naps);
fprintf(stderr, " sb: %d\n", screen_blank); 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 fprintf(stderr, " sigpipe: %s\n", sigpipe
? sigpipe : "null"); ? sigpipe : "null");
fprintf(stderr, " threads: %d\n", use_threads); fprintf(stderr, " threads: %d\n", use_threads);
...@@ -19050,6 +19812,12 @@ int main(int argc, char* argv[]) { ...@@ -19050,6 +19812,12 @@ int main(int argc, char* argv[]) {
xdamage_present = 1; xdamage_present = 1;
} }
#endif #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; overlay_present = 0;
#ifdef SOLARIS_OVERLAY #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