Commit 00a9a0ea authored by runge's avatar runge

x11vnc: -appshare mode for sharing an application windows instead of the

entire desktop. map port + 5500 in reverse connect.  Add id_cmd remote
control functions for id (and other) windows.  Allow zero port in SSL
reverse connections.  Adjust delays between multiple reverse connections;
X11VNC_REVERSE_SLEEP_MAX env var.  Add some missing mutex locks; add
INPUT_LOCK and threads_drop_input.  More safety in -threads mode for
new framebuffer change.  Fix some stderr leaking in -inetd mode.
parent f40b0111
2009-12-02 Karl Runge <runge@karlrunge.com>
* x11vnc: -appshare mode for sharing an application windows intead
of the entire desktop. map port + 5500 in reverse connect.
Add id_cmd remote control functions for id (and other) windows.
Allow zero port in SSL reverse connections. Adjust delays
between multiple reverse connections; X11VNC_REVERSE_SLEEP_MAX
env var. Add some missing mutex locks; add INPUT_LOCK and
threads_drop_input. More safety in -threads mode for new
framebuffer change. Fix some stderr leaking in -inetd mode.
2009-11-18 Karl Runge <runge@karlrunge.com> 2009-11-18 Karl Runge <runge@karlrunge.com>
* x11vnc: use -timeout setting for reverse connections too. * x11vnc: use -timeout setting for reverse connections too.
Delay calling xfixes at the beginning of 1st connection to avoid Delay calling xfixes at the beginning of 1st connection to avoid
......
...@@ -23,7 +23,7 @@ LD_CYGIPC=-lcygipc ...@@ -23,7 +23,7 @@ LD_CYGIPC=-lcygipc
endif endif
bin_PROGRAMS=x11vnc bin_PROGRAMS=x11vnc
x11vnc_SOURCES = 8to24.c avahi.c cleanup.c connections.c cursor.c gui.c help.c inet.c keyboard.c linuxfb.c macosx.c macosxCG.c macosxCGP.c macosxCGS.c options.c pm.c pointer.c rates.c remote.c scan.c screen.c selection.c solid.c sslcmds.c sslhelper.c uinput.c unixpw.c user.c userinput.c util.c v4l.c win_utils.c x11vnc.c x11vnc_defs.c xdamage.c xevents.c xinerama.c xkb_bell.c xrandr.c xrecord.c xwrappers.c 8to24.h allowed_input_t.h avahi.h blackout_t.h cleanup.h connections.h cursor.h enc.h enums.h gui.h help.h inet.h keyboard.h linuxfb.h macosx.h macosxCG.h macosxCGP.h macosxCGS.h nox11.h nox11_funcs.h options.h params.h pm.h pointer.h rates.h remote.h scan.h screen.h scrollevent_t.h selection.h solid.h sslcmds.h sslhelper.h ssltools.h tkx11vnc.h uinput.h unixpw.h user.h userinput.h util.h v4l.h win_utils.h winattr_t.h x11vnc.h xdamage.h xevents.h xinerama.h xkb_bell.h xrandr.h xrecord.h xwrappers.h x11vnc_SOURCES = 8to24.c appshare.c avahi.c cleanup.c connections.c cursor.c gui.c help.c inet.c keyboard.c linuxfb.c macosx.c macosxCG.c macosxCGP.c macosxCGS.c options.c pm.c pointer.c rates.c remote.c scan.c screen.c selection.c solid.c sslcmds.c sslhelper.c uinput.c unixpw.c user.c userinput.c util.c v4l.c win_utils.c x11vnc.c x11vnc_defs.c xdamage.c xevents.c xinerama.c xkb_bell.c xrandr.c xrecord.c xwrappers.c 8to24.h allowed_input_t.h avahi.h blackout_t.h cleanup.h connections.h cursor.h enc.h enums.h gui.h help.h inet.h keyboard.h linuxfb.h macosx.h macosxCG.h macosxCGP.h macosxCGS.h nox11.h nox11_funcs.h options.h params.h pm.h pointer.h rates.h remote.h scan.h screen.h scrollevent_t.h selection.h solid.h sslcmds.h sslhelper.h ssltools.h tkx11vnc.h uinput.h unixpw.h user.h userinput.h util.h v4l.h win_utils.h winattr_t.h x11vnc.h xdamage.h xevents.h xinerama.h xkb_bell.h xrandr.h xrecord.h xwrappers.h
if HAVE_SYSTEM_LIBVNCSERVER if HAVE_SYSTEM_LIBVNCSERVER
INCLUDES_LIBVNCSERVER = @SYSTEM_LIBVNCSERVER_CFLAGS@ INCLUDES_LIBVNCSERVER = @SYSTEM_LIBVNCSERVER_CFLAGS@
......
This diff is collapsed.
This diff is collapsed.
...@@ -53,6 +53,7 @@ so, delete this exception statement from your version. ...@@ -53,6 +53,7 @@ so, delete this exception statement from your version.
#include "macosxCG.h" #include "macosxCG.h"
#include "userinput.h" #include "userinput.h"
#include "pointer.h" #include "pointer.h"
#include "xrandr.h"
/* /*
* routines for handling incoming, outgoing, etc connections * routines for handling incoming, outgoing, etc connections
...@@ -257,10 +258,10 @@ static rfbClientPtr *client_match(char *str) { ...@@ -257,10 +258,10 @@ static rfbClientPtr *client_match(char *str) {
i = 0; i = 0;
iter = rfbGetClientIterator(screen); iter = rfbGetClientIterator(screen);
while( (cl = rfbClientIteratorNext(iter)) ) { while( (cl = rfbClientIteratorNext(iter)) ) {
ClientData *cd = (ClientData *) cl->clientData;
if (strstr(str, "0x") == str) { if (strstr(str, "0x") == str) {
unsigned int in; unsigned int in;
int id; int id;
ClientData *cd = (ClientData *) cl->clientData;
if (! cd) { if (! cd) {
continue; continue;
} }
...@@ -277,25 +278,52 @@ static rfbClientPtr *client_match(char *str) { ...@@ -277,25 +278,52 @@ static rfbClientPtr *client_match(char *str) {
cl_list[i++] = cl; cl_list[i++] = cl;
} }
} else { } else {
char *rstr = str; int port = -1;
char *rstr = strdup(str);
char *q = strrchr(rstr, ':');
if (q) {
port = atoi(q+1);
*q = '\0';
if (port == 0 && q[1] != '0') {
port = -1;
} else if (port < 0) {
port = -port;
} else if (port < 200) {
port = 5500 + port;
}
}
if (! dotted_ip(str)) { if (! dotted_ip(str)) {
rstr = host2ip(str); char *orig = rstr;
rstr = host2ip(rstr);
free(orig);
if (rstr == NULL || *rstr == '\0') { if (rstr == NULL || *rstr == '\0') {
if (host_warn++) { if (host_warn++) {
continue; continue;
} }
rfbLog("skipping bad lookup: \"%s\"\n", rfbLog("skipping bad lookup: \"%s\"\n", str);
str);
continue; continue;
} }
rfbLog("lookup: %s -> %s\n", str, rstr); rfbLog("lookup: %s -> %s port=%d\n", str, rstr, port);
} }
if (!strcmp(rstr, cl->host)) { if (!strcmp(rstr, cl->host)) {
cl_list[i++] = cl; int ok = 1;
} if (port > 0) {
if (rstr != str) { if (cd != NULL && cd->client_port > 0) {
free(rstr); if (cd->client_port != port) {
ok = 0;
}
} else {
int cport = get_remote_port(cl->sock);
if (cport != port) {
ok = 0;
}
}
}
if (ok) {
cl_list[i++] = cl;
}
} }
free(rstr);
} }
if (i >= n - 1) { if (i >= n - 1) {
break; break;
...@@ -766,6 +794,7 @@ void client_gone(rfbClientPtr client) { ...@@ -766,6 +794,7 @@ void client_gone(rfbClientPtr client) {
if (unixpw_in_progress && unixpw_client) { if (unixpw_in_progress && unixpw_client) {
if (client == unixpw_client) { if (client == unixpw_client) {
unixpw_in_progress = 0; unixpw_in_progress = 0;
/* mutex */
screen->permitFileTransfer = unixpw_file_xfer_save; screen->permitFileTransfer = unixpw_file_xfer_save;
if ((tightfilexfer = unixpw_tightvnc_xfer_save)) { if ((tightfilexfer = unixpw_tightvnc_xfer_save)) {
#ifdef LIBVNCSERVER_WITH_TIGHTVNC_FILETRANSFER #ifdef LIBVNCSERVER_WITH_TIGHTVNC_FILETRANSFER
...@@ -1670,14 +1699,20 @@ static void check_connect_file(char *file) { ...@@ -1670,14 +1699,20 @@ static void check_connect_file(char *file) {
FILE *in; FILE *in;
char line[VNC_CONNECT_MAX], host[VNC_CONNECT_MAX]; char line[VNC_CONNECT_MAX], host[VNC_CONNECT_MAX];
static int first_warn = 1, truncate_ok = 1; static int first_warn = 1, truncate_ok = 1;
static time_t last_time = 0; static double last_time = 0.0, delay = 0.5;
time_t now = time(NULL); double now = dnow();
struct stat sbuf;
if (last_time == 0) {
last_time = now; if (last_time == 0.0) {
if (!getenv("X11VNC_APPSHARE_ACTIVE")) {
/* skip first */
last_time = now;
} else {
delay = 0.25;
}
} }
if (now - last_time < 1) { if (now - last_time < delay) {
/* check only once a second */ /* check only about once a second */
return; return;
} }
last_time = now; last_time = now;
...@@ -1691,6 +1726,13 @@ static void check_connect_file(char *file) { ...@@ -1691,6 +1726,13 @@ static void check_connect_file(char *file) {
} }
} }
if (stat(file, &sbuf) == 0) {
/* skip empty file directly */
if (sbuf.st_size == 0) {
return;
}
}
in = fopen(file, "r"); in = fopen(file, "r");
if (in == NULL) { if (in == NULL) {
if (first_warn) { if (first_warn) {
...@@ -2567,6 +2609,12 @@ void reverse_connect(char *str) { ...@@ -2567,6 +2609,12 @@ void reverse_connect(char *str) {
int nclients0 = client_count; int nclients0 = client_count;
int lcnt, j; int lcnt, j;
char **list; char **list;
int do_appshare = 0;
if (!getenv("X11VNC_REVERSE_USE_OLD_SLEEP")) {
sleep_min = 500;
sleep_max = 2500;
}
if (unixpw_in_progress) return; if (unixpw_in_progress) return;
...@@ -2582,19 +2630,56 @@ void reverse_connect(char *str) { ...@@ -2582,19 +2630,56 @@ void reverse_connect(char *str) {
} }
free(tmp); free(tmp);
if (subwin && getenv("X11VNC_APPSHARE_ACTIVE")) {
do_appshare = 1;
sleep_between_host = 0; /* too agressive??? */
}
if (getenv("X11VNC_REVERSE_SLEEP_BETWEEN_HOST")) {
sleep_between_host = atoi(getenv("X11VNC_REVERSE_SLEEP_BETWEEN_HOST"));
}
if (do_appshare) {
if (screen && dpy) {
char *s = choose_title(DisplayString(dpy));
/* mutex */
screen->desktopName = s;
if (rfb_desktop_name) {
free(rfb_desktop_name);
}
rfb_desktop_name = strdup(s);
}
}
for (j = 0; j < lcnt; j++) { for (j = 0; j < lcnt; j++) {
p = list[j]; p = list[j];
if ((n = do_reverse_connect(p)) != 0) { if ((n = do_reverse_connect(p)) != 0) {
int i;
progress_client(); progress_client();
rfbPE(-1); for (i=0; i < 3; i++) {
rfbPE(-1);
}
} }
cnt += n; cnt += n;
if (list[j+1] != NULL) { if (list[j+1] != NULL) {
t = 0; t = 0;
while (t < sleep_between_host) { while (t < sleep_between_host) {
double t1, t2;
int i;
t1 = dnow();
for (i=0; i < 8; i++) {
rfbPE(-1);
if (do_appshare && t == 0) {
rfbPE(-1);
}
}
t2 = dnow();
t += (int) (1000 * (t2 - t1));
if (t >= sleep_between_host) {
break;
}
usleep(dt * 1000); usleep(dt * 1000);
rfbPE(-1);
t += dt; t += dt;
} }
} }
...@@ -2616,6 +2701,9 @@ void reverse_connect(char *str) { ...@@ -2616,6 +2701,9 @@ void reverse_connect(char *str) {
} }
clean_up_exit(0); clean_up_exit(0);
} }
if (xrandr || xrandr_maybe) {
check_xrandr_event("reverse_connect1");
}
return; return;
} }
...@@ -2623,6 +2711,8 @@ void reverse_connect(char *str) { ...@@ -2623,6 +2711,8 @@ void reverse_connect(char *str) {
* XXX: we need to process some of the initial handshaking * XXX: we need to process some of the initial handshaking
* events, otherwise the client can get messed up (why??) * events, otherwise the client can get messed up (why??)
* so we send rfbProcessEvents() all over the place. * so we send rfbProcessEvents() all over the place.
*
* How much is this still needed?
*/ */
n = cnt; n = cnt;
...@@ -2632,17 +2722,42 @@ void reverse_connect(char *str) { ...@@ -2632,17 +2722,42 @@ void reverse_connect(char *str) {
t = sleep_max - sleep_min; t = sleep_max - sleep_min;
tot = sleep_min + ((n-1) * t) / (n_max-1); tot = sleep_min + ((n-1) * t) / (n_max-1);
if (do_appshare) {
tot /= 3;
if (tot < dt) {
tot = dt;
}
tot = 0; /* too agressive??? */
}
if (getenv("X11VNC_REVERSE_SLEEP_MAX")) {
tot = atoi(getenv("X11VNC_REVERSE_SLEEP_MAX"));
}
t = 0; t = 0;
while (t < tot) { while (t < tot) {
rfbPE(-1); int i;
rfbPE(-1); double t1, t2;
t1 = dnow();
for (i=0; i < 8; i++) {
rfbPE(-1);
if (t == 0) rfbPE(-1);
}
t2 = dnow();
t += (int) (1000 * (t2 - t1));
if (t >= tot) {
break;
}
usleep(dt * 1000); usleep(dt * 1000);
t += dt; t += dt;
} }
if (connect_or_exit) { if (connect_or_exit) {
if (client_count <= nclients0) { if (client_count <= nclients0) {
for (t = 0; t < 10; t++) { for (t = 0; t < 10; t++) {
rfbPE(-1); int i;
for (i=0; i < 3; i++) {
rfbPE(-1);
}
usleep(100 * 1000); usleep(100 * 1000);
} }
} }
...@@ -2656,6 +2771,9 @@ void reverse_connect(char *str) { ...@@ -2656,6 +2771,9 @@ void reverse_connect(char *str) {
clean_up_exit(0); clean_up_exit(0);
} }
} }
if (xrandr || xrandr_maybe) {
check_xrandr_event("reverse_connect2");
}
} }
/* /*
...@@ -2857,7 +2975,9 @@ static void pmove(int x, int y) { ...@@ -2857,7 +2975,9 @@ static void pmove(int x, int y) {
} }
rfbLog("pmove: x y: %d %d\n", x, y); rfbLog("pmove: x y: %d %d\n", x, y);
pointer(0, x, y, NULL); pointer(0, x, y, NULL);
X_LOCK;
XFlush_wr(dpy); XFlush_wr(dpy);
X_UNLOCK;
} }
...@@ -3472,6 +3592,7 @@ static void turn_off_truecolor_ad(rfbClientPtr client) { ...@@ -3472,6 +3592,7 @@ static void turn_off_truecolor_ad(rfbClientPtr client) {
if (client) {} if (client) {}
if (turn_off_truecolor) { if (turn_off_truecolor) {
rfbLog("turning off truecolor advertising.\n"); rfbLog("turning off truecolor advertising.\n");
/* mutex */
screen->serverFormat.trueColour = FALSE; screen->serverFormat.trueColour = FALSE;
screen->displayHook = NULL; screen->displayHook = NULL;
screen->serverFormat.redShift = 0; screen->serverFormat.redShift = 0;
...@@ -3639,6 +3760,7 @@ enum rfbNewClientAction new_client(rfbClientPtr client) { ...@@ -3639,6 +3760,7 @@ enum rfbNewClientAction new_client(rfbClientPtr client) {
} }
} else if (strstr(passwdfile, "custom:") == passwdfile) { } else if (strstr(passwdfile, "custom:") == passwdfile) {
if (screen) { if (screen) {
/* mutex */
screen->passwordCheck = custom_passwd_check; screen->passwordCheck = custom_passwd_check;
} }
} }
...@@ -3683,8 +3805,9 @@ enum rfbNewClientAction new_client(rfbClientPtr client) { ...@@ -3683,8 +3805,9 @@ enum rfbNewClientAction new_client(rfbClientPtr client) {
cd->cmp_bytes_sent = 0; cd->cmp_bytes_sent = 0;
cd->raw_bytes_sent = 0; cd->raw_bytes_sent = 0;
rfbLog("incr accepted_client for %s:%d sock=%d\n", client->host, get_remote_port(client->sock), client->sock);
accepted_client++; accepted_client++;
rfbLog("incr accepted_client=%d for %s:%d sock=%d\n", accepted_client,
client->host, get_remote_port(client->sock), client->sock);
last_client = time(NULL); last_client = time(NULL);
if (ncache) { if (ncache) {
...@@ -3720,6 +3843,7 @@ enum rfbNewClientAction new_client(rfbClientPtr client) { ...@@ -3720,6 +3843,7 @@ enum rfbNewClientAction new_client(rfbClientPtr client) {
rfbSetTranslateFunction(client); rfbSetTranslateFunction(client);
/* mutex */
screen->serverFormat.trueColour = TRUE; screen->serverFormat.trueColour = TRUE;
screen->serverFormat.redShift = rs; screen->serverFormat.redShift = rs;
screen->serverFormat.greenShift = gs; screen->serverFormat.greenShift = gs;
......
...@@ -576,7 +576,9 @@ void first_cursor(void) { ...@@ -576,7 +576,9 @@ void first_cursor(void) {
return; return;
} }
if (! show_cursor) { if (! show_cursor) {
LOCK(screen->cursorMutex);
screen->cursor = NULL; screen->cursor = NULL;
UNLOCK(screen->cursorMutex);
} else { } else {
got_xfixes_cursor_notify++; got_xfixes_cursor_notify++;
set_rfb_cursor(get_which_cursor()); set_rfb_cursor(get_which_cursor());
...@@ -591,7 +593,7 @@ static void setup_cursors(void) { ...@@ -591,7 +593,7 @@ static void setup_cursors(void) {
int w_in = 0, h_in = 0; int w_in = 0, h_in = 0;
static int first = 1; static int first = 1;
if (verbose) { if (verbose || use_threads) {
rfbLog("setting up %d cursors...\n", CURS_MAX); rfbLog("setting up %d cursors...\n", CURS_MAX);
} }
...@@ -603,8 +605,8 @@ static void setup_cursors(void) { ...@@ -603,8 +605,8 @@ static void setup_cursors(void) {
first = 0; first = 0;
if (screen) { if (screen) {
screen->cursor = NULL;
LOCK(screen->cursorMutex); LOCK(screen->cursorMutex);
screen->cursor = NULL;
} }
for (i=0; i<CURS_MAX; i++) { for (i=0; i<CURS_MAX; i++) {
...@@ -985,7 +987,6 @@ static void tree_descend_cursor(int *depth, Window *w, win_str_info_t *winfo) { ...@@ -985,7 +987,6 @@ static void tree_descend_cursor(int *depth, Window *w, win_str_info_t *winfo) {
void initialize_xfixes(void) { void initialize_xfixes(void) {
#if LIBVNCSERVER_HAVE_LIBXFIXES #if LIBVNCSERVER_HAVE_LIBXFIXES
if (xfixes_present) { if (xfixes_present) {
xfixes_first_initialized = 1;
X_LOCK; X_LOCK;
if (use_xfixes) { if (use_xfixes) {
XFixesSelectCursorInput(dpy, rootwin, XFixesSelectCursorInput(dpy, rootwin,
...@@ -994,6 +995,7 @@ void initialize_xfixes(void) { ...@@ -994,6 +995,7 @@ void initialize_xfixes(void) {
XFixesSelectCursorInput(dpy, rootwin, 0); XFixesSelectCursorInput(dpy, rootwin, 0);
} }
X_UNLOCK; X_UNLOCK;
xfixes_first_initialized = 1;
} }
#endif #endif
} }
...@@ -1325,24 +1327,23 @@ static int get_exact_cursor(int init) { ...@@ -1325,24 +1327,23 @@ static int get_exact_cursor(int init) {
return which; return which;
} }
X_LOCK;
if (! got_xfixes_cursor_notify && xfixes_base_event_type) { if (! got_xfixes_cursor_notify && xfixes_base_event_type) {
/* try again for XFixesCursorNotify event */ /* try again for XFixesCursorNotify event */
XEvent xev; XEvent xev;
X_LOCK;
if (XCheckTypedEvent(dpy, xfixes_base_event_type + if (XCheckTypedEvent(dpy, xfixes_base_event_type +
XFixesCursorNotify, &xev)) { XFixesCursorNotify, &xev)) {
got_xfixes_cursor_notify++; got_xfixes_cursor_notify++;
} }
X_UNLOCK;
} }
if (! got_xfixes_cursor_notify) { if (! got_xfixes_cursor_notify) {
/* evidently no cursor change, just return last one */ /* evidently no cursor change, just return last one */
X_UNLOCK;
return which; return which;
} }
got_xfixes_cursor_notify = 0; got_xfixes_cursor_notify = 0;
/* retrieve the cursor info + pixels from server: */ /* retrieve the cursor info + pixels from server: */
X_LOCK;
xfc = XFixesGetCursorImage(dpy); xfc = XFixesGetCursorImage(dpy);
X_UNLOCK; X_UNLOCK;
if (! xfc) { if (! xfc) {
...@@ -1512,7 +1513,9 @@ void initialize_cursors_mode(void) { ...@@ -1512,7 +1513,9 @@ void initialize_cursors_mode(void) {
} }
} else { } else {
if (screen) { if (screen) {
LOCK(screen->cursorMutex);
screen->cursor = NULL; screen->cursor = NULL;
UNLOCK(screen->cursorMutex);
set_cursor_was_changed(screen); set_cursor_was_changed(screen);
} }
} }
...@@ -1656,9 +1659,11 @@ static void set_cursor_was_changed(rfbScreenInfoPtr s) { ...@@ -1656,9 +1659,11 @@ static void set_cursor_was_changed(rfbScreenInfoPtr s) {
return; return;
} }
iter = rfbGetClientIterator(s); iter = rfbGetClientIterator(s);
LOCK(screen->cursorMutex);
while( (cl = rfbClientIteratorNext(iter)) ) { while( (cl = rfbClientIteratorNext(iter)) ) {
cl->cursorWasChanged = TRUE; cl->cursorWasChanged = TRUE;
} }
UNLOCK(screen->cursorMutex);
rfbReleaseClientIterator(iter); rfbReleaseClientIterator(iter);
} }
......
...@@ -176,6 +176,21 @@ void print_help(int mode) { ...@@ -176,6 +176,21 @@ void print_help(int mode) {
" shifts a root view to it: this shows SaveUnders menus,\n" " shifts a root view to it: this shows SaveUnders menus,\n"
" etc, although they will be clipped if they extend beyond\n" " etc, although they will be clipped if they extend beyond\n"
" the window.\n" " the window.\n"
"\n"
"-appshare Simple application sharing based on the -id/-sid\n"
" mechanism. Every new toplevel window that the\n"
" application creates induces a new viewer window via\n"
" a reverse connection. The -id/-sid and -connect\n"
" options are required. Run 'x11vnc -appshare -help'\n"
" for more info.\n"
"\n"
#if 0
"-freeze_when_obscured Probably only of use in -appshare mode: if the -id/-sid\n"
" window is partially or fully obscured by other windows,\n"
" stop checking for framebuffer updates. Mouse and\n"
" keyboard events are still processed and injected.\n"
"\n"
#endif
"-clip WxH+X+Y Only show the sub-region of the full display that\n" "-clip WxH+X+Y Only show the sub-region of the full display that\n"
" corresponds to the rectangle geometry with size WxH and\n" " corresponds to the rectangle geometry with size WxH and\n"
" offset +X+Y. The VNC display has size WxH (i.e. smaller\n" " offset +X+Y. The VNC display has size WxH (i.e. smaller\n"
...@@ -2779,7 +2794,7 @@ void print_help(int mode) { ...@@ -2779,7 +2794,7 @@ void print_help(int mode) {
" \"debug crash shell\" when fatal errors are trapped.\n" " \"debug crash shell\" when fatal errors are trapped.\n"
"\n" "\n"
"-q, -quiet Be quiet by printing less informational output to\n" "-q, -quiet Be quiet by printing less informational output to\n"
" stderr.\n" " stderr. (use -noquiet to undo an earlier -quiet.)\n"
"-v, -verbose Print out more information to stderr.\n" "-v, -verbose Print out more information to stderr.\n"
"\n" "\n"
"-bg Go into the background after screen setup. Messages to\n" "-bg Go into the background after screen setup. Messages to\n"
...@@ -3175,7 +3190,7 @@ void print_help(int mode) { ...@@ -3175,7 +3190,7 @@ void print_help(int mode) {
" (an integer) times that of the full display is allocated\n" " (an integer) times that of the full display is allocated\n"
" below the actual framebuffer to cache screen contents\n" " below the actual framebuffer to cache screen contents\n"
" for rapid retrieval. So a W x H frambuffer is expanded\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" " to a W x (n+1)*H one. Use 0 to disable.\n"
"\n" "\n"
" The \"n\" is actually optional, the default is 10.\n" " The \"n\" is actually optional, the default is 10.\n"
"\n" "\n"
...@@ -3183,13 +3198,17 @@ void print_help(int mode) { ...@@ -3183,13 +3198,17 @@ void print_help(int mode) {
" abbreviate \"-ncache\" with \"-nc\". Also, \"-nonc\"\n" " abbreviate \"-ncache\" with \"-nc\". Also, \"-nonc\"\n"
" is the same as \"-ncache 0\"\n" " is the same as \"-ncache 0\"\n"
"\n" "\n"
" This is an experimental option, currently implemented\n" " This is an experimental option, currently implemented in\n"
" in an awkward way in that in the VNC Viewer you can\n" " an awkward way in that in the VNC Viewer you can see the\n"
" see the cache contents if you scroll down, etc. So you\n" " pixel cache contents if you scroll down, etc. So you\n"
" will have to set things up so you can't see that region.\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" " If this method is successful, the changes required for\n"
" clients to do this less awkwardly will be investigated.\n" " clients to do this less awkwardly will be investigated.\n"
"\n" "\n"
" The SSVNC viewer does a good job at automatically hiding\n"
" the pixel cache region. Or use SSVNC's -ycrop option\n"
" to explicitly hide the region.\n"
"\n"
" Note that this mode consumes a huge amount of memory,\n" " Note that this mode consumes a huge amount of memory,\n"
" both on the x11vnc server side and on the VNC Viewer\n" " both on the x11vnc server side and on the VNC Viewer\n"
" side. If n=2 then the amount of RAM used is roughly\n" " side. If n=2 then the amount of RAM used is roughly\n"
...@@ -3896,10 +3915,7 @@ void print_help(int mode) { ...@@ -3896,10 +3915,7 @@ void print_help(int mode) {
" for output) are created to handle each new client.\n" " for output) are created to handle each new client.\n"
" Default: %s.\n" " Default: %s.\n"
"\n" "\n"
" NOTE: The -threads mode may be disabled due to its\n" " Thread stability is much improved in version 0.9.8.\n"
" unstable behavior. If it is disabled, a warning is\n"
" printed out. Stability has been improved in version\n"
" 0.9.8 and so the feature has been re-enabled.\n"
"\n" "\n"
" Multiple clients in threaded mode should be stable\n" " Multiple clients in threaded mode should be stable\n"
" for the ZRLE encoding on all platforms. The Tight and\n" " for the ZRLE encoding on all platforms. The Tight and\n"
...@@ -3907,9 +3923,14 @@ void print_help(int mode) { ...@@ -3907,9 +3923,14 @@ void print_help(int mode) {
" multiple clients. Compile with -DTLS=__thread if your\n" " multiple clients. Compile with -DTLS=__thread if your\n"
" OS and compiler and linker support it.\n" " OS and compiler and linker support it.\n"
"\n" "\n"
" For resizes (randr, etc.) set this env. var. to the number\n"
" of milliseconds to sleep: X11VNC_THREADS_NEW_FB_SLEEP\n"
" at various places in the do_new_fb() action. This is to\n"
" let various activities settle. Default is about 500ms.\n"
"\n"
" Multiple clients in threaded mode could yield better\n" " Multiple clients in threaded mode could yield better\n"
" performance for 'class-room' broadcasting usage.\n" " performance for 'class-room' broadcasting usage; also in\n"
" See also the -reflect option.\n" " -appshare broadcast mode. See also the -reflect option.\n"
"\n" "\n"
"-fs f If the fraction of changed tiles in a poll is greater\n" "-fs f If the fraction of changed tiles in a poll is greater\n"
" than f, the whole screen is updated. Default: %.2f\n" " than f, the whole screen is updated. Default: %.2f\n"
...@@ -4599,6 +4620,12 @@ void print_help(int mode) { ...@@ -4599,6 +4620,12 @@ void print_help(int mode) {
" id:windowid set -id window to \"windowid\". empty\n" " id:windowid set -id window to \"windowid\". empty\n"
" or \"root\" to go back to root window\n" " or \"root\" to go back to root window\n"
" sid:windowid set -sid window to \"windowid\"\n" " sid:windowid set -sid window to \"windowid\"\n"
" id_cmd:cmd cmds: raise, lower, map, unmap, iconify,\n"
" move:dXdY, resize:dWdH, geom:WxH+X+Y. dX\n"
" dY, dW, and dH must have a leading \"+\"\n"
" or \"-\" e.g.: move:-30+10 resize:+20+35\n"
" also: wm_delete, wm_name:string and\n"
" icon_name:string. Also id_cmd:win=N:cmd\n"
" waitmapped wait until subwin is mapped.\n" " waitmapped wait until subwin is mapped.\n"
" nowaitmapped do not wait until subwin is mapped.\n" " nowaitmapped do not wait until subwin is mapped.\n"
" clip:WxH+X+Y set -clip mode to \"WxH+X+Y\"\n" " clip:WxH+X+Y set -clip mode to \"WxH+X+Y\"\n"
...@@ -5081,8 +5108,8 @@ void print_help(int mode) { ...@@ -5081,8 +5108,8 @@ void print_help(int mode) {
" file use \"qry=...\" instead of \"cmd=...\"\n" " file use \"qry=...\" instead of \"cmd=...\"\n"
"\n" "\n"
" ans= stop quit exit shutdown ping resend_cutbuffer\n" " ans= stop quit exit shutdown ping resend_cutbuffer\n"
" resend_clipboard resend_primary blacken zero\n" " resend_clipboard resend_primary blacken zero refresh\n"
" refresh reset close disconnect id sid waitmapped\n" " reset close disconnect id_cmd id sid waitmapped\n"
" nowaitmapped clip flashcmap noflashcmap shiftcmap\n" " nowaitmapped clip flashcmap noflashcmap shiftcmap\n"
" truecolor notruecolor overlay nooverlay overlay_cursor\n" " truecolor notruecolor overlay nooverlay overlay_cursor\n"
" overlay_yescursor nooverlay_nocursor nooverlay_cursor\n" " overlay_yescursor nooverlay_nocursor nooverlay_cursor\n"
...@@ -5224,6 +5251,10 @@ void print_help(int mode) { ...@@ -5224,6 +5251,10 @@ void print_help(int mode) {
" The returned output is also prefixed with \"str\".\n" " The returned output is also prefixed with \"str\".\n"
" Example: -remote_prefix DO_THIS:\n" " Example: -remote_prefix DO_THIS:\n"
"\n" "\n"
" Note that enabling -remote_prefix allows the remote\n"
" VNC viewers to run x11vnc -remote commands. Do not\n"
" use this option if they are not to be trusted.\n"
"\n"
"-noremote Do not process any remote control commands or queries.\n" "-noremote Do not process any remote control commands or queries.\n"
"-yesremote Do process remote control commands or queries.\n" "-yesremote Do process remote control commands or queries.\n"
" Default: %s\n" " Default: %s\n"
......
...@@ -3056,6 +3056,10 @@ void keyboard(rfbBool down, rfbKeySym keysym, rfbClientPtr client) { ...@@ -3056,6 +3056,10 @@ void keyboard(rfbBool down, rfbKeySym keysym, rfbClientPtr client) {
static double max_keyrepeat_last_time = 0.0; static double max_keyrepeat_last_time = 0.0;
static double max_keyrepeat_always = -1.0; static double max_keyrepeat_always = -1.0;
if (threads_drop_input) {
return;
}
dtime0(&tnow); dtime0(&tnow);
got_keyboard_calls++; got_keyboard_calls++;
...@@ -3125,6 +3129,8 @@ void keyboard(rfbBool down, rfbKeySym keysym, rfbClientPtr client) { ...@@ -3125,6 +3129,8 @@ void keyboard(rfbBool down, rfbKeySym keysym, rfbClientPtr client) {
} }
} }
INPUT_LOCK;
last_down = down; last_down = down;
last_keysym = keysym; last_keysym = keysym;
last_keyboard_time = tnow; last_keyboard_time = tnow;
...@@ -3215,6 +3221,7 @@ void keyboard(rfbBool down, rfbKeySym keysym, rfbClientPtr client) { ...@@ -3215,6 +3221,7 @@ void keyboard(rfbBool down, rfbKeySym keysym, rfbClientPtr client) {
if (db) rfbLog("--- scroll keyrate skipping 0x%lx %s " if (db) rfbLog("--- scroll keyrate skipping 0x%lx %s "
"%.4f %.4f\n", keysym, down ? "down":"up ", "%.4f %.4f\n", keysym, down ? "down":"up ",
tnow - x11vnc_start, tnow - max_keyrepeat_last_time); tnow - x11vnc_start, tnow - max_keyrepeat_last_time);
INPUT_UNLOCK;
return; return;
} }
} }
...@@ -3237,6 +3244,7 @@ void keyboard(rfbBool down, rfbKeySym keysym, rfbClientPtr client) { ...@@ -3237,6 +3244,7 @@ void keyboard(rfbBool down, rfbKeySym keysym, rfbClientPtr client) {
tnow - x11vnc_start, tnow - max_keyrepeat_last_time); tnow - x11vnc_start, tnow - max_keyrepeat_last_time);
max_keyrepeat_last_keysym = keysym; max_keyrepeat_last_keysym = keysym;
skipped_last_down = 1; skipped_last_down = 1;
INPUT_UNLOCK;
return; return;
} else { } else {
if (db) rfbLog("--- scroll keyrate KEEPING 0x%lx %s " if (db) rfbLog("--- scroll keyrate KEEPING 0x%lx %s "
...@@ -3267,15 +3275,18 @@ void keyboard(rfbBool down, rfbKeySym keysym, rfbClientPtr client) { ...@@ -3267,15 +3275,18 @@ void keyboard(rfbBool down, rfbKeySym keysym, rfbClientPtr client) {
got_user_input++; got_user_input++;
got_keyboard_input++; got_keyboard_input++;
} }
INPUT_UNLOCK;
return; return;
} }
} }
if (view_only) { if (view_only) {
INPUT_UNLOCK;
return; return;
} }
get_allowed_input(client, &input); get_allowed_input(client, &input);
if (! input.keystroke) { if (! input.keystroke) {
INPUT_UNLOCK;
return; return;
} }
...@@ -3327,6 +3338,7 @@ void keyboard(rfbBool down, rfbKeySym keysym, rfbClientPtr client) { ...@@ -3327,6 +3338,7 @@ void keyboard(rfbBool down, rfbKeySym keysym, rfbClientPtr client) {
char *b, bstr[32]; char *b, bstr[32];
if (! down) { if (! down) {
INPUT_UNLOCK;
return; /* nothing to send */ return; /* nothing to send */
} }
if (debug_keyboard) { if (debug_keyboard) {
...@@ -3360,6 +3372,7 @@ void keyboard(rfbBool down, rfbKeySym keysym, rfbClientPtr client) { ...@@ -3360,6 +3372,7 @@ void keyboard(rfbBool down, rfbKeySym keysym, rfbClientPtr client) {
} }
XFlush_wr(dpy); XFlush_wr(dpy);
X_UNLOCK; X_UNLOCK;
INPUT_UNLOCK;
return; return;
} }
...@@ -3368,6 +3381,7 @@ void keyboard(rfbBool down, rfbKeySym keysym, rfbClientPtr client) { ...@@ -3368,6 +3381,7 @@ void keyboard(rfbBool down, rfbKeySym keysym, rfbClientPtr client) {
X_LOCK; X_LOCK;
XFlush_wr(dpy); XFlush_wr(dpy);
X_UNLOCK; X_UNLOCK;
INPUT_UNLOCK;
return; return;
} }
...@@ -3394,6 +3408,7 @@ void keyboard(rfbBool down, rfbKeySym keysym, rfbClientPtr client) { ...@@ -3394,6 +3408,7 @@ void keyboard(rfbBool down, rfbKeySym keysym, rfbClientPtr client) {
} }
X_UNLOCK; X_UNLOCK;
INPUT_UNLOCK;
} }
...@@ -206,6 +206,8 @@ int macosx_icon_anim_time = 450; ...@@ -206,6 +206,8 @@ int macosx_icon_anim_time = 450;
unsigned long subwin = 0x0; /* -id, -sid */ unsigned long subwin = 0x0; /* -id, -sid */
int subwin_wait_mapped = 0; int subwin_wait_mapped = 0;
int freeze_when_obscured = 0;
int subwin_obscured = 0;
int debug_xevents = 0; /* -R debug_xevents:1 */ int debug_xevents = 0; /* -R debug_xevents:1 */
int debug_xdamage = 0; /* -R debug_xdamage:1 or 2 ... */ int debug_xdamage = 0; /* -R debug_xdamage:1 or 2 ... */
...@@ -472,6 +474,7 @@ int verbose = 0; ...@@ -472,6 +474,7 @@ int verbose = 0;
/* threaded vs. non-threaded (default) */ /* threaded vs. non-threaded (default) */
int use_threads = 0; int use_threads = 0;
int started_rfbRunEventLoop = 0; int started_rfbRunEventLoop = 0;
int threads_drop_input = 0;
/* info about command line opts */ /* info about command line opts */
int got_noxwarppointer = 0; int got_noxwarppointer = 0;
......
...@@ -178,6 +178,8 @@ extern int macosx_icon_anim_time; ...@@ -178,6 +178,8 @@ extern int macosx_icon_anim_time;
extern unsigned long subwin; extern unsigned long subwin;
extern int subwin_wait_mapped; extern int subwin_wait_mapped;
extern int freeze_when_obscured;
extern int subwin_obscured;
extern int debug_xevents; extern int debug_xevents;
extern int debug_xdamage; extern int debug_xdamage;
...@@ -367,6 +369,7 @@ extern int verbose; ...@@ -367,6 +369,7 @@ extern int verbose;
extern int use_threads; extern int use_threads;
extern int started_rfbRunEventLoop; extern int started_rfbRunEventLoop;
extern int threads_drop_input;
extern int got_noxwarppointer; extern int got_noxwarppointer;
extern int got_rfbport; extern int got_rfbport;
......
...@@ -49,6 +49,16 @@ static void check_dpms(void); ...@@ -49,6 +49,16 @@ static void check_dpms(void);
#endif #endif
void check_pm(void) { void check_pm(void) {
static int skip = -1;
if (skip < 0) {
skip = 0;
if (getenv("X11VNC_NO_CHECK_PM")) {
skip = 1;
}
}
if (skip) {
return;
}
check_fbpm(); check_fbpm();
check_dpms(); check_dpms();
/* someday dpms activities? */ /* someday dpms activities? */
......
...@@ -76,9 +76,6 @@ typedef struct ptrremap { ...@@ -76,9 +76,6 @@ typedef struct ptrremap {
int up; int up;
} prtremap_t; } prtremap_t;
#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD
MUTEX(pointerMutex);
#endif
#define MAX_BUTTON_EVENTS 50 #define MAX_BUTTON_EVENTS 50
static prtremap_t pointer_map[MAX_BUTTONS+1][MAX_BUTTON_EVENTS]; static prtremap_t pointer_map[MAX_BUTTONS+1][MAX_BUTTON_EVENTS];
...@@ -674,6 +671,10 @@ void pointer(int mask, int x, int y, rfbClientPtr client) { ...@@ -674,6 +671,10 @@ void pointer(int mask, int x, int y, rfbClientPtr client) {
int sent = 0, buffer_it = 0; int sent = 0, buffer_it = 0;
double now; double now;
if (threads_drop_input) {
return;
}
if (mask >= 0) { if (mask >= 0) {
got_pointer_calls++; got_pointer_calls++;
} }
...@@ -721,6 +722,8 @@ void pointer(int mask, int x, int y, rfbClientPtr client) { ...@@ -721,6 +722,8 @@ void pointer(int mask, int x, int y, rfbClientPtr client) {
y = nfix(y, dpy_y); y = nfix(y, dpy_y);
} }
INPUT_LOCK;
if ((pipeinput_fh != NULL || pipeinput_int) && mask >= 0) { if ((pipeinput_fh != NULL || pipeinput_int) && mask >= 0) {
pipe_pointer(mask, x, y, client); /* MACOSX here. */ pipe_pointer(mask, x, y, client); /* MACOSX here. */
if (! pipeinput_tee) { if (! pipeinput_tee) {
...@@ -739,11 +742,13 @@ void pointer(int mask, int x, int y, rfbClientPtr client) { ...@@ -739,11 +742,13 @@ void pointer(int mask, int x, int y, rfbClientPtr client) {
if (!view_only && (input.motion || input.button)) { if (!view_only && (input.motion || input.button)) {
last_rfb_ptr_injected = dnow(); last_rfb_ptr_injected = dnow();
} }
INPUT_UNLOCK;
return; return;
} }
} }
if (view_only) { if (view_only) {
INPUT_UNLOCK;
return; return;
} }
...@@ -755,6 +760,7 @@ void pointer(int mask, int x, int y, rfbClientPtr client) { ...@@ -755,6 +760,7 @@ void pointer(int mask, int x, int y, rfbClientPtr client) {
* to flush the event queue; there is no real pointer event. * to flush the event queue; there is no real pointer event.
*/ */
if (! input.motion && ! input.button) { if (! input.motion && ! input.button) {
INPUT_UNLOCK;
return; return;
} }
...@@ -786,6 +792,7 @@ void pointer(int mask, int x, int y, rfbClientPtr client) { ...@@ -786,6 +792,7 @@ void pointer(int mask, int x, int y, rfbClientPtr client) {
blackr[b].x1, blackr[b].y1, blackr[b].x1, blackr[b].y1,
blackr[b].x2, blackr[b].y2); blackr[b].x2, blackr[b].y2);
} }
INPUT_UNLOCK;
return; return;
} }
} }
...@@ -800,18 +807,12 @@ void pointer(int mask, int x, int y, rfbClientPtr client) { ...@@ -800,18 +807,12 @@ void pointer(int mask, int x, int y, rfbClientPtr client) {
if ((use_threads && pointer_mode != 1) || pointer_flush_delay > 0.0) { if ((use_threads && pointer_mode != 1) || pointer_flush_delay > 0.0) {
# define NEV 32 # define NEV 32
/* storage for the event queue */ /* storage for the event queue */
static int mutex_init = 0;
static int nevents = 0; static int nevents = 0;
static int ev[NEV][3]; static int ev[NEV][3];
int i; int i;
/* timer things */ /* timer things */
static double dt = 0.0, tmr = 0.0, maxwait = 0.4; static double dt = 0.0, tmr = 0.0, maxwait = 0.4;
if (! mutex_init) {
INIT_MUTEX(pointerMutex);
mutex_init = 1;
}
if (pointer_flush_delay > 0.0) { if (pointer_flush_delay > 0.0) {
maxwait = pointer_flush_delay; maxwait = pointer_flush_delay;
} }
...@@ -821,7 +822,7 @@ void pointer(int mask, int x, int y, rfbClientPtr client) { ...@@ -821,7 +822,7 @@ void pointer(int mask, int x, int y, rfbClientPtr client) {
} }
} }
LOCK(pointerMutex); POINTER_LOCK;
/* /*
* If the framebuffer is being copied in another thread * If the framebuffer is being copied in another thread
...@@ -856,11 +857,12 @@ void pointer(int mask, int x, int y, rfbClientPtr client) { ...@@ -856,11 +857,12 @@ void pointer(int mask, int x, int y, rfbClientPtr client) {
ev[i][1] = -1; ev[i][1] = -1;
ev[i][2] = -1; ev[i][2] = -1;
} }
UNLOCK(pointerMutex);
if (debug_pointer) { if (debug_pointer) {
rfbLog("pointer(): deferring event %d" rfbLog("pointer(): deferring event %d"
" %.4f\n", i, tmr - x11vnc_start); " %.4f\n", i, tmr - x11vnc_start);
} }
POINTER_UNLOCK;
INPUT_UNLOCK;
return; return;
} }
} }
...@@ -912,13 +914,14 @@ void pointer(int mask, int x, int y, rfbClientPtr client) { ...@@ -912,13 +914,14 @@ void pointer(int mask, int x, int y, rfbClientPtr client) {
dt = 0.0; dt = 0.0;
dtime0(&tmr); dtime0(&tmr);
UNLOCK(pointerMutex); POINTER_UNLOCK;
} }
if (mask < 0) { /* -1 just means flush the event queue */ if (mask < 0) { /* -1 just means flush the event queue */
if (debug_pointer) { if (debug_pointer) {
rfbLog("pointer(): flush only. %.4f\n", rfbLog("pointer(): flush only. %.4f\n",
dnowx()); dnowx());
} }
INPUT_UNLOCK;
return; return;
} }
...@@ -955,6 +958,7 @@ void pointer(int mask, int x, int y, rfbClientPtr client) { ...@@ -955,6 +958,7 @@ void pointer(int mask, int x, int y, rfbClientPtr client) {
XFlush_wr(dpy); XFlush_wr(dpy);
X_UNLOCK; X_UNLOCK;
} }
INPUT_UNLOCK;
} }
void initialize_pipeinput(void) { void initialize_pipeinput(void) {
......
...@@ -484,6 +484,7 @@ void http_connections(int on) { ...@@ -484,6 +484,7 @@ void http_connections(int on) {
if (screen->httpPort == 0) { if (screen->httpPort == 0) {
int port = find_free_port(5800, 5850); int port = find_free_port(5800, 5850);
if (port) { if (port) {
/* mutex */
screen->httpPort = port; screen->httpPort = port;
} }
} }
...@@ -517,6 +518,7 @@ static void reset_httpport(int old, int new) { ...@@ -517,6 +518,7 @@ static void reset_httpport(int old, int new) {
rfbLog("reset_httpport: cannot set httpport: %d" rfbLog("reset_httpport: cannot set httpport: %d"
" in inetd.\n", hp); " in inetd.\n", hp);
} else if (screen) { } else if (screen) {
/* mutex */
screen->httpPort = hp; screen->httpPort = hp;
screen->httpInitDone = FALSE; screen->httpInitDone = FALSE;
if (screen->httpListenSock > -1) { if (screen->httpListenSock > -1) {
...@@ -544,6 +546,7 @@ static void reset_rfbport(int old, int new) { ...@@ -544,6 +546,7 @@ static void reset_rfbport(int old, int new) {
rfbClientIteratorPtr iter; rfbClientIteratorPtr iter;
rfbClientPtr cl; rfbClientPtr cl;
int maxfd; int maxfd;
/* mutex */
if (rp == 0) { if (rp == 0) {
screen->autoPort = TRUE; screen->autoPort = TRUE;
} else { } else {
...@@ -655,7 +658,9 @@ int remote_control_access_ok(void) { ...@@ -655,7 +658,9 @@ int remote_control_access_ok(void) {
} }
} }
X_LOCK;
xha = XListHosts(dpy, &n, &enabled); xha = XListHosts(dpy, &n, &enabled);
X_UNLOCK;
if (! enabled) { if (! enabled) {
rfbLog("X access control is disabled, X clients can\n"); rfbLog("X access control is disabled, X clients can\n");
rfbLog(" connect from any host. Run 'xhost -'\n"); rfbLog(" connect from any host. Run 'xhost -'\n");
...@@ -1055,6 +1060,13 @@ char *process_remote_cmd(char *cmd, int stringonly) { ...@@ -1055,6 +1060,13 @@ char *process_remote_cmd(char *cmd, int stringonly) {
close_clients(p); close_clients(p);
goto done; goto done;
} }
if (strstr(p, "id_cmd") == p) {
NOTAPP
COLON_CHECK("id_cmd:")
p += strlen("id_cmd:");
id_cmd(p);
goto done;
}
if (strstr(p, "id") == p) { if (strstr(p, "id") == p) {
int ok = 0; int ok = 0;
Window twin; Window twin;
...@@ -1465,6 +1477,7 @@ char *process_remote_cmd(char *cmd, int stringonly) { ...@@ -1465,6 +1477,7 @@ char *process_remote_cmd(char *cmd, int stringonly) {
rfbLog("remote_cmd: enable sharing.\n"); rfbLog("remote_cmd: enable sharing.\n");
shared = 1; shared = 1;
if (screen) { if (screen) {
/* mutex */
screen->alwaysShared = TRUE; screen->alwaysShared = TRUE;
screen->neverShared = FALSE; screen->neverShared = FALSE;
} }
...@@ -1477,6 +1490,7 @@ char *process_remote_cmd(char *cmd, int stringonly) { ...@@ -1477,6 +1490,7 @@ char *process_remote_cmd(char *cmd, int stringonly) {
rfbLog("remote_cmd: disable sharing.\n"); rfbLog("remote_cmd: disable sharing.\n");
shared = 0; shared = 0;
if (screen) { if (screen) {
/* mutex */
screen->alwaysShared = FALSE; screen->alwaysShared = FALSE;
screen->neverShared = TRUE; screen->neverShared = TRUE;
} }
...@@ -1562,6 +1576,7 @@ char *process_remote_cmd(char *cmd, int stringonly) { ...@@ -1562,6 +1576,7 @@ char *process_remote_cmd(char *cmd, int stringonly) {
} }
if (! screen->permitFileTransfer) { if (! screen->permitFileTransfer) {
rfbLog("remote_cmd: enabling -ultrafilexfer for clients.\n"); rfbLog("remote_cmd: enabling -ultrafilexfer for clients.\n");
/* mutex */
screen->permitFileTransfer = TRUE; screen->permitFileTransfer = TRUE;
} }
goto done; goto done;
...@@ -1577,6 +1592,7 @@ char *process_remote_cmd(char *cmd, int stringonly) { ...@@ -1577,6 +1592,7 @@ char *process_remote_cmd(char *cmd, int stringonly) {
} }
if (screen->permitFileTransfer) { if (screen->permitFileTransfer) {
rfbLog("remote_cmd: disabling -ultrafilexfer for clients.\n"); rfbLog("remote_cmd: disabling -ultrafilexfer for clients.\n");
/* mutex */
screen->permitFileTransfer = FALSE; screen->permitFileTransfer = FALSE;
} }
goto done; goto done;
...@@ -1595,6 +1611,7 @@ char *process_remote_cmd(char *cmd, int stringonly) { ...@@ -1595,6 +1611,7 @@ char *process_remote_cmd(char *cmd, int stringonly) {
p += strlen("rfbversion:"); p += strlen("rfbversion:");
if (sscanf(p, "%d.%d", &maj, &min) == 2) { if (sscanf(p, "%d.%d", &maj, &min) == 2) {
/* mutex */
screen->protocolMajorVersion = maj; screen->protocolMajorVersion = maj;
screen->protocolMinorVersion = min; screen->protocolMinorVersion = min;
rfbLog("remote_cmd: set rfbversion to: %d.%d\n", maj, min); rfbLog("remote_cmd: set rfbversion to: %d.%d\n", maj, min);
...@@ -1766,6 +1783,7 @@ char *process_remote_cmd(char *cmd, int stringonly) { ...@@ -1766,6 +1783,7 @@ char *process_remote_cmd(char *cmd, int stringonly) {
} }
listen_str = strdup("localhost"); listen_str = strdup("localhost");
/* mutex */
screen->listenInterface = htonl(INADDR_LOOPBACK); screen->listenInterface = htonl(INADDR_LOOPBACK);
rfbLog("listening on loopback network only.\n"); rfbLog("listening on loopback network only.\n");
rfbLog("allow list is: '%s'\n", NONUL(allow_list)); rfbLog("allow list is: '%s'\n", NONUL(allow_list));
...@@ -1813,6 +1831,7 @@ char *process_remote_cmd(char *cmd, int stringonly) { ...@@ -1813,6 +1831,7 @@ char *process_remote_cmd(char *cmd, int stringonly) {
} }
listen_str = NULL; listen_str = NULL;
/* mutex */
screen->listenInterface = htonl(INADDR_ANY); screen->listenInterface = htonl(INADDR_ANY);
rfbLog("listening on ALL network interfaces.\n"); rfbLog("listening on ALL network interfaces.\n");
rfbLog("allow list is: '%s'\n", NONUL(allow_list)); rfbLog("allow list is: '%s'\n", NONUL(allow_list));
...@@ -1853,6 +1872,7 @@ char *process_remote_cmd(char *cmd, int stringonly) { ...@@ -1853,6 +1872,7 @@ char *process_remote_cmd(char *cmd, int stringonly) {
} }
ok = 1; ok = 1;
/* mutex */
if (listen_str == NULL || *listen_str == '\0' || if (listen_str == NULL || *listen_str == '\0' ||
!strcmp(listen_str, "any")) { !strcmp(listen_str, "any")) {
screen->listenInterface = htonl(INADDR_ANY); screen->listenInterface = htonl(INADDR_ANY);
...@@ -4134,6 +4154,7 @@ char *process_remote_cmd(char *cmd, int stringonly) { ...@@ -4134,6 +4154,7 @@ char *process_remote_cmd(char *cmd, int stringonly) {
} }
#endif #endif
} else { } else {
X_LOCK;
if (down == -1) { if (down == -1) {
XTestFakeKeyEvent_wr(dpy, kc, 1, CurrentTime); XTestFakeKeyEvent_wr(dpy, kc, 1, CurrentTime);
usleep(50*1000); usleep(50*1000);
...@@ -4141,6 +4162,7 @@ char *process_remote_cmd(char *cmd, int stringonly) { ...@@ -4141,6 +4162,7 @@ char *process_remote_cmd(char *cmd, int stringonly) {
} else { } else {
XTestFakeKeyEvent_wr(dpy, kc, down, CurrentTime); XTestFakeKeyEvent_wr(dpy, kc, down, CurrentTime);
} }
X_UNLOCK;
} }
goto done; goto done;
} }
...@@ -4340,8 +4362,9 @@ char *process_remote_cmd(char *cmd, int stringonly) { ...@@ -4340,8 +4362,9 @@ char *process_remote_cmd(char *cmd, int stringonly) {
rfbLog("bcx_xattach: failed grab check for '%s': %s. Retrying[%d]...\n", p, res, try); rfbLog("bcx_xattach: failed grab check for '%s': %s. Retrying[%d]...\n", p, res, try);
free(res); free(res);
pointer(0, dpy_x/2 + try, dpy_y/2 + try, NULL); pointer(0, dpy_x/2 + try, dpy_y/2 + try, NULL);
XFlush_wr(dpy);
#if !NO_X11 #if !NO_X11
X_LOCK;
XFlush_wr(dpy);
if (dpy) { if (dpy) {
if (try == 2) { if (try == 2) {
XSync(dpy, False); XSync(dpy, False);
...@@ -4349,6 +4372,7 @@ char *process_remote_cmd(char *cmd, int stringonly) { ...@@ -4349,6 +4372,7 @@ char *process_remote_cmd(char *cmd, int stringonly) {
XSync(dpy, True); XSync(dpy, True);
} }
} }
X_UNLOCK;
#endif #endif
if (try == 1) { if (try == 1) {
usleep(250*1000); usleep(250*1000);
...@@ -4382,6 +4406,7 @@ char *process_remote_cmd(char *cmd, int stringonly) { ...@@ -4382,6 +4406,7 @@ char *process_remote_cmd(char *cmd, int stringonly) {
if (d < 0) d = 0; if (d < 0) d = 0;
rfbLog("remote_cmd: setting defer to %d ms.\n", d); rfbLog("remote_cmd: setting defer to %d ms.\n", d);
defer_update = d; defer_update = d;
/* mutex */
screen->deferUpdateTime = d; screen->deferUpdateTime = d;
got_defer = 1; got_defer = 1;
goto done; goto done;
...@@ -4403,6 +4428,7 @@ char *process_remote_cmd(char *cmd, int stringonly) { ...@@ -4403,6 +4428,7 @@ char *process_remote_cmd(char *cmd, int stringonly) {
if (d < 0) d = 0; if (d < 0) d = 0;
rfbLog("remote_cmd: setting defer to %d ms.\n", d); rfbLog("remote_cmd: setting defer to %d ms.\n", d);
defer_update = d; defer_update = d;
/* mutex */
screen->deferUpdateTime = d; screen->deferUpdateTime = d;
got_defer = 1; got_defer = 1;
goto done; goto done;
...@@ -4907,6 +4933,7 @@ char *process_remote_cmd(char *cmd, int stringonly) { ...@@ -4907,6 +4933,7 @@ char *process_remote_cmd(char *cmd, int stringonly) {
if (f < 0) f = 0; if (f < 0) f = 0;
rfbLog("remote_cmd: setting progressive %d -> %d.\n", rfbLog("remote_cmd: setting progressive %d -> %d.\n",
screen->progressiveSliceHeight, f); screen->progressiveSliceHeight, f);
/* mutex */
screen->progressiveSliceHeight = f; screen->progressiveSliceHeight = f;
goto done; goto done;
} }
...@@ -4995,6 +5022,7 @@ char *process_remote_cmd(char *cmd, int stringonly) { ...@@ -4995,6 +5022,7 @@ char *process_remote_cmd(char *cmd, int stringonly) {
goto qry; goto qry;
} }
rfbLog("turning on enablehttpproxy.\n"); rfbLog("turning on enablehttpproxy.\n");
/* mutex */
screen->httpEnableProxyConnect = 1; screen->httpEnableProxyConnect = 1;
goto done; goto done;
} }
...@@ -5081,6 +5109,7 @@ char *process_remote_cmd(char *cmd, int stringonly) { ...@@ -5081,6 +5109,7 @@ char *process_remote_cmd(char *cmd, int stringonly) {
free(rfb_desktop_name); free(rfb_desktop_name);
} }
rfb_desktop_name = strdup(p); rfb_desktop_name = strdup(p);
/* mutex */
screen->desktopName = rfb_desktop_name; screen->desktopName = rfb_desktop_name;
rfbLog("remote_cmd: setting desktop name to %s\n", rfbLog("remote_cmd: setting desktop name to %s\n",
rfb_desktop_name); rfb_desktop_name);
...@@ -5449,6 +5478,7 @@ char *process_remote_cmd(char *cmd, int stringonly) { ...@@ -5449,6 +5478,7 @@ char *process_remote_cmd(char *cmd, int stringonly) {
passwds_new[0] = strdup(p); passwds_new[0] = strdup(p);
/* mutex */
if (screen->authPasswdData && if (screen->authPasswdData &&
screen->passwordCheck == rfbCheckPasswordByList) { screen->passwordCheck == rfbCheckPasswordByList) {
passwds_new[1] = passwds_old[1]; passwds_new[1] = passwds_old[1];
...@@ -5984,8 +6014,10 @@ char *process_remote_cmd(char *cmd, int stringonly) { ...@@ -5984,8 +6014,10 @@ char *process_remote_cmd(char *cmd, int stringonly) {
} }
} else { } else {
if (dpy) { /* raw_fb hack */ if (dpy) { /* raw_fb hack */
X_LOCK;
set_x11vnc_remote_prop(buf); set_x11vnc_remote_prop(buf);
XFlush_wr(dpy); XFlush_wr(dpy);
X_UNLOCK;
} }
} }
#endif /* REMOTE_CONTROL */ #endif /* REMOTE_CONTROL */
......
This diff is collapsed.
...@@ -2666,8 +2666,8 @@ void check_https(void) { ...@@ -2666,8 +2666,8 @@ void check_https(void) {
} }
void openssl_port(void) { void openssl_port(void) {
int sock, shutdown = 0; int sock = -1, shutdown = 0;
static int port = 0; static int port = -1;
static in_addr_t iface = INADDR_ANY; static in_addr_t iface = INADDR_ANY;
int db = 0; int db = 0;
...@@ -2683,6 +2683,8 @@ void openssl_port(void) { ...@@ -2683,6 +2683,8 @@ void openssl_port(void) {
if (screen->listenSock > -1 && screen->port > 0) { if (screen->listenSock > -1 && screen->port > 0) {
port = screen->port; port = screen->port;
shutdown = 1; shutdown = 1;
} else if (screen->port == 0) {
port = screen->port;
} }
if (screen->listenInterface) { if (screen->listenInterface) {
iface = screen->listenInterface; iface = screen->listenInterface;
...@@ -2696,14 +2698,18 @@ void openssl_port(void) { ...@@ -2696,14 +2698,18 @@ void openssl_port(void) {
#endif #endif
} }
if (port <= 0) { if (port < 0) {
rfbLog("openssl_port: could not obtain listening port %d\n", port); rfbLog("openssl_port: could not obtain listening port %d\n", port);
clean_up_exit(1); clean_up_exit(1);
} } else if (port == 0) {
sock = rfbListenOnTCPPort(port, iface); /* no listen case, i.e. -connect */
if (sock < 0) { sock = -1;
rfbLog("openssl_port: could not reopen port %d\n", port); } else {
clean_up_exit(1); sock = rfbListenOnTCPPort(port, iface);
if (sock < 0) {
rfbLog("openssl_port: could not reopen port %d\n", port);
clean_up_exit(1);
}
} }
rfbLog("openssl_port: listen on port/sock %d/%d\n", port, sock); rfbLog("openssl_port: listen on port/sock %d/%d\n", port, sock);
if (!quiet) { if (!quiet) {
...@@ -3852,6 +3858,7 @@ void accept_openssl(int mode, int presock) { ...@@ -3852,6 +3858,7 @@ void accept_openssl(int mode, int presock) {
if (screen->port == 0) { if (screen->port == 0) {
int fd = fileno(stdin); int fd = fileno(stdin);
if (getenv("X11VNC_INETD_PORT")) { if (getenv("X11VNC_INETD_PORT")) {
/* mutex */
screen->port = atoi(getenv( screen->port = atoi(getenv(
"X11VNC_INETD_PORT")); "X11VNC_INETD_PORT"));
} else { } else {
......
...@@ -176,6 +176,7 @@ Screen ...@@ -176,6 +176,7 @@ Screen
=GAL SubWindow:: =GAL SubWindow::
id: id:
sid: sid:
=RA id_cmd:
=GAL LOFF =GAL LOFF
=GAL ResizeRotate:: =GAL ResizeRotate::
= xrandr = xrandr
......
...@@ -187,6 +187,7 @@ char gui_code[] = ""; ...@@ -187,6 +187,7 @@ char gui_code[] = "";
" =GAL SubWindow::\n" " =GAL SubWindow::\n"
" id:\n" " id:\n"
" sid:\n" " sid:\n"
" =RA id_cmd:\n"
" =GAL LOFF\n" " =GAL LOFF\n"
" =GAL ResizeRotate::\n" " =GAL ResizeRotate::\n"
" = xrandr\n" " = xrandr\n"
......
...@@ -2033,6 +2033,7 @@ void unixpw_accept(char *user) { ...@@ -2033,6 +2033,7 @@ void unixpw_accept(char *user) {
unixpw_client->viewOnly = TRUE; unixpw_client->viewOnly = TRUE;
} }
unixpw_in_progress = 0; unixpw_in_progress = 0;
/* mutex */
screen->permitFileTransfer = unixpw_file_xfer_save; screen->permitFileTransfer = unixpw_file_xfer_save;
if ((tightfilexfer = unixpw_tightvnc_xfer_save)) { if ((tightfilexfer = unixpw_tightvnc_xfer_save)) {
/* this doesn't work: the current client is never registered! */ /* this doesn't work: the current client is never registered! */
...@@ -2078,6 +2079,7 @@ void unixpw_deny(void) { ...@@ -2078,6 +2079,7 @@ void unixpw_deny(void) {
} }
unixpw_in_progress = 0; unixpw_in_progress = 0;
/* mutex */
screen->permitFileTransfer = unixpw_file_xfer_save; screen->permitFileTransfer = unixpw_file_xfer_save;
if ((tightfilexfer = unixpw_tightvnc_xfer_save)) { if ((tightfilexfer = unixpw_tightvnc_xfer_save)) {
#ifdef LIBVNCSERVER_WITH_TIGHTVNC_FILETRANSFER #ifdef LIBVNCSERVER_WITH_TIGHTVNC_FILETRANSFER
......
...@@ -1085,6 +1085,7 @@ void install_passwds(void) { ...@@ -1085,6 +1085,7 @@ void install_passwds(void) {
passwds_new[0] = passwds_old[0]; passwds_new[0] = passwds_old[0];
passwds_new[1] = viewonly_passwd; passwds_new[1] = viewonly_passwd;
passwds_new[2] = NULL; passwds_new[2] = NULL;
/* mutex */
screen->authPasswdData = (void*) passwds_new; screen->authPasswdData = (void*) passwds_new;
} else if (passwd_list) { } else if (passwd_list) {
int i = 0; int i = 0;
...@@ -1094,6 +1095,7 @@ void install_passwds(void) { ...@@ -1094,6 +1095,7 @@ void install_passwds(void) {
if (begin_viewonly < 0) { if (begin_viewonly < 0) {
begin_viewonly = i+1; begin_viewonly = i+1;
} }
/* mutex */
screen->authPasswdData = (void*) passwd_list; screen->authPasswdData = (void*) passwd_list;
screen->authPasswdFirstViewOnly = begin_viewonly; screen->authPasswdFirstViewOnly = begin_viewonly;
} }
...@@ -1167,6 +1169,7 @@ static void handle_one_http_request(void) { ...@@ -1167,6 +1169,7 @@ static void handle_one_http_request(void) {
if (inetd || screen->httpPort == 0) { if (inetd || screen->httpPort == 0) {
int port = find_free_port(5800, 5860); int port = find_free_port(5800, 5860);
if (port) { if (port) {
/* mutex */
screen->httpPort = port; screen->httpPort = port;
} else { } else {
rfbLog("handle_one_http_request: no http port.\n"); rfbLog("handle_one_http_request: no http port.\n");
...@@ -1703,6 +1706,7 @@ static void vnc_redirect_loop(char *vnc_redirect_test, int *vnc_redirect_cnt) { ...@@ -1703,6 +1706,7 @@ static void vnc_redirect_loop(char *vnc_redirect_test, int *vnc_redirect_cnt) {
#if LIBVNCSERVER_HAVE_FORK #if LIBVNCSERVER_HAVE_FORK
if ((pid = fork()) > 0) { if ((pid = fork()) > 0) {
close(screen->httpListenSock); close(screen->httpListenSock);
/* mutex */
screen->httpListenSock = -2; screen->httpListenSock = -2;
usleep(500 * 1000); usleep(500 * 1000);
} else { } else {
......
...@@ -373,6 +373,7 @@ static void parse_wireframe_str(char *wf) { ...@@ -373,6 +373,7 @@ static void parse_wireframe_str(char *wf) {
Colormap cmap; Colormap cmap;
if (dpy && (bpp == 32 || bpp == 16)) { if (dpy && (bpp == 32 || bpp == 16)) {
#if !NO_X11 #if !NO_X11
X_LOCK;
cmap = DefaultColormap (dpy, scr); cmap = DefaultColormap (dpy, scr);
if (XParseColor(dpy, cmap, str, &cdef) && if (XParseColor(dpy, cmap, str, &cdef) &&
XAllocColor(dpy, cmap, &cdef)) { XAllocColor(dpy, cmap, &cdef)) {
...@@ -389,6 +390,7 @@ static void parse_wireframe_str(char *wf) { ...@@ -389,6 +390,7 @@ static void parse_wireframe_str(char *wf) {
wireframe_shade = n; wireframe_shade = n;
ok = 1; ok = 1;
} }
X_UNLOCK;
#else #else
r = g = b = 0; r = g = b = 0;
cmap = 0; cmap = 0;
......
...@@ -471,6 +471,7 @@ double rfac(void) { ...@@ -471,6 +471,7 @@ double rfac(void) {
void check_allinput_rate(void) { void check_allinput_rate(void) {
static double last_all_input_check = 0.0; static double last_all_input_check = 0.0;
static int set = 0, verb = -1; static int set = 0, verb = -1;
if (use_threads) { if (use_threads) {
return; return;
} }
...@@ -703,7 +704,7 @@ double rect_overlap(int x1, int y1, int x2, int y2, int X1, int Y1, ...@@ -703,7 +704,7 @@ double rect_overlap(int x1, int y1, int x2, int y2, int X1, int Y1,
char *choose_title(char *display) { char *choose_title(char *display) {
static char title[(MAXN+10)]; static char title[(MAXN+10)];
memset(title, 0, MAXN+10); memset(title, 0, sizeof(title));
strcpy(title, "x11vnc"); strcpy(title, "x11vnc");
if (display == NULL) { if (display == NULL) {
...@@ -724,13 +725,33 @@ char *choose_title(char *display) { ...@@ -724,13 +725,33 @@ char *choose_title(char *display) {
if (subwin && dpy && valid_window(subwin, NULL, 0)) { if (subwin && dpy && valid_window(subwin, NULL, 0)) {
#if !NO_X11 #if !NO_X11
char *name = NULL; char *name = NULL;
int do_appshare = getenv("X11VNC_APPSHARE_ACTIVE") ? 1 : 0;
if (0 && do_appshare) {
title[0] = '\0';
}
if (XFetchName(dpy, subwin, &name)) { if (XFetchName(dpy, subwin, &name)) {
if (name) { if (name) {
strncat(title, " ", MAXN - strlen(title)); if (title[0] != '\0') {
strncat(title, " ", MAXN - strlen(title));
}
strncat(title, name, MAXN - strlen(title)); strncat(title, name, MAXN - strlen(title));
free(name); free(name);
} }
} }
if (do_appshare) {
Window c;
int x, y;
if (xtranslate(subwin, rootwin, 0, 0, &x, &y, &c, 1)) {
char tmp[32];
if (scaling) {
x *= scale_fac_x;
y *= scale_fac_y;
}
sprintf(tmp, " XY=%d,%d", x, y);
strncat(title, tmp, MAXN - strlen(title));
}
rfbLog("appshare title: %s\n", title);
}
#endif /* NO_X11 */ #endif /* NO_X11 */
} }
X_UNLOCK; X_UNLOCK;
......
...@@ -72,6 +72,11 @@ extern char *choose_title(char *display); ...@@ -72,6 +72,11 @@ extern char *choose_title(char *display);
#define NONUL(x) ((x) ? (x) : "") #define NONUL(x) ((x) ? (x) : "")
/*
Put this in usleep2() for debug printout.
fprintf(stderr, "_mysleep: %08d %10.6f %s:%d\n", (x), dnow() - x11vnc_start, __FILE__, __LINE__); \
*/
/* XXX usleep(3) is not thread safe on some older systems... */ /* XXX usleep(3) is not thread safe on some older systems... */
extern struct timeval _mysleep; extern struct timeval _mysleep;
#define usleep2(x) \ #define usleep2(x) \
...@@ -96,6 +101,10 @@ extern struct timeval _mysleep; ...@@ -96,6 +101,10 @@ extern struct timeval _mysleep;
*/ */
#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD #ifdef LIBVNCSERVER_HAVE_LIBPTHREAD
extern MUTEX(x11Mutex); extern MUTEX(x11Mutex);
extern MUTEX(scrollMutex);
MUTEX(clientMutex);
MUTEX(inputMutex);
MUTEX(pointerMutex);
#endif #endif
#define X_INIT INIT_MUTEX(x11Mutex) #define X_INIT INIT_MUTEX(x11Mutex)
...@@ -105,26 +114,33 @@ extern MUTEX(x11Mutex); ...@@ -105,26 +114,33 @@ extern MUTEX(x11Mutex);
#define X_UNLOCK UNLOCK(x11Mutex) #define X_UNLOCK UNLOCK(x11Mutex)
#else #else
extern int hxl; extern int hxl;
#define X_LOCK fprintf(stderr, "*** X_LOCK**[%05d] %d%s\n", \ #define X_LOCK fprintf(stderr, "*** X_LOCK** %d%s %s:%d\n", \
__LINE__, hxl, hxl ? " BAD-PRE-LOCK":""); LOCK(x11Mutex); hxl = 1; hxl, hxl ? " BAD-PRE-LOCK":"", __FILE__, __LINE__); LOCK(x11Mutex); hxl = 1;
#define X_UNLOCK fprintf(stderr, " x_unlock[%05d] %d%s\n", \ #define X_UNLOCK fprintf(stderr, " x_unlock %d%s %s:%d\n", \
__LINE__, hxl, !hxl ? " BAD-PRE-UNLOCK":""); UNLOCK(x11Mutex); hxl = 0; hxl, !hxl ? " BAD-PRE-UNLOCK":"", __FILE__, __LINE__); UNLOCK(x11Mutex); hxl = 0;
#endif #endif
#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD
extern MUTEX(scrollMutex);
#endif
#define SCR_LOCK if (use_threads) {LOCK(scrollMutex);} #define SCR_LOCK if (use_threads) {LOCK(scrollMutex);}
#define SCR_UNLOCK if (use_threads) {UNLOCK(scrollMutex);} #define SCR_UNLOCK if (use_threads) {UNLOCK(scrollMutex);}
#define SCR_INIT INIT_MUTEX(scrollMutex) #define SCR_INIT INIT_MUTEX(scrollMutex)
#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD
MUTEX(clientMutex);
#endif
#define CLIENT_LOCK if (use_threads) {LOCK(clientMutex);} #define CLIENT_LOCK if (use_threads) {LOCK(clientMutex);}
#define CLIENT_UNLOCK if (use_threads) {UNLOCK(clientMutex);} #define CLIENT_UNLOCK if (use_threads) {UNLOCK(clientMutex);}
#define CLIENT_INIT INIT_MUTEX(clientMutex) #define CLIENT_INIT INIT_MUTEX(clientMutex)
#if 1
#define INPUT_LOCK if (use_threads) {LOCK(inputMutex);}
#define INPUT_UNLOCK if (use_threads) {UNLOCK(inputMutex);}
#else
#define INPUT_LOCK
#define INPUT_UNLOCK
#endif
#define INPUT_INIT INIT_MUTEX(inputMutex)
#define POINTER_LOCK if (use_threads) {LOCK(pointerMutex);}
#define POINTER_UNLOCK if (use_threads) {UNLOCK(pointerMutex);}
#define POINTER_INIT INIT_MUTEX(pointerMutex)
/* /*
* The sendMutex member was added to libvncserver 0.9.8 * The sendMutex member was added to libvncserver 0.9.8
* rfb/rfb.h sets LIBVNCSERVER_SEND_MUTEX if present. * rfb/rfb.h sets LIBVNCSERVER_SEND_MUTEX if present.
......
...@@ -38,6 +38,7 @@ so, delete this exception statement from your version. ...@@ -38,6 +38,7 @@ so, delete this exception statement from your version.
#include "cleanup.h" #include "cleanup.h"
#include "xwrappers.h" #include "xwrappers.h"
#include "connections.h" #include "connections.h"
#include "xrandr.h"
#include "macosx.h" #include "macosx.h"
winattr_t *stack_list = NULL; winattr_t *stack_list = NULL;
...@@ -49,7 +50,7 @@ Window parent_window(Window win, char **name); ...@@ -49,7 +50,7 @@ Window parent_window(Window win, char **name);
int valid_window(Window win, XWindowAttributes *attr_ret, int bequiet); int valid_window(Window win, XWindowAttributes *attr_ret, int bequiet);
Bool xtranslate(Window src, Window dst, int src_x, int src_y, int *dst_x, Bool xtranslate(Window src, Window dst, int src_x, int src_y, int *dst_x,
int *dst_y, Window *child, int bequiet); int *dst_y, Window *child, int bequiet);
int get_window_size(Window win, int *x, int *y); int get_window_size(Window win, int *w, int *h);
void snapshot_stack_list(int free_only, double allowed_age); void snapshot_stack_list(int free_only, double allowed_age);
int get_boff(void); int get_boff(void);
int get_bwin(void); int get_bwin(void);
...@@ -58,6 +59,7 @@ Window query_pointer(Window start); ...@@ -58,6 +59,7 @@ Window query_pointer(Window start);
unsigned int mask_state(void); unsigned int mask_state(void);
int pick_windowid(unsigned long *num); int pick_windowid(unsigned long *num);
Window descend_pointer(int depth, Window start, char *name_info, int len); Window descend_pointer(int depth, Window start, char *name_info, int len);
void id_cmd(char *cmd);
Window parent_window(Window win, char **name) { Window parent_window(Window win, char **name) {
...@@ -184,12 +186,12 @@ Bool xtranslate(Window src, Window dst, int src_x, int src_y, int *dst_x, ...@@ -184,12 +186,12 @@ Bool xtranslate(Window src, Window dst, int src_x, int src_y, int *dst_x,
#endif /* NO_X11 */ #endif /* NO_X11 */
} }
int get_window_size(Window win, int *x, int *y) { int get_window_size(Window win, int *w, int *h) {
XWindowAttributes attr; XWindowAttributes attr;
/* valid_window? */ /* valid_window? */
if (valid_window(win, &attr, 1)) { if (valid_window(win, &attr, 1)) {
*x = attr.width; *w = attr.width;
*y = attr.height; *h = attr.height;
return 1; return 1;
} else { } else {
return 0; return 0;
...@@ -609,3 +611,161 @@ Window descend_pointer(int depth, Window start, char *name_info, int len) { ...@@ -609,3 +611,161 @@ Window descend_pointer(int depth, Window start, char *name_info, int len) {
#endif /* NO_X11 */ #endif /* NO_X11 */
} }
void id_cmd(char *cmd) {
int rc, dx = 0, dy = 0, dw = 0, dh = 0;
int x0, y0, w0, h0;
int x, y, w, h, do_move = 0, do_resize = 0;
int disp_x = DisplayWidth(dpy, scr);
int disp_y = DisplayHeight(dpy, scr);
Window win = subwin;
XWindowAttributes attr;
XErrorHandler old_handler = NULL;
Window twin;
if (!cmd || !strcmp(cmd, "")) {
return;
}
if (strstr(cmd, "win=") == cmd) {
if (! scan_hexdec(cmd + strlen("win="), &win)) {
rfbLog("id_cmd: incorrect win= hex/dec number: %s\n", cmd);
return;
} else {
char *q = strchr(cmd, ':');
if (!q) {
rfbLog("id_cmd: incorrect win=...: hex/dec number: %s\n", cmd);
return;
}
rfbLog("id_cmd:%s set window id to 0x%lx\n", cmd, win);
cmd = q+1;
}
}
if (!win) {
rfbLog("id_cmd:%s not in sub-window mode or no win=0xNNNN.\n", cmd);
return;
}
#if !NO_X11
X_LOCK;
if (!valid_window(win, &attr, 1)) {
X_UNLOCK;
return;
}
w0 = w = attr.width;
h0 = h = attr.height;
old_handler = XSetErrorHandler(trap_xerror);
trapped_xerror = 0;
XTranslateCoordinates(dpy, win, rootwin, 0, 0, &x, &y, &twin);
x0 = x;
y0 = y;
if (strstr(cmd, "move:") == cmd) {
if (sscanf(cmd, "move:%d%d", &dx, &dy) == 2) {
x = x + dx;
y = y + dy;
do_move = 1;
}
} else if (strstr(cmd, "resize:") == cmd) {
if (sscanf(cmd, "resize:%d%d", &dw, &dh) == 2) {
w = w + dw;
h = h + dh;
do_move = 1;
do_resize = 1;
}
} else if (strstr(cmd, "geom:") == cmd) {
if (parse_geom(cmd+strlen("geom:"), &w, &h, &x, &y, disp_x, disp_y)) {
do_move = 1;
do_resize = 1;
if (w <= 0) {
w = w0;
}
if (h <= 0) {
h = h0;
}
if (scaling && getenv("X11VNC_APPSHARE_ACTIVE")) {
x /= scale_fac_x;
y /= scale_fac_y;
}
}
} else if (!strcmp(cmd, "raise")) {
rc = XRaiseWindow(dpy, win);
rfbLog("id_cmd:%s rc=%d\n", cmd, rc);
} else if (!strcmp(cmd, "lower")) {
rc = XLowerWindow(dpy, win);
rfbLog("id_cmd:%s rc=%d\n", cmd, rc);
} else if (!strcmp(cmd, "map")) {
rc= XMapRaised(dpy, win);
rfbLog("id_cmd:%s rc=%d\n", cmd, rc);
} else if (!strcmp(cmd, "unmap")) {
rc= XUnmapWindow(dpy, win);
rfbLog("id_cmd:%s rc=%d\n", cmd, rc);
} else if (!strcmp(cmd, "iconify")) {
rc= XIconifyWindow(dpy, win, scr);
rfbLog("id_cmd:%s rc=%d\n", cmd, rc);
} else if (strstr(cmd, "wm_name:") == cmd) {
rc= XStoreName(dpy, win, cmd+strlen("wm_name:"));
rfbLog("id_cmd:%s rc=%d\n", cmd, rc);
} else if (strstr(cmd, "icon_name:") == cmd) {
rc= XSetIconName(dpy, win, cmd+strlen("icon_name:"));
rfbLog("id_cmd:%s rc=%d\n", cmd, rc);
} else if (!strcmp(cmd, "wm_delete")) {
XClientMessageEvent ev;
memset(&ev, 0, sizeof(ev));
ev.type = ClientMessage;
ev.send_event = True;
ev.display = dpy;
ev.window = win;
ev.message_type = XInternAtom(dpy, "WM_PROTOCOLS", False);
ev.format = 32;
ev.data.l[0] = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
rc = XSendEvent(dpy, win, False, 0, (XEvent *) &ev);
rfbLog("id_cmd:%s rc=%d\n", cmd, rc);
} else {
rfbLog("id_cmd:%s unrecognized command.\n", cmd);
}
if (do_move || do_resize) {
if (w >= disp_x) {
w = disp_x - 4;
}
if (h >= disp_y) {
h = disp_y - 4;
}
if (w < 1) {
w = 1;
}
if (h < 1) {
h = 1;
}
if (x + w > disp_x) {
x = disp_x - w - 1;
}
if (y + h > disp_y) {
y = disp_y - h - 1;
}
if (x < 0) {
x = 1;
}
if (y < 0) {
y = 1;
}
rc = 0;
rc += XMoveWindow(dpy, win, x, y);
off_x = x;
off_y = y;
rc += XResizeWindow(dpy, win, w, h);
rfbLog("id_cmd:%s rc=%d dx=%d dy=%d dw=%d dh=%d %dx%d+%d+%d -> %dx%d+%d+%d\n",
cmd, rc, dx, dy, dw, dh, w0, h0, x0, y0, w, h, x, h);
}
XSync(dpy, False);
XSetErrorHandler(old_handler);
if (trapped_xerror) {
rfbLog("id_cmd:%s trapped_xerror.\n", cmd);
}
trapped_xerror = 0;
if (do_resize) {
rfbLog("id_cmd:%s calling check_xrandr_event.\n", cmd);
check_xrandr_event("id_cmd");
}
X_UNLOCK;
#endif
}
...@@ -45,7 +45,7 @@ extern Window parent_window(Window win, char **name); ...@@ -45,7 +45,7 @@ extern Window parent_window(Window win, char **name);
extern int valid_window(Window win, XWindowAttributes *attr_ret, int bequiet); extern int valid_window(Window win, XWindowAttributes *attr_ret, int bequiet);
extern Bool xtranslate(Window src, Window dst, int src_x, int src_y, int *dst_x, extern Bool xtranslate(Window src, Window dst, int src_x, int src_y, int *dst_x,
int *dst_y, Window *child, int bequiet); int *dst_y, Window *child, int bequiet);
extern int get_window_size(Window win, int *x, int *y); extern int get_window_size(Window win, int *w, int *h);
extern void snapshot_stack_list(int free_only, double allowed_age); extern void snapshot_stack_list(int free_only, double allowed_age);
extern int get_boff(void); extern int get_boff(void);
extern int get_bwin(void); extern int get_bwin(void);
...@@ -54,5 +54,6 @@ extern Window query_pointer(Window start); ...@@ -54,5 +54,6 @@ extern Window query_pointer(Window start);
extern unsigned int mask_state(void); extern unsigned int mask_state(void);
extern int pick_windowid(unsigned long *num); extern int pick_windowid(unsigned long *num);
extern Window descend_pointer(int depth, Window start, char *name_info, int len); extern Window descend_pointer(int depth, Window start, char *name_info, int len);
extern void id_cmd(char *cmd);
#endif /* _X11VNC_WIN_UTILS_H */ #endif /* _X11VNC_WIN_UTILS_H */
.\" This file was automatically generated from x11vnc -help output. .\" This file was automatically generated from x11vnc -help output.
.TH X11VNC "1" "November 2009" "x11vnc " "User Commands" .TH X11VNC "1" "December 2009" "x11vnc " "User Commands"
.SH NAME .SH NAME
x11vnc - allow VNC connections to real X11 displays x11vnc - allow VNC connections to real X11 displays
version: 0.9.9, lastmod: 2009-11-18 version: 0.9.9, lastmod: 2009-12-02
.SH SYNOPSIS .SH SYNOPSIS
.B x11vnc .B x11vnc
[OPTION]... [OPTION]...
...@@ -158,6 +158,15 @@ shifts a root view to it: this shows SaveUnders menus, ...@@ -158,6 +158,15 @@ shifts a root view to it: this shows SaveUnders menus,
etc, although they will be clipped if they extend beyond etc, although they will be clipped if they extend beyond
the window. the window.
.PP .PP
\fB-appshare\fR
.IP
Simple application sharing based on the \fB-id/-sid\fR
mechanism. Every new toplevel window that the
application creates induces a new viewer window via
a reverse connection. The \fB-id/-sid\fR and \fB-connect\fR
options are required. Run 'x11vnc \fB-appshare\fR \fB-help'\fR
for more info.
.PP
\fB-clip\fR \fIWxH+X+Y\fR \fB-clip\fR \fIWxH+X+Y\fR
.IP .IP
Only show the sub-region of the full display that Only show the sub-region of the full display that
...@@ -3110,7 +3119,7 @@ Instead of exiting after cleaning up, run a simple ...@@ -3110,7 +3119,7 @@ Instead of exiting after cleaning up, run a simple
\fB-q,\fR \fB-quiet\fR \fB-q,\fR \fB-quiet\fR
.IP .IP
Be quiet by printing less informational output to Be quiet by printing less informational output to
stderr. stderr. (use \fB-noquiet\fR to undo an earlier \fB-quiet.)\fR
.PP .PP
\fB-v,\fR \fB-verbose\fR \fB-v,\fR \fB-verbose\fR
.IP .IP
...@@ -3611,7 +3620,7 @@ Client-side caching scheme. Framebuffer memory \fIn\fR ...@@ -3611,7 +3620,7 @@ Client-side caching scheme. Framebuffer memory \fIn\fR
(an integer) times that of the full display is allocated (an integer) times that of the full display is allocated
below the actual framebuffer to cache screen contents below the actual framebuffer to cache screen contents
for rapid retrieval. So a W x H frambuffer is expanded 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. to a W x (n+1)*H one. Use 0 to disable.
.IP .IP
The \fIn\fR is actually optional, the default is 10. The \fIn\fR is actually optional, the default is 10.
.IP .IP
...@@ -3619,13 +3628,17 @@ For this and the other \fB-ncache*\fR options below you can ...@@ -3619,13 +3628,17 @@ For this and the other \fB-ncache*\fR options below you can
abbreviate "\fB-ncache\fR" with "\fB-nc\fR". Also, "\fB-nonc\fR" abbreviate "\fB-ncache\fR" with "\fB-nc\fR". Also, "\fB-nonc\fR"
is the same as "\fB-ncache\fR \fI0\fR" is the same as "\fB-ncache\fR \fI0\fR"
.IP .IP
This is an experimental option, currently implemented This is an experimental option, currently implemented in
in an awkward way in that in the VNC Viewer you can an awkward way in that in the VNC Viewer you can see the
see the cache contents if you scroll down, etc. So you pixel cache contents if you scroll down, etc. So you
will have to set things up so you can't see that region. will have to set things up so you can't see that region.
If this method is successful, the changes required for If this method is successful, the changes required for
clients to do this less awkwardly will be investigated. clients to do this less awkwardly will be investigated.
.IP .IP
The SSVNC viewer does a good job at automatically hiding
the pixel cache region. Or use SSVNC's \fB-ycrop\fR option
to explicitly hide the region.
.IP
Note that this mode consumes a huge amount of memory, Note that this mode consumes a huge amount of memory,
both on the x11vnc server side and on the VNC Viewer both on the x11vnc server side and on the VNC Viewer
side. If n=2 then the amount of RAM used is roughly side. If n=2 then the amount of RAM used is roughly
...@@ -4465,10 +4478,7 @@ In this mode new threads (one for input and one ...@@ -4465,10 +4478,7 @@ In this mode new threads (one for input and one
for output) are created to handle each new client. for output) are created to handle each new client.
Default: \fB-nothreads.\fR Default: \fB-nothreads.\fR
.IP .IP
NOTE: The \fB-threads\fR mode may be disabled due to its Thread stability is much improved in version 0.9.8.
unstable behavior. If it is disabled, a warning is
printed out. Stability has been improved in version
0.9.8 and so the feature has been re-enabled.
.IP .IP
Multiple clients in threaded mode should be stable Multiple clients in threaded mode should be stable
for the ZRLE encoding on all platforms. The Tight and for the ZRLE encoding on all platforms. The Tight and
...@@ -4476,9 +4486,14 @@ Zlib encodings are currently only stable on Linux for ...@@ -4476,9 +4486,14 @@ Zlib encodings are currently only stable on Linux for
multiple clients. Compile with \fB-DTLS=__thread\fR if your multiple clients. Compile with \fB-DTLS=__thread\fR if your
OS and compiler and linker support it. OS and compiler and linker support it.
.IP .IP
For resizes (randr, etc.) set this env. var. to the number
of milliseconds to sleep: X11VNC_THREADS_NEW_FB_SLEEP
at various places in the do_new_fb() action. This is to
let various activities settle. Default is about 500ms.
.IP
Multiple clients in threaded mode could yield better Multiple clients in threaded mode could yield better
performance for 'class-room' broadcasting usage. performance for 'class-room' broadcasting usage; also in
See also the \fB-reflect\fR option. \fB-appshare\fR broadcast mode. See also the \fB-reflect\fR option.
.PP .PP
\fB-fs\fR \fIf\fR \fB-fs\fR \fIf\fR
.IP .IP
...@@ -5252,6 +5267,13 @@ or "root" to go back to root window ...@@ -5252,6 +5267,13 @@ or "root" to go back to root window
.IP .IP
sid:windowid set \fB-sid\fR window to "windowid" sid:windowid set \fB-sid\fR window to "windowid"
.IP .IP
id_cmd:cmd cmds: raise, lower, map, unmap, iconify,
move:dXdY, resize:dWdH, geom:WxH+X+Y. dX
dY, dW, and dH must have a leading "+"
or "-" e.g.: move:-30+10 resize:+20+35
also: wm_delete, wm_name:string and
icon_name:string. Also id_cmd:win=N:cmd
.IP
waitmapped wait until subwin is mapped. waitmapped wait until subwin is mapped.
.IP .IP
nowaitmapped do not wait until subwin is mapped. nowaitmapped do not wait until subwin is mapped.
...@@ -6035,8 +6057,8 @@ query straight to the X11VNC_REMOTE property or connect ...@@ -6035,8 +6057,8 @@ query straight to the X11VNC_REMOTE property or connect
file use "qry=..." instead of "cmd=..." file use "qry=..." instead of "cmd=..."
.IP .IP
ans= stop quit exit shutdown ping resend_cutbuffer ans= stop quit exit shutdown ping resend_cutbuffer
resend_clipboard resend_primary blacken zero resend_clipboard resend_primary blacken zero refresh
refresh reset close disconnect id sid waitmapped reset close disconnect id_cmd id sid waitmapped
nowaitmapped clip flashcmap noflashcmap shiftcmap nowaitmapped clip flashcmap noflashcmap shiftcmap
truecolor notruecolor overlay nooverlay overlay_cursor truecolor notruecolor overlay nooverlay overlay_cursor
overlay_yescursor nooverlay_nocursor nooverlay_cursor overlay_yescursor nooverlay_nocursor nooverlay_cursor
...@@ -6185,6 +6207,10 @@ Any corresponding output text for that remote control ...@@ -6185,6 +6207,10 @@ Any corresponding output text for that remote control
command is sent back to all client as rfbCutText. command is sent back to all client as rfbCutText.
The returned output is also prefixed with \fIstr\fR. The returned output is also prefixed with \fIstr\fR.
Example: \fB-remote_prefix\fR DO_THIS: Example: \fB-remote_prefix\fR DO_THIS:
.IP
Note that enabling \fB-remote_prefix\fR allows the remote
VNC viewers to run x11vnc \fB-remote\fR commands. Do not
use this option if they are not to be trusted.
.PP .PP
\fB-noremote,\fR \fB-yesremote\fR \fB-noremote,\fR \fB-yesremote\fR
.IP .IP
......
...@@ -172,6 +172,7 @@ static void check_rcfile(int argc, char **argv); ...@@ -172,6 +172,7 @@ static void check_rcfile(int argc, char **argv);
static void immediate_switch_user(int argc, char* argv[]); static void immediate_switch_user(int argc, char* argv[]);
static void print_settings(int try_http, int bg, char *gui_str); static void print_settings(int try_http, int bg, char *gui_str);
static void check_loop_mode(int argc, char* argv[], int force); static void check_loop_mode(int argc, char* argv[], int force);
static void check_appshare_mode(int argc, char* argv[]);
static int tsdo_timeout_flag; static int tsdo_timeout_flag;
...@@ -1702,6 +1703,24 @@ static void check_loop_mode(int argc, char* argv[], int force) { ...@@ -1702,6 +1703,24 @@ static void check_loop_mode(int argc, char* argv[], int force) {
#endif #endif
} }
} }
extern int appshare_main(int argc, char* argv[]);
static void check_appshare_mode(int argc, char* argv[]) {
int i;
for (i=1; i < argc; i++) {
char *p = argv[i];
if (strstr(p, "--") == p) {
p++;
}
if (strstr(p, "-appshare") == p) {
appshare_main(argc, argv);
exit(0);
}
}
}
static void store_homedir_passwd(char *file) { static void store_homedir_passwd(char *file) {
char str1[32], str2[32], *p, *h, *f; char str1[32], str2[32], *p, *h, *f;
struct stat sbuf; struct stat sbuf;
...@@ -1992,21 +2011,32 @@ int main(int argc, char* argv[]) { ...@@ -1992,21 +2011,32 @@ int main(int argc, char* argv[]) {
char *got_rfbport_str = NULL; char *got_rfbport_str = NULL;
int got_rfbport_pos = -1; int got_rfbport_pos = -1;
int got_tls = 0; int got_tls = 0;
int got_inetd = 0;
int got_noxrandr = 0;
/* used to pass args we do not know about to rfbGetScreen(): */ /* used to pass args we do not know about to rfbGetScreen(): */
int argc_vnc_max = 1024; int argc_vnc_max = 1024;
int argc_vnc = 1; char *argv_vnc[2048]; int argc_vnc = 1; char *argv_vnc[2048];
/* check for -loop mode: */ /* check for -loop mode: */
check_loop_mode(argc, argv, 0); check_loop_mode(argc, argv, 0);
/* check for -appshare mode: */
check_appshare_mode(argc, argv);
dtime0(&x11vnc_start); dtime0(&x11vnc_start);
for (i=1; i < argc; i++) {
if (!strcmp(argv[i], "-inetd")) {
got_inetd = 1;
}
}
if (!getuid() || !geteuid()) { if (!getuid() || !geteuid()) {
started_as_root = 1; started_as_root = 1;
rfbLog("getuid: %d geteuid: %d\n", getuid(), geteuid()); if (0 && !got_inetd) {
rfbLog("getuid: %d geteuid: %d\n", getuid(), geteuid());
}
/* check for '-users =bob' */ /* check for '-users =bob' */
immediate_switch_user(argc, argv); immediate_switch_user(argc, argv);
...@@ -2363,6 +2393,14 @@ int main(int argc, char* argv[]) { ...@@ -2363,6 +2393,14 @@ int main(int argc, char* argv[]) {
; /* handled above */ ; /* handled above */
continue; continue;
} }
if (strstr(arg, "-appshare") == arg) {
; /* handled above */
continue;
}
if (strstr(arg, "-freeze_when_obscured") == arg) {
freeze_when_obscured = 1;
continue;
}
if (!strcmp(arg, "-timeout")) { if (!strcmp(arg, "-timeout")) {
CHECK_ARGC CHECK_ARGC
first_conn_timeout = atoi(argv[++i]); first_conn_timeout = atoi(argv[++i]);
...@@ -2955,6 +2993,7 @@ int main(int argc, char* argv[]) { ...@@ -2955,6 +2993,7 @@ int main(int argc, char* argv[]) {
if (!strcmp(arg, "-noxrandr")) { if (!strcmp(arg, "-noxrandr")) {
xrandr = 0; xrandr = 0;
xrandr_maybe = 0; xrandr_maybe = 0;
got_noxrandr = 1;
continue; continue;
} }
if (!strcmp(arg, "-rotate")) { if (!strcmp(arg, "-rotate")) {
...@@ -3040,6 +3079,10 @@ int main(int argc, char* argv[]) { ...@@ -3040,6 +3079,10 @@ int main(int argc, char* argv[]) {
quiet = 1; quiet = 1;
continue; continue;
} }
if (!strcmp(arg, "-noquiet")) {
quiet = 0;
continue;
}
if (!strcmp(arg, "-v") || !strcmp(arg, "-verbose")) { if (!strcmp(arg, "-v") || !strcmp(arg, "-verbose")) {
verbose = 1; verbose = 1;
continue; continue;
...@@ -3049,7 +3092,9 @@ int main(int argc, char* argv[]) { ...@@ -3049,7 +3092,9 @@ int main(int argc, char* argv[]) {
bg = 1; bg = 1;
opts_bg = bg; opts_bg = bg;
#else #else
fprintf(stderr, "warning: -bg mode not supported.\n"); if (!got_inetd) {
fprintf(stderr, "warning: -bg mode not supported.\n");
}
#endif #endif
continue; continue;
} }
...@@ -3446,8 +3491,10 @@ int main(int argc, char* argv[]) { ...@@ -3446,8 +3491,10 @@ int main(int argc, char* argv[]) {
*p = '\0'; *p = '\0';
} }
if (atoi(s) < 1 || atoi(s) > pointer_mode_max) { if (atoi(s) < 1 || atoi(s) > pointer_mode_max) {
rfbLog("pointer_mode out of range 1-%d: %d\n", if (!got_inetd) {
pointer_mode_max, atoi(s)); rfbLog("pointer_mode out of range 1-%d: %d\n",
pointer_mode_max, atoi(s));
}
} else { } else {
pointer_mode = atoi(s); pointer_mode = atoi(s);
got_pointer_mode = pointer_mode; got_pointer_mode = pointer_mode;
...@@ -3591,7 +3638,9 @@ int main(int argc, char* argv[]) { ...@@ -3591,7 +3638,9 @@ int main(int argc, char* argv[]) {
if (!strcmp(arg, "-chatwindow")) { if (!strcmp(arg, "-chatwindow")) {
chat_window = 1; chat_window = 1;
if (argc_vnc + 1 < argc_vnc_max) { if (argc_vnc + 1 < argc_vnc_max) {
rfbLog("setting '-rfbversion 3.6' for -chatwindow.\n"); if (!got_inetd) {
rfbLog("setting '-rfbversion 3.6' for -chatwindow.\n");
}
argv_vnc[argc_vnc++] = strdup("-rfbversion"); argv_vnc[argc_vnc++] = strdup("-rfbversion");
argv_vnc[argc_vnc++] = strdup("3.6"); argv_vnc[argc_vnc++] = strdup("3.6");
} }
...@@ -3645,14 +3694,16 @@ int main(int argc, char* argv[]) { ...@@ -3645,14 +3694,16 @@ int main(int argc, char* argv[]) {
/* we re-enable it due to threaded mode bugfixes. */ /* we re-enable it due to threaded mode bugfixes. */
use_threads = 1; use_threads = 1;
} else { } else {
rfbLog("\n"); if (!got_inetd) {
rfbLog("The -threads mode is unstable and not tested or maintained.\n"); rfbLog("\n");
rfbLog("It is disabled in the source code. If you really need\n"); rfbLog("The -threads mode is unstable and not tested or maintained.\n");
rfbLog("the feature you can reenable it at build time by setting\n"); rfbLog("It is disabled in the source code. If you really need\n");
rfbLog("-DX11VNC_THREADED in CPPFLAGS. Or set X11VNC_THREADED=1\n"); rfbLog("the feature you can reenable it at build time by setting\n");
rfbLog("in your runtime environment.\n"); rfbLog("-DX11VNC_THREADED in CPPFLAGS. Or set X11VNC_THREADED=1\n");
rfbLog("\n"); rfbLog("in your runtime environment.\n");
usleep(500*1000); rfbLog("\n");
usleep(500*1000);
}
} }
#endif #endif
continue; continue;
...@@ -3931,9 +3982,11 @@ int main(int argc, char* argv[]) { ...@@ -3931,9 +3982,11 @@ int main(int argc, char* argv[]) {
if (!strcasecmp(argv[i+1], "prompt")) { if (!strcasecmp(argv[i+1], "prompt")) {
; ;
} else if (!is_decimal(argv[i+1])) { } else if (!is_decimal(argv[i+1])) {
rfbLog("Invalid -rfbport value: '%s'\n", argv[i+1]); if (!got_inetd) {
rfbLog("setting it to '-1' to induce failure.\n"); rfbLog("Invalid -rfbport value: '%s'\n", argv[i+1]);
argv[i+1] = strdup("-1"); rfbLog("setting it to '-1' to induce failure.\n");
argv[i+1] = strdup("-1");
}
} }
got_rfbport_str = strdup(argv[i+1]); got_rfbport_str = strdup(argv[i+1]);
got_rfbport_pos = argc_vnc+1; got_rfbport_pos = argc_vnc+1;
...@@ -4032,7 +4085,9 @@ int main(int argc, char* argv[]) { ...@@ -4032,7 +4085,9 @@ int main(int argc, char* argv[]) {
client_connect_file = str; client_connect_file = str;
} }
if (client_connect_file) { if (client_connect_file) {
rfbLog("MacOS X: set -connect file to %s\n", client_connect_file); if (!got_inetd) {
rfbLog("MacOS X: set -connect file to %s\n", client_connect_file);
}
} }
} }
} }
...@@ -4053,7 +4108,9 @@ int main(int argc, char* argv[]) { ...@@ -4053,7 +4108,9 @@ int main(int argc, char* argv[]) {
rfbLog("Port prompt indicated cancel.\n"); rfbLog("Port prompt indicated cancel.\n");
clean_up_exit(1); clean_up_exit(1);
} }
rfbLog("Port prompt selected: %d\n", got_rfbport_val); if (!got_inetd) {
rfbLog("Port prompt selected: %d\n", got_rfbport_val);
}
sprintf(tport, "%d", got_rfbport_val); sprintf(tport, "%d", got_rfbport_val);
argv_vnc[got_rfbport_pos] = strdup(tport); argv_vnc[got_rfbport_pos] = strdup(tport);
free(opts); free(opts);
...@@ -4117,8 +4174,9 @@ int main(int argc, char* argv[]) { ...@@ -4117,8 +4174,9 @@ int main(int argc, char* argv[]) {
q = t + strlen(pstr); q = t + strlen(pstr);
} }
logfile = new; logfile = new;
if (!quiet) { if (!quiet && !got_inetd) {
rfbLog("Expanded logfile to '%s'\n", new); rfbLog("Expanded logfile to '%s'\n", new);
} }
free(s); free(s);
} }
...@@ -4152,7 +4210,7 @@ int main(int argc, char* argv[]) { ...@@ -4152,7 +4210,7 @@ int main(int argc, char* argv[]) {
q = t + strlen(pstr); q = t + strlen(pstr);
} }
logfile = new; logfile = new;
if (!quiet) { if (!quiet && !got_inetd) {
rfbLog("Expanded logfile to '%s'\n", new); rfbLog("Expanded logfile to '%s'\n", new);
} }
free(s); free(s);
...@@ -4389,7 +4447,7 @@ int main(int argc, char* argv[]) { ...@@ -4389,7 +4447,7 @@ int main(int argc, char* argv[]) {
if (1) { if (1) {
/* mix things up a little bit */ /* mix things up a little bit */
unsigned char buf[CHALLENGESIZE]; unsigned char buf[CHALLENGESIZE];
int k, kmax = (int) (500 * rfac()) + 100; int k, kmax = (int) (50 * rfac()) + 10;
for (k=0; k < kmax; k++) { for (k=0; k < kmax; k++) {
rfbRandomBytes(buf); rfbRandomBytes(buf);
} }
...@@ -4550,6 +4608,13 @@ int main(int argc, char* argv[]) { ...@@ -4550,6 +4608,13 @@ int main(int argc, char* argv[]) {
exit(1); exit(1);
} }
if (use_threads && !got_noxrandr) {
xrandr = 1;
if (! quiet) {
rfbLog("enabling -xrandr in -threads mode.\n");
}
}
/* fixup settings that do not make sense */ /* fixup settings that do not make sense */
if (use_threads && nofb && cursor_pos_updates) { if (use_threads && nofb && cursor_pos_updates) {
...@@ -4626,6 +4691,7 @@ int main(int argc, char* argv[]) { ...@@ -4626,6 +4691,7 @@ int main(int argc, char* argv[]) {
/* increase rfbwait if threaded */ /* increase rfbwait if threaded */
if (use_threads && ! got_rfbwait) { if (use_threads && ! got_rfbwait) {
/* ??? lower this ??? */
rfbMaxClientWait = 604800000; rfbMaxClientWait = 604800000;
} }
...@@ -4712,6 +4778,8 @@ int main(int argc, char* argv[]) { ...@@ -4712,6 +4778,8 @@ int main(int argc, char* argv[]) {
X_INIT; X_INIT;
SCR_INIT; SCR_INIT;
CLIENT_INIT; CLIENT_INIT;
INPUT_INIT;
POINTER_INIT;
/* open the X display: */ /* open the X display: */
...@@ -5331,9 +5399,7 @@ int main(int argc, char* argv[]) { ...@@ -5331,9 +5399,7 @@ int main(int argc, char* argv[]) {
} }
#endif #endif
if (!getenv("X11VNC_NO_CHECK_PM")) { check_pm();
check_pm();
}
if (! quiet && ! raw_fb_str) { if (! quiet && ! raw_fb_str) {
rfbLog("--------------------------------------------------------\n"); rfbLog("--------------------------------------------------------\n");
...@@ -5644,4 +5710,3 @@ int main(int argc, char* argv[]) { ...@@ -5644,4 +5710,3 @@ int main(int argc, char* argv[]) {
} }
...@@ -47,7 +47,7 @@ int xtrap_base_event_type = 0; ...@@ -47,7 +47,7 @@ int xtrap_base_event_type = 0;
int xdamage_base_event_type = 0; int xdamage_base_event_type = 0;
/* date +'lastmod: %Y-%m-%d' */ /* date +'lastmod: %Y-%m-%d' */
char lastmod[] = "0.9.9 lastmod: 2009-11-18"; char lastmod[] = "0.9.9 lastmod: 2009-12-02";
/* X display info */ /* X display info */
......
...@@ -340,6 +340,10 @@ static void initialize_xevents(int reset) { ...@@ -340,6 +340,10 @@ static void initialize_xevents(int reset) {
X_LOCK; X_LOCK;
xselectinput_rootwin |= PropertyChangeMask; xselectinput_rootwin |= PropertyChangeMask;
XSelectInput_wr(dpy, rootwin, xselectinput_rootwin); XSelectInput_wr(dpy, rootwin, xselectinput_rootwin);
if (subwin && freeze_when_obscured) {
XSelectInput_wr(dpy, subwin, VisibilityChangeMask);
}
X_UNLOCK; X_UNLOCK;
did_xselect_input = 1; did_xselect_input = 1;
} }
...@@ -1284,6 +1288,22 @@ void check_xevents(int reset) { ...@@ -1284,6 +1288,22 @@ void check_xevents(int reset) {
last_call = now; last_call = now;
} }
if (freeze_when_obscured) {
if (XCheckTypedEvent(dpy, VisibilityNotify, &xev)) {
if (xev.type == VisibilityNotify && xev.xany.window == subwin) {
int prev = subwin_obscured;
if (xev.xvisibility.state == VisibilityUnobscured) {
subwin_obscured = 0;
} else if (xev.xvisibility.state == VisibilityPartiallyObscured) {
subwin_obscured = 1;
} else {
subwin_obscured = 2;
}
rfbLog("subwin_obscured: %d -> %d\n", prev, subwin_obscured);
}
}
}
/* check for CUT_BUFFER0, VNC_CONNECT, X11VNC_REMOTE changes: */ /* check for CUT_BUFFER0, VNC_CONNECT, X11VNC_REMOTE changes: */
if (XCheckTypedEvent(dpy, PropertyNotify, &xev)) { if (XCheckTypedEvent(dpy, PropertyNotify, &xev)) {
int got_cutbuffer = 0; int got_cutbuffer = 0;
...@@ -1622,6 +1642,10 @@ extern int rawfb_vnc_reflect; ...@@ -1622,6 +1642,10 @@ extern int rawfb_vnc_reflect;
void xcut_receive(char *text, int len, rfbClientPtr cl) { void xcut_receive(char *text, int len, rfbClientPtr cl) {
allowed_input_t input; allowed_input_t input;
if (threads_drop_input) {
return;
}
if (unixpw_in_progress) { if (unixpw_in_progress) {
rfbLog("xcut_receive: unixpw_in_progress, skipping.\n"); rfbLog("xcut_receive: unixpw_in_progress, skipping.\n");
return; return;
...@@ -1640,6 +1664,7 @@ void xcut_receive(char *text, int len, rfbClientPtr cl) { ...@@ -1640,6 +1664,7 @@ void xcut_receive(char *text, int len, rfbClientPtr cl) {
if (!input.clipboard) { if (!input.clipboard) {
return; return;
} }
INPUT_LOCK;
if (remote_prefix != NULL && strstr(text, remote_prefix) == text) { if (remote_prefix != NULL && strstr(text, remote_prefix) == text) {
char *result, *rcmd = text + strlen(remote_prefix); char *result, *rcmd = text + strlen(remote_prefix);
...@@ -1649,9 +1674,29 @@ void xcut_receive(char *text, int len, rfbClientPtr cl) { ...@@ -1649,9 +1674,29 @@ void xcut_receive(char *text, int len, rfbClientPtr cl) {
strcat(tmp, "qry="); strcat(tmp, "qry=");
} }
strncat(tmp, rcmd, len - strlen(remote_prefix)); strncat(tmp, rcmd, len - strlen(remote_prefix));
rfbLog("remote_prefix command: '%s'\n", tmp); rfbLog("remote_prefix command: '%s'\n", tmp);
if (use_threads) {
if (client_connect_file) {
FILE *f = fopen(client_connect_file, "w");
if (f) {
fprintf(f, "%s\n", tmp);
fclose(f);
free(tmp);
INPUT_UNLOCK;
return;
}
}
if (vnc_connect) {
sprintf(x11vnc_remote_str, "%s", tmp);
free(tmp);
INPUT_UNLOCK;
return;
}
}
INPUT_UNLOCK;
result = process_remote_cmd(tmp, 1); result = process_remote_cmd(tmp, 1);
if (result == NULL ) { if (result == NULL ) {
result = strdup("null"); result = strdup("null");
...@@ -1675,24 +1720,28 @@ void xcut_receive(char *text, int len, rfbClientPtr cl) { ...@@ -1675,24 +1720,28 @@ void xcut_receive(char *text, int len, rfbClientPtr cl) {
} }
if (! check_sel_direction("recv", "xcut_receive", text, len)) { if (! check_sel_direction("recv", "xcut_receive", text, len)) {
INPUT_UNLOCK;
return; return;
} }
#ifdef MACOSX #ifdef MACOSX
if (macosx_console) { if (macosx_console) {
macosx_set_sel(text, len); macosx_set_sel(text, len);
INPUT_UNLOCK;
return; return;
} }
#endif #endif
if (rawfb_vnc_reflect) { if (rawfb_vnc_reflect) {
vnc_reflect_send_cuttext(text, len); vnc_reflect_send_cuttext(text, len);
INPUT_UNLOCK;
return; return;
} }
RAWFB_RET_VOID RAWFB_RET_VOID
#if NO_X11 #if NO_X11
INPUT_UNLOCK;
return; return;
#else #else
...@@ -1751,6 +1800,7 @@ void xcut_receive(char *text, int len, rfbClientPtr cl) { ...@@ -1751,6 +1800,7 @@ void xcut_receive(char *text, int len, rfbClientPtr cl) {
XFlush_wr(dpy); XFlush_wr(dpy);
X_UNLOCK; X_UNLOCK;
INPUT_UNLOCK;
set_cutbuffer = 1; set_cutbuffer = 1;
#endif /* NO_X11 */ #endif /* NO_X11 */
...@@ -1956,6 +2006,7 @@ static void try_local_chat_window(void) { ...@@ -1956,6 +2006,7 @@ static void try_local_chat_window(void) {
return; return;
} }
/* mutex */
new_save = screen->newClientHook; new_save = screen->newClientHook;
screen->newClientHook = new_client_chat_helper; screen->newClientHook = new_client_chat_helper;
......
...@@ -344,12 +344,14 @@ static void initialize_xinerama (void) { ...@@ -344,12 +344,14 @@ static void initialize_xinerama (void) {
RAWFB_RET_VOID RAWFB_RET_VOID
X_LOCK;
if (! XineramaQueryExtension(dpy, &ev, &er)) { if (! XineramaQueryExtension(dpy, &ev, &er)) {
if (verbose) { if (verbose) {
rfbLog("Xinerama: disabling: display does not support it.\n"); rfbLog("Xinerama: disabling: display does not support it.\n");
} }
xinerama = 0; xinerama = 0;
xinerama_present = 0; xinerama_present = 0;
X_UNLOCK;
return; return;
} }
if (! XineramaIsActive(dpy)) { if (! XineramaIsActive(dpy)) {
...@@ -359,6 +361,7 @@ static void initialize_xinerama (void) { ...@@ -359,6 +361,7 @@ static void initialize_xinerama (void) {
} }
xinerama = 0; xinerama = 0;
xinerama_present = 0; xinerama_present = 0;
X_UNLOCK;
return; return;
} }
xinerama_present = 1; xinerama_present = 1;
...@@ -385,6 +388,7 @@ static void initialize_xinerama (void) { ...@@ -385,6 +388,7 @@ static void initialize_xinerama (void) {
rfbLog("\n"); rfbLog("\n");
} }
XFree_wr(xineramas); XFree_wr(xineramas);
X_UNLOCK;
return; /* must be OK w/o change */ return; /* must be OK w/o change */
} }
...@@ -406,6 +410,7 @@ static void initialize_xinerama (void) { ...@@ -406,6 +410,7 @@ static void initialize_xinerama (void) {
sc++; sc++;
} }
XFree_wr(xineramas); XFree_wr(xineramas);
X_UNLOCK;
if (sraRgnEmpty(black_region)) { if (sraRgnEmpty(black_region)) {
......
...@@ -143,6 +143,8 @@ static void handle_xrandr_change(int new_x, int new_y) { ...@@ -143,6 +143,8 @@ static void handle_xrandr_change(int new_x, int new_y) {
RAWFB_RET_VOID RAWFB_RET_VOID
/* assumes no X_LOCK */
/* sanity check xrandr_mode */ /* sanity check xrandr_mode */
if (! xrandr_mode) { if (! xrandr_mode) {
xrandr_mode = strdup("default"); xrandr_mode = strdup("default");
...@@ -184,6 +186,8 @@ int check_xrandr_event(char *msg) { ...@@ -184,6 +186,8 @@ int check_xrandr_event(char *msg) {
RAWFB_RET(0) RAWFB_RET(0)
/* it is assumed that X_LOCK is on at this point. */
if (subwin) { if (subwin) {
return handle_subwin_resize(msg); return handle_subwin_resize(msg);
} }
...@@ -235,8 +239,13 @@ int check_xrandr_event(char *msg) { ...@@ -235,8 +239,13 @@ int check_xrandr_event(char *msg) {
if (wdpy_x == rev->width && wdpy_y == rev->height && if (wdpy_x == rev->width && wdpy_y == rev->height &&
xrandr_rotation == (int) rev->rotation) { xrandr_rotation == (int) rev->rotation) {
rfbLog("check_xrandr_event: no change detected.\n"); rfbLog("check_xrandr_event: no change detected.\n");
do_change = 0; do_change = 0;
if (! xrandr) {
rfbLog("check_xrandr_event: "
"enabling full XRANDR trapping anyway.\n");
xrandr = 1;
}
} else { } else {
do_change = 1; do_change = 1;
if (! xrandr) { if (! xrandr) {
...@@ -256,6 +265,7 @@ int check_xrandr_event(char *msg) { ...@@ -256,6 +265,7 @@ int check_xrandr_event(char *msg) {
XRRUpdateConfiguration(&xev); XRRUpdateConfiguration(&xev);
if (do_change) { if (do_change) {
/* under do_change caller normally returns before its X_UNLOCK */
X_UNLOCK; X_UNLOCK;
handle_xrandr_change(rev->width, rev->height); handle_xrandr_change(rev->width, rev->height);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment