Commit 90d96b97 authored by runge's avatar runge

x11vnc: watch textchat, etc in unixpw, implement kbdReleaseAllKeys,...

x11vnc: watch textchat, etc in unixpw, implement kbdReleaseAllKeys, setSingleWindow, setServerInput. watch for OpenGL apps breaking XDAMAGE.
parent 76720eb7
2007-02-10 Karl Runge <runge@karlrunge.com>
* x11vnc: watch things like textchat, etc. more carefully
in unixpw state. Monitor broken XDAMAGE reports when
OpenGL apps like beryl are running. Implement simple
kbdReleaseAllKeys, setSingleWindow, setServerInput actions
(ultravnc extentions). Try to send XDM the username in
FINDCREATEDISPLAY, also try .dmrc before .xsession.
2007-01-31 Karl Runge <runge@karlrunge.com>
* x11vnc: -reflect reflector/repeater mode with libvncclient.
-ncache tweaks: no kde animations and wm improvements,
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -657,6 +657,12 @@ void client_gone(rfbClientPtr client) {
if (unixpw_in_progress && unixpw_client) {
if (client == unixpw_client) {
unixpw_in_progress = 0;
screen->permitFileTransfer = unixpw_file_xfer_save;
if ((filexfer = unixpw_tightvnc_xfer_save)) {
#ifdef LIBVNCSERVER_WITH_TIGHTVNC_FILETRANSFER
rfbRegisterTightVNCFileTransferExtension();
#endif
}
unixpw_client = NULL;
copy_screen();
}
......@@ -2155,6 +2161,15 @@ enum rfbNewClientAction new_client(rfbClientPtr client) {
unixpw_in_progress = 1;
unixpw_client = client;
unixpw_login_viewonly = 0;
unixpw_file_xfer_save = screen->permitFileTransfer;
screen->permitFileTransfer = FALSE;
unixpw_tightvnc_xfer_save = filexfer;
filexfer = 0;
#ifdef LIBVNCSERVER_WITH_TIGHTVNC_FILETRANSFER
rfbUnregisterTightVNCFileTransferExtension();
#endif
if (client->viewOnly) {
unixpw_login_viewonly = 1;
client->viewOnly = FALSE;
......
......@@ -3,6 +3,7 @@
#include "cleanup.h"
void check_pm(void);
void set_dpms_mode(char *mode);
static void check_fbpm(void);
static void check_dpms(void);
......@@ -104,6 +105,57 @@ static void check_fbpm(void) {
#endif
}
void set_dpms_mode(char *mode) {
#if NO_X11
return;
#else
RAWFB_RET_VOID
#if LIBVNCSERVER_HAVE_DPMS
if (dpy && DPMSCapable(dpy)) {
CARD16 level;
CARD16 want;
BOOL enabled;
if (!strcmp(mode, "off")) {
want = DPMSModeOff;
} else if (!strcmp(mode, "on")) {
want = DPMSModeOn;
} else if (!strcmp(mode, "standby")) {
want = DPMSModeStandby;
} else if (!strcmp(mode, "suspend")) {
want = DPMSModeSuspend;
} else {
return;
}
if (DPMSInfo(dpy, &level, &enabled)) {
char *from;
fprintf(stderr, "DPMSInfo level: %d enabled: %d\n", level, enabled);
if (enabled && level != want) {
XErrorHandler old_handler = XSetErrorHandler(trap_xerror);
trapped_xerror = 0;
if (level == DPMSModeStandby) {
from = "DPMSModeStandby";
} else if (level == DPMSModeSuspend) {
from = "DPMSModeSuspend";
} else if (level == DPMSModeOff) {
from = "DPMSModeOff";
} else if (level == DPMSModeOn) {
from = "DPMSModeOn";
}
rfbLog("switching DPMS state from %s to %s\n", from, mode);
DPMSForceLevel(dpy, want);
XSetErrorHandler(old_handler);
trapped_xerror = 0;
}
}
}
#endif
#endif
}
static void check_dpms(void) {
static int init_dpms = 0;
#if LIBVNCSERVER_HAVE_DPMS
......
......@@ -3,5 +3,6 @@
/* -- pm.h -- */
extern void check_pm(void);
extern void set_dpms_mode(char *mode);
#endif /* _X11VNC_PM_H */
......@@ -25,10 +25,10 @@ void do_button_mask_change(int mask, int button);
void pointer(int mask, int x, int y, rfbClientPtr client);
void initialize_pipeinput(void);
int check_pipeinput(void);
void update_x11_pointer_position(int x, int y);
static void buttonparse(int from, char **s);
static void update_x11_pointer_position(int x, int y);
static void update_x11_pointer_mask(int mask);
static void pipe_pointer(int mask, int x, int y, rfbClientPtr client);
......@@ -301,7 +301,7 @@ void initialize_pointer_map(char *pointer_remap) {
/*
* Send a pointer position event to the X server.
*/
static void update_x11_pointer_position(int x, int y) {
void update_x11_pointer_position(int x, int y) {
#if NO_X11
RAWFB_RET_VOID
if (!x || !y) {}
......
......@@ -10,5 +10,6 @@ extern void do_button_mask_change(int mask, int button);
extern void pointer(int mask, int x, int y, rfbClientPtr client);
extern int check_pipeinput(void);
extern void initialize_pipeinput(void);
extern void update_x11_pointer_position(int x, int y);
#endif /* _X11VNC_POINTER_H */
......@@ -2831,18 +2831,23 @@ void set_offset(void) {
X_UNLOCK;
}
static int xd_samples = 0, xd_misses = 0, xd_do_check = 0;
/*
* Loop over 1-pixel tall horizontal scanlines looking for changes.
* Record the changes in tile_has_diff[]. Scanlines in the loop are
* equally spaced along y by NSCAN pixels, but have a slightly random
* starting offset ystart ( < NSCAN ) from scanlines[].
*/
static int scan_display(int ystart, int rescan) {
char *src, *dst;
int pixelsize = bpp/8;
int x, y, w, n;
int tile_count = 0;
int nodiffs = 0, diff_hint;
int xd_check, xd_freq = 1;
static int xd_tck = 0;
y = ystart;
......@@ -2859,10 +2864,24 @@ static int scan_display(int ystart, int rescan) {
if (use_xdamage) {
XD_tot++;
xd_check = 0;
if (xdamage_hint_skip(y)) {
XD_skip++;
y += NSCAN;
continue;
if (xd_do_check && dpy && use_xdamage == 1) {
xd_tck = (xd_tck++) % xd_freq;
if (xd_tck == 0) {
xd_check = 1;
xd_samples++;
}
}
if (!xd_check) {
XD_skip++;
y += NSCAN;
continue;
}
} else {
if (xd_do_check && 0) {
fprintf(stderr, "ns y=%d\n", y);
}
}
}
......@@ -2931,6 +2950,9 @@ fprintf(stderr, "\n*** SCAN_DISPLAY CHECK_NCACHE/%d *** %d rescan=%d\n", gotone,
continue;
}
}
if (xd_check) {
xd_misses++;
}
x = 0;
while (x < dpy_x) {
......@@ -3132,6 +3154,33 @@ int scan_for_updates(int count_only) {
}
}
}
if (dpy && use_xdamage == 1) {
static time_t last_xd_check = 0;
if (time(NULL) > last_xd_check + 2) {
int cp = (scan_count + 3) % NSCAN;
xd_do_check = 1;
tile_count = scan_display(scanlines[cp], 0);
xd_do_check = 0;
SCAN_FATAL(tile_count);
last_xd_check = time(NULL);
if (xd_samples > 200) {
static bad = 0;
if (xd_misses > (5 * xd_samples) / 100) {
rfbLog("XDAMAGE is not working well... misses: %d/%d\n", xd_misses, xd_samples);
rfbLog("Maybe a OpenGL app like Beryl is the problem? Use -noxdamage\n");
rfbLog("To disable this check and warning specify -xdamage twice.\n");
if (++bad >= 10) {
rfbLog("XDAMAGE appears broken (OpenGL app?), turning it off.\n");
use_xdamage = 0;
initialize_xdamage();
destroy_xdamage_if_needed();
}
}
xd_samples = 0;
xd_misses = 0;
}
}
}
nap_set(tile_count);
......
......@@ -2834,6 +2834,11 @@ void initialize_screen(int *argc, char **argv, XImage *fb) {
screen->setXCutText = xcut_receive;
screen->setTranslateFunction = set_xlate_wrapper;
screen->kbdReleaseAllKeys = kbd_release_all_keys;
screen->setSingleWindow = set_single_window;
screen->setServerInput = set_server_input;
screen->setTextChat = set_text_chat;
/* called from inetd, we need to treat stdio as our socket */
if (inetd && use_openssl) {
/* accept_openssl() called later */
......
......@@ -946,13 +946,6 @@ char create_display[] =
" home=__noplace__\n"
" fi\n"
" fi\n"
" if [ -f \"$home/.xsession\" ]; then\n"
" echo \"$home/.xsession\"\n"
" return\n"
" elif [ -f \"$home/.xinitrc\" ]; then\n"
" echo \"$home/.xinitrc\"\n"
" return\n"
" fi\n"
" if [ -f \"$home/.dmrc\" ]; then\n"
" if [ \"X$have_startkde\" != \"X\" ]; then\n"
" if egrep -i 'Session=(default|kde)' \"$home/.dmrc\" > /dev/null; then\n"
......@@ -979,6 +972,13 @@ char create_display[] =
" \n"
" done\n"
" fi\n"
" if [ -f \"$home/.xsession\" ]; then\n"
" echo \"$home/.xsession\"\n"
" return\n"
" elif [ -f \"$home/.xinitrc\" ]; then\n"
" echo \"$home/.xinitrc\"\n"
" return\n"
" fi\n"
" if [ \"X$have_xterm\" != \"X\" ]; then\n"
" echo $have_xterm\n"
" return\n"
......
......@@ -76,6 +76,8 @@ int unixpw_in_progress = 0;
int unixpw_denied = 0;
int unixpw_in_rfbPE = 0;
int unixpw_login_viewonly = 0;
int unixpw_tightvnc_xfer_save = 0;
rfbBool unixpw_file_xfer_save = FALSE;
time_t unixpw_last_try_time = 0;
rfbClientPtr unixpw_client = NULL;
......@@ -1550,6 +1552,12 @@ void unixpw_accept(char *user) {
unixpw_client->viewOnly = TRUE;
}
unixpw_in_progress = 0;
screen->permitFileTransfer = unixpw_file_xfer_save;
if ((filexfer = unixpw_tightvnc_xfer_save)) {
#ifdef LIBVNCSERVER_WITH_TIGHTVNC_FILETRANSFER
rfbRegisterTightVNCFileTransferExtension();
#endif
}
unixpw_client = NULL;
mark_rect_as_modified(0, 0, dpy_x, dpy_y, 0);
if (macosx_console) {
......@@ -1590,6 +1598,12 @@ void unixpw_deny(void) {
}
unixpw_in_progress = 0;
screen->permitFileTransfer = unixpw_file_xfer_save;
if ((filexfer = unixpw_tightvnc_xfer_save)) {
#ifdef LIBVNCSERVER_WITH_TIGHTVNC_FILETRANSFER
rfbRegisterTightVNCFileTransferExtension();
#endif
}
unixpw_client = NULL;
copy_screen();
}
......
......@@ -17,6 +17,8 @@ extern int unixpw_in_progress;
extern int unixpw_denied;
extern int unixpw_in_rfbPE;
extern int unixpw_login_viewonly;
extern int unixpw_tightvnc_xfer_save;
extern rfbBool unixpw_file_xfer_save;
extern time_t unixpw_last_try_time;
extern rfbClientPtr unixpw_client;
extern int keep_unixpw;
......
......@@ -22,6 +22,7 @@ void install_passwds(void);
void check_new_passwds(int force);
int wait_for_client(int *argc, char** argv, int http);
rfbBool custom_passwd_check(rfbClientPtr cl, const char *response, int len);
char *xdmcp_insert = NULL;
static void switch_user_task_dummy(void);
static void switch_user_task_solid_bg(void);
......@@ -1255,6 +1256,8 @@ int wait_for_client(int *argc, char** argv, int http) {
str = strdup(use_dpy);
str += strlen("WAIT");
xdmcp_insert = NULL;
/* get any leading geometry: */
q = strchr(str+1, ':');
if (q) {
......@@ -1434,12 +1437,15 @@ int wait_for_client(int *argc, char** argv, int http) {
}
}
if (0) db = 1;
if (cmd) {
char line1[1024];
char line2[16384];
char *q;
int n;
int nodisp = 0;
int saw_xdmcp = 0;
memset(line1, 0, 1024);
memset(line2, 0, 16384);
......@@ -1462,6 +1468,9 @@ int wait_for_client(int *argc, char** argv, int http) {
char st[] = "";
if (opts) {
opts++;
if (strstr(opts, "xdmcp")) {
saw_xdmcp = 1;
}
} else {
opts = st;
}
......@@ -1513,7 +1522,7 @@ if (db) {fprintf(stderr, "line: "); write(2, line, n); write(2, "\n", 1); fprint
n = 18000;
res = su_verify(keep_unixpw_user,
keep_unixpw_pass, create_cmd, line, &n, nodisp);
/*if (1) fprintf(stderr, "line: '%s'\n", line); */
if (db) fprintf(stderr, "line: '%s'\n", line);
} else {
FILE *p;
......@@ -1540,6 +1549,9 @@ if (db) fprintf(stderr, "line1: '%s'\n", line1);
}
}
}
if (res && saw_xdmcp) {
xdmcp_insert = strdup(keep_unixpw_user);
}
}
if (tmp_fd >= 0) {
......@@ -1727,7 +1739,9 @@ if (db) fprintf(stderr, "%d -- %s -- %s\n", i, proc, buf);
xauth_raw_data = (char *)malloc(n);
xauth_raw_len = n;
memcpy(xauth_raw_data, line2, n);
if (db) fprintf(stderr, "xauth_raw_len: %d\n", n);
if (db) {fprintf(stderr, "xauth_raw_len: %d\n", n);
write(2, xauth_raw_data, n);
fprintf(stderr, "\n");}
}
}
......
......@@ -11,5 +11,6 @@ extern void install_passwds(void);
extern void check_new_passwds(int force);
extern int wait_for_client(int *argc, char** argv, int http);
extern rfbBool custom_passwd_check(rfbClientPtr cl, const char *response, int len);
extern char *xdmcp_insert;
#endif /* _X11VNC_USER_H */
......@@ -8796,7 +8796,7 @@ int check_ncache(int reset, int mode) {
RAWFB_RET(-1)
#endif
if (! screen) {
if (! screen || ! dpy) {
return -1;
}
......@@ -8806,6 +8806,10 @@ int check_ncache(int reset, int mode) {
ncache = 0;
#endif
if (reset && (first || cache_list_len == 0)) {
return -1;
}
if (ncache0) {
if (reset) {
;
......@@ -8858,7 +8862,7 @@ if (c) fprintf(stderr, "check_ncache purged %d events\n", c);
if (reset) {
rfbLog("check_ncache: resetting cache\n");
rfbLog("check_ncache: resetting cache: %d/%d %d %d\n", cache_list_num, cache_list_len, ncache, first);
for (i=0; i < cache_list_num; i++) {
free_rect(i);
}
......
.\" This file was automatically generated from x11vnc -help output.
.TH X11VNC "1" "January 2007" "x11vnc " "User Commands"
.TH X11VNC "1" "February 2007" "x11vnc " "User Commands"
.SH NAME
x11vnc - allow VNC connections to real X11 displays
version: 0.8.5, lastmod: 2007-02-01
version: 0.8.5, lastmod: 2007-02-10
.SH SYNOPSIS
.B x11vnc
[OPTION]...
......
......@@ -2345,7 +2345,7 @@ int main(int argc, char* argv[]) {
} else if (!strcmp(arg, "-dpms")) {
watch_dpms = 0;
} else if (!strcmp(arg, "-xdamage")) {
use_xdamage = 1;
use_xdamage++;
} else if (!strcmp(arg, "-noxdamage")) {
use_xdamage = 0;
} else if (!strcmp(arg, "-xd_area")) {
......@@ -3156,7 +3156,6 @@ int main(int argc, char* argv[]) {
dpy = XOpenDisplay_wr("");
}
#ifdef MACOSX
if (! dpy && ! raw_fb_str) {
raw_fb_str = strdup("console");
......@@ -3207,6 +3206,7 @@ int main(int argc, char* argv[]) {
if (! quiet) rfbLog("Using default X display.\n");
}
scr = DefaultScreen(dpy);
rootwin = RootWindow(dpy, scr);
......@@ -3646,6 +3646,68 @@ int main(int argc, char* argv[]) {
if (macosx_console) {
refresh_screen(1);
}
if (dpy && xdmcp_insert != NULL) {
#if !NO_X11
char c;
int n = strlen(xdmcp_insert);
KeyCode k, k2;
KeySym sym;
int i, ok = 1;
for (i = 0; i < n; i++) {
c = xdmcp_insert[i];
sym = (KeySym) c;
if (sym < ' ' || sym > 0x7f) {
ok = 0;
break;
}
k = XKeysymToKeycode(dpy, sym);
if (k == NoSymbol) {
ok = 0;
break;
}
}
if (ok) {
XFlush_wr(dpy);
usleep(2*1000*1000);
if (!quiet) {
rfbLog("sending XDM '%s'\n", xdmcp_insert);
}
for (i = 0; i < n; i++) {
c = xdmcp_insert[i];
sym = (KeySym) c;
k = XKeysymToKeycode(dpy, sym);
if (isupper(c)) {
k2 = XKeysymToKeycode(dpy, XK_Shift_L);
XTestFakeKeyEvent_wr(dpy, k2, True, CurrentTime);
XFlush_wr(dpy);
usleep(100*1000);
}
if (0) fprintf(stderr, "C/k %c/%x\n", c, k);
XTestFakeKeyEvent_wr(dpy, k, True, CurrentTime);
XFlush_wr(dpy);
usleep(100*1000);
XTestFakeKeyEvent_wr(dpy, k, False, CurrentTime);
XFlush_wr(dpy);
usleep(100*1000);
if (isupper(c)) {
k2 = XKeysymToKeycode(dpy, XK_Shift_L);
XTestFakeKeyEvent_wr(dpy, k2, False, CurrentTime);
XFlush_wr(dpy);
usleep(100*1000);
}
}
k2 = XKeysymToKeycode(dpy, XK_Tab);
XTestFakeKeyEvent_wr(dpy, k2, True, CurrentTime);
XFlush_wr(dpy);
usleep(100*1000);
XTestFakeKeyEvent_wr(dpy, k2, False, CurrentTime);
XFlush_wr(dpy);
usleep(100*1000);
}
free(xdmcp_insert);
#endif
}
}
if (! waited_for_client) {
......
......@@ -15,7 +15,7 @@ int xtrap_base_event_type = 0;
int xdamage_base_event_type = 0;
/* date +'lastmod: %Y-%m-%d' */
char lastmod[] = "0.8.5 lastmod: 2007-02-01";
char lastmod[] = "0.8.5 lastmod: 2007-02-10";
/* X display info */
......
......@@ -15,6 +15,7 @@
#include "cleanup.h"
#include "macosx.h"
#include "screen.h"
#include "pm.h"
/* XXX CHECK BEFORE RELEASE */
int grab_buster = 0;
......@@ -33,6 +34,12 @@ void set_prop_atom(Atom atom);
void check_xevents(int reset);
void xcut_receive(char *text, int len, rfbClientPtr cl);
void kbd_release_all_keys(rfbClientPtr cl);
void set_single_window(rfbClientPtr cl, int x, int y);
void set_server_input(rfbClientPtr cl, int s);
void set_text_chat(rfbClientPtr cl, int l, char *t);
int get_keyboard_led_state_hook(rfbScreenInfoPtr s);
int get_file_transfer_permitted(rfbClientPtr cl);
static void initialize_xevents(int reset);
static void print_xevent_bases(void);
......@@ -1261,4 +1268,125 @@ void xcut_receive(char *text, int len, rfbClientPtr cl) {
#endif /* NO_X11 */
}
void kbd_release_all_keys(rfbClientPtr cl) {
if (unixpw_in_progress) {
rfbLog("kbd_release_all_keys: unixpw_in_progress, skipping.\n");
return;
}
if (cl->viewOnly) {
return;
}
RAWFB_RET_VOID
#if NO_X11
return;
#else
clear_keys();
clear_modifiers(0);
#endif
}
void set_single_window(rfbClientPtr cl, int x, int y) {
int ok = 0;
if (unixpw_in_progress) {
rfbLog("set_single_window: unixpw_in_progress, skipping.\n");
return;
}
if (cl->viewOnly) {
return;
}
RAWFB_RET_VOID
#if NO_X11
return;
#else
if (x==1 && y==1) {
if (subwin) {
subwin = 0x0;
ok = 1;
}
} else {
Window r, c;
int rootx, rooty, wx, wy;
unsigned int mask;
update_x11_pointer_position(x, y);
XSync(dpy, False);
if (XQueryPointer_wr(dpy, rootwin, &r, &c, &rootx, &rooty,
&wx, &wy, &mask)) {
if (c != None) {
subwin = c;
ok = 1;
}
}
}
if (ok) {
check_black_fb();
do_new_fb(1);
}
#endif
}
void set_server_input(rfbClientPtr cl, int grab) {
if (unixpw_in_progress) {
rfbLog("set_server_input: unixpw_in_progress, skipping.\n");
return;
}
if (cl->viewOnly) {
return;
}
RAWFB_RET_VOID
#if NO_X11
return;
#else
if (grab) {
process_remote_cmd("cmd=grabkbd", 0);
process_remote_cmd("cmd=grabptr", 0);
set_dpms_mode("off");
} else {
process_remote_cmd("cmd=nograbkbd", 0);
process_remote_cmd("cmd=nograbptr", 0);
}
#endif
}
void set_text_chat(rfbClientPtr cl, int len, char *txt) {
char buf[100];
rfbLog("set_text_chat: len=0x%x txt='", len);
if (0 < len && len < 10000) write(2, txt, len);
fprintf(stderr, "'\n");
if (unixpw_in_progress) {
rfbLog("set_text_chat: unixpw_in_progress, skipping.\n");
return;
}
if (0 && len == rfbTextChatOpen) {
if (rfbSendTextChatMessage(cl, rfbTextChatOpen, "")) {
rfbLog("rfbSendTextChatMessage: true\n");
} else {
rfbLog("rfbSendTextChatMessage: false\n");
}
}
}
int get_keyboard_led_state_hook(rfbScreenInfoPtr s) {
if (unixpw_in_progress) {
rfbLog("get_keyboard_led_state_hook: unixpw_in_progress, skipping.\n");
return 0;
}
return 0;
}
int get_file_transfer_permitted(rfbClientPtr cl) {
if (unixpw_in_progress) {
rfbLog("get_file_transfer_permitted: unixpw_in_progress, skipping.\n");
return FALSE;
}
return screen->permitFileTransfer;
}
......@@ -19,4 +19,12 @@ extern void set_prop_atom(Atom atom);
extern void check_xevents(int reset);
extern void xcut_receive(char *text, int len, rfbClientPtr cl);
extern void kbd_release_all_keys(rfbClientPtr cl);
extern void set_single_window(rfbClientPtr cl, int x, int y);
extern void set_server_input(rfbClientPtr cl, int s);
extern void set_text_chat(rfbClientPtr cl, int l, char *t);
extern int get_keyboard_led_state_hook(rfbScreenInfoPtr s);
extern int get_file_transfer_permitted(rfbClientPtr cl);
#endif /* _X11VNC_XEVENTS_H */
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