Commit ae59284a authored by runge's avatar runge

x11vnc: scrolling: grabserver, autorepeat throttling, mouse wheel, fix onetile

parent ff590d0a
2005-05-24 Karl Runge <runge@karlrunge.com>
* x11vnc: scrollcopyrect: GrabServer detection, autorepeat throttling..
* prepare_x11vnc_dist.sh: grep out new libvncserver-config line.
2005-05-23 Karl Runge <runge@karlrunge.com>
* configure.ac: malloc(0) is never used, so we don't need the check
......
......@@ -7,6 +7,7 @@ cd "$(dirname "$0")"
mv configure.ac configure.ac.LibVNCServer
cat configure.ac.LibVNCServer | \
egrep -v 'AC_CONFIG_COMMANDS.*libvncserver-config' | \
sed -e "s/LibVNCServer, [^,)]*\([(,]\)*/x11vnc, $VERSION\1/g" \
-e "s/\(contrib\|examples\|vncterm\|libvncclient\|test\|client_examples\)\/Makefile//g" \
-e "s/LibVNCServer.spec/x11vnc.spec/g" \
......
2005-05-24 Karl Runge <runge@karlrunge.com>
* more -scrollcopyrect: GrabServer detection, autorepeat throttling,
hack to clean screen 3,4,5 Alt_L in a row, mouse wheel detect.
* fix bug wrt switching to single_copytile, add Darwin to shm limit.
2005-05-17 Karl Runge <runge@karlrunge.com>
* more -scrollcopyrect, -scr_term hacks for terminals.
* -wait_ui, -nowait_bog tunables. push cursor sooner.
......
x11vnc README file Date: Tue May 17 14:39:38 EDT 2005
x11vnc README file Date: Tue May 24 23:49:07 EDT 2005
The following information is taken from these URLs:
......@@ -4238,7 +4238,7 @@ x11vnc: a VNC server for real X displays
Here are all of x11vnc command line options:
% x11vnc -opts (see below for -help long descriptions)
x11vnc: allow VNC connections to real X11 displays. 0.7.2 lastmod: 2005-05-17
x11vnc: allow VNC connections to real X11 displays. 0.7.2 lastmod: 2005-05-24
x11vnc options:
-display disp -auth file
......@@ -4289,7 +4289,8 @@ x11vnc options:
-noscrollcopyrect -scr_area n
-scr_skip list -scr_inc list
-scr_keys list -scr_term list
-scr_parms string -debug_scroll
-scr_keyrepeat lo-hi -scr_parms string
-debug_scroll -noxrecord
-pointer_mode n -input_skip n
-speeds rd,bw,lat -debug_pointer
-debug_keyboard -defer time
......@@ -4335,7 +4336,7 @@ libvncserver options:
% x11vnc -help
x11vnc: allow VNC connections to real X11 displays. 0.7.2 lastmod: 2005-05-17
x11vnc: allow VNC connections to real X11 displays. 0.7.2 lastmod: 2005-05-24
Typical usage is:
......@@ -4357,8 +4358,12 @@ the name of the machine running x11vnc and N is XXXX - 5900, i.e. usually
By default x11vnc will not allow the screen to be shared and it will exit
as soon as the client disconnects. See -shared and -forever below to override
these protections. See the FAQ on how to tunnel the VNC connection through
an encrypted channel such as ssh(1).
these protections. See the FAQ for details how to tunnel the VNC connection
through an encrypted channel such as ssh(1). In brief:
ssh -L 5900:localhost:5900 far-host 'x11vnc -localhost -display :0'
vncviewer -encodings 'copyrect tight zrle hextile' localhost:0
For additional info see: http://www.karlrunge.com/x11vnc/
and http://www.karlrunge.com/x11vnc/#faq
......@@ -5215,7 +5220,7 @@ Options:
to Keystroke generated scrolls (e.g. Up arrow). If it
is prefixed with "MOUSE:" it only applies to Mouse
induced scrolls (e.g. dragging on a scrollbar).
Default: ##Soffice.bin
Default: ##Soffice.bin,##StarOffice
-scr_inc list Opposite of -scr_skip: this list is consulted first
and if there is a match the window will be monitored
......@@ -5246,14 +5251,14 @@ Options:
never induce scrolling by themselves.
-scr_term list Yet another cosmetic kludge. Apply shell/terminal
heuristics to applications matching comma separated list
(same as -scr_skip/-scr_inc). For example an annoying
transient under scroll detection is if you hit Enter in
a terminal shell with full text window, the solid text
cursor block will be scrolled up. So for a short time
there are two (or more) block cursors on the screen.
There are similar scenarios, (e.g. an output line is
duplicated).
heuristics to applications matching comma separated
list (same as for -scr_skip/-scr_inc). For example an
annoying transient under scroll detection is if you
hit Enter in a terminal shell with full text window,
the solid text cursor block will be scrolled up.
So for a short time there are two (or more) block
cursors on the screen. There are similar scenarios,
(e.g. an output line is duplicated).
These transients are induced by the approximation of
scroll detection (e.g. it detects the scroll, but not
......@@ -5268,6 +5273,19 @@ Options:
the annoying artifacts. Use "none" to disable.
Default: "term"
-scr_keyrepeat lo-hi If a key is held down (or otherwise repeats rapidly) and
this induces a rapid sequence of scrolls (e.g. holding
down an Arrow key) the "scrollcopyrect" detection
and overhead may not be able to keep up. A time per
single scroll estimate is performed and if that estimate
predicts a sustainable scrollrate of keys per second
between "lo" and "hi" then repeated keys will be
DISCARDED to maintain the scrollrate. For example your
key autorepeat may be 25 keys/sec, but for a large
window or slow link only 8 scrolls per second can be
sustained, then roughly 2 out of every 3 repeated keys
will be discarded during this period. Default: "4-20"
-scr_parms string Set various parameters for the scrollcopyrect mode.
The format is similar to that for -wireframe and packed
with lots of parameters:
......@@ -5314,6 +5332,10 @@ Options:
heuristics. "-ds" is an alias. Specify it multiple
times for more output.
-noxrecord Disable any use of the RECORD extension. This is
currently used by the -scrollcopyrect scheme and to
monitor X server grabs.
-pointer_mode n Various pointer motion update schemes. "-pm" is
an alias. The problem is pointer motion can cause
rapid changes on the screen: consider the rapid changes
......@@ -5529,8 +5551,8 @@ Options:
usage should be very rare, i.e. doing something strange
with /dev/fb0.
-pipeinput cmd Another experimental option: it lets you supply
an extern command in "cmd" that x11vnc will pipe
-pipeinput cmd Another experimental option: it lets you supply an
external command in "cmd" that x11vnc will pipe
all of the user input events to in a simple format.
In -pipeinput mode by default x11vnc will not process
any of the user input events. If you prefix "cmd"
......@@ -5789,7 +5811,10 @@ Options:
scr_inc:list set -scr_inc to "list"
scr_keys:list set -scr_keys to "list"
scr_term:list set -scr_term to "list"
scr_keyrepeat:str set -scr_keyrepeat to "str"
scr_parms:str set -scr_parms parameters.
noxrecord disable all use of RECORD extension.
xrecord enable use of RECORD extension.
pointer_mode:n set -pointer_mode to n. same as "pm"
input_skip:n set -input_skip to n.
speeds:str set -speeds to str.
......@@ -5905,14 +5930,15 @@ Options:
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 arrow xfixes noxfixes
xdamage noxdamage xd_area xd_mem alphacut alphafrac
alpharemove noalpharemove alphablend noalphablend
xwarppointer xwarp noxwarppointer noxwarp buttonmap
dragging nodragging wireframe_mode wireframe wf
nowireframe nowf wirecopyrect wcr nowirecopyrect nowcr
scr_area scr_skip scr_inc scr_keys scr_term scr_parms
scrollcopyrect scr noscrollcopyrect noscr pointer_mode
show_cursor noshow_cursor nocursor arrow xfixes
noxfixes xdamage noxdamage xd_area xd_mem alphacut
alphafrac alpharemove noalpharemove alphablend
noalphablend xwarppointer xwarp noxwarppointer
noxwarp buttonmap dragging nodragging wireframe_mode
wireframe wf nowireframe nowf wirecopyrect wcr
nowirecopyrect nowcr scr_area scr_skip scr_inc scr_keys
scr_term scr_keyrepeat scr_parms scrollcopyrect scr
noscrollcopyrect noscr noxrecord xrecord pointer_mode
pm input_skip input client_input speeds debug_pointer dp
nodebug_pointer nodp debug_keyboard dk nodebug_keyboard
nodk deferupdate defer wait_ui wait_bog nowait_bog wait
......
......@@ -172,6 +172,7 @@ Misc
nolookup
--
xtrap
xrecord
--
bg
=-C:ignore,exit sigpipe:
......@@ -266,6 +267,7 @@ Tuning
scr_inc:
scr_keys:
scr_term:
scr_keyrepeat:
scr_parms:
-- D
speeds:
......
......@@ -178,6 +178,7 @@
" nolookup\n"
" --\n"
" xtrap\n"
" xrecord\n"
" --\n"
" bg\n"
" =-C:ignore,exit sigpipe:\n"
......@@ -272,6 +273,7 @@
" scr_inc:\n"
" scr_keys:\n"
" scr_term:\n"
" scr_keyrepeat:\n"
" scr_parms:\n"
" -- D\n"
" speeds:\n"
......
......@@ -2,7 +2,7 @@
.TH X11VNC "1" "May 2005" "x11vnc " "User Commands"
.SH NAME
x11vnc - allow VNC connections to real X11 displays
version: 0.7.2, lastmod: 2005-05-17
version: 0.7.2, lastmod: 2005-05-24
.SH SYNOPSIS
.B x11vnc
[OPTION]...
......@@ -28,9 +28,14 @@ the name of the machine running x11vnc and N is XXXX - 5900, i.e. usually
.PP
By default x11vnc will not allow the screen to be shared and it will exit
as soon as the client disconnects. See \fB-shared\fR and \fB-forever\fR below to override
these protections. See the FAQ on how to tunnel the VNC connection through
an encrypted channel such as
these protections. See the FAQ for details how to tunnel the VNC connection
through an encrypted channel such as
.IR ssh (1).
In brief:
.IP
ssh -L 5900:localhost:5900 far-host 'x11vnc -localhost -display :0'
.IP
vncviewer -encodings 'copyrect tight zrle hextile' localhost:0
.PP
For additional info see: http://www.karlrunge.com/x11vnc/
and http://www.karlrunge.com/x11vnc/#faq
......@@ -1152,7 +1157,7 @@ If a pattern is prefixed with "KEY:" it only applies
to Keystroke generated scrolls (e.g. Up arrow). If it
is prefixed with "MOUSE:" it only applies to Mouse
induced scrolls (e.g. dragging on a scrollbar).
Default: ##Soffice.bin
Default: ##Soffice.bin,##StarOffice
.PP
\fB-scr_inc\fR \fIlist\fR
.IP
......@@ -1212,6 +1217,21 @@ from the actual X framebuffer. This usually reduces
the annoying artifacts. Use "none" to disable.
Default: "term"
.PP
\fB-scr_keyrepeat\fR \fIlo-hi\fR
.IP
If a key is held down (or otherwise repeats rapidly) and
this induces a rapid sequence of scrolls (e.g. holding
down an Arrow key) the "scrollcopyrect" detection
and overhead may not be able to keep up. A time per
single scroll estimate is performed and if that estimate
predicts a sustainable scrollrate of keys per second
between "lo" and "hi" then repeated keys will be
DISCARDED to maintain the scrollrate. For example your
key autorepeat may be 25 keys/sec, but for a large
window or slow link only 8 scrolls per second can be
sustained, then roughly 2 out of every 3 repeated keys
will be discarded during this period. Default: "4-20"
.PP
\fB-scr_parms\fR \fIstring\fR
.IP
Set various parameters for the scrollcopyrect mode.
......@@ -1262,6 +1282,12 @@ Turn on debugging info printout for the scroll
heuristics. "\fB-ds\fR" is an alias. Specify it multiple
times for more output.
.PP
\fB-noxrecord\fR
.IP
Disable any use of the RECORD extension. This is
currently used by the \fB-scrollcopyrect\fR scheme and to
monitor X server grabs.
.PP
\fB-pointer_mode\fR \fIn\fR
.IP
Various pointer motion update schemes. "\fB-pm\fR" is
......@@ -1942,8 +1968,14 @@ scr_keys:list set \fB-scr_keys\fR to "list"
.IP
scr_term:list set \fB-scr_term\fR to "list"
.IP
scr_keyrepeat:str set \fB-scr_keyrepeat\fR to "str"
.IP
scr_parms:str set \fB-scr_parms\fR parameters.
.IP
noxrecord disable all use of RECORD extension.
.IP
xrecord enable use of RECORD extension.
.IP
pointer_mode:n set \fB-pointer_mode\fR to n. same as "pm"
.IP
input_skip:n set \fB-input_skip\fR to n.
......@@ -2128,14 +2160,15 @@ noskip_dups add_keysyms noadd_keysyms 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 arrow xfixes noxfixes
xdamage noxdamage xd_area xd_mem alphacut alphafrac
alpharemove noalpharemove alphablend noalphablend
xwarppointer xwarp noxwarppointer noxwarp buttonmap
dragging nodragging wireframe_mode wireframe wf
nowireframe nowf wirecopyrect wcr nowirecopyrect nowcr
scr_area scr_skip scr_inc scr_keys scr_term scr_parms
scrollcopyrect scr noscrollcopyrect noscr pointer_mode
show_cursor noshow_cursor nocursor arrow xfixes
noxfixes xdamage noxdamage xd_area xd_mem alphacut
alphafrac alpharemove noalpharemove alphablend
noalphablend xwarppointer xwarp noxwarppointer
noxwarp buttonmap dragging nodragging wireframe_mode
wireframe wf nowireframe nowf wirecopyrect wcr
nowirecopyrect nowcr scr_area scr_skip scr_inc scr_keys
scr_term scr_keyrepeat scr_parms scrollcopyrect scr
noscrollcopyrect noscr noxrecord xrecord pointer_mode
pm input_skip input client_input speeds debug_pointer dp
nodebug_pointer nodp debug_keyboard dk nodebug_keyboard
nodk deferupdate defer wait_ui wait_bog nowait_bog wait
......
......@@ -372,12 +372,12 @@ double xdamage_scheduled_mark = 0.0;
sraRegionPtr xdamage_scheduled_mark_region = NULL;
/* date +'lastmod: %Y-%m-%d' */
char lastmod[] = "0.7.2 lastmod: 2005-05-17";
char lastmod[] = "0.7.2 lastmod: 2005-05-24";
int hack_val = 0;
/* X display info */
Display *dpy = 0; /* the single display screen we connect to */
Display *dpy = NULL; /* the single display screen we connect to */
int scr;
Window window, rootwin; /* polled window, root window (usu. same) */
Visual *default_visual; /* the default visual (unless -visual) */
......@@ -494,6 +494,10 @@ unsigned char *tile_has_xdamage_diff, *tile_row_has_xdamage_diff;
time_t last_event, last_input = 0, last_client = 0;
time_t last_keyboard_input = 0, last_pointer_input = 0;
double last_keyboard_time = 0.0;
double last_pointer_time = 0.0;
double last_pointer_click_time = 0.0;
double last_pointer_motion_time = 0.0;
double last_key_to_button_remap_time = 0.0;
double servertime_diff = 0.0;
double x11vnc_start = 0.0;
......@@ -512,7 +516,10 @@ int got_pointer_input = 0;
int got_keyboard_input = 0;
int urgent_update = 0;
int last_keyboard_keycode = 0;
rfbKeySym last_keysym = 0;
rfbBool last_rfb_down = FALSE;
rfbBool last_rfb_key_accepted = FALSE;
rfbKeySym last_rfb_keysym = 0;
double last_rfb_keytime = 0.0;
int fb_copy_in_progress = 0;
int drag_in_progress = 0;
int shut_down = 0;
......@@ -593,10 +600,12 @@ void initialize_xinerama(void);
void initialize_xfixes(void);
void initialize_xdamage(void);
int valid_window(Window, XWindowAttributes *, int);
int xtranslate(Window, Window, int, int, int*, int*, Window*, int);
void create_xdamage_if_needed(void);
void destroy_xdamage_if_needed(void);
void mark_for_xdamage(int, int, int, int);
void mark_region_for_xdamage(sraRegionPtr);
void set_xdamage_mark(int, int, int, int);
void initialize_xrandr(void);
XImage *initialize_xdisplay_fb(void);
......@@ -638,6 +647,7 @@ void set_wirecopyrect_mode(char *);
void set_scrollcopyrect_mode(char *);
void initialize_scroll_matches(void);
void initialize_scroll_term(void);
void initialize_max_keyrepeat(void);
void initialize_scroll_keys(void);
int try_copyrect(Window, int, int, int, int, int, int, int *, sraRegionPtr,
double);
......@@ -721,7 +731,7 @@ int scale_round(int, double);
void zero_fb(int, int, int, int);
void push_black_screen(int);
void push_sleep(int);
void refresh_screen(void);
void refresh_screen(int);
/* -- options.h -- */
......@@ -842,9 +852,14 @@ char *pad_geometry = NULL;
time_t pad_geometry_time;
int use_snapfb = 0;
Display *rdpy_data = 0; /* Data connection for RECORD */
Display *rdpy_ctrl = 0; /* Control connection for RECORD */
Display *rdpy_data = NULL; /* Data connection for RECORD */
Display *rdpy_ctrl = NULL; /* Control connection for RECORD */
int use_xrecord = 0;
int noxrecord = 0;
Display *gdpy_data = NULL; /* Ditto for GrabServer watcher */
Display *gdpy_ctrl = NULL;
int xserver_grabbed = 0;
char *client_connect = NULL; /* strings for -connect option */
char *client_connect_file = NULL;
......@@ -924,6 +939,10 @@ int debug_scroll = 0;
double pointer_flush_delay = 0.0;
double last_scroll_event = 0.0;
int max_scroll_keyrate = 0;
double max_keyrepeat_time = 0.0;
char *max_keyrepeat_str = NULL;
char *max_keyrepeat_str0 = "4-20";
int max_keyrepeat_lo = 1, max_keyrepeat_hi = 40;
enum scroll_types {
SCR_NONE = 0,
SCR_MOUSE,
......@@ -950,7 +969,8 @@ char **scroll_skip_mouse = NULL;
char *scroll_skip_str = NULL;
char *scroll_skip_str0 =
/* "##Konsole," * no problems, known heuristics do not work */
"##Soffice.bin" /* big problems, no clips, scrolls outside area */
"##Soffice.bin," /* big problems, no clips, scrolls outside area */
"##StarOffice"
;
char **scroll_term = NULL;
......@@ -1924,7 +1944,7 @@ int try_user_and_display(uid_t uid, char *dpystr) {
return 0;
} else {
/* child */
Display *dpy2 = 0;
Display *dpy2 = NULL;
int rc;
rc = switch_user_env(uid, name, home, 0);
......@@ -2811,13 +2831,15 @@ int XTRAP_GrabControl_wr(Display *dpy, Bool impervious) {
return 0;
}
void disable_grabserver(Display *in_dpy) {
void disable_grabserver(Display *in_dpy, int change) {
int ok = 0;
static int didmsg = 0;
if (! xtrap_input) {
if (XTestGrabControl_wr(in_dpy, True)) {
if (change) {
XTRAP_GrabControl_wr(in_dpy, False);
}
if (! didmsg) {
rfbLog("GrabServer control via XTEST.\n");
didmsg = 1;
......@@ -2835,7 +2857,9 @@ void disable_grabserver(Display *in_dpy) {
}
} else {
if (XTRAP_GrabControl_wr(in_dpy, True)) {
if (change) {
XTestGrabControl_wr(in_dpy, False);
}
if (! didmsg) {
rfbLog("GrabServer control via DEC-XTRAP.\n");
didmsg = 1;
......@@ -2868,11 +2892,17 @@ Bool XRecordQueryVersion_wr(Display *dpy, int *maj, int *min) {
}
#if LIBVNCSERVER_HAVE_RECORD
XRecordRange *rr_CA;
XRecordRange *rr_CW;
XRecordRange *rr_CA = NULL;
XRecordRange *rr_CW = NULL;
XRecordRange *rr_GS = NULL;
XRecordRange *rr_scroll[10];
XRecordContext rc_scroll;
XRecordClientSpec rcs_scroll;
XRecordRange *rr_grab[10];
XRecordContext rc_grab;
XRecordClientSpec rcs_grab;
void record_grab(XPointer, XRecordInterceptData *);
#endif
int xrecording = 0;
......@@ -2885,6 +2915,63 @@ KeySym xrecord_keysym = NoSymbol;
#define NAMEINFO 2048
char xrecord_name_info[NAMEINFO];
char *xerror_string(XErrorEvent *error);
int trap_record_xerror(Display *, XErrorEvent *);
int trapped_record_xerror;
XErrorEvent *trapped_record_xerror_event;
void xrecord_grabserver(int start) {
XErrorHandler old_handler = NULL;
int rc;
if (! gdpy_ctrl || ! gdpy_data) {
return;
}
#if LIBVNCSERVER_HAVE_RECORD
if (!start) {
if (! rc_grab) {
return;
}
XRecordDisableContext(gdpy_ctrl, rc_grab);
XRecordFreeContext(gdpy_ctrl, rc_grab);
XFlush(gdpy_ctrl);
rc_grab = 0;
return;
}
xserver_grabbed = 0;
rr_grab[0] = rr_GS;
rcs_grab = XRecordAllClients;
rc_grab = XRecordCreateContext(gdpy_ctrl, 0, &rcs_grab, 1, rr_grab, 1);
trapped_record_xerror = 0;
old_handler = XSetErrorHandler(trap_record_xerror);
XSync(gdpy_ctrl, True);
if (! rc_grab || trapped_record_xerror) {
XCloseDisplay(gdpy_ctrl);
XCloseDisplay(gdpy_data);
gdpy_ctrl = NULL;
gdpy_data = NULL;
XSetErrorHandler(old_handler);
return;
}
rc = XRecordEnableContextAsync(gdpy_data, rc_grab, record_grab, NULL);
if (!rc || trapped_record_xerror) {
XCloseDisplay(gdpy_ctrl);
XCloseDisplay(gdpy_data);
gdpy_ctrl = NULL;
gdpy_data = NULL;
XSetErrorHandler(old_handler);
return;
}
XSetErrorHandler(old_handler);
XFlush(gdpy_data);
#endif
}
void initialize_xrecord(void) {
use_xrecord = 0;
if (! xrecord_present) {
......@@ -2893,10 +2980,19 @@ void initialize_xrecord(void) {
if (nofb) {
return;
}
if (noxrecord) {
return;
}
#if LIBVNCSERVER_HAVE_RECORD
if (rr_CA) XFree(rr_CA);
if (rr_CW) XFree(rr_CW);
if (rr_GS) XFree(rr_GS);
rr_CA = XRecordAllocRange();
rr_CW = XRecordAllocRange();
if (! rr_CA || ! rr_CW) {
rr_GS = XRecordAllocRange();
if (!rr_CA || !rr_CW || !rr_GS) {
return;
}
/* protocol request ranges: */
......@@ -2906,21 +3002,109 @@ void initialize_xrecord(void) {
rr_CW->core_requests.first = X_ConfigureWindow;
rr_CW->core_requests.last = X_ConfigureWindow;
rr_GS->core_requests.first = X_GrabServer;
rr_GS->core_requests.last = X_UngrabServer;
X_LOCK;
/* open a 2nd control connection to DISPLAY: */
if (rdpy_data) {
XCloseDisplay(rdpy_data);
rdpy_data = NULL;
}
if (rdpy_ctrl) {
XCloseDisplay(rdpy_ctrl);
rdpy_ctrl = NULL;
}
rdpy_ctrl = XOpenDisplay(DisplayString(dpy));
XSync(dpy, True);
XSync(rdpy_ctrl, True);
/* open datalink connection to DISPLAY: */
rdpy_data = XOpenDisplay(DisplayString(dpy));
if (!rdpy_ctrl || ! rdpy_data) {
X_UNLOCK;
return;
}
disable_grabserver(rdpy_ctrl);
disable_grabserver(rdpy_data);
disable_grabserver(rdpy_ctrl, 0);
disable_grabserver(rdpy_data, 0);
use_xrecord = 1;
/*
* now set up the GrabServer watcher. We get GrabServer
* deadlock in XRecordCreateContext() even with XTestGrabServer
* in place, why? Not sure, so we manually watch for grabs...
*/
if (gdpy_data) {
XCloseDisplay(gdpy_data);
gdpy_data = NULL;
}
if (gdpy_ctrl) {
XCloseDisplay(gdpy_ctrl);
gdpy_ctrl = NULL;
}
xserver_grabbed = 0;
gdpy_ctrl = XOpenDisplay(DisplayString(dpy));
XSync(dpy, True);
XSync(gdpy_ctrl, True);
gdpy_data = XOpenDisplay(DisplayString(dpy));
if (gdpy_ctrl && gdpy_data) {
disable_grabserver(gdpy_ctrl, 0);
disable_grabserver(gdpy_data, 0);
xrecord_grabserver(1);
}
X_UNLOCK;
#endif
}
void shutdown_xrecord(void) {
#if LIBVNCSERVER_HAVE_RECORD
if (rr_CA) XFree(rr_CA);
if (rr_CW) XFree(rr_CW);
if (rr_GS) XFree(rr_GS);
rr_CA = NULL;
rr_CW = NULL;
rr_GS = NULL;
X_LOCK;
if (rdpy_ctrl && rc_scroll) {
XRecordDisableContext(rdpy_ctrl, rc_scroll);
XRecordFreeContext(rdpy_ctrl, rc_scroll);
XSync(rdpy_ctrl, False);
rc_scroll = 0;
}
if (gdpy_ctrl && rc_grab) {
XRecordDisableContext(gdpy_ctrl, rc_grab);
XRecordFreeContext(gdpy_ctrl, rc_grab);
XSync(gdpy_ctrl, False);
rc_grab = 0;
}
if (rdpy_data) {
XCloseDisplay(rdpy_data);
rdpy_data = NULL;
}
if (rdpy_ctrl) {
XCloseDisplay(rdpy_ctrl);
rdpy_ctrl = NULL;
}
if (gdpy_data) {
XCloseDisplay(gdpy_data);
gdpy_data = NULL;
}
if (gdpy_ctrl) {
XCloseDisplay(gdpy_ctrl);
gdpy_ctrl = NULL;
}
xserver_grabbed = 0;
X_UNLOCK;
#endif
use_xrecord = 0;
}
int xrecord_skip_keysym(rfbKeySym keysym) {
KeySym sym = (KeySym) keysym;
int ok = -1, matched = 0;
......@@ -3047,7 +3231,7 @@ winattr_t scr_attr_cache[SCR_ATTR_CACHE];
double attr_cache_max_age = 1.5;
int lookup_attr_cache(Window win, int *cache_index, int *next_index) {
double dnow, t, oldest;
double now, t, oldest;
int i, old_index = -1, count = 0;
Window cwin;
......@@ -3061,13 +3245,13 @@ int lookup_attr_cache(Window win, int *cache_index, int *next_index) {
return 0;
}
dtime0(&dnow);
dtime0(&now);
for (i=0; i < SCR_ATTR_CACHE; i++) {
cwin = scr_attr_cache[i].win;
t = scr_attr_cache[i].time;
if (dnow > t + attr_cache_max_age) {
if (now > t + attr_cache_max_age) {
/* expire it even if it is the one we want */
scr_attr_cache[i].win = cwin = None;
scr_attr_cache[i].fetched = 0;
......@@ -3110,6 +3294,7 @@ if (0) fprintf(stderr, "lookup_attr_cache count: %d\n", count);
}
}
typedef struct scroll_event {
Window win, frame;
int dx, dy;
......@@ -3253,8 +3438,9 @@ if (db > 1) fprintf(stderr, "record_CA-%d\n", k++);
valid = valid_window(src, &attr, 1);
if (valid) {
XTranslateCoordinates(dpy, src, rootwin, 0, 0,
&rx, &ry, &c);
if (!xtranslate(src, rootwin, 0, 0, &rx, &ry, &c, 1)) {
valid = 0;
}
}
if (next_index >= 0) {
i = next_index;
......@@ -3289,7 +3475,7 @@ if (db > 1) fprintf(stderr, "record_CA-%d\n", k++);
}
if (dba || db) {
if (0 || dba || db) {
double st, dt;
st = (double) rec_data->server_time/1000.0;
dt = (dnow() - servertime_diff) - st;
......@@ -3744,8 +3930,9 @@ if (0) fprintf(stderr, "lookup_attr_cache MISS: %2d %2d 0x%lx %d\n",
cache_index, next_index, win, valid);
if (valid) {
XTranslateCoordinates(dpy, win, rootwin, 0, 0,
&rx, &ry, &c);
if (!xtranslate(win, rootwin, 0, 0, &rx, &ry, &c, 1)) {
valid = 0;
}
}
if (next_index >= 0) {
i = next_index;
......@@ -3780,7 +3967,7 @@ if (db > 1) fprintf(stderr, "record_CW-%d\n", k++);
}
if (db > 1) fprintf(stderr, "record_CW-%d\n", k++);
if (dba || db) {
if (0 || dba || db) {
double st, dt;
st = (double) rec_data->server_time/1000.0;
dt = (dnow() - servertime_diff) - st;
......@@ -3885,18 +4072,101 @@ void record_switch(XPointer ptr, XRecordInterceptData *rec_data) {
}
XRecordFreeData(rec_data);
}
void record_grab(XPointer ptr, XRecordInterceptData *rec_data) {
xReq *req;
/* should handle control msgs, start/stop/etc */
if (rec_data->category == XRecordStartOfData) {
;
} else if (rec_data->category == XRecordEndOfData) {
;
} else if (rec_data->category == XRecordClientStarted) {
;
} else if (rec_data->category == XRecordClientDied) {
;
} else if (rec_data->category == XRecordFromServer) {
;
}
if (rec_data->category != XRecordFromClient) {
XRecordFreeData(rec_data);
return;
}
req = (xReq *) rec_data->data;
if (req->reqType == X_GrabServer) {
double now = dnow() - x11vnc_start;
xserver_grabbed++;
if (0) rfbLog("X server Grabbed: %d %.5f\n", xserver_grabbed, now);
if (xserver_grabbed > 1) {
/*
* some apps do multiple grabs... very unlikely
* two apps will be doing it at same time.
*/
xserver_grabbed = 1;
}
} else if (req->reqType == X_UngrabServer) {
double now = dnow() - x11vnc_start;
xserver_grabbed--;
if (xserver_grabbed < 0) {
xserver_grabbed = 0;
}
if (0) rfbLog("X server Un-Grabbed: %d %.5f\n", xserver_grabbed, now);
} else {
;
}
XRecordFreeData(rec_data);
}
#endif
void check_xrecord_grabserver(void) {
int last_val, cnt = 0, i, max = 10;
double d;
#if LIBVNCSERVER_HAVE_RECORD
if (!gdpy_ctrl || !gdpy_data) {
return;
}
if (0) dtime0(&d);
XFlush(gdpy_ctrl);
for (i=0; i<max; i++) {
last_val = xserver_grabbed;
XRecordProcessReplies(gdpy_data);
if (xserver_grabbed != last_val) {
cnt++;
} else if (i > 2) {
break;
}
}
if (cnt) {
XFlush(gdpy_ctrl);
}
if (0) {
d = dtime(&d);
fprintf(stderr, "check_xrecord_grabserver: cnt=%d i=%d %.4f\n", cnt, i, d);
}
#endif
}
#if LIBVNCSERVER_HAVE_RECORD
void shutdown_record_context(XRecordContext rc, int bequiet, int reopen) {
int ret1, ret2;
int verb = (!bequiet && !quiet);
if (0 || debug_scroll) {
rfbLog("shutdown_record_context(0x%lx, %d, %d)\n", rc,
bequiet, reopen);
verb = 1;
}
ret1 = XRecordDisableContext(rdpy_ctrl, rc);
if (!ret1 && !bequiet && !quiet) {
if (!ret1 && verb) {
rfbLog("XRecordDisableContext(0x%lx) failed.\n", rc);
}
ret2 = XRecordFreeContext(rdpy_ctrl, rc_scroll);
if (!ret2 && !bequiet && !quiet) {
ret2 = XRecordFreeContext(rdpy_ctrl, rc);
if (!ret2 && verb) {
rfbLog("XRecordFreeContext(0x%lx) failed.\n", rc);
}
XFlush(rdpy_ctrl);
......@@ -3904,44 +4174,139 @@ void shutdown_record_context(XRecordContext rc, int bequiet, int reopen) {
if (reopen == 2 && ret1 && ret2) {
reopen = 0; /* 2 means reopen only on failure */
}
if (reopen && gdpy_ctrl) {
check_xrecord_grabserver();
if (xserver_grabbed) {
rfbLog("shutdown_record_context: skip reopen,"
" server grabbed\n");
reopen = 0;
}
}
if (reopen) {
char *dpystr = DisplayString(dpy);
if (debug_scroll) {
rfbLog("closing RECORD data connection.\n");
}
XCloseDisplay(rdpy_data);
rdpy_data = XOpenDisplay(dpystr);
rdpy_data = NULL;
if (! rdpy_data) {
rfbLog("Failed to reopen RECORD data connection:"
if (debug_scroll) {
rfbLog("closing RECORD control connection.\n");
}
XCloseDisplay(rdpy_ctrl);
rdpy_ctrl = NULL;
rdpy_ctrl = XOpenDisplay(dpystr);
if (! rdpy_ctrl) {
rfbLog("Failed to reopen RECORD control connection:"
"%s\n", dpystr);
rfbLog(" disabling RECORD scroll detection.\n");
use_xrecord = 0;
return;
}
XSync(dpy, False);
XCloseDisplay(rdpy_ctrl);
rdpy_ctrl = XOpenDisplay(dpystr);
disable_grabserver(rdpy_ctrl, 0);
XSync(rdpy_ctrl, True);
if (! rdpy_ctrl) {
rfbLog("Failed to reopen RECORD control connection:"
rdpy_data = XOpenDisplay(dpystr);
if (! rdpy_data) {
rfbLog("Failed to reopen RECORD data connection:"
"%s\n", dpystr);
rfbLog(" disabling RECORD scroll detection.\n");
XCloseDisplay(rdpy_ctrl);
rdpy_ctrl = NULL;
use_xrecord = 0;
return;
}
if (! bequiet && reopen == 2) {
disable_grabserver(rdpy_data, 0);
if (debug_scroll || (! bequiet && reopen == 2)) {
rfbLog("reopened RECORD data and control display"
" connections: %s\n", dpystr);
}
disable_grabserver(rdpy_ctrl);
disable_grabserver(rdpy_data);
}
}
#endif
char *xerror_string(XErrorEvent *error);
int trap_record_xerror(Display *, XErrorEvent *);
int trapped_record_xerror;
XErrorEvent *trapped_record_xerror_event;
void check_xrecord_reset(void) {
static double last_reset = 0.0;
int reset_time = 120, reset_idle = 15;
int reset_time2 = 600, reset_idle2 = 40;
double now;
XErrorHandler old_handler = NULL;
if (gdpy_ctrl) {
X_LOCK;
check_xrecord_grabserver();
X_UNLOCK;
} else {
/* more dicey if not watching grabserver */
reset_time = reset_time2;
reset_idle = reset_idle2;
}
if (!use_xrecord) {
return;
}
if (xrecording) {
return;
}
if (button_mask) {
return;
}
if (xserver_grabbed) {
return;
}
#if LIBVNCSERVER_HAVE_RECORD
if (! rc_scroll) {
return;
}
now = dnow();
if (last_reset == 0.0) {
last_reset = now;
return;
}
/*
* try to wait for a break in input to reopen the displays
* this is only to avoid XGrabServer deadlock on the repopens.
*/
if (now < last_reset + reset_time) {
return;
}
if (now < last_pointer_click_time + reset_idle) {
return;
}
if (now < last_keyboard_time + reset_idle) {
return;
}
X_LOCK;
trapped_record_xerror = 0;
old_handler = XSetErrorHandler(trap_record_xerror);
/* unlikely, but check again since we will definitely be doing it. */
if (gdpy_ctrl) {
check_xrecord_grabserver();
if (xserver_grabbed) {
XSetErrorHandler(old_handler);
X_UNLOCK;
return;
}
}
shutdown_record_context(rc_scroll, 0, 1);
rc_scroll = 0;
XSetErrorHandler(old_handler);
X_UNLOCK;
last_reset = now;
#endif
}
#define RECORD_ERROR_MSG \
if (! quiet) { \
......@@ -3956,7 +4321,7 @@ XErrorEvent *trapped_record_xerror_event;
void xrecord_watch(int start, int setby) {
Window focus, wm, c, clast;
static double create_time = 0.0;
double dnow;
double now;
static double last_error = 0.0;
int rc, db = debug_scroll;
int do_shutdown = 0;
......@@ -3964,6 +4329,8 @@ void xrecord_watch(int start, int setby) {
XErrorHandler old_handler = NULL;
static Window last_win = None, last_result = None;
if (0) db = 1;
if (nofb) {
xrecording = 0;
return;
......@@ -3975,15 +4342,25 @@ void xrecord_watch(int start, int setby) {
return;
}
dtime0(&dnow);
if (dnow < last_error + 0.5) {
dtime0(&now);
if (now < last_error + 0.5) {
return;
}
if (gdpy_ctrl) {
X_LOCK;
check_xrecord_grabserver();
X_UNLOCK;
if (xserver_grabbed) {
if (db) fprintf(stderr, "xrecord_watch: %d/%d out xserver_grabbed\n", start, setby);
return;
}
}
#if LIBVNCSERVER_HAVE_RECORD
if (! start) {
int shut_reopen = 2, shut_time = 25;
if (db) fprintf(stderr, "XRECORD OFF: %d/%d %.4f\n", xrecording, setby, dnow - x11vnc_start);
if (db) fprintf(stderr, "XRECORD OFF: %d/%d %.4f\n", xrecording, setby, now - x11vnc_start);
xrecording = 0;
if (! rc_scroll) {
xrecord_focus_window = None;
......@@ -3994,10 +4371,9 @@ if (db) fprintf(stderr, "XRECORD OFF: %d/%d %.4f\n", xrecording, setby, dnow -
return;
}
if (! do_shutdown && dnow > create_time + shut_time) {
if (! do_shutdown && now > create_time + shut_time) {
/* XXX unstable if we keep a RECORD going forever */
do_shutdown = 1;
shut_reopen = 1;
}
SCR_LOCK;
......@@ -4009,18 +4385,36 @@ if (db > 1) fprintf(stderr, "=== shutdown-scroll 0x%lx\n", rc_scroll);
old_handler = XSetErrorHandler(trap_record_xerror);
shutdown_record_context(rc_scroll, 0, shut_reopen);
if (! use_xrecord) return;
rc_scroll = 0;
/*
* n.b. there is a grabserver issue wrt
* XRecordCreateContext() even though rdpy_ctrl
* is set imprevious to grabs. Perhaps a bug
* in the X server or library...
*
* If there are further problems, a thought
* to recreate rc_scroll right after the
* reopen.
*/
if (! use_xrecord) {
XSetErrorHandler(old_handler);
X_UNLOCK;
SCR_UNLOCK;
return;
}
XRecordProcessReplies(rdpy_data);
if (trapped_record_xerror) {
RECORD_ERROR_MSG;
last_error = dnow;
last_error = now;
}
XSetErrorHandler(old_handler);
X_UNLOCK;
rc_scroll = 0;
SCR_UNLOCK;
} else {
if (rcs_scroll) {
......@@ -4042,11 +4436,16 @@ if (db > 1) fprintf(stderr, "=== disab-scroll 0x%lx 0x%lx\n", rc_scroll, rcs_scr
shutdown_record_context(rc_scroll,
0, reopen_dpys);
last_error = dnow;
rc_scroll = 0;
if (! use_xrecord) return;
last_error = now;
if (! use_xrecord) {
XSetErrorHandler(old_handler);
X_UNLOCK;
SCR_UNLOCK;
return;
}
}
XSetErrorHandler(old_handler);
X_UNLOCK;
......@@ -4076,7 +4475,7 @@ if (db > 1) fprintf(stderr, "=== disab-scroll 0x%lx 0x%lx\n", rc_scroll, rcs_scr
rcs_scroll = 0;
return;
}
if (db) fprintf(stderr, "XRECORD ON: %d/%d %.4f\n", xrecording, setby, dnow - x11vnc_start);
if (db) fprintf(stderr, "XRECORD ON: %d/%d %.4f\n", xrecording, setby, now - x11vnc_start);
if (xrecording) {
return;
......@@ -4085,7 +4484,7 @@ if (db) fprintf(stderr, "XRECORD ON: %d/%d %.4f\n", xrecording, setby, dnow -
if (do_shutdown && rc_scroll) {
static int didmsg = 0;
/* should not happen... */
if (1 || !didmsg) {
if (0 || !didmsg) {
rfbLog("warning: do_shutdown && rc_scroll\n");
didmsg = 1;
}
......@@ -4192,13 +4591,31 @@ if (db) fprintf(stderr, "--- xrecord_watch: SKIP.\n");
trapped_record_xerror = 0;
old_handler = XSetErrorHandler(trap_record_xerror);
if (! rc_scroll) {
/* do_shutdown case or first time in */
if (gdpy_ctrl) {
/*
* Even though rdpy_ctrl is impervious to grabs
* at this point, we still get deadlock, why?
* It blocks in the library find_display() call.
*/
check_xrecord_grabserver();
if (xserver_grabbed) {
XSetErrorHandler(old_handler);
X_UNLOCK;
SCR_UNLOCK;
return;
}
}
rcs_scroll = (XRecordClientSpec) clast;
rc_scroll = XRecordCreateContext(rdpy_ctrl, 0, &rcs_scroll, 1,
rr_scroll, 2);
if (! do_shutdown) {
XSync(rdpy_ctrl, False);
}
if (db) fprintf(stderr, "NEW rc: 0x%lx\n", rc_scroll);
if (rc_scroll) {
dtime0(&create_time);
} else {
......@@ -4224,11 +4641,11 @@ if (db > 1) fprintf(stderr, "=-= reg-scroll 0x%lx 0x%lx\n", rc_scroll, rcs_scr
if (!XRecordRegisterClients(rdpy_ctrl, rc_scroll, 0,
&rcs_scroll, 1, rr_scroll, 2)) {
if (1 || dnow > last_error + 60) {
if (1 || now > last_error + 60) {
rfbLog("failed to register client 0x%lx with"
" X RECORD context rc_scroll.\n", clast);
}
last_error = dnow;
last_error = now;
rcs_scroll = 0;
/* continue on for now... */
}
......@@ -4252,14 +4669,12 @@ if (db) fprintf(stderr, "rc_scroll: 0x%lx\n", rc_scroll);
} else if (! rcs_scroll || trapped_record_xerror) {
/* try again later */
shutdown_record_context(rc_scroll, 0, reopen_dpys);
if (! use_xrecord) return;
rc_scroll = 0;
last_error = dnow;
last_error = now;
XSetErrorHandler(old_handler);
X_UNLOCK;
SCR_UNLOCK;
return;
}
......@@ -4285,24 +4700,25 @@ if (db) fprintf(stderr, "rc_scroll: 0x%lx\n", rc_scroll);
(XPointer) xrecord_seq);
if (!rc || trapped_record_xerror) {
if (1 || dnow > last_error + 60) {
if (1 || now > last_error + 60) {
rfbLog("failed to enable RECORD context "
"rc_scroll: 0x%lx\n", rc_scroll);
"rc_scroll: 0x%lx rc: %d\n", rc_scroll, rc);
if (trapped_record_xerror) {
RECORD_ERROR_MSG;
}
}
shutdown_record_context(rc_scroll, 0, reopen_dpys);
if (! use_xrecord) return;
rc_scroll = 0;
last_error = dnow;
last_error = now;
xrecording = 0;
/* continue on for now... */
}
XSetErrorHandler(old_handler);
/* XXX this may cause more problems than it solves... */
if (use_xrecord) {
XFlush(rdpy_data);
}
X_UNLOCK;
SCR_UNLOCK;
......@@ -4398,14 +4814,7 @@ void clean_up_exit (int ret) {
XEFreeTC(trap_ctx);
}
#endif
#if LIBVNCSERVER_HAVE_RECORD
/* XXX currently blocks: */
#if 0
if (rdpy_ctrl && rc_scroll) XRecordDisableContext(rdpy_ctrl, rc_scroll);
if (rdpy_data) XCloseDisplay(rdpy_data);
if (rdpy_ctrl) XCloseDisplay(rdpy_ctrl);
#endif
#endif
/* XXX rdpy_ctrl, etc. cannot close w/o blocking */
XCloseDisplay(dpy);
X_UNLOCK;
......@@ -4673,6 +5082,30 @@ int valid_window(Window win, XWindowAttributes *attr_ret, int bequiet) {
return ok;
}
Bool xtranslate(Window src, Window dst, int src_x, int src_y, int *dst_x,
int *dst_y, Window *child, int bequiet) {
XErrorHandler old_handler;
Bool ok = False;
trapped_xerror = 0;
old_handler = XSetErrorHandler(trap_xerror);
if (XTranslateCoordinates(dpy, src, dst, src_x, src_y, dst_x,
dst_y, child)) {
ok = True;
}
if (trapped_xerror && trapped_xerror_event) {
if (! quiet && ! bequiet) {
rfbLog("xtranslate: trapped XError: %s (0x%lx)\n",
xerror_string(trapped_xerror_event), src);
}
ok = False;
}
XSetErrorHandler(old_handler);
trapped_xerror = 0;
return ok;
}
int wait_until_mapped(Window win) {
int ms = 50, waittime = 30;
time_t start = time(0);
......@@ -8470,7 +8903,7 @@ keyevent_t key_history[KEY_HIST];
double typing_rate(double time_window, int *repeating) {
double dt = 1.0, now = dnow();
KeySym key = NoSymbol;
int i, idx, cnt = 0, diff_keys = 0;
int i, idx, cnt = 0, repeat_keys = 0;
if (key_history_idx == -1) {
if (repeating) {
......@@ -8493,15 +8926,17 @@ double typing_rate(double time_window, int *repeating) {
break;
}
cnt++;
if (key != NoSymbol && key != key_history[idx].sym) {
diff_keys++;
}
if (key == NoSymbol) {
key = key_history[idx].sym;
repeat_keys = 1;
} else if (key == key_history[idx].sym) {
repeat_keys++;
}
}
if (repeating) {
if (! diff_keys && cnt > 4) {
*repeating = 1;
if (repeat_keys >= 2) {
*repeating = repeat_keys;
} else {
*repeating = 0;
}
......@@ -8525,18 +8960,21 @@ void keyboard(rfbBool down, rfbKeySym keysym, rfbClientPtr client) {
int idx, isbutton = 0;
allowed_input_t input;
time_t now = time(0);
double dnow;
double tnow;
static int skipped_last_down;
static rfbBool last_down;
static rfbKeySym last_keysym;
static rfbKeySym last_keysym = NoSymbol;
static rfbKeySym max_keyrepeat_last_keysym = NoSymbol;
static double max_keyrepeat_last_time = 0.0;
dtime0(&dnow);
dtime0(&tnow);
if (debug_keyboard) {
char *str;
X_LOCK;
str = XKeysymToString(keysym);
rfbLog("keyboard(%s, 0x%x \"%s\") %.4f\n", down ? "down":"up",
(int) keysym, str ? str : "null", dnow - x11vnc_start);
(int) keysym, str ? str : "null", tnow - x11vnc_start);
X_UNLOCK;
}
......@@ -8552,7 +8990,12 @@ void keyboard(rfbBool down, rfbKeySym keysym, rfbClientPtr client) {
last_down = down;
last_keysym = keysym;
last_keyboard_time = dnow;
last_keyboard_time = tnow;
last_rfb_down = down;
last_rfb_keysym = keysym;
last_rfb_keytime = tnow;
last_rfb_key_accepted = FALSE;
if (key_history_idx == -1) {
for (idx=0; idx<KEY_HIST; idx++) {
......@@ -8568,73 +9011,80 @@ void keyboard(rfbBool down, rfbKeySym keysym, rfbClientPtr client) {
}
key_history[idx].sym = keysym;
key_history[idx].down = down;
key_history[idx].time = dnow;
if (0 && max_scroll_keyrate) {
/* XXX not working... */
static int hlen = 256, hidx = 0;
static keyevent_t history[256];
static rfbKeySym last_down_skip_keysym = None;
double key_dt, keytimes[256];
int idx, i, nrep = 0, skip = 0;
if (!down) {
if (last_down_skip_keysym != None) {
if (keysym == last_down_skip_keysym) {
skip = 1;
}
key_history[idx].time = tnow;
if (use_xdamage && down && skip_duplicate_key_events &&
(keysym == XK_Alt_L || keysym == XK_Super_L)) {
int i, k, run = 0;
double delay = 1.0;
for (i=0; i<16; i++) {
k = idx - i;
if (k < 0) k += KEY_HIST;
if (!key_history[k].down) {
continue;
}
if (key_history[k].time < tnow - delay) {
break;
} else if (key_history[k].sym == XK_Alt_L) {
run++;
} else if (key_history[k].sym == XK_Super_L) {
run++;
} else {
if (last_scroll_type == SCR_KEY &&
dnow < last_scroll_event + 1.0) {
key_dt = 1.0/max_scroll_keyrate;
if (0) fprintf(stderr, "key_dt: %.4f\n", key_dt);
for (i=0; i<hlen; i++) {
idx = hidx - i - 1;
if (idx < 0) idx += hlen;
if (history[idx].sym != keysym) {
break;
}
if (dnow > history[idx].time + 1.5) {
break;
}
if (history[idx].down == down) {
if (0) fprintf(stderr, "key_dt: %.4f %d %d %.4f\n", key_dt, history[idx].sym,
history[idx].down, history[idx].time - x11vnc_start);
keytimes[nrep++] =
history[idx].time;
if (run == 3) {
rfbLog("3*Alt_L, calling: set_xdamage_mark()\n");
set_xdamage_mark(0, 0, dpy_x, dpy_y);
} else if (run == 4) {
rfbLog("4*Alt_L, calling: refresh_screen(0)\n");
refresh_screen(0);
} else if (run == 5) {
rfbLog("5*Alt_L, setting: do_copy_screen\n");
do_copy_screen = 1;
}
}
if (nrep > 0) {
idx = hidx - 1;
if (idx < 0) idx += hlen;
if (dnow < keytimes[0] + key_dt) {
skip = 1;
if (!down && skipped_last_down) {
int db = debug_scroll;
if (keysym == max_keyrepeat_last_keysym) {
skipped_last_down = 0;
if (db) rfbLog("--- scroll keyrate skipping 0x%lx %s "
"%.4f %.4f\n", keysym, down ? "down":"up ",
tnow - x11vnc_start, tnow - max_keyrepeat_last_time);
return;
}
}
if (down && max_keyrepeat_time > 0.0) {
int skip = 0;
int db = debug_scroll;
if (max_keyrepeat_last_keysym != NoSymbol &&
max_keyrepeat_last_keysym != keysym) {
;
} else {
if (tnow < max_keyrepeat_last_time+max_keyrepeat_time) {
skip = 1;
}
}
max_keyrepeat_time = 0.0;
if (skip) {
rfbLog("--- scroll keyrate skipping 0x%lx %s rep:%d "
"%.4f\n", keysym, down ? "down":"up", nrep,
down ? dnow - keytimes[0] : dnow - x11vnc_start);
if (down) {
last_down_skip_keysym = keysym;
}
if (db) rfbLog("--- scroll keyrate skipping 0x%lx %s "
"%.4f %.4f\n", keysym, down ? "down":"up ",
tnow - x11vnc_start, tnow - max_keyrepeat_last_time);
max_keyrepeat_last_keysym = keysym;
skipped_last_down = 1;
return;
}
last_down_skip_keysym = None;
history[hidx].sym = keysym;
history[hidx].time = dnow;
history[hidx].down = down;
if (++hidx >= hlen) {
hidx = 0;
} else {
if (db) rfbLog("--- scroll keyrate KEEPING 0x%lx %s "
"%.4f %.4f\n", keysym, down ? "down":"up ",
tnow - x11vnc_start, tnow - max_keyrepeat_last_time);
}
}
max_keyrepeat_last_keysym = keysym;
max_keyrepeat_last_time = tnow;
skipped_last_down = 0;
last_rfb_key_accepted = TRUE;
if (pipeinput_fh != NULL) {
pipe_keyboard(down, keysym, client);
......@@ -8645,6 +9095,11 @@ if (0) fprintf(stderr, "key_dt: %.4f %d %d %.4f\n", key_dt, history[idx].sym,
last_keyboard_input = now;
last_keysym = keysym;
last_rfb_down = down;
last_rfb_keysym = keysym;
last_rfb_keytime = tnow;
got_user_input++;
got_keyboard_input++;
}
......@@ -8665,6 +9120,11 @@ if (0) fprintf(stderr, "key_dt: %.4f %d %d %.4f\n", key_dt, history[idx].sym,
last_keyboard_input = now;
last_keysym = keysym;
last_rfb_down = down;
last_rfb_keysym = keysym;
last_rfb_keytime = tnow;
got_user_input++;
got_keyboard_input++;
......@@ -8723,6 +9183,7 @@ if (0) fprintf(stderr, "key_dt: %.4f %d %d %.4f\n", key_dt, history[idx].sym,
rfbLog("keyboard(): remapping keystroke to button %d"
" click\n", button);
}
dtime0(&last_key_to_button_remap_time);
X_LOCK;
/*
......@@ -9145,6 +9606,10 @@ static void update_x11_pointer_position(int x, int y) {
}
X_UNLOCK;
if (cursor_x != x || cursor_y != y) {
last_pointer_motion_time = dnow();
}
cursor_x = x;
cursor_y = y;
......@@ -9230,6 +9695,10 @@ static void update_x11_pointer_mask(int mask) {
if (raw_fb && ! dpy) return; /* raw_fb hack */
if (mask != button_mask) {
last_pointer_click_time = dnow();
}
if (scaling && ! got_scrollcopyrect) {
xr_mouse = 0;
} else if (nofb) {
......@@ -9268,10 +9737,18 @@ if (debug_scroll > 1) fprintf(stderr, "wm_win: 0x%lx\n", mwin);
skip = 1;
} else {
int ok = 0;
int btn4 = (1<<3);
int btn5 = (1<<4);
if (near_scrollbar_edge(x, y, w, h, px, py)) {
ok = 1;
}
if (! ok && mwin != None) {
if (mask & (btn4|btn5)) {
/* scroll wheel mouse */
ok = 1;
}
if (mwin != None) {
/* skinny internal window */
int w = attr.width;
int h = attr.height;
if (h > 10 * w || w > 10 * h) {
......@@ -9401,6 +9878,7 @@ void pipe_pointer(int mask, int x, int y, rfbClientPtr client) {
void pointer(int mask, int x, int y, rfbClientPtr client) {
allowed_input_t input;
int sent = 0, buffer_it = 0;
double now;
if (debug_pointer && mask >= 0) {
static int show_motion = -1;
......@@ -9455,6 +9933,9 @@ void pointer(int mask, int x, int y, rfbClientPtr client) {
if (view_only) {
return;
}
now = dnow();
if (mask >= 0) {
/*
* mask = -1 is a special case call from scan_for_updates()
......@@ -9468,6 +9949,8 @@ void pointer(int mask, int x, int y, rfbClientPtr client) {
got_user_input++;
got_pointer_input++;
last_pointer_client = client;
last_pointer_time = now;
}
/*
......@@ -10863,8 +11346,9 @@ void check_xevents(void) {
if (now > last_sync + 1200) {
/* kludge for any remaining event leaks */
int bugout = use_xdamage ? 500 : 50;
int qlen, i;
if (last_sync != 0) {
int qlen = XEventsQueued(dpy, QueuedAlready);
qlen = XEventsQueued(dpy, QueuedAlready);
if (qlen >= bugout) {
rfbLog("event leak: %d queued, "
" calling XSync(dpy, True)\n", qlen);
......@@ -10874,6 +11358,20 @@ void check_xevents(void) {
}
}
last_sync = now;
/* clear these, we don't want any events on them */
if (rdpy_ctrl) {
qlen = XEventsQueued(rdpy_ctrl, QueuedAlready);
for (i=0; i<qlen; i++) {
XNextEvent(rdpy_ctrl, &xev);
}
}
if (gdpy_ctrl) {
qlen = XEventsQueued(gdpy_ctrl, QueuedAlready);
for (i=0; i<qlen; i++) {
XNextEvent(gdpy_ctrl, &xev);
}
}
}
X_UNLOCK;
......@@ -11574,7 +12072,7 @@ char *process_remote_cmd(char *cmd, int stringonly) {
push_black_screen(4);
} else if (!strcmp(p, "refresh")) {
NOTAPP
refresh_screen();
refresh_screen(1);
} else if (!strcmp(p, "reset")) {
NOTAPP
do_new_fb(1);
......@@ -12459,7 +12957,7 @@ char *process_remote_cmd(char *cmd, int stringonly) {
"(if applicable).\n");
if (! xtrap_input) {
xtrap_input = 1;
disable_grabserver(dpy);
disable_grabserver(dpy, 1);
}
} else if (!strcmp(p, "noxtrap")) {
......@@ -12471,7 +12969,7 @@ char *process_remote_cmd(char *cmd, int stringonly) {
"(if applicable).\n");
if (xtrap_input) {
xtrap_input = 0;
disable_grabserver(dpy);
disable_grabserver(dpy, 1);
}
} else if (!strcmp(p, "xrandr")) {
......@@ -13401,6 +13899,24 @@ char *process_remote_cmd(char *cmd, int stringonly) {
scroll_term_str);
initialize_scroll_term();
} else if (strstr(p, "scr_keyrepeat") == p) {
char *s = max_keyrepeat_str;
if (!s || *s == '\0') s = max_keyrepeat_str0;
COLON_CHECK("scr_keyrepeat:")
if (query) {
snprintf(buf, bufn, "ans=%s%s%s", p, co, NONUL(s));
goto qry;
}
p += strlen("scr_keyrepeat:");
if (max_keyrepeat_str) {
free(max_keyrepeat_str);
}
max_keyrepeat_str = strdup(p);
rfbLog("remote_cmd: changed -scr_keyrepeat to: %s\n",
max_keyrepeat_str);
initialize_max_keyrepeat();
} else if (strstr(p, "scr_parms") == p) {
COLON_CHECK("scr_parms:")
if (query) {
......@@ -13460,6 +13976,29 @@ char *process_remote_cmd(char *cmd, int stringonly) {
rfbLog("remote_cmd: changed -scrollcopyrect mode "
"to: %s\n", NONUL(scroll_copyrect));
} else if (!strcmp(p, "noxrecord")) {
int orig = noxrecord;
if (query) {
snprintf(buf, bufn, "ans=%s:%d", p, noxrecord);
goto qry;
}
noxrecord = 1;
rfbLog("set noxrecord to: %d\n", noxrecord);
if (orig != noxrecord) {
shutdown_xrecord();
}
} else if (!strcmp(p, "xrecord")) {
int orig = noxrecord;
if (query) {
snprintf(buf, bufn, "ans=%s:%d", p, !noxrecord);
goto qry;
}
noxrecord = 0;
rfbLog("set noxrecord to: %d\n", noxrecord);
if (orig != noxrecord) {
initialize_xrecord();
}
} else if (strstr(p, "pointer_mode") == p) {
int pm;
COLON_CHECK("pointer_mode:")
......@@ -14476,6 +15015,7 @@ void add_region_xdamage(sraRegionPtr new_region) {
reg = xdamage_regions[prev_tick];
if (reg != NULL) {
if (0) fprintf(stderr, "add_region_xdamage: prev_tick: %d reg %p\n", prev_tick, reg);
sraRgnOr(reg, new_region);
}
}
......@@ -17161,7 +17701,7 @@ XImage *initialize_raw_fb(void) {
DisplayString(dpy));
XCloseDisplay(dpy); /* yow! */
}
dpy = 0;
dpy = NULL;
}
#endif
......@@ -17580,8 +18120,11 @@ XImage *initialize_xdisplay_fb(void) {
int disp_y = DisplayHeight(dpy, scr);
Window twin;
/* subwins can be a dicey if they are changing size... */
trapped_xerror = 0;
old_handler = XSetErrorHandler(trap_xerror);
XTranslateCoordinates(dpy, window, rootwin, 0, 0, &subwin_x,
&subwin_y, &twin);
if (subwin_x + wdpy_x > disp_x) {
shift = 1;
subwin_x = disp_x - wdpy_x - 3;
......@@ -17599,8 +18142,6 @@ XImage *initialize_xdisplay_fb(void) {
subwin_y = 1;
}
trapped_xerror = 0;
old_handler = XSetErrorHandler(trap_xerror);
if (shift) {
XMoveWindow(dpy, window, subwin_x, subwin_y);
}
......@@ -18982,10 +19523,9 @@ void blackout_tiles(void) {
}
/*
* to simplify things drop down to single copy mode, no vcr, etc...
* to simplify things drop down to single copy mode, etc...
*/
single_copytile = 1;
/* loop over all tiles. */
for (ty=0; ty < ntiles_y; ty++) {
for (tx=0; tx < ntiles_x; tx++) {
......@@ -19237,12 +19777,15 @@ void push_black_screen(int n) {
push_sleep(n);
}
void refresh_screen(void) {
void refresh_screen(int push) {
int i;
if (!screen) {
return;
}
mark_rect_as_modified(0, 0, dpy_x, dpy_y, 1);
for (i=0; i<push; i++) {
rfbPE(-1);
}
}
/*
......@@ -19635,6 +20178,7 @@ void initialize_polling_images(void) {
" to manually\n");
rfbLog("shm: delete unattached shm segments.\n");
single_copytile_count = i;
single_copytile = 1;
}
tile_shm_count++;
if (single_copytile && i >= 1) {
......@@ -19757,7 +20301,6 @@ static void hint_updates(void) {
}
}
for (i=0; i < hint_count; i++) {
/* pass update info to vnc: */
mark_hint(hint_list[i]);
......@@ -21432,7 +21975,7 @@ void set_offset(void) {
return;
}
X_LOCK;
XTranslateCoordinates(dpy, window, rootwin, 0, 0, &off_x, &off_y, &w);
xtranslate(window, rootwin, 0, 0, &off_x, &off_y, &w, 0);
X_UNLOCK;
}
......@@ -21880,6 +22423,7 @@ void run_gui(char *gui_xdisplay, int connect_to_x11vnc, int simple_gui,
}
if (dpy) {
XCloseDisplay(dpy);
dpy = NULL;
}
if (old_xauth) {
if (*old_xauth == '\0') {
......@@ -22792,6 +23336,30 @@ void initialize_scroll_term(void) {
}
}
void initialize_max_keyrepeat(void) {
char *str;
int lo, hi;
if (max_keyrepeat_str != NULL && *max_keyrepeat_str != '\0') {
str = max_keyrepeat_str;
} else {
str = max_keyrepeat_str0;
}
if (sscanf(str, "%d-%d", &lo, &hi) != 2) {
rfbLog("skipping invalid -scr_keyrepeat string: %s\n", str);
sscanf(max_keyrepeat_str0, "%d-%d", &lo, &hi);
}
max_keyrepeat_lo = lo;
max_keyrepeat_hi = hi;
if (max_keyrepeat_lo < 1) {
max_keyrepeat_lo = 1;
}
if (max_keyrepeat_hi > 40) {
max_keyrepeat_hi = 40;
}
}
typedef struct saveline {
int x0, y0, x1, y1;
int shift;
......@@ -23382,7 +23950,7 @@ if (n) { \
fprintf(stderr, "---PUSH\n"); \
}
int push_scr_ev(double max_age, int type, int bdpush, int bdx, int bdy,
int push_scr_ev(double *age, int type, int bdpush, int bdx, int bdy,
int bdskinny) {
Window frame, win, win0;
int x, y, w, h, wx, wy, ww, wh, dx, dy;
......@@ -23390,12 +23958,16 @@ int push_scr_ev(double max_age, int type, int bdpush, int bdx, int bdy,
int nx, ny, nw, nh;
int dret = 1, do_fb_push = 0, obscured;
int ev, ev_tot = scr_ev_cnt;
double tm, dt, st, dnow, waittime = 0.125;
double tm, dt, st, waittime = 0.125;
double max_age = *age;
int db = debug_scroll, rrate = get_read_rate();
sraRegionPtr backfill, whole, tmpregion, tmpregion2;
int link, latency, netrate;
int ypad = 0;
/* we return the oldest one. */
*age = 0.0;
if (ev_tot == 0) {
return dret;
}
......@@ -23410,8 +23982,6 @@ int push_scr_ev(double max_age, int type, int bdpush, int bdx, int bdy,
waittime *= 3;
}
dtime0(&dnow);
backfill = sraRgnCreate();
whole = sraRgnCreateRect(0, 0, dpy_x, dpy_y);
......@@ -23426,6 +23996,7 @@ int push_scr_ev(double max_age, int type, int bdpush, int bdx, int bdy,
if (db) fprintf(stderr, "ypad: %d dy[0]: %d\n", ypad, scr_ev[0].dy);
for (ev=0; ev < ev_tot; ev++) {
double ag;
x = scr_ev[ev].x;
y = scr_ev[ev].y;
......@@ -23444,12 +24015,18 @@ if (db) fprintf(stderr, "ypad: %d dy[0]: %d\n", ypad, scr_ev[0].dy);
nh = scr_ev[ev].new_h;
st = scr_ev[ev].t;
if (dabs((dnow - servertime_diff) - st) > max_age) {
if (db) fprintf(stderr, "push_scr_ev: TOO OLD: %.4f :: (%.4f - %.4f) - %.4f \n", (dnow - servertime_diff) - st, dnow, servertime_diff, st);
ag = (dnow() - servertime_diff) - st;
if (ag > *age) {
*age = ag;
}
if (dabs(ag) > max_age) {
if (db) fprintf(stderr, "push_scr_ev: TOO OLD: %.4f :: (%.4f - %.4f) "
"- %.4f \n", ag, dnow(), servertime_diff, st);
dret = 0;
break;
} else {
if (db) fprintf(stderr, "push_scr_ev: AGE: %.4f\n", (dnow - servertime_diff) - st);
if (db) fprintf(stderr, "push_scr_ev: AGE: %.4f\n", ag);
}
if (win != win0) {
if (db) fprintf(stderr, "push_scr_ev: DIFF WIN: 0x%lx != 0x%lx\n", win, win0);
......@@ -23659,7 +24236,7 @@ PUSH_TEST(0);
}
sraRgnReleaseIterator(iter);
dt = dtime(&tm);
if (0) fprintf(stderr, " dfc---- dt: %.4f", dt);
if (db) fprintf(stderr, " dfc---- dt: %.4f", dt);
}
if (db && dret) fprintf(stderr, " **** dret=%d", dret);
......@@ -23992,6 +24569,9 @@ void mark_region_for_xdamage(sraRegionPtr region) {
void set_xdamage_mark(int x, int y, int w, int h) {
sraRegionPtr region;
if (! use_xdamage) {
return;
}
mark_for_xdamage(x, y, w, h);
if (xdamage_scheduled_mark == 0.0) {
......@@ -24021,8 +24601,12 @@ int check_xrecord_keys(void) {
static int persist_count = 0;
double last_scroll, scroll_persist = scr_key_persist;
double spin_fac = 1.0, scroll_fac = 2.0;
double max_spin;
double max_long_spin = 0.3;
double max_spin, max_long_spin = 0.3;
double set_repeat_in;
static double set_repeat = 0.0;
set_repeat_in = set_repeat;
set_repeat = 0.0;
get_out = 1;
if (got_keyboard_input) {
......@@ -24034,6 +24618,10 @@ int check_xrecord_keys(void) {
get_out = 0;
}
if (set_repeat_in > 0.0 && tnow < last_key_scroll + set_repeat_in) {
get_out = 0;
}
if (get_out) {
persist_start = 0.0;
persist_count = 0;
......@@ -24048,9 +24636,14 @@ int check_xrecord_keys(void) {
max_spin = scr_key_time;
if (tnow < last_key_scroll + scroll_persist) {
if (set_repeat_in > 0.0 && tnow < last_key_scroll + 2*set_repeat_in) {
max_spin = 2 * set_repeat_in;
} else if (tnow < last_key_scroll + scroll_persist) {
max_spin = 1.25*(tnow - last_key_scroll);
} else if (xrecord_scroll_keysym(last_keysym)) {
} else if (tnow < last_key_to_button_remap_time + scroll_persist) {
/* mostly a hack I use for testing -remap key -> btn4/btn5 */
max_spin = scroll_persist;
} else if (xrecord_scroll_keysym(last_rfb_keysym)) {
spin_fac = scroll_fac;
}
if (max_spin > max_long_spin) {
......@@ -24058,13 +24651,13 @@ int check_xrecord_keys(void) {
}
/* XXX use this somehow */
link = link_rate(&latency, &netrate);
if (0) link = link_rate(&latency, &netrate);
gk = gk0 = got_keyboard_input;
dtime0(&tm);
if (db) fprintf(stderr, "check_xrecord_keys: BEGIN LOOP: scr_ev_cnt: %d max: %.3f\n",
scr_ev_cnt, max_spin);
if (db) fprintf(stderr, "check_xrecord_keys: BEGIN LOOP: scr_ev_cnt: "
"%d max: %.3f %.4f\n", scr_ev_cnt, max_spin, tm - x11vnc_start);
while (1) {
......@@ -24085,6 +24678,10 @@ if (db) fprintf(stderr, "check_xrecord_keys: BEGIN LOOP: scr_ev_cnt: %d max: %.3
XFlush(dpy);
X_UNLOCK;
if (set_repeat_in > 0.0) {
max_keyrepeat_time = set_repeat_in;
}
if (use_threads) {
usleep(1000);
} else {
......@@ -24096,10 +24693,14 @@ if (db) fprintf(stderr, "check_xrecord_keys: BEGIN LOOP: scr_ev_cnt: %d max: %.3
if (got_keyboard_input > gk) {
gk = got_keyboard_input;
input++;
if (xrecord_scroll_keysym(last_keysym)) {
if (set_repeat_in) {
;
} else if (xrecord_scroll_keysym(last_rfb_keysym)) {
spin_fac = scroll_fac;
}
if (db) fprintf(stderr, "check_xrecord: more keys: %.3f\n", spin);
if (0 || db) fprintf(stderr, "check_xrecord: more keys: %.3f 0x%x "
" %.4f %s %s\n", spin, last_rfb_keysym, last_rfb_keytime - x11vnc_start,
last_rfb_down ? "down":"up ", last_rfb_key_accepted ? "accept":"skip");
flush2 = 1;
XFlush(dpy);
}
......@@ -24109,16 +24710,20 @@ if (db) fprintf(stderr, "check_xrecord: more keys: %.3f\n", spin);
X_UNLOCK;
if (spin >= max_spin * spin_fac) {
if (db) fprintf(stderr, "check_xrecord: SPIN-OUT: %.3f/%.3f\n", spin,
if (0 || db) fprintf(stderr, "check_xrecord: SPIN-OUT: %.3f/%.3f\n", spin,
max_spin * spin_fac);
fail = 1;
break;
}
}
max_keyrepeat_time = 0.0;
if (scr_ev_cnt) {
int dret, ev = scr_ev_cnt - 1;
int bdx, bdy, bdskinny, bdpush = 0;
double max_age = 0.25, age, tm, dt;
static double last_scr_ev = 0.0;
last_wx = scr_ev[ev].win_x;
last_wy = scr_ev[ev].win_y;
......@@ -24136,10 +24741,34 @@ if (db) fprintf(stderr, "check_xrecord: SPIN-OUT: %.3f/%.3f\n", spin,
set_bdpush(SCR_KEY, &last_bdpush, &bdpush);
}
dret = push_scr_ev(0.25, SCR_KEY, bdpush, bdx, bdy, bdskinny);
dtime0(&tm);
age = max_age;
dret = push_scr_ev(&age, SCR_KEY, bdpush, bdx, bdy, bdskinny);
dt = dtime(&tm);
ret = 1 + dret;
scr_ev_cnt = 0;
if (ret == 2 && xrecord_scroll_keysym(last_rfb_keysym)) {
int repeating;
double time_lo = 1.0/max_keyrepeat_lo;
double time_hi = 1.0/max_keyrepeat_hi;
double rate = typing_rate(0.0, &repeating);
if (0 || db) fprintf(stderr, "Typing: dt: %.4f rate: %.1f\n", dt, rate);
if (repeating) {
/* n.b. the "quantum" is about 1/30 sec. */
max_keyrepeat_time = 1.0*dt;
if (max_keyrepeat_time > time_lo ||
max_keyrepeat_time < time_hi) {
max_keyrepeat_time = 0.0;
} else {
set_repeat = max_keyrepeat_time;
if (0 || db) fprintf(stderr, "set max_keyrepeat_time: %.2f\n", max_keyrepeat_time);
}
}
}
last_scr_ev = dnow();
}
if ((got_one && ret < 2) || persist_count) {
......@@ -24197,6 +24826,10 @@ int check_xrecord_mouse(void) {
static int want_back_in = 0;
int came_back_in;
int scroll_wheel = 0;
int btn4 = (1<<3);
int btn5 = (1<<4);
get_out = 1;
if (button_mask) {
get_out = 0;
......@@ -24226,6 +24859,10 @@ if (0) fprintf(stderr, "check_xrecord_mouse: IN xrecording: %d\n", xrecording);
}
want_back_in = 0;
if (button_mask & (btn4|btn5)) {
scroll_wheel = 1;
}
/*
* set up times for the various "reputations"
*
......@@ -24278,15 +24915,15 @@ if (0) fprintf(stderr, "check_xrecord_mouse: IN xrecording: %d\n", xrecording);
last_x = start_x = cursor_x;
last_y = start_y = cursor_y;
if (db) fprintf(stderr, "check_xrecord_mouse: BEGIN LOOP: scr_ev_cnt: %d max: %.3f\n",
scr_ev_cnt, max_spin[scroll_rep]);
if (db) fprintf(stderr, "check_xrecord_mouse: BEGIN LOOP: scr_ev_cnt: "
"%d max: %.3f %.4f\n", scr_ev_cnt, max_spin[scroll_rep], tm - x11vnc_start);
while (1) {
double spin_check;
if (scr_ev_cnt) {
int dret, ev = scr_ev_cnt - 1;
int bdpush = 0, bdx, bdy, bdskinny;
double tm, dt;
double tm, dt, age = 0.35;
got_one = 1;
scrollability(xrecord_ptr_window, SCR_SUCCESS);
......@@ -24309,7 +24946,7 @@ if (db) fprintf(stderr, "check_xrecord_mouse: BEGIN LOOP: scr_ev_cnt: %d max: %.
dtime0(&tm);
dret = push_scr_ev(0.35, SCR_MOUSE, bdpush, bdx,
dret = push_scr_ev(&age, SCR_MOUSE, bdpush, bdx,
bdy, bdskinny);
ret = 1 + dret;
......@@ -24406,6 +25043,10 @@ if (db) fprintf(stderr, "check_xrecord: SPIN-OUT-3: %.3f/%.3f\n", spin, max_long
} else if (came_back_in) {
dtime0(&button_up_time);
doflush = 1;
} else if (scroll_wheel) {
if (db) fprintf(stderr, "check_xrecord: SCROLL-WHEEL-BUTTON-UP-KEEP-GOING: %.3f/%.3f %d/%d %d/%d\n", spin, max_long[scroll_rep], last_x, last_y, cursor_x, cursor_y);
doflush = 1;
dtime0(&button_up_time);
} else if (last_x == cursor_x && last_y == cursor_y) {
if (db) fprintf(stderr, "check_xrecord: BUTTON-UP: %.3f/%.3f %d/%d %d/%d\n", spin, max_long[scroll_rep], last_x, last_y, cursor_x, cursor_y);
break;
......@@ -26701,6 +27342,7 @@ if (0 && dt > 0.0) fprintf(stderr, "dt: %.5f %.4f\n", dt, dnow() - x11vnc_start)
msec = (int) (1000 * 1.75 * bave);
if (dts[ndt - nave - 1] > 0.75 * bave) {
msec = 1.5 * msec;
set_xdamage_mark(0, 0, dpy_x, dpy_y);
}
if (msec > 1500) {
msec = 1500;
......@@ -26828,6 +27470,7 @@ if (debug_scroll) fprintf(stderr, "watch_loop: LOOP-BACK: %d\n", ret);
check_connect_inputs();
check_padded_fb();
check_xdamage_state();
check_xrecord_reset();
check_add_keysyms();
if (started_as_root) {
check_switched_user();
......@@ -26952,8 +27595,12 @@ static void print_help(int mode) {
"\n"
"By default x11vnc will not allow the screen to be shared and it will exit\n"
"as soon as the client disconnects. See -shared and -forever below to override\n"
"these protections. See the FAQ on how to tunnel the VNC connection through\n"
"an encrypted channel such as ssh(1).\n"
"these protections. See the FAQ for details how to tunnel the VNC connection\n"
"through an encrypted channel such as ssh(1). In brief:\n"
"\n"
" ssh -L 5900:localhost:5900 far-host 'x11vnc -localhost -display :0'\n"
"\n"
" vncviewer -encodings 'copyrect tight zrle hextile' localhost:0\n"
"\n"
"For additional info see: http://www.karlrunge.com/x11vnc/\n"
" and http://www.karlrunge.com/x11vnc/#faq\n"
......@@ -27875,6 +28522,19 @@ static void print_help(int mode) {
" the annoying artifacts. Use \"none\" to disable.\n"
" Default: \"%s\"\n"
"\n"
"-scr_keyrepeat lo-hi If a key is held down (or otherwise repeats rapidly) and\n"
" this induces a rapid sequence of scrolls (e.g. holding\n"
" down an Arrow key) the \"scrollcopyrect\" detection\n"
" and overhead may not be able to keep up. A time per\n"
" single scroll estimate is performed and if that estimate\n"
" predicts a sustainable scrollrate of keys per second\n"
" between \"lo\" and \"hi\" then repeated keys will be\n"
" DISCARDED to maintain the scrollrate. For example your\n"
" key autorepeat may be 25 keys/sec, but for a large\n"
" window or slow link only 8 scrolls per second can be\n"
" sustained, then roughly 2 out of every 3 repeated keys\n"
" will be discarded during this period. Default: \"%s\"\n"
"\n"
"-scr_parms string Set various parameters for the scrollcopyrect mode.\n"
" The format is similar to that for -wireframe and packed\n"
" with lots of parameters:\n"
......@@ -27921,6 +28581,10 @@ static void print_help(int mode) {
" heuristics. \"-ds\" is an alias. Specify it multiple\n"
" times for more output.\n"
"\n"
"-noxrecord Disable any use of the RECORD extension. This is\n"
" currently used by the -scrollcopyrect scheme and to\n"
" monitor X server grabs.\n"
"\n"
"-pointer_mode n Various pointer motion update schemes. \"-pm\" is\n"
" an alias. The problem is pointer motion can cause\n"
" rapid changes on the screen: consider the rapid changes\n"
......@@ -28403,7 +29067,10 @@ static void print_help(int mode) {
" scr_inc:list set -scr_inc to \"list\"\n"
" scr_keys:list set -scr_keys to \"list\"\n"
" scr_term:list set -scr_term to \"list\"\n"
" scr_keyrepeat:str set -scr_keyrepeat to \"str\"\n"
" scr_parms:str set -scr_parms parameters.\n"
" noxrecord disable all use of RECORD extension.\n"
" xrecord enable use of RECORD extension.\n"
" pointer_mode:n set -pointer_mode to n. same as \"pm\"\n"
" input_skip:n set -input_skip to n.\n"
" speeds:str set -speeds to str.\n"
......@@ -28519,14 +29186,15 @@ static void print_help(int mode) {
" noclear_mods clear_keys noclear_keys remap repeat\n"
" norepeat fb nofb bell nobell sel nosel primary noprimary\n"
" cursorshape nocursorshape cursorpos nocursorpos cursor\n"
" show_cursor noshow_cursor nocursor arrow xfixes noxfixes\n"
" xdamage noxdamage xd_area xd_mem alphacut alphafrac\n"
" alpharemove noalpharemove alphablend noalphablend\n"
" xwarppointer xwarp noxwarppointer noxwarp buttonmap\n"
" dragging nodragging wireframe_mode wireframe wf\n"
" nowireframe nowf wirecopyrect wcr nowirecopyrect nowcr\n"
" scr_area scr_skip scr_inc scr_keys scr_term scr_parms\n"
" scrollcopyrect scr noscrollcopyrect noscr pointer_mode\n"
" show_cursor noshow_cursor nocursor arrow xfixes\n"
" noxfixes xdamage noxdamage xd_area xd_mem alphacut\n"
" alphafrac alpharemove noalpharemove alphablend\n"
" noalphablend xwarppointer xwarp noxwarppointer\n"
" noxwarp buttonmap dragging nodragging wireframe_mode\n"
" wireframe wf nowireframe nowf wirecopyrect wcr\n"
" nowirecopyrect nowcr scr_area scr_skip scr_inc scr_keys\n"
" scr_term scr_keyrepeat scr_parms scrollcopyrect scr\n"
" noscrollcopyrect noscr noxrecord xrecord pointer_mode\n"
" pm input_skip input client_input speeds debug_pointer dp\n"
" nodebug_pointer nodp debug_keyboard dk nodebug_keyboard\n"
" nodk deferupdate defer wait_ui wait_bog nowait_bog wait\n"
......@@ -28667,6 +29335,7 @@ static void print_help(int mode) {
scrollcopyrect_min_area,
scroll_skip_str0 ? scroll_skip_str0 : "(empty)",
scroll_term_str0,
max_keyrepeat_str0,
SCROLL_COPYRECT_PARMS,
pointer_mode_max, pointer_mode,
ui_skip,
......@@ -28825,6 +29494,8 @@ static int limit_shm(void) {
limit = 1;
}
}
} else if (!strcmp(UT.sysname, "Darwin")) {
limit = 1;
}
if (limit && ! quiet) {
fprintf(stderr, "reducing shm usage on %s %s (adding "
......@@ -29455,12 +30126,20 @@ int main(int argc, char* argv[]) {
} else if (!strcmp(arg, "-scr_keys")) {
CHECK_ARGC
scroll_key_list_str = strdup(argv[++i]);
} else if (!strcmp(arg, "-scr_term")) {
CHECK_ARGC
scroll_term_str = strdup(argv[++i]);
} else if (!strcmp(arg, "-scr_keyrepeat")) {
CHECK_ARGC
max_keyrepeat_str = strdup(argv[++i]);
} else if (!strcmp(arg, "-scr_parms")) {
CHECK_ARGC
scroll_copyrect_str = strdup(argv[++i]);
} else if (!strcmp(arg, "-debug_scroll")
|| !strcmp(arg, "-ds")) {
debug_scroll++;
} else if (!strcmp(arg, "-noxrecord")) {
noxrecord = 1;
} else if (!strcmp(arg, "-pointer_mode")
|| !strcmp(arg, "-pm")) {
char *p, *s;
......@@ -29868,6 +30547,7 @@ int main(int argc, char* argv[]) {
}
initialize_scroll_matches();
initialize_scroll_term();
initialize_max_keyrepeat();
/* increase rfbwait if threaded */
if (use_threads && ! got_rfbwait) {
......@@ -30384,7 +31064,7 @@ int main(int argc, char* argv[]) {
* input is not processed) we tell the server to process our
* requests during all grabs:
*/
disable_grabserver(dpy);
disable_grabserver(dpy, 0);
/* check for RECORD */
if (! XRecordQueryVersion_wr(dpy, &maj, &min)) {
......@@ -30508,7 +31188,6 @@ int main(int argc, char* argv[]) {
initialize_signals();
initialize_speeds();
initialize_keyboard_and_pointer();
......@@ -30562,5 +31241,3 @@ int main(int argc, char* argv[]) {
#undef argc
#undef argv
}
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