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
98e4f895
Commit
98e4f895
authored
Jun 06, 2004
by
runge
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
x11vnc: rearrange file for easier maintenance, add RFB_CLIENT_COUNT to -accept/-gone
parent
f988c5b2
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
783 additions
and
619 deletions
+783
-619
ChangeLog
ChangeLog
+5
-1
ChangeLog
x11vnc/ChangeLog
+5
-0
x11vnc.c
x11vnc/x11vnc.c
+773
-618
No files found.
ChangeLog
View file @
98e4f895
2004-06-05 Karl Runge <runge@karlrunge.com>
* x11vnc: rearrange file for easier maintenance
* add RFB_CLIENT_COUNT to -accept and -gone commands
2004-05-27 Karl Runge <runge@karlrunge.com>
2004-05-27 Karl Runge <runge@karlrunge.com>
* x11vnc: -viewpasswd, viewonly passwds.
* x11vnc: -viewpasswd, viewonly passwds.
* some typos in prepare_x11vnc_dist.sh
* some typos in prepare_x11vnc_dist.sh
...
@@ -19,7 +23,7 @@
...
@@ -19,7 +23,7 @@
* shm OS blacklist revert to -onetile
* shm OS blacklist revert to -onetile
2004-04-28 Karl Runge <runge@karlrunge.com>
2004-04-28 Karl Runge <runge@karlrunge.com>
* x11vnc: -auth, more -curso
por
and -nofb work
* x11vnc: -auth, more -curso
rpos
and -nofb work
2004-04-19 Karl Runge <runge@karlrunge.com>
2004-04-19 Karl Runge <runge@karlrunge.com>
* x11vnc: -cursorpos, -sigpipe
* x11vnc: -cursorpos, -sigpipe
...
...
x11vnc/ChangeLog
View file @
98e4f895
2004-06-05 Karl Runge <runge@karlrunge.com>
* rearrange file for easier maintenance, indicating file breakup.
* add RFB_CLIENT_COUNT, number of other connected clients to
-accept and -gone commands.
2004-05-27 Karl Runge <runge@karlrunge.com>
2004-05-27 Karl Runge <runge@karlrunge.com>
* add view-only passwd via -viewpasswd and 2nd line of -passwdfile
* add view-only passwd via -viewpasswd and 2nd line of -passwdfile
...
...
x11vnc/x11vnc.c
View file @
98e4f895
/*
/*
* x11vnc.c: a VNC server for X displays.
* x11vnc.c: a VNC server for X displays.
*
*
* Copyright (c) 2002-200
3
Karl J. Runge <runge@karlrunge.com>
* Copyright (c) 2002-200
4
Karl J. Runge <runge@karlrunge.com>
* All rights reserved.
* All rights reserved.
*
*
* This is free software; you can redistribute it and/or modify
* This is free software; you can redistribute it and/or modify
...
@@ -93,6 +93,19 @@
...
@@ -93,6 +93,19 @@
*
*
*/
*/
/*
* These ' -- filename -- ' comments represent a partial cleanup: they
* are an odd way to indicate how this huge file could be split up someday
* into multiple files. Externs and other things would need to be done,
* but it indicates the breakup, including static keyword for local items.
*
* The primary reason we do not break up this file is for user
* convenience: those wanting to use the latest version download a single
* file, x11vnc.c, and off they go...
*/
/* -- x11vnc.h -- */
#include <unistd.h>
#include <unistd.h>
#include <signal.h>
#include <signal.h>
#include <sys/utsname.h>
#include <sys/utsname.h>
...
@@ -133,16 +146,9 @@
...
@@ -133,16 +146,9 @@
#endif
#endif
/* date +'"lastmod: %Y-%m-%d";' */
/* date +'"lastmod: %Y-%m-%d";' */
char
lastmod
[]
=
"lastmod: 2004-05-27"
;
char
lastmod
[]
=
"lastmod: 2004-06-05"
;
/*
* Well, here starts all our global data, someday we need to split this
* file up. One advantage to this big blob is that it is easy for users
* to download and replace a single file to try out the latest version...
*/
/* X
and rfb framebuffer
*/
/* X
display info
*/
Display
*
dpy
=
0
;
Display
*
dpy
=
0
;
Visual
*
visual
;
Visual
*
visual
;
Window
window
,
rootwin
;
Window
window
,
rootwin
;
...
@@ -151,19 +157,20 @@ int bpp, depth;
...
@@ -151,19 +157,20 @@ int bpp, depth;
int
button_mask
=
0
;
int
button_mask
=
0
;
int
dpy_x
,
dpy_y
;
int
dpy_x
,
dpy_y
;
int
off_x
,
off_y
;
int
off_x
,
off_y
;
int
subwin
=
0
;
int
indexed_colour
=
0
;
int
indexed_colour
=
0
;
int
num_buttons
=
-
1
;
XImage
*
tile
;
/* image structures */
XImage
**
tile_row
;
/* for all possible row runs */
XImage
*
scanline
;
XImage
*
scanline
;
XImage
*
fullscreen
;
XImage
*
fullscreen
;
int
fs_factor
=
0
;
XImage
**
tile_row
;
/* for all possible row runs */
XShmSegmentInfo
*
tile_row_shm
;
/* for all possible row run
s */
/* corresponding shm structure
s */
XShmSegmentInfo
scanline_shm
;
XShmSegmentInfo
scanline_shm
;
XShmSegmentInfo
fullscreen_shm
;
XShmSegmentInfo
fullscreen_shm
;
XShmSegmentInfo
*
tile_row_shm
;
/* for all possible row runs */
/* rfb info */
rfbScreenInfoPtr
screen
;
rfbScreenInfoPtr
screen
;
rfbCursorPtr
cursor
;
rfbCursorPtr
cursor
;
int
bytes_per_line
;
int
bytes_per_line
;
...
@@ -185,32 +192,111 @@ typedef struct tbout {
...
@@ -185,32 +192,111 @@ typedef struct tbout {
int
cover
;
int
cover
;
int
count
;
int
count
;
}
tile_blackout_t
;
}
tile_blackout_t
;
blackout_t
black
[
100
];
/* hardwired max blackouts */
blackout_t
blackr
[
100
];
/* hardwired max blackouts */
int
blackouts
=
0
;
int
blackouts
=
0
;
tile_blackout_t
*
tile_blackout
;
tile_blackout_t
*
tile_blackout
;
/* saved cursor */
int
cur_save_x
,
cur_save_y
,
cur_save_w
,
cur_save_h
,
cur_saved
=
0
;
typedef
struct
tile_change_region
{
/* times of recent events */
/* start and end lines, along y, of the changed area inside a tile. */
time_t
last_event
,
last_input
,
last_client
=
0
;
unsigned
short
first_line
,
last_line
;
/* info about differences along edges. */
unsigned
short
left_diff
,
right_diff
;
unsigned
short
top_diff
,
bot_diff
;
}
region_t
;
/* array to hold the tiles region_t-s. */
/* last client to move pointer */
region_t
*
tile_region
;
rfbClientPtr
last_pointer_client
=
NULL
;
int
cursor_x
,
cursor_y
;
/* x and y from the viewer(s) */
int
got_user_input
=
0
;
int
got_pointer_input
=
0
;
int
got_keyboard_input
=
0
;
int
fb_copy_in_progress
=
0
;
/* string for the VNC_CONNECT property */
#define VNC_CONNECT_MAX 512
char
vnc_connect_str
[
VNC_CONNECT_MAX
+
1
];
Atom
vnc_connect_prop
=
None
;
/* XXX usleep(3) is not thread safe on some older systems... */
struct
timeval
_mysleep
;
#define usleep2(x) \
_mysleep.tv_sec = (x) / 1000000; \
_mysleep.tv_usec = (x) % 1000000; \
select(0, NULL, NULL, NULL, &_mysleep);
#if !defined(X11VNC_USLEEP)
#undef usleep
#define usleep usleep2
#endif
/*
* Not sure why... but when threaded we have to mutex our X11 calls to
* avoid XIO crashes.
*/
MUTEX
(
x11Mutex
);
#define X_LOCK LOCK(x11Mutex)
#define X_UNLOCK UNLOCK(x11Mutex)
#define X_INIT INIT_MUTEX(x11Mutex)
/* function prototypes */
int
all_clients_initialized
(
void
);
void
blackout_tiles
(
void
);
void
check_connect_inputs
(
void
);
void
clean_up_exit
(
int
);
void
copy_screen
(
void
);
double
dtime
(
double
*
);
void
initialize_blackout
(
char
*
);
void
initialize_modtweak
(
void
);
void
initialize_pointer_map
(
char
*
);
void
initialize_remap
(
char
*
);
void
initialize_screen
(
int
*
argc
,
char
**
argv
,
XImage
*
fb
);
void
initialize_shm
(
void
);
void
initialize_signals
(
void
);
void
initialize_tiles
(
void
);
void
initialize_watch_bell
(
void
);
void
initialize_xinerama
(
void
);
void
keyboard
(
rfbBool
down
,
rfbKeySym
keysym
,
rfbClientPtr
client
);
void
myXTestFakeKeyEvent
(
Display
*
,
KeyCode
,
Bool
,
time_t
);
typedef
struct
hint
{
typedef
struct
hint
{
/* location x, y, height, and width of a change-rectangle */
/* location x, y, height, and width of a change-rectangle */
/* (grows as adjacent horizontal tiles are glued together) */
/* (grows as adjacent horizontal tiles are glued together) */
int
x
,
y
,
w
,
h
;
int
x
,
y
,
w
,
h
;
}
hint_t
;
}
hint_t
;
void
mark_hint
(
hint_t
);
/* array to hold the hints: */
enum
rfbNewClientAction
new_client
(
rfbClientPtr
client
);
hint_t
*
hint_list
;
void
nofb_hook
(
rfbClientPtr
client
);
void
pointer
(
int
mask
,
int
x
,
int
y
,
rfbClientPtr
client
);
/* various command line options */
void
read_vnc_connect_prop
(
void
);
void
redraw_mouse
(
void
);
void
restore_mouse_patch
(
void
);
void
rfbPE
(
rfbScreenInfoPtr
,
long
);
void
scan_for_updates
(
void
);
void
set_colormap
(
void
);
void
set_offset
(
void
);
void
set_visual
(
char
*
vstring
);
void
shm_clean
(
XShmSegmentInfo
*
,
XImage
*
);
void
shm_delete
(
XShmSegmentInfo
*
);
void
update_mouse
(
void
);
void
watch_bell_event
(
void
);
void
watch_xevents
(
void
);
void
xcut_receive
(
char
*
text
,
int
len
,
rfbClientPtr
client
);
void
zero_fb
(
int
,
int
,
int
,
int
);
/* -- options.h -- */
/*
* variables for the command line options
*/
int
shared
=
0
;
/* share vnc display. */
int
shared
=
0
;
/* share vnc display. */
char
*
allow_list
=
NULL
;
/* for -allow and -localhost */
char
*
allow_list
=
NULL
;
/* for -allow and -localhost */
...
@@ -224,10 +310,10 @@ int flash_cmap = 0; /* follow installed colormaps */
...
@@ -224,10 +310,10 @@ int flash_cmap = 0; /* follow installed colormaps */
int
force_indexed_color
=
0
;
/* whether to force indexed color for 8bpp */
int
force_indexed_color
=
0
;
/* whether to force indexed color for 8bpp */
int
use_modifier_tweak
=
0
;
/* use the altgr_keyboard modifier tweak */
int
use_modifier_tweak
=
0
;
/* use the altgr_keyboard modifier tweak */
char
*
remap_file
=
NULL
;
/* user supplied remapping file or list */
int
nofb
=
0
;
/* do not send any fb updates */
int
nofb
=
0
;
/* do not send any fb updates */
char
*
blackout_string
=
NULL
;
/* -blackout */
int
subwin
=
0
;
/* -id */
int
xinerama
=
0
;
/* -xinerama */
int
xinerama
=
0
;
/* -xinerama */
char
*
client_connect
=
NULL
;
/* strings for -connect option */
char
*
client_connect
=
NULL
;
/* strings for -connect option */
...
@@ -253,7 +339,6 @@ int flip_byte_order = 0; /* sometimes needed when using_shm = 0 */
...
@@ -253,7 +339,6 @@ int flip_byte_order = 0; /* sometimes needed when using_shm = 0 */
*/
*/
int
waitms
=
30
;
int
waitms
=
30
;
int
defer_update
=
30
;
/* rfbDeferUpdateTime ms to wait before sends. */
int
defer_update
=
30
;
/* rfbDeferUpdateTime ms to wait before sends. */
int
defer_update_nofb
=
6
;
/* defer a shorter time under -nofb */
int
screen_blank
=
60
;
/* number of seconds of no activity to throttle */
int
screen_blank
=
60
;
/* number of seconds of no activity to throttle */
/* down the screen polls. zero to disable. */
/* down the screen polls. zero to disable. */
...
@@ -263,13 +348,15 @@ int napfac = 4; /* time = napfac*waitms, cut load with extra waits */
...
@@ -263,13 +348,15 @@ int napfac = 4; /* time = napfac*waitms, cut load with extra waits */
int
napmax
=
1500
;
/* longest nap in ms. */
int
napmax
=
1500
;
/* longest nap in ms. */
int
ui_skip
=
10
;
/* see watchloop. negative means ignore input */
int
ui_skip
=
10
;
/* see watchloop. negative means ignore input */
int
watch_selection
=
1
;
/* normal selection/cutbuffer maintenance */
int
watch_primary
=
1
;
/* more dicey, poll for changes in PRIMARY */
int
sigpipe
=
1
;
/* 0=skip, 1=ignore, 2=exit */
/* for -visual override */
/* for -visual override */
VisualID
visual_id
=
(
VisualID
)
0
;
VisualID
visual_id
=
(
VisualID
)
0
;
int
visual_depth
=
0
;
int
visual_depth
=
0
;
int
nap_ok
=
0
,
nap_diff_count
=
0
;
time_t
last_event
,
last_input
,
last_client
=
0
;
/* tile heuristics: */
/* tile heuristics: */
double
fs_frac
=
0
.
75
;
/* threshold tile fraction to do fullscreen updates. */
double
fs_frac
=
0
.
75
;
/* threshold tile fraction to do fullscreen updates. */
int
use_hints
=
1
;
/* use the krfb scheme of gluing tiles together. */
int
use_hints
=
1
;
/* use the krfb scheme of gluing tiles together. */
...
@@ -278,35 +365,16 @@ int tile_fuzz = 2; /* tolerance for suspecting changed tiles touching */
...
@@ -278,35 +365,16 @@ int tile_fuzz = 2; /* tolerance for suspecting changed tiles touching */
int
grow_fill
=
3
;
/* do the grow islands heuristic with this width. */
int
grow_fill
=
3
;
/* do the grow islands heuristic with this width. */
int
gaps_fill
=
4
;
/* do a final pass to try to fill gaps between tiles. */
int
gaps_fill
=
4
;
/* do a final pass to try to fill gaps between tiles. */
/* scan pattern jitter from x0rfbserver */
#define NSCAN 32
int
scanlines
[
NSCAN
]
=
{
0
,
16
,
8
,
24
,
4
,
20
,
12
,
28
,
10
,
26
,
18
,
2
,
22
,
6
,
30
,
14
,
1
,
17
,
9
,
25
,
7
,
23
,
15
,
31
,
19
,
3
,
27
,
11
,
29
,
13
,
5
,
21
};
int
count
=
0
;
/* indicates which scan pattern we are on */
int
cursor_x
,
cursor_y
;
/* x and y from the viewer(s) */
int
got_user_input
=
0
;
int
got_pointer_input
=
0
;
int
got_keyboard_input
=
0
;
int
scan_in_progress
=
0
;
int
fb_copy_in_progress
=
0
;
int
client_count
=
0
;
int
shut_down
=
0
;
int
sigpipe
=
1
;
/* 0=skip, 1=ignore, 2=exit */
int
debug_pointer
=
0
;
int
debug_pointer
=
0
;
int
debug_keyboard
=
0
;
int
debug_keyboard
=
0
;
int
quiet
=
0
;
int
quiet
=
0
;
double
dtime
(
double
*
);
int
all_clients_initialized
(
void
);
void
zero_fb
(
int
,
int
,
int
,
int
);
int
got_rfbport
=
0
;
int
got_alwaysshared
=
0
;
int
got_nevershared
=
0
;
/* threaded vs. non-threaded (default) */
#if defined(LIBVNCSERVER_X11VNC_THREADED) && ! defined(X11VNC_THREADED)
#if defined(LIBVNCSERVER_X11VNC_THREADED) && ! defined(X11VNC_THREADED)
#define X11VNC_THREADED
#define X11VNC_THREADED
#endif
#endif
...
@@ -317,33 +385,17 @@ void zero_fb(int, int, int, int);
...
@@ -317,33 +385,17 @@ void zero_fb(int, int, int, int);
int
use_threads
=
0
;
int
use_threads
=
0
;
#endif
#endif
/* XXX usleep(3) is not thread safe on some older systems... */
struct
timeval
_mysleep
;
#define usleep2(x) \
_mysleep.tv_sec = (x) / 1000000; \
_mysleep.tv_usec = (x) % 1000000; \
select(0, NULL, NULL, NULL, &_mysleep);
#if !defined(X11VNC_USLEEP)
#undef usleep
#define usleep usleep2
#endif
/* -- cleanup.c -- */
/*
/*
* Not sure why... but when threaded we have to mutex our X11 calls to
* Exiting and error handling routines
* avoid XIO crashes.
*/
*/
MUTEX
(
x11Mutex
);
#define X_LOCK LOCK(x11Mutex)
static
int
exit_flag
=
0
;
#define X_UNLOCK UNLOCK(x11Mutex)
#define X_INIT INIT_MUTEX(x11Mutex)
/*
/*
*
Exiting and error handling:
*
Normal exiting
*/
*/
void
shm_clean
(
XShmSegmentInfo
*
,
XImage
*
);
void
shm_delete
(
XShmSegmentInfo
*
);
int
exit_flag
=
0
;
void
clean_up_exit
(
int
ret
)
{
void
clean_up_exit
(
int
ret
)
{
int
i
;
int
i
;
exit_flag
=
1
;
exit_flag
=
1
;
...
@@ -370,7 +422,7 @@ void clean_up_exit (int ret) {
...
@@ -370,7 +422,7 @@ void clean_up_exit (int ret) {
/*
/*
* General problem handler
* General problem handler
*/
*/
void
interrupted
(
int
sig
)
{
static
void
interrupted
(
int
sig
)
{
int
i
;
int
i
;
if
(
exit_flag
)
{
if
(
exit_flag
)
{
exit_flag
++
;
exit_flag
++
;
...
@@ -410,20 +462,25 @@ void interrupted (int sig) {
...
@@ -410,20 +462,25 @@ void interrupted (int sig) {
}
}
}
}
XErrorHandler
Xerror_def
;
/* X11 error handlers */
XIOErrorHandler
XIOerr_def
;
int
Xerror
(
Display
*
d
,
XErrorEvent
*
error
)
{
static
XErrorHandler
Xerror_def
;
static
XIOErrorHandler
XIOerr_def
;
static
int
Xerror
(
Display
*
d
,
XErrorEvent
*
error
)
{
X_UNLOCK
;
X_UNLOCK
;
interrupted
(
0
);
interrupted
(
0
);
return
(
*
Xerror_def
)(
d
,
error
);
return
(
*
Xerror_def
)(
d
,
error
);
}
}
int
XIOerr
(
Display
*
d
)
{
static
int
XIOerr
(
Display
*
d
)
{
X_UNLOCK
;
X_UNLOCK
;
interrupted
(
0
);
interrupted
(
0
);
return
(
*
XIOerr_def
)(
d
);
return
(
*
XIOerr_def
)(
d
);
}
}
void
set_signals
(
void
)
{
/* signal handlers */
void
initialize_signals
(
void
)
{
signal
(
SIGHUP
,
interrupted
);
signal
(
SIGHUP
,
interrupted
);
signal
(
SIGINT
,
interrupted
);
signal
(
SIGINT
,
interrupted
);
signal
(
SIGQUIT
,
interrupted
);
signal
(
SIGQUIT
,
interrupted
);
...
@@ -438,7 +495,7 @@ void set_signals(void) {
...
@@ -438,7 +495,7 @@ void set_signals(void) {
signal
(
SIGPIPE
,
SIG_IGN
);
signal
(
SIGPIPE
,
SIG_IGN
);
#endif
#endif
}
else
if
(
sigpipe
==
2
)
{
}
else
if
(
sigpipe
==
2
)
{
rfbLog
(
"
set
_signals: will exit on SIGPIPE
\n
"
);
rfbLog
(
"
initialize
_signals: will exit on SIGPIPE
\n
"
);
signal
(
SIGPIPE
,
interrupted
);
signal
(
SIGPIPE
,
interrupted
);
}
}
...
@@ -448,10 +505,111 @@ void set_signals(void) {
...
@@ -448,10 +505,111 @@ void set_signals(void) {
X_UNLOCK
;
X_UNLOCK
;
}
}
int
run_user_command
(
char
*
,
rfbClientPtr
);
/* -- connections.c -- */
/*
* routines for handling incoming, outgoing, etc connections
*/
static
int
accepted_client
=
0
;
static
int
client_count
=
0
;
/*
* check that all clients are in RFB_NORMAL state
*/
int
all_clients_initialized
(
void
)
{
rfbClientIteratorPtr
iter
;
rfbClientPtr
cl
;
int
ok
=
1
;
iter
=
rfbGetClientIterator
(
screen
);
while
(
(
cl
=
rfbClientIteratorNext
(
iter
))
)
{
if
(
cl
->
state
!=
RFB_NORMAL
)
{
ok
=
0
;
break
;
}
}
rfbReleaseClientIterator
(
iter
);
return
ok
;
}
/*
* utility to run a user supplied command setting some RFB_ env vars.
* used by, e.g., accept_client() and client_gone()
*/
static
int
run_user_command
(
char
*
cmd
,
rfbClientPtr
client
)
{
char
*
dpystr
=
DisplayString
(
dpy
);
static
char
*
display_env
=
NULL
;
static
char
env_rfb_client_id
[
100
];
static
char
env_rfb_client_ip
[
100
];
static
char
env_rfb_client_port
[
100
];
static
char
env_rfb_x11vnc_pid
[
100
];
static
char
env_rfb_client_count
[
100
];
char
*
addr
=
client
->
host
;
int
rc
,
fromlen
,
fromport
;
struct
sockaddr_in
from
;
if
(
addr
==
NULL
||
addr
[
0
]
==
'\0'
)
{
addr
=
"unknown-host"
;
}
/* set RFB_CLIENT_ID to semi unique id for command to use */
sprintf
(
env_rfb_client_id
,
"RFB_CLIENT_ID=%d"
,
(
int
)
client
);
putenv
(
env_rfb_client_id
);
/* set RFB_CLIENT_IP to IP addr for command to use */
sprintf
(
env_rfb_client_ip
,
"RFB_CLIENT_IP=%s"
,
addr
);
putenv
(
env_rfb_client_ip
);
/* set RFB_X11VNC_PID to our pid for command to use */
sprintf
(
env_rfb_x11vnc_pid
,
"RFB_X11VNC_PID=%d"
,
(
int
)
getpid
());
putenv
(
env_rfb_x11vnc_pid
);
/* set RFB_CLIENT_PORT to peer port for command to use */
fromlen
=
sizeof
(
from
);
memset
(
&
from
,
0
,
sizeof
(
from
));
fromport
=
-
1
;
if
(
!
getpeername
(
client
->
sock
,
(
struct
sockaddr
*
)
&
from
,
&
fromlen
))
{
fromport
=
ntohs
(
from
.
sin_port
);
}
sprintf
(
env_rfb_client_port
,
"RFB_CLIENT_PORT=%d"
,
fromport
);
putenv
(
env_rfb_client_port
);
/*
* Better set DISPLAY to the one we are polling, if they
* want something trickier, they can handle on their own
* via environment, etc. XXX really should save/restore old.
*/
if
(
display_env
==
NULL
)
{
display_env
=
(
char
*
)
malloc
(
strlen
(
dpystr
)
+
10
);
}
sprintf
(
display_env
,
"DISPLAY=%s"
,
dpystr
);
putenv
(
display_env
);
int
accepted_client
=
0
;
/*
void
client_gone
(
rfbClientPtr
client
)
{
* work out the number of clients (have to use client_count
* since there is deadlock in rfbGetClientIterator)
*/
sprintf
(
env_rfb_client_count
,
"RFB_CLIENT_COUNT=%d"
,
client_count
);
putenv
(
env_rfb_client_count
);
rfbLog
(
"running command:
\n
"
);
rfbLog
(
" %s
\n
"
,
cmd
);
rc
=
system
(
cmd
);
if
(
rc
>=
256
)
{
rc
=
rc
/
256
;
}
rfbLog
(
"command returned: %d
\n
"
,
rc
);
return
rc
;
}
/*
* callback for when a client disconnects
*/
static
void
client_gone
(
rfbClientPtr
client
)
{
client_count
--
;
client_count
--
;
rfbLog
(
"client_count: %d
\n
"
,
client_count
);
rfbLog
(
"client_count: %d
\n
"
,
client_count
);
...
@@ -489,7 +647,7 @@ void client_gone(rfbClientPtr client) {
...
@@ -489,7 +647,7 @@ void client_gone(rfbClientPtr client) {
* Simple routine to limit access via string compare. A power user will
* Simple routine to limit access via string compare. A power user will
* want to compile libvncserver with libwrap support and use /etc/hosts.allow.
* want to compile libvncserver with libwrap support and use /etc/hosts.allow.
*/
*/
int
check_access
(
char
*
addr
)
{
static
int
check_access
(
char
*
addr
)
{
int
allowed
=
0
;
int
allowed
=
0
;
char
*
p
,
*
list
;
char
*
p
,
*
list
;
...
@@ -523,8 +681,8 @@ int check_access(char *addr) {
...
@@ -523,8 +681,8 @@ int check_access(char *addr) {
* x11vnc's first (and only) visible widget: accept/reject dialog window.
* x11vnc's first (and only) visible widget: accept/reject dialog window.
* We go through this pain to avoid dependency on libXt.
* We go through this pain to avoid dependency on libXt.
*/
*/
static
int
ugly_accept_window
(
char
*
addr
,
int
X
,
int
Y
,
int
timeout
,
int
ugly_accept_window
(
char
*
addr
,
int
X
,
int
Y
,
int
timeout
,
char
*
mode
)
{
char
*
mode
)
{
#define t2x2_width 16
#define t2x2_width 16
#define t2x2_height 16
#define t2x2_height 16
...
@@ -786,88 +944,11 @@ static char t2x2_bits[] = {
...
@@ -786,88 +944,11 @@ static char t2x2_bits[] = {
return
ret
;
return
ret
;
}
}
/*
* utility to run a user supplied command setting some RFB_ env vars.
* used by, e.g., accept_client() and client_gone()
*/
int
run_user_command
(
char
*
cmd
,
rfbClientPtr
client
)
{
char
*
dpystr
=
DisplayString
(
dpy
);
static
char
*
display_env
=
NULL
;
static
char
env_rfb_client_id
[
100
];
static
char
env_rfb_client_ip
[
100
];
static
char
env_rfb_client_port
[
100
];
static
char
env_rfb_x11vnc_pid
[
100
];
char
*
addr
=
client
->
host
;
int
rc
,
fromlen
,
fromport
;
struct
sockaddr_in
from
;
if
(
addr
==
NULL
||
addr
[
0
]
==
'\0'
)
{
addr
=
"unknown-host"
;
}
/* set RFB_CLIENT_ID to semi unique id for command to use */
sprintf
(
env_rfb_client_id
,
"RFB_CLIENT_ID=%d"
,
(
int
)
client
);
putenv
(
env_rfb_client_id
);
/* set RFB_CLIENT_IP to IP addr for command to use */
sprintf
(
env_rfb_client_ip
,
"RFB_CLIENT_IP=%s"
,
addr
);
putenv
(
env_rfb_client_ip
);
/* set RFB_X11VNC_PID to our pid for command to use */
sprintf
(
env_rfb_x11vnc_pid
,
"RFB_X11VNC_PID=%d"
,
(
int
)
getpid
());
putenv
(
env_rfb_x11vnc_pid
);
/* set RFB_CLIENT_PORT to peer port for command to use */
fromlen
=
sizeof
(
from
);
memset
(
&
from
,
0
,
sizeof
(
from
));
fromport
=
-
1
;
if
(
!
getpeername
(
client
->
sock
,
(
struct
sockaddr
*
)
&
from
,
&
fromlen
))
{
fromport
=
ntohs
(
from
.
sin_port
);
}
sprintf
(
env_rfb_client_port
,
"RFB_CLIENT_PORT=%d"
,
fromport
);
putenv
(
env_rfb_client_port
);
/*
* Better set DISPLAY to the one we are polling, if they
* want something trickier, they can handle on their own
* via environment, etc. XXX really should save/restore old.
*/
if
(
display_env
==
NULL
)
{
display_env
=
(
char
*
)
malloc
(
strlen
(
dpystr
)
+
10
);
}
sprintf
(
display_env
,
"DISPLAY=%s"
,
dpystr
);
putenv
(
display_env
);
rfbLog
(
"running command:
\n
"
);
rfbLog
(
" %s
\n
"
,
cmd
);
rc
=
system
(
cmd
);
if
(
rc
>=
256
)
{
rc
=
rc
/
256
;
}
rfbLog
(
"command returned: %d
\n
"
,
rc
);
sprintf
(
env_rfb_client_id
,
"RFB_CLIENT_ID="
);
putenv
(
env_rfb_client_id
);
sprintf
(
env_rfb_client_ip
,
"RFB_CLIENT_IP="
);
putenv
(
env_rfb_client_ip
);
sprintf
(
env_rfb_client_port
,
"RFB_CLIENT_PORT="
);
putenv
(
env_rfb_client_port
);
sprintf
(
env_rfb_x11vnc_pid
,
"RFB_X11VNC_PID="
);
putenv
(
env_rfb_x11vnc_pid
);
return
rc
;
}
/*
/*
* process a "yes:0,no:*,view:3" type action list comparing to command
* process a "yes:0,no:*,view:3" type action list comparing to command
* return code rc. * means the default action with no other match.
* return code rc. * means the default action with no other match.
*/
*/
int
action_match
(
char
*
action
,
int
rc
)
{
static
int
action_match
(
char
*
action
,
int
rc
)
{
char
*
p
,
*
q
,
*
s
=
strdup
(
action
);
char
*
p
,
*
q
,
*
s
=
strdup
(
action
);
int
cases
[
4
],
i
,
result
;
int
cases
[
4
],
i
,
result
;
char
*
labels
[
4
];
char
*
labels
[
4
];
...
@@ -964,7 +1045,7 @@ int action_match(char *action, int rc) {
...
@@ -964,7 +1045,7 @@ int action_match(char *action, int rc) {
* popup: use internal X widgets for prompting.
* popup: use internal X widgets for prompting.
*
*
*/
*/
int
accept_client
(
rfbClientPtr
client
)
{
static
int
accept_client
(
rfbClientPtr
client
)
{
char
xmessage
[
200
],
*
cmd
=
NULL
;
char
xmessage
[
200
],
*
cmd
=
NULL
;
char
*
addr
=
client
->
host
;
char
*
addr
=
client
->
host
;
...
@@ -1123,7 +1204,7 @@ int accept_client(rfbClientPtr client) {
...
@@ -1123,7 +1204,7 @@ int accept_client(rfbClientPtr client) {
* For the -connect <file> option: periodically read the file looking for
* For the -connect <file> option: periodically read the file looking for
* a connect string. If one is found set client_connect to it.
* a connect string. If one is found set client_connect to it.
*/
*/
void
check_connect_file
(
char
*
file
)
{
static
void
check_connect_file
(
char
*
file
)
{
FILE
*
in
;
FILE
*
in
;
char
line
[
512
],
host
[
512
];
char
line
[
512
],
host
[
512
];
static
int
first_warn
=
1
,
truncate_ok
=
1
;
static
int
first_warn
=
1
,
truncate_ok
=
1
;
...
@@ -1177,8 +1258,10 @@ void check_connect_file(char *file) {
...
@@ -1177,8 +1258,10 @@ void check_connect_file(char *file) {
}
}
}
}
/* Do a reverse connect for a single "host" or "host:port" */
/*
int
do_reverse_connect
(
char
*
str
)
{
* Do a reverse connect for a single "host" or "host:port"
*/
static
int
do_reverse_connect
(
char
*
str
)
{
rfbClientPtr
cl
;
rfbClientPtr
cl
;
char
*
host
,
*
p
;
char
*
host
,
*
p
;
int
port
=
5500
,
len
=
strlen
(
str
);
int
port
=
5500
,
len
=
strlen
(
str
);
...
@@ -1218,15 +1301,10 @@ int do_reverse_connect(char *str) {
...
@@ -1218,15 +1301,10 @@ int do_reverse_connect(char *str) {
}
}
}
}
void
rfbPE
(
rfbScreenInfoPtr
scr
,
long
us
)
{
/*
if
(
!
use_threads
)
{
* Break up comma separated list of hosts and call do_reverse_connect()
return
rfbProcessEvents
(
scr
,
us
);
*/
}
static
void
reverse_connect
(
char
*
str
)
{
}
/* break up comma separated list of hosts and call do_reverse_connect() */
void
reverse_connect
(
char
*
str
)
{
char
*
p
,
*
tmp
=
strdup
(
str
);
char
*
p
,
*
tmp
=
strdup
(
str
);
int
sleep_between_host
=
300
;
int
sleep_between_host
=
300
;
int
sleep_min
=
1500
,
sleep_max
=
4500
,
n_max
=
5
;
int
sleep_min
=
1500
,
sleep_max
=
4500
,
n_max
=
5
;
...
@@ -1276,9 +1354,54 @@ void reverse_connect(char *str) {
...
@@ -1276,9 +1354,54 @@ void reverse_connect(char *str) {
}
}
}
}
/* check if client_connect has been set, if so make the reverse connections. */
/*
* Routines for monitoring the VNC_CONNECT property for changes.
* The vncconnect(1) will set it on our X display.
*/
void
read_vnc_connect_prop
(
void
)
{
Atom
type
;
int
format
,
slen
,
dlen
;
unsigned
long
nitems
=
0
,
bytes_after
=
0
;
unsigned
char
*
data
=
NULL
;
vnc_connect_str
[
0
]
=
'\0'
;
slen
=
0
;
if
(
!
vnc_connect
||
vnc_connect_prop
==
None
)
{
/* not active or problem with VNC_CONNECT atom */
return
;
}
/* read the property value into vnc_connect_str: */
do
{
if
(
XGetWindowProperty
(
dpy
,
DefaultRootWindow
(
dpy
),
vnc_connect_prop
,
nitems
/
4
,
VNC_CONNECT_MAX
/
16
,
False
,
AnyPropertyType
,
&
type
,
&
format
,
&
nitems
,
&
bytes_after
,
&
data
)
==
Success
)
{
dlen
=
nitems
*
(
format
/
8
);
if
(
slen
+
dlen
>
VNC_CONNECT_MAX
)
{
/* too big */
rfbLog
(
"warning: truncating large VNC_CONNECT"
" string > %d bytes.
\n
"
,
VNC_CONNECT_MAX
);
XFree
(
data
);
break
;
}
memcpy
(
vnc_connect_str
+
slen
,
data
,
dlen
);
slen
+=
dlen
;
vnc_connect_str
[
slen
]
=
'\0'
;
XFree
(
data
);
}
}
while
(
bytes_after
>
0
);
void
send_client_connect
()
{
vnc_connect_str
[
VNC_CONNECT_MAX
]
=
'\0'
;
rfbLog
(
"read property VNC_CONNECT: %s
\n
"
,
vnc_connect_str
);
}
/*
* check if client_connect has been set, if so make the reverse connections.
*/
static
void
send_client_connect
(
void
)
{
if
(
client_connect
!=
NULL
)
{
if
(
client_connect
!=
NULL
)
{
reverse_connect
(
client_connect
);
reverse_connect
(
client_connect
);
free
(
client_connect
);
free
(
client_connect
);
...
@@ -1286,12 +1409,10 @@ void send_client_connect() {
...
@@ -1286,12 +1409,10 @@ void send_client_connect() {
}
}
}
}
/* string for the VNC_CONNECT property */
/*
#define VNC_CONNECT_MAX 512
* monitor the various input methods
char
vnc_connect_str
[
VNC_CONNECT_MAX
+
1
];
*/
void
check_connect_inputs
(
void
)
{
/* monitor the various input methods */
void
check_connect_inputs
()
{
/* flush any already set: */
/* flush any already set: */
send_client_connect
();
send_client_connect
();
...
@@ -1362,18 +1483,20 @@ enum rfbNewClientAction new_client(rfbClientPtr client) {
...
@@ -1362,18 +1483,20 @@ enum rfbNewClientAction new_client(rfbClientPtr client) {
return
(
RFB_CLIENT_ACCEPT
);
return
(
RFB_CLIENT_ACCEPT
);
}
}
/* -- keyboard.c -- */
/*
/*
* For tweaking modifiers wrt the Alt-Graph key, etc.
* For tweaking modifiers wrt the Alt-Graph key, etc.
*/
*/
#define LEFTSHIFT 1
#define LEFTSHIFT 1
#define RIGHTSHIFT 2
#define RIGHTSHIFT 2
#define ALTGR 4
#define ALTGR 4
char
mod_state
=
0
;
static
char
mod_state
=
0
;
char
modifiers
[
0x100
];
static
char
modifiers
[
0x100
];
KeyCode
keycodes
[
0x100
],
left_shift_code
,
right_shift_code
,
altgr_code
;
static
KeyCode
keycodes
[
0x100
];
static
KeyCode
left_shift_code
,
right_shift_code
,
altgr_code
;
void
initialize_modtweak
()
{
void
initialize_modtweak
(
void
)
{
KeySym
key
,
*
keymap
;
KeySym
key
,
*
keymap
;
int
i
,
j
,
minkey
,
maxkey
,
syms_per_keycode
;
int
i
,
j
,
minkey
,
maxkey
,
syms_per_keycode
;
...
@@ -1432,8 +1555,11 @@ typedef struct keyremap {
...
@@ -1432,8 +1555,11 @@ typedef struct keyremap {
struct
keyremap
*
next
;
struct
keyremap
*
next
;
}
keyremap_t
;
}
keyremap_t
;
keyremap_t
*
keyremaps
=
NULL
;
static
keyremap_t
*
keyremaps
=
NULL
;
/*
* process the -remap string (file or mapping string)
*/
void
initialize_remap
(
char
*
infile
)
{
void
initialize_remap
(
char
*
infile
)
{
FILE
*
in
;
FILE
*
in
;
char
*
p
,
*
q
,
line
[
256
],
str1
[
256
],
str2
[
256
];
char
*
p
,
*
q
,
line
[
256
],
str1
[
256
],
str2
[
256
];
...
@@ -1529,8 +1655,11 @@ void initialize_remap(char *infile) {
...
@@ -1529,8 +1655,11 @@ void initialize_remap(char *infile) {
fclose
(
in
);
fclose
(
in
);
}
}
void
DebugXTestFakeKeyEvent
(
Display
*
dpy
,
KeyCode
key
,
Bool
down
,
time_t
cur_time
)
/*
{
* debugging wrapper for XTestFakeKeyEvent()
*/
void
myXTestFakeKeyEvent
(
Display
*
dpy
,
KeyCode
key
,
Bool
down
,
time_t
cur_time
)
{
if
(
debug_keyboard
)
{
if
(
debug_keyboard
)
{
rfbLog
(
"XTestFakeKeyEvent(dpy, keycode=0x%x
\"
%s
\"
, %s)
\n
"
,
rfbLog
(
"XTestFakeKeyEvent(dpy, keycode=0x%x
\"
%s
\"
, %s)
\n
"
,
key
,
XKeysymToString
(
XKeycodeToKeysym
(
dpy
,
key
,
0
)),
key
,
XKeysymToString
(
XKeycodeToKeysym
(
dpy
,
key
,
0
)),
...
@@ -1540,11 +1669,9 @@ void DebugXTestFakeKeyEvent(Display* dpy, KeyCode key, Bool down, time_t cur_tim
...
@@ -1540,11 +1669,9 @@ void DebugXTestFakeKeyEvent(Display* dpy, KeyCode key, Bool down, time_t cur_tim
}
}
/*
/*
*
This is to allow debug_keyboard option trap everything
:
*
does the actual tweak
:
*/
*/
#define XTestFakeKeyEvent DebugXTestFakeKeyEvent
static
void
tweak_mod
(
signed
char
mod
,
rfbBool
down
)
{
void
tweak_mod
(
signed
char
mod
,
rfbBool
down
)
{
rfbBool
is_shift
=
mod_state
&
(
LEFTSHIFT
|
RIGHTSHIFT
);
rfbBool
is_shift
=
mod_state
&
(
LEFTSHIFT
|
RIGHTSHIFT
);
Bool
dn
=
(
Bool
)
down
;
Bool
dn
=
(
Bool
)
down
;
...
@@ -1564,20 +1691,20 @@ void tweak_mod(signed char mod, rfbBool down) {
...
@@ -1564,20 +1691,20 @@ void tweak_mod(signed char mod, rfbBool down) {
X_LOCK
;
X_LOCK
;
if
(
is_shift
&&
mod
!=
1
)
{
if
(
is_shift
&&
mod
!=
1
)
{
if
(
mod_state
&
LEFTSHIFT
)
{
if
(
mod_state
&
LEFTSHIFT
)
{
XTestFakeKeyEvent
(
dpy
,
left_shift_code
,
!
dn
,
CurrentTime
);
my
XTestFakeKeyEvent
(
dpy
,
left_shift_code
,
!
dn
,
CurrentTime
);
}
}
if
(
mod_state
&
RIGHTSHIFT
)
{
if
(
mod_state
&
RIGHTSHIFT
)
{
XTestFakeKeyEvent
(
dpy
,
right_shift_code
,
!
dn
,
CurrentTime
);
my
XTestFakeKeyEvent
(
dpy
,
right_shift_code
,
!
dn
,
CurrentTime
);
}
}
}
}
if
(
!
is_shift
&&
mod
==
1
)
{
if
(
!
is_shift
&&
mod
==
1
)
{
XTestFakeKeyEvent
(
dpy
,
left_shift_code
,
dn
,
CurrentTime
);
my
XTestFakeKeyEvent
(
dpy
,
left_shift_code
,
dn
,
CurrentTime
);
}
}
if
(
altgr_code
&&
(
mod_state
&
ALTGR
)
&&
mod
!=
2
)
{
if
(
altgr_code
&&
(
mod_state
&
ALTGR
)
&&
mod
!=
2
)
{
XTestFakeKeyEvent
(
dpy
,
altgr_code
,
!
dn
,
CurrentTime
);
my
XTestFakeKeyEvent
(
dpy
,
altgr_code
,
!
dn
,
CurrentTime
);
}
}
if
(
altgr_code
&&
!
(
mod_state
&
ALTGR
)
&&
mod
==
2
)
{
if
(
altgr_code
&&
!
(
mod_state
&
ALTGR
)
&&
mod
==
2
)
{
XTestFakeKeyEvent
(
dpy
,
altgr_code
,
dn
,
CurrentTime
);
my
XTestFakeKeyEvent
(
dpy
,
altgr_code
,
dn
,
CurrentTime
);
}
}
X_UNLOCK
;
X_UNLOCK
;
if
(
debug_keyboard
)
{
if
(
debug_keyboard
)
{
...
@@ -1587,6 +1714,9 @@ void tweak_mod(signed char mod, rfbBool down) {
...
@@ -1587,6 +1714,9 @@ void tweak_mod(signed char mod, rfbBool down) {
}
}
}
}
/*
* tweak the modifier under -modtweak
*/
static
void
modifier_tweak_keyboard
(
rfbBool
down
,
rfbKeySym
keysym
,
static
void
modifier_tweak_keyboard
(
rfbBool
down
,
rfbKeySym
keysym
,
rfbClientPtr
client
)
{
rfbClientPtr
client
)
{
KeyCode
k
;
KeyCode
k
;
...
@@ -1632,7 +1762,7 @@ static void modifier_tweak_keyboard(rfbBool down, rfbKeySym keysym,
...
@@ -1632,7 +1762,7 @@ static void modifier_tweak_keyboard(rfbBool down, rfbKeySym keysym,
}
}
if
(
k
!=
NoSymbol
)
{
if
(
k
!=
NoSymbol
)
{
X_LOCK
;
X_LOCK
;
XTestFakeKeyEvent
(
dpy
,
k
,
(
Bool
)
down
,
CurrentTime
);
my
XTestFakeKeyEvent
(
dpy
,
k
,
(
Bool
)
down
,
CurrentTime
);
X_UNLOCK
;
X_UNLOCK
;
}
}
...
@@ -1645,10 +1775,9 @@ static void modifier_tweak_keyboard(rfbBool down, rfbKeySym keysym,
...
@@ -1645,10 +1775,9 @@ static void modifier_tweak_keyboard(rfbBool down, rfbKeySym keysym,
* key event handler. See the above functions for contortions for
* key event handler. See the above functions for contortions for
* running under -modtweak.
* running under -modtweak.
*/
*/
rfbClientPtr
last_keyboard_client
=
NULL
;
static
rfbClientPtr
last_keyboard_client
=
NULL
;
int
num_buttons
=
-
1
;
static
void
keyboard
(
rfbBool
down
,
rfbKeySym
keysym
,
rfbClientPtr
client
)
{
void
keyboard
(
rfbBool
down
,
rfbKeySym
keysym
,
rfbClientPtr
client
)
{
KeyCode
k
;
KeyCode
k
;
int
isbutton
=
0
;
int
isbutton
=
0
;
...
@@ -1731,7 +1860,7 @@ static void keyboard(rfbBool down, rfbKeySym keysym, rfbClientPtr client) {
...
@@ -1731,7 +1860,7 @@ static void keyboard(rfbBool down, rfbKeySym keysym, rfbClientPtr client) {
}
}
if
(
k
!=
NoSymbol
)
{
if
(
k
!=
NoSymbol
)
{
XTestFakeKeyEvent
(
dpy
,
k
,
(
Bool
)
down
,
CurrentTime
);
my
XTestFakeKeyEvent
(
dpy
,
k
,
(
Bool
)
down
,
CurrentTime
);
XFlush
(
dpy
);
XFlush
(
dpy
);
last_event
=
last_input
=
time
(
0
);
last_event
=
last_input
=
time
(
0
);
...
@@ -1742,6 +1871,7 @@ static void keyboard(rfbBool down, rfbKeySym keysym, rfbClientPtr client) {
...
@@ -1742,6 +1871,7 @@ static void keyboard(rfbBool down, rfbKeySym keysym, rfbClientPtr client) {
X_UNLOCK
;
X_UNLOCK
;
}
}
/* -- pointer.c -- */
/*
/*
* pointer event handling routines.
* pointer event handling routines.
*/
*/
...
@@ -1757,20 +1887,18 @@ typedef struct ptrremap {
...
@@ -1757,20 +1887,18 @@ typedef struct ptrremap {
MUTEX
(
pointerMutex
);
MUTEX
(
pointerMutex
);
#define MAX_BUTTONS 5
#define MAX_BUTTONS 5
#define MAX_BUTTON_EVENTS 50
#define MAX_BUTTON_EVENTS 50
prtremap_t
pointer_map
[
MAX_BUTTONS
+
1
][
MAX_BUTTON_EVENTS
];
static
prtremap_t
pointer_map
[
MAX_BUTTONS
+
1
][
MAX_BUTTON_EVENTS
];
char
*
pointer_remap
=
NULL
;
void
update_pointer
(
int
,
int
,
int
);
/* based on IsModifierKey in Xutil.h */
/*
* following is based on IsModifierKey in Xutil.h
*/
#define ismodkey(keysym) \
#define ismodkey(keysym) \
((((KeySym)(keysym) >= XK_Shift_L) && ((KeySym)(keysym) <= XK_Hyper_R)))
((((KeySym)(keysym) >= XK_Shift_L) && ((KeySym)(keysym) <= XK_Hyper_R)))
/*
/*
* For parsing the -buttonmap sections, e.g. "4" or ":Up+Up+Up:"
* For parsing the -buttonmap sections, e.g. "4" or ":Up+Up+Up:"
*/
*/
void
buttonparse
(
int
from
,
char
**
s
)
{
static
void
buttonparse
(
int
from
,
char
**
s
)
{
char
*
q
;
char
*
q
;
int
to
,
i
;
int
to
,
i
;
int
modisdown
[
256
];
int
modisdown
[
256
];
...
@@ -1914,7 +2042,10 @@ void buttonparse(int from, char **s) {
...
@@ -1914,7 +2042,10 @@ void buttonparse(int from, char **s) {
}
}
}
}
void
initialize_pointer_map
(
void
)
{
/*
* process the -buttonmap string
*/
void
initialize_pointer_map
(
char
*
pointer_remap
)
{
unsigned
char
map
[
MAX_BUTTONS
];
unsigned
char
map
[
MAX_BUTTONS
];
int
i
,
k
;
int
i
,
k
;
/*
/*
...
@@ -1972,27 +2103,125 @@ void initialize_pointer_map(void) {
...
@@ -1972,27 +2103,125 @@ void initialize_pointer_map(void) {
rfbLog
(
"remapping pointer buttons using string:
\n
"
);
rfbLog
(
"remapping pointer buttons using string:
\n
"
);
rfbLog
(
"
\"
%s
\"\n
"
,
remap
);
rfbLog
(
"
\"
%s
\"\n
"
,
remap
);
p
=
remap
;
p
=
remap
;
q
++
;
q
++
;
i
=
0
;
i
=
0
;
str
[
1
]
=
'\0'
;
str
[
1
]
=
'\0'
;
while
(
*
p
!=
'-'
)
{
while
(
*
p
!=
'-'
)
{
str
[
0
]
=
*
p
;
str
[
0
]
=
*
p
;
from
=
atoi
(
str
);
from
=
atoi
(
str
);
buttonparse
(
from
,
&
q
);
buttonparse
(
from
,
&
q
);
p
++
;
p
++
;
}
}
}
X_UNLOCK
;
}
/*
* Send a pointer event to the X server.
*/
static
void
update_pointer
(
int
mask
,
int
x
,
int
y
)
{
int
i
,
mb
;
X_LOCK
;
if
(
!
use_xwarppointer
)
{
XTestFakeMotionEvent
(
dpy
,
scr
,
x
+
off_x
,
y
+
off_y
,
CurrentTime
);
}
else
{
XWarpPointer
(
dpy
,
None
,
window
,
0
,
0
,
0
,
0
,
x
+
off_x
,
y
+
off_y
);
}
cursor_x
=
x
;
cursor_y
=
y
;
last_event
=
last_input
=
time
(
0
);
for
(
i
=
0
;
i
<
MAX_BUTTONS
;
i
++
)
{
/* look for buttons that have be clicked or released: */
if
(
(
button_mask
&
(
1
<<
i
))
!=
(
mask
&
(
1
<<
i
))
)
{
int
k
;
if
(
debug_pointer
)
{
rfbLog
(
"pointer(): mask change: mask: 0x%x -> "
"0x%x button: %d
\n
"
,
button_mask
,
mask
,
i
+
1
);
}
for
(
k
=
0
;
k
<
MAX_BUTTON_EVENTS
;
k
++
)
{
int
bmask
=
(
mask
&
(
1
<<
i
));
if
(
pointer_map
[
i
+
1
][
k
].
end
)
{
break
;
}
if
(
pointer_map
[
i
+
1
][
k
].
button
)
{
/* sent button up or down */
mb
=
pointer_map
[
i
+
1
][
k
].
button
;
if
((
num_buttons
&&
mb
>
num_buttons
)
||
mb
<
1
)
{
rfbLog
(
"ignoring mouse button out of "
"bounds: %d>%d mask: 0x%x -> 0x%x
\n
"
,
mb
,
num_buttons
,
button_mask
,
mask
);
continue
;
}
if
(
debug_pointer
)
{
rfbLog
(
"pointer(): sending button %d"
" %s (event %d)
\n
"
,
mb
,
bmask
?
"down"
:
"up"
,
k
+
1
);
}
XTestFakeButtonEvent
(
dpy
,
mb
,
(
mask
&
(
1
<<
i
))
?
True
:
False
,
CurrentTime
);
}
else
{
/* sent keysym up or down */
KeyCode
key
=
pointer_map
[
i
+
1
][
k
].
keycode
;
int
up
=
pointer_map
[
i
+
1
][
k
].
up
;
int
down
=
pointer_map
[
i
+
1
][
k
].
down
;
if
(
!
bmask
)
{
/* do not send keysym on button up */
continue
;
}
if
(
debug_pointer
)
{
rfbLog
(
"pointer(): sending button %d "
"down as keycode 0x%x (event %d)
\n
"
,
i
+
1
,
key
,
k
+
1
);
rfbLog
(
" down=%d up=%d "
"keysym: %s
\n
"
,
down
,
up
,
XKeysymToString
(
XKeycodeToKeysym
(
dpy
,
key
,
0
)));
}
if
(
down
)
{
myXTestFakeKeyEvent
(
dpy
,
key
,
True
,
CurrentTime
);
}
if
(
up
)
{
myXTestFakeKeyEvent
(
dpy
,
key
,
False
,
CurrentTime
);
}
}
}
}
}
}
}
}
if
(
nofb
)
{
/*
* nofb is for, e.g. Win2VNC, where fastest pointer
* updates are desired.
*/
XFlush
(
dpy
);
}
X_UNLOCK
;
X_UNLOCK
;
/*
* Remember the button state for next time and also for the
* -nodragging case:
*/
button_mask
=
mask
;
}
}
/*
/*
* Actual callback from libvncserver when it gets a pointer event.
* Actual callback from libvncserver when it gets a pointer event.
*/
*/
rfbClientPtr
last_pointer_client
=
NULL
;
void
pointer
(
int
mask
,
int
x
,
int
y
,
rfbClientPtr
client
)
{
static
void
pointer
(
int
mask
,
int
x
,
int
y
,
rfbClientPtr
client
)
{
if
(
debug_pointer
&&
mask
>=
0
)
{
if
(
debug_pointer
&&
mask
>=
0
)
{
rfbLog
(
"pointer(mask: 0x%x, x:%4d, y:%4d)
\n
"
,
mask
,
x
,
y
);
rfbLog
(
"pointer(mask: 0x%x, x:%4d, y:%4d)
\n
"
,
mask
,
x
,
y
);
...
@@ -2103,115 +2332,18 @@ static void pointer(int mask, int x, int y, rfbClientPtr client) {
...
@@ -2103,115 +2332,18 @@ static void pointer(int mask, int x, int y, rfbClientPtr client) {
update_pointer
(
mask
,
x
,
y
);
update_pointer
(
mask
,
x
,
y
);
}
}
/*
/* -- bell.c -- */
* Send a pointer event to the X server.
*/
void
update_pointer
(
int
mask
,
int
x
,
int
y
)
{
int
i
,
mb
;
X_LOCK
;
if
(
!
use_xwarppointer
)
{
XTestFakeMotionEvent
(
dpy
,
scr
,
x
+
off_x
,
y
+
off_y
,
CurrentTime
);
}
else
{
XWarpPointer
(
dpy
,
None
,
window
,
0
,
0
,
0
,
0
,
x
+
off_x
,
y
+
off_y
);
}
cursor_x
=
x
;
cursor_y
=
y
;
last_event
=
last_input
=
time
(
0
);
for
(
i
=
0
;
i
<
MAX_BUTTONS
;
i
++
)
{
/* look for buttons that have be clicked or released: */
if
(
(
button_mask
&
(
1
<<
i
))
!=
(
mask
&
(
1
<<
i
))
)
{
int
k
;
if
(
debug_pointer
)
{
rfbLog
(
"pointer(): mask change: mask: 0x%x -> "
"0x%x button: %d
\n
"
,
button_mask
,
mask
,
i
+
1
);
}
for
(
k
=
0
;
k
<
MAX_BUTTON_EVENTS
;
k
++
)
{
int
bmask
=
(
mask
&
(
1
<<
i
));
if
(
pointer_map
[
i
+
1
][
k
].
end
)
{
break
;
}
if
(
pointer_map
[
i
+
1
][
k
].
button
)
{
/* sent button up or down */
mb
=
pointer_map
[
i
+
1
][
k
].
button
;
if
((
num_buttons
&&
mb
>
num_buttons
)
||
mb
<
1
)
{
rfbLog
(
"ignoring mouse button out of "
"bounds: %d>%d mask: 0x%x -> 0x%x
\n
"
,
mb
,
num_buttons
,
button_mask
,
mask
);
continue
;
}
if
(
debug_pointer
)
{
rfbLog
(
"pointer(): sending button %d"
" %s (event %d)
\n
"
,
mb
,
bmask
?
"down"
:
"up"
,
k
+
1
);
}
XTestFakeButtonEvent
(
dpy
,
mb
,
(
mask
&
(
1
<<
i
))
?
True
:
False
,
CurrentTime
);
}
else
{
/* sent keysym up or down */
KeyCode
key
=
pointer_map
[
i
+
1
][
k
].
keycode
;
int
up
=
pointer_map
[
i
+
1
][
k
].
up
;
int
down
=
pointer_map
[
i
+
1
][
k
].
down
;
if
(
!
bmask
)
{
/* do not send keysym on button up */
continue
;
}
if
(
debug_pointer
)
{
rfbLog
(
"pointer(): sending button %d "
"down as keycode 0x%x (event %d)
\n
"
,
i
+
1
,
key
,
k
+
1
);
rfbLog
(
" down=%d up=%d "
"keysym: %s
\n
"
,
down
,
up
,
XKeysymToString
(
XKeycodeToKeysym
(
dpy
,
key
,
0
)));
}
if
(
down
)
{
XTestFakeKeyEvent
(
dpy
,
key
,
True
,
CurrentTime
);
}
if
(
up
)
{
XTestFakeKeyEvent
(
dpy
,
key
,
False
,
CurrentTime
);
}
}
}
}
}
if
(
nofb
)
{
/*
* nofb is for, e.g. Win2VNC, where fastest pointer
* updates are desired.
*/
XFlush
(
dpy
);
}
X_UNLOCK
;
/*
* Remember the button state for next time and also for the
* -nodragging case:
*/
button_mask
=
mask
;
}
/*
/*
* Bell event handling. Requires XKEYBOARD extension.
* Bell event handling. Requires XKEYBOARD extension.
*/
*/
#ifdef LIBVNCSERVER_HAVE_XKEYBOARD
#ifdef LIBVNCSERVER_HAVE_XKEYBOARD
int
xkb_base_event_type
;
static
int
xkb_base_event_type
;
void
initialize_watch_bell
()
{
/*
* check for XKEYBOARD, set up xkb_base_event_type
*/
void
initialize_watch_bell
(
void
)
{
int
ir
,
reason
;
int
ir
,
reason
;
if
(
!
XkbSelectEvents
(
dpy
,
XkbUseCoreKbd
,
XkbBellNotifyMask
,
if
(
!
XkbSelectEvents
(
dpy
,
XkbUseCoreKbd
,
XkbBellNotifyMask
,
XkbBellNotifyMask
)
)
{
XkbBellNotifyMask
)
)
{
...
@@ -2234,7 +2366,7 @@ void initialize_watch_bell() {
...
@@ -2234,7 +2366,7 @@ void initialize_watch_bell() {
* We call this periodically to process any bell events that have
* We call this periodically to process any bell events that have
* taken place.
* taken place.
*/
*/
void
watch_bell_event
()
{
void
watch_bell_event
(
void
)
{
XEvent
xev
;
XEvent
xev
;
XkbAnyEvent
*
xkb_ev
;
XkbAnyEvent
*
xkb_ev
;
int
got_bell
=
0
;
int
got_bell
=
0
;
...
@@ -2264,26 +2396,24 @@ void watch_bell_event() {
...
@@ -2264,26 +2396,24 @@ void watch_bell_event() {
}
}
}
}
#else
#else
void
watch_bell_event
()
{}
void
watch_bell_event
(
void
)
{}
#endif
#endif
/* -- selection.c -- */
/*
/*
* Selection/Cutbuffer/Clipboard handlers.
* Selection/Cutbuffer/Clipboard handlers.
*/
*/
int
watch_selection
=
1
;
/* normal selection/cutbuffer maintenance */
static
int
own_selection
=
0
;
/* whether we currently own PRIMARY or not */
int
watch_primary
=
1
;
/* more dicey, poll for changes in PRIMARY */
static
int
set_cutbuffer
=
0
;
/* to avoid bouncing the CutText right back */
int
own_selection
=
0
;
/* whether we currently own PRIMARY or not */
static
int
sel_waittime
=
15
;
/* some seconds to skip before first send */
int
set_cutbuffer
=
0
;
/* to avoid bouncing the CutText right back */
static
Window
selwin
;
/* special window for our selection */
int
sel_waittime
=
15
;
/* some seconds to skip before first send */
Window
selwin
;
/* special window for our selection */
/*
/*
* This is where we keep our selection: the string sent TO us from VNC
* This is where we keep our selection: the string sent TO us from VNC
* clients, and the string sent BY us to requesting X11 clients.
* clients, and the string sent BY us to requesting X11 clients.
*/
*/
char
*
xcut_string
=
NULL
;
static
char
*
xcut_string
=
NULL
;
/*
/*
* Our callbacks instruct us to check for changes in the cutbuffer
* Our callbacks instruct us to check for changes in the cutbuffer
...
@@ -2295,7 +2425,7 @@ char *xcut_string = NULL;
...
@@ -2295,7 +2425,7 @@ char *xcut_string = NULL;
* SelectionNotify handling).
* SelectionNotify handling).
*/
*/
#define PROP_MAX (131072L)
#define PROP_MAX (131072L)
char
selection_str
[
PROP_MAX
+
1
];
static
char
selection_str
[
PROP_MAX
+
1
];
/*
/*
* An X11 (not VNC) client on the local display has requested the selection
* An X11 (not VNC) client on the local display has requested the selection
...
@@ -2303,7 +2433,7 @@ char selection_str[PROP_MAX+1];
...
@@ -2303,7 +2433,7 @@ char selection_str[PROP_MAX+1];
*
*
* n.b.: our caller already has the X_LOCK.
* n.b.: our caller already has the X_LOCK.
*/
*/
void
selection_request
(
XEvent
*
ev
)
{
static
void
selection_request
(
XEvent
*
ev
)
{
XSelectionEvent
notify_event
;
XSelectionEvent
notify_event
;
XSelectionRequestEvent
*
req_event
;
XSelectionRequestEvent
*
req_event
;
unsigned
int
length
;
unsigned
int
length
;
...
@@ -2359,30 +2489,13 @@ void selection_request(XEvent *ev) {
...
@@ -2359,30 +2489,13 @@ void selection_request(XEvent *ev) {
XFlush
(
dpy
);
XFlush
(
dpy
);
}
}
int
all_clients_initialized
()
{
rfbClientIteratorPtr
iter
;
rfbClientPtr
cl
;
int
ok
=
1
;
iter
=
rfbGetClientIterator
(
screen
);
while
(
(
cl
=
rfbClientIteratorNext
(
iter
))
)
{
if
(
cl
->
state
!=
RFB_NORMAL
)
{
ok
=
0
;
break
;
}
}
rfbReleaseClientIterator
(
iter
);
return
ok
;
}
/*
/*
* CUT_BUFFER0 property on the local display has changed, we read and
* CUT_BUFFER0 property on the local display has changed, we read and
* store it and send it out to any connected VNC clients.
* store it and send it out to any connected VNC clients.
*
*
* n.b.: our caller already has the X_LOCK.
* n.b.: our caller already has the X_LOCK.
*/
*/
void
cutbuffer_send
(
)
{
static
void
cutbuffer_send
(
void
)
{
Atom
type
;
Atom
type
;
int
format
,
slen
,
dlen
;
int
format
,
slen
,
dlen
;
unsigned
long
nitems
=
0
,
bytes_after
=
0
;
unsigned
long
nitems
=
0
,
bytes_after
=
0
;
...
@@ -2435,7 +2548,7 @@ void cutbuffer_send() {
...
@@ -2435,7 +2548,7 @@ void cutbuffer_send() {
* timestamps to speed up the checking... XtGetSelectionValue().
* timestamps to speed up the checking... XtGetSelectionValue().
*/
*/
#define CHKSZ 32
#define CHKSZ 32
void
selection_send
(
XEvent
*
ev
)
{
static
void
selection_send
(
XEvent
*
ev
)
{
Atom
type
;
Atom
type
;
int
format
,
slen
,
dlen
,
oldlen
,
newlen
,
toobig
=
0
;
int
format
,
slen
,
dlen
,
oldlen
,
newlen
,
toobig
=
0
;
static
int
err
=
0
,
sent_one
=
0
;
static
int
err
=
0
,
sent_one
=
0
;
...
@@ -2515,59 +2628,11 @@ void selection_send(XEvent *ev) {
...
@@ -2515,59 +2628,11 @@ void selection_send(XEvent *ev) {
rfbSendServerCutText
(
screen
,
selection_str
,
newlen
);
rfbSendServerCutText
(
screen
,
selection_str
,
newlen
);
}
}
/*
* Routines for monitoring the VNC_CONNECT property for changes.
* The vncconnect(1) will set it on our X display.
*/
Atom
vnc_connect_prop
=
None
;
void
read_vnc_connect_prop
()
{
Atom
type
;
int
format
,
slen
,
dlen
;
unsigned
long
nitems
=
0
,
bytes_after
=
0
;
unsigned
char
*
data
=
NULL
;
vnc_connect_str
[
0
]
=
'\0'
;
slen
=
0
;
if
(
!
vnc_connect
||
vnc_connect_prop
==
None
)
{
/* not active or problem with VNC_CONNECT atom */
return
;
}
/* read the property value into vnc_connect_str: */
do
{
if
(
XGetWindowProperty
(
dpy
,
DefaultRootWindow
(
dpy
),
vnc_connect_prop
,
nitems
/
4
,
VNC_CONNECT_MAX
/
16
,
False
,
AnyPropertyType
,
&
type
,
&
format
,
&
nitems
,
&
bytes_after
,
&
data
)
==
Success
)
{
dlen
=
nitems
*
(
format
/
8
);
if
(
slen
+
dlen
>
VNC_CONNECT_MAX
)
{
/* too big */
rfbLog
(
"warning: truncating large VNC_CONNECT"
" string > %d bytes.
\n
"
,
VNC_CONNECT_MAX
);
XFree
(
data
);
break
;
}
memcpy
(
vnc_connect_str
+
slen
,
data
,
dlen
);
slen
+=
dlen
;
vnc_connect_str
[
slen
]
=
'\0'
;
XFree
(
data
);
}
}
while
(
bytes_after
>
0
);
vnc_connect_str
[
VNC_CONNECT_MAX
]
=
'\0'
;
rfbLog
(
"read property VNC_CONNECT: %s
\n
"
,
vnc_connect_str
);
}
/*
/*
* This routine is periodically called to check for selection related
* This routine is periodically called to check for selection related
* and other X11 events and respond to them as needed.
* and other X11 events and respond to them as needed.
*/
*/
void
watch_xevents
()
{
void
watch_xevents
(
void
)
{
XEvent
xev
;
XEvent
xev
;
static
int
first
=
1
,
sent_sel
=
0
;
static
int
first
=
1
,
sent_sel
=
0
;
int
have_clients
=
screen
->
rfbClientHead
?
1
:
0
;
int
have_clients
=
screen
->
rfbClientHead
?
1
:
0
;
...
@@ -2746,10 +2811,10 @@ void xcut_receive(char *text, int len, rfbClientPtr cl) {
...
@@ -2746,10 +2811,10 @@ void xcut_receive(char *text, int len, rfbClientPtr cl) {
set_cutbuffer
=
1
;
set_cutbuffer
=
1
;
}
}
void
mark_hint
(
hint_t
);
/* -- cursor.c -- */
/*
/*
* Here begins a bit of a mess to experiment with multiple cursors ...
* Here begins a bit of a mess to experiment with multiple cursors
* drawn on the remote background ...
*/
*/
typedef
struct
cursor_info
{
typedef
struct
cursor_info
{
char
*
data
;
/* data and mask pointers */
char
*
data
;
/* data and mask pointers */
...
@@ -2802,7 +2867,7 @@ static char* cur_mask =
...
@@ -2802,7 +2867,7 @@ static char* cur_mask =
#define CUR_SIZE 18
#define CUR_SIZE 18
#define CUR_DATA cur_data
#define CUR_DATA cur_data
#define CUR_MASK cur_mask
#define CUR_MASK cur_mask
cursor_info_t
cur0
=
{
NULL
,
NULL
,
CUR_SIZE
,
CUR_SIZE
,
0
,
0
,
0
};
static
cursor_info_t
cur0
=
{
NULL
,
NULL
,
CUR_SIZE
,
CUR_SIZE
,
0
,
0
,
0
};
/*
/*
* It turns out we can at least detect mouse is on the root window so
* It turns out we can at least detect mouse is on the root window so
...
@@ -2847,10 +2912,11 @@ static char* root_mask =
...
@@ -2847,10 +2912,11 @@ static char* root_mask =
" xxxxx xxxxx "
" xxxxx xxxxx "
" xxxx xxxx "
" xxxx xxxx "
" "
;
" "
;
cursor_info_t
cur1
=
{
NULL
,
NULL
,
18
,
18
,
8
,
8
,
1
};
static
cursor_info_t
cur1
=
{
NULL
,
NULL
,
18
,
18
,
8
,
8
,
1
};
static
cursor_info_t
*
cursors
[
2
];
cursor_info_t
*
cursors
[
2
];
static
void
setup_cursors
(
void
)
{
void
setup_cursors
(
void
)
{
/* TODO clean this up if we ever do more cursors... */
/* TODO clean this up if we ever do more cursors... */
cur0
.
data
=
cur_data
;
cur0
.
data
=
cur_data
;
...
@@ -2866,14 +2932,14 @@ void setup_cursors(void) {
...
@@ -2866,14 +2932,14 @@ void setup_cursors(void) {
/*
/*
* data and functions for -mouse real pointer position updates
* data and functions for -mouse real pointer position updates
*/
*/
char
cur_save
[(
4
*
CUR_SIZE
*
CUR_SIZE
)];
static
char
cur_save
[(
4
*
CUR_SIZE
*
CUR_SIZE
)];
int
cur_save_x
,
cur_save_y
,
cur_save_w
,
cur_save_h
;
static
int
cur_save_cx
,
cur_save_cy
,
cur_save_which
;
int
cur_save_cx
,
cur_save_cy
,
cur_save_which
,
cur_saved
=
0
;
/*
/*
* save current cursor info and the patch of non-cursor data it covers
* save current cursor info and the patch of non-cursor data it covers
*/
*/
void
save_mouse_patch
(
int
x
,
int
y
,
int
w
,
int
h
,
int
cx
,
int
cy
,
int
which
)
{
static
void
save_mouse_patch
(
int
x
,
int
y
,
int
w
,
int
h
,
int
cx
,
int
cy
,
int
which
)
{
int
pixelsize
=
bpp
>>
3
;
int
pixelsize
=
bpp
>>
3
;
char
*
rfb_fb
=
screen
->
frameBuffer
;
char
*
rfb_fb
=
screen
->
frameBuffer
;
int
ly
,
i
=
0
;
int
ly
,
i
=
0
;
...
@@ -2899,7 +2965,7 @@ void save_mouse_patch(int x, int y, int w, int h, int cx, int cy, int which) {
...
@@ -2899,7 +2965,7 @@ void save_mouse_patch(int x, int y, int w, int h, int cx, int cy, int which) {
/*
/*
* put the non-cursor patch back in the rfb fb
* put the non-cursor patch back in the rfb fb
*/
*/
void
restore_mouse_patch
()
{
void
restore_mouse_patch
(
void
)
{
int
pixelsize
=
bpp
>>
3
;
int
pixelsize
=
bpp
>>
3
;
char
*
rfb_fb
=
screen
->
frameBuffer
;
char
*
rfb_fb
=
screen
->
frameBuffer
;
int
ly
,
i
=
0
;
int
ly
,
i
=
0
;
...
@@ -2923,7 +2989,7 @@ void restore_mouse_patch() {
...
@@ -2923,7 +2989,7 @@ void restore_mouse_patch() {
* It seems impossible to do, but if the actual cursor could ever be
* It seems impossible to do, but if the actual cursor could ever be
* determined we might want to hash that info on window ID or something...
* determined we might want to hash that info on window ID or something...
*/
*/
int
tree_descend_cursor
(
void
)
{
static
int
tree_descend_cursor
(
void
)
{
Window
r
,
c
;
Window
r
,
c
;
int
rx
,
ry
,
wx
,
wy
;
int
rx
,
ry
,
wx
,
wy
;
unsigned
int
mask
;
unsigned
int
mask
;
...
@@ -2946,7 +3012,10 @@ int tree_descend_cursor(void) {
...
@@ -2946,7 +3012,10 @@ int tree_descend_cursor(void) {
return
descend
;
return
descend
;
}
}
void
blackout_nearby_tiles
(
x
,
y
,
dt
)
{
/*
* This is for mouse patch drawing under -xinerama or -blackout
*/
static
void
blackout_nearby_tiles
(
x
,
y
,
dt
)
{
int
sx
,
sy
,
n
,
b
;
int
sx
,
sy
,
n
,
b
;
int
tx
=
x
/
tile_x
;
int
tx
=
x
/
tile_x
;
int
ty
=
y
/
tile_y
;
int
ty
=
y
/
tile_y
;
...
@@ -2987,7 +3056,7 @@ void blackout_nearby_tiles(x, y, dt) {
...
@@ -2987,7 +3056,7 @@ void blackout_nearby_tiles(x, y, dt) {
* Send rfbCursorPosUpdates back to clients that understand them. This
* Send rfbCursorPosUpdates back to clients that understand them. This
* seems to be TightVNC specific.
* seems to be TightVNC specific.
*/
*/
void
cursor_pos_updates
(
int
x
,
int
y
)
{
static
void
cursor_pos_updates
(
int
x
,
int
y
)
{
rfbClientIteratorPtr
iter
;
rfbClientIteratorPtr
iter
;
rfbClientPtr
cl
;
rfbClientPtr
cl
;
int
cnt
=
0
;
int
cnt
=
0
;
...
@@ -3048,7 +3117,7 @@ void cursor_pos_updates(int x, int y) {
...
@@ -3048,7 +3117,7 @@ void cursor_pos_updates(int x, int y) {
/*
/*
* draw one of the mouse cursors into the rfb fb
* draw one of the mouse cursors into the rfb fb
*/
*/
void
draw_mouse
(
int
x
,
int
y
,
int
which
,
int
update
)
{
static
void
draw_mouse
(
int
x
,
int
y
,
int
which
,
int
update
)
{
int
px
,
py
,
i
,
offset
;
int
px
,
py
,
i
,
offset
;
int
pixelsize
=
bpp
>>
3
;
int
pixelsize
=
bpp
>>
3
;
char
*
rfb_fb
=
screen
->
frameBuffer
;
char
*
rfb_fb
=
screen
->
frameBuffer
;
...
@@ -3205,6 +3274,9 @@ void draw_mouse(int x, int y, int which, int update) {
...
@@ -3205,6 +3274,9 @@ void draw_mouse(int x, int y, int which, int update) {
}
}
}
}
/*
* wrapper to redraw the mouse patch
*/
void
redraw_mouse
(
void
)
{
void
redraw_mouse
(
void
)
{
if
(
cur_saved
)
{
if
(
cur_saved
)
{
/* redraw saved mouse from info (save_mouse_patch) */
/* redraw saved mouse from info (save_mouse_patch) */
...
@@ -3212,6 +3284,10 @@ void redraw_mouse(void) {
...
@@ -3212,6 +3284,10 @@ void redraw_mouse(void) {
}
}
}
}
/*
* routine called periodically to update the mouse aspects (drawn &
* cursorpos updates)
*/
void
update_mouse
(
void
)
{
void
update_mouse
(
void
)
{
Window
root_w
,
child_w
;
Window
root_w
,
child_w
;
rfbBool
ret
;
rfbBool
ret
;
...
@@ -3240,18 +3316,10 @@ void update_mouse(void) {
...
@@ -3240,18 +3316,10 @@ void update_mouse(void) {
draw_mouse
(
root_x
-
off_x
,
root_y
-
off_y
,
which
,
1
);
draw_mouse
(
root_x
-
off_x
,
root_y
-
off_y
,
which
,
1
);
}
}
/* -- screen.c -- */
/*
/*
*
For the subwin case follows the window if it is moved.
*
X11 and rfb display/screen related routines
*/
*/
void
set_offset
(
void
)
{
Window
w
;
if
(
!
subwin
)
{
return
;
}
X_LOCK
;
XTranslateCoordinates
(
dpy
,
window
,
rootwin
,
0
,
0
,
&
off_x
,
&
off_y
,
&
w
);
X_UNLOCK
;
}
/*
/*
* Some handling of 8bpp PseudoColor colormaps. Called for initializing
* Some handling of 8bpp PseudoColor colormaps. Called for initializing
...
@@ -3450,9 +3518,6 @@ void nofb_hook(rfbClientPtr cl) {
...
@@ -3450,9 +3518,6 @@ void nofb_hook(rfbClientPtr cl) {
screen
->
displayHook
=
NULL
;
screen
->
displayHook
=
NULL
;
}
}
int
got_rfbport
=
0
;
int
got_alwaysshared
=
0
;
int
got_nevershared
=
0
;
/*
/*
* initialize the rfb framebuffer/screen
* initialize the rfb framebuffer/screen
*/
*/
...
@@ -3482,17 +3547,18 @@ void initialize_screen(int *argc, char **argv, XImage *fb) {
...
@@ -3482,17 +3547,18 @@ void initialize_screen(int *argc, char **argv, XImage *fb) {
* Remove at some point. BTW, this assumes no usage of earlier "0.7pre".
* Remove at some point. BTW, this assumes no usage of earlier "0.7pre".
*/
*/
#ifdef LIBVNCSERVER_VERSION
#ifdef LIBVNCSERVER_VERSION
if
(
strcmp
(
LIBVNCSERVER_VERSION
,
"0.5"
)
&&
strcmp
(
LIBVNCSERVER_VERSION
,
"0.6"
))
{
if
(
strcmp
(
LIBVNCSERVER_VERSION
,
"0.5"
)
if
(
*
argc
!=
1
)
{
&&
strcmp
(
LIBVNCSERVER_VERSION
,
"0.6"
))
{
int
i
;
if
(
*
argc
!=
1
)
{
rfbLog
(
"*** unrecognized option(s) ***
\n
"
);
int
i
;
for
(
i
=
1
;
i
<
*
argc
;
i
++
)
{
rfbLog
(
"*** unrecognized option(s) ***
\n
"
);
rfbLog
(
"
\t
[%d] %s
\n
"
,
i
,
argv
[
i
]);
for
(
i
=
1
;
i
<
*
argc
;
i
++
)
{
rfbLog
(
"
\t
[%d] %s
\n
"
,
i
,
argv
[
i
]);
}
rfbLog
(
"for a list of options run: x11vnc -help
\n
"
);
clean_up_exit
(
1
);
}
}
rfbLog
(
"for a list of options run: x11vnc -help
\n
"
);
clean_up_exit
(
1
);
}
}
}
#endif
#endif
screen
->
paddedWidthInBytes
=
fb
->
bytes_per_line
;
screen
->
paddedWidthInBytes
=
fb
->
bytes_per_line
;
...
@@ -3619,6 +3685,11 @@ if (strcmp(LIBVNCSERVER_VERSION, "0.5") && strcmp(LIBVNCSERVER_VERSION, "0.6"))
...
@@ -3619,6 +3685,11 @@ if (strcmp(LIBVNCSERVER_VERSION, "0.5") && strcmp(LIBVNCSERVER_VERSION, "0.6"))
}
}
}
}
/* -- xinerama.c -- */
/*
* routines related to xinerama and blacking out rectangles
*/
/*
/*
* Take a comma separated list of geometries: WxH+X+Y and register them as
* Take a comma separated list of geometries: WxH+X+Y and register them as
* rectangles to black out from the screen.
* rectangles to black out from the screen.
...
@@ -3661,10 +3732,10 @@ void initialize_blackout (char *list) {
...
@@ -3661,10 +3732,10 @@ void initialize_blackout (char *list) {
* for the region. i.e. the x2, y2 are outside
* for the region. i.e. the x2, y2 are outside
* by 1 pixel.
* by 1 pixel.
*/
*/
black
[
blackouts
].
x1
=
x
;
black
r
[
blackouts
].
x1
=
x
;
black
[
blackouts
].
y1
=
y
;
black
r
[
blackouts
].
y1
=
y
;
black
[
blackouts
].
x2
=
X
;
black
r
[
blackouts
].
x2
=
X
;
black
[
blackouts
].
y2
=
Y
;
black
r
[
blackouts
].
y2
=
Y
;
blackouts
++
;
blackouts
++
;
if
(
blackouts
>=
100
)
{
if
(
blackouts
>=
100
)
{
rfbLog
(
"too many blackouts: %d
\n
"
,
blackouts
);
rfbLog
(
"too many blackouts: %d
\n
"
,
blackouts
);
...
@@ -3681,7 +3752,7 @@ void initialize_blackout (char *list) {
...
@@ -3681,7 +3752,7 @@ void initialize_blackout (char *list) {
* they have with the tiles in the system. If a tile is touched by a
* they have with the tiles in the system. If a tile is touched by a
* blackout, record information.
* blackout, record information.
*/
*/
void
blackout_tiles
()
{
void
blackout_tiles
(
void
)
{
int
tx
,
ty
;
int
tx
,
ty
;
if
(
!
blackouts
)
{
if
(
!
blackouts
)
{
return
;
return
;
...
@@ -3728,8 +3799,8 @@ void blackout_tiles() {
...
@@ -3728,8 +3799,8 @@ void blackout_tiles() {
/* union of blackouts */
/* union of blackouts */
for
(
b
=
0
;
b
<
blackouts
;
b
++
)
{
for
(
b
=
0
;
b
<
blackouts
;
b
++
)
{
sraRegionPtr
tmp_reg
=
(
sraRegionPtr
)
sraRegionPtr
tmp_reg
=
(
sraRegionPtr
)
sraRgnCreateRect
(
black
[
b
].
x1
,
black
[
b
].
y1
,
sraRgnCreateRect
(
black
r
[
b
].
x1
,
blackr
[
b
].
y1
,
black
[
b
].
x2
,
black
[
b
].
y2
);
black
r
[
b
].
x2
,
blackr
[
b
].
y2
);
sraRgnOr
(
black_reg
,
tmp_reg
);
sraRgnOr
(
black_reg
,
tmp_reg
);
sraRgnDestroy
(
tmp_reg
);
sraRgnDestroy
(
tmp_reg
);
...
@@ -3795,7 +3866,7 @@ void blackout_tiles() {
...
@@ -3795,7 +3866,7 @@ void blackout_tiles() {
}
}
}
}
void
initialize_xinerama
()
{
void
initialize_xinerama
(
void
)
{
#ifndef LIBVNCSERVER_HAVE_LIBXINERAMA
#ifndef LIBVNCSERVER_HAVE_LIBXINERAMA
rfbLog
(
"Xinerama: Library libXinerama is not available to determine
\n
"
);
rfbLog
(
"Xinerama: Library libXinerama is not available to determine
\n
"
);
rfbLog
(
"Xinerama: the head geometries, consider using -blackout
\n
"
);
rfbLog
(
"Xinerama: the head geometries, consider using -blackout
\n
"
);
...
@@ -3911,24 +3982,50 @@ void zero_fb(x1, y1, x2, y2) {
...
@@ -3911,24 +3982,50 @@ void zero_fb(x1, y1, x2, y2) {
line
=
y1
;
line
=
y1
;
while
(
line
++
<
y2
)
{
while
(
line
++
<
y2
)
{
memset
(
dst
,
fill
,
(
size_t
)
(
x2
-
x1
)
*
pixelsize
);
memset
(
dst
,
fill
,
(
size_t
)
(
x2
-
x1
)
*
pixelsize
);
dst
+=
bytes_per_line
;
dst
+=
bytes_per_line
;
}
}
/*
* Fill the framebuffer with zeros for each blackout region
*/
void
blackout_regions
()
{
int
i
;
for
(
i
=
0
;
i
<
blackouts
;
i
++
)
{
zero_fb
(
black
[
i
].
x1
,
black
[
i
].
y1
,
black
[
i
].
x2
,
black
[
i
].
y2
);
}
}
}
}
/* -- scan.c -- */
/*
* routines for scanning and reading the X11 display for changes, and
* for doing all the tile work (shm, etc).
*/
/* array to hold the hints: */
static
hint_t
*
hint_list
;
/* nap state */
static
int
nap_ok
=
0
,
nap_diff_count
=
0
;
static
int
scan_count
=
0
;
/* indicates which scan pattern we are on */
static
int
scan_in_progress
=
0
;
/* scan pattern jitter from x0rfbserver */
#define NSCAN 32
static
int
scanlines
[
NSCAN
]
=
{
0
,
16
,
8
,
24
,
4
,
20
,
12
,
28
,
10
,
26
,
18
,
2
,
22
,
6
,
30
,
14
,
1
,
17
,
9
,
25
,
7
,
23
,
15
,
31
,
19
,
3
,
27
,
11
,
29
,
13
,
5
,
21
};
typedef
struct
tile_change_region
{
/* start and end lines, along y, of the changed area inside a tile. */
unsigned
short
first_line
,
last_line
;
/* info about differences along edges. */
unsigned
short
left_diff
,
right_diff
;
unsigned
short
top_diff
,
bot_diff
;
}
region_t
;
/* array to hold the tiles region_t-s. */
static
region_t
*
tile_region
;
/*
/*
* setup tile numbers and allocate the tile and hint arrays:
* setup tile numbers and allocate the tile and hint arrays:
*/
*/
void
initialize_tiles
()
{
void
initialize_tiles
(
void
)
{
ntiles_x
=
(
dpy_x
-
1
)
/
tile_x
+
1
;
ntiles_x
=
(
dpy_x
-
1
)
/
tile_x
+
1
;
ntiles_y
=
(
dpy_y
-
1
)
/
tile_y
+
1
;
ntiles_y
=
(
dpy_y
-
1
)
/
tile_y
+
1
;
...
@@ -3956,7 +4053,9 @@ void initialize_tiles() {
...
@@ -3956,7 +4053,9 @@ void initialize_tiles() {
* should always work unless dpy_y is a large prime or something... under
* should always work unless dpy_y is a large prime or something... under
* failure fs_factor remains 0 and no fullscreen updates will be tried.
* failure fs_factor remains 0 and no fullscreen updates will be tried.
*/
*/
void
set_fs_factor
(
int
max
)
{
static
int
fs_factor
=
0
;
static
void
set_fs_factor
(
int
max
)
{
int
f
,
fac
=
1
,
n
=
dpy_y
;
int
f
,
fac
=
1
,
n
=
dpy_y
;
if
(
(
bpp
/
8
)
*
dpy_x
*
dpy_y
<=
max
)
{
if
(
(
bpp
/
8
)
*
dpy_x
*
dpy_y
<=
max
)
{
...
@@ -3978,7 +4077,7 @@ void set_fs_factor(int max) {
...
@@ -3978,7 +4077,7 @@ void set_fs_factor(int max) {
/*
/*
* set up an XShm image
* set up an XShm image
*/
*/
int
shm_create
(
XShmSegmentInfo
*
shm
,
XImage
**
ximg_ptr
,
int
w
,
int
h
,
static
int
shm_create
(
XShmSegmentInfo
*
shm
,
XImage
**
ximg_ptr
,
int
w
,
int
h
,
char
*
name
)
{
char
*
name
)
{
XImage
*
xim
;
XImage
*
xim
;
...
@@ -4121,7 +4220,7 @@ void shm_clean(XShmSegmentInfo *shm, XImage *xim) {
...
@@ -4121,7 +4220,7 @@ void shm_clean(XShmSegmentInfo *shm, XImage *xim) {
shm_delete
(
shm
);
shm_delete
(
shm
);
}
}
void
initialize_shm
()
{
void
initialize_shm
(
void
)
{
int
i
;
int
i
;
/* set all shm areas to "none" before trying to create any */
/* set all shm areas to "none" before trying to create any */
...
@@ -4193,13 +4292,12 @@ void initialize_shm() {
...
@@ -4193,13 +4292,12 @@ void initialize_shm() {
}
}
}
}
/*
/*
* A hint is a rectangular region built from 1 or more adjacent tiles
* A hint is a rectangular region built from 1 or more adjacent tiles
* glued together. Ultimately, this information in a single hint is sent
* glued together. Ultimately, this information in a single hint is sent
* to libvncserver rather than sending each tile separately.
* to libvncserver rather than sending each tile separately.
*/
*/
void
create_tile_hint
(
int
x
,
int
y
,
int
th
,
hint_t
*
hint
)
{
static
void
create_tile_hint
(
int
x
,
int
y
,
int
th
,
hint_t
*
hint
)
{
int
w
=
dpy_x
-
x
;
int
w
=
dpy_x
-
x
;
int
h
=
dpy_y
-
y
;
int
h
=
dpy_y
-
y
;
...
@@ -4216,7 +4314,7 @@ void create_tile_hint(int x, int y, int th, hint_t *hint) {
...
@@ -4216,7 +4314,7 @@ void create_tile_hint(int x, int y, int th, hint_t *hint) {
hint
->
h
=
h
;
hint
->
h
=
h
;
}
}
void
extend_tile_hint
(
int
x
,
int
y
,
int
th
,
hint_t
*
hint
)
{
static
void
extend_tile_hint
(
int
x
,
int
y
,
int
th
,
hint_t
*
hint
)
{
int
w
=
dpy_x
-
x
;
int
w
=
dpy_x
-
x
;
int
h
=
dpy_y
-
y
;
int
h
=
dpy_y
-
y
;
...
@@ -4244,7 +4342,7 @@ void extend_tile_hint(int x, int y, int th, hint_t *hint) {
...
@@ -4244,7 +4342,7 @@ void extend_tile_hint(int x, int y, int th, hint_t *hint) {
}
}
}
}
void
save_hint
(
hint_t
hint
,
int
loc
)
{
static
void
save_hint
(
hint_t
hint
,
int
loc
)
{
/* simply copy it to the global array for later use. */
/* simply copy it to the global array for later use. */
hint_list
[
loc
].
x
=
hint
.
x
;
hint_list
[
loc
].
x
=
hint
.
x
;
hint_list
[
loc
].
y
=
hint
.
y
;
hint_list
[
loc
].
y
=
hint
.
y
;
...
@@ -4256,7 +4354,7 @@ void save_hint(hint_t hint, int loc) {
...
@@ -4256,7 +4354,7 @@ void save_hint(hint_t hint, int loc) {
* Glue together horizontal "runs" of adjacent changed tiles into one big
* Glue together horizontal "runs" of adjacent changed tiles into one big
* rectangle change "hint" to be passed to the vnc machinery.
* rectangle change "hint" to be passed to the vnc machinery.
*/
*/
void
hint_updates
(
)
{
static
void
hint_updates
(
void
)
{
hint_t
hint
;
hint_t
hint
;
int
x
,
y
,
i
,
n
,
ty
,
th
;
int
x
,
y
,
i
,
n
,
ty
,
th
;
int
hint_count
=
0
,
in_run
=
0
;
int
hint_count
=
0
,
in_run
=
0
;
...
@@ -4312,7 +4410,7 @@ void mark_hint(hint_t hint) {
...
@@ -4312,7 +4410,7 @@ void mark_hint(hint_t hint) {
/*
/*
* Notifies libvncserver of a changed tile rectangle.
* Notifies libvncserver of a changed tile rectangle.
*/
*/
void
mark_tile
(
int
x
,
int
y
,
int
height
)
{
static
void
mark_tile
(
int
x
,
int
y
,
int
height
)
{
int
w
=
dpy_x
-
x
;
int
w
=
dpy_x
-
x
;
int
h
=
dpy_y
-
y
;
int
h
=
dpy_y
-
y
;
...
@@ -4332,7 +4430,7 @@ void mark_tile(int x, int y, int height) {
...
@@ -4332,7 +4430,7 @@ void mark_tile(int x, int y, int height) {
* Simply send each modified tile separately to the vnc machinery:
* Simply send each modified tile separately to the vnc machinery:
* (i.e. no hints)
* (i.e. no hints)
*/
*/
void
tile_updates
(
)
{
static
void
tile_updates
(
void
)
{
int
x
,
y
,
n
,
ty
,
th
;
int
x
,
y
,
n
,
ty
,
th
;
for
(
y
=
0
;
y
<
ntiles_y
;
y
++
)
{
for
(
y
=
0
;
y
<
ntiles_y
;
y
++
)
{
...
@@ -4349,7 +4447,6 @@ void tile_updates() {
...
@@ -4349,7 +4447,6 @@ void tile_updates() {
}
}
}
}
/*
/*
* copy_tiles() gives a slight improvement over copy_tile() since
* copy_tiles() gives a slight improvement over copy_tile() since
* adjacent runs of tiles are done all at once there is some savings
* adjacent runs of tiles are done all at once there is some savings
...
@@ -4360,11 +4457,10 @@ void tile_updates() {
...
@@ -4360,11 +4457,10 @@ void tile_updates() {
* the read bandwidth, sometimes only 5 MB/sec on otherwise fast
* the read bandwidth, sometimes only 5 MB/sec on otherwise fast
* hardware.
* hardware.
*/
*/
static
int
*
first_line
=
NULL
,
*
last_line
;
static
unsigned
short
*
left_diff
,
*
right_diff
;
int
*
first_line
=
NULL
,
*
last_line
;
static
void
copy_tiles
(
int
tx
,
int
ty
,
int
nt
)
{
unsigned
short
*
left_diff
,
*
right_diff
;
void
copy_tiles
(
int
tx
,
int
ty
,
int
nt
)
{
int
x
,
y
,
line
;
int
x
,
y
,
line
;
int
size_x
,
size_y
,
width1
,
width2
;
int
size_x
,
size_y
,
width1
,
width2
;
int
off
,
len
,
n
,
dw
,
dx
,
t
;
int
off
,
len
,
n
,
dw
,
dx
,
t
;
...
@@ -4704,7 +4800,7 @@ void copy_tiles(int tx, int ty, int nt) {
...
@@ -4704,7 +4800,7 @@ void copy_tiles(int tx, int ty, int nt) {
* See copy_tiles_backward_pass() for analogous checking upward and
* See copy_tiles_backward_pass() for analogous checking upward and
* left tiles.
* left tiles.
*/
*/
int
copy_all_tiles
(
)
{
static
int
copy_all_tiles
(
void
)
{
int
x
,
y
,
n
,
m
;
int
x
,
y
,
n
,
m
;
int
diffs
=
0
;
int
diffs
=
0
;
...
@@ -4747,7 +4843,7 @@ int copy_all_tiles() {
...
@@ -4747,7 +4843,7 @@ int copy_all_tiles() {
* Routine analogous to copy_all_tiles() above, but for horizontal runs
* Routine analogous to copy_all_tiles() above, but for horizontal runs
* of adjacent changed tiles.
* of adjacent changed tiles.
*/
*/
int
copy_all_tile_runs
(
)
{
static
int
copy_all_tile_runs
(
void
)
{
int
x
,
y
,
n
,
m
,
i
;
int
x
,
y
,
n
,
m
,
i
;
int
diffs
=
0
;
int
diffs
=
0
;
int
in_run
=
0
,
run
=
0
;
int
in_run
=
0
,
run
=
0
;
...
@@ -4814,7 +4910,7 @@ int copy_all_tile_runs() {
...
@@ -4814,7 +4910,7 @@ int copy_all_tile_runs() {
* Try to predict whether the upward and/or leftward tile has been modified.
* Try to predict whether the upward and/or leftward tile has been modified.
* copy_all_tiles() has already done downward and rightward tiles.
* copy_all_tiles() has already done downward and rightward tiles.
*/
*/
int
copy_tiles_backward_pass
(
)
{
static
int
copy_tiles_backward_pass
(
void
)
{
int
x
,
y
,
n
,
m
;
int
x
,
y
,
n
,
m
;
int
diffs
=
0
;
int
diffs
=
0
;
...
@@ -4853,7 +4949,7 @@ int copy_tiles_backward_pass() {
...
@@ -4853,7 +4949,7 @@ int copy_tiles_backward_pass() {
return
diffs
;
return
diffs
;
}
}
void
gap_try
(
int
x
,
int
y
,
int
*
run
,
int
*
saw
,
int
along_x
)
{
static
void
gap_try
(
int
x
,
int
y
,
int
*
run
,
int
*
saw
,
int
along_x
)
{
int
n
,
m
,
i
,
xt
,
yt
;
int
n
,
m
,
i
,
xt
,
yt
;
n
=
x
+
y
*
ntiles_x
;
n
=
x
+
y
*
ntiles_x
;
...
@@ -4898,7 +4994,7 @@ void gap_try(int x, int y, int *run, int *saw, int along_x) {
...
@@ -4898,7 +4994,7 @@ void gap_try(int x, int y, int *run, int *saw, int along_x) {
*
*
* BTW, grow_islands() is actually pretty successful at doing this too...
* BTW, grow_islands() is actually pretty successful at doing this too...
*/
*/
int
fill_tile_gaps
(
)
{
static
int
fill_tile_gaps
(
void
)
{
int
x
,
y
,
run
,
saw
;
int
x
,
y
,
run
,
saw
;
int
n
,
diffs
=
0
;
int
n
,
diffs
=
0
;
...
@@ -4928,7 +5024,7 @@ int fill_tile_gaps() {
...
@@ -4928,7 +5024,7 @@ int fill_tile_gaps() {
return
diffs
;
return
diffs
;
}
}
void
island_try
(
int
x
,
int
y
,
int
u
,
int
v
,
int
*
run
)
{
static
void
island_try
(
int
x
,
int
y
,
int
u
,
int
v
,
int
*
run
)
{
int
n
,
m
;
int
n
,
m
;
n
=
x
+
y
*
ntiles_x
;
n
=
x
+
y
*
ntiles_x
;
...
@@ -4958,7 +5054,7 @@ void island_try(int x, int y, int u, int v, int *run) {
...
@@ -4958,7 +5054,7 @@ void island_try(int x, int y, int u, int v, int *run) {
* the boundary of the discontinuity (i.e. make the island larger).
* the boundary of the discontinuity (i.e. make the island larger).
* Vertical scans are skipped since they do not seem to yield much...
* Vertical scans are skipped since they do not seem to yield much...
*/
*/
int
grow_islands
(
)
{
static
int
grow_islands
(
void
)
{
int
x
,
y
,
n
,
run
;
int
x
,
y
,
n
,
run
;
int
diffs
=
0
;
int
diffs
=
0
;
...
@@ -4989,13 +5085,23 @@ int grow_islands() {
...
@@ -4989,13 +5085,23 @@ int grow_islands() {
return
diffs
;
return
diffs
;
}
}
/*
* Fill the framebuffer with zeros for each blackout region
*/
static
void
blackout_regions
(
void
)
{
int
i
;
for
(
i
=
0
;
i
<
blackouts
;
i
++
)
{
zero_fb
(
blackr
[
i
].
x1
,
blackr
[
i
].
y1
,
blackr
[
i
].
x2
,
blackr
[
i
].
y2
);
}
}
/*
/*
* copy the whole X screen to the rfb framebuffer. For a large enough
* copy the whole X screen to the rfb framebuffer. For a large enough
* number of changed tiles, this is faster than tiles scheme at retrieving
* number of changed tiles, this is faster than tiles scheme at retrieving
* the info from the X server. Bandwidth to client and compression time
* the info from the X server. Bandwidth to client and compression time
* are other issues... use -fs 1.0 to disable.
* are other issues... use -fs 1.0 to disable.
*/
*/
void
copy_screen
()
{
void
copy_screen
(
void
)
{
int
pixelsize
=
bpp
>>
3
;
int
pixelsize
=
bpp
>>
3
;
char
*
rfb_fb
;
char
*
rfb_fb
;
int
i
,
y
,
block_size
;
int
i
,
y
,
block_size
;
...
@@ -5031,34 +5137,13 @@ void copy_screen() {
...
@@ -5031,34 +5137,13 @@ void copy_screen() {
rfbMarkRectAsModified
(
screen
,
0
,
0
,
dpy_x
,
dpy_y
);
rfbMarkRectAsModified
(
screen
,
0
,
0
,
dpy_x
,
dpy_y
);
}
}
/* profiling routines */
double
dtime
(
double
*
t_old
)
{
/*
* usage: call with 0.0 to initialize, subsequent calls give
* the time differences.
*/
double
t_now
,
dt
;
struct
timeval
now
;
gettimeofday
(
&
now
,
NULL
);
t_now
=
now
.
tv_sec
+
(
(
double
)
now
.
tv_usec
/
1000000
.
);
if
(
*
t_old
==
0
)
{
*
t_old
=
t_now
;
return
t_now
;
}
dt
=
t_now
-
*
t_old
;
*
t_old
=
t_now
;
return
(
dt
);
}
/*
/*
* Utilities for managing the "naps" to cut down on amount of polling.
* Utilities for managing the "naps" to cut down on amount of polling.
*/
*/
void
nap_set
(
int
tile_cnt
)
{
static
void
nap_set
(
int
tile_cnt
)
{
if
(
count
==
0
)
{
if
(
scan_
count
==
0
)
{
/* roll up check for all NSCAN scans */
/* roll up check for all NSCAN scans */
nap_ok
=
0
;
nap_ok
=
0
;
if
(
naptile
&&
nap_diff_count
<
2
*
NSCAN
*
naptile
)
{
if
(
naptile
&&
nap_diff_count
<
2
*
NSCAN
*
naptile
)
{
...
@@ -5078,10 +5163,12 @@ void nap_set(int tile_cnt) {
...
@@ -5078,10 +5163,12 @@ void nap_set(int tile_cnt) {
}
}
}
}
void
nap_sleep
(
int
ms
,
int
split
)
{
/*
* split up a long nap to improve the wakeup time
*/
static
void
nap_sleep
(
int
ms
,
int
split
)
{
int
i
,
input
=
got_user_input
;
int
i
,
input
=
got_user_input
;
/* split up a long nap to improve the wakeup time */
for
(
i
=
0
;
i
<
split
;
i
++
)
{
for
(
i
=
0
;
i
<
split
;
i
++
)
{
usleep
(
ms
*
1000
/
split
);
usleep
(
ms
*
1000
/
split
);
if
(
!
use_threads
&&
i
!=
split
-
1
)
{
if
(
!
use_threads
&&
i
!=
split
-
1
)
{
...
@@ -5093,7 +5180,10 @@ void nap_sleep(int ms, int split) {
...
@@ -5093,7 +5180,10 @@ void nap_sleep(int ms, int split) {
}
}
}
}
void
nap_check
(
int
tile_cnt
)
{
/*
* see if we should take a nap of some sort between polls
*/
static
void
nap_check
(
int
tile_cnt
)
{
time_t
now
;
time_t
now
;
nap_diff_count
+=
tile_cnt
;
nap_diff_count
+=
tile_cnt
;
...
@@ -5129,7 +5219,7 @@ void nap_check(int tile_cnt) {
...
@@ -5129,7 +5219,7 @@ void nap_check(int tile_cnt) {
* This is called to avoid a ~20 second timeout in libvncserver.
* This is called to avoid a ~20 second timeout in libvncserver.
* May no longer be needed.
* May no longer be needed.
*/
*/
void
ping_clients
(
int
tile_cnt
)
{
static
void
ping_clients
(
int
tile_cnt
)
{
static
time_t
last_send
=
0
;
static
time_t
last_send
=
0
;
time_t
now
=
time
(
0
);
time_t
now
=
time
(
0
);
...
@@ -5151,7 +5241,8 @@ void ping_clients(int tile_cnt) {
...
@@ -5151,7 +5241,8 @@ void ping_clients(int tile_cnt) {
* scan_display() wants to know if this tile can be skipped due to
* scan_display() wants to know if this tile can be skipped due to
* blackout regions: (no data compare is done, just a quick geometric test)
* blackout regions: (no data compare is done, just a quick geometric test)
*/
*/
int
blackout_line_skip
(
int
n
,
int
x
,
int
y
,
int
rescan
,
int
*
tile_count
)
{
static
int
blackout_line_skip
(
int
n
,
int
x
,
int
y
,
int
rescan
,
int
*
tile_count
)
{
if
(
tile_blackout
[
n
].
cover
==
2
)
{
if
(
tile_blackout
[
n
].
cover
==
2
)
{
tile_has_diff
[
n
]
=
0
;
tile_has_diff
[
n
]
=
0
;
...
@@ -5198,7 +5289,7 @@ int blackout_line_skip(int n, int x, int y, int rescan, int *tile_count) {
...
@@ -5198,7 +5289,7 @@ int blackout_line_skip(int n, int x, int y, int rescan, int *tile_count) {
* scan_display() wants to know if this changed tile can be skipped due
* scan_display() wants to know if this changed tile can be skipped due
* to blackout regions (we do an actual compare to find the changed region).
* to blackout regions (we do an actual compare to find the changed region).
*/
*/
int
blackout_line_cmpskip
(
int
n
,
int
x
,
int
y
,
char
*
dst
,
char
*
src
,
static
int
blackout_line_cmpskip
(
int
n
,
int
x
,
int
y
,
char
*
dst
,
char
*
src
,
int
w
,
int
pixelsize
)
{
int
w
,
int
pixelsize
)
{
int
i
,
x1
,
y1
,
x2
,
y2
,
b
,
hit
=
0
;
int
i
,
x1
,
y1
,
x2
,
y2
,
b
,
hit
=
0
;
...
@@ -5255,13 +5346,26 @@ int blackout_line_cmpskip(int n, int x, int y, char *dst, char *src,
...
@@ -5255,13 +5346,26 @@ int blackout_line_cmpskip(int n, int x, int y, char *dst, char *src,
}
}
}
}
/*
* For the subwin case follows the window if it is moved.
*/
void
set_offset
(
void
)
{
Window
w
;
if
(
!
subwin
)
{
return
;
}
X_LOCK
;
XTranslateCoordinates
(
dpy
,
window
,
rootwin
,
0
,
0
,
&
off_x
,
&
off_y
,
&
w
);
X_UNLOCK
;
}
/*
/*
* Loop over 1-pixel tall horizontal scanlines looking for changes.
* Loop over 1-pixel tall horizontal scanlines looking for changes.
* Record the changes in tile_has_diff[]. Scanlines in the loop are
* Record the changes in tile_has_diff[]. Scanlines in the loop are
* equally spaced along y by NSCAN pixels, but have a slightly random
* equally spaced along y by NSCAN pixels, but have a slightly random
* starting offset ystart ( < NSCAN ) from scanlines[].
* starting offset ystart ( < NSCAN ) from scanlines[].
*/
*/
int
scan_display
(
int
ystart
,
int
rescan
)
{
static
int
scan_display
(
int
ystart
,
int
rescan
)
{
char
*
src
,
*
dst
;
char
*
src
,
*
dst
;
int
pixelsize
=
bpp
>>
3
;
int
pixelsize
=
bpp
>>
3
;
int
x
,
y
,
w
,
n
;
int
x
,
y
,
w
,
n
;
...
@@ -5353,7 +5457,7 @@ int scan_display(int ystart, int rescan) {
...
@@ -5353,7 +5457,7 @@ int scan_display(int ystart, int rescan) {
/*
/*
* toplevel for the scanning, rescanning, and applying the heuristics.
* toplevel for the scanning, rescanning, and applying the heuristics.
*/
*/
void
scan_for_updates
()
{
void
scan_for_updates
(
void
)
{
int
i
,
tile_count
,
tile_diffs
;
int
i
,
tile_count
,
tile_diffs
;
double
frac1
=
0
.
1
;
/* tweak parameter to try a 2nd scan_display() */
double
frac1
=
0
.
1
;
/* tweak parameter to try a 2nd scan_display() */
double
frac2
=
0
.
35
;
/* or 3rd */
double
frac2
=
0
.
35
;
/* or 3rd */
...
@@ -5367,10 +5471,10 @@ void scan_for_updates() {
...
@@ -5367,10 +5471,10 @@ void scan_for_updates() {
* tile_x = tile_y = NSCAN = 32!
* tile_x = tile_y = NSCAN = 32!
*/
*/
count
++
;
scan_
count
++
;
count
%=
NSCAN
;
scan_
count
%=
NSCAN
;
if
(
count
%
(
NSCAN
/
4
)
==
0
)
{
if
(
scan_
count
%
(
NSCAN
/
4
)
==
0
)
{
/* some periodic maintenance */
/* some periodic maintenance */
if
(
subwin
)
{
if
(
subwin
)
{
...
@@ -5388,7 +5492,7 @@ void scan_for_updates() {
...
@@ -5388,7 +5492,7 @@ void scan_for_updates() {
/* scan with the initial y to the jitter value from scanlines: */
/* scan with the initial y to the jitter value from scanlines: */
scan_in_progress
=
1
;
scan_in_progress
=
1
;
tile_count
=
scan_display
(
scanlines
[
count
],
0
);
tile_count
=
scan_display
(
scanlines
[
scan_
count
],
0
);
nap_set
(
tile_count
);
nap_set
(
tile_count
);
...
@@ -5408,13 +5512,13 @@ void scan_for_updates() {
...
@@ -5408,13 +5512,13 @@ void scan_for_updates() {
int
cp
,
tile_count_old
=
tile_count
;
int
cp
,
tile_count_old
=
tile_count
;
/* choose a different y shift for the 2nd scan: */
/* choose a different y shift for the 2nd scan: */
cp
=
(
NSCAN
-
count
)
%
NSCAN
;
cp
=
(
NSCAN
-
scan_
count
)
%
NSCAN
;
tile_count
=
scan_display
(
scanlines
[
cp
],
1
);
tile_count
=
scan_display
(
scanlines
[
cp
],
1
);
if
(
tile_count
>=
(
1
+
frac2
)
*
tile_count_old
)
{
if
(
tile_count
>=
(
1
+
frac2
)
*
tile_count_old
)
{
/* on a roll... do a 3rd scan */
/* on a roll... do a 3rd scan */
cp
=
(
NSCAN
-
count
+
7
)
%
NSCAN
;
cp
=
(
NSCAN
-
scan_
count
+
7
)
%
NSCAN
;
tile_count
=
scan_display
(
scanlines
[
cp
],
1
);
tile_count
=
scan_display
(
scanlines
[
cp
],
1
);
}
}
}
}
...
@@ -5530,78 +5634,13 @@ void scan_for_updates() {
...
@@ -5530,78 +5634,13 @@ void scan_for_updates() {
nap_check
(
tile_diffs
);
nap_check
(
tile_diffs
);
}
}
int
check_user_input
(
double
,
int
*
);
/* -- x11vnc.c -- */
/*
void
watch_loop
(
void
)
{
* main routine for the x11vnc program
int
cnt
=
0
;
*/
double
dt
=
0
.
0
;
if
(
use_threads
)
{
rfbRunEventLoop
(
screen
,
-
1
,
TRUE
);
}
while
(
1
)
{
got_user_input
=
0
;
got_pointer_input
=
0
;
got_keyboard_input
=
0
;
if
(
!
use_threads
)
{
rfbProcessEvents
(
screen
,
-
1
);
if
(
check_user_input
(
dt
,
&
cnt
))
{
/* true means loop back for more input */
continue
;
}
}
if
(
shut_down
)
{
clean_up_exit
(
0
);
}
watch_xevents
();
check_connect_inputs
();
if
(
!
screen
->
rfbClientHead
)
{
/* waiting for a client */
usleep
(
200
*
1000
);
continue
;
}
if
(
nofb
)
{
/* no framebuffer polling needed */
if
(
cursor_pos
)
{
update_mouse
();
}
continue
;
}
if
(
watch_bell
)
{
/*
* check for any bell events.
* n.b. assumes -nofb folks do not want bell...
*/
watch_bell_event
();
}
if
(
!
show_dragging
&&
button_mask
)
{
/* if any button is pressed do not update screen */
/* XXX consider: use_threads || got_pointer_input */
X_LOCK
;
XFlush
(
dpy
);
X_UNLOCK
;
}
else
{
/* for timing the scan to try to detect thrashing */
double
tm
=
0
.
0
;
dtime
(
&
tm
);
rfbUndrawCursor
(
screen
);
scan_for_updates
();
dt
=
dtime
(
&
tm
);
}
/* sleep a bit to lessen load */
static
int
defer_update_nofb
=
6
;
/* defer a shorter time under -nofb */
usleep
(
waitms
*
1000
);
static
int
shut_down
=
0
;
cnt
++
;
}
}
/*
/*
* We need to handle user input, particularly pointer input, carefully.
* We need to handle user input, particularly pointer input, carefully.
...
@@ -5620,8 +5659,7 @@ void watch_loop(void) {
...
@@ -5620,8 +5659,7 @@ void watch_loop(void) {
* return of 1 means watch_loop should short-circuit and reloop,
* return of 1 means watch_loop should short-circuit and reloop,
* return of 0 means watch_loop should proceed to scan_for_updates().
* return of 0 means watch_loop should proceed to scan_for_updates().
*/
*/
static
int
check_user_input
(
double
dt
,
int
*
cnt
)
{
int
check_user_input
(
double
dt
,
int
*
cnt
)
{
if
(
old_pointer
)
{
if
(
old_pointer
)
{
/* every n-th drops thru to scan */
/* every n-th drops thru to scan */
...
@@ -5748,7 +5786,116 @@ int check_user_input(double dt, int *cnt) {
...
@@ -5748,7 +5786,116 @@ int check_user_input(double dt, int *cnt) {
return
0
;
return
0
;
}
}
void
print_help
()
{
/*
* simple function for measuring sub-second time differences, using
* a double to hold the value.
*/
double
dtime
(
double
*
t_old
)
{
/*
* usage: call with 0.0 to initialize, subsequent calls give
* the time differences.
*/
double
t_now
,
dt
;
struct
timeval
now
;
gettimeofday
(
&
now
,
NULL
);
t_now
=
now
.
tv_sec
+
(
(
double
)
now
.
tv_usec
/
1000000
.
);
if
(
*
t_old
==
0
)
{
*
t_old
=
t_now
;
return
t_now
;
}
dt
=
t_now
-
*
t_old
;
*
t_old
=
t_now
;
return
(
dt
);
}
/*
* utility wrapper to call rfbProcessEvents
*/
void
rfbPE
(
rfbScreenInfoPtr
scr
,
long
us
)
{
if
(
!
use_threads
)
{
return
rfbProcessEvents
(
scr
,
us
);
}
}
/*
* main x11vnc loop: polls, checks for events, iterate libvncserver, etc.
*/
static
void
watch_loop
(
void
)
{
int
cnt
=
0
;
double
dt
=
0
.
0
;
if
(
use_threads
)
{
rfbRunEventLoop
(
screen
,
-
1
,
TRUE
);
}
while
(
1
)
{
got_user_input
=
0
;
got_pointer_input
=
0
;
got_keyboard_input
=
0
;
if
(
!
use_threads
)
{
rfbProcessEvents
(
screen
,
-
1
);
if
(
check_user_input
(
dt
,
&
cnt
))
{
/* true means loop back for more input */
continue
;
}
}
if
(
shut_down
)
{
clean_up_exit
(
0
);
}
watch_xevents
();
check_connect_inputs
();
if
(
!
screen
->
rfbClientHead
)
{
/* waiting for a client */
usleep
(
200
*
1000
);
continue
;
}
if
(
nofb
)
{
/* no framebuffer polling needed */
if
(
cursor_pos
)
{
update_mouse
();
}
continue
;
}
if
(
watch_bell
)
{
/*
* check for any bell events.
* n.b. assumes -nofb folks do not want bell...
*/
watch_bell_event
();
}
if
(
!
show_dragging
&&
button_mask
)
{
/* if any button is pressed do not update screen */
/* XXX consider: use_threads || got_pointer_input */
X_LOCK
;
XFlush
(
dpy
);
X_UNLOCK
;
}
else
{
/* for timing the scan to try to detect thrashing */
double
tm
=
0
.
0
;
dtime
(
&
tm
);
rfbUndrawCursor
(
screen
);
scan_for_updates
();
dt
=
dtime
(
&
tm
);
}
/* sleep a bit to lessen load */
usleep
(
waitms
*
1000
);
cnt
++
;
}
}
/*
* text printed out under -help option
*/
static
void
print_help
(
void
)
{
char
help
[]
=
char
help
[]
=
"
\n
"
"
\n
"
"x11vnc: allow VNC connections to real X11 displays.
\n
"
"x11vnc: allow VNC connections to real X11 displays.
\n
"
...
@@ -5829,11 +5976,12 @@ void print_help() {
...
@@ -5829,11 +5976,12 @@ void print_help() {
" contains spaces, etc. The RFB_CLIENT_IP environment
\n
"
" contains spaces, etc. The RFB_CLIENT_IP environment
\n
"
" variable will be set to the incoming client IP number
\n
"
" variable will be set to the incoming client IP number
\n
"
" and the port in RFB_CLIENT_PORT (or -1 if unavailable).
\n
"
" and the port in RFB_CLIENT_PORT (or -1 if unavailable).
\n
"
" The x11vnc process id will be in RFB_X11VNC_PID and a
\n
"
" The x11vnc process id will be in RFB_X11VNC_PID, a
\n
"
" client id number in RFB_CLIENT_ID. If the external
\n
"
" client id number in RFB_CLIENT_ID and the number of
\n
"
" command returns 0 the client is accepted, otherwise
\n
"
" other connected clients in RFB_CLIENT_COUNT. If the
\n
"
" the client is rejected. See below for an extension to
\n
"
" external command returns 0 the client is accepted,
\n
"
" accept a client view-only.
\n
"
" otherwise the client is rejected. See below for an
\n
"
" extension to accept a client view-only.
\n
"
"
\n
"
"
\n
"
" If
\"
string
\"
is
\"
popup
\"
then a builtin popup window
\n
"
" If
\"
string
\"
is
\"
popup
\"
then a builtin popup window
\n
"
" is used. The popup will time out after 120 seconds,
\n
"
" is used. The popup will time out after 120 seconds,
\n
"
...
@@ -6016,11 +6164,11 @@ void print_help() {
...
@@ -6016,11 +6164,11 @@ void print_help() {
}
}
/*
/*
*
choose a desktop
name
*
utility to get the current host
name
*/
*/
#define MAXN 256
#define MAXN 256
char
*
this_host
(
)
{
static
char
*
this_host
(
void
)
{
char
host
[
MAXN
];
char
host
[
MAXN
];
#ifdef LIBVNCSERVER_HAVE_GETHOSTNAME
#ifdef LIBVNCSERVER_HAVE_GETHOSTNAME
if
(
gethostname
(
host
,
MAXN
)
==
0
)
{
if
(
gethostname
(
host
,
MAXN
)
==
0
)
{
...
@@ -6030,7 +6178,10 @@ char *this_host() {
...
@@ -6030,7 +6178,10 @@ char *this_host() {
return
NULL
;
return
NULL
;
}
}
char
*
choose_title
(
char
*
display
)
{
/*
* choose a desktop name
*/
static
char
*
choose_title
(
char
*
display
)
{
static
char
title
[(
MAXN
+
10
)];
static
char
title
[(
MAXN
+
10
)];
strcpy
(
title
,
"x11vnc"
);
strcpy
(
title
,
"x11vnc"
);
...
@@ -6060,7 +6211,7 @@ char *choose_title(char *display) {
...
@@ -6060,7 +6211,7 @@ char *choose_title(char *display) {
/*
/*
* check blacklist for OSs with tight shm limits.
* check blacklist for OSs with tight shm limits.
*/
*/
int
limit_shm
(
void
)
{
static
int
limit_shm
(
void
)
{
struct
utsname
ut
;
struct
utsname
ut
;
int
limit
=
0
;
int
limit
=
0
;
...
@@ -6091,6 +6242,9 @@ int main(int argc, char** argv) {
...
@@ -6091,6 +6242,9 @@ int main(int argc, char** argv) {
char
*
arg
,
*
visual_str
=
NULL
;
char
*
arg
,
*
visual_str
=
NULL
;
char
*
logfile
=
NULL
;
char
*
logfile
=
NULL
;
char
*
passwdfile
=
NULL
;
char
*
passwdfile
=
NULL
;
char
*
blackout_string
=
NULL
;
char
*
remap_file
=
NULL
;
char
*
pointer_remap
=
NULL
;
int
pw_loc
=
-
1
;
int
pw_loc
=
-
1
;
int
vpw_loc
=
-
1
;
int
vpw_loc
=
-
1
;
int
dt
=
0
;
int
dt
=
0
;
...
@@ -6657,7 +6811,7 @@ int main(int argc, char** argv) {
...
@@ -6657,7 +6811,7 @@ int main(int argc, char** argv) {
depth
=
visual_depth
;
/* force it */
depth
=
visual_depth
;
/* force it */
}
}
if
(
!
quiet
)
{
if
(
!
quiet
)
{
fprintf
(
stderr
,
"vis id: 0x%x
\n
"
,
fprintf
(
stderr
,
"vis id: 0x%x
\n
"
,
(
int
)
vinfo
->
visualid
);
(
int
)
vinfo
->
visualid
);
fprintf
(
stderr
,
"vis scr: %d
\n
"
,
vinfo
->
screen
);
fprintf
(
stderr
,
"vis scr: %d
\n
"
,
vinfo
->
screen
);
fprintf
(
stderr
,
"vis depth %d
\n
"
,
vinfo
->
depth
);
fprintf
(
stderr
,
"vis depth %d
\n
"
,
vinfo
->
depth
);
...
@@ -6725,7 +6879,7 @@ int main(int argc, char** argv) {
...
@@ -6725,7 +6879,7 @@ int main(int argc, char** argv) {
initialize_shm
();
/* also creates XImages when using_shm = 0 */
initialize_shm
();
/* also creates XImages when using_shm = 0 */
set
_signals
();
initialize
_signals
();
if
(
blackouts
)
{
/* blackout fb as needed. */
if
(
blackouts
)
{
/* blackout fb as needed. */
copy_screen
();
copy_screen
();
...
@@ -6737,7 +6891,7 @@ int main(int argc, char** argv) {
...
@@ -6737,7 +6891,7 @@ int main(int argc, char** argv) {
if
(
remap_file
!=
NULL
)
{
if
(
remap_file
!=
NULL
)
{
initialize_remap
(
remap_file
);
initialize_remap
(
remap_file
);
}
}
initialize_pointer_map
();
initialize_pointer_map
(
pointer_remap
);
if
(
!
inetd
)
{
if
(
!
inetd
)
{
if
(
!
screen
->
rfbPort
||
screen
->
rfbListenSock
<
0
)
{
if
(
!
screen
->
rfbPort
||
screen
->
rfbListenSock
<
0
)
{
...
@@ -6815,3 +6969,4 @@ int main(int argc, char** argv) {
...
@@ -6815,3 +6969,4 @@ int main(int argc, char** argv) {
return
(
0
);
return
(
0
);
}
}
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