From 1c7ca906f7971bc45a90f425d5d8754ddd5eb1d7 Mon Sep 17 00:00:00 2001 From: runge Date: Wed, 28 Apr 2004 19:12:45 +0000 Subject: [PATCH] x11vnc: add -auth, more -cursorpos and -nofb work --- ChangeLog | 3 + contrib/ChangeLog | 6 ++ contrib/x11vnc.c | 193 +++++++++++++++++++++++++++++++++++++--------- 3 files changed, 165 insertions(+), 37 deletions(-) diff --git a/ChangeLog b/ChangeLog index 003d00d..10d7f20 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +2004-03-28 Karl Runge + * x11vnc: -auth, more -cursopor and -nofb work + 2004-03-19 Karl Runge * x11vnc: -cursorpos, -sigpipe diff --git a/contrib/ChangeLog b/contrib/ChangeLog index 23301f7..06e29e5 100644 --- a/contrib/ChangeLog +++ b/contrib/ChangeLog @@ -1,3 +1,9 @@ +2004-04-28 Karl Runge + * -auth cmdline option for xauthority. + * decrease default deferupdate under -nofb. + * update_client_pointer() from Edoardo Tirtarahardja. + * remove some assumptions about libvncserver defaults. + 2004-04-19 Karl Runge * support for cursor positions updates -cursorpos * option for SIGPIPE handling -sigpipe diff --git a/contrib/x11vnc.c b/contrib/x11vnc.c index 20ceeec..a0b6e95 100644 --- a/contrib/x11vnc.c +++ b/contrib/x11vnc.c @@ -238,6 +238,7 @@ int flip_byte_order = 0; /* sometimes needed when using_shm = 0 */ */ int waitms = 30; int defer_update = 30; /* rfbDeferUpdateTime ms to wait before sends. */ +int defer_update_nofb = 6; /* defer a shorter time under -nofb */ int screen_blank = 60; /* number of seconds of no activity to throttle */ /* down the screen polls. zero to disable. */ @@ -2055,6 +2056,50 @@ void blackout_nearby_tiles(x, y, dt) { } } +/* + * This is a special workaround to quickly send rfbCursorPosUpdates + * to client(s) when in -nofb mode, e.g. Win2VNC. It sends the updates + * immediately (by-passing libvncserver). Requires a customized Win2VNC + * to interpret the rfbCursorPosUpdates. Currently no big reason to + * do this for non-nofb mode (i.e. normal viewing) and so the normal + * libvncserver mechanism is used. Thanks to Edoardo Tirtarahardja. + */ +void update_client_pointer(rfbClientPtr cl, rfbBool send) { + rfbFramebufferUpdateMsg *fu; + + if (! nofb) { + /* normal libvncserver mechanism: */ + cl->cursorWasMoved = send; + return; + } + if (! send) { + return; + } + if (cl->state != RFB_NORMAL) { + /* bad idea to force this data to initializing clients */ + return; + } + + fu = (rfbFramebufferUpdateMsg*) cl->updateBuf; + cl->rfbFramebufferUpdateMessagesSent++; + fu->type = rfbFramebufferUpdate; + fu->nRects = Swap16IfLE(1); + memcpy(&cl->updateBuf[cl->ublen], (char*) fu, + sz_rfbFramebufferUpdateMsg); + cl->ublen = sz_rfbFramebufferUpdateMsg; + + rfbSendCursorPos(cl); + + if (debug_pointer) { + rfbLog("Sending rfbEncodingPointerPos message to host %s with " + "x=%d,y=%d\n", cl->host, screen->cursorX, screen->cursorY); + } +} + +/* + * Send rfbCursorPosUpdates back to clients that understand them. This + * seems to be TightVNC specific. + */ void cursor_pos_updates(int x, int y) { rfbClientIteratorPtr iter; rfbClientPtr cl; @@ -2063,6 +2108,7 @@ void cursor_pos_updates(int x, int y) { if (! cursor_pos) { return; } + /* x and y are current positions of X11 pointer on the X11 display */ if (x == screen->cursorX && y == screen->cursorY) { return; } @@ -2083,25 +2129,24 @@ void cursor_pos_updates(int x, int y) { continue; } if (cl == last_pointer_client) { + /* + * special case if this client was the last one to + * send a pointer position. + */ if (x == cursor_x && y == cursor_y) { - if (cursor_pos > 1) { - /* send to all */ - cl->cursorWasMoved = TRUE; - cnt++; - } else { - cl->cursorWasMoved = FALSE; - } + update_client_pointer(cl, FALSE); } else { + /* an X11 app evidently warped the pointer */ if (debug_pointer) { rfbLog("cursor_pos_updates: warp " "detected dx=%3d dy=%3d\n", cursor_x - x, cursor_y - y); } - cl->cursorWasMoved = TRUE; + update_client_pointer(cl, TRUE); cnt++; } } else { - cl->cursorWasMoved = TRUE; + update_client_pointer(cl, TRUE); cnt++; } } @@ -2286,11 +2331,6 @@ void update_mouse(void) { int root_x, root_y, win_x, win_y, which = 0; unsigned int mask; - if (! show_mouse && cursor_pos == 1 && last_pointer_client) { - if (client_count == 1) { - return; /* can save some effort for the 1 client case */ - } - } X_LOCK; ret = XQueryPointer(dpy, rootwin, &root_w, &child_w, &root_x, &root_y, &win_x, &win_y, &mask); @@ -2498,9 +2538,10 @@ void set_visual(char *vstring) { /* * Presumably under -nofb the clients will never request the framebuffer. - * But we have gotten such a request... so let's just give them the - * current view on the display. n.b. x2vnc and perhaps win2vnc requests - * a 1x1 pixel for some workaround so sadly this evidently always happens. + * But we have gotten such a request... so let's just give them + * the current view on the display. n.b. x2vnc and perhaps win2vnc + * requests a 1x1 pixel for some workaround so sadly this evidently + * nearly always happens. */ void nofb_hook(rfbClientPtr cl) { static int loaded_fb = 0; @@ -2515,6 +2556,9 @@ void nofb_hook(rfbClientPtr cl) { screen->displayHook = NULL; } +int got_rfbport = 0; +int got_alwaysshared = 0; +int got_nevershared = 0; /* * initialize the rfb framebuffer/screen */ @@ -2629,16 +2673,12 @@ if (strcmp(LIBVNCSERVER_VERSION, "0.5") && strcmp(LIBVNCSERVER_VERSION, "0.6")) /* we keep stderr for logging */ screen->inetdSock = fd; screen->rfbPort = 0; - } - /* XXX the following 3 settings are based on libvncserver defaults. */ - if (screen->rfbPort == 5900) { + } else if (! got_rfbport) { screen->autoPort = TRUE; } - if (screen->rfbDeferUpdateTime == 5) { - screen->rfbDeferUpdateTime = defer_update; - } - if (! screen->rfbNeverShared && ! screen->rfbAlwaysShared) { + + if (! got_nevershared && ! got_alwaysshared) { if (shared) { screen->rfbAlwaysShared = TRUE; } else { @@ -2646,6 +2686,11 @@ if (strcmp(LIBVNCSERVER_VERSION, "0.5") && strcmp(LIBVNCSERVER_VERSION, "0.6")) screen->rfbNeverShared = TRUE; } } + /* XXX the following is based on libvncserver defaults. */ + if (screen->rfbDeferUpdateTime == 5) { + /* XXX will be fixed someday */ + screen->rfbDeferUpdateTime = defer_update; + } /* event callbacks: */ screen->newClientHook = new_client; @@ -3242,8 +3287,15 @@ void initialize_shm() { if (i == 1) { clean_up_exit(1); } - rfbLog("error creating tile-row shm for len=%d\n", i); - rfbLog("reverting to single_copytile mode\n"); + rfbLog("shm: Error creating shared memory tile-row for" + " len=%d,\n", i); + rfbLog("shm: reverting to -onetile mode. If this" + " problem persists\n"); + rfbLog("shm: try using the -onetile or -noshm options" + " to limit\n"); + rfbLog("shm: shared memory usage, or run ipcrm(1)" + " to manually\n"); + rfbLog("shm: delete unattached shm segments.\n"); /* n.b.: "i" not "1", a kludge for cleanup */ single_copytile = i; } @@ -4607,7 +4659,7 @@ void watch_loop(void) { if (! use_threads) { rfbProcessEvents(screen, -1); - if (check_user_input(dt, &cnt)) { + if (! nofb && check_user_input(dt, &cnt)) { /* true means loop back for more input */ continue; } @@ -4857,6 +4909,8 @@ void print_help() { " contains \"/\" it is a file to periodically check for new\n" " hosts. The first line is read and then file is truncated.\n" "-vncconnect Monitor the VNC_CONNECT X property set by vncconnect(1).\n" +"-auth file Set the X authority file to be \"file\", equivalent to\n" +" setting the XAUTHORITY env. var to \"file\" before startup.\n" "-allow addr1[,addr2..] Only allow client connections from IP addresses matching\n" " the comma separated list of numerical addresses. Can be\n" " a prefix, e.g. \"192.168.100.\" to match a simple subnet,\n" @@ -4904,8 +4958,6 @@ void print_help() { " on touchscreens or other non-standard setups).\n" "-cursorpos Send the X cursor position back to all vnc clients that\n" " support the TightVNC CursorPosUpdates extension.\n" -"-cursorposall As -cursorpos, but send to all clients, even the one\n" -" that is currently moving the cursor around.\n" "-buttonmap str String to remap mouse buttons. Format: IJK-LMN, this\n" " maps buttons I -> L, etc., e.g. -buttonmap 13-31\n" "-nodragging Do not update the display during mouse dragging events\n" @@ -5021,11 +5073,13 @@ int main(int argc, char** argv) { XImage *fb; int i, op, ev, er, maj, min; char *use_dpy = NULL; + char *auth_file = NULL; char *arg, *visual_str = NULL; int pw_loc = -1; int dt = 0; int bg = 0; int got_waitms = 0, got_rfbwait = 0; + int got_deferupdate = 0, got_defer = 0; /* used to pass args we do not know about to rfbGetScreen(): */ int argc2 = 1; char *argv2[100]; @@ -5059,6 +5113,8 @@ int main(int argc, char** argv) { view_only = 1; } else if (!strcmp(arg, "-shared")) { shared = 1; + } else if (!strcmp(arg, "-auth")) { + auth_file = argv[++i]; } else if (!strcmp(arg, "-allow")) { allow_list = argv[++i]; } else if (!strcmp(arg, "-localhost")) { @@ -5114,8 +5170,6 @@ int main(int argc, char** argv) { use_xwarppointer = 1; } else if (!strcmp(arg, "-cursorpos")) { cursor_pos = 1; - } else if (!strcmp(arg, "-cursorposall")) { - cursor_pos = 2; } else if (!strcmp(arg, "-buttonmap")) { pointer_remap = argv[++i]; } else if (!strcmp(arg, "-nodragging")) { @@ -5134,6 +5188,7 @@ int main(int argc, char** argv) { debug_keyboard++; } else if (!strcmp(arg, "-defer")) { defer_update = atoi(argv[++i]); + got_defer = 1; } else if (!strcmp(arg, "-wait")) { waitms = atoi(argv[++i]); got_waitms = 1; @@ -5188,6 +5243,18 @@ int main(int argc, char** argv) { if (!strcmp(arg, "-rfbwait")) { got_rfbwait = 1; } + if (!strcmp(arg, "-deferupdate")) { + got_deferupdate = 1; + } + if (!strcmp(arg, "-rfbport")) { + got_rfbport = 1; + } + if (!strcmp(arg, "-alwaysshared ")) { + got_alwaysshared = 1; + } + if (!strcmp(arg, "-nevershared")) { + got_nevershared = 1; + } /* otherwise copy it for use below. */ if (! quiet && i != pw_loc && i != pw_loc+1) { fprintf(stderr, "passing arg to libvncserver: %s\n", @@ -5218,6 +5285,10 @@ int main(int argc, char** argv) { /* fixup settings that do not make sense */ + if (use_threads && nofb && cursor_pos) { + fprintf(stderr, "disabling -threads under -nofb -cursorpos\n"); + use_threads = 0; + } if (tile_fuzz < 1) { tile_fuzz = 1; } @@ -5240,41 +5311,89 @@ int main(int argc, char** argv) { argv2[argc2++] = "604800000"; /* one week... */ } + if (nofb && ! got_deferupdate && ! got_defer) { + /* reduce defer time under -nofb */ + defer_update = defer_update_nofb; + } + if (! got_deferupdate) { + char tmp[40]; + /* XXX not working yet in libvncserver */ + sprintf(tmp, "%d", defer_update); + argv2[argc2++] = "-deferupdate"; + argv2[argc2++] = strdup(tmp); + } + if (! quiet) { fprintf(stderr, "\n"); + fprintf(stderr, "display: %s\n", use_dpy ? use_dpy + : "null"); + fprintf(stderr, "subwin: 0x%x\n", subwin); + fprintf(stderr, "visual: %s\n", visual_str ? visual_str + : "null"); + fprintf(stderr, "flashcmap: %d\n", flash_cmap); + fprintf(stderr, "force_idx: %d\n", force_indexed_color); fprintf(stderr, "viewonly: %d\n", view_only); fprintf(stderr, "shared: %d\n", shared); + fprintf(stderr, "authfile: %s\n", auth_file ? auth_file + : "null"); fprintf(stderr, "allow: %s\n", allow_list ? allow_list : "null"); - fprintf(stderr, "inetd: %d\n", inetd); fprintf(stderr, "conn_once: %d\n", connect_once); - fprintf(stderr, "flashcmap: %d\n", flash_cmap); - fprintf(stderr, "force_idx: %d\n", force_indexed_color); + fprintf(stderr, "connect: %s\n", client_connect + ? client_connect : "null"); + fprintf(stderr, "connectfile %s\n", client_connect_file + ? client_connect_file : "null"); + fprintf(stderr, "vnc_conn: %d\n", vnc_connect); + fprintf(stderr, "inetd: %d\n", inetd); fprintf(stderr, "using_shm: %d\n", using_shm); fprintf(stderr, "flipbytes: %d\n", flip_byte_order); - fprintf(stderr, "nofb: %d\n", nofb); - fprintf(stderr, "watchbell: %d\n", watch_bell); fprintf(stderr, "mod_tweak: %d\n", use_modifier_tweak); + fprintf(stderr, "remap: %s\n", remap_file ? remap_file + : "null"); + fprintf(stderr, "blackout: %s\n", blackout_string + ? blackout_string : "null"); + fprintf(stderr, "xinerama: %d\n", xinerama); + fprintf(stderr, "watchbell: %d\n", watch_bell); + fprintf(stderr, "nofb: %d\n", nofb); + fprintf(stderr, "watchsel: %d\n", watch_selection); + fprintf(stderr, "watchprim: %d\n", watch_primary); fprintf(stderr, "loc_curs: %d\n", local_cursor); fprintf(stderr, "mouse: %d\n", show_mouse); + fprintf(stderr, "root_curs: %d\n", show_root_cursor); + fprintf(stderr, "xwarpptr: %d\n", use_xwarppointer); + fprintf(stderr, "cursorpos: %d\n", cursor_pos); + fprintf(stderr, "buttonmap: %s\n", pointer_remap + ? pointer_remap : "null"); fprintf(stderr, "dragging: %d\n", show_dragging); fprintf(stderr, "inputskip: %d\n", ui_skip); - fprintf(stderr, "root_curs: %d\n", show_root_cursor); + fprintf(stderr, "old_ptr: %d\n", old_pointer); + fprintf(stderr, "onetile: %d\n", single_copytile); + fprintf(stderr, "debug_ptr: %d\n", debug_pointer); + fprintf(stderr, "debug_key: %d\n", debug_keyboard); fprintf(stderr, "defer: %d\n", defer_update); fprintf(stderr, "waitms: %d\n", waitms); fprintf(stderr, "take_naps: %d\n", take_naps); + fprintf(stderr, "sigpipe: %d\n", sigpipe); fprintf(stderr, "threads: %d\n", use_threads); fprintf(stderr, "fs_frac: %.2f\n", fs_frac); fprintf(stderr, "gaps_fill: %d\n", gaps_fill); fprintf(stderr, "grow_fill: %d\n", grow_fill); fprintf(stderr, "tile_fuzz: %d\n", tile_fuzz); fprintf(stderr, "use_hints: %d\n", use_hints); + fprintf(stderr, "bg: %d\n", bg); } else { rfbLogEnable(0); } /* open the X display: */ X_INIT; + if (auth_file) { + char *tmp; + int len = strlen("XAUTHORITY=") + strlen(auth_file) + 1; + tmp = (char *) malloc((size_t) len); + sprintf(tmp, "XAUTHORITY=%s", auth_file); + putenv(tmp); + } if (use_dpy) { dpy = XOpenDisplay(use_dpy); } else if ( (use_dpy = getenv("DISPLAY")) ) {