Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
L
libvncserver
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
rasky
libvncserver
Commits
8aa6fb95
Commit
8aa6fb95
authored
Dec 17, 2006
by
runge
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
x11vnc: first pass at client-side caching, -ncache option.
parent
399a175f
Changes
19
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
2167 additions
and
1154 deletions
+2167
-1154
ChangeLog
x11vnc/ChangeLog
+4
-0
README
x11vnc/README
+1170
-1131
help.c
x11vnc/help.c
+26
-0
options.c
x11vnc/options.c
+3
-0
options.h
x11vnc/options.h
+3
-0
remote.c
x11vnc/remote.c
+37
-1
scan.c
x11vnc/scan.c
+25
-0
screen.c
x11vnc/screen.c
+17
-0
unixpw.c
x11vnc/unixpw.c
+11
-10
unixpw.h
x11vnc/unixpw.h
+1
-0
userinput.c
x11vnc/userinput.c
+799
-3
userinput.h
x11vnc/userinput.h
+1
-0
winattr_t.h
x11vnc/winattr_t.h
+5
-0
x11vnc.1
x11vnc/x11vnc.1
+27
-1
x11vnc.c
x11vnc/x11vnc.c
+13
-2
x11vnc.h
x11vnc/x11vnc.h
+4
-0
x11vnc_defs.c
x11vnc/x11vnc_defs.c
+3
-1
xevents.c
x11vnc/xevents.c
+2
-1
xinerama.c
x11vnc/xinerama.c
+16
-4
No files found.
x11vnc/ChangeLog
View file @
8aa6fb95
2006-12-17 Karl Runge <runge@karlrunge.com>
* x11vnc: first pass at client-side caching, -ncache option.
have -http guess ../classes/.. to run out of build area.
2006-12-17 Karl Runge <runge@karlrunge.com>
* x11vnc: make -xwarppointer the default if xinerama is active.
...
...
x11vnc/README
View file @
8aa6fb95
This source diff could not be displayed because it is too large. You can
view the blob
instead.
x11vnc/help.c
View file @
8aa6fb95
...
...
@@ -2014,6 +2014,32 @@ void print_help(int mode) {
" text selection, and some menu traversals. It overrides
\n
"
" any -pointer_mode setting.
\n
"
"
\n
"
#ifndef NO_NCACHE
"-ncache n Client-side caching scheme. Framebuffer memory
\"
n
\"\n
"
" (an integer) times that of the full display is allocated
\n
"
" below the actual framebuffer to cache screen contents
\n
"
" for rapid retrieval. So a W x H frambuffer is expanded
\n
"
" to a W x (n+1)*H one. Use 0 to disable. Default: XXX.
\n
"
"
\n
"
" This is an experimental option, currently implemented
\n
"
" in an awkward way in that in the VNC Viewer you can
\n
"
" see the cache contents if you scroll down, etc. So you
\n
"
" will have to set things up so you can't see that region.
\n
"
" If this method is successful, the changes required for
\n
"
" clients to do this less awkwardly will be investigated.
\n
"
"
\n
"
" Note that this mode consumes a lot of memory, both
\n
"
" on the x11vnc server side and on the VNC Viewer side.
\n
"
" If n=2 then the amount of RAM used is roughly tripled
\n
"
" for both x11vnc and the VNC Viewer. As a rule of
\n
"
" thumb, note that 1280x1024 at depth 24 is about 5MB of
\n
"
" pixel data.
\n
"
"
\n
"
" Because of the way window backingstore and saveunders
\n
"
" are implemented, n must be even. It will be incremented
\n
"
" by 1 if it is not.
\n
"
"
\n
"
#endif
"-wireframe [str] Try to detect window moves or resizes when a mouse
\n
"
"-nowireframe button is held down and show a wireframe instead of
\n
"
" the full opaque window. This is based completely on
\n
"
...
...
x11vnc/options.c
View file @
8aa6fb95
...
...
@@ -193,6 +193,9 @@ char *wireframe_copyrect_default = "never";
int
wireframe_in_progress
=
0
;
int
wireframe_local
=
1
;
int
ncache
=
0
;
int
ncache0
=
0
;
/* T+B+L+R,tkey+presist_key,tmouse+persist_mouse */
char
*
scroll_copyrect_str
=
NULL
;
#ifndef SCROLL_COPYRECT
...
...
x11vnc/options.h
View file @
8aa6fb95
...
...
@@ -155,6 +155,9 @@ extern char *wireframe_copyrect;
extern
char
*
wireframe_copyrect_default
;
extern
int
wireframe_in_progress
;
extern
int
ncache
;
extern
int
ncache0
;
extern
char
*
scroll_copyrect_str
;
extern
char
*
scroll_copyrect
;
extern
char
*
scroll_copyrect_default
;
...
...
x11vnc/remote.c
View file @
8aa6fb95
...
...
@@ -25,6 +25,7 @@
#include "selection.h"
#include "unixpw.h"
#include "uinput.h"
#include "userinput.h"
int
send_remote_cmd
(
char
*
cmd
,
int
query
,
int
wait
);
int
do_remote_query
(
char
*
remote_cmd
,
char
*
query_cmd
,
int
remote_sync
,
...
...
@@ -335,6 +336,13 @@ int check_httpdir(void) {
}
else
{
snprintf
(
httpdir
,
len
,
"%s/../share/x11vnc/classes"
,
prog
);
}
if
(
stat
(
httpdir
,
&
sbuf
)
!=
0
)
{
if
(
use_openssl
||
use_stunnel
||
http_ssl
)
{
snprintf
(
httpdir
,
len
,
"%s/../classes/ssl"
,
prog
);
}
else
{
snprintf
(
httpdir
,
len
,
"%s/../classes"
,
prog
);
}
}
free
(
prog
);
if
(
stat
(
httpdir
,
&
sbuf
)
==
0
)
{
...
...
@@ -749,7 +757,35 @@ char *process_remote_cmd(char *cmd, int stringonly) {
/*
* Maybe add: passwdfile logfile bg rfbauth passwd...
*/
if
(
!
strcmp
(
p
,
"stop"
)
||
!
strcmp
(
p
,
"quit"
)
||
if
(
strstr
(
p
,
"CR:"
)
==
p
)
{
/* skip-cmd-list */
/* CR:WxH+X+Y,dx,dy */
int
w
,
h
,
x
,
y
,
dx
,
dy
;
NOTAPP
if
(
sscanf
(
p
+
3
,
"%dx%d+%d+%d,%d,%d"
,
&
w
,
&
h
,
&
x
,
&
y
,
&
dx
,
&
dy
)
==
6
)
{
sraRegionPtr
r
;
rfbLog
(
"rfbDoCopyRect(screen, %d, %d, %d, %d, %d, %d)
\n
"
,
x
,
y
,
x
+
w
,
y
+
h
,
dx
,
dy
);
r
=
sraRgnCreateRect
(
x
,
y
,
x
+
w
,
y
+
h
);
do_copyregion
(
r
,
dx
,
dy
);
fb_push
();
sraRgnDestroy
(
r
);
rfbLog
(
"did
\n
"
);
}
else
{
rfbLog
(
"remote_cmd: bad CR string: %s
\n
"
,
p
);
}
}
else
if
(
strstr
(
p
,
"ncache"
)
==
p
)
{
/* skip-cmd-list */
COLON_CHECK
(
"ncache:"
)
if
(
query
)
{
snprintf
(
buf
,
bufn
,
"ans=%s%s%d"
,
p
,
co
,
ncache
);
goto
qry
;
}
p
+=
strlen
(
"ncache:"
);
ncache
=
atoi
(
p
);
if
(
ncache
%
2
!=
0
)
{
ncache
++
;
}
rfbLog
(
"remote_cmd: set -ncache %d
\n
"
,
ncache
);
}
else
if
(
!
strcmp
(
p
,
"stop"
)
||
!
strcmp
(
p
,
"quit"
)
||
!
strcmp
(
p
,
"exit"
)
||
!
strcmp
(
p
,
"shutdown"
))
{
NOTAPP
if
(
client_connect_file
)
{
...
...
x11vnc/scan.c
View file @
8aa6fb95
...
...
@@ -2816,6 +2816,31 @@ static int scan_display(int ystart, int rescan) {
/* grab the horizontal scanline from the display: */
X_LOCK
;
#ifndef NO_NCACHE
#if !NO_X11
if
(
ncache
>
0
&&
dpy
)
{
/* XXX watch for problems. */
XEvent
ev
;
int
gotone
=
0
;
if
(
XCheckTypedEvent
(
dpy
,
MapNotify
,
&
ev
))
{
gotone
=
1
;
}
else
if
(
XCheckTypedEvent
(
dpy
,
UnmapNotify
,
&
ev
))
{
gotone
=
2
;
}
else
if
(
XCheckTypedEvent
(
dpy
,
CreateNotify
,
&
ev
))
{
gotone
=
3
;
}
if
(
gotone
)
{
XPutBackEvent
(
dpy
,
&
ev
);
X_UNLOCK
;
fprintf
(
stderr
,
"*** SCAN_DISPLAY CHECK_NCACHE/%d *** %d
\n
"
,
gotone
,
y
);
check_ncache
(
0
);
X_LOCK
;
}
}
#endif
#endif
XRANDR_SET_TRAP_RET
(
-
1
,
"scan_display-set"
);
copy_image
(
scanline
,
0
,
y
,
0
,
0
);
XRANDR_CHK_TRAP_RET
(
-
1
,
"scan_display-chk"
);
...
...
x11vnc/screen.c
View file @
8aa6fb95
...
...
@@ -2033,6 +2033,23 @@ void initialize_screen(int *argc, char **argv, XImage *fb) {
}
}
#ifndef NO_NCACHE
if
(
ncache
>
0
)
{
char
*
new_fb
;
int
sz
=
fb
->
height
*
fb
->
bytes_per_line
;
new_fb
=
(
char
*
)
calloc
((
size_t
)
(
sz
*
(
1
+
ncache
)),
1
);
if
(
fb
->
data
)
{
memcpy
(
new_fb
,
fb
->
data
,
sz
);
free
(
fb
->
data
);
}
fb
->
data
=
new_fb
;
fb
->
height
*=
(
1
+
ncache
);
height
*=
(
1
+
ncache
);
ncache0
=
ncache
;
}
#endif
if
(
cmap8to24
&&
depth
==
8
)
{
rfb_bytes_per_line
*=
4
;
rot_bytes_per_line
*=
4
;
...
...
x11vnc/unixpw.c
View file @
8aa6fb95
...
...
@@ -56,6 +56,7 @@ extern char *crypt(const char*, const char *);
#undef UNIXPW_CRYPT
#endif
int
white_pixel
(
void
);
void
unixpw_screen
(
int
init
);
void
unixpw_keystroke
(
rfbBool
down
,
rfbKeySym
keysym
,
int
init
);
void
unixpw_accept
(
char
*
user
);
...
...
@@ -65,7 +66,7 @@ int su_verify(char *user, char *pass, char *cmd, char *rbuf, int *rbuf_size);
int
crypt_verify
(
char
*
user
,
char
*
pass
);
int
cmd_verify
(
char
*
user
,
char
*
pass
);
static
int
white
(
void
);
static
int
text_x
(
void
);
static
int
text_y
(
void
);
static
void
set_db
(
void
);
...
...
@@ -89,7 +90,7 @@ static int char_x = 0, char_y = 0, char_w = 8, char_h = 16;
static
int
db
=
0
;
static
int
white
(
void
)
{
int
white_pixel
(
void
)
{
static
unsigned
long
black_pix
=
0
,
white_pix
=
1
,
set
=
0
;
RAWFB_RET
(
0xffffff
)
...
...
@@ -162,7 +163,7 @@ void unixpw_screen(int init) {
pscreen
=
screen
;
}
rfbDrawString
(
pscreen
,
&
default8x16Font
,
x
,
y
,
log
,
white
());
rfbDrawString
(
pscreen
,
&
default8x16Font
,
x
,
y
,
log
,
white
_pixel
());
char_x
=
x
;
char_y
=
y
;
...
...
@@ -1075,13 +1076,13 @@ if (db) fprintf(stderr, "unixpw_verify: '%s' '%s'\n", user, db > 1 ? pass : "***
x
=
text_x
();
y
=
text_y
();
rfbDrawString
(
pscreen
,
&
default8x16Font
,
x
,
y
,
li
,
white
());
rfbDrawString
(
pscreen
,
&
default8x16Font
,
x
,
y
,
li
,
white
_pixel
());
char_row
+=
2
;
x
=
text_x
();
y
=
text_y
();
rfbDrawString
(
pscreen
,
&
default8x16Font
,
x
,
y
,
log
,
white
());
rfbDrawString
(
pscreen
,
&
default8x16Font
,
x
,
y
,
log
,
white
_pixel
());
char_col
=
strlen
(
log
);
...
...
@@ -1245,7 +1246,7 @@ void unixpw_keystroke(rfbBool down, rfbKeySym keysym, int init) {
x
=
text_x
();
y
=
text_y
();
rfbDrawString
(
pscreen
,
&
default8x16Font
,
x
,
y
,
pw
,
white
());
white
_pixel
());
char_col
=
strlen
(
pw
);
if
(
scaling
)
{
...
...
@@ -1279,7 +1280,7 @@ void unixpw_keystroke(rfbBool down, rfbKeySym keysym, int init) {
x
=
text_x
();
y
=
text_y
();
rfbDrawString
(
pscreen
,
&
default8x16Font
,
x
,
y
,
str
,
white
());
str
,
white
_pixel
());
mark_rect_as_modified
(
x
,
y
-
char_h
,
x
+
char_w
,
y
,
scaling
);
char_col
++
;
...
...
@@ -1323,7 +1324,7 @@ void unixpw_keystroke(rfbBool down, rfbKeySym keysym, int init) {
if
(
db
&&
db
<=
2
)
fprintf
(
stderr
,
"u_cnt: %d %d/%d ks: 0x%x '%s'
\n
"
,
u_cnt
,
x
,
y
,
keysym
,
keystr
);
rfbDrawString
(
pscreen
,
&
default8x16Font
,
x
,
y
,
keystr
,
white
());
rfbDrawString
(
pscreen
,
&
default8x16Font
,
x
,
y
,
keystr
,
white
_pixel
());
mark_rect_as_modified
(
x
,
y
-
char_h
,
x
+
char_w
,
y
,
scaling
);
char_col
++
;
...
...
@@ -1555,7 +1556,7 @@ void unixpw_deny(void) {
x
=
char_x
+
char_col
*
char_w
;
y
=
char_y
+
char_row
*
char_h
;
rfbDrawString
(
pscreen
,
&
default8x16Font
,
x
,
y
,
pd
,
white
());
rfbDrawString
(
pscreen
,
&
default8x16Font
,
x
,
y
,
pd
,
white
_pixel
());
if
(
scaling
)
{
mark_rect_as_modified
(
0
,
0
,
scaled_x
,
scaled_y
,
1
);
}
else
{
...
...
@@ -1587,7 +1588,7 @@ void unixpw_msg(char *msg, int delay) {
x
=
char_x
+
char_col
*
char_w
;
y
=
char_y
+
char_row
*
char_h
;
rfbDrawString
(
pscreen
,
&
default8x16Font
,
x
,
y
,
msg
,
white
());
rfbDrawString
(
pscreen
,
&
default8x16Font
,
x
,
y
,
msg
,
white
_pixel
());
if
(
scaling
)
{
mark_rect_as_modified
(
0
,
0
,
scaled_x
,
scaled_y
,
1
);
}
else
{
...
...
x11vnc/unixpw.h
View file @
8aa6fb95
...
...
@@ -3,6 +3,7 @@
/* -- unixpw.h -- */
extern
int
white_pixel
(
void
);
extern
void
unixpw_screen
(
int
init
);
extern
void
unixpw_keystroke
(
rfbBool
down
,
rfbKeySym
keysym
,
int
init
);
extern
void
unixpw_accept
(
char
*
user
);
...
...
x11vnc/userinput.c
View file @
8aa6fb95
...
...
@@ -53,10 +53,9 @@ int check_xrecord(void);
int
check_wireframe
(
void
);
int
fb_update_sent
(
int
*
count
);
int
check_user_input
(
double
dt
,
double
dtr
,
int
tile_diffs
,
int
*
cnt
);
void
do_copyregion
(
sraRegionPtr
region
,
int
dx
,
int
dy
);
static
void
get_client_regions
(
int
*
req
,
int
*
mod
,
int
*
cpy
,
int
*
num
)
;
static
void
do_copyregion
(
sraRegionPtr
region
,
int
dx
,
int
dy
)
;
static
void
parse_scroll_copyrect_str
(
char
*
scr
);
static
void
parse_wireframe_str
(
char
*
wf
);
static
void
destroy_str_list
(
char
**
list
);
...
...
@@ -81,6 +80,8 @@ static void check_user_input2(double dt);
static
void
check_user_input3
(
double
dt
,
double
dtr
,
int
tile_diffs
);
static
void
check_user_input4
(
double
dt
,
double
dtr
,
int
tile_diffs
);
winattr_t
*
cache_list
;
int
lookup_win_index
(
Window
);
/*
* For -wireframe: find the direct child of rootwin that has the
...
...
@@ -1757,7 +1758,7 @@ static void get_client_regions(int *req, int *mod, int *cpy, int *num) {
* is being done. Note that copyrect under the scaling case is often
* only approximate.
*/
static
void
do_copyregion
(
sraRegionPtr
region
,
int
dx
,
int
dy
)
{
void
do_copyregion
(
sraRegionPtr
region
,
int
dx
,
int
dy
)
{
sraRectangleIterator
*
iter
;
sraRect
rect
;
int
Bpp0
=
bpp
/
8
,
Bpp
;
...
...
@@ -3364,6 +3365,7 @@ int check_wireframe(void) {
double
max_spin
=
wireframe_t3
;
double
min_draw
=
wireframe_t4
;
int
try_it
=
0
;
Window
desc
[
6
];
DB_SET
if
(
unixpw_in_progress
)
return
0
;
...
...
@@ -3837,6 +3839,43 @@ if (db) fprintf(stderr, "sent_copyrect: %d - obs: %d frame: 0x%lx\n", sent_copy
/* no diff for now... */
fb_push_wait
(
0
.
1
,
FB_COPY
);
}
#ifndef NO_NCACHE
if
(
ncache
>
0
)
{
int
idx
=
lookup_win_index
(
frame
);
fprintf
(
stderr
,
"sent_copyrect: idx=%d 0x%x
\n
"
,
idx
,
frame
);
if
(
idx
<
0
)
{
idx
=
lookup_win_index
(
orig_frame
);
fprintf
(
stderr
,
"sent_copyrect: idx=%d 0x%x
\n
"
,
idx
,
orig_frame
);
}
if
(
idx
>=
0
&&
cache_list
[
idx
].
su_time
>
0
.
0
)
{
sraRegionPtr
r0
,
r1
,
r2
;
sraRectangleIterator
*
iter
;
sraRect
rt
;
int
su_x
=
cache_list
[
idx
].
su_x
;
int
su_y
=
cache_list
[
idx
].
su_y
;
int
dx
,
dy
;
r0
=
sraRgnCreateRect
(
0
,
0
,
dpy_x
,
dpy_y
);
r1
=
sraRgnCreateRect
(
orig_x
,
orig_y
,
orig_x
+
orig_w
,
orig_y
+
orig_h
);
sraRgnAnd
(
r1
,
r0
);
r2
=
sraRgnCreateRect
(
x
,
y
,
x
+
w
,
y
+
h
);
sraRgnAnd
(
r2
,
r0
);
sraRgnSubtract
(
r1
,
r2
);
dx
=
orig_x
-
su_x
;
dy
=
orig_y
-
su_y
;
fprintf
(
stderr
,
"sent_copyrect: su_restore: %d %d
\n
"
,
dx
,
dy
);
do_copyregion
(
r1
,
dx
,
dy
);
fb_push_wait
(
0
.
1
,
FB_COPY
);
fprintf
(
stderr
,
"sent_copyrect: su_restore: done.
\n
"
);
sraRgnDestroy
(
r0
);
sraRgnDestroy
(
r1
);
sraRgnDestroy
(
r2
);
cache_list
[
idx
].
su_time
=
0
.
0
;
}
}
#endif
if
(
scaling
)
{
static
double
last_time
=
0
.
0
;
double
now
=
dnow
(),
delay
=
0
.
35
;
...
...
@@ -4504,4 +4543,761 @@ if (debug_scroll && rc > 1) fprintf(stderr, " CXR: check_user_input ret %d\n",
return
0
;
}
#if defined(NO_NCACHE) || NO_X11
void
check_ncache
(
void
)
{
return
;
}
int
lookup_win_index
(
Window
win
)
{
return
-
1
;
}
#else
/* maybe ncache.c it if works */
winattr_t
*
cache_list
=
NULL
;
int
cache_list_num
=
0
;
int
cache_list_len
=
0
;
void
snapshot_cache_list
(
int
free_only
,
double
allowed_age
)
{
static
double
last_snap
=
0
.
0
,
last_free
=
0
.
0
;
double
now
;
int
num
,
rc
,
i
,
j
;
unsigned
int
ui
;
Window
r
,
w
;
Window
*
list
;
int
start
=
2048
;
if
(
!
cache_list
)
{
cache_list
=
(
winattr_t
*
)
malloc
(
start
*
sizeof
(
winattr_t
));
cache_list_num
=
0
;
cache_list_len
=
start
;
}
dtime0
(
&
now
);
if
(
free_only
)
{
/* we really don't free it, just reset to zero windows */
cache_list_num
=
0
;
last_free
=
now
;
return
;
}
if
(
cache_list_num
&&
now
<
last_snap
+
allowed_age
)
{
return
;
}
cache_list_num
=
0
;
last_free
=
now
;
#ifdef MACOSX
if
(
!
macosx_console
)
{
RAWFB_RET_VOID
}
#else
RAWFB_RET_VOID
#endif
#if NO_X11 && !defined(MACOSX)
return
;
#else
X_LOCK
;
/* no need to trap error since rootwin */
rc
=
XQueryTree_wr
(
dpy
,
rootwin
,
&
r
,
&
w
,
&
list
,
&
ui
);
num
=
(
int
)
ui
;
if
(
!
rc
)
{
cache_list_num
=
0
;
last_free
=
now
;
last_snap
=
0
.
0
;
X_UNLOCK
;
return
;
}
last_snap
=
now
;
if
(
num
>
cache_list_len
)
{
int
n
=
2
*
num
;
free
(
cache_list
);
cache_list
=
(
winattr_t
*
)
malloc
(
n
*
sizeof
(
winattr_t
));
cache_list_len
=
n
;
}
j
=
0
;
for
(
i
=
0
;
i
<
num
;
i
++
)
{
cache_list
[
j
].
win
=
list
[
i
];
cache_list
[
j
].
fetched
=
0
;
cache_list
[
j
].
valid
=
0
;
cache_list
[
j
].
time
=
now
;
cache_list
[
j
].
selectinput
=
0
;
j
++
;
}
cache_list_num
=
num
;
XFree_wr
(
list
);
X_UNLOCK
;
#endif
/* NO_X11 */
}
#define NRECENT 32
Window
recent
[
NRECENT
];
int
recidx
[
NRECENT
];
int
rlast
,
rfree
;
int
lookup_win_index
(
Window
win
)
{
int
k
,
idx
=
-
1
;
int
foundfree
=
0
;
if
(
win
==
rootwin
||
win
==
None
)
{
return
idx
;
}
for
(
k
=
0
;
k
<
NRECENT
;
k
++
)
{
if
(
recent
[
k
]
==
win
)
{
int
k2
=
recidx
[
k
];
if
(
cache_list
[
k2
].
win
==
win
)
{
idx
=
k2
;
fprintf
(
stderr
,
"recentA: %d 0x%x
\n
"
,
idx
,
win
);
break
;
}
}
}
if
(
idx
<
0
)
{
for
(
k
=
0
;
k
<
cache_list_num
;
k
++
)
{
if
(
!
foundfree
&&
cache_list
[
k
].
win
==
None
)
{
rfree
=
k
;
foundfree
=
1
;
}
if
(
cache_list
[
k
].
win
==
win
)
{
idx
=
k
;
fprintf
(
stderr
,
"recentB: %d 0x%x
\n
"
,
idx
,
win
);
break
;
}
}
if
(
idx
>=
0
)
{
recent
[
rlast
]
=
win
;
recidx
[
rlast
++
]
=
idx
;
rlast
=
rlast
%
NRECENT
;
}
}
if
(
idx
<
0
)
{
fprintf
(
stderr
,
"recentC: %d 0x%x
\n
"
,
idx
,
win
);
}
return
idx
;
}
int
lookup_free_index
(
void
)
{
int
k
;
if
(
rfree
>=
0
)
{
if
(
cache_list
[
rfree
].
win
==
None
)
{
fprintf
(
stderr
,
"lookup_freeA: %d
\n
"
,
rfree
);
return
rfree
;
}
}
rfree
=
-
1
;
for
(
k
=
0
;
k
<
cache_list_num
;
k
++
)
{
if
(
cache_list
[
k
].
win
==
None
)
{
rfree
=
k
;
break
;
}
}
if
(
rfree
<
0
)
{
rfree
=
cache_list_num
++
;
if
(
rfree
>=
cache_list_len
)
{
/* bad news... */
fprintf
(
stderr
,
"Whoops: %d %d
\n
"
,
rfree
,
cache_list_len
);
}
}
fprintf
(
stderr
,
"lookup_freeB: %d
\n
"
,
rfree
);
return
rfree
;
}
#define STORE(k, w, attr) \
cache_list[k].win = w; \
cache_list[k].fetched = 1; \
cache_list[k].valid = 1; \
cache_list[k].x = attr.x; \
cache_list[k].y = attr.y; \
cache_list[k].width = attr.width; \
cache_list[k].height = attr.height; \
cache_list[k].map_state = attr.map_state; \
cache_list[k].time = dnow();
#define CLEAR(k) \
cache_list[k].bs_x = -1; \
cache_list[k].bs_y = -1; \
cache_list[k].bs_w = -1; \
cache_list[k].bs_h = -1; \
cache_list[k].su_x = -1; \
cache_list[k].su_y = -1; \
cache_list[k].su_w = -1; \
cache_list[k].su_h = -1; \
cache_list[k].bs_time = 0.0; \
cache_list[k].su_time = 0.0; \
cache_list[k].selectinput = 0;
#define DELETE(k) \
cache_list[k].win = None; \
cache_list[k].fetched = 0; \
cache_list[k].valid = 0; \
free_rect(k);
char
*
Etype
(
int
type
)
{
if
(
type
==
KeyPress
)
return
"KeyPress"
;
if
(
type
==
KeyRelease
)
return
"KeyRelease"
;
if
(
type
==
ButtonPress
)
return
"ButtonPress"
;
if
(
type
==
ButtonRelease
)
return
"ButtonRelease"
;
if
(
type
==
MotionNotify
)
return
"MotionNotify"
;
if
(
type
==
EnterNotify
)
return
"EnterNotify"
;
if
(
type
==
LeaveNotify
)
return
"LeaveNotify"
;
if
(
type
==
FocusIn
)
return
"FocusIn"
;
if
(
type
==
FocusOut
)
return
"FocusOut"
;
if
(
type
==
KeymapNotify
)
return
"KeymapNotify"
;
if
(
type
==
Expose
)
return
"Expose"
;
if
(
type
==
GraphicsExpose
)
return
"GraphicsExpose"
;
if
(
type
==
NoExpose
)
return
"NoExpose"
;
if
(
type
==
VisibilityNotify
)
return
"VisibilityNotify"
;
if
(
type
==
CreateNotify
)
return
"CreateNotify"
;
if
(
type
==
DestroyNotify
)
return
"DestroyNotify"
;
if
(
type
==
UnmapNotify
)
return
"UnmapNotify"
;
if
(
type
==
MapNotify
)
return
"MapNotify"
;
if
(
type
==
MapRequest
)
return
"MapRequest"
;
if
(
type
==
ReparentNotify
)
return
"ReparentNotify"
;
if
(
type
==
ConfigureNotify
)
return
"ConfigureNotify"
;
if
(
type
==
ConfigureRequest
)
return
"ConfigureRequest"
;
if
(
type
==
GravityNotify
)
return
"GravityNotify"
;
if
(
type
==
ResizeRequest
)
return
"ResizeRequest"
;
if
(
type
==
CirculateNotify
)
return
"CirculateNotify"
;
if
(
type
==
CirculateRequest
)
return
"CirculateRequest"
;
if
(
type
==
PropertyNotify
)
return
"PropertyNotify"
;
if
(
type
==
SelectionClear
)
return
"SelectionClear"
;
if
(
type
==
SelectionRequest
)
return
"SelectionRequest"
;
if
(
type
==
SelectionNotify
)
return
"SelectionNotify"
;
if
(
type
==
ColormapNotify
)
return
"ColormapNotify"
;
if
(
type
==
ClientMessage
)
return
"ClientMessage"
;
if
(
type
==
MappingNotify
)
return
"MappingNotify"
;
if
(
type
==
LASTEvent
)
return
"LASTEvent"
;
return
"Unknown"
;
}
sraRegionPtr
rect_reg
[
32
];
int
find_rect
(
int
idx
,
int
x
,
int
y
,
int
w
,
int
h
)
{
static
int
first
=
1
;
sraRegionPtr
r1
,
r2
;
sraRectangleIterator
*
iter
;
sraRect
rt
;
int
n
,
x_hit
=
-
1
,
y_hit
=
-
1
;
if
(
first
)
{
first
=
0
;
for
(
n
=
1
;
n
<=
ncache
;
n
++
)
{
rect_reg
[
n
]
=
sraRgnCreateRect
(
0
,
n
*
dpy_y
,
dpy_x
,
(
n
+
1
)
*
dpy_y
);
}
}
for
(
n
=
1
;
n
<
ncache
;
n
+=
2
)
{
r1
=
rect_reg
[
n
];
r2
=
NULL
;
iter
=
sraRgnGetIterator
(
r1
);
while
(
sraRgnIteratorNext
(
iter
,
&
rt
))
{
int
rw
=
nabs
(
rt
.
x2
-
rt
.
x1
);
int
rh
=
nabs
(
rt
.
y2
-
rt
.
y1
);
if
(
rw
>=
w
&&
rh
>=
h
)
{
if
(
rt
.
x1
<
rt
.
x2
)
{
x_hit
=
rt
.
x1
;
}
else
{
x_hit
=
rt
.
x2
;
}
if
(
rt
.
y1
<
rt
.
y2
)
{
y_hit
=
rt
.
y1
;
}
else
{
y_hit
=
rt
.
y2
;
}
r2
=
sraRgnCreateRect
(
x_hit
,
y_hit
,
x_hit
+
w
,
y_hit
+
h
);
break
;
}
}
sraRgnReleaseIterator
(
iter
);
if
(
r2
!=
NULL
)
{
sraRgnSubtract
(
r1
,
r2
);
sraRgnDestroy
(
r2
);
break
;
}
}
if
(
x_hit
<
0
)
{
/* bad news */
fprintf
(
stderr
,
"*FAIL rect: %d %d %d %d -- %d %d
\n
"
,
x
,
y
,
w
,
h
,
x_hit
,
y_hit
);
}
else
{
fprintf
(
stderr
,
"found rect: %d %d %d %d -- %d %d
\n
"
,
x
,
y
,
w
,
h
,
x_hit
,
y_hit
);
}
cache_list
[
idx
].
bs_x
=
x_hit
;
cache_list
[
idx
].
bs_y
=
y_hit
;
cache_list
[
idx
].
bs_w
=
w
;
cache_list
[
idx
].
bs_h
=
h
;
cache_list
[
idx
].
su_x
=
x_hit
;
cache_list
[
idx
].
su_y
=
y_hit
+
dpy_y
;
cache_list
[
idx
].
su_w
=
w
;
cache_list
[
idx
].
su_h
=
h
;
}
int
free_rect
(
int
idx
)
{
int
n
,
ok
=
0
;
sraRegionPtr
r1
,
r2
;
int
x
,
y
,
w
,
h
;
x
=
cache_list
[
idx
].
bs_x
;
y
=
cache_list
[
idx
].
bs_y
;
w
=
cache_list
[
idx
].
bs_w
;
h
=
cache_list
[
idx
].
bs_h
;
if
(
x
<
0
)
{
CLEAR
(
idx
);
fprintf
(
stderr
,
"free_rect: invalid: %d
\n
"
,
idx
);
return
0
;
}
r2
=
sraRgnCreateRect
(
x
,
y
,
x
+
w
,
y
+
h
);
for
(
n
=
1
;
n
<
ncache
;
n
+=
2
)
{
if
(
y
>=
n
*
dpy_y
&&
y
<
(
n
+
1
)
*
dpy_y
)
{
r1
=
rect_reg
[
n
];
sraRgnOr
(
r1
,
r2
);
ok
=
1
;
fprintf
(
stderr
,
"free_rect: found %d region: %d
\n
"
,
idx
,
n
);
break
;
}
}
sraRgnDestroy
(
r2
);
CLEAR
(
idx
);
if
(
!
ok
)
fprintf
(
stderr
,
"free_rect: not-found %d
\n
"
,
idx
);
return
ok
;
}
int
bs_save
(
int
idx
)
{
Window
win
=
cache_list
[
idx
].
win
;
XWindowAttributes
attr
;
int
x1
,
y1
,
w1
,
h1
;
int
x2
,
y2
,
w2
,
h2
;
int
x
,
y
,
w
,
h
;
int
dx
,
dy
;
sraRegionPtr
r
;
x1
=
cache_list
[
idx
].
x
;
y1
=
cache_list
[
idx
].
y
;
w1
=
cache_list
[
idx
].
width
;
h1
=
cache_list
[
idx
].
height
;
if
(
!
valid_window
(
win
,
&
attr
,
1
))
{
fprintf
(
stderr
,
"bs_save: not valid
\n
"
);
// DELETE(idx);
return
0
;
}
x2
=
attr
.
x
;
y2
=
attr
.
y
;
w2
=
attr
.
width
;
h2
=
attr
.
height
;
if
(
cache_list
[
idx
].
bs_x
<
0
||
w2
>
cache_list
[
idx
].
bs_w
||
h2
>
cache_list
[
idx
].
bs_h
)
{
find_rect
(
idx
,
x2
,
y2
,
w2
,
h2
);
}
x
=
cache_list
[
idx
].
bs_x
;
y
=
cache_list
[
idx
].
bs_y
;
w
=
cache_list
[
idx
].
bs_w
;
h
=
cache_list
[
idx
].
bs_h
;
if
(
x
<
0
)
{
STORE
(
idx
,
win
,
attr
);
return
0
;
}
dx
=
x
-
x2
;
dy
=
y
-
y2
;
r
=
sraRgnCreateRect
(
x2
+
dx
,
y2
+
dy
,
x2
+
w2
+
dx
,
y2
+
h2
+
dy
);
fprintf
(
stderr
,
"bs_save: dx=%d dy=%d
\n
"
,
dx
,
dy
);
do_copyregion
(
r
,
dx
,
dy
);
fb_push_wait
(
0
.
01
,
FB_COPY
);
fprintf
(
stderr
,
"bs_save: done. %dx%d+%d+%d %dx%d+%d+%d %.2f %.2f
\n
"
,
w1
,
h1
,
x1
,
y1
,
w2
,
h2
,
x2
,
y2
,
cache_list
[
idx
].
bs_time
,
dnow
());
sraRgnDestroy
(
r
);
STORE
(
idx
,
win
,
attr
);
cache_list
[
idx
].
bs_time
=
dnow
();
return
1
;
}
int
su_save
(
int
idx
)
{
Window
win
=
cache_list
[
idx
].
win
;
XWindowAttributes
attr
;
int
x1
,
y1
,
w1
,
h1
;
int
x2
,
y2
,
w2
,
h2
;
int
x
,
y
,
w
,
h
;
int
dx
,
dy
;
sraRegionPtr
r
;
x1
=
cache_list
[
idx
].
x
;
y1
=
cache_list
[
idx
].
y
;
w1
=
cache_list
[
idx
].
width
;
h1
=
cache_list
[
idx
].
height
;
if
(
!
valid_window
(
win
,
&
attr
,
1
))
{
fprintf
(
stderr
,
"su_save: not valid
\n
"
);
// DELETE(idx);
return
0
;
}
x2
=
attr
.
x
;
y2
=
attr
.
y
;
w2
=
attr
.
width
;
h2
=
attr
.
height
;
if
(
cache_list
[
idx
].
su_x
<
0
||
w2
>
cache_list
[
idx
].
su_w
||
h2
>
cache_list
[
idx
].
su_h
)
{
find_rect
(
idx
,
x2
,
y2
,
w2
,
h2
);
}
x
=
cache_list
[
idx
].
su_x
;
y
=
cache_list
[
idx
].
su_y
;
w
=
cache_list
[
idx
].
su_w
;
h
=
cache_list
[
idx
].
su_h
;
if
(
x
<
0
)
{
STORE
(
idx
,
win
,
attr
);
return
0
;
}
dx
=
x
-
x2
;
dy
=
y
-
y2
;
r
=
sraRgnCreateRect
(
x2
+
dx
,
y2
+
dy
,
x2
+
w2
+
dx
,
y2
+
h2
+
dy
);
fprintf
(
stderr
,
"su_save: dx=%d dy=%d
\n
"
,
dx
,
dy
);
do_copyregion
(
r
,
dx
,
dy
);
fb_push_wait
(
0
.
01
,
FB_COPY
);
fprintf
(
stderr
,
"su_save: done. %dx%d+%d+%d %dx%d+%d+%d %.2f %.2f
\n
"
,
w1
,
h1
,
x1
,
y1
,
w2
,
h2
,
x2
,
y2
,
cache_list
[
idx
].
su_time
,
dnow
());
sraRgnDestroy
(
r
);
STORE
(
idx
,
win
,
attr
);
cache_list
[
idx
].
su_time
=
dnow
();
return
1
;
}
int
bs_restore
(
int
idx
)
{
Window
win
=
cache_list
[
idx
].
win
;
XWindowAttributes
attr
;
int
x1
,
y1
,
w1
,
h1
;
int
x2
,
y2
,
w2
,
h2
;
int
x
,
y
,
w
,
h
;
int
dx
,
dy
;
sraRegionPtr
r
;
if
(
cache_list
[
idx
].
bs_x
<
0
||
cache_list
[
idx
].
bs_time
==
0
.
0
)
{
return
0
;
}
x1
=
cache_list
[
idx
].
x
;
y1
=
cache_list
[
idx
].
y
;
w1
=
cache_list
[
idx
].
width
;
h1
=
cache_list
[
idx
].
height
;
if
(
!
valid_window
(
win
,
&
attr
,
1
))
{
fprintf
(
stderr
,
"bs_restore: not valid
\n
"
);
DELETE
(
idx
);
return
0
;
}
x2
=
attr
.
x
;
y2
=
attr
.
y
;
w2
=
attr
.
width
;
h2
=
attr
.
height
;
x
=
cache_list
[
idx
].
bs_x
;
y
=
cache_list
[
idx
].
bs_y
;
w
=
cache_list
[
idx
].
bs_w
;
h
=
cache_list
[
idx
].
bs_h
;
if
(
x
<
0
)
{
STORE
(
idx
,
win
,
attr
);
return
0
;
}
dx
=
x2
-
x
;
dy
=
y2
-
y
;
r
=
sraRgnCreateRect
(
x
+
dx
,
y
+
dy
,
x
+
w2
+
dx
,
y
+
h2
+
dy
);
fprintf
(
stderr
,
"bs_restore: dx=%d dy=%d
\n
"
,
dx
,
dy
);
do_copyregion
(
r
,
dx
,
dy
);
fb_push_wait
(
0
.
01
,
FB_COPY
);
fprintf
(
stderr
,
"bs_rest: done. %dx%d+%d+%d %dx%d+%d+%d %.2f %.2f
\n
"
,
w1
,
h1
,
x1
,
y1
,
w2
,
h2
,
x2
,
y2
,
cache_list
[
idx
].
bs_time
,
dnow
());
sraRgnDestroy
(
r
);
STORE
(
idx
,
win
,
attr
);
return
1
;
}
int
su_restore
(
int
idx
)
{
Window
win
=
cache_list
[
idx
].
win
;
XWindowAttributes
attr
;
int
x1
,
y1
,
w1
,
h1
;
int
x2
,
y2
,
w2
,
h2
;
int
x
,
y
,
w
,
h
;
int
dx
,
dy
;
sraRegionPtr
r
;
int
invalid
=
0
;
if
(
cache_list
[
idx
].
su_x
<
0
||
cache_list
[
idx
].
su_time
==
0
.
0
)
{
return
0
;
}
x1
=
cache_list
[
idx
].
x
;
y1
=
cache_list
[
idx
].
y
;
w1
=
cache_list
[
idx
].
width
;
h1
=
cache_list
[
idx
].
height
;
if
(
!
valid_window
(
win
,
&
attr
,
1
))
{
fprintf
(
stderr
,
"su_restore: not valid
\n
"
);
invalid
=
1
;
x2
=
x1
;
y2
=
y1
;
w2
=
w1
;
h2
=
h1
;
}
else
{
x2
=
attr
.
x
;
y2
=
attr
.
y
;
w2
=
attr
.
width
;
h2
=
attr
.
height
;
}
x
=
cache_list
[
idx
].
su_x
;
y
=
cache_list
[
idx
].
su_y
;
w
=
cache_list
[
idx
].
su_w
;
h
=
cache_list
[
idx
].
su_h
;
if
(
x
<
0
)
{
if
(
invalid
)
{
DELETE
(
idx
);
}
return
0
;
}
dx
=
x2
-
x
;
dy
=
y2
-
y
;
r
=
sraRgnCreateRect
(
x
+
dx
,
y
+
dy
,
x
+
w2
+
dx
,
y
+
h2
+
dy
);
fprintf
(
stderr
,
"su_restore: dx=%d dy=%d
\n
"
,
dx
,
dy
);
do_copyregion
(
r
,
dx
,
dy
);
fb_push_wait
(
0
.
01
,
FB_COPY
);
fprintf
(
stderr
,
"su_rest: done. %dx%d+%d+%d %dx%d+%d+%d %.2f %.2f
\n
"
,
w1
,
h1
,
x1
,
y1
,
w2
,
h2
,
x2
,
y2
,
cache_list
[
idx
].
su_time
,
dnow
());
sraRgnDestroy
(
r
);
if
(
invalid
)
{
DELETE
(
idx
);
return
0
;
}
else
{
STORE
(
idx
,
win
,
attr
);
return
1
;
}
}
#include <rfb/default8x16.h>
void
check_ncache
(
void
)
{
static
int
last_map
=
-
1
;
static
double
last_root
=
0
.
0
;
static
int
first
=
1
;
int
i
,
j
,
k
;
double
now
,
refresh
=
60
.
0
;
Window
win
,
win2
;
XWindowAttributes
attr
;
XEvent
ev
;
if
(
!
ncache
||
!
ncache0
)
{
return
;
}
if
(
!
screen
)
{
return
;
}
if
(
!
dpy
)
{
return
;
}
if
(
first
)
{
int
dx
=
10
,
dy
=
24
;
for
(
i
=
0
;
i
<
NRECENT
;
i
++
)
{
recent
[
i
]
=
None
;
}
rlast
=
0
;
X_LOCK
;
/* event leak with client_count == 0 */
xselectinput_rootwin
|=
SubstructureNotifyMask
;
XSelectInput
(
dpy
,
rootwin
,
xselectinput_rootwin
);
X_UNLOCK
;
first
=
0
;
rfbDrawString
(
screen
,
&
default8x16Font
,
dx
,
dpy_y
+
1
*
dy
,
"This is the Pixel buffer cache region. Your VNC Viewer is not hiding it from you."
,
white_pixel
());
rfbDrawString
(
screen
,
&
default8x16Font
,
dx
,
dpy_y
+
2
*
dy
,
"Try resizing your VNC Viewer so you don't see it !!"
,
white_pixel
());
rfbDrawString
(
screen
,
&
default8x16Font
,
dx
,
dpy_y
+
3
*
dy
,
"To disable run the server with: x11vnc -ncache 0 ..."
,
white_pixel
());
rfbDrawString
(
screen
,
&
default8x16Font
,
dx
,
dpy_y
+
4
*
dy
,
"More info: http://www.karlrunge.com/x11vnc/#faq-client-caching"
,
white_pixel
());
snapshot_cache_list
(
0
,
100
.
0
);
}
if
(
!
client_count
)
{
return
;
}
now
=
dnow
();
if
(
now
>
last_root
+
refresh
)
{
fprintf
(
stderr
,
"
\n
**** checking cache_list[%d]
\n\n
"
,
cache_list_num
);
for
(
k
=
0
;
k
<
cache_list_num
;
k
++
)
{
win
=
cache_list
[
k
].
win
;
if
(
win
==
None
)
{
fprintf
(
stderr
,
" Empty[%d]: 0x%x
\n
"
,
k
,
win
);
}
else
if
(
cache_list
[
k
].
selectinput
&&
cache_list
[
k
].
time
>
now
-
refresh
)
{
fprintf
(
stderr
,
" Young[%d]: 0x%x
\n
"
,
k
,
win
);
}
else
if
(
valid_window
(
win
,
&
attr
,
1
))
{
STORE
(
k
,
win
,
attr
);
if
(
!
cache_list
[
k
].
selectinput
)
{
X_LOCK
;
fprintf
(
stderr
,
" XSelectInput[%d]: 0x%x
\n
"
,
k
,
win
);
XSelectInput
(
dpy
,
win
,
StructureNotifyMask
);
X_UNLOCK
;
CLEAR
(
k
);
cache_list
[
k
].
selectinput
=
1
;
}
else
{
//fprintf(stderr, " SKIP XSelectInput[%d]: 0x%x\n", k, win);
}
}
else
{
fprintf
(
stderr
,
" DELETE(%d) 0x%x
\n
"
,
k
,
win
);
DELETE
(
k
);
}
}
last_root
=
dnow
();
}
X_LOCK
;
while
(
XCheckMaskEvent
(
dpy
,
SubstructureNotifyMask
|
StructureNotifyMask
,
&
ev
))
{
int
type
=
ev
.
type
;
int
idx
;
win
=
ev
.
xany
.
window
;
//fprintf(stderr, "evnt: 0x%x %d pending: %d\n", win, type, XPending(dpy));
if
(
win
==
rootwin
)
{
if
(
type
==
CreateNotify
)
{
int
x
=
0
,
y
=
0
,
w
=
0
,
h
=
0
;
win2
=
ev
.
xcreatewindow
.
window
;
idx
=
lookup_win_index
(
win2
);
if
(
idx
<
0
)
{
idx
=
lookup_free_index
();
}
if
(
valid_window
(
win2
,
&
attr
,
1
))
{
STORE
(
idx
,
win2
,
attr
);
CLEAR
(
idx
);
// su_save(idx); // not working
x
=
attr
.
x
;
y
=
attr
.
y
;
w
=
attr
.
width
;
h
=
attr
.
height
;
XSelectInput
(
dpy
,
win2
,
StructureNotifyMask
);
cache_list
[
idx
].
selectinput
=
1
;
}
fprintf
(
stderr
,
"root: ** CreateNotify 0x%x %d -- %dx%d+%d+%d
\n
"
,
win2
,
idx
,
w
,
h
,
x
,
y
);
}
else
if
(
type
==
ReparentNotify
)
{
if
(
ev
.
xreparent
.
parent
!=
rootwin
)
{
win2
=
ev
.
xreparent
.
window
;
if
(
win2
!=
rootwin
)
{
idx
=
lookup_win_index
(
win2
);
fprintf
(
stderr
,
"root: ReparentNotify RM: 0x%x %d
\n
"
,
win2
,
idx
);
if
(
idx
>=
0
)
{
DELETE
(
idx
);
}
XSelectInput
(
dpy
,
win2
,
0
);
}
}
}
else
{
Window
ww
=
None
;
/* skip rest */
if
(
type
==
DestroyNotify
)
ww
=
ev
.
xdestroywindow
.
window
;
if
(
type
==
UnmapNotify
)
ww
=
ev
.
xunmap
.
window
;
if
(
type
==
MapNotify
)
ww
=
ev
.
xmap
.
window
;
if
(
type
==
Expose
)
ww
=
ev
.
xexpose
.
window
;
if
(
type
==
ConfigureNotify
)
ww
=
ev
.
xconfigure
.
window
;
fprintf
(
stderr
,
"root: skip %s for 0x%x
\n
"
,
Etype
(
type
),
ww
);
}
}
else
{
if
(
type
==
ReparentNotify
)
{
if
(
ev
.
xreparent
.
parent
!=
rootwin
)
{
win2
=
ev
.
xreparent
.
window
;
if
(
win2
!=
rootwin
)
{
idx
=
lookup_win_index
(
win2
);
fprintf
(
stderr
,
"----- ReparentNotify RM: 0x%x %d
\n
"
,
win2
,
idx
);
if
(
idx
>=
0
)
{
DELETE
(
idx
);
}
XSelectInput
(
dpy
,
win2
,
0
);
}
}
}
else
if
(
type
==
DestroyNotify
)
{
win2
=
ev
.
xdestroywindow
.
window
;
idx
=
lookup_win_index
(
win2
);
fprintf
(
stderr
,
"----- DestroyNotify 0x%x %d
\n
"
,
win2
,
idx
);
if
(
idx
>=
0
)
{
DELETE
(
idx
);
}
}
else
if
(
type
==
ConfigureNotify
)
{
idx
=
lookup_win_index
(
win
);
fprintf
(
stderr
,
"----- ConfigureNotify 0x%x %d -- %dx%d+%d+%d
\n
"
,
win
,
idx
,
ev
.
xconfigure
.
width
,
ev
.
xconfigure
.
height
,
ev
.
xconfigure
.
x
,
ev
.
xconfigure
.
y
);
if
(
idx
>=
0
)
{
/* XXX invalidate su and/or bs */
cache_list
[
idx
].
x
=
ev
.
xconfigure
.
x
;
cache_list
[
idx
].
y
=
ev
.
xconfigure
.
y
;
cache_list
[
idx
].
width
=
ev
.
xconfigure
.
width
;
cache_list
[
idx
].
height
=
ev
.
xconfigure
.
height
;
}
}
else
if
(
type
==
MapNotify
)
{
idx
=
lookup_win_index
(
win
);
fprintf
(
stderr
,
"----- MapNotify 0x%x %d
\n
"
,
win
,
idx
);
if
(
idx
<
0
)
{
continue
;
}
if
(
cache_list
[
idx
].
map_state
==
IsUnmapped
)
{
X_UNLOCK
;
su_save
(
idx
);
bs_restore
(
idx
);
X_LOCK
;
}
}
else
if
(
type
==
UnmapNotify
)
{
idx
=
lookup_win_index
(
win
);
fprintf
(
stderr
,
"----- UnmapNotify 0x%x %d
\n
"
,
win
,
idx
);
if
(
idx
<
0
)
{
continue
;
}
if
(
cache_list
[
idx
].
map_state
==
IsViewable
)
{
X_UNLOCK
;
bs_save
(
idx
);
su_restore
(
idx
);
X_LOCK
;
}
}
else
{
/* skip rest */
fprintf
(
stderr
,
"----- skip %s
\n
"
,
Etype
(
type
));
}
}
}
//fprintf(stderr, "pending2: %d\n", XPending(dpy));
X_UNLOCK
;
if
(
dnow
()
-
now
>
0
.
05
)
fprintf
(
stderr
,
"check_ncache OUT: %f
\n
"
,
dnow
()
-
now
);
}
#endif
x11vnc/userinput.h
View file @
8aa6fb95
...
...
@@ -35,5 +35,6 @@ extern int check_xrecord(void);
extern
int
check_wireframe
(
void
);
extern
int
fb_update_sent
(
int
*
count
);
extern
int
check_user_input
(
double
dt
,
double
dtr
,
int
tile_diffs
,
int
*
cnt
);
extern
void
do_copyregion
(
sraRegionPtr
region
,
int
dx
,
int
dy
);
#endif
/* _X11VNC_USERINPUT_H */
x11vnc/winattr_t.h
View file @
8aa6fb95
...
...
@@ -15,6 +15,11 @@ typedef struct winattr {
int
map_state
;
int
rx
,
ry
;
double
time
;
double
bs_time
;
double
su_time
;
int
bs_x
,
bs_y
,
bs_w
,
bs_h
;
int
su_x
,
su_y
,
su_w
,
su_h
;
int
selectinput
;
}
winattr_t
;
#endif
/* _X11VNC_WINATTR_T_H */
x11vnc/x11vnc.1
View file @
8aa6fb95
...
...
@@ -2,7 +2,7 @@
.TH X11VNC "1" "December 2006" "x11vnc " "User Commands"
.SH NAME
x11vnc - allow VNC connections to real X11 displays
version: 0.8.4, lastmod: 2006-12-1
4
version: 0.8.4, lastmod: 2006-12-1
7
.SH SYNOPSIS
.B x11vnc
[OPTION]...
...
...
@@ -2376,6 +2376,32 @@ slow setups, but you lose all visual feedback for drags,
text selection, and some menu traversals. It overrides
any \fB-pointer_mode\fR setting.
.PP
\fB-ncache\fR \fIn\fR
.IP
Client-side caching scheme. Framebuffer memory \fIn\fR
(an integer) times that of the full display is allocated
below the actual framebuffer to cache screen contents
for rapid retrieval. So a W x H frambuffer is expanded
to a W x (n+1)*H one. Use 0 to disable. Default: XXX.
.IP
This is an experimental option, currently implemented
in an awkward way in that in the VNC Viewer you can
see the cache contents if you scroll down, etc. So you
will have to set things up so you can't see that region.
If this method is successful, the changes required for
clients to do this less awkwardly will be investigated.
.IP
Note that this mode consumes a lot of memory, both
on the x11vnc server side and on the VNC Viewer side.
If n=2 then the amount of RAM used is roughly tripled
for both x11vnc and the VNC Viewer. As a rule of
thumb, note that 1280x1024 at depth 24 is about 5MB of
pixel data.
.IP
Because of the way window backingstore and saveunders
are implemented, n must be even. It will be incremented
by 1 if it is not.
.PP
\fB-wireframe\fR \fI[str],\fR \fB-nowireframe\fR
.IP
Try to detect window moves or resizes when a mouse
...
...
x11vnc/x11vnc.c
View file @
8aa6fb95
...
...
@@ -554,6 +554,7 @@ static void watch_loop(void) {
}
check_new_clients
();
check_ncache
();
check_xevents
(
0
);
check_autorepeat
();
check_pm
();
...
...
@@ -611,8 +612,9 @@ static void watch_loop(void) {
if
(
button_mask
&&
(
!
show_dragging
||
pointer_mode
==
0
))
{
/*
* if any button is pressed do not update rfb
* screen, but do flush the X11 display.
* if any button is pressed in this mode do
* not update rfb screen, but do flush the
* X11 display.
*/
X_LOCK
;
XFlush_wr
(
dpy
);
...
...
@@ -1200,6 +1202,7 @@ static void print_settings(int try_http, int bg, char *gui_str) {
fprintf
(
stderr
,
" buttonmap: %s
\n
"
,
pointer_remap
?
pointer_remap
:
"null"
);
fprintf
(
stderr
,
" dragging: %d
\n
"
,
show_dragging
);
fprintf
(
stderr
,
" ncache: %d
\n
"
,
ncache
);
fprintf
(
stderr
,
" wireframe: %s
\n
"
,
wireframe_str
?
wireframe_str
:
WIREFRAME_PARMS
);
fprintf
(
stderr
,
" wirecopy: %s
\n
"
,
wireframe_copyrect
?
...
...
@@ -2105,6 +2108,14 @@ int main(int argc, char* argv[]) {
pointer_remap
=
strdup
(
argv
[
++
i
]);
}
else
if
(
!
strcmp
(
arg
,
"-nodragging"
))
{
show_dragging
=
0
;
#ifndef NO_NCACHE
}
else
if
(
!
strcmp
(
arg
,
"-ncache"
))
{
CHECK_ARGC
ncache
=
atoi
(
argv
[
++
i
]);
if
(
ncache
%
2
!=
0
)
{
ncache
++
;
}
#endif
}
else
if
(
!
strcmp
(
arg
,
"-wireframe"
)
||
!
strcmp
(
arg
,
"-wf"
))
{
wireframe
=
1
;
...
...
x11vnc/x11vnc.h
View file @
8aa6fb95
...
...
@@ -134,7 +134,9 @@
#define PASSWD_UNLESS_NOPW 0
#endif
/* these are for delaying features: */
#define xxNO_SSL_OR_UNIXPW
#define xxNO_NCACHE
/*
* Beginning of support for small binary footprint build for embedded
...
...
@@ -360,6 +362,8 @@ extern int button_mask; /* button state and info */
extern
int
button_mask_prev
;
extern
int
num_buttons
;
extern
long
xselectinput_rootwin
;
extern
unsigned
int
display_button_mask
;
extern
unsigned
int
display_mod_mask
;
...
...
x11vnc/x11vnc_defs.c
View file @
8aa6fb95
...
...
@@ -15,7 +15,7 @@ int xtrap_base_event_type = 0;
int
xdamage_base_event_type
=
0
;
/* date +'lastmod: %Y-%m-%d' */
char
lastmod
[]
=
"0.8.4 lastmod: 2006-12-1
4
"
;
char
lastmod
[]
=
"0.8.4 lastmod: 2006-12-1
7
"
;
/* X display info */
...
...
@@ -36,6 +36,8 @@ int button_mask = 0; /* button state and info */
int
button_mask_prev
=
0
;
int
num_buttons
=
-
1
;
long
xselectinput_rootwin
=
0
;
unsigned
int
display_button_mask
=
0
;
unsigned
int
display_mod_mask
=
0
;
...
...
x11vnc/xevents.c
View file @
8aa6fb95
...
...
@@ -107,7 +107,8 @@ static void initialize_xevents(int reset) {
* XXX: does this cause a flood of other stuff?
*/
X_LOCK
;
XSelectInput
(
dpy
,
rootwin
,
PropertyChangeMask
);
xselectinput_rootwin
|=
PropertyChangeMask
;
XSelectInput
(
dpy
,
rootwin
,
xselectinput_rootwin
);
X_UNLOCK
;
did_xselect_input
=
1
;
}
...
...
x11vnc/xinerama.c
View file @
8aa6fb95
...
...
@@ -382,11 +382,17 @@ void push_sleep(int n) {
* try to forcefully push a black screen to all connected clients
*/
void
push_black_screen
(
int
n
)
{
int
Lx
=
dpy_x
,
Ly
=
dpy_y
;
if
(
!
screen
)
{
return
;
}
zero_fb
(
0
,
0
,
dpy_x
,
dpy_y
);
mark_rect_as_modified
(
0
,
0
,
dpy_x
,
dpy_y
,
0
);
#ifndef NO_NCACHE
if
(
ncache
>
0
)
{
Ly
=
dpy_y
*
(
1
+
ncache
);
}
#endif
zero_fb
(
0
,
0
,
Lx
,
Ly
);
mark_rect_as_modified
(
0
,
0
,
Lx
,
Ly
,
0
);
push_sleep
(
n
);
}
...
...
@@ -406,13 +412,19 @@ void refresh_screen(int push) {
*/
void
zero_fb
(
int
x1
,
int
y1
,
int
x2
,
int
y2
)
{
int
pixelsize
=
bpp
/
8
;
int
line
,
fill
=
0
;
int
line
,
fill
=
0
,
yfac
=
1
;
char
*
dst
;
#ifndef NO_NCACHE
if
(
ncache
>
0
)
{
yfac
=
1
+
ncache
;
}
#endif
if
(
x1
<
0
||
x2
<=
x1
||
x2
>
dpy_x
)
{
return
;
}
if
(
y1
<
0
||
y2
<=
y1
||
y2
>
dpy_y
)
{
if
(
y1
<
0
||
y2
<=
y1
||
y2
>
yfac
*
dpy_y
)
{
return
;
}
if
(
!
main_fb
)
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment